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).
6 ;; This file is part of GNU CC.
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)
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.
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.
22 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
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.
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")))]
38 arm_output_asm_insn (\"adds\\t%0, %1, %2\", operands);
39 return (arm_output_asm_insn (\"adc\\t%R0, %R1, %R2\", operands));
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")))]
48 switch (which_alternative)
51 return (arm_output_asm_insn (\"add\\t%0, %1, %2\", operands));
53 return (output_add_immediate (operands));
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")))]
63 return (arm_output_asm_insn (\"adfs\\t%0, %1, %2\", operands));
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")))]
72 return (arm_output_asm_insn (\"adfd\\t%0, %1, %2\", operands));
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")))]
81 arm_output_asm_insn (\"subs\\t%0, %1, %2\", operands);
82 return (arm_output_asm_insn (\"sbc\\t%R0, %R1, %R2\", operands));
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")))]
91 switch (which_alternative)
94 return (arm_output_asm_insn (\"sub\\t%0, %1, %2\", operands));
96 operands[2] = gen_rtx (CONST_INT, VOIDmode, -INTVAL (operands[2]));
97 return (output_add_immediate (operands));
99 return (arm_output_asm_insn (\"rsb\\t%0, %2, %1\", operands));
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")))]
109 switch (which_alternative)
112 return (arm_output_asm_insn (\"sufs\\t%0, %1, %2\", operands));
114 return (arm_output_asm_insn (\"rsfs\\t%0, %2, %1\", operands));
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")))]
124 switch (which_alternative)
127 return (arm_output_asm_insn (\"sufd\\t%0, %1, %2\", operands));
129 return (arm_output_asm_insn (\"rsfd\\t%0, %2, %1\", operands));
133 ;; Multiplication insns
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")))]
142 if (REGNO (operands[0]) == REGNO (operands[1]))
143 return (arm_output_asm_insn (\"mul\\t%0, %2, %1\", operands));
145 return (arm_output_asm_insn (\"mul\\t%0, %1, %2\", operands));
148 ;; Unnamed templates to match MLA instruction.
151 [(set (match_operand:SI 0 "register_operand" "=&r")
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")))]
158 if (REGNO (operands[0]) == REGNO (operands[1]))
159 return (arm_output_asm_insn (\"mla\\t%0, %2, %1, %3\", operands));
161 return (arm_output_asm_insn (\"mla\\t%0, %1, %2, %3\", operands));
165 [(set (match_operand:SI 0 "register_operand" "=&r")
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"))))]
172 if (REGNO (operands[0]) == REGNO (operands[1]))
173 return (arm_output_asm_insn (\"mla\\t%0, %2, %1, %3\", operands));
175 return (arm_output_asm_insn (\"mla\\t%0, %1, %2, %3\", operands));
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")))]
183 "*return (arm_output_asm_insn (\"mufs\\t%0, %1, %2\", operands));")
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")))]
191 return (arm_output_asm_insn (\"mufd\\t%0, %1, %2\", operands));
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")))]
202 switch (which_alternative)
205 return (arm_output_asm_insn (\"dvfs\\t%0, %1, %2\", operands));
207 return (arm_output_asm_insn (\"rdfs\\t%0, %2, %1\", operands));
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")))]
217 switch (which_alternative)
220 return (arm_output_asm_insn (\"dvfd\\t%0, %1, %2\", operands));
222 return (arm_output_asm_insn (\"rdfd\\t%0, %2, %1\", operands));
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")))]
234 return (arm_output_asm_insn (\"rmfs\\t%0, %1, %2\", operands));
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")))]
243 return (arm_output_asm_insn (\"rmfd\\t%0, %1, %2\", operands));
246 ;; Boolean and,ior,xor insns
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")))]
254 arm_output_asm_insn (\"and\\t%0, %1, %2\", operands);
255 return (arm_output_asm_insn (\"and\\t%R0, %R1, %R2\", operands));
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")))]
264 return (arm_output_asm_insn (\"and\\t%0, %1, %2\", operands));
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"))))]
273 return (arm_output_asm_insn (\"bic\\t%0, %1, %2\", operands));
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")))]
282 arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands);
283 return (arm_output_asm_insn (\"orr\\t%R0, %R1, %R2\", operands));
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")))]
292 switch (which_alternative)
295 return (arm_output_asm_insn (\"orr\\t%0, %1, %2\", operands));
297 return (output_multi_immediate (operands,
298 \"orr\\t%0, %1, %2\", \"orr\\t%0, %0, %2\",
299 2, INTVAL (operands[2])));
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")))]
309 switch (which_alternative)
312 return (arm_output_asm_insn (\"eor\\t%0, %1, %2\", operands));
314 return (output_multi_immediate (operands,
315 \"eor\\t%0, %1, %2\", \"eor\\t%0, %0, %2\",
316 2, INTVAL (operands[2])));
320 ;; Shift and rotation insns
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")))]
328 return (output_shifted_move (ASHIFT, operands));
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")))]
337 return (output_shifted_move (ASHIFTRT, operands));
340 ;; lshlsi3 is not defined because shift counts cannot be negative
341 ;; An unnamed pattern is needed for expansion of zero_extend.
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")))]
349 return (output_shifted_move (LSHIFT, operands));
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")))]
358 return (output_shifted_move (LSHIFTRT, operands));
361 ;; rotlsi3 is not defined yet to see what happens
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")))]
369 switch (which_alternative)
372 return (arm_output_asm_insn (\"mov\\t%0, %1,ror %2\", operands));
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));
380 ;; Unary arithmetic insns
382 (define_insn "negdi2"
383 [(set (match_operand:DI 0 "di_operand" "=&r")
384 (neg:DI (match_operand:DI 1 "di_operand" "r")))]
387 arm_output_asm_insn (\"rsb\\t%0, %1, #0\", operands);
388 return (arm_output_asm_insn (\"rsc\\t%R0, %R1, #0\", operands));
391 (define_insn "negsi2"
392 [(set (match_operand:SI 0 "register_operand" "=r")
393 (neg:SI (match_operand:SI 1 "register_operand" "r")))]
396 return (arm_output_asm_insn (\"rsb\\t%0, %1, #0\", operands));
399 (define_insn "negsf2"
400 [(set (match_operand:SF 0 "register_operand" "=f")
401 (neg:SF (match_operand:SF 1 "register_operand" "f")))]
404 return (arm_output_asm_insn (\"mnfs\\t%0, %1\", operands));
407 (define_insn "negdf2"
408 [(set (match_operand:DF 0 "register_operand" "=f")
409 (neg:DF (match_operand:DF 1 "register_operand" "f")))]
412 return (arm_output_asm_insn (\"mnfd\\t%0, %1\", operands));
415 (define_insn "abssf2"
416 [(set (match_operand:SF 0 "register_operand" "=f")
417 (abs:SF (match_operand:SF 1 "register_operand" "f")))]
420 return (arm_output_asm_insn (\"abss\\t%0, %1\", operands));
423 (define_insn "absdf2"
424 [(set (match_operand:DF 0 "register_operand" "=f")
425 (abs:DF (match_operand:DF 1 "register_operand" "f")))]
428 return (arm_output_asm_insn (\"absd\\t%0, %1\", operands));
431 (define_insn "sqrtsf2"
432 [(set (match_operand:SF 0 "register_operand" "=f")
433 (sqrt:SF (match_operand:SF 1 "register_operand" "f")))]
436 return (arm_output_asm_insn (\"sqts\\t%0, %1\", operands));
439 (define_insn "sqrtdf2"
440 [(set (match_operand:DF 0 "register_operand" "=f")
441 (sqrt:DF (match_operand:DF 1 "register_operand" "f")))]
444 return (arm_output_asm_insn (\"sqtd\\t%0, %1\", operands));
447 (define_insn "one_cmplsi2"
448 [(set (match_operand:SI 0 "register_operand" "=r")
449 (not:SI (match_operand:SI 1 "register_operand" "r")))]
452 return (arm_output_asm_insn (\"mvn\\t%0, %1\", operands));
455 ;; Fixed <--> Floating conversion insns
457 (define_insn "floatsisf2"
458 [(set (match_operand:SF 0 "register_operand" "=f")
459 (float:SF (match_operand:SI 1 "register_operand" "r")))]
462 return (arm_output_asm_insn (\"flts\\t%0, %1\", operands));
465 (define_insn "floatsidf2"
466 [(set (match_operand:DF 0 "register_operand" "=f")
467 (float:DF (match_operand:SI 1 "register_operand" "r")))]
470 return (arm_output_asm_insn (\"fltd\\t%0, %1\", operands));
475 (define_insn "truncdfsf2"
476 [(set (match_operand:SF 0 "register_operand" "=f")
478 (match_operand:DF 1 "register_operand" "f")))]
481 return (arm_output_asm_insn (\"mvfs\\t%0, %1\", operands));
484 ;; Zero extension instructions.
486 (define_expand "zero_extendhisi2"
488 (ashift:SI (match_operand:HI 1 "register_operand" "")
490 (set (match_operand:SI 0 "register_operand" "")
491 (lshiftrt:SI (match_dup 2)
495 { operands[1] = gen_lowpart (SImode, operands[1]);
496 operands[2] = gen_reg_rtx (SImode); }")
498 (define_insn "zero_extendqihi2"
499 [(set (match_operand:HI 0 "register_operand" "=r")
501 (match_operand:QI 1 "register_operand" "r")))]
504 return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ zero_extendqihi2\", operands));
507 (define_insn "zero_extendqisi2"
508 [(set (match_operand:SI 0 "register_operand" "=r,r")
510 (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
513 switch (which_alternative)
516 return (arm_output_asm_insn (\"and\\t%0, %1, #255\\t@ zero_extendqisi2\", operands));
518 return (arm_output_asm_insn (\"ldrb\\t%0, %1\\t@ zero_extendqisi2\", operands));
522 (define_expand "extendhisi2"
524 (ashift:SI (match_operand:HI 1 "register_operand" "")
526 (set (match_operand:SI 0 "register_operand" "")
527 (ashiftrt:SI (match_dup 2)
531 { operands[1] = gen_lowpart (SImode, operands[1]);
532 operands[2] = gen_reg_rtx (SImode); }")
534 (define_expand "extendqihi2"
536 (ashift:SI (match_operand:QI 1 "register_operand" "")
538 (set (match_operand:HI 0 "register_operand" "")
539 (ashiftrt:SI (match_dup 2)
543 { operands[0] = gen_lowpart (SImode, operands[0]);
544 operands[1] = gen_lowpart (SImode, operands[1]);
545 operands[2] = gen_reg_rtx (SImode); }")
547 (define_expand "extendqisi2"
549 (ashift:SI (match_operand:QI 1 "register_operand" "")
551 (set (match_operand:SI 0 "register_operand" "")
552 (ashiftrt:SI (match_dup 2)
556 { operands[1] = gen_lowpart (SImode, operands[1]);
557 operands[2] = gen_reg_rtx (SImode); }")
559 (define_insn "extendsfdf2"
560 [(set (match_operand:DF 0 "register_operand" "=f")
561 (float_extend:DF (match_operand:SF 1 "register_operand" "f")))]
564 return (arm_output_asm_insn (\"mvfd\\t%0, %1\", operands));
567 ;; Move insns (including loads and stores)
569 ;; XXX Just some ideas about movti.
571 ;;(define_expand "loadti"
572 ;; [(set (match_operand:TI 0 "register_operand" "")
573 ;; (mem:TI (match_operand:SI 1 "address_operand" "")))]
576 ;;(define_expand "storeti"
577 ;; [(set (mem:TI (match_operand:TI 0 "address_operand" ""))
578 ;; (match_operand:TI 1 "register_operand" ""))]
581 ;;(define_expand "movti"
582 ;; [(set (match_operand:TI 0 "general_operand" "")
583 ;; (match_operand:TI 1 "general_operand" ""))]
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));
602 ;; Recognise garbage generated above.
605 ;; [(set (match_operand:TI 0 "general_operand" "=r,r,r,<,>,m")
606 ;; (match_operand:TI 1 "general_operand" "<,>,m,r,r,r"))]
610 ;; register mem = (which_alternative < 3);
611 ;; register char *template;
613 ;; operands[mem] = XEXP (operands[mem], 0);
614 ;; switch (which_alternative)
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;
623 ;; return (arm_output_asm_insn (template, operands));
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"))]
632 return (output_move_double (operands));
636 [(set (match_operand:SI 0 "general_operand" "=r,r,r,m")
637 (match_operand:SI 1 "general_operand" "r,n,m,r"))]
640 switch (which_alternative)
643 return (arm_output_asm_insn (\"mov\\t%0, %1\", operands));
645 return (output_mov_immediate (operands));
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));
651 return (arm_output_asm_insn (\"ldr\\t%0, %1\", operands));
653 return (arm_output_asm_insn (\"str\\t%1, %0\", operands));
657 ;; XXX The movhi stuff isn't as correct or as nice as it could be...
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).
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))]
675 ;; Load op0 from mem:op1. Subroutine in case we're reloading and the normal
676 ;; loadhi is not allowed.
678 ;;(define_expand "reloadhi"
680 ;; (mem:SI (match_operand:SI 1 "address_operand" "")))
681 ;; (set (match_operand:HI 0 "register_operand" "")
682 ;; (subreg:HI (reg:SI 10) 0))]
685 ;; Store op0 into mem:op1. Subroutine in case we're reloading and the normal
686 ;; storehi is not allowed.
688 (define_expand "restorehi"
689 [(set (mem:QI (match_operand:SI 1 "" ""))
692 (ashiftrt:SI (match_operand 0 "" "") (const_int 8)))
693 (set (mem:QI (plus:SI (match_dup 1) (const_int 1)))
698 operands[2] = gen_lowpart (QImode, operands[0]);
699 operands[0] = gen_lowpart (SImode, operands[0]);
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)
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
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
717 { operands[3] = gen_lowpart (QImode, operands[0]);
718 operands[0] = gen_lowpart (SImode, operands[0]);
719 operands[2] = gen_reg_rtx (SImode); }")
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)
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)))
734 int value = INTVAL (operands[0]);
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));
741 (define_expand "movhi"
742 [(set (match_operand:HI 0 "general_operand" "")
743 (match_operand:HI 1 "general_operand" ""))]
749 if (reload_in_progress || reload_completed)
751 if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == REG)
752 insn = gen_restorehi (operands[1], XEXP (operands[0], 0));
754 insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]);
758 if (GET_CODE (operands[0]) == MEM)
760 if (GET_CODE (operands[1]) == CONST_INT)
762 insn = gen_storeinthi (operands[1], force_reg (SImode, XEXP (operands[0], 0)));
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)));
772 else if (GET_CODE (operands[1]) == MEM)
774 insn = gen_loadhi (operands[0], XEXP (operands[1], 0),
775 gen_reg_rtx (SImode));
779 insn = gen_rtx (SET, VOIDmode, operands[0], operands[1]);
786 ;; Pattern to recognise insn generated default case above
789 [(set (match_operand:HI 0 "general_operand" "=r,r,r,m")
790 (match_operand:HI 1 "general_operand" "r,n,m,r"))]
793 switch (which_alternative)
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));
803 [(set (match_operand:QI 0 "general_operand" "=r,r,r,m")
804 (match_operand:QI 1 "general_operand" "r,n,m,r"))]
807 switch (which_alternative)
810 return (arm_output_asm_insn (\"mov\\t%0, %1\", operands));
812 return (output_mov_immediate (operands));
814 return (arm_output_asm_insn (\"ldrb\\t%0, %1\", operands));
816 return (arm_output_asm_insn (\"strb\\t%1, %0\", operands));
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"))]
825 switch (which_alternative)
828 return (arm_output_asm_insn (\"mvfs\\t%0, %1\", operands));
830 return (arm_output_asm_insn (\"ldfs\\t%0, %1\", operands));
832 return (arm_output_asm_insn (\"stfs\\t%1, %0\", operands));
834 arm_output_asm_insn(\"stmfd\\tsp!, {%1}\", operands);
835 return (arm_output_asm_insn (\"ldfs\\t%0, [sp],#4\", operands));
837 arm_output_asm_insn(\"stfs\\t%1, [sp,#-4]!\", operands);
838 return (arm_output_asm_insn (\"ldmfd\\tsp!, {%0}\", operands));
840 return (arm_output_asm_insn (\"mov\\t%0, %1\", operands));
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"))]
849 switch (which_alternative)
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));
860 ;; Comparison and test insns
864 (compare (match_operand:SI 0 "register_operand" "r")
865 (match_operand:SI 1 "arm_rhs_operand" "rI")))]
868 return (arm_output_asm_insn (\"cmp\\t%0, %1\", operands));
872 [(set (cc0) (match_operand:SI 0 "register_operand" "r"))]
875 return (arm_output_asm_insn (\"cmp\\t%0, #0\", operands));
880 (compare (match_operand:SI 0 "register_operand" "r")
881 (neg:SI (match_operand:SI 1 "arm_rhs_operand" "rI"))))]
884 return (arm_output_asm_insn (\"cmn\\t%0, %1\", operands));
889 (compare (match_operand:SF 0 "register_operand" "f")
890 (match_operand:SF 1 "fpu_rhs_operand" "fG")))]
893 return (arm_output_asm_insn (\"cmf\\t%0, %1\", operands));
898 (compare (match_operand:DF 0 "register_operand" "f")
899 (match_operand:DF 1 "fpu_rhs_operand" "fG")))]
902 return (arm_output_asm_insn (\"cmf\\t%0, %1\", operands));
905 ;; Conditional branch insns
909 (if_then_else (eq (cc0) (const_int 0))
910 (label_ref (match_operand 0 "" ""))
914 return (arm_output_asm_insn (\"beq\\t%l0\", operands));
919 (if_then_else (ne (cc0) (const_int 0))
920 (label_ref (match_operand 0 "" ""))
924 return (arm_output_asm_insn (\"bne\\t%l0\", operands));
929 (if_then_else (gt (cc0) (const_int 0))
930 (label_ref (match_operand 0 "" ""))
934 return (arm_output_asm_insn (\"bgt\\t%l0\", operands));
939 (if_then_else (le (cc0) (const_int 0))
940 (label_ref (match_operand 0 "" ""))
944 return (arm_output_asm_insn (\"ble\\t%l0\", operands));
949 (if_then_else (ge (cc0) (const_int 0))
950 (label_ref (match_operand 0 "" ""))
954 return (arm_output_asm_insn (\"bge\\t%l0\", operands));
959 (if_then_else (lt (cc0) (const_int 0))
960 (label_ref (match_operand 0 "" ""))
964 return (arm_output_asm_insn (\"blt\\t%l0\", operands));
969 (if_then_else (gtu (cc0) (const_int 0))
970 (label_ref (match_operand 0 "" ""))
974 return (arm_output_asm_insn (\"bhi\\t%l0\", operands));
979 (if_then_else (leu (cc0) (const_int 0))
980 (label_ref (match_operand 0 "" ""))
984 return (arm_output_asm_insn (\"bls\\t%l0\", operands));
989 (if_then_else (geu (cc0) (const_int 0))
990 (label_ref (match_operand 0 "" ""))
994 return (arm_output_asm_insn (\"bhs\\t%l0\", operands));
999 (if_then_else (ltu (cc0) (const_int 0))
1000 (label_ref (match_operand 0 "" ""))
1004 return (arm_output_asm_insn (\"blo\\t%l0\", operands));
1007 ;; Inverted conditional branch insns
1011 (if_then_else (eq (cc0) (const_int 0))
1013 (label_ref (match_operand 0 "" ""))))]
1016 return (arm_output_asm_insn (\"bne\\t%l0\", operands));
1021 (if_then_else (ne (cc0) (const_int 0))
1023 (label_ref (match_operand 0 "" ""))))]
1026 return (arm_output_asm_insn (\"beq\\t%l0\", operands));
1031 (if_then_else (gt (cc0) (const_int 0))
1033 (label_ref (match_operand 0 "" ""))))]
1036 return (arm_output_asm_insn (\"ble\\t%l0\", operands));
1041 (if_then_else (le (cc0) (const_int 0))
1043 (label_ref (match_operand 0 "" ""))))]
1046 return (arm_output_asm_insn (\"bgt\\t%l0\", operands));
1051 (if_then_else (ge (cc0) (const_int 0))
1053 (label_ref (match_operand 0 "" ""))))]
1056 return (arm_output_asm_insn (\"blt\\t%l0\", operands));
1061 (if_then_else (lt (cc0) (const_int 0))
1063 (label_ref (match_operand 0 "" ""))))]
1066 return (arm_output_asm_insn (\"bge\\t%l0\", operands));
1071 (if_then_else (gtu (cc0) (const_int 0))
1073 (label_ref (match_operand 0 "" ""))))]
1076 return (arm_output_asm_insn (\"bls\\t%l0\", operands));
1081 (if_then_else (leu (cc0) (const_int 0))
1083 (label_ref (match_operand 0 "" ""))))]
1086 return (arm_output_asm_insn (\"bhi\\t%l0\", operands));
1091 (if_then_else (geu (cc0) (const_int 0))
1093 (label_ref (match_operand 0 "" ""))))]
1096 return (arm_output_asm_insn (\"blo\\t%l0\", operands));
1101 (if_then_else (ltu (cc0) (const_int 0))
1103 (label_ref (match_operand 0 "" ""))))]
1106 return (arm_output_asm_insn (\"bhs\\t%l0\", operands));
1109 ;; Jump and linkage insns
1110 ;; `return' is still a jump-to-epilogue...
1114 (label_ref (match_operand 0 "" "")))]
1117 return (arm_output_asm_insn (\"b\\t%l0\", operands));
1121 [(call (match_operand 0 "memory_operand" "m")
1122 (match_operand 1 "general_operand" "g"))
1123 (clobber (reg:SI 14))]
1126 return (output_call (operands));
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))]
1136 return (output_call (&operands[1]));
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.
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"
1148 return (arm_output_asm_insn (\"bl\\t%a0\", operands));
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"
1158 return (arm_output_asm_insn (\"bl\\t%a1\", operands));
1161 ;; Call subroutine returning any type.
1163 (define_expand "untyped_call"
1164 [(parallel [(call (match_operand 0 "" "")
1166 (match_operand 1 "" "")
1167 (match_operand 2 "" "")])]
1173 emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
1175 for (i = 0; i < XVECLEN (operands[2], 0); i++)
1177 rtx set = XVECEXP (operands[2], 0, i);
1178 emit_move_insn (SET_DEST (set), SET_SRC (set));
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
1185 emit_insn (gen_blockage ());
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.
1193 (define_insn "blockage"
1194 [(unspec_volatile [(const_int 0)] 0)]
1198 (define_insn "tablejump"
1200 (match_operand:SI 0 "register_operand" "r"))
1201 (use (label_ref (match_operand 1 "" "")))]
1204 return (arm_output_asm_insn (\"mov\\tpc, %0\\t@ table jump, label %l1\", operands));
1207 (define_insn "indirect_jump"
1209 (match_operand:SI 0 "register_operand" "r"))]
1212 return (arm_output_asm_insn (\"mov\\tpc, %0\\t@ indirect jump\", operands));
1221 return (arm_output_asm_insn (\"mov\\tr0, r0\\t@ nop\", operands));
1224 ;; Patterns to allow combination of arithmetic, cond code and shifts
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")])]))]
1235 ; return (output_arithmetic_with_shift (operands, FALSE, FALSE));
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")]))]
1248 ; return (output_arithmetic_with_shift (operands, TRUE, FALSE));
1251 ;; Patterns to allow combination of arithmetic and left shift
1254 ; [(set (match_operand:SI 0 "register_operand" "=r")
1255 ; (match_operator:SI 1 "shiftable_operator"
1256 ; [(match_operand:SI 2 "register_operand" "r")
1258 ; (match_operand:SI 3 "register_operand" "r")
1259 ; (match_operand:SI 4 "power_of_two_operand" "n"))]))]
1262 ; return (output_arithmetic_with_immediate_multiply (operands, FALSE));
1266 [(set (match_operand:SI 0 "register_operand" "=r")
1267 (match_operator:SI 1 "shiftable_operator"
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")]))]
1274 return (output_arithmetic_with_immediate_multiply (operands, TRUE));
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.
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"
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);
1297 ;; Peephole optimizations.
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
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))
1312 ;; (if_then_else (ne (cc0) (const_int 0))
1313 ;; (label_ref (match_operand 3 "" ""))
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]))"
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));
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))
1334 ;; (if_then_else (ne (cc0) (const_int 0))
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]))"
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));
1347 ;; This allows negative constants to be compared since GCC appears not to try
1348 ;; converting them with a NEG.
1351 ;; [(set (match_operand:SI 2 "register_operand" "=r")
1352 ;; (match_operand:SI 1 "immediate_operand" "n"))
1354 ;; (compare (match_operand:SI 0 "register_operand" "r")
1356 ;; "const_ok_for_arm (-INTVAL (operands[1]))
1357 ;; && dead_or_set_p (prev_real_insn (insn), operands[0])"
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));