]> gcc.gnu.org Git - gcc.git/blame - gcc/config/stormy16/stormy16.md
stormy16.md (pushqi): New.
[gcc.git] / gcc / config / stormy16 / stormy16.md
CommitLineData
c6243b4c 1;; XSTORMY16 Machine description template
e03f5d43 2;; Copyright (C) 1997, 1998, 1999, 2001, 2002 Free Software Foundation, Inc.
4b58290f
GK
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;; ::::::::::::::::::::
5ee4950e
AH
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")])
4b58290f
GK
102
103(define_expand "movqi"
5ee4950e 104 [(set (match_operand:QI 0 "nonimmediate_nonstack_operand" "")
4b58290f
GK
105 (match_operand:QI 1 "general_operand" ""))]
106 ""
c6243b4c 107 "{ xstormy16_expand_move (QImode, operands[0], operands[1]); DONE; }")
4b58290f
GK
108
109(define_insn "*movqi_internal"
5ee4950e
AH
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"))]
4b58290f
GK
112 ""
113 "@
114 mov %0,%1
4b58290f
GK
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)
4b58290f
GK
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)])
5ee4950e
AH
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")])
4b58290f
GK
150
151(define_expand "movhi"
5ee4950e 152 [(set (match_operand:HI 0 "nonimmediate_nonstack_operand" "")
4b58290f
GK
153 (match_operand:HI 1 "general_operand" ""))]
154 ""
c6243b4c 155 "{ xstormy16_expand_move (HImode, operands[0], operands[1]); DONE; }")
4b58290f
GK
156
157(define_insn "*movhi_internal"
5ee4950e
AH
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"))]
4b58290f
GK
160 ""
161 "@
162 mov %0,%1
4b58290f
GK
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)
4b58290f
GK
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)])
5ee4950e 181 (set_attr "psw_operand" "0,0,0,0,nop,0,nop")])
4b58290f
GK
182
183(define_expand "movsi"
184 [(set (match_operand:SI 0 "nonimmediate_operand" "")
185 (match_operand:SI 1 "general_operand" ""))]
186 ""
c6243b4c 187 "{ xstormy16_expand_move (SImode, operands[0], operands[1]); DONE; }")
4b58290f
GK
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)]
c6243b4c 196 "{ xstormy16_split_move (SImode, operands[0], operands[1]); DONE; }"
4b58290f
GK
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\f
228;; ::::::::::::::::::::
229;; ::
230;; :: Bit field extraction
231;; ::
232;; ::::::::::::::::::::
233
234;; Extract an unsigned bit field
235;(define_insn "extzv"
236; [(set (match_operand:SI 0 "register_operand" "=r")
237; (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
238; (match_operand:SI 2 "const_int_operand" "n")
239; (match_operand:SI 3 "const_int_operand" "n")))]
240; ""
241; "extzv %0,%1,%2,%3"
242; [(set_attr "length" "4")])
243
244;; Insert a bit field
245;(define_insn "insv"
246; [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r")
247; (match_operand:SI 1 "const_int_operand" "n")
248; (match_operand:SI 2 "const_int_operand" "n"))
249; (match_operand:SI 3 "nonmemory_operand" "ri"))]
250; ""
251; "insv %0,%1,%2,%3"
252; [(set_attr "length" "4")])
253
254\f
255;; ::::::::::::::::::::
256;; ::
257;; :: 16 bit Integer arithmetic
258;; ::
259;; ::::::::::::::::::::
260
261;; Addition
262; Operand 3 is marked earlyclobber because that helps reload
263; to generate better code---this pattern will never need the
264; carry register as an input, and some output reloads or input
265; reloads might need to use it. In fact, without the '&' reload
266; will fail in some cases.
267(define_insn "addhi3"
268 [(set (match_operand:HI 0 "register_operand" "=r,r,T,T,r,r,r")
269 (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0,0,0,0,0")
270 (match_operand:HI 2 "nonmemory_operand" "O,P,L,M,Ir,N,i")))
271 (clobber (match_scratch:BI 3 "=X,X,&y,&y,&y,&y,&y"))]
272 ""
273 "@
274 inc %0,%o2
275 dec %0,%O2
276 add Rx,%2
277 sub Rx,#%n2
278 add %0,%2
279 sub %0,#%n2
280 add %0,%2"
281 [(set_attr "length" "2,2,2,2,2,2,4")])
282
283; Reload can generate addition operations. The SECONDARY_RELOAD_CLASS
284; macro causes it to allocate the carry register; this pattern
285; shows it how to place the register in RTL to make the addition work.
286(define_expand "reload_inhi"
287 [(parallel [(set (match_operand:HI 0 "register_operand" "=r")
c6243b4c 288 (match_operand:HI 1 "xstormy16_carry_plus_operand" ""))
4b58290f
GK
289 (clobber (match_operand:BI 2 "" "=&y"))])]
290 ""
291 "if (! rtx_equal_p (operands[0], XEXP (operands[1], 0)))
292 {
293 emit_insn (gen_rtx_SET (VOIDmode, operands[0], XEXP (operands[1], 0)));
294 operands[1] = gen_rtx_PLUS (GET_MODE (operands[1]), operands[0],
295 XEXP (operands[1], 1));
296 }
297 ")
298
299(define_insn "addchi4"
300 [(set (match_operand:HI 0 "register_operand" "=T,r,r")
301 (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
302 (match_operand:HI 2 "nonmemory_operand" "L,Ir,i")))
303 (set (match_operand:BI 3 "register_operand" "=y,y,y")
304 (truncate:BI (lshiftrt:SI (plus:SI (zero_extend:SI (match_dup 1))
305 (zero_extend:SI (match_dup 2)))
306 (const_int 16))))]
307 ""
308 "@
309 add Rx,%2
310 add %0,%2
311 add %0,%2"
312 [(set_attr "length" "2,2,4")])
313
314(define_insn "addchi5"
315 [(set (match_operand:HI 0 "register_operand" "=T,r,r")
316 (plus:HI (plus:HI (match_operand:HI 1 "register_operand" "%0,0,0")
317 (zero_extend:HI (match_operand:BI 3
318 "register_operand"
319 "y,y,y")))
320 (match_operand:HI 2 "nonmemory_operand" "L,Ir,i")))
321 (set (match_operand:BI 4 "register_operand" "=y,y,y")
322 (truncate:BI (lshiftrt:SI (plus:SI (plus:SI
323 (zero_extend:SI (match_dup 1))
324 (zero_extend:SI (match_dup 3)))
325 (zero_extend:SI (match_dup 2)))
326 (const_int 16))))]
327 ""
328 "@
329 adc Rx,%2
330 adc %0,%2
331 adc %0,%2"
332 [(set_attr "length" "2,2,4")])
333
334;; Subtraction
335; Operand 3 is marked earlyclobber because that helps reload
336; to generate better code---this pattern will never need the
337; carry register as an input, and some output reloads or input
338; reloads might need to use it. In fact, without the '&' reload
339; will fail in some cases.
340(define_insn "subhi3"
341 [(set (match_operand:HI 0 "register_operand" "=r,r,T,T,r,r,r")
342 (minus:HI (match_operand:HI 1 "register_operand" "0,0,0,0,0,0,0")
343 (match_operand:HI 2 "nonmemory_operand" "O,P,L,M,rI,M,i")))
344 (clobber (match_scratch:BI 3 "=X,X,&y,&y,&y,&y,&y"))]
345 ""
346 "@
347 dec %0,%o2
348 inc %0,%O2
349 sub Rx,%2
350 add Rx,#%n2
351 sub %0,%2
352 add %0,#%n2
353 sub %0,%2"
354 [(set_attr "length" "2,2,2,2,2,2,4")])
355
356(define_insn "subchi4"
357 [(set (match_operand:HI 0 "register_operand" "=T,r,r")
358 (minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
359 (match_operand:HI 2 "nonmemory_operand" "L,Ir,i")))
360 (set (match_operand:BI 3 "register_operand" "=y,y,y")
361 (truncate:BI (lshiftrt:SI (minus:SI (zero_extend:SI (match_dup 1))
362 (zero_extend:SI (match_dup 2)))
363 (const_int 16))))]
364 ""
365 "@
366 sub Rx,%2
367 sub %0,%2
368 sub %0,%2"
369 [(set_attr "length" "2,2,4")])
370
371(define_insn "subchi5"
372 [(set (match_operand:HI 0 "register_operand" "=T,r,r")
373 (minus:HI (minus:HI (match_operand:HI 1 "register_operand" "0,0,0")
374 (zero_extend:HI (match_operand:BI 3
375 "register_operand"
376 "y,y,y")))
377 (match_operand:HI 2 "nonmemory_operand" "L,Ir,i")))
378 (set (match_operand:BI 4 "register_operand" "=y,y,y")
379 (truncate:BI (lshiftrt:SI (minus:SI (minus:SI
380 (zero_extend:SI (match_dup 1))
381 (zero_extend:SI (match_dup 3)))
382 (zero_extend:SI (match_dup 2)))
383 (const_int 16))))]
384 ""
385 "@
386 sbc Rx,%2
387 sbc %0,%2
388 sbc %0,%2"
389 [(set_attr "length" "2,2,4")])
390
391; Basic multiplication
392(define_insn "mulhi3"
393 [(set (match_operand:HI 0 "register_operand" "=a")
394 (mult:HI (match_operand:HI 1 "register_operand" "%a")
395 (match_operand:HI 2 "register_operand" "c")))
396 (clobber (match_scratch:HI 3 "=b"))
397 ]
398 ""
399 "mul"
400 [(set_attr "psw_operand" "nop")])
401
402;; Unsigned multiplication producing 64 bit results from 32 bit inputs
403; The constraint on operand 0 is 't' because it is actually two regs
404; long, and both regs must match the constraint.
405(define_insn "umulhisi3"
406 [(set (match_operand:SI 0 "register_operand" "=t")
407 (mult:SI (zero_extend:SI (match_operand:HI 1 "register_operand" "%a"))
408 (zero_extend:SI (match_operand:HI 2 "register_operand" "c"))))
409 ]
410 ""
411 "mul"
412 [(set_attr "psw_operand" "nop")])
413
414;; Unsigned division giving both quotient and remainder
415(define_insn "udivmodhi4"
416 [(set (match_operand:HI 0 "register_operand" "=a")
ed09481d
GK
417 (udiv:HI (match_operand:HI 1 "register_operand" "a")
418 (match_operand:HI 2 "register_operand" "c")))
4b58290f 419 (set (match_operand:HI 3 "register_operand" "=b")
ed09481d
GK
420 (umod:HI (match_dup 1)
421 (match_dup 2)))]
4b58290f
GK
422 ""
423 "div"
424 [(set_attr "psw_operand" "nop")])
425
426;; Negation
427
428(define_expand "neghi2"
429 [(set (match_operand:HI 0 "register_operand" "")
430 (not:HI (match_operand:HI 1 "register_operand" "")))
431 (parallel [(set (match_dup 0) (plus:HI (match_dup 0) (const_int 1)))
432 (clobber (match_scratch:BI 3 ""))])]
433 ""
434 "")
435
436\f
437;; ::::::::::::::::::::
438;; ::
439;; :: 16 bit Integer Shifts and Rotates
440;; ::
441;; ::::::::::::::::::::
442
443;; Arithmetic Shift Left
444(define_insn "ashlhi3"
445 [(set (match_operand:HI 0 "register_operand" "=r")
446 (ashift:HI (match_operand:HI 1 "register_operand" "0")
447 (match_operand:HI 2 "nonmemory_operand" "ri")))
448 (clobber (match_scratch:BI 3 "=y"))]
449 ""
450 "shl %0,%2")
451
452;; Arithmetic Shift Right
453(define_insn "ashrhi3"
454 [(set (match_operand:HI 0 "register_operand" "=r")
455 (ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
456 (match_operand:HI 2 "nonmemory_operand" "ri")))
457 (clobber (match_scratch:BI 3 "=y"))]
458 ""
459 "asr %0,%2")
460
461;; Logical Shift Right
462(define_insn "lshrhi3"
463 [(set (match_operand:HI 0 "register_operand" "=r")
464 (lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
465 (match_operand:HI 2 "nonmemory_operand" "ri")))
466 (clobber (match_scratch:BI 3 "=y"))]
467 ""
468 "shr %0,%2")
469
470\f
471;; ::::::::::::::::::::
472;; ::
473;; :: 16 Bit Integer Logical operations
474;; ::
475;; ::::::::::::::::::::
476
477;; Logical AND, 16 bit integers
478(define_insn "andhi3"
479 [(set (match_operand:HI 0 "register_operand" "=T,r,r,r")
480 (and:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
481 (match_operand:HI 2 "nonmemory_operand" "L,r,K,i")))]
482 ""
483 "@
484 and Rx,%2
485 and %0,%2
486 clr1 %0,%B2
487 and %0,%2"
488 [(set_attr "length" "2,2,2,4")])
489
490;; Inclusive OR, 16 bit integers
491(define_insn "iorhi3"
492 [(set (match_operand:HI 0 "register_operand" "=T,r,r,r")
493 (ior:HI (match_operand:HI 1 "register_operand" "%0,0,0,0")
494 (match_operand:HI 2 "nonmemory_operand" "L,r,J,i")))]
495 ""
496 "@
497 or Rx,%2
498 or %0,%2
499 set1 %0,%B2
500 or %0,%2"
501 [(set_attr "length" "2,2,2,4")])
502
503;; Exclusive OR, 16 bit integers
504(define_insn "xorhi3"
505 [(set (match_operand:HI 0 "register_operand" "=T,r,r")
506 (xor:HI (match_operand:HI 1 "register_operand" "%0,0,0")
507 (match_operand:HI 2 "nonmemory_operand" "L,r,i")))]
508 ""
509 "@
510 xor Rx,%2
511 xor %0,%2
512 xor %0,%2"
513 [(set_attr "length" "2,2,4")])
514
515;; One's complement, 16 bit integers
516(define_insn "one_cmplhi2"
517 [(set (match_operand:HI 0 "register_operand" "=r")
518 (not:HI (match_operand:HI 1 "register_operand" "0")))]
519 ""
520 "not %0")
521
522\f
523;; ::::::::::::::::::::
524;; ::
525;; :: 32 bit Integer arithmetic
526;; ::
527;; ::::::::::::::::::::
528
529;; Addition
530(define_insn_and_split "addsi3"
531 [(set (match_operand:SI 0 "register_operand" "=r")
532 (plus:SI (match_operand:SI 1 "register_operand" "%0")
533 (match_operand:SI 2 "nonmemory_operand" "ri")))
534 (clobber (match_scratch:BI 3 "=y"))]
535 ""
536 "#"
537 "reload_completed"
538 [(pc)]
c6243b4c 539 "{ xstormy16_expand_arith (SImode, PLUS, operands[0], operands[1],
4b58290f
GK
540 operands[2], operands[3]); DONE; } "
541 [(set_attr "length" "4")])
542
543;; Subtraction
544(define_insn_and_split "subsi3"
545 [(set (match_operand:SI 0 "register_operand" "=r")
546 (minus:SI (match_operand:SI 1 "register_operand" "0")
547 (match_operand:SI 2 "nonmemory_operand" "ri")))
548 (clobber (match_scratch:BI 3 "=y"))]
549 ""
550 "#"
551 "reload_completed"
552 [(pc)]
c6243b4c 553 "{ xstormy16_expand_arith (SImode, MINUS, operands[0], operands[1],
4b58290f
GK
554 operands[2], operands[3]); DONE; } "
555 [(set_attr "length" "4")])
556
557(define_expand "negsi2"
558 [(set (match_operand:SI 0 "register_operand" "")
559 (neg:SI (match_operand:SI 1 "register_operand" "")))]
560 ""
c6243b4c 561 "{ xstormy16_expand_arith (SImode, NEG, operands[0], const0_rtx,
4b58290f
GK
562 operands[1], gen_reg_rtx (BImode)); DONE; }")
563
564;; ::::::::::::::::::::
565;; ::
566;; :: 32 bit Integer Shifts and Rotates
567;; ::
568;; ::::::::::::::::::::
569
570;; Arithmetic Shift Left
571(define_expand "ashlsi3"
572 [(parallel [(set (match_operand:SI 0 "register_operand" "")
573 (ashift:SI (match_operand:SI 1 "register_operand" "")
574 (match_operand:SI 2 "const_int_operand" "")))
575 (clobber (match_dup 3))
576 (clobber (match_dup 4))])]
577 ""
578 " if (! const_int_operand (operands[2], SImode)) FAIL;
579 operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
580
581;; Arithmetic Shift Right
582(define_expand "ashrsi3"
583 [(parallel [(set (match_operand:SI 0 "register_operand" "")
584 (ashiftrt:SI (match_operand:SI 1 "register_operand" "")
585 (match_operand:SI 2 "const_int_operand" "")))
586 (clobber (match_dup 3))
587 (clobber (match_dup 4))])]
588 ""
589 " if (! const_int_operand (operands[2], SImode)) FAIL;
590 operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
591
592;; Logical Shift Right
593(define_expand "lshrsi3"
594 [(parallel [(set (match_operand:SI 0 "register_operand" "")
595 (lshiftrt:SI (match_operand:SI 1 "register_operand" "")
596 (match_operand:SI 2 "const_int_operand" "")))
597 (clobber (match_dup 3))
598 (clobber (match_dup 4))])]
599 ""
600 " if (! const_int_operand (operands[2], SImode)) FAIL;
601 operands[3] = gen_reg_rtx (BImode); operands[4] = gen_reg_rtx (HImode); ")
602
603(define_insn "*shiftsi"
604 [(set (match_operand:SI 0 "register_operand" "=r,r")
605 (match_operator:SI 5 "shift_operator"
606 [(match_operand:SI 1 "register_operand" "0,0")
607 (match_operand:SI 2 "const_int_operand" "U,n")]))
608 (clobber (match_operand:BI 3 "register_operand" "=y,y"))
609 (clobber (match_operand:HI 4 "" "=X,r"))]
610 ""
c6243b4c 611 "* return xstormy16_output_shift (SImode, GET_CODE (operands[5]),
4b58290f
GK
612 operands[0], operands[2], operands[4]);"
613 [(set_attr "length" "6,10")
614 (set_attr "psw_operand" "clobber,clobber")])
615
616\f
617;; ::::::::::::::::::::
618;; ::
619;; :: Comparisons
620;; ::
621;; ::::::::::::::::::::
622
623;; Note, we store the operands in the comparison insns, and use them later
624;; when generating the branch or scc operation.
625
626;; First the routines called by the machine independent part of the compiler
627(define_expand "cmphi"
628 [(set (cc0)
629 (compare (match_operand:HI 0 "register_operand" "")
630 (match_operand:HI 1 "nonmemory_operand" "")))]
631 ""
632 "
633{
c6243b4c
GK
634 xstormy16_compare_op0 = operands[0];
635 xstormy16_compare_op1 = operands[1];
4b58290f
GK
636 DONE;
637}")
638
639; There are no real SImode comparisons, but some can be emulated
640; by performing a SImode subtract and looking at the condition flags.
641(define_expand "cmpsi"
642 [(set (cc0)
643 (compare (match_operand:SI 0 "register_operand" "")
644 (match_operand:SI 1 "nonmemory_operand" "")))]
645 ""
646 "
647{
c6243b4c
GK
648 xstormy16_compare_op0 = operands[0];
649 xstormy16_compare_op1 = operands[1];
4b58290f
GK
650 DONE;
651}")
652
653\f
654;; ::::::::::::::::::::
655;; ::
656;; :: Branches
657;; ::
658;; ::::::::::::::::::::
659
660(define_expand "beq"
661 [(use (match_operand 0 "" ""))]
662 ""
c6243b4c 663 "{ xstormy16_emit_cbranch (EQ, operands[0]); DONE; }")
4b58290f
GK
664
665(define_expand "bne"
666 [(use (match_operand 0 "" ""))]
667 ""
c6243b4c 668 "{ xstormy16_emit_cbranch (NE, operands[0]); DONE; }")
4b58290f
GK
669
670(define_expand "bge"
671 [(use (match_operand 0 "" ""))]
672 ""
c6243b4c 673 "{ xstormy16_emit_cbranch (GE, operands[0]); DONE; }")
4b58290f
GK
674
675(define_expand "bgt"
676 [(use (match_operand 0 "" ""))]
677 ""
c6243b4c 678 "{ xstormy16_emit_cbranch (GT, operands[0]); DONE; }")
4b58290f
GK
679
680(define_expand "ble"
681 [(use (match_operand 0 "" ""))]
682 ""
c6243b4c 683 "{ xstormy16_emit_cbranch (LE, operands[0]); DONE; }")
4b58290f
GK
684
685(define_expand "blt"
686 [(use (match_operand 0 "" ""))]
687 ""
c6243b4c 688 "{ xstormy16_emit_cbranch (LT, operands[0]); DONE; }")
4b58290f
GK
689
690(define_expand "bgeu"
691 [(use (match_operand 0 "" ""))]
692 ""
c6243b4c 693 "{ xstormy16_emit_cbranch (GEU, operands[0]); DONE; }")
4b58290f
GK
694
695(define_expand "bgtu"
696 [(use (match_operand 0 "" ""))]
697 ""
c6243b4c 698 "{ xstormy16_emit_cbranch (GTU, operands[0]); DONE; }")
4b58290f
GK
699
700(define_expand "bleu"
701 [(use (match_operand 0 "" ""))]
702 ""
c6243b4c 703 "{ xstormy16_emit_cbranch (LEU, operands[0]); DONE; }")
4b58290f
GK
704
705(define_expand "bltu"
706 [(use (match_operand 0 "" ""))]
707 ""
c6243b4c 708 "{ xstormy16_emit_cbranch (LTU, operands[0]); DONE; }")
4b58290f
GK
709
710
711(define_insn "*cbranchhi"
712 [(set (pc)
713 (if_then_else (match_operator:HI 1 "comparison_operator"
714 [(match_operand:HI 2 "nonmemory_operand"
715 "r,e,L")
716 (match_operand:HI 3 "nonmemory_operand"
717 "r,L,e")])
718 (label_ref (match_operand 0 "" ""))
719 (pc)))
720 (clobber (match_operand:BI 4 "" "=&y,&y,&y"))]
721 ""
722 "*
723{
c6243b4c 724 return xstormy16_output_cbranch_hi (operands[1], \"%l0\", 0, insn);
4b58290f
GK
725}"
726 [(set_attr "branch_class" "bcc12")
727 (set_attr "psw_operand" "0,0,1")])
728
729(define_insn "*cbranchhi_neg"
730 [(set (pc)
731 (if_then_else (match_operator:HI 1 "comparison_operator"
732 [(match_operand:HI 2 "nonmemory_operand"
733 "r,e,L")
734 (match_operand:HI 3 "nonmemory_operand"
735 "r,L,e")])
736 (pc)
737 (label_ref (match_operand 0 "" ""))))
738 (clobber (match_operand:BI 4 "" "=&y,&y,&y"))]
739 ""
740 "*
741{
c6243b4c 742 return xstormy16_output_cbranch_hi (operands[1], \"%l0\", 1, insn);
4b58290f
GK
743}"
744 [(set_attr "branch_class" "bcc12")
745 (set_attr "psw_operand" "0,0,1")])
746
747(define_insn "*eqbranchsi"
748 [(set (pc)
749 (if_then_else (match_operator:SI 1 "equality_operator"
750 [(match_operand:SI 2 "register_operand"
751 "+r")
752 (const_int 0)])
753 (label_ref (match_operand 0 "" ""))
754 (pc)))
755;; Although I would greatly like the 'match_dup' in the following line
756;; to actually be a register constraint, there is (at the time of writing) no
757;; way for reload to insert an output reload on the edges out of a branch.
758;; If reload is fixed to use insert_insn_on_edge, this can be changed.
759 (clobber (match_dup 2))]
760 ""
761 "*
762{
c6243b4c 763 return xstormy16_output_cbranch_si (operands[1], \"%l0\", 0, insn);
4b58290f
GK
764}"
765 [(set_attr "branch_class" "bcc8p2")
766 (set_attr "psw_operand" "clobber")])
767
768(define_insn_and_split "*ineqbranchsi"
769 [(set (pc)
c6243b4c 770 (if_then_else (match_operator:SI 1 "xstormy16_ineqsi_operator"
4b58290f
GK
771 [(match_operand:SI 2 "register_operand"
772 "+r")
773 (match_operand:SI 3 "nonmemory_operand"
774 "ri")])
775 (label_ref (match_operand 0 "" ""))
776 (pc)))
777;; Although I would greatly like the 'match_dup' in the following line
778;; to actually be a register constraint, there is (at the time of writing) no
779;; way for reload to insert an output reload on the edges out of a branch.
780;; If reload is fixed to use insert_insn_on_edge, this can be changed,
781;; preferably to a 'minus' operand that explains the actual operation, like:
782; (set (match_operand 5 "register_operand" "=2")
783; (minus:SI (match_operand 6 "register_operand" "2")
784; (match_operand 7 "register_operand" "3")))
785 (clobber (match_dup 2))
786 (clobber (match_operand:BI 4 "" "=&y"))]
787 ""
788 "#"
789 "reload_completed"
790 [(pc)]
c6243b4c 791 "{ xstormy16_split_cbranch (SImode, operands[0], operands[1], operands[2],
4b58290f
GK
792 operands[4]); DONE; }"
793 [(set_attr "length" "8")])
794
795(define_insn "*ineqbranch_1"
796 [(set (pc)
c6243b4c 797 (if_then_else (match_operator:HI 5 "xstormy16_ineqsi_operator"
4b58290f
GK
798 [(minus:HI (match_operand:HI 1 "register_operand"
799 "T,r,r")
800 (zero_extend:HI (match_operand:BI 4
801 "register_operand"
802 "y,y,y")))
803 (match_operand:HI 3 "nonmemory_operand" "L,Ir,i")])
804 (label_ref (match_operand 0 "" ""))
805 (pc)))
806 (set (match_operand:HI 2 "register_operand" "=2,2,2")
807 (minus:HI (minus:HI (match_dup 1) (zero_extend:HI (match_dup 4)))
808 (match_dup 3)))
809 (clobber (match_operand:BI 6 "" "=y,y,y"))]
810 ""
811 "*
812{
c6243b4c 813 return xstormy16_output_cbranch_si (operands[5], \"%l0\", 0, insn);
4b58290f
GK
814}"
815 [(set_attr "branch_class" "bcc8p2,bcc8p2,bcc8p4")
816 (set_attr "psw_operand" "2,2,2")])
817
818\f
819;; ::::::::::::::::::::
820;; ::
821;; :: Call and branch instructions
822;; ::
823;; ::::::::::::::::::::
824
825;; Subroutine call instruction returning no value. Operand 0 is the function
826;; to call; operand 1 is the number of bytes of arguments pushed (in mode
827;; `SImode', except it is normally a `const_int'); operand 2 is the number of
828;; registers used as operands.
829
830;; On most machines, operand 2 is not actually stored into the RTL pattern. It
831;; is supplied for the sake of some RISC machines which need to put this
832;; information into the assembler code; they can put it in the RTL instead of
833;; operand 1.
834
835(define_expand "call"
836 [(call (match_operand:HI 0 "memory_operand" "m")
837 (match_operand 1 "" ""))
838 (use (match_operand 2 "immediate_operand" ""))]
839 ""
c6243b4c 840 "xstormy16_expand_call (NULL_RTX, operands[0], operands[1]); DONE;")
4b58290f
GK
841
842;; Subroutine call instruction returning a value. Operand 0 is the hard
843;; register in which the value is returned. There are three more operands, the
844;; same as the three operands of the `call' instruction (but with numbers
845;; increased by one).
846
847;; Subroutines that return `BLKmode' objects use the `call' insn.
848
849(define_expand "call_value"
850 [(set (match_operand 0 "register_operand" "=r")
851 (call (match_operand:HI 1 "memory_operand" "m")
852 (match_operand:SI 2 "" "")))
853 (use (match_operand 3 "immediate_operand" ""))]
854 ""
c6243b4c 855 "xstormy16_expand_call (operands[0], operands[1], operands[2]); DONE;")
4b58290f
GK
856
857(define_insn "*call_internal"
858 [(call (mem:HI (match_operand:HI 0 "nonmemory_operand" "i,r"))
859 (match_operand 1 "" ""))
da6e254e 860 (use (match_operand:HI 2 "nonmemory_operand" "X,z"))]
4b58290f
GK
861 ""
862 "@
863 callf %C0
864 call %2,%0"
865 [(set_attr "length" "4,2")
866 (set_attr "psw_operand" "clobber")])
867
868(define_insn "*call_value_internal"
869 [(set (match_operand 3 "register_operand" "=r,r")
870 (call (mem:HI (match_operand:HI 0 "nonmemory_operand" "i,r"))
871 (match_operand 1 "" "")))
da6e254e 872 (use (match_operand:HI 2 "nonmemory_operand" "X,z"))]
4b58290f
GK
873 ""
874 "@
875 callf %C0
876 call %2,%0"
877 [(set_attr "length" "4,2")
878 (set_attr "psw_operand" "clobber")])
879
880;; Subroutine return
881(define_expand "return"
882 [(return)]
883 "direct_return()"
884 "")
885
886(define_insn "return_internal"
887 [(return)]
888 ""
889 "ret"
890 [(set_attr "psw_operand" "nop")])
891
892(define_insn "return_internal_interrupt"
893 [(return)
894 (unspec_volatile [(const_int 0)] 1)]
895 ""
896 "iret"
897 [(set_attr "psw_operand" "clobber")])
898
899;; Normal unconditional jump
900(define_insn "jump"
901 [(set (pc) (label_ref (match_operand 0 "" "")))]
902 ""
903 "*
904{
c6243b4c 905 return xstormy16_output_cbranch_hi (NULL_RTX, \"%l0\", 0, insn);
4b58290f
GK
906}"
907 [(set_attr "branch_class" "br12")
908 (set_attr "psw_operand" "nop")])
909
910;; Indirect jump through a register
911(define_expand "indirect_jump"
912 [(set (match_dup 1) (const_int 0))
913 (parallel [(set (pc) (match_operand:HI 0 "register_operand" "r"))
914 (use (match_dup 1))])]
915 ""
916 "operands[1] = gen_reg_rtx (HImode);")
917
918(define_insn ""
919 [(set (pc) (match_operand:HI 0 "register_operand" "r"))
da6e254e 920 (use (match_operand:HI 1 "register_operand" "z"))]
4b58290f
GK
921 ""
922 "jmp %1,%0"
923 [(set_attr "length" "4")
924 (set_attr "psw_operand" "nop")])
925
926;; Table-based switch statements.
927(define_expand "casesi"
928 [(use (match_operand:SI 0 "register_operand" ""))
929 (use (match_operand:SI 1 "immediate_operand" ""))
930 (use (match_operand:SI 2 "immediate_operand" ""))
931 (use (label_ref (match_operand 3 "" "")))
932 (use (label_ref (match_operand 4 "" "")))]
933 ""
934 "
935{
c6243b4c 936 xstormy16_expand_casesi (operands[0], operands[1], operands[2],
4b58290f
GK
937 operands[3], operands[4]);
938 DONE;
939}")
940
941(define_insn "tablejump_pcrel"
3d8dd3c0
GK
942 [(set (pc) (mem:HI (plus:HI (pc)
943 (match_operand:HI 0 "register_operand" "r"))))
4b58290f
GK
944 (use (label_ref:SI (match_operand 1 "" "")))]
945 ""
946 "br %0"
947 [(set_attr "psw_operand" "nop")])
948
949\f
950;; ::::::::::::::::::::
951;; ::
952;; :: Prologue and Epilogue instructions
953;; ::
954;; ::::::::::::::::::::
955
41441dc7
NB
956;; Called after register allocation to add any instructions needed for
957;; the prologue. Using a prologue insn is favored compared to putting
958;; all of the instructions in the TARGET_ASM_FUNCTION_PROLOGUE macro,
959;; since it allows the scheduler to intermix instructions with the
960;; saves of the caller saved registers. In some cases, it might be
961;; necessary to emit a barrier instruction as the last insn to prevent
962;; such scheduling.
4b58290f
GK
963(define_expand "prologue"
964 [(const_int 1)]
965 ""
966 "
967{
c6243b4c 968 xstormy16_expand_prologue ();
4b58290f
GK
969 DONE;
970}")
971
41441dc7 972;; Called after register allocation to add any instructions needed for
e03f5d43 973;; the epilogue. Using an epilogue insn is favored compared to putting
41441dc7
NB
974;; all of the instructions in the TARGET_ASM_FUNCTION_EPILOGUE macro,
975;; since it allows the scheduler to intermix instructions with the
976;; restires of the caller saved registers. In some cases, it might be
977;; necessary to emit a barrier instruction as the first insn to
978;; prevent such scheduling.
4b58290f
GK
979(define_expand "epilogue"
980 [(const_int 2)]
981 ""
982 "
983{
c6243b4c 984 xstormy16_expand_epilogue ();
4b58290f
GK
985 DONE;
986}")
987
988\f
989;; ::::::::::::::::::::
990;; ::
991;; :: Miscellaneous instructions
992;; ::
993;; ::::::::::::::::::::
994
995;; No operation, needed in case the user uses -g but not -O.
996(define_insn "nop"
997 [(const_int 0)]
998 ""
999 "nop"
1000 [(set_attr "psw_operand" "nop")])
1001
1002;; Pseudo instruction that prevents the scheduler from moving code above this
1003;; point.
1004(define_insn "blockage"
1005 [(unspec_volatile [(const_int 0)] 0)]
1006 ""
1007 ""
1008 [(set_attr "length" "0")
1009 (set_attr "psw_operand" "nop")])
This page took 0.264121 seconds and 5 git commands to generate.