summaryrefslogtreecommitdiff
path: root/libgcc/config/avr/lib2funcs.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc/config/avr/lib2funcs.c')
-rw-r--r--libgcc/config/avr/lib2funcs.c226
1 files changed, 226 insertions, 0 deletions
diff --git a/libgcc/config/avr/lib2funcs.c b/libgcc/config/avr/lib2funcs.c
new file mode 100644
index 00000000000..83f2e23fb05
--- /dev/null
+++ b/libgcc/config/avr/lib2funcs.c
@@ -0,0 +1,226 @@
+/* Copyright (C) 2013 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 */