/* Copyright (C) 2013-2020 Free Software Foundation, Inc.
This file is part of GCC.
GCC is free software; you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free
Software Foundation; either version 3, or (at your option) any later
version.
GCC is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
for more details.
Under Section 7 of GPL version 3, you are granted additional
permissions described in the GCC Runtime Library Exception, version
3.1, as published by the Free Software Foundation.
You should have received a copy of the GNU General Public License and
a copy of the GCC Runtime Library Exception along with this program;
see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
<http://www.gnu.org/licenses/>. */
/* This file supplies implementations for some AVR-specific builtin
functions so that code like the following works as expected:
int (*f (void))(_Fract)
{
return __builtin_avr_countlsr;
}
In this specific case, the generated code is:
f:
ldi r24,lo8(gs(__countlsHI))
ldi r25,hi8(gs(__countlsHI))
ret
*/
/* Map fixed-point suffix to the corresponding fixed-point type. */
typedef short _Fract fx_hr_t;
typedef _Fract fx_r_t;
typedef long _Fract fx_lr_t;
typedef long long _Fract fx_llr_t;
typedef unsigned short _Fract fx_uhr_t;
typedef unsigned _Fract fx_ur_t;
typedef unsigned long _Fract fx_ulr_t;
typedef unsigned long long _Fract fx_ullr_t;
typedef short _Accum fx_hk_t;
typedef _Accum fx_k_t;
typedef long _Accum fx_lk_t;
typedef long long _Accum fx_llk_t;
typedef unsigned short _Accum fx_uhk_t;
typedef unsigned _Accum fx_uk_t;
typedef unsigned long _Accum fx_ulk_t;
typedef unsigned long long _Accum fx_ullk_t;
/* Map fixed-point suffix to the corresponding natural integer type. */
typedef char int_hr_t;
typedef int int_r_t;
typedef long int_lr_t;
typedef long long int_llr_t;
typedef unsigned char int_uhr_t;
typedef unsigned int int_ur_t;
typedef unsigned long int_ulr_t;
typedef unsigned long long int_ullr_t;
typedef int int_hk_t;
typedef long int_k_t;
typedef long long int_lk_t;
typedef long long int_llk_t;
typedef unsigned int int_uhk_t;
typedef unsigned long int_uk_t;
typedef unsigned long long int_ulk_t;
typedef unsigned long long int_ullk_t;
/* Map mode to the corresponding integer type. */
typedef char int_qi_t;
typedef int int_hi_t;
typedef long int_si_t;
typedef long long int_di_t;
typedef unsigned char uint_qi_t;
typedef unsigned int uint_hi_t;
typedef unsigned long uint_si_t;
typedef unsigned long long uint_di_t;
/************************************************************************/
/* Supply implementations / symbols for __builtin_roundFX ASM_NAME. */
#ifdef L_round
#define ROUND1(FX) \
ROUND2 (FX)
#define ROUND2(FX) \
extern fx_## FX ##_t __round## FX (fx_## FX ##_t x, int rpoint); \
\
fx_## FX ##_t \
__round## FX (fx_## FX ##_t x, int rpoint) \
{ \
return __builtin_avr_round ##FX (x, rpoint); \
}
ROUND1(L_LABEL)
#endif /* L_round */
/*********************************************************************/
/* Implement some count-leading-redundant-sign-bits to be used with
coundlsFX implementation. */
#ifdef L__clrsbqi
extern int __clrsbqi2 (char x);
int
__clrsbqi2 (char x)
{
int ret;
if (x < 0)
x = ~x;
if (x == 0)
return 8 * sizeof (x) -1;
ret = __builtin_clz (x << 8);
return ret - 1;
}
#endif /* L__clrsbqi */
#ifdef L__clrsbdi
extern int __clrsbdi2 (long long x);
int
__clrsbdi2 (long long x)
{
int ret;
if (x < 0LL)
x = ~x;
if (x == 0LL)
return 8 * sizeof (x) -1;
ret = __builtin_clzll ((unsigned long long) x);
return ret - 1;
}
#endif /* L__clrsbdi */
/*********************************************************************/
/* Supply implementations / symbols for __builtin_avr_countlsFX. */
/* Signed */
#ifdef L_countls
#define COUNTLS1(MM) \
COUNTLS2 (MM)
#define COUNTLS2(MM) \
extern int __countls## MM ##2 (int_## MM ##_t); \
extern int __clrsb## MM ##2 (int_## MM ##_t); \
\
int \
__countls## MM ##2 (int_## MM ##_t x) \
{ \
if (x == 0) \
return __INT8_MAX__; \
\
return __clrsb## MM ##2 (x); \
}
COUNTLS1(L_LABEL)
#endif /* L_countls */
/* Unsigned */
#ifdef L_countlsu
#define clz_qi2 __builtin_clz /* unused, avoid warning */
#define clz_hi2 __builtin_clz
#define clz_si2 __builtin_clzl
#define clz_di2 __builtin_clzll
#define COUNTLS1(MM) \
COUNTLS2 (MM)
#define COUNTLS2(MM) \
extern int __countlsu## MM ##2 (uint_## MM ##_t); \
\
int \
__countlsu## MM ##2 (uint_## MM ##_t x) \
{ \
if (x == 0) \
return __INT8_MAX__; \
\
if (sizeof (x) == 1) \
return clz_hi2 (x << 8); \
else \
return clz_## MM ##2 (x); \
}
COUNTLS1(L_LABEL)
#endif /* L_countlsu */