1  /* Copyright (C) 2013-2023 Free Software Foundation, Inc.
       2  
       3     This file is part of GCC.
       4  
       5     GCC is free software; you can redistribute it and/or modify it under
       6     the terms of the GNU General Public License as published by the Free
       7     Software Foundation; either version 3, or (at your option) any later
       8     version.
       9  
      10     GCC is distributed in the hope that it will be useful, but WITHOUT ANY
      11     WARRANTY; without even the implied warranty of MERCHANTABILITY or
      12     FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
      13     for more details.
      14  
      15     Under Section 7 of GPL version 3, you are granted additional
      16     permissions described in the GCC Runtime Library Exception, version
      17     3.1, as published by the Free Software Foundation.
      18  
      19     You should have received a copy of the GNU General Public License and
      20     a copy of the GCC Runtime Library Exception along with this program;
      21     see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
      22     <http://www.gnu.org/licenses/>.  */
      23  
      24  
      25  /* This file supplies implementations for some AVR-specific builtin
      26     functions so that code like the following works as expected:
      27  
      28     int (*f (void))(_Fract)
      29     {
      30         return __builtin_avr_countlsr;
      31     }
      32  
      33     In this specific case, the generated code is:
      34  
      35     f:
      36         ldi r24,lo8(gs(__countlsHI))
      37         ldi r25,hi8(gs(__countlsHI))
      38         ret
      39  */
      40  
      41  /* Map fixed-point suffix to the corresponding fixed-point type.  */
      42  
      43  typedef short _Fract fx_hr_t;
      44  typedef _Fract fx_r_t;
      45  typedef long _Fract fx_lr_t;
      46  typedef long long _Fract fx_llr_t;
      47  
      48  typedef unsigned short _Fract fx_uhr_t;
      49  typedef unsigned _Fract fx_ur_t;
      50  typedef unsigned long _Fract fx_ulr_t;
      51  typedef unsigned long long _Fract fx_ullr_t;
      52  
      53  typedef short _Accum fx_hk_t;
      54  typedef _Accum fx_k_t;
      55  typedef long _Accum fx_lk_t;
      56  typedef long long _Accum fx_llk_t;
      57  
      58  typedef unsigned short _Accum fx_uhk_t;
      59  typedef unsigned _Accum fx_uk_t;
      60  typedef unsigned long _Accum fx_ulk_t;
      61  typedef unsigned long long _Accum fx_ullk_t;
      62  
      63  /* Map fixed-point suffix to the corresponding natural integer type.  */
      64  
      65  typedef char int_hr_t;
      66  typedef int int_r_t;
      67  typedef long int_lr_t;
      68  typedef long long int_llr_t;
      69  
      70  typedef unsigned char int_uhr_t;
      71  typedef unsigned int int_ur_t;
      72  typedef unsigned long int_ulr_t;
      73  typedef unsigned long long int_ullr_t;
      74  
      75  typedef int int_hk_t;
      76  typedef long int_k_t;
      77  typedef long long int_lk_t;
      78  typedef long long int_llk_t;
      79  
      80  typedef unsigned int int_uhk_t;
      81  typedef unsigned long int_uk_t;
      82  typedef unsigned long long int_ulk_t;
      83  typedef unsigned long long int_ullk_t;
      84  
      85  /* Map mode to the corresponding integer type.  */
      86  
      87  typedef char int_qi_t;
      88  typedef int int_hi_t;
      89  typedef long int_si_t;
      90  typedef long long int_di_t;
      91  
      92  typedef unsigned char uint_qi_t;
      93  typedef unsigned int uint_hi_t;
      94  typedef unsigned long uint_si_t;
      95  typedef unsigned long long uint_di_t;
      96  
      97  
      98  
      99  /************************************************************************/
     100  
     101  /* Supply implementations / symbols for __builtin_roundFX ASM_NAME.  */
     102  
     103  #ifdef L_round
     104  
     105  #define ROUND1(FX)                              \
     106    ROUND2 (FX)
     107  
     108  #define ROUND2(FX)                                                      \
     109    extern fx_## FX ##_t __round## FX (fx_## FX ##_t x, int rpoint);      \
     110                                                                          \
     111    fx_## FX ##_t                                                         \
     112    __round## FX (fx_## FX ##_t x, int rpoint)                            \
     113    {                                                                     \
     114      return __builtin_avr_round ##FX (x, rpoint);                        \
     115    }
     116  
     117  ROUND1(L_LABEL)
     118  
     119  #endif /* L_round */
     120  
     121  
     122  
     123  /*********************************************************************/
     124  
     125  /* Implement some count-leading-redundant-sign-bits to be used with
     126     coundlsFX implementation.  */
     127  
     128  #ifdef L__clrsbqi
     129  extern int __clrsbqi2 (char x);
     130  
     131  int
     132  __clrsbqi2 (char x)
     133  {
     134    int ret;
     135  
     136    if (x < 0)
     137      x = ~x;
     138  
     139    if (x == 0)
     140      return 8 * sizeof (x) -1;
     141  
     142    ret = __builtin_clz (x << 8);
     143    return ret - 1;
     144  }
     145  #endif /* L__clrsbqi */
     146  
     147  
     148  #ifdef L__clrsbdi
     149  extern int __clrsbdi2 (long long x);
     150  
     151  int
     152  __clrsbdi2 (long long x)
     153  {
     154    int ret;
     155  
     156    if (x < 0LL)
     157      x = ~x;
     158  
     159    if (x == 0LL)
     160      return 8 * sizeof (x) -1;
     161  
     162    ret = __builtin_clzll ((unsigned long long) x);
     163    return ret - 1;
     164  }
     165  #endif /* L__clrsbdi */
     166  
     167  
     168  
     169  /*********************************************************************/
     170  
     171  /* Supply implementations / symbols for __builtin_avr_countlsFX.  */
     172  
     173  /* Signed */
     174  
     175  #ifdef L_countls
     176  
     177  #define COUNTLS1(MM)                            \
     178    COUNTLS2 (MM)
     179  
     180  #define COUNTLS2(MM)                                                    \
     181    extern int __countls## MM ##2 (int_## MM ##_t);                       \
     182    extern int __clrsb## MM ##2 (int_## MM ##_t);                         \
     183                                                                          \
     184    int                                                                   \
     185    __countls## MM ##2 (int_## MM ##_t x)                                 \
     186    {                                                                     \
     187      if (x == 0)                                                         \
     188        return __INT8_MAX__;                                              \
     189                                                                          \
     190      return __clrsb## MM ##2 (x);                                        \
     191    }
     192  
     193  COUNTLS1(L_LABEL)
     194  
     195  #endif /* L_countls */
     196  
     197  /* Unsigned */
     198  
     199  #ifdef L_countlsu
     200  
     201  #define clz_qi2 __builtin_clz /* unused, avoid warning */
     202  #define clz_hi2 __builtin_clz
     203  #define clz_si2 __builtin_clzl
     204  #define clz_di2 __builtin_clzll
     205  
     206  #define COUNTLS1(MM)                            \
     207    COUNTLS2 (MM)
     208  
     209  #define COUNTLS2(MM)                                                    \
     210    extern int __countlsu## MM ##2 (uint_## MM ##_t);                     \
     211                                                                          \
     212    int                                                                   \
     213    __countlsu## MM ##2 (uint_## MM ##_t x)                               \
     214    {                                                                     \
     215      if (x == 0)                                                         \
     216        return __INT8_MAX__;                                              \
     217                                                                          \
     218      if (sizeof (x) == 1)                                                \
     219        return clz_hi2 (x << 8);                                          \
     220      else                                                                \
     221        return clz_## MM ##2 (x);                                         \
     222    }
     223  
     224  COUNTLS1(L_LABEL)
     225  
     226  #endif /* L_countlsu */