diff options
author | Georg-Johann Lay <avr@gjlay.de> | 2013-01-25 09:28:09 +0000 |
---|---|---|
committer | Georg-Johann Lay <gjl@gcc.gnu.org> | 2013-01-25 09:28:09 +0000 |
commit | 556f9906c548af7332f7f274f9e05cacfaeb64a6 (patch) | |
tree | 918c673cf4287a1ff60b0fbe521ff2d09b487c88 /gcc/config/avr | |
parent | 1f546bbbc4dcc9cf044310cf0eafb091415df614 (diff) | |
download | gcc-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.c | 2 | ||||
-rw-r--r-- | gcc/config/avr/avr.c | 84 | ||||
-rw-r--r-- | gcc/config/avr/builtins.def | 60 | ||||
-rw-r--r-- | gcc/config/avr/stdfix.h | 78 |
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 */ |