1 ;; XSTORMY16 Machine description template
2 ;; Copyright (C) 1997, 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
3 ;; Contributed by Red Hat, Inc.
5 ;; This file is part of GNU CC.
7 ;; GNU CC is free software; you can redistribute it and/or modify
8 ;; it under the terms of the GNU General Public License as published by
9 ;; the Free Software Foundation; either version 2, or (at your option)
12 ;; GNU CC is distributed in the hope that it will be useful,
13 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
14 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 ;; GNU General Public License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GNU CC; see the file COPYING. If not, write to
19 ;; the Free Software Foundation, 59 Temple Place - Suite 330,
20 ;; Boston, MA 02111-1307, USA.
22 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
25 ;; ::::::::::::::::::::
29 ;; ::::::::::::::::::::
31 ; Categorize branches for the conditional in the length attribute.
32 (define_attr "branch_class" "notdirectbranch,br12,bcc12,bcc8p2,bcc8p4"
33 (const_string "notdirectbranch"))
35 ; The length of an instruction, used for branch shortening.
36 (define_attr "length" ""
38 [(eq_attr "branch_class" "br12")
39 (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2046))
40 (lt (minus (match_dup 0) (pc)) (const_int 2048)))
43 (eq_attr "branch_class" "bcc12")
44 (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
45 (lt (minus (match_dup 0) (pc)) (const_int 2048)))
48 (eq_attr "branch_class" "bcc8p2")
49 (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -124))
50 (lt (minus (match_dup 0) (pc)) (const_int 128)))
53 (eq_attr "branch_class" "bcc8p4")
54 (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -122))
55 (lt (minus (match_dup 0) (pc)) (const_int 128)))
60 ; The operand which determines the setting of Rpsw.
61 ; The numbers indicate the operand number,
62 ; 'clobber' indicates it is changed in some unspecified way
63 ; 'nop' means it is not changed.
64 (define_attr "psw_operand" "clobber,nop,0,1,2,3,4" (const_string "0"))
66 (define_asm_attributes [(set_attr "length" "4")
67 (set_attr "psw_operand" "clobber")])
70 ;; ::::::::::::::::::::
74 ;; ::::::::::::::::::::
75 ;; push/pop qi and hi are here as separate insns rather than part of
76 ;; the movqi/hi patterns because we need to ensure that reload isn't
77 ;; passed anything it can't cope with. Without these patterns, we
80 ;; (set (mem (post_inc (sp))) mem (post_inc (reg)))
82 ;; If, in this example, reg needs reloading, reload will read reg from
83 ;; the stack , adjust sp, and store reg back at what is now the wrong
84 ;; offset. By using separate patterns for push and pop we ensure that
85 ;; insns like this one are never generated.
88 [(set (mem:QI (post_inc (reg:HI 15)))
89 (match_operand:QI 0 "register_operand" "r"))]
92 [(set_attr "psw_operand" "nop")
93 (set_attr "length" "2")])
96 [(set (match_operand:QI 0 "register_operand" "=r")
97 (mem:QI (pre_dec (reg:HI 15))))]
100 [(set_attr "psw_operand" "nop")
101 (set_attr "length" "2")])
103 (define_expand "movqi"
104 [(set (match_operand:QI 0 "nonimmediate_nonstack_operand" "")
105 (match_operand:QI 1 "general_operand" ""))]
107 "{ xstormy16_expand_move (QImode, operands[0], operands[1]); DONE; }")
109 (define_insn "*movqi_internal"
110 [(set (match_operand:QI 0 "nonimmediate_nonstack_operand" "=r,m,e,e,T,r,S")
111 (match_operand:QI 1 "general_operand" "r,e,m,i,i,i,i"))]
121 [(set_attr_alternative "length"
123 (if_then_else (match_operand:QI 0 "short_memory_operand" "")
126 (if_then_else (match_operand:QI 1 "short_memory_operand" "")
133 (set_attr "psw_operand" "0,0,0,0,nop,0,nop")])
135 (define_insn "pushhi"
136 [(set (mem:HI (post_inc (reg:HI 15)))
137 (match_operand:HI 0 "register_operand" "r"))]
140 [(set_attr "psw_operand" "nop")
141 (set_attr "length" "2")])
144 [(set (match_operand:HI 0 "register_operand" "=r")
145 (mem:HI (pre_dec (reg:HI 15))))]
148 [(set_attr "psw_operand" "nop")
149 (set_attr "length" "2")])
151 (define_expand "movhi"
152 [(set (match_operand:HI 0 "nonimmediate_nonstack_operand" "")
153 (match_operand:HI 1 "general_operand" ""))]
155 "{ xstormy16_expand_move (HImode, operands[0], operands[1]); DONE; }")
157 (define_insn "*movhi_internal"
158 [(set (match_operand:HI 0 "nonimmediate_nonstack_operand" "=r,m,e,e,T,r,S")
159 (match_operand:HI 1 "general_operand" "r,e,m,L,L,i,i"))]
169 [(set_attr_alternative "length"
171 (if_then_else (match_operand:QI 0 "short_memory_operand" "")
174 (if_then_else (match_operand:QI 1 "short_memory_operand" "")
181 (set_attr "psw_operand" "0,0,0,0,nop,0,nop")])
183 (define_expand "movsi"
184 [(set (match_operand:SI 0 "nonimmediate_operand" "")
185 (match_operand:SI 1 "general_operand" ""))]
187 "{ xstormy16_expand_move (SImode, operands[0], operands[1]); DONE; }")
189 (define_insn_and_split "*movsi_internal"
190 [(set (match_operand:SI 0 "nonimmediate_operand" "=r,Q,r,m,e,&e,e,r,S")
191 (match_operand:SI 1 "general_operand" "r,r,R,e,o, V,L,i,i"))]
196 "{ xstormy16_split_move (SImode, operands[0], operands[1]); DONE; }"
197 [(set_attr_alternative "length"
201 (if_then_else (match_operand:QI 0 "short_memory_operand" "")
204 (if_then_else (match_operand:QI 1 "short_memory_operand" "")
207 (if_then_else (match_operand:QI 1 "short_memory_operand" "")
215 ;; ::::::::::::::::::::
219 ;; ::::::::::::::::::::
221 (define_insn "extendqihi2"
222 [(set (match_operand:HI 0 "register_operand" "=r")
223 (sign_extend:HI (match_operand:QI 1 "register_operand" "0")))]
227 (define_insn "zero_extendqihi2"
228 [(set (match_operand:HI 0 "register_operand" "=e,r")
229 (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,0")))]
233 shl %0,#8\n\tshr %0,#8"
234 [(set_attr "psw_operand" "nop,0")
235 (set_attr_alternative "length"
240 ;; ::::::::::::::::::::
242 ;; :: Bit field extraction
244 ;; ::::::::::::::::::::
246 ;; Extract an unsigned bit field
247 ;(define_insn "extzv"
248 ; [(set (match_operand:SI 0 "register_operand" "=r")
249 ; (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
250 ; (match_operand:SI 2 "const_int_operand" "n")
251 ; (match_operand:SI 3 "const_int_operand" "n")))]
253 ; "extzv %0,%1,%2,%3"
254 ; [(set_attr "length" "4")])
256 ;; Insert a bit field
258 ; [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
259 ; (match_operand:SI 1 "const_int_operand" "n")
260 ; (match_operand:SI 2 "const_int_operand" "n"))
261 ; (match_operand:SI 3 "nonmemory_operand" "ri"))]
264 ; [(set_attr "length" "4")])
267 ;; ::::::::::::::::::::
269 ;; :: 16 bit Integer arithmetic
271 ;; ::::::::::::::::::::
274 ; Operand 3 is marked earlyclobber because that helps reload
275 ; to generate better code---this pattern will never need the
276 ; carry register as an input, and some output reloads or input
277 ; reloads might need to use it. In fact, without the '&' reload
278 ; will fail in some cases.
279 (define_insn "addhi3"
280 [(set (match_operand:HI 0 "register_operand" "=r,r,T,T,r,r,r")
281 (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0,0")
282 (match_operand:HI 2 "nonmemory_operand" "O,P,L,M,Ir,N,i")))
283 (clobber (match_scratch:BI 3 "=X,X,&y,&y,&y,&y,&y"))]
293 [(set_attr "length" "2,2,2,2,2,2,4")])
295 ; Reload can generate addition operations. The SECONDARY_RELOAD_CLASS
296 ; macro causes it to allocate the carry register; this pattern
297 ; shows it how to place the register in RTL to make the addition work.
298 (define_expand "reload_inhi"
299 [(parallel [(set (match_operand:HI 0 "register_operand" "=r")
300 (match_operand:HI 1 "xstormy16_carry_plus_operand" ""))
301 (clobber (match_operand:BI 2 "" "=&y"))])]
303 "if (! rtx_equal_p (operands[0], XEXP (operands[1], 0)))
305 emit_insn (gen_rtx_SET (VOIDmode, operands[0], XEXP (operands[1], 0)));
306 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]), operands[0],
307 XEXP (operands[1], 1));
311 (define_insn "addchi4"
312 [(set (match_operand:HI 0 "register_operand" "=T,r,r")
313 (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
314 (match_operand:HI 2 "nonmemory_operand" "L,Ir,i")))
315 (set (match_operand:BI 3 "register_operand" "=y,y,y")
316 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
317 (zero_extend:SI (match_dup 2)))
324 [(set_attr "length" "2,2,4")])
326 (define_insn "addchi5"
327 [(set (match_operand:HI 0 "register_operand" "=T,r,r")
328 (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
329 (zero_extend:HI (match_operand:BI 3
332 (match_operand:HI 2 "nonmemory_operand" "L,Ir,i")))
333 (set (match_operand:BI 4 "register_operand" "=y,y,y")
334 (truncate:BI (lshiftrt:SI (plus:SI (plus:SI
335 (zero_extend:SI (match_dup 1))
336 (zero_extend:SI (match_dup 3)))
337 (zero_extend:SI (match_dup 2)))
344 [(set_attr "length" "2,2,4")])
347 ; Operand 3 is marked earlyclobber because that helps reload
348 ; to generate better code---this pattern will never need the
349 ; carry register as an input, and some output reloads or input
350 ; reloads might need to use it. In fact, without the '&' reload
351 ; will fail in some cases.
352 (define_insn "subhi3"
353 [(set (match_operand:HI 0 "register_operand" "=r,r,T,T,r,r,r")
354 (minus:HI (match_operand:HI 1 "register_operand" "0,0,0,0,0,0,0")
355 (match_operand:HI 2 "nonmemory_operand" "O,P,L,M,rI,M,i")))
356 (clobber (match_scratch:BI 3 "=X,X,&y,&y,&y,&y,&y"))]
366 [(set_attr "length" "2,2,2,2,2,2,4")])
368 (define_insn "subchi4"
369 [(set (match_operand:HI 0 "register_operand" "=T,r,r")
370 (minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
371 (match_operand:HI 2 "nonmemory_operand" "L,Ir,i")))
372 (set (match_operand:BI 3 "register_operand" "=y,y,y")
373 (truncate:BI (lshiftrt:SI (minus:SI (zero_extend:SI (match_dup 1))
374 (zero_extend:SI (match_dup 2)))
381 [(set_attr "length" "2,2,4")])
383 (define_insn "subchi5"
384 [(set (match_operand:HI 0 "register_operand" "=T,r,r")
385 (minus:HI (minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
386 (zero_extend:HI (match_operand:BI 3
389 (match_operand:HI 2 "nonmemory_operand" "L,Ir,i")))
390 (set (match_operand:BI 4 "register_operand" "=y,y,y")
391 (truncate:BI (lshiftrt:SI (minus:SI (minus:SI
392 (zero_extend:SI (match_dup 1))
393 (zero_extend:SI (match_dup 3)))
394 (zero_extend:SI (match_dup 2)))
401 [(set_attr "length" "2,2,4")])
403 ; Basic multiplication
404 (define_insn "mulhi3"
405 [(set (match_operand:HI 0 "register_operand" "=a")
406 (mult:HI (match_operand:HI 1 "register_operand" "%a")
407 (match_operand:HI 2 "register_operand" "c")))
408 (clobber (match_scratch:HI 3 "=b"))
412 [(set_attr "psw_operand" "nop")])
414 ;; Unsigned multiplication producing 64 bit results from 32 bit inputs
415 ; The constraint on operand 0 is 't' because it is actually two regs
416 ; long, and both regs must match the constraint.
417 (define_insn "umulhisi3"
418 [(set (match_operand:SI 0 "register_operand" "=t")
419 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%a"))
420 (zero_extend:SI (match_operand:HI 2 "register_operand" "c"))))
424 [(set_attr "psw_operand" "nop")])
426 ;; Unsigned division giving both quotient and remainder
427 (define_insn "udivmodhi4"
428 [(set (match_operand:HI 0 "register_operand" "=a")
429 (udiv:HI (match_operand:HI 1 "register_operand" "a")
430 (match_operand:HI 2 "register_operand" "c")))
431 (set (match_operand:HI 3 "register_operand" "=b")
432 (umod:HI (match_dup 1)
436 [(set_attr "psw_operand" "nop")])
440 (define_expand "neghi2"
441 [(set (match_operand:HI 0 "register_operand" "")
442 (not:HI (match_operand:HI 1 "register_operand" "")))
443 (parallel [(set (match_dup 0) (plus:HI (match_dup 0) (const_int 1)))
444 (clobber (match_scratch:BI 3 ""))])]
449 ;; ::::::::::::::::::::
451 ;; :: 16 bit Integer Shifts and Rotates
453 ;; ::::::::::::::::::::
455 ;; Arithmetic Shift Left
456 (define_insn "ashlhi3"
457 [(set (match_operand:HI 0 "register_operand" "=r")
458 (ashift:HI (match_operand:HI 1 "register_operand" "0")
459 (match_operand:HI 2 "nonmemory_operand" "ri")))
460 (clobber (match_scratch:BI 3 "=y"))]
464 ;; Arithmetic Shift Right
465 (define_insn "ashrhi3"
466 [(set (match_operand:HI 0 "register_operand" "=r")
467 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
468 (match_operand:HI 2 "nonmemory_operand" "ri")))
469 (clobber (match_scratch:BI 3 "=y"))]
473 ;; Logical Shift Right
474 (define_insn "lshrhi3"
475 [(set (match_operand:HI 0 "register_operand" "=r")
476 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
477 (match_operand:HI 2 "nonmemory_operand" "ri")))
478 (clobber (match_scratch:BI 3 "=y"))]
483 ;; ::::::::::::::::::::
485 ;; :: 16 Bit Integer Logical operations
487 ;; ::::::::::::::::::::
489 ;; Logical AND, 16 bit integers
490 (define_insn "andhi3"
491 [(set (match_operand:HI 0 "register_operand" "=T,r,r,r")
492 (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
493 (match_operand:HI 2 "nonmemory_operand" "L,r,K,i")))]
500 [(set_attr "length" "2,2,2,4")])
502 ;; Inclusive OR, 16 bit integers
503 (define_insn "iorhi3"
504 [(set (match_operand:HI 0 "register_operand" "=T,r,r,r")
505 (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
506 (match_operand:HI 2 "nonmemory_operand" "L,r,J,i")))]
513 [(set_attr "length" "2,2,2,4")])
515 ;; Exclusive OR, 16 bit integers
516 (define_insn "xorhi3"
517 [(set (match_operand:HI 0 "register_operand" "=T,r,r")
518 (xor:HI (match_operand:HI 1 "register_operand" "%0,0,0")
519 (match_operand:HI 2 "nonmemory_operand" "L,r,i")))]
525 [(set_attr "length" "2,2,4")])
527 ;; One's complement, 16 bit integers
528 (define_insn "one_cmplhi2"
529 [(set (match_operand:HI 0 "register_operand" "=r")
530 (not:HI (match_operand:HI 1 "register_operand" "0")))]
535 ;; ::::::::::::::::::::
537 ;; :: 32 bit Integer arithmetic
539 ;; ::::::::::::::::::::
542 (define_insn_and_split "addsi3"
543 [(set (match_operand:SI 0 "register_operand" "=r")
544 (plus:SI (match_operand:SI 1 "register_operand" "%0")
545 (match_operand:SI 2 "nonmemory_operand" "ri")))
546 (clobber (match_scratch:BI 3 "=y"))]
551 "{ xstormy16_expand_arith (SImode, PLUS, operands[0], operands[1],
552 operands[2], operands[3]); DONE; } "
553 [(set_attr "length" "4")])
556 (define_insn_and_split "subsi3"
557 [(set (match_operand:SI 0 "register_operand" "=r")
558 (minus:SI (match_operand:SI 1 "register_operand" "0")
559 (match_operand:SI 2 "nonmemory_operand" "ri")))
560 (clobber (match_scratch:BI 3 "=y"))]
565 "{ xstormy16_expand_arith (SImode, MINUS, operands[0], operands[1],
566 operands[2], operands[3]); DONE; } "
567 [(set_attr "length" "4")])
569 (define_expand "negsi2"
570 [(set (match_operand:SI 0 "register_operand" "")
571 (neg:SI (match_operand:SI 1 "register_operand" "")))]
573 "{ xstormy16_expand_arith (SImode, NEG, operands[0], const0_rtx,
574 operands[1], gen_reg_rtx (BImode)); DONE; }")
576 ;; ::::::::::::::::::::
578 ;; :: 32 bit Integer Shifts and Rotates
580 ;; ::::::::::::::::::::
582 ;; Arithmetic Shift Left
583 (define_expand "ashlsi3"
584 [(parallel [(set (match_operand:SI 0 "register_operand" "")
585 (ashift:SI (match_operand:SI 1 "register_operand" "")
586 (match_operand:SI 2 "const_int_operand" "")))
587 (clobber (match_dup 3))
588 (clobber (match_dup 4))])]
590 " if (! const_int_operand (operands[2], SImode)) FAIL;
591 operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
593 ;; Arithmetic Shift Right
594 (define_expand "ashrsi3"
595 [(parallel [(set (match_operand:SI 0 "register_operand" "")
596 (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
597 (match_operand:SI 2 "const_int_operand" "")))
598 (clobber (match_dup 3))
599 (clobber (match_dup 4))])]
601 " if (! const_int_operand (operands[2], SImode)) FAIL;
602 operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
604 ;; Logical Shift Right
605 (define_expand "lshrsi3"
606 [(parallel [(set (match_operand:SI 0 "register_operand" "")
607 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
608 (match_operand:SI 2 "const_int_operand" "")))
609 (clobber (match_dup 3))
610 (clobber (match_dup 4))])]
612 " if (! const_int_operand (operands[2], SImode)) FAIL;
613 operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
615 (define_insn "*shiftsi"
616 [(set (match_operand:SI 0 "register_operand" "=r,r")
617 (match_operator:SI 5 "shift_operator"
618 [(match_operand:SI 1 "register_operand" "0,0")
619 (match_operand:SI 2 "const_int_operand" "U,n")]))
620 (clobber (match_operand:BI 3 "register_operand" "=y,y"))
621 (clobber (match_operand:HI 4 "" "=X,r"))]
623 "* return xstormy16_output_shift (SImode, GET_CODE (operands[5]),
624 operands[0], operands[2], operands[4]);"
625 [(set_attr "length" "6,10")
626 (set_attr "psw_operand" "clobber,clobber")])
629 ;; ::::::::::::::::::::
633 ;; ::::::::::::::::::::
635 ;; Note, we store the operands in the comparison insns, and use them later
636 ;; when generating the branch or scc operation.
638 ;; First the routines called by the machine independent part of the compiler
639 (define_expand "cmphi"
641 (compare (match_operand:HI 0 "register_operand" "")
642 (match_operand:HI 1 "nonmemory_operand" "")))]
646 xstormy16_compare_op0 = operands[0];
647 xstormy16_compare_op1 = operands[1];
651 ; There are no real SImode comparisons, but some can be emulated
652 ; by performing a SImode subtract and looking at the condition flags.
653 (define_expand "cmpsi"
655 (compare (match_operand:SI 0 "register_operand" "")
656 (match_operand:SI 1 "nonmemory_operand" "")))]
660 xstormy16_compare_op0 = operands[0];
661 xstormy16_compare_op1 = operands[1];
666 ;; ::::::::::::::::::::
670 ;; ::::::::::::::::::::
673 [(use (match_operand 0 "" ""))]
675 "{ xstormy16_emit_cbranch (EQ, operands[0]); DONE; }")
678 [(use (match_operand 0 "" ""))]
680 "{ xstormy16_emit_cbranch (NE, operands[0]); DONE; }")
683 [(use (match_operand 0 "" ""))]
685 "{ xstormy16_emit_cbranch (GE, operands[0]); DONE; }")
688 [(use (match_operand 0 "" ""))]
690 "{ xstormy16_emit_cbranch (GT, operands[0]); DONE; }")
693 [(use (match_operand 0 "" ""))]
695 "{ xstormy16_emit_cbranch (LE, operands[0]); DONE; }")
698 [(use (match_operand 0 "" ""))]
700 "{ xstormy16_emit_cbranch (LT, operands[0]); DONE; }")
702 (define_expand "bgeu"
703 [(use (match_operand 0 "" ""))]
705 "{ xstormy16_emit_cbranch (GEU, operands[0]); DONE; }")
707 (define_expand "bgtu"
708 [(use (match_operand 0 "" ""))]
710 "{ xstormy16_emit_cbranch (GTU, operands[0]); DONE; }")
712 (define_expand "bleu"
713 [(use (match_operand 0 "" ""))]
715 "{ xstormy16_emit_cbranch (LEU, operands[0]); DONE; }")
717 (define_expand "bltu"
718 [(use (match_operand 0 "" ""))]
720 "{ xstormy16_emit_cbranch (LTU, operands[0]); DONE; }")
723 (define_insn "*cbranchhi"
725 (if_then_else (match_operator:HI 1 "comparison_operator"
726 [(match_operand:HI 2 "nonmemory_operand"
728 (match_operand:HI 3 "nonmemory_operand"
730 (label_ref (match_operand 0 "" ""))
732 (clobber (match_operand:BI 4 "" "=&y,&y,&y"))]
736 return xstormy16_output_cbranch_hi (operands[1], \"%l0\", 0, insn);
738 [(set_attr "branch_class" "bcc12")
739 (set_attr "psw_operand" "0,0,1")])
741 (define_insn "*cbranchhi_neg"
743 (if_then_else (match_operator:HI 1 "comparison_operator"
744 [(match_operand:HI 2 "nonmemory_operand"
746 (match_operand:HI 3 "nonmemory_operand"
749 (label_ref (match_operand 0 "" ""))))
750 (clobber (match_operand:BI 4 "" "=&y,&y,&y"))]
754 return xstormy16_output_cbranch_hi (operands[1], \"%l0\", 1, insn);
756 [(set_attr "branch_class" "bcc12")
757 (set_attr "psw_operand" "0,0,1")])
759 (define_insn "*eqbranchsi"
761 (if_then_else (match_operator:SI 1 "equality_operator"
762 [(match_operand:SI 2 "register_operand"
765 (label_ref (match_operand 0 "" ""))
767 ;; Although I would greatly like the 'match_dup' in the following line
768 ;; to actually be a register constraint, there is (at the time of writing) no
769 ;; way for reload to insert an output reload on the edges out of a branch.
770 ;; If reload is fixed to use insert_insn_on_edge, this can be changed.
771 (clobber (match_dup 2))]
775 return xstormy16_output_cbranch_si (operands[1], \"%l0\", 0, insn);
777 [(set_attr "branch_class" "bcc8p2")
778 (set_attr "psw_operand" "clobber")])
780 (define_insn_and_split "*ineqbranchsi"
782 (if_then_else (match_operator:SI 1 "xstormy16_ineqsi_operator"
783 [(match_operand:SI 2 "register_operand"
785 (match_operand:SI 3 "nonmemory_operand"
787 (label_ref (match_operand 0 "" ""))
789 ;; Although I would greatly like the 'match_dup' in the following line
790 ;; to actually be a register constraint, there is (at the time of writing) no
791 ;; way for reload to insert an output reload on the edges out of a branch.
792 ;; If reload is fixed to use insert_insn_on_edge, this can be changed,
793 ;; preferably to a 'minus' operand that explains the actual operation, like:
794 ; (set (match_operand 5 "register_operand" "=2")
795 ; (minus:SI (match_operand 6 "register_operand" "2")
796 ; (match_operand 7 "register_operand" "3")))
797 (clobber (match_dup 2))
798 (clobber (match_operand:BI 4 "" "=&y"))]
803 "{ xstormy16_split_cbranch (SImode, operands[0], operands[1], operands[2],
804 operands[4]); DONE; }"
805 [(set_attr "length" "8")])
807 (define_insn "*ineqbranch_1"
809 (if_then_else (match_operator:HI 5 "xstormy16_ineqsi_operator"
810 [(minus:HI (match_operand:HI 1 "register_operand"
812 (zero_extend:HI (match_operand:BI 4
815 (match_operand:HI 3 "nonmemory_operand" "L,Ir,i")])
816 (label_ref (match_operand 0 "" ""))
818 (set (match_operand:HI 2 "register_operand" "=2,2,2")
819 (minus:HI (minus:HI (match_dup 1) (zero_extend:HI (match_dup 4)))
821 (clobber (match_operand:BI 6 "" "=y,y,y"))]
825 return xstormy16_output_cbranch_si (operands[5], \"%l0\", 0, insn);
827 [(set_attr "branch_class" "bcc8p2,bcc8p2,bcc8p4")
828 (set_attr "psw_operand" "2,2,2")])
831 ;; ::::::::::::::::::::
833 ;; :: Call and branch instructions
835 ;; ::::::::::::::::::::
837 ;; Subroutine call instruction returning no value. Operand 0 is the function
838 ;; to call; operand 1 is the number of bytes of arguments pushed (in mode
839 ;; `SImode', except it is normally a `const_int'); operand 2 is the number of
840 ;; registers used as operands.
842 ;; On most machines, operand 2 is not actually stored into the RTL pattern. It
843 ;; is supplied for the sake of some RISC machines which need to put this
844 ;; information into the assembler code; they can put it in the RTL instead of
847 (define_expand "call"
848 [(call (match_operand:HI 0 "memory_operand" "m")
849 (match_operand 1 "" ""))
850 (use (match_operand 2 "immediate_operand" ""))]
852 "xstormy16_expand_call (NULL_RTX, operands[0], operands[1]); DONE;")
854 ;; Subroutine call instruction returning a value. Operand 0 is the hard
855 ;; register in which the value is returned. There are three more operands, the
856 ;; same as the three operands of the `call' instruction (but with numbers
857 ;; increased by one).
859 ;; Subroutines that return `BLKmode' objects use the `call' insn.
861 (define_expand "call_value"
862 [(set (match_operand 0 "register_operand" "=r")
863 (call (match_operand:HI 1 "memory_operand" "m")
864 (match_operand:SI 2 "" "")))
865 (use (match_operand 3 "immediate_operand" ""))]
867 "xstormy16_expand_call (operands[0], operands[1], operands[2]); DONE;")
869 (define_insn "*call_internal"
870 [(call (mem:HI (match_operand:HI 0 "nonmemory_operand" "i,r"))
871 (match_operand 1 "" ""))
872 (use (match_operand:HI 2 "nonmemory_operand" "X,z"))]
877 [(set_attr "length" "4,2")
878 (set_attr "psw_operand" "clobber")])
880 (define_insn "*call_value_internal"
881 [(set (match_operand 3 "register_operand" "=r,r")
882 (call (mem:HI (match_operand:HI 0 "nonmemory_operand" "i,r"))
883 (match_operand 1 "" "")))
884 (use (match_operand:HI 2 "nonmemory_operand" "X,z"))]
889 [(set_attr "length" "4,2")
890 (set_attr "psw_operand" "clobber")])
893 (define_expand "return"
898 (define_insn "return_internal"
902 [(set_attr "psw_operand" "nop")])
904 (define_insn "return_internal_interrupt"
906 (unspec_volatile [(const_int 0)] 1)]
909 [(set_attr "psw_operand" "clobber")])
911 ;; Normal unconditional jump
913 [(set (pc) (label_ref (match_operand 0 "" "")))]
917 return xstormy16_output_cbranch_hi (NULL_RTX, \"%l0\", 0, insn);
919 [(set_attr "branch_class" "br12")
920 (set_attr "psw_operand" "nop")])
922 ;; Indirect jump through a register
923 (define_expand "indirect_jump"
924 [(set (match_dup 1) (const_int 0))
925 (parallel [(set (pc) (match_operand:HI 0 "register_operand" "r"))
926 (use (match_dup 1))])]
928 "operands[1] = gen_reg_rtx (HImode);")
931 [(set (pc) (match_operand:HI 0 "register_operand" "r"))
932 (use (match_operand:HI 1 "register_operand" "z"))]
935 [(set_attr "length" "4")
936 (set_attr "psw_operand" "nop")])
938 ;; Table-based switch statements.
939 (define_expand "casesi"
940 [(use (match_operand:SI 0 "register_operand" ""))
941 (use (match_operand:SI 1 "immediate_operand" ""))
942 (use (match_operand:SI 2 "immediate_operand" ""))
943 (use (label_ref (match_operand 3 "" "")))
944 (use (label_ref (match_operand 4 "" "")))]
948 xstormy16_expand_casesi (operands[0], operands[1], operands[2],
949 operands[3], operands[4]);
953 (define_insn "tablejump_pcrel"
954 [(set (pc) (mem:HI (plus:HI (pc)
955 (match_operand:HI 0 "register_operand" "r"))))
956 (use (label_ref:SI (match_operand 1 "" "")))]
959 [(set_attr "psw_operand" "nop")])
962 ;; ::::::::::::::::::::
964 ;; :: Prologue and Epilogue instructions
966 ;; ::::::::::::::::::::
968 ;; Called after register allocation to add any instructions needed for
969 ;; the prologue. Using a prologue insn is favored compared to putting
970 ;; all of the instructions in the TARGET_ASM_FUNCTION_PROLOGUE macro,
971 ;; since it allows the scheduler to intermix instructions with the
972 ;; saves of the caller saved registers. In some cases, it might be
973 ;; necessary to emit a barrier instruction as the last insn to prevent
975 (define_expand "prologue"
980 xstormy16_expand_prologue ();
984 ;; Called after register allocation to add any instructions needed for
985 ;; the epilogue. Using an epilogue insn is favored compared to putting
986 ;; all of the instructions in the TARGET_ASM_FUNCTION_EPILOGUE macro,
987 ;; since it allows the scheduler to intermix instructions with the
988 ;; restires of the caller saved registers. In some cases, it might be
989 ;; necessary to emit a barrier instruction as the first insn to
990 ;; prevent such scheduling.
991 (define_expand "epilogue"
996 xstormy16_expand_epilogue ();
1001 ;; ::::::::::::::::::::
1003 ;; :: Miscellaneous instructions
1005 ;; ::::::::::::::::::::
1007 ;; No operation, needed in case the user uses -g but not -O.
1012 [(set_attr "psw_operand" "nop")])
1014 ;; Pseudo instruction that prevents the scheduler from moving code above this
1016 (define_insn "blockage"
1017 [(unspec_volatile [(const_int 0)] 0)]
1020 [(set_attr "length" "0")
1021 (set_attr "psw_operand" "nop")])