]> git.ipfire.org Git - thirdparty/gcc.git/blame - gcc/config/arm/arm.md
(addhi3): Use byte opcodes when the low byte of a word is known to be zero.
[thirdparty/gcc.git] / gcc / config / arm / arm.md
CommitLineData
3a33f76f
RK
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"
c4c5de64 33 [(set (match_operand:DI 0 "di_operand" "=&r")
3a33f76f
RK
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")
fd3f89a9
TG
44 (plus:SI (match_operand:SI 1 "register_operand" "r,r")
45 (match_operand:SI 2 "general_operand" "r,n")))]
3a33f76f
RK
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")
fd3f89a9
TG
59 (plus:SF (match_operand:SF 1 "register_operand" "f")
60 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
3a33f76f
RK
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")
fd3f89a9
TG
68 (plus:DF (match_operand:DF 1 "register_operand" "f")
69 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
3a33f76f
RK
70 ""
71 "*
72 return (arm_output_asm_insn (\"adfd\\t%0, %1, %2\", operands));
73")
74
75(define_insn "subdi3"
c4c5de64 76 [(set (match_operand:DI 0 "di_operand" "=&r")
3a33f76f
RK
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")
fd3f89a9
TG
87 (minus:SI (match_operand:SI 1 "arm_rhs_operand" "r,r,I")
88 (match_operand:SI 2 "general_operand" "r,n,r")))]
3a33f76f
RK
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")
fd3f89a9
TG
105 (minus:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
106 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
3a33f76f
RK
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")
fd3f89a9 120 (minus:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
3a33f76f
RK
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
448ff736 135;; The `&' is too strict, but at least generates correct code.
3a33f76f 136(define_insn "mulsi3"
448ff736 137 [(set (match_operand:SI 0 "register_operand" "=&r")
fd3f89a9
TG
138 (mult:SI (match_operand:SI 1 "register_operand" "%r")
139 (match_operand:SI 2 "register_operand" "r")))]
3a33f76f
RK
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 ""
448ff736 151 [(set (match_operand:SI 0 "register_operand" "=&r")
fd3f89a9
TG
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")))]
3a33f76f
RK
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 ""
448ff736 165 [(set (match_operand:SI 0 "register_operand" "=&r")
fd3f89a9
TG
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"))))]
3a33f76f
RK
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")
fd3f89a9
TG
180 (mult:SF (match_operand:SF 1 "register_operand" "f")
181 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
3a33f76f
RK
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")
fd3f89a9
TG
187 (mult:DF (match_operand:DF 1 "register_operand" "f")
188 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
3a33f76f
RK
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")
fd3f89a9
TG
198 (div:SF (match_operand:SF 1 "fpu_rhs_operand" "f,G")
199 (match_operand:SF 2 "fpu_rhs_operand" "fG,f")))]
3a33f76f
RK
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")
fd3f89a9
TG
213 (div:DF (match_operand:DF 1 "fpu_rhs_operand" "f,G")
214 (match_operand:DF 2 "fpu_rhs_operand" "fG,f")))]
3a33f76f
RK
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")
fd3f89a9
TG
230 (mod:SF (match_operand:SF 1 "register_operand" "f")
231 (match_operand:SF 2 "fpu_rhs_operand" "fG")))]
3a33f76f
RK
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")
fd3f89a9
TG
239 (mod:DF (match_operand:DF 1 "register_operand" "f")
240 (match_operand:DF 2 "fpu_rhs_operand" "fG")))]
3a33f76f
RK
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"
c4c5de64 249 [(set (match_operand:DI 0 "di_operand" "=&r")
3a33f76f
RK
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")
fd3f89a9
TG
260 (and:SI (match_operand:SI 1 "register_operand" "r")
261 (match_operand:SI 2 "arm_rhs_operand" "rI")))]
3a33f76f
RK
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")
fd3f89a9
TG
269 (and:SI (match_operand:SI 1 "register_operand" "r")
270 (not:SI (match_operand:SI 2 "arm_rhs_operand" "rI"))))]
3a33f76f
RK
271 ""
272 "*
273 return (arm_output_asm_insn (\"bic\\t%0, %1, %2\", operands));
274")
275
276(define_insn "iordi3"
c4c5de64 277 [(set (match_operand:DI 0 "di_operand" "=&r")
3a33f76f
RK
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")
fd3f89a9
TG
288 (ior:SI (match_operand:SI 1 "register_operand" "r,r")
289 (match_operand:SI 2 "nonmemory_operand" "r,n")))]
3a33f76f
RK
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")
fd3f89a9
TG
305 (xor:SI (match_operand:SI 1 "register_operand" "r,r")
306 (match_operand:SI 2 "nonmemory_operand" "r,n")))]
3a33f76f
RK
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\",
fd3f89a9 316 2, INTVAL (operands[2])));
3a33f76f
RK
317 }
318")
319\f
320;; Shift and rotation insns
321
322(define_insn "ashlsi3"
323 [(set (match_operand:SI 0 "register_operand" "=r")
fd3f89a9
TG
324 (ashift:SI (match_operand:SI 1 "register_operand" "r")
325 (match_operand:SI 2 "general_operand" "rn")))]
3a33f76f
RK
326 ""
327 "*
328 return (output_shifted_move (ASHIFT, operands));
329")
330
331(define_insn "ashrsi3"
332 [(set (match_operand:SI 0 "register_operand" "=r")
fd3f89a9
TG
333 (ashiftrt:SI (match_operand:SI 1 "register_operand" "r")
334 (match_operand:SI 2 "general_operand" "rn")))]
3a33f76f
RK
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")
fd3f89a9
TG
345 (lshift:SI (match_operand:SI 1 "register_operand" "r")
346 (match_operand:SI 2 "general_operand" "rn")))]
3a33f76f
RK
347 ""
348 "*
349 return (output_shifted_move (LSHIFT, operands));
350")
351
352(define_insn "lshrsi3"
353 [(set (match_operand:SI 0 "register_operand" "=r")
fd3f89a9
TG
354 (lshiftrt:SI (match_operand:SI 1 "register_operand" "r")
355 (match_operand:SI 2 "general_operand" "rn")))]
3a33f76f
RK
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")
fd3f89a9
TG
365 (rotatert:SI (match_operand:SI 1 "register_operand" "r,r")
366 (match_operand:SI 2 "general_operand" "r,n")))]
3a33f76f
RK
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)
fd3f89a9 375 operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) % 32);
3a33f76f
RK
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"
c4c5de64 383 [(set (match_operand:DI 0 "di_operand" "=&r")
fd3f89a9 384 (neg:DI (match_operand:DI 1 "di_operand" "r")))]
3a33f76f
RK
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")
fd3f89a9 393 (neg:SI (match_operand:SI 1 "register_operand" "r")))]
3a33f76f
RK
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")
fd3f89a9 401 (neg:SF (match_operand:SF 1 "register_operand" "f")))]
3a33f76f
RK
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")
fd3f89a9 409 (neg:DF (match_operand:DF 1 "register_operand" "f")))]
3a33f76f
RK
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")
fd3f89a9 417 (abs:SF (match_operand:SF 1 "register_operand" "f")))]
3a33f76f
RK
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")
fd3f89a9 425 (abs:DF (match_operand:DF 1 "register_operand" "f")))]
3a33f76f
RK
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")
fd3f89a9 433 (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
3a33f76f
RK
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")
fd3f89a9 441 (sqrt:DF (match_operand:DF 1 "register_operand" "f")))]
3a33f76f
RK
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")
fd3f89a9 449 (not:SI (match_operand:SI 1 "register_operand" "r")))]
3a33f76f
RK
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")
fd3f89a9 459 (float:SF (match_operand:SI 1 "register_operand" "r")))]
3a33f76f
RK
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")
fd3f89a9 467 (float:DF (match_operand:SI 1 "register_operand" "r")))]
3a33f76f
RK
468 ""
469 "*
470 return (arm_output_asm_insn (\"fltd\\t%0, %1\", operands));
471")
3a33f76f 472
3a7a2719 473;; Truncation insns
3a33f76f
RK
474
475(define_insn "truncdfsf2"
476 [(set (match_operand:SF 0 "register_operand" "=f")
fd3f89a9
TG
477 (float_truncate:SF
478 (match_operand:DF 1 "register_operand" "f")))]
3a33f76f
RK
479 ""
480 "*
481 return (arm_output_asm_insn (\"mvfs\\t%0, %1\", operands));
482")
483\f
448ff736 484;; Zero extension instructions.
3a33f76f
RK
485
486(define_expand "zero_extendhisi2"
fd3f89a9 487 [(set (match_dup 2)
3a33f76f
RK
488 (ashift:SI (match_operand:HI 1 "register_operand" "")
489 (const_int 16)))
fd3f89a9
TG
490 (set (match_operand:SI 0 "register_operand" "")
491 (lshiftrt:SI (match_dup 2)
492 (const_int 16)))]
3a33f76f
RK
493 ""
494 "
fd3f89a9
TG
495{ operands[1] = gen_lowpart (SImode, operands[1]);
496 operands[2] = gen_reg_rtx (SImode); }")
3a33f76f
RK
497
498(define_insn "zero_extendqihi2"
499 [(set (match_operand:HI 0 "register_operand" "=r")
fd3f89a9 500 (zero_extend:HI
3a33f76f
RK
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")
fd3f89a9 509 (zero_extend:SI
3a33f76f
RK
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
3a33f76f 522(define_expand "extendhisi2"
fd3f89a9 523 [(set (match_dup 2)
3a33f76f
RK
524 (ashift:SI (match_operand:HI 1 "register_operand" "")
525 (const_int 16)))
fd3f89a9
TG
526 (set (match_operand:SI 0 "register_operand" "")
527 (ashiftrt:SI (match_dup 2)
528 (const_int 16)))]
3a33f76f
RK
529 ""
530 "
fd3f89a9
TG
531{ operands[1] = gen_lowpart (SImode, operands[1]);
532 operands[2] = gen_reg_rtx (SImode); }")
3a33f76f 533
fd3f89a9
TG
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)))]
3a33f76f 541 ""
fd3f89a9
TG
542 "
543{ operands[0] = gen_lowpart (SImode, operands[0]);
544 operands[1] = gen_lowpart (SImode, operands[1]);
545 operands[2] = gen_reg_rtx (SImode); }")
3a33f76f
RK
546
547(define_expand "extendqisi2"
fd3f89a9 548 [(set (match_dup 2)
3a33f76f
RK
549 (ashift:SI (match_operand:QI 1 "register_operand" "")
550 (const_int 24)))
fd3f89a9
TG
551 (set (match_operand:SI 0 "register_operand" "")
552 (ashiftrt:SI (match_dup 2)
553 (const_int 24)))]
3a33f76f
RK
554 ""
555 "
fd3f89a9
TG
556{ operands[1] = gen_lowpart (SImode, operands[1]);
557 operands[2] = gen_reg_rtx (SImode); }")
3a33f76f
RK
558
559(define_insn "extendsfdf2"
560 [(set (match_operand:DF 0 "register_operand" "=f")
fd3f89a9 561 (float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
3a33f76f
RK
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")
fd3f89a9 629 (match_operand:DI 1 "di_operand" "r,n,o,r,F"))]
3a33f76f
RK
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")
fd3f89a9 637 (match_operand:SI 1 "general_operand" "r,n,m,r"))]
3a33f76f
RK
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
fd3f89a9 648 && CONSTANT_POOL_ADDRESS_P (XEXP (operands[1], 0)))
3a33f76f
RK
649 return (arm_output_llc (operands));
650 else
fd3f89a9 651 return (arm_output_asm_insn (\"ldr\\t%0, %1\", operands));
3a33f76f
RK
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"
6d5363fa 689 [(set (mem:QI (match_operand:SI 1 "" ""))
fd3f89a9
TG
690 (match_dup 2))
691 (set (reg:SI 10)
692 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3a33f76f 693 (set (mem:QI (plus:SI (match_dup 1) (const_int 1)))
fd3f89a9
TG
694 (reg:QI 10))]
695 ""
696 "
697{
698 operands[2] = gen_lowpart (QImode, operands[0]);
699 operands[0] = gen_lowpart (SImode, operands[0]);
700}")
3a33f76f
RK
701
702;; Subroutine to store a half word from a register into memory.
703;; Operand 0 is the source register (HImode)
fd3f89a9 704;; Operand 1 is the destination address in a register (SImode)
3a33f76f
RK
705
706(define_expand "storehi"
fd3f89a9 707 [;; store the low byte
6d5363fa 708 (set (mem:QI (match_operand:SI 1 "" "")) (match_dup 3))
3a33f76f 709 ;; extract the high byte
fd3f89a9
TG
710 (set (match_dup 2)
711 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
3a33f76f 712 ;; store the high byte
6d5363fa 713 (set (mem:QI (plus:SI (match_dup 1) (const_int 1)))
fd3f89a9 714 (subreg:QI (match_dup 2) 0))] ;explicit subreg safe
3a33f76f
RK
715 ""
716 "
fd3f89a9 717{ operands[3] = gen_lowpart (QImode, operands[0]);
3a7a2719 718 operands[0] = gen_lowpart (SImode, operands[0]);
fd3f89a9 719 operands[2] = gen_reg_rtx (SImode); }")
3a33f76f
RK
720
721;; Subroutine to store a half word integer constant into memory.
722;; Operand 0 is the constant
fd3f89a9 723;; Operand 1 is the destination address in a register (SImode)
3a33f76f
RK
724
725(define_expand "storeinthi"
fd3f89a9 726 [;; store the low byte
6d5363fa 727 (set (mem:QI (match_operand:SI 1 "" "")) (match_operand 0 "" ""))
3a33f76f 728 ;; store the high byte
6d5363fa 729 (set (mem:QI (plus:SI (match_dup 1) (const_int 1)))
fd3f89a9 730 (match_dup 2))]
3a33f76f
RK
731 ""
732 "
733 {
fd3f89a9 734 int value = INTVAL (operands[0]);
3a33f76f 735
fd3f89a9
TG
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));
3a33f76f
RK
738 }
739")
740
741(define_expand "movhi"
742 [(set (match_operand:HI 0 "general_operand" "")
fd3f89a9 743 (match_operand:HI 1 "general_operand" ""))]
3a33f76f
RK
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 {
3a33f76f
RK
760 if (GET_CODE (operands[1]) == CONST_INT)
761 {
fd3f89a9 762 insn = gen_storeinthi (operands[1], force_reg (SImode, XEXP (operands[0], 0)));
3a33f76f
RK
763 }
764 else
765 {
fd3f89a9
TG
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)));
3a33f76f
RK
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")
fd3f89a9 790 (match_operand:HI 1 "general_operand" "r,n,m,r"))]
3a33f76f
RK
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")
fd3f89a9 804 (match_operand:QI 1 "general_operand" "r,n,m,r"))]
3a33f76f
RK
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 }
3a33f76f
RK
818")
819
820(define_insn "movsf"
821 [(set (match_operand:SF 0 "general_operand" "=f,f,m,f,r,r")
fd3f89a9 822 (match_operand:SF 1 "general_operand" "fG,m,f,r,f,r"))]
3a33f76f
RK
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")
fd3f89a9 846 (match_operand:DF 1 "general_operand" "fG,m,f,r,f,r"))]
3a33f76f
RK
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)
fd3f89a9 864 (compare (match_operand:SI 0 "register_operand" "r")
3a33f76f
RK
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)
fd3f89a9
TG
880 (compare (match_operand:SI 0 "register_operand" "r")
881 (neg:SI (match_operand:SI 1 "arm_rhs_operand" "rI"))))]
3a33f76f
RK
882 ""
883 "*
884 return (arm_output_asm_insn (\"cmn\\t%0, %1\", operands));
885")
886
887(define_insn "cmpsf"
888 [(set (cc0)
fd3f89a9 889 (compare (match_operand:SF 0 "register_operand" "f")
3a33f76f
RK
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)
fd3f89a9 898 (compare (match_operand:DF 0 "register_operand" "f")
3a33f76f
RK
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)
fd3f89a9 909 (if_then_else (eq (cc0) (const_int 0))
304f705f
TG
910 (label_ref (match_operand 0 "" ""))
911 (pc)))]
3a33f76f
RK
912 ""
913 "*
914 return (arm_output_asm_insn (\"beq\\t%l0\", operands));
915")
916
917(define_insn "bne"
918 [(set (pc)
fd3f89a9 919 (if_then_else (ne (cc0) (const_int 0))
304f705f
TG
920 (label_ref (match_operand 0 "" ""))
921 (pc)))]
3a33f76f
RK
922 ""
923 "*
924 return (arm_output_asm_insn (\"bne\\t%l0\", operands));
925")
926
927(define_insn "bgt"
928 [(set (pc)
fd3f89a9 929 (if_then_else (gt (cc0) (const_int 0))
304f705f
TG
930 (label_ref (match_operand 0 "" ""))
931 (pc)))]
3a33f76f
RK
932 ""
933 "*
934 return (arm_output_asm_insn (\"bgt\\t%l0\", operands));
935")
936
937(define_insn "ble"
938 [(set (pc)
fd3f89a9 939 (if_then_else (le (cc0) (const_int 0))
304f705f
TG
940 (label_ref (match_operand 0 "" ""))
941 (pc)))]
3a33f76f
RK
942 ""
943 "*
944 return (arm_output_asm_insn (\"ble\\t%l0\", operands));
945")
946
947(define_insn "bge"
948 [(set (pc)
fd3f89a9 949 (if_then_else (ge (cc0) (const_int 0))
304f705f
TG
950 (label_ref (match_operand 0 "" ""))
951 (pc)))]
3a33f76f
RK
952 ""
953 "*
954 return (arm_output_asm_insn (\"bge\\t%l0\", operands));
955")
956
957(define_insn "blt"
958 [(set (pc)
fd3f89a9 959 (if_then_else (lt (cc0) (const_int 0))
304f705f
TG
960 (label_ref (match_operand 0 "" ""))
961 (pc)))]
3a33f76f
RK
962 ""
963 "*
964 return (arm_output_asm_insn (\"blt\\t%l0\", operands));
965")
966
967(define_insn "bgtu"
968 [(set (pc)
fd3f89a9 969 (if_then_else (gtu (cc0) (const_int 0))
304f705f
TG
970 (label_ref (match_operand 0 "" ""))
971 (pc)))]
3a33f76f
RK
972 ""
973 "*
974 return (arm_output_asm_insn (\"bhi\\t%l0\", operands));
975")
976
977(define_insn "bleu"
978 [(set (pc)
fd3f89a9 979 (if_then_else (leu (cc0) (const_int 0))
304f705f
TG
980 (label_ref (match_operand 0 "" ""))
981 (pc)))]
3a33f76f
RK
982 ""
983 "*
984 return (arm_output_asm_insn (\"bls\\t%l0\", operands));
985")
986
987(define_insn "bgeu"
988 [(set (pc)
fd3f89a9 989 (if_then_else (geu (cc0) (const_int 0))
304f705f
TG
990 (label_ref (match_operand 0 "" ""))
991 (pc)))]
3a33f76f
RK
992 ""
993 "*
994 return (arm_output_asm_insn (\"bhs\\t%l0\", operands));
995")
996
997(define_insn "bltu"
998 [(set (pc)
fd3f89a9 999 (if_then_else (ltu (cc0) (const_int 0))
304f705f
TG
1000 (label_ref (match_operand 0 "" ""))
1001 (pc)))]
3a33f76f
RK
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)
fd3f89a9 1011 (if_then_else (eq (cc0) (const_int 0))
304f705f
TG
1012 (pc)
1013 (label_ref (match_operand 0 "" ""))))]
3a33f76f
RK
1014 ""
1015 "*
1016 return (arm_output_asm_insn (\"bne\\t%l0\", operands));
1017")
1018
1019(define_insn ""
1020 [(set (pc)
fd3f89a9 1021 (if_then_else (ne (cc0) (const_int 0))
304f705f
TG
1022 (pc)
1023 (label_ref (match_operand 0 "" ""))))]
3a33f76f
RK
1024 ""
1025 "*
1026 return (arm_output_asm_insn (\"beq\\t%l0\", operands));
1027")
1028
1029(define_insn ""
1030 [(set (pc)
fd3f89a9 1031 (if_then_else (gt (cc0) (const_int 0))
304f705f
TG
1032 (pc)
1033 (label_ref (match_operand 0 "" ""))))]
3a33f76f
RK
1034 ""
1035 "*
1036 return (arm_output_asm_insn (\"ble\\t%l0\", operands));
1037")
1038
1039(define_insn ""
1040 [(set (pc)
fd3f89a9 1041 (if_then_else (le (cc0) (const_int 0))
304f705f
TG
1042 (pc)
1043 (label_ref (match_operand 0 "" ""))))]
3a33f76f
RK
1044 ""
1045 "*
1046 return (arm_output_asm_insn (\"bgt\\t%l0\", operands));
1047")
1048
1049(define_insn ""
1050 [(set (pc)
fd3f89a9 1051 (if_then_else (ge (cc0) (const_int 0))
304f705f
TG
1052 (pc)
1053 (label_ref (match_operand 0 "" ""))))]
3a33f76f
RK
1054 ""
1055 "*
1056 return (arm_output_asm_insn (\"blt\\t%l0\", operands));
1057")
1058
1059(define_insn ""
1060 [(set (pc)
fd3f89a9 1061 (if_then_else (lt (cc0) (const_int 0))
304f705f
TG
1062 (pc)
1063 (label_ref (match_operand 0 "" ""))))]
3a33f76f
RK
1064 ""
1065 "*
1066 return (arm_output_asm_insn (\"bge\\t%l0\", operands));
1067")
1068
1069(define_insn ""
1070 [(set (pc)
fd3f89a9 1071 (if_then_else (gtu (cc0) (const_int 0))
304f705f
TG
1072 (pc)
1073 (label_ref (match_operand 0 "" ""))))]
3a33f76f
RK
1074 ""
1075 "*
1076 return (arm_output_asm_insn (\"bls\\t%l0\", operands));
1077")
1078
1079(define_insn ""
1080 [(set (pc)
fd3f89a9 1081 (if_then_else (leu (cc0) (const_int 0))
304f705f
TG
1082 (pc)
1083 (label_ref (match_operand 0 "" ""))))]
3a33f76f
RK
1084 ""
1085 "*
1086 return (arm_output_asm_insn (\"bhi\\t%l0\", operands));
1087")
1088
1089(define_insn ""
1090 [(set (pc)
fd3f89a9 1091 (if_then_else (geu (cc0) (const_int 0))
304f705f
TG
1092 (pc)
1093 (label_ref (match_operand 0 "" ""))))]
3a33f76f
RK
1094 ""
1095 "*
1096 return (arm_output_asm_insn (\"blo\\t%l0\", operands));
1097")
1098
1099(define_insn ""
1100 [(set (pc)
fd3f89a9 1101 (if_then_else (ltu (cc0) (const_int 0))
304f705f
TG
1102 (pc)
1103 (label_ref (match_operand 0 "" ""))))]
3a33f76f
RK
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)
fd3f89a9 1114 (label_ref (match_operand 0 "" "")))]
3a33f76f
RK
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")
fd3f89a9 1122 (match_operand 1 "general_operand" "g"))
3a33f76f
RK
1123 (clobber (reg:SI 14))]
1124 ""
1125 "*
1126 return (output_call (operands));
1127")
1128
1129(define_insn "call_value"
effeb5cc 1130 [(set (match_operand 0 "" "=rf")
fd3f89a9
TG
1131 (call (match_operand 1 "memory_operand" "m")
1132 (match_operand 2 "general_operand" "g")))
3a33f76f
RK
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"))
fd3f89a9 1144 (match_operand:SI 1 "general_operand" "g"))
3a33f76f
RK
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")
fd3f89a9
TG
1153 (call (mem:SI (match_operand:SI 1 "" "i"))
1154 (match_operand:SI 2 "general_operand" "g")))
3a33f76f
RK
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
9f072981
TW
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
3a33f76f
RK
1198(define_insn "tablejump"
1199 [(set (pc)
fd3f89a9 1200 (match_operand:SI 0 "register_operand" "r"))
3a33f76f
RK
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)
fd3f89a9 1209 (match_operand:SI 0 "register_operand" "r"))]
3a33f76f
RK
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;")
6d5363fa
RS
1250
1251;; Patterns to allow combination of arithmetic and left shift
3a33f76f
RK
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
6d5363fa
RS
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);
70c2344d
RS
1292 arm_output_asm_insn (\"add\\t%0, %2, %3, asl %4\", operands);
1293 operands[2] = operands[1];
1294 operands[1] = operands[0];
6d5363fa
RS
1295 return output_add_immediate (operands);
1296}")
3a33f76f
RK
1297\f
1298;; Peephole optimizations.
1299
1300;; When testing a bitset smaller than 9 bits for (un)equality, a
1301;; shift/and/cmp/b{eq,ne} sequence can be replaced by one tst and the same
1302;; branch sequence.
1303
1304;;(define_peephole
1305;; [(set (match_operand:SI 0 "register_operand" "=r")
1306;; (lshiftrt:SI (match_dup 0)
1307;; (match_operand 1 "immediate_operand" "")))
1308;; (set (match_dup 0)
1309;; (and:SI (match_dup 0)
1310;; (match_operand 2 "immediate_operand" "")))
1311;; (set (cc0) (match_dup 0))
1312;; (set (pc)
1313;; (if_then_else (ne (cc0) (const_int 0))
1314;; (label_ref (match_operand 3 "" ""))
1315;; (pc)))]
1316;; "dead_or_set_p (PREV_INSN (insn), operands[0])
1317;; && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[1]) == CONST_INT
1318;; && const_ok_for_arm (INTVAL (operands[2]) << INTVAL (operands[1]))"
1319;; "*
1320;; operands[2] = gen_rtx (CONST_INT, VOIDmode,
1321;; INTVAL (operands[2]) << INTVAL (operands[1]));
1322;; arm_output_asm_insn (\"tst\\t%0, %2\\t\\t@ ph test bitfield\", operands);
1323;; return (arm_output_asm_insn (\"bne\\t%l3\", operands));
1324;;")
1325
1326;;(define_peephole
1327;; [(set (match_operand:SI 0 "register_operand" "=r")
1328;; (lshiftrt:SI (match_dup 0)
1329;; (match_operand 1 "immediate_operand" "")))
1330;; (set (match_dup 0)
1331;; (and:SI (match_dup 0)
1332;; (match_operand 2 "immediate_operand" "")))
1333;; (set (cc0) (match_dup 0))
1334;; (set (pc)
1335;; (if_then_else (ne (cc0) (const_int 0))
1336;; (pc)
1337;; (label_ref (match_operand 3 "" ""))))]
1338;; "dead_or_set_p (prev_real_insn (insn), operands[0])
1339;; && GET_CODE (operands[2]) == CONST_INT && GET_CODE (operands[1]) == CONST_INT
1340;; && const_ok_for_arm (INTVAL (operands[2]) << INTVAL (operands[1]))"
1341;; "*
1342;; operands[2] = gen_rtx (CONST_INT, VOIDmode,
1343;; INTVAL (operands[2]) << INTVAL (operands[1]));
1344;; arm_output_asm_insn (\"tst\\t%0, %2\\t\\t@ ph test bitfield\", operands);
1345;; return (arm_output_asm_insn (\"beq\\t%l3\", operands));
1346;;")
1347
1348;; This allows negative constants to be compared since GCC appears not to try
1349;; converting them with a NEG.
1350
1351;;(define_peephole
1352;; [(set (match_operand:SI 2 "register_operand" "=r")
1353;; (match_operand:SI 1 "immediate_operand" "n"))
1354;; (set (cc0)
1355;; (compare (match_operand:SI 0 "register_operand" "r")
1356;; (match_dup 1)))]
1357;; "const_ok_for_arm (-INTVAL (operands[1]))
1358;; && dead_or_set_p (prev_real_insn (insn), operands[0])"
1359;; "*
1360;; operands[1] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[1]));
1361;; return (arm_output_asm_insn (\"cmn\\t%0, %1\\t\\t@ ph negate comparison\", operands));
1362;;")