1 ;;- Machine description for ARM for GNU compiler
2 ;; Copyright (C) 1991, 93-98, 1999 Free Software Foundation, Inc.
3 ;; Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
4 ;; and Martin Simmons (@harleqn.co.uk).
5 ;; More major hacks by Richard Earnshaw (rearnsha@arm.com).
7 ;; This file is part of GNU CC.
9 ;; GNU CC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
14 ;; GNU CC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU CC; see the file COPYING. If not, write to
21 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
24 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
26 ;; There are patterns in this file to support XFmode arithmetic.
27 ;; Unfortunately RISC iX doesn't work well with these so they are disabled.
31 ;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
32 ;; the mode is MODE_FLOAT
33 ;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
34 ;; the mode is MODE_FLOAT
35 ;; 2 `push multiple' operation: operand 0 is the first register. Subsequent
36 ;; registers are in parallel (use...) expressions.
37 ;; 3 A symbol that has been treated properly for pic usage, that is, we
38 ;; will add the pic_register value to it before trying to dereference it.
39 ;; Note: sin and cos are no-longer used.
43 (define_attr "is_thumb" "no,yes" (const (symbol_ref "TARGET_ARM")))
45 ; PROG_MODE attribute is used to determine whether condition codes are
46 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
47 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
48 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
50 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
52 ; Floating Point Unit. If we only have floating point emulation, then there
53 ; is no point in scheduling the floating point insns. (Well, for best
54 ; performance we should try and group them together).
56 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
58 ; LENGTH of an instruction (in bytes)
59 (define_attr "length" "" (const_int 4))
61 ; POOL_RANGE is how far away from a constant pool entry that this insn
62 ; can be placed. If the distance is zero, then this insn will never
64 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
66 (define_attr "pool_range" "" (const_int 0))
67 (define_attr "neg_pool_range" "" (const_int 0))
69 ; An assembler sequence may clobber the condition codes without us knowing
70 (define_asm_attributes
71 [(set_attr "conds" "clob")])
73 ; TYPE attribute is used to detect floating point instructions which, if
74 ; running on a co-processor can run in parallel with other, basic instructions
75 ; If write-buffer scheduling is enabled then it can also be used in the
76 ; scheduling of writes.
78 ; Classification of each insn
79 ; normal any data instruction that doesn't hit memory or fp regs
80 ; mult a multiply instruction
81 ; block blockage insn, this blocks all functional units
82 ; float a floating point arithmetic operation (subject to expansion)
83 ; fdivx XFmode floating point division
84 ; fdivd DFmode floating point division
85 ; fdivs SFmode floating point division
86 ; fmul Floating point multiply
87 ; ffmul Fast floating point multiply
88 ; farith Floating point arithmetic (4 cycle)
89 ; ffarith Fast floating point arithmetic (2 cycle)
90 ; float_em a floating point arithmetic operation that is normally emulated
91 ; even on a machine with an fpa.
92 ; f_load a floating point load from memory
93 ; f_store a floating point store to memory
94 ; f_mem_r a transfer of a floating point register to a real reg via mem
95 ; r_mem_f the reverse of f_mem_r
96 ; f_2_r fast transfer float to arm (no memory needed)
97 ; r_2_f fast transfer arm to float
98 ; call a subroutine call
99 ; load any load from memory
100 ; store1 store 1 word to memory from arm registers
101 ; store2 store 2 words
102 ; store3 store 3 words
103 ; store4 store 4 words
106 "normal,mult,block,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith,float_em,f_load,f_store,f_mem_r,r_mem_f,f_2_r,r_2_f,call,load,store1,store2,store3,store4"
107 (const_string "normal"))
109 ; Load scheduling, set from the arm_ld_sched variable
110 ; initialised by arm_override_options()
111 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
113 ; condition codes: this one is used by final_prescan_insn to speed up
114 ; conditionalizing instructions. It saves having to scan the rtl to see if
115 ; it uses or alters the condition codes.
117 ; USE means that the condition codes are used by the insn in the process of
118 ; outputting code, this means (at present) that we can't use the insn in
121 ; SET means that the purpose of the insn is to set the condition codes in a
122 ; well defined manner.
124 ; CLOB means that the condition codes are altered in an undefined manner, if
125 ; they are altered at all
127 ; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
128 ; but are if the branch wasn't taken; the effect is to limit the branch
129 ; elimination scanning.
131 ; NOCOND means that the condition codes are neither altered nor affect the
132 ; output of this insn
134 (define_attr "conds" "use,set,clob,jump_clob,nocond"
135 (if_then_else (eq_attr "type" "call")
136 (if_then_else (eq_attr "prog_mode" "prog32")
137 (const_string "clob") (const_string "nocond"))
138 (const_string "nocond")))
140 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
141 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
142 ; suffer blockages enough to warrent modelling this (and it can adversely
143 ; affect the schedule).
144 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
146 (define_attr "write_conflict" "no,yes"
147 (if_then_else (eq_attr "type"
148 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
150 (const_string "no")))
152 (define_attr "core_cycles" "single,multi"
153 (if_then_else (eq_attr "type"
154 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
155 (const_string "single")
156 (const_string "multi")))
158 ;; FAR_JUMP is "yes" if a BL instruction is used to generate a branch to a
160 (define_attr "far_jump" "yes,no" (const_string "no"))
163 ; The write buffer on some of the arm6 processors is hard to model exactly.
164 ; There is room in the buffer for up to two addresses and up to eight words
165 ; of memory, but the two needn't be split evenly. When writing the two
166 ; addresses are fully pipelined. However, a read from memory that is not
167 ; currently in the cache will block until the writes have completed.
168 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
169 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
170 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
171 ; cycle to add as well.
173 ;; (define_function_unit {name} {num-units} {n-users} {test}
174 ;; {ready-delay} {issue-delay} [{conflict-list}])
175 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
176 (eq_attr "type" "fdivx")) 71 69)
178 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
179 (eq_attr "type" "fdivd")) 59 57)
181 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
182 (eq_attr "type" "fdivs")) 31 29)
184 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
185 (eq_attr "type" "fmul")) 9 7)
187 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
188 (eq_attr "type" "ffmul")) 6 4)
190 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
191 (eq_attr "type" "farith")) 4 2)
193 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
194 (eq_attr "type" "ffarith")) 2 2)
196 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
197 (eq_attr "type" "r_2_f")) 5 3)
199 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
200 (eq_attr "type" "f_2_r")) 1 2)
202 ;; The fpa10 doesn't really have a memory read unit, but it can start to
203 ;; speculatively execute the instruction in the pipeline, provided the data
204 ;; is already loaded, so pretend reads have a delay of 2 (and that the
205 ;; pipeline is infinite.
207 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
208 (eq_attr "type" "f_load")) 3 1)
210 ;;--------------------------------------------------------------------
212 ;;--------------------------------------------------------------------
213 ;; Strictly we should model a 4-deep write buffer for ARM7xx based chips
214 (define_function_unit "write_buf" 1 2
215 (and (eq_attr "model_wbuf" "yes")
216 (eq_attr "type" "store1,r_mem_f")) 5 3)
217 (define_function_unit "write_buf" 1 2
218 (and (eq_attr "model_wbuf" "yes")
219 (eq_attr "type" "store2")) 7 4)
220 (define_function_unit "write_buf" 1 2
221 (and (eq_attr "model_wbuf" "yes")
222 (eq_attr "type" "store3")) 9 5)
223 (define_function_unit "write_buf" 1 2
224 (and (eq_attr "model_wbuf" "yes")
225 (eq_attr "type" "store4")) 11 6)
227 ;;--------------------------------------------------------------------
228 ;; Write blockage unit
229 ;;--------------------------------------------------------------------
230 ;; The write_blockage unit models (partially), the fact that reads will stall
231 ;; until the write buffer empties.
232 ;; The f_mem_r and r_mem_f could also block, but they are to the stack,
233 ;; so we don't model them here
234 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
235 (eq_attr "type" "store1")) 5 5
236 [(eq_attr "write_conflict" "yes")])
237 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
238 (eq_attr "type" "store2")) 7 7
239 [(eq_attr "write_conflict" "yes")])
240 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
241 (eq_attr "type" "store3")) 9 9
242 [(eq_attr "write_conflict" "yes")])
243 (define_function_unit "write_blockage" 1 0
244 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
245 [(eq_attr "write_conflict" "yes")])
246 (define_function_unit "write_blockage" 1 0
247 (and (eq_attr "model_wbuf" "yes")
248 (eq_attr "write_conflict" "yes")) 1 1)
250 ;;--------------------------------------------------------------------
252 ;;--------------------------------------------------------------------
253 ;; Everything must spend at least one cycle in the core unit
254 (define_function_unit "core" 1 0 (eq_attr "core_cycles" "single") 1 1)
256 (define_function_unit "core" 1 0
257 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
259 (define_function_unit "core" 1 0
260 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
262 (define_function_unit "core" 1 0
263 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
265 (define_function_unit "core" 1 0
266 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
268 (define_function_unit "core" 1 0
269 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
271 (define_function_unit "core" 1 0
272 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
274 (define_function_unit "core" 1 0
275 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
277 (define_function_unit "core" 1 0
278 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
280 (define_function_unit "core" 1 0
281 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
282 (eq_attr "type" "mult")) 4 4)
284 (define_function_unit "core" 1 0
285 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
286 (eq_attr "type" "mult")) 3 2)
288 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
290 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
292 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
294 (define_function_unit "core" 1 0
295 (and (eq_attr "core_cycles" "multi")
296 (eq_attr "type" "!mult,load,store1,store2,store3,store4")) 32 32)
298 ;; Note: For DImode insns, there is normally no reason why operands should
299 ;; not be in the same register, what we don't want is for something being
300 ;; written to partially overlap something that is an input.
302 ;; Split up 64bit addition so that the component insns can schedule
305 [(set (match_operand:DI 0 "s_register_operand" "")
306 (plus:DI (match_operand:DI 1 "s_register_operand" "")
307 (match_operand:DI 2 "s_register_operand" "")))
308 (clobber (reg:CC 24))]
309 "TARGET_ARM && reload_completed"
310 [(parallel [(set (reg:CC_C 24)
311 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
313 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
314 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
315 (plus:SI (match_dup 4) (match_dup 5))))]
318 operands[3] = gen_highpart (SImode, operands[0]);
319 operands[0] = gen_lowpart (SImode, operands[0]);
320 operands[4] = gen_highpart (SImode, operands[1]);
321 operands[1] = gen_lowpart (SImode, operands[1]);
322 operands[5] = gen_highpart (SImode, operands[2]);
323 operands[2] = gen_lowpart (SImode, operands[2]);
326 ;; The first insn created by this splitter must set the low part of
327 ;; operand0 as well as the carry bit in the CC register. The second
328 ;; insn must compute the sum of the carry bit, the sign extension of
329 ;; operand 2 from 32 to 64 bits and the high part of operand 1.
331 [(set (match_operand:DI 0 "s_register_operand" "")
332 (plus:DI (sign_extend:DI
333 (match_operand:SI 2 "s_register_operand" ""))
334 (match_operand:DI 1 "s_register_operand" "")))
335 (clobber (reg:CC 24))]
336 "TARGET_ARM && reload_completed"
337 [(parallel [(set (reg:CC_C 24)
338 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
340 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
341 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
342 (plus:SI (ashiftrt:SI (match_dup 2)
347 operands[3] = gen_highpart (SImode, operands[0]);
348 operands[0] = gen_lowpart (SImode, operands[0]);
349 operands[4] = gen_highpart (SImode, operands[1]);
350 operands[1] = gen_lowpart (SImode, operands[1]);
351 operands[2] = gen_lowpart (SImode, operands[2]);
354 ;; The first insn created by this splitter must set the low part of
355 ;; operand0 as well as the carry bit in the CC register. The second
356 ;; insn must compute the sum of the carry bit and the high bits from
359 [(set (match_operand:DI 0 "s_register_operand" "")
360 (plus:DI (zero_extend:DI
361 (match_operand:SI 2 "s_register_operand" ""))
362 (match_operand:DI 1 "s_register_operand" "")))
363 (clobber (reg:CC 24))]
364 "TARGET_ARM && reload_completed"
365 [(parallel [(set (reg:CC_C 24)
366 (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
368 (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
369 (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
370 (plus:SI (match_dup 4) (const_int 0))))]
373 operands[3] = gen_highpart (SImode, operands[0]);
374 operands[0] = gen_lowpart (SImode, operands[0]);
375 operands[4] = gen_highpart (SImode, operands[1]);
376 operands[1] = gen_lowpart (SImode, operands[1]);
377 operands[2] = gen_lowpart (SImode, operands[2]);
382 (define_expand "adddi3"
384 [(set (match_operand:DI 0 "s_register_operand" "")
385 (plus:DI (match_operand:DI 1 "s_register_operand" "")
386 (match_operand:DI 2 "s_register_operand" "")))
387 (clobber (reg:CC 24))
393 if (GET_CODE (operands[1]) != REG)
394 operands[1] = force_reg (SImode, operands[1]);
395 if (GET_CODE (operands[2]) != REG)
396 operands[2] = force_reg (SImode, operands[2]);
401 (define_insn "*thumb_adddi3"
402 [(set (match_operand:DI 0 "register_operand" "=l")
403 (plus:DI (match_operand:DI 1 "register_operand" "%0")
404 (match_operand:DI 2 "register_operand" "l")))
405 (clobber (reg:CC 24))
408 "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
409 [(set_attr "length" "4")]
412 (define_insn "*arm_adddi3"
413 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
414 (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
415 (match_operand:DI 2 "s_register_operand" "r,0")))
416 (clobber (reg:CC 24))
420 [(set_attr "conds" "clob")
421 (set_attr "length" "8")]
424 (define_insn "*adddi_sesidi_di"
425 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
426 (plus:DI (sign_extend:DI
427 (match_operand:SI 2 "s_register_operand" "r,r"))
428 (match_operand:DI 1 "s_register_operand" "r,0")))
429 (clobber (reg:CC 24))
433 [(set_attr "conds" "clob")
434 (set_attr "length" "8")])
436 (define_insn "*adddi_zesidi_di"
437 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
438 (plus:DI (zero_extend:DI
439 (match_operand:SI 2 "s_register_operand" "r,r"))
440 (match_operand:DI 1 "s_register_operand" "r,0")))
441 (clobber (reg:CC 24))
445 [(set_attr "conds" "clob")
446 (set_attr "length" "8")]
449 (define_expand "addsi3"
450 [(set (match_operand:SI 0 "s_register_operand" "")
451 (plus:SI (match_operand:SI 1 "s_register_operand" "")
452 (match_operand:SI 2 "reg_or_int_operand" "")))]
455 if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
457 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
459 (reload_in_progress || reload_completed ? 0
460 : preserve_subexpressions_p ()));
467 [(set (match_operand:SI 0 "s_register_operand" "")
468 (plus:SI (match_operand:SI 1 "s_register_operand" "")
469 (match_operand:SI 2 "const_int_operand" "")))]
471 (! (const_ok_for_arm (INTVAL (operands[2]))
472 || const_ok_for_arm (-INTVAL (operands[2]))))"
473 [(clobber (const_int 0))]
475 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
480 (define_insn "*arm_addsi3"
481 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
482 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
483 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
489 [(set_attr "length" "4,4,16")]
492 ;; Register group 'k' is a single register group containing only the stack
493 ;; register. Trying to reload it will always fail catastrophically,
494 ;; so never allow those alternatives to match if reloading is needed.
496 (define_insn "*thumb_addsi3"
497 [(set (match_operand:SI 0 "register_operand" "=l,l,l,*r,*h,l,!k")
498 (plus:SI (match_operand:SI 1 "register_operand" "%0,0,l,*0,*0,!k,!k")
499 (match_operand:SI 2 "nonmemory_operand" "I,J,lL,*h,*r,!M,!O")))]
502 static char * asms[] =
504 \"add\\t%0, %0, %2\",
505 \"sub\\t%0, %0, #%n2\",
506 \"add\\t%0, %1, %2\",
507 \"add\\t%0, %0, %2\",
508 \"add\\t%0, %0, %2\",
509 \"add\\t%0, %1, %2\",
512 if ((which_alternative == 2 || which_alternative == 6)
513 && GET_CODE (operands[2]) == CONST_INT
514 && INTVAL (operands[2]) < 0)
515 return \"sub\\t%0, %1, #%n2\";
516 return asms[which_alternative];
518 [(set_attr "length" "2")]
521 ;; Reloading and elimination of the frame pointer can
522 ;; sometimes cause this optimization to be missed.
524 [(set (match_operand:SI 0 "register_operand" "=l")
525 (match_operand:SI 1 "const_int_operand" "M"))
527 (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
529 && REGNO (operands[2]) == STACK_POINTER_REGNUM
530 && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
531 && (INTVAL (operands[1]) & 3) == 0"
533 [(set_attr "length" "2")]
536 (define_insn "*addsi3_compare0"
537 [(set (reg:CC_NOOV 24)
539 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
540 (match_operand:SI 2 "arm_add_operand" "rI,L"))
542 (set (match_operand:SI 0 "s_register_operand" "=r,r")
543 (plus:SI (match_dup 1) (match_dup 2)))]
547 sub%?s\\t%0, %1, #%n2"
548 [(set_attr "conds" "set")]
551 (define_insn "*addsi3_compare0_scratch"
552 [(set (reg:CC_NOOV 24)
554 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
555 (match_operand:SI 1 "arm_add_operand" "rI,L"))
561 [(set_attr "conds" "set")])
563 ;; These patterns are the same ones as the two regular addsi3_compare0
564 ;; patterns, except we write them slightly different - the combiner
565 ;; tends to generate them this way.
566 (define_insn "*addsi3_compare0_for_combiner"
569 (match_operand:SI 1 "s_register_operand" "r,r")
570 (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
571 (set (match_operand:SI 0 "s_register_operand" "=r,r")
572 (plus:SI (match_dup 1) (match_dup 2)))]
576 sub%?s\\t%0, %1, #%n2"
577 [(set_attr "conds" "set")]
580 (define_insn "*addsi3_compare0_scratch_for_combiner"
583 (match_operand:SI 0 "s_register_operand" "r,r")
584 (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
589 [(set_attr "conds" "set")])
591 ;; The next four insns work because they compare the result with one of
592 ;; the operands, and we know that the use of the condition code is
593 ;; either GEU or LTU, so we can use the carry flag from the addition
594 ;; instead of doing the compare a second time.
595 (define_insn "*addsi3_compare_op1"
598 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
599 (match_operand:SI 2 "arm_add_operand" "rI,L"))
601 (set (match_operand:SI 0 "s_register_operand" "=r,r")
602 (plus:SI (match_dup 1) (match_dup 2)))]
606 sub%?s\\t%0, %1, #%n2"
607 [(set_attr "conds" "set")])
609 (define_insn "*addsi3_compare_op2"
612 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
613 (match_operand:SI 2 "arm_add_operand" "rI,L"))
615 (set (match_operand:SI 0 "s_register_operand" "=r,r")
616 (plus:SI (match_dup 1) (match_dup 2)))]
620 sub%?s\\t%0, %1, #%n2"
621 [(set_attr "conds" "set")])
623 (define_insn "*compare_addsi2_op0"
626 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
627 (match_operand:SI 1 "arm_add_operand" "rI,L"))
633 [(set_attr "conds" "set")])
635 (define_insn "*compare_addsi2_op1"
638 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
639 (match_operand:SI 1 "arm_add_operand" "rI,L"))
645 [(set_attr "conds" "set")])
647 (define_insn "*addsi3_carryin"
648 [(set (match_operand:SI 0 "s_register_operand" "=r")
649 (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
650 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
651 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
654 [(set_attr "conds" "use")]
657 (define_insn "*addsi3_carryin_shift"
658 [(set (match_operand:SI 0 "s_register_operand" "")
659 (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
661 (match_operator:SI 2 "shift_operator"
662 [(match_operand:SI 3 "s_register_operand" "")
663 (match_operand:SI 4 "reg_or_int_operand" "")])
664 (match_operand:SI 1 "s_register_operand" ""))))]
666 "adc%?\\t%0, %1, %3%S2"
667 [(set_attr "conds" "use")]
670 (define_insn "*addsi3_carryin_alt1"
671 [(set (match_operand:SI 0 "s_register_operand" "=r")
672 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
673 (match_operand:SI 2 "arm_rhs_operand" "rI"))
674 (ltu:SI (reg:CC_C 24) (const_int 0))))]
677 [(set_attr "conds" "use")]
680 (define_insn "*addsi3_carryin_alt2"
681 [(set (match_operand:SI 0 "s_register_operand" "=r")
682 (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
683 (match_operand:SI 1 "s_register_operand" "r"))
684 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
687 [(set_attr "conds" "use")])
689 (define_insn "*addsi3_carryin_alt3"
690 [(set (match_operand:SI 0 "s_register_operand" "=r")
691 (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
692 (match_operand:SI 2 "arm_rhs_operand" "rI"))
693 (match_operand:SI 1 "s_register_operand" "r")))]
696 [(set_attr "conds" "use")]
699 (define_insn "incscc"
700 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
701 (plus:SI (match_operator:SI 2 "comparison_operator"
702 [(match_operand:CC 3 "cc_register" "") (const_int 0)])
703 (match_operand:SI 1 "s_register_operand" "0,?r")))]
707 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
708 [(set_attr "conds" "use")
709 (set_attr "length" "4,8")])
711 ; If a constant is too big to fit in a single instruction then the constant
712 ; will be pre-loaded into a register taking at least two insns, we might be
713 ; able to merge it with an add, but it depends on the exact value.
716 [(set (match_operand:SI 0 "s_register_operand" "=r")
717 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
718 (match_operand:SI 2 "const_int_operand" "n")))]
720 && (! (const_ok_for_arm (INTVAL (operands[2]))
721 || const_ok_for_arm (-INTVAL (operands[2]))))"
722 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
723 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
726 unsigned int val = (unsigned) INTVAL (operands[2]);
730 /* This code is similar to the approach followed in movsi,
731 but it must generate exactly two insns. */
733 for (i = 30; i >= 0; i -= 2)
739 if (const_ok_for_arm (temp = (val & ~(255 << i))))
744 /* We might be able to do this as (larger number - small number). */
745 temp = ((val >> i) & 255) + 1;
746 if (temp > 255 && i < 24)
749 temp = ((val >> i) & 255) + 1;
751 if (const_ok_for_arm ((temp << i) - val))
754 temp = (unsigned) - (int) (i - val);
761 /* If we got here, we have found a way of doing it in two instructions.
762 the two constants are in val and temp. */
763 operands[2] = GEN_INT ((int) val);
764 operands[3] = GEN_INT ((int) temp);
768 (define_insn "addsf3"
769 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
770 (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
771 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
772 "TARGET_ARM && TARGET_HARD_FLOAT"
775 suf%?s\\t%0, %1, #%N2"
776 [(set_attr "type" "farith")]
779 (define_insn "adddf3"
780 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
781 (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
782 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
783 "TARGET_ARM && TARGET_HARD_FLOAT"
786 suf%?d\\t%0, %1, #%N2"
787 [(set_attr "type" "farith")]
790 (define_insn "*adddf_esfdf_df"
791 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
792 (plus:DF (float_extend:DF
793 (match_operand:SF 1 "s_register_operand" "f,f"))
794 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
795 "TARGET_ARM && TARGET_HARD_FLOAT"
798 suf%?d\\t%0, %1, #%N2"
799 [(set_attr "type" "farith")]
802 (define_insn "*adddf_df_esfdf"
803 [(set (match_operand:DF 0 "s_register_operand" "=f")
804 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
806 (match_operand:SF 2 "s_register_operand" "f"))))]
807 "TARGET_ARM && TARGET_HARD_FLOAT"
808 "adf%?d\\t%0, %1, %2"
809 [(set_attr "type" "farith")]
812 (define_insn "*adddf_esfdf_esfdf"
813 [(set (match_operand:DF 0 "s_register_operand" "=f")
814 (plus:DF (float_extend:DF
815 (match_operand:SF 1 "s_register_operand" "f"))
817 (match_operand:SF 2 "s_register_operand" "f"))))]
818 "TARGET_ARM && TARGET_HARD_FLOAT"
819 "adf%?d\\t%0, %1, %2"
820 [(set_attr "type" "farith")]
823 (define_insn "addxf3"
824 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
825 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
826 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
827 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
830 suf%?e\\t%0, %1, #%N2"
831 [(set_attr "type" "farith")]
834 (define_expand "subdi3"
836 [(set (match_operand:DI 0 "s_register_operand" "")
837 (minus:DI (match_operand:DI 1 "s_register_operand" "")
838 (match_operand:DI 2 "s_register_operand" "")))
839 (clobber (reg:CC 24))
846 if (GET_CODE (operands[1]) != REG)
847 operands[1] = force_reg (SImode, operands[1]);
848 if (GET_CODE (operands[2]) != REG)
849 operands[2] = force_reg (SImode, operands[2]);
854 (define_insn "*arm_subdi3"
855 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
856 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
857 (match_operand:DI 2 "s_register_operand" "r,0,0")))
858 (clobber (reg:CC 24))
861 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
862 [(set_attr "conds" "clob")
863 (set_attr "length" "8")]
866 (define_insn "*thumb_subdi3"
867 [(set (match_operand:DI 0 "register_operand" "=l")
868 (minus:DI (match_operand:DI 1 "register_operand" "0")
869 (match_operand:DI 2 "register_operand" "l")))
870 (clobber (reg:CC 24))
873 "sub\\t%Q0, %Q0, %Q2\;sbc\\t%R0, %R0, %R2"
874 [(set_attr "length" "4")]
877 (define_insn "*subdi_di_zesidi"
878 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
879 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
881 (match_operand:SI 2 "s_register_operand" "r,r"))))
882 (clobber (reg:CC 24))
885 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
886 [(set_attr "conds" "clob")
887 (set_attr "length" "8")]
890 (define_insn "*subdi_di_sesidi"
891 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
892 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
894 (match_operand:SI 2 "s_register_operand" "r,r"))))
895 (clobber (reg:CC 24))
898 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
899 [(set_attr "conds" "clob")
900 (set_attr "length" "8")]
903 (define_insn "*subdi_zesidi_di"
904 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
905 (minus:DI (zero_extend:DI
906 (match_operand:SI 2 "s_register_operand" "r,r"))
907 (match_operand:DI 1 "s_register_operand" "?r,0")))
908 (clobber (reg:CC 24))
911 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
912 [(set_attr "conds" "clob")
913 (set_attr "length" "8")]
916 (define_insn "*subdi_sesidi_di"
917 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
918 (minus:DI (sign_extend:DI
919 (match_operand:SI 2 "s_register_operand" "r,r"))
920 (match_operand:DI 1 "s_register_operand" "?r,0")))
921 (clobber (reg:CC 24))
924 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
925 [(set_attr "conds" "clob")
926 (set_attr "length" "8")]
929 (define_insn "*subdi_zesidi_zesidi"
930 [(set (match_operand:DI 0 "s_register_operand" "=r")
931 (minus:DI (zero_extend:DI
932 (match_operand:SI 1 "s_register_operand" "r"))
934 (match_operand:SI 2 "s_register_operand" "r"))))
935 (clobber (reg:CC 24))
938 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
939 [(set_attr "conds" "clob")
940 (set_attr "length" "8")]
943 (define_expand "subsi3"
944 [(set (match_operand:SI 0 "s_register_operand" "")
945 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
946 (match_operand:SI 2 "s_register_operand" "")))]
949 if (GET_CODE (operands[1]) == CONST_INT)
953 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
955 (reload_in_progress || reload_completed ? 0
956 : preserve_subexpressions_p ()));
959 else /* TARGET_THUMB */
960 operands[1] = force_reg (SImode, operands[1]);
965 (define_insn "*thumb_subsi3_insn"
966 [(set (match_operand:SI 0 "register_operand" "=l")
967 (minus:SI (match_operand:SI 1 "register_operand" "l")
968 (match_operand:SI 2 "register_operand" "l")))]
971 [(set_attr "length" "2")]
974 (define_insn "*arm_subsi3_insn"
975 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
976 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
977 (match_operand:SI 2 "s_register_operand" "r,r")))]
982 [(set_attr "length" "4,16")]
986 [(set (match_operand:SI 0 "s_register_operand" "")
987 (minus:SI (match_operand:SI 1 "const_int_operand" "")
988 (match_operand:SI 2 "s_register_operand" "")))]
989 "TARGET_ARM && (! const_ok_for_arm (INTVAL (operands[1])))"
990 [(clobber (const_int 0))]
992 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
998 (define_insn "*subsi3_compare0"
999 [(set (reg:CC_NOOV 24)
1000 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
1001 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
1003 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1004 (minus:SI (match_dup 1) (match_dup 2)))]
1008 rsb%?s\\t%0, %2, %1"
1009 [(set_attr "conds" "set")]
1012 (define_insn "decscc"
1013 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1014 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
1015 (match_operator:SI 2 "comparison_operator"
1016 [(match_operand 3 "cc_register" "") (const_int 0)])))]
1020 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
1021 [(set_attr "conds" "use")
1022 (set_attr "length" "*,8")]
1025 (define_insn "subsf3"
1026 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1027 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1028 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1029 "TARGET_ARM && TARGET_HARD_FLOAT"
1032 rsf%?s\\t%0, %2, %1"
1033 [(set_attr "type" "farith")]
1036 (define_insn "subdf3"
1037 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1038 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1039 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1040 "TARGET_ARM && TARGET_HARD_FLOAT"
1043 rsf%?d\\t%0, %2, %1"
1044 [(set_attr "type" "farith")]
1047 (define_insn "*subdf_esfdf_df"
1048 [(set (match_operand:DF 0 "s_register_operand" "=f")
1049 (minus:DF (float_extend:DF
1050 (match_operand:SF 1 "s_register_operand" "f"))
1051 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1052 "TARGET_ARM && TARGET_HARD_FLOAT"
1053 "suf%?d\\t%0, %1, %2"
1054 [(set_attr "type" "farith")]
1057 (define_insn "*subdf_df_esfdf"
1058 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1059 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1061 (match_operand:SF 2 "s_register_operand" "f,f"))))]
1062 "TARGET_ARM && TARGET_HARD_FLOAT"
1065 rsf%?d\\t%0, %2, %1"
1066 [(set_attr "type" "farith")]
1069 (define_insn "*subdf_esfdf_esfdf"
1070 [(set (match_operand:DF 0 "s_register_operand" "=f")
1071 (minus:DF (float_extend:DF
1072 (match_operand:SF 1 "s_register_operand" "f"))
1074 (match_operand:SF 2 "s_register_operand" "f"))))]
1075 "TARGET_ARM && TARGET_HARD_FLOAT"
1076 "suf%?d\\t%0, %1, %2"
1077 [(set_attr "type" "farith")]
1080 (define_insn "subxf3"
1081 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1082 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1083 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1084 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1087 rsf%?e\\t%0, %2, %1"
1088 [(set_attr "type" "farith")]
1091 ;; Multiplication insns
1093 (define_expand "mulsi3"
1094 [(set (match_operand:SI 0 "s_register_operand" "")
1095 (mult:SI (match_operand:SI 2 "s_register_operand" "")
1096 (match_operand:SI 1 "s_register_operand" "")))]
1101 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
1102 (define_insn "*arm_mulsi3"
1103 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1104 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
1105 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
1107 "mul%?\\t%0, %2, %1"
1108 [(set_attr "type" "mult")]
1111 ;; Unfortunately with the Thumb the '&'/'0' trick can fails when operands 1 and 2
1112 ;; are the same, because reload will make operand 0 match operand 1 without
1113 ;; realizing that this conflicts with operand 2. We fix this by adding another
1114 ;; alternative to match this case, and then `reload' it ourselves. This
1115 ;; alternative must come first.
1116 (define_insn "*thumb_mulsi3"
1117 [(set (match_operand:SI 0 "register_operand" "=&l,&l,&l")
1118 (mult:SI (match_operand:SI 1 "register_operand" "%l,*h,0")
1119 (match_operand:SI 2 "register_operand" "l,l,l")))]
1122 if (which_alternative < 2)
1123 return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1125 return \"mul\\t%0, %0, %2\";
1127 [(set_attr "length" "4,4,2")
1128 (set_attr "type" "mult")]
1131 (define_insn "*mulsi3_compare0"
1132 [(set (reg:CC_NOOV 24)
1133 (compare:CC_NOOV (mult:SI
1134 (match_operand:SI 2 "s_register_operand" "r,r")
1135 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1137 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1138 (mult:SI (match_dup 2) (match_dup 1)))]
1140 "mul%?s\\t%0, %2, %1"
1141 [(set_attr "conds" "set")
1142 (set_attr "type" "mult")]
1145 (define_insn "*mulsi_compare0_scratch"
1146 [(set (reg:CC_NOOV 24)
1147 (compare:CC_NOOV (mult:SI
1148 (match_operand:SI 2 "s_register_operand" "r,r")
1149 (match_operand:SI 1 "s_register_operand" "%?r,0"))
1151 (clobber (match_scratch:SI 0 "=&r,&r"))]
1153 "mul%?s\\t%0, %2, %1"
1154 [(set_attr "conds" "set")
1155 (set_attr "type" "mult")]
1158 ;; Unnamed templates to match MLA instruction.
1160 (define_insn "*mulsi3addsi"
1161 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1163 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1164 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1165 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
1167 "mla%?\\t%0, %2, %1, %3"
1168 [(set_attr "type" "mult")])
1170 (define_insn "*mulsi3addsi_compare0"
1171 [(set (reg:CC_NOOV 24)
1172 (compare:CC_NOOV (plus:SI
1174 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1175 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1176 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1178 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1179 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1182 "mla%?s\\t%0, %2, %1, %3"
1183 [(set_attr "conds" "set")
1184 (set_attr "type" "mult")])
1186 (define_insn "*mulsi3addsi_compare0_scratch"
1187 [(set (reg:CC_NOOV 24)
1188 (compare:CC_NOOV (plus:SI
1190 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1191 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1192 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1194 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1196 "mla%?s\\t%0, %2, %1, %3"
1197 [(set_attr "conds" "set")
1198 (set_attr "type" "mult")]
1201 ;; Unnamed template to match long long multiply-accumlate (smlal)
1203 (define_insn "*mulsidi3adddi"
1204 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
1206 (mult:DI (sign_extend:DI
1207 (match_operand:SI 2 "s_register_operand" "r,0,1"))
1209 (match_operand:SI 1 "s_register_operand" "%r,r,r")))
1211 "TARGET_ARM && arm_fast_multiply"
1212 "smlal%?\\t%Q0, %R0, %1, %2"
1213 [(set_attr "type" "mult")])
1215 (define_insn "mulsidi3"
1216 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1217 (mult:DI (sign_extend:DI
1218 (match_operand:SI 1 "s_register_operand" "%r"))
1220 (match_operand:SI 2 "s_register_operand" "r"))))]
1221 "TARGET_ARM && arm_fast_multiply"
1222 "smull%?\\t%Q0, %R0, %1, %2"
1223 [(set_attr "type" "mult")])
1225 (define_insn "umulsidi3"
1226 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1227 (mult:DI (zero_extend:DI
1228 (match_operand:SI 1 "s_register_operand" "%r"))
1230 (match_operand:SI 2 "s_register_operand" "r"))))]
1231 "TARGET_ARM && arm_fast_multiply"
1232 "umull%?\\t%Q0, %R0, %1, %2"
1233 [(set_attr "type" "mult")])
1235 ;; Unnamed template to match long long unsigned multiply-accumlate (umlal)
1237 (define_insn "*umulsidi3adddi"
1238 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
1240 (mult:DI (zero_extend:DI
1241 (match_operand:SI 2 "s_register_operand" "r,0,1"))
1243 (match_operand:SI 1 "s_register_operand" "%r,r,r")))
1245 "TARGET_ARM && arm_fast_multiply"
1246 "umlal%?\\t%Q0, %R0, %1, %2"
1247 [(set_attr "type" "mult")])
1249 (define_insn "smulsi3_highpart"
1250 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1253 (mult:DI (sign_extend:DI
1254 (match_operand:SI 1 "s_register_operand" "%r,0"))
1256 (match_operand:SI 2 "s_register_operand" "r,r")))
1258 (clobber (match_scratch:SI 3 "=&r,&r"))]
1259 "TARGET_ARM && arm_fast_multiply"
1260 "smull%?\\t%3, %0, %2, %1"
1261 [(set_attr "type" "mult")]
1264 (define_insn "umulsi3_highpart"
1265 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1268 (mult:DI (zero_extend:DI
1269 (match_operand:SI 1 "s_register_operand" "%r,0"))
1271 (match_operand:SI 2 "s_register_operand" "r,r")))
1273 (clobber (match_scratch:SI 3 "=&r,&r"))]
1274 "TARGET_ARM && arm_fast_multiply"
1275 "umull%?\\t%3, %0, %2, %1"
1276 [(set_attr "type" "mult")]
1279 (define_insn "mulsf3"
1280 [(set (match_operand:SF 0 "s_register_operand" "=f")
1281 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
1282 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1283 "TARGET_ARM && TARGET_HARD_FLOAT"
1284 "fml%?s\\t%0, %1, %2"
1285 [(set_attr "type" "ffmul")])
1287 (define_insn "muldf3"
1288 [(set (match_operand:DF 0 "s_register_operand" "=f")
1289 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1290 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1291 "TARGET_ARM && TARGET_HARD_FLOAT"
1292 "muf%?d\\t%0, %1, %2"
1293 [(set_attr "type" "fmul")])
1295 (define_insn "*muldf_esfdf_df"
1296 [(set (match_operand:DF 0 "s_register_operand" "=f")
1297 (mult:DF (float_extend:DF
1298 (match_operand:SF 1 "s_register_operand" "f"))
1299 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1300 "TARGET_ARM && TARGET_HARD_FLOAT"
1301 "muf%?d\\t%0, %1, %2"
1302 [(set_attr "type" "fmul")])
1304 (define_insn "*muldf_df_esfdf"
1305 [(set (match_operand:DF 0 "s_register_operand" "=f")
1306 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
1308 (match_operand:SF 2 "s_register_operand" "f"))))]
1309 "TARGET_ARM && TARGET_HARD_FLOAT"
1310 "muf%?d\\t%0, %1, %2"
1311 [(set_attr "type" "fmul")])
1313 (define_insn "*muldf_esfdf_esfdf"
1314 [(set (match_operand:DF 0 "s_register_operand" "=f")
1315 (mult:DF (float_extend:DF
1316 (match_operand:SF 1 "s_register_operand" "f"))
1318 (match_operand:SF 2 "s_register_operand" "f"))))]
1319 "TARGET_ARM && TARGET_HARD_FLOAT"
1320 "muf%?d\\t%0, %1, %2"
1321 [(set_attr "type" "fmul")])
1323 (define_insn "mulxf3"
1324 [(set (match_operand:XF 0 "s_register_operand" "=f")
1325 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
1326 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1327 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1328 "muf%?e\\t%0, %1, %2"
1329 [(set_attr "type" "fmul")])
1333 (define_insn "divsf3"
1334 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
1335 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
1336 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
1337 "TARGET_ARM && TARGET_HARD_FLOAT"
1340 frd%?s\\t%0, %2, %1"
1341 [(set_attr "type" "fdivs")])
1343 (define_insn "divdf3"
1344 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
1345 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
1346 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
1347 "TARGET_ARM && TARGET_HARD_FLOAT"
1350 rdf%?d\\t%0, %2, %1"
1351 [(set_attr "type" "fdivd")])
1353 (define_insn "*divdf_esfdf_df"
1354 [(set (match_operand:DF 0 "s_register_operand" "=f")
1355 (div:DF (float_extend:DF
1356 (match_operand:SF 1 "s_register_operand" "f"))
1357 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1358 "TARGET_ARM && TARGET_HARD_FLOAT"
1359 "dvf%?d\\t%0, %1, %2"
1360 [(set_attr "type" "fdivd")])
1362 (define_insn "*divdf_df_esfdf"
1363 [(set (match_operand:DF 0 "s_register_operand" "=f")
1364 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1366 (match_operand:SF 2 "s_register_operand" "f"))))]
1367 "TARGET_ARM && TARGET_HARD_FLOAT"
1368 "rdf%?d\\t%0, %2, %1"
1369 [(set_attr "type" "fdivd")])
1371 (define_insn "*divdf_esfdf_esfdf"
1372 [(set (match_operand:DF 0 "s_register_operand" "=f")
1373 (div:DF (float_extend:DF
1374 (match_operand:SF 1 "s_register_operand" "f"))
1376 (match_operand:SF 2 "s_register_operand" "f"))))]
1377 "TARGET_ARM && TARGET_HARD_FLOAT"
1378 "dvf%?d\\t%0, %1, %2"
1379 [(set_attr "type" "fdivd")])
1381 (define_insn "divxf3"
1382 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1383 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1384 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1385 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1388 rdf%?e\\t%0, %2, %1"
1389 [(set_attr "type" "fdivx")])
1393 (define_insn "modsf3"
1394 [(set (match_operand:SF 0 "s_register_operand" "=f")
1395 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1396 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1397 "TARGET_ARM && TARGET_HARD_FLOAT"
1398 "rmf%?s\\t%0, %1, %2"
1399 [(set_attr "type" "fdivs")])
1401 (define_insn "moddf3"
1402 [(set (match_operand:DF 0 "s_register_operand" "=f")
1403 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1404 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1405 "TARGET_ARM && TARGET_HARD_FLOAT"
1406 "rmf%?d\\t%0, %1, %2"
1407 [(set_attr "type" "fdivd")])
1409 (define_insn "*moddf_esfdf_df"
1410 [(set (match_operand:DF 0 "s_register_operand" "=f")
1411 (mod:DF (float_extend:DF
1412 (match_operand:SF 1 "s_register_operand" "f"))
1413 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1414 "TARGET_ARM && TARGET_HARD_FLOAT"
1415 "rmf%?d\\t%0, %1, %2"
1416 [(set_attr "type" "fdivd")])
1418 (define_insn "*moddf_df_esfdf"
1419 [(set (match_operand:DF 0 "s_register_operand" "=f")
1420 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1422 (match_operand:SF 2 "s_register_operand" "f"))))]
1423 "TARGET_ARM && TARGET_HARD_FLOAT"
1424 "rmf%?d\\t%0, %1, %2"
1425 [(set_attr "type" "fdivd")])
1427 (define_insn "*moddf_esfdf_esfdf"
1428 [(set (match_operand:DF 0 "s_register_operand" "=f")
1429 (mod:DF (float_extend:DF
1430 (match_operand:SF 1 "s_register_operand" "f"))
1432 (match_operand:SF 2 "s_register_operand" "f"))))]
1433 "TARGET_ARM && TARGET_HARD_FLOAT"
1434 "rmf%?d\\t%0, %1, %2"
1435 [(set_attr "type" "fdivd")])
1437 (define_insn "modxf3"
1438 [(set (match_operand:XF 0 "s_register_operand" "=f")
1439 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1440 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1441 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1442 "rmf%?e\\t%0, %1, %2"
1443 [(set_attr "type" "fdivx")])
1445 ;; Boolean and,ior,xor insns
1447 ;; Split up double word logical operations
1449 ;; Split up simple DImode logical operations. Simply perform the logical
1450 ;; operation on the upper and lower halves of the registers.
1452 [(set (match_operand:DI 0 "s_register_operand" "")
1453 (match_operator:DI 6 "logical_binary_operator"
1454 [(match_operand:DI 1 "s_register_operand" "")
1455 (match_operand:DI 2 "s_register_operand" "")]))]
1456 "TARGET_ARM && reload_completed"
1457 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1458 (set (match_dup 3) (match_op_dup:SI 6 [(match_dup 4) (match_dup 5)]))]
1461 operands[3] = gen_highpart (SImode, operands[0]);
1462 operands[0] = gen_lowpart (SImode, operands[0]);
1463 operands[4] = gen_highpart (SImode, operands[1]);
1464 operands[1] = gen_lowpart (SImode, operands[1]);
1465 operands[5] = gen_highpart (SImode, operands[2]);
1466 operands[2] = gen_lowpart (SImode, operands[2]);
1470 [(set (match_operand:DI 0 "s_register_operand" "")
1471 (not:DI (match_operand:DI 1 "s_register_operand" "")))]
1472 "TARGET_ARM && reload_completed"
1473 [(set (match_dup 0) (not:SI (match_dup 1)))
1474 (set (match_dup 2) (not:SI (match_dup 3)))]
1477 operands[2] = gen_highpart (SImode, operands[0]);
1478 operands[0] = gen_lowpart (SImode, operands[0]);
1479 operands[3] = gen_highpart (SImode, operands[1]);
1480 operands[1] = gen_lowpart (SImode, operands[1]);
1484 [(set (match_operand:DI 0 "s_register_operand" "")
1486 (not:DI (match_operand:DI 1 "s_register_operand" ""))
1487 (match_operand:DI 2 "s_register_operand" "")))]
1488 "TARGET_ARM && reload_completed"
1489 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1490 (set (match_dup 3) (and:SI (not:SI (match_dup 4)) (match_dup 5)))]
1493 operands[3] = gen_highpart (SImode, operands[0]);
1494 operands[0] = gen_lowpart (SImode, operands[0]);
1495 operands[4] = gen_highpart (SImode, operands[1]);
1496 operands[1] = gen_lowpart (SImode, operands[1]);
1497 operands[5] = gen_highpart (SImode, operands[2]);
1498 operands[2] = gen_lowpart (SImode, operands[2]);
1502 [(set (match_operand:DI 0 "s_register_operand" "")
1503 (match_operator:DI 6 "logical_binary_operator"
1504 [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1505 (match_operand:DI 1 "s_register_operand" "")]))]
1506 "TARGET_ARM && reload_completed"
1507 [(set (match_dup 0) (match_op_dup:SI 6 [(match_dup 1) (match_dup 2)]))
1508 (set (match_dup 3) (match_op_dup:SI 6
1509 [(ashiftrt:SI (match_dup 2) (const_int 31))
1513 operands[3] = gen_highpart (SImode, operands[0]);
1514 operands[0] = gen_lowpart (SImode, operands[0]);
1515 operands[4] = gen_highpart (SImode, operands[1]);
1516 operands[1] = gen_lowpart (SImode, operands[1]);
1517 operands[5] = gen_highpart (SImode, operands[2]);
1518 operands[2] = gen_lowpart (SImode, operands[2]);
1522 [(set (match_operand:DI 0 "s_register_operand" "")
1523 (and:DI (not:DI (sign_extend:DI
1524 (match_operand:SI 2 "s_register_operand" "")))
1525 (match_operand:DI 1 "s_register_operand" "")))]
1526 "TARGET_ARM && reload_completed"
1527 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1528 (set (match_dup 3) (and:SI (not:SI
1529 (ashiftrt:SI (match_dup 2) (const_int 31)))
1533 operands[3] = gen_highpart (SImode, operands[0]);
1534 operands[0] = gen_lowpart (SImode, operands[0]);
1535 operands[4] = gen_highpart (SImode, operands[1]);
1536 operands[1] = gen_lowpart (SImode, operands[1]);
1537 operands[2] = gen_lowpart (SImode, operands[2]);
1540 ;; The zero extend of operand 2 clears the high word of the output
1543 [(set (match_operand:DI 0 "s_register_operand" "")
1545 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1546 (match_operand:DI 1 "s_register_operand" "")))]
1547 "TARGET_ARM && reload_completed"
1548 [(set (match_dup 0) (and:SI (match_dup 1) (match_dup 2)))
1549 (set (match_dup 3) (const_int 0))]
1552 operands[3] = gen_highpart (SImode, operands[0]);
1553 operands[0] = gen_lowpart (SImode, operands[0]);
1554 operands[1] = gen_lowpart (SImode, operands[1]);
1557 ;; The zero extend of operand 2 means we can just copy the high part of
1558 ;; operand1 into operand0.
1560 [(set (match_operand:DI 0 "s_register_operand" "")
1562 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1563 (match_operand:DI 1 "s_register_operand" "")))]
1564 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1565 [(set (match_dup 0) (ior:SI (match_dup 1) (match_dup 2)))
1566 (set (match_dup 3) (match_dup 4))]
1569 operands[4] = gen_highpart (SImode, operands[1]);
1570 operands[3] = gen_highpart (SImode, operands[0]);
1571 operands[0] = gen_lowpart (SImode, operands[0]);
1572 operands[1] = gen_lowpart (SImode, operands[1]);
1575 ;; The zero extend of operand 2 means we can just copy the high part of
1576 ;; operand1 into operand0.
1578 [(set (match_operand:DI 0 "s_register_operand" "")
1580 (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1581 (match_operand:DI 1 "s_register_operand" "")))]
1582 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1583 [(set (match_dup 0) (xor:SI (match_dup 1) (match_dup 2)))
1584 (set (match_dup 3) (match_dup 4))]
1587 operands[4] = gen_highpart (SImode, operands[1]);
1588 operands[3] = gen_highpart (SImode, operands[0]);
1589 operands[0] = gen_lowpart (SImode, operands[0]);
1590 operands[1] = gen_lowpart (SImode, operands[1]);
1593 ;; (not (zero_extend ...)) allows us to just copy the high word from
1594 ;; operand1 to operand0.
1596 [(set (match_operand:DI 0 "s_register_operand" "")
1597 (and:DI (not:DI (zero_extend:DI
1598 (match_operand:SI 2 "s_register_operand" "")))
1599 (match_operand:DI 1 "s_register_operand" "")))]
1600 "TARGET_ARM && operands[0] != operands[1] && reload_completed"
1601 [(set (match_dup 0) (and:SI (not:SI (match_dup 1)) (match_dup 2)))
1602 (set (match_dup 3) (match_dup 4))]
1605 operands[3] = gen_highpart (SImode, operands[0]);
1606 operands[0] = gen_lowpart (SImode, operands[0]);
1607 operands[4] = gen_highpart (SImode, operands[1]);
1608 operands[1] = gen_lowpart (SImode, operands[1]);
1609 operands[2] = gen_lowpart (SImode, operands[2]);
1612 (define_insn "anddi3"
1613 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1614 (and:DI (match_operand:DI 1 "s_register_operand" "%0,r")
1615 (match_operand:DI 2 "s_register_operand" "r,r")))]
1618 [(set_attr "length" "8")])
1620 (define_insn "*anddi_zesidi_di"
1621 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1622 (and:DI (zero_extend:DI
1623 (match_operand:SI 2 "s_register_operand" "r,r"))
1624 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1627 [(set_attr "length" "8")])
1629 (define_insn "*anddi_sesdi_di"
1630 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1631 (and:DI (sign_extend:DI
1632 (match_operand:SI 2 "s_register_operand" "r,r"))
1633 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1636 [(set_attr "length" "8")]
1639 (define_expand "andsi3"
1640 [(set (match_operand:SI 0 "s_register_operand" "")
1641 (and:SI (match_operand:SI 1 "s_register_operand" "")
1642 (match_operand:SI 2 "reg_or_int_operand" "")))]
1647 if (GET_CODE (operands[2]) == CONST_INT)
1649 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1651 (reload_in_progress || reload_completed
1652 ? 0 : preserve_subexpressions_p ()));
1656 else /* TARGET_THUMB */
1658 if (GET_CODE (operands[2]) != CONST_INT)
1659 operands[2] = force_reg (SImode, operands[2]);
1664 if (((unsigned HOST_WIDE_INT) ~ INTVAL (operands[2])) < 256)
1666 operands[2] = force_reg (SImode, GEN_INT (~INTVAL (operands[2])));
1668 emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1673 for (i = 9; i <= 31; i++)
1675 if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1677 emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1681 else if ((((HOST_WIDE_INT) 1) << i) - 1 == ~ INTVAL (operands[2]))
1683 rtx shift = GEN_INT (i);
1684 rtx reg = gen_reg_rtx (SImode);
1686 emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1687 emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1693 operands[2] = force_reg (SImode, operands[2]);
1698 (define_insn "*arm_andsi3_insn"
1699 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1700 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1701 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1705 bic%?\\t%0, %1, #%B2
1707 [(set_attr "length" "4,4,16")]
1710 (define_insn "*thumb_andsi3_insn"
1711 [(set (match_operand:SI 0 "register_operand" "=l")
1712 (and:SI (match_operand:SI 1 "register_operand" "%0")
1713 (match_operand:SI 2 "register_operand" "l")))]
1716 [(set_attr "length" "2")]
1720 [(set (match_operand:SI 0 "s_register_operand" "")
1721 (and:SI (match_operand:SI 1 "s_register_operand" "")
1722 (match_operand:SI 2 "const_int_operand" "")))]
1724 && (! (const_ok_for_arm ( INTVAL (operands[2]))
1725 || const_ok_for_arm (~ INTVAL (operands[2]))))"
1726 [(clobber (const_int 0))]
1728 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1733 (define_insn "*andsi3_compare0"
1734 [(set (reg:CC_NOOV 24)
1736 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1737 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1739 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1740 (and:SI (match_dup 1) (match_dup 2)))]
1744 bic%?s\\t%0, %1, #%B2"
1745 [(set_attr "conds" "set")]
1748 (define_insn "*andsi3_compare0_scratch"
1749 [(set (reg:CC_NOOV 24)
1751 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1752 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1754 (clobber (match_scratch:SI 3 "=X,r"))]
1758 bic%?s\\t%3, %0, #%B1"
1759 [(set_attr "conds" "set")])
1761 (define_insn "*zeroextractsi_compare0_scratch"
1762 [(set (reg:CC_NOOV 24)
1763 (compare:CC_NOOV (zero_extract:SI
1764 (match_operand:SI 0 "s_register_operand" "r")
1765 (match_operand 1 "const_int_operand" "n")
1766 (match_operand 2 "const_int_operand" "n"))
1769 && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1770 && INTVAL (operands[1]) > 0
1771 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1772 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1774 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1775 << INTVAL (operands[2]));
1776 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1779 [(set_attr "conds" "set")])
1781 (define_insn "*ne_zeroextractsi"
1782 [(set (match_operand:SI 0 "s_register_operand" "=r")
1783 (ne:SI (zero_extract:SI
1784 (match_operand:SI 1 "s_register_operand" "r")
1785 (match_operand:SI 2 "const_int_operand" "n")
1786 (match_operand:SI 3 "const_int_operand" "n"))
1789 && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1790 && INTVAL (operands[2]) > 0
1791 && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1792 && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1794 operands[2] = GEN_INT (((1 << INTVAL (operands[2])) - 1)
1795 << INTVAL (operands[3]));
1796 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
1797 return \"movne\\t%0, #1\";
1799 [(set_attr "conds" "clob")
1800 (set_attr "length" "8")])
1802 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1803 ;;; represented by the bitfield, then this will produce incorrect results.
1804 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1805 ;;; which have a real bitfield insert instruction, the truncation happens
1806 ;;; in the bitfield insert instruction itself. Since arm does not have a
1807 ;;; bitfield insert instruction, we would have to emit code here to truncate
1808 ;;; the value before we insert. This loses some of the advantage of having
1809 ;;; this insv pattern, so this pattern needs to be reevalutated.
1811 (define_expand "insv"
1812 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1813 (match_operand:SI 1 "general_operand" "")
1814 (match_operand:SI 2 "general_operand" ""))
1815 (match_operand:SI 3 "nonmemory_operand" ""))]
1819 int start_bit = INTVAL (operands[2]);
1820 int width = INTVAL (operands[1]);
1821 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1822 rtx target, subtarget;
1824 target = operands[0];
1825 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1826 subreg as the final target. */
1827 if (GET_CODE (target) == SUBREG)
1829 subtarget = gen_reg_rtx (SImode);
1830 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1831 < GET_MODE_SIZE (SImode))
1832 target = SUBREG_REG (target);
1837 if (GET_CODE (operands[3]) == CONST_INT)
1839 /* Since we are inserting a known constant, we may be able to
1840 reduce the number of bits that we have to clear so that
1841 the mask becomes simple. */
1842 /* ??? This code does not check to see if the new mask is actually
1843 simpler. It may not be. */
1844 rtx op1 = gen_reg_rtx (SImode);
1845 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1846 start of this pattern. */
1847 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1848 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1850 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1851 emit_insn (gen_iorsi3 (subtarget, op1,
1852 GEN_INT (op3_value << start_bit)));
1854 else if (start_bit == 0
1855 && ! (const_ok_for_arm (mask)
1856 || const_ok_for_arm (~mask)))
1858 /* A Trick, since we are setting the bottom bits in the word,
1859 we can shift operand[3] up, operand[0] down, OR them together
1860 and rotate the result back again. This takes 3 insns, and
1861 the third might be mergable into another op. */
1862 /* The shift up copes with the possibility that operand[3] is
1863 wider than the bitfield. */
1864 rtx op0 = gen_reg_rtx (SImode);
1865 rtx op1 = gen_reg_rtx (SImode);
1867 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1868 emit_insn (gen_lshrsi3 (op1, operands[0], operands[1]));
1869 emit_insn (gen_iorsi3 (op1, op1, op0));
1870 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1872 else if ((width + start_bit == 32)
1873 && ! (const_ok_for_arm (mask)
1874 || const_ok_for_arm (~mask)))
1876 /* Similar trick, but slightly less efficient. */
1878 rtx op0 = gen_reg_rtx (SImode);
1879 rtx op1 = gen_reg_rtx (SImode);
1881 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1882 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1883 emit_insn (gen_lshrsi3 (op1, op1, operands[1]));
1884 emit_insn (gen_iorsi3 (subtarget, op1, op0));
1888 rtx op0 = GEN_INT (mask);
1889 rtx op1 = gen_reg_rtx (SImode);
1890 rtx op2 = gen_reg_rtx (SImode);
1892 if (! (const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1894 rtx tmp = gen_reg_rtx (SImode);
1896 emit_insn (gen_movsi (tmp, op0));
1900 /* Mask out any bits in operand[3] that are not needed. */
1901 emit_insn (gen_andsi3 (op1, operands[3], op0));
1903 if (GET_CODE (op0) == CONST_INT
1904 && (const_ok_for_arm (mask << start_bit)
1905 || const_ok_for_arm (~ (mask << start_bit))))
1907 op0 = GEN_INT (~(mask << start_bit));
1908 emit_insn (gen_andsi3 (op2, operands[0], op0));
1912 if (GET_CODE (op0) == CONST_INT)
1914 rtx tmp = gen_reg_rtx (SImode);
1916 emit_insn (gen_movsi (tmp, op0));
1921 emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1923 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1927 emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1929 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1932 if (subtarget != target)
1934 /* If TARGET is still a SUBREG, then it must be wider than a word,
1935 so we must be careful only to set the subword we were asked to. */
1936 if (GET_CODE (target) == SUBREG)
1937 emit_move_insn (target, subtarget);
1939 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1946 ;; constants for op 2 will never be given to these patterns.
1947 (define_insn "*anddi_notdi_di"
1948 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1949 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1950 (match_operand:DI 1 "s_register_operand" "0,r")))]
1953 [(set_attr "length" "8")])
1955 (define_insn "*anddi_notzesidi_di"
1956 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1957 (and:DI (not:DI (zero_extend:DI
1958 (match_operand:SI 2 "s_register_operand" "r,r")))
1959 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1962 bic%?\\t%Q0, %Q1, %2
1964 [(set_attr "length" "4,8")])
1966 (define_insn "*anddi_notsesidi_di"
1967 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1968 (and:DI (not:DI (sign_extend:DI
1969 (match_operand:SI 2 "s_register_operand" "r,r")))
1970 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1973 [(set_attr "length" "8")])
1975 (define_insn "andsi_notsi_si"
1976 [(set (match_operand:SI 0 "s_register_operand" "=r")
1977 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1978 (match_operand:SI 1 "s_register_operand" "r")))]
1980 "bic%?\\t%0, %1, %2")
1982 (define_insn "bicsi3"
1983 [(set (match_operand:SI 0 "register_operand" "=l")
1984 (and:SI (not:SI (match_operand:SI 1 "register_operand" "l"))
1985 (match_operand:SI 2 "register_operand" "0")))]
1988 [(set_attr "length" "2")]
1991 (define_insn "andsi_not_shiftsi_si"
1992 [(set (match_operand:SI 0 "s_register_operand" "=r")
1993 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1994 [(match_operand:SI 2 "s_register_operand" "r")
1995 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1996 (match_operand:SI 1 "s_register_operand" "r")))]
1998 "bic%?\\t%0, %1, %2%S4"
2001 (define_insn "*andsi_notsi_si_compare0"
2002 [(set (reg:CC_NOOV 24)
2004 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2005 (match_operand:SI 1 "s_register_operand" "r"))
2007 (set (match_operand:SI 0 "s_register_operand" "=r")
2008 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2010 "bic%?s\\t%0, %1, %2"
2011 [(set_attr "conds" "set")])
2013 (define_insn "*andsi_notsi_si_compare0_scratch"
2014 [(set (reg:CC_NOOV 24)
2016 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2017 (match_operand:SI 1 "s_register_operand" "r"))
2019 (clobber (match_scratch:SI 0 "=r"))]
2021 "bic%?s\\t%0, %1, %2"
2022 [(set_attr "conds" "set")])
2024 (define_insn "iordi3"
2025 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2026 (ior:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2027 (match_operand:DI 2 "s_register_operand" "r,r")))]
2030 [(set_attr "length" "8")]
2033 (define_insn "*iordi_zesidi_di"
2034 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2035 (ior:DI (zero_extend:DI
2036 (match_operand:SI 2 "s_register_operand" "r,r"))
2037 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2040 orr%?\\t%Q0, %Q1, %2
2042 [(set_attr "length" "4,8")]
2045 (define_insn "*iordi_sesidi_di"
2046 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2047 (ior:DI (sign_extend:DI
2048 (match_operand:SI 2 "s_register_operand" "r,r"))
2049 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2052 [(set_attr "length" "8")]
2055 (define_expand "iorsi3"
2056 [(set (match_operand:SI 0 "s_register_operand" "")
2057 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2058 (match_operand:SI 2 "reg_or_int_operand" "")))]
2061 if (GET_CODE (operands[2]) == CONST_INT)
2065 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2067 (reload_in_progress || reload_completed
2068 ? 0 : preserve_subexpressions_p ()));
2071 else /* TARGET_THUMB */
2072 operands [2] = force_reg (SImode, operands [2]);
2077 (define_insn "*arm_iorsi3"
2078 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2079 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
2080 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
2085 [(set_attr "length" "4,16")]
2088 (define_insn "*thumb_iorsi3"
2089 [(set (match_operand:SI 0 "register_operand" "=l")
2090 (ior:SI (match_operand:SI 1 "register_operand" "%0")
2091 (match_operand:SI 2 "register_operand" "l")))]
2094 [(set_attr "length" "2")]
2098 [(set (match_operand:SI 0 "s_register_operand" "")
2099 (ior:SI (match_operand:SI 1 "s_register_operand" "")
2100 (match_operand:SI 2 "const_int_operand" "")))]
2101 "TARGET_ARM && (! const_ok_for_arm (INTVAL (operands[2])))"
2102 [(clobber (const_int 0))]
2104 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2109 (define_insn "*iorsi3_compare0"
2110 [(set (reg:CC_NOOV 24)
2111 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2112 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2114 (set (match_operand:SI 0 "s_register_operand" "=r")
2115 (ior:SI (match_dup 1) (match_dup 2)))]
2117 "orr%?s\\t%0, %1, %2"
2118 [(set_attr "conds" "set")]
2121 (define_insn "*iorsi3_compare0_scratch"
2122 [(set (reg:CC_NOOV 24)
2123 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
2124 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2126 (clobber (match_scratch:SI 0 "=r"))]
2128 "orr%?s\\t%0, %1, %2"
2129 [(set_attr "conds" "set")])
2131 (define_insn "xordi3"
2132 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2133 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,r")
2134 (match_operand:DI 2 "s_register_operand" "r,r")))]
2137 [(set_attr "length" "8")]
2140 (define_insn "*xordi_zesidi_di"
2141 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2142 (xor:DI (zero_extend:DI
2143 (match_operand:SI 2 "s_register_operand" "r,r"))
2144 (match_operand:DI 1 "s_register_operand" "0,?r")))]
2147 eor%?\\t%Q0, %Q1, %2
2149 [(set_attr "length" "4,8")]
2152 (define_insn "*xordi_sesidi_di"
2153 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2154 (xor:DI (sign_extend:DI
2155 (match_operand:SI 2 "s_register_operand" "r,r"))
2156 (match_operand:DI 1 "s_register_operand" "?r,0")))]
2159 [(set_attr "length" "8")]
2162 (define_expand "xorsi3"
2163 [(set (match_operand:SI 0 "s_register_operand" "")
2164 (xor:SI (match_operand:SI 1 "s_register_operand" "")
2165 (match_operand:SI 2 "arm_rhs_operand" "")))]
2168 if (GET_CODE (operands[2]) == CONST_INT)
2169 operands[2] = force_reg (SImode, operands[2]);
2173 (define_insn "*arm_xorsi3"
2174 [(set (match_operand:SI 0 "s_register_operand" "=r")
2175 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2176 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
2178 "eor%?\\t%0, %1, %2"
2181 (define_insn "*thumb_xorsi3"
2182 [(set (match_operand:SI 0 "register_operand" "=l")
2183 (xor:SI (match_operand:SI 1 "register_operand" "%0")
2184 (match_operand:SI 2 "register_operand" "l")))]
2187 [(set_attr "length" "2")]
2190 (define_insn "*xorsi3_compare0"
2191 [(set (reg:CC_NOOV 24)
2192 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
2193 (match_operand:SI 2 "arm_rhs_operand" "rI"))
2195 (set (match_operand:SI 0 "s_register_operand" "=r")
2196 (xor:SI (match_dup 1) (match_dup 2)))]
2198 "eor%?s\\t%0, %1, %2"
2199 [(set_attr "conds" "set")])
2201 (define_insn "*xorsi3_compare0_scratch"
2202 [(set (reg:CC_NOOV 24)
2203 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
2204 (match_operand:SI 1 "arm_rhs_operand" "rI"))
2208 [(set_attr "conds" "set")]
2211 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
2212 ;; (NOT D) we can sometimes merge the final NOT into one of the following
2216 [(set (match_operand:SI 0 "s_register_operand" "=r")
2217 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2218 (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
2219 (match_operand:SI 3 "arm_rhs_operand" "rI")))
2220 (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
2222 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2223 (not:SI (match_dup 3))))
2224 (set (match_dup 0) (not:SI (match_dup 4)))]
2228 (define_insn "*andsi_iorsi3_notsi"
2229 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
2230 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
2231 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
2232 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
2234 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
2235 [(set_attr "length" "8")]
2240 ;; Minimum and maximum insns
2242 (define_insn "smaxsi3"
2243 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2244 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2245 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2246 (clobber (reg:CC 24))]
2249 cmp\\t%1, %2\;movlt\\t%0, %2
2250 cmp\\t%1, %2\;movge\\t%0, %1
2251 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
2252 [(set_attr "conds" "clob")
2253 (set_attr "length" "8,8,12")]
2256 (define_insn "sminsi3"
2257 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2258 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2259 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2260 (clobber (reg:CC 24))]
2263 cmp\\t%1, %2\;movge\\t%0, %2
2264 cmp\\t%1, %2\;movlt\\t%0, %1
2265 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
2266 [(set_attr "conds" "clob")
2267 (set_attr "length" "8,8,12")])
2269 (define_insn "umaxsi3"
2270 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2271 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2272 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2273 (clobber (reg:CC 24))]
2276 cmp\\t%1, %2\;movcc\\t%0, %2
2277 cmp\\t%1, %2\;movcs\\t%0, %1
2278 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
2279 [(set_attr "conds" "clob")
2280 (set_attr "length" "8,8,12")])
2282 (define_insn "uminsi3"
2283 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
2284 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
2285 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
2286 (clobber (reg:CC 24))]
2289 cmp\\t%1, %2\;movcs\\t%0, %2
2290 cmp\\t%1, %2\;movcc\\t%0, %1
2291 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
2292 [(set_attr "conds" "clob")
2293 (set_attr "length" "8,8,12")])
2295 (define_insn "*store_minmaxsi"
2296 [(set (match_operand:SI 0 "memory_operand" "=m")
2297 (match_operator:SI 3 "minmax_operator"
2298 [(match_operand:SI 1 "s_register_operand" "r")
2299 (match_operand:SI 2 "s_register_operand" "r")]))
2300 (clobber (reg:CC 24))]
2303 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2305 output_asm_insn (\"cmp\\t%1, %2\", operands);
2306 output_asm_insn (\"str%d3\\t%1, %0\", operands);
2307 output_asm_insn (\"str%D3\\t%2, %0\", operands);
2310 [(set_attr "conds" "clob")
2311 (set_attr "length" "12")
2312 (set_attr "type" "store1")])
2314 ; Reject the frame pointer in operand[1], since reloading this after
2315 ; it has been eliminated can cause carnage.
2316 (define_insn "*minmax_arithsi"
2317 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2318 (match_operator:SI 4 "shiftable_operator"
2319 [(match_operator:SI 5 "minmax_operator"
2320 [(match_operand:SI 2 "s_register_operand" "r,r")
2321 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
2322 (match_operand:SI 1 "s_register_operand" "0,?r")]))
2323 (clobber (reg:CC 24))]
2325 && (GET_CODE (operands[1]) != REG
2326 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2327 && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2330 enum rtx_code code = GET_CODE (operands[4]);
2332 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2334 output_asm_insn (\"cmp\\t%2, %3\", operands);
2335 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
2336 if (which_alternative != 0 || operands[3] != const0_rtx
2337 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
2338 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
2342 [(set_attr "conds" "clob")
2343 (set_attr "length" "12")])
2346 ;; Shift and rotation insns
2348 (define_expand "ashlsi3"
2349 [(set (match_operand:SI 0 "s_register_operand" "")
2350 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
2351 (match_operand:SI 2 "arm_rhs_operand" "")))]
2354 if (GET_CODE (operands[2]) == CONST_INT
2355 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2357 emit_insn (gen_movsi (operands[0], const0_rtx));
2363 (define_insn "*thumb_ashlsi3"
2364 [(set (match_operand:SI 0 "register_operand" "=l,l")
2365 (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2366 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2369 [(set_attr "length" "2")]
2372 (define_expand "ashrsi3"
2373 [(set (match_operand:SI 0 "s_register_operand" "")
2374 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2375 (match_operand:SI 2 "arm_rhs_operand" "")))]
2378 if (GET_CODE (operands[2]) == CONST_INT
2379 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2380 operands[2] = GEN_INT (31);
2384 (define_insn "*thumb_ashrsi3"
2385 [(set (match_operand:SI 0 "register_operand" "=l,l")
2386 (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2387 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2390 [(set_attr "length" "2")]
2393 (define_expand "lshrsi3"
2394 [(set (match_operand:SI 0 "s_register_operand" "")
2395 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
2396 (match_operand:SI 2 "arm_rhs_operand" "")))]
2399 if (GET_CODE (operands[2]) == CONST_INT
2400 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2402 emit_insn (gen_movsi (operands[0], const0_rtx));
2408 (define_insn "*thumb_lshrsi3"
2409 [(set (match_operand:SI 0 "register_operand" "=l,l")
2410 (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2411 (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2414 [(set_attr "length" "2")]
2417 (define_expand "rotlsi3"
2418 [(set (match_operand:SI 0 "s_register_operand" "")
2419 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2420 (match_operand:SI 2 "reg_or_int_operand" "")))]
2423 if (GET_CODE (operands[2]) == CONST_INT)
2424 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2427 rtx reg = gen_reg_rtx (SImode);
2428 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2434 (define_expand "rotrsi3"
2435 [(set (match_operand:SI 0 "s_register_operand" "")
2436 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
2437 (match_operand:SI 2 "arm_rhs_operand" "")))]
2442 if (GET_CODE (operands[2]) == CONST_INT
2443 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2444 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2446 else /* TARGET_THUMB */
2448 if (GET_CODE (operands [2]) == CONST_INT)
2449 operands [2] = force_reg (SImode, operands[2]);
2454 (define_insn "*thumb_rotrsi3"
2455 [(set (match_operand:SI 0 "register_operand" "=l")
2456 (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2457 (match_operand:SI 2 "register_operand" "l")))]
2460 [(set_attr "length" "2")]
2463 (define_insn "*arm_shiftsi3"
2464 [(set (match_operand:SI 0 "s_register_operand" "=r")
2465 (match_operator:SI 3 "shift_operator"
2466 [(match_operand:SI 1 "s_register_operand" "r")
2467 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
2472 (define_insn "*shiftsi3_compare0"
2473 [(set (reg:CC_NOOV 24)
2474 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2475 [(match_operand:SI 1 "s_register_operand" "r")
2476 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2478 (set (match_operand:SI 0 "s_register_operand" "=r")
2479 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2481 "mov%?s\\t%0, %1%S3"
2482 [(set_attr "conds" "set")
2485 (define_insn "*shiftsi3_compare0_scratch"
2486 [(set (reg:CC_NOOV 24)
2487 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
2488 [(match_operand:SI 1 "s_register_operand" "r")
2489 (match_operand:SI 2 "arm_rhs_operand" "rM")])
2491 (clobber (match_scratch:SI 0 "=r"))]
2493 "mov%?s\\t%0, %1%S3"
2494 [(set_attr "conds" "set")
2497 (define_insn "*notsi_shiftsi"
2498 [(set (match_operand:SI 0 "s_register_operand" "=r")
2499 (not:SI (match_operator:SI 3 "shift_operator"
2500 [(match_operand:SI 1 "s_register_operand" "r")
2501 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
2504 [(set_attr "conds" "set")
2507 (define_insn "*notsi_shiftsi_compare0"
2508 [(set (reg:CC_NOOV 24)
2509 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2510 [(match_operand:SI 1 "s_register_operand" "r")
2511 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2513 (set (match_operand:SI 0 "s_register_operand" "=r")
2514 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2516 "mvn%?s\\t%0, %1%S3"
2517 [(set_attr "conds" "set")
2520 (define_insn "*not_shiftsi_compare0_scratch"
2521 [(set (reg:CC_NOOV 24)
2522 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
2523 [(match_operand:SI 1 "s_register_operand" "r")
2524 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
2526 (clobber (match_scratch:SI 0 "=r"))]
2528 "mvn%?s\\t%0, %1%S3"
2529 [(set_attr "conds" "set")
2532 ;; We don't really have extzv, but defining this using shifts helps
2533 ;; to reduce register pressure later on.
2535 (define_expand "extzv"
2537 (ashift:SI (match_operand:SI 1 "register_operand" "")
2538 (match_operand:SI 2 "const_int_operand" "")))
2539 (set (match_operand:SI 0 "register_operand" "")
2540 (lshiftrt:SI (match_dup 4)
2541 (match_operand:SI 3 "const_int_operand" "")))
2546 HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2547 HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2549 operands[3] = GEN_INT (rshift);
2553 emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2557 operands[2] = GEN_INT (lshift);
2558 operands[4] = gen_reg_rtx (SImode);
2564 ;; Unary arithmetic insns
2566 (define_expand "negdi2"
2568 [(set (match_operand:DI 0 "s_register_operand" "")
2569 (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2570 (clobber (reg:CC 24))
2577 if (GET_CODE (operands[1]) != REG)
2578 operands[1] = force_reg (SImode, operands[1]);
2583 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2584 ;; The second alternative is to allow the common case of a *full* overlap.
2585 (define_insn "*arm_negdi2"
2586 [(set (match_operand:DI 0 "s_register_operand" "=&r,r")
2587 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))
2588 (clobber (reg:CC 24))
2591 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
2592 [(set_attr "conds" "clob")
2593 (set_attr "length" "8")]
2596 (define_insn "*thumb_negdi2"
2597 [(set (match_operand:DI 0 "register_operand" "=&l")
2598 (neg:DI (match_operand:DI 1 "register_operand" "l")))
2599 (clobber (reg:CC 24))
2602 "mov\\t%R0, #0\;neg\\t%Q0, %Q1\;sbc\\t%R0, %R1"
2603 [(set_attr "length" "6")]
2606 (define_expand "negsi2"
2607 [(set (match_operand:SI 0 "s_register_operand" "")
2608 (neg:SI (match_operand:SI 1 "s_register_operand" "")))]
2613 (define_insn "*arm_negsi2"
2614 [(set (match_operand:SI 0 "s_register_operand" "=r")
2615 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2617 "rsb%?\\t%0, %1, #0"
2620 (define_insn "*thumb_negsi2"
2621 [(set (match_operand:SI 0 "register_operand" "=l")
2622 (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2625 [(set_attr "length" "2")]
2628 (define_insn "negsf2"
2629 [(set (match_operand:SF 0 "s_register_operand" "=f")
2630 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
2631 "TARGET_ARM && TARGET_HARD_FLOAT"
2633 [(set_attr "type" "ffarith")]
2636 (define_insn "negdf2"
2637 [(set (match_operand:DF 0 "s_register_operand" "=f")
2638 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
2639 "TARGET_ARM && TARGET_HARD_FLOAT"
2641 [(set_attr "type" "ffarith")])
2643 (define_insn "*negdf_esfdf"
2644 [(set (match_operand:DF 0 "s_register_operand" "=f")
2645 (neg:DF (float_extend:DF
2646 (match_operand:SF 1 "s_register_operand" "f"))))]
2647 "TARGET_ARM && TARGET_HARD_FLOAT"
2649 [(set_attr "type" "ffarith")])
2651 (define_insn "negxf2"
2652 [(set (match_operand:XF 0 "s_register_operand" "=f")
2653 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
2654 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2656 [(set_attr "type" "ffarith")])
2658 ;; abssi2 doesn't really clobber the condition codes if a different register
2659 ;; is being set. To keep things simple, assume during rtl manipulations that
2660 ;; it does, but tell the final scan operator the truth. Similarly for
2663 (define_insn "abssi2"
2664 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2665 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
2666 (clobber (reg:CC 24))]
2669 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
2670 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
2671 [(set_attr "conds" "clob,*")
2672 (set_attr "length" "8")]
2675 (define_insn "*neg_abssi2"
2676 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
2677 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
2678 (clobber (reg:CC 24))]
2681 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
2682 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
2683 [(set_attr "conds" "clob,*")
2684 (set_attr "length" "8")]
2687 (define_insn "abssf2"
2688 [(set (match_operand:SF 0 "s_register_operand" "=f")
2689 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
2690 "TARGET_ARM && TARGET_HARD_FLOAT"
2692 [(set_attr "type" "ffarith")])
2694 (define_insn "absdf2"
2695 [(set (match_operand:DF 0 "s_register_operand" "=f")
2696 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
2697 "TARGET_ARM && TARGET_HARD_FLOAT"
2699 [(set_attr "type" "ffarith")])
2701 (define_insn "*absdf_esfdf"
2702 [(set (match_operand:DF 0 "s_register_operand" "=f")
2703 (abs:DF (float_extend:DF
2704 (match_operand:SF 1 "s_register_operand" "f"))))]
2705 "TARGET_ARM && TARGET_HARD_FLOAT"
2707 [(set_attr "type" "ffarith")])
2709 (define_insn "absxf2"
2710 [(set (match_operand:XF 0 "s_register_operand" "=f")
2711 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
2712 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2714 [(set_attr "type" "ffarith")])
2716 (define_insn "sqrtsf2"
2717 [(set (match_operand:SF 0 "s_register_operand" "=f")
2718 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
2719 "TARGET_ARM && TARGET_HARD_FLOAT"
2721 [(set_attr "type" "float_em")])
2723 (define_insn "sqrtdf2"
2724 [(set (match_operand:DF 0 "s_register_operand" "=f")
2725 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
2726 "TARGET_ARM && TARGET_HARD_FLOAT"
2728 [(set_attr "type" "float_em")])
2730 (define_insn "*sqrtdf_esfdf"
2731 [(set (match_operand:DF 0 "s_register_operand" "=f")
2732 (sqrt:DF (float_extend:DF
2733 (match_operand:SF 1 "s_register_operand" "f"))))]
2734 "TARGET_ARM && TARGET_HARD_FLOAT"
2736 [(set_attr "type" "float_em")])
2738 (define_insn "sqrtxf2"
2739 [(set (match_operand:XF 0 "s_register_operand" "=f")
2740 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
2741 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2743 [(set_attr "type" "float_em")])
2745 ;; SIN COS TAN and family are always emulated, so it's probably better
2746 ;; to always call a library function.
2747 ;(define_insn "sinsf2"
2748 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2749 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
2750 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2752 ;[(set_attr "type" "float_em")])
2754 ;(define_insn "sindf2"
2755 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2756 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
2757 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2759 ;[(set_attr "type" "float_em")])
2761 ;(define_insn "*sindf_esfdf"
2762 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2763 ; (unspec:DF [(float_extend:DF
2764 ; (match_operand:SF 1 "s_register_operand" "f"))] 0))]
2765 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2767 ;[(set_attr "type" "float_em")])
2769 ;(define_insn "sinxf2"
2770 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2771 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
2772 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2774 ;[(set_attr "type" "float_em")])
2776 ;(define_insn "cossf2"
2777 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
2778 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
2779 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2781 ;[(set_attr "type" "float_em")])
2783 ;(define_insn "cosdf2"
2784 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2785 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
2786 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2788 ;[(set_attr "type" "float_em")])
2790 ;(define_insn "*cosdf_esfdf"
2791 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2792 ; (unspec:DF [(float_extend:DF
2793 ; (match_operand:SF 1 "s_register_operand" "f"))] 1))]
2794 ; "TARGET_ARM && TARGET_HARD_FLOAT"
2796 ;[(set_attr "type" "float_em")])
2798 ;(define_insn "cosxf2"
2799 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2800 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
2801 ; "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2803 ;[(set_attr "type" "float_em")])
2805 (define_insn "one_cmpldi2"
2806 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2807 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2810 [(set_attr "length" "8")]
2813 (define_expand "one_cmplsi2"
2814 [(set (match_operand:SI 0 "s_register_operand" "")
2815 (not:SI (match_operand:SI 1 "s_register_operand" "")))]
2820 (define_insn "*arm_one_cmplsi2"
2821 [(set (match_operand:SI 0 "s_register_operand" "=r")
2822 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2827 (define_insn "*thumb_one_cmplsi2"
2828 [(set (match_operand:SI 0 "register_operand" "=l")
2829 (not:SI (match_operand:SI 1 "register_operand" "l")))]
2832 [(set_attr "length" "2")]
2835 (define_insn "*notsi_compare0"
2836 [(set (reg:CC_NOOV 24)
2837 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2839 (set (match_operand:SI 0 "s_register_operand" "=r")
2840 (not:SI (match_dup 1)))]
2843 [(set_attr "conds" "set")]
2846 (define_insn "*notsi_compare0_scratch"
2847 [(set (reg:CC_NOOV 24)
2848 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2850 (clobber (match_scratch:SI 0 "=r"))]
2853 [(set_attr "conds" "set")]
2856 ;; Fixed <--> Floating conversion insns
2858 (define_insn "floatsisf2"
2859 [(set (match_operand:SF 0 "s_register_operand" "=f")
2860 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2861 "TARGET_ARM && TARGET_HARD_FLOAT"
2863 [(set_attr "type" "r_2_f")])
2865 (define_insn "floatsidf2"
2866 [(set (match_operand:DF 0 "s_register_operand" "=f")
2867 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2868 "TARGET_ARM && TARGET_HARD_FLOAT"
2870 [(set_attr "type" "r_2_f")])
2872 (define_insn "floatsixf2"
2873 [(set (match_operand:XF 0 "s_register_operand" "=f")
2874 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
2875 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2877 [(set_attr "type" "r_2_f")])
2879 (define_insn "fix_truncsfsi2"
2880 [(set (match_operand:SI 0 "s_register_operand" "=r")
2881 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2882 "TARGET_ARM && TARGET_HARD_FLOAT"
2884 [(set_attr "type" "f_2_r")])
2886 (define_insn "fix_truncdfsi2"
2887 [(set (match_operand:SI 0 "s_register_operand" "=r")
2888 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2889 "TARGET_ARM && TARGET_HARD_FLOAT"
2891 [(set_attr "type" "f_2_r")])
2893 (define_insn "fix_truncxfsi2"
2894 [(set (match_operand:SI 0 "s_register_operand" "=r")
2895 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
2896 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2898 [(set_attr "type" "f_2_r")])
2902 (define_insn "truncdfsf2"
2903 [(set (match_operand:SF 0 "s_register_operand" "=f")
2905 (match_operand:DF 1 "s_register_operand" "f")))]
2906 "TARGET_ARM && TARGET_HARD_FLOAT"
2908 [(set_attr "type" "ffarith")])
2910 (define_insn "truncxfsf2"
2911 [(set (match_operand:SF 0 "s_register_operand" "=f")
2913 (match_operand:XF 1 "s_register_operand" "f")))]
2914 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2916 [(set_attr "type" "ffarith")])
2918 (define_insn "truncxfdf2"
2919 [(set (match_operand:DF 0 "s_register_operand" "=f")
2921 (match_operand:XF 1 "s_register_operand" "f")))]
2922 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2924 [(set_attr "type" "ffarith")])
2926 ;; Zero and sign extension instructions.
2928 (define_insn "zero_extendsidi2"
2929 [(set (match_operand:DI 0 "s_register_operand" "=r")
2930 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2933 if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2934 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2935 return \"mov%?\\t%R0, #0\";
2937 [(set_attr "length" "8")])
2939 (define_insn "zero_extendqidi2"
2940 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2941 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2944 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2945 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2946 [(set_attr "length" "8")
2947 (set_attr "type" "*,load")
2948 (set_attr "pool_range" "*,4092")
2949 (set_attr "neg_pool_range" "*,4084")]
2952 (define_insn "extendsidi2"
2953 [(set (match_operand:DI 0 "s_register_operand" "=r")
2954 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2957 if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2958 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2959 return \"mov%?\\t%R0, %Q0, asr #31\";
2961 [(set_attr "length" "8")
2964 (define_expand "zero_extendhisi2"
2966 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "") (const_int 16)))
2967 (set (match_operand:SI 0 "s_register_operand" "")
2968 (lshiftrt:SI (match_dup 2) (const_int 16)))]
2974 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2976 /* Note: We do not have to worry about TARGET_MMU_TRAPS
2977 here because the insn below will generate an LDRH instruction
2978 rather than an LDR instruction, so we cannot get an unaligned
2980 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2981 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
2984 if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2986 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2989 if (! s_register_operand (operands[1], HImode))
2990 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2991 operands[1] = gen_lowpart (SImode, operands[1]);
2992 operands[2] = gen_reg_rtx (SImode);
2994 else /* TARGET_THUMB */
2996 if (GET_CODE (operands[1]) == MEM)
3000 tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3001 tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3008 if (! s_register_operand (operands[1], HImode))
3009 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3010 operands[1] = gen_lowpart (SImode, operands[1]);
3011 operands[2] = gen_reg_rtx (SImode);
3013 ops[0] = operands[2];
3014 ops[1] = operands[1];
3015 ops[2] = GEN_INT (16);
3017 emit_insn (gen_rtx_SET (VOIDmode, ops[0], gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3019 ops[0] = operands[0];
3020 ops[1] = operands[2];
3021 ops[2] = GEN_INT (16);
3023 emit_insn (gen_rtx_SET (VOIDmode, ops[0], gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3030 (define_insn "*thumb_zero_extendhisi2"
3031 [(set (match_operand:SI 0 "register_operand" "=l")
3032 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3035 rtx mem = XEXP (operands[1], 0);
3037 if (GET_CODE (mem) == CONST)
3038 mem = XEXP (mem, 0);
3040 if (GET_CODE (mem) == LABEL_REF)
3041 return \"ldr\\t%0, %1\";
3043 if (GET_CODE (mem) == PLUS)
3045 rtx a = XEXP (mem, 0);
3046 rtx b = XEXP (mem, 1);
3048 /* This can happen due to bugs in reload. */
3049 if (GET_CODE (a) == REG && REGNO (a) == SP_REGNUM)
3052 ops[0] = operands[0];
3055 output_asm_insn (\"mov %0, %1\", ops);
3057 XEXP (mem, 0) = operands[0];
3060 else if ( GET_CODE (a) == LABEL_REF
3061 && GET_CODE (b) == CONST_INT)
3062 return \"ldr\\t%0, %1\";
3065 return \"ldrh\\t%0, %1\";
3067 [(set_attr "length" "4")
3068 (set_attr "type" "load")
3069 (set_attr "pool_range" "60")]
3072 (define_insn "*arm_zero_extendhisi2"
3073 [(set (match_operand:SI 0 "s_register_operand" "=r")
3074 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3075 "TARGET_ARM && arm_arch4"
3077 [(set_attr "type" "load")
3078 (set_attr "pool_range" "256")
3079 (set_attr "neg_pool_range" "244")]
3083 [(set (match_operand:SI 0 "s_register_operand" "")
3084 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3085 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3086 "TARGET_ARM && (! arm_arch4)"
3087 [(set (match_dup 2) (match_dup 1))
3088 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
3091 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3096 [(set (match_operand:SI 0 "s_register_operand" "")
3097 (match_operator:SI 3 "shiftable_operator"
3098 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3099 (match_operand:SI 4 "s_register_operand" "")]))
3100 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3101 "TARGET_ARM && (! arm_arch4)"
3102 [(set (match_dup 2) (match_dup 1))
3105 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3108 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3112 (define_expand "zero_extendqisi2"
3113 [(set (match_operand:SI 0 "s_register_operand" "")
3114 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3117 if (GET_CODE (operands[1]) != MEM)
3121 emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
3124 else /* TARGET_THUMB */
3126 rtx temp = gen_reg_rtx (SImode);
3129 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3130 operands[1] = gen_lowpart (SImode, operands[1]);
3133 ops[1] = operands[1];
3134 ops[2] = GEN_INT (24);
3136 emit_insn (gen_rtx_SET (VOIDmode, ops[0], gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3138 ops[0] = operands[0];
3140 ops[2] = GEN_INT (24);
3142 emit_insn (gen_rtx_SET (VOIDmode, ops[0], gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3148 (define_insn "*thumb_zero_extendqisi2"
3149 [(set (match_operand:SI 0 "register_operand" "=l")
3150 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3153 [(set_attr "length" "2")
3154 (set_attr "type" "load")
3155 (set_attr "pool_range" "32")]
3158 (define_insn "*arm_zero_extendqisi2"
3159 [(set (match_operand:SI 0 "s_register_operand" "=r")
3160 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3162 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
3163 [(set_attr "type" "load")
3164 (set_attr "pool_range" "4096")
3165 (set_attr "neg_pool_range" "4084")]
3169 [(set (match_operand:SI 0 "s_register_operand" "")
3170 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3171 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3172 "TARGET_ARM && (GET_CODE (operands[1]) != MEM)"
3173 [(set (match_dup 2) (match_dup 1))
3174 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
3178 (define_insn "*compareqi_eq0"
3180 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3184 [(set_attr "conds" "set")]
3187 (define_expand "extendhisi2"
3189 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3191 (set (match_operand:SI 0 "s_register_operand" "")
3192 (ashiftrt:SI (match_dup 2)
3197 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3199 /* Note: We do not have to worry about TARGET_MMU_TRAPS
3200 here because the insn below will generate an LDRH instruction
3201 rather than an LDR instruction, so we cannot get an unaligned
3203 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3204 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3208 if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3210 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3213 if (! s_register_operand (operands[1], HImode))
3214 operands[1] = copy_to_mode_reg (HImode, operands[1]);
3215 operands[1] = gen_lowpart (SImode, operands[1]);
3216 operands[2] = gen_reg_rtx (SImode);
3222 ops[0] = operands[2];
3223 ops[1] = operands[1];
3224 ops[2] = GEN_INT (16);
3226 emit_insn (gen_rtx_SET (VOIDmode, ops[0], gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3228 ops[0] = operands[0];
3229 ops[1] = operands[2];
3230 ops[2] = GEN_INT (16);
3232 emit_insn (gen_rtx_SET (VOIDmode, ops[0], gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3239 (define_insn "*thumb_extendhisi2_insn"
3240 [(set (match_operand:SI 0 "register_operand" "=l")
3241 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))
3242 (clobber (match_scratch:SI 2 "=&l"))]
3247 rtx mem = XEXP (operands[1], 0);
3249 /* This code used to try to use 'V', and fix the address only if it was
3250 offsettable, but this fails for e.g. REG+48 because 48 is outside the
3251 range of QImode offsets, and offsettable_address_p does a QImode
3254 if (GET_CODE (mem) == CONST)
3255 mem = XEXP (mem, 0);
3257 if (GET_CODE (mem) == LABEL_REF)
3258 return \"ldr\\t%0, %1\";
3260 if (GET_CODE (mem) == PLUS)
3262 rtx a = XEXP (mem, 0);
3263 rtx b = XEXP (mem, 1);
3265 if (GET_CODE (a) == LABEL_REF
3266 && GET_CODE (b) == CONST_INT)
3267 return \"ldr\\t%0, %1\";
3269 if (GET_CODE (b) == REG)
3270 return \"ldrsh\\t%0, %1\";
3278 ops[2] = const0_rtx;
3281 if (GET_CODE (ops[1]) != REG)
3287 ops[0] = operands[0];
3288 ops[3] = operands[2];
3289 output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3292 [(set_attr "length" "4")
3293 (set_attr "type" "load")
3294 (set_attr "pool_range" "1020")]
3297 (define_expand "extendhisi2_mem"
3298 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3300 (zero_extend:SI (match_dup 7)))
3301 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
3302 (set (match_operand:SI 0 "" "")
3303 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
3308 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3310 mem1 = gen_rtx_MEM (QImode, addr);
3311 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3312 RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
3313 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3314 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3315 RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
3316 operands[0] = gen_lowpart (SImode, operands[0]);
3318 operands[2] = gen_reg_rtx (SImode);
3319 operands[3] = gen_reg_rtx (SImode);
3320 operands[6] = gen_reg_rtx (SImode);
3323 if (BYTES_BIG_ENDIAN)
3325 operands[4] = operands[2];
3326 operands[5] = operands[3];
3330 operands[4] = operands[3];
3331 operands[5] = operands[2];
3336 (define_insn "*arm_extendhisi_insn"
3337 [(set (match_operand:SI 0 "s_register_operand" "=r")
3338 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
3339 "TARGET_ARM && arm_arch4"
3341 [(set_attr "type" "load")
3342 (set_attr "pool_range" "256")
3343 (set_attr "neg_pool_range" "244")]
3347 [(set (match_operand:SI 0 "s_register_operand" "")
3348 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3349 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3350 "TARGET_ARM && (! arm_arch4)"
3351 [(set (match_dup 2) (match_dup 1))
3352 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
3354 if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3360 [(set (match_operand:SI 0 "s_register_operand" "")
3361 (match_operator:SI 3 "shiftable_operator"
3362 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3363 (match_operand:SI 4 "s_register_operand" "")]))
3364 (clobber (match_operand:SI 2 "s_register_operand" ""))]
3365 "TARGET_ARM && (! arm_arch4)"
3366 [(set (match_dup 2) (match_dup 1))
3369 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3370 "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3375 (define_expand "extendqihi2"
3377 (ashift:SI (match_operand:QI 1 "general_operand" "")
3379 (set (match_operand:HI 0 "s_register_operand" "")
3380 (ashiftrt:SI (match_dup 2)
3385 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3387 emit_insn (gen_rtx_SET (VOIDmode,
3389 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3392 if (! s_register_operand (operands[1], QImode))
3393 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3394 operands[0] = gen_lowpart (SImode, operands[0]);
3395 operands[1] = gen_lowpart (SImode, operands[1]);
3396 operands[2] = gen_reg_rtx (SImode);
3399 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3400 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3401 (define_insn "*extendqihi_insn"
3402 [(set (match_operand:HI 0 "s_register_operand" "=r")
3403 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
3404 "TARGET_ARM && arm_arch4"
3406 /* If the address is invalid, this will split the instruction into two. */
3407 if (bad_signed_byte_operand (operands[1], VOIDmode))
3409 return \"ldr%?sb\\t%0, %1\";
3411 [(set_attr "type" "load")
3412 (set_attr "length" "8")
3413 (set_attr "pool_range" "256")
3414 (set_attr "neg_pool_range" "244")]
3418 [(set (match_operand:HI 0 "s_register_operand" "")
3419 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3420 "TARGET_ARM && arm_arch4 && reload_completed"
3421 [(set (match_dup 3) (match_dup 1))
3422 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
3425 HOST_WIDE_INT offset;
3427 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
3428 operands[2] = gen_rtx_MEM (QImode, operands[3]);
3429 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3430 RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
3431 operands[1] = XEXP (operands[1], 0);
3432 if (GET_CODE (operands[1]) == PLUS
3433 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3434 && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3435 || const_ok_for_arm (-offset)))
3437 HOST_WIDE_INT low = (offset > 0
3438 ? (offset & 0xff) : -((-offset) & 0xff));
3439 XEXP (operands[2], 0) = plus_constant (operands[3], low);
3440 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3442 /* Ensure the sum is in correct canonical form */
3443 else if (GET_CODE (operands[1]) == PLUS
3444 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3445 && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
3446 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3447 XEXP (operands[1], 1),
3448 XEXP (operands[1], 0));
3452 (define_expand "extendqisi2"
3454 (ashift:SI (match_operand:QI 1 "general_operand" "")
3456 (set (match_operand:SI 0 "s_register_operand" "")
3457 (ashiftrt:SI (match_dup 2)
3462 if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3464 emit_insn (gen_rtx_SET (VOIDmode,
3466 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3469 if (! s_register_operand (operands[1], QImode))
3470 operands[1] = copy_to_mode_reg (QImode, operands[1]);
3471 operands[1] = gen_lowpart (SImode, operands[1]);
3472 operands[2] = gen_reg_rtx (SImode);
3478 ops[0] = operands[2];
3479 ops[1] = operands[1];
3480 ops[2] = GEN_INT (24);
3482 emit_insn (gen_rtx_SET (VOIDmode, ops[0], gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3484 ops[0] = operands[0];
3485 ops[1] = operands[2];
3486 ops[2] = GEN_INT (24);
3488 emit_insn (gen_rtx_SET (VOIDmode, ops[0], gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3495 ; Rather than restricting all byte accesses to memory addresses that ldrsb
3496 ; can handle, we fix up the ones that ldrsb can't grok with a split.
3497 (define_insn "*arm_extendqisi_insn"
3498 [(set (match_operand:SI 0 "s_register_operand" "=r")
3499 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
3500 "TARGET_ARM && arm_arch4"
3502 /* If the address is invalid, this will split the instruction into two. */
3503 if (bad_signed_byte_operand (operands[1], VOIDmode))
3505 return \"ldr%?sb\\t%0, %1\";
3507 [(set_attr "type" "load")
3508 (set_attr "length" "8")
3509 (set_attr "pool_range" "256")
3510 (set_attr "neg_pool_range" "244")]
3514 [(set (match_operand:SI 0 "s_register_operand" "")
3515 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
3516 "TARGET_ARM && arm_arch4 && reload_completed"
3517 [(set (match_dup 0) (match_dup 1))
3518 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
3521 HOST_WIDE_INT offset;
3523 operands[2] = gen_rtx_MEM (QImode, operands[0]);
3524 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
3525 RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
3526 operands[1] = XEXP (operands[1], 0);
3527 if (GET_CODE (operands[1]) == PLUS
3528 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
3529 && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
3530 || const_ok_for_arm (-offset)))
3532 HOST_WIDE_INT low = (offset > 0
3533 ? (offset & 0xff) : -((-offset) & 0xff));
3534 XEXP (operands[2], 0) = plus_constant (operands[0], low);
3535 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
3537 /* Ensure the sum is in correct canonical form */
3538 else if (GET_CODE (operands[1]) == PLUS
3539 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
3540 && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
3541 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
3542 XEXP (operands[1], 1),
3543 XEXP (operands[1], 0));
3547 (define_insn "*thumb_extendqisi2_insn"
3548 [(set (match_operand:SI 0 "register_operand" "=l,l")
3549 (sign_extend:SI (match_operand:QI 1 "memory_operand" "V,m")))]
3554 rtx mem = XEXP (operands[1], 0);
3556 if (GET_CODE (mem) == CONST)
3557 mem = XEXP (mem, 0);
3559 if (GET_CODE (mem) == LABEL_REF)
3560 return \"ldr\\t%0, %1\";
3562 if (GET_CODE (mem) == PLUS
3563 && GET_CODE (XEXP (mem, 0)) == LABEL_REF)
3564 return \"ldr\\t%0, %1\";
3566 if (which_alternative == 0)
3567 return \"ldrsb\\t%0, %1\";
3569 ops[0] = operands[0];
3571 if (GET_CODE (mem) == PLUS)
3573 rtx a = XEXP (mem, 0);
3574 rtx b = XEXP (mem, 1);
3579 if (GET_CODE (a) == REG)
3581 if (GET_CODE (b) == REG)
3582 output_asm_insn (\"ldrsb\\t%0, [%1, %2]\", ops);
3583 else if (REGNO (a) == REGNO (ops[0]))
3584 output_asm_insn (\"ldrb\\t%0, [%1, %2]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
3586 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3588 else if (GET_CODE (b) != REG)
3592 if (REGNO (b) == REGNO (ops[0]))
3593 output_asm_insn (\"ldrb\\t%0, [%2, %1]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
3595 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3598 else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3600 output_asm_insn (\"ldrb\\t%0, [%0, #0]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
3605 ops[2] = const0_rtx;
3607 output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3611 [(set_attr "length" "2,6")
3612 (set_attr "type" "load,load")
3613 (set_attr "pool_range" "32,32")]
3616 (define_insn "extendsfdf2"
3617 [(set (match_operand:DF 0 "s_register_operand" "=f")
3618 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
3619 "TARGET_ARM && TARGET_HARD_FLOAT"
3621 [(set_attr "type" "ffarith")])
3623 (define_insn "extendsfxf2"
3624 [(set (match_operand:XF 0 "s_register_operand" "=f")
3625 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
3626 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3628 [(set_attr "type" "ffarith")])
3630 (define_insn "extenddfxf2"
3631 [(set (match_operand:XF 0 "s_register_operand" "=f")
3632 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
3633 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3635 [(set_attr "type" "ffarith")])
3638 ;; Move insns (including loads and stores)
3640 ;; XXX Just some ideas about movti.
3641 ;; I don't think these are a good idea on the arm, there just aren't enough
3643 ;;(define_expand "loadti"
3644 ;; [(set (match_operand:TI 0 "s_register_operand" "")
3645 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
3648 ;;(define_expand "storeti"
3649 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3650 ;; (match_operand:TI 1 "s_register_operand" ""))]
3653 ;;(define_expand "movti"
3654 ;; [(set (match_operand:TI 0 "general_operand" "")
3655 ;; (match_operand:TI 1 "general_operand" ""))]
3661 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
3662 ;; operands[1] = copy_to_reg (operands[1]);
3663 ;; if (GET_CODE (operands[0]) == MEM)
3664 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
3665 ;; else if (GET_CODE (operands[1]) == MEM)
3666 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
3670 ;; emit_insn (insn);
3674 ;; Recognise garbage generated above.
3677 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3678 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3682 ;; register mem = (which_alternative < 3);
3683 ;; register char *template;
3685 ;; operands[mem] = XEXP (operands[mem], 0);
3686 ;; switch (which_alternative)
3688 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
3689 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
3690 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
3691 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
3692 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
3693 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
3695 ;; output_asm_insn (template, operands);
3699 (define_expand "movdi"
3700 [(set (match_operand:DI 0 "general_operand" "")
3701 (match_operand:DI 1 "general_operand" ""))]
3706 if (! (reload_in_progress || reload_completed))
3708 if (GET_CODE (operands[0]) != REG)
3709 operands[1] = force_reg (DImode, operands[1]);
3715 (define_insn "*arm_movdi"
3716 [(set (match_operand:DI 0 "nonimmediate_di_operand" "=r,r,o<>")
3717 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
3720 return (output_move_double (operands));
3722 [(set_attr "length" "8")
3723 (set_attr "type" "*,load,store2")
3724 (set_attr "pool_range" "*,1020,*")
3725 (set_attr "neg_pool_range" "*,1012,*")]
3728 ;;; ??? This should have alternatives for constants.
3729 ;;; ??? This was originally identical to the movdf_insn pattern.
3730 ;;; ??? The 'i' constraint looks funny, but it should always be replaced by
3731 ;;; thumb_reorg with a memory reference.
3732 (define_insn "*thumb_movdi_insn"
3733 [(set (match_operand:DI 0 "nonimmediate_operand" "=l,l,l,l,>,l,m,*r")
3734 (match_operand:DI 1 "general_operand" "l,I,J,>,l,mi,l,*r"))]
3736 && ( register_operand (operands[0], DImode)
3737 || register_operand (operands[1], DImode))"
3740 switch (which_alternative)
3744 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3745 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
3746 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
3748 return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3750 operands[1] = GEN_INT (- INTVAL (operands[1]));
3751 return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3753 return \"ldmia\\t%1, {%0, %H0}\";
3755 return \"stmia\\t%0, {%1, %H1}\";
3757 return thumb_load_double_from_address (operands);
3759 operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));
3760 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
3763 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
3764 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
3765 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
3768 [(set_attr "length" "4,4,6,2,2,6,4,4")
3769 (set_attr "type" "*,*,*,load,store2,load,store2,*")
3770 (set_attr "pool_range" "*,*,*,*,*,1020,*,*")]
3773 (define_expand "movsi"
3774 [(set (match_operand:SI 0 "general_operand" "")
3775 (match_operand:SI 1 "general_operand" ""))]
3780 /* Everything except mem = const or mem = mem can be done easily */
3781 if (GET_CODE (operands[0]) == MEM)
3782 operands[1] = force_reg (SImode, operands[1]);
3783 if (GET_CODE (operands[1]) == CONST_INT
3784 && !(const_ok_for_arm (INTVAL (operands[1]))
3785 || const_ok_for_arm (~INTVAL (operands[1]))))
3787 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3789 (reload_in_progress || reload_completed ? 0
3790 : preserve_subexpressions_p ()));
3794 else /* TARGET_THUMB.... */
3796 if (! (reload_in_progress || reload_completed))
3798 if (GET_CODE (operands[0]) != REG)
3799 operands[1] = force_reg (SImode, operands[1]);
3804 && (CONSTANT_P (operands[1])
3805 || symbol_mentioned_p (operands[1])
3806 || label_mentioned_p (operands[1])))
3807 operands[1] = legitimize_pic_address (operands[1], SImode,
3808 ((reload_in_progress
3809 || reload_completed)
3810 ? operands[0] : 0));
3813 (define_insn "*arm_movsi_insn"
3814 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r,m")
3815 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
3817 && ( register_operand (operands[0], SImode)
3818 || register_operand (operands[1], SImode))"
3824 [(set_attr "type" "*,*,load,store1")
3825 (set_attr "pool_range" "*,*,4096,*")
3826 (set_attr "neg_pool_range" "*,*,4084,*")]
3830 [(set (match_operand:SI 0 "s_register_operand" "")
3831 (match_operand:SI 1 "const_int_operand" ""))]
3833 && (! ( const_ok_for_arm (INTVAL (operands[1]))
3834 || const_ok_for_arm (~INTVAL (operands[1]))))"
3835 [(clobber (const_int 0))]
3837 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3842 (define_insn "*thumb_movsi_insn"
3843 [(set (match_operand:SI 0 "nonimmediate_operand" "=l,l,l,l,l,>,l,m,*lh")
3844 (match_operand:SI 1 "general_operand" "l,I,J,K,>,l,mi,l,*lh"))]
3846 && ( register_operand (operands[0], SImode)
3847 || register_operand (operands[1], SImode))"
3858 [(set_attr "length" "2,2,4,4,2,2,2,2,2")
3859 (set_attr "type" "*,*,*,*,load,store1,load,store1,*")
3860 (set_attr "pool_range" "*,*,*,*,*,*,1020,*,*")]
3864 [(set (match_operand:SI 0 "register_operand" "")
3865 (match_operand:SI 1 "const_int_operand" ""))]
3866 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'J')"
3867 [(set (match_dup 0) (match_dup 1))
3868 (set (match_dup 0) (neg:SI (match_dup 0)))]
3869 "operands[1] = GEN_INT (- INTVAL (operands[1]));"
3873 [(set (match_operand:SI 0 "register_operand" "")
3874 (match_operand:SI 1 "const_int_operand" ""))]
3875 "TARGET_THUMB && CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'K')"
3876 [(set (match_dup 0) (match_dup 1))
3877 (set (match_dup 0) (ashift:SI (match_dup 0) (match_dup 2)))]
3880 unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3881 unsigned HOST_WIDE_INT mask = 0xff;
3884 for (i = 0; i < 25; i++)
3885 if ((val & (mask << i)) == val)
3891 operands[1] = GEN_INT (val >> i);
3892 operands[2] = GEN_INT (i);
3896 (define_expand "movaddr"
3897 [(set (match_operand:SI 0 "s_register_operand" "")
3898 (match_operand:DI 1 "address_operand" ""))]
3903 (define_insn "*movaddr_insn"
3904 [(set (match_operand:SI 0 "s_register_operand" "=r")
3905 (match_operand:DI 1 "address_operand" "p"))]
3908 && (GET_CODE (operands[1]) == LABEL_REF
3909 || (GET_CODE (operands[1]) == CONST
3910 && GET_CODE (XEXP (operands[1], 0)) == PLUS
3911 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
3912 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
3916 ;; When generating pic, we need to load the symbol offset into a register.
3917 ;; So that the optimizer does not confuse this with a normal symbol load
3918 ;; we use an unspec. The offset will be loaded from a constant pool entry,
3919 ;; since that is the only type of relocation we can use.
3921 ;; The rather odd constraints on the following are to force reload to leave
3922 ;; the insn alone, and to force the minipool generation pass to then move
3923 ;; the GOT symbol to memory.
3925 (define_insn "pic_load_addr"
3926 [(set (match_operand:SI 0 "s_register_operand" "=r")
3927 (unspec:SI [(match_operand:SI 1 "" "mX")] 3))]
3928 "TARGET_EITHER && flag_pic"
3930 [(set_attr "type" "load")
3931 (set (attr "pool_range")
3932 (if_then_else (eq_attr "is_thumb" "yes")
3935 (set (attr "neg_pool_range")
3936 (if_then_else (eq_attr "is_thumb" "yes")
3941 ;; This variant is used for AOF assembly, since it needs to mention the
3942 ;; pic register in the rtl.
3943 (define_expand "pic_load_addr_based"
3944 [(set (match_operand:SI 0 "s_register_operand" "=r")
3945 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
3946 "TARGET_ARM && flag_pic"
3947 "operands[2] = pic_offset_table_rtx;"
3950 (define_insn "*pic_load_addr_based_insn"
3951 [(set (match_operand:SI 0 "s_register_operand" "=r")
3952 (unspec:SI [(match_operand 1 "" "")
3953 (match_operand 2 "s_register_operand" "r")] 3))]
3954 "TARGET_EITHER && flag_pic && operands[2] == pic_offset_table_rtx"
3956 #ifdef AOF_ASSEMBLER
3957 operands[1] = aof_pic_entry (operands[1]);
3959 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3962 [(set_attr "type" "load")
3963 (set (attr "pool_range")
3964 (if_then_else (eq_attr "is_thumb" "yes")
3967 (set (attr "neg_pool_range")
3968 (if_then_else (eq_attr "is_thumb" "yes")
3973 (define_insn "pic_add_dot_plus_four"
3974 [(set (match_operand:SI 0 "register_operand" "+r")
3975 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 4)))))
3976 (use (label_ref (match_operand 1 "" "")))]
3977 "TARGET_THUMB && flag_pic"
3979 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
3980 CODE_LABEL_NUMBER (operands[1]));
3981 return \"add\\t%0, %|pc\";
3983 [(set_attr "length" "2")]
3986 (define_insn "pic_add_dot_plus_eight"
3987 [(set (match_operand:SI 0 "register_operand" "+r")
3988 (plus:SI (match_dup 0) (const (plus:SI (pc) (const_int 8)))))
3989 (use (label_ref (match_operand 1 "" "")))]
3990 "TARGET_ARM && flag_pic"
3992 ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
3993 CODE_LABEL_NUMBER (operands[1]));
3994 return \"add%?\\t%0, %|pc, %0\";
3998 ;; If copying one reg to another we can set the condition codes according to
3999 ;; its value. Such a move is common after a return from subroutine and the
4000 ;; result is being tested against zero.
4002 (define_insn "*movsi_compare0"
4004 (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4006 (set (match_operand:SI 0 "s_register_operand" "=r,r")
4011 sub%?s\\t%0, %1, #0"
4012 [(set_attr "conds" "set")]
4015 ;; Subroutine to store a half word from a register into memory.
4016 ;; Operand 0 is the source register (HImode)
4017 ;; Operand 1 is the destination address in a register (SImode)
4019 ;; In both this routine and the next, we must be careful not to spill
4020 ;; a memory address of reg+large_const into a separate PLUS insn, since this
4021 ;; can generate unrecognizable rtl.
4023 (define_expand "storehi"
4024 [;; store the low byte
4025 (set (match_operand 1 "" "") (match_dup 3))
4026 ;; extract the high byte
4028 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4029 ;; store the high byte
4030 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
4034 rtx addr = XEXP (operands[1], 0);
4035 enum rtx_code code = GET_CODE (addr);
4037 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4039 addr = force_reg (SImode, addr);
4041 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
4042 operands[1] = change_address (operands[1], QImode, NULL_RTX);
4043 operands[3] = gen_lowpart (QImode, operands[0]);
4044 operands[0] = gen_lowpart (SImode, operands[0]);
4045 operands[2] = gen_reg_rtx (SImode);
4049 (define_expand "storehi_bigend"
4050 [(set (match_dup 4) (match_dup 3))
4052 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4053 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
4057 rtx addr = XEXP (operands[1], 0);
4058 enum rtx_code code = GET_CODE (addr);
4060 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4062 addr = force_reg (SImode, addr);
4064 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
4065 operands[1] = change_address (operands[1], QImode, NULL_RTX);
4066 operands[3] = gen_lowpart (QImode, operands[0]);
4067 operands[0] = gen_lowpart (SImode, operands[0]);
4068 operands[2] = gen_reg_rtx (SImode);
4072 ;; Subroutine to store a half word integer constant into memory.
4073 (define_expand "storeinthi"
4074 [(set (match_operand 0 "" "")
4075 (subreg:QI (match_operand 1 "" "") 0))
4076 (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
4080 HOST_WIDE_INT value = INTVAL (operands[1]);
4081 rtx addr = XEXP (operands[0], 0);
4082 enum rtx_code code = GET_CODE (addr);
4084 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
4086 addr = force_reg (SImode, addr);
4088 operands[1] = gen_reg_rtx (SImode);
4089 if (BYTES_BIG_ENDIAN)
4091 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4092 if ((value & 255) == ((value >> 8) & 255))
4093 operands[2] = operands[1];
4096 operands[2] = gen_reg_rtx (SImode);
4097 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4102 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4103 if ((value & 255) == ((value >> 8) & 255))
4104 operands[2] = operands[1];
4107 operands[2] = gen_reg_rtx (SImode);
4108 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4112 operands[3] = change_address (operands[0], QImode, plus_constant (addr, 1));
4113 operands[0] = change_address (operands[0], QImode, NULL_RTX);
4117 (define_expand "storehi_single_op"
4118 [(set (match_operand:HI 0 "memory_operand" "")
4119 (match_operand:HI 1 "general_operand" ""))]
4120 "TARGET_ARM && arm_arch4"
4122 if (! s_register_operand (operands[1], HImode))
4123 operands[1] = copy_to_mode_reg (HImode, operands[1]);
4126 (define_expand "movhi"
4127 [(set (match_operand:HI 0 "general_operand" "")
4128 (match_operand:HI 1 "general_operand" ""))]
4133 if (! (reload_in_progress || reload_completed))
4135 if (GET_CODE (operands[0]) == MEM)
4139 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4142 if (GET_CODE (operands[1]) == CONST_INT)
4143 emit_insn (gen_storeinthi (operands[0], operands[1]));
4146 if (GET_CODE (operands[1]) == MEM)
4147 operands[1] = force_reg (HImode, operands[1]);
4148 if (BYTES_BIG_ENDIAN)
4149 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
4151 emit_insn (gen_storehi (operands[1], operands[0]));
4155 /* Sign extend a constant, and keep it in an SImode reg. */
4156 else if (GET_CODE (operands[1]) == CONST_INT)
4158 rtx reg = gen_reg_rtx (SImode);
4159 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
4161 /* If the constant is already valid, leave it alone. */
4162 if (! const_ok_for_arm (val))
4164 /* If setting all the top bits will make the constant
4165 loadable in a single instruction, then set them.
4166 Otherwise, sign extend the number. */
4168 if (const_ok_for_arm (~ (val | ~0xffff)))
4170 else if (val & 0x8000)
4174 emit_insn (gen_movsi (reg, GEN_INT (val)));
4175 operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
4177 else if (! arm_arch4)
4179 /* Note: We do not have to worry about TARGET_MMU_TRAPS
4180 for v4 and up architectures because LDRH instructions will
4181 be used to access the HI values, and these cannot generate
4182 unaligned word access faults in the MMU. */
4183 if (GET_CODE (operands[1]) == MEM)
4185 if (TARGET_MMU_TRAPS)
4188 rtx offset = const0_rtx;
4189 rtx reg = gen_reg_rtx (SImode);
4191 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4192 || (GET_CODE (base) == PLUS
4193 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
4194 && ((INTVAL(offset) & 1) != 1)
4195 && GET_CODE (base = XEXP (base, 0)) == REG))
4196 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
4198 HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4201 new = gen_rtx_MEM (SImode,
4202 plus_constant (base, new_offset));
4203 MEM_COPY_ATTRIBUTES (new, operands[1]);
4204 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
4205 emit_insn (gen_movsi (reg, new));
4206 if (((INTVAL (offset) & 2) != 0)
4207 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
4209 rtx reg2 = gen_reg_rtx (SImode);
4211 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4216 emit_insn (gen_movhi_bytes (reg, operands[1]));
4218 operands[1] = gen_lowpart (HImode, reg);
4220 else if (BYTES_BIG_ENDIAN)
4223 rtx offset = const0_rtx;
4225 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
4226 || (GET_CODE (base) == PLUS
4227 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
4228 && GET_CODE (base = XEXP (base, 0)) == REG))
4229 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
4231 rtx reg = gen_reg_rtx (SImode);
4234 if ((INTVAL (offset) & 2) == 2)
4236 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
4237 new = gen_rtx_MEM (SImode,
4238 plus_constant (base, new_offset));
4239 MEM_COPY_ATTRIBUTES (new, operands[1]);
4240 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
4241 emit_insn (gen_movsi (reg, new));
4245 new = gen_rtx_MEM (SImode, XEXP (operands[1], 0));
4246 MEM_COPY_ATTRIBUTES (new, operands[1]);
4247 RTX_UNCHANGING_P (new)
4248 = RTX_UNCHANGING_P (operands[1]);
4249 emit_insn (gen_rotated_loadsi (reg, new));
4252 operands[1] = gen_lowpart (HImode, reg);
4256 emit_insn (gen_movhi_bigend (operands[0], operands[1]));
4263 /* Handle loading a large integer during reload */
4264 else if (GET_CODE (operands[1]) == CONST_INT
4265 && ! const_ok_for_arm (INTVAL (operands[1]))
4266 && ! const_ok_for_arm (~INTVAL (operands[1])))
4268 /* Writing a constant to memory needs a scratch, which should
4269 be handled with SECONDARY_RELOADs. */
4270 if (GET_CODE (operands[0]) != REG)
4273 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4274 emit_insn (gen_movsi (operands[0], operands[1]));
4278 else /* TARGET_THUMB */
4280 if (! (reload_in_progress || reload_completed))
4282 if (GET_CODE (operands[0]) != REG)
4283 operands[1] = force_reg (HImode, operands[1]);
4285 /* ??? We shouldn't really get invalid addresses here, but this can
4286 happen if we are passed a SP (never OK for HImode/QImode) or virtual
4287 register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)
4288 relative address. */
4289 /* ??? This should perhaps be fixed elsewhere, for instance, in
4290 fixup_stack_1, by checking for other kinds of invalid addresses,
4291 e.g. a bare reference to a virtual register. This may confuse the
4292 alpha though, which must handle this case differently. */
4293 if (GET_CODE (operands[0]) == MEM
4294 && ! memory_address_p (GET_MODE (operands[0]),
4295 XEXP (operands[0], 0)))
4297 rtx temp = copy_to_reg (XEXP (operands[0], 0));
4298 operands[0] = change_address (operands[0], VOIDmode, temp);
4301 if (GET_CODE (operands[1]) == MEM
4302 && ! memory_address_p (GET_MODE (operands[1]),
4303 XEXP (operands[1], 0)))
4305 rtx temp = copy_to_reg (XEXP (operands[1], 0));
4306 operands[1] = change_address (operands[1], VOIDmode, temp);
4309 /* Handle loading a large integer during reload */
4310 else if (GET_CODE (operands[1]) == CONST_INT
4311 && ! CONST_OK_FOR_THUMB_LETTER (INTVAL (operands[1]), 'I'))
4313 /* Writing a constant to memory needs a scratch, which should
4314 be handled with SECONDARY_RELOADs. */
4315 if (GET_CODE (operands[0]) != REG)
4318 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4319 emit_insn (gen_movsi (operands[0], operands[1]));
4326 (define_insn "*thumb_movhi_insn"
4327 [(set (match_operand:HI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4328 (match_operand:HI 1 "general_operand" "l,mn,l,*h,*r,I"))]
4330 && ( register_operand (operands[0], HImode)
4331 || register_operand (operands[1], HImode))"
4333 switch (which_alternative)
4335 case 0: return \"add %0, %1, #0\";
4336 case 2: return \"strh %1, %0\";
4337 case 3: return \"mov %0, %1\";
4338 case 4: return \"mov %0, %1\";
4339 case 5: return \"mov %0, %1\";
4342 /* The stack pointer can end up being taken as an index register.
4343 Catch this case here and deal with it. */
4344 if (GET_CODE (XEXP (operands[1], 0)) == PLUS
4345 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == REG
4346 && REGNO (XEXP (XEXP (operands[1], 0), 0)) == SP_REGNUM)
4349 ops[0] = operands[0];
4350 ops[1] = XEXP (XEXP (operands[1], 0), 0);
4352 output_asm_insn (\"mov %0, %1\", ops);
4354 XEXP (XEXP (operands[1], 0), 0) = operands[0];
4357 return \"ldrh %0, %1\";
4359 [(set_attr "length" "2,4,2,2,2,2")
4360 (set_attr "type" "*,load,store1,*,*,*")
4361 (set_attr "pool_range" "*,64,*,*,*,*")]
4365 (define_insn "rotated_loadsi"
4366 [(set (match_operand:SI 0 "s_register_operand" "=r")
4367 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
4369 "TARGET_ARM && (! TARGET_MMU_TRAPS)"
4374 ops[0] = operands[0];
4375 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
4376 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
4379 [(set_attr "type" "load")]
4382 (define_expand "movhi_bytes"
4383 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4385 (zero_extend:SI (match_dup 6)))
4386 (set (match_operand:SI 0 "" "")
4387 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
4392 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
4394 mem1 = gen_rtx_MEM (QImode, addr);
4395 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
4396 RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
4397 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
4398 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
4399 RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
4400 operands[0] = gen_lowpart (SImode, operands[0]);
4402 operands[2] = gen_reg_rtx (SImode);
4403 operands[3] = gen_reg_rtx (SImode);
4406 if (BYTES_BIG_ENDIAN)
4408 operands[4] = operands[2];
4409 operands[5] = operands[3];
4413 operands[4] = operands[3];
4414 operands[5] = operands[2];
4419 (define_expand "movhi_bigend"
4421 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4424 (ashiftrt:SI (match_dup 2) (const_int 16)))
4425 (set (match_operand:HI 0 "s_register_operand" "")
4426 (subreg:HI (match_dup 3) 0))]
4429 operands[2] = gen_reg_rtx (SImode);
4430 operands[3] = gen_reg_rtx (SImode);
4433 ;; Pattern to recognise insn generated default case above
4434 (define_insn "*movhi_insn_arch4"
4435 [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r,m,r")
4436 (match_operand:HI 1 "general_operand" "rI,K,r,m"))]
4439 && (GET_CODE (operands[1]) != CONST_INT
4440 || const_ok_for_arm (INTVAL (operands[1]))
4441 || const_ok_for_arm (~INTVAL (operands[1])))"
4443 mov%?\\t%0, %1\\t%@ movhi
4444 mvn%?\\t%0, #%B1\\t%@ movhi
4445 str%?h\\t%1, %0\\t%@ movhi
4446 ldr%?h\\t%0, %1\\t%@ movhi"
4447 [(set_attr "type" "*,*,store1,load")
4448 (set_attr "pool_range" "*,*,*,256")
4449 (set_attr "neg_pool_range" "*,*,*,244")]
4452 (define_insn "*movhi_insn_littleend"
4453 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4454 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4457 && ! BYTES_BIG_ENDIAN
4458 && ! TARGET_MMU_TRAPS
4459 && (GET_CODE (operands[1]) != CONST_INT
4460 || const_ok_for_arm (INTVAL (operands[1]))
4461 || const_ok_for_arm (~INTVAL (operands[1])))"
4463 mov%?\\t%0, %1\\t%@ movhi
4464 mvn%?\\t%0, #%B1\\t%@ movhi
4465 ldr%?\\t%0, %1\\t%@ movhi"
4466 [(set_attr "type" "*,*,load")
4467 (set_attr "pool_range" "4096")
4468 (set_attr "neg_pool_range" "4084")]
4471 (define_insn "*movhi_insn_bigend"
4472 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
4473 (match_operand:HI 1 "general_operand" "rI,K,m"))]
4477 && ! TARGET_MMU_TRAPS
4478 && (GET_CODE (operands[1]) != CONST_INT
4479 || const_ok_for_arm (INTVAL (operands[1]))
4480 || const_ok_for_arm (~INTVAL (operands[1])))"
4482 mov%?\\t%0, %1\\t%@ movhi
4483 mvn%?\\t%0, #%B1\\t%@ movhi
4484 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
4485 [(set_attr "type" "*,*,load")
4486 (set_attr "length" "4,4,8")
4487 (set_attr "pool_range" "*,*,4092")
4488 (set_attr "neg_pool_range" "*,*,4084")]
4491 (define_insn "*loadhi_si_bigend"
4492 [(set (match_operand:SI 0 "s_register_operand" "=r")
4493 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
4497 && ! TARGET_MMU_TRAPS"
4498 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
4499 [(set_attr "type" "load")
4500 (set_attr "pool_range" "4096")
4501 (set_attr "neg_pool_range" "4084")]
4504 (define_insn "*movhi_bytes"
4505 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
4506 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
4507 "TARGET_ARM && TARGET_MMU_TRAPS"
4509 mov%?\\t%0, %1\\t%@ movhi
4510 mvn%?\\t%0, #%B1\\t%@ movhi")
4512 (define_insn "thumb_movhi_clobber"
4513 [(set (match_operand:HI 0 "memory_operand" "=m")
4514 (match_operand:HI 1 "register_operand" "l"))
4515 (clobber (match_operand:SI 2 "register_operand" "=&l"))]
4520 ;; We use a DImode scratch because we may occasionally need an additional
4521 ;; temporary if the address isn't offsettable -- push_reload doesn't seem
4522 ;; to take any notice of the "o" constraints on reload_memory_operand operand.
4523 (define_expand "reload_outhi"
4524 [(parallel [(match_operand:HI 0 "arm_reload_memory_operand" "=o")
4525 (match_operand:HI 1 "s_register_operand" "r")
4526 (match_operand:DI 2 "s_register_operand" "=&l")])]
4529 arm_reload_out_hi (operands);
4531 thumb_reload_out_hi (operands);
4536 (define_expand "reload_inhi"
4537 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
4538 (match_operand:HI 1 "arm_reload_memory_operand" "o")
4539 (match_operand:DI 2 "s_register_operand" "=&r")])]
4540 "TARGET_THUMB || (TARGET_ARM && TARGET_MMU_TRAPS)"
4543 arm_reload_in_hi (operands);
4545 thumb_reload_out_hi (operands);
4549 (define_expand "movqi"
4550 [(set (match_operand:QI 0 "general_operand" "")
4551 (match_operand:QI 1 "general_operand" ""))]
4556 /* Everything except mem = const or mem = mem can be done easily */
4558 if (!(reload_in_progress || reload_completed))
4560 if (GET_CODE (operands[1]) == CONST_INT)
4562 rtx reg = gen_reg_rtx (SImode);
4564 emit_insn (gen_movsi (reg, operands[1]));
4565 operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
4567 if (GET_CODE (operands[0]) == MEM)
4568 operands[1] = force_reg (QImode, operands[1]);
4571 else /* TARGET_THUMB */
4573 if (! (reload_in_progress || reload_completed))
4575 if (GET_CODE (operands[0]) != REG)
4576 operands[1] = force_reg (QImode, operands[1]);
4578 /* ??? We shouldn't really get invalid addresses here, but this can
4579 happen if we are passed a SP (never OK for HImode/QImode) or virtual
4580 register (rejected by GO_IF_LEGITIMATE_ADDRESS for HImode/QImode)
4581 relative address. */
4582 /* ??? This should perhaps be fixed elsewhere, for instance, in
4583 fixup_stack_1, by checking for other kinds of invalid addresses,
4584 e.g. a bare reference to a virtual register. This may confuse the
4585 alpha though, which must handle this case differently. */
4586 if (GET_CODE (operands[0]) == MEM
4587 && ! memory_address_p (GET_MODE (operands[0]),
4588 XEXP (operands[0], 0)))
4590 rtx temp = copy_to_reg (XEXP (operands[0], 0));
4591 operands[0] = change_address (operands[0], VOIDmode, temp);
4593 if (GET_CODE (operands[1]) == MEM
4594 && ! memory_address_p (GET_MODE (operands[1]),
4595 XEXP (operands[1], 0)))
4597 rtx temp = copy_to_reg (XEXP (operands[1], 0));
4598 operands[1] = change_address (operands[1], VOIDmode, temp);
4601 /* Handle loading a large integer during reload */
4602 else if (GET_CODE (operands[1]) == CONST_INT
4603 && ! CONST_OK_FOR_LETTER_P (INTVAL (operands[1]), 'I'))
4605 /* Writing a constant to memory needs a scratch, which should
4606 be handled with SECONDARY_RELOADs. */
4607 if (GET_CODE (operands[0]) != REG)
4610 operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4611 emit_insn (gen_movsi (operands[0], operands[1]));
4619 (define_insn "*arm_movqi_insn"
4620 [(set (match_operand:QI 0 "nonimmediate_operand" "=r,r,r,m")
4621 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
4623 && ( register_operand (operands[0], QImode)
4624 || register_operand (operands[1], QImode))"
4630 [(set_attr "type" "*,*,load,store1")]
4633 (define_insn "*thumb_movqi_insn"
4634 [(set (match_operand:QI 0 "nonimmediate_operand" "=l,l,m,*r,*h,l")
4635 (match_operand:QI 1 "general_operand" "l,m,l,*h,*r,I"))]
4637 && ( register_operand (operands[0], QImode)
4638 || register_operand (operands[1], QImode))"
4646 [(set_attr "length" "2")
4647 (set_attr "type" "*,load,store1,*,*,*")
4648 (set_attr "pool_range" "*,32,*,*,*,*")]
4651 (define_expand "movsf"
4652 [(set (match_operand:SF 0 "general_operand" "")
4653 (match_operand:SF 1 "general_operand" ""))]
4658 if (GET_CODE (operands[0]) == MEM)
4659 operands[1] = force_reg (SFmode, operands[1]);
4661 else /* TARGET_THUMB */
4663 if (! (reload_in_progress || reload_completed))
4665 if (GET_CODE (operands[0]) != REG)
4666 operands[1] = force_reg (SFmode, operands[1]);
4673 [(set (match_operand:SF 0 "nonimmediate_operand" "")
4674 (match_operand:SF 1 "immediate_operand" ""))]
4676 && ! TARGET_HARD_FLOAT
4678 && GET_CODE (operands[1]) == CONST_DOUBLE"
4679 [(set (match_dup 2) (match_dup 3))]
4681 operands[2] = gen_lowpart (SImode, operands[0]);
4682 operands[3] = gen_lowpart (SImode, operands[1]);
4683 if (operands[2] == 0 || operands[3] == 0)
4687 (define_insn "*arm_movsf_hard_insn"
4688 [(set (match_operand:SF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r,r,m")
4689 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
4691 && TARGET_HARD_FLOAT
4692 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
4698 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4699 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4701 ldr%?\\t%0, %1\\t%@ float
4702 str%?\\t%1, %0\\t%@ float"
4703 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
4705 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")
4706 (set_attr "pool_range" "*,*,1024,*,*,*,*,4096,*")
4707 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*,4084,*")]
4710 ;; Exactly the same as above, except that all `f' cases are deleted.
4711 ;; This is necessary to prevent reload from ever trying to use a `f' reg
4712 ;; when -msoft-float.
4714 (define_insn "*arm_movsf_soft_insn"
4715 [(set (match_operand:SF 0 "nonimmediate_operand" "=r,r,m")
4716 (match_operand:SF 1 "general_operand" "r,mE,r"))]
4718 && TARGET_SOFT_FLOAT
4719 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
4722 ldr%?\\t%0, %1\\t%@ float
4723 str%?\\t%1, %0\\t%@ float"
4724 [(set_attr "length" "4,4,4")
4725 (set_attr "type" "*,load,store1")
4726 (set_attr "pool_range" "*,4096,*")
4727 (set_attr "neg_pool_range" "*,4084,*")]
4730 ;;; ??? This should have alternatives for constants.
4731 (define_insn "*thumb_movsf_insn"
4732 [(set (match_operand:SF 0 "nonimmediate_operand" "=l,l,>,l,m,*r,*h")
4733 (match_operand:SF 1 "general_operand" "l,>,l,mF,l,*h,*r"))]
4735 && ( register_operand (operands[0], SFmode)
4736 || register_operand (operands[1], SFmode))"
4745 [(set_attr "length" "2")
4746 (set_attr "type" "*,load,store1,load,store1,*,*")
4747 (set_attr "pool_range" "*,*,*,1020,*,*,*")]
4750 (define_expand "movdf"
4751 [(set (match_operand:DF 0 "general_operand" "")
4752 (match_operand:DF 1 "general_operand" ""))]
4757 if (GET_CODE (operands[0]) == MEM)
4758 operands[1] = force_reg (DFmode, operands[1]);
4760 else /* TARGET_THUMB */
4762 if (! (reload_in_progress || reload_completed))
4764 if (GET_CODE (operands[0]) != REG)
4765 operands[1] = force_reg (DFmode, operands[1]);
4771 ;; Reloading a df mode value stored in integer regs to memory can require a
4773 (define_expand "reload_outdf"
4774 [(match_operand:DF 0 "arm_reload_memory_operand" "=o")
4775 (match_operand:DF 1 "s_register_operand" "r")
4776 (match_operand:SI 2 "s_register_operand" "=&r")]
4780 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4783 operands[2] = XEXP (operands[0], 0);
4784 else if (code == POST_INC || code == PRE_DEC)
4786 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
4787 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
4788 emit_insn (gen_movdi (operands[0], operands[1]));
4791 else if (code == PRE_INC)
4793 rtx reg = XEXP (XEXP (operands[0], 0), 0);
4794 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4797 else if (code == POST_DEC)
4798 operands[2] = XEXP (XEXP (operands[0], 0), 0);
4800 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
4801 XEXP (XEXP (operands[0], 0), 1)));
4803 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
4806 if (code == POST_DEC)
4807 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4813 (define_insn "*movdf_hard_insn"
4814 [(set (match_operand:DF 0 "nonimmediate_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
4815 (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
4817 && TARGET_HARD_FLOAT
4818 && (GET_CODE (operands[0]) != MEM
4819 || register_operand (operands[1], DFmode))"
4822 switch (which_alternative)
4825 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
4826 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
4827 case 2: case 3: case 4: return output_move_double (operands);
4828 case 5: return \"mvf%?d\\t%0, %1\";
4829 case 6: return \"mnf%?d\\t%0, #%N1\";
4830 case 7: return \"ldf%?d\\t%0, %1\";
4831 case 8: return \"stf%?d\\t%1, %0\";
4832 case 9: return output_mov_double_fpu_from_arm (operands);
4833 case 10: return output_mov_double_arm_from_fpu (operands);
4837 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
4839 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")
4840 (set_attr "pool_range" "*,*,*,*,252,*,*,1024,*,*,*")
4841 (set_attr "neg_pool_range" "*,*,*,*,244,*,*,1012,*,*,*")]
4844 ;; Software floating point version. This is essentially the same as movdi.
4845 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
4848 (define_insn "*movdf_soft_insn"
4849 [(set (match_operand:DF 0 "nonimmediate_soft_df_operand" "=r,r,m")
4850 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
4851 "TARGET_ARM && TARGET_SOFT_FLOAT"
4852 "* return output_move_double (operands);"
4853 [(set_attr "length" "8,8,8")
4854 (set_attr "type" "*,load,store2")
4855 (set_attr "pool_range" "252")
4856 (set_attr "neg_pool_range" "244")]
4859 ;;; ??? This should have alternatives for constants.
4860 ;;; ??? This was originally identical to the movdi_insn pattern.
4861 ;;; ??? The 'F' constraint looks funny, but it should always be replaced by
4862 ;;; thumb_reorg with a memory reference.
4863 (define_insn "*thumb_movdf_insn"
4864 [(set (match_operand:DF 0 "nonimmediate_operand" "=l,l,>,l,m,*r")
4865 (match_operand:DF 1 "general_operand" "l,>,l,mF,l,*r"))]
4867 && ( register_operand (operands[0], DFmode)
4868 || register_operand (operands[1], DFmode))"
4870 switch (which_alternative)
4874 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4875 return \"add\\t%0, %1, #0\;add\\t%H0, %H1, #0\";
4876 return \"add\\t%H0, %H1, #0\;add\\t%0, %1, #0\";
4878 return \"ldmia\\t%1, {%0, %H0}\";
4880 return \"stmia\\t%0, {%1, %H1}\";
4882 return thumb_load_double_from_address (operands);
4884 operands[2] = gen_rtx (MEM, SImode, plus_constant (XEXP (operands[0], 0), 4));
4885 output_asm_insn (\"str\\t%1, %0\;str\\t%H1, %2\", operands);
4888 if (REGNO (operands[1]) == REGNO (operands[0]) + 1)
4889 return \"mov\\t%0, %1\;mov\\t%H0, %H1\";
4890 return \"mov\\t%H0, %H1\;mov\\t%0, %1\";
4893 [(set_attr "length" "4,2,2,6,4,4")
4894 (set_attr "type" "*,load,store2,load,store2,*")
4895 (set_attr "pool_range" "*,*,*,1020,*,*")]
4899 (define_expand "movxf"
4900 [(set (match_operand:XF 0 "general_operand" "")
4901 (match_operand:XF 1 "general_operand" ""))]
4902 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
4905 ;; Even when the XFmode patterns aren't enabled, we enable this after
4906 ;; reloading so that we can push floating point registers in the prologue.
4908 (define_insn "*movxf_hard_insn"
4909 [(set (match_operand:XF 0 "nonimmediate_operand" "=f,f,f,m,f,r,r")
4910 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
4911 "TARGET_ARM && TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
4913 switch (which_alternative)
4916 case 0: return \"mvf%?e\\t%0, %1\";
4917 case 1: return \"mnf%?e\\t%0, #%N1\";
4918 case 2: return \"ldf%?e\\t%0, %1\";
4919 case 3: return \"stf%?e\\t%1, %0\";
4920 case 4: return output_mov_long_double_fpu_from_arm (operands);
4921 case 5: return output_mov_long_double_arm_from_fpu (operands);
4922 case 6: return output_mov_long_double_arm_from_arm (operands);
4925 [(set_attr "length" "4,4,4,4,8,8,12")
4926 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")
4927 (set_attr "pool_range" "*,*,1024,*,*,*,*")
4928 (set_attr "neg_pool_range" "*,*,1012,*,*,*,*")]
4932 ;; load- and store-multiple insns
4933 ;; The arm can load/store any set of registers, provided that they are in
4934 ;; ascending order; but that is beyond GCC so stick with what it knows.
4936 (define_expand "load_multiple"
4937 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
4938 (match_operand:SI 1 "" ""))
4939 (use (match_operand:SI 2 "" ""))])]
4942 /* Support only fixed point registers */
4943 if (GET_CODE (operands[2]) != CONST_INT
4944 || INTVAL (operands[2]) > 14
4945 || INTVAL (operands[2]) < 2
4946 || GET_CODE (operands[1]) != MEM
4947 || GET_CODE (operands[0]) != REG
4948 || REGNO (operands[0]) > 14
4949 || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
4953 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
4954 force_reg (SImode, XEXP (operands[1], 0)),
4955 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
4956 MEM_IN_STRUCT_P(operands[1]),
4957 MEM_SCALAR_P (operands[1]));
4960 ;; Load multiple with write-back
4962 (define_insn "*ldmsi_postinc"
4963 [(match_parallel 0 "load_multiple_operation"
4964 [(set (match_operand:SI 1 "s_register_operand" "+r")
4965 (plus:SI (match_dup 1)
4966 (match_operand:SI 2 "const_int_operand" "n")))
4967 (set (match_operand:SI 3 "s_register_operand" "=r")
4968 (mem:SI (match_dup 1)))])]
4969 "TARGET_ARM && (INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
4973 int count = XVECLEN (operands[0], 0);
4975 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
4976 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
4977 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
4979 output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
4983 [(set_attr "type" "load")])
4985 ;; Ordinary load multiple
4987 (define_insn "*ldmsi"
4988 [(match_parallel 0 "load_multiple_operation"
4989 [(set (match_operand:SI 1 "s_register_operand" "=r")
4990 (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
4995 int count = XVECLEN (operands[0], 0);
4997 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
4998 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
4999 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
5001 output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
5005 [(set_attr "type" "load")])
5007 (define_expand "store_multiple"
5008 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
5009 (match_operand:SI 1 "" ""))
5010 (use (match_operand:SI 2 "" ""))])]
5013 /* Support only fixed point registers */
5014 if (GET_CODE (operands[2]) != CONST_INT
5015 || INTVAL (operands[2]) > 14
5016 || INTVAL (operands[2]) < 2
5017 || GET_CODE (operands[1]) != REG
5018 || GET_CODE (operands[0]) != MEM
5019 || REGNO (operands[1]) > 14
5020 || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
5024 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
5025 force_reg (SImode, XEXP (operands[0], 0)),
5026 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
5027 MEM_IN_STRUCT_P(operands[0]),
5028 MEM_SCALAR_P (operands[0]));
5031 ;; Store multiple with write-back
5033 (define_insn "*stmsi_postinc"
5034 [(match_parallel 0 "store_multiple_operation"
5035 [(set (match_operand:SI 1 "s_register_operand" "+r")
5036 (plus:SI (match_dup 1)
5037 (match_operand:SI 2 "const_int_operand" "n")))
5038 (set (mem:SI (match_dup 1))
5039 (match_operand:SI 3 "s_register_operand" "r"))])]
5040 "TARGET_ARM && (INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
5044 int count = XVECLEN (operands[0], 0);
5046 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
5047 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
5048 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
5050 output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
5055 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
5056 (const_string "store2")
5057 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
5058 (const_string "store3")]
5059 (const_string "store4")))]
5062 ;; Ordinary store multiple
5064 (define_insn "*stmsi"
5065 [(match_parallel 0 "store_multiple_operation"
5066 [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
5067 (match_operand:SI 1 "s_register_operand" "r"))])]
5072 int count = XVECLEN (operands[0], 0);
5074 ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
5075 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
5076 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
5078 output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
5083 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
5084 (const_string "store2")
5085 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
5086 (const_string "store3")]
5087 (const_string "store4")))]
5090 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
5091 ;; We could let this apply for blocks of less than this, but it clobbers so
5092 ;; many registers that there is then probably a better way.
5094 (define_expand "movstrqi"
5095 [(match_operand:BLK 0 "general_operand" "")
5096 (match_operand:BLK 1 "general_operand" "")
5097 (match_operand:SI 2 "const_int_operand" "")
5098 (match_operand:SI 3 "const_int_operand" "")]
5103 if (arm_gen_movstrqi (operands))
5107 else /* TARGET_THUMB */
5109 if ( INTVAL (operands[3]) != 4
5110 || INTVAL (operands[2]) > 48)
5113 thumb_expand_movstrqi (operands);
5121 (define_insn "movmem12b"
5122 [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l"))
5123 (mem:SI (match_operand:SI 1 "register_operand" "+&l")))
5124 (set (mem:SI (plus:SI (match_dup 0) (const_int 4)))
5125 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5126 (set (mem:SI (plus:SI (match_dup 0) (const_int 8)))
5127 (mem:SI (plus:SI (match_dup 1) (const_int 8))))
5128 (set (match_dup 0) (plus:SI (match_dup 0) (const_int 12)))
5129 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 12)))
5130 (clobber (match_scratch:SI 2 "=&l"))
5131 (clobber (match_scratch:SI 3 "=&l"))
5132 (clobber (match_scratch:SI 4 "=&l"))]
5134 "* return thumb_output_move_mem_multiple (3, operands);"
5135 [(set_attr "length" "4")
5136 ;; This isn't entirely accurate... It loads as well, but in terms of
5137 ;; scheduling the following insn it is better to consider it as a store
5138 (set_attr "type" "store3")]
5141 (define_insn "movmem8b"
5142 [(set (mem:SI (match_operand:SI 0 "register_operand" "+&l"))
5143 (mem:SI (match_operand:SI 1 "register_operand" "+&l")))
5144 (set (mem:SI (plus:SI (match_dup 0) (const_int 4)))
5145 (mem:SI (plus:SI (match_dup 1) (const_int 4))))
5146 (set (match_dup 0) (plus:SI (match_dup 0) (const_int 8)))
5147 (set (match_dup 1) (plus:SI (match_dup 1) (const_int 8)))
5148 (clobber (match_scratch:SI 2 "=&l"))
5149 (clobber (match_scratch:SI 3 "=&l"))]
5151 "* return thumb_output_move_mem_multiple (2, operands);"
5152 [(set_attr "length" "4")
5153 ;; This isn't entirely accurate... It loads as well, but in terms of
5154 ;; scheduling the following insn it is better to consider it as a store
5155 (set_attr "type" "store2")]
5160 ;; Comapre & branch insns
5162 (define_insn "cbranchsi4"
5165 (match_operator 0 "comparison_operator"
5166 [(match_operand:SI 1 "register_operand" "l,r")
5167 (match_operand:SI 2 "nonmemory_operand" "rI,r")])
5168 (label_ref (match_operand 3 "" ""))
5172 output_asm_insn (\"cmp\\t%1, %2\", operands);
5173 switch (get_attr_length (insn))
5175 case 4: return \"b%d0\\t%l3\";
5176 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5177 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5180 [(set (attr "far_jump")
5182 (eq_attr "length" "8")
5183 (const_string "yes")
5184 (const_string "no")))
5185 (set (attr "length")
5187 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5188 (le (minus (match_dup 3) (pc)) (const_int 256)))
5191 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5192 (le (minus (match_dup 3) (pc)) (const_int 2054)))
5197 (define_insn "*negated_cbranchsi4"
5200 (match_operator 0 "comparison_operator"
5201 [(match_operand:SI 1 "register_operand" "l")
5202 (neg:SI (match_operand:SI 2 "nonmemory_operand" "l"))])
5203 (label_ref (match_operand 3 "" ""))
5207 output_asm_insn (\"cmn\\t%1, %2\", operands);
5208 switch (get_attr_length (insn))
5210 case 4: return \"b%d0\\t%l3\";
5211 case 6: return \"b%D0\\t.LCB%=\;b\\t%l3\\t%@long jump\\n.LCB%=:\";
5212 default: return \"b%D0\\t.LCB%=\;bl\\t%l3\\t%@far jump\\n.LCB%=:\";
5215 [(set (attr "far_jump")
5217 (eq_attr "length" "8")
5218 (const_string "yes")
5219 (const_string "no")))
5220 (set (attr "length")
5222 (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5223 (le (minus (match_dup 3) (pc)) (const_int 254)))
5226 (and (ge (minus (match_dup 3) (pc)) (const_int -2044))
5227 (le (minus (match_dup 3) (pc)) (const_int 2044)))
5233 ;; Comparison and test insns
5235 (define_expand "cmpsi"
5236 [(match_operand:SI 0 "s_register_operand" "")
5237 (match_operand:SI 1 "arm_add_operand" "")]
5240 arm_compare_op0 = operands[0];
5241 arm_compare_op1 = operands[1];
5246 (define_expand "cmpsf"
5247 [(match_operand:SF 0 "s_register_operand" "")
5248 (match_operand:SF 1 "fpu_rhs_operand" "")]
5249 "TARGET_ARM && TARGET_HARD_FLOAT"
5252 arm_compare_op0 = operands[0];
5253 arm_compare_op1 = operands[1];
5258 (define_expand "cmpdf"
5259 [(match_operand:DF 0 "s_register_operand" "")
5260 (match_operand:DF 1 "fpu_rhs_operand" "")]
5261 "TARGET_ARM && TARGET_HARD_FLOAT"
5264 arm_compare_op0 = operands[0];
5265 arm_compare_op1 = operands[1];
5270 (define_expand "cmpxf"
5271 [(match_operand:XF 0 "s_register_operand" "")
5272 (match_operand:XF 1 "fpu_rhs_operand" "")]
5273 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5275 arm_compare_op0 = operands[0];
5276 arm_compare_op1 = operands[1];
5281 (define_insn "*arm_cmpsi_insn"
5283 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5284 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
5289 [(set_attr "conds" "set")]
5292 (define_insn "*cmpsi_shiftsi"
5294 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5295 (match_operator:SI 3 "shift_operator"
5296 [(match_operand:SI 1 "s_register_operand" "r")
5297 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
5300 [(set_attr "conds" "set")
5303 (define_insn "*cmpsi_shiftsi_swp"
5304 [(set (reg:CC_SWP 24)
5305 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
5306 [(match_operand:SI 1 "s_register_operand" "r")
5307 (match_operand:SI 2 "reg_or_int_operand" "rM")])
5308 (match_operand:SI 0 "s_register_operand" "r")))]
5311 [(set_attr "conds" "set")
5314 (define_insn "*cmpsi_neg_shiftsi"
5316 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
5317 (neg:SI (match_operator:SI 3 "shift_operator"
5318 [(match_operand:SI 1 "s_register_operand" "r")
5319 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
5322 [(set_attr "conds" "set")
5325 (define_insn "*cmpsf_insn"
5327 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
5328 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5329 "TARGET_ARM && TARGET_HARD_FLOAT"
5333 [(set_attr "conds" "set")
5334 (set_attr "type" "f_2_r")])
5336 (define_insn "*cmpdf_insn"
5338 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
5339 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5340 "TARGET_ARM && TARGET_HARD_FLOAT"
5344 [(set_attr "conds" "set")
5345 (set_attr "type" "f_2_r")])
5347 (define_insn "*cmpesfdf_df"
5349 (compare:CCFP (float_extend:DF
5350 (match_operand:SF 0 "s_register_operand" "f,f"))
5351 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5352 "TARGET_ARM && TARGET_HARD_FLOAT"
5356 [(set_attr "conds" "set")
5357 (set_attr "type" "f_2_r")])
5359 (define_insn "*cmpdf_esfdf"
5361 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5363 (match_operand:SF 1 "s_register_operand" "f"))))]
5364 "TARGET_ARM && TARGET_HARD_FLOAT"
5366 [(set_attr "conds" "set")
5367 (set_attr "type" "f_2_r")])
5369 (define_insn "*cmpxf_insn"
5371 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
5372 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5373 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5377 [(set_attr "conds" "set")
5378 (set_attr "type" "f_2_r")])
5380 (define_insn "*cmpsf_trap"
5381 [(set (reg:CCFPE 24)
5382 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
5383 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
5384 "TARGET_ARM && TARGET_HARD_FLOAT"
5388 [(set_attr "conds" "set")
5389 (set_attr "type" "f_2_r")])
5391 (define_insn "*cmpdf_trap"
5392 [(set (reg:CCFPE 24)
5393 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
5394 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5395 "TARGET_ARM && TARGET_HARD_FLOAT"
5399 [(set_attr "conds" "set")
5400 (set_attr "type" "f_2_r")])
5402 (define_insn "*cmp_esfdf_df_trap"
5403 [(set (reg:CCFPE 24)
5404 (compare:CCFPE (float_extend:DF
5405 (match_operand:SF 0 "s_register_operand" "f,f"))
5406 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
5407 "TARGET_ARM && TARGET_HARD_FLOAT"
5411 [(set_attr "conds" "set")
5412 (set_attr "type" "f_2_r")])
5414 (define_insn "*cmp_df_esfdf_trap"
5415 [(set (reg:CCFPE 24)
5416 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
5418 (match_operand:SF 1 "s_register_operand" "f"))))]
5419 "TARGET_ARM && TARGET_HARD_FLOAT"
5421 [(set_attr "conds" "set")
5422 (set_attr "type" "f_2_r")])
5424 (define_insn "*cmpxf_trap"
5425 [(set (reg:CCFPE 24)
5426 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
5427 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
5428 "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
5432 [(set_attr "conds" "set")
5433 (set_attr "type" "f_2_r")])
5435 ; This insn allows redundant compares to be removed by cse, nothing should
5436 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
5437 ; is deleted later on. The match_dup will match the mode here, so that
5438 ; mode changes of the condition codes aren't lost by this even though we don't
5439 ; specify what they are.
5441 (define_insn "*deleted_compare"
5442 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
5444 "\\t%@ deleted compare"
5445 [(set_attr "conds" "set")
5446 (set_attr "length" "0")]
5450 ;; Conditional branch insns
5452 (define_expand "beq"
5454 (if_then_else (eq (match_dup 1) (const_int 0))
5455 (label_ref (match_operand 0 "" ""))
5458 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5461 (define_expand "bne"
5463 (if_then_else (ne (match_dup 1) (const_int 0))
5464 (label_ref (match_operand 0 "" ""))
5467 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5470 (define_expand "bgt"
5472 (if_then_else (gt (match_dup 1) (const_int 0))
5473 (label_ref (match_operand 0 "" ""))
5476 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5479 (define_expand "ble"
5481 (if_then_else (le (match_dup 1) (const_int 0))
5482 (label_ref (match_operand 0 "" ""))
5485 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5488 (define_expand "bge"
5490 (if_then_else (ge (match_dup 1) (const_int 0))
5491 (label_ref (match_operand 0 "" ""))
5494 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5497 (define_expand "blt"
5499 (if_then_else (lt (match_dup 1) (const_int 0))
5500 (label_ref (match_operand 0 "" ""))
5503 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5506 (define_expand "bgtu"
5508 (if_then_else (gtu (match_dup 1) (const_int 0))
5509 (label_ref (match_operand 0 "" ""))
5512 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5515 (define_expand "bleu"
5517 (if_then_else (leu (match_dup 1) (const_int 0))
5518 (label_ref (match_operand 0 "" ""))
5521 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5524 (define_expand "bgeu"
5526 (if_then_else (geu (match_dup 1) (const_int 0))
5527 (label_ref (match_operand 0 "" ""))
5530 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5533 (define_expand "bltu"
5535 (if_then_else (ltu (match_dup 1) (const_int 0))
5536 (label_ref (match_operand 0 "" ""))
5539 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5542 ;; patterns to match conditional branch insns
5544 (define_insn "*arm_cond_branch"
5546 (if_then_else (match_operator 1 "comparison_operator"
5547 [(match_operand 2 "cc_register" "") (const_int 0)])
5548 (label_ref (match_operand 0 "" ""))
5552 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5554 arm_ccfsm_state += 2;
5557 return \"b%d1\\t%l0\";
5559 [(set_attr "conds" "use")]
5562 (define_insn "*arm_cond_branch_reversed"
5564 (if_then_else (match_operator 1 "comparison_operator"
5565 [(match_operand 2 "cc_register" "") (const_int 0)])
5567 (label_ref (match_operand 0 "" ""))))]
5570 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5572 arm_ccfsm_state += 2;
5575 return \"b%D1\\t%l0\";
5577 [(set_attr "conds" "use")]
5584 (define_expand "seq"
5585 [(set (match_operand:SI 0 "s_register_operand" "=r")
5586 (eq:SI (match_dup 1) (const_int 0)))]
5588 "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5591 (define_expand "sne"
5592 [(set (match_operand:SI 0 "s_register_operand" "=r")
5593 (ne:SI (match_dup 1) (const_int 0)))]
5595 "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5598 (define_expand "sgt"
5599 [(set (match_operand:SI 0 "s_register_operand" "=r")
5600 (gt:SI (match_dup 1) (const_int 0)))]
5602 "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5605 (define_expand "sle"
5606 [(set (match_operand:SI 0 "s_register_operand" "=r")
5607 (le:SI (match_dup 1) (const_int 0)))]
5609 "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5612 (define_expand "sge"
5613 [(set (match_operand:SI 0 "s_register_operand" "=r")
5614 (ge:SI (match_dup 1) (const_int 0)))]
5616 "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5619 (define_expand "slt"
5620 [(set (match_operand:SI 0 "s_register_operand" "=r")
5621 (lt:SI (match_dup 1) (const_int 0)))]
5623 "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5626 (define_expand "sgtu"
5627 [(set (match_operand:SI 0 "s_register_operand" "=r")
5628 (gtu:SI (match_dup 1) (const_int 0)))]
5630 "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5633 (define_expand "sleu"
5634 [(set (match_operand:SI 0 "s_register_operand" "=r")
5635 (leu:SI (match_dup 1) (const_int 0)))]
5637 "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5640 (define_expand "sgeu"
5641 [(set (match_operand:SI 0 "s_register_operand" "=r")
5642 (geu:SI (match_dup 1) (const_int 0)))]
5644 "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5647 (define_expand "sltu"
5648 [(set (match_operand:SI 0 "s_register_operand" "=r")
5649 (ltu:SI (match_dup 1) (const_int 0)))]
5651 "operands[1] = arm_gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1);"
5654 (define_insn "*mov_scc"
5655 [(set (match_operand:SI 0 "s_register_operand" "=r")
5656 (match_operator:SI 1 "comparison_operator"
5657 [(match_operand 2 "cc_register" "") (const_int 0)]))]
5659 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
5660 [(set_attr "conds" "use")
5661 (set_attr "length" "8")]
5664 (define_insn "*mov_negscc"
5665 [(set (match_operand:SI 0 "s_register_operand" "=r")
5666 (neg:SI (match_operator:SI 1 "comparison_operator"
5667 [(match_operand 2 "cc_register" "") (const_int 0)])))]
5669 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
5670 [(set_attr "conds" "use")
5671 (set_attr "length" "8")]
5674 (define_insn "*mov_notscc"
5675 [(set (match_operand:SI 0 "s_register_operand" "=r")
5676 (not:SI (match_operator:SI 1 "comparison_operator"
5677 [(match_operand 2 "cc_register" "") (const_int 0)])))]
5679 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
5680 [(set_attr "conds" "use")
5681 (set_attr "length" "8")]
5685 ;; Conditional move insns
5687 (define_expand "movsicc"
5688 [(set (match_operand:SI 0 "s_register_operand" "")
5689 (if_then_else:SI (match_operand 1 "comparison_operator" "")
5690 (match_operand:SI 2 "arm_not_operand" "")
5691 (match_operand:SI 3 "arm_not_operand" "")))]
5695 enum rtx_code code = GET_CODE (operands[1]);
5696 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5698 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5701 (define_expand "movsfcc"
5702 [(set (match_operand:SF 0 "s_register_operand" "")
5703 (if_then_else:SF (match_operand 1 "comparison_operator" "")
5704 (match_operand:SF 2 "s_register_operand" "")
5705 (match_operand:SF 3 "nonmemory_operand" "")))]
5709 enum rtx_code code = GET_CODE (operands[1]);
5712 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
5713 Otherwise, ensure it is a valid FP add operand */
5714 if ((! TARGET_HARD_FLOAT)
5715 || (! fpu_add_operand (operands[3], SFmode)))
5716 operands[3] = force_reg (SFmode, operands[3]);
5718 ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5720 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5723 (define_expand "movdfcc"
5724 [(set (match_operand:DF 0 "s_register_operand" "")
5725 (if_then_else:DF (match_operand 1 "comparison_operator" "")
5726 (match_operand:DF 2 "s_register_operand" "")
5727 (match_operand:DF 3 "fpu_add_operand" "")))]
5728 "TARGET_ARM && TARGET_HARD_FLOAT"
5731 enum rtx_code code = GET_CODE (operands[1]);
5732 rtx ccreg = arm_gen_compare_reg (code, arm_compare_op0, arm_compare_op1);
5734 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
5737 (define_insn "*movsicc_insn"
5738 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
5740 (match_operator 3 "comparison_operator"
5741 [(match_operand 4 "cc_register" "") (const_int 0)])
5742 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
5743 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
5750 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
5751 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
5752 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
5753 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
5754 [(set_attr "length" "4,4,4,4,8,8,8,8")
5755 (set_attr "conds" "use")])
5757 (define_insn "*movsfcc_hard_insn"
5758 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
5760 (match_operator 3 "comparison_operator"
5761 [(match_operand 4 "cc_register" "") (const_int 0)])
5762 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
5763 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
5764 "TARGET_ARM && TARGET_HARD_FLOAT"
5770 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
5771 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
5772 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
5773 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
5774 [(set_attr "length" "4,4,4,4,8,8,8,8")
5775 (set_attr "type" "ffarith")
5776 (set_attr "conds" "use")])
5778 (define_insn "*movsfcc_soft_insn"
5779 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
5780 (if_then_else:SF (match_operator 3 "comparison_operator"
5781 [(match_operand 4 "cc_register" "") (const_int 0)])
5782 (match_operand:SF 1 "s_register_operand" "0,r")
5783 (match_operand:SF 2 "s_register_operand" "r,0")))]
5784 "TARGET_ARM && TARGET_SOFT_FLOAT"
5788 [(set_attr "conds" "use")])
5790 (define_insn "*movdfcc_insn"
5791 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
5793 (match_operator 3 "comparison_operator"
5794 [(match_operand 4 "cc_register" "") (const_int 0)])
5795 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
5796 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
5797 "TARGET_ARM && TARGET_HARD_FLOAT"
5803 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
5804 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
5805 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
5806 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
5807 [(set_attr "length" "4,4,4,4,8,8,8,8")
5808 (set_attr "type" "ffarith")
5809 (set_attr "conds" "use")])
5811 ;; Jump and linkage insns
5813 (define_expand "jump"
5815 (label_ref (match_operand 0 "" "")))]
5820 (define_insn "*arm_jump"
5822 (label_ref (match_operand 0 "" "")))]
5826 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5828 arm_ccfsm_state += 2;
5831 return \"b%?\\t%l0\";
5834 (define_insn "*thumb_jump"
5836 (label_ref (match_operand 0 "" "")))]
5839 if (get_attr_length (insn) == 2)
5841 return \"bl\\t%l0\\t%@ far jump\";
5843 [(set (attr "far_jump")
5845 (eq_attr "length" "4")
5846 (const_string "yes")
5847 (const_string "no")))
5848 (set (attr "length")
5850 (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
5851 (le (minus (match_dup 0) (pc)) (const_int 2044)))
5856 (define_expand "call"
5857 [(parallel [(call (match_operand 0 "memory_operand" "")
5858 (match_operand 1 "general_operand" ""))
5859 (use (match_operand 2 "" ""))
5860 (clobber (reg:SI 14))])]
5866 /* In an untyped call, we can get NULL for operand 2. */
5867 if (operands[2] == NULL_RTX)
5868 operands[2] = const0_rtx;
5870 /* This is to decide if we should generate indirect calls by loading the
5871 32 bit address of the callee into a register before performing the
5872 branch and link. operand[2] encodes the long_call/short_call
5873 attribute of the function being called. This attribute is set whenever
5874 __attribute__((long_call/short_call)) or #pragma long_call/no_long_call
5875 is used, and the short_call attribute can also be set if function is
5876 declared as static or if it has already been defined in the current
5877 compilation unit. See arm.c and arm.h for info about this. The third
5878 parameter to arm_is_longcall_p is used to tell it which pattern
5880 callee = XEXP (operands[0], 0);
5882 if (GET_CODE (callee) != REG
5883 && arm_is_longcall_p (operands[0], INTVAL (operands[2]), 0))
5884 XEXP (operands[0], 0) = force_reg (Pmode, callee);
5888 (define_insn "*call_reg"
5889 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
5890 (match_operand 1 "" ""))
5891 (use (match_operand 2 "" ""))
5892 (clobber (reg:SI 14))]
5895 return output_call (operands);
5897 ;; length is worst case, normally it is only two
5898 [(set_attr "length" "12")
5899 (set_attr "type" "call")]
5902 (define_insn "*call_mem"
5903 [(call (mem:SI (match_operand:SI 0 "memory_operand" "m"))
5904 (match_operand 1 "" ""))
5905 (use (match_operand 2 "" ""))
5906 (clobber (reg:SI 14))]
5909 return output_call_mem (operands);
5911 [(set_attr "length" "12")
5912 (set_attr "type" "call")]
5915 (define_insn "*call_indirect"
5916 [(call (mem:SI (match_operand:SI 0 "register_operand" "l*r"))
5917 (match_operand 1 "" ""))
5918 (use (match_operand 2 "" ""))
5919 (clobber (reg:SI 14))]
5923 if (TARGET_CALLER_INTERWORKING)
5924 return \"bl\\t%__interwork_call_via_%0\";
5926 return \"bl\\t%__call_via_%0\";
5928 [(set_attr "type" "call")]
5931 (define_insn "*call_value_indirect"
5932 [(set (match_operand 0 "" "=l")
5933 (call (mem:SI (match_operand:SI 1 "register_operand" "l*r"))
5934 (match_operand 2 "" "")))
5935 (use (match_operand 3 "" ""))
5936 (clobber (reg:SI 14))]
5940 if (TARGET_CALLER_INTERWORKING)
5941 return \"bl\\t%__interwork_call_via_%1\";
5943 return \"bl\\t%__call_via_%1\";
5945 [(set_attr "type" "call")]
5948 (define_expand "call_value"
5949 [(parallel [(set (match_operand 0 "" "=rf")
5950 (call (match_operand 1 "memory_operand" "m")
5951 (match_operand 2 "general_operand" "g")))
5952 (use (match_operand 3 "" ""))
5953 (clobber (reg:SI 14))])]
5957 rtx callee = XEXP (operands[1], 0);
5959 /* In an untyped call, we can get NULL for operand 2. */
5960 if (operands[3] == 0)
5961 operands[3] = const0_rtx;
5963 /* See the comment in define_expand \"call\". */
5964 if (GET_CODE (callee) != REG
5965 && arm_is_longcall_p (operands[1], INTVAL (operands[3]), 0))
5966 XEXP (operands[1], 0) = force_reg (Pmode, callee);
5970 (define_insn "*call_value_reg"
5971 [(set (match_operand 0 "" "=rf")
5972 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
5973 (match_operand 2 "" "")))
5974 (use (match_operand 3 "" ""))
5975 (clobber (reg:SI 14))]
5978 return output_call (& operands[1]);
5980 [(set_attr "length" "12")
5981 (set_attr "type" "call")]
5984 (define_insn "*call_value_mem"
5985 [(set (match_operand 0 "" "=rf")
5986 (call (mem:SI (match_operand:SI 1 "memory_operand" "m"))
5987 (match_operand 2 "" "")))
5988 (use (match_operand 3 "" ""))
5989 (clobber (reg:SI 14))]
5990 "TARGET_ARM && (! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))"
5992 return output_call_mem (& operands[1]);
5994 [(set_attr "length" "12")
5995 (set_attr "type" "call")]
5998 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
5999 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
6001 (define_insn "*call_symbol"
6002 [(call (mem:SI (match_operand:SI 0 "" "X"))
6003 (match_operand 1 "" ""))
6004 (use (match_operand 2 "" ""))
6005 (clobber (reg:SI 14))]
6007 && (GET_CODE (operands[0]) == SYMBOL_REF)
6008 && ! arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6011 return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6013 [(set_attr "type" "call")]
6016 (define_insn "*call_value_symbol"
6017 [(set (match_operand 0 "s_register_operand" "=rf")
6018 (call (mem:SI (match_operand:SI 1 "" "X"))
6019 (match_operand:SI 2 "general_operand" "g")))
6020 (use (match_operand 3 "" ""))
6021 (clobber (reg:SI 14))]
6023 && (GET_CODE (operands[1]) == SYMBOL_REF)
6024 && ! arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6027 return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6029 [(set_attr "type" "call")]
6032 (define_insn "*call_insn"
6033 [(call (mem:SI (match_operand:SI 0 "" "X"))
6034 (match_operand:SI 1 "" ""))
6035 (use (match_operand 2 "" ""))
6036 (clobber (reg:SI 14))]
6037 "TARGET_THUMB && operands[2] == const0_rtx && (GET_CODE (operands[0]) == SYMBOL_REF)"
6039 [(set_attr "length" "4")
6040 (set_attr "type" "call")]
6043 (define_insn "*call_value_insn"
6044 [(set (match_operand 0 "register_operand" "=l")
6045 (call (mem:SI (match_operand 1 "" "X"))
6046 (match_operand 2 "" "")))
6047 (use (match_operand 3 "" ""))
6048 (clobber (reg:SI 14))]
6049 "TARGET_THUMB && operands[3] == const0_rtx && (GET_CODE (operands[1]) == SYMBOL_REF)"
6051 [(set_attr "length" "4")
6052 (set_attr "type" "call")]
6055 ;; Often the return insn will be the same as loading from memory, so set attr
6056 (define_insn "return"
6058 "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6061 if (arm_ccfsm_state == 2)
6063 arm_ccfsm_state += 2;
6066 return output_return_instruction (NULL, TRUE, FALSE);
6068 [(set_attr "type" "load")]
6071 (define_insn "*cond_return"
6073 (if_then_else (match_operator 0 "comparison_operator"
6074 [(match_operand 1 "cc_register" "") (const_int 0)])
6077 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6080 if (arm_ccfsm_state == 2)
6082 arm_ccfsm_state += 2;
6085 return output_return_instruction (operands[0], TRUE, FALSE);
6087 [(set_attr "conds" "use")
6088 (set_attr "type" "load")])
6090 (define_insn "*cond_return_inverted"
6092 (if_then_else (match_operator 0 "comparison_operator"
6093 [(match_operand 1 "cc_register" "") (const_int 0)])
6096 "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6099 if (arm_ccfsm_state == 2)
6101 arm_ccfsm_state += 2;
6104 return output_return_instruction (operands[0], TRUE, TRUE);
6106 [(set_attr "conds" "use")
6107 (set_attr "type" "load")])
6109 ;; Call subroutine returning any type.
6111 (define_expand "untyped_call"
6112 [(parallel [(call (match_operand 0 "" "")
6114 (match_operand 1 "" "")
6115 (match_operand 2 "" "")])]
6121 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
6123 for (i = 0; i < XVECLEN (operands[2], 0); i++)
6125 rtx set = XVECEXP (operands[2], 0, i);
6126 emit_move_insn (SET_DEST (set), SET_SRC (set));
6129 /* The optimizer does not know that the call sets the function value
6130 registers we stored in the result block. We avoid problems by
6131 claiming that all hard registers are used and clobbered at this
6133 emit_insn (gen_blockage ());
6138 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
6139 ;; all of memory. This blocks insns from being moved across this point.
6141 (define_insn "blockage"
6142 [(unspec_volatile [(const_int 0)] 0)]
6145 [(set_attr "length" "0")
6146 (set_attr "type" "block")]
6149 (define_expand "casesi"
6150 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
6151 (match_operand:SI 1 "const_int_operand" "") ; lower bound
6152 (match_operand:SI 2 "const_int_operand" "") ; total range
6153 (match_operand:SI 3 "" "") ; table label
6154 (match_operand:SI 4 "" "")] ; Out of range label
6159 if (operands[1] != const0_rtx)
6161 reg = gen_reg_rtx (SImode);
6162 emit_insn (gen_addsi3 (reg, operands[0],
6163 GEN_INT (-INTVAL (operands[1]))));
6167 if (! const_ok_for_arm (INTVAL (operands[2])))
6168 operands[2] = force_reg (SImode, operands[2]);
6170 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
6175 ;; The USE in this pattern is needed to tell flow analysis that this is
6176 ;; a CASESI insn. It has no other purpose.
6177 (define_insn "casesi_internal"
6178 [(parallel [(set (pc)
6180 (leu (match_operand:SI 0 "s_register_operand" "r")
6181 (match_operand:SI 1 "arm_rhs_operand" "rI"))
6182 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
6183 (label_ref (match_operand 2 "" ""))))
6184 (label_ref (match_operand 3 "" ""))))
6185 (clobber (reg:CC 24))
6186 (use (label_ref (match_dup 2)))])]
6190 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
6191 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
6193 [(set_attr "conds" "clob")
6194 (set_attr "length" "12")])
6196 (define_expand "indirect_jump"
6198 (match_operand:SI 0 "s_register_operand" ""))]
6203 (define_insn "*arm_indirect_jump"
6205 (match_operand:SI 0 "s_register_operand" "r"))]
6207 "mov%?\\t%|pc, %0\\t%@ indirect register jump"
6210 ;; Although not supported by the define_expand above,
6211 ;; cse/combine may generate this form.
6212 (define_insn "*load_indirect_jump"
6214 (match_operand:SI 0 "memory_operand" "m"))]
6216 "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6217 [(set_attr "type" "load")]
6220 (define_insn "*thumb_indirect_jump"
6222 (match_operand:SI 0 "register_operand" "l*r"))]
6225 [(set_attr "conds" "clob")
6226 (set_attr "length" "2")]
6237 return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6238 return \"mov\\tr8, r8\";
6240 [(set (attr "length")
6241 (if_then_else (eq_attr "is_thumb" "yes")
6247 ;; Patterns to allow combination of arithmetic, cond code and shifts
6249 (define_insn "*arith_shiftsi"
6250 [(set (match_operand:SI 0 "s_register_operand" "=r")
6251 (match_operator:SI 1 "shiftable_operator"
6252 [(match_operator:SI 3 "shift_operator"
6253 [(match_operand:SI 4 "s_register_operand" "r")
6254 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6255 (match_operand:SI 2 "s_register_operand" "r")]))]
6257 "%i1%?\\t%0, %2, %4%S3"
6260 (define_insn "*arith_shiftsi_compare0"
6261 [(set (reg:CC_NOOV 24)
6262 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6263 [(match_operator:SI 3 "shift_operator"
6264 [(match_operand:SI 4 "s_register_operand" "r")
6265 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6266 (match_operand:SI 2 "s_register_operand" "r")])
6268 (set (match_operand:SI 0 "s_register_operand" "=r")
6269 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
6272 "%i1%?s\\t%0, %2, %4%S3"
6273 [(set_attr "conds" "set")
6276 (define_insn "*arith_shiftsi_compare0_scratch"
6277 [(set (reg:CC_NOOV 24)
6278 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
6279 [(match_operator:SI 3 "shift_operator"
6280 [(match_operand:SI 4 "s_register_operand" "r")
6281 (match_operand:SI 5 "reg_or_int_operand" "rI")])
6282 (match_operand:SI 2 "s_register_operand" "r")])
6284 (clobber (match_scratch:SI 0 "=r"))]
6286 "%i1%?s\\t%0, %2, %4%S3"
6287 [(set_attr "conds" "set")
6290 (define_insn "*sub_shiftsi"
6291 [(set (match_operand:SI 0 "s_register_operand" "=r")
6292 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6293 (match_operator:SI 2 "shift_operator"
6294 [(match_operand:SI 3 "s_register_operand" "r")
6295 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
6297 "sub%?\\t%0, %1, %3%S2"
6300 (define_insn "*sub_shiftsi_compare0"
6301 [(set (reg:CC_NOOV 24)
6303 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6304 (match_operator:SI 2 "shift_operator"
6305 [(match_operand:SI 3 "s_register_operand" "r")
6306 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6308 (set (match_operand:SI 0 "s_register_operand" "=r")
6309 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6312 "sub%?s\\t%0, %1, %3%S2"
6313 [(set_attr "conds" "set")
6316 (define_insn "*sub_shiftsi_compare0_scratch"
6317 [(set (reg:CC_NOOV 24)
6319 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
6320 (match_operator:SI 2 "shift_operator"
6321 [(match_operand:SI 3 "s_register_operand" "r")
6322 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
6324 (clobber (match_scratch:SI 0 "=r"))]
6326 "sub%?s\\t%0, %1, %3%S2"
6327 [(set_attr "conds" "set")
6330 ;; These variants of the above insns can occur if the first operand is the
6331 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
6332 ;; seem to be a way around it. Most of the predicates have to be null
6333 ;; because the format can be generated part way through reload, so
6334 ;; if we don't match it as soon as it becomes available, reload doesn't know
6335 ;; how to reload pseudos that haven't got hard registers; the constraints will
6336 ;; sort everything out.
6338 (define_insn "*reload_mulsi3"
6339 [(set (match_operand:SI 0 "" "=&r")
6340 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
6341 [(match_operand:SI 3 "" "r")
6342 (match_operand:SI 4 "" "rM")])
6343 (match_operand:SI 2 "" "r"))
6344 (match_operand:SI 1 "const_int_operand" "n")))]
6345 "TARGET_ARM && reload_in_progress"
6347 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
6348 operands[2] = operands[1];
6349 operands[1] = operands[0];
6350 return output_add_immediate (operands);
6352 ; we have no idea how long the add_immediate is, it could be up to 4.
6353 [(set_attr "length" "20")])
6355 (define_insn "*reload_mulsi_compare0"
6356 [(set (reg:CC_NOOV 24)
6357 (compare:CC_NOOV (plus:SI
6359 (match_operator:SI 5 "shift_operator"
6360 [(match_operand:SI 3 "" "r")
6361 (match_operand:SI 4 "" "rM")])
6362 (match_operand:SI 1 "" "r"))
6363 (match_operand:SI 2 "const_int_operand" "n"))
6365 (set (match_operand:SI 0 "" "=&r")
6366 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
6369 "TARGET_ARM && reload_in_progress"
6371 output_add_immediate (operands);
6372 return \"add%?s\\t%0, %0, %3%S5\";
6374 [(set_attr "conds" "set")
6375 (set_attr "length" "20")])
6377 (define_insn "*reload_mulsi_compare0_scratch"
6378 [(set (reg:CC_NOOV 24)
6379 (compare:CC_NOOV (plus:SI
6381 (match_operator:SI 5 "shift_operator"
6382 [(match_operand:SI 3 "" "r")
6383 (match_operand:SI 4 "" "rM")])
6384 (match_operand:SI 1 "" "r"))
6385 (match_operand:SI 2 "const_int_operand" "n"))
6387 (clobber (match_scratch:SI 0 "=&r"))]
6388 "TARGET_ARM && reload_in_progress"
6390 output_add_immediate (operands);
6391 return \"add%?s\\t%0, %0, %3%S5\";
6393 [(set_attr "conds" "set")
6394 (set_attr "length" "20")])
6396 ;; These are similar, but are needed when the mla pattern contains the
6397 ;; eliminated register as operand 3.
6399 (define_insn "*reload_muladdsi"
6400 [(set (match_operand:SI 0 "" "=&r,&r")
6401 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
6402 (match_operand:SI 2 "" "r,r"))
6403 (match_operand:SI 3 "" "r,r"))
6404 (match_operand:SI 4 "const_int_operand" "n,n")))]
6405 "TARGET_ARM && reload_in_progress"
6407 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
6408 operands[2] = operands[4];
6409 operands[1] = operands[0];
6410 return output_add_immediate (operands);
6412 [(set_attr "length" "20")
6413 (set_attr "type" "mult")])
6415 (define_insn "*reload_muladdsi_compare0"
6416 [(set (reg:CC_NOOV 24)
6417 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
6418 (match_operand:SI 3 "" "r")
6419 (match_operand:SI 4 "" "r"))
6420 (match_operand:SI 1 "" "r"))
6421 (match_operand:SI 2 "const_int_operand" "n"))
6423 (set (match_operand:SI 0 "" "=&r")
6424 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
6426 "TARGET_ARM && reload_in_progress"
6428 output_add_immediate (operands);
6429 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
6432 [(set_attr "length" "20")
6433 (set_attr "conds" "set")
6434 (set_attr "type" "mult")])
6436 (define_insn "*reload_muladdsi_compare0_scratch"
6437 [(set (reg:CC_NOOV 24)
6438 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
6439 (match_operand:SI 3 "" "r")
6440 (match_operand:SI 4 "" "r"))
6441 (match_operand:SI 1 "" "r"))
6442 (match_operand:SI 2 "const_int_operand" "n"))
6444 (clobber (match_scratch:SI 0 "=&r"))]
6445 "TARGET_ARM && reload_in_progress"
6447 output_add_immediate (operands);
6448 return \"mla%?s\\t%0, %3, %4, %0\";
6450 [(set_attr "length" "20")
6451 (set_attr "conds" "set")
6452 (set_attr "type" "mult")])
6456 (define_insn "*and_scc"
6457 [(set (match_operand:SI 0 "s_register_operand" "=r")
6458 (and:SI (match_operator 1 "comparison_operator"
6459 [(match_operand 3 "cc_register" "") (const_int 0)])
6460 (match_operand:SI 2 "s_register_operand" "r")))]
6462 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
6463 [(set_attr "conds" "use")
6464 (set_attr "length" "8")])
6466 (define_insn "*ior_scc"
6467 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6468 (ior:SI (match_operator 2 "comparison_operator"
6469 [(match_operand 3 "cc_register" "") (const_int 0)])
6470 (match_operand:SI 1 "s_register_operand" "0,?r")))]
6474 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
6475 [(set_attr "conds" "use")
6476 (set_attr "length" "4,8")])
6478 (define_insn "*compare_scc"
6479 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6480 (match_operator:SI 1 "comparison_operator"
6481 [(match_operand:SI 2 "s_register_operand" "r,r")
6482 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
6483 (clobber (reg:CC 24))]
6486 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
6487 return \"mov\\t%0, %2, lsr #31\";
6489 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
6490 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
6492 if (GET_CODE (operands[1]) == NE)
6494 if (which_alternative == 1)
6495 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
6496 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
6498 if (which_alternative == 1)
6499 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6501 output_asm_insn (\"cmp\\t%2, %3\", operands);
6502 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
6504 [(set_attr "conds" "clob")
6505 (set_attr "length" "12")])
6507 (define_insn "*cond_move"
6508 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6509 (if_then_else:SI (match_operator 3 "equality_operator"
6510 [(match_operator 4 "comparison_operator"
6511 [(match_operand 5 "cc_register" "") (const_int 0)])
6513 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6514 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
6517 if (GET_CODE (operands[3]) == NE)
6519 if (which_alternative != 1)
6520 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
6521 if (which_alternative != 0)
6522 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
6525 if (which_alternative != 0)
6526 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6527 if (which_alternative != 1)
6528 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
6531 [(set_attr "conds" "use")
6532 (set_attr "length" "4,4,8")])
6534 (define_insn "*cond_arith"
6535 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6536 (match_operator:SI 5 "shiftable_operator"
6537 [(match_operator:SI 4 "comparison_operator"
6538 [(match_operand:SI 2 "s_register_operand" "r,r")
6539 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
6540 (match_operand:SI 1 "s_register_operand" "0,?r")]))
6541 (clobber (reg:CC 24))]
6544 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
6545 return \"%i5\\t%0, %1, %2, lsr #31\";
6547 output_asm_insn (\"cmp\\t%2, %3\", operands);
6548 if (GET_CODE (operands[5]) == AND)
6549 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
6550 else if (GET_CODE (operands[5]) == MINUS)
6551 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
6552 else if (which_alternative != 0)
6553 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6554 return \"%i5%d4\\t%0, %1, #1\";
6556 [(set_attr "conds" "clob")
6557 (set_attr "length" "12")])
6559 (define_insn "*cond_sub"
6560 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6561 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
6562 (match_operator:SI 4 "comparison_operator"
6563 [(match_operand:SI 2 "s_register_operand" "r,r")
6564 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
6565 (clobber (reg:CC 24))]
6568 output_asm_insn (\"cmp\\t%2, %3\", operands);
6569 if (which_alternative != 0)
6570 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
6571 return \"sub%d4\\t%0, %1, #1\";
6573 [(set_attr "conds" "clob")
6574 (set_attr "length" "8,12")])
6576 (define_insn "*cmp_ite0"
6577 [(set (match_operand 6 "dominant_cc_register" "")
6580 (match_operator 4 "comparison_operator"
6581 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6582 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6583 (match_operator:SI 5 "comparison_operator"
6584 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6585 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6591 char * opcodes[4][2] =
6593 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
6594 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
6595 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
6596 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
6597 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
6600 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
6602 return opcodes[which_alternative][swap];
6605 [(set_attr "conds" "set")
6606 (set_attr "length" "8")])
6608 (define_insn "*cmp_ite1"
6609 [(set (match_operand 6 "dominant_cc_register" "")
6612 (match_operator 4 "comparison_operator"
6613 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
6614 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
6615 (match_operator:SI 5 "comparison_operator"
6616 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
6617 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
6623 char * opcodes[4][2] =
6625 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
6626 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
6627 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
6628 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
6629 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
6632 comparison_dominates_p (GET_CODE (operands[5]),
6633 reverse_condition (GET_CODE (operands[4])));
6635 return opcodes[which_alternative][swap];
6638 [(set_attr "conds" "set")
6639 (set_attr "length" "8")])
6641 (define_insn "*negscc"
6642 [(set (match_operand:SI 0 "s_register_operand" "=r")
6643 (neg:SI (match_operator 3 "comparison_operator"
6644 [(match_operand:SI 1 "s_register_operand" "r")
6645 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
6646 (clobber (reg:CC 24))]
6649 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
6650 return \"mov\\t%0, %1, asr #31\";
6652 if (GET_CODE (operands[3]) == NE)
6653 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
6655 if (GET_CODE (operands[3]) == GT)
6656 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
6658 output_asm_insn (\"cmp\\t%1, %2\", operands);
6659 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
6660 return \"mvn%d3\\t%0, #0\";
6662 [(set_attr "conds" "clob")
6663 (set_attr "length" "12")])
6665 (define_insn "movcond"
6666 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6668 (match_operator 5 "comparison_operator"
6669 [(match_operand:SI 3 "s_register_operand" "r,r,r")
6670 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
6671 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
6672 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
6673 (clobber (reg:CC 24))]
6676 if (GET_CODE (operands[5]) == LT
6677 && (operands[4] == const0_rtx))
6679 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
6681 if (operands[2] == const0_rtx)
6682 return \"and\\t%0, %1, %3, asr #31\";
6683 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
6685 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
6687 if (operands[1] == const0_rtx)
6688 return \"bic\\t%0, %2, %3, asr #31\";
6689 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
6691 /* The only case that falls through to here is when both ops 1 & 2
6695 if (GET_CODE (operands[5]) == GE
6696 && (operands[4] == const0_rtx))
6698 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
6700 if (operands[2] == const0_rtx)
6701 return \"bic\\t%0, %1, %3, asr #31\";
6702 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
6704 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
6706 if (operands[1] == const0_rtx)
6707 return \"and\\t%0, %2, %3, asr #31\";
6708 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
6710 /* The only case that falls through to here is when both ops 1 & 2
6713 if (GET_CODE (operands[4]) == CONST_INT
6714 && !const_ok_for_arm (INTVAL (operands[4])))
6715 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
6717 output_asm_insn (\"cmp\\t%3, %4\", operands);
6718 if (which_alternative != 0)
6719 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
6720 if (which_alternative != 1)
6721 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
6724 [(set_attr "conds" "clob")
6725 (set_attr "length" "8,8,12")])
6727 (define_insn "*ifcompare_plus_move"
6728 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6729 (if_then_else:SI (match_operator 6 "comparison_operator"
6730 [(match_operand:SI 4 "s_register_operand" "r,r")
6731 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
6733 (match_operand:SI 2 "s_register_operand" "r,r")
6734 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
6735 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
6736 (clobber (reg:CC 24))]
6739 [(set_attr "conds" "clob")
6740 (set_attr "length" "8,12")])
6742 (define_insn "*if_plus_move"
6743 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
6745 (match_operator 4 "comparison_operator"
6746 [(match_operand 5 "cc_register" "") (const_int 0)])
6748 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
6749 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
6750 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
6754 sub%d4\\t%0, %2, #%n3
6755 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
6756 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
6757 [(set_attr "conds" "use")
6758 (set_attr "length" "4,4,8,8")
6759 (set_attr "type" "*,*,*,*")])
6761 (define_insn "*ifcompare_move_plus"
6762 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6763 (if_then_else:SI (match_operator 6 "comparison_operator"
6764 [(match_operand:SI 4 "s_register_operand" "r,r")
6765 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
6766 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
6768 (match_operand:SI 2 "s_register_operand" "r,r")
6769 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
6770 (clobber (reg:CC 24))]
6773 [(set_attr "conds" "clob")
6774 (set_attr "length" "8,12")])
6776 (define_insn "*if_move_plus"
6777 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
6779 (match_operator 4 "comparison_operator"
6780 [(match_operand 5 "cc_register" "") (const_int 0)])
6781 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
6783 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
6784 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
6788 sub%D4\\t%0, %2, #%n3
6789 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
6790 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
6791 [(set_attr "conds" "use")
6792 (set_attr "length" "4,4,8,8")
6793 (set_attr "type" "*,*,*,*")])
6795 (define_insn "*ifcompare_arith_arith"
6796 [(set (match_operand:SI 0 "s_register_operand" "=r")
6797 (if_then_else:SI (match_operator 9 "comparison_operator"
6798 [(match_operand:SI 5 "s_register_operand" "r")
6799 (match_operand:SI 6 "arm_add_operand" "rIL")])
6800 (match_operator:SI 8 "shiftable_operator"
6801 [(match_operand:SI 1 "s_register_operand" "r")
6802 (match_operand:SI 2 "arm_rhs_operand" "rI")])
6803 (match_operator:SI 7 "shiftable_operator"
6804 [(match_operand:SI 3 "s_register_operand" "r")
6805 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
6806 (clobber (reg:CC 24))]
6809 [(set_attr "conds" "clob")
6810 (set_attr "length" "12")])
6812 (define_insn "*if_arith_arith"
6813 [(set (match_operand:SI 0 "s_register_operand" "=r")
6814 (if_then_else:SI (match_operator 5 "comparison_operator"
6815 [(match_operand 8 "cc_register" "") (const_int 0)])
6816 (match_operator:SI 6 "shiftable_operator"
6817 [(match_operand:SI 1 "s_register_operand" "r")
6818 (match_operand:SI 2 "arm_rhs_operand" "rI")])
6819 (match_operator:SI 7 "shiftable_operator"
6820 [(match_operand:SI 3 "s_register_operand" "r")
6821 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
6823 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
6824 [(set_attr "conds" "use")
6825 (set_attr "length" "8")])
6827 (define_insn "*ifcompare_arith_move"
6828 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6829 (if_then_else:SI (match_operator 6 "comparison_operator"
6830 [(match_operand:SI 2 "s_register_operand" "r,r")
6831 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
6832 (match_operator:SI 7 "shiftable_operator"
6833 [(match_operand:SI 4 "s_register_operand" "r,r")
6834 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
6835 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
6836 (clobber (reg:CC 24))]
6839 /* If we have an operation where (op x 0) is the identity operation and
6840 the conditional operator is LT or GE and we are comparing against zero and
6841 everything is in registers then we can do this in two instructions */
6842 if (operands[3] == const0_rtx
6843 && GET_CODE (operands[7]) != AND
6844 && GET_CODE (operands[5]) == REG
6845 && GET_CODE (operands[1]) == REG
6846 && REGNO (operands[1]) == REGNO (operands[4])
6847 && REGNO (operands[4]) != REGNO (operands[0]))
6849 if (GET_CODE (operands[6]) == LT)
6850 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
6851 else if (GET_CODE (operands[6]) == GE)
6852 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
6854 if (GET_CODE (operands[3]) == CONST_INT
6855 && !const_ok_for_arm (INTVAL (operands[3])))
6856 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6858 output_asm_insn (\"cmp\\t%2, %3\", operands);
6859 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
6860 if (which_alternative != 0)
6861 return \"mov%D6\\t%0, %1\";
6864 [(set_attr "conds" "clob")
6865 (set_attr "length" "8,12")])
6867 (define_insn "*if_arith_move"
6868 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6869 (if_then_else:SI (match_operator 4 "comparison_operator"
6870 [(match_operand 6 "cc_register" "") (const_int 0)])
6871 (match_operator:SI 5 "shiftable_operator"
6872 [(match_operand:SI 2 "s_register_operand" "r,r")
6873 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
6874 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
6878 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
6879 [(set_attr "conds" "use")
6880 (set_attr "length" "4,8")
6881 (set_attr "type" "*,*")])
6883 (define_insn "*ifcompare_move_arith"
6884 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6885 (if_then_else:SI (match_operator 6 "comparison_operator"
6886 [(match_operand:SI 4 "s_register_operand" "r,r")
6887 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
6888 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
6889 (match_operator:SI 7 "shiftable_operator"
6890 [(match_operand:SI 2 "s_register_operand" "r,r")
6891 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
6892 (clobber (reg:CC 24))]
6895 /* If we have an operation where (op x 0) is the identity operation and
6896 the conditional operator is LT or GE and we are comparing against zero and
6897 everything is in registers then we can do this in two instructions */
6898 if (operands[5] == const0_rtx
6899 && GET_CODE (operands[7]) != AND
6900 && GET_CODE (operands[3]) == REG
6901 && GET_CODE (operands[1]) == REG
6902 && REGNO (operands[1]) == REGNO (operands[2])
6903 && REGNO (operands[2]) != REGNO (operands[0]))
6905 if (GET_CODE (operands[6]) == GE)
6906 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
6907 else if (GET_CODE (operands[6]) == LT)
6908 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
6911 if (GET_CODE (operands[5]) == CONST_INT
6912 && !const_ok_for_arm (INTVAL (operands[5])))
6913 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
6915 output_asm_insn (\"cmp\\t%4, %5\", operands);
6917 if (which_alternative != 0)
6918 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
6919 return \"%I7%D6\\t%0, %2, %3\";
6921 [(set_attr "conds" "clob")
6922 (set_attr "length" "8,12")])
6924 (define_insn "*if_move_arith"
6925 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6927 (match_operator 4 "comparison_operator"
6928 [(match_operand 6 "cc_register" "") (const_int 0)])
6929 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
6930 (match_operator:SI 5 "shiftable_operator"
6931 [(match_operand:SI 2 "s_register_operand" "r,r")
6932 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
6936 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
6937 [(set_attr "conds" "use")
6938 (set_attr "length" "4,8")
6939 (set_attr "type" "*,*")])
6941 (define_insn "*ifcompare_move_not"
6942 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6944 (match_operator 5 "comparison_operator"
6945 [(match_operand:SI 3 "s_register_operand" "r,r")
6946 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
6947 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
6949 (match_operand:SI 2 "s_register_operand" "r,r"))))
6950 (clobber (reg:CC 24))]
6953 [(set_attr "conds" "clob")
6954 (set_attr "length" "8,12")])
6956 (define_insn "*if_move_not"
6957 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6959 (match_operator 4 "comparison_operator"
6960 [(match_operand 3 "cc_register" "") (const_int 0)])
6961 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
6962 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
6966 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
6967 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
6968 [(set_attr "conds" "use")
6969 (set_attr "length" "4,8,8")])
6971 (define_insn "*ifcompare_not_move"
6972 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
6974 (match_operator 5 "comparison_operator"
6975 [(match_operand:SI 3 "s_register_operand" "r,r")
6976 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
6978 (match_operand:SI 2 "s_register_operand" "r,r"))
6979 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
6980 (clobber (reg:CC 24))]
6983 [(set_attr "conds" "clob")
6984 (set_attr "length" "8,12")])
6986 (define_insn "*if_not_move"
6987 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
6989 (match_operator 4 "comparison_operator"
6990 [(match_operand 3 "cc_register" "") (const_int 0)])
6991 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
6992 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
6996 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
6997 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
6998 [(set_attr "conds" "use")
6999 (set_attr "length" "4,8,8")])
7001 (define_insn "*ifcompare_shift_move"
7002 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7004 (match_operator 6 "comparison_operator"
7005 [(match_operand:SI 4 "s_register_operand" "r,r")
7006 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7007 (match_operator:SI 7 "shift_operator"
7008 [(match_operand:SI 2 "s_register_operand" "r,r")
7009 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
7010 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7011 (clobber (reg:CC 24))]
7014 [(set_attr "conds" "clob")
7015 (set_attr "length" "8,12")])
7017 (define_insn "*if_shift_move"
7018 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7020 (match_operator 5 "comparison_operator"
7021 [(match_operand 6 "cc_register" "") (const_int 0)])
7022 (match_operator:SI 4 "shift_operator"
7023 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7024 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
7025 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7029 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
7030 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
7031 [(set_attr "conds" "use")
7032 (set_attr "length" "4,8,8")])
7034 (define_insn "*ifcompare_move_shift"
7035 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7037 (match_operator 6 "comparison_operator"
7038 [(match_operand:SI 4 "s_register_operand" "r,r")
7039 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
7040 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7041 (match_operator:SI 7 "shift_operator"
7042 [(match_operand:SI 2 "s_register_operand" "r,r")
7043 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
7044 (clobber (reg:CC 24))]
7047 [(set_attr "conds" "clob")
7048 (set_attr "length" "8,12")])
7050 (define_insn "*if_move_shift"
7051 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7053 (match_operator 5 "comparison_operator"
7054 [(match_operand 6 "cc_register" "") (const_int 0)])
7055 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7056 (match_operator:SI 4 "shift_operator"
7057 [(match_operand:SI 2 "s_register_operand" "r,r,r")
7058 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
7062 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
7063 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
7064 [(set_attr "conds" "use")
7065 (set_attr "length" "4,8,8")])
7067 (define_insn "*ifcompare_shift_shift"
7068 [(set (match_operand:SI 0 "s_register_operand" "=r")
7070 (match_operator 7 "comparison_operator"
7071 [(match_operand:SI 5 "s_register_operand" "r")
7072 (match_operand:SI 6 "arm_add_operand" "rIL")])
7073 (match_operator:SI 8 "shift_operator"
7074 [(match_operand:SI 1 "s_register_operand" "r")
7075 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7076 (match_operator:SI 9 "shift_operator"
7077 [(match_operand:SI 3 "s_register_operand" "r")
7078 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
7079 (clobber (reg:CC 24))]
7082 [(set_attr "conds" "clob")
7083 (set_attr "length" "12")])
7085 (define_insn "*if_shift_shift"
7086 [(set (match_operand:SI 0 "s_register_operand" "=r")
7088 (match_operator 5 "comparison_operator"
7089 [(match_operand 8 "cc_register" "") (const_int 0)])
7090 (match_operator:SI 6 "shift_operator"
7091 [(match_operand:SI 1 "s_register_operand" "r")
7092 (match_operand:SI 2 "arm_rhs_operand" "rM")])
7093 (match_operator:SI 7 "shift_operator"
7094 [(match_operand:SI 3 "s_register_operand" "r")
7095 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
7097 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
7098 [(set_attr "conds" "use")
7099 (set_attr "length" "8")])
7101 (define_insn "*ifcompare_not_arith"
7102 [(set (match_operand:SI 0 "s_register_operand" "=r")
7104 (match_operator 6 "comparison_operator"
7105 [(match_operand:SI 4 "s_register_operand" "r")
7106 (match_operand:SI 5 "arm_add_operand" "rIL")])
7107 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7108 (match_operator:SI 7 "shiftable_operator"
7109 [(match_operand:SI 2 "s_register_operand" "r")
7110 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
7111 (clobber (reg:CC 24))]
7114 [(set_attr "conds" "clob")
7115 (set_attr "length" "12")])
7117 (define_insn "*if_not_arith"
7118 [(set (match_operand:SI 0 "s_register_operand" "=r")
7120 (match_operator 5 "comparison_operator"
7121 [(match_operand 4 "cc_register" "") (const_int 0)])
7122 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
7123 (match_operator:SI 6 "shiftable_operator"
7124 [(match_operand:SI 2 "s_register_operand" "r")
7125 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
7127 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
7128 [(set_attr "conds" "use")
7129 (set_attr "length" "8")])
7131 (define_insn "*ifcompare_arith_not"
7132 [(set (match_operand:SI 0 "s_register_operand" "=r")
7134 (match_operator 6 "comparison_operator"
7135 [(match_operand:SI 4 "s_register_operand" "r")
7136 (match_operand:SI 5 "arm_add_operand" "rIL")])
7137 (match_operator:SI 7 "shiftable_operator"
7138 [(match_operand:SI 2 "s_register_operand" "r")
7139 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7140 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
7141 (clobber (reg:CC 24))]
7144 [(set_attr "conds" "clob")
7145 (set_attr "length" "12")])
7147 (define_insn "*if_arith_not"
7148 [(set (match_operand:SI 0 "s_register_operand" "=r")
7150 (match_operator 5 "comparison_operator"
7151 [(match_operand 4 "cc_register" "") (const_int 0)])
7152 (match_operator:SI 6 "shiftable_operator"
7153 [(match_operand:SI 2 "s_register_operand" "r")
7154 (match_operand:SI 3 "arm_rhs_operand" "rI")])
7155 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
7157 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
7158 [(set_attr "conds" "use")
7159 (set_attr "length" "8")])
7161 (define_insn "*ifcompare_neg_move"
7162 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7164 (match_operator 5 "comparison_operator"
7165 [(match_operand:SI 3 "s_register_operand" "r,r")
7166 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7167 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
7168 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
7169 (clobber (reg:CC 24))]
7172 [(set_attr "conds" "clob")
7173 (set_attr "length" "8,12")])
7175 (define_insn "*if_neg_move"
7176 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7178 (match_operator 4 "comparison_operator"
7179 [(match_operand 3 "cc_register" "") (const_int 0)])
7180 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
7181 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
7185 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
7186 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
7187 [(set_attr "conds" "use")
7188 (set_attr "length" "4,8,8")])
7190 (define_insn "*ifcompare_move_neg"
7191 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
7193 (match_operator 5 "comparison_operator"
7194 [(match_operand:SI 3 "s_register_operand" "r,r")
7195 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
7196 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
7197 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
7198 (clobber (reg:CC 24))]
7201 [(set_attr "conds" "clob")
7202 (set_attr "length" "8,12")])
7204 (define_insn "*if_move_neg"
7205 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
7207 (match_operator 4 "comparison_operator"
7208 [(match_operand 3 "cc_register" "") (const_int 0)])
7209 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
7210 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
7214 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
7215 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
7216 [(set_attr "conds" "use")
7217 (set_attr "length" "4,8,8")])
7219 (define_insn "*arith_adjacentmem"
7220 [(set (match_operand:SI 0 "s_register_operand" "=r")
7221 (match_operator:SI 1 "shiftable_operator"
7222 [(match_operand:SI 2 "memory_operand" "m")
7223 (match_operand:SI 3 "memory_operand" "m")]))
7224 (clobber (match_scratch:SI 4 "=r"))]
7225 "TARGET_ARM && adjacent_mem_locations (operands[2], operands[3])"
7230 int val1 = 0, val2 = 0;
7232 if (REGNO (operands[0]) > REGNO (operands[4]))
7234 ldm[1] = operands[4];
7235 ldm[2] = operands[0];
7239 ldm[1] = operands[0];
7240 ldm[2] = operands[4];
7242 if (GET_CODE (XEXP (operands[2], 0)) != REG)
7243 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
7244 if (GET_CODE (XEXP (operands[3], 0)) != REG)
7245 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
7246 arith[0] = operands[0];
7247 arith[3] = operands[1];
7261 ldm[0] = ops[0] = operands[4];
7262 ops[1] = XEXP (XEXP (operands[2], 0), 0);
7263 ops[2] = XEXP (XEXP (operands[2], 0), 1);
7264 output_add_immediate (ops);
7266 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7268 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7272 ldm[0] = XEXP (operands[3], 0);
7274 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7276 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7280 ldm[0] = XEXP (operands[2], 0);
7282 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7284 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7286 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7290 [(set_attr "length" "12")
7291 (set_attr "type" "load")])
7293 ;; the arm can support extended pre-inc instructions
7295 ;; In all these cases, we use operands 0 and 1 for the register being
7296 ;; incremented because those are the operands that local-alloc will
7297 ;; tie and these are the pair most likely to be tieable (and the ones
7298 ;; that will benefit the most).
7300 ;; We reject the frame pointer if it occurs anywhere in these patterns since
7301 ;; elimination will cause too many headaches.
7303 (define_insn "*strqi_preinc"
7304 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7305 (match_operand:SI 2 "index_operand" "rJ")))
7306 (match_operand:QI 3 "s_register_operand" "r"))
7307 (set (match_operand:SI 0 "s_register_operand" "=r")
7308 (plus:SI (match_dup 1) (match_dup 2)))]
7310 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7311 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7312 && (GET_CODE (operands[2]) != REG
7313 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7314 "str%?b\\t%3, [%0, %2]!"
7315 [(set_attr "type" "store1")])
7317 (define_insn "*strqi_predec"
7318 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7319 (match_operand:SI 2 "s_register_operand" "r")))
7320 (match_operand:QI 3 "s_register_operand" "r"))
7321 (set (match_operand:SI 0 "s_register_operand" "=r")
7322 (minus:SI (match_dup 1) (match_dup 2)))]
7324 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7325 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7326 && (GET_CODE (operands[2]) != REG
7327 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7328 "str%?b\\t%3, [%0, -%2]!"
7329 [(set_attr "type" "store1")])
7331 (define_insn "*loadqi_preinc"
7332 [(set (match_operand:QI 3 "s_register_operand" "=r")
7333 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7334 (match_operand:SI 2 "index_operand" "rJ"))))
7335 (set (match_operand:SI 0 "s_register_operand" "=r")
7336 (plus:SI (match_dup 1) (match_dup 2)))]
7338 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7339 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7340 && (GET_CODE (operands[2]) != REG
7341 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7342 "ldr%?b\\t%3, [%0, %2]!"
7343 [(set_attr "type" "load")])
7345 (define_insn "*loadqi_predec"
7346 [(set (match_operand:QI 3 "s_register_operand" "=r")
7347 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7348 (match_operand:SI 2 "s_register_operand" "r"))))
7349 (set (match_operand:SI 0 "s_register_operand" "=r")
7350 (minus:SI (match_dup 1) (match_dup 2)))]
7352 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7353 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7354 && (GET_CODE (operands[2]) != REG
7355 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7356 "ldr%?b\\t%3, [%0, -%2]!"
7357 [(set_attr "type" "load")])
7359 (define_insn "*loadqisi_preinc"
7360 [(set (match_operand:SI 3 "s_register_operand" "=r")
7362 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7363 (match_operand:SI 2 "index_operand" "rJ")))))
7364 (set (match_operand:SI 0 "s_register_operand" "=r")
7365 (plus:SI (match_dup 1) (match_dup 2)))]
7367 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7368 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7369 && (GET_CODE (operands[2]) != REG
7370 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7371 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
7372 [(set_attr "type" "load")])
7374 (define_insn "*loadqisi_predec"
7375 [(set (match_operand:SI 3 "s_register_operand" "=r")
7377 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7378 (match_operand:SI 2 "s_register_operand" "r")))))
7379 (set (match_operand:SI 0 "s_register_operand" "=r")
7380 (minus:SI (match_dup 1) (match_dup 2)))]
7382 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7383 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7384 && (GET_CODE (operands[2]) != REG
7385 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7386 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
7387 [(set_attr "type" "load")])
7389 (define_insn "*strsi_preinc"
7390 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7391 (match_operand:SI 2 "index_operand" "rJ")))
7392 (match_operand:SI 3 "s_register_operand" "r"))
7393 (set (match_operand:SI 0 "s_register_operand" "=r")
7394 (plus:SI (match_dup 1) (match_dup 2)))]
7396 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7397 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7398 && (GET_CODE (operands[2]) != REG
7399 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7400 "str%?\\t%3, [%0, %2]!"
7401 [(set_attr "type" "store1")])
7403 (define_insn "*strsi_predec"
7404 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7405 (match_operand:SI 2 "s_register_operand" "r")))
7406 (match_operand:SI 3 "s_register_operand" "r"))
7407 (set (match_operand:SI 0 "s_register_operand" "=r")
7408 (minus:SI (match_dup 1) (match_dup 2)))]
7410 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7411 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7412 && (GET_CODE (operands[2]) != REG
7413 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7414 "str%?\\t%3, [%0, -%2]!"
7415 [(set_attr "type" "store1")])
7417 (define_insn "*loadsi_preinc"
7418 [(set (match_operand:SI 3 "s_register_operand" "=r")
7419 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7420 (match_operand:SI 2 "index_operand" "rJ"))))
7421 (set (match_operand:SI 0 "s_register_operand" "=r")
7422 (plus:SI (match_dup 1) (match_dup 2)))]
7424 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7425 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7426 && (GET_CODE (operands[2]) != REG
7427 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7428 "ldr%?\\t%3, [%0, %2]!"
7429 [(set_attr "type" "load")])
7431 (define_insn "*loadsi_predec"
7432 [(set (match_operand:SI 3 "s_register_operand" "=r")
7433 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7434 (match_operand:SI 2 "s_register_operand" "r"))))
7435 (set (match_operand:SI 0 "s_register_operand" "=r")
7436 (minus:SI (match_dup 1) (match_dup 2)))]
7438 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7439 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7440 && (GET_CODE (operands[2]) != REG
7441 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7442 "ldr%?\\t%3, [%0, -%2]!"
7443 [(set_attr "type" "load")])
7445 (define_insn "*loadhi_preinc"
7446 [(set (match_operand:HI 3 "s_register_operand" "=r")
7447 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
7448 (match_operand:SI 2 "index_operand" "rJ"))))
7449 (set (match_operand:SI 0 "s_register_operand" "=r")
7450 (plus:SI (match_dup 1) (match_dup 2)))]
7452 && (! BYTES_BIG_ENDIAN)
7453 && ! TARGET_MMU_TRAPS
7454 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7455 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7456 && (GET_CODE (operands[2]) != REG
7457 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7458 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
7459 [(set_attr "type" "load")])
7461 (define_insn "*loadhi_predec"
7462 [(set (match_operand:HI 3 "s_register_operand" "=r")
7463 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7464 (match_operand:SI 2 "s_register_operand" "r"))))
7465 (set (match_operand:SI 0 "s_register_operand" "=r")
7466 (minus:SI (match_dup 1) (match_dup 2)))]
7468 && (!BYTES_BIG_ENDIAN)
7469 && ! TARGET_MMU_TRAPS
7470 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7471 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7472 && (GET_CODE (operands[2]) != REG
7473 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
7474 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
7475 [(set_attr "type" "load")])
7477 (define_insn "*strqi_shiftpreinc"
7478 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
7479 [(match_operand:SI 3 "s_register_operand" "r")
7480 (match_operand:SI 4 "const_shift_operand" "n")])
7481 (match_operand:SI 1 "s_register_operand" "0")))
7482 (match_operand:QI 5 "s_register_operand" "r"))
7483 (set (match_operand:SI 0 "s_register_operand" "=r")
7484 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7487 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7488 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7489 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7490 "str%?b\\t%5, [%0, %3%S2]!"
7491 [(set_attr "type" "store1")])
7493 (define_insn "*strqi_shiftpredec"
7494 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7495 (match_operator:SI 2 "shift_operator"
7496 [(match_operand:SI 3 "s_register_operand" "r")
7497 (match_operand:SI 4 "const_shift_operand" "n")])))
7498 (match_operand:QI 5 "s_register_operand" "r"))
7499 (set (match_operand:SI 0 "s_register_operand" "=r")
7500 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7503 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7504 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7505 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7506 "str%?b\\t%5, [%0, -%3%S2]!"
7507 [(set_attr "type" "store1")])
7509 (define_insn "*loadqi_shiftpreinc"
7510 [(set (match_operand:QI 5 "s_register_operand" "=r")
7511 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
7512 [(match_operand:SI 3 "s_register_operand" "r")
7513 (match_operand:SI 4 "const_shift_operand" "n")])
7514 (match_operand:SI 1 "s_register_operand" "0"))))
7515 (set (match_operand:SI 0 "s_register_operand" "=r")
7516 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7519 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7520 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7521 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7522 "ldr%?b\\t%5, [%0, %3%S2]!"
7523 [(set_attr "type" "load")])
7525 (define_insn "*loadqi_shiftpredec"
7526 [(set (match_operand:QI 5 "s_register_operand" "=r")
7527 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7528 (match_operator:SI 2 "shift_operator"
7529 [(match_operand:SI 3 "s_register_operand" "r")
7530 (match_operand:SI 4 "const_shift_operand" "n")]))))
7531 (set (match_operand:SI 0 "s_register_operand" "=r")
7532 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7535 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7536 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7537 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7538 "ldr%?b\\t%5, [%0, -%3%S2]!"
7539 [(set_attr "type" "load")])
7541 (define_insn "*strsi_shiftpreinc"
7542 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
7543 [(match_operand:SI 3 "s_register_operand" "r")
7544 (match_operand:SI 4 "const_shift_operand" "n")])
7545 (match_operand:SI 1 "s_register_operand" "0")))
7546 (match_operand:SI 5 "s_register_operand" "r"))
7547 (set (match_operand:SI 0 "s_register_operand" "=r")
7548 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7551 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7552 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7553 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7554 "str%?\\t%5, [%0, %3%S2]!"
7555 [(set_attr "type" "store1")])
7557 (define_insn "*strsi_shiftpredec"
7558 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7559 (match_operator:SI 2 "shift_operator"
7560 [(match_operand:SI 3 "s_register_operand" "r")
7561 (match_operand:SI 4 "const_shift_operand" "n")])))
7562 (match_operand:SI 5 "s_register_operand" "r"))
7563 (set (match_operand:SI 0 "s_register_operand" "=r")
7564 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7567 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7568 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7569 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7570 "str%?\\t%5, [%0, -%3%S2]!"
7571 [(set_attr "type" "store1")])
7573 (define_insn "*loadsi_shiftpreinc"
7574 [(set (match_operand:SI 5 "s_register_operand" "=r")
7575 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
7576 [(match_operand:SI 3 "s_register_operand" "r")
7577 (match_operand:SI 4 "const_shift_operand" "n")])
7578 (match_operand:SI 1 "s_register_operand" "0"))))
7579 (set (match_operand:SI 0 "s_register_operand" "=r")
7580 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7583 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7584 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7585 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7586 "ldr%?\\t%5, [%0, %3%S2]!"
7587 [(set_attr "type" "load")])
7589 (define_insn "*loadsi_shiftpredec"
7590 [(set (match_operand:SI 5 "s_register_operand" "=r")
7591 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7592 (match_operator:SI 2 "shift_operator"
7593 [(match_operand:SI 3 "s_register_operand" "r")
7594 (match_operand:SI 4 "const_shift_operand" "n")]))))
7595 (set (match_operand:SI 0 "s_register_operand" "=r")
7596 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7599 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7600 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7601 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7602 "ldr%?\\t%5, [%0, -%3%S2]!"
7603 [(set_attr "type" "load")])
7605 (define_insn "*loadhi_shiftpreinc"
7606 [(set (match_operand:HI 5 "s_register_operand" "=r")
7607 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
7608 [(match_operand:SI 3 "s_register_operand" "r")
7609 (match_operand:SI 4 "const_shift_operand" "n")])
7610 (match_operand:SI 1 "s_register_operand" "0"))))
7611 (set (match_operand:SI 0 "s_register_operand" "=r")
7612 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7615 && (! BYTES_BIG_ENDIAN)
7616 && ! TARGET_MMU_TRAPS
7617 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7618 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7619 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7620 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
7621 [(set_attr "type" "load")])
7623 (define_insn "*loadhi_shiftpredec"
7624 [(set (match_operand:HI 5 "s_register_operand" "=r")
7625 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
7626 (match_operator:SI 2 "shift_operator"
7627 [(match_operand:SI 3 "s_register_operand" "r")
7628 (match_operand:SI 4 "const_shift_operand" "n")]))))
7629 (set (match_operand:SI 0 "s_register_operand" "=r")
7630 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
7633 && (! BYTES_BIG_ENDIAN)
7634 && ! TARGET_MMU_TRAPS
7635 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
7636 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
7637 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
7638 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
7639 [(set_attr "type" "load")])
7641 ; It can also support extended post-inc expressions, but combine doesn't
7643 ; It doesn't seem worth adding peepholes for anything but the most common
7644 ; cases since, unlike combine, the increment must immediately follow the load
7645 ; for this pattern to match.
7646 ; When loading we must watch to see that the base register isn't trampled by
7647 ; the load. In such cases this isn't a post-inc expression.
7650 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
7651 (match_operand:QI 2 "s_register_operand" "r"))
7653 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
7655 "str%?b\\t%2, [%0], %1")
7658 [(set (match_operand:QI 0 "s_register_operand" "=r")
7659 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
7661 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
7662 "TARGET_ARM && REGNO(operands[0]) != REGNO(operands[1])
7663 && (GET_CODE (operands[2]) != REG
7664 || REGNO(operands[0]) != REGNO (operands[2]))"
7665 "ldr%?b\\t%0, [%1], %2")
7668 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
7669 (match_operand:SI 2 "s_register_operand" "r"))
7671 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
7673 "str%?\\t%2, [%0], %1")
7676 [(set (match_operand:HI 0 "s_register_operand" "=r")
7677 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
7679 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
7681 && (! BYTES_BIG_ENDIAN)
7682 && ! TARGET_MMU_TRAPS
7683 && REGNO(operands[0]) != REGNO(operands[1])
7684 && (GET_CODE (operands[2]) != REG
7685 || REGNO(operands[0]) != REGNO (operands[2]))"
7686 "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
7689 [(set (match_operand:SI 0 "s_register_operand" "=r")
7690 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
7692 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
7694 && REGNO(operands[0]) != REGNO(operands[1])
7695 && (GET_CODE (operands[2]) != REG
7696 || REGNO(operands[0]) != REGNO (operands[2]))"
7697 "ldr%?\\t%0, [%1], %2")
7700 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
7701 (match_operand:SI 1 "index_operand" "rJ")))
7702 (match_operand:QI 2 "s_register_operand" "r"))
7703 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
7705 "str%?b\\t%2, [%0, %1]!")
7708 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
7709 [(match_operand:SI 0 "s_register_operand" "r")
7710 (match_operand:SI 1 "const_int_operand" "n")])
7711 (match_operand:SI 2 "s_register_operand" "+r")))
7712 (match_operand:QI 3 "s_register_operand" "r"))
7713 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
7716 "str%?b\\t%3, [%2, %0%S4]!")
7718 ; This pattern is never tried by combine, so do it as a peephole
7721 [(set (match_operand:SI 0 "s_register_operand" "=r")
7722 (match_operand:SI 1 "s_register_operand" "r"))
7724 (compare:CC (match_dup 1) (const_int 0)))]
7726 "sub%?s\\t%0, %1, #0"
7727 [(set_attr "conds" "set")])
7729 ; Peepholes to spot possible load- and store-multiples, if the ordering is
7730 ; reversed, check that the memory references aren't volatile.
7733 [(set (match_operand:SI 0 "s_register_operand" "=r")
7734 (match_operand:SI 4 "memory_operand" "m"))
7735 (set (match_operand:SI 1 "s_register_operand" "=r")
7736 (match_operand:SI 5 "memory_operand" "m"))
7737 (set (match_operand:SI 2 "s_register_operand" "=r")
7738 (match_operand:SI 6 "memory_operand" "m"))
7739 (set (match_operand:SI 3 "s_register_operand" "=r")
7740 (match_operand:SI 7 "memory_operand" "m"))]
7741 "TARGET_ARM && load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
7743 return emit_ldm_seq (operands, 4);
7747 [(set (match_operand:SI 0 "s_register_operand" "=r")
7748 (match_operand:SI 3 "memory_operand" "m"))
7749 (set (match_operand:SI 1 "s_register_operand" "=r")
7750 (match_operand:SI 4 "memory_operand" "m"))
7751 (set (match_operand:SI 2 "s_register_operand" "=r")
7752 (match_operand:SI 5 "memory_operand" "m"))]
7753 "TARGET_ARM && load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
7755 return emit_ldm_seq (operands, 3);
7759 [(set (match_operand:SI 0 "s_register_operand" "=r")
7760 (match_operand:SI 2 "memory_operand" "m"))
7761 (set (match_operand:SI 1 "s_register_operand" "=r")
7762 (match_operand:SI 3 "memory_operand" "m"))]
7763 "TARGET_ARM && load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
7765 return emit_ldm_seq (operands, 2);
7769 [(set (match_operand:SI 4 "memory_operand" "=m")
7770 (match_operand:SI 0 "s_register_operand" "r"))
7771 (set (match_operand:SI 5 "memory_operand" "=m")
7772 (match_operand:SI 1 "s_register_operand" "r"))
7773 (set (match_operand:SI 6 "memory_operand" "=m")
7774 (match_operand:SI 2 "s_register_operand" "r"))
7775 (set (match_operand:SI 7 "memory_operand" "=m")
7776 (match_operand:SI 3 "s_register_operand" "r"))]
7777 "TARGET_ARM && store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
7779 return emit_stm_seq (operands, 4);
7783 [(set (match_operand:SI 3 "memory_operand" "=m")
7784 (match_operand:SI 0 "s_register_operand" "r"))
7785 (set (match_operand:SI 4 "memory_operand" "=m")
7786 (match_operand:SI 1 "s_register_operand" "r"))
7787 (set (match_operand:SI 5 "memory_operand" "=m")
7788 (match_operand:SI 2 "s_register_operand" "r"))]
7789 "TARGET_ARM && store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
7791 return emit_stm_seq (operands, 3);
7795 [(set (match_operand:SI 2 "memory_operand" "=m")
7796 (match_operand:SI 0 "s_register_operand" "r"))
7797 (set (match_operand:SI 3 "memory_operand" "=m")
7798 (match_operand:SI 1 "s_register_operand" "r"))]
7799 "TARGET_ARM && store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
7801 return emit_stm_seq (operands, 2);
7804 ;; A call followed by return can be replaced by restoring the regs and
7805 ;; jumping to the subroutine, provided we aren't passing the address of
7806 ;; any of our local variables. If we call alloca then this is unsafe
7807 ;; since restoring the frame frees the memory, which is not what we want.
7808 ;; Sometimes the return might have been targeted by the final prescan:
7809 ;; if so then emit a proper return insn as well.
7810 ;; Unfortunately, if the frame pointer is required, we don't know if the
7811 ;; current function has any implicit stack pointer adjustments that will
7812 ;; be restored by the return: we can't therefore do a tail call.
7813 ;; Another unfortunate that we can't handle is if current_function_args_size
7814 ;; is non-zero: in this case elimination of the argument pointer assumed
7815 ;; that lr was pushed onto the stack, so eliminating upsets the offset
7819 [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
7820 (match_operand:SI 1 "general_operand" "g"))
7821 (use (match_operand 2 "" ""))
7822 (clobber (reg:SI 14))])
7825 && (GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN (FALSE)
7826 && !get_frame_size () && !current_function_calls_alloca
7827 && !frame_pointer_needed && !current_function_args_size)"
7830 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
7832 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
7833 output_return_instruction (NULL, TRUE, FALSE);
7834 arm_ccfsm_state = 0;
7835 arm_target_insn = NULL;
7838 output_return_instruction (NULL, FALSE, FALSE);
7839 return NEED_PLT_RELOC ? \"b%?\\t%a0(PLT)\" : \"b%?\\t%a0\";
7841 [(set_attr "type" "call")
7842 (set_attr "length" "8")])
7845 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
7846 (call (mem:SI (match_operand:SI 1 "" "X"))
7847 (match_operand:SI 2 "general_operand" "g")))
7848 (use (match_operand 3 "" ""))
7849 (clobber (reg:SI 14))])
7851 "TARGET_ARM && (GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN (FALSE)
7852 && !get_frame_size () && !current_function_calls_alloca
7853 && !frame_pointer_needed && !current_function_args_size)"
7856 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
7858 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
7859 output_return_instruction (NULL, TRUE, FALSE);
7860 arm_ccfsm_state = 0;
7861 arm_target_insn = NULL;
7864 output_return_instruction (NULL, FALSE, FALSE);
7865 return NEED_PLT_RELOC ? \"b%?\\t%a1(PLT)\" : \"b%?\\t%a1\";
7867 [(set_attr "type" "call")
7868 (set_attr "length" "8")])
7870 ;; As above but when this function is not void, we must be returning the
7871 ;; result of the called subroutine.
7874 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
7875 (call (mem:SI (match_operand:SI 1 "" "X"))
7876 (match_operand:SI 2 "general_operand" "g")))
7877 (use (match_operand 3 "" ""))
7878 (clobber (reg:SI 14))])
7882 && (GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN (FALSE)
7883 && !get_frame_size () && !current_function_calls_alloca
7884 && !frame_pointer_needed && !current_function_args_size)"
7887 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
7889 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
7890 output_return_instruction (NULL, TRUE, FALSE);
7891 arm_ccfsm_state = 0;
7892 arm_target_insn = NULL;
7895 output_return_instruction (NULL, FALSE, FALSE);
7896 return \"b%?\\t%a1\";
7898 [(set_attr "type" "call")
7899 (set_attr "length" "8")])
7902 [(set (match_operand:SI 0 "s_register_operand" "")
7903 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
7905 (neg:SI (match_operator:SI 2 "comparison_operator"
7906 [(match_operand:SI 3 "s_register_operand" "")
7907 (match_operand:SI 4 "arm_rhs_operand" "")]))))
7908 (clobber (match_operand:SI 5 "s_register_operand" ""))]
7910 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
7911 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
7915 ;; This split can be used because CC_Z mode implies that the following
7916 ;; branch will be an equality, or an unsigned inequality, so the sign
7917 ;; extension is not needed.
7922 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
7924 (match_operand 1 "const_int_operand" "")))
7925 (clobber (match_scratch:SI 2 ""))]
7927 && (((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
7928 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24)"
7929 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
7930 (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))]
7932 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
7935 (define_expand "prologue"
7936 [(clobber (const_int 0))]
7939 arm_expand_prologue ();
7941 thumb_expand_prologue ();
7946 (define_expand "epilogue"
7947 [(unspec_volatile [(return)] 1)]
7951 thumb_expand_epilogue ();
7952 else if (USE_RETURN_INSN (FALSE))
7954 emit_jump_insn (gen_return ());
7957 emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
7959 gen_rtx_RETURN (VOIDmode)),
7965 (define_insn "*epilogue_insns"
7966 [(unspec_volatile [(return)] 1)]
7970 return arm_output_epilogue ();
7971 else /* TARGET_THUMB */
7972 return thumb_unexpanded_epilogue ();
7974 ;; Length is absolute worst case
7975 [(set_attr "length" "44")
7976 (set_attr "type" "block")]
7979 (define_expand "eh_epilogue"
7980 [(use (match_operand:SI 0 "register_operand" "r"))
7981 (use (match_operand:SI 1 "register_operand" "r"))
7982 (use (match_operand:SI 2 "register_operand" "r"))]
7986 cfun->machine->eh_epilogue_sp_ofs = operands[1];
7987 if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
7989 rtx ra = gen_rtx_REG (Pmode, 2);
7990 emit_move_insn (ra, operands[2]);
7995 ;; This split is only used during output to reduce the number of patterns
7996 ;; that need assembler instructions adding to them. We allowed the setting
7997 ;; of the conditions to be implicit during rtl generation so that
7998 ;; the conditional compare patterns would work. However this conflicts to
7999 ;; some extent with the conditional data operations, so we have to split them
8003 [(set (match_operand:SI 0 "s_register_operand" "")
8004 (if_then_else:SI (match_operator 1 "comparison_operator"
8005 [(match_operand 2 "" "") (match_operand 3 "" "")])
8006 (match_operand 4 "" "")
8007 (match_operand 5 "" "")))
8008 (clobber (reg:CC 24))]
8009 "TARGET_ARM && reload_completed"
8010 [(set (match_dup 6) (match_dup 7))
8012 (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
8017 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
8020 operands[6] = gen_rtx_REG (mode, 24);
8021 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8026 [(set (match_operand:SI 0 "s_register_operand" "")
8027 (if_then_else:SI (match_operator 1 "comparison_operator"
8028 [(match_operand:SI 2 "s_register_operand" "")
8029 (match_operand:SI 3 "arm_add_operand" "")])
8030 (match_operand:SI 4 "arm_rhs_operand" "")
8032 (match_operand:SI 5 "s_register_operand" ""))))
8033 (clobber (reg:CC 24))]
8034 "TARGET_ARM && reload_completed"
8035 [(set (match_dup 6) (match_dup 7))
8037 (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
8039 (not:SI (match_dup 5))))]
8042 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
8045 operands[6] = gen_rtx_REG (mode, 24);
8046 operands[7] = gen_rtx (COMPARE, mode, operands[2], operands[3]);
8050 (define_insn "*cond_move_not"
8051 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
8052 (if_then_else:SI (match_operator 4 "comparison_operator"
8053 [(match_operand 3 "cc_register" "") (const_int 0)])
8054 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
8056 (match_operand:SI 2 "s_register_operand" "r,r"))))]
8060 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2"
8061 [(set_attr "conds" "use")
8062 (set_attr "length" "4,8")])
8064 ;; The next two patterns occur when an AND operation is followed by a
8065 ;; scc insn sequence
8067 (define_insn "*sign_extract_onebit"
8068 [(set (match_operand:SI 0 "s_register_operand" "=r")
8069 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8071 (match_operand:SI 2 "const_int_operand" "n")))]
8074 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8075 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
8076 return \"mvnne\\t%0, #0\";
8078 [(set_attr "conds" "clob")
8079 (set_attr "length" "8")])
8081 (define_insn "*not_signextract_onebit"
8082 [(set (match_operand:SI 0 "s_register_operand" "=r")
8084 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8086 (match_operand:SI 2 "const_int_operand" "n"))))]
8089 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
8090 output_asm_insn (\"tst\\t%1, %2\", operands);
8091 output_asm_insn (\"mvneq\\t%0, #0\", operands);
8092 return \"movne\\t%0, #0\";
8094 [(set_attr "conds" "clob")
8095 (set_attr "length" "12")])
8097 ;; Push multiple registers to the stack. The first register is in the
8098 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
8100 (define_insn "*push_multi"
8101 [(match_parallel 2 "multi_register_push"
8102 [(set (match_operand:BLK 0 "memory_operand" "=m")
8103 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
8107 extern int lr_save_eliminated;
8108 int num_saves = XVECLEN (operands[2], 0);
8110 if (lr_save_eliminated)
8115 /* For the StrongARM at least it is faster to
8116 use STR to store only a single register. */
8117 else if (num_saves == 1)
8118 output_asm_insn (\"str\\t%1, [%m0, #-4]!\", operands);
8124 if (lr_save_eliminated)
8127 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8129 for (i = 1; i < num_saves; i++)
8131 strcat (pattern, \", %|\");
8132 strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
8136 strcat (pattern, \"}\");
8137 output_asm_insn (pattern, operands);
8142 [(set_attr "type" "store4")])
8144 ;; Similarly for the floating point registers
8145 (define_insn "*push_fp_multi"
8146 [(match_parallel 2 "multi_register_push"
8147 [(set (match_operand:BLK 0 "memory_operand" "=m")
8148 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
8154 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8155 output_asm_insn (pattern, operands);
8158 [(set_attr "type" "f_store")])
8160 ;; Special patterns for dealing with the constant pool
8162 (define_insn "align_4"
8163 [(unspec_volatile [(const_int 0)] 2)]
8166 assemble_align (32);
8171 (define_insn "consttable_end"
8172 [(unspec_volatile [(const_int 0)] 3)]
8175 making_const_table = FALSE;
8180 (define_insn "consttable_1"
8181 [(unspec_volatile [(match_operand 0 "" "")] 4)]
8184 making_const_table = TRUE;
8185 assemble_integer (operands[0], 1, 1);
8189 [(set_attr "length" "4")]
8192 (define_insn "consttable_2"
8193 [(unspec_volatile [(match_operand 0 "" "")] 5)]
8196 making_const_table = TRUE;
8197 assemble_integer (operands[0], 2, 1);
8201 [(set_attr "length" "4")]
8204 (define_insn "consttable_4"
8205 [(unspec_volatile [(match_operand 0 "" "")] 6)]
8209 making_const_table = TRUE;
8210 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8214 union real_extract u;
8215 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
8216 assemble_real (u.d, GET_MODE (operands[0]));
8220 assemble_integer (operands[0], 4, 1);
8225 [(set_attr "length" "4")]
8228 (define_insn "consttable_8"
8229 [(unspec_volatile [(match_operand 0 "" "")] 7)]
8233 making_const_table = TRUE;
8234 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8238 union real_extract u;
8239 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
8240 assemble_real (u.d, GET_MODE (operands[0]));
8244 assemble_integer (operands[0], 8, 1);
8249 [(set_attr "length" "8")]
8252 ;; Miscellaneous Thumb patterns
8254 (define_insn "tablejump"
8255 [(set (pc) (match_operand:SI 0 "register_operand" "l*r"))
8256 (use (label_ref (match_operand 1 "" "")))]
8259 [(set_attr "length" "2")]