Home | History | Annotate | Line # | Download | only in ft32
      1 ;; Machine description for FT32
      2 ;; Copyright (C) 2015-2022 Free Software Foundation, Inc.
      3 ;; Contributed by FTDI <support (a] 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")
     93     (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
     94          (zero_extend:DI (match_operand:SI 2 "register_operand" "r"))))
     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