2014-01-02 23:25:22 +01:00
|
|
|
|
/* Copyright (C) 2013-2014 Free Software Foundation, Inc.
|
re PR target/54222 ([avr] Implement fixed-point support)
gcc/
PR target/54222
* config/avr/avr.md (unspec) <UNSPEC_ROUND>: Add.
* config/avr/avr-fixed.md (ALL4QA, ALL124QA): New mode iterators.
(round<mode>3, round<mode>3_const): New expanders for fixed-mode.
(*round<mode>3.libgcc): New insns for fixed-modes.
* config/avr/builtins.def (ABSxx): Use a non-NULL LIBNAME.
(ROUNDxx, COUNTLSxx, BITSxx, xxBITS): New DEF_BUILTINs.
(ROUNDFX, COUNTLSFX, ABSFX): New DEF_BUILTINs.
* config/avr/stdfix.h (absFX, bitsFX, FXbits): Remove inline
implementations. Define to __builtin_avr_absFX,
__builtin_avr_bitsFX, __builtin_avr_FXbits, respectively.
(roundFX, countlsFX): Define to __builtin_avr_roundFX,
__builtin_avr_countlsFX, respectively.
* config/avr/avr-c.c (target.h): Include it.
(enum avr_builtin_id): New enum.
(avr_resolve_overloaded_builtin): New static function.
(avr_register_target_pragmas): Use it to set
targetm.resolve_overloaded_builtin.
* config/avr/avr.c (avr_init_builtins): Supply myriads of local
tree nodes used by DEF_BUILTIN.
(avr_expand_builtin) <AVR_BUILTIN_ROUNDxx>: Sanity-check them.
(avr_fold_builtin) <AVR_BUILTIN_BITSxx>: Fold to VIEW_COVERT_EXPR.
<AVR_BUILTIN_xxBITS>: Same.
libgcc/
PR target/54222
* config/avr/lib2funcs.c: New C sources for modules for libgcc.a.
* config/avr/lib2-object.mk: New iterator to build objects from it.
* config/avr/t-avr: Iterate lib2-object.mk to build objects from
lib2funcs.c.
(LIB2FUNCS_EXCLUDE): Add _clrsbdi2.
(LIB1ASMFUNCS): Add: _ssabs_1, _mask1, _ret, _roundqq3, _rounduqq3,
_round_s2, _round_u2, _round_2_const, _addmask_2, _round_s4,
_round_u4, _round_4_const, _addmask_4, _round_x8, _rounddq3
_roundudq3, _roundda3 _rounduda3, _roundta3 _rounduta3.
* config/avr/lib1funcs-fixed.S: Implement them.
gcc/testsuite/
PR target/54222
* gcc.target/avr/torture/builtins-4-roundfx.c: New test.
* gcc.target/avr/torture/builtins-5-countlsfx.c: New test.
From-SVN: r195878
2013-02-08 11:13:37 +01:00
|
|
|
|
|
|
|
|
|
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 */
|