aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/avr
diff options
context:
space:
mode:
authorGeorg-Johann Lay <avr@gjlay.de>2013-01-25 09:28:09 +0000
committerGeorg-Johann Lay <gjl@gcc.gnu.org>2013-01-25 09:28:09 +0000
commit556f9906c548af7332f7f274f9e05cacfaeb64a6 (patch)
tree918c673cf4287a1ff60b0fbe521ff2d09b487c88 /gcc/config/avr
parent1f546bbbc4dcc9cf044310cf0eafb091415df614 (diff)
downloadgcc-556f9906c548af7332f7f274f9e05cacfaeb64a6.zip
gcc-556f9906c548af7332f7f274f9e05cacfaeb64a6.tar.gz
gcc-556f9906c548af7332f7f274f9e05cacfaeb64a6.tar.bz2
re PR target/54222 ([avr] Implement fixed-point support)
gcc/ PR target/54222 * config/avr/builtins.def (DEF_BUILTIN): Add LIBNAME argument. Add NULL LIBNAME argument to existing definitions. (ABSHR, ABSR, ABSLR, ABSLLR, ABSHK, ABSK, ABSLK, ABSLLK): New. * config/avr/avr-c.c (DEF_BUILTIN): Add LIBNAME argument. * config/avr/avr.c (DEF_BUILTIN): Same. (avr_init_builtins): Pass down LIBNAME to add_builtin_function. (avr_expand_builtin): Expand to a vanilla call if a libgcc implementation is available (DECL_ASSEMBLER_NAME is set). (avr_fold_absfx): New static function. (avr_fold_builtin): Use it to handle: AVR_BUILTIN_ABSHR, AVR_BUILTIN_ABSR, AVR_BUILTIN_ABSLR, AVR_BUILTIN_ABSLLR, AVR_BUILTIN_ABSHK, AVR_BUILTIN_ABSK, AVR_BUILTIN_ABSLK, AVR_BUILTIN_ABSLLK. * config/avr/stdfix.h (abshr, absr, abslr, absllr) (abshk, absk, abslk, absllk): Provide as static inline functions. gcc/testsuite/ PR target/54222 * gcc.target/avr/torture/builtins-3-absfx.c: New test. From-SVN: r195464
Diffstat (limited to 'gcc/config/avr')
-rw-r--r--gcc/config/avr/avr-c.c2
-rw-r--r--gcc/config/avr/avr.c84
-rw-r--r--gcc/config/avr/builtins.def60
-rw-r--r--gcc/config/avr/stdfix.h78
4 files changed, 194 insertions, 30 deletions
diff --git a/gcc/config/avr/avr-c.c b/gcc/config/avr/avr-c.c
index 075d9ef..ddcab54 100644
--- a/gcc/config/avr/avr-c.c
+++ b/gcc/config/avr/avr-c.c
@@ -168,7 +168,7 @@ avr_cpu_cpp_builtins (struct cpp_reader *pfile)
/* Define builtin macros so that the user can easily query whether or
not a specific builtin is available. */
-#define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE) \
+#define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
cpp_define (pfile, "__BUILTIN_AVR_" #NAME);
#include "builtins.def"
#undef DEF_BUILTIN
diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c
index f0906fa..c833bfb 100644
--- a/gcc/config/avr/avr.c
+++ b/gcc/config/avr/avr.c
@@ -11384,7 +11384,7 @@ avr_out_insert_bits (rtx *op, int *plen)
enum avr_builtin_id
{
-#define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE) \
+#define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
AVR_BUILTIN_ ## NAME,
#include "builtins.def"
#undef DEF_BUILTIN
@@ -11407,7 +11407,7 @@ struct GTY(()) avr_builtin_description
static GTY(()) struct avr_builtin_description
avr_bdesc[AVR_BUILTIN_COUNT] =
{
-#define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE) \
+#define DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME) \
{ (enum insn_code) CODE_FOR_ ## ICODE, N_ARGS, NULL_TREE },
#include "builtins.def"
#undef DEF_BUILTIN
@@ -11489,7 +11489,33 @@ avr_init_builtins (void)
const_memx_ptr_type_node,
NULL);
-#define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE) \
+ tree hr_ftype_hr
+ = build_function_type_list (short_fract_type_node,
+ short_fract_type_node, NULL);
+ tree r_ftype_r
+ = build_function_type_list (fract_type_node,
+ fract_type_node, NULL);
+ tree lr_ftype_lr
+ = build_function_type_list (long_fract_type_node,
+ long_fract_type_node, NULL);
+ tree llr_ftype_llr
+ = build_function_type_list (long_long_fract_type_node,
+ long_long_fract_type_node, NULL);
+
+ tree hk_ftype_hk
+ = build_function_type_list (short_accum_type_node,
+ short_accum_type_node, NULL);
+ tree k_ftype_k
+ = build_function_type_list (accum_type_node,
+ accum_type_node, NULL);
+ tree lk_ftype_lk
+ = build_function_type_list (long_accum_type_node,
+ long_accum_type_node, NULL);
+ tree llk_ftype_llk
+ = build_function_type_list (long_long_accum_type_node,
+ long_long_accum_type_node, NULL);
+
+#define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \
{ \
int id = AVR_BUILTIN_ ## NAME; \
const char *Name = "__builtin_avr_" #NAME; \
@@ -11498,7 +11524,7 @@ avr_init_builtins (void)
gcc_assert (id < AVR_BUILTIN_COUNT); \
avr_bdesc[id].fndecl \
= add_builtin_function (avr_tolower (name, Name), TYPE, id, \
- BUILT_IN_MD, NULL, NULL_TREE); \
+ BUILT_IN_MD, LIBNAME, NULL_TREE); \
}
#include "builtins.def"
#undef DEF_BUILTIN
@@ -11580,7 +11606,7 @@ static rtx
avr_expand_builtin (tree exp, rtx target,
rtx subtarget ATTRIBUTE_UNUSED,
enum machine_mode mode ATTRIBUTE_UNUSED,
- int ignore ATTRIBUTE_UNUSED)
+ int ignore)
{
tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
const char *bname = IDENTIFIER_POINTER (DECL_NAME (fndecl));
@@ -11624,6 +11650,14 @@ avr_expand_builtin (tree exp, rtx target,
}
}
+ /* No fold found and no insn: Call support function from libgcc. */
+
+ if (d->icode == CODE_FOR_nothing
+ && DECL_ASSEMBLER_NAME (get_callee_fndecl (exp)) != NULL_TREE)
+ {
+ return expand_call (exp, target, ignore);
+ }
+
/* No special treatment needed: vanilla expand. */
gcc_assert (d->icode != CODE_FOR_nothing);
@@ -11639,6 +11673,33 @@ avr_expand_builtin (tree exp, rtx target,
}
+/* Helper for `avr_fold_builtin' that folds absfx (FIXED_CST). */
+
+static tree
+avr_fold_absfx (tree tval)
+{
+ if (FIXED_CST != TREE_CODE (tval))
+ return NULL_TREE;
+
+ /* Our fixed-points have no padding: Use double_int payload directly. */
+
+ FIXED_VALUE_TYPE fval = TREE_FIXED_CST (tval);
+ unsigned int bits = GET_MODE_BITSIZE (fval.mode);
+ double_int ival = fval.data.sext (bits);
+
+ if (!ival.is_negative())
+ return tval;
+
+ /* ISO/IEC TR 18037, 7.18a.6.2: The absfx functions are saturating. */
+
+ fval.data = (ival == double_int::min_value (bits, false).sext (bits))
+ ? double_int::max_value (bits, false)
+ : -ival;
+
+ return build_fixed (TREE_TYPE (tval), fval);
+}
+
+
/* Implement `TARGET_FOLD_BUILTIN'. */
static tree
@@ -11662,6 +11723,19 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg,
build_int_cst (val_type, 4));
}
+ case AVR_BUILTIN_ABSHR:
+ case AVR_BUILTIN_ABSR:
+ case AVR_BUILTIN_ABSLR:
+ case AVR_BUILTIN_ABSLLR:
+
+ case AVR_BUILTIN_ABSHK:
+ case AVR_BUILTIN_ABSK:
+ case AVR_BUILTIN_ABSLK:
+ case AVR_BUILTIN_ABSLLK:
+ /* GCC is not good with folding ABS for fixed-point. Do it by hand. */
+
+ return avr_fold_absfx (arg[0]);
+
case AVR_BUILTIN_INSERT_BITS:
{
tree tbits = arg[1];
diff --git a/gcc/config/avr/builtins.def b/gcc/config/avr/builtins.def
index c8314ac..ecce186 100644
--- a/gcc/config/avr/builtins.def
+++ b/gcc/config/avr/builtins.def
@@ -20,35 +20,53 @@
builtins defined in the AVR part of the GNU compiler.
Befor including this file, define a macro
- DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE)
+ DEF_BUILTIN(NAME, N_ARGS, TYPE, ICODE, LIBNAME)
- NAME: `__builtin_avr_name' will be the user-level name of the builtin.
- `AVR_BUILTIN_NAME' will be the internal builtin's id.
- N_ARGS: Number of input arguments. If special treatment is needed,
- set to -1 and handle it by hand, see avr.c:avr_expand_builtin().
- TYPE: A tree node describing the prototype of the built-in.
- ICODE: Name of attached insn or expander. If special treatment in avr.c
- is needed to expand the built-in, use `nothing'.
-*/
+ NAME: `__builtin_avr_name' will be the user-level name of the builtin.
+ `AVR_BUILTIN_NAME' will be the internal builtin's id.
+ N_ARGS: Number of input arguments. If special treatment is needed,
+ set to -1 and handle it by hand, see avr.c:avr_expand_builtin().
+ TYPE: A tree node describing the prototype of the built-in.
+ ICODE: Name of attached insn or expander. If special treatment in avr.c
+ is needed to expand the built-in, use `nothing'.
+ LIBNAME: Name of the attached implementation in libgcc which is used if
+ the builtin cannot be folded away and there is no insn. */
/* Mapped to respective instruction. */
-DEF_BUILTIN (NOP, -1, void_ftype_void, nothing)
-DEF_BUILTIN (SEI, 0, void_ftype_void, enable_interrupt)
-DEF_BUILTIN (CLI, 0, void_ftype_void, disable_interrupt)
-DEF_BUILTIN (WDR, 0, void_ftype_void, wdr)
-DEF_BUILTIN (SLEEP, 0, void_ftype_void, sleep)
+DEF_BUILTIN (NOP, -1, void_ftype_void, nothing, NULL)
+DEF_BUILTIN (SEI, 0, void_ftype_void, enable_interrupt, NULL)
+DEF_BUILTIN (CLI, 0, void_ftype_void, disable_interrupt, NULL)
+DEF_BUILTIN (WDR, 0, void_ftype_void, wdr, NULL)
+DEF_BUILTIN (SLEEP, 0, void_ftype_void, sleep, NULL)
/* Mapped to respective instruction but might also be folded away
or emit as libgcc call if ISA does not provide the instruction. */
-DEF_BUILTIN (SWAP, 1, uchar_ftype_uchar, rotlqi3_4)
-DEF_BUILTIN (FMUL, 2, uint_ftype_uchar_uchar, fmul)
-DEF_BUILTIN (FMULS, 2, int_ftype_char_char, fmuls)
-DEF_BUILTIN (FMULSU, 2, int_ftype_char_uchar, fmulsu)
+DEF_BUILTIN (SWAP, 1, uchar_ftype_uchar, rotlqi3_4, NULL)
+DEF_BUILTIN (FMUL, 2, uint_ftype_uchar_uchar, fmul, NULL)
+DEF_BUILTIN (FMULS, 2, int_ftype_char_char, fmuls, NULL)
+DEF_BUILTIN (FMULSU, 2, int_ftype_char_uchar, fmulsu, NULL)
/* More complex stuff that cannot be mapped 1:1 to an instruction. */
-DEF_BUILTIN (DELAY_CYCLES, -1, void_ftype_ulong, nothing)
-DEF_BUILTIN (INSERT_BITS, 3, uchar_ftype_ulong_uchar_uchar, insert_bits)
-DEF_BUILTIN (FLASH_SEGMENT, 1, char_ftype_const_memx_ptr, flash_segment)
+DEF_BUILTIN (DELAY_CYCLES, -1, void_ftype_ulong, nothing, NULL)
+DEF_BUILTIN (INSERT_BITS, 3, uchar_ftype_ulong_uchar_uchar, insert_bits, NULL)
+DEF_BUILTIN (FLASH_SEGMENT, 1, char_ftype_const_memx_ptr, flash_segment, NULL)
+
+/* ISO/IEC TR 18037 "Embedded C"
+ The following builtins are undocumented and used by stdfix.h. */
+
+/* 7.18a.6 The fixed-point intrinsic functions. */
+
+/* 7.18a.6.2 The fixed-point absolute value functions. */
+
+DEF_BUILTIN (ABSHR, 1, hr_ftype_hr, ssabsqq2, NULL)
+DEF_BUILTIN (ABSR, 1, r_ftype_r, ssabshq2, NULL)
+DEF_BUILTIN (ABSLR, 1, lr_ftype_lr, ssabssq2, NULL)
+DEF_BUILTIN (ABSLLR, 1, llr_ftype_llr, nothing, "__ssabsdq2") // GCC extension
+
+DEF_BUILTIN (ABSHK, 1, hk_ftype_hk, ssabsha2, NULL)
+DEF_BUILTIN (ABSK, 1, k_ftype_k, ssabssa2, NULL)
+DEF_BUILTIN (ABSLK, -1, lk_ftype_lk, nothing, "__ssabsda2")
+DEF_BUILTIN (ABSLLK, -1, llk_ftype_llk, nothing, "__ssabsta2") // GCC extension
diff --git a/gcc/config/avr/stdfix.h b/gcc/config/avr/stdfix.h
index 95535a8..b86195a 100644
--- a/gcc/config/avr/stdfix.h
+++ b/gcc/config/avr/stdfix.h
@@ -35,12 +35,11 @@
#include <stdfix-gcc.h>
-/* 2.1.7.4 The bitwise fixed-point to integer conversion functions. */
-/* 2.1.7.5 The bitwise integer to fixed-point conversion functions. */
-
#define _GCC_TYPEPUN(A, B) \
__builtin_memcpy (&A, &B, sizeof (A))
+/* 7.18a.6 The fixed-point intrinsic functions. */
+
#if __SIZEOF_INT__ == 2
typedef signed char int_hr_t;
@@ -88,6 +87,79 @@ typedef long long unsigned int uint_uk_t;
#endif /* __SIZEOF_INT__ == 2 */
+/* 7.18a.6.2 The fixed-point absolute value functions. */
+
+/* short fract (hr): abshr */
+
+static __inline__ __attribute__((__always_inline__))
+short fract abshr (const short fract __q)
+{
+ return __builtin_avr_abshr (__q);
+}
+
+/* fract (r): absr */
+
+static __inline__ __attribute__((__always_inline__))
+fract absr (const fract __q)
+{
+ return __builtin_avr_absr (__q);
+}
+
+/* long fract (lr): abslr */
+
+static __inline__ __attribute__((__always_inline__))
+long fract abslr (const long fract __q)
+{
+ return __builtin_avr_abslr (__q);
+}
+
+/* short accum (hk): abshk */
+
+static __inline__ __attribute__((__always_inline__))
+short accum abshk (const short accum __q)
+{
+ return __builtin_avr_abshk (__q);
+}
+
+/* accum (k): absk */
+
+static __inline__ __attribute__((__always_inline__))
+accum absk (const accum __q)
+{
+ return __builtin_avr_absk (__q);
+}
+
+#if __SIZEOF_INT__ == 2
+
+/* long long fract (llr): absllr */
+
+static __inline__ __attribute__((__always_inline__))
+long long fract absllr (const long long fract __q) /* GCC extension */
+{
+ return __builtin_avr_absllr (__q);
+}
+
+/* long accum (lk): abslk */
+
+static __inline__ __attribute__((__always_inline__))
+long accum abslk (const long accum __q)
+{
+ return __builtin_avr_abslk (__q);
+}
+
+/* long long accum (llk): absllk */
+
+static __inline__ __attribute__((__always_inline__))
+long long accum absllk (const long long accum __q) /* GCC extension */
+{
+ return __builtin_avr_absllk (__q);
+}
+
+#endif /* __SIZEOF_INT__ == 2 */
+
+
+/* 7.18a.6.5 The bitwise fixed-point to integer conversion functions. */
+/* 7.18a.6.6 The bitwise integer to fixed-point conversion functions. */
/* short fract (hr): bitshr, bitsuhr, hrbits, uhrbits */