2015-05-22 Robert Dewar <dewar@adacore.com>
[official-gcc.git] / gcc / config / ft32 / ft32.md
blob68dc683023d3cd57b807570677313186f486cb3a
1 ;; Machine description for FT32
2 ;; Copyright (C) 2015 Free Software Foundation, Inc.
3 ;; Contributed by FTDI <support@ftdi.com>
5 ;; This file is part of GCC.
7 ;; GCC is free software; you can redistribute it and/or modify it
8 ;; under the terms of the GNU General Public License as published
9 ;; by the Free Software Foundation; either version 3, or (at your
10 ;; option) any later version.
12 ;; GCC is distributed in the hope that it will be useful, but WITHOUT
13 ;; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14 ;; or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public
15 ;; License for more details.
17 ;; You should have received a copy of the GNU General Public License
18 ;; along with GCC; see the file COPYING3.  If not see
19 ;; <http://www.gnu.org/licenses/>.
21 ;; -------------------------------------------------------------------------
22 ;; FT32 specific constraints, predicates and attributes
23 ;; -------------------------------------------------------------------------
25 (include "constraints.md")
26 (include "predicates.md")
28 (define_constants [
29   (FP_REG 0)
30   (SP_REG 1)
31   (CC_REG 35)
34 (define_c_enum "unspec"
35   [UNSPEC_STRLEN
36    UNSPEC_MOVMEM
37    UNSPEC_SETMEM
38    UNSPEC_STPCPY
39    UNSPEC_INDEX_JMP
40    UNSPEC_LPM
41    UNSPEC_FMUL
42    UNSPEC_FMULS
43    UNSPEC_FMULSU
44    UNSPEC_COPYSIGN
45    UNSPEC_IDENTITY
46    UNSPEC_INSERT_BITS
47    UNSPEC_JMP_EPILOG
48    UNSPEC_JMP_EPILOG24
49    UNSPEC_JMP_PROLOG
50    UNSPEC_XCHG
51    ])
53 ;; -------------------------------------------------------------------------
54 ;; nop instruction
55 ;; -------------------------------------------------------------------------
57 (define_insn "nop"
58   [(const_int 0)]
59   ""
60   "nop")
62 ;; -------------------------------------------------------------------------
63 ;; Arithmetic instructions
64 ;; -------------------------------------------------------------------------
66 (define_insn "addsi3"
67   [(set (match_operand:SI 0 "register_operand" "=r,r")
68           (plus:SI
69            (match_operand:SI 1 "register_operand" "r,r")
70            (match_operand:SI 2 "ft32_rimm_operand" "KA,r")))
71    ]
72   ""
73   "add.l  %0,%1,%2")
75 (define_insn "subsi3"
76   [(set (match_operand:SI 0 "register_operand" "=r,r")
77           (minus:SI
78            (match_operand:SI 1 "register_operand" "r,r")
79            (match_operand:SI 2 "ft32_rimm_operand" "KA,r")))]
80   ""
81   "sub.l  %0,%1,%2")
83 (define_insn "mulsi3"
84   [(set (match_operand:SI 0 "register_operand" "=r,r")
85           (mult:SI
86            (match_operand:SI 1 "register_operand" "r,r")
87            (match_operand:SI 2 "ft32_rimm_operand" "KA,r")))]
88   ""
89   "mul.l  %0,%1,%2")
91 (define_insn "umulsidi3"
92   [(set (match_operand:DI 0 "register_operand" "=r,r")
93     (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r,r"))
94          (zero_extend:DI (match_operand:SI 2 "ft32_rimm_operand" "r,KA"))))
95    (clobber (reg:CC CC_REG))]
96   ""
97   "mul.l  $cc,%1,%2\;muluh.l %h0,%1,%2\;move.l   %0,$cc")
99 (define_insn "divsi3"
100   [(set (match_operand:SI 0 "register_operand" "=r,r")
101           (div:SI
102            (match_operand:SI 1 "register_operand" "r,r")
103            (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))]
104   ""
105   "div.l  %0,%1,%2")
107 (define_insn "modsi3"
108   [(set (match_operand:SI 0 "register_operand" "=r,r")
109           (mod:SI
110            (match_operand:SI 1 "register_operand" "r,r")
111            (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))]
112   ""
113   "mod.l  %0,%1,%2")
115 (define_insn "udivsi3"
116   [(set (match_operand:SI 0 "register_operand" "=r,r")
117           (udiv:SI
118            (match_operand:SI 1 "register_operand" "r,r")
119            (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))]
120   ""
121   "udiv.l %0,%1,%2")
123 (define_insn "umodsi3"
124   [(set (match_operand:SI 0 "register_operand" "=r,r")
125           (umod:SI
126            (match_operand:SI 1 "register_operand" "r,r")
127            (match_operand:SI 2 "register_operand" "r,KA")))]
128   ""
129   "umod.l %0,%1,%2")
131 (define_insn "extvsi"
132   [(set (match_operand:SI 0 "register_operand" "=r")
133         (sign_extract:SI (match_operand:SI 1 "register_operand" "r")
134                       (match_operand:SI 2 "ft32_bwidth_operand" "b")
135                       (match_operand:SI 3 "const_int_operand" "i")))]
136   ""
137   "bexts.l %0,%1,((15 & %2) << 5) | (%3)")
139 (define_insn "extzvsi"
140   [(set (match_operand:SI 0 "register_operand" "=r")
141         (zero_extract:SI (match_operand:SI 1 "register_operand" "r")
142                       (match_operand:SI 2 "ft32_bwidth_operand" "b")
143                       (match_operand:SI 3 "const_int_operand" "i")))]
144   ""
145   "bextu.l %0,%1,((15 & %2) << 5) | (%3)")
147 (define_insn "insvsi"
148   [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+r,r")
149                          (match_operand:SI 1 "ft32_bwidth_operand" "b,b")
150                          (match_operand:SI 2 "const_int_operand" "i,i"))
151         (match_operand:SI 3 "general_operand" "r,O"))
152    (clobber (match_scratch:SI 4 "=&r,r"))]
153   ""
154   {
155     if (which_alternative == 0)
156       {
157         return \"ldl.l %4,%3,((%1&15)<<5)|(%2)\;bins.l %0,%0,%4\";
158       }
159     else
160       {
161         if ((INTVAL(operands[3]) == 0) || (INTVAL(operands[1]) == 1))
162           return \"bins.l %0,%0,(%3<<9)|((%1&15)<<5)|(%2)\";
163         else
164           return \"ldk.l %4,(%3<<10)|((%1&15)<<5)|(%2)\;bins.l %0,%0,%4\";
165       }
166   })
168 ;; -------------------------------------------------------------------------
169 ;; Unary arithmetic instructions
170 ;; -------------------------------------------------------------------------
172 (define_insn "one_cmplsi2"
173   [(set (match_operand:SI 0 "register_operand" "=r")
174         (not:SI (match_operand:SI 1 "register_operand" "r")))]
175   ""
176   "xor.l    %0,%1,-1")
178 ;; -------------------------------------------------------------------------
179 ;; Logical operators
180 ;; -------------------------------------------------------------------------
182 (define_insn "andsi3"
183   [(set (match_operand:SI 0 "register_operand" "=r,r,r")
184         (and:SI (match_operand:SI 1 "register_operand" "r,r,r")
185                 (match_operand:SI 2 "general_operand"  "r,x,KA")))]
186   ""
187   "@
188   and.l  %0,%1,%2
189   bins.l %0,%1,%g2
190   and.l  %0,%1,%2")
192 (define_insn "andqi3"
193   [(set (match_operand:QI 0 "register_operand" "=r,r,r")
194         (and:QI (match_operand:QI 1 "register_operand" "r,r,r")
195                 (match_operand:QI 2 "general_operand"  "r,x,KA")))]
196   ""
197   "@
198   and.b  %0,%1,%2
199   bins.b %0,%1,%g2
200   and.b  %0,%1,%2")
202 (define_insn "xorsi3"
203   [(set (match_operand:SI 0 "register_operand" "=r,r")
204         (xor:SI (match_operand:SI 1 "register_operand" "r,r")
205                 (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))]
206   ""
208   return "xor.l  %0,%1,%2";
211 (define_insn "iorsi3"
212   [(set (match_operand:SI 0 "register_operand" "=r,r,r")
213         (ior:SI (match_operand:SI 1 "register_operand" "r,r,r")
214                 (match_operand:SI 2 "general_operand"  "r,w,KA")))]
215   ""
216   "@
217   or.l   %0,%1,%2
218   bins.l %0,%1,%f2
219   or.l   %0,%1,%2")
221 ;; -------------------------------------------------------------------------
222 ;; Shifters
223 ;; -------------------------------------------------------------------------
225 (define_insn "ashlsi3"
226   [(set (match_operand:SI 0 "register_operand" "=r,r")
227         (ashift:SI (match_operand:SI 1 "register_operand" "r,r")
228                    (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))]
229   ""
231   return "ashl.l %0,%1,%2";
234 (define_insn "ashrsi3"
235   [(set (match_operand:SI 0 "register_operand" "=r,r")
236         (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
237                      (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))]
238   ""
240   return "ashr.l %0,%1,%2";
243 (define_insn "lshrsi3"
244   [(set (match_operand:SI 0 "register_operand" "=r,r")
245         (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
246                      (match_operand:SI 2 "ft32_rimm_operand" "r,KA")))]
247   ""
249   return "lshr.l %0,%1,%2";
252 ;; -------------------------------------------------------------------------
253 ;; Move instructions
254 ;; -------------------------------------------------------------------------
256 ;; SImode
258 ;; Push a register onto the stack
259 (define_insn "movsi_push"
260   [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
261         (match_operand:SI 0 "register_operand" "r"))]
262   ""
263   "push.l %0")
265 ;; Pop a register from the stack
266 (define_insn "movsi_pop"
267   [(set (match_operand:SI 0 "register_operand" "=r")
268         (mem:SI (post_inc:SI (reg:SI SP_REG))))]
269   ""
270   "pop.l  %0")
272 (define_expand "movsi"
273    [(set (match_operand:SI 0 "general_operand" "")
274         (match_operand:SI 1 "general_operand" ""))]
275    ""
277   /* If this is a store, force the value into a register.  */
278   if (!(reload_in_progress || reload_completed))
279     {
280       if (MEM_P (operands[0]))
281         {
282           operands[1] = force_reg (SImode, operands[1]);
283           if (MEM_P (XEXP (operands[0], 0)))
284             operands[0] = gen_rtx_MEM (SImode, force_reg (SImode, XEXP (operands[0], 0)));
285         }
286       else
287         {
288           if (MEM_P (operands[1]) && MEM_P (XEXP (operands[1], 0)))
289             operands[1] = gen_rtx_MEM (SImode, force_reg (SImode, XEXP (operands[1], 0)));
290         }
291       /*
292       if (MEM_P (operands[0])) {
293         rtx o = XEXP (operands[0], 0);
294         if (!REG_P(o) &&
295             !CONST_INT_P(o) &&
296             GET_CODE(o) != SYMBOL_REF &&
297             GET_CODE(o) != LABEL_REF) {
298           operands[0] = gen_rtx_MEM (SImode, force_reg (SImode, XEXP (operands[0], 0)));
299         }
300       }
301       */
302     }
305 (define_insn "*rtestsi"
306   [(set (reg:SI CC_REG)
307         (match_operand:SI 0 "register_operand" "r"))]
308   ""
309   "cmp.l  %0,0"
312 (define_insn "*rtestqi"
313   [(set (reg:QI CC_REG)
314         (match_operand:QI 0 "register_operand" "r"))]
315   ""
316   "cmp.b  %0,0"
319 (define_insn "*movsi"
320   [(set (match_operand:SI 0 "nonimmediate_operand"         "=r,BW,r,r,r,r,A,r,r")
321         (match_operand:SI 1 "ft32_general_movsrc_operand"   "r,r,BW,A,S,i,r,e,f"))]
322   "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)"
323   "@
324    move.l %0,%1
325    sti.l  %0,%1
326    ldi.l  %0,%1
327    lda.l  %0,%1
328    ldk.l  %0,%1
329    *return ft32_load_immediate(operands[0], INTVAL(operands[1]));
330    sta.l  %0,%1
331    lpm.l  %0,%1
332    lpmi.l %0,%1"
335 (define_expand "movqi"
336   [(set (match_operand:QI 0 "general_operand" "")
337         (match_operand:QI 1 "general_operand" ""))]
338   ""
340   /* If this is a store, force the value into a register.  */
341   if (!(reload_in_progress || reload_completed))
342     {
343       if (MEM_P (operands[0]))
344         {
345           operands[1] = force_reg (QImode, operands[1]);
346           if (MEM_P (XEXP (operands[0], 0)))
347             operands[0] = gen_rtx_MEM (QImode, force_reg (SImode, XEXP (operands[0], 0)));
348         }
349       else
350         {
351           if (MEM_P (operands[1]) && MEM_P (XEXP (operands[1], 0)))
352             operands[1] = gen_rtx_MEM (QImode, force_reg (SImode, XEXP (operands[1], 0)));
353         }
354       if (MEM_P (operands[0]) && !REG_P(XEXP (operands[0], 0)))
355         {
356           operands[0] = gen_rtx_MEM (QImode, force_reg (SImode, XEXP (operands[0], 0)));
357         }
358     }
361 (define_insn "zero_extendqisi2"
362   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r")
363     (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "BW,r,f")))]
364   ""
365   "@
366   ldi.b  %0,%1
367   and.l  %0,%1,255
368   lpmi.b %0,%1"
371 (define_insn "extendqisi2"
372   [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
373     (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r")))]
374   ""
375   "bexts.l %0,%1,(8<<5)|0"
378 (define_insn "zero_extendhisi2"
379   [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r")
380     (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "BW,r,f")))]
381   ""
382   "@
383   ldi.s  %0,%1
384   bextu.l %0,%1,(0<<5)|0
385   lpmi.s %0,%1"
388 (define_insn "extendhisi2"
389   [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
390     (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))]
391   ""
392   "bexts.l %0,%1,(0<<5)|0"
395 (define_insn "*movqi"
396   [(set (match_operand:QI 0 "nonimmediate_operand"           "=r,BW,r,r,A,r,r,r")
397         (match_operand:QI 1 "ft32_general_movsrc_operand"  "r,r,BW,A,r,I,e,f"))]
398   "register_operand (operands[0], QImode)
399    || register_operand (operands[1], QImode)"
400   "@
401    move.b %0,%1
402    sti.b  %0,%1
403    ldi.b  %0,%1
404    lda.b  %0,%1
405    sta.b  %0,%1
406    ldk.b  %0,%1
407    lpm.b  %0,%1
408    lpmi.b %0,%1"
411 (define_expand "movhi"
412   [(set (match_operand:HI 0 "general_operand" "")
413         (match_operand:HI 1 "general_operand" ""))]
414   ""
416   /* If this is a store, force the value into a register.  */
417   if (!(reload_in_progress || reload_completed))
418     {
419       if (MEM_P (operands[0]))
420         {
421           operands[1] = force_reg (HImode, operands[1]);
422           if (MEM_P (XEXP (operands[0], 0)))
423             operands[0] = gen_rtx_MEM (HImode, force_reg (SImode, XEXP (operands[0], 0)));
424         }
425       else
426         {
427           if (MEM_P (operands[1]) && MEM_P (XEXP (operands[1], 0)))
428             operands[1] = gen_rtx_MEM (HImode, force_reg (SImode, XEXP (operands[1], 0)));
429         }
430       if (MEM_P (operands[0]))
431         {
432           rtx o = XEXP (operands[0], 0);
433           if (!REG_P(o) &&
434               !CONST_INT_P(o) &&
435               GET_CODE(o) != SYMBOL_REF &&
436               GET_CODE(o) != LABEL_REF) {
437             operands[0] = gen_rtx_MEM (HImode, force_reg (SImode, XEXP (operands[0], 0)));
438           }
439         }
440     }
443 (define_insn "*movhi"
444   [(set (match_operand:HI 0 "nonimmediate_operand" "=r,BW,r,r,A,r,r,r")
445         (match_operand:HI 1 "ft32_general_movsrc_operand"  "r,r,BW,A,r,I,e,f"))]
446   "(register_operand (operands[0], HImode)
447     || register_operand (operands[1], HImode))"
448   "@
449    move.s %0,%1
450    sti.s  %0,%1
451    ldi.s  %0,%1
452    lda.s  %0,%1
453    sta.s  %0,%1
454    ldk.s  %0,%1
455    lpm.s  %0,%1
456    lpmi.s %0,%1"
459 (define_expand "movsf"
460   [(set (match_operand:SF 0 "general_operand" "")
461         (match_operand:SF 1 "general_operand" ""))]
462   ""
464   /* If this is a store, force the value into a register.  */
465   if (MEM_P (operands[0]))
466     operands[1] = force_reg (SFmode, operands[1]);
467   if (CONST_DOUBLE_P(operands[1]))
468     operands[1] = force_const_mem(SFmode, operands[1]);
471 (define_insn "*movsf"
472   [(set (match_operand:SF 0 "nonimmediate_operand" "=r,BW,r,r,A,r,r")
473         (match_operand:SF 1 "ft32_general_movsrc_operand"  "r,r,BW,A,r,I,f"))]
474   "(register_operand (operands[0], SFmode)
475     || register_operand (operands[1], SFmode))"
476   "@
477    move.l %0,%1
478    sti.l  %0,%1
479    ldi.l  %0,%1
480    lda.l  %0,%1
481    sta.l  %0,%1
482    ldk.l  %0,%1
483    lpmi.l %0,%1"
486 ;; -------------------------------------------------------------------------
487 ;; Compare instructions
488 ;; -------------------------------------------------------------------------
490 (define_expand "cbranchsi4"
491   [(set (reg:CC CC_REG)
492         (compare:CC
493          (match_operand:SI 1 "register_operand" "")
494          (match_operand:SI 2 "ft32_rimm_operand" "")))
495    (set (pc)
496         (if_then_else (match_operator 0 "comparison_operator"
497                        [(reg:CC CC_REG) (const_int 0)])
498                       (label_ref (match_operand 3 "" ""))
499                       (pc)))]
500   ""
501   "")
503 (define_insn "cmpsi"
504   [(set (reg:CC CC_REG)
505         (compare:CC
506          (match_operand:SI 0 "register_operand" "r,r")
507          (match_operand:SI 1 "ft32_rimm_operand" "r,KA")))]
508   ""
509   "cmp.l  %0,%1")
511 (define_insn ""
512   [(set (pc)
513         (if_then_else
514          (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
515                               (const_int 1)
516                               (match_operand:SI 1 "const_int_operand" "i"))
517              (const_int 0))
518          (label_ref (match_operand 2 "" ""))
519          (pc)))
520    (clobber (reg:CC CC_REG))]
521   ""
522   "btst.l %0,(1<<5)|%1\;jmpc   nz,%l2")
524 (define_insn ""
525   [(set (pc)
526         (if_then_else
527          (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
528                               (const_int 1)
529                               (match_operand:SI 1 "const_int_operand" "i"))
530              (const_int 0))
531          (label_ref (match_operand 2 "" ""))
532          (pc)))
533    (clobber (reg:CC CC_REG))]
534   ""
535   "btst.l %0,(1<<5)|%1\;jmpc   z,%l2")
537 (define_expand "cbranchqi4"
538   [(set (reg:CC CC_REG)
539         (compare:CC
540          (match_operand:QI 1 "register_operand" "")
541          (match_operand:QI 2 "ft32_rimm_operand" "")))
542    (set (pc)
543         (if_then_else (match_operator 0 "comparison_operator"
544                        [(reg:CC CC_REG) (const_int 0)])
545                       (label_ref (match_operand 3 "" ""))
546                       (pc)))]
547   ""
548   "")
550 (define_insn "*cmpqi"
551   [(set (reg:CC CC_REG)
552         (compare:CC
553          (match_operand:QI 0 "register_operand" "r,r")
554          (match_operand:QI 1 "ft32_rimm_operand" "r,KA")))]
555   ""
556   "cmp.b  %0,%1")
558 ;; -------------------------------------------------------------------------
559 ;; Branch instructions
560 ;; -------------------------------------------------------------------------
562 (define_code_iterator cond [ne eq lt ltu gt gtu ge le geu leu])
563 (define_code_attr CC [(ne "nz") (eq "z") (lt "lt") (ltu "b")
564                       (gt "gt") (gtu "a") (ge "gte") (le "lte")
565                       (geu "ae") (leu "be") ])
566 (define_code_attr rCC [(ne "z") (eq "nz") (lt "gte") (ltu "ae")
567                        (gt "lte") (gtu "be") (ge "lt") (le "gt")
568                        (geu "b") (leu "a") ])
570 (define_insn "*b<cond:code>"
571   [(set (pc)
572         (if_then_else (cond (reg:CC CC_REG)
573                             (const_int 0))
574                       (label_ref (match_operand 0 "" ""))
575                       (pc)))]
576   ""
578   return "jmpc   <CC>,%l0";
582 (define_expand "cstoresi4"
583   [(set (reg:CC CC_REG)
584         (compare:CC (match_operand:SI 2 "register_operand" "r,r")
585                     (match_operand:SI 3 "ft32_rimm_operand" "r,KA")))
586    (set (match_operand:SI 0 "register_operand")
587         (match_operator:SI 1 "ordered_comparison_operator"
588         [(reg:CC CC_REG) (const_int 0)]))]
589   ""
591   rtx test;
593   switch (GET_CODE (operands[1])) {
594   case NE:
595   case GEU:
596   case LT:
597   case LE:
598   case LEU:
599     test = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])),
600                      SImode, operands[2], operands[3]);
601     emit_insn(gen_cstoresi4(operands[0], test, operands[2], operands[3]));
602     emit_insn(gen_xorsi3(operands[0], operands[0], gen_int_mode(1, SImode)));
603     DONE;
604   default:
605     ;
606   }
609 (define_insn "*seq"
610   [(set (match_operand:SI 0 "register_operand" "=r")
611         (eq:SI (reg CC_REG) (const_int 0)))]
612   ""
613   "bextu.l %0,$cc,32|0"
616 (define_insn "*sltu"
617   [(set (match_operand:SI 0 "register_operand" "=r")
618         (ltu:SI (reg CC_REG) (const_int 0)))]
619   ""
620   "bextu.l %0,$cc,32|1"
623 (define_insn "*sge"
624   [(set (match_operand:SI 0 "register_operand" "=r")
625         (ge:SI (reg CC_REG) (const_int 0)))]
626   ""
627   "bextu.l %0,$cc,32|4"
630 (define_insn "*sgt"
631   [(set (match_operand:SI 0 "register_operand" "=r")
632         (gt:SI (reg CC_REG) (const_int 0)))]
633   ""
634   "bextu.l %0,$cc,32|5"
637 (define_insn "*sgtu"
638   [(set (match_operand:SI 0 "register_operand" "=r")
639         (gtu:SI (reg CC_REG) (const_int 0)))]
640   ""
641   "bextu.l %0,$cc,32|6"
644 ;; -------------------------------------------------------------------------
645 ;; Call and Jump instructions
646 ;; -------------------------------------------------------------------------
648 (define_expand "call"
649   [(call (match_operand:QI 0 "memory_operand" "")
650                 (match_operand 1 "general_operand" ""))]
651   ""
653   gcc_assert (MEM_P (operands[0]));
656 (define_insn "*call"
657   [(call (mem:QI (match_operand:SI
658                   0 "nonmemory_operand" "i,r"))
659          (match_operand 1 "" ""))]
660   ""
661   "@
662    call   %0
663    calli  %0"
666 (define_expand "call_value"
667   [(set (match_operand 0 "" "")
668                 (call (match_operand:QI 1 "memory_operand" "")
669                  (match_operand 2 "" "")))]
670   ""
672   gcc_assert (MEM_P (operands[1]));
675 (define_insn "*call_value"
676   [(set (match_operand 0 "register_operand" "=r")
677         (call (mem:QI (match_operand:SI
678                        1 "immediate_operand" "i"))
679               (match_operand 2 "" "")))]
680   ""
681   "call   %1"
684 (define_insn "*call_value_indirect"
685   [(set (match_operand 0 "register_operand" "=r")
686         (call (mem:QI (match_operand:SI
687                        1 "register_operand" "r"))
688               (match_operand 2 "" "")))]
689   ""
690   "calli  %1"
693 (define_insn "indirect_jump"
694   [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "r"))]
695   ""
696   "jmpi   %0")
698 (define_insn "jump"
699   [(set (pc)
700         (label_ref (match_operand 0 "" "")))]
701   ""
702   "jmp    %l0"
705 (define_insn "call_prolog"
706   [(unspec:SI [(match_operand 0 "" "")]
707                    UNSPEC_JMP_PROLOG)]
708   ""
709   "call   __prolog_%0"
712 (define_insn "jump_epilog"
713   [(unspec:SI [(match_operand 0 "" "")]
714                    UNSPEC_JMP_EPILOG)]
715   ""
716   "jmp    __epilog_%0"
719 (define_insn "jump_epilog24"
720   [(unspec:SI [(match_operand 0 "" "")]
721                    UNSPEC_JMP_EPILOG24)]
722   ""
723   "jmp    __epilog24_%0"
727 ;; Subroutines of "casesi".
728 ;; operand 0 is index
729 ;; operand 1 is the minimum bound
730 ;; operand 2 is the maximum bound - minimum bound + 1
731 ;; operand 3 is CODE_LABEL for the table;
732 ;; operand 4 is the CODE_LABEL to go to if index out of range.
734 (define_expand "casesi"
735   [(match_operand:SI 0 "general_operand" "")
736    (match_operand:SI 1 "const_int_operand" "")
737    (match_operand:SI 2 "const_int_operand" "")
738    (match_operand 3 "" "")
739    (match_operand 4 "" "")]
740   ""
741   "
743   if (GET_CODE (operands[0]) != REG)
744     operands[0] = force_reg (SImode, operands[0]);
746   if (operands[1] != const0_rtx)
747     {
748       rtx index = gen_reg_rtx (SImode);
749       rtx offset = gen_reg_rtx (SImode);
751       emit_insn (gen_movsi (offset, operands[1]));
752       emit_insn (gen_subsi3 (index, operands[0], offset));
753       operands[0] = index;
754     }
756   {
757     rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[2]);
758     emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], operands[4]));
759   }
761   emit_jump_insn (gen_casesi0 (operands[0], operands[3]));
762   DONE;
765 (define_insn "casesi0"
766   [(set (pc) (mem:SI (plus:SI
767                        (mult:SI (match_operand:SI 0 "register_operand" "r")
768                                 (const_int 4))
769                        (label_ref (match_operand 1 "" "")))))
770    (clobber (match_scratch:SI 2 "=&r"))
771   ]
772   ""
773   "ldk.l\t$cc,%l1\;ashl.l\t%2,%0,2\;add.l\t%2,%2,$cc\;jmpi\t%2"
774   )
776 ;; -------------------------------------------------------------------------
777 ;; Atomic exchange instruction
778 ;; -------------------------------------------------------------------------
780 (define_insn "atomic_exchangesi"
781   [(set (match_operand:SI 0 "register_operand" "=&r,r") ;; output
782         (match_operand:SI 1 "memory_operand" "+BW,A"))  ;; memory
783    (set (match_dup 1)
784         (unspec:SI
785           [(match_operand:SI 2 "register_operand" "0,0")        ;; input
786            (match_operand:SI 3 "const_int_operand")]            ;; model
787           UNSPEC_XCHG))]
788   ""
789   "@
790    exi.l  %0,%1
791    exa.l  %0,%1")
793 (define_insn "atomic_exchangehi"
794   [(set (match_operand:HI 0 "register_operand" "=&r,r") ;; output
795         (match_operand:HI 1 "memory_operand" "+BW,A"))  ;; memory
796    (set (match_dup 1)
797         (unspec:HI
798           [(match_operand:HI 2 "register_operand" "0,0")        ;; input
799            (match_operand:HI 3 "const_int_operand")]            ;; model
800           UNSPEC_XCHG))]
801   ""
802   "@
803    exi.s  %0,%1
804    exa.s  %0,%1")
806 (define_insn "atomic_exchangeqi"
807   [(set (match_operand:QI 0 "register_operand" "=&r,r") ;; output
808         (match_operand:QI 1 "memory_operand" "+BW,A"))  ;; memory
809    (set (match_dup 1)
810         (unspec:QI
811           [(match_operand:QI 2 "register_operand" "0,0")        ;; input
812            (match_operand:QI 3 "const_int_operand")]            ;; model
813           UNSPEC_XCHG))]
814   ""
815   "@
816    exi.b  %0,%1
817    exa.b  %0,%1")
819 ;; -------------------------------------------------------------------------
820 ;; String instructions
821 ;; -------------------------------------------------------------------------
823 (define_insn "cmpstrsi"
824   [(set (match_operand:SI 0 "register_operand" "=r,r")
825         (compare:SI (match_operand:BLK 1 "memory_operand" "W,BW")
826                     (match_operand:BLK 2 "memory_operand" "W,BW")))
827    (clobber (match_operand:SI 3))
828    ]
829   ""
830   "strcmp.%d3 %0,%b1,%b2"
833 (define_insn "movstr"
834 [(set (match_operand:BLK 1 "memory_operand" "=W")
835       (match_operand:BLK 2 "memory_operand" "W"))
836       (use (match_operand:SI 0))
837       (clobber (match_dup 0))
840 "stpcpy %b1,%b2 # %0 %b1 %b2"
843 (define_insn "movmemsi"
844   [(set (match_operand:BLK 0 "memory_operand" "=W,W,BW")
845         (match_operand:BLK 1 "memory_operand" "W,W,BW"))
846         (use (match_operand:SI 2 "ft32_rimm_operand" "r,KA,rKA"))
847         (use (match_operand:SI 3))
848    ]
849   ""
850   "memcpy.%d3 %b0,%b1,%2 # %3!"
853 (define_insn "setmemsi"
854   [(set (match_operand:BLK 0 "memory_operand" "=BW,BW") (unspec:BLK [
855      (use (match_operand:QI 2 "register_operand" "r,r"))
856      (use (match_operand:SI 1 "ft32_rimm_operand" "r,KA"))
857    ] UNSPEC_SETMEM))
858    (use (match_operand:SI 3))
859    ]
860   ""
861   "memset.%d3 %b0,%2,%1"
864 (define_insn "strlensi"
865   [(set (match_operand:SI 0 "register_operand" "=r")
866         (unspec:SI [(match_operand:BLK 1 "memory_operand" "W")
867                     (match_operand:QI 2 "const_int_operand" "")
868                     (match_operand:SI 3 "ft32_rimm_operand" "")]
869                    UNSPEC_STRLEN))]
870   ""
871   "strlen.%d3 %0,%b1 # %2 %3"
874 ;; -------------------------------------------------------------------------
875 ;; Prologue & Epilogue
876 ;; -------------------------------------------------------------------------
878 (define_expand "prologue"
879   [(clobber (const_int 0))]
880   ""
882   extern void ft32_expand_prologue();
883   ft32_expand_prologue ();
884   DONE;
887 (define_expand "epilogue"
888   [(return)]
889   ""
891   extern void ft32_expand_epilogue();
892   ft32_expand_epilogue ();
893   DONE;
896 (define_insn "link"
897   [
898 ;;   (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
899 ;;        (reg:SI FP_REG))
900    (set (match_operand:SI 0)
901         (reg:SI SP_REG))
902    (set (reg:SI SP_REG)
903         (plus:SI (reg:SI SP_REG)
904                  (match_operand:SI 1 "general_operand" "L")))]
905   ""
906   "link   %0,%m1"
909 (define_insn "unlink"
910   [(set (reg:SI FP_REG)
911         (mem:SI (reg:SI FP_REG)))
912    (set (reg:SI SP_REG)
913         (plus:SI (reg:SI FP_REG)
914                  (const_int 4)))]
915   ""
916   "unlink $r29"
919 (define_insn "returner"
920   [(return)]
921   "reload_completed"
922   "return")
924 (define_insn "returner24"
925   [
926   (set (reg:SI SP_REG)
927           (plus:SI
928            (reg:SI SP_REG)
929            (const_int 24)))
930   (return)]
931   ""
932   "jmp    __epilog24")