Home | History | Annotate | Line # | Download | only in avr
      1 ;;   This file contains instructions that support fixed-point operations
      2 ;;   for Atmel AVR micro controllers.
      3 ;;   Copyright (C) 2012-2022 Free Software Foundation, Inc.
      4 ;;
      5 ;;   Contributed by Sean D'Epagnier  (sean (a] depagnier.com)
      6 ;;                  Georg-Johann Lay (avr (a] gjlay.de)
      7 
      8 ;; This file is part of GCC.
      9 ;;
     10 ;; GCC is free software; you can redistribute it and/or modify
     11 ;; it under the terms of the GNU General Public License as published by
     12 ;; the Free Software Foundation; either version 3, or (at your option)
     13 ;; any later version.
     14 ;;
     15 ;; GCC is distributed in the hope that it will be useful,
     16 ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     17 ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     18 ;; GNU General Public License for more details.
     19 ;;
     20 ;; You should have received a copy of the GNU General Public License
     21 ;; along with GCC; see the file COPYING3.  If not see
     22 ;; <http://www.gnu.org/licenses/>.
     23 
     24 (define_mode_iterator ALL1Q  [QQ UQQ])
     25 (define_mode_iterator ALL2Q  [HQ UHQ])
     26 (define_mode_iterator ALL2A  [HA UHA])
     27 (define_mode_iterator ALL4A  [SA USA])
     28 (define_mode_iterator ALL2QA [HQ UHQ HA UHA])
     29 (define_mode_iterator ALL4QA [SQ USQ SA USA])
     30 (define_mode_iterator ALL124QA [ QQ   HQ  HA  SA  SQ
     31                                 UQQ  UHQ UHA USA USQ])
     32 
     33 (define_mode_iterator ALL2S [HQ HA])
     34 (define_mode_iterator ALL4S [SA SQ])
     35 (define_mode_iterator ALL24S  [     HQ  HA  SA  SQ])
     36 (define_mode_iterator ALL124S [ QQ  HQ  HA  SA  SQ])
     37 (define_mode_iterator ALL124U [UQQ UHQ UHA USA USQ])
     38 
     39 ;;; Conversions
     40 
     41 (define_mode_iterator FIXED_A
     42   [QQ UQQ
     43    HQ UHQ HA UHA
     44    SQ USQ SA USA
     45    DQ UDQ DA UDA
     46    TA UTA
     47    QI HI SI DI])
     48 
     49 ;; Same so that be can build cross products
     50 
     51 (define_mode_iterator FIXED_B
     52   [QQ UQQ
     53    HQ UHQ HA UHA
     54    SQ USQ SA USA
     55    DQ UDQ DA UDA
     56    TA UTA
     57    QI HI SI DI])
     58 
     59 (define_insn_and_split "fract<FIXED_B:mode><FIXED_A:mode>2"
     60   [(set (match_operand:FIXED_A 0 "register_operand" "=r")
     61         (fract_convert:FIXED_A
     62          (match_operand:FIXED_B 1 "register_operand" "r")))]
     63   "<FIXED_B:MODE>mode != <FIXED_A:MODE>mode"
     64   "#"
     65   "&& reload_completed"
     66   [(parallel [(set (match_dup 0)
     67                    (fract_convert:FIXED_A
     68                     (match_dup 1)))
     69               (clobber (reg:CC REG_CC))])])
     70 
     71 (define_insn "*fract<FIXED_B:mode><FIXED_A:mode>2"
     72   [(set (match_operand:FIXED_A 0 "register_operand" "=r")
     73         (fract_convert:FIXED_A
     74          (match_operand:FIXED_B 1 "register_operand" "r")))
     75    (clobber (reg:CC REG_CC))]
     76   "<FIXED_B:MODE>mode != <FIXED_A:MODE>mode
     77    && reload_completed"
     78   {
     79     return avr_out_fract (insn, operands, true, NULL);
     80   }
     81   [(set_attr "adjust_len" "sfract")])
     82 
     83 (define_insn_and_split "fractuns<FIXED_B:mode><FIXED_A:mode>2"
     84   [(set (match_operand:FIXED_A 0 "register_operand" "=r")
     85         (unsigned_fract_convert:FIXED_A
     86          (match_operand:FIXED_B 1 "register_operand" "r")))]
     87   "<FIXED_B:MODE>mode != <FIXED_A:MODE>mode"
     88   "#"
     89   "&& reload_completed"
     90   [(parallel [(set (match_dup 0)
     91                    (unsigned_fract_convert:FIXED_A
     92                     (match_dup 1)))
     93               (clobber (reg:CC REG_CC))])])
     94 
     95 (define_insn "*fractuns<FIXED_B:mode><FIXED_A:mode>2"
     96   [(set (match_operand:FIXED_A 0 "register_operand" "=r")
     97         (unsigned_fract_convert:FIXED_A
     98          (match_operand:FIXED_B 1 "register_operand" "r")))
     99    (clobber (reg:CC REG_CC))]
    100   "<FIXED_B:MODE>mode != <FIXED_A:MODE>mode
    101    && reload_completed"
    102   {
    103     return avr_out_fract (insn, operands, false, NULL);
    104   }
    105   [(set_attr "adjust_len" "ufract")])
    106 
    107 ;******************************************************************************
    108 ;** Saturated Addition and Subtraction
    109 ;******************************************************************************
    110 
    111 ;; Fixme:  It would be nice if we could expand the 32-bit versions to a
    112 ;;    transparent libgcc call if $2 is a REG.  Problem is that it is
    113 ;;    not possible to describe that addition is commutative.
    114 ;;    And defining register classes/constraintrs for the involved hard
    115 ;;    registers and let IRA do the work, yields inacceptable bloated code.
    116 ;;    Thus, we have to live with the up to 11 instructions that are output
    117 ;;    for these 32-bit saturated operations.
    118 
    119 ;; "ssaddqq3"  "ssaddhq3"  "ssaddha3"  "ssaddsq3"  "ssaddsa3"
    120 ;; "sssubqq3"  "sssubhq3"  "sssubha3"  "sssubsq3"  "sssubsa3"
    121 (define_insn_and_split "<code_stdname><mode>3"
    122   [(set (match_operand:ALL124S 0 "register_operand"                          "=??d,d")
    123         (ss_addsub:ALL124S (match_operand:ALL124S 1 "register_operand" "<abelian>0,0")
    124                            (match_operand:ALL124S 2 "nonmemory_operand"         "r,Ynn")))]
    125   ""
    126   "#"
    127   "&& reload_completed"
    128   [(parallel [(set (match_dup 0)
    129                    (ss_addsub:ALL124S (match_dup 1)
    130                                       (match_dup 2)))
    131               (clobber (reg:CC REG_CC))])])
    132 
    133 (define_insn "*<code_stdname><mode>3"
    134   [(set (match_operand:ALL124S 0 "register_operand"                          "=??d,d")
    135         (ss_addsub:ALL124S (match_operand:ALL124S 1 "register_operand" "<abelian>0,0")
    136                            (match_operand:ALL124S 2 "nonmemory_operand"         "r,Ynn")))
    137    (clobber (reg:CC REG_CC))]
    138   "reload_completed"
    139   {
    140     return avr_out_plus (insn, operands);
    141   }
    142   [(set_attr "adjust_len" "plus")])
    143 
    144 ;; "usadduqq3"  "usadduhq3"  "usadduha3" "usaddusq3"  "usaddusa3"
    145 ;; "ussubuqq3"  "ussubuhq3"  "ussubuha3" "ussubusq3"  "ussubusa3"
    146 (define_insn_and_split "<code_stdname><mode>3"
    147   [(set (match_operand:ALL124U 0 "register_operand"                          "=??r,d")
    148         (us_addsub:ALL124U (match_operand:ALL124U 1 "register_operand" "<abelian>0,0")
    149                            (match_operand:ALL124U 2 "nonmemory_operand"         "r,Ynn")))]
    150   ""
    151   "#"
    152   "&& reload_completed"
    153   [(parallel [(set (match_dup 0)
    154                    (us_addsub:ALL124U (match_dup 1)
    155                                       (match_dup 2)))
    156               (clobber (reg:CC REG_CC))])])
    157 
    158 (define_insn "*<code_stdname><mode>3"
    159   [(set (match_operand:ALL124U 0 "register_operand"                          "=??r,d")
    160         (us_addsub:ALL124U (match_operand:ALL124U 1 "register_operand" "<abelian>0,0")
    161                            (match_operand:ALL124U 2 "nonmemory_operand"         "r,Ynn")))
    162    (clobber (reg:CC REG_CC))]
    163   "reload_completed"
    164   {
    165     return avr_out_plus (insn, operands);
    166   }
    167   [(set_attr "adjust_len" "plus")])
    168 
    169 ;******************************************************************************
    170 ;** Saturated Negation and Absolute Value
    171 ;******************************************************************************
    172 
    173 ;; Fixme: This will always result in 0.  Dunno why simplify-rtx.cc says
    174 ;;   "unknown" on how to optimize this.  libgcc call would be in order,
    175 ;;   but the performance is *PLAIN* *HORROR* because the optimizers don't
    176 ;;   manage to optimize out MEMCPY that's sprincled all over fixed-bit.c  */
    177 
    178 (define_expand "usneg<mode>2"
    179   [(parallel [(match_operand:ALL124U 0 "register_operand" "")
    180               (match_operand:ALL124U 1 "nonmemory_operand" "")])]
    181   ""
    182   {
    183     emit_move_insn (operands[0], CONST0_RTX (<MODE>mode));
    184     DONE;
    185   })
    186 
    187 (define_insn_and_split "ssnegqq2"
    188   [(set (match_operand:QQ 0 "register_operand"            "=r")
    189         (ss_neg:QQ (match_operand:QQ 1 "register_operand"  "0")))]
    190   ""
    191   "#"
    192   "&& reload_completed"
    193   [(parallel [(set (match_dup 0)
    194                    (ss_neg:QQ (match_dup 1)))
    195               (clobber (reg:CC REG_CC))])])
    196 
    197 (define_insn "*ssnegqq2"
    198   [(set (match_operand:QQ 0 "register_operand"            "=r")
    199         (ss_neg:QQ (match_operand:QQ 1 "register_operand"  "0")))
    200    (clobber (reg:CC REG_CC))]
    201   "reload_completed"
    202   "neg %0\;brvc 0f\;dec %0\;0:"
    203   [(set_attr "length" "3")])
    204 
    205 (define_insn_and_split "ssabsqq2"
    206   [(set (match_operand:QQ 0 "register_operand"            "=r")
    207         (ss_abs:QQ (match_operand:QQ 1 "register_operand"  "0")))]
    208   ""
    209   "#"
    210   "&& reload_completed"
    211   [(parallel [(set (match_dup 0)
    212                    (ss_abs:QQ (match_dup 1)))
    213               (clobber (reg:CC REG_CC))])])
    214 
    215 (define_insn "*ssabsqq2"
    216   [(set (match_operand:QQ 0 "register_operand"            "=r")
    217         (ss_abs:QQ (match_operand:QQ 1 "register_operand"  "0")))
    218    (clobber (reg:CC REG_CC))]
    219   "reload_completed"
    220   "sbrc %0,7\;neg %0\;sbrc %0,7\;dec %0"
    221   [(set_attr "length" "4")])
    222 
    223 ;; "ssneghq2"  "ssnegha2"  "ssnegsq2"  "ssnegsa2"
    224 ;; "ssabshq2"  "ssabsha2"  "ssabssq2"  "ssabssa2"
    225 (define_expand "<code_stdname><mode>2"
    226   [(set (match_dup 2)
    227         (match_operand:ALL24S 1 "register_operand" ""))
    228    (set (match_dup 2)
    229         (ss_abs_neg:ALL24S (match_dup 2)))
    230    (set (match_operand:ALL24S 0 "register_operand" "")
    231         (match_dup 2))]
    232   ""
    233   {
    234     operands[2] = gen_rtx_REG (<MODE>mode, 26 - GET_MODE_SIZE (<MODE>mode));
    235   })
    236 
    237 ;; "*ssneghq2"  "*ssnegha2"
    238 ;; "*ssabshq2"  "*ssabsha2"
    239 (define_insn_and_split "*<code_stdname><mode>2_split"
    240   [(set (reg:ALL2S 24)
    241         (ss_abs_neg:ALL2S (reg:ALL2S 24)))]
    242   ""
    243   "#"
    244   "&& reload_completed"
    245   [(parallel [(set (reg:ALL2S 24)
    246                    (ss_abs_neg:ALL2S (reg:ALL2S 24)))
    247               (clobber (reg:CC REG_CC))])])
    248 
    249 (define_insn "*<code_stdname><mode>2"
    250   [(set (reg:ALL2S 24)
    251         (ss_abs_neg:ALL2S (reg:ALL2S 24)))
    252    (clobber (reg:CC REG_CC))]
    253   "reload_completed"
    254   "%~call __<code_stdname>_2"
    255   [(set_attr "type" "xcall")])
    256 
    257 ;; "*ssnegsq2"  "*ssnegsa2"
    258 ;; "*ssabssq2"  "*ssabssa2"
    259 (define_insn_and_split "*<code_stdname><mode>2_split"
    260   [(set (reg:ALL4S 22)
    261         (ss_abs_neg:ALL4S (reg:ALL4S 22)))]
    262   ""
    263   "#"
    264   "&& reload_completed"
    265   [(parallel [(set (reg:ALL4S 22)
    266                    (ss_abs_neg:ALL4S (reg:ALL4S 22)))
    267               (clobber (reg:CC REG_CC))])])
    268 
    269 (define_insn "*<code_stdname><mode>2"
    270   [(set (reg:ALL4S 22)
    271         (ss_abs_neg:ALL4S (reg:ALL4S 22)))
    272    (clobber (reg:CC REG_CC))]
    273   "reload_completed"
    274   "%~call __<code_stdname>_4"
    275   [(set_attr "type" "xcall")])
    276 
    277 ;******************************************************************************
    278 ; mul
    279 
    280 ;; "mulqq3" "muluqq3"
    281 (define_expand "mul<mode>3"
    282   [(parallel [(match_operand:ALL1Q 0 "register_operand" "")
    283               (match_operand:ALL1Q 1 "register_operand" "")
    284               (match_operand:ALL1Q 2 "register_operand" "")])]
    285   ""
    286   {
    287     emit_insn (AVR_HAVE_MUL
    288       ? gen_mul<mode>3_enh (operands[0], operands[1], operands[2])
    289       : gen_mul<mode>3_nomul (operands[0], operands[1], operands[2]));
    290     DONE;
    291   })
    292 
    293 (define_insn_and_split "mulqq3_enh"
    294   [(set (match_operand:QQ 0 "register_operand"         "=r")
    295         (mult:QQ (match_operand:QQ 1 "register_operand" "a")
    296                  (match_operand:QQ 2 "register_operand" "a")))]
    297   "AVR_HAVE_MUL"
    298   "#"
    299   "&& reload_completed"
    300   [(parallel [(set (match_dup 0)
    301                    (mult:QQ (match_dup 1)
    302                             (match_dup 2)))
    303               (clobber (reg:CC REG_CC))])])
    304 
    305 (define_insn "*mulqq3_enh"
    306   [(set (match_operand:QQ 0 "register_operand"         "=r")
    307         (mult:QQ (match_operand:QQ 1 "register_operand" "a")
    308                  (match_operand:QQ 2 "register_operand" "a")))
    309    (clobber (reg:CC REG_CC))]
    310   "AVR_HAVE_MUL && reload_completed"
    311   "fmuls %1,%2\;dec r1\;brvs 0f\;inc r1\;0:\;mov %0,r1\;clr __zero_reg__"
    312   [(set_attr "length" "6")])
    313 
    314 (define_insn_and_split "muluqq3_enh"
    315   [(set (match_operand:UQQ 0 "register_operand"          "=r")
    316         (mult:UQQ (match_operand:UQQ 1 "register_operand" "r")
    317                   (match_operand:UQQ 2 "register_operand" "r")))]
    318   "AVR_HAVE_MUL"
    319   "#"
    320   "&& reload_completed"
    321   [(parallel [(set (match_dup 0)
    322                    (mult:UQQ (match_dup 1)
    323                              (match_dup 2)))
    324               (clobber (reg:CC REG_CC))])])
    325 
    326 (define_insn "*muluqq3_enh"
    327   [(set (match_operand:UQQ 0 "register_operand"          "=r")
    328         (mult:UQQ (match_operand:UQQ 1 "register_operand" "r")
    329                   (match_operand:UQQ 2 "register_operand" "r")))
    330    (clobber (reg:CC REG_CC))]
    331   "AVR_HAVE_MUL && reload_completed"
    332   "mul %1,%2\;mov %0,r1\;clr __zero_reg__"
    333   [(set_attr "length" "3")])
    334 
    335 (define_expand "mulqq3_nomul"
    336   [(set (reg:QQ 24)
    337         (match_operand:QQ 1 "register_operand" ""))
    338    (set (reg:QQ 25)
    339         (match_operand:QQ 2 "register_operand" ""))
    340    ;; "*mulqq3.call"
    341    (parallel [(set (reg:QQ 23)
    342                    (mult:QQ (reg:QQ 24)
    343                             (reg:QQ 25)))
    344               (clobber (reg:QI 22))
    345               (clobber (reg:HI 24))])
    346    (set (match_operand:QQ 0 "register_operand" "")
    347         (reg:QQ 23))]
    348   "!AVR_HAVE_MUL"
    349   {
    350     avr_fix_inputs (operands, 1 << 2, regmask (QQmode, 24));
    351   })
    352 
    353 
    354 (define_expand "muluqq3_nomul"
    355   [(set (reg:UQQ 22)
    356         (match_operand:UQQ 1 "register_operand" ""))
    357    (set (reg:UQQ 24)
    358         (match_operand:UQQ 2 "register_operand" ""))
    359    ;; "*umulqihi3.call"
    360    (parallel [(set (reg:HI 24)
    361                    (mult:HI (zero_extend:HI (reg:QI 22))
    362                             (zero_extend:HI (reg:QI 24))))
    363               (clobber (reg:QI 21))
    364               (clobber (reg:HI 22))])
    365    (set (match_operand:UQQ 0 "register_operand" "")
    366         (reg:UQQ 25))]
    367   "!AVR_HAVE_MUL"
    368   {
    369     avr_fix_inputs (operands, 1 << 2, regmask (UQQmode, 22));
    370   })
    371 
    372 (define_insn_and_split "*mulqq3.call_split"
    373   [(set (reg:QQ 23)
    374         (mult:QQ (reg:QQ 24)
    375                  (reg:QQ 25)))
    376    (clobber (reg:QI 22))
    377    (clobber (reg:HI 24))]
    378   "!AVR_HAVE_MUL"
    379   "#"
    380   "&& reload_completed"
    381   [(parallel [(set (reg:QQ 23)
    382                    (mult:QQ (reg:QQ 24)
    383                             (reg:QQ 25)))
    384               (clobber (reg:QI 22))
    385               (clobber (reg:HI 24))
    386               (clobber (reg:CC REG_CC))])])
    387 
    388 (define_insn "*mulqq3.call"
    389   [(set (reg:QQ 23)
    390         (mult:QQ (reg:QQ 24)
    391                  (reg:QQ 25)))
    392    (clobber (reg:QI 22))
    393    (clobber (reg:HI 24))
    394    (clobber (reg:CC REG_CC))]
    395   "!AVR_HAVE_MUL && reload_completed"
    396   "%~call __mulqq3"
    397   [(set_attr "type" "xcall")])
    398 
    399 
    400 ;; "mulhq3" "muluhq3"
    401 ;; "mulha3" "muluha3"
    402 (define_expand "mul<mode>3"
    403   [(set (reg:ALL2QA 18)
    404         (match_operand:ALL2QA 1 "register_operand" ""))
    405    (set (reg:ALL2QA 26)
    406         (match_operand:ALL2QA 2 "register_operand" ""))
    407    ;; "*mulhq3.call.enh"
    408    (parallel [(set (reg:ALL2QA 24)
    409                    (mult:ALL2QA (reg:ALL2QA 18)
    410                                 (reg:ALL2QA 26)))
    411               (clobber (reg:HI 22))])
    412    (set (match_operand:ALL2QA 0 "register_operand" "")
    413         (reg:ALL2QA 24))]
    414   "AVR_HAVE_MUL"
    415   {
    416     avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 18));
    417   })
    418 
    419 ;; "*mulhq3.call"  "*muluhq3.call"
    420 ;; "*mulha3.call"  "*muluha3.call"
    421 (define_insn_and_split "*mul<mode>3.call_split"
    422   [(set (reg:ALL2QA 24)
    423         (mult:ALL2QA (reg:ALL2QA 18)
    424                      (reg:ALL2QA 26)))
    425    (clobber (reg:HI 22))]
    426   "AVR_HAVE_MUL"
    427   "#"
    428   "&& reload_completed"
    429   [(parallel [(set (reg:ALL2QA 24)
    430                    (mult:ALL2QA (reg:ALL2QA 18)
    431                                 (reg:ALL2QA 26)))
    432               (clobber (reg:HI 22))
    433               (clobber (reg:CC REG_CC))])])
    434 
    435 (define_insn "*mul<mode>3.call"
    436   [(set (reg:ALL2QA 24)
    437         (mult:ALL2QA (reg:ALL2QA 18)
    438                      (reg:ALL2QA 26)))
    439    (clobber (reg:HI 22))
    440    (clobber (reg:CC REG_CC))]
    441   "AVR_HAVE_MUL && reload_completed"
    442   "%~call __mul<mode>3"
    443   [(set_attr "type" "xcall")])
    444 
    445 
    446 ;; On the enhanced core, don't clobber either input and use a separate output
    447 
    448 ;; "mulsa3" "mulusa3"
    449 (define_expand "mul<mode>3"
    450   [(set (reg:ALL4A 16)
    451         (match_operand:ALL4A 1 "register_operand" ""))
    452    (set (reg:ALL4A 20)
    453         (match_operand:ALL4A 2 "register_operand" ""))
    454    (set (reg:ALL4A 24)
    455         (mult:ALL4A (reg:ALL4A 16)
    456                     (reg:ALL4A 20)))
    457    (set (match_operand:ALL4A 0 "register_operand" "")
    458         (reg:ALL4A 24))]
    459   "AVR_HAVE_MUL"
    460   {
    461     avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 16));
    462   })
    463 
    464 ;; "*mulsa3.call" "*mulusa3.call"
    465 (define_insn_and_split "*mul<mode>3.call_split"
    466   [(set (reg:ALL4A 24)
    467         (mult:ALL4A (reg:ALL4A 16)
    468                     (reg:ALL4A 20)))]
    469   "AVR_HAVE_MUL"
    470   "#"
    471   "&& reload_completed"
    472   [(parallel [(set (reg:ALL4A 24)
    473                    (mult:ALL4A (reg:ALL4A 16)
    474                                (reg:ALL4A 20)))
    475               (clobber (reg:CC REG_CC))])])
    476 
    477 (define_insn "*mul<mode>3.call"
    478   [(set (reg:ALL4A 24)
    479         (mult:ALL4A (reg:ALL4A 16)
    480                     (reg:ALL4A 20)))
    481    (clobber (reg:CC REG_CC))]
    482   "AVR_HAVE_MUL && reload_completed"
    483   "%~call __mul<mode>3"
    484   [(set_attr "type" "xcall")])
    485 
    486 ; / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / / /
    487 ; div
    488 
    489 (define_code_iterator usdiv [udiv div])
    490 
    491 ;; "divqq3" "udivuqq3"
    492 (define_expand "<code><mode>3"
    493   [(set (reg:ALL1Q 25)
    494         (match_operand:ALL1Q 1 "register_operand" ""))
    495    (set (reg:ALL1Q 22)
    496         (match_operand:ALL1Q 2 "register_operand" ""))
    497    (parallel [(set (reg:ALL1Q 24)
    498                    (usdiv:ALL1Q (reg:ALL1Q 25)
    499                                 (reg:ALL1Q 22)))
    500               (clobber (reg:QI 25))])
    501    (set (match_operand:ALL1Q 0 "register_operand" "")
    502         (reg:ALL1Q 24))]
    503   ""
    504   {
    505     avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 25));
    506   })
    507 
    508 
    509 ;; "*divqq3.call" "*udivuqq3.call"
    510 (define_insn_and_split "*<code><mode>3.call_split"
    511   [(set (reg:ALL1Q 24)
    512         (usdiv:ALL1Q (reg:ALL1Q 25)
    513                      (reg:ALL1Q 22)))
    514    (clobber (reg:QI 25))]
    515   ""
    516   "#"
    517   "&& reload_completed"
    518   [(parallel [(set (reg:ALL1Q 24)
    519                    (usdiv:ALL1Q (reg:ALL1Q 25)
    520                                 (reg:ALL1Q 22)))
    521               (clobber (reg:QI 25))
    522               (clobber (reg:CC REG_CC))])])
    523 
    524 (define_insn "*<code><mode>3.call"
    525   [(set (reg:ALL1Q 24)
    526         (usdiv:ALL1Q (reg:ALL1Q 25)
    527                      (reg:ALL1Q 22)))
    528    (clobber (reg:QI 25))
    529    (clobber (reg:CC REG_CC))]
    530   "reload_completed"
    531   "%~call __<code><mode>3"
    532   [(set_attr "type" "xcall")])
    533 
    534 ;; "divhq3" "udivuhq3"
    535 ;; "divha3" "udivuha3"
    536 (define_expand "<code><mode>3"
    537   [(set (reg:ALL2QA 26)
    538         (match_operand:ALL2QA 1 "register_operand" ""))
    539    (set (reg:ALL2QA 22)
    540         (match_operand:ALL2QA 2 "register_operand" ""))
    541    (parallel [(set (reg:ALL2QA 24)
    542                    (usdiv:ALL2QA (reg:ALL2QA 26)
    543                                  (reg:ALL2QA 22)))
    544               (clobber (reg:HI 26))
    545               (clobber (reg:QI 21))])
    546    (set (match_operand:ALL2QA 0 "register_operand" "")
    547         (reg:ALL2QA 24))]
    548   ""
    549   {
    550     avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 26));
    551   })
    552 
    553 ;; "*divhq3.call" "*udivuhq3.call"
    554 ;; "*divha3.call" "*udivuha3.call"
    555 (define_insn_and_split "*<code><mode>3.call_split"
    556   [(set (reg:ALL2QA 24)
    557         (usdiv:ALL2QA (reg:ALL2QA 26)
    558                       (reg:ALL2QA 22)))
    559    (clobber (reg:HI 26))
    560    (clobber (reg:QI 21))]
    561   ""
    562   "#"
    563   "&& reload_completed"
    564   [(parallel [(set (reg:ALL2QA 24)
    565                    (usdiv:ALL2QA (reg:ALL2QA 26)
    566                                  (reg:ALL2QA 22)))
    567               (clobber (reg:HI 26))
    568               (clobber (reg:QI 21))
    569               (clobber (reg:CC REG_CC))])])
    570 
    571 (define_insn "*<code><mode>3.call"
    572   [(set (reg:ALL2QA 24)
    573         (usdiv:ALL2QA (reg:ALL2QA 26)
    574                       (reg:ALL2QA 22)))
    575    (clobber (reg:HI 26))
    576    (clobber (reg:QI 21))
    577    (clobber (reg:CC REG_CC))]
    578   "reload_completed"
    579   "%~call __<code><mode>3"
    580   [(set_attr "type" "xcall")])
    581 
    582 ;; Note the first parameter gets passed in already offset by 2 bytes
    583 
    584 ;; "divsa3" "udivusa3"
    585 (define_expand "<code><mode>3"
    586   [(set (reg:ALL4A 24)
    587         (match_operand:ALL4A 1 "register_operand" ""))
    588    (set (reg:ALL4A 18)
    589         (match_operand:ALL4A 2 "register_operand" ""))
    590    (parallel [(set (reg:ALL4A 22)
    591                    (usdiv:ALL4A (reg:ALL4A 24)
    592                                 (reg:ALL4A 18)))
    593               (clobber (reg:HI 26))
    594               (clobber (reg:HI 30))])
    595    (set (match_operand:ALL4A 0 "register_operand" "")
    596         (reg:ALL4A 22))]
    597   ""
    598   {
    599     avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, 24));
    600   })
    601 
    602 ;; "*divsa3.call" "*udivusa3.call"
    603 (define_insn_and_split "*<code><mode>3.call_split"
    604   [(set (reg:ALL4A 22)
    605         (usdiv:ALL4A (reg:ALL4A 24)
    606                      (reg:ALL4A 18)))
    607    (clobber (reg:HI 26))
    608    (clobber (reg:HI 30))]
    609   ""
    610   "#"
    611   "&& reload_completed"
    612   [(parallel [(set (reg:ALL4A 22)
    613                    (usdiv:ALL4A (reg:ALL4A 24)
    614                                 (reg:ALL4A 18)))
    615               (clobber (reg:HI 26))
    616               (clobber (reg:HI 30))
    617               (clobber (reg:CC REG_CC))])])
    618 
    619 (define_insn "*<code><mode>3.call"
    620   [(set (reg:ALL4A 22)
    621         (usdiv:ALL4A (reg:ALL4A 24)
    622                      (reg:ALL4A 18)))
    623    (clobber (reg:HI 26))
    624    (clobber (reg:HI 30))
    625    (clobber (reg:CC REG_CC))]
    626   "reload_completed"
    627   "%~call __<code><mode>3"
    628   [(set_attr "type" "xcall")])
    629 
    630 
    631 ;******************************************************************************
    632 ;** Rounding
    633 ;******************************************************************************
    634 
    635 ;; "roundqq3"  "rounduqq3"
    636 ;; "roundhq3"  "rounduhq3"  "roundha3"  "rounduha3"
    637 ;; "roundsq3"  "roundusq3"  "roundsa3"  "roundusa3"
    638 (define_expand "round<mode>3"
    639   [(set (match_dup 4)
    640         (match_operand:ALL124QA 1 "register_operand" ""))
    641    (set (reg:QI 24)
    642         (match_dup 5))
    643    (parallel [(set (match_dup 3)
    644                    (unspec:ALL124QA [(match_dup 4)
    645                                      (reg:QI 24)] UNSPEC_ROUND))
    646               (clobber (match_dup 4))])
    647    (set (match_operand:ALL124QA 0 "register_operand" "")
    648         (match_dup 3))
    649    (use (match_operand:HI 2 "nonmemory_operand" ""))]
    650   ""
    651   {
    652     if (CONST_INT_P (operands[2])
    653         && !(optimize_size
    654              && 4 == GET_MODE_SIZE (<MODE>mode)))
    655       {
    656         emit_insn (gen_round<mode>3_const (operands[0], operands[1], operands[2]));
    657         DONE;
    658       }
    659 
    660     // Input and output of the libgcc function
    661     const unsigned int regno_in[]  = { -1U, 22, 22, -1U, 18 };
    662     const unsigned int regno_out[] = { -1U, 24, 24, -1U, 22 };
    663 
    664     operands[3] = gen_rtx_REG (<MODE>mode, regno_out[(size_t) GET_MODE_SIZE (<MODE>mode)]);
    665     operands[4] = gen_rtx_REG (<MODE>mode,  regno_in[(size_t) GET_MODE_SIZE (<MODE>mode)]);
    666     avr_fix_inputs (operands, 1 << 2, regmask (<MODE>mode, REGNO (operands[4])));
    667     operands[5] = simplify_gen_subreg (QImode, force_reg (HImode, operands[2]), HImode, 0);
    668     // $2 is no more needed, but is referenced for expand.
    669     operands[2] = const0_rtx;
    670   })
    671 
    672 ;; Expand rounding with known rounding points inline so that the addend / mask
    673 ;; will be consumed by operation with immediate operands and there is no
    674 ;; need for a shift with variable offset.
    675 
    676 ;; "roundqq3_const"  "rounduqq3_const"
    677 ;; "roundhq3_const"  "rounduhq3_const"  "roundha3_const"  "rounduha3_const"
    678 ;; "roundsq3_const"  "roundusq3_const"  "roundsa3_const"  "roundusa3_const"
    679 (define_insn_and_split "round<mode>3_const"
    680   [(set (match_operand:ALL124QA 0 "register_operand"                  "=d")
    681         (unspec:ALL124QA [(match_operand:ALL124QA 1 "register_operand" "0")
    682                           (match_operand:HI 2 "const_int_operand"      "n")
    683                           (const_int 0)]
    684                          UNSPEC_ROUND))]
    685   ""
    686   "#"
    687   "&& reload_completed"
    688   [(parallel [(set (match_dup 0)
    689                    (unspec:ALL124QA [(match_dup 1)
    690                                      (match_dup 2)
    691                                      (const_int 0)]
    692                                     UNSPEC_ROUND))
    693               (clobber (reg:CC REG_CC))])])
    694 
    695 (define_insn "*round<mode>3_const"
    696   [(set (match_operand:ALL124QA 0 "register_operand"                  "=d")
    697         (unspec:ALL124QA [(match_operand:ALL124QA 1 "register_operand" "0")
    698                           (match_operand:HI 2 "const_int_operand"      "n")
    699                           (const_int 0)]
    700                          UNSPEC_ROUND))
    701    (clobber (reg:CC REG_CC))]
    702   "reload_completed"
    703   {
    704     return avr_out_round (insn, operands);
    705   }
    706   [(set_attr "adjust_len" "round")])
    707 
    708 
    709 ;; "*roundqq3.libgcc"  "*rounduqq3.libgcc"
    710 (define_insn_and_split "*round<mode>3.libgcc_split"
    711   [(set (reg:ALL1Q 24)
    712         (unspec:ALL1Q [(reg:ALL1Q 22)
    713                        (reg:QI 24)] UNSPEC_ROUND))
    714    (clobber (reg:ALL1Q 22))]
    715   ""
    716   "#"
    717   "&& reload_completed"
    718   [(parallel [(set (reg:ALL1Q 24)
    719                    (unspec:ALL1Q [(reg:ALL1Q 22)
    720                                   (reg:QI 24)] UNSPEC_ROUND))
    721               (clobber (reg:ALL1Q 22))
    722               (clobber (reg:CC REG_CC))])])
    723 
    724 (define_insn "*round<mode>3.libgcc"
    725   [(set (reg:ALL1Q 24)
    726         (unspec:ALL1Q [(reg:ALL1Q 22)
    727                        (reg:QI 24)] UNSPEC_ROUND))
    728    (clobber (reg:ALL1Q 22))
    729    (clobber (reg:CC REG_CC))]
    730   "reload_completed"
    731   "%~call __round<mode>3"
    732   [(set_attr "type" "xcall")])
    733 
    734 ;; "*roundhq3.libgcc"  "*rounduhq3.libgcc"
    735 ;; "*roundha3.libgcc"  "*rounduha3.libgcc"
    736 (define_insn_and_split "*round<mode>3.libgcc_split"
    737   [(set (reg:ALL2QA 24)
    738         (unspec:ALL2QA [(reg:ALL2QA 22)
    739                         (reg:QI 24)] UNSPEC_ROUND))
    740    (clobber (reg:ALL2QA 22))]
    741   ""
    742   "#"
    743   "&& reload_completed"
    744   [(parallel [(set (reg:ALL2QA 24)
    745                    (unspec:ALL2QA [(reg:ALL2QA 22)
    746                                    (reg:QI 24)] UNSPEC_ROUND))
    747               (clobber (reg:ALL2QA 22))
    748               (clobber (reg:CC REG_CC))])])
    749 
    750 (define_insn "*round<mode>3.libgcc"
    751   [(set (reg:ALL2QA 24)
    752         (unspec:ALL2QA [(reg:ALL2QA 22)
    753                         (reg:QI 24)] UNSPEC_ROUND))
    754    (clobber (reg:ALL2QA 22))
    755    (clobber (reg:CC REG_CC))]
    756   "reload_completed"
    757   "%~call __round<mode>3"
    758   [(set_attr "type" "xcall")])
    759 
    760 ;; "*roundsq3.libgcc"  "*roundusq3.libgcc"
    761 ;; "*roundsa3.libgcc"  "*roundusa3.libgcc"
    762 (define_insn_and_split "*round<mode>3.libgcc_split"
    763   [(set (reg:ALL4QA 22)
    764         (unspec:ALL4QA [(reg:ALL4QA 18)
    765                         (reg:QI 24)] UNSPEC_ROUND))
    766    (clobber (reg:ALL4QA 18))]
    767   ""
    768   "#"
    769   "&& reload_completed"
    770   [(parallel [(set (reg:ALL4QA 22)
    771                    (unspec:ALL4QA [(reg:ALL4QA 18)
    772                                    (reg:QI 24)] UNSPEC_ROUND))
    773               (clobber (reg:ALL4QA 18))
    774               (clobber (reg:CC REG_CC))])])
    775 
    776 (define_insn "*round<mode>3.libgcc"
    777   [(set (reg:ALL4QA 22)
    778         (unspec:ALL4QA [(reg:ALL4QA 18)
    779                         (reg:QI 24)] UNSPEC_ROUND))
    780    (clobber (reg:ALL4QA 18))
    781    (clobber (reg:CC REG_CC))]
    782   "reload_completed"
    783   "%~call __round<mode>3"
    784   [(set_attr "type" "xcall")])
    785