1;; Machine description for FT32
2;; Copyright (C) 2015-2020 Free Software Foundation, Inc.
3;; Contributed by FTDI <support@ftdi.com>
4
5;; This file is part of GCC.
6
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.
11
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.
16
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/>.
20
21;; -------------------------------------------------------------------------
22;; FT32 specific constraints, predicates and attributes
23;; -------------------------------------------------------------------------
24
25(include "constraints.md")
26(include "predicates.md")
27
28(define_constants [
29  (FP_REG 0)
30  (SP_REG 1)
31  (CC_REG 35)
32])
33
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   ])
52
53;; -------------------------------------------------------------------------
54;; nop instruction
55;; -------------------------------------------------------------------------
56
57(define_insn "nop"
58  [(const_int 0)]
59  ""
60  "nop")
61
62;; -------------------------------------------------------------------------
63;; Arithmetic instructions
64;; -------------------------------------------------------------------------
65
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")
74
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")
82
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")
90
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")
98
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  "!TARGET_NODIV"
105  "div.l  %0,%1,%2")
106
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  "!TARGET_NODIV"
113  "mod.l  %0,%1,%2")
114
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  "!TARGET_NODIV"
121  "udiv.l %0,%1,%2")
122
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  "!TARGET_NODIV"
129  "umod.l %0,%1,%2")
130
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)")
138
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)")
146
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  })
167
168;; -------------------------------------------------------------------------
169;; Unary arithmetic instructions
170;; -------------------------------------------------------------------------
171
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")
177
178;; -------------------------------------------------------------------------
179;; Logical operators
180;; -------------------------------------------------------------------------
181
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")
191
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")
201
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  ""
207{
208  return "xor.l  %0,%1,%2";
209})
210
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")
220
221;; -------------------------------------------------------------------------
222;; Shifters
223;; -------------------------------------------------------------------------
224
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  ""
230{
231  return "ashl.l %0,%1,%2";
232})
233
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  ""
239{
240  return "ashr.l %0,%1,%2";
241})
242
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  ""
248{
249  return "lshr.l %0,%1,%2";
250})
251
252;; -------------------------------------------------------------------------
253;; Move instructions
254;; -------------------------------------------------------------------------
255
256;; SImode
257
258(define_insn "*sne"
259   [(set (match_operand:SI 0 "register_operand" "=r")
260         (reg:SI CC_REG))]
261   ""
262   "bextu.l %0,$cc,32|0\;xor.l %0,%0,-1"
263)
264
265;; Push a register onto the stack
266(define_insn "movsi_push"
267  [(set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
268        (match_operand:SI 0 "register_operand" "r"))]
269  ""
270  "push.l %0")
271
272;; Pop a register from the stack
273(define_insn "movsi_pop"
274  [(set (match_operand:SI 0 "register_operand" "=r")
275        (mem:SI (post_inc:SI (reg:SI SP_REG))))]
276  ""
277  "pop.l  %0")
278
279(define_expand "movsi"
280   [(set (match_operand:SI 0 "general_operand" "")
281        (match_operand:SI 1 "general_operand" ""))]
282   ""
283{
284  /* If this is a store, force the value into a register.  */
285  if (!(reload_in_progress || reload_completed))
286    {
287      if (MEM_P (operands[0]))
288        {
289          operands[1] = force_reg (SImode, operands[1]);
290          if (MEM_P (XEXP (operands[0], 0)))
291            operands[0] = gen_rtx_MEM (SImode, force_reg (SImode, XEXP (operands[0], 0)));
292        }
293      else
294        {
295          if (MEM_P (operands[1]) && MEM_P (XEXP (operands[1], 0)))
296            operands[1] = gen_rtx_MEM (SImode, force_reg (SImode, XEXP (operands[1], 0)));
297        }
298      /*
299      if (MEM_P (operands[0])) {
300        rtx o = XEXP (operands[0], 0);
301        if (!REG_P(o) &&
302            !CONST_INT_P(o) &&
303            GET_CODE(o) != SYMBOL_REF &&
304            GET_CODE(o) != LABEL_REF) {
305          operands[0] = gen_rtx_MEM (SImode, force_reg (SImode, XEXP (operands[0], 0)));
306        }
307      }
308      */
309    }
310})
311
312(define_insn "*rtestsi"
313  [(set (reg:SI CC_REG)
314        (match_operand:SI 0 "register_operand" "r"))]
315  ""
316  "cmp.l  %0,0"
317)
318
319(define_insn "*rtestqi"
320  [(set (reg:QI CC_REG)
321        (match_operand:QI 0 "register_operand" "r"))]
322  ""
323  "cmp.b  %0,0"
324)
325
326(define_insn "*movsi"
327  [(set (match_operand:SI 0 "nonimmediate_operand"         "=r,BW,r,r,r,r,A,r,r")
328        (match_operand:SI 1 "ft32_general_movsrc_operand"   "r,r,BW,A,S,i,r,e,f"))]
329  "register_operand (operands[0], SImode) || register_operand (operands[1], SImode)"
330  "@
331   move.l %0,%1
332   sti.l  %0,%1
333   ldi.l  %0,%1
334   lda.l  %0,%1
335   ldk.l  %0,%1
336   *return ft32_load_immediate(operands[0], INTVAL(operands[1]));
337   sta.l  %0,%1
338   lpm.l  %0,%1
339   lpmi.l %0,%1"
340)
341
342(define_expand "movqi"
343  [(set (match_operand:QI 0 "general_operand" "")
344        (match_operand:QI 1 "general_operand" ""))]
345  ""
346{
347  /* If this is a store, force the value into a register.  */
348  if (!(reload_in_progress || reload_completed))
349    {
350      if (MEM_P (operands[0]))
351        {
352          operands[1] = force_reg (QImode, operands[1]);
353          if (MEM_P (XEXP (operands[0], 0)))
354            operands[0] = gen_rtx_MEM (QImode, force_reg (SImode, XEXP (operands[0], 0)));
355        }
356      else
357        {
358          if (MEM_P (operands[1]) && MEM_P (XEXP (operands[1], 0)))
359            operands[1] = gen_rtx_MEM (QImode, force_reg (SImode, XEXP (operands[1], 0)));
360        }
361      if (MEM_P (operands[0]) && !REG_P(XEXP (operands[0], 0)))
362        {
363          operands[0] = gen_rtx_MEM (QImode, force_reg (SImode, XEXP (operands[0], 0)));
364        }
365    }
366})
367
368(define_insn "zero_extendqisi2"
369  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r")
370    (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "BW,r,f")))]
371  ""
372  "@
373  ldi.b  %0,%1
374  and.l  %0,%1,255
375  lpmi.b %0,%1"
376)
377
378(define_insn "extendqisi2"
379  [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
380    (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r")))]
381  ""
382  "bexts.l %0,%1,(8<<5)|0"
383)
384
385(define_insn "zero_extendhisi2"
386  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r,r")
387    (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "BW,r,f")))]
388  ""
389  "@
390  ldi.s  %0,%1
391  bextu.l %0,%1,(0<<5)|0
392  lpmi.s %0,%1"
393)
394
395(define_insn "extendhisi2"
396  [(set (match_operand:SI 0 "nonimmediate_operand" "=r")
397    (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r")))]
398  ""
399  "bexts.l %0,%1,(0<<5)|0"
400)
401
402(define_insn "*movqi"
403  [(set (match_operand:QI 0 "nonimmediate_operand"           "=r,BW,r,r,A,r,r,r")
404        (match_operand:QI 1 "ft32_general_movsrc_operand"  "r,r,BW,A,r,I,e,f"))]
405  "register_operand (operands[0], QImode)
406   || register_operand (operands[1], QImode)"
407  "@
408   move.b %0,%1
409   sti.b  %0,%1
410   ldi.b  %0,%1
411   lda.b  %0,%1
412   sta.b  %0,%1
413   ldk.b  %0,%1
414   lpm.b  %0,%1
415   lpmi.b %0,%1"
416)
417
418(define_expand "movhi"
419  [(set (match_operand:HI 0 "general_operand" "")
420        (match_operand:HI 1 "general_operand" ""))]
421  ""
422{
423  /* If this is a store, force the value into a register.  */
424  if (!(reload_in_progress || reload_completed))
425    {
426      if (MEM_P (operands[0]))
427        {
428          operands[1] = force_reg (HImode, operands[1]);
429          if (MEM_P (XEXP (operands[0], 0)))
430            operands[0] = gen_rtx_MEM (HImode, force_reg (SImode, XEXP (operands[0], 0)));
431        }
432      else
433        {
434          if (MEM_P (operands[1]) && MEM_P (XEXP (operands[1], 0)))
435            operands[1] = gen_rtx_MEM (HImode, force_reg (SImode, XEXP (operands[1], 0)));
436        }
437      if (MEM_P (operands[0]))
438        {
439          rtx o = XEXP (operands[0], 0);
440          if (!REG_P(o) &&
441              !CONST_INT_P(o) &&
442              GET_CODE(o) != SYMBOL_REF &&
443              GET_CODE(o) != LABEL_REF) {
444            operands[0] = gen_rtx_MEM (HImode, force_reg (SImode, XEXP (operands[0], 0)));
445          }
446        }
447    }
448})
449
450(define_insn "*movhi"
451  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,BW,r,r,A,r,r,r")
452        (match_operand:HI 1 "ft32_general_movsrc_operand"  "r,r,BW,A,r,I,e,f"))]
453  "(register_operand (operands[0], HImode)
454    || register_operand (operands[1], HImode))"
455  "@
456   move.s %0,%1
457   sti.s  %0,%1
458   ldi.s  %0,%1
459   lda.s  %0,%1
460   sta.s  %0,%1
461   ldk.s  %0,%1
462   lpm.s  %0,%1
463   lpmi.s %0,%1"
464)
465
466(define_expand "movsf"
467  [(set (match_operand:SF 0 "general_operand" "")
468        (match_operand:SF 1 "general_operand" ""))]
469  ""
470{
471  /* If this is a store, force the value into a register.  */
472  if (MEM_P (operands[0]))
473    operands[1] = force_reg (SFmode, operands[1]);
474  if (CONST_DOUBLE_P(operands[1]))
475    operands[1] = force_const_mem(SFmode, operands[1]);
476})
477
478(define_insn "*movsf"
479  [(set (match_operand:SF 0 "nonimmediate_operand" "=r,BW,r,r,A,r,r")
480        (match_operand:SF 1 "ft32_general_movsrc_operand"  "r,r,BW,A,r,I,f"))]
481  "(register_operand (operands[0], SFmode)
482    || register_operand (operands[1], SFmode))"
483  "@
484   move.l %0,%1
485   sti.l  %0,%1
486   ldi.l  %0,%1
487   lda.l  %0,%1
488   sta.l  %0,%1
489   ldk.l  %0,%1
490   lpmi.l %0,%1"
491)
492
493;; -------------------------------------------------------------------------
494;; Compare instructions
495;; -------------------------------------------------------------------------
496
497(define_expand "cbranchsi4"
498  [(set (reg:CC CC_REG)
499        (compare:CC
500         (match_operand:SI 1 "register_operand" "")
501         (match_operand:SI 2 "ft32_rimm_operand" "")))
502   (set (pc)
503        (if_then_else (match_operator 0 "comparison_operator"
504                       [(reg:CC CC_REG) (const_int 0)])
505                      (label_ref (match_operand 3 "" ""))
506                      (pc)))]
507  ""
508  "")
509
510(define_insn "cmpsi"
511  [(set (reg:CC CC_REG)
512        (compare:CC
513         (match_operand:SI 0 "register_operand" "r,r")
514         (match_operand:SI 1 "ft32_rimm_operand" "r,KA")))]
515  ""
516  "cmp.l  %0,%1")
517
518(define_insn ""
519  [(set (pc)
520	(if_then_else
521	 (ne (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
522			      (const_int 1)
523			      (match_operand:SI 1 "const_int_operand" "i"))
524	     (const_int 0))
525	 (label_ref (match_operand 2 "" ""))
526	 (pc)))
527   (clobber (reg:CC CC_REG))]
528  ""
529  "btst.l %0,(1<<5)|%1\;jmpc   nz,%l2")
530
531(define_insn ""
532  [(set (pc)
533	(if_then_else
534	 (eq (zero_extract:SI (match_operand:SI 0 "register_operand" "r")
535			      (const_int 1)
536			      (match_operand:SI 1 "const_int_operand" "i"))
537	     (const_int 0))
538	 (label_ref (match_operand 2 "" ""))
539	 (pc)))
540   (clobber (reg:CC CC_REG))]
541  ""
542  "btst.l %0,(1<<5)|%1\;jmpc   z,%l2")
543
544(define_expand "cbranchqi4"
545  [(set (reg:CC CC_REG)
546        (compare:CC
547         (match_operand:QI 1 "register_operand" "")
548         (match_operand:QI 2 "ft32_rimm_operand" "")))
549   (set (pc)
550        (if_then_else (match_operator 0 "comparison_operator"
551                       [(reg:CC CC_REG) (const_int 0)])
552                      (label_ref (match_operand 3 "" ""))
553                      (pc)))]
554  ""
555  "")
556
557(define_insn "*cmpqi"
558  [(set (reg:CC CC_REG)
559        (compare:CC
560         (match_operand:QI 0 "register_operand" "r,r")
561         (match_operand:QI 1 "ft32_rimm_operand" "r,KA")))]
562  ""
563  "cmp.b  %0,%1")
564
565;; -------------------------------------------------------------------------
566;; Branch instructions
567;; -------------------------------------------------------------------------
568
569(define_code_iterator cond [ne eq lt ltu gt gtu ge le geu leu])
570(define_code_attr CC [(ne "nz") (eq "z") (lt "lt") (ltu "b")
571                      (gt "gt") (gtu "a") (ge "gte") (le "lte")
572                      (geu "ae") (leu "be") ])
573(define_code_attr rCC [(ne "z") (eq "nz") (lt "gte") (ltu "ae")
574                       (gt "lte") (gtu "be") (ge "lt") (le "gt")
575                       (geu "b") (leu "a") ])
576
577(define_insn "*b<cond:code>"
578  [(set (pc)
579        (if_then_else (cond (reg:CC CC_REG)
580                            (const_int 0))
581                      (label_ref (match_operand 0 "" ""))
582                      (pc)))]
583  ""
584{
585  return "jmpc   <CC>,%l0";
586}
587)
588
589(define_expand "cstoresi4"
590  [(set (reg:CC CC_REG)
591 	(compare:CC (match_operand:SI 2 "register_operand" "r,r")
592 		    (match_operand:SI 3 "ft32_rimm_operand" "r,KA")))
593   (set (match_operand:SI 0 "register_operand")
594	(match_operator:SI 1 "ordered_comparison_operator"
595	[(reg:CC CC_REG) (const_int 0)]))]
596  ""
597{
598  rtx test;
599
600  switch (GET_CODE (operands[1])) {
601  case NE:
602  case GEU:
603  case LT:
604  case LE:
605  case LEU:
606    test = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])),
607       		     SImode, operands[2], operands[3]);
608    emit_insn(gen_cstoresi4(operands[0], test, operands[2], operands[3]));
609    emit_insn(gen_xorsi3(operands[0], operands[0], gen_int_mode(1, SImode)));
610    DONE;
611  default:
612    ;
613  }
614})
615
616(define_insn "*seq"
617  [(set (match_operand:SI 0 "register_operand" "=r")
618        (eq:SI (reg CC_REG) (const_int 0)))]
619  ""
620  "bextu.l %0,$cc,32|0"
621)
622
623(define_insn "*sltu"
624  [(set (match_operand:SI 0 "register_operand" "=r")
625        (ltu:SI (reg CC_REG) (const_int 0)))]
626  ""
627  "bextu.l %0,$cc,32|1"
628)
629
630(define_insn "*sge"
631  [(set (match_operand:SI 0 "register_operand" "=r")
632        (ge:SI (reg CC_REG) (const_int 0)))]
633  ""
634  "bextu.l %0,$cc,32|4"
635)
636
637(define_insn "*sgt"
638  [(set (match_operand:SI 0 "register_operand" "=r")
639        (gt:SI (reg CC_REG) (const_int 0)))]
640  ""
641  "bextu.l %0,$cc,32|5"
642)
643
644(define_insn "*sgtu"
645  [(set (match_operand:SI 0 "register_operand" "=r")
646        (gtu:SI (reg CC_REG) (const_int 0)))]
647  ""
648  "bextu.l %0,$cc,32|6"
649)
650
651;; -------------------------------------------------------------------------
652;; Call and Jump instructions
653;; -------------------------------------------------------------------------
654
655(define_expand "call"
656  [(call (match_operand:QI 0 "memory_operand" "")
657                (match_operand 1 "general_operand" ""))]
658  ""
659{
660  gcc_assert (MEM_P (operands[0]));
661})
662
663(define_insn "*call"
664  [(call (mem:QI (match_operand:SI
665                  0 "nonmemory_operand" "i,r"))
666         (match_operand 1 "" ""))]
667  ""
668  "@
669   call   %0
670   calli  %0"
671)
672
673(define_expand "call_value"
674  [(set (match_operand 0 "" "")
675                (call (match_operand:QI 1 "memory_operand" "")
676                 (match_operand 2 "" "")))]
677  ""
678{
679  gcc_assert (MEM_P (operands[1]));
680})
681
682(define_insn "*call_value"
683  [(set (match_operand 0 "register_operand" "=r")
684        (call (mem:QI (match_operand:SI
685                       1 "immediate_operand" "i"))
686              (match_operand 2 "" "")))]
687  ""
688  "call   %1"
689)
690
691(define_insn "*call_value_indirect"
692  [(set (match_operand 0 "register_operand" "=r")
693        (call (mem:QI (match_operand:SI
694                       1 "register_operand" "r"))
695              (match_operand 2 "" "")))]
696  ""
697  "calli  %1"
698)
699
700(define_insn "indirect_jump"
701  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "r"))]
702  ""
703  "jmpi   %0")
704
705(define_insn "jump"
706  [(set (pc)
707        (label_ref (match_operand 0 "" "")))]
708  ""
709  "jmp    %l0"
710)
711
712(define_insn "call_prolog"
713  [(unspec:SI [(match_operand 0 "" "")]
714                   UNSPEC_JMP_PROLOG)]
715  ""
716  "call   __prolog_%0"
717)
718
719(define_insn "jump_epilog"
720  [(unspec:SI [(match_operand 0 "" "")]
721                   UNSPEC_JMP_EPILOG)]
722  ""
723  "jmp    __epilog_%0"
724)
725
726(define_insn "jump_epilog24"
727  [(unspec:SI [(match_operand 0 "" "")]
728                   UNSPEC_JMP_EPILOG24)]
729  ""
730  "jmp    __epilog24_%0"
731)
732
733
734;; Subroutines of "casesi".
735;; operand 0 is index
736;; operand 1 is the minimum bound
737;; operand 2 is the maximum bound - minimum bound + 1
738;; operand 3 is CODE_LABEL for the table;
739;; operand 4 is the CODE_LABEL to go to if index out of range.
740
741(define_expand "casesi"
742  [(match_operand:SI 0 "general_operand" "")
743   (match_operand:SI 1 "const_int_operand" "")
744   (match_operand:SI 2 "const_int_operand" "")
745   (match_operand 3 "" "")
746   (match_operand 4 "" "")]
747  ""
748  "
749{
750  if (GET_CODE (operands[0]) != REG)
751    operands[0] = force_reg (SImode, operands[0]);
752
753  if (operands[1] != const0_rtx)
754    {
755      rtx index = gen_reg_rtx (SImode);
756      rtx offset = gen_reg_rtx (SImode);
757
758      emit_insn (gen_movsi (offset, operands[1]));
759      emit_insn (gen_subsi3 (index, operands[0], offset));
760      operands[0] = index;
761    }
762
763  {
764    rtx test = gen_rtx_GTU (VOIDmode, operands[0], operands[2]);
765    emit_jump_insn (gen_cbranchsi4 (test, operands[0], operands[2], operands[4]));
766  }
767
768  emit_jump_insn (gen_casesi0 (operands[0], operands[3]));
769  DONE;
770}")
771
772(define_insn "casesi0"
773  [(set (pc) (mem:SI (plus:SI
774		       (mult:SI (match_operand:SI 0 "register_operand" "r")
775				(const_int 4))
776		       (label_ref (match_operand 1 "" "")))))
777   (clobber (match_scratch:SI 2 "=&r"))
778  ]
779  ""
780  {
781    if (TARGET_NOPM)
782      return \"ldk.l\t$cc,%l1\;ashl.l\t%2,%0,2\;add.l\t%2,%2,$cc\;ldi.l\t%2,%2,0\;jmpi\t%2\";
783    else
784      return \"ldk.l\t$cc,%l1\;ashl.l\t%2,%0,2\;add.l\t%2,%2,$cc\;lpmi.l\t%2,%2,0\;jmpi\t%2\";
785  })
786
787;; -------------------------------------------------------------------------
788;; Atomic exchange instruction
789;; -------------------------------------------------------------------------
790
791(define_insn "atomic_exchangesi"
792  [(set (match_operand:SI 0 "register_operand" "=&r,r")	;; output
793	(match_operand:SI 1 "memory_operand" "+BW,A"))	;; memory
794   (set (match_dup 1)
795	(unspec:SI
796	  [(match_operand:SI 2 "register_operand" "0,0")	;; input
797	   (match_operand:SI 3 "const_int_operand")]		;; model
798	  UNSPEC_XCHG))]
799  ""
800  "@
801   exi.l  %0,%1
802   exa.l  %0,%1")
803
804(define_insn "atomic_exchangehi"
805  [(set (match_operand:HI 0 "register_operand" "=&r,r")	;; output
806	(match_operand:HI 1 "memory_operand" "+BW,A"))	;; memory
807   (set (match_dup 1)
808	(unspec:HI
809	  [(match_operand:HI 2 "register_operand" "0,0")	;; input
810	   (match_operand:HI 3 "const_int_operand")]		;; model
811	  UNSPEC_XCHG))]
812  ""
813  "@
814   exi.s  %0,%1
815   exa.s  %0,%1")
816
817(define_insn "atomic_exchangeqi"
818  [(set (match_operand:QI 0 "register_operand" "=&r,r")	;; output
819	(match_operand:QI 1 "memory_operand" "+BW,A"))	;; memory
820   (set (match_dup 1)
821	(unspec:QI
822	  [(match_operand:QI 2 "register_operand" "0,0")	;; input
823	   (match_operand:QI 3 "const_int_operand")]		;; model
824	  UNSPEC_XCHG))]
825  ""
826  "@
827   exi.b  %0,%1
828   exa.b  %0,%1")
829
830;; -------------------------------------------------------------------------
831;; String instructions
832;; -------------------------------------------------------------------------
833
834(define_insn "cmpstrsi"
835  [(set (match_operand:SI 0 "register_operand" "=r,r")
836        (compare:SI (match_operand:BLK 1 "memory_operand" "W,BW")
837                    (match_operand:BLK 2 "memory_operand" "W,BW")))
838   (clobber (match_operand:SI 3))
839   ]
840  ""
841  "strcmp.%d3 %0,%b1,%b2"
842)
843
844(define_insn "movstr"
845[(set (match_operand:BLK 1 "memory_operand" "=W")
846      (match_operand:BLK 2 "memory_operand" "W"))
847      (use (match_operand:SI 0))
848      (clobber (match_dup 0))
849 ]
850"0"
851"stpcpy %b1,%b2 # %0 %b1 %b2"
852)
853
854(define_insn "cpymemsi"
855  [(set (match_operand:BLK 0 "memory_operand" "=W,BW")
856        (match_operand:BLK 1 "memory_operand" "W,BW"))
857        (use (match_operand:SI 2 "ft32_imm_operand" "KA,KA"))
858        (use (match_operand:SI 3))
859   ]
860  ""
861  "memcpy.%d3 %b0,%b1,%2 "
862)
863
864(define_insn "setmemsi"
865  [(set (match_operand:BLK 0 "memory_operand" "=BW") (unspec:BLK [
866     (use (match_operand:QI 2 "register_operand" "r"))
867     (use (match_operand:SI 1 "ft32_imm_operand" "KA"))
868   ] UNSPEC_SETMEM))
869   (use (match_operand:SI 3))
870   ]
871  ""
872  "memset.%d3 %b0,%2,%1"
873)
874
875(define_insn "strlensi"
876  [(set (match_operand:SI 0 "register_operand" "=r")
877        (unspec:SI [(match_operand:BLK 1 "memory_operand" "W")
878                    (match_operand:QI 2 "const_int_operand" "")
879                    (match_operand:SI 3 "ft32_rimm_operand" "")]
880                   UNSPEC_STRLEN))]
881  ""
882  "strlen.%d3 %0,%b1 # %2 %3"
883)
884
885;; -------------------------------------------------------------------------
886;; Prologue & Epilogue
887;; -------------------------------------------------------------------------
888
889(define_expand "prologue"
890  [(clobber (const_int 0))]
891  ""
892{
893  extern void ft32_expand_prologue();
894  ft32_expand_prologue ();
895  DONE;
896})
897
898
899(define_expand "epilogue"
900  [(return)]
901  ""
902{
903  extern void ft32_expand_epilogue();
904  ft32_expand_epilogue ();
905  DONE;
906})
907
908(define_insn "link"
909  [
910;;   (set (mem:SI (pre_dec:SI (reg:SI SP_REG)))
911;;        (reg:SI FP_REG))
912   (set (match_operand:SI 0)
913        (reg:SI SP_REG))
914   (set (reg:SI SP_REG)
915        (plus:SI (reg:SI SP_REG)
916                 (match_operand:SI 1 "general_operand" "L")))]
917  ""
918  "link   %0,%m1"
919)
920
921(define_insn "unlink"
922  [(set (reg:SI FP_REG)
923        (mem:SI (reg:SI FP_REG)))
924   (set (reg:SI SP_REG)
925        (plus:SI (reg:SI FP_REG)
926                 (const_int 4)))]
927  ""
928  "unlink $r29"
929)
930
931(define_insn "returner"
932  [(return)]
933  "reload_completed"
934  "return")
935
936(define_insn "pretend_returner"
937  [(set (reg:SI SP_REG)
938        (plus:SI (reg:SI SP_REG)
939                 (match_operand:SI 0)))
940   (return)]
941  "reload_completed"
942  "pop.l  $cc\;add.l  $sp,$sp,%0\;jmpi   $cc")
943
944(define_insn "returner24"
945  [
946  (set (reg:SI SP_REG)
947          (plus:SI
948           (reg:SI SP_REG)
949           (const_int 24)))
950  (return)]
951  ""
952  "jmp    __epilog24")
953