(combined mult/arithmetic recognizers): Switch on.
[platform/upstream/gcc.git] / gcc / config / arm / arm.md
1 ;;- Machine description Acorn RISC Machine for GNU compiler
2 ;;  Copyright (C) 1991 Free Software Foundation, Inc.
3 ;;  Contributed by Pieter `Tiggr' Schoenmakers (rcpieter@win.tue.nl)
4 ;;             and Martin Simmons (@harleqn.co.uk).
5
6 ;; This file is part of GNU CC.
7
8 ;; GNU CC is free software; you can redistribute it and/or modify
9 ;; it under the terms of the GNU General Public License as published by
10 ;; the Free Software Foundation; either version 2, or (at your option)
11 ;; any later version.
12
13 ;; GNU CC is distributed in the hope that it will be useful,
14 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
15 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 ;; GNU General Public License for more details.
17
18 ;; You should have received a copy of the GNU General Public License
19 ;; along with GNU CC; see the file COPYING.  If not, write to
20 ;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
21
22 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
23
24 ;; Every template must be output by arm_output_asm_insn, since this keeps
25 ;; track of the offset of labels within the text segment.  This is needed to
26 ;; to be able to (correctly) output instructions for loading a value from a
27 ;; function's constant pool, since different instructions are needed when the
28 ;; constant pool is more than 4095 bytes away from the PC.
29 \f
30 ;; Addition insns.
31
32 (define_insn "adddi3"
33   [(set (match_operand:DI 0 "di_operand" "=&r")
34         (plus:DI (match_operand:DI 1 "di_operand" "%r")
35                  (match_operand:DI 2 "di_operand" "r")))]
36   ""
37   "*
38   arm_output_asm_insn (\"adds\\t%0, %1, %2\", operands);
39   return (arm_output_asm_insn (\"adc\\t%R0, %R1, %R2\", operands));
40 ")
41
42 (define_insn "addsi3"
43   [(set (match_operand:SI 0 "register_operand" "=r,r")
44         (plus:SI (match_operand:SI 1 "register_operand" "r,r")
45                  (match_operand:SI 2 "general_operand" "r,n")))]
46   ""
47   "*
48   switch (which_alternative)
49     {
50     case 0:
51       return (arm_output_asm_insn (\"add\\t%0, %1, %2\", operands));
52     case 1:
53       return (output_add_immediate (operands));
54     }
55 ")
56
57 (define_insn "addsf3"
58   [(set (match_operand:SF 0 "register_operand" "=f")
59         (plus:SF (match_operand:SF 1 "register_operand" "f")
60                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
61   ""
62   "*
63   return (arm_output_asm_insn (\"adfs\\t%0, %1, %2\", operands));
64 ")
65
66 (define_insn "adddf3"
67   [(set (match_operand:DF 0 "register_operand" "=f")
68         (plus:DF (match_operand:DF 1 "register_operand" "f")
69                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
70   ""
71   "*
72   return (arm_output_asm_insn (\"adfd\\t%0, %1, %2\", operands));
73 ")
74
75 (define_insn "subdi3"
76   [(set (match_operand:DI 0 "di_operand" "=&r")
77         (minus:DI (match_operand:DI 1 "di_operand" "%r")
78                   (match_operand:DI 2 "di_operand" "r")))]
79   ""
80   "*
81   arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
82   return (arm_output_asm_insn (\"sbc\\t%R0, %R1, %R2\", operands));
83 ")
84
85 (define_insn "subsi3"
86   [(set (match_operand:SI 0 "register_operand" "=r,r,r")
87         (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
88                   (match_operand:SI 2 "general_operand" "r,n,r")))]
89   ""
90   "*
91   switch (which_alternative)
92     {
93     case 0:
94       return (arm_output_asm_insn (\"sub\\t%0, %1, %2\", operands));
95     case 1:
96       operands[2] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[2]));
97       return (output_add_immediate (operands));
98     case 2:
99       return (arm_output_asm_insn (\"rsb\\t%0, %2, %1\", operands));
100     }
101 ")
102
103 (define_insn "subsf3"
104   [(set (match_operand:SF 0 "register_operand" "=f,f")
105         (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
106                   (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
107   ""
108   "*
109   switch (which_alternative)
110     {
111     case 0:
112       return (arm_output_asm_insn (\"sufs\\t%0, %1, %2\", operands));
113     case 1:
114       return (arm_output_asm_insn (\"rsfs\\t%0, %2, %1\", operands));
115     }
116 ")
117
118 (define_insn "subdf3"
119   [(set (match_operand:DF 0 "register_operand" "=f,f")
120         (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
121       (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
122   ""
123   "*
124   switch (which_alternative)
125     {
126     case 0:
127       return (arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands));
128     case 2:
129       return (arm_output_asm_insn (\"rsfd\\t%0, %2, %1\", operands));
130     }
131 ")
132 \f
133 ;; Multiplication insns
134
135 ;; The `&' is too strict, but at least generates correct code.
136 (define_insn "mulsi3"
137   [(set (match_operand:SI 0 "register_operand" "=&r")
138         (mult:SI (match_operand:SI 1 "register_operand" "%r")
139                  (match_operand:SI 2 "register_operand" "r")))]
140   ""
141   "*
142   if (REGNO (operands[0]) == REGNO (operands[1]))
143     return (arm_output_asm_insn (\"mul\\t%0, %2, %1\", operands));
144   else
145     return (arm_output_asm_insn (\"mul\\t%0, %1, %2\", operands));
146 ")
147
148 ;; Unnamed templates to match MLA instruction.
149
150 (define_insn ""
151   [(set (match_operand:SI 0 "register_operand" "=&r")
152         (plus:SI
153           (mult:SI (match_operand:SI 1 "register_operand" "%r")
154                    (match_operand:SI 2 "register_operand" "r"))
155           (match_operand:SI 3 "register_operand" "r")))]
156   ""
157   "*
158   if (REGNO (operands[0]) == REGNO (operands[1]))
159     return (arm_output_asm_insn (\"mla\\t%0, %2, %1, %3\", operands));
160   else
161     return (arm_output_asm_insn (\"mla\\t%0, %1, %2, %3\", operands));
162 ")
163
164 (define_insn ""
165   [(set (match_operand:SI 0 "register_operand" "=&r")
166         (plus:SI
167           (match_operand:SI 3 "register_operand" "r")
168           (mult:SI (match_operand:SI 1 "register_operand" "%r")
169                    (match_operand:SI 2 "register_operand" "r"))))]
170   ""
171   "*
172   if (REGNO (operands[0]) == REGNO (operands[1]))
173     return (arm_output_asm_insn (\"mla\\t%0, %2, %1, %3\", operands));
174   else
175     return (arm_output_asm_insn (\"mla\\t%0, %1, %2, %3\", operands));
176 ")
177
178 (define_insn "mulsf3"
179   [(set (match_operand:SF 0 "register_operand" "=f")
180         (mult:SF (match_operand:SF 1 "register_operand" "f")
181                  (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
182   ""
183   "*return (arm_output_asm_insn (\"mufs\\t%0, %1, %2\", operands));")
184
185 (define_insn "muldf3"
186   [(set (match_operand:DF 0 "register_operand" "=f")
187         (mult:DF (match_operand:DF 1 "register_operand" "f")
188                  (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
189   ""
190   "*
191   return (arm_output_asm_insn (\"mufd\\t%0, %1, %2\", operands));
192 ")
193 \f
194 ;; Division insns
195
196 (define_insn "divsf3"
197   [(set (match_operand:SF 0 "register_operand" "=f,f")
198         (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
199                 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
200   ""
201   "*
202   switch (which_alternative)
203     {
204     case 0:
205       return (arm_output_asm_insn (\"dvfs\\t%0, %1, %2\", operands));
206     case 1:
207       return (arm_output_asm_insn (\"rdfs\\t%0, %2, %1\", operands));
208     }
209 ")
210
211 (define_insn "divdf3"
212   [(set (match_operand:DF 0 "register_operand" "=f,f")
213         (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
214                 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
215   ""
216   "*
217   switch (which_alternative)
218     {
219     case 0:
220       return (arm_output_asm_insn (\"dvfd\\t%0, %1, %2\", operands));
221     case 1:
222       return (arm_output_asm_insn (\"rdfd\\t%0, %2, %1\", operands));
223     }
224 ")
225 \f
226 ;; Modulo insns
227
228 (define_insn "modsf3"
229   [(set (match_operand:SF 0 "register_operand" "=f")
230         (mod:SF (match_operand:SF 1 "register_operand" "f")
231                 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
232   ""
233   "*
234   return (arm_output_asm_insn (\"rmfs\\t%0, %1, %2\", operands));
235 ")
236
237 (define_insn "moddf3"
238   [(set (match_operand:DF 0 "register_operand" "=f")
239         (mod:DF (match_operand:DF 1 "register_operand" "f")
240                 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
241   ""
242   "*
243   return (arm_output_asm_insn (\"rmfd\\t%0, %1, %2\", operands));
244 ")
245 \f
246 ;; Boolean and,ior,xor insns
247
248 (define_insn "anddi3"
249   [(set (match_operand:DI 0 "di_operand" "=&r")
250         (and:DI (match_operand:DI 1 "di_operand" "%r")
251                 (match_operand:DI 2 "di_operand" "r")))]
252   ""
253   "*
254   arm_output_asm_insn (\"and\\t%0, %1, %2\", operands);
255   return (arm_output_asm_insn (\"and\\t%R0, %R1, %R2\", operands));
256 ")
257
258 (define_insn "andsi3"
259   [(set (match_operand:SI 0 "register_operand" "=r")
260         (and:SI (match_operand:SI 1 "register_operand" "r")
261                 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
262   ""
263   "*
264   return (arm_output_asm_insn (\"and\\t%0, %1, %2\", operands));
265 ")
266
267 (define_insn "andcbsi3"
268   [(set (match_operand:SI 0 "register_operand" "=r")
269         (and:SI (match_operand:SI 1 "register_operand" "r")
270                 (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
271   ""
272   "*
273   return (arm_output_asm_insn (\"bic\\t%0, %1, %2\", operands));
274 ")
275
276 (define_insn "iordi3"
277   [(set (match_operand:DI 0 "di_operand" "=&r")
278         (ior:DI (match_operand:DI 1 "di_operand" "%r")
279                 (match_operand:DI 2 "di_operand" "r")))]
280   ""
281   "*
282   arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands);
283   return (arm_output_asm_insn (\"orr\\t%R0, %R1, %R2\", operands));
284 ")
285
286 (define_insn "iorsi3"
287   [(set (match_operand:SI 0 "register_operand" "=r,r")
288         (ior:SI (match_operand:SI 1 "register_operand" "r,r")
289                 (match_operand:SI 2 "nonmemory_operand" "r,n")))]
290   ""
291   "*
292   switch (which_alternative)
293     {
294     case 0:
295       return (arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands));
296     case 1:
297       return (output_multi_immediate (operands,
298                                       \"orr\\t%0, %1, %2\", \"orr\\t%0, %0, %2\",
299                                       2, INTVAL (operands[2])));
300     }
301 ")
302
303 (define_insn "xorsi3"
304   [(set (match_operand:SI 0 "register_operand" "=r,r")
305         (xor:SI (match_operand:SI 1 "register_operand" "r,r")
306                 (match_operand:SI 2 "nonmemory_operand" "r,n")))]
307   ""
308   "*
309   switch (which_alternative)
310     {
311     case 0:
312       return (arm_output_asm_insn (\"eor\\t%0, %1, %2\", operands));
313     case 1:
314       return (output_multi_immediate (operands,
315                                       \"eor\\t%0, %1, %2\", \"eor\\t%0, %0, %2\",
316                                       2, INTVAL (operands[2])));
317     }
318 ")
319 \f
320 ;; Shift and rotation insns
321
322 (define_insn "ashlsi3"
323   [(set (match_operand:SI 0 "register_operand" "=r")
324         (ashift:SI (match_operand:SI 1 "register_operand" "r")
325                    (match_operand:SI 2 "general_operand" "rn")))]
326   ""
327   "*
328   return (output_shifted_move (ASHIFT, operands));
329 ")
330
331 (define_insn "ashrsi3"
332   [(set (match_operand:SI 0 "register_operand" "=r")
333         (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
334                      (match_operand:SI 2 "general_operand" "rn")))]
335   ""
336   "*
337   return (output_shifted_move (ASHIFTRT, operands));
338 ")
339
340 ;; lshlsi3 is not defined because shift counts cannot be negative
341 ;; An unnamed pattern is needed for expansion of zero_extend.
342
343 (define_insn ""
344   [(set (match_operand:SI 0 "register_operand" "=r")
345         (lshift:SI (match_operand:SI 1 "register_operand" "r")
346                    (match_operand:SI 2 "general_operand" "rn")))]
347   ""
348   "*
349   return (output_shifted_move (LSHIFT, operands));
350 ")
351
352 (define_insn "lshrsi3"
353   [(set (match_operand:SI 0 "register_operand" "=r")
354         (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
355                      (match_operand:SI 2 "general_operand" "rn")))]
356   ""
357   "*
358   return (output_shifted_move (LSHIFTRT, operands));
359 ")
360
361 ;; rotlsi3 is not defined yet to see what happens
362
363 (define_insn "rotrsi3"
364   [(set (match_operand:SI 0 "register_operand" "=r,r")
365         (rotatert:SI (match_operand:SI 1 "register_operand" "r,r")
366                      (match_operand:SI 2 "general_operand" "r,n")))]
367   ""
368   "*
369   switch (which_alternative)
370     {
371     case 0:
372       return (arm_output_asm_insn (\"mov\\t%0, %1,ror %2\", operands));
373     case 1:
374       if (INTVAL(operands[2]) > 31)
375         operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) % 32);
376       return (arm_output_asm_insn (\"mov\\t%0, %1,ror%2\", operands));
377     }
378 ")
379 \f
380 ;; Unary arithmetic insns
381
382 (define_insn "negdi2"
383   [(set (match_operand:DI 0 "di_operand" "=&r")
384         (neg:DI (match_operand:DI 1 "di_operand" "r")))]
385   ""
386   "*
387   arm_output_asm_insn (\"rsb\\t%0, %1, #0\", operands);
388   return (arm_output_asm_insn (\"rsc\\t%R0, %R1, #0\", operands));
389 ")
390
391 (define_insn "negsi2"
392   [(set (match_operand:SI 0 "register_operand" "=r")
393         (neg:SI (match_operand:SI 1 "register_operand" "r")))]
394   ""
395   "*
396   return (arm_output_asm_insn (\"rsb\\t%0, %1, #0\", operands));
397 ")
398
399 (define_insn "negsf2"
400   [(set (match_operand:SF 0 "register_operand" "=f")
401         (neg:SF (match_operand:SF 1 "register_operand" "f")))]
402   ""
403   "*
404   return (arm_output_asm_insn (\"mnfs\\t%0, %1\", operands));
405 ")
406
407 (define_insn "negdf2"
408   [(set (match_operand:DF 0 "register_operand" "=f")
409         (neg:DF (match_operand:DF 1 "register_operand" "f")))]
410   ""
411   "*
412   return (arm_output_asm_insn (\"mnfd\\t%0, %1\", operands));
413 ")
414
415 (define_insn "abssf2"
416   [(set (match_operand:SF 0 "register_operand" "=f")
417          (abs:SF (match_operand:SF 1 "register_operand" "f")))]
418   ""
419   "*
420   return (arm_output_asm_insn (\"abss\\t%0, %1\", operands));
421 ")
422
423 (define_insn "absdf2"
424   [(set (match_operand:DF 0 "register_operand" "=f")
425         (abs:DF (match_operand:DF 1 "register_operand" "f")))]
426   ""
427   "*
428   return (arm_output_asm_insn (\"absd\\t%0, %1\", operands));
429 ")
430
431 (define_insn "sqrtsf2"
432   [(set (match_operand:SF 0 "register_operand" "=f")
433         (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
434   ""
435   "*
436   return (arm_output_asm_insn (\"sqts\\t%0, %1\", operands));
437 ")
438
439 (define_insn "sqrtdf2"
440   [(set (match_operand:DF 0 "register_operand" "=f")
441         (sqrt:DF (match_operand:DF 1 "register_operand" "f")))]
442   ""
443   "*
444   return (arm_output_asm_insn (\"sqtd\\t%0, %1\", operands));
445 ")
446
447 (define_insn "one_cmplsi2"
448   [(set (match_operand:SI 0 "register_operand" "=r")
449         (not:SI (match_operand:SI 1 "register_operand" "r")))]
450   ""
451   "*
452   return (arm_output_asm_insn (\"mvn\\t%0, %1\", operands));
453 ")
454 \f
455 ;; Fixed <--> Floating conversion insns
456
457 (define_insn "floatsisf2"
458   [(set (match_operand:SF 0 "register_operand" "=f")
459         (float:SF (match_operand:SI 1 "register_operand" "r")))]
460   ""
461   "*
462   return (arm_output_asm_insn (\"flts\\t%0, %1\", operands));
463 ")
464
465 (define_insn "floatsidf2"
466   [(set (match_operand:DF 0 "register_operand" "=f")
467         (float:DF (match_operand:SI 1 "register_operand" "r")))]
468   ""
469   "*
470   return (arm_output_asm_insn (\"fltd\\t%0, %1\", operands));
471 ")
472
473 ;; Truncation insns
474
475 (define_insn "truncdfsf2"
476   [(set (match_operand:SF 0 "register_operand" "=f")
477         (float_truncate:SF
478          (match_operand:DF 1 "register_operand" "f")))]
479   ""
480   "*
481   return (arm_output_asm_insn (\"mvfs\\t%0, %1\", operands));
482 ")
483 \f
484 ;; Zero extension instructions.
485
486 (define_expand "zero_extendhisi2"
487   [(set (match_dup 2)
488         (ashift:SI (match_operand:HI 1 "register_operand" "")
489                    (const_int 16)))
490    (set (match_operand:SI 0 "register_operand" "")
491         (lshiftrt:SI (match_dup 2)
492                      (const_int 16)))]
493   ""
494   "
495 { operands[1] = gen_lowpart (SImode, operands[1]);
496   operands[2] = gen_reg_rtx (SImode); }")
497
498 (define_insn "zero_extendqihi2"
499   [(set (match_operand:HI 0 "register_operand" "=r")
500         (zero_extend:HI
501          (match_operand:QI 1 "register_operand" "r")))]
502   ""
503   "*
504   return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ zero_extendqihi2\", operands));
505 ")
506
507 (define_insn "zero_extendqisi2"
508   [(set (match_operand:SI 0 "register_operand" "=r,r")
509         (zero_extend:SI
510          (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
511   ""
512   "*
513   switch (which_alternative)
514     {
515     case 0:
516       return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ zero_extendqisi2\", operands));
517     case 1:
518       return (arm_output_asm_insn (\"ldrb\\t%0, %1\\t@ zero_extendqisi2\", operands));
519     }
520 ")
521
522 (define_expand "extendhisi2"
523   [(set (match_dup 2)
524         (ashift:SI (match_operand:HI 1 "register_operand" "")
525                    (const_int 16)))
526    (set (match_operand:SI 0 "register_operand" "")
527         (ashiftrt:SI (match_dup 2)
528                      (const_int 16)))]
529   ""
530   "
531 { operands[1] = gen_lowpart (SImode, operands[1]);
532   operands[2] = gen_reg_rtx (SImode); }")
533
534 (define_expand "extendqihi2"
535   [(set (match_dup 2)
536         (ashift:SI (match_operand:QI 1 "register_operand" "")
537                    (const_int 24)))
538    (set (match_operand:HI 0 "register_operand" "")
539         (ashiftrt:SI (match_dup 2)
540                      (const_int 24)))]
541   ""
542   "
543 { operands[0] = gen_lowpart (SImode, operands[0]);
544   operands[1] = gen_lowpart (SImode, operands[1]);
545   operands[2] = gen_reg_rtx (SImode); }")
546
547 (define_expand "extendqisi2"
548   [(set (match_dup 2)
549         (ashift:SI (match_operand:QI 1 "register_operand" "")
550                    (const_int 24)))
551    (set (match_operand:SI 0 "register_operand" "")
552         (ashiftrt:SI (match_dup 2)
553                      (const_int 24)))]
554   ""
555   "
556 { operands[1] = gen_lowpart (SImode, operands[1]);
557   operands[2] = gen_reg_rtx (SImode); }")
558
559 (define_insn "extendsfdf2"
560   [(set (match_operand:DF 0 "register_operand" "=f")
561         (float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
562   ""
563   "*
564   return (arm_output_asm_insn (\"mvfd\\t%0, %1\", operands));
565 ")
566 \f
567 ;; Move insns (including loads and stores)
568
569 ;; XXX Just some ideas about movti.
570
571 ;;(define_expand "loadti"
572 ;;  [(set (match_operand:TI 0 "register_operand" "")
573 ;;      (mem:TI (match_operand:SI 1 "address_operand" "")))]
574 ;;  "" "")
575
576 ;;(define_expand "storeti"
577 ;;  [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
578 ;;      (match_operand:TI 1 "register_operand" ""))]
579 ;;  "" "")
580
581 ;;(define_expand "movti"
582 ;;  [(set (match_operand:TI 0 "general_operand" "")
583 ;;      (match_operand:TI 1 "general_operand" ""))]
584 ;;  ""
585 ;;  "
586 ;;{
587 ;;  rtx insn;
588 ;;
589 ;;  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
590 ;;    operands[1] = copy_to_reg (operands[1]);
591 ;;  if (GET_CODE (operands[0]) == MEM)
592 ;;    insn = gen_storeti (XEXP (operands[0], 0), operands[1]);
593 ;;  else if (GET_CODE (operands[1]) == MEM)
594 ;;    insn = gen_loadti (operands[0], XEXP (operands[1], 0));
595 ;;  else
596 ;;    FAIL;
597 ;;
598 ;;  emit_insn (insn);
599 ;;  DONE;
600 ;;}")
601
602 ;; Recognise garbage generated above.
603
604 ;;(define_insn ""
605 ;;  [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
606 ;;      (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
607 ;;  ""
608 ;;  "*
609 ;;  {
610 ;;    register mem = (which_alternative < 3);
611 ;;    register char *template;
612 ;;
613 ;;    operands[mem] = XEXP (operands[mem], 0);
614 ;;    switch (which_alternative)
615 ;;      {
616 ;;      case 0: template = \"ldmdb\\t%1!, %M0\"; break;
617 ;;      case 1: template = \"ldmia\\t%1!, %M0\"; break;
618 ;;      case 2: template = \"ldmia\\t%1, %M0\"; break;
619 ;;      case 3: template = \"stmdb\\t%0!, %M1\"; break;
620 ;;      case 4: template = \"stmia\\t%0!, %M1\"; break;
621 ;;      case 5: template = \"stmia\\t%0, %M1\"; break;
622 ;;      }
623 ;;    return (arm_output_asm_insn (template, operands));
624 ;;  }")
625
626
627 (define_insn "movdi"
628   [(set (match_operand:DI 0 "di_operand" "=r,r,r,o,r")
629         (match_operand:DI 1 "di_operand" "r,n,o,r,F"))]
630   ""
631   "*
632   return (output_move_double (operands));
633 ")
634
635 (define_insn "movsi"
636   [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
637         (match_operand:SI 1 "general_operand"  "r,n,m,r"))]
638   ""
639   "*
640   switch (which_alternative)
641     {
642     case 0:
643       return (arm_output_asm_insn (\"mov\\t%0, %1\", operands));
644     case 1:
645       return (output_mov_immediate (operands));
646     case 2:
647       if (GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF
648           &&  CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
649         return (arm_output_llc (operands));
650       else
651         return (arm_output_asm_insn (\"ldr\\t%0, %1\", operands));
652     case 3:
653       return (arm_output_asm_insn (\"str\\t%1, %0\", operands));
654     }
655 ")
656
657 ;; XXX The movhi stuff isn't as correct or as nice as it could be...
658
659 ;; Subroutine to load a half word into a register from memory.
660 ;; Operand 0 is the destination register (HImode).
661 ;; Operand 1 is the source address (SImode).
662 ;; Operand 2 is a temporary (SImode).
663
664 ;;(define_expand "loadhi"
665 ;;  [;; load the whole word (ARM realigns it if not on word boundary)
666 ;;   (set (match_operand:SI 2 "register_operand" "")
667 ;;        (mem:SI (match_operand:SI 1 "address_operand" "")))
668 ;;   ;; quietly forget the upper 16 bits
669 ;;   (set (match_operand:HI 0 "register_operand" "")
670 ;;        (subreg:HI (match_dup 2) 0))]
671 ;;  ""
672 ;;  ""
673 ;;)
674
675 ;; Load op0 from mem:op1.  Subroutine in case we're reloading and the normal
676 ;; loadhi is not allowed.
677
678 ;;(define_expand "reloadhi"
679 ;;  [(set (reg:SI 10)
680 ;;      (mem:SI (match_operand:SI 1 "address_operand" "")))
681 ;;   (set (match_operand:HI 0 "register_operand" "")
682 ;;      (subreg:HI (reg:SI 10) 0))]
683 ;;  "" "")
684
685 ;; Store op0 into mem:op1.  Subroutine in case we're reloading and the normal
686 ;; storehi is not allowed.
687
688 (define_expand "restorehi"
689   [(set (mem:QI (match_operand:SI 1 "" ""))
690         (match_dup 2))
691    (set (reg:SI 10)
692         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
693    (set (mem:QI (plus:SI (match_dup 1) (const_int 1)))
694         (reg:QI 10))]
695   ""
696   "
697 {
698   operands[2] = gen_lowpart (QImode, operands[0]);
699   operands[0] = gen_lowpart (SImode, operands[0]);
700 }")
701
702 ;; Subroutine to store a half word from a register into memory.
703 ;; Operand 0 is the source register (HImode)
704 ;; Operand 1 is the destination address in a register (SImode)
705
706 (define_expand "storehi"
707   [;; store the low byte
708    (set (mem:QI (match_operand:SI 1 "" "")) (match_dup 3))
709    ;; extract the high byte
710    (set (match_dup 2)
711         (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
712    ;; store the high byte
713    (set (mem:QI (plus:SI (match_dup 1) (const_int 1)))
714         (subreg:QI (match_dup 2) 0))]   ;explicit subreg safe
715   ""
716   "
717 { operands[3] = gen_lowpart (QImode, operands[0]);
718   operands[0] = gen_lowpart (SImode, operands[0]);
719   operands[2] = gen_reg_rtx (SImode); }")
720
721 ;; Subroutine to store a half word integer constant into memory.
722 ;; Operand 0 is the constant
723 ;; Operand 1 is the destination address in a register (SImode)
724
725 (define_expand "storeinthi"
726   [;; store the low byte
727    (set (mem:QI (match_operand:SI 1 "" "")) (match_operand 0 "" ""))
728    ;; store the high byte
729    (set (mem:QI (plus:SI (match_dup 1) (const_int 1)))
730         (match_dup 2))]
731   ""
732   "
733     {
734       int value = INTVAL (operands[0]);
735
736       operands[0] = force_reg (QImode, gen_rtx (CONST_INT, VOIDmode, value & 255));
737       operands[2] = force_reg (QImode, gen_rtx (CONST_INT, VOIDmode,(value>>8) & 255));
738     }
739 ")
740
741 (define_expand "movhi"
742   [(set (match_operand:HI 0 "general_operand" "")
743         (match_operand:HI 1 "general_operand" ""))]
744   ""
745   "
746 {
747   rtx insn;
748
749   if (reload_in_progress || reload_completed)
750     {
751       if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == REG)
752         insn = gen_restorehi (operands[1], XEXP (operands[0], 0));
753       else
754         insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]);
755     }
756   else
757     {
758       if (GET_CODE (operands[0]) == MEM)
759         {
760           if (GET_CODE (operands[1]) == CONST_INT)
761             {
762               insn = gen_storeinthi (operands[1], force_reg (SImode, XEXP (operands[0], 0)));
763             }
764           else
765             {
766               if (GET_CODE (operands[1]) == MEM)
767                 operands[1] = copy_to_reg (operands[1]);
768               insn = gen_storehi (operands[1], force_reg (SImode, XEXP (operands[0], 0)));
769             }
770         }
771 #if 0
772       else if (GET_CODE (operands[1]) == MEM)
773         {
774           insn = gen_loadhi (operands[0], XEXP (operands[1], 0),
775                              gen_reg_rtx (SImode));
776         }
777 #endif
778       else
779         insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]);
780     }
781
782   emit_insn (insn);
783   DONE;
784 }")
785
786 ;; Pattern to recognise insn generated default case above
787
788 (define_insn ""
789   [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
790         (match_operand:HI 1 "general_operand"  "r,n,m,r"))]
791   ""
792   "*
793   switch (which_alternative)
794     {
795       case 0: return (arm_output_asm_insn (\"mov\\t%0, %1\\t@movhi\", operands));
796       case 1: return (output_mov_immediate (operands));
797       case 2: return (arm_output_asm_insn (\"ldr\\t%0, %1\\t@movhi\", operands));
798       case 3: return (arm_output_asm_insn (\"str\\t%1, %0\\t@movhi\", operands));
799     }
800 ")
801
802 (define_insn "movqi"
803   [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
804         (match_operand:QI 1 "general_operand" "r,n,m,r"))]
805   ""
806   "*
807   switch (which_alternative)
808     {
809     case 0:
810       return (arm_output_asm_insn (\"mov\\t%0, %1\", operands));
811     case 1:
812       return (output_mov_immediate (operands));
813     case 2:
814       return (arm_output_asm_insn (\"ldrb\\t%0, %1\", operands));
815     case 3:
816       return (arm_output_asm_insn (\"strb\\t%1, %0\", operands));
817     }
818 ")
819
820 (define_insn "movsf"
821   [(set (match_operand:SF 0 "general_operand" "=f,f,m,f,r,r")
822         (match_operand:SF 1 "general_operand" "fG,m,f,r,f,r"))]
823   ""
824   "*
825   switch (which_alternative)
826     {
827     case 0:
828       return (arm_output_asm_insn (\"mvfs\\t%0, %1\", operands));
829     case 1:
830       return (arm_output_asm_insn (\"ldfs\\t%0, %1\", operands));
831     case 2:
832       return (arm_output_asm_insn (\"stfs\\t%1, %0\", operands));
833     case 3:
834       arm_output_asm_insn(\"stmfd\\tsp!, {%1}\", operands);
835       return (arm_output_asm_insn (\"ldfs\\t%0, [sp],#4\", operands));
836     case 4:
837       arm_output_asm_insn(\"stfs\\t%1, [sp,#-4]!\", operands);
838       return (arm_output_asm_insn (\"ldmfd\\tsp!, {%0}\", operands));
839     case 5:
840       return (arm_output_asm_insn (\"mov\\t%0, %1\", operands));
841   }
842 ")
843
844 (define_insn "movdf"
845   [(set (match_operand:DF 0 "general_operand" "=f,f,m,f,r,r")
846         (match_operand:DF 1 "general_operand" "fG,m,f,r,f,r"))]
847   ""
848   "*
849   switch (which_alternative)
850     {
851       case 0: return (arm_output_asm_insn (\"mvfd\\t%0, %1\", operands));
852       case 1: return (arm_output_asm_insn (\"ldfd\\t%0, %1\", operands));
853       case 2: return (arm_output_asm_insn (\"stfd\\t%1, %0\", operands));
854       case 3: return (output_mov_double_fpu_from_arm (operands));
855       case 4: return (output_mov_double_arm_from_fpu (operands));
856       case 5: return (output_move_double (operands));
857     }
858 ")
859 \f
860 ;; Comparison and test insns
861
862 (define_insn "cmpsi"
863   [(set (cc0)
864         (compare (match_operand:SI 0 "register_operand" "r")
865                  (match_operand:SI 1 "arm_rhs_operand" "rI")))]
866   ""
867   "*
868   return (arm_output_asm_insn (\"cmp\\t%0, %1\", operands));
869 ")
870
871 (define_insn "tstsi"
872   [(set (cc0) (match_operand:SI 0 "register_operand" "r"))]
873   ""
874   "*
875   return (arm_output_asm_insn (\"cmp\\t%0, #0\", operands));
876 ")
877
878 (define_insn ""
879   [(set (cc0)
880         (compare (match_operand:SI 0 "register_operand" "r")
881                  (neg:SI (match_operand:SI 1 "arm_rhs_operand" "rI"))))]
882   ""
883   "*
884   return (arm_output_asm_insn (\"cmn\\t%0, %1\", operands));
885 ")
886
887 (define_insn "cmpsf"
888   [(set (cc0)
889         (compare (match_operand:SF 0 "register_operand" "f")
890                  (match_operand:SF 1 "fpu_rhs_operand" "fG")))]
891   ""
892   "*
893   return (arm_output_asm_insn (\"cmf\\t%0, %1\", operands));
894 ")
895
896 (define_insn "cmpdf"
897   [(set (cc0)
898         (compare (match_operand:DF 0 "register_operand" "f")
899                  (match_operand:DF 1 "fpu_rhs_operand" "fG")))]
900   ""
901   "*
902   return (arm_output_asm_insn (\"cmf\\t%0, %1\", operands));
903 ")
904 \f
905 ;; Conditional branch insns
906
907 (define_insn "beq"
908   [(set (pc)
909         (if_then_else (eq (cc0) (const_int 0))
910                       (label_ref (match_operand 0 "" ""))
911                       (pc)))]
912   ""
913   "*
914   return (arm_output_asm_insn (\"beq\\t%l0\", operands));
915 ")
916
917 (define_insn "bne"
918   [(set (pc)
919         (if_then_else (ne (cc0) (const_int 0))
920                       (label_ref (match_operand 0 "" ""))
921                       (pc)))]
922   ""
923   "*
924   return (arm_output_asm_insn (\"bne\\t%l0\", operands));
925 ")
926
927 (define_insn "bgt"
928   [(set (pc)
929         (if_then_else (gt (cc0) (const_int 0))
930                       (label_ref (match_operand 0 "" ""))
931                       (pc)))]
932   ""
933   "*
934   return (arm_output_asm_insn (\"bgt\\t%l0\", operands));
935 ")
936
937 (define_insn "ble"
938   [(set (pc)
939         (if_then_else (le (cc0) (const_int 0))
940                       (label_ref (match_operand 0 "" ""))
941                       (pc)))]
942   ""
943   "*
944   return (arm_output_asm_insn (\"ble\\t%l0\", operands));
945 ")
946
947 (define_insn "bge"
948   [(set (pc)
949         (if_then_else (ge (cc0) (const_int 0))
950                       (label_ref (match_operand 0 "" ""))
951                       (pc)))]
952   ""
953   "*
954   return (arm_output_asm_insn (\"bge\\t%l0\", operands));
955 ")
956
957 (define_insn "blt"
958   [(set (pc)
959         (if_then_else (lt (cc0) (const_int 0))
960                       (label_ref (match_operand 0 "" ""))
961                       (pc)))]
962   ""
963   "*
964   return (arm_output_asm_insn (\"blt\\t%l0\", operands));
965 ")
966
967 (define_insn "bgtu"
968   [(set (pc)
969         (if_then_else (gtu (cc0) (const_int 0))
970                       (label_ref (match_operand 0 "" ""))
971                       (pc)))]
972   ""
973   "*
974   return (arm_output_asm_insn (\"bhi\\t%l0\", operands));
975 ")
976
977 (define_insn "bleu"
978   [(set (pc)
979         (if_then_else (leu (cc0) (const_int 0))
980                       (label_ref (match_operand 0 "" ""))
981                       (pc)))]
982   ""
983   "*
984   return (arm_output_asm_insn (\"bls\\t%l0\", operands));
985 ")
986
987 (define_insn "bgeu"
988   [(set (pc)
989         (if_then_else (geu (cc0) (const_int 0))
990                       (label_ref (match_operand 0 "" ""))
991                       (pc)))]
992   ""
993   "*
994   return (arm_output_asm_insn (\"bhs\\t%l0\", operands));
995 ")
996
997 (define_insn "bltu"
998   [(set (pc)
999         (if_then_else (ltu (cc0) (const_int 0))
1000                       (label_ref (match_operand 0 "" ""))
1001                       (pc)))]
1002   ""
1003   "*
1004   return (arm_output_asm_insn (\"blo\\t%l0\", operands));
1005 ")
1006 \f
1007 ;; Inverted conditional branch insns
1008
1009 (define_insn ""
1010   [(set (pc)
1011         (if_then_else (eq (cc0) (const_int 0))
1012                       (pc)
1013                       (label_ref (match_operand 0 "" ""))))]
1014   ""
1015   "*
1016   return (arm_output_asm_insn (\"bne\\t%l0\", operands));
1017 ")
1018
1019 (define_insn ""
1020   [(set (pc)
1021         (if_then_else (ne (cc0) (const_int 0))
1022                       (pc)
1023                       (label_ref (match_operand 0 "" ""))))]
1024   ""
1025   "*
1026   return (arm_output_asm_insn (\"beq\\t%l0\", operands));
1027 ")
1028
1029 (define_insn ""
1030   [(set (pc)
1031         (if_then_else (gt (cc0) (const_int 0))
1032                       (pc)
1033                       (label_ref (match_operand 0 "" ""))))]
1034   ""
1035   "*
1036   return (arm_output_asm_insn (\"ble\\t%l0\", operands));
1037 ")
1038
1039 (define_insn ""
1040   [(set (pc)
1041         (if_then_else (le (cc0) (const_int 0))
1042                       (pc)
1043                       (label_ref (match_operand 0 "" ""))))]
1044   ""
1045   "*
1046   return (arm_output_asm_insn (\"bgt\\t%l0\", operands));
1047 ")
1048
1049 (define_insn ""
1050   [(set (pc)
1051         (if_then_else (ge (cc0) (const_int 0))
1052                       (pc)
1053                       (label_ref (match_operand 0 "" ""))))]
1054   ""
1055   "*
1056   return (arm_output_asm_insn (\"blt\\t%l0\", operands));
1057 ")
1058
1059 (define_insn ""
1060   [(set (pc)
1061         (if_then_else (lt (cc0) (const_int 0))
1062                       (pc)
1063                       (label_ref (match_operand 0 "" ""))))]
1064   ""
1065   "*
1066   return (arm_output_asm_insn (\"bge\\t%l0\", operands));
1067 ")
1068
1069 (define_insn ""
1070   [(set (pc)
1071         (if_then_else (gtu (cc0) (const_int 0))
1072                       (pc)
1073                       (label_ref (match_operand 0 "" ""))))]
1074   ""
1075   "*
1076   return (arm_output_asm_insn (\"bls\\t%l0\", operands));
1077 ")
1078
1079 (define_insn ""
1080   [(set (pc)
1081         (if_then_else (leu (cc0) (const_int 0))
1082                       (pc)
1083                       (label_ref (match_operand 0 "" ""))))]
1084   ""
1085   "*
1086   return (arm_output_asm_insn (\"bhi\\t%l0\", operands));
1087 ")
1088
1089 (define_insn ""
1090   [(set (pc)
1091         (if_then_else (geu (cc0) (const_int 0))
1092                       (pc)
1093                       (label_ref (match_operand 0 "" ""))))]
1094   ""
1095   "*
1096   return (arm_output_asm_insn (\"blo\\t%l0\", operands));
1097 ")
1098
1099 (define_insn ""
1100   [(set (pc)
1101         (if_then_else (ltu (cc0) (const_int 0))
1102                       (pc)
1103                       (label_ref (match_operand 0 "" ""))))]
1104   ""
1105   "*
1106   return (arm_output_asm_insn (\"bhs\\t%l0\", operands));
1107 ")
1108 \f
1109 ;; Jump and linkage insns
1110 ;; `return' is still a jump-to-epilogue...
1111
1112 (define_insn "jump"
1113   [(set (pc)
1114         (label_ref (match_operand 0 "" "")))]
1115   ""
1116   "*
1117   return (arm_output_asm_insn (\"b\\t%l0\", operands));
1118 ")
1119
1120 (define_insn "call"
1121   [(call (match_operand 0 "memory_operand" "m")
1122          (match_operand 1 "general_operand" "g"))
1123    (clobber (reg:SI 14))]
1124   ""
1125   "*
1126   return (output_call (operands));
1127 ")
1128
1129 (define_insn "call_value"
1130   [(set (match_operand 0 "" "=rf")
1131         (call (match_operand 1 "memory_operand" "m")
1132         (match_operand 2 "general_operand" "g")))
1133    (clobber (reg:SI 14))]
1134   ""
1135   "*
1136   return (output_call (&operands[1]));
1137 ")
1138
1139 ;; Allow calls to SYMBOL_REFs specially as they are not valid general addresses
1140 ;; The 'a' causes the operand to be treated as an address, i.e. no '#' output.
1141
1142 (define_insn ""
1143   [(call (mem:SI (match_operand:SI 0 "" "i"))
1144          (match_operand:SI 1 "general_operand" "g"))
1145    (clobber (reg:SI 14))]
1146   "GET_CODE (operands[0]) == SYMBOL_REF"
1147   "*
1148   return (arm_output_asm_insn (\"bl\\t%a0\", operands));
1149 ")
1150
1151 (define_insn ""
1152   [(set (match_operand 0 "register_operand" "=rf")
1153         (call (mem:SI (match_operand:SI 1 "" "i"))
1154         (match_operand:SI 2 "general_operand" "g")))
1155    (clobber (reg:SI 14))]
1156   "GET_CODE(operands[1]) == SYMBOL_REF"
1157   "*
1158   return (arm_output_asm_insn (\"bl\\t%a1\", operands));
1159 ")
1160
1161 ;; Call subroutine returning any type.
1162
1163 (define_expand "untyped_call"
1164   [(parallel [(call (match_operand 0 "" "")
1165                     (const_int 0))
1166               (match_operand 1 "" "")
1167               (match_operand 2 "" "")])]
1168   ""
1169   "
1170 {
1171   int i;
1172
1173   emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
1174
1175   for (i = 0; i < XVECLEN (operands[2], 0); i++)
1176     {
1177       rtx set = XVECEXP (operands[2], 0, i);
1178       emit_move_insn (SET_DEST (set), SET_SRC (set));
1179     }
1180
1181   /* The optimizer does not know that the call sets the function value
1182      registers we stored in the result block.  We avoid problems by
1183      claiming that all hard registers are used and clobbered at this
1184      point.  */
1185   emit_insn (gen_blockage ());
1186
1187   DONE;
1188 }")
1189
1190 ;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
1191 ;; all of memory.  This blocks insns from being moved across this point.
1192
1193 (define_insn "blockage"
1194   [(unspec_volatile [(const_int 0)] 0)]
1195   ""
1196   "")
1197
1198 (define_insn "tablejump"
1199   [(set (pc)
1200         (match_operand:SI 0 "register_operand" "r"))
1201    (use (label_ref (match_operand 1 "" "")))]
1202   ""
1203   "*
1204   return (arm_output_asm_insn (\"mov\\tpc, %0\\t@ table jump, label %l1\", operands));
1205 ")
1206
1207 (define_insn "indirect_jump"
1208   [(set (pc)
1209         (match_operand:SI 0 "register_operand" "r"))]
1210   ""
1211   "*
1212   return (arm_output_asm_insn (\"mov\\tpc, %0\\t@ indirect jump\", operands));
1213 ")
1214 \f
1215 ;; Misc insns
1216
1217 (define_insn "nop"
1218   [(const_int 0)]
1219   ""
1220   "*
1221   return (arm_output_asm_insn (\"mov\\tr0, r0\\t@ nop\", operands));
1222 ")
1223 \f
1224 ;; Patterns to allow combination of arithmetic, cond code and shifts
1225
1226 ;(define_insn ""
1227 ;  [(set (match_operand:SI 0 "register_operand" "=r")
1228 ;        (match_operator:SI 1 "shiftable_operator"
1229 ;          [(match_operand:SI 2 "register_operand" "r")
1230 ;           (match_operator:SI 3 "shift_operator"
1231 ;             [(match_operand:SI 4 "register_operand" "r")
1232 ;             (match_operand:SI 5 "nonmemory_operand" "rn")])]))]
1233 ;  ""
1234 ;  "*
1235 ;  return (output_arithmetic_with_shift (operands, FALSE, FALSE));
1236 ;  "
1237 ;)
1238
1239 ;(define_insn ""
1240 ;  [(set (match_operand:SI 0 "register_operand" "=r")
1241 ;        (match_operator:SI 1 "shiftable_operator"
1242 ;          [(match_operator:SI 3 "shift_operator"
1243 ;             [(match_operand:SI 4 "register_operand" "r")
1244 ;              (match_operand:SI 5 "nonmemory_operand" "rI")])
1245 ;           (match_operand:SI 2 "register_operand" "r")]))]
1246 ;  ""
1247 ;  "*
1248 ;  return (output_arithmetic_with_shift (operands, TRUE, FALSE));
1249 ;")
1250
1251 ;; Patterns to allow combination of arithmetic and left shift
1252
1253 ;(define_insn ""
1254 ;  [(set (match_operand:SI 0 "register_operand" "=r")
1255 ;        (match_operator:SI 1 "shiftable_operator"
1256 ;          [(match_operand:SI 2 "register_operand" "r")
1257 ;             (mult:SI
1258 ;               (match_operand:SI 3 "register_operand" "r")
1259 ;               (match_operand:SI 4 "power_of_two_operand" "n"))]))]
1260 ;  ""
1261 ;  "*
1262 ;  return (output_arithmetic_with_immediate_multiply (operands, FALSE));
1263 ;")
1264
1265 (define_insn ""
1266   [(set (match_operand:SI 0 "register_operand" "=r")
1267         (match_operator:SI 1 "shiftable_operator"
1268           [(mult:SI
1269             (match_operand:SI 3 "register_operand" "r")
1270             (match_operand:SI 4 "power_of_two_operand" "n"))
1271            (match_operand:SI 2 "register_operand" "r")]))]
1272   ""
1273   "*
1274   return (output_arithmetic_with_immediate_multiply (operands, TRUE));
1275 ")
1276
1277 ;; This variant of the above insn can occur if the first operand is the
1278 ;; frame pointer and we eliminate that.  This is a kludge, but there doesn't
1279 ;; seem to be a way around it.
1280
1281 (define_insn ""
1282   [(set (match_operand:SI 0 "register_operand" "=&r")
1283         (plus:SI (plus:SI (mult:SI (match_operand:SI 3 "register_operand" "r")
1284                                    (match_operand:SI 4 "power_of_two_operand" "n"))
1285                           (match_operand:SI 2 "register_operand" "r"))
1286                  (match_operand:SI 1 "const_int_operand" "n")))]
1287   "reload_in_progress"
1288   "*
1289 {
1290   int shift = int_log2 (INTVAL (operands[4]));
1291   operands[4] = GEN_INT (shift);
1292   arm_output_asm_insn (\"add\\t%0, %2, %3, asl#%4\", operands);
1293   operands[2] = operands[0];
1294   return output_add_immediate (operands);
1295 }")
1296 \f
1297 ;; Peephole optimizations.
1298
1299 ;; When testing a bitset smaller than 9 bits for (un)equality, a
1300 ;; shift/and/cmp/b{eq,ne} sequence can be replaced by one tst and the same
1301 ;; branch sequence.
1302
1303 ;;(define_peephole
1304 ;;  [(set (match_operand:SI 0 "register_operand" "=r")
1305 ;;      (lshiftrt:SI (match_dup 0)
1306 ;;                   (match_operand 1 "immediate_operand" "")))
1307 ;;   (set (match_dup 0)
1308 ;;      (and:SI (match_dup 0)
1309 ;;              (match_operand 2 "immediate_operand" "")))
1310 ;;   (set (cc0) (match_dup 0))
1311 ;;   (set (pc)
1312 ;;      (if_then_else (ne (cc0) (const_int 0))
1313 ;;                    (label_ref (match_operand 3 "" ""))
1314 ;;                    (pc)))]
1315 ;;  "dead_or_set_p (PREV_INSN (insn), operands[0])
1316 ;;   && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[1]) == CONST_INT
1317 ;;   && const_ok_for_arm (INTVAL (operands[2]) << INTVAL (operands[1]))"
1318 ;;  "*
1319 ;;  operands[2] = gen_rtx (CONST_INT, VOIDmode,
1320 ;;                         INTVAL (operands[2]) << INTVAL (operands[1]));
1321 ;;  arm_output_asm_insn (\"tst\\t%0, %2\\t\\t@ ph test bitfield\", operands);
1322 ;;  return (arm_output_asm_insn (\"bne\\t%l3\", operands));
1323 ;;")
1324
1325 ;;(define_peephole
1326 ;;  [(set (match_operand:SI 0 "register_operand" "=r")
1327 ;;      (lshiftrt:SI (match_dup 0)
1328 ;;                   (match_operand 1 "immediate_operand" "")))
1329 ;;   (set (match_dup 0)
1330 ;;      (and:SI (match_dup 0)
1331 ;;              (match_operand 2 "immediate_operand" "")))
1332 ;;   (set (cc0) (match_dup 0))
1333 ;;   (set (pc)
1334 ;;      (if_then_else (ne (cc0) (const_int 0))
1335 ;;                    (pc)
1336 ;;                    (label_ref (match_operand 3 "" ""))))]
1337 ;;  "dead_or_set_p (prev_real_insn (insn), operands[0])
1338 ;;   && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[1]) == CONST_INT
1339 ;;   && const_ok_for_arm (INTVAL (operands[2]) << INTVAL (operands[1]))"
1340 ;;  "*
1341 ;;  operands[2] = gen_rtx (CONST_INT, VOIDmode,
1342 ;;                         INTVAL (operands[2]) << INTVAL (operands[1]));
1343 ;;  arm_output_asm_insn (\"tst\\t%0, %2\\t\\t@ ph test bitfield\", operands);
1344 ;;  return (arm_output_asm_insn (\"beq\\t%l3\", operands));
1345 ;;")
1346
1347 ;; This allows negative constants to be compared since GCC appears not to try
1348 ;; converting them with a NEG.
1349
1350 ;;(define_peephole
1351 ;;  [(set (match_operand:SI 2 "register_operand" "=r")
1352 ;;        (match_operand:SI 1 "immediate_operand" "n"))
1353 ;;   (set (cc0)
1354 ;;        (compare (match_operand:SI 0 "register_operand" "r")
1355 ;;                 (match_dup 1)))]
1356 ;;  "const_ok_for_arm (-INTVAL (operands[1]))
1357 ;;   && dead_or_set_p (prev_real_insn (insn), operands[0])"
1358 ;;  "*
1359 ;;  operands[1] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[1]));
1360 ;;  return (arm_output_asm_insn (\"cmn\\t%0, %1\\t\\t@ ph negate comparison\", operands));
1361 ;;")