OSDN Git Service

* doc/tm.texi (INIT_CUMULATIVE_ARGS): Update doco.
[pf3gnuchains/gcc-fork.git] / gcc / config / stormy16 / stormy16.md
1 ;; XSTORMY16 Machine description template
2 ;; Copyright (C) 1997, 1998, 1999, 2001, 2002, 2003 Free Software Foundation, Inc.
3 ;; Contributed by Red Hat, Inc.
4
5 ;; This file is part of GCC.
6
7 ;; GCC 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 ;; GCC 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 GCC; 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 ;; Constraints
25 ;; a  $0
26 ;; b  $1
27 ;; c  $2
28 ;; d  $8
29 ;; e  $0..$7
30 ;; t  $0..$1
31 ;; y  Carry
32 ;; z  $8..$9
33 ;; I  0..3
34 ;; J  2**N mask
35 ;; K  2**N antimask
36 ;; L  0..255
37 ;; M  -255..0
38 ;; N  -3..0
39 ;; O  1..4
40 ;; P  -4..-1
41 ;; Q  post-inc mem (push)
42 ;; R  pre-dec mem (pop)
43 ;; S  immediate mem
44 ;; T  Rx
45 ;; U  -inf..1 or 16..inf
46 ;; Z  0
47
48 \f
49 ;; ::::::::::::::::::::
50 ;; ::
51 ;; :: Attributes
52 ;; ::
53 ;; ::::::::::::::::::::
54
55 ; Categorize branches for the conditional in the length attribute.
56 (define_attr "branch_class" "notdirectbranch,br12,bcc12,bcc8p2,bcc8p4" 
57     (const_string "notdirectbranch"))
58
59 ; The length of an instruction, used for branch shortening.
60 (define_attr "length" "" 
61   (cond
62    [(eq_attr "branch_class" "br12")
63      (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2046))
64                         (lt (minus (match_dup 0) (pc)) (const_int 2048)))
65                    (const_int 2)
66                    (const_int 4))
67     (eq_attr "branch_class" "bcc12")
68      (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -2044))
69                         (lt (minus (match_dup 0) (pc)) (const_int 2048)))
70                    (const_int 4)
71                    (const_int 8))
72     (eq_attr "branch_class" "bcc8p2")
73      (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -124))
74                         (lt (minus (match_dup 0) (pc)) (const_int 128)))
75                    (const_int 4)
76                    (const_int 8))
77     (eq_attr "branch_class" "bcc8p4")
78      (if_then_else (and (ge (minus (match_dup 0) (pc)) (const_int -122))
79                         (lt (minus (match_dup 0) (pc)) (const_int 128)))
80                    (const_int 6)
81                    (const_int 10))]
82    (const_int 2)))
83
84 ; The operand which determines the setting of Rpsw.
85 ; The numbers indicate the operand number,
86 ; 'clobber' indicates it is changed in some unspecified way
87 ; 'nop' means it is not changed.
88 (define_attr "psw_operand" "clobber,nop,0,1,2,3,4" (const_string "0"))
89
90 (define_asm_attributes [(set_attr "length" "4")
91                         (set_attr "psw_operand" "clobber")])
92
93 \f
94 ;; ::::::::::::::::::::
95 ;; ::
96 ;; :: Moves
97 ;; ::
98 ;; ::::::::::::::::::::
99 ;; push/pop qi and hi are here as separate insns rather than part of
100 ;; the movqi/hi patterns because we need to ensure that reload isn't
101 ;; passed anything it can't cope with.  Without these patterns, we
102 ;; might end up with
103
104 ;; (set (mem (post_inc (sp))) mem (post_inc (reg)))
105
106 ;; If, in this example, reg needs reloading, reload will read reg from
107 ;; the stack , adjust sp, and store reg back at what is now the wrong
108 ;; offset.  By using separate patterns for push and pop we ensure that
109 ;; insns like this one are never generated.
110
111 (define_insn "pushqi"
112   [(set (mem:QI (post_inc (reg:HI 15)))
113         (match_operand:QI 0 "register_operand" "r"))]
114   ""
115   "push %0"
116   [(set_attr "psw_operand" "nop")
117    (set_attr "length" "2")])
118
119 (define_insn "popqi"
120   [(set (match_operand:QI 0 "register_operand" "=r")
121         (mem:QI (pre_dec (reg:HI 15))))]
122   ""
123   "pop %0"
124   [(set_attr "psw_operand" "nop")
125    (set_attr "length" "2")])
126
127 (define_expand "movqi"
128   [(set (match_operand:QI 0 "nonimmediate_nonstack_operand" "")
129         (match_operand:QI 1 "general_operand" ""))]
130   ""
131   "{ xstormy16_expand_move (QImode, operands[0], operands[1]); DONE; }")
132
133 (define_insn "*movqi_internal"
134   [(set (match_operand:QI 0 "nonimmediate_nonstack_operand" "=r,m,e,e,T,r,S")
135         (match_operand:QI 1 "general_operand"       "r,e,m,i,i,i,i"))]
136   ""
137   "@
138    mov %0,%1
139    mov.b %0,%1
140    mov.b %0,%1
141    mov %0,%1
142    mov Rx,%1
143    mov %0,%1
144    mov.b %0,%1"
145   [(set_attr_alternative "length" 
146              [(const_int 2)
147               (if_then_else (match_operand:QI 0 "short_memory_operand" "")
148                             (const_int 2)
149                             (const_int 4))
150               (if_then_else (match_operand:QI 1 "short_memory_operand" "")
151                             (const_int 2)
152                             (const_int 4))
153               (const_int 2)
154               (const_int 2)
155               (const_int 4)
156               (const_int 4)])
157    (set_attr "psw_operand" "0,0,0,0,nop,0,nop")])
158
159 (define_insn "pushhi"
160   [(set (mem:HI (post_inc (reg:HI 15)))
161         (match_operand:HI 0 "register_operand" "r"))]
162   ""
163   "push %0"
164   [(set_attr "psw_operand" "nop")
165    (set_attr "length" "2")])
166
167 (define_insn "pophi"
168   [(set (match_operand:HI 0 "register_operand" "=r")
169         (mem:HI (pre_dec (reg:HI 15))))]
170   ""
171   "pop %0"
172   [(set_attr "psw_operand" "nop")
173    (set_attr "length" "2")])
174
175 (define_expand "movhi"
176   [(set (match_operand:HI 0 "nonimmediate_nonstack_operand" "")
177         (match_operand:HI 1 "xs_hi_general_operand" ""))]
178   ""
179   "{ xstormy16_expand_move (HImode, operands[0], operands[1]); DONE; }")
180
181 (define_insn "*movhi_internal"
182   [(set (match_operand:HI 0 "nonimmediate_nonstack_operand" "=r,m,e,e,T,r,S")
183         (match_operand:HI 1 "xs_hi_general_operand"       "r,e,m,L,L,i,i"))]
184   ""
185   "@
186    mov %0,%1
187    mov.w %0,%1
188    mov.w %0,%1
189    mov.w %0,%1
190    mov.w Rx,%1
191    mov.w %0,%1
192    mov.w %0,%1"
193   [(set_attr_alternative "length" 
194              [(const_int 2)
195               (if_then_else (match_operand:QI 0 "short_memory_operand" "")
196                             (const_int 2)
197                             (const_int 4))
198               (if_then_else (match_operand:QI 1 "short_memory_operand" "")
199                             (const_int 2)
200                             (const_int 4))
201               (const_int 2)
202               (const_int 2)
203               (const_int 4)
204               (const_int 4)])
205    (set_attr "psw_operand" "0,0,0,0,nop,0,nop")])
206
207 (define_expand "movsi"
208   [(set (match_operand:SI 0 "nonimmediate_operand" "")
209         (match_operand:SI 1 "general_operand" ""))]
210   ""
211   "{ xstormy16_expand_move (SImode, operands[0], operands[1]); DONE; }")
212
213 (define_insn_and_split "*movsi_internal"
214   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,Q,r,m,e,&e,e,r,S")
215         (match_operand:SI 1 "general_operand"       "r,r,R,e,o, V,L,i,i"))]
216   ""
217   "#"
218   "reload_completed"
219   [(pc)]
220   "{ xstormy16_split_move (SImode, operands[0], operands[1]); DONE; }"
221   [(set_attr_alternative "length" 
222              [(const_int 4)
223               (const_int 4)
224               (const_int 4)
225               (if_then_else (match_operand:QI 0 "short_memory_operand" "")
226                             (const_int 6)
227                             (const_int 8))
228               (if_then_else (match_operand:QI 1 "short_memory_operand" "")
229                             (const_int 6)
230                             (const_int 8))
231               (if_then_else (match_operand:QI 1 "short_memory_operand" "")
232                             (const_int 6)
233                             (const_int 8))
234               (const_int 4)
235               (const_int 8)
236               (const_int 8)])])
237
238 \f
239 ;; ::::::::::::::::::::
240 ;; ::
241 ;; :: Conversions
242 ;; ::
243 ;; ::::::::::::::::::::
244
245 (define_insn "extendqihi2"
246   [(set (match_operand:HI 0 "register_operand" "=r")
247         (sign_extend:HI (match_operand:QI 1 "register_operand" "0")))]
248   ""
249   "cbw %0")
250
251 (define_insn "zero_extendqihi2"
252   [(set (match_operand:HI                 0 "register_operand"     "=e,r")
253         (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "m,0")))]
254   ""
255   "@
256    mov.b %0, %1
257    shl %0,#8\n\tshr %0,#8"
258   [(set_attr "psw_operand" "nop,0")
259    (set_attr_alternative "length" 
260              [(const_int 2)
261               (const_int 4)])])
262
263 \f
264 ;; ::::::::::::::::::::
265 ;; ::
266 ;; :: Bit field extraction
267 ;; ::
268 ;; ::::::::::::::::::::
269
270 ;; Extract an unsigned bit field
271 ;(define_insn "extzv"
272 ;  [(set (match_operand:SI 0 "register_operand" "=r")
273 ;       (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
274 ;                        (match_operand:SI 2 "const_int_operand" "n")
275 ;                        (match_operand:SI 3 "const_int_operand" "n")))]
276 ;  ""
277 ;  "extzv %0,%1,%2,%3"
278 ;  [(set_attr "length" "4")])
279
280 ;; Insert a bit field
281 ;(define_insn "insv"
282 ;  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
283 ;                        (match_operand:SI 1 "const_int_operand" "n")
284 ;                        (match_operand:SI 2 "const_int_operand" "n"))
285 ;       (match_operand:SI 3 "nonmemory_operand" "ri"))]
286 ;  ""
287 ;  "insv %0,%1,%2,%3"
288 ;  [(set_attr "length" "4")])
289
290 \f
291 ;; ::::::::::::::::::::
292 ;; ::
293 ;; :: 16 bit Integer arithmetic
294 ;; ::
295 ;; ::::::::::::::::::::
296
297 ;; Addition
298 ; Operand 3 is marked earlyclobber because that helps reload
299 ; to generate better code---this pattern will never need the
300 ; carry register as an input, and some output reloads or input
301 ; reloads might need to use it.  In fact, without the '&' reload
302 ; will fail in some cases.
303 ; Note that the 'Z' constraint matches "add $reg,0", which reload
304 ; will occasionally emit.  We avoid the "add $reg,imm" match because
305 ; it clobbers the carry.
306 (define_insn "addhi3"
307   [(set (match_operand:HI 0 "register_operand" "=r,r,r,T,T,r,r,r")
308         (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0,0,0")
309                  (match_operand:HI 2 "xs_hi_nonmemory_operand" "O,P,Z,L,M,Ir,N,i")))
310    (clobber (match_scratch:BI 3 "=X,X,X,&y,&y,&y,&y,&y"))]
311   ""
312   "@
313    inc %0,%o2
314    dec %0,%O2
315    ;
316    add Rx,%2
317    sub Rx,#%n2
318    add %0,%2
319    sub %0,#%n2
320    add %0,%2"
321   [(set_attr "length" "2,2,0,2,2,2,2,4")])
322
323 ; Reload can generate addition operations.  The SECONDARY_RELOAD_CLASS
324 ; macro causes it to allocate the carry register; this pattern
325 ; shows it how to place the register in RTL to make the addition work.
326 (define_expand "reload_inhi"
327   [(parallel [(set (match_operand:HI 0 "register_operand" "=r")
328                    (match_operand:HI 1 "xstormy16_carry_plus_operand" ""))
329               (clobber (match_operand:BI 2 "" "=&y"))])]
330   ""
331   "if (! rtx_equal_p (operands[0], XEXP (operands[1], 0)))
332     {
333       emit_insn (gen_rtx_SET (VOIDmode, operands[0], XEXP (operands[1], 0)));
334       operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]), operands[0],
335                                   XEXP (operands[1], 1));
336     }
337  ")
338
339 (define_insn "addchi4"
340   [(set (match_operand:HI 0 "register_operand" "=T,r,r")
341         (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
342                  (match_operand:HI 2 "xs_hi_nonmemory_operand" "L,Ir,i")))
343    (set (match_operand:BI 3 "register_operand" "=y,y,y")
344         (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
345                                            (zero_extend:SI (match_dup 2)))
346                                   (const_int 16))))]
347   ""
348   "@
349    add Rx,%2
350    add %0,%2
351    add %0,%2"
352   [(set_attr "length" "2,2,4")])
353
354 (define_insn "addchi5"
355   [(set (match_operand:HI 0 "register_operand" "=T,r,r")
356         (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
357                           (zero_extend:HI (match_operand:BI 3 
358                                                             "register_operand"
359                                                             "y,y,y")))
360                  (match_operand:HI 2 "xs_hi_nonmemory_operand" "L,Ir,i")))
361    (set (match_operand:BI 4 "register_operand" "=y,y,y") 
362         (truncate:BI (lshiftrt:SI (plus:SI (plus:SI 
363                                             (zero_extend:SI (match_dup 1))
364                                             (zero_extend:SI (match_dup 3)))
365                                            (zero_extend:SI (match_dup 2)))
366                                   (const_int 16))))]
367   ""
368   "@
369    adc Rx,%2
370    adc %0,%2
371    adc %0,%2"
372   [(set_attr "length" "2,2,4")])
373
374 ;; Subtraction
375 ; Operand 3 is marked earlyclobber because that helps reload
376 ; to generate better code---this pattern will never need the
377 ; carry register as an input, and some output reloads or input
378 ; reloads might need to use it.  In fact, without the '&' reload
379 ; will fail in some cases.
380 (define_insn "subhi3"
381   [(set (match_operand:HI 0 "register_operand" "=r,r,T,T,r,r,r")
382         (minus:HI (match_operand:HI 1 "register_operand" "0,0,0,0,0,0,0")
383                   (match_operand:HI 2 "xs_hi_nonmemory_operand" "O,P,L,M,rI,M,i")))
384    (clobber (match_scratch:BI 3 "=X,X,&y,&y,&y,&y,&y"))]
385   ""
386   "@
387    dec %0,%o2
388    inc %0,%O2
389    sub Rx,%2
390    add Rx,#%n2
391    sub %0,%2
392    add %0,#%n2
393    sub %0,%2"
394   [(set_attr "length" "2,2,2,2,2,2,4")])
395
396 (define_insn "subchi4"
397   [(set (match_operand:HI 0 "register_operand" "=T,r,r")
398         (minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
399                   (match_operand:HI 2 "xs_hi_nonmemory_operand" "L,Ir,i")))
400    (set (match_operand:BI 3 "register_operand" "=y,y,y") 
401         (truncate:BI (lshiftrt:SI (minus:SI (zero_extend:SI (match_dup 1))
402                                             (zero_extend:SI (match_dup 2)))
403                                   (const_int 16))))]
404   ""
405   "@
406    sub Rx,%2
407    sub %0,%2
408    sub %0,%2"
409   [(set_attr "length" "2,2,4")])
410
411 (define_insn "subchi5"
412   [(set (match_operand:HI 0 "register_operand" "=T,r,r")
413         (minus:HI (minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
414                           (zero_extend:HI (match_operand:BI 3 
415                                                             "register_operand"
416                                                             "y,y,y")))
417                  (match_operand:HI 2 "xs_hi_nonmemory_operand" "L,Ir,i")))
418    (set (match_operand:BI 4 "register_operand" "=y,y,y") 
419         (truncate:BI (lshiftrt:SI (minus:SI (minus:SI 
420                                              (zero_extend:SI (match_dup 1))
421                                              (zero_extend:SI (match_dup 3)))
422                                             (zero_extend:SI (match_dup 2)))
423                                   (const_int 16))))]
424   ""
425   "@
426    sbc Rx,%2
427    sbc %0,%2
428    sbc %0,%2"
429   [(set_attr "length" "2,2,4")])
430
431 ; Basic multiplication
432 (define_insn "mulhi3"
433   [(set (match_operand:HI 0 "register_operand" "=a")
434         (mult:HI (match_operand:HI 1 "register_operand" "%a")
435                  (match_operand:HI 2 "register_operand" "c")))
436    (clobber (match_scratch:HI 3 "=b"))
437    ]
438   ""
439   "mul"
440   [(set_attr "psw_operand" "nop")])
441
442 ;; Unsigned multiplication producing 64 bit results from 32 bit inputs
443 ; The constraint on operand 0 is 't' because it is actually two regs
444 ; long, and both regs must match the constraint.
445 (define_insn "umulhisi3"
446   [(set (match_operand:SI 0 "register_operand" "=t")
447         (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%a"))
448                  (zero_extend:SI (match_operand:HI 2 "register_operand" "c"))))
449    ]
450   ""
451   "mul"
452   [(set_attr "psw_operand" "nop")])
453
454 ;; Unsigned division giving both quotient and remainder
455 (define_insn "udivmodhi4"
456   [(set (match_operand:HI 0 "register_operand" "=a")
457         (udiv:HI (match_operand:HI 1 "register_operand" "a")
458                  (match_operand:HI 2 "register_operand" "c")))
459    (set (match_operand:HI 3 "register_operand" "=b")
460         (umod:HI (match_dup 1)
461                  (match_dup 2)))]
462   ""
463   "div"
464   [(set_attr "psw_operand" "nop")])
465
466 ;; Signed division giving both quotient and remainder
467 (define_insn "divmodhi4"
468   [(set (match_operand:HI 0 "register_operand" "=a")
469         (div:HI (match_operand:HI 1 "register_operand" "a")
470                  (match_operand:HI 2 "register_operand" "c")))
471    (set (match_operand:HI 3 "register_operand" "=b")
472         (mod:HI (match_dup 1)
473                  (match_dup 2)))]
474   ""
475   "sdiv"
476   [(set_attr "psw_operand" "nop")])
477
478 ;; Signed 32/16 division
479 (define_insn "sdivlh"
480   [(set (match_operand:HI 0 "register_operand" "=a")
481         (div:HI (match_operand:SI 2 "register_operand" "t")
482                  (match_operand:HI 3 "register_operand" "c")))
483    (set (match_operand:HI 1 "register_operand" "=b")
484         (mod:HI (match_dup 2)
485                  (match_dup 3)))]
486   ""
487   "sdivlh"
488   [(set_attr "psw_operand" "nop")])
489
490 ;; Unsigned 32/16 division
491 (define_insn "udivlh"
492   [(set (match_operand:HI 0 "register_operand" "=a")
493         (udiv:HI (match_operand:SI 2 "register_operand" "t")
494                  (match_operand:HI 3 "register_operand" "c")))
495    (set (match_operand:HI 1 "register_operand" "=b")
496         (umod:HI (match_dup 2)
497                  (match_dup 3)))]
498   ""
499   "divlh"
500   [(set_attr "psw_operand" "nop")])
501
502 ;; Negation
503
504 (define_expand "neghi2"
505   [(set (match_operand:HI 0 "register_operand" "")
506         (not:HI (match_operand:HI 1 "register_operand" "")))
507    (parallel [(set (match_dup 0) (plus:HI (match_dup 0) (const_int 1)))
508               (clobber (match_scratch:BI 3 ""))])]
509   ""
510   "")
511
512 \f
513 ;; ::::::::::::::::::::
514 ;; ::
515 ;; :: 16 bit Integer Shifts and Rotates
516 ;; ::
517 ;; ::::::::::::::::::::
518
519 ;; Arithmetic Shift Left
520 (define_insn "ashlhi3"
521   [(set (match_operand:HI 0 "register_operand" "=r")
522         (ashift:HI (match_operand:HI 1 "register_operand" "0")
523                    (match_operand:HI 2 "nonmemory_operand" "ri")))
524    (clobber (match_scratch:BI 3 "=y"))]
525   ""
526   "shl %0,%2")
527
528 ;; Arithmetic Shift Right
529 (define_insn "ashrhi3"
530   [(set (match_operand:HI 0 "register_operand" "=r")
531         (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
532                      (match_operand:HI 2 "nonmemory_operand" "ri")))
533    (clobber (match_scratch:BI 3 "=y"))]
534   ""
535   "asr %0,%2")
536
537 ;; Logical Shift Right
538 (define_insn "lshrhi3"
539   [(set (match_operand:HI 0 "register_operand" "=r")
540         (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
541                      (match_operand:HI 2 "nonmemory_operand" "ri")))
542    (clobber (match_scratch:BI 3 "=y"))]
543   ""
544   "shr %0,%2")
545
546 \f
547 ;; ::::::::::::::::::::
548 ;; ::
549 ;; :: 16 Bit Integer Logical operations
550 ;; ::
551 ;; ::::::::::::::::::::
552
553 ;; Logical AND, 16 bit integers
554 (define_insn "andhi3"
555   [(set (match_operand:HI 0 "register_operand" "=T,r,r,r")
556         (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
557                 (match_operand:HI 2 "nonmemory_operand" "L,r,K,i")))]
558   ""
559   "@
560    and Rx,%2
561    and %0,%2
562    clr1 %0,%B2
563    and %0,%2"
564   [(set_attr "length" "2,2,2,4")])
565
566 ;; Inclusive OR, 16 bit integers
567 (define_insn "iorhi3"
568   [(set (match_operand:HI 0 "register_operand" "=T,r,r,r")
569         (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
570                 (match_operand:HI 2 "nonmemory_operand" "L,r,J,i")))]
571   ""
572   "@
573    or Rx,%2
574    or %0,%2
575    set1 %0,%B2
576    or %0,%2"
577   [(set_attr "length" "2,2,2,4")])
578
579 ;; Exclusive OR, 16 bit integers
580 (define_insn "xorhi3"
581   [(set (match_operand:HI 0 "register_operand" "=T,r,r")
582         (xor:HI (match_operand:HI 1 "register_operand" "%0,0,0")
583                 (match_operand:HI 2 "nonmemory_operand" "L,r,i")))]
584   ""
585   "@
586    xor Rx,%2
587    xor %0,%2
588    xor %0,%2"
589   [(set_attr "length" "2,2,4")])
590
591 ;; One's complement, 16 bit integers
592 (define_insn "one_cmplhi2"
593   [(set (match_operand:HI 0 "register_operand" "=r")
594         (not:HI (match_operand:HI 1 "register_operand" "0")))]
595   ""
596   "not %0")
597
598 \f
599 ;; ::::::::::::::::::::
600 ;; ::
601 ;; :: 32 bit Integer arithmetic
602 ;; ::
603 ;; ::::::::::::::::::::
604
605 ;; Addition
606 (define_insn_and_split "addsi3"
607   [(set (match_operand:SI 0 "register_operand" "=r")
608         (plus:SI (match_operand:SI 1 "register_operand" "%0")
609                  (match_operand:SI 2 "nonmemory_operand" "ri")))
610    (clobber (match_scratch:BI 3 "=y"))]
611   ""
612   "#"
613   "reload_completed"
614   [(pc)]
615   "{ xstormy16_expand_arith (SImode, PLUS, operands[0], operands[1],
616                             operands[2], operands[3]); DONE; } "
617   [(set_attr "length" "4")])
618
619 ;; Subtraction
620 (define_insn_and_split "subsi3"
621   [(set (match_operand:SI 0 "register_operand" "=r")
622         (minus:SI (match_operand:SI 1 "register_operand" "0")
623                  (match_operand:SI 2 "nonmemory_operand" "ri")))
624    (clobber (match_scratch:BI 3 "=y"))]
625   ""
626   "#"
627   "reload_completed"
628   [(pc)]
629   "{ xstormy16_expand_arith (SImode, MINUS, operands[0], operands[1],
630                             operands[2], operands[3]); DONE; } "
631   [(set_attr "length" "4")])
632
633 (define_expand "negsi2"
634   [(parallel [(set (match_operand:SI 0 "register_operand" "")
635                    (neg:SI (match_operand:SI 1 "register_operand" "")))
636               (clobber (match_scratch:BI 2 ""))])]
637   ""
638   "{ operands[2] = gen_reg_rtx (HImode);
639      operands[3] = gen_reg_rtx (BImode); }")
640
641 (define_insn_and_split "*negsi2_internal"
642   [(set (match_operand:SI 0 "register_operand" "=&r")
643         (neg:SI (match_operand:SI 1 "register_operand" "r")))
644    (clobber (match_scratch:BI 2 "=y"))]
645   ""
646   "#"
647   "reload_completed"
648   [(pc)]
649   "{ xstormy16_expand_arith (SImode, NEG, operands[0], operands[0],
650                             operands[1], operands[2]); DONE; }")
651
652 ;; ::::::::::::::::::::
653 ;; ::
654 ;; :: 32 bit Integer Shifts and Rotates
655 ;; ::
656 ;; ::::::::::::::::::::
657
658 ;; Arithmetic Shift Left
659 (define_expand "ashlsi3"
660   [(parallel [(set (match_operand:SI 0 "register_operand" "")
661                    (ashift:SI (match_operand:SI 1 "register_operand" "")
662                               (match_operand:SI 2 "const_int_operand" "")))
663               (clobber (match_dup 3))
664               (clobber (match_dup 4))])]
665   ""
666   " if (! const_int_operand (operands[2], SImode)) FAIL;
667   operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
668
669 ;; Arithmetic Shift Right
670 (define_expand "ashrsi3"
671   [(parallel [(set (match_operand:SI 0 "register_operand" "")
672                    (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
673                                 (match_operand:SI 2 "const_int_operand" "")))
674               (clobber (match_dup 3))
675               (clobber (match_dup 4))])]
676   ""
677   " if (! const_int_operand (operands[2], SImode)) FAIL;
678   operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
679
680 ;; Logical Shift Right
681 (define_expand "lshrsi3"
682   [(parallel [(set (match_operand:SI 0 "register_operand" "")
683                    (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
684                                 (match_operand:SI 2 "const_int_operand" "")))
685               (clobber (match_dup 3))
686               (clobber (match_dup 4))])]
687   ""
688   " if (! const_int_operand (operands[2], SImode)) FAIL;
689   operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
690
691 (define_insn "*shiftsi"
692   [(set (match_operand:SI 0 "register_operand" "=r,r")
693         (match_operator:SI 5 "shift_operator"
694          [(match_operand:SI 1 "register_operand" "0,0")
695           (match_operand:SI 2 "const_int_operand" "U,n")]))
696    (clobber (match_operand:BI 3 "register_operand" "=y,y"))
697    (clobber (match_operand:HI 4 "" "=X,r"))]
698   ""
699   "* return xstormy16_output_shift (SImode, GET_CODE (operands[5]), 
700                                    operands[0], operands[2], operands[4]);"
701   [(set_attr "length" "6,10")
702    (set_attr "psw_operand" "clobber,clobber")])
703
704 \f
705 ;; ::::::::::::::::::::
706 ;; ::
707 ;; :: Comparisons
708 ;; ::
709 ;; ::::::::::::::::::::
710
711 ;; Note, we store the operands in the comparison insns, and use them later
712 ;; when generating the branch or scc operation.
713
714 ;; First the routines called by the machine independent part of the compiler
715 (define_expand "cmphi"
716   [(set (cc0)
717         (compare (match_operand:HI 0 "register_operand" "")
718                  (match_operand:HI 1 "nonmemory_operand" "")))]
719   ""
720   "
721 {
722   xstormy16_compare_op0 = operands[0];
723   xstormy16_compare_op1 = operands[1];
724   DONE;
725 }")
726
727 ; There are no real SImode comparisons, but some can be emulated
728 ; by performing a SImode subtract and looking at the condition flags.
729 (define_expand "cmpsi"
730   [(set (cc0)
731         (compare (match_operand:SI 0 "register_operand" "")
732                  (match_operand:SI 1 "nonmemory_operand" "")))]
733   ""
734   "
735 {
736   xstormy16_compare_op0 = operands[0];
737   xstormy16_compare_op1 = operands[1];
738   DONE;
739 }")
740
741 \f
742 ;; ::::::::::::::::::::
743 ;; ::
744 ;; :: Branches
745 ;; ::
746 ;; ::::::::::::::::::::
747
748 (define_expand "beq"
749   [(use (match_operand 0 "" ""))]
750   ""
751   "{ xstormy16_emit_cbranch (EQ, operands[0]); DONE; }")
752
753 (define_expand "bne"
754   [(use (match_operand 0 "" ""))]
755   ""
756   "{ xstormy16_emit_cbranch (NE, operands[0]); DONE; }")
757
758 (define_expand "bge"
759   [(use (match_operand 0 "" ""))]
760   ""
761   "{ xstormy16_emit_cbranch (GE, operands[0]); DONE; }")
762
763 (define_expand "bgt"
764   [(use (match_operand 0 "" ""))]
765   ""
766   "{ xstormy16_emit_cbranch (GT, operands[0]); DONE; }")
767
768 (define_expand "ble"
769   [(use (match_operand 0 "" ""))]
770   ""
771   "{ xstormy16_emit_cbranch (LE, operands[0]); DONE; }")
772
773 (define_expand "blt"
774   [(use (match_operand 0 "" ""))]
775   ""
776   "{ xstormy16_emit_cbranch (LT, operands[0]); DONE; }")
777
778 (define_expand "bgeu"
779   [(use (match_operand 0 "" ""))]
780   ""
781   "{ xstormy16_emit_cbranch (GEU, operands[0]); DONE; }")
782
783 (define_expand "bgtu"
784   [(use (match_operand 0 "" ""))]
785   ""
786   "{ xstormy16_emit_cbranch (GTU, operands[0]); DONE; }")
787
788 (define_expand "bleu"
789   [(use (match_operand 0 "" ""))]
790   ""
791   "{ xstormy16_emit_cbranch (LEU, operands[0]); DONE; }")
792
793 (define_expand "bltu"
794   [(use (match_operand 0 "" ""))]
795   ""
796   "{ xstormy16_emit_cbranch (LTU, operands[0]); DONE; }")
797
798
799 (define_insn "*cbranchhi"
800   [(set (pc) 
801         (if_then_else (match_operator:HI 1 "comparison_operator"
802                                       [(match_operand:HI 2 "nonmemory_operand" 
803                                         "r,e,L")
804                                        (match_operand:HI 3 "nonmemory_operand"
805                                                       "r,L,e")])
806                       (label_ref (match_operand 0 "" ""))
807                       (pc)))
808    (clobber (match_operand:BI 4 "" "=&y,&y,&y"))]
809   ""
810   "*
811 {
812   return xstormy16_output_cbranch_hi (operands[1], \"%l0\", 0, insn);
813 }"
814   [(set_attr "branch_class" "bcc12")
815    (set_attr "psw_operand" "0,0,1")])
816
817 (define_insn "*cbranchhi_neg"
818   [(set (pc) 
819         (if_then_else (match_operator:HI 1 "comparison_operator"
820                                       [(match_operand:HI 2 "nonmemory_operand" 
821                                                          "r,e,L")
822                                        (match_operand:HI 3 "nonmemory_operand"
823                                                          "r,L,e")])
824                       (pc)
825                       (label_ref (match_operand 0 "" ""))))
826    (clobber (match_operand:BI 4 "" "=&y,&y,&y"))]
827   ""
828   "*
829 {
830   return xstormy16_output_cbranch_hi (operands[1], \"%l0\", 1, insn);
831 }"
832   [(set_attr "branch_class" "bcc12")
833    (set_attr "psw_operand" "0,0,1")])
834
835 (define_insn "*eqbranchsi"
836   [(set (pc)
837         (if_then_else (match_operator:SI 1 "equality_operator"
838                                       [(match_operand:SI 2 "register_operand" 
839                                                          "r")
840                                        (const_int 0)])
841                       (label_ref (match_operand 0 "" ""))
842                       (pc)))
843 ;; Although I would greatly like the 'match_dup' in the following line
844 ;; to actually be a register constraint, there is (at the time of writing) no
845 ;; way for reload to insert an output reload on the edges out of a branch.
846 ;; If reload is fixed to use insert_insn_on_edge, this can be changed.
847    (clobber (match_dup 2))]
848   ""
849   "*
850 {
851   return xstormy16_output_cbranch_si (operands[1], \"%l0\", 0, insn);
852 }"
853   [(set_attr "branch_class" "bcc8p2")
854    (set_attr "psw_operand" "clobber")])
855
856 (define_insn_and_split "*ineqbranchsi"
857   [(set (pc)
858         (if_then_else (match_operator:SI 1 "xstormy16_ineqsi_operator"
859                                       [(match_operand:SI 2 "register_operand" 
860                                                          "r")
861                                        (match_operand:SI 3 "nonmemory_operand" 
862                                                          "ri")])
863                       (label_ref (match_operand 0 "" ""))
864                       (pc)))
865 ;; Although I would greatly like the 'match_dup' in the following line
866 ;; to actually be a register constraint, there is (at the time of writing) no
867 ;; way for reload to insert an output reload on the edges out of a branch.
868 ;; If reload is fixed to use insert_insn_on_edge, this can be changed,
869 ;; preferably to a 'minus' operand that explains the actual operation, like:
870 ; (set (match_operand 5 "register_operand" "=2")
871 ;      (minus:SI (match_operand 6 "register_operand" "2")
872 ;                (match_operand 7 "register_operand" "3")))
873    (clobber (match_dup 2))
874    (clobber (match_operand:BI 4 "" "=&y"))]
875   ""
876   "#"
877   "reload_completed"
878   [(pc)]
879   "{ xstormy16_split_cbranch (SImode, operands[0], operands[1], operands[2],
880                              operands[4]); DONE; }"
881   [(set_attr "length" "8")])
882
883 (define_insn "*ineqbranch_1"
884   [(set (pc)
885         (if_then_else (match_operator:HI 5 "xstormy16_ineqsi_operator"
886                        [(minus:HI (match_operand:HI 1 "register_operand" 
887                                                     "T,r,r")
888                            (zero_extend:HI (match_operand:BI 4
889                                                              "register_operand"
890                                                              "y,y,y")))
891                         (match_operand:HI 3 "nonmemory_operand" "L,Ir,i")])
892                       (label_ref (match_operand 0 "" ""))
893                       (pc)))
894    (set (match_operand:HI 2 "register_operand" "=1,1,1")
895         (minus:HI (minus:HI (match_dup 1) (zero_extend:HI (match_dup 4)))
896                   (match_dup 3)))
897    (clobber (match_operand:BI 6 "" "=y,y,y"))]
898   ""
899   "*
900 {
901   return xstormy16_output_cbranch_si (operands[5], \"%l0\", 0, insn);
902 }"
903   [(set_attr "branch_class" "bcc8p2,bcc8p2,bcc8p4")
904    (set_attr "psw_operand" "2,2,2")])
905
906 \f
907 ;; ::::::::::::::::::::
908 ;; ::
909 ;; :: Call and branch instructions
910 ;; ::
911 ;; ::::::::::::::::::::
912
913 ;; Subroutine call instruction returning no value.  Operand 0 is the function
914 ;; to call; operand 1 is the number of bytes of arguments pushed (in mode
915 ;; `SImode', except it is normally a `const_int'); operand 2 is the number of
916 ;; registers used as operands.
917
918 ;; On most machines, operand 2 is not actually stored into the RTL pattern.  It
919 ;; is supplied for the sake of some RISC machines which need to put this
920 ;; information into the assembler code; they can put it in the RTL instead of
921 ;; operand 1.
922
923 (define_expand "call"
924   [(call (match_operand:HI 0 "memory_operand" "m")
925          (match_operand 1 "" ""))
926    (use (match_operand 2 "immediate_operand" ""))]
927   ""
928   "xstormy16_expand_call (NULL_RTX, operands[0], operands[1]); DONE;")
929
930 ;; Subroutine call instruction returning a value.  Operand 0 is the hard
931 ;; register in which the value is returned.  There are three more operands, the
932 ;; same as the three operands of the `call' instruction (but with numbers
933 ;; increased by one).
934
935 ;; Subroutines that return `BLKmode' objects use the `call' insn.
936
937 (define_expand "call_value"
938   [(set (match_operand 0 "register_operand" "=r")
939         (call (match_operand:HI 1 "memory_operand" "m")
940               (match_operand:SI 2 "" "")))
941         (use (match_operand 3 "immediate_operand" ""))]
942   ""
943   "xstormy16_expand_call (operands[0], operands[1], operands[2]); DONE;")
944
945 (define_insn "*call_internal"
946   [(call (mem:HI (match_operand:HI 0 "nonmemory_operand" "i,r"))
947          (match_operand 1 "" ""))
948    (use (match_operand:HI 2 "nonmemory_operand" "X,z"))]
949   ""
950   "@
951    callf %C0
952    call %2,%0"
953   [(set_attr "length" "4,2")
954    (set_attr "psw_operand" "clobber")])
955
956 (define_insn "*call_value_internal"
957   [(set (match_operand 3 "register_operand" "=r,r")
958         (call (mem:HI (match_operand:HI 0 "nonmemory_operand" "i,r"))
959               (match_operand 1 "" "")))
960    (use (match_operand:HI 2 "nonmemory_operand" "X,z"))]
961   ""
962   "@
963    callf %C0
964    call %2,%0"
965   [(set_attr "length" "4,2")
966    (set_attr "psw_operand" "clobber")])
967
968 ;; Subroutine return
969 (define_expand "return"
970   [(return)]
971   "direct_return()"
972   "")
973
974 (define_insn "return_internal"
975   [(return)]
976   ""
977   "ret"
978   [(set_attr "psw_operand" "nop")])
979
980 (define_insn "return_internal_interrupt"
981   [(return)
982    (unspec_volatile [(const_int 0)] 1)]
983   ""
984   "iret"
985   [(set_attr "psw_operand" "clobber")])
986
987 ;; Normal unconditional jump
988 (define_insn "jump"
989   [(set (pc) (label_ref (match_operand 0 "" "")))]
990   ""
991   "*
992 {
993   return xstormy16_output_cbranch_hi (NULL_RTX, \"%l0\", 0, insn);
994 }"
995   [(set_attr "branch_class" "br12")
996    (set_attr "psw_operand" "nop")])
997
998 ;; Indirect jump through a register
999 (define_expand "indirect_jump"
1000   [(set (match_dup 1) (const_int 0))
1001    (parallel [(set (pc) (match_operand:HI 0 "register_operand" "r"))
1002               (use (match_dup 1))])]
1003   ""
1004   "operands[1] = gen_reg_rtx (HImode);")
1005
1006 (define_insn ""
1007   [(set (pc) (match_operand:HI 0 "register_operand" "r"))
1008    (use (match_operand:HI 1 "register_operand" "z"))]
1009   ""
1010   "jmp %1,%0"
1011   [(set_attr "length" "4")
1012    (set_attr "psw_operand" "nop")])
1013
1014 ;; Table-based switch statements.
1015 (define_expand "casesi"
1016   [(use (match_operand:SI 0 "register_operand" ""))
1017    (use (match_operand:SI 1 "immediate_operand" ""))
1018    (use (match_operand:SI 2 "immediate_operand" ""))
1019    (use (label_ref (match_operand 3 "" "")))
1020    (use (label_ref (match_operand 4 "" "")))]
1021   ""
1022   "
1023 {
1024   xstormy16_expand_casesi (operands[0], operands[1], operands[2],
1025                           operands[3], operands[4]);
1026   DONE;
1027 }")
1028
1029 (define_insn "tablejump_pcrel"
1030   [(set (pc) (mem:HI (plus:HI (pc) 
1031                               (match_operand:HI 0 "register_operand" "r"))))
1032    (use (label_ref:SI (match_operand 1 "" "")))]
1033   ""
1034   "br %0"
1035   [(set_attr "psw_operand" "nop")])
1036
1037 \f
1038 ;; ::::::::::::::::::::
1039 ;; ::
1040 ;; :: Prologue and Epilogue instructions
1041 ;; ::
1042 ;; ::::::::::::::::::::
1043
1044 ;; Called after register allocation to add any instructions needed for
1045 ;; the prologue.  Using a prologue insn is favored compared to putting
1046 ;; all of the instructions in the TARGET_ASM_FUNCTION_PROLOGUE macro,
1047 ;; since it allows the scheduler to intermix instructions with the
1048 ;; saves of the caller saved registers.  In some cases, it might be
1049 ;; necessary to emit a barrier instruction as the last insn to prevent
1050 ;; such scheduling.
1051 (define_expand "prologue"
1052   [(const_int 1)]
1053   ""
1054   "
1055 {
1056   xstormy16_expand_prologue ();
1057   DONE;
1058 }")
1059
1060 ;; Called after register allocation to add any instructions needed for
1061 ;; the epilogue.  Using an epilogue insn is favored compared to putting
1062 ;; all of the instructions in the TARGET_ASM_FUNCTION_EPILOGUE macro,
1063 ;; since it allows the scheduler to intermix instructions with the
1064 ;; restires of the caller saved registers.  In some cases, it might be
1065 ;; necessary to emit a barrier instruction as the first insn to
1066 ;; prevent such scheduling.
1067 (define_expand "epilogue"
1068   [(const_int 2)]
1069   ""
1070   "
1071 {
1072   xstormy16_expand_epilogue ();
1073   DONE;
1074 }")
1075
1076 \f
1077 ;; ::::::::::::::::::::
1078 ;; ::
1079 ;; :: Miscellaneous instructions
1080 ;; ::
1081 ;; ::::::::::::::::::::
1082
1083 ;; No operation, needed in case the user uses -g but not -O.
1084 (define_insn "nop"
1085   [(const_int 0)]
1086   ""
1087   "nop"
1088   [(set_attr "psw_operand" "nop")])
1089
1090 ;; Pseudo instruction that prevents the scheduler from moving code above this
1091 ;; point.
1092 (define_insn "blockage"
1093   [(unspec_volatile [(const_int 0)] 0)]
1094   ""
1095   ""
1096   [(set_attr "length" "0")
1097    (set_attr "psw_operand" "nop")])