Apply ARM/Linux patches.
[gcc.git] / gcc / config / arm / arm.md
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).
6
7 ;; This file is part of GNU CC.
8
9 ;; GNU CC is free software; you can redistribute it and/or modify
10 ;; it under the terms of the GNU General Public License as published by
11 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; any later version.
13
14 ;; GNU CC is distributed in the hope that it will be useful,
15 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
16 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 ;; GNU General Public License for more details.
18
19 ;; You should have received a copy of the GNU General Public License
20 ;; along with GNU CC; see the file COPYING. If not, write to
21 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
22 ;; Boston, MA 02111-1307, USA.
23
24 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
25
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)
29 \f
30 ;; UNSPEC Usage:
31 ;; 0 `sin' operation: operand 0 is the result, operand 1 the parameter,
32 ;; the mode is MODE_FLOAT
33 ;; 1 `cos' operation: operand 0 is the result, operand 1 the parameter,
34 ;; the mode is MODE_FLOAT
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.
40 \f
41 ;; Attributes
42
43 ; PROG_MODE attribute is used to determine whether condition codes are
44 ; clobbered by a call insn: they are if in prog32 mode. This is controlled
45 ; by the -mapcs-{32,26} flag, and possibly the -mcpu=... option.
46 (define_attr "prog_mode" "prog26,prog32" (const (symbol_ref "arm_prog_mode")))
47
48 (define_attr "is_strongarm" "no,yes" (const (symbol_ref "arm_is_strong")))
49
50 ; Floating Point Unit. If we only have floating point emulation, then there
51 ; is no point in scheduling the floating point insns. (Well, for best
52 ; performance we should try and group them together).
53
54 (define_attr "fpu" "fpa,fpe2,fpe3" (const (symbol_ref "arm_fpu_attr")))
55
56 ; LENGTH of an instruction (in bytes)
57 (define_attr "length" "" (const_int 4))
58
59 ; An assembler sequence may clobber the condition codes without us knowing
60 (define_asm_attributes
61 [(set_attr "conds" "clob")
62 (set_attr "length" "4")])
63
64 ; TYPE attribute is used to detect floating point instructions which, if
65 ; running on a co-processor can run in parallel with other, basic instructions
66 ; If write-buffer scheduling is enabled then it can also be used in the
67 ; scheduling of writes.
68
69 ; Classification of each insn
70 ; normal any data instruction that doesn't hit memory or fp regs
71 ; mult a multiply instruction
72 ; block blockage insn, this blocks all functional units
73 ; float a floating point arithmetic operation (subject to expansion)
74 ; fdivx XFmode floating point division
75 ; fdivd DFmode floating point division
76 ; fdivs SFmode floating point division
77 ; fmul Floating point multiply
78 ; ffmul Fast floating point multiply
79 ; farith Floating point arithmetic (4 cycle)
80 ; ffarith Fast floating point arithmetic (2 cycle)
81 ; float_em a floating point arithmetic operation that is normally emulated
82 ; even on a machine with an fpa.
83 ; f_load a floating point load from memory
84 ; f_store a floating point store to memory
85 ; f_mem_r a transfer of a floating point register to a real reg via mem
86 ; r_mem_f the reverse of f_mem_r
87 ; f_2_r fast transfer float to arm (no memory needed)
88 ; r_2_f fast transfer arm to float
89 ; call a subroutine call
90 ; load any load from memory
91 ; store1 store 1 word to memory from arm registers
92 ; store2 store 2 words
93 ; store3 store 3 words
94 ; store4 store 4 words
95 ;
96 (define_attr "type"
97 "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"
98 (const_string "normal"))
99
100 ; Load scheduling, set from the arm_ld_sched variable
101 ; initialised by arm_override_options()
102 (define_attr "ldsched" "no,yes" (const (symbol_ref "arm_ld_sched")))
103
104 ; condition codes: this one is used by final_prescan_insn to speed up
105 ; conditionalizing instructions. It saves having to scan the rtl to see if
106 ; it uses or alters the condition codes.
107
108 ; USE means that the condition codes are used by the insn in the process of
109 ; outputting code, this means (at present) that we can't use the insn in
110 ; inlined branches
111
112 ; SET means that the purpose of the insn is to set the condition codes in a
113 ; well defined manner.
114
115 ; CLOB means that the condition codes are altered in an undefined manner, if
116 ; they are altered at all
117
118 ; JUMP_CLOB is used when the conditions are not defined if a branch is taken,
119 ; but are if the branch wasn't taken; the effect is to limit the branch
120 ; elimination scanning.
121
122 ; NOCOND means that the condition codes are neither altered nor affect the
123 ; output of this insn
124
125 (define_attr "conds" "use,set,clob,jump_clob,nocond"
126 (if_then_else (eq_attr "type" "call")
127 (if_then_else (eq_attr "prog_mode" "prog32")
128 (const_string "clob") (const_string "nocond"))
129 (const_string "nocond")))
130
131 ; Only model the write buffer for ARM6 and ARM7. Earlier processors don't
132 ; have one. Later ones, such as StrongARM, have write-back caches, so don't
133 ; suffer blockages enough to warrent modelling this (and it can adversely
134 ; affect the schedule).
135 (define_attr "model_wbuf" "no,yes" (const (symbol_ref "arm_is_6_or_7")))
136
137 (define_attr "write_conflict" "no,yes"
138 (if_then_else (eq_attr "type"
139 "block,float_em,f_load,f_store,f_mem_r,r_mem_f,call,load")
140 (const_string "yes")
141 (const_string "no")))
142
143 (define_attr "core_cycles" "single,multi"
144 (if_then_else (eq_attr "type"
145 "normal,float,fdivx,fdivd,fdivs,fmul,ffmul,farith,ffarith")
146 (const_string "single")
147 (const_string "multi")))
148
149 ; The write buffer on some of the arm6 processors is hard to model exactly.
150 ; There is room in the buffer for up to two addresses and up to eight words
151 ; of memory, but the two needn't be split evenly. When writing the two
152 ; addresses are fully pipelined. However, a read from memory that is not
153 ; currently in the cache will block until the writes have completed.
154 ; It is normally the case that FCLK and MCLK will be in the ratio 2:1, so
155 ; writes will take 2 FCLK cycles per word, if FCLK and MCLK are asynchronous
156 ; (they aren't allowed to be at present) then there is a startup cost of 1MCLK
157 ; cycle to add as well.
158
159 ;; (define_function_unit {name} {num-units} {n-users} {test}
160 ;; {ready-delay} {issue-delay} [{conflict-list}])
161 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
162 (eq_attr "type" "fdivx")) 71 69)
163
164 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
165 (eq_attr "type" "fdivd")) 59 57)
166
167 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
168 (eq_attr "type" "fdivs")) 31 29)
169
170 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
171 (eq_attr "type" "fmul")) 9 7)
172
173 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
174 (eq_attr "type" "ffmul")) 6 4)
175
176 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
177 (eq_attr "type" "farith")) 4 2)
178
179 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
180 (eq_attr "type" "ffarith")) 2 2)
181
182 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
183 (eq_attr "type" "r_2_f")) 5 3)
184
185 (define_function_unit "fpa" 1 0 (and (eq_attr "fpu" "fpa")
186 (eq_attr "type" "f_2_r")) 1 2)
187
188 ;; The fpa10 doesn't really have a memory read unit, but it can start to
189 ;; speculatively execute the instruction in the pipeline, provided the data
190 ;; is already loaded, so pretend reads have a delay of 2 (and that the
191 ;; pipeline is infinite.
192
193 (define_function_unit "fpa_mem" 1 0 (and (eq_attr "fpu" "fpa")
194 (eq_attr "type" "f_load")) 3 1)
195
196 ;;--------------------------------------------------------------------
197 ;; Write buffer
198 ;;--------------------------------------------------------------------
199 ;; Strictly we should model a 4-deep write buffer for ARM7xx based chips
200 (define_function_unit "write_buf" 1 2
201 (and (eq_attr "model_wbuf" "yes")
202 (eq_attr "type" "store1,r_mem_f")) 5 3)
203 (define_function_unit "write_buf" 1 2
204 (and (eq_attr "model_wbuf" "yes")
205 (eq_attr "type" "store2")) 7 4)
206 (define_function_unit "write_buf" 1 2
207 (and (eq_attr "model_wbuf" "yes")
208 (eq_attr "type" "store3")) 9 5)
209 (define_function_unit "write_buf" 1 2
210 (and (eq_attr "model_wbuf" "yes")
211 (eq_attr "type" "store4")) 11 6)
212
213 ;;--------------------------------------------------------------------
214 ;; Write blockage unit
215 ;;--------------------------------------------------------------------
216 ;; The write_blockage unit models (partially), the fact that reads will stall
217 ;; until the write buffer empties.
218 ;; The f_mem_r and r_mem_f could also block, but they are to the stack,
219 ;; so we don't model them here
220 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
221 (eq_attr "type" "store1")) 5 5
222 [(eq_attr "write_conflict" "yes")])
223 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
224 (eq_attr "type" "store2")) 7 7
225 [(eq_attr "write_conflict" "yes")])
226 (define_function_unit "write_blockage" 1 0 (and (eq_attr "model_wbuf" "yes")
227 (eq_attr "type" "store3")) 9 9
228 [(eq_attr "write_conflict" "yes")])
229 (define_function_unit "write_blockage" 1 0
230 (and (eq_attr "model_wbuf" "yes") (eq_attr "type" "store4")) 11 11
231 [(eq_attr "write_conflict" "yes")])
232 (define_function_unit "write_blockage" 1 0
233 (and (eq_attr "model_wbuf" "yes")
234 (eq_attr "write_conflict" "yes")) 1 1)
235
236 ;;--------------------------------------------------------------------
237 ;; Core unit
238 ;;--------------------------------------------------------------------
239 ;; Everything must spend at least one cycle in the core unit
240 (define_function_unit "core" 1 0
241 (and (eq_attr "ldsched" "yes") (eq_attr "type" "store1")) 1 1)
242
243 (define_function_unit "core" 1 0
244 (and (eq_attr "ldsched" "yes") (eq_attr "type" "load")) 2 1)
245
246 (define_function_unit "core" 1 0
247 (and (eq_attr "ldsched" "!yes") (eq_attr "type" "load,store1")) 2 2)
248
249 (define_function_unit "core" 1 0
250 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_load")) 3 3)
251
252 (define_function_unit "core" 1 0
253 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_store")) 4 4)
254
255 (define_function_unit "core" 1 0
256 (and (eq_attr "fpu" "fpa") (eq_attr "type" "r_mem_f")) 6 6)
257
258 (define_function_unit "core" 1 0
259 (and (eq_attr "fpu" "fpa") (eq_attr "type" "f_mem_r")) 7 7)
260
261 (define_function_unit "core" 1 0
262 (and (eq_attr "ldsched" "no") (eq_attr "type" "mult")) 16 16)
263
264 (define_function_unit "core" 1 0
265 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "no"))
266 (eq_attr "type" "mult")) 4 4)
267
268 (define_function_unit "core" 1 0
269 (and (and (eq_attr "ldsched" "yes") (eq_attr "is_strongarm" "yes"))
270 (eq_attr "type" "mult")) 3 2)
271
272 (define_function_unit "core" 1 0 (eq_attr "type" "store2") 3 3)
273
274 (define_function_unit "core" 1 0 (eq_attr "type" "store3") 4 4)
275
276 (define_function_unit "core" 1 0 (eq_attr "type" "store4") 5 5)
277 \f
278 ;; Note: For DImode insns, there is normally no reason why operands should
279 ;; not be in the same register, what we don't want is for something being
280 ;; written to partially overlap something that is an input.
281
282 ;; Addition insns.
283
284 (define_insn "adddi3"
285 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
286 (plus:DI (match_operand:DI 1 "s_register_operand" "%0,0")
287 (match_operand:DI 2 "s_register_operand" "r,0")))
288 (clobber (reg:CC 24))]
289 ""
290 "adds\\t%Q0, %Q1, %Q2\;adc\\t%R0, %R1, %R2"
291 [(set_attr "conds" "clob")
292 (set_attr "length" "8")])
293
294 (define_insn "*adddi_sesidi_di"
295 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
296 (plus:DI (sign_extend:DI
297 (match_operand:SI 2 "s_register_operand" "r,r"))
298 (match_operand:DI 1 "s_register_operand" "r,0")))
299 (clobber (reg:CC 24))]
300 ""
301 "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, %2, asr #31"
302 [(set_attr "conds" "clob")
303 (set_attr "length" "8")])
304
305 (define_insn "*adddi_zesidi_di"
306 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
307 (plus:DI (zero_extend:DI
308 (match_operand:SI 2 "s_register_operand" "r,r"))
309 (match_operand:DI 1 "s_register_operand" "r,0")))
310 (clobber (reg:CC 24))]
311 ""
312 "adds\\t%Q0, %Q1, %2\;adc\\t%R0, %R1, #0"
313 [(set_attr "conds" "clob")
314 (set_attr "length" "8")])
315
316 (define_expand "addsi3"
317 [(set (match_operand:SI 0 "s_register_operand" "")
318 (plus:SI (match_operand:SI 1 "s_register_operand" "")
319 (match_operand:SI 2 "reg_or_int_operand" "")))]
320 ""
321 "
322 if (GET_CODE (operands[2]) == CONST_INT)
323 {
324 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
325 operands[1],
326 (reload_in_progress || reload_completed ? 0
327 : preserve_subexpressions_p ()));
328 DONE;
329 }
330 ")
331
332 (define_split
333 [(set (match_operand:SI 0 "s_register_operand" "")
334 (plus:SI (match_operand:SI 1 "s_register_operand" "")
335 (match_operand:SI 2 "const_int_operand" "")))]
336 "! (const_ok_for_arm (INTVAL (operands[2]))
337 || const_ok_for_arm (-INTVAL (operands[2])))"
338 [(clobber (const_int 0))]
339 "
340 arm_split_constant (PLUS, SImode, INTVAL (operands[2]), operands[0],
341 operands[1], 0);
342 DONE;
343 ")
344
345 (define_insn "*addsi3_insn"
346 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
347 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
348 (match_operand:SI 2 "reg_or_int_operand" "rI,L,?n")))]
349 ""
350 "@
351 add%?\\t%0, %1, %2
352 sub%?\\t%0, %1, #%n2
353 #"
354 [(set_attr "length" "4,4,16")])
355
356 (define_insn "*addsi3_compare0"
357 [(set (reg:CC_NOOV 24)
358 (compare:CC_NOOV
359 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
360 (match_operand:SI 2 "arm_add_operand" "rI,L"))
361 (const_int 0)))
362 (set (match_operand:SI 0 "s_register_operand" "=r,r")
363 (plus:SI (match_dup 1) (match_dup 2)))]
364 ""
365 "@
366 add%?s\\t%0, %1, %2
367 sub%?s\\t%0, %1, #%n2"
368 [(set_attr "conds" "set")])
369
370 (define_insn "*addsi3_compare0_scratch"
371 [(set (reg:CC_NOOV 24)
372 (compare:CC_NOOV
373 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
374 (match_operand:SI 1 "arm_add_operand" "rI,L"))
375 (const_int 0)))]
376 ""
377 "@
378 cmn%?\\t%0, %1
379 cmp%?\\t%0, #%n1"
380 [(set_attr "conds" "set")])
381
382 ;; The next four insns work because they compare the result with one of
383 ;; the operands, and we know that the use of the condition code is
384 ;; either GEU or LTU, so we can use the carry flag from the addition
385 ;; instead of doing the compare a second time.
386 (define_insn "*addsi3_compare_op1"
387 [(set (reg:CC_C 24)
388 (compare:CC_C
389 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
390 (match_operand:SI 2 "arm_add_operand" "rI,L"))
391 (match_dup 1)))
392 (set (match_operand:SI 0 "s_register_operand" "=r,r")
393 (plus:SI (match_dup 1) (match_dup 2)))]
394 ""
395 "@
396 add%?s\\t%0, %1, %2
397 sub%?s\\t%0, %1, #%n2"
398 [(set_attr "conds" "set")])
399
400 (define_insn "*addsi3_compare_op2"
401 [(set (reg:CC_C 24)
402 (compare:CC_C
403 (plus:SI (match_operand:SI 1 "s_register_operand" "r,r")
404 (match_operand:SI 2 "arm_add_operand" "rI,L"))
405 (match_dup 2)))
406 (set (match_operand:SI 0 "s_register_operand" "=r,r")
407 (plus:SI (match_dup 1) (match_dup 2)))]
408 ""
409 "@
410 add%?s\\t%0, %1, %2
411 sub%?s\\t%0, %1, #%n2"
412 [(set_attr "conds" "set")])
413
414 (define_insn "*compare_addsi2_op0"
415 [(set (reg:CC_C 24)
416 (compare:CC_C
417 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
418 (match_operand:SI 1 "arm_add_operand" "rI,L"))
419 (match_dup 0)))]
420 ""
421 "@
422 cmn%?\\t%0, %1
423 cmp%?\\t%0, #%n1"
424 [(set_attr "conds" "set")])
425
426 (define_insn "*compare_addsi2_op1"
427 [(set (reg:CC_C 24)
428 (compare:CC_C
429 (plus:SI (match_operand:SI 0 "s_register_operand" "r,r")
430 (match_operand:SI 1 "arm_add_operand" "rI,L"))
431 (match_dup 1)))]
432 ""
433 "@
434 cmn%?\\t%0, %1
435 cmp%?\\t%0, #%n1"
436 [(set_attr "conds" "set")])
437
438 (define_insn "*addsi3_carryin"
439 [(set (match_operand:SI 0 "s_register_operand" "=r")
440 (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
441 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
442 (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
443 ""
444 "adc%?\\t%0, %1, %2"
445 [(set_attr "conds" "use")])
446
447 (define_insn "*addsi3_carryin_alt1"
448 [(set (match_operand:SI 0 "s_register_operand" "=r")
449 (plus:SI (plus:SI (match_operand:SI 1 "s_register_operand" "r")
450 (match_operand:SI 2 "arm_rhs_operand" "rI"))
451 (ltu:SI (reg:CC_C 24) (const_int 0))))]
452 ""
453 "adc%?\\t%0, %1, %2"
454 [(set_attr "conds" "use")])
455
456 (define_insn "*addsi3_carryin_alt2"
457 [(set (match_operand:SI 0 "s_register_operand" "=r")
458 (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
459 (match_operand:SI 1 "s_register_operand" "r"))
460 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
461 ""
462 "adc%?\\t%0, %1, %2"
463 [(set_attr "conds" "use")])
464
465 (define_insn "*addsi3_carryin_alt3"
466 [(set (match_operand:SI 0 "s_register_operand" "=r")
467 (plus:SI (plus:SI (ltu:SI (reg:CC_C 24) (const_int 0))
468 (match_operand:SI 2 "arm_rhs_operand" "rI"))
469 (match_operand:SI 1 "s_register_operand" "r")))]
470 ""
471 "adc%?\\t%0, %1, %2"
472 [(set_attr "conds" "use")])
473
474 (define_insn "incscc"
475 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
476 (plus:SI (match_operator:SI 2 "comparison_operator"
477 [(match_operand 3 "cc_register" "") (const_int 0)])
478 (match_operand:SI 1 "s_register_operand" "0,?r")))]
479 ""
480 "@
481 add%d2\\t%0, %1, #1
482 mov%D2\\t%0, %1\;add%d2\\t%0, %1, #1"
483 [(set_attr "conds" "use")
484 (set_attr "length" "4,8")])
485
486 ; If a constant is too big to fit in a single instruction then the constant
487 ; will be pre-loaded into a register taking at least two insns, we might be
488 ; able to merge it with an add, but it depends on the exact value.
489
490 (define_split
491 [(set (match_operand:SI 0 "s_register_operand" "=r")
492 (plus:SI (match_operand:SI 1 "s_register_operand" "r")
493 (match_operand:SI 2 "const_int_operand" "n")))]
494 "!(const_ok_for_arm (INTVAL (operands[2]))
495 || const_ok_for_arm (-INTVAL (operands[2])))"
496 [(set (match_dup 0) (plus:SI (match_dup 1) (match_dup 2)))
497 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 3)))]
498 "
499 {
500 unsigned int val = (unsigned) INTVAL (operands[2]);
501 int i;
502 unsigned int temp;
503
504 /* this code is similar to the approach followed in movsi, but it must
505 generate exactly two insns */
506
507 for (i = 30; i >= 0; i -= 2)
508 {
509 if (val & (3 << i))
510 {
511 i -= 6;
512 if (i < 0) i = 0;
513 if (const_ok_for_arm (temp = (val & ~(255 << i))))
514 {
515 val &= 255 << i;
516 break;
517 }
518 /* we might be able to do this as (larger number - small number) */
519 temp = ((val >> i) & 255) + 1;
520 if (temp > 255 && i < 24)
521 {
522 i += 2;
523 temp = ((val >> i) & 255) + 1;
524 }
525 if (const_ok_for_arm ((temp << i) - val))
526 {
527 i = temp << i;
528 temp = (unsigned) - (int) (i - val);
529 val = i;
530 break;
531 }
532 FAIL;
533 }
534 }
535 /* if we got here, we have found a way of doing it in two instructions.
536 the two constants are in val and temp */
537 operands[2] = GEN_INT ((int)val);
538 operands[3] = GEN_INT ((int)temp);
539 }
540 ")
541
542 (define_insn "addsf3"
543 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
544 (plus:SF (match_operand:SF 1 "s_register_operand" "f,f")
545 (match_operand:SF 2 "fpu_add_operand" "fG,H")))]
546 "TARGET_HARD_FLOAT"
547 "@
548 adf%?s\\t%0, %1, %2
549 suf%?s\\t%0, %1, #%N2"
550 [(set_attr "type" "farith")])
551
552 (define_insn "adddf3"
553 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
554 (plus:DF (match_operand:DF 1 "s_register_operand" "f,f")
555 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
556 "TARGET_HARD_FLOAT"
557 "@
558 adf%?d\\t%0, %1, %2
559 suf%?d\\t%0, %1, #%N2"
560 [(set_attr "type" "farith")])
561
562 (define_insn "*adddf_df_esfdf"
563 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
564 (plus:DF (float_extend:DF
565 (match_operand:SF 1 "s_register_operand" "f,f"))
566 (match_operand:DF 2 "fpu_add_operand" "fG,H")))]
567 "TARGET_HARD_FLOAT"
568 "@
569 adf%?d\\t%0, %1, %2
570 suf%?d\\t%0, %1, #%N2"
571 [(set_attr "type" "farith")])
572
573 (define_insn "*adddf_df_esfdf"
574 [(set (match_operand:DF 0 "s_register_operand" "=f")
575 (plus:DF (match_operand:DF 1 "s_register_operand" "f")
576 (float_extend:DF
577 (match_operand:SF 2 "s_register_operand" "f"))))]
578 "TARGET_HARD_FLOAT"
579 "adf%?d\\t%0, %1, %2"
580 [(set_attr "type" "farith")])
581
582 (define_insn "*adddf_esfdf_esfdf"
583 [(set (match_operand:DF 0 "s_register_operand" "=f")
584 (plus:DF (float_extend:DF
585 (match_operand:SF 1 "s_register_operand" "f"))
586 (float_extend:DF
587 (match_operand:SF 2 "s_register_operand" "f"))))]
588 "TARGET_HARD_FLOAT"
589 "adf%?d\\t%0, %1, %2"
590 [(set_attr "type" "farith")])
591
592 (define_insn "addxf3"
593 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
594 (plus:XF (match_operand:XF 1 "s_register_operand" "f,f")
595 (match_operand:XF 2 "fpu_add_operand" "fG,H")))]
596 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
597 "@
598 adf%?e\\t%0, %1, %2
599 suf%?e\\t%0, %1, #%N2"
600 [(set_attr "type" "farith")])
601
602 (define_insn "subdi3"
603 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r,&r")
604 (minus:DI (match_operand:DI 1 "s_register_operand" "0,r,0")
605 (match_operand:DI 2 "s_register_operand" "r,0,0")))
606 (clobber (reg:CC 24))]
607 ""
608 "subs\\t%Q0, %Q1, %Q2\;sbc\\t%R0, %R1, %R2"
609 [(set_attr "conds" "clob")
610 (set_attr "length" "8")])
611
612 (define_insn "*subdi_di_zesidi"
613 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
614 (minus:DI (match_operand:DI 1 "s_register_operand" "?r,0")
615 (zero_extend:DI
616 (match_operand:SI 2 "s_register_operand" "r,r"))))
617 (clobber (reg:CC 24))]
618 ""
619 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, #0"
620 [(set_attr "conds" "clob")
621 (set_attr "length" "8")])
622
623 (define_insn "*subdi_di_sesidi"
624 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
625 (minus:DI (match_operand:DI 1 "s_register_operand" "r,0")
626 (sign_extend:DI
627 (match_operand:SI 2 "s_register_operand" "r,r"))))
628 (clobber (reg:CC 24))]
629 ""
630 "subs\\t%Q0, %Q1, %2\;sbc\\t%R0, %R1, %2, asr #31"
631 [(set_attr "conds" "clob")
632 (set_attr "length" "8")])
633
634 (define_insn "*subdi_zesidi_di"
635 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
636 (minus:DI (zero_extend:DI
637 (match_operand:SI 2 "s_register_operand" "r,r"))
638 (match_operand:DI 1 "s_register_operand" "?r,0")))
639 (clobber (reg:CC 24))]
640 ""
641 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, #0"
642 [(set_attr "conds" "clob")
643 (set_attr "length" "8")])
644
645 (define_insn "*subdi_sesidi_di"
646 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
647 (minus:DI (sign_extend:DI
648 (match_operand:SI 2 "s_register_operand" "r,r"))
649 (match_operand:DI 1 "s_register_operand" "?r,0")))
650 (clobber (reg:CC 24))]
651 ""
652 "rsbs\\t%Q0, %Q1, %2\;rsc\\t%R0, %R1, %2, asr #31"
653 [(set_attr "conds" "clob")
654 (set_attr "length" "8")])
655
656 (define_insn "*subdi_zesidi_zesidi"
657 [(set (match_operand:DI 0 "s_register_operand" "=r")
658 (minus:DI (zero_extend:DI
659 (match_operand:SI 1 "s_register_operand" "r"))
660 (zero_extend:DI
661 (match_operand:SI 2 "s_register_operand" "r"))))
662 (clobber (reg:CC 24))]
663 ""
664 "subs\\t%Q0, %1, %2\;rsc\\t%R0, %1, %1"
665 [(set_attr "conds" "clob")
666 (set_attr "length" "8")])
667
668 (define_expand "subsi3"
669 [(set (match_operand:SI 0 "s_register_operand" "")
670 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "")
671 (match_operand:SI 2 "s_register_operand" "")))]
672 ""
673 "
674 if (GET_CODE (operands[1]) == CONST_INT)
675 {
676 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
677 operands[2],
678 (reload_in_progress || reload_completed ? 0
679 : preserve_subexpressions_p ()));
680 DONE;
681 }
682 ")
683
684 (define_insn "*subsi3_insn"
685 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
686 (minus:SI (match_operand:SI 1 "reg_or_int_operand" "rI,?n")
687 (match_operand:SI 2 "s_register_operand" "r,r")))]
688 ""
689 "@
690 rsb%?\\t%0, %2, %1
691 #"
692 [(set_attr "length" "4,16")])
693
694 (define_split
695 [(set (match_operand:SI 0 "s_register_operand" "")
696 (minus:SI (match_operand:SI 1 "const_int_operand" "")
697 (match_operand:SI 2 "s_register_operand" "")))]
698 "! const_ok_for_arm (INTVAL (operands[1]))"
699 [(clobber (const_int 0))]
700 "
701 arm_split_constant (MINUS, SImode, INTVAL (operands[1]), operands[0],
702 operands[2], 0);
703 DONE;
704 ")
705
706 (define_insn "*subsi3_compare0"
707 [(set (reg:CC_NOOV 24)
708 (compare:CC_NOOV (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,I")
709 (match_operand:SI 2 "arm_rhs_operand" "rI,r"))
710 (const_int 0)))
711 (set (match_operand:SI 0 "s_register_operand" "=r,r")
712 (minus:SI (match_dup 1) (match_dup 2)))]
713 ""
714 "@
715 sub%?s\\t%0, %1, %2
716 rsb%?s\\t%0, %2, %1"
717 [(set_attr "conds" "set")])
718
719 (define_insn "decscc"
720 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
721 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
722 (match_operator:SI 2 "comparison_operator"
723 [(match_operand 3 "cc_register" "") (const_int 0)])))]
724 ""
725 "@
726 sub%d2\\t%0, %1, #1
727 mov%D2\\t%0, %1\;sub%d2\\t%0, %1, #1"
728 [(set_attr "conds" "use")
729 (set_attr "length" "*,8")])
730
731 (define_insn "subsf3"
732 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
733 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
734 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
735 "TARGET_HARD_FLOAT"
736 "@
737 suf%?s\\t%0, %1, %2
738 rsf%?s\\t%0, %2, %1"
739 [(set_attr "type" "farith")])
740
741 (define_insn "subdf3"
742 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
743 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
744 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
745 "TARGET_HARD_FLOAT"
746 "@
747 suf%?d\\t%0, %1, %2
748 rsf%?d\\t%0, %2, %1"
749 [(set_attr "type" "farith")])
750
751 (define_insn "*subdf_esfdf_df"
752 [(set (match_operand:DF 0 "s_register_operand" "=f")
753 (minus:DF (float_extend:DF
754 (match_operand:SF 1 "s_register_operand" "f"))
755 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
756 "TARGET_HARD_FLOAT"
757 "suf%?d\\t%0, %1, %2"
758 [(set_attr "type" "farith")])
759
760 (define_insn "*subdf_df_esfdf"
761 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
762 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
763 (float_extend:DF
764 (match_operand:SF 2 "s_register_operand" "f,f"))))]
765 "TARGET_HARD_FLOAT"
766 "@
767 suf%?d\\t%0, %1, %2
768 rsf%?d\\t%0, %2, %1"
769 [(set_attr "type" "farith")])
770
771 (define_insn "*subdf_esfdf_esfdf"
772 [(set (match_operand:DF 0 "s_register_operand" "=f")
773 (minus:DF (float_extend:DF
774 (match_operand:SF 1 "s_register_operand" "f"))
775 (float_extend:DF
776 (match_operand:SF 2 "s_register_operand" "f"))))]
777 "TARGET_HARD_FLOAT"
778 "suf%?d\\t%0, %1, %2"
779 [(set_attr "type" "farith")])
780
781 (define_insn "subxf3"
782 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
783 (minus:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
784 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
785 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
786 "@
787 suf%?e\\t%0, %1, %2
788 rsf%?e\\t%0, %2, %1"
789 [(set_attr "type" "farith")])
790 \f
791 ;; Multiplication insns
792
793 ;; Use `&' and then `0' to prevent the operands 0 and 1 being the same
794 (define_insn "mulsi3"
795 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
796 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r")
797 (match_operand:SI 1 "s_register_operand" "%?r,0")))]
798 ""
799 "mul%?\\t%0, %2, %1"
800 [(set_attr "type" "mult")])
801
802 (define_insn "*mulsi3_compare0"
803 [(set (reg:CC_NOOV 24)
804 (compare:CC_NOOV (mult:SI
805 (match_operand:SI 2 "s_register_operand" "r,r")
806 (match_operand:SI 1 "s_register_operand" "%?r,0"))
807 (const_int 0)))
808 (set (match_operand:SI 0 "s_register_operand" "=&r,&r")
809 (mult:SI (match_dup 2) (match_dup 1)))]
810 ""
811 "mul%?s\\t%0, %2, %1"
812 [(set_attr "conds" "set")
813 (set_attr "type" "mult")])
814
815 (define_insn "*mulsi_compare0_scratch"
816 [(set (reg:CC_NOOV 24)
817 (compare:CC_NOOV (mult:SI
818 (match_operand:SI 2 "s_register_operand" "r,r")
819 (match_operand:SI 1 "s_register_operand" "%?r,0"))
820 (const_int 0)))
821 (clobber (match_scratch:SI 0 "=&r,&r"))]
822 ""
823 "mul%?s\\t%0, %2, %1"
824 [(set_attr "conds" "set")
825 (set_attr "type" "mult")])
826
827 ;; Unnamed templates to match MLA instruction.
828
829 (define_insn "*mulsi3addsi"
830 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
831 (plus:SI
832 (mult:SI (match_operand:SI 2 "s_register_operand" "r,r,r,r")
833 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
834 (match_operand:SI 3 "s_register_operand" "?r,r,0,0")))]
835 ""
836 "mla%?\\t%0, %2, %1, %3"
837 [(set_attr "type" "mult")])
838
839 (define_insn "*mulsi3addsi_compare0"
840 [(set (reg:CC_NOOV 24)
841 (compare:CC_NOOV (plus:SI
842 (mult:SI
843 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
844 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
845 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
846 (const_int 0)))
847 (set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r,&r")
848 (plus:SI (mult:SI (match_dup 2) (match_dup 1))
849 (match_dup 3)))]
850 ""
851 "mla%?s\\t%0, %2, %1, %3"
852 [(set_attr "conds" "set")
853 (set_attr "type" "mult")])
854
855 (define_insn "*mulsi3addsi_compare0_scratch"
856 [(set (reg:CC_NOOV 24)
857 (compare:CC_NOOV (plus:SI
858 (mult:SI
859 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
860 (match_operand:SI 1 "s_register_operand" "%r,0,r,0"))
861 (match_operand:SI 3 "s_register_operand" "?r,r,0,0"))
862 (const_int 0)))
863 (clobber (match_scratch:SI 0 "=&r,&r,&r,&r"))]
864 ""
865 "mla%?s\\t%0, %2, %1, %3"
866 [(set_attr "conds" "set")
867 (set_attr "type" "mult")])
868
869 (define_insn "mulsidi3"
870 [(set (match_operand:DI 0 "s_register_operand" "=&r")
871 (mult:DI (sign_extend:DI
872 (match_operand:SI 1 "s_register_operand" "%r"))
873 (sign_extend:DI
874 (match_operand:SI 2 "s_register_operand" "r"))))]
875 "arm_fast_multiply"
876 "smull%?\\t%Q0, %R0, %1, %2"
877 [(set_attr "type" "mult")])
878
879 (define_insn "umulsidi3"
880 [(set (match_operand:DI 0 "s_register_operand" "=&r")
881 (mult:DI (zero_extend:DI
882 (match_operand:SI 1 "s_register_operand" "%r"))
883 (zero_extend:DI
884 (match_operand:SI 2 "s_register_operand" "r"))))]
885 "arm_fast_multiply"
886 "umull%?\\t%Q0, %R0, %1, %2"
887 [(set_attr "type" "mult")])
888
889 (define_insn "smulsi3_highpart"
890 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
891 (truncate:SI
892 (lshiftrt:DI
893 (mult:DI (sign_extend:DI
894 (match_operand:SI 1 "s_register_operand" "%r,0"))
895 (sign_extend:DI
896 (match_operand:SI 2 "s_register_operand" "r,r")))
897 (const_int 32))))
898 (clobber (match_scratch:SI 3 "=&r,&r"))]
899 "arm_fast_multiply"
900 "smull%?\\t%3, %0, %2, %1"
901 [(set_attr "type" "mult")])
902
903 (define_insn "umulsi3_highpart"
904 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r")
905 (truncate:SI
906 (lshiftrt:DI
907 (mult:DI (zero_extend:DI
908 (match_operand:SI 1 "s_register_operand" "%r,0"))
909 (zero_extend:DI
910 (match_operand:SI 2 "s_register_operand" "r,r")))
911 (const_int 32))))
912 (clobber (match_scratch:SI 3 "=&r,&r"))]
913 "arm_fast_multiply"
914 "umull%?\\t%3, %0, %2, %1"
915 [(set_attr "type" "mult")])
916
917 (define_insn "mulsf3"
918 [(set (match_operand:SF 0 "s_register_operand" "=f")
919 (mult:SF (match_operand:SF 1 "s_register_operand" "f")
920 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
921 "TARGET_HARD_FLOAT"
922 "fml%?s\\t%0, %1, %2"
923 [(set_attr "type" "ffmul")])
924
925 (define_insn "muldf3"
926 [(set (match_operand:DF 0 "s_register_operand" "=f")
927 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
928 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
929 "TARGET_HARD_FLOAT"
930 "muf%?d\\t%0, %1, %2"
931 [(set_attr "type" "fmul")])
932
933 (define_insn "*muldf_esfdf_df"
934 [(set (match_operand:DF 0 "s_register_operand" "=f")
935 (mult:DF (float_extend:DF
936 (match_operand:SF 1 "s_register_operand" "f"))
937 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
938 "TARGET_HARD_FLOAT"
939 "muf%?d\\t%0, %1, %2"
940 [(set_attr "type" "fmul")])
941
942 (define_insn "*muldf_df_esfdf"
943 [(set (match_operand:DF 0 "s_register_operand" "=f")
944 (mult:DF (match_operand:DF 1 "s_register_operand" "f")
945 (float_extend:DF
946 (match_operand:SF 2 "s_register_operand" "f"))))]
947 "TARGET_HARD_FLOAT"
948 "muf%?d\\t%0, %1, %2"
949 [(set_attr "type" "fmul")])
950
951 (define_insn "*muldf_esfdf_esfdf"
952 [(set (match_operand:DF 0 "s_register_operand" "=f")
953 (mult:DF (float_extend:DF
954 (match_operand:SF 1 "s_register_operand" "f"))
955 (float_extend:DF
956 (match_operand:SF 2 "s_register_operand" "f"))))]
957 "TARGET_HARD_FLOAT"
958 "muf%?d\\t%0, %1, %2"
959 [(set_attr "type" "fmul")])
960
961 (define_insn "mulxf3"
962 [(set (match_operand:XF 0 "s_register_operand" "=f")
963 (mult:XF (match_operand:XF 1 "s_register_operand" "f")
964 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
965 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
966 "muf%?e\\t%0, %1, %2"
967 [(set_attr "type" "fmul")])
968 \f
969 ;; Division insns
970
971 (define_insn "divsf3"
972 [(set (match_operand:SF 0 "s_register_operand" "=f,f")
973 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
974 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
975 "TARGET_HARD_FLOAT"
976 "@
977 fdv%?s\\t%0, %1, %2
978 frd%?s\\t%0, %2, %1"
979 [(set_attr "type" "fdivs")])
980
981 (define_insn "divdf3"
982 [(set (match_operand:DF 0 "s_register_operand" "=f,f")
983 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
984 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
985 "TARGET_HARD_FLOAT"
986 "@
987 dvf%?d\\t%0, %1, %2
988 rdf%?d\\t%0, %2, %1"
989 [(set_attr "type" "fdivd")])
990
991 (define_insn "*divdf_esfdf_df"
992 [(set (match_operand:DF 0 "s_register_operand" "=f")
993 (div:DF (float_extend:DF
994 (match_operand:SF 1 "s_register_operand" "f"))
995 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
996 "TARGET_HARD_FLOAT"
997 "dvf%?d\\t%0, %1, %2"
998 [(set_attr "type" "fdivd")])
999
1000 (define_insn "*divdf_df_esfdf"
1001 [(set (match_operand:DF 0 "s_register_operand" "=f")
1002 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "fG")
1003 (float_extend:DF
1004 (match_operand:SF 2 "s_register_operand" "f"))))]
1005 "TARGET_HARD_FLOAT"
1006 "rdf%?d\\t%0, %2, %1"
1007 [(set_attr "type" "fdivd")])
1008
1009 (define_insn "*divdf_esfdf_esfdf"
1010 [(set (match_operand:DF 0 "s_register_operand" "=f")
1011 (div:DF (float_extend:DF
1012 (match_operand:SF 1 "s_register_operand" "f"))
1013 (float_extend:DF
1014 (match_operand:SF 2 "s_register_operand" "f"))))]
1015 "TARGET_HARD_FLOAT"
1016 "dvf%?d\\t%0, %1, %2"
1017 [(set_attr "type" "fdivd")])
1018
1019 (define_insn "divxf3"
1020 [(set (match_operand:XF 0 "s_register_operand" "=f,f")
1021 (div:XF (match_operand:XF 1 "fpu_rhs_operand" "f,G")
1022 (match_operand:XF 2 "fpu_rhs_operand" "fG,f")))]
1023 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1024 "@
1025 dvf%?e\\t%0, %1, %2
1026 rdf%?e\\t%0, %2, %1"
1027 [(set_attr "type" "fdivx")])
1028 \f
1029 ;; Modulo insns
1030
1031 (define_insn "modsf3"
1032 [(set (match_operand:SF 0 "s_register_operand" "=f")
1033 (mod:SF (match_operand:SF 1 "s_register_operand" "f")
1034 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
1035 "TARGET_HARD_FLOAT"
1036 "rmf%?s\\t%0, %1, %2"
1037 [(set_attr "type" "fdivs")])
1038
1039 (define_insn "moddf3"
1040 [(set (match_operand:DF 0 "s_register_operand" "=f")
1041 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1042 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1043 "TARGET_HARD_FLOAT"
1044 "rmf%?d\\t%0, %1, %2"
1045 [(set_attr "type" "fdivd")])
1046
1047 (define_insn "*moddf_esfdf_df"
1048 [(set (match_operand:DF 0 "s_register_operand" "=f")
1049 (mod:DF (float_extend:DF
1050 (match_operand:SF 1 "s_register_operand" "f"))
1051 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
1052 "TARGET_HARD_FLOAT"
1053 "rmf%?d\\t%0, %1, %2"
1054 [(set_attr "type" "fdivd")])
1055
1056 (define_insn "*moddf_df_esfdf"
1057 [(set (match_operand:DF 0 "s_register_operand" "=f")
1058 (mod:DF (match_operand:DF 1 "s_register_operand" "f")
1059 (float_extend:DF
1060 (match_operand:SF 2 "s_register_operand" "f"))))]
1061 "TARGET_HARD_FLOAT"
1062 "rmf%?d\\t%0, %1, %2"
1063 [(set_attr "type" "fdivd")])
1064
1065 (define_insn "*moddf_esfdf_esfdf"
1066 [(set (match_operand:DF 0 "s_register_operand" "=f")
1067 (mod:DF (float_extend:DF
1068 (match_operand:SF 1 "s_register_operand" "f"))
1069 (float_extend:DF
1070 (match_operand:SF 2 "s_register_operand" "f"))))]
1071 "TARGET_HARD_FLOAT"
1072 "rmf%?d\\t%0, %1, %2"
1073 [(set_attr "type" "fdivd")])
1074
1075 (define_insn "modxf3"
1076 [(set (match_operand:XF 0 "s_register_operand" "=f")
1077 (mod:XF (match_operand:XF 1 "s_register_operand" "f")
1078 (match_operand:XF 2 "fpu_rhs_operand" "fG")))]
1079 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1080 "rmf%?e\\t%0, %1, %2"
1081 [(set_attr "type" "fdivx")])
1082 \f
1083 ;; Boolean and,ior,xor insns
1084
1085 (define_insn "anddi3"
1086 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1087 (and:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1088 (match_operand:DI 2 "s_register_operand" "r,0")))]
1089 ""
1090 "and%?\\t%Q0, %Q1, %Q2\;and%?\\t%R0, %R1, %R2"
1091 [(set_attr "length" "8")])
1092
1093 (define_insn "*anddi_zesidi_di"
1094 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1095 (and:DI (zero_extend:DI
1096 (match_operand:SI 2 "s_register_operand" "r,r"))
1097 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1098 ""
1099 "and%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, #0"
1100 [(set_attr "length" "8")])
1101
1102 (define_insn "*anddi_sesdi_di"
1103 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1104 (and:DI (sign_extend:DI
1105 (match_operand:SI 2 "s_register_operand" "r,r"))
1106 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1107 ""
1108 "and%?\\t%Q0, %Q1, %2\;and%?\\t%R0, %R1, %2, asr #31"
1109 [(set_attr "length" "8")])
1110
1111 (define_expand "andsi3"
1112 [(set (match_operand:SI 0 "s_register_operand" "")
1113 (and:SI (match_operand:SI 1 "s_register_operand" "")
1114 (match_operand:SI 2 "reg_or_int_operand" "")))]
1115 ""
1116 "
1117 if (GET_CODE (operands[2]) == CONST_INT)
1118 {
1119 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1120 operands[1],
1121 (reload_in_progress || reload_completed
1122 ? 0 : preserve_subexpressions_p ()));
1123 DONE;
1124 }
1125 ")
1126
1127 (define_insn "*andsi3_insn"
1128 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1129 (and:SI (match_operand:SI 1 "s_register_operand" "r,r,r")
1130 (match_operand:SI 2 "reg_or_int_operand" "rI,K,?n")))]
1131 ""
1132 "@
1133 and%?\\t%0, %1, %2
1134 bic%?\\t%0, %1, #%B2
1135 #"
1136 [(set_attr "length" "4,4,16")])
1137
1138 (define_split
1139 [(set (match_operand:SI 0 "s_register_operand" "")
1140 (and:SI (match_operand:SI 1 "s_register_operand" "")
1141 (match_operand:SI 2 "const_int_operand" "")))]
1142 "! (const_ok_for_arm (INTVAL (operands[2]))
1143 || const_ok_for_arm (~ INTVAL (operands[2])))"
1144 [(clobber (const_int 0))]
1145 "
1146 arm_split_constant (AND, SImode, INTVAL (operands[2]), operands[0],
1147 operands[1], 0);
1148 DONE;
1149 ")
1150
1151 (define_insn "*andsi3_compare0"
1152 [(set (reg:CC_NOOV 24)
1153 (compare:CC_NOOV
1154 (and:SI (match_operand:SI 1 "s_register_operand" "r,r")
1155 (match_operand:SI 2 "arm_not_operand" "rI,K"))
1156 (const_int 0)))
1157 (set (match_operand:SI 0 "s_register_operand" "=r,r")
1158 (and:SI (match_dup 1) (match_dup 2)))]
1159 ""
1160 "@
1161 and%?s\\t%0, %1, %2
1162 bic%?s\\t%0, %1, #%B2"
1163 [(set_attr "conds" "set")])
1164
1165 (define_insn "*andsi3_compare0_scratch"
1166 [(set (reg:CC_NOOV 24)
1167 (compare:CC_NOOV
1168 (and:SI (match_operand:SI 0 "s_register_operand" "r,r")
1169 (match_operand:SI 1 "arm_not_operand" "rI,K"))
1170 (const_int 0)))
1171 (clobber (match_scratch:SI 3 "=X,r"))]
1172 ""
1173 "@
1174 tst%?\\t%0, %1
1175 bic%?s\\t%3, %0, #%B1"
1176 [(set_attr "conds" "set")])
1177
1178 (define_insn "*zeroextractsi_compare0_scratch"
1179 [(set (reg:CC_NOOV 24)
1180 (compare:CC_NOOV (zero_extract:SI
1181 (match_operand:SI 0 "s_register_operand" "r")
1182 (match_operand 1 "const_int_operand" "n")
1183 (match_operand 2 "const_int_operand" "n"))
1184 (const_int 0)))]
1185 "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) < 32
1186 && INTVAL (operands[1]) > 0
1187 && INTVAL (operands[1]) + (INTVAL (operands[2]) & 1) <= 8
1188 && INTVAL (operands[1]) + INTVAL (operands[2]) <= 32"
1189 "*
1190 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1191 << INTVAL (operands[2]));
1192 output_asm_insn (\"tst%?\\t%0, %1\", operands);
1193 return \"\";
1194 "
1195 [(set_attr "conds" "set")])
1196
1197 (define_insn "*zeroextractqi_compare0_scratch"
1198 [(set (reg:CC_NOOV 24)
1199 (compare:CC_NOOV (zero_extract:SI
1200 (match_operand:QI 0 "memory_operand" "m")
1201 (match_operand 1 "const_int_operand" "n")
1202 (match_operand 2 "const_int_operand" "n"))
1203 (const_int 0)))
1204 (clobber (match_scratch:QI 3 "=r"))]
1205 "INTVAL (operands[2]) >= 0 && INTVAL (operands[1]) > 0
1206 && ((INTVAL (operands[2]) + INTVAL (operands[1])) <= 8)"
1207 "*
1208 operands[1] = GEN_INT (((1 << INTVAL (operands[1])) - 1)
1209 << INTVAL (operands[2]));
1210 output_asm_insn (\"ldr%?b\\t%3, %0\", operands);
1211 output_asm_insn (\"tst%?\\t%3, %1\", operands);
1212 return \"\";
1213 "
1214 [(set_attr "conds" "set")
1215 (set_attr "length" "8")])
1216
1217 ;;; ??? This pattern is bogus. If operand3 has bits outside the range
1218 ;;; represented by the bitfield, then this will produce incorrect results.
1219 ;;; Somewhere, the value needs to be truncated. On targets like the m68k,
1220 ;;; which have a real bitfield insert instruction, the truncation happens
1221 ;;; in the bitfield insert instruction itself. Since arm does not have a
1222 ;;; bitfield insert instruction, we would have to emit code here to truncate
1223 ;;; the value before we insert. This loses some of the advantage of having
1224 ;;; this insv pattern, so this pattern needs to be reevalutated.
1225
1226 (define_expand "insv"
1227 [(set (zero_extract:SI (match_operand:SI 0 "s_register_operand" "")
1228 (match_operand:SI 1 "general_operand" "")
1229 (match_operand:SI 2 "general_operand" ""))
1230 (match_operand:SI 3 "nonmemory_operand" ""))]
1231 ""
1232 "
1233 {
1234 int start_bit = INTVAL (operands[2]);
1235 int width = INTVAL (operands[1]);
1236 HOST_WIDE_INT mask = (((HOST_WIDE_INT)1) << width) - 1;
1237 rtx target, subtarget;
1238
1239 target = operands[0];
1240 /* Avoid using a subreg as a subtarget, and avoid writing a paradoxical
1241 subreg as the final target. */
1242 if (GET_CODE (target) == SUBREG)
1243 {
1244 subtarget = gen_reg_rtx (SImode);
1245 if (GET_MODE_SIZE (GET_MODE (SUBREG_REG (target)))
1246 < GET_MODE_SIZE (SImode))
1247 target = SUBREG_REG (target);
1248 }
1249 else
1250 subtarget = target;
1251
1252 if (GET_CODE (operands[3]) == CONST_INT)
1253 {
1254 /* Since we are inserting a known constant, we may be able to
1255 reduce the number of bits that we have to clear so that
1256 the mask becomes simple. */
1257 /* ??? This code does not check to see if the new mask is actually
1258 simpler. It may not be. */
1259 rtx op1 = gen_reg_rtx (SImode);
1260 /* ??? Truncate operand3 to fit in the bitfield. See comment before
1261 start of this pattern. */
1262 HOST_WIDE_INT op3_value = mask & INTVAL (operands[3]);
1263 HOST_WIDE_INT mask2 = ((mask & ~op3_value) << start_bit);
1264
1265 emit_insn (gen_andsi3 (op1, operands[0], GEN_INT (~mask2)));
1266 emit_insn (gen_iorsi3 (subtarget, op1,
1267 GEN_INT (op3_value << start_bit)));
1268 }
1269 else if (start_bit == 0
1270 && ! (const_ok_for_arm (mask)
1271 || const_ok_for_arm (~mask)))
1272 {
1273 /* A Trick, since we are setting the bottom bits in the word,
1274 we can shift operand[3] up, operand[0] down, OR them together
1275 and rotate the result back again. This takes 3 insns, and
1276 the third might be mergable into another op. */
1277 /* The shift up copes with the possibility that operand[3] is
1278 wider than the bitfield. */
1279 rtx op0 = gen_reg_rtx (SImode);
1280 rtx op1 = gen_reg_rtx (SImode);
1281
1282 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1283 emit_insn (gen_iorsi3 (op1, gen_rtx_LSHIFTRT (SImode, operands[0],
1284 operands[1]),
1285 op0));
1286 emit_insn (gen_rotlsi3 (subtarget, op1, operands[1]));
1287 }
1288 else if ((width + start_bit == 32)
1289 && ! (const_ok_for_arm (mask)
1290 || const_ok_for_arm (~mask)))
1291 {
1292 /* Similar trick, but slightly less efficient. */
1293
1294 rtx op0 = gen_reg_rtx (SImode);
1295 rtx op1 = gen_reg_rtx (SImode);
1296
1297 emit_insn (gen_ashlsi3 (op0, operands[3], GEN_INT (32 - width)));
1298 emit_insn (gen_ashlsi3 (op1, operands[0], operands[1]));
1299 emit_insn (gen_iorsi3 (subtarget,
1300 gen_rtx_LSHIFTRT (SImode, op1, operands[1]),
1301 op0));
1302 }
1303 else
1304 {
1305 rtx op0 = GEN_INT (mask);
1306 rtx op1 = gen_reg_rtx (SImode);
1307 rtx op2 = gen_reg_rtx (SImode);
1308
1309 if (! (const_ok_for_arm (mask) || const_ok_for_arm (~mask)))
1310 {
1311 rtx tmp = gen_reg_rtx (SImode);
1312
1313 emit_insn (gen_movsi (tmp, op0));
1314 op0 = tmp;
1315 }
1316
1317 /* Mask out any bits in operand[3] that are not needed. */
1318 emit_insn (gen_andsi3 (op1, operands[3], op0));
1319
1320 if (GET_CODE (op0) == CONST_INT
1321 && (const_ok_for_arm (mask << start_bit)
1322 || const_ok_for_arm (~ (mask << start_bit))))
1323 {
1324 op0 = GEN_INT (~(mask << start_bit));
1325 emit_insn (gen_andsi3 (op2, operands[0], op0));
1326 }
1327 else
1328 {
1329 if (GET_CODE (op0) == CONST_INT)
1330 {
1331 rtx tmp = gen_reg_rtx (SImode);
1332
1333 emit_insn (gen_movsi (tmp, op0));
1334 op0 = tmp;
1335 }
1336
1337 if (start_bit != 0)
1338 op0 = gen_rtx_ASHIFT (SImode, op0, operands[2]);
1339
1340 emit_insn (gen_andsi_notsi_si (op2, operands[0], op0));
1341 }
1342
1343 if (start_bit != 0)
1344 op1 = gen_rtx_ASHIFT (SImode, op1, operands[2]);
1345
1346 emit_insn (gen_iorsi3 (subtarget, op1, op2));
1347 }
1348
1349 if (subtarget != target)
1350 {
1351 /* If TARGET is still a SUBREG, then it must be wider than a word,
1352 so we must be careful only to set the subword we were asked to. */
1353 if (GET_CODE (target) == SUBREG)
1354 emit_move_insn (target, subtarget);
1355 else
1356 emit_move_insn (target, gen_lowpart (GET_MODE (target), subtarget));
1357 }
1358
1359 DONE;
1360 }
1361 ")
1362
1363 ;; constants for op 2 will never be given to these patterns.
1364 (define_insn "*anddi_notdi_di"
1365 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1366 (and:DI (not:DI (match_operand:DI 2 "s_register_operand" "r,0"))
1367 (match_operand:DI 1 "s_register_operand" "0,r")))]
1368 ""
1369 "bic%?\\t%Q0, %Q1, %Q2\;bic%?\\t%R0, %R1, %R2"
1370 [(set_attr "length" "8")])
1371
1372 (define_insn "*anddi_notzesidi_di"
1373 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1374 (and:DI (not:DI (zero_extend:DI
1375 (match_operand:SI 2 "s_register_operand" "r,r")))
1376 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1377 ""
1378 "@
1379 bic%?\\t%Q0, %Q1, %2
1380 bic%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1381 [(set_attr "length" "4,8")])
1382
1383 (define_insn "*anddi_notsesidi_di"
1384 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1385 (and:DI (not:DI (sign_extend:DI
1386 (match_operand:SI 2 "s_register_operand" "r,r")))
1387 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1388 ""
1389 "bic%?\\t%Q0, %Q1, %2\;bic%?\\t%R0, %R1, %2, asr #31"
1390 [(set_attr "length" "8")])
1391
1392 (define_insn "andsi_notsi_si"
1393 [(set (match_operand:SI 0 "s_register_operand" "=r")
1394 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1395 (match_operand:SI 1 "s_register_operand" "r")))]
1396 ""
1397 "bic%?\\t%0, %1, %2")
1398
1399 (define_insn "andsi_not_shiftsi_si"
1400 [(set (match_operand:SI 0 "s_register_operand" "=r")
1401 (and:SI (not:SI (match_operator:SI 4 "shift_operator"
1402 [(match_operand:SI 2 "s_register_operand" "r")
1403 (match_operand:SI 3 "arm_rhs_operand" "rM")]))
1404 (match_operand:SI 1 "s_register_operand" "r")))]
1405 ""
1406 "bic%?\\t%0, %1, %2%S4")
1407
1408 (define_insn "*andsi_notsi_si_compare0"
1409 [(set (reg:CC_NOOV 24)
1410 (compare:CC_NOOV
1411 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1412 (match_operand:SI 1 "s_register_operand" "r"))
1413 (const_int 0)))
1414 (set (match_operand:SI 0 "s_register_operand" "=r")
1415 (and:SI (not:SI (match_dup 2)) (match_dup 1)))]
1416 ""
1417 "bic%?s\\t%0, %1, %2"
1418 [(set_attr "conds" "set")])
1419
1420 (define_insn "*andsi_notsi_si_compare0_scratch"
1421 [(set (reg:CC_NOOV 24)
1422 (compare:CC_NOOV
1423 (and:SI (not:SI (match_operand:SI 2 "s_register_operand" "r"))
1424 (match_operand:SI 1 "s_register_operand" "r"))
1425 (const_int 0)))
1426 (clobber (match_scratch:SI 0 "=r"))]
1427 ""
1428 "bic%?s\\t%0, %1, %2"
1429 [(set_attr "conds" "set")])
1430
1431 (define_insn "iordi3"
1432 [(set (match_operand:DI 0 "s_register_operand" "=&r")
1433 (ior:DI (match_operand:DI 1 "s_register_operand" "%0")
1434 (match_operand:DI 2 "s_register_operand" "r")))]
1435 ""
1436 "orr%?\\t%Q0, %Q1, %Q2\;orr%?\\t%R0, %R1, %R2"
1437 [(set_attr "length" "8")])
1438
1439 (define_insn "*iordi_zesidi_di"
1440 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1441 (ior:DI (zero_extend:DI
1442 (match_operand:SI 2 "s_register_operand" "r,r"))
1443 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1444 ""
1445 "@
1446 orr%?\\t%Q0, %Q1, %2
1447 orr%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1448 [(set_attr "length" "4,8")])
1449
1450 (define_insn "*iordi_sesidi_di"
1451 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1452 (ior:DI (sign_extend:DI
1453 (match_operand:SI 2 "s_register_operand" "r,r"))
1454 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1455 ""
1456 "orr%?\\t%Q0, %Q1, %2\;orr%?\\t%R0, %R1, %2, asr #31"
1457 [(set_attr "length" "8")])
1458
1459 (define_expand "iorsi3"
1460 [(set (match_operand:SI 0 "s_register_operand" "")
1461 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1462 (match_operand:SI 2 "reg_or_int_operand" "")))]
1463 ""
1464 "
1465 if (GET_CODE (operands[2]) == CONST_INT)
1466 {
1467 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1468 operands[1],
1469 (reload_in_progress || reload_completed
1470 ? 0 : preserve_subexpressions_p ()));
1471 DONE;
1472 }
1473 ")
1474
1475 (define_insn "*iorsi3_insn"
1476 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1477 (ior:SI (match_operand:SI 1 "s_register_operand" "r,r")
1478 (match_operand:SI 2 "reg_or_int_operand" "rI,?n")))]
1479 ""
1480 "@
1481 orr%?\\t%0, %1, %2
1482 #"
1483 [(set_attr "length" "4,16")])
1484
1485 (define_split
1486 [(set (match_operand:SI 0 "s_register_operand" "")
1487 (ior:SI (match_operand:SI 1 "s_register_operand" "")
1488 (match_operand:SI 2 "const_int_operand" "")))]
1489 "! const_ok_for_arm (INTVAL (operands[2]))"
1490 [(clobber (const_int 0))]
1491 "
1492 arm_split_constant (IOR, SImode, INTVAL (operands[2]), operands[0],
1493 operands[1], 0);
1494 DONE;
1495 ")
1496
1497 (define_insn "*iorsi3_compare0"
1498 [(set (reg:CC_NOOV 24)
1499 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1500 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1501 (const_int 0)))
1502 (set (match_operand:SI 0 "s_register_operand" "=r")
1503 (ior:SI (match_dup 1) (match_dup 2)))]
1504 ""
1505 "orr%?s\\t%0, %1, %2"
1506 [(set_attr "conds" "set")])
1507
1508 (define_insn "*iorsi3_compare0_scratch"
1509 [(set (reg:CC_NOOV 24)
1510 (compare:CC_NOOV (ior:SI (match_operand:SI 1 "s_register_operand" "%r")
1511 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1512 (const_int 0)))
1513 (clobber (match_scratch:SI 0 "=r"))]
1514 ""
1515 "orr%?s\\t%0, %1, %2"
1516 [(set_attr "conds" "set")])
1517
1518 (define_insn "xordi3"
1519 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1520 (xor:DI (match_operand:DI 1 "s_register_operand" "%0,0")
1521 (match_operand:DI 2 "s_register_operand" "r,0")))]
1522 ""
1523 "eor%?\\t%Q0, %Q1, %Q2\;eor%?\\t%R0, %R1, %R2"
1524 [(set_attr "length" "8")])
1525
1526 (define_insn "*xordi_zesidi_di"
1527 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1528 (xor:DI (zero_extend:DI
1529 (match_operand:SI 2 "s_register_operand" "r,r"))
1530 (match_operand:DI 1 "s_register_operand" "0,?r")))]
1531 ""
1532 "@
1533 eor%?\\t%Q0, %Q1, %2
1534 eor%?\\t%Q0, %Q1, %2\;mov%?\\t%R0, %R1"
1535 [(set_attr "length" "4,8")])
1536
1537 (define_insn "*xordi_sesidi_di"
1538 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1539 (xor:DI (sign_extend:DI
1540 (match_operand:SI 2 "s_register_operand" "r,r"))
1541 (match_operand:DI 1 "s_register_operand" "?r,0")))]
1542 ""
1543 "eor%?\\t%Q0, %Q1, %2\;eor%?\\t%R0, %R1, %2, asr #31"
1544 [(set_attr "length" "8")])
1545
1546 (define_insn "xorsi3"
1547 [(set (match_operand:SI 0 "s_register_operand" "=r")
1548 (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1549 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
1550 ""
1551 "eor%?\\t%0, %1, %2")
1552
1553 (define_insn "*xorsi3_compare0"
1554 [(set (reg:CC_NOOV 24)
1555 (compare:CC_NOOV (xor:SI (match_operand:SI 1 "s_register_operand" "r")
1556 (match_operand:SI 2 "arm_rhs_operand" "rI"))
1557 (const_int 0)))
1558 (set (match_operand:SI 0 "s_register_operand" "=r")
1559 (xor:SI (match_dup 1) (match_dup 2)))]
1560 ""
1561 "eor%?s\\t%0, %1, %2"
1562 [(set_attr "conds" "set")])
1563
1564 (define_insn "*xorsi3_compare0_scratch"
1565 [(set (reg:CC_NOOV 24)
1566 (compare:CC_NOOV (xor:SI (match_operand:SI 0 "s_register_operand" "r")
1567 (match_operand:SI 1 "arm_rhs_operand" "rI"))
1568 (const_int 0)))]
1569 ""
1570 "teq%?\\t%0, %1"
1571 [(set_attr "conds" "set")])
1572
1573 ;; by splitting (IOR (AND (NOT A) (NOT B)) C) as D = AND (IOR A B) (NOT C),
1574 ;; (NOT D) we can sometimes merge the final NOT into one of the following
1575 ;; insns
1576
1577 (define_split
1578 [(set (match_operand:SI 0 "s_register_operand" "=r")
1579 (ior:SI (and:SI (not:SI (match_operand:SI 1 "s_register_operand" "r"))
1580 (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI")))
1581 (match_operand:SI 3 "arm_rhs_operand" "rI")))
1582 (clobber (match_operand:SI 4 "s_register_operand" "=r"))]
1583 ""
1584 [(set (match_dup 4) (and:SI (ior:SI (match_dup 1) (match_dup 2))
1585 (not:SI (match_dup 3))))
1586 (set (match_dup 0) (not:SI (match_dup 4)))]
1587 ""
1588 )
1589
1590 (define_insn "*andsi_iorsi3_notsi"
1591 [(set (match_operand:SI 0 "s_register_operand" "=&r,&r,&r")
1592 (and:SI (ior:SI (match_operand:SI 1 "s_register_operand" "r,r,0")
1593 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI"))
1594 (not:SI (match_operand:SI 3 "arm_rhs_operand" "rI,rI,rI"))))]
1595 ""
1596 "orr%?\\t%0, %1, %2\;bic%?\\t%0, %0, %3"
1597 [(set_attr "length" "8")])
1598
1599 \f
1600
1601 ;; Minimum and maximum insns
1602
1603 (define_insn "smaxsi3"
1604 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1605 (smax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1606 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1607 (clobber (reg:CC 24))]
1608 ""
1609 "@
1610 cmp\\t%1, %2\;movlt\\t%0, %2
1611 cmp\\t%1, %2\;movge\\t%0, %1
1612 cmp\\t%1, %2\;movge\\t%0, %1\;movlt\\t%0, %2"
1613 [(set_attr "conds" "clob")
1614 (set_attr "length" "8,8,12")])
1615
1616 (define_insn "sminsi3"
1617 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1618 (smin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1619 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1620 (clobber (reg:CC 24))]
1621 ""
1622 "@
1623 cmp\\t%1, %2\;movge\\t%0, %2
1624 cmp\\t%1, %2\;movlt\\t%0, %1
1625 cmp\\t%1, %2\;movlt\\t%0, %1\;movge\\t%0, %2"
1626 [(set_attr "conds" "clob")
1627 (set_attr "length" "8,8,12")])
1628
1629 (define_insn "umaxsi3"
1630 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1631 (umax:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1632 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1633 (clobber (reg:CC 24))]
1634 ""
1635 "@
1636 cmp\\t%1, %2\;movcc\\t%0, %2
1637 cmp\\t%1, %2\;movcs\\t%0, %1
1638 cmp\\t%1, %2\;movcs\\t%0, %1\;movcc\\t%0, %2"
1639 [(set_attr "conds" "clob")
1640 (set_attr "length" "8,8,12")])
1641
1642 (define_insn "uminsi3"
1643 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
1644 (umin:SI (match_operand:SI 1 "s_register_operand" "0,r,?r")
1645 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
1646 (clobber (reg:CC 24))]
1647 ""
1648 "@
1649 cmp\\t%1, %2\;movcs\\t%0, %2
1650 cmp\\t%1, %2\;movcc\\t%0, %1
1651 cmp\\t%1, %2\;movcc\\t%0, %1\;movcs\\t%0, %2"
1652 [(set_attr "conds" "clob")
1653 (set_attr "length" "8,8,12")])
1654
1655 (define_insn "*store_minmaxsi"
1656 [(set (match_operand:SI 0 "memory_operand" "=m")
1657 (match_operator:SI 3 "minmax_operator"
1658 [(match_operand:SI 1 "s_register_operand" "r")
1659 (match_operand:SI 2 "s_register_operand" "r")]))
1660 (clobber (reg:CC 24))]
1661 ""
1662 "*
1663 operands[3] = gen_rtx (minmax_code (operands[3]), SImode, operands[1],
1664 operands[2]);
1665 output_asm_insn (\"cmp\\t%1, %2\", operands);
1666 output_asm_insn (\"str%d3\\t%1, %0\", operands);
1667 output_asm_insn (\"str%D3\\t%2, %0\", operands);
1668 return \"\";
1669 "
1670 [(set_attr "conds" "clob")
1671 (set_attr "length" "12")
1672 (set_attr "type" "store1")])
1673
1674 ; Reject the frame pointer in operand[1], since reloading this after
1675 ; it has been eliminated can cause carnage.
1676 (define_insn "*minmax_arithsi"
1677 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
1678 (match_operator:SI 4 "shiftable_operator"
1679 [(match_operator:SI 5 "minmax_operator"
1680 [(match_operand:SI 2 "s_register_operand" "r,r")
1681 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
1682 (match_operand:SI 1 "s_register_operand" "0,?r")]))
1683 (clobber (reg:CC 24))]
1684 "GET_CODE (operands[1]) != REG
1685 || (REGNO(operands[1]) != FRAME_POINTER_REGNUM
1686 && REGNO(operands[1]) != ARG_POINTER_REGNUM)"
1687 "*
1688 {
1689 enum rtx_code code = GET_CODE (operands[4]);
1690
1691 operands[5] = gen_rtx (minmax_code (operands[5]), SImode, operands[2],
1692 operands[3]);
1693 output_asm_insn (\"cmp\\t%2, %3\", operands);
1694 output_asm_insn (\"%i4%d5\\t%0, %1, %2\", operands);
1695 if (which_alternative != 0 || operands[3] != const0_rtx
1696 || (code != PLUS && code != MINUS && code != IOR && code != XOR))
1697 output_asm_insn (\"%i4%D5\\t%0, %1, %3\", operands);
1698 return \"\";
1699 }
1700 "
1701 [(set_attr "conds" "clob")
1702 (set_attr "length" "12")])
1703
1704 \f
1705 ;; Shift and rotation insns
1706
1707 (define_expand "ashlsi3"
1708 [(set (match_operand:SI 0 "s_register_operand" "")
1709 (ashift:SI (match_operand:SI 1 "s_register_operand" "")
1710 (match_operand:SI 2 "arm_rhs_operand" "")))]
1711 ""
1712 "
1713 if (GET_CODE (operands[2]) == CONST_INT
1714 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1715 {
1716 emit_insn (gen_movsi (operands[0], const0_rtx));
1717 DONE;
1718 }
1719 ")
1720
1721 (define_expand "ashrsi3"
1722 [(set (match_operand:SI 0 "s_register_operand" "")
1723 (ashiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1724 (match_operand:SI 2 "arm_rhs_operand" "")))]
1725 ""
1726 "
1727 if (GET_CODE (operands[2]) == CONST_INT
1728 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1729 operands[2] = GEN_INT (31);
1730 ")
1731
1732 (define_expand "lshrsi3"
1733 [(set (match_operand:SI 0 "s_register_operand" "")
1734 (lshiftrt:SI (match_operand:SI 1 "s_register_operand" "")
1735 (match_operand:SI 2 "arm_rhs_operand" "")))]
1736 ""
1737 "
1738 if (GET_CODE (operands[2]) == CONST_INT
1739 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1740 {
1741 emit_insn (gen_movsi (operands[0], const0_rtx));
1742 DONE;
1743 }
1744 ")
1745
1746 (define_expand "rotlsi3"
1747 [(set (match_operand:SI 0 "s_register_operand" "")
1748 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1749 (match_operand:SI 2 "reg_or_int_operand" "")))]
1750 ""
1751 "
1752 if (GET_CODE (operands[2]) == CONST_INT)
1753 operands[2] = GEN_INT ((32 - INTVAL (operands[2])) % 32);
1754 else
1755 {
1756 rtx reg = gen_reg_rtx (SImode);
1757 emit_insn (gen_subsi3 (reg, GEN_INT (32), operands[2]));
1758 operands[2] = reg;
1759 }
1760 ")
1761
1762 (define_expand "rotrsi3"
1763 [(set (match_operand:SI 0 "s_register_operand" "")
1764 (rotatert:SI (match_operand:SI 1 "s_register_operand" "")
1765 (match_operand:SI 2 "arm_rhs_operand" "")))]
1766 ""
1767 "
1768 if (GET_CODE (operands[2]) == CONST_INT
1769 && ((unsigned HOST_WIDE_INT) INTVAL (operands[2])) > 31)
1770 operands[2] = GEN_INT (INTVAL (operands[2]) % 32);
1771 ")
1772
1773 (define_insn "*shiftsi3"
1774 [(set (match_operand:SI 0 "s_register_operand" "=r")
1775 (match_operator:SI 3 "shift_operator"
1776 [(match_operand:SI 1 "s_register_operand" "r")
1777 (match_operand:SI 2 "reg_or_int_operand" "rM")]))]
1778 ""
1779 "mov%?\\t%0, %1%S3")
1780
1781 (define_insn "*shiftsi3_compare0"
1782 [(set (reg:CC_NOOV 24)
1783 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1784 [(match_operand:SI 1 "s_register_operand" "r")
1785 (match_operand:SI 2 "arm_rhs_operand" "rM")])
1786 (const_int 0)))
1787 (set (match_operand:SI 0 "s_register_operand" "=r")
1788 (match_op_dup 3 [(match_dup 1) (match_dup 2)]))]
1789 ""
1790 "mov%?s\\t%0, %1%S3"
1791 [(set_attr "conds" "set")])
1792
1793 (define_insn "*shiftsi3_compare0_scratch"
1794 [(set (reg:CC_NOOV 24)
1795 (compare:CC_NOOV (match_operator:SI 3 "shift_operator"
1796 [(match_operand:SI 1 "s_register_operand" "r")
1797 (match_operand:SI 2 "arm_rhs_operand" "rM")])
1798 (const_int 0)))
1799 (clobber (match_scratch:SI 0 "=r"))]
1800 ""
1801 "mov%?s\\t%0, %1%S3"
1802 [(set_attr "conds" "set")])
1803
1804 (define_insn "*notsi_shiftsi"
1805 [(set (match_operand:SI 0 "s_register_operand" "=r")
1806 (not:SI (match_operator:SI 3 "shift_operator"
1807 [(match_operand:SI 1 "s_register_operand" "r")
1808 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
1809 ""
1810 "mvn%?\\t%0, %1%S3")
1811
1812 (define_insn "*notsi_shiftsi_compare0"
1813 [(set (reg:CC_NOOV 24)
1814 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1815 [(match_operand:SI 1 "s_register_operand" "r")
1816 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1817 (const_int 0)))
1818 (set (match_operand:SI 0 "s_register_operand" "=r")
1819 (not:SI (match_op_dup 3 [(match_dup 1) (match_dup 2)])))]
1820 ""
1821 "mvn%?s\\t%0, %1%S3"
1822 [(set_attr "conds" "set")])
1823
1824 (define_insn "*not_shiftsi_compare0_scratch"
1825 [(set (reg:CC_NOOV 24)
1826 (compare:CC_NOOV (not:SI (match_operator:SI 3 "shift_operator"
1827 [(match_operand:SI 1 "s_register_operand" "r")
1828 (match_operand:SI 2 "arm_rhs_operand" "rM")]))
1829 (const_int 0)))
1830 (clobber (match_scratch:SI 0 "=r"))]
1831 ""
1832 "mvn%?s\\t%0, %1%S3"
1833 [(set_attr "conds" "set")])
1834
1835 \f
1836 ;; Unary arithmetic insns
1837
1838 (define_insn "negdi2"
1839 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
1840 (neg:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
1841 ""
1842 "rsbs\\t%Q0, %Q1, #0\;rsc\\t%R0, %R1, #0"
1843 [(set_attr "conds" "clob")
1844 (set_attr "length" "8")])
1845
1846 (define_insn "negsi2"
1847 [(set (match_operand:SI 0 "s_register_operand" "=r")
1848 (neg:SI (match_operand:SI 1 "s_register_operand" "r")))]
1849 ""
1850 "rsb%?\\t%0, %1, #0")
1851
1852 (define_insn "negsf2"
1853 [(set (match_operand:SF 0 "s_register_operand" "=f")
1854 (neg:SF (match_operand:SF 1 "s_register_operand" "f")))]
1855 "TARGET_HARD_FLOAT"
1856 "mnf%?s\\t%0, %1"
1857 [(set_attr "type" "ffarith")])
1858
1859 (define_insn "negdf2"
1860 [(set (match_operand:DF 0 "s_register_operand" "=f")
1861 (neg:DF (match_operand:DF 1 "s_register_operand" "f")))]
1862 "TARGET_HARD_FLOAT"
1863 "mnf%?d\\t%0, %1"
1864 [(set_attr "type" "ffarith")])
1865
1866 (define_insn "*negdf_esfdf"
1867 [(set (match_operand:DF 0 "s_register_operand" "=f")
1868 (neg:DF (float_extend:DF
1869 (match_operand:SF 1 "s_register_operand" "f"))))]
1870 "TARGET_HARD_FLOAT"
1871 "mnf%?d\\t%0, %1"
1872 [(set_attr "type" "ffarith")])
1873
1874 (define_insn "negxf2"
1875 [(set (match_operand:XF 0 "s_register_operand" "=f")
1876 (neg:XF (match_operand:XF 1 "s_register_operand" "f")))]
1877 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1878 "mnf%?e\\t%0, %1"
1879 [(set_attr "type" "ffarith")])
1880
1881 ;; abssi2 doesn't really clobber the condition codes if a different register
1882 ;; is being set. To keep things simple, assume during rtl manipulations that
1883 ;; it does, but tell the final scan operator the truth. Similarly for
1884 ;; (neg (abs...))
1885
1886 (define_insn "abssi2"
1887 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1888 (abs:SI (match_operand:SI 1 "s_register_operand" "0,r")))
1889 (clobber (reg:CC 24))]
1890 ""
1891 "@
1892 cmp\\t%0, #0\;rsblt\\t%0, %0, #0
1893 eor%?\\t%0, %1, %1, asr #31\;sub%?\\t%0, %0, %1, asr #31"
1894 [(set_attr "conds" "clob,*")
1895 (set_attr "length" "8")])
1896
1897 (define_insn "*neg_abssi2"
1898 [(set (match_operand:SI 0 "s_register_operand" "=r,&r")
1899 (neg:SI (abs:SI (match_operand:SI 1 "s_register_operand" "0,r"))))
1900 (clobber (reg:CC 24))]
1901 ""
1902 "@
1903 cmp\\t%0, #0\;rsbgt\\t%0, %0, #0
1904 eor%?\\t%0, %1, %1, asr #31\;rsb%?\\t%0, %0, %1, asr #31"
1905 [(set_attr "conds" "clob,*")
1906 (set_attr "length" "8")])
1907
1908 (define_insn "abssf2"
1909 [(set (match_operand:SF 0 "s_register_operand" "=f")
1910 (abs:SF (match_operand:SF 1 "s_register_operand" "f")))]
1911 "TARGET_HARD_FLOAT"
1912 "abs%?s\\t%0, %1"
1913 [(set_attr "type" "ffarith")])
1914
1915 (define_insn "absdf2"
1916 [(set (match_operand:DF 0 "s_register_operand" "=f")
1917 (abs:DF (match_operand:DF 1 "s_register_operand" "f")))]
1918 "TARGET_HARD_FLOAT"
1919 "abs%?d\\t%0, %1"
1920 [(set_attr "type" "ffarith")])
1921
1922 (define_insn "*absdf_esfdf"
1923 [(set (match_operand:DF 0 "s_register_operand" "=f")
1924 (abs:DF (float_extend:DF
1925 (match_operand:SF 1 "s_register_operand" "f"))))]
1926 "TARGET_HARD_FLOAT"
1927 "abs%?d\\t%0, %1"
1928 [(set_attr "type" "ffarith")])
1929
1930 (define_insn "absxf2"
1931 [(set (match_operand:XF 0 "s_register_operand" "=f")
1932 (abs:XF (match_operand:XF 1 "s_register_operand" "f")))]
1933 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1934 "abs%?e\\t%0, %1"
1935 [(set_attr "type" "ffarith")])
1936
1937 (define_insn "sqrtsf2"
1938 [(set (match_operand:SF 0 "s_register_operand" "=f")
1939 (sqrt:SF (match_operand:SF 1 "s_register_operand" "f")))]
1940 "TARGET_HARD_FLOAT"
1941 "sqt%?s\\t%0, %1"
1942 [(set_attr "type" "float_em")])
1943
1944 (define_insn "sqrtdf2"
1945 [(set (match_operand:DF 0 "s_register_operand" "=f")
1946 (sqrt:DF (match_operand:DF 1 "s_register_operand" "f")))]
1947 "TARGET_HARD_FLOAT"
1948 "sqt%?d\\t%0, %1"
1949 [(set_attr "type" "float_em")])
1950
1951 (define_insn "*sqrtdf_esfdf"
1952 [(set (match_operand:DF 0 "s_register_operand" "=f")
1953 (sqrt:DF (float_extend:DF
1954 (match_operand:SF 1 "s_register_operand" "f"))))]
1955 "TARGET_HARD_FLOAT"
1956 "sqt%?d\\t%0, %1"
1957 [(set_attr "type" "float_em")])
1958
1959 (define_insn "sqrtxf2"
1960 [(set (match_operand:XF 0 "s_register_operand" "=f")
1961 (sqrt:XF (match_operand:XF 1 "s_register_operand" "f")))]
1962 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1963 "sqt%?e\\t%0, %1"
1964 [(set_attr "type" "float_em")])
1965
1966 ;; SIN COS TAN and family are always emulated, so it's probably better
1967 ;; to always call a library function.
1968 ;(define_insn "sinsf2"
1969 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
1970 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 0))]
1971 ; "TARGET_HARD_FLOAT"
1972 ; "sin%?s\\t%0, %1"
1973 ;[(set_attr "type" "float_em")])
1974 ;
1975 ;(define_insn "sindf2"
1976 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
1977 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 0))]
1978 ; "TARGET_HARD_FLOAT"
1979 ; "sin%?d\\t%0, %1"
1980 ;[(set_attr "type" "float_em")])
1981 ;
1982 ;(define_insn "*sindf_esfdf"
1983 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
1984 ; (unspec:DF [(float_extend:DF
1985 ; (match_operand:SF 1 "s_register_operand" "f"))] 0))]
1986 ; "TARGET_HARD_FLOAT"
1987 ; "sin%?d\\t%0, %1"
1988 ;[(set_attr "type" "float_em")])
1989 ;
1990 ;(define_insn "sinxf2"
1991 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
1992 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 0))]
1993 ; "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
1994 ; "sin%?e\\t%0, %1"
1995 ;[(set_attr "type" "float_em")])
1996 ;
1997 ;(define_insn "cossf2"
1998 ; [(set (match_operand:SF 0 "s_register_operand" "=f")
1999 ; (unspec:SF [(match_operand:SF 1 "s_register_operand" "f")] 1))]
2000 ; "TARGET_HARD_FLOAT"
2001 ; "cos%?s\\t%0, %1"
2002 ;[(set_attr "type" "float_em")])
2003 ;
2004 ;(define_insn "cosdf2"
2005 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2006 ; (unspec:DF [(match_operand:DF 1 "s_register_operand" "f")] 1))]
2007 ; "TARGET_HARD_FLOAT"
2008 ; "cos%?d\\t%0, %1"
2009 ;[(set_attr "type" "float_em")])
2010 ;
2011 ;(define_insn "*cosdf_esfdf"
2012 ; [(set (match_operand:DF 0 "s_register_operand" "=f")
2013 ; (unspec:DF [(float_extend:DF
2014 ; (match_operand:SF 1 "s_register_operand" "f"))] 1))]
2015 ; "TARGET_HARD_FLOAT"
2016 ; "cos%?d\\t%0, %1"
2017 ;[(set_attr "type" "float_em")])
2018 ;
2019 ;(define_insn "cosxf2"
2020 ; [(set (match_operand:XF 0 "s_register_operand" "=f")
2021 ; (unspec:XF [(match_operand:XF 1 "s_register_operand" "f")] 1))]
2022 ; "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2023 ; "cos%?e\\t%0, %1"
2024 ;[(set_attr "type" "float_em")])
2025
2026 (define_insn "one_cmpldi2"
2027 [(set (match_operand:DI 0 "s_register_operand" "=&r,&r")
2028 (not:DI (match_operand:DI 1 "s_register_operand" "?r,0")))]
2029 ""
2030 "mvn%?\\t%Q0, %Q1\;mvn%?\\t%R0, %R1"
2031 [(set_attr "length" "8")])
2032
2033 (define_insn "one_cmplsi2"
2034 [(set (match_operand:SI 0 "s_register_operand" "=r")
2035 (not:SI (match_operand:SI 1 "s_register_operand" "r")))]
2036 ""
2037 "mvn%?\\t%0, %1")
2038
2039 (define_insn "*notsi_compare0"
2040 [(set (reg:CC_NOOV 24)
2041 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2042 (const_int 0)))
2043 (set (match_operand:SI 0 "s_register_operand" "=r")
2044 (not:SI (match_dup 1)))]
2045 ""
2046 "mvn%?s\\t%0, %1"
2047 [(set_attr "conds" "set")])
2048
2049 (define_insn "*notsi_compare0_scratch"
2050 [(set (reg:CC_NOOV 24)
2051 (compare:CC_NOOV (not:SI (match_operand:SI 1 "s_register_operand" "r"))
2052 (const_int 0)))
2053 (clobber (match_scratch:SI 0 "=r"))]
2054 ""
2055 "mvn%?s\\t%0, %1"
2056 [(set_attr "conds" "set")])
2057 \f
2058 ;; Fixed <--> Floating conversion insns
2059
2060 (define_insn "floatsisf2"
2061 [(set (match_operand:SF 0 "s_register_operand" "=f")
2062 (float:SF (match_operand:SI 1 "s_register_operand" "r")))]
2063 "TARGET_HARD_FLOAT"
2064 "flt%?s\\t%0, %1"
2065 [(set_attr "type" "r_2_f")])
2066
2067 (define_insn "floatsidf2"
2068 [(set (match_operand:DF 0 "s_register_operand" "=f")
2069 (float:DF (match_operand:SI 1 "s_register_operand" "r")))]
2070 "TARGET_HARD_FLOAT"
2071 "flt%?d\\t%0, %1"
2072 [(set_attr "type" "r_2_f")])
2073
2074 (define_insn "floatsixf2"
2075 [(set (match_operand:XF 0 "s_register_operand" "=f")
2076 (float:XF (match_operand:SI 1 "s_register_operand" "r")))]
2077 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2078 "flt%?e\\t%0, %1"
2079 [(set_attr "type" "r_2_f")])
2080
2081 (define_insn "fix_truncsfsi2"
2082 [(set (match_operand:SI 0 "s_register_operand" "=r")
2083 (fix:SI (match_operand:SF 1 "s_register_operand" "f")))]
2084 "TARGET_HARD_FLOAT"
2085 "fix%?z\\t%0, %1"
2086 [(set_attr "type" "f_2_r")])
2087
2088 (define_insn "fix_truncdfsi2"
2089 [(set (match_operand:SI 0 "s_register_operand" "=r")
2090 (fix:SI (match_operand:DF 1 "s_register_operand" "f")))]
2091 "TARGET_HARD_FLOAT"
2092 "fix%?z\\t%0, %1"
2093 [(set_attr "type" "f_2_r")])
2094
2095 (define_insn "fix_truncxfsi2"
2096 [(set (match_operand:SI 0 "s_register_operand" "=r")
2097 (fix:SI (match_operand:XF 1 "s_register_operand" "f")))]
2098 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2099 "fix%?z\\t%0, %1"
2100 [(set_attr "type" "f_2_r")])
2101
2102 ;; Truncation insns
2103
2104 (define_insn "truncdfsf2"
2105 [(set (match_operand:SF 0 "s_register_operand" "=f")
2106 (float_truncate:SF
2107 (match_operand:DF 1 "s_register_operand" "f")))]
2108 "TARGET_HARD_FLOAT"
2109 "mvf%?s\\t%0, %1"
2110 [(set_attr "type" "ffarith")])
2111
2112 (define_insn "truncxfsf2"
2113 [(set (match_operand:SF 0 "s_register_operand" "=f")
2114 (float_truncate:SF
2115 (match_operand:XF 1 "s_register_operand" "f")))]
2116 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2117 "mvf%?s\\t%0, %1"
2118 [(set_attr "type" "ffarith")])
2119
2120 (define_insn "truncxfdf2"
2121 [(set (match_operand:DF 0 "s_register_operand" "=f")
2122 (float_truncate:DF
2123 (match_operand:XF 1 "s_register_operand" "f")))]
2124 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2125 "mvf%?d\\t%0, %1"
2126 [(set_attr "type" "ffarith")])
2127 \f
2128 ;; Zero and sign extension instructions.
2129
2130 (define_insn "zero_extendsidi2"
2131 [(set (match_operand:DI 0 "s_register_operand" "=r")
2132 (zero_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2133 ""
2134 "*
2135 if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2136 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2137 return \"mov%?\\t%R0, #0\";
2138 "
2139 [(set_attr "length" "8")])
2140
2141 (define_insn "zero_extendqidi2"
2142 [(set (match_operand:DI 0 "s_register_operand" "=r,r")
2143 (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2144 ""
2145 "@
2146 and%?\\t%Q0, %1, #255\;mov%?\\t%R0, #0
2147 ldr%?b\\t%Q0, %1\;mov%?\\t%R0, #0"
2148 [(set_attr "length" "8")
2149 (set_attr "type" "*,load")])
2150
2151 (define_insn "extendsidi2"
2152 [(set (match_operand:DI 0 "s_register_operand" "=r")
2153 (sign_extend:DI (match_operand:SI 1 "s_register_operand" "r")))]
2154 ""
2155 "*
2156 if (REGNO (operands[1]) != REGNO (operands[0]) + (WORDS_BIG_ENDIAN ? 1 : 0))
2157 output_asm_insn (\"mov%?\\t%Q0, %1\", operands);
2158 return \"mov%?\\t%R0, %Q0, asr #31\";
2159 "
2160 [(set_attr "length" "8")])
2161
2162 (define_expand "zero_extendhisi2"
2163 [(set (match_dup 2) (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2164 (const_int 16)))
2165 (set (match_operand:SI 0 "s_register_operand" "")
2166 (lshiftrt:SI (match_dup 2) (const_int 16)))]
2167 ""
2168 "
2169 {
2170 if (GET_CODE (operands[1]) == MEM)
2171 {
2172 if (TARGET_SHORT_BY_BYTES)
2173 {
2174 emit_insn (gen_movhi_bytes (operands[0], operands[1]));
2175 DONE;
2176 }
2177 else if (arm_arch4)
2178 {
2179 emit_insn (gen_rtx_SET (VOIDmode,
2180 operands[0],
2181 gen_rtx_ZERO_EXTEND (SImode, operands[1])));
2182 DONE;
2183 }
2184 }
2185 if (! s_register_operand (operands[1], HImode))
2186 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2187 operands[1] = gen_lowpart (SImode, operands[1]);
2188 operands[2] = gen_reg_rtx (SImode);
2189 }")
2190
2191 (define_insn "*zero_extendhisi_insn"
2192 [(set (match_operand:SI 0 "s_register_operand" "=r")
2193 (zero_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2194 "arm_arch4"
2195 "ldr%?h\\t%0, %1"
2196 [(set_attr "type" "load")])
2197
2198 (define_split
2199 [(set (match_operand:SI 0 "s_register_operand" "")
2200 (zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2201 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2202 "! arm_arch4"
2203 [(set (match_dup 2) (match_dup 1))
2204 (set (match_dup 0) (lshiftrt:SI (match_dup 2) (const_int 16)))]
2205 "
2206 {
2207 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2208 FAIL;
2209 }")
2210
2211 (define_split
2212 [(set (match_operand:SI 0 "s_register_operand" "")
2213 (match_operator:SI 3 "shiftable_operator"
2214 [(zero_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2215 (match_operand:SI 4 "s_register_operand" "")]))
2216 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2217 "! arm_arch4"
2218 [(set (match_dup 2) (match_dup 1))
2219 (set (match_dup 0)
2220 (match_op_dup 3
2221 [(lshiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2222 "
2223 {
2224 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2225 FAIL;
2226 }")
2227
2228 (define_expand "zero_extendqisi2"
2229 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
2230 (zero_extend:SI
2231 (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
2232 ""
2233 "
2234 if (GET_CODE (operands[1]) != MEM)
2235 {
2236 emit_insn (gen_andsi3 (operands[0], gen_lowpart (SImode, operands[1]),
2237 GEN_INT (255)));
2238 DONE;
2239 }
2240 ")
2241
2242 (define_insn "*load_extendqisi"
2243 [(set (match_operand:SI 0 "s_register_operand" "=r")
2244 (zero_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2245 ""
2246 "ldr%?b\\t%0, %1\\t%@ zero_extendqisi2"
2247 [(set_attr "type" "load")])
2248
2249 (define_split
2250 [(set (match_operand:SI 0 "s_register_operand" "")
2251 (zero_extend:SI (subreg:QI (match_operand:SI 1 "" "") 0)))
2252 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2253 "GET_CODE (operands[1]) != MEM"
2254 [(set (match_dup 2) (match_dup 1))
2255 (set (match_dup 0) (and:SI (match_dup 2) (const_int 255)))]
2256 "")
2257
2258 (define_insn "*compareqi_eq0"
2259 [(set (reg:CC_Z 24)
2260 (compare:CC_Z (match_operand:QI 0 "s_register_operand" "r")
2261 (const_int 0)))]
2262 ""
2263 "tst\\t%0, #255"
2264 [(set_attr "conds" "set")])
2265
2266 (define_expand "extendhisi2"
2267 [(set (match_dup 2)
2268 (ashift:SI (match_operand:HI 1 "nonimmediate_operand" "")
2269 (const_int 16)))
2270 (set (match_operand:SI 0 "s_register_operand" "")
2271 (ashiftrt:SI (match_dup 2)
2272 (const_int 16)))]
2273 ""
2274 "
2275 {
2276 if (GET_CODE (operands[1]) == MEM)
2277 {
2278 if (TARGET_SHORT_BY_BYTES)
2279 {
2280 emit_insn (gen_extendhisi2_mem (operands[0], operands[1]));
2281 DONE;
2282 }
2283 else if (arm_arch4)
2284 {
2285 emit_insn (gen_rtx_SET (VOIDmode, operands[0],
2286 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
2287 DONE;
2288 }
2289 }
2290 if (! s_register_operand (operands[1], HImode))
2291 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2292 operands[1] = gen_lowpart (SImode, operands[1]);
2293 operands[2] = gen_reg_rtx (SImode);
2294 }")
2295
2296 (define_expand "extendhisi2_mem"
2297 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
2298 (set (match_dup 3)
2299 (zero_extend:SI (match_dup 7)))
2300 (set (match_dup 6) (ashift:SI (match_dup 4) (const_int 24)))
2301 (set (match_operand:SI 0 "" "")
2302 (ior:SI (ashiftrt:SI (match_dup 6) (const_int 16)) (match_dup 5)))]
2303 ""
2304 "
2305 {
2306 rtx mem1, mem2;
2307 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
2308
2309 mem1 = gen_rtx_MEM (QImode, addr);
2310 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
2311 RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
2312 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
2313 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
2314 RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
2315 operands[0] = gen_lowpart (SImode, operands[0]);
2316 operands[1] = mem1;
2317 operands[2] = gen_reg_rtx (SImode);
2318 operands[3] = gen_reg_rtx (SImode);
2319 operands[6] = gen_reg_rtx (SImode);
2320 operands[7] = mem2;
2321
2322 if (BYTES_BIG_ENDIAN)
2323 {
2324 operands[4] = operands[2];
2325 operands[5] = operands[3];
2326 }
2327 else
2328 {
2329 operands[4] = operands[3];
2330 operands[5] = operands[2];
2331 }
2332 }
2333 ")
2334
2335 (define_insn "*extendhisi_insn"
2336 [(set (match_operand:SI 0 "s_register_operand" "=r")
2337 (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
2338 "arm_arch4"
2339 "ldr%?sh\\t%0, %1"
2340 [(set_attr "type" "load")])
2341
2342 (define_split
2343 [(set (match_operand:SI 0 "s_register_operand" "")
2344 (sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" "")))
2345 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2346 "! arm_arch4"
2347 [(set (match_dup 2) (match_dup 1))
2348 (set (match_dup 0) (ashiftrt:SI (match_dup 2) (const_int 16)))]
2349 "
2350 {
2351 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2352 FAIL;
2353 }")
2354
2355 (define_split
2356 [(set (match_operand:SI 0 "s_register_operand" "")
2357 (match_operator:SI 3 "shiftable_operator"
2358 [(sign_extend:SI (match_operand:HI 1 "alignable_memory_operand" ""))
2359 (match_operand:SI 4 "s_register_operand" "")]))
2360 (clobber (match_operand:SI 2 "s_register_operand" ""))]
2361 "! arm_arch4"
2362 [(set (match_dup 2) (match_dup 1))
2363 (set (match_dup 0)
2364 (match_op_dup 3
2365 [(ashiftrt:SI (match_dup 2) (const_int 16)) (match_dup 4)]))]
2366 "
2367 {
2368 if ((operands[1] = gen_rotated_half_load (operands[1])) == NULL)
2369 FAIL;
2370 }")
2371
2372 (define_expand "extendqihi2"
2373 [(set (match_dup 2)
2374 (ashift:SI (match_operand:QI 1 "general_operand" "")
2375 (const_int 24)))
2376 (set (match_operand:HI 0 "s_register_operand" "")
2377 (ashiftrt:SI (match_dup 2)
2378 (const_int 24)))]
2379 ""
2380 "
2381 {
2382 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2383 {
2384 emit_insn (gen_rtx_SET (VOIDmode,
2385 operands[0],
2386 gen_rtx_SIGN_EXTEND (HImode, operands[1])));
2387 DONE;
2388 }
2389 if (! s_register_operand (operands[1], QImode))
2390 operands[1] = copy_to_mode_reg (QImode, operands[1]);
2391 operands[0] = gen_lowpart (SImode, operands[0]);
2392 operands[1] = gen_lowpart (SImode, operands[1]);
2393 operands[2] = gen_reg_rtx (SImode);
2394 }")
2395
2396 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2397 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2398 (define_insn "*extendqihi_insn"
2399 [(set (match_operand:HI 0 "s_register_operand" "=r")
2400 (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
2401 "arm_arch4"
2402 "*
2403 /* If the address is invalid, this will split the instruction into two. */
2404 if (bad_signed_byte_operand(operands[1], QImode))
2405 return \"#\";
2406 return \"ldr%?sb\\t%0, %1\";
2407 "
2408 [(set_attr "type" "load")
2409 (set_attr "length" "8")])
2410
2411 (define_split
2412 [(set (match_operand:HI 0 "s_register_operand" "")
2413 (sign_extend:HI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2414 "arm_arch4 && reload_completed"
2415 [(set (match_dup 3) (match_dup 1))
2416 (set (match_dup 0) (sign_extend:HI (match_dup 2)))]
2417 "
2418 {
2419 HOST_WIDE_INT offset;
2420
2421 operands[3] = gen_rtx_REG (SImode, REGNO (operands[0]));
2422 operands[2] = gen_rtx_MEM (QImode, operands[3]);
2423 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2424 RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2425 operands[1] = XEXP (operands[1], 0);
2426 if (GET_CODE (operands[1]) == PLUS
2427 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2428 && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2429 || const_ok_for_arm (-offset)))
2430 {
2431 HOST_WIDE_INT low = (offset > 0
2432 ? (offset & 0xff) : -((-offset) & 0xff));
2433 XEXP (operands[2], 0) = plus_constant (operands[3], low);
2434 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2435 }
2436 /* Ensure the sum is in correct canonical form */
2437 else if (GET_CODE (operands[1]) == PLUS
2438 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2439 && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2440 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
2441 XEXP (operands[1], 1),
2442 XEXP (operands[1], 0));
2443 }
2444 ")
2445
2446 (define_expand "extendqisi2"
2447 [(set (match_dup 2)
2448 (ashift:SI (match_operand:QI 1 "general_operand" "")
2449 (const_int 24)))
2450 (set (match_operand:SI 0 "s_register_operand" "")
2451 (ashiftrt:SI (match_dup 2)
2452 (const_int 24)))]
2453 ""
2454 "
2455 {
2456 if (arm_arch4 && GET_CODE (operands[1]) == MEM)
2457 {
2458 emit_insn (gen_rtx_SET (VOIDmode,
2459 operands[0],
2460 gen_rtx_SIGN_EXTEND (SImode, operands[1])));
2461 DONE;
2462 }
2463 if (! s_register_operand (operands[1], QImode))
2464 operands[1] = copy_to_mode_reg (QImode, operands[1]);
2465 operands[1] = gen_lowpart (SImode, operands[1]);
2466 operands[2] = gen_reg_rtx (SImode);
2467 }")
2468
2469 ; Rather than restricting all byte accesses to memory addresses that ldrsb
2470 ; can handle, we fix up the ones that ldrsb can't grok with a split.
2471 (define_insn "*extendqisi_insn"
2472 [(set (match_operand:SI 0 "s_register_operand" "=r")
2473 (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
2474 "arm_arch4"
2475 "*
2476 /* If the address is invalid, this will split the instruction into two. */
2477 if (bad_signed_byte_operand(operands[1], QImode))
2478 return \"#\";
2479 return \"ldr%?sb\\t%0, %1\";
2480 "
2481 [(set_attr "type" "load")
2482 (set_attr "length" "8")])
2483
2484 (define_split
2485 [(set (match_operand:SI 0 "s_register_operand" "")
2486 (sign_extend:SI (match_operand:QI 1 "bad_signed_byte_operand" "")))]
2487 "arm_arch4 && reload_completed"
2488 [(set (match_dup 0) (match_dup 1))
2489 (set (match_dup 0) (sign_extend:SI (match_dup 2)))]
2490 "
2491 {
2492 HOST_WIDE_INT offset;
2493
2494 operands[2] = gen_rtx_MEM (QImode, operands[0]);
2495 MEM_COPY_ATTRIBUTES (operands[2], operands[1]);
2496 RTX_UNCHANGING_P (operands[2]) = RTX_UNCHANGING_P (operands[1]);
2497 operands[1] = XEXP (operands[1], 0);
2498 if (GET_CODE (operands[1]) == PLUS
2499 && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
2500 && ! (const_ok_for_arm (offset = INTVAL (XEXP (operands[1], 1)))
2501 || const_ok_for_arm (-offset)))
2502 {
2503 HOST_WIDE_INT low = (offset > 0
2504 ? (offset & 0xff) : -((-offset) & 0xff));
2505 XEXP (operands[2], 0) = plus_constant (operands[0], low);
2506 operands[1] = plus_constant (XEXP (operands[1], 0), offset - low);
2507 }
2508 /* Ensure the sum is in correct canonical form */
2509 else if (GET_CODE (operands[1]) == PLUS
2510 && GET_CODE (XEXP (operands[1], 1)) != CONST_INT
2511 && ! s_register_operand (XEXP (operands[1], 1), VOIDmode))
2512 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]),
2513 XEXP (operands[1], 1),
2514 XEXP (operands[1], 0));
2515 }
2516 ")
2517
2518 (define_insn "extendsfdf2"
2519 [(set (match_operand:DF 0 "s_register_operand" "=f")
2520 (float_extend:DF (match_operand:SF 1 "s_register_operand" "f")))]
2521 "TARGET_HARD_FLOAT"
2522 "mvf%?d\\t%0, %1"
2523 [(set_attr "type" "ffarith")])
2524
2525 (define_insn "extendsfxf2"
2526 [(set (match_operand:XF 0 "s_register_operand" "=f")
2527 (float_extend:XF (match_operand:SF 1 "s_register_operand" "f")))]
2528 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2529 "mvf%?e\\t%0, %1"
2530 [(set_attr "type" "ffarith")])
2531
2532 (define_insn "extenddfxf2"
2533 [(set (match_operand:XF 0 "s_register_operand" "=f")
2534 (float_extend:XF (match_operand:DF 1 "s_register_operand" "f")))]
2535 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
2536 "mvf%?e\\t%0, %1"
2537 [(set_attr "type" "ffarith")])
2538
2539 \f
2540 ;; Move insns (including loads and stores)
2541
2542 ;; XXX Just some ideas about movti.
2543 ;; I don't think these are a good idea on the arm, there just aren't enough
2544 ;; registers
2545 ;;(define_expand "loadti"
2546 ;; [(set (match_operand:TI 0 "s_register_operand" "")
2547 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
2548 ;; "" "")
2549
2550 ;;(define_expand "storeti"
2551 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
2552 ;; (match_operand:TI 1 "s_register_operand" ""))]
2553 ;; "" "")
2554
2555 ;;(define_expand "movti"
2556 ;; [(set (match_operand:TI 0 "general_operand" "")
2557 ;; (match_operand:TI 1 "general_operand" ""))]
2558 ;; ""
2559 ;; "
2560 ;;{
2561 ;; rtx insn;
2562 ;;
2563 ;; if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
2564 ;; operands[1] = copy_to_reg (operands[1]);
2565 ;; if (GET_CODE (operands[0]) == MEM)
2566 ;; insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
2567 ;; else if (GET_CODE (operands[1]) == MEM)
2568 ;; insn = gen_loadti (operands[0], XEXP (operands[1], 0));
2569 ;; else
2570 ;; FAIL;
2571 ;;
2572 ;; emit_insn (insn);
2573 ;; DONE;
2574 ;;}")
2575
2576 ;; Recognise garbage generated above.
2577
2578 ;;(define_insn ""
2579 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
2580 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
2581 ;; ""
2582 ;; "*
2583 ;; {
2584 ;; register mem = (which_alternative < 3);
2585 ;; register char *template;
2586 ;;
2587 ;; operands[mem] = XEXP (operands[mem], 0);
2588 ;; switch (which_alternative)
2589 ;; {
2590 ;; case 0: template = \"ldmdb\\t%1!, %M0\"; break;
2591 ;; case 1: template = \"ldmia\\t%1!, %M0\"; break;
2592 ;; case 2: template = \"ldmia\\t%1, %M0\"; break;
2593 ;; case 3: template = \"stmdb\\t%0!, %M1\"; break;
2594 ;; case 4: template = \"stmia\\t%0!, %M1\"; break;
2595 ;; case 5: template = \"stmia\\t%0, %M1\"; break;
2596 ;; }
2597 ;; output_asm_insn (template, operands);
2598 ;; return \"\";
2599 ;; }")
2600
2601
2602 (define_insn "movdi"
2603 [(set (match_operand:DI 0 "di_operand" "=r,r,o<>")
2604 (match_operand:DI 1 "di_operand" "rIK,mi,r"))]
2605 ""
2606 "*
2607 return (output_move_double (operands));
2608 "
2609 [(set_attr "length" "8,8,8")
2610 (set_attr "type" "*,load,store2")])
2611
2612 (define_expand "movsi"
2613 [(set (match_operand:SI 0 "general_operand" "")
2614 (match_operand:SI 1 "general_operand" ""))]
2615 ""
2616 "
2617 /* Everything except mem = const or mem = mem can be done easily */
2618 if (GET_CODE (operands[0]) == MEM)
2619 operands[1] = force_reg (SImode, operands[1]);
2620 if (GET_CODE (operands[1]) == CONST_INT
2621 && !(const_ok_for_arm (INTVAL (operands[1]))
2622 || const_ok_for_arm (~INTVAL (operands[1]))))
2623 {
2624 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2625 NULL_RTX,
2626 (reload_in_progress || reload_completed ? 0
2627 : preserve_subexpressions_p ()));
2628 DONE;
2629 }
2630 if (CONSTANT_P (operands[1]) && flag_pic)
2631 operands[1] = legitimize_pic_address (operands[1], SImode,
2632 ((reload_in_progress
2633 || reload_completed)
2634 ? operands[0] : 0));
2635 ")
2636
2637 (define_insn "*movsi_insn"
2638 [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
2639 (match_operand:SI 1 "general_operand" "rI,K,mi,r"))]
2640 "register_operand (operands[0], SImode)
2641 || register_operand (operands[1], SImode)"
2642 "@
2643 mov%?\\t%0, %1
2644 mvn%?\\t%0, #%B1
2645 ldr%?\\t%0, %1
2646 str%?\\t%1, %0"
2647 [(set_attr "type" "*,*,load,store1")])
2648
2649 (define_split
2650 [(set (match_operand:SI 0 "s_register_operand" "")
2651 (match_operand:SI 1 "const_int_operand" ""))]
2652 "! (const_ok_for_arm (INTVAL (operands[1]))
2653 || const_ok_for_arm (~INTVAL (operands[1])))"
2654 [(clobber (const_int 0))]
2655 "
2656 arm_split_constant (SET, SImode, INTVAL (operands[1]), operands[0],
2657 NULL_RTX, 0);
2658 DONE;
2659 ")
2660
2661 (define_expand "movaddr"
2662 [(set (match_operand:SI 0 "s_register_operand" "")
2663 (match_operand:DI 1 "address_operand" ""))]
2664 ""
2665 "")
2666
2667 (define_insn "*movaddr_insn"
2668 [(set (match_operand:SI 0 "s_register_operand" "=r")
2669 (match_operand:DI 1 "address_operand" "p"))]
2670 "reload_completed
2671 && (GET_CODE (operands[1]) == LABEL_REF
2672 || (GET_CODE (operands[1]) == CONST
2673 && GET_CODE (XEXP (operands[1], 0)) == PLUS
2674 && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
2675 && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == CONST_INT))"
2676 "adr%?\\t%0, %a1")
2677
2678 /* When generating pic, we need to load the symbol offset into a register.
2679 So that the optimizer does not confuse this with a normal symbol load
2680 we use an unspec. The offset will be loaded from a constant pool entry,
2681 since that is the only type of relocation we can use. */
2682
2683 (define_insn "pic_load_addr"
2684 [(set (match_operand:SI 0 "s_register_operand" "=r")
2685 (unspec:SI [(match_operand 1 "" "")] 3))]
2686 "flag_pic"
2687 "ldr%?\\t%0, %a1"
2688 [(set_attr "type" "load")])
2689
2690 ;; This variant is used for AOF assembly, since it needs to mention the
2691 ;; pic register in the rtl.
2692 (define_expand "pic_load_addr_based"
2693 [(set (match_operand:SI 0 "s_register_operand" "=r")
2694 (unspec:SI [(match_operand 1 "" "") (match_dup 2)] 3))]
2695 "flag_pic"
2696 "operands[2] = pic_offset_table_rtx;")
2697
2698 (define_insn "*pic_load_addr_based_insn"
2699 [(set (match_operand:SI 0 "s_register_operand" "=r")
2700 (unspec:SI [(match_operand 1 "" "")
2701 (match_operand 2 "s_register_operand" "r")] 3))]
2702 "flag_pic && operands[2] == pic_offset_table_rtx"
2703 "*
2704 #ifdef AOF_ASSEMBLER
2705 operands[1] = aof_pic_entry (operands[1]);
2706 #endif
2707 output_asm_insn (\"ldr%?\\t%0, %a1\", operands);
2708 return \"\";
2709 " [(set_attr "type" "load")])
2710
2711 (define_insn "pic_add_dot_plus_eight"
2712 [(set (pc) (label_ref (match_operand 0 "" "")))
2713 (set (match_operand 1 "register_operand" "+r")
2714 (plus:SI (match_dup 1) (const (plus:SI (pc) (const_int 8)))))]
2715 "flag_pic"
2716 "add%?\\t%1, %|pc, %1")
2717
2718 ;; If copying one reg to another we can set the condition codes according to
2719 ;; its value. Such a move is common after a return from subroutine and the
2720 ;; result is being tested against zero.
2721
2722 (define_insn "*movsi_compare0"
2723 [(set (reg:CC 24) (compare:CC (match_operand:SI 1 "s_register_operand" "0,r")
2724 (const_int 0)))
2725 (set (match_operand:SI 0 "s_register_operand" "=r,r") (match_dup 1))]
2726 ""
2727 "@
2728 cmp%?\\t%0, #0
2729 sub%?s\\t%0, %1, #0"
2730 [(set_attr "conds" "set")])
2731
2732 ;; Subroutine to store a half word from a register into memory.
2733 ;; Operand 0 is the source register (HImode)
2734 ;; Operand 1 is the destination address in a register (SImode)
2735
2736 ;; In both this routine and the next, we must be careful not to spill
2737 ;; a memory address of reg+large_const into a separate PLUS insn, since this
2738 ;; can generate unrecognizable rtl.
2739
2740 (define_expand "storehi"
2741 [;; store the low byte
2742 (set (match_operand 1 "" "") (match_dup 3))
2743 ;; extract the high byte
2744 (set (match_dup 2)
2745 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2746 ;; store the high byte
2747 (set (match_dup 4) (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
2748 ""
2749 "
2750 {
2751 rtx addr = XEXP (operands[1], 0);
2752 enum rtx_code code = GET_CODE (addr);
2753
2754 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2755 || code == MINUS)
2756 addr = force_reg (SImode, addr);
2757
2758 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2759 operands[1] = change_address (operands[1], QImode, NULL_RTX);
2760 operands[3] = gen_lowpart (QImode, operands[0]);
2761 operands[0] = gen_lowpart (SImode, operands[0]);
2762 operands[2] = gen_reg_rtx (SImode);
2763 }
2764 ")
2765
2766 (define_expand "storehi_bigend"
2767 [(set (match_dup 4) (match_dup 3))
2768 (set (match_dup 2)
2769 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
2770 (set (match_operand 1 "" "") (subreg:QI (match_dup 2) 0))]
2771 ""
2772 "
2773 {
2774 rtx addr = XEXP (operands[1], 0);
2775 enum rtx_code code = GET_CODE (addr);
2776
2777 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2778 || code == MINUS)
2779 addr = force_reg (SImode, addr);
2780
2781 operands[4] = change_address (operands[1], QImode, plus_constant (addr, 1));
2782 operands[1] = change_address (operands[1], QImode, NULL_RTX);
2783 operands[3] = gen_lowpart (QImode, operands[0]);
2784 operands[0] = gen_lowpart (SImode, operands[0]);
2785 operands[2] = gen_reg_rtx (SImode);
2786 }
2787 ")
2788
2789 ;; Subroutine to store a half word integer constant into memory.
2790 (define_expand "storeinthi"
2791 [(set (match_operand 0 "" "")
2792 (subreg:QI (match_operand 1 "" "") 0))
2793 (set (match_dup 3) (subreg:QI (match_dup 2) 0))]
2794 ""
2795 "
2796 {
2797 HOST_WIDE_INT value = INTVAL (operands[1]);
2798 rtx addr = XEXP (operands[0], 0);
2799 enum rtx_code code = GET_CODE (addr);
2800
2801 if ((code == PLUS && GET_CODE (XEXP (addr, 1)) != CONST_INT)
2802 || code == MINUS)
2803 addr = force_reg (SImode, addr);
2804
2805 operands[1] = gen_reg_rtx (SImode);
2806 if (BYTES_BIG_ENDIAN)
2807 {
2808 emit_insn (gen_movsi (operands[1], GEN_INT ((value >> 8) & 255)));
2809 if ((value & 255) == ((value >> 8) & 255))
2810 operands[2] = operands[1];
2811 else
2812 {
2813 operands[2] = gen_reg_rtx (SImode);
2814 emit_insn (gen_movsi (operands[2], GEN_INT (value & 255)));
2815 }
2816 }
2817 else
2818 {
2819 emit_insn (gen_movsi (operands[1], GEN_INT (value & 255)));
2820 if ((value & 255) == ((value >> 8) & 255))
2821 operands[2] = operands[1];
2822 else
2823 {
2824 operands[2] = gen_reg_rtx (SImode);
2825 emit_insn (gen_movsi (operands[2], GEN_INT ((value >> 8) & 255)));
2826 }
2827 }
2828
2829 operands[3] = change_address (operands[0], QImode, plus_constant (addr, 1));
2830 operands[0] = change_address (operands[0], QImode, NULL_RTX);
2831 }
2832 ")
2833
2834 (define_expand "storehi_single_op"
2835 [(set (match_operand:HI 0 "memory_operand" "")
2836 (match_operand:HI 1 "general_operand" ""))]
2837 "arm_arch4"
2838 "
2839 if (! s_register_operand (operands[1], HImode))
2840 operands[1] = copy_to_mode_reg (HImode, operands[1]);
2841 ")
2842
2843 (define_expand "movhi"
2844 [(set (match_operand:HI 0 "general_operand" "")
2845 (match_operand:HI 1 "general_operand" ""))]
2846 ""
2847 "
2848 {
2849 rtx insn;
2850
2851 if (! (reload_in_progress || reload_completed))
2852 {
2853 if (GET_CODE (operands[0]) == MEM)
2854 {
2855 if (arm_arch4)
2856 {
2857 emit_insn (gen_storehi_single_op (operands[0], operands[1]));
2858 DONE;
2859 }
2860 if (GET_CODE (operands[1]) == CONST_INT)
2861 emit_insn (gen_storeinthi (operands[0], operands[1]));
2862 else
2863 {
2864 if (GET_CODE (operands[1]) == MEM)
2865 operands[1] = force_reg (HImode, operands[1]);
2866 if (BYTES_BIG_ENDIAN)
2867 emit_insn (gen_storehi_bigend (operands[1], operands[0]));
2868 else
2869 emit_insn (gen_storehi (operands[1], operands[0]));
2870 }
2871 DONE;
2872 }
2873 /* Sign extend a constant, and keep it in an SImode reg. */
2874 else if (GET_CODE (operands[1]) == CONST_INT)
2875 {
2876 rtx reg = gen_reg_rtx (SImode);
2877 HOST_WIDE_INT val = INTVAL (operands[1]) & 0xffff;
2878
2879 /* If the constant is already valid, leave it alone. */
2880 if (! const_ok_for_arm (val))
2881 {
2882 /* If setting all the top bits will make the constant
2883 loadable in a single instruction, then set them.
2884 Otherwise, sign extend the number. */
2885
2886 if (const_ok_for_arm (~ (val | ~0xffff)))
2887 val |= ~0xffff;
2888 else if (val & 0x8000)
2889 val |= ~0xffff;
2890 }
2891
2892 emit_insn (gen_movsi (reg, GEN_INT (val)));
2893 operands[1] = gen_rtx_SUBREG (HImode, reg, 0);
2894 }
2895 else if (! arm_arch4)
2896 {
2897 if (GET_CODE (operands[1]) == MEM)
2898 {
2899 if (TARGET_SHORT_BY_BYTES)
2900 {
2901 rtx base;
2902 rtx offset = const0_rtx;
2903 rtx reg = gen_reg_rtx (SImode);
2904
2905 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2906 || (GET_CODE (base) == PLUS
2907 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2908 && GET_CODE (base = XEXP (base, 0)) == REG))
2909 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2910 {
2911 HOST_WIDE_INT new_offset = INTVAL (offset) & ~2;
2912 rtx new;
2913
2914 new = gen_rtx_MEM (SImode,
2915 plus_constant (base, new_offset));
2916 MEM_COPY_ATTRIBUTES (new, operands[1]);
2917 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2918 emit_insn (gen_movsi (reg, new));
2919 if (((INTVAL (offset) & 2) != 0)
2920 ^ (BYTES_BIG_ENDIAN ? 1 : 0))
2921 {
2922 rtx reg2 = gen_reg_rtx (SImode);
2923
2924 emit_insn (gen_lshrsi3 (reg2, reg, GEN_INT (16)));
2925 reg = reg2;
2926 }
2927 }
2928 else
2929 emit_insn (gen_movhi_bytes (reg, operands[1]));
2930
2931 operands[1] = gen_lowpart (HImode, reg);
2932 }
2933 else if (BYTES_BIG_ENDIAN)
2934 {
2935 rtx base;
2936 rtx offset = const0_rtx;
2937
2938 if ((GET_CODE (base = XEXP (operands[1], 0)) == REG
2939 || (GET_CODE (base) == PLUS
2940 && GET_CODE (offset = XEXP (base, 1)) == CONST_INT
2941 && GET_CODE (base = XEXP (base, 0)) == REG))
2942 && REGNO_POINTER_ALIGN (REGNO (base)) >= 4)
2943 {
2944 rtx reg = gen_reg_rtx (SImode);
2945 rtx new;
2946
2947 if ((INTVAL (offset) & 2) == 2)
2948 {
2949 HOST_WIDE_INT new_offset = INTVAL (offset) ^ 2;
2950 new = gen_rtx_MEM (SImode,
2951 plus_constant (base, new_offset));
2952 MEM_COPY_ATTRIBUTES (new, operands[1]);
2953 RTX_UNCHANGING_P (new) = RTX_UNCHANGING_P (operands[1]);
2954 emit_insn (gen_movsi (reg, new));
2955 }
2956 else
2957 {
2958 new = gen_rtx_MEM (SImode, XEXP (operands[1], 0));
2959 MEM_COPY_ATTRIBUTES (new, operands[1]);
2960 RTX_UNCHANGING_P (new)
2961 = RTX_UNCHANGING_P (operands[1]);
2962 emit_insn (gen_rotated_loadsi (reg, new));
2963 }
2964
2965 operands[1] = gen_lowpart (HImode, reg);
2966 }
2967 else
2968 {
2969 emit_insn (gen_movhi_bigend (operands[0], operands[1]));
2970 DONE;
2971 }
2972 }
2973 }
2974 }
2975 }
2976 /* Handle loading a large integer during reload */
2977 else if (GET_CODE (operands[1]) == CONST_INT
2978 && ! const_ok_for_arm (INTVAL (operands[1]))
2979 && ! const_ok_for_arm (~INTVAL (operands[1])))
2980 {
2981 /* Writing a constant to memory needs a scratch, which should
2982 be handled with SECONDARY_RELOADs. */
2983 if (GET_CODE (operands[0]) != REG)
2984 abort ();
2985
2986 operands[0] = gen_rtx_SUBREG (SImode, operands[0], 0);
2987 emit_insn (gen_movsi (operands[0], operands[1]));
2988 DONE;
2989 }
2990 }
2991 ")
2992
2993 (define_insn "rotated_loadsi"
2994 [(set (match_operand:SI 0 "s_register_operand" "=r")
2995 (rotate:SI (match_operand:SI 1 "offsettable_memory_operand" "o")
2996 (const_int 16)))]
2997 "! TARGET_SHORT_BY_BYTES"
2998 "*
2999 {
3000 rtx ops[2];
3001
3002 ops[0] = operands[0];
3003 ops[1] = gen_rtx_MEM (SImode, plus_constant (XEXP (operands[1], 0), 2));
3004 output_asm_insn (\"ldr%?\\t%0, %1\\t%@ load-rotate\", ops);
3005 return \"\";
3006 }"
3007 [(set_attr "type" "load")])
3008
3009 (define_expand "movhi_bytes"
3010 [(set (match_dup 2) (zero_extend:SI (match_operand:HI 1 "" "")))
3011 (set (match_dup 3)
3012 (zero_extend:SI (match_dup 6)))
3013 (set (match_operand:SI 0 "" "")
3014 (ior:SI (ashift:SI (match_dup 4) (const_int 8)) (match_dup 5)))]
3015 ""
3016 "
3017 {
3018 rtx mem1, mem2;
3019 rtx addr = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
3020
3021 mem1 = gen_rtx_MEM (QImode, addr);
3022 MEM_COPY_ATTRIBUTES (mem1, operands[1]);
3023 RTX_UNCHANGING_P (mem1) = RTX_UNCHANGING_P (operands[1]);
3024 mem2 = gen_rtx_MEM (QImode, plus_constant (addr, 1));
3025 MEM_COPY_ATTRIBUTES (mem2, operands[1]);
3026 RTX_UNCHANGING_P (mem2) = RTX_UNCHANGING_P (operands[1]);
3027 operands[0] = gen_lowpart (SImode, operands[0]);
3028 operands[1] = mem1;
3029 operands[2] = gen_reg_rtx (SImode);
3030 operands[3] = gen_reg_rtx (SImode);
3031 operands[6] = mem2;
3032
3033 if (BYTES_BIG_ENDIAN)
3034 {
3035 operands[4] = operands[2];
3036 operands[5] = operands[3];
3037 }
3038 else
3039 {
3040 operands[4] = operands[3];
3041 operands[5] = operands[2];
3042 }
3043 }
3044 ")
3045
3046 (define_expand "movhi_bigend"
3047 [(set (match_dup 2)
3048 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "") 0)
3049 (const_int 16)))
3050 (set (match_dup 3)
3051 (ashiftrt:SI (match_dup 2) (const_int 16)))
3052 (set (match_operand:HI 0 "s_register_operand" "")
3053 (subreg:HI (match_dup 3) 0))]
3054 ""
3055 "
3056 operands[2] = gen_reg_rtx (SImode);
3057 operands[3] = gen_reg_rtx (SImode);
3058 ")
3059
3060 ;; Pattern to recognise insn generated default case above
3061
3062 (define_insn "*movhi_insn_arch4"
3063 [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
3064 (match_operand:HI 1 "general_operand" "rI,K,m,r"))]
3065 "arm_arch4
3066 && (GET_CODE (operands[1]) != CONST_INT
3067 || const_ok_for_arm (INTVAL (operands[1]))
3068 || const_ok_for_arm (~INTVAL (operands[1])))"
3069 "@
3070 mov%?\\t%0, %1\\t%@ movhi
3071 mvn%?\\t%0, #%B1\\t%@ movhi
3072 ldr%?h\\t%0, %1\\t%@ movhi
3073 str%?h\\t%1, %0\\t%@ movhi"
3074 [(set_attr "type" "*,*,load,store1")])
3075
3076 (define_insn "*movhi_insn_littleend"
3077 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3078 (match_operand:HI 1 "general_operand" "rI,K,m"))]
3079 "! arm_arch4
3080 && ! BYTES_BIG_ENDIAN
3081 && ! TARGET_SHORT_BY_BYTES
3082 && (GET_CODE (operands[1]) != CONST_INT
3083 || const_ok_for_arm (INTVAL (operands[1]))
3084 || const_ok_for_arm (~INTVAL (operands[1])))"
3085 "@
3086 mov%?\\t%0, %1\\t%@ movhi
3087 mvn%?\\t%0, #%B1\\t%@ movhi
3088 ldr%?\\t%0, %1\\t%@ movhi"
3089 [(set_attr "type" "*,*,load")])
3090
3091 (define_insn "*movhi_insn_bigend"
3092 [(set (match_operand:HI 0 "s_register_operand" "=r,r,r")
3093 (match_operand:HI 1 "general_operand" "rI,K,m"))]
3094 "! arm_arch4
3095 && BYTES_BIG_ENDIAN
3096 && ! TARGET_SHORT_BY_BYTES
3097 && (GET_CODE (operands[1]) != CONST_INT
3098 || const_ok_for_arm (INTVAL (operands[1]))
3099 || const_ok_for_arm (~INTVAL (operands[1])))"
3100 "@
3101 mov%?\\t%0, %1\\t%@ movhi
3102 mvn%?\\t%0, #%B1\\t%@ movhi
3103 ldr%?\\t%0, %1\\t%@ movhi_bigend\;mov%?\\t%0, %0, asr #16"
3104 [(set_attr "type" "*,*,load")
3105 (set_attr "length" "4,4,8")])
3106
3107 (define_insn "*loadhi_si_bigend"
3108 [(set (match_operand:SI 0 "s_register_operand" "=r")
3109 (rotate:SI (subreg:SI (match_operand:HI 1 "memory_operand" "m") 0)
3110 (const_int 16)))]
3111 "BYTES_BIG_ENDIAN
3112 && ! TARGET_SHORT_BY_BYTES"
3113 "ldr%?\\t%0, %1\\t%@ movhi_bigend"
3114 [(set_attr "type" "load")])
3115
3116 (define_insn "*movhi_bytes"
3117 [(set (match_operand:HI 0 "s_register_operand" "=r,r")
3118 (match_operand:HI 1 "arm_rhs_operand" "rI,K"))]
3119 "TARGET_SHORT_BY_BYTES"
3120 "@
3121 mov%?\\t%0, %1\\t%@ movhi
3122 mvn%?\\t%0, #%B1\\t%@ movhi")
3123
3124
3125 (define_expand "reload_outhi"
3126 [(parallel [(match_operand:HI 0 "reload_memory_operand" "=o")
3127 (match_operand:HI 1 "s_register_operand" "r")
3128 (match_operand:SI 2 "s_register_operand" "=&r")])]
3129 ""
3130 "
3131 arm_reload_out_hi (operands);
3132 DONE;
3133 ")
3134
3135 (define_expand "reload_inhi"
3136 [(parallel [(match_operand:HI 0 "s_register_operand" "=r")
3137 (match_operand:HI 1 "reload_memory_operand" "o")
3138 (match_operand:SI 2 "s_register_operand" "=&r")])]
3139 "TARGET_SHORT_BY_BYTES"
3140 "
3141 arm_reload_in_hi (operands);
3142 DONE;
3143 ")
3144
3145 (define_expand "movqi"
3146 [(set (match_operand:QI 0 "general_operand" "")
3147 (match_operand:QI 1 "general_operand" ""))]
3148 ""
3149 "
3150 /* Everything except mem = const or mem = mem can be done easily */
3151
3152 if (!(reload_in_progress || reload_completed))
3153 {
3154 if (GET_CODE (operands[1]) == CONST_INT)
3155 {
3156 rtx reg = gen_reg_rtx (SImode);
3157
3158 emit_insn (gen_movsi (reg, operands[1]));
3159 operands[1] = gen_rtx_SUBREG (QImode, reg, 0);
3160 }
3161 if (GET_CODE (operands[0]) == MEM)
3162 operands[1] = force_reg (QImode, operands[1]);
3163 }
3164 ")
3165
3166
3167 (define_insn "*movqi_insn"
3168 [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
3169 (match_operand:QI 1 "general_operand" "rI,K,m,r"))]
3170 "register_operand (operands[0], QImode)
3171 || register_operand (operands[1], QImode)"
3172 "@
3173 mov%?\\t%0, %1
3174 mvn%?\\t%0, #%B1
3175 ldr%?b\\t%0, %1
3176 str%?b\\t%1, %0"
3177 [(set_attr "type" "*,*,load,store1")])
3178
3179 (define_expand "movsf"
3180 [(set (match_operand:SF 0 "general_operand" "")
3181 (match_operand:SF 1 "general_operand" ""))]
3182 ""
3183 "
3184 if (GET_CODE (operands[0]) == MEM)
3185 operands[1] = force_reg (SFmode, operands[1]);
3186 ")
3187
3188 (define_insn "*movsf_hard_insn"
3189 [(set (match_operand:SF 0 "general_operand" "=f,f,f,m,f,r,r,r,m")
3190 (match_operand:SF 1 "general_operand" "fG,H,mE,f,r,f,r,mE,r"))]
3191 "TARGET_HARD_FLOAT
3192 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3193 "@
3194 mvf%?s\\t%0, %1
3195 mnf%?s\\t%0, #%N1
3196 ldf%?s\\t%0, %1
3197 stf%?s\\t%1, %0
3198 str%?\\t%1, [%|sp, #-4]!\;ldf%?s\\t%0, [%|sp], #4
3199 stf%?s\\t%1, [%|sp, #-4]!\;ldr%?\\t%0, [%|sp], #4
3200 mov%?\\t%0, %1
3201 ldr%?\\t%0, %1\\t%@ float
3202 str%?\\t%1, %0\\t%@ float"
3203 [(set_attr "length" "4,4,4,4,8,8,4,4,4")
3204 (set_attr "type"
3205 "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*,load,store1")])
3206
3207 ;; Exactly the same as above, except that all `f' cases are deleted.
3208 ;; This is necessary to prevent reload from ever trying to use a `f' reg
3209 ;; when -msoft-float.
3210
3211 (define_insn "*movsf_soft_insn"
3212 [(set (match_operand:SF 0 "general_operand" "=r,r,m")
3213 (match_operand:SF 1 "general_operand" "r,mE,r"))]
3214 "TARGET_SOFT_FLOAT
3215 && (GET_CODE (operands[0]) != MEM || register_operand (operands[1], SFmode))"
3216 "@
3217 mov%?\\t%0, %1
3218 ldr%?\\t%0, %1\\t%@ float
3219 str%?\\t%1, %0\\t%@ float"
3220 [(set_attr "length" "4,4,4")
3221 (set_attr "type" "*,load,store1")])
3222
3223 (define_expand "movdf"
3224 [(set (match_operand:DF 0 "general_operand" "")
3225 (match_operand:DF 1 "general_operand" ""))]
3226 ""
3227 "
3228 if (GET_CODE (operands[0]) == MEM)
3229 operands[1] = force_reg (DFmode, operands[1]);
3230 ")
3231
3232 ;; Reloading a df mode value stored in integer regs to memory can require a
3233 ;; scratch reg.
3234 (define_expand "reload_outdf"
3235 [(match_operand:DF 0 "reload_memory_operand" "=o")
3236 (match_operand:DF 1 "s_register_operand" "r")
3237 (match_operand:SI 2 "s_register_operand" "=&r")]
3238 ""
3239 "
3240 {
3241 enum rtx_code code = GET_CODE (XEXP (operands[0], 0));
3242
3243 if (code == REG)
3244 operands[2] = XEXP (operands[0], 0);
3245 else if (code == POST_INC || code == PRE_DEC)
3246 {
3247 operands[0] = gen_rtx_SUBREG (DImode, operands[0], 0);
3248 operands[1] = gen_rtx_SUBREG (DImode, operands[1], 0);
3249 emit_insn (gen_movdi (operands[0], operands[1]));
3250 DONE;
3251 }
3252 else if (code == PRE_INC)
3253 {
3254 rtx reg = XEXP (XEXP (operands[0], 0), 0);
3255 emit_insn (gen_addsi3 (reg, reg, GEN_INT (8)));
3256 operands[2] = reg;
3257 }
3258 else if (code == POST_DEC)
3259 operands[2] = XEXP (XEXP (operands[0], 0), 0);
3260 else
3261 emit_insn (gen_addsi3 (operands[2], XEXP (XEXP (operands[0], 0), 0),
3262 XEXP (XEXP (operands[0], 0), 1)));
3263
3264 emit_insn (gen_rtx_SET (VOIDmode, gen_rtx_MEM (DFmode, operands[2]),
3265 operands[1]));
3266
3267 if (code == POST_DEC)
3268 emit_insn (gen_addsi3 (operands[2], operands[2], GEN_INT (-8)));
3269
3270 DONE;
3271 }
3272 ")
3273
3274 (define_insn "*movdf_hard_insn"
3275 [(set (match_operand:DF 0 "general_operand" "=r,Q,r,m,r,f,f,f,m,!f,!r")
3276 (match_operand:DF 1 "general_operand" "Q,r,r,r,mF,fG,H,mF,f,r,f"))]
3277 "TARGET_HARD_FLOAT
3278 && (GET_CODE (operands[0]) != MEM
3279 || register_operand (operands[1], DFmode))"
3280 "*
3281 {
3282 rtx ops[3];
3283
3284 switch (which_alternative)
3285 {
3286 case 0: return \"ldm%?ia\\t%m1, %M0\\t%@ double\";
3287 case 1: return \"stm%?ia\\t%m0, %M1\\t%@ double\";
3288 case 2: case 3: case 4: return output_move_double (operands);
3289 case 5: return \"mvf%?d\\t%0, %1\";
3290 case 6: return \"mnf%?d\\t%0, #%N1\";
3291 case 7: return \"ldf%?d\\t%0, %1\";
3292 case 8: return \"stf%?d\\t%1, %0\";
3293 case 9: return output_mov_double_fpu_from_arm (operands);
3294 case 10: return output_mov_double_arm_from_fpu (operands);
3295 }
3296 }
3297 "
3298 [(set_attr "length" "4,4,8,8,8,4,4,4,4,8,8")
3299 (set_attr "type"
3300 "load,store2,*,store2,load,ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r")])
3301
3302 ;; Software floating point version. This is essentially the same as movdi.
3303 ;; Do not use `f' as a constraint to prevent reload from ever trying to use
3304 ;; an `f' reg.
3305
3306 (define_insn "*movdf_soft_insn"
3307 [(set (match_operand:DF 0 "soft_df_operand" "=r,r,m")
3308 (match_operand:DF 1 "soft_df_operand" "r,mF,r"))]
3309 "TARGET_SOFT_FLOAT"
3310 "* return output_move_double (operands);"
3311 [(set_attr "length" "8,8,8")
3312 (set_attr "type" "*,load,store2")])
3313
3314 (define_expand "movxf"
3315 [(set (match_operand:XF 0 "general_operand" "")
3316 (match_operand:XF 1 "general_operand" ""))]
3317 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3318 "")
3319
3320 ;; Even when the XFmode patterns aren't enabled, we enable this after
3321 ;; reloading so that we can push floating point registers in the prologue.
3322
3323 (define_insn "*movxf_hard_insn"
3324 [(set (match_operand:XF 0 "general_operand" "=f,f,f,m,f,r,r")
3325 (match_operand:XF 1 "general_operand" "fG,H,m,f,r,f,r"))]
3326 "TARGET_HARD_FLOAT && (ENABLE_XF_PATTERNS || reload_completed)"
3327 "*
3328 switch (which_alternative)
3329 {
3330 case 0: return \"mvf%?e\\t%0, %1\";
3331 case 1: return \"mnf%?e\\t%0, #%N1\";
3332 case 2: return \"ldf%?e\\t%0, %1\";
3333 case 3: return \"stf%?e\\t%1, %0\";
3334 case 4: return output_mov_long_double_fpu_from_arm (operands);
3335 case 5: return output_mov_long_double_arm_from_fpu (operands);
3336 case 6: return output_mov_long_double_arm_from_arm (operands);
3337 }
3338 "
3339 [(set_attr "length" "4,4,4,4,8,8,12")
3340 (set_attr "type" "ffarith,ffarith,f_load,f_store,r_mem_f,f_mem_r,*")])
3341 \f
3342
3343 ;; load- and store-multiple insns
3344 ;; The arm can load/store any set of registers, provided that they are in
3345 ;; ascending order; but that is beyond GCC so stick with what it knows.
3346
3347 (define_expand "load_multiple"
3348 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3349 (match_operand:SI 1 "" ""))
3350 (use (match_operand:SI 2 "" ""))])]
3351 ""
3352 "
3353 /* Support only fixed point registers */
3354 if (GET_CODE (operands[2]) != CONST_INT
3355 || INTVAL (operands[2]) > 14
3356 || INTVAL (operands[2]) < 2
3357 || GET_CODE (operands[1]) != MEM
3358 || GET_CODE (operands[0]) != REG
3359 || REGNO (operands[0]) > 14
3360 || REGNO (operands[0]) + INTVAL (operands[2]) > 15)
3361 FAIL;
3362
3363 operands[3]
3364 = arm_gen_load_multiple (REGNO (operands[0]), INTVAL (operands[2]),
3365 force_reg (SImode, XEXP (operands[1], 0)),
3366 TRUE, FALSE, RTX_UNCHANGING_P(operands[1]),
3367 MEM_IN_STRUCT_P(operands[1]),
3368 MEM_SCALAR_P (operands[1]));
3369 ")
3370
3371 ;; Load multiple with write-back
3372
3373 (define_insn "*ldmsi_postinc"
3374 [(match_parallel 0 "load_multiple_operation"
3375 [(set (match_operand:SI 1 "s_register_operand" "+r")
3376 (plus:SI (match_dup 1)
3377 (match_operand:SI 2 "const_int_operand" "n")))
3378 (set (match_operand:SI 3 "s_register_operand" "=r")
3379 (mem:SI (match_dup 1)))])]
3380 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3381 "*
3382 {
3383 rtx ops[3];
3384 int count = XVECLEN (operands[0], 0);
3385
3386 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3387 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 1));
3388 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 2));
3389
3390 output_asm_insn (\"ldm%?ia\\t%0!, {%1-%2}\\t%@ load multiple\", ops);
3391 return \"\";
3392 }
3393 "
3394 [(set_attr "type" "load")])
3395
3396 ;; Ordinary load multiple
3397
3398 (define_insn "*ldmsi"
3399 [(match_parallel 0 "load_multiple_operation"
3400 [(set (match_operand:SI 1 "s_register_operand" "=r")
3401 (mem:SI (match_operand:SI 2 "s_register_operand" "r")))])]
3402 ""
3403 "*
3404 {
3405 rtx ops[3];
3406 int count = XVECLEN (operands[0], 0);
3407
3408 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3409 ops[1] = SET_DEST (XVECEXP (operands[0], 0, 0));
3410 ops[2] = SET_DEST (XVECEXP (operands[0], 0, count - 1));
3411
3412 output_asm_insn (\"ldm%?ia\\t%0, {%1-%2}\\t%@ load multiple\", ops);
3413 return \"\";
3414 }
3415 "
3416 [(set_attr "type" "load")])
3417
3418 (define_expand "store_multiple"
3419 [(match_par_dup 3 [(set (match_operand:SI 0 "" "")
3420 (match_operand:SI 1 "" ""))
3421 (use (match_operand:SI 2 "" ""))])]
3422 ""
3423 "
3424 /* Support only fixed point registers */
3425 if (GET_CODE (operands[2]) != CONST_INT
3426 || INTVAL (operands[2]) > 14
3427 || INTVAL (operands[2]) < 2
3428 || GET_CODE (operands[1]) != REG
3429 || GET_CODE (operands[0]) != MEM
3430 || REGNO (operands[1]) > 14
3431 || REGNO (operands[1]) + INTVAL (operands[2]) > 15)
3432 FAIL;
3433
3434 operands[3]
3435 = arm_gen_store_multiple (REGNO (operands[1]), INTVAL (operands[2]),
3436 force_reg (SImode, XEXP (operands[0], 0)),
3437 TRUE, FALSE, RTX_UNCHANGING_P (operands[0]),
3438 MEM_IN_STRUCT_P(operands[0]),
3439 MEM_SCALAR_P (operands[0]));
3440 ")
3441
3442 ;; Store multiple with write-back
3443
3444 (define_insn "*stmsi_postinc"
3445 [(match_parallel 0 "store_multiple_operation"
3446 [(set (match_operand:SI 1 "s_register_operand" "+r")
3447 (plus:SI (match_dup 1)
3448 (match_operand:SI 2 "const_int_operand" "n")))
3449 (set (mem:SI (match_dup 1))
3450 (match_operand:SI 3 "s_register_operand" "r"))])]
3451 "(INTVAL (operands[2]) == 4 * (XVECLEN (operands[0], 0) - 2))"
3452 "*
3453 {
3454 rtx ops[3];
3455 int count = XVECLEN (operands[0], 0);
3456
3457 ops[0] = XEXP (SET_SRC (XVECEXP (operands[0], 0, 0)), 0);
3458 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 1));
3459 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 2));
3460
3461 output_asm_insn (\"stm%?ia\\t%0!, {%1-%2}\\t%@ str multiple\", ops);
3462 return \"\";
3463 }
3464 "
3465 [(set (attr "type")
3466 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3467 (const_string "store2")
3468 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 5))
3469 (const_string "store3")]
3470 (const_string "store4")))])
3471
3472 ;; Ordinary store multiple
3473
3474 (define_insn "*stmsi"
3475 [(match_parallel 0 "store_multiple_operation"
3476 [(set (mem:SI (match_operand:SI 2 "s_register_operand" "r"))
3477 (match_operand:SI 1 "s_register_operand" "r"))])]
3478 ""
3479 "*
3480 {
3481 rtx ops[3];
3482 int count = XVECLEN (operands[0], 0);
3483
3484 ops[0] = XEXP (SET_DEST (XVECEXP (operands[0], 0, 0)), 0);
3485 ops[1] = SET_SRC (XVECEXP (operands[0], 0, 0));
3486 ops[2] = SET_SRC (XVECEXP (operands[0], 0, count - 1));
3487
3488 output_asm_insn (\"stm%?ia\\t%0, {%1-%2}\\t%@ str multiple\", ops);
3489 return \"\";
3490 }
3491 "
3492 [(set (attr "type")
3493 (cond [(eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 3))
3494 (const_string "store2")
3495 (eq (symbol_ref "XVECLEN (operands[0],0)") (const_int 4))
3496 (const_string "store3")]
3497 (const_string "store4")))])
3498
3499 ;; Move a block of memory if it is word aligned and MORE than 2 words long.
3500 ;; We could let this apply for blocks of less than this, but it clobbers so
3501 ;; many registers that there is then probably a better way.
3502
3503 (define_expand "movstrqi"
3504 [(match_operand:BLK 0 "general_operand" "")
3505 (match_operand:BLK 1 "general_operand" "")
3506 (match_operand:SI 2 "const_int_operand" "")
3507 (match_operand:SI 3 "const_int_operand" "")]
3508 ""
3509 "
3510 if (arm_gen_movstrqi (operands))
3511 DONE;
3512 FAIL;
3513 ")
3514 \f
3515
3516 ;; Comparison and test insns
3517
3518 (define_expand "cmpsi"
3519 [(match_operand:SI 0 "s_register_operand" "")
3520 (match_operand:SI 1 "arm_add_operand" "")]
3521 ""
3522 "
3523 {
3524 arm_compare_op0 = operands[0];
3525 arm_compare_op1 = operands[1];
3526 arm_compare_fp = 0;
3527 DONE;
3528 }
3529 ")
3530
3531 (define_expand "cmpsf"
3532 [(match_operand:SF 0 "s_register_operand" "")
3533 (match_operand:SF 1 "fpu_rhs_operand" "")]
3534 "TARGET_HARD_FLOAT"
3535 "
3536 {
3537 arm_compare_op0 = operands[0];
3538 arm_compare_op1 = operands[1];
3539 arm_compare_fp = 1;
3540 DONE;
3541 }
3542 ")
3543
3544 (define_expand "cmpdf"
3545 [(match_operand:DF 0 "s_register_operand" "")
3546 (match_operand:DF 1 "fpu_rhs_operand" "")]
3547 "TARGET_HARD_FLOAT"
3548 "
3549 {
3550 arm_compare_op0 = operands[0];
3551 arm_compare_op1 = operands[1];
3552 arm_compare_fp = 1;
3553 DONE;
3554 }
3555 ")
3556
3557 (define_expand "cmpxf"
3558 [(match_operand:XF 0 "s_register_operand" "")
3559 (match_operand:XF 1 "fpu_rhs_operand" "")]
3560 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3561 "
3562 {
3563 arm_compare_op0 = operands[0];
3564 arm_compare_op1 = operands[1];
3565 arm_compare_fp = 1;
3566 DONE;
3567 }
3568 ")
3569
3570 (define_insn "*cmpsi_insn"
3571 [(set (reg:CC 24)
3572 (compare:CC (match_operand:SI 0 "s_register_operand" "r,r")
3573 (match_operand:SI 1 "arm_add_operand" "rI,L")))]
3574 ""
3575 "@
3576 cmp%?\\t%0, %1
3577 cmn%?\\t%0, #%n1"
3578 [(set_attr "conds" "set")])
3579
3580 (define_insn "*cmpsi_shiftsi"
3581 [(set (reg:CC 24)
3582 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3583 (match_operator:SI 3 "shift_operator"
3584 [(match_operand:SI 1 "s_register_operand" "r")
3585 (match_operand:SI 2 "arm_rhs_operand" "rM")])))]
3586 ""
3587 "cmp%?\\t%0, %1%S3"
3588 [(set_attr "conds" "set")])
3589
3590 (define_insn "*cmpsi_shiftsi_swp"
3591 [(set (reg:CC_SWP 24)
3592 (compare:CC_SWP (match_operator:SI 3 "shift_operator"
3593 [(match_operand:SI 1 "s_register_operand" "r")
3594 (match_operand:SI 2 "reg_or_int_operand" "rM")])
3595 (match_operand:SI 0 "s_register_operand" "r")))]
3596 ""
3597 "cmp%?\\t%0, %1%S3"
3598 [(set_attr "conds" "set")])
3599
3600 (define_insn "*cmpsi_neg_shiftsi"
3601 [(set (reg:CC 24)
3602 (compare:CC (match_operand:SI 0 "s_register_operand" "r")
3603 (neg:SI (match_operator:SI 3 "shift_operator"
3604 [(match_operand:SI 1 "s_register_operand" "r")
3605 (match_operand:SI 2 "arm_rhs_operand" "rM")]))))]
3606 ""
3607 "cmn%?\\t%0, %1%S3"
3608 [(set_attr "conds" "set")])
3609
3610 (define_insn "*cmpsf_insn"
3611 [(set (reg:CCFP 24)
3612 (compare:CCFP (match_operand:SF 0 "s_register_operand" "f,f")
3613 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3614 "TARGET_HARD_FLOAT"
3615 "@
3616 cmf%?\\t%0, %1
3617 cnf%?\\t%0, #%N1"
3618 [(set_attr "conds" "set")
3619 (set_attr "type" "f_2_r")])
3620
3621 (define_insn "*cmpdf_insn"
3622 [(set (reg:CCFP 24)
3623 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f,f")
3624 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3625 "TARGET_HARD_FLOAT"
3626 "@
3627 cmf%?\\t%0, %1
3628 cnf%?\\t%0, #%N1"
3629 [(set_attr "conds" "set")
3630 (set_attr "type" "f_2_r")])
3631
3632 (define_insn "*cmpesfdf_df"
3633 [(set (reg:CCFP 24)
3634 (compare:CCFP (float_extend:DF
3635 (match_operand:SF 0 "s_register_operand" "f,f"))
3636 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3637 "TARGET_HARD_FLOAT"
3638 "@
3639 cmf%?\\t%0, %1
3640 cnf%?\\t%0, #%N1"
3641 [(set_attr "conds" "set")
3642 (set_attr "type" "f_2_r")])
3643
3644 (define_insn "*cmpdf_esfdf"
3645 [(set (reg:CCFP 24)
3646 (compare:CCFP (match_operand:DF 0 "s_register_operand" "f")
3647 (float_extend:DF
3648 (match_operand:SF 1 "s_register_operand" "f"))))]
3649 "TARGET_HARD_FLOAT"
3650 "cmf%?\\t%0, %1"
3651 [(set_attr "conds" "set")
3652 (set_attr "type" "f_2_r")])
3653
3654 (define_insn "*cmpxf_insn"
3655 [(set (reg:CCFP 24)
3656 (compare:CCFP (match_operand:XF 0 "s_register_operand" "f,f")
3657 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3658 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3659 "@
3660 cmf%?\\t%0, %1
3661 cnf%?\\t%0, #%N1"
3662 [(set_attr "conds" "set")
3663 (set_attr "type" "f_2_r")])
3664
3665 (define_insn "*cmpsf_trap"
3666 [(set (reg:CCFPE 24)
3667 (compare:CCFPE (match_operand:SF 0 "s_register_operand" "f,f")
3668 (match_operand:SF 1 "fpu_add_operand" "fG,H")))]
3669 "TARGET_HARD_FLOAT"
3670 "@
3671 cmf%?e\\t%0, %1
3672 cnf%?e\\t%0, #%N1"
3673 [(set_attr "conds" "set")
3674 (set_attr "type" "f_2_r")])
3675
3676 (define_insn "*cmpdf_trap"
3677 [(set (reg:CCFPE 24)
3678 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f,f")
3679 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3680 "TARGET_HARD_FLOAT"
3681 "@
3682 cmf%?e\\t%0, %1
3683 cnf%?e\\t%0, #%N1"
3684 [(set_attr "conds" "set")
3685 (set_attr "type" "f_2_r")])
3686
3687 (define_insn "*cmp_esfdf_df_trap"
3688 [(set (reg:CCFPE 24)
3689 (compare:CCFPE (float_extend:DF
3690 (match_operand:SF 0 "s_register_operand" "f,f"))
3691 (match_operand:DF 1 "fpu_add_operand" "fG,H")))]
3692 "TARGET_HARD_FLOAT"
3693 "@
3694 cmf%?e\\t%0, %1
3695 cnf%?e\\t%0, #%N1"
3696 [(set_attr "conds" "set")
3697 (set_attr "type" "f_2_r")])
3698
3699 (define_insn "*cmp_df_esfdf_trap"
3700 [(set (reg:CCFPE 24)
3701 (compare:CCFPE (match_operand:DF 0 "s_register_operand" "f")
3702 (float_extend:DF
3703 (match_operand:SF 1 "s_register_operand" "f"))))]
3704 "TARGET_HARD_FLOAT"
3705 "cmf%?e\\t%0, %1"
3706 [(set_attr "conds" "set")
3707 (set_attr "type" "f_2_r")])
3708
3709 (define_insn "*cmpxf_trap"
3710 [(set (reg:CCFPE 24)
3711 (compare:CCFPE (match_operand:XF 0 "s_register_operand" "f,f")
3712 (match_operand:XF 1 "fpu_add_operand" "fG,H")))]
3713 "ENABLE_XF_PATTERNS && TARGET_HARD_FLOAT"
3714 "@
3715 cmf%?e\\t%0, %1
3716 cnf%?e\\t%0, #%N1"
3717 [(set_attr "conds" "set")
3718 (set_attr "type" "f_2_r")])
3719
3720 ; This insn allows redundant compares to be removed by cse, nothing should
3721 ; ever appear in the output file since (set (reg x) (reg x)) is a no-op that
3722 ; is deleted later on. The match_dup will match the mode here, so that
3723 ; mode changes of the condition codes aren't lost by this even though we don't
3724 ; specify what they are.
3725
3726 (define_insn "*deleted_compare"
3727 [(set (match_operand 0 "cc_register" "") (match_dup 0))]
3728 ""
3729 "\\t%@ deleted compare"
3730 [(set_attr "conds" "set")
3731 (set_attr "length" "0")])
3732
3733 \f
3734 ;; Conditional branch insns
3735
3736 (define_expand "beq"
3737 [(set (pc)
3738 (if_then_else (eq (match_dup 1) (const_int 0))
3739 (label_ref (match_operand 0 "" ""))
3740 (pc)))]
3741 ""
3742 "
3743 {
3744 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3745 arm_compare_fp);
3746 }
3747 ")
3748
3749 (define_expand "bne"
3750 [(set (pc)
3751 (if_then_else (ne (match_dup 1) (const_int 0))
3752 (label_ref (match_operand 0 "" ""))
3753 (pc)))]
3754 ""
3755 "
3756 {
3757 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3758 arm_compare_fp);
3759 }
3760 ")
3761
3762 (define_expand "bgt"
3763 [(set (pc)
3764 (if_then_else (gt (match_dup 1) (const_int 0))
3765 (label_ref (match_operand 0 "" ""))
3766 (pc)))]
3767 ""
3768 "
3769 {
3770 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3771 arm_compare_fp);
3772 }
3773 ")
3774
3775 (define_expand "ble"
3776 [(set (pc)
3777 (if_then_else (le (match_dup 1) (const_int 0))
3778 (label_ref (match_operand 0 "" ""))
3779 (pc)))]
3780 ""
3781 "
3782 {
3783 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3784 arm_compare_fp);
3785 }
3786 ")
3787
3788 (define_expand "bge"
3789 [(set (pc)
3790 (if_then_else (ge (match_dup 1) (const_int 0))
3791 (label_ref (match_operand 0 "" ""))
3792 (pc)))]
3793 ""
3794 "
3795 {
3796 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3797 arm_compare_fp);
3798 }
3799 ")
3800
3801 (define_expand "blt"
3802 [(set (pc)
3803 (if_then_else (lt (match_dup 1) (const_int 0))
3804 (label_ref (match_operand 0 "" ""))
3805 (pc)))]
3806 ""
3807 "
3808 {
3809 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3810 arm_compare_fp);
3811 }
3812 ")
3813
3814 (define_expand "bgtu"
3815 [(set (pc)
3816 (if_then_else (gtu (match_dup 1) (const_int 0))
3817 (label_ref (match_operand 0 "" ""))
3818 (pc)))]
3819 ""
3820 "
3821 {
3822 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3823 arm_compare_fp);
3824 }
3825 ")
3826
3827 (define_expand "bleu"
3828 [(set (pc)
3829 (if_then_else (leu (match_dup 1) (const_int 0))
3830 (label_ref (match_operand 0 "" ""))
3831 (pc)))]
3832 ""
3833 "
3834 {
3835 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3836 arm_compare_fp);
3837 }
3838 ")
3839
3840 (define_expand "bgeu"
3841 [(set (pc)
3842 (if_then_else (geu (match_dup 1) (const_int 0))
3843 (label_ref (match_operand 0 "" ""))
3844 (pc)))]
3845 ""
3846 "
3847 {
3848 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
3849 arm_compare_fp);
3850 }
3851 ")
3852
3853 (define_expand "bltu"
3854 [(set (pc)
3855 (if_then_else (ltu (match_dup 1) (const_int 0))
3856 (label_ref (match_operand 0 "" ""))
3857 (pc)))]
3858 ""
3859 "
3860 {
3861 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
3862 arm_compare_fp);
3863 }
3864 ")
3865
3866 ;; patterns to match conditional branch insns
3867
3868 (define_insn "*condbranch"
3869 [(set (pc)
3870 (if_then_else (match_operator 1 "comparison_operator"
3871 [(match_operand 2 "cc_register" "") (const_int 0)])
3872 (label_ref (match_operand 0 "" ""))
3873 (pc)))]
3874 ""
3875 "*
3876 {
3877 extern int arm_ccfsm_state;
3878
3879 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3880 {
3881 arm_ccfsm_state += 2;
3882 return \"\";
3883 }
3884 return \"b%d1\\t%l0\";
3885 }"
3886 [(set_attr "conds" "use")])
3887
3888 (define_insn "*condbranch_reversed"
3889 [(set (pc)
3890 (if_then_else (match_operator 1 "comparison_operator"
3891 [(match_operand 2 "cc_register" "") (const_int 0)])
3892 (pc)
3893 (label_ref (match_operand 0 "" ""))))]
3894 ""
3895 "*
3896 {
3897 extern int arm_ccfsm_state;
3898
3899 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
3900 {
3901 arm_ccfsm_state += 2;
3902 return \"\";
3903 }
3904 return \"b%D1\\t%l0\";
3905 }"
3906 [(set_attr "conds" "use")])
3907 \f
3908
3909 ; scc insns
3910
3911 (define_expand "seq"
3912 [(set (match_operand:SI 0 "s_register_operand" "=r")
3913 (eq:SI (match_dup 1) (const_int 0)))]
3914 ""
3915 "
3916 {
3917 operands[1] = gen_compare_reg (EQ, arm_compare_op0, arm_compare_op1,
3918 arm_compare_fp);
3919 }
3920 ")
3921
3922 (define_expand "sne"
3923 [(set (match_operand:SI 0 "s_register_operand" "=r")
3924 (ne:SI (match_dup 1) (const_int 0)))]
3925 ""
3926 "
3927 {
3928 operands[1] = gen_compare_reg (NE, arm_compare_op0, arm_compare_op1,
3929 arm_compare_fp);
3930 }
3931 ")
3932
3933 (define_expand "sgt"
3934 [(set (match_operand:SI 0 "s_register_operand" "=r")
3935 (gt:SI (match_dup 1) (const_int 0)))]
3936 ""
3937 "
3938 {
3939 operands[1] = gen_compare_reg (GT, arm_compare_op0, arm_compare_op1,
3940 arm_compare_fp);
3941 }
3942 ")
3943
3944 (define_expand "sle"
3945 [(set (match_operand:SI 0 "s_register_operand" "=r")
3946 (le:SI (match_dup 1) (const_int 0)))]
3947 ""
3948 "
3949 {
3950 operands[1] = gen_compare_reg (LE, arm_compare_op0, arm_compare_op1,
3951 arm_compare_fp);
3952 }
3953 ")
3954
3955 (define_expand "sge"
3956 [(set (match_operand:SI 0 "s_register_operand" "=r")
3957 (ge:SI (match_dup 1) (const_int 0)))]
3958 ""
3959 "
3960 {
3961 operands[1] = gen_compare_reg (GE, arm_compare_op0, arm_compare_op1,
3962 arm_compare_fp);
3963 }
3964 ")
3965
3966 (define_expand "slt"
3967 [(set (match_operand:SI 0 "s_register_operand" "=r")
3968 (lt:SI (match_dup 1) (const_int 0)))]
3969 ""
3970 "
3971 {
3972 operands[1] = gen_compare_reg (LT, arm_compare_op0, arm_compare_op1,
3973 arm_compare_fp);
3974 }
3975 ")
3976
3977 (define_expand "sgtu"
3978 [(set (match_operand:SI 0 "s_register_operand" "=r")
3979 (gtu:SI (match_dup 1) (const_int 0)))]
3980 ""
3981 "
3982 {
3983 operands[1] = gen_compare_reg (GTU, arm_compare_op0, arm_compare_op1,
3984 arm_compare_fp);
3985 }
3986 ")
3987
3988 (define_expand "sleu"
3989 [(set (match_operand:SI 0 "s_register_operand" "=r")
3990 (leu:SI (match_dup 1) (const_int 0)))]
3991 ""
3992 "
3993 {
3994 operands[1] = gen_compare_reg (LEU, arm_compare_op0, arm_compare_op1,
3995 arm_compare_fp);
3996 }
3997 ")
3998
3999 (define_expand "sgeu"
4000 [(set (match_operand:SI 0 "s_register_operand" "=r")
4001 (geu:SI (match_dup 1) (const_int 0)))]
4002 ""
4003 "
4004 {
4005 operands[1] = gen_compare_reg (GEU, arm_compare_op0, arm_compare_op1,
4006 arm_compare_fp);
4007 }
4008 ")
4009
4010 (define_expand "sltu"
4011 [(set (match_operand:SI 0 "s_register_operand" "=r")
4012 (ltu:SI (match_dup 1) (const_int 0)))]
4013 ""
4014 "
4015 {
4016 operands[1] = gen_compare_reg (LTU, arm_compare_op0, arm_compare_op1,
4017 arm_compare_fp);
4018 }
4019 ")
4020
4021 (define_insn "*mov_scc"
4022 [(set (match_operand:SI 0 "s_register_operand" "=r")
4023 (match_operator:SI 1 "comparison_operator"
4024 [(match_operand 2 "cc_register" "") (const_int 0)]))]
4025 ""
4026 "mov%D1\\t%0, #0\;mov%d1\\t%0, #1"
4027 [(set_attr "conds" "use")
4028 (set_attr "length" "8")])
4029
4030 (define_insn "*mov_negscc"
4031 [(set (match_operand:SI 0 "s_register_operand" "=r")
4032 (neg:SI (match_operator:SI 1 "comparison_operator"
4033 [(match_operand 2 "cc_register" "") (const_int 0)])))]
4034 ""
4035 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #0"
4036 [(set_attr "conds" "use")
4037 (set_attr "length" "8")])
4038
4039 (define_insn "*mov_notscc"
4040 [(set (match_operand:SI 0 "s_register_operand" "=r")
4041 (not:SI (match_operator:SI 1 "comparison_operator"
4042 [(match_operand 2 "cc_register" "") (const_int 0)])))]
4043 ""
4044 "mov%D1\\t%0, #0\;mvn%d1\\t%0, #1"
4045 [(set_attr "conds" "use")
4046 (set_attr "length" "8")])
4047
4048 \f
4049 ;; Conditional move insns
4050
4051 (define_expand "movsicc"
4052 [(set (match_operand:SI 0 "s_register_operand" "")
4053 (if_then_else:SI (match_operand 1 "comparison_operator" "")
4054 (match_operand:SI 2 "arm_not_operand" "")
4055 (match_operand:SI 3 "arm_not_operand" "")))]
4056 ""
4057 "
4058 {
4059 enum rtx_code code = GET_CODE (operands[1]);
4060 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4061 arm_compare_fp);
4062
4063 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4064 }")
4065
4066 (define_expand "movsfcc"
4067 [(set (match_operand:SF 0 "s_register_operand" "")
4068 (if_then_else:SF (match_operand 1 "comparison_operator" "")
4069 (match_operand:SF 2 "s_register_operand" "")
4070 (match_operand:SF 3 "nonmemory_operand" "")))]
4071 ""
4072 "
4073 {
4074 enum rtx_code code = GET_CODE (operands[1]);
4075 rtx ccreg;
4076
4077 /* When compiling for SOFT_FLOAT, ensure both arms are in registers.
4078 Otherwise, ensure it is a valid FP add operand */
4079 if ((! TARGET_HARD_FLOAT)
4080 || (! fpu_add_operand (operands[3], SFmode)))
4081 operands[3] = force_reg (SFmode, operands[3]);
4082
4083 ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4084 arm_compare_fp);
4085
4086 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4087 }")
4088
4089 (define_expand "movdfcc"
4090 [(set (match_operand:DF 0 "s_register_operand" "")
4091 (if_then_else:DF (match_operand 1 "comparison_operator" "")
4092 (match_operand:DF 2 "s_register_operand" "")
4093 (match_operand:DF 3 "fpu_add_operand" "")))]
4094 "TARGET_HARD_FLOAT"
4095 "
4096 {
4097 enum rtx_code code = GET_CODE (operands[1]);
4098 rtx ccreg = gen_compare_reg (code, arm_compare_op0, arm_compare_op1,
4099 arm_compare_fp);
4100
4101 operands[1] = gen_rtx (code, VOIDmode, ccreg, const0_rtx);
4102 }")
4103
4104 (define_insn "*movsicc_insn"
4105 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r,r,r,r,r")
4106 (if_then_else:SI
4107 (match_operator 3 "comparison_operator"
4108 [(match_operand 4 "cc_register" "") (const_int 0)])
4109 (match_operand:SI 1 "arm_not_operand" "0,0,rI,K,rI,rI,K,K")
4110 (match_operand:SI 2 "arm_not_operand" "rI,K,0,0,rI,K,rI,K")))]
4111 ""
4112 "@
4113 mov%D3\\t%0, %2
4114 mvn%D3\\t%0, #%B2
4115 mov%d3\\t%0, %1
4116 mvn%d3\\t%0, #%B1
4117 mov%d3\\t%0, %1\;mov%D3\\t%0, %2
4118 mov%d3\\t%0, %1\;mvn%D3\\t%0, #%B2
4119 mvn%d3\\t%0, #%B1\;mov%D3\\t%0, %2
4120 mvn%d3\\t%0, #%B1\;mvn%D3\\t%0, #%B2"
4121 [(set_attr "length" "4,4,4,4,8,8,8,8")
4122 (set_attr "conds" "use")])
4123
4124 (define_insn "*movsfcc_hard_insn"
4125 [(set (match_operand:SF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4126 (if_then_else:SF
4127 (match_operator 3 "comparison_operator"
4128 [(match_operand 4 "cc_register" "") (const_int 0)])
4129 (match_operand:SF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4130 (match_operand:SF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4131 "TARGET_HARD_FLOAT"
4132 "@
4133 mvf%D3s\\t%0, %2
4134 mnf%D3s\\t%0, #%N2
4135 mvf%d3s\\t%0, %1
4136 mnf%d3s\\t%0, #%N1
4137 mvf%d3s\\t%0, %1\;mvf%D3s\\t%0, %2
4138 mvf%d3s\\t%0, %1\;mnf%D3s\\t%0, #%N2
4139 mnf%d3s\\t%0, #%N1\;mvf%D3s\\t%0, %2
4140 mnf%d3s\\t%0, #%N1\;mnf%D3s\\t%0, #%N2"
4141 [(set_attr "length" "4,4,4,4,8,8,8,8")
4142 (set_attr "type" "ffarith")
4143 (set_attr "conds" "use")])
4144
4145 (define_insn "*movsfcc_soft_insn"
4146 [(set (match_operand:SF 0 "s_register_operand" "=r,r")
4147 (if_then_else:SF (match_operator 3 "comparison_operator"
4148 [(match_operand 4 "cc_register" "") (const_int 0)])
4149 (match_operand:SF 1 "s_register_operand" "0,r")
4150 (match_operand:SF 2 "s_register_operand" "r,0")))]
4151 "TARGET_SOFT_FLOAT"
4152 "@
4153 mov%D3\\t%0, %2
4154 mov%d3\\t%0, %1"
4155 [(set_attr "conds" "use")])
4156
4157 (define_insn "*movdfcc_insn"
4158 [(set (match_operand:DF 0 "s_register_operand" "=f,f,f,f,f,f,f,f")
4159 (if_then_else:DF
4160 (match_operator 3 "comparison_operator"
4161 [(match_operand 4 "cc_register" "") (const_int 0)])
4162 (match_operand:DF 1 "fpu_add_operand" "0,0,fG,H,fG,fG,H,H")
4163 (match_operand:DF 2 "fpu_add_operand" "fG,H,0,0,fG,H,fG,H")))]
4164 "TARGET_HARD_FLOAT"
4165 "@
4166 mvf%D3d\\t%0, %2
4167 mnf%D3d\\t%0, #%N2
4168 mvf%d3d\\t%0, %1
4169 mnf%d3d\\t%0, #%N1
4170 mvf%d3d\\t%0, %1\;mvf%D3d\\t%0, %2
4171 mvf%d3d\\t%0, %1\;mnf%D3d\\t%0, #%N2
4172 mnf%d3d\\t%0, #%N1\;mvf%D3d\\t%0, %2
4173 mnf%d3d\\t%0, #%N1\;mnf%D3d\\t%0, #%N2"
4174 [(set_attr "length" "4,4,4,4,8,8,8,8")
4175 (set_attr "type" "ffarith")
4176 (set_attr "conds" "use")])
4177 \f
4178 ;; Jump and linkage insns
4179
4180 (define_insn "jump"
4181 [(set (pc)
4182 (label_ref (match_operand 0 "" "")))]
4183 ""
4184 "*
4185 {
4186 extern int arm_ccfsm_state;
4187
4188 if (arm_ccfsm_state == 1 || arm_ccfsm_state == 2)
4189 {
4190 arm_ccfsm_state += 2;
4191 return \"\";
4192 }
4193 return \"b%?\\t%l0\";
4194 }")
4195
4196 (define_expand "call"
4197 [(parallel [(call (match_operand 0 "memory_operand" "")
4198 (match_operand 1 "general_operand" ""))
4199 (clobber (reg:SI 14))])]
4200 ""
4201 "")
4202
4203 (define_insn "*call_reg"
4204 [(call (mem:SI (match_operand:SI 0 "s_register_operand" "r"))
4205 (match_operand 1 "" "g"))
4206 (clobber (reg:SI 14))]
4207 ""
4208 "*
4209 return output_call (operands);
4210 "
4211 ;; length is worst case, normally it is only two
4212 [(set_attr "length" "12")
4213 (set_attr "type" "call")])
4214
4215 (define_insn "*call_mem"
4216 [(call (mem:SI (match_operand 0 "memory_operand" "m"))
4217 (match_operand 1 "general_operand" "g"))
4218 (clobber (reg:SI 14))]
4219 ""
4220 "*
4221 return output_call_mem (operands);
4222 "
4223 [(set_attr "length" "12")
4224 (set_attr "type" "call")])
4225
4226 (define_expand "call_value"
4227 [(parallel [(set (match_operand 0 "" "=rf")
4228 (call (match_operand 1 "memory_operand" "m")
4229 (match_operand 2 "general_operand" "g")))
4230 (clobber (reg:SI 14))])]
4231 ""
4232 "")
4233
4234 (define_insn "*call_value_reg"
4235 [(set (match_operand 0 "" "=rf")
4236 (call (mem:SI (match_operand:SI 1 "s_register_operand" "r"))
4237 (match_operand 2 "general_operand" "g")))
4238 (clobber (reg:SI 14))]
4239 ""
4240 "*
4241 return output_call (&operands[1]);
4242 "
4243 [(set_attr "length" "12")
4244 (set_attr "type" "call")])
4245
4246 (define_insn "*call_value_mem"
4247 [(set (match_operand 0 "" "=rf")
4248 (call (mem:SI (match_operand 1 "memory_operand" "m"))
4249 (match_operand 2 "general_operand" "g")))
4250 (clobber (reg:SI 14))]
4251 "! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))"
4252 "*
4253 return output_call_mem (&operands[1]);
4254 "
4255 [(set_attr "length" "12")
4256 (set_attr "type" "call")])
4257
4258 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
4259 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
4260
4261 (define_insn "*call_symbol"
4262 [(call (mem:SI (match_operand:SI 0 "" "X"))
4263 (match_operand:SI 1 "general_operand" "g"))
4264 (clobber (reg:SI 14))]
4265 "GET_CODE (operands[0]) == SYMBOL_REF"
4266 "bl%?\\t%a0"
4267 [(set_attr "type" "call")])
4268
4269 (define_insn "*call_value_symbol"
4270 [(set (match_operand 0 "s_register_operand" "=rf")
4271 (call (mem:SI (match_operand:SI 1 "" "X"))
4272 (match_operand:SI 2 "general_operand" "g")))
4273 (clobber (reg:SI 14))]
4274 "GET_CODE(operands[1]) == SYMBOL_REF"
4275 "bl%?\\t%a1"
4276 [(set_attr "type" "call")])
4277
4278 ;; Often the return insn will be the same as loading from memory, so set attr
4279 (define_insn "return"
4280 [(return)]
4281 "USE_RETURN_INSN(FALSE)"
4282 "*
4283 {
4284 extern int arm_ccfsm_state;
4285
4286 if (arm_ccfsm_state == 2)
4287 {
4288 arm_ccfsm_state += 2;
4289 return \"\";
4290 }
4291 return output_return_instruction (NULL, TRUE, FALSE);
4292 }"
4293 [(set_attr "type" "load")])
4294
4295 (define_insn "*cond_return"
4296 [(set (pc)
4297 (if_then_else (match_operator 0 "comparison_operator"
4298 [(match_operand 1 "cc_register" "") (const_int 0)])
4299 (return)
4300 (pc)))]
4301 "USE_RETURN_INSN(TRUE)"
4302 "*
4303 {
4304 extern int arm_ccfsm_state;
4305
4306 if (arm_ccfsm_state == 2)
4307 {
4308 arm_ccfsm_state += 2;
4309 return \"\";
4310 }
4311 return output_return_instruction (operands[0], TRUE, FALSE);
4312 }"
4313 [(set_attr "conds" "use")
4314 (set_attr "type" "load")])
4315
4316 (define_insn "*cond_return_inverted"
4317 [(set (pc)
4318 (if_then_else (match_operator 0 "comparison_operator"
4319 [(match_operand 1 "cc_register" "") (const_int 0)])
4320 (pc)
4321 (return)))]
4322 "USE_RETURN_INSN(TRUE)"
4323 "*
4324 {
4325 extern int arm_ccfsm_state;
4326
4327 if (arm_ccfsm_state == 2)
4328 {
4329 arm_ccfsm_state += 2;
4330 return \"\";
4331 }
4332 return output_return_instruction (operands[0], TRUE, TRUE);
4333 }"
4334 [(set_attr "conds" "use")
4335 (set_attr "type" "load")])
4336
4337 ;; Call subroutine returning any type.
4338
4339 (define_expand "untyped_call"
4340 [(parallel [(call (match_operand 0 "" "")
4341 (const_int 0))
4342 (match_operand 1 "" "")
4343 (match_operand 2 "" "")])]
4344 ""
4345 "
4346 {
4347 int i;
4348
4349 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
4350
4351 for (i = 0; i < XVECLEN (operands[2], 0); i++)
4352 {
4353 rtx set = XVECEXP (operands[2], 0, i);
4354 emit_move_insn (SET_DEST (set), SET_SRC (set));
4355 }
4356
4357 /* The optimizer does not know that the call sets the function value
4358 registers we stored in the result block. We avoid problems by
4359 claiming that all hard registers are used and clobbered at this
4360 point. */
4361 emit_insn (gen_blockage ());
4362
4363 DONE;
4364 }")
4365
4366 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
4367 ;; all of memory. This blocks insns from being moved across this point.
4368
4369 (define_insn "blockage"
4370 [(unspec_volatile [(const_int 0)] 0)]
4371 ""
4372 ""
4373 [(set_attr "length" "0")
4374 (set_attr "type" "block")])
4375
4376 (define_expand "casesi"
4377 [(match_operand:SI 0 "s_register_operand" "") ; index to jump on
4378 (match_operand:SI 1 "const_int_operand" "") ; lower bound
4379 (match_operand:SI 2 "const_int_operand" "") ; total range
4380 (match_operand:SI 3 "" "") ; table label
4381 (match_operand:SI 4 "" "")] ; Out of range label
4382 ""
4383 "
4384 {
4385 rtx reg;
4386 if (operands[1] != const0_rtx)
4387 {
4388 reg = gen_reg_rtx (SImode);
4389 emit_insn (gen_addsi3 (reg, operands[0],
4390 GEN_INT (-INTVAL (operands[1]))));
4391 operands[0] = reg;
4392 }
4393
4394 if (! const_ok_for_arm (INTVAL (operands[2])))
4395 operands[2] = force_reg (SImode, operands[2]);
4396
4397 emit_jump_insn (gen_casesi_internal (operands[0], operands[2], operands[3],
4398 operands[4]));
4399 DONE;
4400 }")
4401
4402 ;; The USE in this pattern is needed to tell flow analysis that this is
4403 ;; a CASESI insn. It has no other purpose.
4404 (define_insn "casesi_internal"
4405 [(parallel [(set (pc)
4406 (if_then_else
4407 (leu (match_operand:SI 0 "s_register_operand" "r")
4408 (match_operand:SI 1 "arm_rhs_operand" "rI"))
4409 (mem:SI (plus:SI (mult:SI (match_dup 0) (const_int 4))
4410 (label_ref (match_operand 2 "" ""))))
4411 (label_ref (match_operand 3 "" ""))))
4412 (use (label_ref (match_dup 2)))])]
4413 ""
4414 "*
4415 if (flag_pic)
4416 return \"cmp\\t%0, %1\;addls\\t%|pc, %|pc, %0, asl #2\;b\\t%l3\";
4417 return \"cmp\\t%0, %1\;ldrls\\t%|pc, [%|pc, %0, asl #2]\;b\\t%l3\";
4418 "
4419 [(set_attr "conds" "clob")
4420 (set_attr "length" "12")])
4421
4422 (define_insn "indirect_jump"
4423 [(set (pc)
4424 (match_operand:SI 0 "s_register_operand" "r"))]
4425 ""
4426 "mov%?\\t%|pc, %0\\t%@ indirect jump")
4427
4428 (define_insn "*load_indirect_jump"
4429 [(set (pc)
4430 (match_operand:SI 0 "memory_operand" "m"))]
4431 ""
4432 "ldr%?\\t%|pc, %0\\t%@ indirect jump"
4433 [(set_attr "type" "load")])
4434 \f
4435 ;; Misc insns
4436
4437 (define_insn "nop"
4438 [(const_int 0)]
4439 ""
4440 "mov%?\\tr0, r0\\t%@ nop")
4441 \f
4442 ;; Patterns to allow combination of arithmetic, cond code and shifts
4443
4444 (define_insn "*arith_shiftsi"
4445 [(set (match_operand:SI 0 "s_register_operand" "=r")
4446 (match_operator:SI 1 "shiftable_operator"
4447 [(match_operator:SI 3 "shift_operator"
4448 [(match_operand:SI 4 "s_register_operand" "r")
4449 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4450 (match_operand:SI 2 "s_register_operand" "r")]))]
4451 ""
4452 "%i1%?\\t%0, %2, %4%S3")
4453
4454 (define_insn "*arith_shiftsi_compare0"
4455 [(set (reg:CC_NOOV 24)
4456 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4457 [(match_operator:SI 3 "shift_operator"
4458 [(match_operand:SI 4 "s_register_operand" "r")
4459 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4460 (match_operand:SI 2 "s_register_operand" "r")])
4461 (const_int 0)))
4462 (set (match_operand:SI 0 "s_register_operand" "=r")
4463 (match_op_dup 1 [(match_op_dup 3 [(match_dup 4) (match_dup 5)])
4464 (match_dup 2)]))]
4465 ""
4466 "%i1%?s\\t%0, %2, %4%S3"
4467 [(set_attr "conds" "set")])
4468
4469 (define_insn "*arith_shiftsi_compare0_scratch"
4470 [(set (reg:CC_NOOV 24)
4471 (compare:CC_NOOV (match_operator:SI 1 "shiftable_operator"
4472 [(match_operator:SI 3 "shift_operator"
4473 [(match_operand:SI 4 "s_register_operand" "r")
4474 (match_operand:SI 5 "reg_or_int_operand" "rI")])
4475 (match_operand:SI 2 "s_register_operand" "r")])
4476 (const_int 0)))
4477 (clobber (match_scratch:SI 0 "=r"))]
4478 ""
4479 "%i1%?s\\t%0, %2, %4%S3"
4480 [(set_attr "conds" "set")])
4481
4482 (define_insn "*sub_shiftsi"
4483 [(set (match_operand:SI 0 "s_register_operand" "=r")
4484 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4485 (match_operator:SI 2 "shift_operator"
4486 [(match_operand:SI 3 "s_register_operand" "r")
4487 (match_operand:SI 4 "reg_or_int_operand" "rM")])))]
4488 ""
4489 "sub%?\\t%0, %1, %3%S2")
4490
4491 (define_insn "*sub_shiftsi_compare0"
4492 [(set (reg:CC_NOOV 24)
4493 (compare:CC_NOOV
4494 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4495 (match_operator:SI 2 "shift_operator"
4496 [(match_operand:SI 3 "s_register_operand" "r")
4497 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4498 (const_int 0)))
4499 (set (match_operand:SI 0 "s_register_operand" "=r")
4500 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
4501 (match_dup 4)])))]
4502 ""
4503 "sub%?s\\t%0, %1, %3%S2"
4504 [(set_attr "conds" "set")])
4505
4506 (define_insn "*sub_shiftsi_compare0_scratch"
4507 [(set (reg:CC_NOOV 24)
4508 (compare:CC_NOOV
4509 (minus:SI (match_operand:SI 1 "s_register_operand" "r")
4510 (match_operator:SI 2 "shift_operator"
4511 [(match_operand:SI 3 "s_register_operand" "r")
4512 (match_operand:SI 4 "reg_or_int_operand" "rM")]))
4513 (const_int 0)))
4514 (clobber (match_scratch:SI 0 "=r"))]
4515 ""
4516 "sub%?s\\t%0, %1, %3%S2"
4517 [(set_attr "conds" "set")])
4518
4519 ;; These variants of the above insns can occur if the first operand is the
4520 ;; frame pointer and we eliminate that. This is a kludge, but there doesn't
4521 ;; seem to be a way around it. Most of the predicates have to be null
4522 ;; because the format can be generated part way through reload, so
4523 ;; if we don't match it as soon as it becomes available, reload doesn't know
4524 ;; how to reload pseudos that haven't got hard registers; the constraints will
4525 ;; sort everything out.
4526
4527 (define_insn "*reload_mulsi3"
4528 [(set (match_operand:SI 0 "" "=&r")
4529 (plus:SI (plus:SI (match_operator:SI 5 "shift_operator"
4530 [(match_operand:SI 3 "" "r")
4531 (match_operand:SI 4 "" "rM")])
4532 (match_operand:SI 2 "" "r"))
4533 (match_operand:SI 1 "const_int_operand" "n")))]
4534 "reload_in_progress"
4535 "*
4536 output_asm_insn (\"add%?\\t%0, %2, %3%S5\", operands);
4537 operands[2] = operands[1];
4538 operands[1] = operands[0];
4539 return output_add_immediate (operands);
4540 "
4541 ; we have no idea how long the add_immediate is, it could be up to 4.
4542 [(set_attr "length" "20")])
4543
4544 (define_insn "*reload_mulsi_compare0"
4545 [(set (reg:CC_NOOV 24)
4546 (compare:CC_NOOV (plus:SI
4547 (plus:SI
4548 (match_operator:SI 5 "shift_operator"
4549 [(match_operand:SI 3 "" "r")
4550 (match_operand:SI 4 "" "rM")])
4551 (match_operand:SI 1 "" "r"))
4552 (match_operand:SI 2 "const_int_operand" "n"))
4553 (const_int 0)))
4554 (set (match_operand:SI 0 "" "=&r")
4555 (plus:SI (plus:SI (match_op_dup 5 [(match_dup 3) (match_dup 4)])
4556 (match_dup 1))
4557 (match_dup 2)))]
4558 "reload_in_progress"
4559 "*
4560 output_add_immediate (operands);
4561 return \"add%?s\\t%0, %0, %3%S5\";
4562 "
4563 [(set_attr "conds" "set")
4564 (set_attr "length" "20")])
4565
4566 (define_insn "*reload_mulsi_compare0_scratch"
4567 [(set (reg:CC_NOOV 24)
4568 (compare:CC_NOOV (plus:SI
4569 (plus:SI
4570 (match_operator:SI 5 "shift_operator"
4571 [(match_operand:SI 3 "" "r")
4572 (match_operand:SI 4 "" "rM")])
4573 (match_operand:SI 1 "" "r"))
4574 (match_operand:SI 2 "const_int_operand" "n"))
4575 (const_int 0)))
4576 (clobber (match_scratch:SI 0 "=&r"))]
4577 "reload_in_progress"
4578 "*
4579 output_add_immediate (operands);
4580 return \"add%?s\\t%0, %0, %3%S5\";
4581 "
4582 [(set_attr "conds" "set")
4583 (set_attr "length" "20")])
4584
4585 ;; These are similar, but are needed when the mla pattern contains the
4586 ;; eliminated register as operand 3.
4587
4588 (define_insn "*reload_muladdsi"
4589 [(set (match_operand:SI 0 "" "=&r,&r")
4590 (plus:SI (plus:SI (mult:SI (match_operand:SI 1 "" "%0,r")
4591 (match_operand:SI 2 "" "r,r"))
4592 (match_operand:SI 3 "" "r,r"))
4593 (match_operand:SI 4 "const_int_operand" "n,n")))]
4594 "reload_in_progress"
4595 "*
4596 output_asm_insn (\"mla%?\\t%0, %2, %1, %3\", operands);
4597 operands[2] = operands[4];
4598 operands[1] = operands[0];
4599 return output_add_immediate (operands);
4600 "
4601 [(set_attr "length" "20")
4602 (set_attr "type" "mult")])
4603
4604 (define_insn "*reload_muladdsi_compare0"
4605 [(set (reg:CC_NOOV 24)
4606 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4607 (match_operand:SI 3 "" "r")
4608 (match_operand:SI 4 "" "r"))
4609 (match_operand:SI 1 "" "r"))
4610 (match_operand:SI 2 "const_int_operand" "n"))
4611 (const_int 0)))
4612 (set (match_operand:SI 0 "" "=&r")
4613 (plus:SI (plus:SI (mult:SI (match_dup 3) (match_dup 4)) (match_dup 1))
4614 (match_dup 2)))]
4615 "reload_in_progress"
4616 "*
4617 output_add_immediate (operands);
4618 output_asm_insn (\"mla%?s\\t%0, %3, %4, %0\", operands);
4619 return \"\";
4620 "
4621 [(set_attr "length" "20")
4622 (set_attr "conds" "set")
4623 (set_attr "type" "mult")])
4624
4625 (define_insn "*reload_muladdsi_compare0_scratch"
4626 [(set (reg:CC_NOOV 24)
4627 (compare:CC_NOOV (plus:SI (plus:SI (mult:SI
4628 (match_operand:SI 3 "" "r")
4629 (match_operand:SI 4 "" "r"))
4630 (match_operand:SI 1 "" "r"))
4631 (match_operand:SI 2 "const_int_operand" "n"))
4632 (const_int 0)))
4633 (clobber (match_scratch:SI 0 "=&r"))]
4634 "reload_in_progress"
4635 "*
4636 output_add_immediate (operands);
4637 return \"mla%?s\\t%0, %3, %4, %0\";
4638 "
4639 [(set_attr "length" "20")
4640 (set_attr "conds" "set")
4641 (set_attr "type" "mult")])
4642
4643 \f
4644
4645 (define_insn "*and_scc"
4646 [(set (match_operand:SI 0 "s_register_operand" "=r")
4647 (and:SI (match_operator 1 "comparison_operator"
4648 [(match_operand 3 "cc_register" "") (const_int 0)])
4649 (match_operand:SI 2 "s_register_operand" "r")))]
4650 ""
4651 "mov%D1\\t%0, #0\;and%d1\\t%0, %2, #1"
4652 [(set_attr "conds" "use")
4653 (set_attr "length" "8")])
4654
4655 (define_insn "*ior_scc"
4656 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4657 (ior:SI (match_operator 2 "comparison_operator"
4658 [(match_operand 3 "cc_register" "") (const_int 0)])
4659 (match_operand:SI 1 "s_register_operand" "0,?r")))]
4660 ""
4661 "@
4662 orr%d2\\t%0, %1, #1
4663 mov%D2\\t%0, %1\;orr%d2\\t%0, %1, #1"
4664 [(set_attr "conds" "use")
4665 (set_attr "length" "4,8")])
4666
4667 (define_insn "*compare_scc"
4668 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4669 (match_operator 1 "comparison_operator"
4670 [(match_operand:SI 2 "s_register_operand" "r,r")
4671 (match_operand:SI 3 "arm_add_operand" "rI,L")]))
4672 (clobber (reg:CC 24))]
4673 ""
4674 "*
4675 if (GET_CODE (operands[1]) == LT && operands[3] == const0_rtx)
4676 return \"mov\\t%0, %2, lsr #31\";
4677
4678 if (GET_CODE (operands[1]) == GE && operands[3] == const0_rtx)
4679 return \"mvn\\t%0, %2\;mov\\t%0, %0, lsr #31\";
4680
4681 if (GET_CODE (operands[1]) == NE)
4682 {
4683 if (which_alternative == 1)
4684 return \"adds\\t%0, %2, #%n3\;movne\\t%0, #1\";
4685 return \"subs\\t%0, %2, %3\;movne\\t%0, #1\";
4686 }
4687 if (which_alternative == 1)
4688 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
4689 else
4690 output_asm_insn (\"cmp\\t%2, %3\", operands);
4691 return \"mov%D1\\t%0, #0\;mov%d1\\t%0, #1\";
4692 "
4693 [(set_attr "conds" "clob")
4694 (set_attr "length" "12")])
4695
4696 (define_insn "*cond_move"
4697 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4698 (if_then_else:SI (match_operator 3 "equality_operator"
4699 [(match_operator 4 "comparison_operator"
4700 [(match_operand 5 "cc_register" "") (const_int 0)])
4701 (const_int 0)])
4702 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4703 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))]
4704 ""
4705 "*
4706 if (GET_CODE (operands[3]) == NE)
4707 {
4708 if (which_alternative != 1)
4709 output_asm_insn (\"mov%D4\\t%0, %2\", operands);
4710 if (which_alternative != 0)
4711 output_asm_insn (\"mov%d4\\t%0, %1\", operands);
4712 return \"\";
4713 }
4714 if (which_alternative != 0)
4715 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4716 if (which_alternative != 1)
4717 output_asm_insn (\"mov%d4\\t%0, %2\", operands);
4718 return \"\";
4719 "
4720 [(set_attr "conds" "use")
4721 (set_attr "length" "4,4,8")])
4722
4723 (define_insn "*cond_arith"
4724 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4725 (match_operator:SI 5 "shiftable_operator"
4726 [(match_operator:SI 4 "comparison_operator"
4727 [(match_operand:SI 2 "s_register_operand" "r,r")
4728 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
4729 (match_operand:SI 1 "s_register_operand" "0,?r")]))
4730 (clobber (reg:CC 24))]
4731 ""
4732 "*
4733 if (GET_CODE (operands[4]) == LT && operands[3] == const0_rtx)
4734 return \"%i5\\t%0, %1, %2, lsr #31\";
4735
4736 output_asm_insn (\"cmp\\t%2, %3\", operands);
4737 if (GET_CODE (operands[5]) == AND)
4738 output_asm_insn (\"mov%D4\\t%0, #0\", operands);
4739 else if (GET_CODE (operands[5]) == MINUS)
4740 output_asm_insn (\"rsb%D4\\t%0, %1, #0\", operands);
4741 else if (which_alternative != 0)
4742 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4743 return \"%i5%d4\\t%0, %1, #1\";
4744 "
4745 [(set_attr "conds" "clob")
4746 (set_attr "length" "12")])
4747
4748 (define_insn "*cond_sub"
4749 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4750 (minus:SI (match_operand:SI 1 "s_register_operand" "0,?r")
4751 (match_operator:SI 4 "comparison_operator"
4752 [(match_operand:SI 2 "s_register_operand" "r,r")
4753 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
4754 (clobber (reg:CC 24))]
4755 ""
4756 "*
4757 output_asm_insn (\"cmp\\t%2, %3\", operands);
4758 if (which_alternative != 0)
4759 output_asm_insn (\"mov%D4\\t%0, %1\", operands);
4760 return \"sub%d4\\t%0, %1, #1\";
4761 "
4762 [(set_attr "conds" "clob")
4763 (set_attr "length" "8,12")])
4764
4765 (define_insn "*cmp_ite0"
4766 [(set (match_operand 6 "dominant_cc_register" "")
4767 (compare
4768 (if_then_else:SI
4769 (match_operator 4 "comparison_operator"
4770 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4771 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4772 (match_operator:SI 5 "comparison_operator"
4773 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4774 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4775 (const_int 0))
4776 (const_int 0)))]
4777 ""
4778 "*
4779 {
4780 char* opcodes[4][2] =
4781 {
4782 {\"cmp\\t%2, %3\;cmp%d5\\t%0, %1\",\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\"},
4783 {\"cmp\\t%2, %3\;cmn%d5\\t%0, #%n1\", \"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\"},
4784 {\"cmn\\t%2, #%n3\;cmp%d5\\t%0, %1\", \"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\"},
4785 {\"cmn\\t%2, #%n3\;cmn%d5\\t%0, #%n1\",
4786 \"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\"}
4787 };
4788 int swap =
4789 comparison_dominates_p (GET_CODE (operands[5]), GET_CODE (operands[4]));
4790
4791 return opcodes[which_alternative][swap];
4792 }
4793 "
4794 [(set_attr "conds" "set")
4795 (set_attr "length" "8")])
4796
4797 (define_insn "*cmp_ite1"
4798 [(set (match_operand 6 "dominant_cc_register" "")
4799 (compare
4800 (if_then_else:SI
4801 (match_operator 4 "comparison_operator"
4802 [(match_operand:SI 0 "s_register_operand" "r,r,r,r")
4803 (match_operand:SI 1 "arm_add_operand" "rI,L,rI,L")])
4804 (match_operator:SI 5 "comparison_operator"
4805 [(match_operand:SI 2 "s_register_operand" "r,r,r,r")
4806 (match_operand:SI 3 "arm_add_operand" "rI,rI,L,L")])
4807 (const_int 1))
4808 (const_int 0)))]
4809 ""
4810 "*
4811 {
4812 char* opcodes[4][2] =
4813 {
4814 {\"cmp\\t%0, %1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmp%D5\\t%0, %1\"},
4815 {\"cmn\\t%0, #%n1\;cmp%d4\\t%2, %3\", \"cmp\\t%2, %3\;cmn%D5\\t%0, #%n1\"},
4816 {\"cmp\\t%0, %1\;cmn%d4\\t%2, #%n3\", \"cmn\\t%2, #%n3\;cmp%D5\\t%0, %1\"},
4817 {\"cmn\\t%0, #%n1\;cmn%d4\\t%2, #%n3\",
4818 \"cmn\\t%2, #%n3\;cmn%D5\\t%0, #%n1\"}
4819 };
4820 int swap =
4821 comparison_dominates_p (GET_CODE (operands[5]),
4822 reverse_condition (GET_CODE (operands[4])));
4823
4824 return opcodes[which_alternative][swap];
4825 }
4826 "
4827 [(set_attr "conds" "set")
4828 (set_attr "length" "8")])
4829
4830 (define_insn "*negscc"
4831 [(set (match_operand:SI 0 "s_register_operand" "=r")
4832 (neg:SI (match_operator 3 "comparison_operator"
4833 [(match_operand:SI 1 "s_register_operand" "r")
4834 (match_operand:SI 2 "arm_rhs_operand" "rI")])))
4835 (clobber (reg:CC 24))]
4836 ""
4837 "*
4838 if (GET_CODE (operands[3]) == LT && operands[3] == const0_rtx)
4839 return \"mov\\t%0, %1, asr #31\";
4840
4841 if (GET_CODE (operands[3]) == NE)
4842 return \"subs\\t%0, %1, %2\;mvnne\\t%0, #0\";
4843
4844 if (GET_CODE (operands[3]) == GT)
4845 return \"subs\\t%0, %1, %2\;mvnne\\t%0, %0, asr #31\";
4846
4847 output_asm_insn (\"cmp\\t%1, %2\", operands);
4848 output_asm_insn (\"mov%D3\\t%0, #0\", operands);
4849 return \"mvn%d3\\t%0, #0\";
4850 "
4851 [(set_attr "conds" "clob")
4852 (set_attr "length" "12")])
4853
4854 (define_insn "movcond"
4855 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
4856 (if_then_else:SI
4857 (match_operator 5 "comparison_operator"
4858 [(match_operand:SI 3 "s_register_operand" "r,r,r")
4859 (match_operand:SI 4 "arm_add_operand" "rIL,rIL,rIL")])
4860 (match_operand:SI 1 "arm_rhs_operand" "0,rI,?rI")
4861 (match_operand:SI 2 "arm_rhs_operand" "rI,0,rI")))
4862 (clobber (reg:CC 24))]
4863 ""
4864 "*
4865 if (GET_CODE (operands[5]) == LT
4866 && (operands[4] == const0_rtx))
4867 {
4868 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4869 {
4870 if (operands[2] == const0_rtx)
4871 return \"and\\t%0, %1, %3, asr #31\";
4872 return \"ands\\t%0, %1, %3, asr #32\;movcc\\t%0, %2\";
4873 }
4874 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4875 {
4876 if (operands[1] == const0_rtx)
4877 return \"bic\\t%0, %2, %3, asr #31\";
4878 return \"bics\\t%0, %2, %3, asr #32\;movcs\\t%0, %1\";
4879 }
4880 /* The only case that falls through to here is when both ops 1 & 2
4881 are constants */
4882 }
4883
4884 if (GET_CODE (operands[5]) == GE
4885 && (operands[4] == const0_rtx))
4886 {
4887 if (which_alternative != 1 && GET_CODE (operands[1]) == REG)
4888 {
4889 if (operands[2] == const0_rtx)
4890 return \"bic\\t%0, %1, %3, asr #31\";
4891 return \"bics\\t%0, %1, %3, asr #32\;movcs\\t%0, %2\";
4892 }
4893 else if (which_alternative != 0 && GET_CODE (operands[2]) == REG)
4894 {
4895 if (operands[1] == const0_rtx)
4896 return \"and\\t%0, %2, %3, asr #31\";
4897 return \"ands\\t%0, %2, %3, asr #32\;movcc\\t%0, %1\";
4898 }
4899 /* The only case that falls through to here is when both ops 1 & 2
4900 are constants */
4901 }
4902 if (GET_CODE (operands[4]) == CONST_INT
4903 && !const_ok_for_arm (INTVAL (operands[4])))
4904 output_asm_insn (\"cmn\\t%3, #%n4\", operands);
4905 else
4906 output_asm_insn (\"cmp\\t%3, %4\", operands);
4907 if (which_alternative != 0)
4908 output_asm_insn (\"mov%d5\\t%0, %1\", operands);
4909 if (which_alternative != 1)
4910 output_asm_insn (\"mov%D5\\t%0, %2\", operands);
4911 return \"\";
4912 "
4913 [(set_attr "conds" "clob")
4914 (set_attr "length" "8,8,12")])
4915
4916 (define_insn "*ifcompare_plus_move"
4917 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4918 (if_then_else:SI (match_operator 6 "comparison_operator"
4919 [(match_operand:SI 4 "s_register_operand" "r,r")
4920 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4921 (plus:SI
4922 (match_operand:SI 2 "s_register_operand" "r,r")
4923 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))
4924 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
4925 (clobber (reg:CC 24))]
4926 ""
4927 "#"
4928 [(set_attr "conds" "clob")
4929 (set_attr "length" "8,12")])
4930
4931 (define_insn "*if_plus_move"
4932 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4933 (if_then_else:SI
4934 (match_operator 4 "comparison_operator"
4935 [(match_operand 5 "cc_register" "") (const_int 0)])
4936 (plus:SI
4937 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
4938 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))
4939 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")))]
4940 ""
4941 "@
4942 add%d4\\t%0, %2, %3
4943 sub%d4\\t%0, %2, #%n3
4944 add%d4\\t%0, %2, %3\;mov%D4\\t%0, %1
4945 sub%d4\\t%0, %2, #%n3\;mov%D4\\t%0, %1"
4946 [(set_attr "conds" "use")
4947 (set_attr "length" "4,4,8,8")
4948 (set_attr "type" "*,*,*,*")])
4949
4950 (define_insn "*ifcompare_move_plus"
4951 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
4952 (if_then_else:SI (match_operator 6 "comparison_operator"
4953 [(match_operand:SI 4 "s_register_operand" "r,r")
4954 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
4955 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
4956 (plus:SI
4957 (match_operand:SI 2 "s_register_operand" "r,r")
4958 (match_operand:SI 3 "arm_add_operand" "rIL,rIL"))))
4959 (clobber (reg:CC 24))]
4960 ""
4961 "#"
4962 [(set_attr "conds" "clob")
4963 (set_attr "length" "8,12")])
4964
4965 (define_insn "*if_move_plus"
4966 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r,r")
4967 (if_then_else:SI
4968 (match_operator 4 "comparison_operator"
4969 [(match_operand 5 "cc_register" "") (const_int 0)])
4970 (match_operand:SI 1 "arm_rhs_operand" "0,0,?rI,?rI")
4971 (plus:SI
4972 (match_operand:SI 2 "s_register_operand" "r,r,r,r")
4973 (match_operand:SI 3 "arm_add_operand" "rI,L,rI,L"))))]
4974 ""
4975 "@
4976 add%D4\\t%0, %2, %3
4977 sub%D4\\t%0, %2, #%n3
4978 add%D4\\t%0, %2, %3\;mov%d4\\t%0, %1
4979 sub%D4\\t%0, %2, #%n3\;mov%d4\\t%0, %1"
4980 [(set_attr "conds" "use")
4981 (set_attr "length" "4,4,8,8")
4982 (set_attr "type" "*,*,*,*")])
4983
4984 (define_insn "*ifcompare_arith_arith"
4985 [(set (match_operand:SI 0 "s_register_operand" "=r")
4986 (if_then_else:SI (match_operator 9 "comparison_operator"
4987 [(match_operand:SI 5 "s_register_operand" "r")
4988 (match_operand:SI 6 "arm_add_operand" "rIL")])
4989 (match_operator:SI 8 "shiftable_operator"
4990 [(match_operand:SI 1 "s_register_operand" "r")
4991 (match_operand:SI 2 "arm_rhs_operand" "rI")])
4992 (match_operator:SI 7 "shiftable_operator"
4993 [(match_operand:SI 3 "s_register_operand" "r")
4994 (match_operand:SI 4 "arm_rhs_operand" "rI")])))
4995 (clobber (reg:CC 24))]
4996 ""
4997 "#"
4998 [(set_attr "conds" "clob")
4999 (set_attr "length" "12")])
5000
5001 (define_insn "*if_arith_arith"
5002 [(set (match_operand:SI 0 "s_register_operand" "=r")
5003 (if_then_else:SI (match_operator 5 "comparison_operator"
5004 [(match_operand 8 "cc_register" "") (const_int 0)])
5005 (match_operator:SI 6 "shiftable_operator"
5006 [(match_operand:SI 1 "s_register_operand" "r")
5007 (match_operand:SI 2 "arm_rhs_operand" "rI")])
5008 (match_operator:SI 7 "shiftable_operator"
5009 [(match_operand:SI 3 "s_register_operand" "r")
5010 (match_operand:SI 4 "arm_rhs_operand" "rI")])))]
5011 ""
5012 "%I6%d5\\t%0, %1, %2\;%I7%D5\\t%0, %3, %4"
5013 [(set_attr "conds" "use")
5014 (set_attr "length" "8")])
5015
5016 (define_insn "*ifcompare_arith_move"
5017 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5018 (if_then_else:SI (match_operator 6 "comparison_operator"
5019 [(match_operand:SI 2 "s_register_operand" "r,r")
5020 (match_operand:SI 3 "arm_add_operand" "rIL,rIL")])
5021 (match_operator:SI 7 "shiftable_operator"
5022 [(match_operand:SI 4 "s_register_operand" "r,r")
5023 (match_operand:SI 5 "arm_rhs_operand" "rI,rI")])
5024 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))
5025 (clobber (reg:CC 24))]
5026 ""
5027 "*
5028 /* If we have an operation where (op x 0) is the identity operation and
5029 the conditional operator is LT or GE and we are comparing against zero and
5030 everything is in registers then we can do this in two instructions */
5031 if (operands[3] == const0_rtx
5032 && GET_CODE (operands[7]) != AND
5033 && GET_CODE (operands[5]) == REG
5034 && GET_CODE (operands[1]) == REG
5035 && REGNO (operands[1]) == REGNO (operands[4])
5036 && REGNO (operands[4]) != REGNO (operands[0]))
5037 {
5038 if (GET_CODE (operands[6]) == LT)
5039 return \"and\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5040 else if (GET_CODE (operands[6]) == GE)
5041 return \"bic\\t%0, %5, %2, asr #31\;%I7\\t%0, %4, %0\";
5042 }
5043 if (GET_CODE (operands[3]) == CONST_INT
5044 && !const_ok_for_arm (INTVAL (operands[3])))
5045 output_asm_insn (\"cmn\\t%2, #%n3\", operands);
5046 else
5047 output_asm_insn (\"cmp\\t%2, %3\", operands);
5048 output_asm_insn (\"%I7%d6\\t%0, %4, %5\", operands);
5049 if (which_alternative != 0)
5050 return \"mov%D6\\t%0, %1\";
5051 return \"\";
5052 "
5053 [(set_attr "conds" "clob")
5054 (set_attr "length" "8,12")])
5055
5056 (define_insn "*if_arith_move"
5057 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5058 (if_then_else:SI (match_operator 4 "comparison_operator"
5059 [(match_operand 6 "cc_register" "") (const_int 0)])
5060 (match_operator:SI 5 "shiftable_operator"
5061 [(match_operand:SI 2 "s_register_operand" "r,r")
5062 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])
5063 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")))]
5064 ""
5065 "@
5066 %I5%d4\\t%0, %2, %3
5067 %I5%d4\\t%0, %2, %3\;mov%D4\\t%0, %1"
5068 [(set_attr "conds" "use")
5069 (set_attr "length" "4,8")
5070 (set_attr "type" "*,*")])
5071
5072 (define_insn "*ifcompare_move_arith"
5073 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5074 (if_then_else:SI (match_operator 6 "comparison_operator"
5075 [(match_operand:SI 4 "s_register_operand" "r,r")
5076 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5077 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5078 (match_operator:SI 7 "shiftable_operator"
5079 [(match_operand:SI 2 "s_register_operand" "r,r")
5080 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))
5081 (clobber (reg:CC 24))]
5082 ""
5083 "*
5084 /* If we have an operation where (op x 0) is the identity operation and
5085 the conditional operator is LT or GE and we are comparing against zero and
5086 everything is in registers then we can do this in two instructions */
5087 if (operands[5] == const0_rtx
5088 && GET_CODE (operands[7]) != AND
5089 && GET_CODE (operands[3]) == REG
5090 && GET_CODE (operands[1]) == REG
5091 && REGNO (operands[1]) == REGNO (operands[2])
5092 && REGNO (operands[2]) != REGNO (operands[0]))
5093 {
5094 if (GET_CODE (operands[6]) == GE)
5095 return \"and\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5096 else if (GET_CODE (operands[6]) == LT)
5097 return \"bic\\t%0, %3, %4, asr #31\;%I7\\t%0, %2, %0\";
5098 }
5099
5100 if (GET_CODE (operands[5]) == CONST_INT
5101 && !const_ok_for_arm (INTVAL (operands[5])))
5102 output_asm_insn (\"cmn\\t%4, #%n5\", operands);
5103 else
5104 output_asm_insn (\"cmp\\t%4, %5\", operands);
5105
5106 if (which_alternative != 0)
5107 output_asm_insn (\"mov%d6\\t%0, %1\", operands);
5108 return \"%I7%D6\\t%0, %2, %3\";
5109 "
5110 [(set_attr "conds" "clob")
5111 (set_attr "length" "8,12")])
5112
5113 (define_insn "*if_move_arith"
5114 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5115 (if_then_else:SI
5116 (match_operator 4 "comparison_operator"
5117 [(match_operand 6 "cc_register" "") (const_int 0)])
5118 (match_operand:SI 1 "arm_rhs_operand" "0,?rI")
5119 (match_operator:SI 5 "shiftable_operator"
5120 [(match_operand:SI 2 "s_register_operand" "r,r")
5121 (match_operand:SI 3 "arm_rhs_operand" "rI,rI")])))]
5122 ""
5123 "@
5124 %I5%D4\\t%0, %2, %3
5125 %I5%D4\\t%0, %2, %3\;mov%d4\\t%0, %1"
5126 [(set_attr "conds" "use")
5127 (set_attr "length" "4,8")
5128 (set_attr "type" "*,*")])
5129
5130 (define_insn "*ifcompare_move_not"
5131 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5132 (if_then_else:SI
5133 (match_operator 5 "comparison_operator"
5134 [(match_operand:SI 3 "s_register_operand" "r,r")
5135 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5136 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5137 (not:SI
5138 (match_operand:SI 2 "s_register_operand" "r,r"))))
5139 (clobber (reg:CC 24))]
5140 ""
5141 "#"
5142 [(set_attr "conds" "clob")
5143 (set_attr "length" "8,12")])
5144
5145 (define_insn "*if_move_not"
5146 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5147 (if_then_else:SI
5148 (match_operator 4 "comparison_operator"
5149 [(match_operand 3 "cc_register" "") (const_int 0)])
5150 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5151 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5152 ""
5153 "@
5154 mvn%D4\\t%0, %2
5155 mov%d4\\t%0, %1\;mvn%D4\\t%0, %2
5156 mvn%d4\\t%0, #%B1\;mvn%D4\\t%0, %2"
5157 [(set_attr "conds" "use")
5158 (set_attr "length" "4,8,8")])
5159
5160 (define_insn "*ifcompare_not_move"
5161 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5162 (if_then_else:SI
5163 (match_operator 5 "comparison_operator"
5164 [(match_operand:SI 3 "s_register_operand" "r,r")
5165 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5166 (not:SI
5167 (match_operand:SI 2 "s_register_operand" "r,r"))
5168 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5169 (clobber (reg:CC 24))]
5170 ""
5171 "#"
5172 [(set_attr "conds" "clob")
5173 (set_attr "length" "8,12")])
5174
5175 (define_insn "*if_not_move"
5176 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5177 (if_then_else:SI
5178 (match_operator 4 "comparison_operator"
5179 [(match_operand 3 "cc_register" "") (const_int 0)])
5180 (not:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5181 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5182 ""
5183 "@
5184 mvn%d4\\t%0, %2
5185 mov%D4\\t%0, %1\;mvn%d4\\t%0, %2
5186 mvn%D4\\t%0, #%B1\;mvn%d4\\t%0, %2"
5187 [(set_attr "conds" "use")
5188 (set_attr "length" "4,8,8")])
5189
5190 (define_insn "*ifcompare_shift_move"
5191 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5192 (if_then_else:SI
5193 (match_operator 6 "comparison_operator"
5194 [(match_operand:SI 4 "s_register_operand" "r,r")
5195 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5196 (match_operator:SI 7 "shift_operator"
5197 [(match_operand:SI 2 "s_register_operand" "r,r")
5198 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])
5199 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5200 (clobber (reg:CC 24))]
5201 ""
5202 "#"
5203 [(set_attr "conds" "clob")
5204 (set_attr "length" "8,12")])
5205
5206 (define_insn "*if_shift_move"
5207 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5208 (if_then_else:SI
5209 (match_operator 5 "comparison_operator"
5210 [(match_operand 6 "cc_register" "") (const_int 0)])
5211 (match_operator:SI 4 "shift_operator"
5212 [(match_operand:SI 2 "s_register_operand" "r,r,r")
5213 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])
5214 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5215 ""
5216 "@
5217 mov%d5\\t%0, %2%S4
5218 mov%D5\\t%0, %1\;mov%d5\\t%0, %2%S4
5219 mvn%D5\\t%0, #%B1\;mov%d5\\t%0, %2%S4"
5220 [(set_attr "conds" "use")
5221 (set_attr "length" "4,8,8")])
5222
5223 (define_insn "*ifcompare_move_shift"
5224 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5225 (if_then_else:SI
5226 (match_operator 6 "comparison_operator"
5227 [(match_operand:SI 4 "s_register_operand" "r,r")
5228 (match_operand:SI 5 "arm_add_operand" "rIL,rIL")])
5229 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5230 (match_operator:SI 7 "shift_operator"
5231 [(match_operand:SI 2 "s_register_operand" "r,r")
5232 (match_operand:SI 3 "arm_rhs_operand" "rM,rM")])))
5233 (clobber (reg:CC 24))]
5234 ""
5235 "#"
5236 [(set_attr "conds" "clob")
5237 (set_attr "length" "8,12")])
5238
5239 (define_insn "*if_move_shift"
5240 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5241 (if_then_else:SI
5242 (match_operator 5 "comparison_operator"
5243 [(match_operand 6 "cc_register" "") (const_int 0)])
5244 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5245 (match_operator:SI 4 "shift_operator"
5246 [(match_operand:SI 2 "s_register_operand" "r,r,r")
5247 (match_operand:SI 3 "arm_rhs_operand" "rM,rM,rM")])))]
5248 ""
5249 "@
5250 mov%D5\\t%0, %2%S4
5251 mov%d5\\t%0, %1\;mov%D5\\t%0, %2%S4
5252 mvn%d5\\t%0, #%B1\;mov%D5\\t%0, %2%S4"
5253 [(set_attr "conds" "use")
5254 (set_attr "length" "4,8,8")])
5255
5256 (define_insn "*ifcompare_shift_shift"
5257 [(set (match_operand:SI 0 "s_register_operand" "=r")
5258 (if_then_else:SI
5259 (match_operator 7 "comparison_operator"
5260 [(match_operand:SI 5 "s_register_operand" "r")
5261 (match_operand:SI 6 "arm_add_operand" "rIL")])
5262 (match_operator:SI 8 "shift_operator"
5263 [(match_operand:SI 1 "s_register_operand" "r")
5264 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5265 (match_operator:SI 9 "shift_operator"
5266 [(match_operand:SI 3 "s_register_operand" "r")
5267 (match_operand:SI 4 "arm_rhs_operand" "rM")])))
5268 (clobber (reg:CC 24))]
5269 ""
5270 "#"
5271 [(set_attr "conds" "clob")
5272 (set_attr "length" "12")])
5273
5274 (define_insn "*if_shift_shift"
5275 [(set (match_operand:SI 0 "s_register_operand" "=r")
5276 (if_then_else:SI
5277 (match_operator 5 "comparison_operator"
5278 [(match_operand 8 "cc_register" "") (const_int 0)])
5279 (match_operator:SI 6 "shift_operator"
5280 [(match_operand:SI 1 "s_register_operand" "r")
5281 (match_operand:SI 2 "arm_rhs_operand" "rM")])
5282 (match_operator:SI 7 "shift_operator"
5283 [(match_operand:SI 3 "s_register_operand" "r")
5284 (match_operand:SI 4 "arm_rhs_operand" "rM")])))]
5285 ""
5286 "mov%d5\\t%0, %1%S6\;mov%D5\\t%0, %3%S7"
5287 [(set_attr "conds" "use")
5288 (set_attr "length" "8")])
5289
5290 (define_insn "*ifcompare_not_arith"
5291 [(set (match_operand:SI 0 "s_register_operand" "=r")
5292 (if_then_else:SI
5293 (match_operator 6 "comparison_operator"
5294 [(match_operand:SI 4 "s_register_operand" "r")
5295 (match_operand:SI 5 "arm_add_operand" "rIL")])
5296 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5297 (match_operator:SI 7 "shiftable_operator"
5298 [(match_operand:SI 2 "s_register_operand" "r")
5299 (match_operand:SI 3 "arm_rhs_operand" "rI")])))
5300 (clobber (reg:CC 24))]
5301 ""
5302 "#"
5303 [(set_attr "conds" "clob")
5304 (set_attr "length" "12")])
5305
5306 (define_insn "*if_not_arith"
5307 [(set (match_operand:SI 0 "s_register_operand" "=r")
5308 (if_then_else:SI
5309 (match_operator 5 "comparison_operator"
5310 [(match_operand 4 "cc_register" "") (const_int 0)])
5311 (not:SI (match_operand:SI 1 "s_register_operand" "r"))
5312 (match_operator:SI 6 "shiftable_operator"
5313 [(match_operand:SI 2 "s_register_operand" "r")
5314 (match_operand:SI 3 "arm_rhs_operand" "rI")])))]
5315 ""
5316 "mvn%d5\\t%0, %1\;%I6%D5\\t%0, %2, %3"
5317 [(set_attr "conds" "use")
5318 (set_attr "length" "8")])
5319
5320 (define_insn "*ifcompare_arith_not"
5321 [(set (match_operand:SI 0 "s_register_operand" "=r")
5322 (if_then_else:SI
5323 (match_operator 6 "comparison_operator"
5324 [(match_operand:SI 4 "s_register_operand" "r")
5325 (match_operand:SI 5 "arm_add_operand" "rIL")])
5326 (match_operator:SI 7 "shiftable_operator"
5327 [(match_operand:SI 2 "s_register_operand" "r")
5328 (match_operand:SI 3 "arm_rhs_operand" "rI")])
5329 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))
5330 (clobber (reg:CC 24))]
5331 ""
5332 "#"
5333 [(set_attr "conds" "clob")
5334 (set_attr "length" "12")])
5335
5336 (define_insn "*if_arith_not"
5337 [(set (match_operand:SI 0 "s_register_operand" "=r")
5338 (if_then_else:SI
5339 (match_operator 5 "comparison_operator"
5340 [(match_operand 4 "cc_register" "") (const_int 0)])
5341 (match_operator:SI 6 "shiftable_operator"
5342 [(match_operand:SI 2 "s_register_operand" "r")
5343 (match_operand:SI 3 "arm_rhs_operand" "rI")])
5344 (not:SI (match_operand:SI 1 "s_register_operand" "r"))))]
5345 ""
5346 "mvn%D5\\t%0, %1\;%I6%d5\\t%0, %2, %3"
5347 [(set_attr "conds" "use")
5348 (set_attr "length" "8")])
5349
5350 (define_insn "*ifcompare_neg_move"
5351 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5352 (if_then_else:SI
5353 (match_operator 5 "comparison_operator"
5354 [(match_operand:SI 3 "s_register_operand" "r,r")
5355 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5356 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))
5357 (match_operand:SI 1 "arm_not_operand" "0,?rIK")))
5358 (clobber (reg:CC 24))]
5359 ""
5360 "#"
5361 [(set_attr "conds" "clob")
5362 (set_attr "length" "8,12")])
5363
5364 (define_insn "*if_neg_move"
5365 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5366 (if_then_else:SI
5367 (match_operator 4 "comparison_operator"
5368 [(match_operand 3 "cc_register" "") (const_int 0)])
5369 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))
5370 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")))]
5371 ""
5372 "@
5373 rsb%d4\\t%0, %2, #0
5374 mov%D4\\t%0, %1\;rsb%d4\\t%0, %2, #0
5375 mvn%D4\\t%0, #%B1\;rsb%d4\\t%0, %2, #0"
5376 [(set_attr "conds" "use")
5377 (set_attr "length" "4,8,8")])
5378
5379 (define_insn "*ifcompare_move_neg"
5380 [(set (match_operand:SI 0 "s_register_operand" "=r,r")
5381 (if_then_else:SI
5382 (match_operator 5 "comparison_operator"
5383 [(match_operand:SI 3 "s_register_operand" "r,r")
5384 (match_operand:SI 4 "arm_add_operand" "rIL,rIL")])
5385 (match_operand:SI 1 "arm_not_operand" "0,?rIK")
5386 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r"))))
5387 (clobber (reg:CC 24))]
5388 ""
5389 "#"
5390 [(set_attr "conds" "clob")
5391 (set_attr "length" "8,12")])
5392
5393 (define_insn "*if_move_neg"
5394 [(set (match_operand:SI 0 "s_register_operand" "=r,r,r")
5395 (if_then_else:SI
5396 (match_operator 4 "comparison_operator"
5397 [(match_operand 3 "cc_register" "") (const_int 0)])
5398 (match_operand:SI 1 "arm_not_operand" "0,?rI,K")
5399 (neg:SI (match_operand:SI 2 "s_register_operand" "r,r,r"))))]
5400 ""
5401 "@
5402 rsb%D4\\t%0, %2, #0
5403 mov%d4\\t%0, %1\;rsb%D4\\t%0, %2, #0
5404 mvn%d4\\t%0, #%B1\;rsb%D4\\t%0, %2, #0"
5405 [(set_attr "conds" "use")
5406 (set_attr "length" "4,8,8")])
5407
5408 (define_insn "*arith_adjacentmem"
5409 [(set (match_operand:SI 0 "s_register_operand" "=r")
5410 (match_operator:SI 1 "shiftable_operator"
5411 [(match_operand:SI 2 "memory_operand" "m")
5412 (match_operand:SI 3 "memory_operand" "m")]))
5413 (clobber (match_scratch:SI 4 "=r"))]
5414 "adjacent_mem_locations (operands[2], operands[3])"
5415 "*
5416 {
5417 rtx ldm[3];
5418 rtx arith[4];
5419 int val1 = 0, val2 = 0;
5420
5421 if (REGNO (operands[0]) > REGNO (operands[4]))
5422 {
5423 ldm[1] = operands[4];
5424 ldm[2] = operands[0];
5425 }
5426 else
5427 {
5428 ldm[1] = operands[0];
5429 ldm[2] = operands[4];
5430 }
5431 if (GET_CODE (XEXP (operands[2], 0)) != REG)
5432 val1 = INTVAL (XEXP (XEXP (operands[2], 0), 1));
5433 if (GET_CODE (XEXP (operands[3], 0)) != REG)
5434 val2 = INTVAL (XEXP (XEXP (operands[3], 0), 1));
5435 arith[0] = operands[0];
5436 arith[3] = operands[1];
5437 if (val1 < val2)
5438 {
5439 arith[1] = ldm[1];
5440 arith[2] = ldm[2];
5441 }
5442 else
5443 {
5444 arith[1] = ldm[2];
5445 arith[2] = ldm[1];
5446 }
5447 if (val1 && val2)
5448 {
5449 rtx ops[3];
5450 ldm[0] = ops[0] = operands[4];
5451 ops[1] = XEXP (XEXP (operands[2], 0), 0);
5452 ops[2] = XEXP (XEXP (operands[2], 0), 1);
5453 output_add_immediate (ops);
5454 if (val1 < val2)
5455 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5456 else
5457 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5458 }
5459 else if (val1)
5460 {
5461 ldm[0] = XEXP (operands[3], 0);
5462 if (val1 < val2)
5463 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5464 else
5465 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5466 }
5467 else
5468 {
5469 ldm[0] = XEXP (operands[2], 0);
5470 if (val1 < val2)
5471 output_asm_insn (\"ldm%?ia\\t%0, {%1, %2}\", ldm);
5472 else
5473 output_asm_insn (\"ldm%?da\\t%0, {%1, %2}\", ldm);
5474 }
5475 output_asm_insn (\"%I3%?\\t%0, %1, %2\", arith);
5476 return \"\";
5477 }
5478 "
5479 [(set_attr "length" "12")
5480 (set_attr "type" "load")])
5481
5482 ;; the arm can support extended pre-inc instructions
5483
5484 ;; In all these cases, we use operands 0 and 1 for the register being
5485 ;; incremented because those are the operands that local-alloc will
5486 ;; tie and these are the pair most likely to be tieable (and the ones
5487 ;; that will benefit the most).
5488
5489 ;; We reject the frame pointer if it occurs anywhere in these patterns since
5490 ;; elimination will cause too many headaches.
5491
5492 (define_insn "*strqi_preinc"
5493 [(set (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5494 (match_operand:SI 2 "index_operand" "rJ")))
5495 (match_operand:QI 3 "s_register_operand" "r"))
5496 (set (match_operand:SI 0 "s_register_operand" "=r")
5497 (plus:SI (match_dup 1) (match_dup 2)))]
5498 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5499 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5500 && (GET_CODE (operands[2]) != REG
5501 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5502 "str%?b\\t%3, [%0, %2]!"
5503 [(set_attr "type" "store1")])
5504
5505 (define_insn "*strqi_predec"
5506 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5507 (match_operand:SI 2 "s_register_operand" "r")))
5508 (match_operand:QI 3 "s_register_operand" "r"))
5509 (set (match_operand:SI 0 "s_register_operand" "=r")
5510 (minus:SI (match_dup 1) (match_dup 2)))]
5511 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5512 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5513 && (GET_CODE (operands[2]) != REG
5514 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5515 "str%?b\\t%3, [%0, -%2]!"
5516 [(set_attr "type" "store1")])
5517
5518 (define_insn "*loadqi_preinc"
5519 [(set (match_operand:QI 3 "s_register_operand" "=r")
5520 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5521 (match_operand:SI 2 "index_operand" "rJ"))))
5522 (set (match_operand:SI 0 "s_register_operand" "=r")
5523 (plus:SI (match_dup 1) (match_dup 2)))]
5524 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5525 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5526 && (GET_CODE (operands[2]) != REG
5527 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5528 "ldr%?b\\t%3, [%0, %2]!"
5529 [(set_attr "type" "load")])
5530
5531 (define_insn "*loadqi_predec"
5532 [(set (match_operand:QI 3 "s_register_operand" "=r")
5533 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5534 (match_operand:SI 2 "s_register_operand" "r"))))
5535 (set (match_operand:SI 0 "s_register_operand" "=r")
5536 (minus:SI (match_dup 1) (match_dup 2)))]
5537 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5538 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5539 && (GET_CODE (operands[2]) != REG
5540 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5541 "ldr%?b\\t%3, [%0, -%2]!"
5542 [(set_attr "type" "load")])
5543
5544 (define_insn "*loadqisi_preinc"
5545 [(set (match_operand:SI 3 "s_register_operand" "=r")
5546 (zero_extend:SI
5547 (mem:QI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5548 (match_operand:SI 2 "index_operand" "rJ")))))
5549 (set (match_operand:SI 0 "s_register_operand" "=r")
5550 (plus:SI (match_dup 1) (match_dup 2)))]
5551 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5552 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5553 && (GET_CODE (operands[2]) != REG
5554 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5555 "ldr%?b\\t%3, [%0, %2]!\\t%@ z_extendqisi"
5556 [(set_attr "type" "load")])
5557
5558 (define_insn "*loadqisi_predec"
5559 [(set (match_operand:SI 3 "s_register_operand" "=r")
5560 (zero_extend:SI
5561 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5562 (match_operand:SI 2 "s_register_operand" "r")))))
5563 (set (match_operand:SI 0 "s_register_operand" "=r")
5564 (minus:SI (match_dup 1) (match_dup 2)))]
5565 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5566 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5567 && (GET_CODE (operands[2]) != REG
5568 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5569 "ldr%?b\\t%3, [%0, -%2]!\\t%@ z_extendqisi"
5570 [(set_attr "type" "load")])
5571
5572 (define_insn "*strsi_preinc"
5573 [(set (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5574 (match_operand:SI 2 "index_operand" "rJ")))
5575 (match_operand:SI 3 "s_register_operand" "r"))
5576 (set (match_operand:SI 0 "s_register_operand" "=r")
5577 (plus:SI (match_dup 1) (match_dup 2)))]
5578 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5579 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5580 && (GET_CODE (operands[2]) != REG
5581 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5582 "str%?\\t%3, [%0, %2]!"
5583 [(set_attr "type" "store1")])
5584
5585 (define_insn "*strqi_predec"
5586 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5587 (match_operand:SI 2 "s_register_operand" "r")))
5588 (match_operand:SI 3 "s_register_operand" "r"))
5589 (set (match_operand:SI 0 "s_register_operand" "=r")
5590 (minus:SI (match_dup 1) (match_dup 2)))]
5591 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5592 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5593 && (GET_CODE (operands[2]) != REG
5594 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5595 "str%?\\t%3, [%0, -%2]!"
5596 [(set_attr "type" "store1")])
5597
5598 (define_insn "*loadsi_preinc"
5599 [(set (match_operand:SI 3 "s_register_operand" "=r")
5600 (mem:SI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5601 (match_operand:SI 2 "index_operand" "rJ"))))
5602 (set (match_operand:SI 0 "s_register_operand" "=r")
5603 (plus:SI (match_dup 1) (match_dup 2)))]
5604 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5605 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5606 && (GET_CODE (operands[2]) != REG
5607 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5608 "ldr%?\\t%3, [%0, %2]!"
5609 [(set_attr "type" "load")])
5610
5611 (define_insn "*loadsi_predec"
5612 [(set (match_operand:SI 3 "s_register_operand" "=r")
5613 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5614 (match_operand:SI 2 "s_register_operand" "r"))))
5615 (set (match_operand:SI 0 "s_register_operand" "=r")
5616 (minus:SI (match_dup 1) (match_dup 2)))]
5617 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5618 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5619 && (GET_CODE (operands[2]) != REG
5620 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5621 "ldr%?\\t%3, [%0, -%2]!"
5622 [(set_attr "type" "load")])
5623
5624 (define_insn "*loadhi_preinc"
5625 [(set (match_operand:HI 3 "s_register_operand" "=r")
5626 (mem:HI (plus:SI (match_operand:SI 1 "s_register_operand" "%0")
5627 (match_operand:SI 2 "index_operand" "rJ"))))
5628 (set (match_operand:SI 0 "s_register_operand" "=r")
5629 (plus:SI (match_dup 1) (match_dup 2)))]
5630 "(! BYTES_BIG_ENDIAN)
5631 && ! TARGET_SHORT_BY_BYTES
5632 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5633 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5634 && (GET_CODE (operands[2]) != REG
5635 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5636 "ldr%?\\t%3, [%0, %2]!\\t%@ loadhi"
5637 [(set_attr "type" "load")])
5638
5639 (define_insn "*loadhi_predec"
5640 [(set (match_operand:HI 3 "s_register_operand" "=r")
5641 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5642 (match_operand:SI 2 "s_register_operand" "r"))))
5643 (set (match_operand:SI 0 "s_register_operand" "=r")
5644 (minus:SI (match_dup 1) (match_dup 2)))]
5645 "(!BYTES_BIG_ENDIAN)
5646 && ! TARGET_SHORT_BY_BYTES
5647 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5648 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5649 && (GET_CODE (operands[2]) != REG
5650 || REGNO (operands[2]) != FRAME_POINTER_REGNUM)"
5651 "ldr%?\\t%3, [%0, -%2]!\\t%@ loadhi"
5652 [(set_attr "type" "load")])
5653
5654 (define_insn "*strqi_shiftpreinc"
5655 [(set (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5656 [(match_operand:SI 3 "s_register_operand" "r")
5657 (match_operand:SI 4 "const_shift_operand" "n")])
5658 (match_operand:SI 1 "s_register_operand" "0")))
5659 (match_operand:QI 5 "s_register_operand" "r"))
5660 (set (match_operand:SI 0 "s_register_operand" "=r")
5661 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5662 (match_dup 1)))]
5663 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5664 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5665 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5666 "str%?b\\t%5, [%0, %3%S2]!"
5667 [(set_attr "type" "store1")])
5668
5669 (define_insn "*strqi_shiftpredec"
5670 [(set (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5671 (match_operator:SI 2 "shift_operator"
5672 [(match_operand:SI 3 "s_register_operand" "r")
5673 (match_operand:SI 4 "const_shift_operand" "n")])))
5674 (match_operand:QI 5 "s_register_operand" "r"))
5675 (set (match_operand:SI 0 "s_register_operand" "=r")
5676 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5677 (match_dup 4)])))]
5678 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5679 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5680 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5681 "str%?b\\t%5, [%0, -%3%S2]!"
5682 [(set_attr "type" "store1")])
5683
5684 (define_insn "*loadqi_shiftpreinc"
5685 [(set (match_operand:QI 5 "s_register_operand" "=r")
5686 (mem:QI (plus:SI (match_operator:SI 2 "shift_operator"
5687 [(match_operand:SI 3 "s_register_operand" "r")
5688 (match_operand:SI 4 "const_shift_operand" "n")])
5689 (match_operand:SI 1 "s_register_operand" "0"))))
5690 (set (match_operand:SI 0 "s_register_operand" "=r")
5691 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5692 (match_dup 1)))]
5693 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5694 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5695 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5696 "ldr%?b\\t%5, [%0, %3%S2]!"
5697 [(set_attr "type" "load")])
5698
5699 (define_insn "*loadqi_shiftpredec"
5700 [(set (match_operand:QI 5 "s_register_operand" "=r")
5701 (mem:QI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5702 (match_operator:SI 2 "shift_operator"
5703 [(match_operand:SI 3 "s_register_operand" "r")
5704 (match_operand:SI 4 "const_shift_operand" "n")]))))
5705 (set (match_operand:SI 0 "s_register_operand" "=r")
5706 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5707 (match_dup 4)])))]
5708 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5709 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5710 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5711 "ldr%?b\\t%5, [%0, -%3%S2]!"
5712 [(set_attr "type" "load")])
5713
5714 (define_insn "*strsi_shiftpreinc"
5715 [(set (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5716 [(match_operand:SI 3 "s_register_operand" "r")
5717 (match_operand:SI 4 "const_shift_operand" "n")])
5718 (match_operand:SI 1 "s_register_operand" "0")))
5719 (match_operand:SI 5 "s_register_operand" "r"))
5720 (set (match_operand:SI 0 "s_register_operand" "=r")
5721 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5722 (match_dup 1)))]
5723 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5724 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5725 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5726 "str%?\\t%5, [%0, %3%S2]!"
5727 [(set_attr "type" "store1")])
5728
5729 (define_insn "*strsi_shiftpredec"
5730 [(set (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5731 (match_operator:SI 2 "shift_operator"
5732 [(match_operand:SI 3 "s_register_operand" "r")
5733 (match_operand:SI 4 "const_shift_operand" "n")])))
5734 (match_operand:SI 5 "s_register_operand" "r"))
5735 (set (match_operand:SI 0 "s_register_operand" "=r")
5736 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5737 (match_dup 4)])))]
5738 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5739 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5740 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5741 "str%?\\t%5, [%0, -%3%S2]!"
5742 [(set_attr "type" "store1")])
5743
5744 (define_insn "*loadqi_shiftpreinc"
5745 [(set (match_operand:SI 5 "s_register_operand" "=r")
5746 (mem:SI (plus:SI (match_operator:SI 2 "shift_operator"
5747 [(match_operand:SI 3 "s_register_operand" "r")
5748 (match_operand:SI 4 "const_shift_operand" "n")])
5749 (match_operand:SI 1 "s_register_operand" "0"))))
5750 (set (match_operand:SI 0 "s_register_operand" "=r")
5751 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5752 (match_dup 1)))]
5753 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5754 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5755 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5756 "ldr%?\\t%5, [%0, %3%S2]!"
5757 [(set_attr "type" "load")])
5758
5759 (define_insn "*loadqi_shiftpredec"
5760 [(set (match_operand:SI 5 "s_register_operand" "=r")
5761 (mem:SI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5762 (match_operator:SI 2 "shift_operator"
5763 [(match_operand:SI 3 "s_register_operand" "r")
5764 (match_operand:SI 4 "const_shift_operand" "n")]))))
5765 (set (match_operand:SI 0 "s_register_operand" "=r")
5766 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5767 (match_dup 4)])))]
5768 "REGNO (operands[0]) != FRAME_POINTER_REGNUM
5769 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5770 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5771 "ldr%?\\t%5, [%0, -%3%S2]!"
5772 [(set_attr "type" "load")])
5773
5774 (define_insn "*loadhi_shiftpreinc"
5775 [(set (match_operand:HI 5 "s_register_operand" "=r")
5776 (mem:HI (plus:SI (match_operator:SI 2 "shift_operator"
5777 [(match_operand:SI 3 "s_register_operand" "r")
5778 (match_operand:SI 4 "const_shift_operand" "n")])
5779 (match_operand:SI 1 "s_register_operand" "0"))))
5780 (set (match_operand:SI 0 "s_register_operand" "=r")
5781 (plus:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
5782 (match_dup 1)))]
5783 "(! BYTES_BIG_ENDIAN)
5784 && ! TARGET_SHORT_BY_BYTES
5785 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5786 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5787 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5788 "ldr%?\\t%5, [%0, %3%S2]!\\t%@ loadhi"
5789 [(set_attr "type" "load")])
5790
5791 (define_insn "*loadhi_shiftpredec"
5792 [(set (match_operand:HI 5 "s_register_operand" "=r")
5793 (mem:HI (minus:SI (match_operand:SI 1 "s_register_operand" "0")
5794 (match_operator:SI 2 "shift_operator"
5795 [(match_operand:SI 3 "s_register_operand" "r")
5796 (match_operand:SI 4 "const_shift_operand" "n")]))))
5797 (set (match_operand:SI 0 "s_register_operand" "=r")
5798 (minus:SI (match_dup 1) (match_op_dup 2 [(match_dup 3)
5799 (match_dup 4)])))]
5800 "(! BYTES_BIG_ENDIAN)
5801 && ! TARGET_SHORT_BY_BYTES
5802 && REGNO (operands[0]) != FRAME_POINTER_REGNUM
5803 && REGNO (operands[1]) != FRAME_POINTER_REGNUM
5804 && REGNO (operands[3]) != FRAME_POINTER_REGNUM"
5805 "ldr%?\\t%5, [%0, -%3%S2]!\\t%@ loadhi"
5806 [(set_attr "type" "load")])
5807
5808 ; It can also support extended post-inc expressions, but combine doesn't
5809 ; try these....
5810 ; It doesn't seem worth adding peepholes for anything but the most common
5811 ; cases since, unlike combine, the increment must immediately follow the load
5812 ; for this pattern to match.
5813 ; When loading we must watch to see that the base register isn't trampled by
5814 ; the load. In such cases this isn't a post-inc expression.
5815
5816 (define_peephole
5817 [(set (mem:QI (match_operand:SI 0 "s_register_operand" "+r"))
5818 (match_operand:QI 2 "s_register_operand" "r"))
5819 (set (match_dup 0)
5820 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5821 ""
5822 "str%?b\\t%2, [%0], %1")
5823
5824 (define_peephole
5825 [(set (match_operand:QI 0 "s_register_operand" "=r")
5826 (mem:QI (match_operand:SI 1 "s_register_operand" "+r")))
5827 (set (match_dup 1)
5828 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5829 "REGNO(operands[0]) != REGNO(operands[1])
5830 && (GET_CODE (operands[2]) != REG
5831 || REGNO(operands[0]) != REGNO (operands[2]))"
5832 "ldr%?b\\t%0, [%1], %2")
5833
5834 (define_peephole
5835 [(set (mem:SI (match_operand:SI 0 "s_register_operand" "+r"))
5836 (match_operand:SI 2 "s_register_operand" "r"))
5837 (set (match_dup 0)
5838 (plus:SI (match_dup 0) (match_operand:SI 1 "index_operand" "rJ")))]
5839 ""
5840 "str%?\\t%2, [%0], %1")
5841
5842 (define_peephole
5843 [(set (match_operand:HI 0 "s_register_operand" "=r")
5844 (mem:HI (match_operand:SI 1 "s_register_operand" "+r")))
5845 (set (match_dup 1)
5846 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5847 "(! BYTES_BIG_ENDIAN)
5848 && ! TARGET_SHORT_BY_BYTES
5849 && REGNO(operands[0]) != REGNO(operands[1])
5850 && (GET_CODE (operands[2]) != REG
5851 || REGNO(operands[0]) != REGNO (operands[2]))"
5852 "ldr%?\\t%0, [%1], %2\\t%@ loadhi")
5853
5854 (define_peephole
5855 [(set (match_operand:SI 0 "s_register_operand" "=r")
5856 (mem:SI (match_operand:SI 1 "s_register_operand" "+r")))
5857 (set (match_dup 1)
5858 (plus:SI (match_dup 1) (match_operand:SI 2 "index_operand" "rJ")))]
5859 "REGNO(operands[0]) != REGNO(operands[1])
5860 && (GET_CODE (operands[2]) != REG
5861 || REGNO(operands[0]) != REGNO (operands[2]))"
5862 "ldr%?\\t%0, [%1], %2")
5863
5864 (define_peephole
5865 [(set (mem:QI (plus:SI (match_operand:SI 0 "s_register_operand" "+r")
5866 (match_operand:SI 1 "index_operand" "rJ")))
5867 (match_operand:QI 2 "s_register_operand" "r"))
5868 (set (match_dup 0) (plus:SI (match_dup 0) (match_dup 1)))]
5869 ""
5870 "str%?b\\t%2, [%0, %1]!")
5871
5872 (define_peephole
5873 [(set (mem:QI (plus:SI (match_operator:SI 4 "shift_operator"
5874 [(match_operand:SI 0 "s_register_operand" "r")
5875 (match_operand:SI 1 "const_int_operand" "n")])
5876 (match_operand:SI 2 "s_register_operand" "+r")))
5877 (match_operand:QI 3 "s_register_operand" "r"))
5878 (set (match_dup 2) (plus:SI (match_op_dup 4 [(match_dup 0) (match_dup 1)])
5879 (match_dup 2)))]
5880 ""
5881 "str%?b\\t%3, [%2, %0%S4]!")
5882
5883 ; This pattern is never tried by combine, so do it as a peephole
5884
5885 (define_peephole
5886 [(set (match_operand:SI 0 "s_register_operand" "=r")
5887 (match_operand:SI 1 "s_register_operand" "r"))
5888 (set (reg:CC 24)
5889 (compare:CC (match_dup 1) (const_int 0)))]
5890 ""
5891 "sub%?s\\t%0, %1, #0"
5892 [(set_attr "conds" "set")])
5893
5894 ; Peepholes to spot possible load- and store-multiples, if the ordering is
5895 ; reversed, check that the memory references aren't volatile.
5896
5897 (define_peephole
5898 [(set (match_operand:SI 0 "s_register_operand" "=r")
5899 (match_operand:SI 4 "memory_operand" "m"))
5900 (set (match_operand:SI 1 "s_register_operand" "=r")
5901 (match_operand:SI 5 "memory_operand" "m"))
5902 (set (match_operand:SI 2 "s_register_operand" "=r")
5903 (match_operand:SI 6 "memory_operand" "m"))
5904 (set (match_operand:SI 3 "s_register_operand" "=r")
5905 (match_operand:SI 7 "memory_operand" "m"))]
5906 "load_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5907 "*
5908 return emit_ldm_seq (operands, 4);
5909 ")
5910
5911 (define_peephole
5912 [(set (match_operand:SI 0 "s_register_operand" "=r")
5913 (match_operand:SI 3 "memory_operand" "m"))
5914 (set (match_operand:SI 1 "s_register_operand" "=r")
5915 (match_operand:SI 4 "memory_operand" "m"))
5916 (set (match_operand:SI 2 "s_register_operand" "=r")
5917 (match_operand:SI 5 "memory_operand" "m"))]
5918 "load_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5919 "*
5920 return emit_ldm_seq (operands, 3);
5921 ")
5922
5923 (define_peephole
5924 [(set (match_operand:SI 0 "s_register_operand" "=r")
5925 (match_operand:SI 2 "memory_operand" "m"))
5926 (set (match_operand:SI 1 "s_register_operand" "=r")
5927 (match_operand:SI 3 "memory_operand" "m"))]
5928 "load_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5929 "*
5930 return emit_ldm_seq (operands, 2);
5931 ")
5932
5933 (define_peephole
5934 [(set (match_operand:SI 4 "memory_operand" "=m")
5935 (match_operand:SI 0 "s_register_operand" "r"))
5936 (set (match_operand:SI 5 "memory_operand" "=m")
5937 (match_operand:SI 1 "s_register_operand" "r"))
5938 (set (match_operand:SI 6 "memory_operand" "=m")
5939 (match_operand:SI 2 "s_register_operand" "r"))
5940 (set (match_operand:SI 7 "memory_operand" "=m")
5941 (match_operand:SI 3 "s_register_operand" "r"))]
5942 "store_multiple_sequence (operands, 4, NULL, NULL, NULL)"
5943 "*
5944 return emit_stm_seq (operands, 4);
5945 ")
5946
5947 (define_peephole
5948 [(set (match_operand:SI 3 "memory_operand" "=m")
5949 (match_operand:SI 0 "s_register_operand" "r"))
5950 (set (match_operand:SI 4 "memory_operand" "=m")
5951 (match_operand:SI 1 "s_register_operand" "r"))
5952 (set (match_operand:SI 5 "memory_operand" "=m")
5953 (match_operand:SI 2 "s_register_operand" "r"))]
5954 "store_multiple_sequence (operands, 3, NULL, NULL, NULL)"
5955 "*
5956 return emit_stm_seq (operands, 3);
5957 ")
5958
5959 (define_peephole
5960 [(set (match_operand:SI 2 "memory_operand" "=m")
5961 (match_operand:SI 0 "s_register_operand" "r"))
5962 (set (match_operand:SI 3 "memory_operand" "=m")
5963 (match_operand:SI 1 "s_register_operand" "r"))]
5964 "store_multiple_sequence (operands, 2, NULL, NULL, NULL)"
5965 "*
5966 return emit_stm_seq (operands, 2);
5967 ")
5968
5969 ;; A call followed by return can be replaced by restoring the regs and
5970 ;; jumping to the subroutine, provided we aren't passing the address of
5971 ;; any of our local variables. If we call alloca then this is unsafe
5972 ;; since restoring the frame frees the memory, which is not what we want.
5973 ;; Sometimes the return might have been targeted by the final prescan:
5974 ;; if so then emit a proper return insn as well.
5975 ;; Unfortunately, if the frame pointer is required, we don't know if the
5976 ;; current function has any implicit stack pointer adjustments that will
5977 ;; be restored by the return: we can't therefore do a tail call.
5978 ;; Another unfortunate that we can't handle is if current_function_args_size
5979 ;; is non-zero: in this case elimination of the argument pointer assumed
5980 ;; that lr was pushed onto the stack, so eliminating upsets the offset
5981 ;; calculations.
5982
5983 (define_peephole
5984 [(parallel [(call (mem:SI (match_operand:SI 0 "" "X"))
5985 (match_operand:SI 1 "general_operand" "g"))
5986 (clobber (reg:SI 14))])
5987 (return)]
5988 "(GET_CODE (operands[0]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
5989 && !get_frame_size () && !current_function_calls_alloca
5990 && !frame_pointer_needed && !current_function_args_size)"
5991 "*
5992 {
5993 extern rtx arm_target_insn;
5994 extern int arm_ccfsm_state;
5995
5996 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
5997 {
5998 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
5999 output_return_instruction (NULL, TRUE, FALSE);
6000 arm_ccfsm_state = 0;
6001 arm_target_insn = NULL;
6002 }
6003
6004 output_return_instruction (NULL, FALSE, FALSE);
6005 return \"b%?\\t%a0\";
6006 }"
6007 [(set_attr "type" "call")
6008 (set_attr "length" "8")])
6009
6010 (define_peephole
6011 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6012 (call (mem:SI (match_operand:SI 1 "" "X"))
6013 (match_operand:SI 2 "general_operand" "g")))
6014 (clobber (reg:SI 14))])
6015 (return)]
6016 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
6017 && !get_frame_size () && !current_function_calls_alloca
6018 && !frame_pointer_needed && !current_function_args_size)"
6019 "*
6020 {
6021 extern rtx arm_target_insn;
6022 extern int arm_ccfsm_state;
6023
6024 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6025 {
6026 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6027 output_return_instruction (NULL, TRUE, FALSE);
6028 arm_ccfsm_state = 0;
6029 arm_target_insn = NULL;
6030 }
6031
6032 output_return_instruction (NULL, FALSE, FALSE);
6033 return \"b%?\\t%a1\";
6034 }"
6035 [(set_attr "type" "call")
6036 (set_attr "length" "8")])
6037
6038 ;; As above but when this function is not void, we must be returning the
6039 ;; result of the called subroutine.
6040
6041 (define_peephole
6042 [(parallel [(set (match_operand 0 "s_register_operand" "=rf")
6043 (call (mem:SI (match_operand:SI 1 "" "X"))
6044 (match_operand:SI 2 "general_operand" "g")))
6045 (clobber (reg:SI 14))])
6046 (use (match_dup 0))
6047 (return)]
6048 "(GET_CODE (operands[1]) == SYMBOL_REF && USE_RETURN_INSN(FALSE)
6049 && !get_frame_size () && !current_function_calls_alloca
6050 && !frame_pointer_needed && !current_function_args_size)"
6051 "*
6052 {
6053 extern rtx arm_target_insn;
6054 extern int arm_ccfsm_state;
6055
6056 if (arm_ccfsm_state && arm_target_insn && INSN_DELETED_P (arm_target_insn))
6057 {
6058 arm_current_cc = ARM_INVERSE_CONDITION_CODE (arm_current_cc);
6059 output_return_instruction (NULL, TRUE, FALSE);
6060 arm_ccfsm_state = 0;
6061 arm_target_insn = NULL;
6062 }
6063
6064 output_return_instruction (NULL, FALSE, FALSE);
6065 return \"b%?\\t%a1\";
6066 }"
6067 [(set_attr "type" "call")
6068 (set_attr "length" "8")])
6069
6070 (define_split
6071 [(set (match_operand:SI 0 "s_register_operand" "")
6072 (and:SI (ge:SI (match_operand:SI 1 "s_register_operand" "")
6073 (const_int 0))
6074 (neg:SI (match_operator:SI 2 "comparison_operator"
6075 [(match_operand:SI 3 "s_register_operand" "")
6076 (match_operand:SI 4 "arm_rhs_operand" "")]))))
6077 (clobber (match_operand:SI 5 "s_register_operand" ""))]
6078 ""
6079 [(set (match_dup 5) (not:SI (ashiftrt:SI (match_dup 1) (const_int 31))))
6080 (set (match_dup 0) (and:SI (match_op_dup 2 [(match_dup 3) (match_dup 4)])
6081 (match_dup 5)))]
6082 "")
6083
6084 ;; This split can be used because CC_Z mode implies that the following
6085 ;; branch will be an equality, or an unsigned inequality, so the sign
6086 ;; extension is not needed.
6087
6088 (define_split
6089 [(set (reg:CC_Z 24)
6090 (compare:CC_Z
6091 (ashift:SI (subreg:SI (match_operand:QI 0 "memory_operand" "") 0)
6092 (const_int 24))
6093 (match_operand 1 "const_int_operand" "")))
6094 (clobber (match_scratch:SI 2 ""))]
6095 "((unsigned HOST_WIDE_INT) INTVAL (operands[1]))
6096 == (((unsigned HOST_WIDE_INT) INTVAL (operands[1])) >> 24) << 24"
6097 [(set (match_dup 2) (zero_extend:SI (match_dup 0)))
6098 (set (reg:CC 24) (compare:CC (match_dup 2) (match_dup 1)))]
6099 "
6100 operands[1] = GEN_INT (((unsigned long) INTVAL (operands[1])) >> 24);
6101 ")
6102
6103 (define_expand "prologue"
6104 [(clobber (const_int 0))]
6105 ""
6106 "
6107 arm_expand_prologue ();
6108 DONE;
6109 ")
6110
6111 ;; This split is only used during output to reduce the number of patterns
6112 ;; that need assembler instructions adding to them. We allowed the setting
6113 ;; of the conditions to be implicit during rtl generation so that
6114 ;; the conditional compare patterns would work. However this conflicts to
6115 ;; some extent with the conditional data operations, so we have to split them
6116 ;; up again here.
6117
6118 (define_split
6119 [(set (match_operand:SI 0 "s_register_operand" "")
6120 (if_then_else:SI (match_operator 1 "comparison_operator"
6121 [(match_operand 2 "" "") (match_operand 3 "" "")])
6122 (match_operand 4 "" "")
6123 (match_operand 5 "" "")))
6124 (clobber (reg:CC 24))]
6125 "reload_completed"
6126 [(set (match_dup 6) (match_dup 7))
6127 (set (match_dup 0)
6128 (if_then_else:SI (match_op_dup 1 [(match_dup 6) (const_int 0)])
6129 (match_dup 4)
6130 (match_dup 5)))]
6131 "
6132 {
6133 enum machine_mode mode = SELECT_CC_MODE (GET_CODE (operands[1]), operands[2],
6134 operands[3]);
6135
6136 operands[6] = gen_rtx_REG (mode, 24);
6137 operands[7] = gen_rtx_COMPARE (mode, operands[2], operands[3]);
6138 }
6139 ")
6140
6141 ;; The next two patterns occur when an AND operation is followed by a
6142 ;; scc insn sequence
6143
6144 (define_insn "*sign_extract_onebit"
6145 [(set (match_operand:SI 0 "s_register_operand" "=r")
6146 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6147 (const_int 1)
6148 (match_operand:SI 2 "const_int_operand" "n")))]
6149 ""
6150 "*
6151 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6152 output_asm_insn (\"ands\\t%0, %1, %2\", operands);
6153 return \"mvnne\\t%0, #0\";
6154 "
6155 [(set_attr "conds" "clob")
6156 (set_attr "length" "8")])
6157
6158 (define_insn "*not_signextract_onebit"
6159 [(set (match_operand:SI 0 "s_register_operand" "=r")
6160 (not:SI
6161 (sign_extract:SI (match_operand:SI 1 "s_register_operand" "r")
6162 (const_int 1)
6163 (match_operand:SI 2 "const_int_operand" "n"))))]
6164 ""
6165 "*
6166 operands[2] = GEN_INT (1 << INTVAL (operands[2]));
6167 output_asm_insn (\"tst\\t%1, %2\", operands);
6168 output_asm_insn (\"mvneq\\t%0, #0\", operands);
6169 return \"movne\\t%0, #0\";
6170 "
6171 [(set_attr "conds" "clob")
6172 (set_attr "length" "12")])
6173
6174 ;; Push multiple registers to the stack. The first register is in the
6175 ;; unspec part of the insn; subsequent registers are in parallel (use ...)
6176 ;; expressions.
6177 (define_insn "*push_multi"
6178 [(match_parallel 2 "multi_register_push"
6179 [(set (match_operand:BLK 0 "memory_operand" "=m")
6180 (unspec:BLK [(match_operand:SI 1 "s_register_operand" "r")] 2))])]
6181 ""
6182 "*
6183 {
6184 char pattern[100];
6185 int i;
6186 extern int lr_save_eliminated;
6187
6188 if (lr_save_eliminated)
6189 {
6190 if (XVECLEN (operands[2], 0) > 1)
6191 abort ();
6192 return \"\";
6193 }
6194 strcpy (pattern, \"stmfd\\t%m0!, {%1\");
6195 for (i = 1; i < XVECLEN (operands[2], 0); i++)
6196 {
6197 strcat (pattern, \", %|\");
6198 strcat (pattern, reg_names[REGNO (XEXP (XVECEXP (operands[2], 0, i),
6199 0))]);
6200 }
6201 strcat (pattern, \"}\");
6202 output_asm_insn (pattern, operands);
6203 return \"\";
6204 }"
6205 [(set_attr "type" "store4")])
6206
6207 ;; Similarly for the floating point registers
6208 (define_insn "*push_fp_multi"
6209 [(match_parallel 2 "multi_register_push"
6210 [(set (match_operand:BLK 0 "memory_operand" "=m")
6211 (unspec:BLK [(match_operand:XF 1 "f_register_operand" "f")] 2))])]
6212 ""
6213 "*
6214 {
6215 char pattern[100];
6216 int i;
6217
6218 sprintf (pattern, \"sfmfd\\t%%1, %d, [%%m0]!\", XVECLEN (operands[2], 0));
6219 output_asm_insn (pattern, operands);
6220 return \"\";
6221 }"
6222 [(set_attr "type" "f_store")])
6223
6224 ;; Special patterns for dealing with the constant pool
6225
6226 (define_insn "consttable_4"
6227 [(unspec_volatile [(match_operand 0 "" "")] 2)]
6228 ""
6229 "*
6230 {
6231 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6232 {
6233 case MODE_FLOAT:
6234 {
6235 union real_extract u;
6236 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6237 assemble_real (u.d, GET_MODE (operands[0]));
6238 break;
6239 }
6240 default:
6241 assemble_integer (operands[0], 4, 1);
6242 break;
6243 }
6244 return \"\";
6245 }"
6246 [(set_attr "length" "4")])
6247
6248 (define_insn "consttable_8"
6249 [(unspec_volatile [(match_operand 0 "" "")] 3)]
6250 ""
6251 "*
6252 {
6253 switch (GET_MODE_CLASS (GET_MODE (operands[0])))
6254 {
6255 case MODE_FLOAT:
6256 {
6257 union real_extract u;
6258 bcopy ((char *) &CONST_DOUBLE_LOW (operands[0]), (char *) &u, sizeof u);
6259 assemble_real (u.d, GET_MODE (operands[0]));
6260 break;
6261 }
6262 default:
6263 assemble_integer (operands[0], 8, 1);
6264 break;
6265 }
6266 return \"\";
6267 }"
6268 [(set_attr "length" "8")])
6269
6270 (define_insn "consttable_end"
6271 [(unspec_volatile [(const_int 0)] 4)]
6272 ""
6273 "*
6274 /* Nothing to do (currently). */
6275 return \"\";
6276 ")
6277
6278 (define_insn "align_4"
6279 [(unspec_volatile [(const_int 0)] 5)]
6280 ""
6281 "*
6282 assemble_align (32);
6283 return \"\";
6284 ")