Merge changes from merged-arm-thumb-backend-branch onto trunk.
[official-gcc.git] / gcc / config / arm / arm.md
blobe67f133fcef708007b895f811be44f92c6cb0de6
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)
12 ;; any later version.
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.
28 ;; (See arm.h)
30 ;; UNSPEC Usage:
31 ;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
32 ;;   the mode is MODE_FLOAT
33 ;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
34 ;;   the mode is MODE_FLOAT
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.
41 ;; Attributes
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
63 ; reference the pool.
64 ; NEG_POOL_RANGE is nonzero for insns that can reference a constant pool entry
65 ; before its address.
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
105 (define_attr "type"
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
119 ; inlined branches
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")
149                 (const_string "yes")
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
159 ;; distant label.
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 ;;--------------------------------------------------------------------
211 ;; Write buffer
212 ;;--------------------------------------------------------------------
213 ;; Strictly we should model a 4-deep write buffer for ARM7xx based chips
214 (define_function_unit "write_buf" 1 2
215   (and (eq_attr "model_wbuf" "yes")
216        (eq_attr "type" "store1,r_mem_f")) 5 3)
217 (define_function_unit "write_buf" 1 2 
218   (and (eq_attr "model_wbuf" "yes")
219        (eq_attr "type" "store2")) 7 4)
220 (define_function_unit "write_buf" 1 2
221   (and (eq_attr "model_wbuf" "yes")
222        (eq_attr "type" "store3")) 9 5)
223 (define_function_unit "write_buf" 1 2
224   (and (eq_attr "model_wbuf" "yes")
225        (eq_attr "type" "store4")) 11 6)
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 ;;--------------------------------------------------------------------
251 ;; Core unit
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
303 ;; independently.
304 (define_split
305   [(set (match_operand:DI          0 "s_register_operand" "")
306         (plus:DI (match_operand:DI 1 "s_register_operand"  "")
307                  (match_operand:DI 2 "s_register_operand"   "")))
308    (clobber (reg:CC 24))]
309   "TARGET_ARM && reload_completed"
310   [(parallel [(set (reg:CC_C 24)
311                       (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
312                                     (match_dup 1)))
313               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
314    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
315                                (plus:SI (match_dup 4) (match_dup 5))))]
316   "
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.
330 (define_split
331   [(set (match_operand:DI 0 "s_register_operand" "")
332         (plus:DI (sign_extend:DI
333                   (match_operand:SI 2 "s_register_operand" ""))
334                   (match_operand:DI 1 "s_register_operand" "")))
335    (clobber (reg:CC 24))]
336   "TARGET_ARM && reload_completed"
337   [(parallel [(set (reg:CC_C 24)
338                       (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
339                                     (match_dup 1)))
340               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
341    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
342                                (plus:SI (ashiftrt:SI (match_dup 2)
343                                                      (const_int 31))
344                                         (match_dup 4))))]
345   "
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
357 ;; operand 1
358 (define_split
359   [(set (match_operand:DI 0 "s_register_operand" "")
360         (plus:DI (zero_extend:DI
361                   (match_operand:SI 2 "s_register_operand" ""))
362                   (match_operand:DI 1 "s_register_operand" "")))
363    (clobber (reg:CC 24))]
364   "TARGET_ARM && reload_completed"
365   [(parallel [(set (reg:CC_C 24)
366                       (compare:CC_C (plus:SI (match_dup 1) (match_dup 2))
367                                     (match_dup 1)))
368               (set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))])
369    (set (match_dup 3) (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
370                                (plus:SI (match_dup 4) (const_int 0))))]
371   "
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]);
380 ;; Addition insns.
382 (define_expand "adddi3"
383  [(parallel
384    [(set (match_operand:DI          0 "s_register_operand" "")
385           (plus:DI (match_operand:DI 1 "s_register_operand" "")
386                    (match_operand:DI 2 "s_register_operand" "")))
387     (clobber (reg:CC 24))
388    ])]
389   "TARGET_EITHER"
390   "
391   if (TARGET_THUMB)
392     {
393       if (GET_CODE (operands[1]) != REG)
394         operands[1] = force_reg (SImode, operands[1]);
395       if (GET_CODE (operands[2]) != REG)
396         operands[2] = force_reg (SImode, operands[2]);
397      }
398   "
401 (define_insn "*thumb_adddi3"
402   [(set (match_operand:DI          0 "register_operand" "=l")
403         (plus:DI (match_operand:DI 1 "register_operand" "%0")
404                  (match_operand:DI 2 "register_operand"  "l")))
405    (clobber (reg:CC 24))
406   ]
407   "TARGET_THUMB"
408   "add\\t%Q0, %Q0, %Q2\;adc\\t%R0, %R0, %R2"
409   [(set_attr "length" "4")]
412 (define_insn "*arm_adddi3"
413   [(set (match_operand:DI          0 "s_register_operand" "=&r,&r")
414         (plus:DI (match_operand:DI 1 "s_register_operand"  "%0,0")
415                  (match_operand:DI 2 "s_register_operand"   "r,0")))
416    (clobber (reg:CC 24))
417   ]
418   "TARGET_ARM"
419   "#"
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))
430   ]
431   "TARGET_ARM"
432   "#"
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))
442   ]
443   "TARGET_ARM"
444   "#"
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" "")))]
453   "TARGET_EITHER"
454   "
455   if (TARGET_ARM && GET_CODE (operands[2]) == CONST_INT)
456     {
457       arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
458                           operands[1],
459                           (reload_in_progress || reload_completed ? 0
460                            : preserve_subexpressions_p ()));
461       DONE;
462     }
463   "
466 (define_split
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"  "")))]
470   "TARGET_ARM &&
471   (! (const_ok_for_arm (INTVAL (operands[2]))
472    || const_ok_for_arm (-INTVAL (operands[2]))))"
473   [(clobber (const_int 0))]
474   "
475   arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
476                       operands[1], 0);
477   DONE;
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")))]
484   "TARGET_ARM"
485   "@
486    add%?\\t%0, %1, %2
487    sub%?\\t%0, %1, #%n2
488    #"
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")))]
500   "TARGET_THUMB"
501   "*
502    static char * asms[] = 
503    {
504      \"add\\t%0, %0, %2\",
505      \"sub\\t%0, %0, #%n2\",
506      \"add\\t%0, %1, %2\",
507      \"add\\t%0, %0, %2\",
508      \"add\\t%0, %0, %2\",
509      \"add\\t%0, %1, %2\",
510      \"add\\t%0, %1, %2\"
511    };
512    if ((which_alternative == 2 || which_alternative == 6)
513        && GET_CODE (operands[2]) == CONST_INT
514        && INTVAL (operands[2]) < 0)
515      return \"sub\\t%0, %1, #%n2\";
516    return asms[which_alternative];
517   "
518   [(set_attr "length" "2")]
521 ;; Reloading and elimination of the frame pointer can
522 ;; sometimes cause this optimization to be missed.
523 (define_peephole
524   [(set (match_operand:SI 0 "register_operand" "=l")
525         (match_operand:SI 1 "const_int_operand" "M"))
526    (set (match_dup 0)
527         (plus:SI (match_dup 0) (match_operand:SI 2 "register_operand" "k")))]
528   "TARGET_THUMB
529    && REGNO (operands[2]) == STACK_POINTER_REGNUM 
530    && (unsigned HOST_WIDE_INT) (INTVAL (operands[1])) < 1024
531    && (INTVAL (operands[1]) & 3) == 0"
532   "add\\t%0, %2, %1"
533   [(set_attr "length" "2")]
536 (define_insn "*addsi3_compare0"
537   [(set (reg:CC_NOOV 24)
538         (compare:CC_NOOV
539          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
540                   (match_operand:SI 2 "arm_add_operand"   "rI,L"))
541          (const_int 0)))
542    (set (match_operand:SI 0 "s_register_operand" "=r,r")
543         (plus:SI (match_dup 1) (match_dup 2)))]
544   "TARGET_ARM"
545   "@
546    add%?s\\t%0, %1, %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)
553         (compare:CC_NOOV
554          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
555                   (match_operand:SI 1 "arm_add_operand"   "rI,L"))
556          (const_int 0)))]
557   "TARGET_ARM"
558   "@
559    cmn%?\\t%0, %1
560    cmp%?\\t%0, #%n1"
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"
567   [(set (reg:CC 24)
568         (compare:CC
569          (match_operand:SI 1 "s_register_operand" "r,r")
570          (neg:SI (match_operand:SI 2 "arm_add_operand" "rI,L"))))
571    (set (match_operand:SI 0 "s_register_operand" "=r,r")
572         (plus:SI (match_dup 1) (match_dup 2)))]
573   "TARGET_ARM"
574   "@
575    add%?s\\t%0, %1, %2
576    sub%?s\\t%0, %1, #%n2"
577   [(set_attr "conds" "set")]
580 (define_insn "*addsi3_compare0_scratch_for_combiner"
581   [(set (reg:CC 24)
582         (compare:CC
583          (match_operand:SI 0 "s_register_operand" "r,r")
584          (neg:SI (match_operand:SI 1 "arm_add_operand" "rI,L"))))]
585   "TARGET_ARM"
586   "@
587    cmn%?\\t%0, %1
588    cmp%?\\t%0, #%n1"
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"
596   [(set (reg:CC_C 24)
597         (compare:CC_C
598          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
599                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
600          (match_dup 1)))
601    (set (match_operand:SI 0 "s_register_operand" "=r,r")
602         (plus:SI (match_dup 1) (match_dup 2)))]
603   "TARGET_ARM"
604   "@
605    add%?s\\t%0, %1, %2
606    sub%?s\\t%0, %1, #%n2"
607 [(set_attr "conds" "set")])
609 (define_insn "*addsi3_compare_op2"
610   [(set (reg:CC_C 24)
611         (compare:CC_C
612          (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
613                   (match_operand:SI 2 "arm_add_operand" "rI,L"))
614          (match_dup 2)))
615    (set (match_operand:SI 0 "s_register_operand" "=r,r")
616         (plus:SI (match_dup 1) (match_dup 2)))]
617   "TARGET_ARM"
618   "@
619    add%?s\\t%0, %1, %2
620    sub%?s\\t%0, %1, #%n2"
621 [(set_attr "conds" "set")])
623 (define_insn "*compare_addsi2_op0"
624   [(set (reg:CC_C 24)
625         (compare:CC_C
626          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
627                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
628          (match_dup 0)))]
629   "TARGET_ARM"
630   "@
631    cmn%?\\t%0, %1
632    cmp%?\\t%0, #%n1"
633 [(set_attr "conds" "set")])
635 (define_insn "*compare_addsi2_op1"
636   [(set (reg:CC_C 24)
637         (compare:CC_C
638          (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
639                   (match_operand:SI 1 "arm_add_operand" "rI,L"))
640          (match_dup 1)))]
641   "TARGET_ARM"
642   "@
643    cmn%?\\t%0, %1
644    cmp%?\\t%0, #%n1"
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"))))]
652   "TARGET_ARM"
653   "adc%?\\t%0, %1, %2"
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))
660                  (plus:SI
661                    (match_operator:SI 2 "shift_operator"
662                       [(match_operand:SI 3 "s_register_operand" "")
663                        (match_operand:SI 4 "reg_or_int_operand" "")])
664                     (match_operand:SI 1 "s_register_operand" ""))))]
665   "TARGET_ARM"
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))))]
675   "TARGET_ARM"
676   "adc%?\\t%0, %1, %2"
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")))]
685   "TARGET_ARM"
686   "adc%?\\t%0, %1, %2"
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")))]
694   "TARGET_ARM"
695   "adc%?\\t%0, %1, %2"
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")))]
704   "TARGET_ARM"
705   "@
706   add%d2\\t%0, %1, #1
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.
715 (define_split
716   [(set (match_operand:SI          0 "s_register_operand" "=r")
717         (plus:SI (match_operand:SI 1 "s_register_operand"  "r")
718                  (match_operand:SI 2 "const_int_operand"   "n")))]
719   "TARGET_ARM
720     && (! (const_ok_for_arm (INTVAL (operands[2]))
721         || const_ok_for_arm (-INTVAL (operands[2]))))"
722   [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
723    (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
724   "
726   unsigned int val = (unsigned) INTVAL (operands[2]);
727   int i;
728   unsigned int temp;
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)
734     {
735       if (val & (3 << i))
736         {
737           i -= 6;
738           if (i < 0) i = 0;
739           if (const_ok_for_arm (temp = (val & ~(255 << i))))
740             {
741               val &= 255 << i;
742               break;
743             }
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)
747             {
748               i += 2;
749               temp = ((val >> i) & 255) + 1;
750             }
751           if (const_ok_for_arm ((temp << i) - val))
752             {
753               i = temp << i;
754               temp = (unsigned) - (int) (i - val);
755               val = i;
756               break;
757             }
758           FAIL;
759         }
760     }
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"
773   "@
774    adf%?s\\t%0, %1, %2
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"
784   "@
785    adf%?d\\t%0, %1, %2
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"
796   "@
797    adf%?d\\t%0, %1, %2
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")
805                  (float_extend:DF
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"))
816                  (float_extend:DF
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"
828   "@
829    adf%?e\\t%0, %1, %2
830    suf%?e\\t%0, %1, #%N2"
831   [(set_attr "type" "farith")]
834 (define_expand "subdi3"
835  [(parallel
836    [(set (match_operand:DI            0 "s_register_operand" "")
837           (minus:DI (match_operand:DI 1 "s_register_operand" "")
838                     (match_operand:DI 2 "s_register_operand" "")))
839     (clobber (reg:CC 24))
840    ])
841   ]
842   "TARGET_EITHER"
843   "
844   if (TARGET_THUMB)
845     {
846       if (GET_CODE (operands[1]) != REG)
847         operands[1] = force_reg (SImode, operands[1]);
848       if (GET_CODE (operands[2]) != REG)
849         operands[2] = force_reg (SImode, operands[2]);
850      }  
851   "
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))
859   ]
860   "TARGET_ARM"
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))
871   ]
872   "TARGET_THUMB"
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")
880                   (zero_extend:DI
881                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
882    (clobber (reg:CC 24))
883   ]
884   "TARGET_ARM"
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")
893                   (sign_extend:DI
894                    (match_operand:SI 2 "s_register_operand"  "r,r"))))
895    (clobber (reg:CC 24))
896   ]
897   "TARGET_ARM"
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))
909   ]
910   "TARGET_ARM"
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))
922   ]
923   "TARGET_ARM"
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"))
933                   (zero_extend:DI
934                    (match_operand:SI 2 "s_register_operand"  "r"))))
935    (clobber (reg:CC 24))
936   ]
937   "TARGET_ARM"
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" "")))]
947   "TARGET_EITHER"
948   "
949   if (GET_CODE (operands[1]) == CONST_INT)
950     {
951       if (TARGET_ARM)
952         {
953           arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
954                               operands[2],
955                               (reload_in_progress || reload_completed ? 0
956                                :  preserve_subexpressions_p ()));
957           DONE;
958         }
959       else /* TARGET_THUMB */
960         operands[1] = force_reg (SImode, operands[1]);
961     }
962   "
965 (define_insn "*thumb_subsi3_insn"
966   [(set (match_operand:SI           0 "register_operand" "=l")
967         (minus:SI (match_operand:SI 1 "register_operand" "l")
968                   (match_operand:SI 2 "register_operand" "l")))]
969   "TARGET_THUMB"
970   "sub\\t%0, %1, %2"
971   [(set_attr "length" "2")]
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")))]
978   "TARGET_ARM"
979   "@
980    rsb%?\\t%0, %2, %1
981    #"
982   [(set_attr "length" "4,16")]
985 (define_split
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))]
991   "
992   arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
993                       operands[2], 0);
994   DONE;
995   "
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"))
1002                          (const_int 0)))
1003    (set (match_operand:SI 0 "s_register_operand" "=r,r")
1004         (minus:SI (match_dup 1) (match_dup 2)))]
1005   "TARGET_ARM"
1006   "@
1007    sub%?s\\t%0, %1, %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)])))]
1017   "TARGET_ARM"
1018   "@
1019   sub%d2\\t%0, %1, #1
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"
1030   "@
1031    suf%?s\\t%0, %1, %2
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"
1041   "@
1042    suf%?d\\t%0, %1, %2
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")
1060                   (float_extend:DF
1061                    (match_operand:SF 2 "s_register_operand" "f,f"))))]
1062   "TARGET_ARM && TARGET_HARD_FLOAT"
1063   "@
1064    suf%?d\\t%0, %1, %2
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"))
1073                   (float_extend:DF
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"
1085   "@
1086    suf%?e\\t%0, %1, %2
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" "")))]
1097   "TARGET_EITHER"
1098   ""
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")))]
1106   "TARGET_ARM"
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")))]
1120   "TARGET_THUMB"
1121   "*
1122   if (which_alternative < 2)
1123     return \"mov\\t%0, %1\;mul\\t%0, %0, %2\";
1124   else
1125     return \"mul\\t%0, %0, %2\";
1126   "
1127   [(set_attr "length" "4,4,2")
1128    (set_attr "type" "mult")]
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"))
1136                          (const_int 0)))
1137    (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
1138         (mult:SI (match_dup 2) (match_dup 1)))]
1139   "TARGET_ARM"
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"))
1150                          (const_int 0)))
1151    (clobber (match_scratch:SI 0 "=&r,&r"))]
1152   "TARGET_ARM"
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")
1162         (plus:SI
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")))]
1166   "TARGET_ARM"
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
1173                           (mult:SI
1174                            (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1175                            (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1176                           (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1177                          (const_int 0)))
1178    (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
1179         (plus:SI (mult:SI (match_dup 2) (match_dup 1))
1180                  (match_dup 3)))]
1181   "TARGET_ARM"
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
1189                           (mult:SI
1190                            (match_operand:SI 2 "s_register_operand" "r,r,r,r")
1191                            (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
1192                           (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
1193                          (const_int 0)))
1194    (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
1195   "TARGET_ARM"
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")
1205         (plus:DI
1206           (mult:DI (sign_extend:DI
1207                     (match_operand:SI 2 "s_register_operand" "r,0,1"))
1208                    (sign_extend:DI
1209                     (match_operand:SI 1 "s_register_operand" "%r,r,r")))
1210           (match_dup 0)))]
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"))
1219                (sign_extend:DI
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"))
1229                (zero_extend:DI
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")
1239         (plus:DI
1240           (mult:DI (zero_extend:DI
1241                     (match_operand:SI 2 "s_register_operand" "r,0,1"))
1242                    (zero_extend:DI
1243                     (match_operand:SI 1 "s_register_operand" "%r,r,r")))
1244           (match_dup 0)))]
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")
1251         (truncate:SI
1252          (lshiftrt:DI
1253           (mult:DI (sign_extend:DI
1254                     (match_operand:SI 1 "s_register_operand" "%r,0"))
1255                    (sign_extend:DI
1256                     (match_operand:SI 2 "s_register_operand" "r,r")))
1257           (const_int 32))))
1258    (clobber (match_scratch:SI 3 "=&r,&r"))]
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")
1266         (truncate:SI
1267          (lshiftrt:DI
1268           (mult:DI (zero_extend:DI
1269                     (match_operand:SI 1 "s_register_operand" "%r,0"))
1270                    (zero_extend:DI
1271                     (match_operand:SI 2 "s_register_operand" "r,r")))
1272           (const_int 32))))
1273    (clobber (match_scratch:SI 3 "=&r,&r"))]
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")
1307                  (float_extend:DF
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"))
1317                  (float_extend:DF
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")])
1331 ;; Division insns
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"
1338   "@
1339    fdv%?s\\t%0, %1, %2
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"
1348   "@
1349    dvf%?d\\t%0, %1, %2
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")
1365                 (float_extend:DF
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"))
1375                 (float_extend:DF
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"
1386   "@
1387    dvf%?e\\t%0, %1, %2
1388    rdf%?e\\t%0, %2, %1"
1389 [(set_attr "type" "fdivx")])
1391 ;; Modulo insns
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")
1421                 (float_extend:DF
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"))
1431                 (float_extend:DF
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.
1451 (define_split
1452   [(set (match_operand:DI 0 "s_register_operand" "")
1453         (match_operator:DI 6 "logical_binary_operator"
1454           [(match_operand:DI 1 "s_register_operand" "")
1455            (match_operand:DI 2 "s_register_operand" "")]))]
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)]))]
1459   "
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]);
1469 (define_split
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)))]
1475   "
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]);
1483 (define_split
1484   [(set (match_operand:DI 0 "s_register_operand" "")
1485         (and:DI
1486           (not:DI (match_operand:DI 1 "s_register_operand" ""))
1487           (match_operand:DI 2 "s_register_operand" "")))]
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)))]
1491   "
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]);
1501 (define_split
1502   [(set (match_operand:DI 0 "s_register_operand" "")
1503         (match_operator:DI 6 "logical_binary_operator"
1504           [(sign_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1505            (match_operand:DI 1 "s_register_operand" "")]))]
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))
1510                          (match_dup 4)]))]
1511   "
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]);
1521 (define_split
1522   [(set (match_operand:DI 0 "s_register_operand" "")
1523         (and:DI (not:DI (sign_extend:DI
1524                         (match_operand:SI 2 "s_register_operand" "")))
1525                 (match_operand:DI 1 "s_register_operand" "")))]
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)))
1530                                (match_dup 4)))]
1531   "
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
1541 ;; operand.
1542 (define_split
1543   [(set (match_operand:DI 0 "s_register_operand" "")
1544         (and:DI
1545           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1546           (match_operand:DI 1 "s_register_operand" "")))]
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))]
1550   "
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.
1559 (define_split
1560   [(set (match_operand:DI 0 "s_register_operand" "")
1561         (ior:DI
1562           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1563           (match_operand:DI 1 "s_register_operand" "")))]
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))]
1567   "
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.
1577 (define_split
1578   [(set (match_operand:DI 0 "s_register_operand" "")
1579         (xor:DI
1580           (zero_extend:DI (match_operand:SI 2 "s_register_operand" ""))
1581           (match_operand:DI 1 "s_register_operand" "")))]
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))]
1585   "
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.
1595 (define_split
1596   [(set (match_operand:DI 0 "s_register_operand" "")
1597         (and:DI (not:DI (zero_extend:DI
1598                         (match_operand:SI 2 "s_register_operand" "")))
1599                 (match_operand:DI 1 "s_register_operand" "")))]
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))]
1603   "
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")))]
1616   "TARGET_ARM"
1617   "#"
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")))]
1625   "TARGET_ARM"
1626   "#"
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")))]
1634   "TARGET_ARM"
1635   "#"
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" "")))]
1643   "TARGET_EITHER"
1644   "
1645   if (TARGET_ARM)
1646     {
1647       if (GET_CODE (operands[2]) == CONST_INT)
1648         {
1649           arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1650                               operands[1],
1651                               (reload_in_progress || reload_completed
1652                                ? 0 : preserve_subexpressions_p ()));
1653           DONE;
1654         }
1655     }
1656   else /* TARGET_THUMB */
1657     {
1658       if (GET_CODE (operands[2]) != CONST_INT)
1659         operands[2] = force_reg (SImode, operands[2]);
1660       else
1661         {
1662           int i;
1663           
1664           if (((unsigned HOST_WIDE_INT) ~ INTVAL (operands[2])) < 256)
1665             {
1666               operands[2] = force_reg (SImode, GEN_INT (~INTVAL (operands[2])));
1667               
1668               emit_insn (gen_bicsi3 (operands[0], operands[2], operands[1]));
1669               
1670               DONE;
1671             }
1673           for (i = 9; i <= 31; i++)
1674             {
1675               if ((((HOST_WIDE_INT) 1) << i) - 1 == INTVAL (operands[2]))
1676                 {
1677                   emit_insn (gen_extzv (operands[0], operands[1], GEN_INT (i),
1678                                         const0_rtx));
1679                   DONE;
1680                 }
1681               else if ((((HOST_WIDE_INT) 1) << i) - 1 == ~ INTVAL (operands[2]))
1682                 {
1683                   rtx shift = GEN_INT (i);
1684                   rtx reg = gen_reg_rtx (SImode);
1685                 
1686                   emit_insn (gen_lshrsi3 (reg, operands[1], shift));
1687                   emit_insn (gen_ashlsi3 (operands[0], reg, shift));
1688                   
1689                   DONE;
1690                 }
1691             }
1693           operands[2] = force_reg (SImode, operands[2]);
1694         }
1695     }"
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")))]
1702   "TARGET_ARM"
1703   "@
1704    and%?\\t%0, %1, %2
1705    bic%?\\t%0, %1, #%B2
1706    #"
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")))]
1714   "TARGET_THUMB"
1715   "and\\t%0, %0, %2"
1716   [(set_attr "length" "2")]
1719 (define_split
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" "")))]
1723   "TARGET_ARM
1724    && (! (const_ok_for_arm (  INTVAL (operands[2]))
1725        || const_ok_for_arm (~ INTVAL (operands[2]))))"
1726   [(clobber (const_int 0))]
1727   "
1728   arm_split_constant  (AND, SImode, INTVAL (operands[2]), operands[0],
1729                        operands[1], 0);
1730   DONE;
1733 (define_insn "*andsi3_compare0"
1734   [(set (reg:CC_NOOV 24)
1735         (compare:CC_NOOV
1736          (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1737                  (match_operand:SI 2 "arm_not_operand" "rI,K"))
1738          (const_int 0)))
1739    (set (match_operand:SI          0 "s_register_operand" "=r,r")
1740         (and:SI (match_dup 1) (match_dup 2)))]
1741   "TARGET_ARM"
1742   "@
1743    and%?s\\t%0, %1, %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)
1750         (compare:CC_NOOV
1751          (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1752                  (match_operand:SI 1 "arm_not_operand" "rI,K"))
1753          (const_int 0)))
1754    (clobber (match_scratch:SI 3 "=X,r"))]
1755   "TARGET_ARM"
1756   "@
1757    tst%?\\t%0, %1
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"))
1767                          (const_int 0)))]
1768   "TARGET_ARM
1769   && (INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1770       && INTVAL (operands[1]) > 0 
1771       && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1772       && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32)"
1773   "*
1774   operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1775                          << INTVAL (operands[2]));
1776   output_asm_insn (\"tst%?\\t%0, %1\", operands);
1777   return \"\";
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"))
1787                (const_int 0)))]
1788   "TARGET_ARM
1789    && (INTVAL (operands[3]) >= 0 && INTVAL (operands[3]) < 32
1790        && INTVAL (operands[2]) > 0 
1791        && INTVAL (operands[2]) + (INTVAL (operands[3]) & 1) <= 8
1792        && INTVAL (operands[2]) + INTVAL (operands[3]) <= 32)"
1793   "*
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" ""))]
1816   "TARGET_ARM"
1817   "
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;
1823   
1824   target = operands[0];
1825   /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical 
1826      subreg as the final target.  */
1827   if (GET_CODE (target) == SUBREG)
1828     {
1829       subtarget = gen_reg_rtx (SImode);
1830       if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1831           < GET_MODE_SIZE (SImode))
1832         target = SUBREG_REG (target);
1833     }
1834   else
1835     subtarget = target;    
1836     
1837   if (GET_CODE (operands[3]) == CONST_INT)
1838     {
1839       /* Since we are inserting a known constant, we may be able to
1840          reduce the number of bits that we have to clear so that
1841          the mask becomes simple.  */
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)));
1853     }
1854   else if (start_bit == 0
1855            && ! (const_ok_for_arm (mask)
1856                  || const_ok_for_arm (~mask)))
1857     {
1858       /* A Trick, since we are setting the bottom bits in the word,
1859          we can shift operand[3] up, operand[0] down, OR them together
1860          and rotate the result back again.  This takes 3 insns, and
1861          the third might be mergable into another op.  */
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]));
1871     }
1872   else if ((width + start_bit == 32)
1873            && ! (const_ok_for_arm (mask)
1874                  || const_ok_for_arm (~mask)))
1875     {
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));
1885     }
1886   else
1887     {
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)))
1893         {
1894           rtx tmp = gen_reg_rtx (SImode);
1896           emit_insn (gen_movsi (tmp, op0));
1897           op0 = tmp;
1898         }
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))))
1906         {
1907           op0 = GEN_INT (~(mask << start_bit));
1908           emit_insn (gen_andsi3 (op2, operands[0], op0));
1909         }
1910       else
1911         {
1912           if (GET_CODE (op0) == CONST_INT)
1913             {
1914               rtx tmp = gen_reg_rtx (SImode);
1916               emit_insn (gen_movsi (tmp, op0));
1917               op0 = tmp;
1918             }
1920           if (start_bit != 0)
1921             emit_insn (gen_ashlsi3 (op0, op0, operands[2]));
1922             
1923           emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1924         }
1926       if (start_bit != 0)
1927         emit_insn (gen_ashlsi3 (op1, op1, operands[2]));
1929       emit_insn (gen_iorsi3 (subtarget, op1, op2));
1930     }
1932   if (subtarget != target)
1933     {
1934       /* If TARGET is still a SUBREG, then it must be wider than a word,
1935          so we must be careful only to set the subword we were asked to. */
1936       if (GET_CODE (target) == SUBREG)
1937         emit_move_insn (target, subtarget);
1938       else
1939         emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1940     }
1942   DONE;
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")))]
1951   "TARGET_ARM"
1952   "#"
1953 [(set_attr "length" "8")])
1954   
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")))]
1960   "TARGET_ARM"
1961   "@
1962    bic%?\\t%Q0, %Q1, %2
1963    #"
1964 [(set_attr "length" "4,8")])
1965   
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")))]
1971   "TARGET_ARM"
1972   "#"
1973 [(set_attr "length" "8")])
1974   
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")))]
1979   "TARGET_ARM"
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")))]
1986   "TARGET_THUMB"
1987   "bic\\t%0, %0, %1"
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")))]
1997   "TARGET_ARM"
1998   "bic%?\\t%0, %1, %2%S4"
2001 (define_insn "*andsi_notsi_si_compare0"
2002   [(set (reg:CC_NOOV 24)
2003         (compare:CC_NOOV
2004          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2005                  (match_operand:SI 1 "s_register_operand" "r"))
2006          (const_int 0)))
2007    (set (match_operand:SI 0 "s_register_operand" "=r")
2008         (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
2009   "TARGET_ARM"
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)
2015         (compare:CC_NOOV
2016          (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
2017                  (match_operand:SI 1 "s_register_operand" "r"))
2018          (const_int 0)))
2019    (clobber (match_scratch:SI 0 "=r"))]
2020   "TARGET_ARM"
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")))]
2028   "TARGET_ARM"
2029   "#"
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")))]
2038   "TARGET_ARM"
2039   "@
2040    orr%?\\t%Q0, %Q1, %2
2041    #"
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")))]
2050   "TARGET_ARM"
2051   "#"
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" "")))]
2059   "TARGET_EITHER"
2060   "
2061   if (GET_CODE (operands[2]) == CONST_INT)
2062     {
2063       if (TARGET_ARM)
2064         {
2065           arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2066                               operands[1],
2067                               (reload_in_progress || reload_completed
2068                               ? 0 : preserve_subexpressions_p ()));
2069           DONE;
2070         }
2071       else /* TARGET_THUMB */
2072         operands [2] = force_reg (SImode, operands [2]);
2073     }
2074   "
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")))]
2081   "TARGET_ARM"
2082   "@
2083    orr%?\\t%0, %1, %2
2084    #"
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")))]
2092   "TARGET_THUMB"
2093   "orr\\t%0, %0, %2"
2094   [(set_attr "length" "2")]
2097 (define_split
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))]
2103   "
2104   arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
2105                       operands[1], 0);
2106   DONE;
2108   
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"))
2113                          (const_int 0)))
2114    (set (match_operand:SI 0 "s_register_operand" "=r")
2115         (ior:SI (match_dup 1) (match_dup 2)))]
2116   "TARGET_ARM"
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"))
2125                          (const_int 0)))
2126    (clobber (match_scratch:SI 0 "=r"))]
2127   "TARGET_ARM"
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")))]
2135   "TARGET_ARM"
2136   "#"
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")))]
2145   "TARGET_ARM"
2146   "@
2147    eor%?\\t%Q0, %Q1, %2
2148    #"
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")))]
2157   "TARGET_ARM"
2158   "#"
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"  "")))]
2166   "TARGET_EITHER"
2167   "if (TARGET_THUMB)
2168      if (GET_CODE (operands[2]) == CONST_INT)
2169        operands[2] = force_reg (SImode, operands[2]);
2170   "
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")))]
2177   "TARGET_ARM"
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")))]
2185   "TARGET_THUMB"
2186   "eor\\t%0, %0, %2"
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"))
2194                          (const_int 0)))
2195    (set (match_operand:SI 0 "s_register_operand" "=r")
2196         (xor:SI (match_dup 1) (match_dup 2)))]
2197   "TARGET_ARM"
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"))
2205                          (const_int 0)))]
2206   "TARGET_ARM"
2207   "teq%?\\t%0, %1"
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
2213 ;; insns
2215 (define_split
2216   [(set (match_operand:SI 0 "s_register_operand" "=r")
2217         (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2218                         (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
2219                 (match_operand:SI 3 "arm_rhs_operand" "rI")))
2220    (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
2221   "TARGET_ARM"
2222   [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
2223                               (not:SI (match_dup 3))))
2224    (set (match_dup 0) (not:SI (match_dup 4)))]
2225   ""
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"))))]
2233   "TARGET_ARM"
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))]
2247   "TARGET_ARM"
2248   "@
2249    cmp\\t%1, %2\;movlt\\t%0, %2
2250    cmp\\t%1, %2\;movge\\t%0, %1
2251    cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
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))]
2261   "TARGET_ARM"
2262   "@
2263    cmp\\t%1, %2\;movge\\t%0, %2
2264    cmp\\t%1, %2\;movlt\\t%0, %1
2265    cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
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))]
2274   "TARGET_ARM"
2275   "@
2276    cmp\\t%1, %2\;movcc\\t%0, %2
2277    cmp\\t%1, %2\;movcs\\t%0, %1
2278    cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
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))]
2287   "TARGET_ARM"
2288   "@
2289    cmp\\t%1, %2\;movcs\\t%0, %2
2290    cmp\\t%1, %2\;movcc\\t%0, %1
2291    cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
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))]
2301   "TARGET_ARM"
2302   "*
2303   operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
2304                          operands[2]);
2305   output_asm_insn (\"cmp\\t%1, %2\", operands);
2306   output_asm_insn (\"str%d3\\t%1, %0\", operands);
2307   output_asm_insn (\"str%D3\\t%2, %0\", operands);
2308   return \"\";
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))]
2324   "TARGET_ARM
2325    && (GET_CODE (operands[1]) != REG
2326        || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
2327            && REGNO(operands[1]) != ARG_POINTER_REGNUM))"
2328   "*
2330   enum rtx_code code = GET_CODE (operands[4]);
2332   operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
2333                          operands[3]);
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);
2339   return \"\";
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" "")))]
2352   "TARGET_EITHER"
2353   "
2354   if (GET_CODE (operands[2]) == CONST_INT
2355       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2356     {
2357       emit_insn (gen_movsi (operands[0], const0_rtx));
2358       DONE;
2359     }
2360   "
2363 (define_insn "*thumb_ashlsi3"
2364   [(set (match_operand:SI            0 "register_operand" "=l,l")
2365         (ashift:SI (match_operand:SI 1 "register_operand" "l,0")
2366                    (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2367   "TARGET_THUMB"
2368   "lsl\\t%0, %1, %2"
2369   [(set_attr "length" "2")]
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" "")))]
2376   "TARGET_EITHER"
2377   "
2378   if (GET_CODE (operands[2]) == CONST_INT
2379       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2380     operands[2] = GEN_INT (31);
2381   "
2384 (define_insn "*thumb_ashrsi3"
2385   [(set (match_operand:SI              0 "register_operand" "=l,l")
2386         (ashiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2387                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2388   "TARGET_THUMB"
2389   "asr\\t%0, %1, %2"
2390   [(set_attr "length" "2")]
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" "")))]
2397   "TARGET_EITHER"
2398   "
2399   if (GET_CODE (operands[2]) == CONST_INT
2400       && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2401     {
2402       emit_insn (gen_movsi (operands[0], const0_rtx));
2403       DONE;
2404     }
2405   "
2408 (define_insn "*thumb_lshrsi3"
2409   [(set (match_operand:SI              0 "register_operand" "=l,l")
2410         (lshiftrt:SI (match_operand:SI 1 "register_operand" "l,0")
2411                      (match_operand:SI 2 "nonmemory_operand" "N,l")))]
2412   "TARGET_THUMB"
2413   "lsr\\t%0, %1, %2"
2414   [(set_attr "length" "2")]
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" "")))]
2421   "TARGET_ARM"
2422   "
2423   if (GET_CODE (operands[2]) == CONST_INT)
2424     operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
2425   else
2426     {
2427       rtx reg = gen_reg_rtx (SImode);
2428       emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
2429       operands[2] = reg;
2430     }
2431   "
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" "")))]
2438   "TARGET_EITHER"
2439   "
2440   if (TARGET_ARM)
2441     {
2442       if (GET_CODE (operands[2]) == CONST_INT
2443           && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
2444         operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
2445     }
2446   else /* TARGET_THUMB */
2447     {
2448       if (GET_CODE (operands [2]) == CONST_INT)
2449         operands [2] = force_reg (SImode, operands[2]);
2450     }
2451   "
2454 (define_insn "*thumb_rotrsi3"
2455   [(set (match_operand:SI              0 "register_operand" "=l")
2456         (rotatert:SI (match_operand:SI 1 "register_operand" "0")
2457                      (match_operand:SI 2 "register_operand" "l")))]
2458   "TARGET_THUMB"
2459   "ror\\t%0, %0, %2"
2460   [(set_attr "length" "2")]
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")]))]
2468   "TARGET_ARM"
2469   "mov%?\\t%0, %1%S3"
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")])
2477                          (const_int 0)))
2478    (set (match_operand:SI 0 "s_register_operand" "=r")
2479         (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
2480   "TARGET_ARM"
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")])
2490                          (const_int 0)))
2491    (clobber (match_scratch:SI 0 "=r"))]
2492   "TARGET_ARM"
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")])))]
2502   "TARGET_ARM"
2503   "mvn%?\\t%0, %1%S3"
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")]))
2512                          (const_int 0)))
2513    (set (match_operand:SI 0 "s_register_operand" "=r")
2514         (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
2515   "TARGET_ARM"
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")]))
2525                          (const_int 0)))
2526    (clobber (match_scratch:SI 0 "=r"))]
2527   "TARGET_ARM"
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"
2536   [(set (match_dup 4)
2537         (ashift:SI (match_operand:SI   1 "register_operand" "")
2538                    (match_operand:SI   2 "const_int_operand" "")))
2539    (set (match_operand:SI              0 "register_operand" "")
2540         (lshiftrt:SI (match_dup 4)
2541                      (match_operand:SI 3 "const_int_operand" "")))
2542    ]
2543   "TARGET_THUMB"
2544   "
2545   {
2546     HOST_WIDE_INT lshift = 32 - INTVAL (operands[2]) - INTVAL (operands[3]);
2547     HOST_WIDE_INT rshift = 32 - INTVAL (operands[2]);
2548     
2549     operands[3] = GEN_INT (rshift);
2550     
2551     if (lshift == 0)
2552       {
2553         emit_insn (gen_lshrsi3 (operands[0], operands[1], operands[3]));
2554         DONE;
2555       }
2556       
2557     operands[2] = GEN_INT (lshift);
2558     operands[4] = gen_reg_rtx (SImode);
2559   }
2560   "
2564 ;; Unary arithmetic insns
2566 (define_expand "negdi2"
2567  [(parallel
2568    [(set (match_operand:DI          0 "s_register_operand" "")
2569           (neg:DI (match_operand:DI 1 "s_register_operand" "")))
2570     (clobber (reg:CC 24))
2571    ])
2572   ]
2573   "TARGET_EITHER"
2574   "
2575   if (TARGET_THUMB)
2576     {
2577       if (GET_CODE (operands[1]) != REG)
2578         operands[1] = force_reg (SImode, operands[1]);
2579      }
2580    "
2583 ;; The constraints here are to prevent a *partial* overlap (where %Q0 == %R1).
2584 ;; The second alternative is to allow the common case of a *full* overlap.
2585 (define_insn "*arm_negdi2"
2586   [(set (match_operand:DI         0 "s_register_operand" "=&r,r")
2587         (neg:DI (match_operand:DI 1 "s_register_operand"  "?r,0")))
2588    (clobber (reg:CC 24))
2589   ]
2590   "TARGET_ARM"
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))
2600   ]
2601   "TARGET_THUMB"
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" "")))]
2609   "TARGET_EITHER"
2610   ""
2613 (define_insn "*arm_negsi2"
2614   [(set (match_operand:SI         0 "s_register_operand" "=r")
2615         (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
2616   "TARGET_ARM"
2617   "rsb%?\\t%0, %1, #0"
2620 (define_insn "*thumb_negsi2"
2621   [(set (match_operand:SI         0 "register_operand" "=l")
2622         (neg:SI (match_operand:SI 1 "register_operand" "l")))]
2623   "TARGET_THUMB"
2624   "neg\\t%0, %1"
2625   [(set_attr "length" "2")]
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"
2632   "mnf%?s\\t%0, %1"
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"
2640   "mnf%?d\\t%0, %1"
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"
2648   "mnf%?d\\t%0, %1"
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"
2655   "mnf%?e\\t%0, %1"
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
2661 ;; (neg (abs...))
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))]
2667   "TARGET_ARM"
2668   "@
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))]
2679   "TARGET_ARM"
2680   "@
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"
2691   "abs%?s\\t%0, %1"
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"
2698   "abs%?d\\t%0, %1"
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"
2706   "abs%?d\\t%0, %1"
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"
2713   "abs%?e\\t%0, %1"
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"
2720   "sqt%?s\\t%0, %1"
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"
2727   "sqt%?d\\t%0, %1"
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"
2735   "sqt%?d\\t%0, %1"
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"
2742   "sqt%?e\\t%0, %1"
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"
2751 ;  "sin%?s\\t%0, %1"
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"
2758 ;  "sin%?d\\t%0, %1"
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"
2766 ;  "sin%?d\\t%0, %1"
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"
2773 ;  "sin%?e\\t%0, %1"
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"
2780 ;  "cos%?s\\t%0, %1"
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"
2787 ;  "cos%?d\\t%0, %1"
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"
2795 ;  "cos%?d\\t%0, %1"
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"
2802 ;  "cos%?e\\t%0, %1"
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")))]
2808   "TARGET_ARM"
2809   "#"
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" "")))]
2816   "TARGET_EITHER"
2817   ""
2820 (define_insn "*arm_one_cmplsi2"
2821   [(set (match_operand:SI         0 "s_register_operand" "=r")
2822         (not:SI (match_operand:SI 1 "s_register_operand"  "r")))]
2823   "TARGET_ARM"
2824   "mvn%?\\t%0, %1"
2827 (define_insn "*thumb_one_cmplsi2"
2828   [(set (match_operand:SI         0 "register_operand" "=l")
2829         (not:SI (match_operand:SI 1 "register_operand"  "l")))]
2830   "TARGET_THUMB"
2831   "mvn\\t%0, %1"
2832   [(set_attr "length" "2")]
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"))
2838                          (const_int 0)))
2839    (set (match_operand:SI 0 "s_register_operand" "=r")
2840         (not:SI (match_dup 1)))]
2841   "TARGET_ARM"
2842   "mvn%?s\\t%0, %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"))
2849                          (const_int 0)))
2850    (clobber (match_scratch:SI 0 "=r"))]
2851   "TARGET_ARM"
2852   "mvn%?s\\t%0, %1"
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"
2862   "flt%?s\\t%0, %1"
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"
2869   "flt%?d\\t%0, %1"
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"
2876   "flt%?e\\t%0, %1"
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"
2883   "fix%?z\\t%0, %1"
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"
2890   "fix%?z\\t%0, %1"
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"
2897   "fix%?z\\t%0, %1"
2898 [(set_attr "type" "f_2_r")])
2900 ;; Truncation insns
2902 (define_insn "truncdfsf2"
2903   [(set (match_operand:SF 0 "s_register_operand" "=f")
2904         (float_truncate:SF
2905          (match_operand:DF 1 "s_register_operand" "f")))]
2906   "TARGET_ARM && TARGET_HARD_FLOAT"
2907   "mvf%?s\\t%0, %1"
2908 [(set_attr "type" "ffarith")])
2910 (define_insn "truncxfsf2"
2911   [(set (match_operand:SF 0 "s_register_operand" "=f")
2912         (float_truncate:SF
2913          (match_operand:XF 1 "s_register_operand" "f")))]
2914   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2915   "mvf%?s\\t%0, %1"
2916 [(set_attr "type" "ffarith")])
2918 (define_insn "truncxfdf2"
2919   [(set (match_operand:DF 0 "s_register_operand" "=f")
2920         (float_truncate:DF
2921          (match_operand:XF 1 "s_register_operand" "f")))]
2922   "TARGET_ARM && ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2923   "mvf%?d\\t%0, %1"
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")))]
2931   "TARGET_ARM"
2932   "*
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")))]
2942   "TARGET_ARM"
2943   "@
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")))]
2955   "TARGET_ARM"
2956   "*
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\";
2960   "
2961   [(set_attr "length" "8")
2964 (define_expand "zero_extendhisi2"
2965   [(set (match_dup 2)
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)))]
2969   "TARGET_EITHER"
2970   "
2971   {
2972     if (TARGET_ARM)
2973       {
2974         if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2975           {
2976            /* Note: We do not have to worry about TARGET_MMU_TRAPS
2977               here because the insn below will generate an LDRH instruction
2978               rather than an LDR instruction, so we cannot get an unaligned
2979               word access.  */
2980             emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2981                                     gen_rtx_ZERO_EXTEND (SImode, operands[1])));
2982             DONE;
2983           }
2984         if (TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
2985           {
2986             emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2987             DONE;
2988           }
2989         if (! s_register_operand (operands[1], HImode))
2990           operands[1] = copy_to_mode_reg (HImode, operands[1]);
2991         operands[1] = gen_lowpart (SImode, operands[1]);
2992         operands[2] = gen_reg_rtx (SImode);
2993       }
2994     else /* TARGET_THUMB */
2995       {
2996         if (GET_CODE (operands[1]) == MEM)
2997           {
2998             rtx tmp;
3000             tmp = gen_rtx_ZERO_EXTEND (SImode, operands[1]);
3001             tmp = gen_rtx_SET (VOIDmode, operands[0], tmp);
3002             emit_insn (tmp);
3003           }
3004         else
3005           {
3006             rtx ops[3];
3007             
3008             if (! s_register_operand (operands[1], HImode))
3009               operands[1] = copy_to_mode_reg (HImode, operands[1]);
3010             operands[1] = gen_lowpart (SImode, operands[1]);
3011             operands[2] = gen_reg_rtx (SImode);
3012             
3013             ops[0] = operands[2];
3014             ops[1] = operands[1];
3015             ops[2] = GEN_INT (16);
3016             
3017             emit_insn (gen_rtx_SET (VOIDmode, ops[0], gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
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])));
3024           }
3025         DONE; 
3026       }
3027   }"
3030 (define_insn "*thumb_zero_extendhisi2"
3031   [(set (match_operand:SI                 0 "register_operand" "=l")
3032         (zero_extend:SI (match_operand:HI 1 "memory_operand"    "m")))]
3033   "TARGET_THUMB"
3034   "*
3035   rtx mem = XEXP (operands[1], 0);
3037   if (GET_CODE (mem) == CONST)
3038     mem = XEXP (mem, 0);
3039     
3040   if (GET_CODE (mem) == LABEL_REF)
3041     return \"ldr\\t%0, %1\";
3042     
3043   if (GET_CODE (mem) == PLUS)
3044     {
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)
3050         {
3051           rtx ops[2];
3052           ops[0] = operands[0];
3053           ops[1] = a;
3054       
3055           output_asm_insn (\"mov        %0, %1\", ops);
3057           XEXP (mem, 0) = operands[0];
3058        }
3060       else if (   GET_CODE (a) == LABEL_REF
3061                && GET_CODE (b) == CONST_INT)
3062         return \"ldr\\t%0, %1\";
3063     }
3064     
3065   return \"ldrh\\t%0, %1\";
3066   "
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"
3076   "ldr%?h\\t%0, %1"
3077   [(set_attr "type" "load")
3078    (set_attr "pool_range" "256")
3079    (set_attr "neg_pool_range" "244")]
3082 (define_split
3083   [(set (match_operand:SI 0 "s_register_operand" "")
3084         (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
3085    (clobber (match_operand:SI 2 "s_register_operand" ""))]
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)))]
3089   "
3091   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3092     FAIL;
3095 (define_split
3096   [(set (match_operand:SI 0 "s_register_operand" "")
3097         (match_operator:SI 3 "shiftable_operator"
3098          [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
3099           (match_operand:SI 4 "s_register_operand" "")]))
3100    (clobber (match_operand:SI 2 "s_register_operand" ""))]
3101   "TARGET_ARM && (! arm_arch4)"
3102   [(set (match_dup 2) (match_dup 1))
3103    (set (match_dup 0)
3104         (match_op_dup 3
3105          [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3106   "
3108   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3109     FAIL;
3112 (define_expand "zero_extendqisi2"
3113   [(set (match_operand:SI 0 "s_register_operand" "")
3114         (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
3115   "TARGET_EITHER"
3116   "
3117   if (GET_CODE (operands[1]) != MEM)
3118     {
3119       if (TARGET_ARM)
3120         {
3121           emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
3122                                  GEN_INT (255)));
3123         }
3124       else /* TARGET_THUMB */
3125         {
3126           rtx temp = gen_reg_rtx (SImode);
3127           rtx ops[3];
3128           
3129           operands[1] = copy_to_mode_reg (QImode, operands[1]);
3130           operands[1] = gen_lowpart (SImode, operands[1]);
3132           ops[0] = temp;
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])));
3137           
3138           ops[0] = operands[0];
3139           ops[1] = temp;
3140           ops[2] = GEN_INT (24);
3142           emit_insn (gen_rtx_SET (VOIDmode, ops[0], gen_rtx_LSHIFTRT (SImode, ops[1], ops[2])));
3143         }
3144       DONE;
3145     }
3148 (define_insn "*thumb_zero_extendqisi2"
3149   [(set (match_operand:SI                 0 "register_operand" "=l")
3150         (zero_extend:SI (match_operand:QI 1 "memory_operand"    "m")))]
3151   "TARGET_THUMB"
3152   "ldrb\\t%0, %1"
3153   [(set_attr "length" "2")
3154    (set_attr "type" "load")
3155    (set_attr "pool_range" "32")]
3158 (define_insn "*arm_zero_extendqisi2"
3159   [(set (match_operand:SI                 0 "s_register_operand" "=r")
3160         (zero_extend:SI (match_operand:QI 1 "memory_operand"      "m")))]
3161   "TARGET_ARM"
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")]
3168 (define_split
3169   [(set (match_operand:SI 0 "s_register_operand" "")
3170         (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
3171    (clobber (match_operand:SI 2 "s_register_operand" ""))]
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)))]
3175   ""
3178 (define_insn "*compareqi_eq0"
3179   [(set (reg:CC_Z 24)
3180         (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
3181                          (const_int 0)))]
3182   "TARGET_ARM"
3183   "tst\\t%0, #255"
3184   [(set_attr "conds" "set")]
3187 (define_expand "extendhisi2"
3188   [(set (match_dup 2)
3189         (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
3190                    (const_int 16)))
3191    (set (match_operand:SI 0 "s_register_operand" "")
3192         (ashiftrt:SI (match_dup 2)
3193                      (const_int 16)))]
3194   "TARGET_EITHER"
3195   "
3196   {
3197     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3198       {
3199        /* Note: We do not have to worry about TARGET_MMU_TRAPS
3200           here because the insn below will generate an LDRH instruction
3201           rather than an LDR instruction, so we cannot get an unaligned
3202           word access.  */
3203         emit_insn (gen_rtx_SET (VOIDmode, operands[0],
3204                    gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3205         DONE;
3206       }
3208     if (TARGET_ARM && TARGET_MMU_TRAPS && GET_CODE (operands[1]) == MEM)
3209       {
3210         emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
3211         DONE;
3212       }
3213     if (! s_register_operand (operands[1], HImode))
3214       operands[1] = copy_to_mode_reg (HImode, operands[1]);
3215     operands[1] = gen_lowpart (SImode, operands[1]);
3216     operands[2] = gen_reg_rtx (SImode);
3218     if (TARGET_THUMB)
3219       {
3220         rtx ops[3];
3221         
3222         ops[0] = operands[2];
3223         ops[1] = operands[1];
3224         ops[2] = GEN_INT (16);
3225         
3226         emit_insn (gen_rtx_SET (VOIDmode, ops[0], gen_rtx_ASHIFT (SImode, ops[1], ops[2])));
3227             
3228         ops[0] = operands[0];
3229         ops[1] = operands[2];
3230         ops[2] = GEN_INT (16);
3231         
3232         emit_insn (gen_rtx_SET (VOIDmode, ops[0], gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3233         
3234         DONE;
3235       }
3236   }"
3239 (define_insn "*thumb_extendhisi2_insn"
3240   [(set (match_operand:SI                 0 "register_operand" "=l")
3241         (sign_extend:SI (match_operand:HI 1 "memory_operand"    "m")))
3242    (clobber (match_scratch:SI             2                   "=&l"))]
3243   "TARGET_THUMB"
3244   "*
3245   {
3246     rtx ops[4];
3247     rtx mem = XEXP (operands[1], 0);
3249     /* This code used to try to use 'V', and fix the address only if it was
3250        offsettable, but this fails for e.g. REG+48 because 48 is outside the
3251        range of QImode offsets, and offsettable_address_p does a QImode
3252        address check.  */
3253        
3254     if (GET_CODE (mem) == CONST)
3255       mem = XEXP (mem, 0);
3256     
3257     if (GET_CODE (mem) == LABEL_REF)
3258       return \"ldr\\t%0, %1\";
3259     
3260     if (GET_CODE (mem) == PLUS)
3261       {
3262         rtx a = XEXP (mem, 0);
3263         rtx b = XEXP (mem, 1);
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\";
3271           
3272         ops[1] = a;
3273         ops[2] = b;
3274       }
3275     else
3276       {
3277         ops[1] = mem;
3278         ops[2] = const0_rtx;
3279       }
3280       
3281     if (GET_CODE (ops[1]) != REG)
3282       {
3283         debug_rtx (ops[1]);
3284         abort ();
3285       }
3287     ops[0] = operands[0];
3288     ops[3] = operands[2];
3289     output_asm_insn (\"mov\\t%3, %2\;ldrsh\\t%0, [%1, %3]\", ops);
3290     return \"\";
3291   }"
3292   [(set_attr "length" "4")
3293    (set_attr "type" "load")
3294    (set_attr "pool_range" "1020")]
3297 (define_expand "extendhisi2_mem"
3298   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3299    (set (match_dup 3)
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)))]
3304   "TARGET_ARM"
3305   "
3307   rtx mem1, mem2;
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]);
3317   operands[1] = mem1;
3318   operands[2] = gen_reg_rtx (SImode);
3319   operands[3] = gen_reg_rtx (SImode);
3320   operands[6] = gen_reg_rtx (SImode);
3321   operands[7] = mem2;
3323   if (BYTES_BIG_ENDIAN)
3324     {
3325       operands[4] = operands[2];
3326       operands[5] = operands[3];
3327     }
3328   else
3329     {
3330       operands[4] = operands[3];
3331       operands[5] = operands[2];
3332     }
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"
3340   "ldr%?sh\\t%0, %1"
3341   [(set_attr "type" "load")
3342    (set_attr "pool_range" "256")
3343    (set_attr "neg_pool_range" "244")]
3346 (define_split
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)))]
3353   "
3354   if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3355     FAIL;
3356   "
3359 (define_split
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))
3367    (set (match_dup 0)
3368         (match_op_dup 3
3369          [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
3370   "if ((operands[1] = arm_gen_rotated_half_load (operands[1])) == NULL)
3371      FAIL;
3372   "
3375 (define_expand "extendqihi2"
3376   [(set (match_dup 2)
3377         (ashift:SI (match_operand:QI 1 "general_operand" "")
3378                    (const_int 24)))
3379    (set (match_operand:HI 0 "s_register_operand" "")
3380         (ashiftrt:SI (match_dup 2)
3381                      (const_int 24)))]
3382   "TARGET_ARM"
3383   "
3385   if (arm_arch4 && GET_CODE (operands[1]) == MEM)
3386     {
3387       emit_insn (gen_rtx_SET (VOIDmode,
3388                               operands[0],
3389                               gen_rtx_SIGN_EXTEND (HImode, operands[1])));
3390       DONE;
3391     }
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"
3405   "*
3406   /* If the address is invalid, this will split the instruction into two. */
3407   if (bad_signed_byte_operand (operands[1], VOIDmode))
3408     return \"#\";
3409   return \"ldr%?sb\\t%0, %1\";
3410   "
3411   [(set_attr "type" "load")
3412    (set_attr "length" "8")
3413    (set_attr "pool_range" "256")
3414    (set_attr "neg_pool_range" "244")]
3417 (define_split
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)))]
3423   "
3424   {
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)))
3436       {
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);
3441       }
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));
3449   }
3452 (define_expand "extendqisi2"
3453   [(set (match_dup 2)
3454         (ashift:SI (match_operand:QI 1 "general_operand" "")
3455                    (const_int 24)))
3456    (set (match_operand:SI 0 "s_register_operand" "")
3457         (ashiftrt:SI (match_dup 2)
3458                      (const_int 24)))]
3459   "TARGET_EITHER"
3460   "
3461   {
3462     if (TARGET_ARM && arm_arch4 && GET_CODE (operands[1]) == MEM)
3463       {
3464         emit_insn (gen_rtx_SET (VOIDmode,
3465                                 operands[0],
3466                                 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
3467         DONE;
3468       }
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);
3473     
3474     if (TARGET_THUMB)
3475       {
3476         rtx ops[3];
3477         
3478         ops[0] = operands[2];
3479         ops[1] = operands[1];
3480         ops[2] = GEN_INT (24);
3481         
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);
3487         
3488         emit_insn (gen_rtx_SET (VOIDmode, ops[0], gen_rtx_ASHIFTRT (SImode, ops[1], ops[2])));
3489         
3490         DONE;
3491       }
3492   }"
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"
3501   "*
3502   /* If the address is invalid, this will split the instruction into two. */
3503   if (bad_signed_byte_operand (operands[1], VOIDmode))
3504     return \"#\";
3505   return \"ldr%?sb\\t%0, %1\";
3506   "
3507   [(set_attr "type" "load")
3508    (set_attr "length" "8")
3509    (set_attr "pool_range" "256")
3510    (set_attr "neg_pool_range" "244")]
3513 (define_split
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)))]
3519   "
3520   {
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)))
3531       {
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);
3536       }
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));
3544   }
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")))]
3550   "TARGET_THUMB"
3551   "*
3552   {
3553     rtx ops[3];
3554     rtx mem = XEXP (operands[1], 0);
3555     
3556     if (GET_CODE (mem) == CONST)
3557       mem = XEXP (mem, 0);
3558     
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\";
3565       
3566     if (which_alternative == 0)
3567       return \"ldrsb\\t%0, %1\";
3568       
3569     ops[0] = operands[0];
3570     
3571     if (GET_CODE (mem) == PLUS)
3572       {
3573         rtx a = XEXP (mem, 0);
3574         rtx b = XEXP (mem, 1);
3575         
3576         ops[1] = a;
3577         ops[2] = b;
3579         if (GET_CODE (a) == REG)
3580           {
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);
3585             else
3586               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3587           }
3588         else if (GET_CODE (b) != REG)
3589           abort ();
3590         else
3591           {
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);
3594             else
3595               output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3596           }
3597       }
3598     else if (GET_CODE (mem) == REG && REGNO (ops[0]) == REGNO (mem))
3599       {
3600         output_asm_insn (\"ldrb\\t%0, [%0, #0]\;lsl\\t%0, %0, #24\;asr\\t%0, %0, #24\", ops);
3601       }
3602     else
3603       {
3604         ops[1] = mem;
3605         ops[2] = const0_rtx;
3606         
3607         output_asm_insn (\"mov\\t%0, %2\;ldrsb\\t%0, [%1, %0]\", ops);
3608       }
3609     return \"\";
3610   }"
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"
3620   "mvf%?d\\t%0, %1"
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"
3627   "mvf%?e\\t%0, %1"
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"
3634   "mvf%?e\\t%0, %1"
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
3642 ;; registers
3643 ;;(define_expand "loadti"
3644 ;;  [(set (match_operand:TI 0 "s_register_operand" "")
3645 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
3646 ;;  "" "")
3648 ;;(define_expand "storeti"
3649 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
3650 ;;      (match_operand:TI 1 "s_register_operand" ""))]
3651 ;;  "" "")
3653 ;;(define_expand "movti"
3654 ;;  [(set (match_operand:TI 0 "general_operand" "")
3655 ;;      (match_operand:TI 1 "general_operand" ""))]
3656 ;;  ""
3657 ;;  "
3659 ;;  rtx insn;
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));
3667 ;;  else
3668 ;;    FAIL;
3670 ;;  emit_insn (insn);
3671 ;;  DONE;
3672 ;;}")
3674 ;; Recognise garbage generated above.
3676 ;;(define_insn ""
3677 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
3678 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
3679 ;;  ""
3680 ;;  "*
3681 ;;  {
3682 ;;    register mem = (which_alternative < 3);
3683 ;;    register char *template;
3685 ;;    operands[mem] = XEXP (operands[mem], 0);
3686 ;;    switch (which_alternative)
3687 ;;      {
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;
3694 ;;      }
3695 ;;    output_asm_insn (template, operands);
3696 ;;    return \"\";
3697 ;;  }")
3699 (define_expand "movdi"
3700   [(set (match_operand:DI 0 "general_operand" "")
3701         (match_operand:DI 1 "general_operand" ""))]
3702   "TARGET_EITHER"
3703   "
3704   if (TARGET_THUMB)
3705     {
3706       if (! (reload_in_progress || reload_completed))
3707         {
3708           if (GET_CODE (operands[0]) != REG)
3709             operands[1] = force_reg (DImode, operands[1]);
3710         }
3711     }
3712   "
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"))]
3718   "TARGET_ARM"
3719   "*
3720   return (output_move_double (operands));
3721   "
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"))]
3735   "TARGET_THUMB
3736    && (   register_operand (operands[0], DImode)
3737        || register_operand (operands[1], DImode))"
3738   "*
3739   {
3740   switch (which_alternative)
3741     {
3742     default:
3743     case 0:
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\";
3747     case 1:
3748       return \"mov\\t%Q0, %1\;mov\\t%R0, #0\";
3749     case 2:
3750       operands[1] = GEN_INT (- INTVAL (operands[1]));
3751       return \"mov\\t%Q0, %1\;neg\\t%Q0, %Q0\;asr\\t%R0, %Q0, #31\";
3752     case 3:
3753       return \"ldmia\\t%1, {%0, %H0}\";
3754     case 4:
3755       return \"stmia\\t%0, {%1, %H1}\";
3756     case 5:
3757       return thumb_load_double_from_address (operands);
3758     case 6:
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);
3761       return \"\";
3762     case 7:
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\";
3766     }
3767   }"
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" ""))]
3776   "TARGET_EITHER"
3777   "
3778   if (TARGET_ARM)
3779     {
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]))))
3786         {
3787            arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3788                               NULL_RTX,
3789                               (reload_in_progress || reload_completed ? 0
3790                                : preserve_subexpressions_p ()));
3791           DONE;
3792         }
3793     }
3794   else /* TARGET_THUMB.... */
3795     {
3796       if (! (reload_in_progress || reload_completed))
3797         {
3798           if (GET_CODE (operands[0]) != REG)
3799             operands[1] = force_reg (SImode, operands[1]);
3800         }
3801     }
3802     
3803   if (flag_pic
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"))]
3816   "TARGET_ARM
3817    && (   register_operand (operands[0], SImode)
3818        || register_operand (operands[1], SImode))"
3819   "@
3820    mov%?\\t%0, %1
3821    mvn%?\\t%0, #%B1
3822    ldr%?\\t%0, %1
3823    str%?\\t%1, %0"
3824   [(set_attr "type" "*,*,load,store1")
3825    (set_attr "pool_range" "*,*,4096,*")
3826    (set_attr "neg_pool_range" "*,*,4084,*")]
3829 (define_split
3830   [(set (match_operand:SI 0 "s_register_operand" "")
3831         (match_operand:SI 1 "const_int_operand" ""))]
3832   "TARGET_ARM
3833   && (! (   const_ok_for_arm (INTVAL (operands[1]))
3834          || const_ok_for_arm (~INTVAL (operands[1]))))"
3835   [(clobber (const_int 0))]
3836   "
3837   arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
3838                       NULL_RTX, 0);
3839   DONE;
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"))]
3845   "TARGET_THUMB
3846    && (   register_operand (operands[0], SImode) 
3847        || register_operand (operands[1], SImode))"
3848   "@
3849    mov  %0, %1
3850    mov  %0, %1
3851    #
3852    #
3853    ldmia\\t%1, {%0}
3854    stmia\\t%0, {%1}
3855    ldr\\t%0, %1
3856    str\\t%1, %0
3857    mov\\t%0, %1"
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,*,*")]
3863 (define_split 
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]));"
3872 (define_split 
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)))]
3878   "
3879   {
3880     unsigned HOST_WIDE_INT val = INTVAL (operands[1]);
3881     unsigned HOST_WIDE_INT mask = 0xff;
3882     int i;
3883     
3884     for (i = 0; i < 25; i++)
3885       if ((val & (mask << i)) == val)
3886         break;
3888     if (i == 0)
3889       FAIL;
3891     operands[1] = GEN_INT (val >> i);
3892     operands[2] = GEN_INT (i);
3893   }"
3896 (define_expand "movaddr"
3897   [(set (match_operand:SI 0 "s_register_operand" "")
3898         (match_operand:DI 1 "address_operand" ""))]
3899   "TARGET_ARM"
3900   ""
3903 (define_insn "*movaddr_insn"
3904   [(set (match_operand:SI 0 "s_register_operand" "=r")
3905         (match_operand:DI 1 "address_operand" "p"))]
3906   "TARGET_ARM
3907    && reload_completed
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))"
3913   "adr%?\\t%0, %a1"
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"
3929   "ldr%?\\t%0, %1"
3930   [(set_attr "type" "load")
3931    (set (attr "pool_range")
3932         (if_then_else (eq_attr "is_thumb" "yes")
3933                       (const_int 1024)
3934                       (const_int 4096)))
3935    (set (attr "neg_pool_range")
3936         (if_then_else (eq_attr "is_thumb" "yes")
3937                       (const_int 0)
3938                       (const_int 4084)))]
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"
3955   "*
3956 #ifdef AOF_ASSEMBLER
3957   operands[1] = aof_pic_entry (operands[1]);
3958 #endif
3959   output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
3960   return \"\";
3961   "
3962   [(set_attr "type" "load")
3963    (set (attr "pool_range")
3964         (if_then_else (eq_attr "is_thumb" "yes")
3965                       (const_int 1024)
3966                       (const_int 4096)))
3967    (set (attr "neg_pool_range")
3968         (if_then_else (eq_attr "is_thumb" "yes")
3969                       (const_int 0)
3970                       (const_int 4084)))]
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"
3978   "*
3979   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
3980                              CODE_LABEL_NUMBER (operands[1]));
3981   return \"add\\t%0, %|pc\";
3982   "
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"
3991   "*
3992   ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
3993                              CODE_LABEL_NUMBER (operands[1]));
3994   return \"add%?\\t%0, %|pc, %0\";
3995   "
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"
4003   [(set (reg:CC 24)
4004         (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
4005                     (const_int 0)))
4006    (set (match_operand:SI 0 "s_register_operand" "=r,r")
4007         (match_dup 1))]
4008   "TARGET_ARM"
4009   "@
4010    cmp%?\\t%0, #0
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
4027    (set (match_dup 2)
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
4031   "TARGET_ARM"
4032   "
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)
4038       || code == MINUS)
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))
4051    (set (match_dup 2)
4052         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
4053    (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
4054   "TARGET_ARM"
4055   "
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)
4061       || code == MINUS)
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))]
4077   "TARGET_ARM"
4078   "
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)
4085       || code == MINUS)
4086     addr = force_reg (SImode, addr);
4088   operands[1] = gen_reg_rtx (SImode);
4089   if (BYTES_BIG_ENDIAN)
4090     {
4091       emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
4092       if ((value & 255) == ((value >> 8) & 255))
4093         operands[2] = operands[1];
4094       else
4095         {
4096           operands[2] = gen_reg_rtx (SImode);
4097           emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
4098         }
4099     }
4100   else
4101     {
4102       emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
4103       if ((value & 255) == ((value >> 8) & 255))
4104         operands[2] = operands[1];
4105       else
4106         {
4107           operands[2] = gen_reg_rtx (SImode);
4108           emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
4109         }
4110     }
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"
4121   "
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" ""))]
4129   "TARGET_EITHER"
4130   "
4131   if (TARGET_ARM)
4132     {
4133       if (! (reload_in_progress || reload_completed))
4134         {
4135           if (GET_CODE (operands[0]) == MEM)
4136             {
4137               if (arm_arch4)
4138                 {
4139                   emit_insn (gen_storehi_single_op (operands[0], operands[1]));
4140                   DONE;
4141                 }
4142               if (GET_CODE (operands[1]) == CONST_INT)
4143                 emit_insn (gen_storeinthi (operands[0], operands[1]));
4144               else
4145                 {
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]));
4150                   else
4151                    emit_insn (gen_storehi (operands[1], operands[0]));
4152                 }
4153               DONE;
4154             }
4155           /* Sign extend a constant, and keep it in an SImode reg.  */
4156           else if (GET_CODE (operands[1]) == CONST_INT)
4157             {
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))
4163                 {
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)))
4169                     val |= ~0xffff;
4170                   else if (val & 0x8000)
4171                     val |= ~0xffff;
4172                 }
4174               emit_insn (gen_movsi (reg, GEN_INT (val)));
4175               operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
4176             }
4177           else if (! arm_arch4)
4178             {
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)
4184                 {
4185                   if (TARGET_MMU_TRAPS)
4186                     {
4187                       rtx base;
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)
4197                         {
4198                           HOST_WIDE_INT new_offset = INTVAL (offset) & ~3;
4199                           rtx new;
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))
4208                             {
4209                               rtx reg2 = gen_reg_rtx (SImode);
4211                               emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
4212                               reg = reg2;
4213                             }
4214                         }
4215                       else
4216                         emit_insn (gen_movhi_bytes (reg, operands[1]));
4218                       operands[1] = gen_lowpart (HImode, reg);
4219                     }
4220                   else if (BYTES_BIG_ENDIAN)
4221                     {
4222                       rtx base;
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)
4230                         {
4231                           rtx reg = gen_reg_rtx (SImode);
4232                           rtx new;
4234                           if ((INTVAL (offset) & 2) == 2)
4235                             {
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));
4242                             }
4243                           else
4244                             {
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));
4250                             }
4252                           operands[1] = gen_lowpart (HImode, reg);
4253                         }
4254                       else
4255                         {
4256                           emit_insn (gen_movhi_bigend (operands[0], operands[1]));
4257                           DONE;
4258                         }
4259                     }
4260                }
4261            }
4262         }
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])))
4267         {
4268           /* Writing a constant to memory needs a scratch, which should
4269              be handled with SECONDARY_RELOADs.  */
4270           if (GET_CODE (operands[0]) != REG)
4271             abort ();
4273           operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
4274           emit_insn (gen_movsi (operands[0], operands[1]));
4275           DONE;
4276        }
4277     }
4278   else /* TARGET_THUMB */
4279     {
4280       if (! (reload_in_progress || reload_completed))
4281         {
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)))
4296             {
4297               rtx temp = copy_to_reg (XEXP (operands[0], 0));
4298               operands[0] = change_address (operands[0], VOIDmode, temp);
4299             }
4300    
4301           if (GET_CODE (operands[1]) == MEM
4302               && ! memory_address_p (GET_MODE (operands[1]),
4303                                  XEXP (operands[1], 0)))
4304             {
4305               rtx temp = copy_to_reg (XEXP (operands[1], 0));
4306               operands[1] = change_address (operands[1], VOIDmode, temp);
4307             }
4308         }
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'))
4312         {
4313           /* Writing a constant to memory needs a scratch, which should
4314              be handled with SECONDARY_RELOADs.  */
4315           if (GET_CODE (operands[0]) != REG)
4316             abort ();
4318           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4319           emit_insn (gen_movsi (operands[0], operands[1]));
4320           DONE;
4321         }
4322     }
4323   "
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"))]
4329   "TARGET_THUMB
4330    && (   register_operand (operands[0], HImode)
4331        || register_operand (operands[1], HImode))"
4332   "*
4333   switch (which_alternative)
4334     {
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\";
4340     default: abort ();
4341     case 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)
4347         {
4348           rtx ops[2];
4349           ops[0] = operands[0];
4350           ops[1] = XEXP (XEXP (operands[1], 0), 0);
4351       
4352           output_asm_insn (\"mov        %0, %1\", ops);
4354           XEXP (XEXP (operands[1], 0), 0) = operands[0];
4355     
4356         }
4357       return \"ldrh     %0, %1\";
4358     }"
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")
4368                    (const_int 16)))]
4369   "TARGET_ARM && (! TARGET_MMU_TRAPS)"
4370   "*
4372   rtx ops[2];
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);
4377   return \"\";
4378   }"
4379   [(set_attr "type" "load")]
4382 (define_expand "movhi_bytes"
4383   [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
4384    (set (match_dup 3)
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)))]
4388   "TARGET_ARM"
4389   "
4391   rtx mem1, mem2;
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]);
4401   operands[1] = mem1;
4402   operands[2] = gen_reg_rtx (SImode);
4403   operands[3] = gen_reg_rtx (SImode);
4404   operands[6] = mem2;
4406   if (BYTES_BIG_ENDIAN)
4407     {
4408       operands[4] = operands[2];
4409       operands[5] = operands[3];
4410     }
4411   else
4412     {
4413       operands[4] = operands[3];
4414       operands[5] = operands[2];
4415     }
4419 (define_expand "movhi_bigend"
4420   [(set (match_dup 2)
4421         (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
4422                    (const_int 16)))
4423    (set (match_dup 3)
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))]
4427   "TARGET_ARM"
4428   "
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"))]
4437   "TARGET_ARM
4438    && arm_arch4
4439    && (GET_CODE (operands[1]) != CONST_INT
4440        || const_ok_for_arm (INTVAL (operands[1]))
4441        || const_ok_for_arm (~INTVAL (operands[1])))"
4442   "@
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"))]
4455   "TARGET_ARM
4456    && ! arm_arch4
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])))"
4462   "@
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"))]
4474   "TARGET_ARM
4475    && ! arm_arch4
4476    && BYTES_BIG_ENDIAN
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])))"
4481   "@
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)
4494                    (const_int 16)))]
4495   "TARGET_ARM
4496    && BYTES_BIG_ENDIAN
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"
4508   "@
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"))]
4516   "TARGET_THUMB"
4517   "Hi Nick"
4519         
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")])]
4527   "TARGET_EITHER"
4528   "if (TARGET_ARM)
4529      arm_reload_out_hi (operands);
4530    else
4531      thumb_reload_out_hi (operands);
4532   DONE;
4533   "
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)"
4541   "
4542   if (TARGET_ARM)
4543     arm_reload_in_hi (operands);
4544   else
4545     thumb_reload_out_hi (operands);
4546   DONE;
4549 (define_expand "movqi"
4550   [(set (match_operand:QI 0 "general_operand" "")
4551         (match_operand:QI 1 "general_operand" ""))]
4552   "TARGET_EITHER"
4553   "
4554   if (TARGET_ARM)
4555     {
4556       /* Everything except mem = const or mem = mem can be done easily */
4558       if (!(reload_in_progress || reload_completed))
4559         {
4560           if (GET_CODE (operands[1]) == CONST_INT)
4561             {
4562               rtx reg = gen_reg_rtx (SImode);
4564               emit_insn (gen_movsi (reg, operands[1]));
4565               operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
4566             }
4567          if (GET_CODE (operands[0]) == MEM)
4568            operands[1] = force_reg (QImode, operands[1]);
4569        }
4570     }
4571   else /* TARGET_THUMB */
4572     {
4573       if (! (reload_in_progress || reload_completed))
4574         {
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)))
4589             {
4590               rtx temp = copy_to_reg (XEXP (operands[0], 0));
4591               operands[0] = change_address (operands[0], VOIDmode, temp);
4592             }
4593          if (GET_CODE (operands[1]) == MEM
4594              && ! memory_address_p (GET_MODE (operands[1]),
4595                                     XEXP (operands[1], 0)))
4596            {
4597               rtx temp = copy_to_reg (XEXP (operands[1], 0));
4598               operands[1] = change_address (operands[1], VOIDmode, temp);
4599            }
4600         }
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'))
4604         {
4605           /* Writing a constant to memory needs a scratch, which should
4606              be handled with SECONDARY_RELOADs.  */
4607           if (GET_CODE (operands[0]) != REG)
4608             abort ();
4610           operands[0] = gen_rtx (SUBREG, SImode, operands[0], 0);
4611           emit_insn (gen_movsi (operands[0], operands[1]));
4612           DONE;
4613        }
4614     }
4615   "
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"))]
4622   "TARGET_ARM
4623    && (   register_operand (operands[0], QImode)
4624        || register_operand (operands[1], QImode))"
4625   "@
4626    mov%?\\t%0, %1
4627    mvn%?\\t%0, #%B1
4628    ldr%?b\\t%0, %1
4629    str%?b\\t%1, %0"
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"))]
4636   "TARGET_THUMB
4637    && (   register_operand (operands[0], QImode)
4638        || register_operand (operands[1], QImode))"
4639   "@
4640    add\\t%0, %1, #0
4641    ldrb\\t%0, %1
4642    strb\\t%1, %0
4643    mov\\t%0, %1
4644    mov\\t%0, %1
4645    mov\\t%0, %1"
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" ""))]
4654   "TARGET_EITHER"
4655   "
4656   if (TARGET_ARM)
4657     {
4658       if (GET_CODE (operands[0]) == MEM)
4659         operands[1] = force_reg (SFmode, operands[1]);
4660     }
4661   else /* TARGET_THUMB */
4662     {
4663       if (! (reload_in_progress || reload_completed))
4664         {
4665            if (GET_CODE (operands[0]) != REG)
4666              operands[1] = force_reg (SFmode, operands[1]);
4667         }
4668     }
4669   "
4672 (define_split
4673   [(set (match_operand:SF 0 "nonimmediate_operand" "")
4674         (match_operand:SF 1 "immediate_operand" ""))]
4675   "TARGET_ARM
4676    && ! TARGET_HARD_FLOAT
4677    && reload_completed
4678    && GET_CODE (operands[1]) == CONST_DOUBLE"
4679   [(set (match_dup 2) (match_dup 3))]
4680   "
4681   operands[2] = gen_lowpart (SImode, operands[0]);
4682   operands[3] = gen_lowpart (SImode, operands[1]);
4683   if (operands[2] == 0 || operands[3] == 0)
4684     FAIL;
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"))]
4690   "TARGET_ARM
4691    && TARGET_HARD_FLOAT
4692    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
4693   "@
4694    mvf%?s\\t%0, %1
4695    mnf%?s\\t%0, #%N1
4696    ldf%?s\\t%0, %1
4697    stf%?s\\t%1, %0
4698    str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
4699    stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
4700    mov%?\\t%0, %1
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")
4704    (set_attr "type"
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"))]
4717   "TARGET_ARM
4718    && TARGET_SOFT_FLOAT
4719    && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
4720   "@
4721    mov%?\\t%0, %1
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"))]
4734   "TARGET_THUMB
4735    && (   register_operand (operands[0], SFmode) 
4736        || register_operand (operands[1], SFmode))"
4737   "@
4738    add\\t%0, %1, #0
4739    ldmia\\t%1, {%0}
4740    stmia\\t%0, {%1}
4741    ldr\\t%0, %1
4742    str\\t%1, %0
4743    mov\\t%0, %1
4744    mov\\t%0, %1"
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" ""))]
4753   "TARGET_EITHER"
4754   "
4755   if (TARGET_ARM)
4756     {
4757       if (GET_CODE (operands[0]) == MEM)
4758         operands[1] = force_reg (DFmode, operands[1]);
4759     }
4760   else /* TARGET_THUMB */
4761     {
4762       if (! (reload_in_progress || reload_completed))
4763         {
4764           if (GET_CODE (operands[0]) != REG)
4765             operands[1] = force_reg (DFmode, operands[1]);
4766         }
4767     }
4768   "
4771 ;; Reloading a df mode value stored in integer regs to memory can require a
4772 ;; scratch reg.
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")]
4777   "TARGET_ARM"
4778   "
4780   enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
4782   if (code == REG)
4783     operands[2] = XEXP (operands[0], 0);
4784   else if (code == POST_INC || code == PRE_DEC)
4785     {
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]));
4789       DONE;
4790     }
4791   else if (code == PRE_INC)
4792     {
4793       rtx reg = XEXP (XEXP (operands[0], 0), 0);
4794       emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
4795       operands[2] = reg;
4796     }
4797   else if (code == POST_DEC)
4798     operands[2] = XEXP (XEXP (operands[0], 0), 0);
4799   else
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]),
4804                                     operands[1]));
4806   if (code == POST_DEC)
4807     emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
4809   DONE;
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"))]
4816   "TARGET_ARM
4817    && TARGET_HARD_FLOAT
4818    && (GET_CODE (operands[0]) != MEM
4819        || register_operand (operands[1], DFmode))"
4820   "*
4821   {
4822   switch (which_alternative)
4823     {
4824     default:
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);
4834     }
4835   }
4836   "
4837   [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
4838    (set_attr "type"
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
4846 ;; an `f' reg.
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"))]
4866   "TARGET_THUMB
4867    && (   register_operand (operands[0], DFmode)
4868        || register_operand (operands[1], DFmode))"
4869   "*
4870   switch (which_alternative)
4871     {
4872     default:
4873     case 0:
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\";
4877     case 1:
4878       return \"ldmia\\t%1, {%0, %H0}\";
4879     case 2:
4880       return \"stmia\\t%0, {%1, %H1}\";
4881     case 3:
4882       return thumb_load_double_from_address (operands);
4883     case 4:
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);
4886       return \"\";
4887     case 5:
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\";
4891     }
4892   "
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"
4903   "")
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)"
4912   "*
4913   switch (which_alternative)
4914     {
4915     default:
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);
4923     }
4924   "
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 "" ""))])]
4940   "TARGET_ARM"
4941   "
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)
4950     FAIL;
4952   operands[3]
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))"
4970   "*
4972   rtx ops[3];
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);
4980   return \"\";
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")))])]
4991   "TARGET_ARM"
4992   "*
4994   rtx ops[3];
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);
5002   return \"\";
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 "" ""))])]
5011   "TARGET_ARM"
5012   "
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)
5021     FAIL;
5023   operands[3]
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))"
5041   "*
5042   {
5043     rtx ops[3];
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);
5051     return \"\";
5052   }
5053   "
5054   [(set (attr "type")
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"))])]
5068   "TARGET_ARM"
5069   "*
5070   {
5071     rtx ops[3];
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);
5079     return \"\";
5080   }
5081   "
5082   [(set (attr "type")
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" "")]
5099   "TARGET_EITHER"
5100   "
5101   if (TARGET_ARM)
5102     {
5103       if (arm_gen_movstrqi (operands))
5104         DONE;
5105       FAIL;
5106     }
5107   else /* TARGET_THUMB */
5108     {
5109       if (   INTVAL (operands[3]) != 4
5110           || INTVAL (operands[2]) > 48)
5111         FAIL;
5113       thumb_expand_movstrqi (operands);
5114       DONE;
5115     }
5116   "
5119 ;; Block-move insns
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"))]
5133   "TARGET_THUMB"
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"))]
5150   "TARGET_THUMB"
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"
5163   [(set (pc)
5164         (if_then_else
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 "" ""))
5169             (pc)))]
5170   "TARGET_THUMB"
5171   "*
5172   output_asm_insn (\"cmp\\t%1, %2\", operands);
5173   switch (get_attr_length (insn))
5174     {
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%=:\";
5178     }
5179   "
5180   [(set (attr "far_jump")
5181         (if_then_else
5182             (eq_attr "length" "8")
5183             (const_string "yes")
5184             (const_string "no")))
5185    (set (attr "length") 
5186         (if_then_else
5187             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5188                  (le (minus (match_dup 3) (pc)) (const_int 256)))
5189             (const_int 4)
5190             (if_then_else
5191                 (and (ge (minus (match_dup 3) (pc)) (const_int -2040))
5192                      (le (minus (match_dup 3) (pc)) (const_int 2054)))
5193                 (const_int 6)
5194                 (const_int 8))))]
5197 (define_insn "*negated_cbranchsi4"
5198   [(set (pc)
5199         (if_then_else
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 "" ""))
5204             (pc)))]
5205   "TARGET_THUMB"
5206   "*
5207   output_asm_insn (\"cmn\\t%1, %2\", operands);
5208   switch (get_attr_length (insn))
5209     {
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%=:\";
5213     }
5214   "
5215   [(set (attr "far_jump")
5216         (if_then_else
5217             (eq_attr "length" "8")
5218             (const_string "yes")
5219             (const_string "no")))
5220    (set (attr "length") 
5221         (if_then_else
5222             (and (ge (minus (match_dup 3) (pc)) (const_int -250))
5223                  (le (minus (match_dup 3) (pc)) (const_int 254)))
5224             (const_int 4)
5225             (if_then_else
5226                 (and (ge (minus (match_dup 3) (pc)) (const_int -2044))
5227                      (le (minus (match_dup 3) (pc)) (const_int 2044)))
5228                 (const_int 6)
5229                 (const_int 8))))]
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" "")]
5238   "TARGET_ARM"
5239   "{
5240     arm_compare_op0 = operands[0];
5241     arm_compare_op1 = operands[1];
5242     DONE;
5243   }"
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"
5250   "
5252   arm_compare_op0 = operands[0];
5253   arm_compare_op1 = operands[1];
5254   DONE;
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"
5262   "
5264   arm_compare_op0 = operands[0];
5265   arm_compare_op1 = operands[1];
5266   DONE;
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"
5274   "{
5275     arm_compare_op0 = operands[0];
5276     arm_compare_op1 = operands[1];
5277     DONE;
5278   }"
5281 (define_insn "*arm_cmpsi_insn"
5282   [(set (reg:CC 24)
5283         (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
5284                     (match_operand:SI 1 "arm_add_operand"    "rI,L")))]
5285   "TARGET_ARM"
5286   "@
5287    cmp%?\\t%0, %1
5288    cmn%?\\t%0, #%n1"
5289   [(set_attr "conds" "set")]
5292 (define_insn "*cmpsi_shiftsi"
5293   [(set (reg:CC 24)
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")])))]
5298   "TARGET_ARM"
5299   "cmp%?\\t%0, %1%S3"
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")))]
5309   "TARGET_ARM"
5310   "cmp%?\\t%0, %1%S3"
5311   [(set_attr "conds" "set")
5314 (define_insn "*cmpsi_neg_shiftsi"
5315   [(set (reg:CC 24)
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")]))))]
5320   "TARGET_ARM"
5321   "cmn%?\\t%0, %1%S3"
5322   [(set_attr "conds" "set")
5325 (define_insn "*cmpsf_insn"
5326   [(set (reg:CCFP 24)
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"
5330   "@
5331    cmf%?\\t%0, %1
5332    cnf%?\\t%0, #%N1"
5333 [(set_attr "conds" "set")
5334  (set_attr "type" "f_2_r")])
5336 (define_insn "*cmpdf_insn"
5337   [(set (reg:CCFP 24)
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"
5341   "@
5342    cmf%?\\t%0, %1
5343    cnf%?\\t%0, #%N1"
5344 [(set_attr "conds" "set")
5345  (set_attr "type" "f_2_r")])
5347 (define_insn "*cmpesfdf_df"
5348   [(set (reg:CCFP 24)
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"
5353   "@
5354    cmf%?\\t%0, %1
5355    cnf%?\\t%0, #%N1"
5356 [(set_attr "conds" "set")
5357  (set_attr "type" "f_2_r")])
5359 (define_insn "*cmpdf_esfdf"
5360   [(set (reg:CCFP 24)
5361         (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
5362                       (float_extend:DF
5363                        (match_operand:SF 1 "s_register_operand" "f"))))]
5364   "TARGET_ARM && TARGET_HARD_FLOAT"
5365   "cmf%?\\t%0, %1"
5366 [(set_attr "conds" "set")
5367  (set_attr "type" "f_2_r")])
5369 (define_insn "*cmpxf_insn"
5370   [(set (reg:CCFP 24)
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"
5374   "@
5375    cmf%?\\t%0, %1
5376    cnf%?\\t%0, #%N1"
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"
5385   "@
5386    cmf%?e\\t%0, %1
5387    cnf%?e\\t%0, #%N1"
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"
5396   "@
5397    cmf%?e\\t%0, %1
5398    cnf%?e\\t%0, #%N1"
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"
5408   "@
5409    cmf%?e\\t%0, %1
5410    cnf%?e\\t%0, #%N1"
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")
5417                        (float_extend:DF
5418                         (match_operand:SF 1 "s_register_operand" "f"))))]
5419   "TARGET_ARM && TARGET_HARD_FLOAT"
5420   "cmf%?e\\t%0, %1"
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"
5429   "@
5430    cmf%?e\\t%0, %1
5431    cnf%?e\\t%0, #%N1"
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))]
5443   "TARGET_ARM"
5444   "\\t%@ deleted compare"
5445   [(set_attr "conds" "set")
5446    (set_attr "length" "0")]
5450 ;; Conditional branch insns
5452 (define_expand "beq"
5453   [(set (pc)
5454         (if_then_else (eq (match_dup 1) (const_int 0))
5455                       (label_ref (match_operand 0 "" ""))
5456                       (pc)))]
5457   "TARGET_ARM"
5458   "operands[1] = arm_gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1);"
5461 (define_expand "bne"
5462   [(set (pc)
5463         (if_then_else (ne (match_dup 1) (const_int 0))
5464                       (label_ref (match_operand 0 "" ""))
5465                       (pc)))]
5466   "TARGET_ARM"
5467   "operands[1] = arm_gen_compare_reg (NE, arm_compare_op0, arm_compare_op1);"
5470 (define_expand "bgt"
5471   [(set (pc)
5472         (if_then_else (gt (match_dup 1) (const_int 0))
5473                       (label_ref (match_operand 0 "" ""))
5474                       (pc)))]
5475   "TARGET_ARM"
5476   "operands[1] = arm_gen_compare_reg (GT, arm_compare_op0, arm_compare_op1);"
5479 (define_expand "ble"
5480   [(set (pc)
5481         (if_then_else (le (match_dup 1) (const_int 0))
5482                       (label_ref (match_operand 0 "" ""))
5483                       (pc)))]
5484   "TARGET_ARM"
5485   "operands[1] = arm_gen_compare_reg (LE, arm_compare_op0, arm_compare_op1);"
5488 (define_expand "bge"
5489   [(set (pc)
5490         (if_then_else (ge (match_dup 1) (const_int 0))
5491                       (label_ref (match_operand 0 "" ""))
5492                       (pc)))]
5493   "TARGET_ARM"
5494   "operands[1] = arm_gen_compare_reg (GE, arm_compare_op0, arm_compare_op1);"
5497 (define_expand "blt"
5498   [(set (pc)
5499         (if_then_else (lt (match_dup 1) (const_int 0))
5500                       (label_ref (match_operand 0 "" ""))
5501                       (pc)))]
5502   "TARGET_ARM"
5503   "operands[1] = arm_gen_compare_reg (LT, arm_compare_op0, arm_compare_op1);"
5506 (define_expand "bgtu"
5507   [(set (pc)
5508         (if_then_else (gtu (match_dup 1) (const_int 0))
5509                       (label_ref (match_operand 0 "" ""))
5510                       (pc)))]
5511   "TARGET_ARM"
5512   "operands[1] = arm_gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1);"
5515 (define_expand "bleu"
5516   [(set (pc)
5517         (if_then_else (leu (match_dup 1) (const_int 0))
5518                       (label_ref (match_operand 0 "" ""))
5519                       (pc)))]
5520   "TARGET_ARM"
5521   "operands[1] = arm_gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1);"
5524 (define_expand "bgeu"
5525   [(set (pc)
5526         (if_then_else (geu (match_dup 1) (const_int 0))
5527                       (label_ref (match_operand 0 "" ""))
5528                       (pc)))]
5529   "TARGET_ARM"
5530   "operands[1] = arm_gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1);"
5533 (define_expand "bltu"
5534   [(set (pc)
5535         (if_then_else (ltu (match_dup 1) (const_int 0))
5536                       (label_ref (match_operand 0 "" ""))
5537                       (pc)))]
5538   "TARGET_ARM"
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"
5545   [(set (pc)
5546         (if_then_else (match_operator 1 "comparison_operator"
5547                        [(match_operand 2 "cc_register" "") (const_int 0)])
5548                       (label_ref (match_operand 0 "" ""))
5549                       (pc)))]
5550   "TARGET_ARM"
5551   "*
5552   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5553     {
5554       arm_ccfsm_state += 2;
5555       return \"\";
5556     }
5557   return \"b%d1\\t%l0\";
5558   "
5559   [(set_attr "conds" "use")]
5562 (define_insn "*arm_cond_branch_reversed"
5563   [(set (pc)
5564         (if_then_else (match_operator 1 "comparison_operator"
5565                        [(match_operand 2 "cc_register" "") (const_int 0)])
5566                       (pc)
5567                       (label_ref (match_operand 0 "" ""))))]
5568   "TARGET_ARM"
5569   "*
5570   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5571     {
5572       arm_ccfsm_state += 2;
5573       return \"\";
5574     }
5575   return \"b%D1\\t%l0\";
5576   "
5577   [(set_attr "conds" "use")]
5582 ; scc insns
5584 (define_expand "seq"
5585   [(set (match_operand:SI 0 "s_register_operand" "=r")
5586         (eq:SI (match_dup 1) (const_int 0)))]
5587   "TARGET_ARM"
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)))]
5594   "TARGET_ARM"
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)))]
5601   "TARGET_ARM"
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)))]
5608   "TARGET_ARM"
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)))]
5615   "TARGET_ARM"
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)))]
5622   "TARGET_ARM"
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)))]
5629   "TARGET_ARM"
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)))]
5636   "TARGET_ARM"
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)))]
5643   "TARGET_ARM"
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)))]
5650   "TARGET_ARM"
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)]))]
5658   "TARGET_ARM"
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)])))]
5668   "TARGET_ARM"
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)])))]
5678   "TARGET_ARM"
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" "")))]
5692   "TARGET_ARM"
5693   "
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" "")))]
5706   "TARGET_ARM"
5707   "
5709   enum rtx_code code = GET_CODE (operands[1]);
5710   rtx ccreg;
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"
5729   "
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")
5739         (if_then_else:SI
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")))]
5744   "TARGET_ARM"
5745   "@
5746    mov%D3\\t%0, %2
5747    mvn%D3\\t%0, #%B2
5748    mov%d3\\t%0, %1
5749    mvn%d3\\t%0, #%B1
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")
5759         (if_then_else:SF
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"
5765   "@
5766    mvf%D3s\\t%0, %2
5767    mnf%D3s\\t%0, #%N2
5768    mvf%d3s\\t%0, %1
5769    mnf%d3s\\t%0, #%N1
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"
5785   "@
5786    mov%D3\\t%0, %2
5787    mov%d3\\t%0, %1"
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")
5792         (if_then_else:DF
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"
5798   "@
5799    mvf%D3d\\t%0, %2
5800    mnf%D3d\\t%0, #%N2
5801    mvf%d3d\\t%0, %1
5802    mnf%d3d\\t%0, #%N1
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"
5814   [(set (pc)
5815         (label_ref (match_operand 0 "" "")))]
5816   "TARGET_EITHER"
5817   ""
5820 (define_insn "*arm_jump"
5821   [(set (pc)
5822         (label_ref (match_operand 0 "" "")))]
5823   "TARGET_ARM"
5824   "*
5826   if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
5827     {
5828       arm_ccfsm_state += 2;
5829       return \"\";
5830     }
5831   return \"b%?\\t%l0\";
5834 (define_insn "*thumb_jump"
5835   [(set (pc)
5836         (label_ref (match_operand 0 "" "")))]
5837   "TARGET_THUMB"
5838   "*
5839   if (get_attr_length (insn) == 2)
5840     return \"b\\t%l0\";
5841   return \"bl\\t%l0\\t%@ far jump\";
5842   "
5843   [(set (attr "far_jump")
5844         (if_then_else
5845             (eq_attr "length" "4")
5846             (const_string "yes")
5847             (const_string "no")))
5848    (set (attr "length") 
5849         (if_then_else
5850             (and (ge (minus (match_dup 0) (pc)) (const_int -2048))
5851                  (le (minus (match_dup 0) (pc)) (const_int 2044)))
5852             (const_int 2)
5853             (const_int 4)))]
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))])]
5861   "TARGET_EITHER"
5862   "
5863   {
5864     rtx callee;
5865     
5866     /* In an untyped call, we can get NULL for operand 2.  */
5867     if (operands[2] == NULL_RTX)
5868       operands[2] = const0_rtx;
5869       
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
5879        invoked it.  */
5880     callee  = XEXP (operands[0], 0);
5881     
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);
5885   }"
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))]
5893   "TARGET_ARM"
5894   "*
5895   return output_call (operands);
5896   "
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))]
5907   "TARGET_ARM"
5908   "*
5909   return output_call_mem (operands);
5910   "
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))]
5920   "TARGET_THUMB"
5921   "*
5922   {
5923     if (TARGET_CALLER_INTERWORKING)
5924       return \"bl\\t%__interwork_call_via_%0\";
5925     else
5926       return \"bl\\t%__call_via_%0\";
5927   }"
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))]
5937   "TARGET_THUMB"
5938   "*
5939   {
5940     if (TARGET_CALLER_INTERWORKING)
5941       return \"bl\\t%__interwork_call_via_%1\";
5942     else
5943       return \"bl\\t%__call_via_%1\";
5944   }"
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))])]
5954   "TARGET_EITHER"
5955   "
5956   {
5957     rtx callee = XEXP (operands[1], 0);
5958     
5959     /* In an untyped call, we can get NULL for operand 2.  */
5960     if (operands[3] == 0)
5961       operands[3] = const0_rtx;
5962       
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);
5967   }"
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))]
5976   "TARGET_ARM"
5977   "*
5978   return output_call (& operands[1]);
5979   "
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)))"
5991   "*
5992   return output_call_mem (& operands[1]);
5993   "
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))]
6006   "TARGET_ARM
6007    && (GET_CODE (operands[0]) == SYMBOL_REF)
6008    && ! arm_is_longcall_p (operands[0], INTVAL (operands[2]), 1)"
6009   "*
6010   {
6011     return NEED_PLT_RELOC ? \"bl%?\\t%a0(PLT)\" : \"bl%?\\t%a0\";
6012   }"
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))]
6022   "TARGET_ARM
6023    && (GET_CODE (operands[1]) == SYMBOL_REF)
6024    && ! arm_is_longcall_p (operands[1], INTVAL (operands[3]), 1)"
6025   "*
6026   {
6027     return NEED_PLT_RELOC ? \"bl%?\\t%a1(PLT)\" : \"bl%?\\t%a1\";
6028   }"
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)"
6038   "bl\\t%a0"
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)"
6050   "bl\\t%a1"
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"
6057   [(return)]
6058   "TARGET_ARM && USE_RETURN_INSN (FALSE)"
6059   "*
6060   {
6061     if (arm_ccfsm_state == 2)
6062       {
6063         arm_ccfsm_state += 2;
6064         return \"\";
6065       }
6066     return output_return_instruction (NULL, TRUE, FALSE);
6067   }"
6068   [(set_attr "type" "load")]
6071 (define_insn "*cond_return"
6072   [(set (pc)
6073         (if_then_else (match_operator 0 "comparison_operator"
6074                        [(match_operand 1 "cc_register" "") (const_int 0)])
6075                       (return)
6076                       (pc)))]
6077   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6078   "*
6080   if (arm_ccfsm_state == 2)
6081     {
6082       arm_ccfsm_state += 2;
6083       return \"\";
6084     }
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"
6091   [(set (pc)
6092         (if_then_else (match_operator 0 "comparison_operator"
6093                        [(match_operand 1 "cc_register" "") (const_int 0)])
6094                       (pc)
6095                       (return)))]
6096   "TARGET_ARM && USE_RETURN_INSN (TRUE)"
6097   "*
6099   if (arm_ccfsm_state == 2)
6100     {
6101       arm_ccfsm_state += 2;
6102       return \"\";
6103     }
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 "" "")
6113                     (const_int 0))
6114               (match_operand 1 "" "")
6115               (match_operand 2 "" "")])]
6116   "TARGET_ARM"
6117   "
6119   int i;
6121   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
6123   for (i = 0; i < XVECLEN (operands[2], 0); i++)
6124     {
6125       rtx set = XVECEXP (operands[2], 0, i);
6126       emit_move_insn (SET_DEST (set), SET_SRC (set));
6127     }
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
6132      point.  */
6133   emit_insn (gen_blockage ());
6135   DONE;
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)]
6143   "TARGET_EITHER"
6144   ""
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
6155   "TARGET_ARM"
6156   "
6158   rtx reg;
6159   if (operands[1] != const0_rtx)
6160     {
6161       reg = gen_reg_rtx (SImode);
6162       emit_insn (gen_addsi3 (reg, operands[0],
6163                              GEN_INT (-INTVAL (operands[1]))));
6164       operands[0] = reg;
6165     }
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],
6171                                        operands[4]));
6172   DONE;
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)
6179                (if_then_else
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)))])]
6187   "TARGET_ARM"
6188   "*
6189   if (flag_pic)
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"
6197   [(set (pc)
6198         (match_operand:SI 0 "s_register_operand" ""))]
6199   "TARGET_EITHER"
6200   ""
6203 (define_insn "*arm_indirect_jump"
6204   [(set (pc)
6205         (match_operand:SI 0 "s_register_operand" "r"))]
6206   "TARGET_ARM"
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"
6213   [(set (pc)
6214         (match_operand:SI 0 "memory_operand" "m"))]
6215   "TARGET_ARM"
6216   "ldr%?\\t%|pc, %0\\t%@ indirect memory jump"
6217   [(set_attr "type" "load")]
6220 (define_insn "*thumb_indirect_jump"
6221   [(set (pc)
6222         (match_operand:SI 0 "register_operand" "l*r"))]
6223   "TARGET_THUMB"
6224   "mov\\tpc, %0"
6225   [(set_attr "conds" "clob")
6226    (set_attr "length" "2")]
6230 ;; Misc insns
6232 (define_insn "nop"
6233   [(const_int 0)]
6234   "TARGET_EITHER"
6235   "*
6236   if (TARGET_ARM)
6237     return \"mov%?\\t%|r0, %|r0\\t%@ nop\";
6238   return  \"mov\\tr8, r8\";
6239   "
6240   [(set (attr "length")
6241         (if_then_else (eq_attr "is_thumb" "yes")
6242                       (const_int 2)
6243                       (const_int 4)))]
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")]))]
6256   "TARGET_ARM"
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")])
6267                          (const_int 0)))
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)])
6270                          (match_dup 2)]))]
6271   "TARGET_ARM"
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")])
6283                          (const_int 0)))
6284    (clobber (match_scratch:SI 0 "=r"))]
6285   "TARGET_ARM"
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")])))]
6296   "TARGET_ARM"
6297   "sub%?\\t%0, %1, %3%S2"
6300 (define_insn "*sub_shiftsi_compare0"
6301   [(set (reg:CC_NOOV 24)
6302         (compare:CC_NOOV
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")]))
6307          (const_int 0)))
6308    (set (match_operand:SI 0 "s_register_operand" "=r")
6309         (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
6310                                                  (match_dup 4)])))]
6311   "TARGET_ARM"
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)
6318         (compare:CC_NOOV
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")]))
6323          (const_int 0)))
6324    (clobber (match_scratch:SI 0 "=r"))]
6325   "TARGET_ARM"
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"
6346   "*
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
6358                           (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"))
6364                          (const_int 0)))
6365    (set (match_operand:SI 0 "" "=&r")
6366         (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
6367                           (match_dup 1))
6368                  (match_dup 2)))]
6369   "TARGET_ARM && reload_in_progress"
6370   "*
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
6380                           (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"))
6386                          (const_int 0)))
6387    (clobber (match_scratch:SI 0 "=&r"))]
6388   "TARGET_ARM && reload_in_progress"
6389   "*
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"
6406   "*
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"))
6422                          (const_int 0)))
6423    (set (match_operand:SI 0 "" "=&r")
6424         (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
6425                  (match_dup 2)))]
6426   "TARGET_ARM && reload_in_progress"
6427   "*
6428   output_add_immediate (operands);
6429   output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
6430   return \"\";
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"))
6443                          (const_int 0)))
6444    (clobber (match_scratch:SI 0 "=&r"))]
6445   "TARGET_ARM && reload_in_progress"
6446   "*
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")))]
6461   "TARGET_ARM"
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")))]
6471   "TARGET_ARM"
6472   "@
6473    orr%d2\\t%0, %1, #1
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))]
6484   "TARGET_ARM"
6485   "*
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)
6493     {
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\";
6497     }
6498   if (which_alternative == 1)
6499     output_asm_insn (\"cmn\\t%2, #%n3\", operands);
6500   else
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)])
6512                            (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")))]
6515   "TARGET_ARM"
6516   "*
6517   if (GET_CODE (operands[3]) == NE)
6518     {
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);
6523       return \"\";
6524     }
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);
6529   return \"\";
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))]
6542   "TARGET_ARM"
6543   "*
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))]
6566   "TARGET_ARM"
6567   "*
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" "")
6578         (compare
6579          (if_then_else:SI
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")])
6586           (const_int 0))
6587          (const_int 0)))]
6588   "TARGET_ARM"
6589   "*
6591   char * opcodes[4][2] =
6592   {
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\"}
6598   };
6599   int swap =
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" "")
6610         (compare
6611          (if_then_else:SI
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")])
6618           (const_int 1))
6619          (const_int 0)))]
6620   "TARGET_ARM"
6621   "*
6623   char * opcodes[4][2] =
6624   {
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\"}
6630   };
6631   int swap =
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))]
6647   "TARGET_ARM"
6648   "*
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")
6667         (if_then_else:SI
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))]
6674   "TARGET_ARM"
6675   "*
6676   if (GET_CODE (operands[5]) == LT
6677       && (operands[4] == const0_rtx))
6678     {
6679       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
6680         {
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\";
6684         }
6685       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
6686         {
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\";
6690         }
6691       /* The only case that falls through to here is when both ops 1 & 2
6692          are constants */
6693     }
6695   if (GET_CODE (operands[5]) == GE
6696       && (operands[4] == const0_rtx))
6697     {
6698       if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
6699         {
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\";
6703         }
6704       else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
6705         {
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\";
6709         }
6710       /* The only case that falls through to here is when both ops 1 & 2
6711          are constants */
6712     }
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);
6716   else
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);
6722   return \"\";
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")])
6732                          (plus:SI
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))]
6737   "TARGET_ARM"
6738   "#"
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")
6744         (if_then_else:SI
6745          (match_operator 4 "comparison_operator"
6746           [(match_operand 5 "cc_register" "") (const_int 0)])
6747          (plus:SI
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")))]
6751   "TARGET_ARM"
6752   "@
6753    add%d4\\t%0, %2, %3
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")
6767                          (plus:SI
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))]
6771   "TARGET_ARM"
6772   "#"
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")
6778         (if_then_else:SI
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")
6782          (plus:SI
6783           (match_operand:SI 2 "s_register_operand" "r,r,r,r")
6784           (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
6785   "TARGET_ARM"
6786   "@
6787    add%D4\\t%0, %2, %3
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))]
6807   "TARGET_ARM"
6808   "#"
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")])))]
6822   "TARGET_ARM"
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))]
6837   "TARGET_ARM"
6838   "*
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]))
6848     {
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\";
6853     }
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);
6857   else
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\";
6862   return \"\";
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")))]
6875   "TARGET_ARM"
6876   "@
6877    %I5%d4\\t%0, %2, %3
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))]
6893   "TARGET_ARM"
6894   "*
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]))
6904     {
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\";
6909     }
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);
6914   else
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")
6926         (if_then_else:SI
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")])))]
6933   "TARGET_ARM"
6934   "@
6935    %I5%D4\\t%0, %2, %3
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")
6943         (if_then_else:SI
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")
6948          (not:SI
6949           (match_operand:SI 2 "s_register_operand" "r,r"))))
6950    (clobber (reg:CC 24))]
6951   "TARGET_ARM"
6952   "#"
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")
6958         (if_then_else:SI
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"))))]
6963   "TARGET_ARM"
6964   "@
6965    mvn%D4\\t%0, %2
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")
6973         (if_then_else:SI 
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")])
6977          (not:SI
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))]
6981   "TARGET_ARM"
6982   "#"
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")
6988         (if_then_else:SI
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")))]
6993   "TARGET_ARM"
6994   "@
6995    mvn%d4\\t%0, %2
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")
7003         (if_then_else:SI
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))]
7012   "TARGET_ARM"
7013   "#"
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")
7019         (if_then_else:SI
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")))]
7026   "TARGET_ARM"
7027   "@
7028    mov%d5\\t%0, %2%S4
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")
7036         (if_then_else:SI
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))]
7045   "TARGET_ARM"
7046   "#"
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")
7052         (if_then_else:SI
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")])))]
7059   "TARGET_ARM"
7060   "@
7061    mov%D5\\t%0, %2%S4
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")
7069         (if_then_else:SI
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))]
7080   "TARGET_ARM"
7081   "#"
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")
7087         (if_then_else:SI
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")])))]
7096   "TARGET_ARM"
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")
7103         (if_then_else:SI
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))]
7112   "TARGET_ARM"
7113   "#"
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")
7119         (if_then_else:SI
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")])))]
7126   "TARGET_ARM"
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")
7133         (if_then_else:SI
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))]
7142   "TARGET_ARM"
7143   "#"
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")
7149         (if_then_else:SI
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"))))]
7156   "TARGET_ARM"
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")
7163         (if_then_else:SI
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))]
7170   "TARGET_ARM"
7171   "#"
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")
7177         (if_then_else:SI
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")))]
7182   "TARGET_ARM"
7183   "@
7184    rsb%d4\\t%0, %2, #0
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")
7192         (if_then_else:SI
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))]
7199   "TARGET_ARM"
7200   "#"
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")
7206         (if_then_else:SI
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"))))]
7211   "TARGET_ARM"
7212   "@
7213    rsb%D4\\t%0, %2, #0
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])"
7226   "*
7228   rtx ldm[3];
7229   rtx arith[4];
7230   int val1 = 0, val2 = 0;
7232   if (REGNO (operands[0]) > REGNO (operands[4]))
7233     {
7234       ldm[1] = operands[4];
7235       ldm[2] = operands[0];
7236     }
7237   else
7238     {
7239       ldm[1] = operands[0];
7240       ldm[2] = operands[4];
7241     }
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];
7248   if (val1 < val2)
7249     {
7250       arith[1] = ldm[1];
7251       arith[2] = ldm[2];
7252     }
7253   else
7254     {
7255       arith[1] = ldm[2];
7256       arith[2] = ldm[1];
7257     }
7258   if (val1 && val2)
7259     {
7260       rtx ops[3];
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);
7265       if (val1 < val2)
7266         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7267       else
7268         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7269     }
7270   else if (val1)
7271     {
7272       ldm[0] = XEXP (operands[3], 0);
7273       if (val1 < val2)
7274         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7275       else
7276         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7277     }
7278   else
7279     {
7280       ldm[0] = XEXP (operands[2], 0);
7281       if (val1 < val2)
7282         output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
7283       else
7284         output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
7285     }
7286   output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
7287   return \"\";
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)))]
7309   "TARGET_ARM
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)))]
7323   "TARGET_ARM
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)))]
7337   "TARGET_ARM
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)))]
7351   "TARGET_ARM
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")
7361         (zero_extend:SI
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)))]
7366   "TARGET_ARM
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")
7376         (zero_extend:SI
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)))]
7381   "TARGET_ARM
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)))]
7395   "TARGET_ARM
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)))]
7409   "TARGET_ARM
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)))]
7423   "TARGET_ARM
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)))]
7437   "TARGET_ARM
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)))]
7451   "TARGET_ARM
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)))]
7467   "TARGET_ARM
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)])
7485                  (match_dup 1)))]
7486   "TARGET_ARM
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)
7501                                                  (match_dup 4)])))]
7502   "TARGET_ARM
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)])
7517                  (match_dup 1)))]
7518   "TARGET_ARM
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)
7533                                                  (match_dup 4)])))]
7534   "TARGET_ARM
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)])
7549                  (match_dup 1)))]
7550   "TARGET_ARM
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)
7565                                                  (match_dup 4)])))]
7566   "TARGET_ARM
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)])
7581                  (match_dup 1)))]
7582   "TARGET_ARM
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)
7597                                                  (match_dup 4)])))]
7598   "TARGET_ARM
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)])
7613                  (match_dup 1)))]
7614   "TARGET_ARM
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)
7631                                                  (match_dup 4)])))]
7632   "TARGET_ARM
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
7642 ; try these....
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.
7649 (define_peephole
7650   [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
7651         (match_operand:QI 2 "s_register_operand" "r"))
7652    (set (match_dup 0)
7653         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
7654   "TARGET_ARM"
7655   "str%?b\\t%2, [%0], %1")
7657 (define_peephole
7658   [(set (match_operand:QI 0 "s_register_operand" "=r")
7659         (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
7660    (set (match_dup 1)
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")
7667 (define_peephole
7668   [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
7669         (match_operand:SI 2 "s_register_operand" "r"))
7670    (set (match_dup 0)
7671         (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
7672   "TARGET_ARM"
7673   "str%?\\t%2, [%0], %1")
7675 (define_peephole
7676   [(set (match_operand:HI 0 "s_register_operand" "=r")
7677         (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
7678    (set (match_dup 1)
7679         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
7680   "TARGET_ARM
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")
7688 (define_peephole
7689   [(set (match_operand:SI 0 "s_register_operand" "=r")
7690         (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
7691    (set (match_dup 1)
7692         (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
7693   "TARGET_ARM
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")
7699 (define_peephole
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)))]
7704   "TARGET_ARM"
7705   "str%?b\\t%2, [%0, %1]!")
7707 (define_peephole
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)])
7714                                (match_dup 2)))]
7715   "TARGET_ARM"
7716   "str%?b\\t%3, [%2, %0%S4]!")
7718 ; This pattern is never tried by combine, so do it as a peephole
7720 (define_peephole
7721   [(set (match_operand:SI 0 "s_register_operand" "=r")
7722         (match_operand:SI 1 "s_register_operand" "r"))
7723    (set (reg:CC 24)
7724         (compare:CC (match_dup 1) (const_int 0)))]
7725   "TARGET_ARM"
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.
7732 (define_peephole
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)"
7742   "*
7743   return emit_ldm_seq (operands, 4);
7746 (define_peephole
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)"
7754   "*
7755   return emit_ldm_seq (operands, 3);
7758 (define_peephole
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)"
7764   "*
7765   return emit_ldm_seq (operands, 2);
7768 (define_peephole
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)"
7778   "*
7779   return emit_stm_seq (operands, 4);
7782 (define_peephole
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)"
7790   "*
7791   return emit_stm_seq (operands, 3);
7794 (define_peephole
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)"
7800   "*
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
7816 ;; calculations.
7818 (define_peephole
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))])
7823    (return)]
7824   "TARGET_ARM
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)"
7828   "*
7830   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
7831     {
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;
7836     }
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")])
7844 (define_peephole
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))])
7850    (return)]
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)"
7854   "*
7856   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
7857     {
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;
7862     }
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.
7873 (define_peephole
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))])
7879    (use (match_dup 0))
7880    (return)]
7881   "TARGET_ARM
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)"
7885   "*
7887   if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
7888     {
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;
7893     }
7895   output_return_instruction (NULL, FALSE, FALSE);
7896   return \"b%?\\t%a1\";
7898 [(set_attr "type" "call")
7899  (set_attr "length" "8")])
7901 (define_split
7902   [(set (match_operand:SI 0 "s_register_operand" "")
7903         (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
7904                        (const_int 0))
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" ""))]
7909   "TARGET_ARM"
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)])
7912                               (match_dup 5)))]
7913   "")
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.
7919 (define_split
7920   [(set (reg:CC_Z 24)
7921         (compare:CC_Z
7922          (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
7923                     (const_int 24))
7924          (match_operand 1 "const_int_operand" "")))
7925    (clobber (match_scratch:SI 2 ""))]
7926   "TARGET_ARM
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)))]
7931   "
7932   operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
7935 (define_expand "prologue"
7936   [(clobber (const_int 0))]
7937   "TARGET_EITHER"
7938   "if (TARGET_ARM)
7939      arm_expand_prologue ();
7940    else
7941      thumb_expand_prologue ();
7942   DONE;
7943   "
7946 (define_expand "epilogue"
7947   [(unspec_volatile [(return)] 1)]
7948   "TARGET_EITHER"
7949   "
7950   if (TARGET_THUMB)
7951     thumb_expand_epilogue ();
7952   else if (USE_RETURN_INSN (FALSE))
7953     {
7954       emit_jump_insn (gen_return ());
7955       DONE;
7956     }
7957   emit_jump_insn (gen_rtx_UNSPEC_VOLATILE (VOIDmode,
7958         gen_rtvec (1,
7959                 gen_rtx_RETURN (VOIDmode)),
7960         1));
7961   DONE;
7962   "
7965 (define_insn "*epilogue_insns"
7966   [(unspec_volatile [(return)] 1)]
7967   "TARGET_EITHER"
7968   "*
7969   if (TARGET_ARM)
7970     return arm_output_epilogue ();
7971   else /* TARGET_THUMB */
7972     return thumb_unexpanded_epilogue ();
7973   "
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"))]
7983   "TARGET_EITHER"
7984   "
7986   cfun->machine->eh_epilogue_sp_ofs = operands[1];
7987   if (GET_CODE (operands[2]) != REG || REGNO (operands[2]) != 2)
7988     {
7989       rtx ra = gen_rtx_REG (Pmode, 2);
7990       emit_move_insn (ra, operands[2]);
7991       operands[2] = ra;
7992     }
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
8000 ;; up again here.
8002 (define_split
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))
8011    (set (match_dup 0) 
8012         (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
8013                          (match_dup 4)
8014                          (match_dup 5)))]
8015   "
8017   enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
8018                                            operands[3]);
8020   operands[6] = gen_rtx_REG (mode, 24);
8021   operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
8025 (define_split
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" "")
8031                          (not:SI
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))
8036    (set (match_dup 0) 
8037         (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
8038                          (match_dup 4)
8039                          (not:SI (match_dup 5))))]
8040   "
8042   enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
8043                                            operands[3]);
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")
8055                          (not:SI
8056                           (match_operand:SI 2 "s_register_operand" "r,r"))))]
8057   "TARGET_ARM"
8058   "@
8059    mvn%D4\\t%0, %2
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")
8070                          (const_int 1)
8071                          (match_operand:SI 2 "const_int_operand" "n")))]
8072   "TARGET_ARM"
8073   "*
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")
8083         (not:SI
8084          (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
8085                           (const_int 1)
8086                           (match_operand:SI 2 "const_int_operand" "n"))))]
8087   "TARGET_ARM"
8088   "*
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 ...)
8099 ;; expressions.
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))])]
8104   "TARGET_ARM"
8105   "*
8107   extern int lr_save_eliminated;
8108   int num_saves = XVECLEN (operands[2], 0);
8109      
8110   if (lr_save_eliminated)
8111     {
8112       if (num_saves > 1)
8113         abort ();
8114     }
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);
8119   else
8120     {
8121       int i;
8122       char pattern[100];
8124       if (lr_save_eliminated)
8125         abort ();
8127       strcpy (pattern, \"stmfd\\t%m0!, {%1\");
8128                        
8129       for (i = 1; i < num_saves; i++)
8130         {
8131           strcat (pattern, \", %|\");
8132           strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
8133                                               0))]);
8134         }
8135         
8136       strcat (pattern, \"}\");
8137       output_asm_insn (pattern, operands);
8138     }
8139   
8140   return \"\";
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))])]
8149   "TARGET_ARM"
8150   "*
8152   char pattern[100];
8154   sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
8155   output_asm_insn (pattern, operands);
8156   return \"\";
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)]
8164   "TARGET_EITHER"
8165   "*
8166   assemble_align (32);
8167   return \"\";
8168   "
8171 (define_insn "consttable_end"
8172   [(unspec_volatile [(const_int 0)] 3)]
8173   "TARGET_EITHER"
8174   "*
8175   making_const_table = FALSE;
8176   return \"\";
8177   "
8180 (define_insn "consttable_1"
8181   [(unspec_volatile [(match_operand 0 "" "")] 4)]
8182   "TARGET_THUMB"
8183   "*
8184   making_const_table = TRUE;
8185   assemble_integer (operands[0], 1, 1);
8186   assemble_zeros (3);
8187   return \"\";
8188   "
8189   [(set_attr "length" "4")]
8192 (define_insn "consttable_2"
8193   [(unspec_volatile [(match_operand 0 "" "")] 5)]
8194   "TARGET_THUMB"
8195   "*
8196   making_const_table = TRUE;
8197   assemble_integer (operands[0], 2, 1);
8198   assemble_zeros (2);
8199   return \"\";
8200   "
8201   [(set_attr "length" "4")]
8204 (define_insn "consttable_4"
8205   [(unspec_volatile [(match_operand 0 "" "")] 6)]
8206   "TARGET_EITHER"
8207   "*
8208   {
8209     making_const_table = TRUE;
8210     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8211       {
8212       case MODE_FLOAT:
8213       {
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]));
8217         break;
8218       }
8219       default:
8220         assemble_integer (operands[0], 4, 1);
8221         break;
8222       }
8223     return \"\";
8224   }"
8225   [(set_attr "length" "4")]
8228 (define_insn "consttable_8"
8229   [(unspec_volatile [(match_operand 0 "" "")] 7)]
8230   "TARGET_EITHER"
8231   "*
8232   {
8233     making_const_table = TRUE;
8234     switch (GET_MODE_CLASS (GET_MODE (operands[0])))
8235       {
8236        case MODE_FLOAT:
8237         {
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]));
8241           break;
8242         }
8243       default:
8244         assemble_integer (operands[0], 8, 1);
8245         break;
8246       }
8247     return \"\";
8248   }"
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 "" "")))]
8257   "TARGET_THUMB"
8258   "mov  pc, %0"
8259   [(set_attr "length" "2")]