stormy16.md (zero_extendqihi2): New.
[platform/upstream/gcc.git] / gcc / config / stormy16 / stormy16.md
1 ;; XSTORMY16 Machine description template
2 ;; Copyright (C) 1997, 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
3 ;; Contributed by Red Hat, Inc.
4
5 ;; This file is part of GNU CC.
6
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)
10 ;; any later version.
11
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.
16
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.
21
22 ;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
23
24 \f
25 ;; ::::::::::::::::::::
26 ;; ::
27 ;; :: Attributes
28 ;; ::
29 ;; ::::::::::::::::::::
30
31 ; Categorize branches for the conditional in the length attribute.
32 (define_attr "branch_class" "notdirectbranch,br12,bcc12,bcc8p2,bcc8p4" 
33     (const_string "notdirectbranch"))
34
35 ; The length of an instruction, used for branch shortening.
36 (define_attr "length" "" 
37   (cond
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)))
41                    (const_int 2)
42                    (const_int 4))
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)))
46                    (const_int 4)
47                    (const_int 8))
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)))
51                    (const_int 4)
52                    (const_int 8))
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)))
56                    (const_int 6)
57                    (const_int 10))]
58    (const_int 2)))
59
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"))
65
66 (define_asm_attributes [(set_attr "length" "4")
67                         (set_attr "psw_operand" "clobber")])
68
69 \f
70 ;; ::::::::::::::::::::
71 ;; ::
72 ;; :: Moves
73 ;; ::
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
78 ;; might end up with
79
80 ;; (set (mem (post_inc (sp))) mem (post_inc (reg)))
81
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.
86
87 (define_insn "pushqi"
88   [(set (mem:QI (post_inc (reg:HI 15)))
89         (match_operand:QI 0 "register_operand" "r"))]
90   ""
91   "push %0"
92   [(set_attr "psw_operand" "nop")
93    (set_attr "length" "2")])
94
95 (define_insn "popqi"
96   [(set (match_operand:QI 0 "register_operand" "=r")
97         (mem:QI (pre_dec (reg:HI 15))))]
98   ""
99   "pop %0"
100   [(set_attr "psw_operand" "nop")
101    (set_attr "length" "2")])
102
103 (define_expand "movqi"
104   [(set (match_operand:QI 0 "nonimmediate_nonstack_operand" "")
105         (match_operand:QI 1 "general_operand" ""))]
106   ""
107   "{ xstormy16_expand_move (QImode, operands[0], operands[1]); DONE; }")
108
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"))]
112   ""
113   "@
114    mov %0,%1
115    mov.b %0,%1
116    mov.b %0,%1
117    mov %0,%1
118    mov Rx,%1
119    mov %0,%1
120    mov.b %0,%1"
121   [(set_attr_alternative "length" 
122              [(const_int 2)
123               (if_then_else (match_operand:QI 0 "short_memory_operand" "")
124                             (const_int 2)
125                             (const_int 4))
126               (if_then_else (match_operand:QI 1 "short_memory_operand" "")
127                             (const_int 2)
128                             (const_int 4))
129               (const_int 2)
130               (const_int 2)
131               (const_int 4)
132               (const_int 4)])
133    (set_attr "psw_operand" "0,0,0,0,nop,0,nop")])
134
135 (define_insn "pushhi"
136   [(set (mem:HI (post_inc (reg:HI 15)))
137         (match_operand:HI 0 "register_operand" "r"))]
138   ""
139   "push %0"
140   [(set_attr "psw_operand" "nop")
141    (set_attr "length" "2")])
142
143 (define_insn "pophi"
144   [(set (match_operand:HI 0 "register_operand" "=r")
145         (mem:HI (pre_dec (reg:HI 15))))]
146   ""
147   "pop %0"
148   [(set_attr "psw_operand" "nop")
149    (set_attr "length" "2")])
150
151 (define_expand "movhi"
152   [(set (match_operand:HI 0 "nonimmediate_nonstack_operand" "")
153         (match_operand:HI 1 "general_operand" ""))]
154   ""
155   "{ xstormy16_expand_move (HImode, operands[0], operands[1]); DONE; }")
156
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"))]
160   ""
161   "@
162    mov %0,%1
163    mov.w %0,%1
164    mov.w %0,%1
165    mov.w %0,%1
166    mov.w Rx,%1
167    mov.w %0,%1
168    mov.w %0,%1"
169   [(set_attr_alternative "length" 
170              [(const_int 2)
171               (if_then_else (match_operand:QI 0 "short_memory_operand" "")
172                             (const_int 2)
173                             (const_int 4))
174               (if_then_else (match_operand:QI 1 "short_memory_operand" "")
175                             (const_int 2)
176                             (const_int 4))
177               (const_int 2)
178               (const_int 2)
179               (const_int 4)
180               (const_int 4)])
181    (set_attr "psw_operand" "0,0,0,0,nop,0,nop")])
182
183 (define_expand "movsi"
184   [(set (match_operand:SI 0 "nonimmediate_operand" "")
185         (match_operand:SI 1 "general_operand" ""))]
186   ""
187   "{ xstormy16_expand_move (SImode, operands[0], operands[1]); DONE; }")
188
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"))]
192   ""
193   "#"
194   "reload_completed"
195   [(pc)]
196   "{ xstormy16_split_move (SImode, operands[0], operands[1]); DONE; }"
197   [(set_attr_alternative "length" 
198              [(const_int 4)
199               (const_int 4)
200               (const_int 4)
201               (if_then_else (match_operand:QI 0 "short_memory_operand" "")
202                             (const_int 6)
203                             (const_int 8))
204               (if_then_else (match_operand:QI 1 "short_memory_operand" "")
205                             (const_int 6)
206                             (const_int 8))
207               (if_then_else (match_operand:QI 1 "short_memory_operand" "")
208                             (const_int 6)
209                             (const_int 8))
210               (const_int 4)
211               (const_int 8)
212               (const_int 8)])])
213
214 \f
215 ;; ::::::::::::::::::::
216 ;; ::
217 ;; :: Conversions
218 ;; ::
219 ;; ::::::::::::::::::::
220
221 (define_insn "extendqihi2"
222   [(set (match_operand:HI 0 "register_operand" "=r")
223         (sign_extend:HI (match_operand:QI 1 "register_operand" "0")))]
224   ""
225   "cbw %0")
226
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")))]
230   ""
231   "@
232    mov.b %0, %1
233    shl %0,#8\n\tshr %0,#8"
234   [(set_attr "psw_operand" "nop,0")
235    (set_attr_alternative "length" 
236              [(const_int 2)
237               (const_int 4)])])
238
239 \f
240 ;; ::::::::::::::::::::
241 ;; ::
242 ;; :: Bit field extraction
243 ;; ::
244 ;; ::::::::::::::::::::
245
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")))]
252 ;  ""
253 ;  "extzv %0,%1,%2,%3"
254 ;  [(set_attr "length" "4")])
255
256 ;; Insert a bit field
257 ;(define_insn "insv"
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"))]
262 ;  ""
263 ;  "insv %0,%1,%2,%3"
264 ;  [(set_attr "length" "4")])
265
266 \f
267 ;; ::::::::::::::::::::
268 ;; ::
269 ;; :: 16 bit Integer arithmetic
270 ;; ::
271 ;; ::::::::::::::::::::
272
273 ;; Addition
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"))]
284   ""
285   "@
286    inc %0,%o2
287    dec %0,%O2
288    add Rx,%2
289    sub Rx,#%n2
290    add %0,%2
291    sub %0,#%n2
292    add %0,%2"
293   [(set_attr "length" "2,2,2,2,2,2,4")])
294
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"))])]
302   ""
303   "if (! rtx_equal_p (operands[0], XEXP (operands[1], 0)))
304     {
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));
308     }
309  ")
310
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)))
318                                   (const_int 16))))]
319   ""
320   "@
321    add Rx,%2
322    add %0,%2
323    add %0,%2"
324   [(set_attr "length" "2,2,4")])
325
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 
330                                                             "register_operand"
331                                                             "y,y,y")))
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)))
338                                   (const_int 16))))]
339   ""
340   "@
341    adc Rx,%2
342    adc %0,%2
343    adc %0,%2"
344   [(set_attr "length" "2,2,4")])
345
346 ;; Subtraction
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"))]
357   ""
358   "@
359    dec %0,%o2
360    inc %0,%O2
361    sub Rx,%2
362    add Rx,#%n2
363    sub %0,%2
364    add %0,#%n2
365    sub %0,%2"
366   [(set_attr "length" "2,2,2,2,2,2,4")])
367
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)))
375                                   (const_int 16))))]
376   ""
377   "@
378    sub Rx,%2
379    sub %0,%2
380    sub %0,%2"
381   [(set_attr "length" "2,2,4")])
382
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 
387                                                             "register_operand"
388                                                             "y,y,y")))
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)))
395                                   (const_int 16))))]
396   ""
397   "@
398    sbc Rx,%2
399    sbc %0,%2
400    sbc %0,%2"
401   [(set_attr "length" "2,2,4")])
402
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"))
409    ]
410   ""
411   "mul"
412   [(set_attr "psw_operand" "nop")])
413
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"))))
421    ]
422   ""
423   "mul"
424   [(set_attr "psw_operand" "nop")])
425
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)
433                  (match_dup 2)))]
434   ""
435   "div"
436   [(set_attr "psw_operand" "nop")])
437
438 ;; Negation
439
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 ""))])]
445   ""
446   "")
447
448 \f
449 ;; ::::::::::::::::::::
450 ;; ::
451 ;; :: 16 bit Integer Shifts and Rotates
452 ;; ::
453 ;; ::::::::::::::::::::
454
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"))]
461   ""
462   "shl %0,%2")
463
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"))]
470   ""
471   "asr %0,%2")
472
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"))]
479   ""
480   "shr %0,%2")
481
482 \f
483 ;; ::::::::::::::::::::
484 ;; ::
485 ;; :: 16 Bit Integer Logical operations
486 ;; ::
487 ;; ::::::::::::::::::::
488
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")))]
494   ""
495   "@
496    and Rx,%2
497    and %0,%2
498    clr1 %0,%B2
499    and %0,%2"
500   [(set_attr "length" "2,2,2,4")])
501
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")))]
507   ""
508   "@
509    or Rx,%2
510    or %0,%2
511    set1 %0,%B2
512    or %0,%2"
513   [(set_attr "length" "2,2,2,4")])
514
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")))]
520   ""
521   "@
522    xor Rx,%2
523    xor %0,%2
524    xor %0,%2"
525   [(set_attr "length" "2,2,4")])
526
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")))]
531   ""
532   "not %0")
533
534 \f
535 ;; ::::::::::::::::::::
536 ;; ::
537 ;; :: 32 bit Integer arithmetic
538 ;; ::
539 ;; ::::::::::::::::::::
540
541 ;; Addition
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"))]
547   ""
548   "#"
549   "reload_completed"
550   [(pc)]
551   "{ xstormy16_expand_arith (SImode, PLUS, operands[0], operands[1],
552                             operands[2], operands[3]); DONE; } "
553   [(set_attr "length" "4")])
554
555 ;; Subtraction
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"))]
561   ""
562   "#"
563   "reload_completed"
564   [(pc)]
565   "{ xstormy16_expand_arith (SImode, MINUS, operands[0], operands[1],
566                             operands[2], operands[3]); DONE; } "
567   [(set_attr "length" "4")])
568
569 (define_expand "negsi2"
570   [(set (match_operand:SI 0 "register_operand" "")
571         (neg:SI (match_operand:SI 1 "register_operand" "")))]
572   ""
573   "{ xstormy16_expand_arith (SImode, NEG, operands[0], const0_rtx,
574                             operands[1], gen_reg_rtx (BImode)); DONE; }")
575
576 ;; ::::::::::::::::::::
577 ;; ::
578 ;; :: 32 bit Integer Shifts and Rotates
579 ;; ::
580 ;; ::::::::::::::::::::
581
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))])]
589   ""
590   " if (! const_int_operand (operands[2], SImode)) FAIL;
591   operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
592
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))])]
600   ""
601   " if (! const_int_operand (operands[2], SImode)) FAIL;
602   operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
603
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))])]
611   ""
612   " if (! const_int_operand (operands[2], SImode)) FAIL;
613   operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
614
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"))]
622   ""
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")])
627
628 \f
629 ;; ::::::::::::::::::::
630 ;; ::
631 ;; :: Comparisons
632 ;; ::
633 ;; ::::::::::::::::::::
634
635 ;; Note, we store the operands in the comparison insns, and use them later
636 ;; when generating the branch or scc operation.
637
638 ;; First the routines called by the machine independent part of the compiler
639 (define_expand "cmphi"
640   [(set (cc0)
641         (compare (match_operand:HI 0 "register_operand" "")
642                  (match_operand:HI 1 "nonmemory_operand" "")))]
643   ""
644   "
645 {
646   xstormy16_compare_op0 = operands[0];
647   xstormy16_compare_op1 = operands[1];
648   DONE;
649 }")
650
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"
654   [(set (cc0)
655         (compare (match_operand:SI 0 "register_operand" "")
656                  (match_operand:SI 1 "nonmemory_operand" "")))]
657   ""
658   "
659 {
660   xstormy16_compare_op0 = operands[0];
661   xstormy16_compare_op1 = operands[1];
662   DONE;
663 }")
664
665 \f
666 ;; ::::::::::::::::::::
667 ;; ::
668 ;; :: Branches
669 ;; ::
670 ;; ::::::::::::::::::::
671
672 (define_expand "beq"
673   [(use (match_operand 0 "" ""))]
674   ""
675   "{ xstormy16_emit_cbranch (EQ, operands[0]); DONE; }")
676
677 (define_expand "bne"
678   [(use (match_operand 0 "" ""))]
679   ""
680   "{ xstormy16_emit_cbranch (NE, operands[0]); DONE; }")
681
682 (define_expand "bge"
683   [(use (match_operand 0 "" ""))]
684   ""
685   "{ xstormy16_emit_cbranch (GE, operands[0]); DONE; }")
686
687 (define_expand "bgt"
688   [(use (match_operand 0 "" ""))]
689   ""
690   "{ xstormy16_emit_cbranch (GT, operands[0]); DONE; }")
691
692 (define_expand "ble"
693   [(use (match_operand 0 "" ""))]
694   ""
695   "{ xstormy16_emit_cbranch (LE, operands[0]); DONE; }")
696
697 (define_expand "blt"
698   [(use (match_operand 0 "" ""))]
699   ""
700   "{ xstormy16_emit_cbranch (LT, operands[0]); DONE; }")
701
702 (define_expand "bgeu"
703   [(use (match_operand 0 "" ""))]
704   ""
705   "{ xstormy16_emit_cbranch (GEU, operands[0]); DONE; }")
706
707 (define_expand "bgtu"
708   [(use (match_operand 0 "" ""))]
709   ""
710   "{ xstormy16_emit_cbranch (GTU, operands[0]); DONE; }")
711
712 (define_expand "bleu"
713   [(use (match_operand 0 "" ""))]
714   ""
715   "{ xstormy16_emit_cbranch (LEU, operands[0]); DONE; }")
716
717 (define_expand "bltu"
718   [(use (match_operand 0 "" ""))]
719   ""
720   "{ xstormy16_emit_cbranch (LTU, operands[0]); DONE; }")
721
722
723 (define_insn "*cbranchhi"
724   [(set (pc) 
725         (if_then_else (match_operator:HI 1 "comparison_operator"
726                                       [(match_operand:HI 2 "nonmemory_operand" 
727                                         "r,e,L")
728                                        (match_operand:HI 3 "nonmemory_operand"
729                                                       "r,L,e")])
730                       (label_ref (match_operand 0 "" ""))
731                       (pc)))
732    (clobber (match_operand:BI 4 "" "=&y,&y,&y"))]
733   ""
734   "*
735 {
736   return xstormy16_output_cbranch_hi (operands[1], \"%l0\", 0, insn);
737 }"
738   [(set_attr "branch_class" "bcc12")
739    (set_attr "psw_operand" "0,0,1")])
740
741 (define_insn "*cbranchhi_neg"
742   [(set (pc) 
743         (if_then_else (match_operator:HI 1 "comparison_operator"
744                                       [(match_operand:HI 2 "nonmemory_operand" 
745                                                          "r,e,L")
746                                        (match_operand:HI 3 "nonmemory_operand"
747                                                          "r,L,e")])
748                       (pc)
749                       (label_ref (match_operand 0 "" ""))))
750    (clobber (match_operand:BI 4 "" "=&y,&y,&y"))]
751   ""
752   "*
753 {
754   return xstormy16_output_cbranch_hi (operands[1], \"%l0\", 1, insn);
755 }"
756   [(set_attr "branch_class" "bcc12")
757    (set_attr "psw_operand" "0,0,1")])
758
759 (define_insn "*eqbranchsi"
760   [(set (pc)
761         (if_then_else (match_operator:SI 1 "equality_operator"
762                                       [(match_operand:SI 2 "register_operand" 
763                                                          "+r")
764                                        (const_int 0)])
765                       (label_ref (match_operand 0 "" ""))
766                       (pc)))
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))]
772   ""
773   "*
774 {
775   return xstormy16_output_cbranch_si (operands[1], \"%l0\", 0, insn);
776 }"
777   [(set_attr "branch_class" "bcc8p2")
778    (set_attr "psw_operand" "clobber")])
779
780 (define_insn_and_split "*ineqbranchsi"
781   [(set (pc)
782         (if_then_else (match_operator:SI 1 "xstormy16_ineqsi_operator"
783                                       [(match_operand:SI 2 "register_operand" 
784                                                          "+r")
785                                        (match_operand:SI 3 "nonmemory_operand" 
786                                                          "ri")])
787                       (label_ref (match_operand 0 "" ""))
788                       (pc)))
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"))]
799   ""
800   "#"
801   "reload_completed"
802   [(pc)]
803   "{ xstormy16_split_cbranch (SImode, operands[0], operands[1], operands[2],
804                              operands[4]); DONE; }"
805   [(set_attr "length" "8")])
806
807 (define_insn "*ineqbranch_1"
808   [(set (pc)
809         (if_then_else (match_operator:HI 5 "xstormy16_ineqsi_operator"
810                        [(minus:HI (match_operand:HI 1 "register_operand" 
811                                                     "T,r,r")
812                            (zero_extend:HI (match_operand:BI 4
813                                                              "register_operand"
814                                                              "y,y,y")))
815                         (match_operand:HI 3 "nonmemory_operand" "L,Ir,i")])
816                       (label_ref (match_operand 0 "" ""))
817                       (pc)))
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)))
820                   (match_dup 3)))
821    (clobber (match_operand:BI 6 "" "=y,y,y"))]
822   ""
823   "*
824 {
825   return xstormy16_output_cbranch_si (operands[5], \"%l0\", 0, insn);
826 }"
827   [(set_attr "branch_class" "bcc8p2,bcc8p2,bcc8p4")
828    (set_attr "psw_operand" "2,2,2")])
829
830 \f
831 ;; ::::::::::::::::::::
832 ;; ::
833 ;; :: Call and branch instructions
834 ;; ::
835 ;; ::::::::::::::::::::
836
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.
841
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
845 ;; operand 1.
846
847 (define_expand "call"
848   [(call (match_operand:HI 0 "memory_operand" "m")
849          (match_operand 1 "" ""))
850    (use (match_operand 2 "immediate_operand" ""))]
851   ""
852   "xstormy16_expand_call (NULL_RTX, operands[0], operands[1]); DONE;")
853
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).
858
859 ;; Subroutines that return `BLKmode' objects use the `call' insn.
860
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" ""))]
866   ""
867   "xstormy16_expand_call (operands[0], operands[1], operands[2]); DONE;")
868
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"))]
873   ""
874   "@
875    callf %C0
876    call %2,%0"
877   [(set_attr "length" "4,2")
878    (set_attr "psw_operand" "clobber")])
879
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"))]
885   ""
886   "@
887    callf %C0
888    call %2,%0"
889   [(set_attr "length" "4,2")
890    (set_attr "psw_operand" "clobber")])
891
892 ;; Subroutine return
893 (define_expand "return"
894   [(return)]
895   "direct_return()"
896   "")
897
898 (define_insn "return_internal"
899   [(return)]
900   ""
901   "ret"
902   [(set_attr "psw_operand" "nop")])
903
904 (define_insn "return_internal_interrupt"
905   [(return)
906    (unspec_volatile [(const_int 0)] 1)]
907   ""
908   "iret"
909   [(set_attr "psw_operand" "clobber")])
910
911 ;; Normal unconditional jump
912 (define_insn "jump"
913   [(set (pc) (label_ref (match_operand 0 "" "")))]
914   ""
915   "*
916 {
917   return xstormy16_output_cbranch_hi (NULL_RTX, \"%l0\", 0, insn);
918 }"
919   [(set_attr "branch_class" "br12")
920    (set_attr "psw_operand" "nop")])
921
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))])]
927   ""
928   "operands[1] = gen_reg_rtx (HImode);")
929
930 (define_insn ""
931   [(set (pc) (match_operand:HI 0 "register_operand" "r"))
932    (use (match_operand:HI 1 "register_operand" "z"))]
933   ""
934   "jmp %1,%0"
935   [(set_attr "length" "4")
936    (set_attr "psw_operand" "nop")])
937
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 "" "")))]
945   ""
946   "
947 {
948   xstormy16_expand_casesi (operands[0], operands[1], operands[2],
949                           operands[3], operands[4]);
950   DONE;
951 }")
952
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 "" "")))]
957   ""
958   "br %0"
959   [(set_attr "psw_operand" "nop")])
960
961 \f
962 ;; ::::::::::::::::::::
963 ;; ::
964 ;; :: Prologue and Epilogue instructions
965 ;; ::
966 ;; ::::::::::::::::::::
967
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
974 ;; such scheduling.
975 (define_expand "prologue"
976   [(const_int 1)]
977   ""
978   "
979 {
980   xstormy16_expand_prologue ();
981   DONE;
982 }")
983
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"
992   [(const_int 2)]
993   ""
994   "
995 {
996   xstormy16_expand_epilogue ();
997   DONE;
998 }")
999
1000 \f
1001 ;; ::::::::::::::::::::
1002 ;; ::
1003 ;; :: Miscellaneous instructions
1004 ;; ::
1005 ;; ::::::::::::::::::::
1006
1007 ;; No operation, needed in case the user uses -g but not -O.
1008 (define_insn "nop"
1009   [(const_int 0)]
1010   ""
1011   "nop"
1012   [(set_attr "psw_operand" "nop")])
1013
1014 ;; Pseudo instruction that prevents the scheduler from moving code above this
1015 ;; point.
1016 (define_insn "blockage"
1017   [(unspec_volatile [(const_int 0)] 0)]
1018   ""
1019   ""
1020   [(set_attr "length" "0")
1021    (set_attr "psw_operand" "nop")])