diff options
author | Georg-Johann Lay <avr@gjlay.de> | 2013-02-08 10:13:37 +0000 |
---|---|---|
committer | Georg-Johann Lay <gjl@gcc.gnu.org> | 2013-02-08 10:13:37 +0000 |
commit | 85d768f349087f3766ff84054ec7b3403c52ac7a (patch) | |
tree | c41ab849c5ffa4c56a753d5d4502a23fdc14617d /gcc | |
parent | 661bc682bcb87f5faa709f9bcd1679874f6652f6 (diff) | |
download | gcc-85d768f349087f3766ff84054ec7b3403c52ac7a.zip gcc-85d768f349087f3766ff84054ec7b3403c52ac7a.tar.gz gcc-85d768f349087f3766ff84054ec7b3403c52ac7a.tar.bz2 |
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
Diffstat (limited to 'gcc')
-rw-r--r-- | gcc/ChangeLog | 26 | ||||
-rw-r--r-- | gcc/config/avr/avr-c.c | 218 | ||||
-rw-r--r-- | gcc/config/avr/avr-fixed.md | 138 | ||||
-rw-r--r-- | gcc/config/avr/avr.c | 204 | ||||
-rw-r--r-- | gcc/config/avr/avr.md | 1 | ||||
-rw-r--r-- | gcc/config/avr/builtins.def | 115 | ||||
-rw-r--r-- | gcc/config/avr/stdfix.h | 477 | ||||
-rw-r--r-- | gcc/testsuite/ChangeLog | 6 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/avr/torture/builtins-4-roundfx.c | 161 | ||||
-rw-r--r-- | gcc/testsuite/gcc.target/avr/torture/builtins-5-countlsfx.c | 82 |
10 files changed, 1050 insertions, 378 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 787efb7..38173e9 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,29 @@ +2013-02-08 Georg-Johann Lay <avr@gjlay.de> + + 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. + 2013-02-08 Richard Biener <rguenther@suse.de> * cfgloop.c (verify_loop_structure): Properly handle diff --git a/gcc/config/avr/avr-c.c b/gcc/config/avr/avr-c.c index ddcab54..4e64405 100644 --- a/gcc/config/avr/avr-c.c +++ b/gcc/config/avr/avr-c.c @@ -26,10 +26,226 @@ #include "tm_p.h" #include "cpplib.h" #include "tree.h" +#include "target.h" #include "c-family/c-common.h" #include "langhooks.h" +/* IDs for all the AVR builtins. */ + +enum avr_builtin_id + { +#define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \ + AVR_BUILTIN_ ## NAME, +#include "builtins.def" +#undef DEF_BUILTIN + + AVR_BUILTIN_COUNT + }; + + +/* Implement `TARGET_RESOLVE_OVERLOADED_PLUGIN'. */ + +static tree +avr_resolve_overloaded_builtin (unsigned int iloc, tree fndecl, void *vargs) +{ + tree type0, type1, fold = NULL_TREE; + enum avr_builtin_id id = AVR_BUILTIN_COUNT; + location_t loc = (location_t) iloc; + vec<tree, va_gc> &args = * (vec<tree, va_gc>*) vargs; + + switch (DECL_FUNCTION_CODE (fndecl)) + { + default: + break; + + case AVR_BUILTIN_ABSFX: + if (args.length() != 1) + { + error_at (loc, "%qs expects 1 argument but %d given", + "absfx", (int) args.length()); + + fold = error_mark_node; + break; + } + + type0 = TREE_TYPE (args[0]); + + if (!FIXED_POINT_TYPE_P (type0)) + { + error_at (loc, "%qs expects a fixed-point value as argument", + "absfx"); + + fold = error_mark_node; + } + + switch (TYPE_MODE (type0)) + { + case QQmode: id = AVR_BUILTIN_ABSHR; break; + case HQmode: id = AVR_BUILTIN_ABSR; break; + case SQmode: id = AVR_BUILTIN_ABSLR; break; + case DQmode: id = AVR_BUILTIN_ABSLLR; break; + + case HAmode: id = AVR_BUILTIN_ABSHK; break; + case SAmode: id = AVR_BUILTIN_ABSK; break; + case DAmode: id = AVR_BUILTIN_ABSLK; break; + case TAmode: id = AVR_BUILTIN_ABSLLK; break; + + case UQQmode: + case UHQmode: + case USQmode: + case UDQmode: + case UHAmode: + case USAmode: + case UDAmode: + case UTAmode: + warning_at (loc, 0, "using %qs with unsigned type has no effect", + "absfx"); + return args[0]; + + default: + error_at (loc, "no matching fixed-point overload found for %qs", + "absfx"); + + fold = error_mark_node; + break; + } + + fold = targetm.builtin_decl (id, true); + + if (fold != error_mark_node) + fold = build_function_call_vec (loc, fold, &args, NULL); + + break; // absfx + + case AVR_BUILTIN_ROUNDFX: + if (args.length() != 2) + { + error_at (loc, "%qs expects 2 arguments but %d given", + "roundfx", (int) args.length()); + + fold = error_mark_node; + break; + } + + type0 = TREE_TYPE (args[0]); + type1 = TREE_TYPE (args[1]); + + if (!FIXED_POINT_TYPE_P (type0)) + { + error_at (loc, "%qs expects a fixed-point value as first argument", + "roundfx"); + + fold = error_mark_node; + } + + if (!INTEGRAL_TYPE_P (type1)) + { + error_at (loc, "%qs expects an integer value as second argument", + "roundfx"); + + fold = error_mark_node; + } + + switch (TYPE_MODE (type0)) + { + case QQmode: id = AVR_BUILTIN_ROUNDHR; break; + case HQmode: id = AVR_BUILTIN_ROUNDR; break; + case SQmode: id = AVR_BUILTIN_ROUNDLR; break; + case DQmode: id = AVR_BUILTIN_ROUNDLLR; break; + + case UQQmode: id = AVR_BUILTIN_ROUNDUHR; break; + case UHQmode: id = AVR_BUILTIN_ROUNDUR; break; + case USQmode: id = AVR_BUILTIN_ROUNDULR; break; + case UDQmode: id = AVR_BUILTIN_ROUNDULLR; break; + + case HAmode: id = AVR_BUILTIN_ROUNDHK; break; + case SAmode: id = AVR_BUILTIN_ROUNDK; break; + case DAmode: id = AVR_BUILTIN_ROUNDLK; break; + case TAmode: id = AVR_BUILTIN_ROUNDLLK; break; + + case UHAmode: id = AVR_BUILTIN_ROUNDUHK; break; + case USAmode: id = AVR_BUILTIN_ROUNDUK; break; + case UDAmode: id = AVR_BUILTIN_ROUNDULK; break; + case UTAmode: id = AVR_BUILTIN_ROUNDULLK; break; + + default: + error_at (loc, "no matching fixed-point overload found for %qs", + "roundfx"); + + fold = error_mark_node; + break; + } + + fold = targetm.builtin_decl (id, true); + + if (fold != error_mark_node) + fold = build_function_call_vec (loc, fold, &args, NULL); + + break; // roundfx + + case AVR_BUILTIN_COUNTLSFX: + if (args.length() != 1) + { + error_at (loc, "%qs expects 1 argument but %d given", + "countlsfx", (int) args.length()); + + fold = error_mark_node; + break; + } + + type0 = TREE_TYPE (args[0]); + + if (!FIXED_POINT_TYPE_P (type0)) + { + error_at (loc, "%qs expects a fixed-point value as first argument", + "countlsfx"); + + fold = error_mark_node; + } + + switch (TYPE_MODE (type0)) + { + case QQmode: id = AVR_BUILTIN_COUNTLSHR; break; + case HQmode: id = AVR_BUILTIN_COUNTLSR; break; + case SQmode: id = AVR_BUILTIN_COUNTLSLR; break; + case DQmode: id = AVR_BUILTIN_COUNTLSLLR; break; + + case UQQmode: id = AVR_BUILTIN_COUNTLSUHR; break; + case UHQmode: id = AVR_BUILTIN_COUNTLSUR; break; + case USQmode: id = AVR_BUILTIN_COUNTLSULR; break; + case UDQmode: id = AVR_BUILTIN_COUNTLSULLR; break; + + case HAmode: id = AVR_BUILTIN_COUNTLSHK; break; + case SAmode: id = AVR_BUILTIN_COUNTLSK; break; + case DAmode: id = AVR_BUILTIN_COUNTLSLK; break; + case TAmode: id = AVR_BUILTIN_COUNTLSLLK; break; + + case UHAmode: id = AVR_BUILTIN_COUNTLSUHK; break; + case USAmode: id = AVR_BUILTIN_COUNTLSUK; break; + case UDAmode: id = AVR_BUILTIN_COUNTLSULK; break; + case UTAmode: id = AVR_BUILTIN_COUNTLSULLK; break; + + default: + error_at (loc, "no matching fixed-point overload found for %qs", + "countlsfx"); + + fold = error_mark_node; + break; + } + + fold = targetm.builtin_decl (id, true); + + if (fold != error_mark_node) + fold = build_function_call_vec (loc, fold, &args, NULL); + + break; // countlsfx + } + + return fold; +} + + /* Implement `REGISTER_TARGET_PRAGMAS'. */ void @@ -49,6 +265,8 @@ avr_register_target_pragmas (void) if (!ADDR_SPACE_GENERIC_P (i)) c_register_addr_space (avr_addrspace[i].name, avr_addrspace[i].id); } + + targetm.resolve_overloaded_builtin = avr_resolve_overloaded_builtin; } diff --git a/gcc/config/avr/avr-fixed.md b/gcc/config/avr/avr-fixed.md index ce7f54d..7d9b525 100644 --- a/gcc/config/avr/avr-fixed.md +++ b/gcc/config/avr/avr-fixed.md @@ -24,14 +24,16 @@ (define_mode_iterator ALL1Q [QQ UQQ]) (define_mode_iterator ALL2Q [HQ UHQ]) (define_mode_iterator ALL2A [HA UHA]) -(define_mode_iterator ALL2QA [HQ UHQ - HA UHA]) (define_mode_iterator ALL4A [SA USA]) +(define_mode_iterator ALL2QA [HQ UHQ HA UHA]) +(define_mode_iterator ALL4QA [SQ USQ SA USA]) +(define_mode_iterator ALL124QA [ QQ HQ HA SA SQ + UQQ UHQ UHA USA USQ]) (define_mode_iterator ALL2S [HQ HA]) (define_mode_iterator ALL4S [SA SQ]) -(define_mode_iterator ALL24S [ HQ HA SA SQ]) -(define_mode_iterator ALL124S [ QQ HQ HA SA SQ]) +(define_mode_iterator ALL24S [ HQ HA SA SQ]) +(define_mode_iterator ALL124S [ QQ HQ HA SA SQ]) (define_mode_iterator ALL124U [UQQ UHQ UHA USA USQ]) ;;; Conversions @@ -396,3 +398,131 @@ "%~call __<code><mode>3" [(set_attr "type" "xcall") (set_attr "cc" "clobber")]) + + +;****************************************************************************** +;** Rounding +;****************************************************************************** + +;; "roundqq3" "rounduqq3" +;; "roundhq3" "rounduhq3" "roundha3" "rounduha3" +;; "roundsq3" "roundusq3" "roundsa3" "roundusa3" +(define_expand "round<mode>3" + [(set (match_dup 4) + (match_operand:ALL124QA 1 "register_operand" "")) + (set (reg:QI 24) + (match_dup 5)) + (parallel [(set (match_dup 3) + (unspec:ALL124QA [(match_dup 4) + (reg:QI 24)] UNSPEC_ROUND)) + (clobber (match_dup 4))]) + (set (match_operand:ALL124QA 0 "register_operand" "") + (match_dup 3)) + (use (match_operand:HI 2 "nonmemory_operand" ""))] + "" + { + if (CONST_INT_P (operands[2]) + && !(optimize_size + && 4 == GET_MODE_SIZE (<MODE>mode))) + { + emit_insn (gen_round<mode>3_const (operands[0], operands[1], operands[2])); + DONE; + } + + // Input and output of the libgcc function + const unsigned int regno_in[] = { -1, 22, 22, -1, 18 }; + const unsigned int regno_out[] = { -1, 24, 24, -1, 22 }; + + operands[3] = gen_rtx_REG (<MODE>mode, regno_out[(size_t) GET_MODE_SIZE (<MODE>mode)]); + operands[4] = gen_rtx_REG (<MODE>mode, regno_in[(size_t) GET_MODE_SIZE (<MODE>mode)]); + operands[5] = simplify_gen_subreg (QImode, force_reg (HImode, operands[2]), HImode, 0); + // $2 is no more needed, but is referenced for expand. + operands[2] = const0_rtx; + }) + +;; Expand rounding with known rounding points inline so that the addend / mask +;; will be consumed by operation with immediate operands and there is no +;; need for a shift with variable offset. + +;; "roundqq3_const" "rounduqq3_const" +;; "roundhq3_const" "rounduhq3_const" "roundha3_const" "rounduha3_const" +;; "roundsq3_const" "roundusq3_const" "roundsa3_const" "roundusa3_const" +(define_expand "round<mode>3_const" + [(parallel [(match_operand:ALL124QA 0 "register_operand" "") + (match_operand:ALL124QA 1 "register_operand" "") + (match_operand:HI 2 "const_int_operand" "")])] + "" + { + // The rounding point RP is $2. The smallest fractional + // bit that is not cleared by the rounding is 2^(-RP). + + enum machine_mode imode = int_mode_for_mode (<MODE>mode); + int fbit = (int) GET_MODE_FBIT (<MODE>mode); + + // Add-Saturate 1/2 * 2^(-RP) + + double_int i_add = double_int_zero.set_bit (fbit-1 - INTVAL (operands[2])); + rtx x_add = const_fixed_from_double_int (i_add, <MODE>mode); + + if (SIGNED_FIXED_POINT_MODE_P (<MODE>mode)) + emit_move_insn (operands[0], + gen_rtx_SS_PLUS (<MODE>mode, operands[1], x_add)); + else + emit_move_insn (operands[0], + gen_rtx_US_PLUS (<MODE>mode, operands[1], x_add)); + + // Keep all bits from RP and higher: ... 2^(-RP) + // Clear all bits from RP+1 and lower: 2^(-RP-1) ... + // Rounding point ^^^^^^^ + // Added above ^^^^^^^^^ + + rtx xreg = simplify_gen_subreg (imode, operands[0], <MODE>mode, 0); + rtx xmask = immed_double_int_const (-i_add - i_add, imode); + + if (SImode == imode) + emit_insn (gen_andsi3 (xreg, xreg, xmask)); + else if (HImode == imode) + emit_insn (gen_andhi3 (xreg, xreg, xmask)); + else if (QImode == imode) + emit_insn (gen_andqi3 (xreg, xreg, xmask)); + else + gcc_unreachable(); + + DONE; + }) + + +;; "*roundqq3.libgcc" "*rounduqq3.libgcc" +(define_insn "*round<mode>3.libgcc" + [(set (reg:ALL1Q 24) + (unspec:ALL1Q [(reg:ALL1Q 22) + (reg:QI 24)] UNSPEC_ROUND)) + (clobber (reg:ALL1Q 22))] + "" + "%~call __round<mode>3" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +;; "*roundhq3.libgcc" "*rounduhq3.libgcc" +;; "*roundha3.libgcc" "*rounduha3.libgcc" +(define_insn "*round<mode>3.libgcc" + [(set (reg:ALL2QA 24) + (unspec:ALL2QA [(reg:ALL2QA 22) + (reg:QI 24)] UNSPEC_ROUND)) + (clobber (reg:ALL2QA 22))] + "" + "%~call __round<mode>3" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) + +;; "*roundsq3.libgcc" "*roundusq3.libgcc" +;; "*roundsa3.libgcc" "*roundusa3.libgcc" +(define_insn "*round<mode>3.libgcc" + [(set (reg:ALL4QA 22) + (unspec:ALL4QA [(reg:ALL4QA 18) + (reg:QI 24)] UNSPEC_ROUND)) + (clobber (reg:ALL4QA 18))] + "" + "%~call __round<mode>3" + [(set_attr "type" "xcall") + (set_attr "cc" "clobber")]) diff --git a/gcc/config/avr/avr.c b/gcc/config/avr/avr.c index c833bfb..0f1d2c1 100644 --- a/gcc/config/avr/avr.c +++ b/gcc/config/avr/avr.c @@ -11489,32 +11489,118 @@ avr_init_builtins (void) const_memx_ptr_type_node, NULL); - 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 ITYP(T) \ + lang_hooks.types.type_for_size (TYPE_PRECISION (T), TYPE_UNSIGNED (T)) +#define FX_FTYPE_FX(fx) \ + tree fx##r_ftype_##fx##r \ + = build_function_type_list (node_##fx##r, node_##fx##r, NULL); \ + tree fx##k_ftype_##fx##k \ + = build_function_type_list (node_##fx##k, node_##fx##k, NULL) + +#define FX_FTYPE_FX_INT(fx) \ + tree fx##r_ftype_##fx##r_int \ + = build_function_type_list (node_##fx##r, node_##fx##r, \ + integer_type_node, NULL); \ + tree fx##k_ftype_##fx##k_int \ + = build_function_type_list (node_##fx##k, node_##fx##k, \ + integer_type_node, NULL) + +#define INT_FTYPE_FX(fx) \ + tree int_ftype_##fx##r \ + = build_function_type_list (integer_type_node, node_##fx##r, NULL); \ + tree int_ftype_##fx##k \ + = build_function_type_list (integer_type_node, node_##fx##k, NULL) + +#define INTX_FTYPE_FX(fx) \ + tree int##fx##r_ftype_##fx##r \ + = build_function_type_list (ITYP (node_##fx##r), node_##fx##r, NULL); \ + tree int##fx##k_ftype_##fx##k \ + = build_function_type_list (ITYP (node_##fx##k), node_##fx##k, NULL) + +#define FX_FTYPE_INTX(fx) \ + tree fx##r_ftype_int##fx##r \ + = build_function_type_list (node_##fx##r, ITYP (node_##fx##r), NULL); \ + tree fx##k_ftype_int##fx##k \ + = build_function_type_list (node_##fx##k, ITYP (node_##fx##k), NULL) + + tree node_hr = short_fract_type_node; + tree node_r = fract_type_node; + tree node_lr = long_fract_type_node; + tree node_llr = long_long_fract_type_node; + + tree node_uhr = unsigned_short_fract_type_node; + tree node_ur = unsigned_fract_type_node; + tree node_ulr = unsigned_long_fract_type_node; + tree node_ullr = unsigned_long_long_fract_type_node; + + tree node_hk = short_accum_type_node; + tree node_k = accum_type_node; + tree node_lk = long_accum_type_node; + tree node_llk = long_long_accum_type_node; + + tree node_uhk = unsigned_short_accum_type_node; + tree node_uk = unsigned_accum_type_node; + tree node_ulk = unsigned_long_accum_type_node; + tree node_ullk = unsigned_long_long_accum_type_node; + + + /* For absfx builtins. */ + + FX_FTYPE_FX (h); + FX_FTYPE_FX (); + FX_FTYPE_FX (l); + FX_FTYPE_FX (ll); + + /* For roundfx builtins. */ + + FX_FTYPE_FX_INT (h); + FX_FTYPE_FX_INT (); + FX_FTYPE_FX_INT (l); + FX_FTYPE_FX_INT (ll); + + FX_FTYPE_FX_INT (uh); + FX_FTYPE_FX_INT (u); + FX_FTYPE_FX_INT (ul); + FX_FTYPE_FX_INT (ull); + + /* For countlsfx builtins. */ + + INT_FTYPE_FX (h); + INT_FTYPE_FX (); + INT_FTYPE_FX (l); + INT_FTYPE_FX (ll); + + INT_FTYPE_FX (uh); + INT_FTYPE_FX (u); + INT_FTYPE_FX (ul); + INT_FTYPE_FX (ull); + + /* For bitsfx builtins. */ + + INTX_FTYPE_FX (h); + INTX_FTYPE_FX (); + INTX_FTYPE_FX (l); + INTX_FTYPE_FX (ll); + + INTX_FTYPE_FX (uh); + INTX_FTYPE_FX (u); + INTX_FTYPE_FX (ul); + INTX_FTYPE_FX (ull); + + /* For fxbits builtins. */ + + FX_FTYPE_INTX (h); + FX_FTYPE_INTX (); + FX_FTYPE_INTX (l); + FX_FTYPE_INTX (ll); + + FX_FTYPE_INTX (uh); + FX_FTYPE_INTX (u); + FX_FTYPE_INTX (ul); + FX_FTYPE_INTX (ull); + + #define DEF_BUILTIN(NAME, N_ARGS, TYPE, CODE, LIBNAME) \ { \ int id = AVR_BUILTIN_ ## NAME; \ @@ -11647,7 +11733,50 @@ avr_expand_builtin (tree exp, rtx target, " as first argument", bname); return target; } + + break; } + + case AVR_BUILTIN_ROUNDHR: case AVR_BUILTIN_ROUNDUHR: + case AVR_BUILTIN_ROUNDR: case AVR_BUILTIN_ROUNDUR: + case AVR_BUILTIN_ROUNDLR: case AVR_BUILTIN_ROUNDULR: + case AVR_BUILTIN_ROUNDLLR: case AVR_BUILTIN_ROUNDULLR: + + case AVR_BUILTIN_ROUNDHK: case AVR_BUILTIN_ROUNDUHK: + case AVR_BUILTIN_ROUNDK: case AVR_BUILTIN_ROUNDUK: + case AVR_BUILTIN_ROUNDLK: case AVR_BUILTIN_ROUNDULK: + case AVR_BUILTIN_ROUNDLLK: case AVR_BUILTIN_ROUNDULLK: + + /* Warn about odd rounding. Rounding points >= FBIT will have + no effect. */ + + if (TREE_CODE (CALL_EXPR_ARG (exp, 1)) != INTEGER_CST) + break; + + int rbit = (int) TREE_INT_CST_LOW (CALL_EXPR_ARG (exp, 1)); + + if (rbit >= (int) GET_MODE_FBIT (mode)) + { + warning (OPT_Wextra, "rounding to %d bits has no effect for " + "fixed-point value with %d fractional bits", + rbit, GET_MODE_FBIT (mode)); + + return expand_expr (CALL_EXPR_ARG (exp, 0), NULL_RTX, mode, + EXPAND_NORMAL); + } + else if (rbit <= - (int) GET_MODE_IBIT (mode)) + { + warning (0, "rounding result will always be 0"); + return CONST0_RTX (mode); + } + + /* The rounding points RP satisfies now: -IBIT < RP < FBIT. + + TR 18037 only specifies results for RP > 0. However, the + remaining cases of -IBIT < RP <= 0 can easily be supported + without any additional overhead. */ + + break; /* round */ } /* No fold found and no insn: Call support function from libgcc. */ @@ -11736,6 +11865,31 @@ avr_fold_builtin (tree fndecl, int n_args ATTRIBUTE_UNUSED, tree *arg, return avr_fold_absfx (arg[0]); + case AVR_BUILTIN_BITSHR: case AVR_BUILTIN_HRBITS: + case AVR_BUILTIN_BITSHK: case AVR_BUILTIN_HKBITS: + case AVR_BUILTIN_BITSUHR: case AVR_BUILTIN_UHRBITS: + case AVR_BUILTIN_BITSUHK: case AVR_BUILTIN_UHKBITS: + + case AVR_BUILTIN_BITSR: case AVR_BUILTIN_RBITS: + case AVR_BUILTIN_BITSK: case AVR_BUILTIN_KBITS: + case AVR_BUILTIN_BITSUR: case AVR_BUILTIN_URBITS: + case AVR_BUILTIN_BITSUK: case AVR_BUILTIN_UKBITS: + + case AVR_BUILTIN_BITSLR: case AVR_BUILTIN_LRBITS: + case AVR_BUILTIN_BITSLK: case AVR_BUILTIN_LKBITS: + case AVR_BUILTIN_BITSULR: case AVR_BUILTIN_ULRBITS: + case AVR_BUILTIN_BITSULK: case AVR_BUILTIN_ULKBITS: + + case AVR_BUILTIN_BITSLLR: case AVR_BUILTIN_LLRBITS: + case AVR_BUILTIN_BITSLLK: case AVR_BUILTIN_LLKBITS: + case AVR_BUILTIN_BITSULLR: case AVR_BUILTIN_ULLRBITS: + case AVR_BUILTIN_BITSULLK: case AVR_BUILTIN_ULLKBITS: + + gcc_assert (TYPE_PRECISION (val_type) + == TYPE_PRECISION (TREE_TYPE (arg[0]))); + + return build1 (VIEW_CONVERT_EXPR, val_type, arg[0]); + case AVR_BUILTIN_INSERT_BITS: { tree tbits = arg[1]; diff --git a/gcc/config/avr/avr.md b/gcc/config/avr/avr.md index 6432d63..e9f5d03 100644 --- a/gcc/config/avr/avr.md +++ b/gcc/config/avr/avr.md @@ -68,6 +68,7 @@ UNSPEC_COPYSIGN UNSPEC_IDENTITY UNSPEC_INSERT_BITS + UNSPEC_ROUND ]) (define_c_enum "unspecv" diff --git a/gcc/config/avr/builtins.def b/gcc/config/avr/builtins.def index ecce186..ce444ab 100644 --- a/gcc/config/avr/builtins.def +++ b/gcc/config/avr/builtins.def @@ -61,12 +61,109 @@ DEF_BUILTIN (FLASH_SEGMENT, 1, char_ftype_const_memx_ptr, flash_segment, NULL) /* 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 +DEF_BUILTIN (ABSHR, 1, hr_ftype_hr, ssabsqq2, "__ssabs_1") +DEF_BUILTIN (ABSR, 1, r_ftype_r, ssabshq2, "__ssabs_2") +DEF_BUILTIN (ABSLR, 1, lr_ftype_lr, ssabssq2, "__ssabs_4") +DEF_BUILTIN (ABSLLR, -1, llr_ftype_llr, nothing, "__ssabsdq2") // GCC extension + +DEF_BUILTIN (ABSHK, 1, hk_ftype_hk, ssabsha2, "__ssabs_2") +DEF_BUILTIN (ABSK, 1, k_ftype_k, ssabssa2, "__ssabs_4") +DEF_BUILTIN (ABSLK, -1, lk_ftype_lk, nothing, "__ssabsda2") +DEF_BUILTIN (ABSLLK, -1, llk_ftype_llk, nothing, "__ssabsta2") // GCC extension + +/* 7.18a.6.3 The fixed-point round functions. */ + +DEF_BUILTIN (ROUNDHR, 2, hr_ftype_hr_int, roundqq3, "__roundhr") +DEF_BUILTIN (ROUNDR, 2, r_ftype_r_int, roundhq3, "__roundr") +DEF_BUILTIN (ROUNDLR, 2, lr_ftype_lr_int, roundsq3, "__roundlr") +DEF_BUILTIN (ROUNDLLR, -1, llr_ftype_llr_int, nothing, "__rounddq3") // GCC extension + +DEF_BUILTIN (ROUNDUHR, 2, uhr_ftype_uhr_int, rounduqq3, "__rounduhr") +DEF_BUILTIN (ROUNDUR, 2, ur_ftype_ur_int, rounduhq3, "__roundur") +DEF_BUILTIN (ROUNDULR, 2, ulr_ftype_ulr_int, roundusq3, "__roundulr") +DEF_BUILTIN (ROUNDULLR, -1, ullr_ftype_ullr_int, nothing, "__roundudq3") // GCC extension + +DEF_BUILTIN (ROUNDHK, 2, hk_ftype_hk_int, roundha3, "__roundhk") +DEF_BUILTIN (ROUNDK, 2, k_ftype_k_int, roundsa3, "__roundk") +DEF_BUILTIN (ROUNDLK, -1, lk_ftype_lk_int, nothing, "__roundda3") +DEF_BUILTIN (ROUNDLLK, -1, llk_ftype_llk_int, nothing, "__roundta3") // GCC extension + +DEF_BUILTIN (ROUNDUHK, 2, uhk_ftype_uhk_int, rounduha3, "__rounduhk") +DEF_BUILTIN (ROUNDUK, 2, uk_ftype_uk_int, roundusa3, "__rounduk") +DEF_BUILTIN (ROUNDULK, -1, ulk_ftype_ulk_int, nothing, "__rounduda3") +DEF_BUILTIN (ROUNDULLK, -1, ullk_ftype_ullk_int, nothing, "__rounduta3") // GCC extension + +/* 7.18a.6.4 The fixed-point bit countls functions. */ + +DEF_BUILTIN (COUNTLSHR, -1, int_ftype_hr, nothing, "__countlsqi2") +DEF_BUILTIN (COUNTLSR, -1, int_ftype_r, nothing, "__countlshi2") +DEF_BUILTIN (COUNTLSLR, -1, int_ftype_lr, nothing, "__countlssi2") +DEF_BUILTIN (COUNTLSLLR, -1, int_ftype_llr, nothing, "__countlsdi2") // GCC extension + +DEF_BUILTIN (COUNTLSUHR, -1, int_ftype_uhr, nothing, "__countlsuqi2") +DEF_BUILTIN (COUNTLSUR, -1, int_ftype_ur, nothing, "__countlsuhi2") +DEF_BUILTIN (COUNTLSULR, -1, int_ftype_ulr, nothing, "__countlsusi2") +DEF_BUILTIN (COUNTLSULLR, -1, int_ftype_ullr, nothing, "__countlsudi2") // GCC extension + +DEF_BUILTIN (COUNTLSHK, -1, int_ftype_hk, nothing, "__countlshi2") +DEF_BUILTIN (COUNTLSK, -1, int_ftype_k, nothing, "__countlssi2") +DEF_BUILTIN (COUNTLSLK, -1, int_ftype_lk, nothing, "__countlsdi2") +DEF_BUILTIN (COUNTLSLLK, -1, int_ftype_llk, nothing, "__countlsdi2") // GCC extension + +DEF_BUILTIN (COUNTLSUHK, -1, int_ftype_uhk, nothing, "__countlsuhi2") +DEF_BUILTIN (COUNTLSUK, -1, int_ftype_uk, nothing, "__countlsusi2") +DEF_BUILTIN (COUNTLSULK, -1, int_ftype_ulk, nothing, "__countlsudi2") +DEF_BUILTIN (COUNTLSULLK, -1, int_ftype_ullk, nothing, "__countlsudi2") // GCC extension + +/* 7.18a.6.5 The bitwise fixed-point to integer conversion functions. */ + +DEF_BUILTIN (BITSHR, -1, inthr_ftype_hr, nothing, "__ret") +DEF_BUILTIN (BITSR, -1, intr_ftype_r, nothing, "__ret") +DEF_BUILTIN (BITSLR, -1, intlr_ftype_lr, nothing, "__ret") +DEF_BUILTIN (BITSLLR, -1, intllr_ftype_llr, nothing, "__ret") // GCC extension + +DEF_BUILTIN (BITSUHR, -1, intuhr_ftype_uhr, nothing, "__ret") +DEF_BUILTIN (BITSUR, -1, intur_ftype_ur, nothing, "__ret") +DEF_BUILTIN (BITSULR, -1, intulr_ftype_ulr, nothing, "__ret") +DEF_BUILTIN (BITSULLR, -1, intullr_ftype_ullr, nothing, "__ret") // GCC extension + +DEF_BUILTIN (BITSHK, -1, inthk_ftype_hk, nothing, "__ret") +DEF_BUILTIN (BITSK, -1, intk_ftype_k, nothing, "__ret") +DEF_BUILTIN (BITSLK, -1, intlk_ftype_lk, nothing, "__ret") +DEF_BUILTIN (BITSLLK, -1, intllk_ftype_llk, nothing, "__ret") // GCC extension + +DEF_BUILTIN (BITSUHK, -1, intuhk_ftype_uhk, nothing, "__ret") +DEF_BUILTIN (BITSUK, -1, intuk_ftype_uk, nothing, "__ret") +DEF_BUILTIN (BITSULK, -1, intulk_ftype_ulk, nothing, "__ret") +DEF_BUILTIN (BITSULLK, -1, intullk_ftype_ullk, nothing, "__ret") // GCC extension + + +/* 7.18a.6.6 The bitwise integer to fixed-point conversion functions. */ + +DEF_BUILTIN ( HRBITS, -1, hr_ftype_inthr, nothing, "__ret") +DEF_BUILTIN ( RBITS, -1, r_ftype_intr, nothing, "__ret") +DEF_BUILTIN ( LRBITS, -1, lr_ftype_intlr, nothing, "__ret") +DEF_BUILTIN ( LLRBITS, -1, llr_ftype_intllr, nothing, "__ret") // GCC extension + +DEF_BUILTIN ( UHRBITS, -1, uhr_ftype_intuhr, nothing, "__ret") +DEF_BUILTIN ( URBITS, -1, ur_ftype_intur, nothing, "__ret") +DEF_BUILTIN ( ULRBITS, -1, ulr_ftype_intulr, nothing, "__ret") +DEF_BUILTIN (ULLRBITS, -1, ullr_ftype_intullr, nothing, "__ret") // GCC extension + +DEF_BUILTIN ( HKBITS, -1, hk_ftype_inthk, nothing, "__ret") +DEF_BUILTIN ( KBITS, -1, k_ftype_intk, nothing, "__ret") +DEF_BUILTIN ( LKBITS, -1, lk_ftype_intlk, nothing, "__ret") +DEF_BUILTIN ( LLKBITS, -1, llk_ftype_intllk, nothing, "__ret") // GCC extension + +DEF_BUILTIN ( UHKBITS, -1, uhk_ftype_intuhk, nothing, "__ret") +DEF_BUILTIN ( UKBITS, -1, uk_ftype_intuk, nothing, "__ret") +DEF_BUILTIN ( ULKBITS, -1, ulk_ftype_intulk, nothing, "__ret") +DEF_BUILTIN (ULLKBITS, -1, ullk_ftype_intullk, nothing, "__ret") // GCC extension + +/* Overloaded */ + +/* 7.18a.6.7 Type-generic fixed-point functions. */ + +DEF_BUILTIN (ABSFX, -1, void_ftype_void /* dummy */, nothing, NULL) +DEF_BUILTIN (ROUNDFX, -1, void_ftype_void /* dummy */, nothing, NULL) +DEF_BUILTIN (COUNTLSFX, -1, void_ftype_void /* dummy */, nothing, NULL) diff --git a/gcc/config/avr/stdfix.h b/gcc/config/avr/stdfix.h index b86195a..afcacdf 100644 --- a/gcc/config/avr/stdfix.h +++ b/gcc/config/avr/stdfix.h @@ -35,10 +35,6 @@ #include <stdfix-gcc.h> -#define _GCC_TYPEPUN(A, B) \ - __builtin_memcpy (&A, &B, sizeof (A)) - -/* 7.18a.6 The fixed-point intrinsic functions. */ #if __SIZEOF_INT__ == 2 @@ -66,8 +62,7 @@ typedef long long unsigned int uint_ulk_t; typedef long long int int_llk_t; typedef long long unsigned int uint_ullk_t; -#else /* __SIZEOF_INT__ = 1 (for -mint8) */ - +#elif __SIZEOF_INT__ == 1 /* -mint8 */ typedef signed char int_hr_t; typedef unsigned char uint_uhr_t; @@ -84,356 +79,158 @@ typedef long long unsigned int uint_ulr_t; typedef long long int int_k_t; typedef long long unsigned int uint_uk_t; -#endif /* __SIZEOF_INT__ == 2 */ +#endif /* __SIZEOF_INT__ == 1, 2 */ + + +/* 7.18a.6 The fixed-point intrinsic functions. */ -/* 7.18a.6.2 The fixed-point absolute value functions. */ +/* 7.18a.6.2 The fixed-point absolute value functions. */ + +#define abshr __builtin_avr_abshr +#define absr __builtin_avr_absr +#define abslr __builtin_avr_abslr + +#define abshk __builtin_avr_abshk +#define absk __builtin_avr_absk + +#if __SIZEOF_INT__ == 2 + +#define abslk __builtin_avr_abslk +#define absllr __builtin_avr_absllr /* GCC Extension */ +#define absllk __builtin_avr_absllk /* GCC Extension */ -/* short fract (hr): abshr */ +#endif /* sizeof (int) == 2 */ -static __inline__ __attribute__((__always_inline__)) -short fract abshr (const short fract __q) -{ - return __builtin_avr_abshr (__q); -} -/* fract (r): absr */ +/* 7.18a.6.3 The fixed-point round functions. */ -static __inline__ __attribute__((__always_inline__)) -fract absr (const fract __q) -{ - return __builtin_avr_absr (__q); -} +/* The Embedded-C paper specifies results only for rounding points -/* long fract (lr): abslr */ + 0 < RP < FBIT + + As an extension, the following functions work as expected + with rounding points -static __inline__ __attribute__((__always_inline__)) -long fract abslr (const long fract __q) -{ - return __builtin_avr_abslr (__q); -} + -IBIT < RP < FBIT + + For example, rounding an accum with a rounding point of -1 will + result in an even integer value. */ -/* short accum (hk): abshk */ +#define roundhr __builtin_avr_roundhr +#define roundr __builtin_avr_roundr +#define roundlr __builtin_avr_roundlr -static __inline__ __attribute__((__always_inline__)) -short accum abshk (const short accum __q) -{ - return __builtin_avr_abshk (__q); -} +#define rounduhr __builtin_avr_rounduhr +#define roundur __builtin_avr_roundur +#define roundulr __builtin_avr_roundulr -/* accum (k): absk */ +#define roundhk __builtin_avr_roundhk +#define roundk __builtin_avr_roundk -static __inline__ __attribute__((__always_inline__)) -accum absk (const accum __q) -{ - return __builtin_avr_absk (__q); -} +#define rounduhk __builtin_avr_rounduhk +#define rounduk __builtin_avr_rounduk #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 */ - -static __inline__ __attribute__((__always_inline__)) -int_hr_t bitshr (const short fract __q) -{ - int_hr_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -uint_uhr_t bitsuhr (const unsigned short fract __q) -{ - uint_uhr_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -short fract hrbits (const int_hr_t __i) -{ - short fract __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -unsigned short fract uhrbits (const uint_uhr_t __i) -{ - unsigned short fract __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -/* fract (r): bitsr, bitsur, rbits, urbits */ - -static __inline__ __attribute__((__always_inline__)) -int_r_t bitsr (const fract __q) -{ - int_r_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -uint_ur_t bitsur (const unsigned fract __q) -{ - uint_ur_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -fract rbits (const int_r_t __i) -{ - fract __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -unsigned fract urbits (const uint_ur_t __i) -{ - unsigned fract __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -/* long fract (lr): bitslr, bitsulr, lrbits, ulrbits */ - -static __inline__ __attribute__((__always_inline__)) -int_lr_t bitslr (const long fract __q) -{ - int_lr_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -uint_ulr_t bitsulr (const unsigned long fract __q) -{ - uint_ulr_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -long fract lrbits (const int_lr_t __i) -{ - long fract __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -unsigned long fract ulrbits (const uint_ulr_t __i) -{ - unsigned long fract __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -/* short accum (hk): bitshk, bitsuhk, hkbits, uhkbits */ - -static __inline__ __attribute__((__always_inline__)) -int_hk_t bitshk (const short accum __q) -{ - int_hk_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -uint_uhk_t bitsuhk (const unsigned short accum __q) -{ - uint_uhk_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -short accum hkbits (const int_hk_t __i) -{ - short accum __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -unsigned short accum uhkbits (const uint_uhk_t __i) -{ - unsigned short accum __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -/* accum (k): bitsk, bitsuk, kbits, ukbits */ - -static __inline__ __attribute__((__always_inline__)) -int_k_t bitsk (const accum __q) -{ - int_k_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -uint_uk_t bitsuk (const unsigned accum __q) -{ - uint_uk_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -accum kbits (const int_k_t __i) -{ - accum __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -unsigned accum ukbits (const uint_uk_t __i) -{ - unsigned accum __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} +#define roundlk __builtin_avr_roundlk +#define roundulk __builtin_avr_roundulk +#define roundllr __builtin_avr_roundllr /* GCC Extension */ +#define roundullr __builtin_avr_roundullr /* GCC Extension */ +#define roundllk __builtin_avr_roundllk /* GCC Extension */ +#define roundullk __builtin_avr_roundullk /* GCC Extension */ + +#endif /* sizeof (int) == 2 */ + + +/* 7.18a.6.4 The fixed-point bit countls functions. */ + +#define countlshr __builtin_avr_countlshr +#define countlsr __builtin_avr_countlsr +#define countlslr __builtin_avr_countlslr + +#define countlsuhr __builtin_avr_countlsuhr +#define countlsur __builtin_avr_countlsur +#define countlsulr __builtin_avr_countlsulr + +#define countlshk __builtin_avr_countlshk +#define countlsk __builtin_avr_countlsk + +#define countlsuhk __builtin_avr_countlsuhk +#define countlsuk __builtin_avr_countlsuk #if __SIZEOF_INT__ == 2 -/* long long fract (llr): bitsllr, bitsullr, llrbits, ullrbits */ - -static __inline__ __attribute__((__always_inline__)) -int_llr_t bitsllr (const long long fract __q) -{ - int_llr_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -uint_ullr_t bitsullr (const unsigned long long fract __q) -{ - uint_ullr_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -long long fract llrbits (const int_llr_t __i) -{ - long long fract __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -unsigned long long fract ullrbits (const uint_ullr_t __i) -{ - unsigned long long fract __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -/* long accum (lk): bitslk, bitsulk, lkbits, ulkbits */ - -static __inline__ __attribute__((__always_inline__)) -int_lk_t bitslk (const long accum __q) -{ - int_lk_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -uint_ulk_t bitsulk (const unsigned long accum __q) -{ - uint_ulk_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -long accum lkbits (const int_lk_t __i) -{ - long accum __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -unsigned long accum ulkbits (const uint_ulk_t __i) -{ - unsigned long accum __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -/* long long accum (llk): bitsllk, bitsullk, llkbits, ullkbits */ - -static __inline__ __attribute__((__always_inline__)) -int_llk_t bitsllk (const long long accum __q) -{ - int_llk_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -uint_ullk_t bitsullk (const unsigned long long accum __q) -{ - uint_ullk_t __result; - _GCC_TYPEPUN (__result, __q); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -long long accum llkbits (const int_llk_t __i) -{ - long long accum __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -static __inline__ __attribute__((__always_inline__)) -unsigned long long accum ullkbits (const uint_ullk_t __i) -{ - unsigned long long accum __result; - _GCC_TYPEPUN (__result, __i); - return __result; -} - -#endif /* __SIZEOF_INT__ == 2 */ +#define countlslk __builtin_avr_countlslk +#define countlsulk __builtin_avr_countlsulk +#define countlsllr __builtin_avr_countlsllr /* GCC Extension */ +#define countlsullr __builtin_avr_countlsullr /* GCC Extension */ +#define countlsllk __builtin_avr_countlsllk /* GCC Extension */ +#define countlsullk __builtin_avr_countlsullk /* GCC Extension */ + +#endif /* sizeof (int) == 2 */ + + +/* 7.18a.6.5 The bitwise fixed-point to integer conversion functions. */ + +#define bitshr __builtin_avr_bitshr +#define bitsr __builtin_avr_bitsr +#define bitslr __builtin_avr_bitslr + +#define bitsuhr __builtin_avr_bitsuhr +#define bitsur __builtin_avr_bitsur +#define bitsulr __builtin_avr_bitsulr + +#define bitshk __builtin_avr_bitshk +#define bitsk __builtin_avr_bitsk + +#define bitsuhk __builtin_avr_bitsuhk +#define bitsuk __builtin_avr_bitsuk + +#if __SIZEOF_INT__ == 2 + +#define bitslk __builtin_avr_bitslk +#define bitsulk __builtin_avr_bitsulk +#define bitsllr __builtin_avr_bitsllr /* GCC Extension */ +#define bitsullr __builtin_avr_bitsullr /* GCC Extension */ +#define bitsllk __builtin_avr_bitsllk /* GCC Extension */ +#define bitsullk __builtin_avr_bitsullk /* GCC Extension */ + +#endif /* sizeof (int) == 2 */ + + +/* 7.18a.6.6 The bitwise integer to fixed-point conversion functions. */ + +#define hrbits __builtin_avr_hrbits +#define rbits __builtin_avr_rbits +#define lrbits __builtin_avr_lrbits + +#define uhrbits __builtin_avr_uhrbits +#define urbits __builtin_avr_urbits +#define ulrbits __builtin_avr_ulrbits + +#define hkbits __builtin_avr_hkbits +#define kbits __builtin_avr_kbits + +#define uhkbits __builtin_avr_uhkbits +#define ukbits __builtin_avr_ukbits + +#if __SIZEOF_INT__ == 2 + +#define lkbits __builtin_avr_lkbits +#define ulkbits __builtin_avr_ulkbits +#define llrbits __builtin_avr_llrbits /* GCC Extension */ +#define ullrbits __builtin_avr_ullrbits /* GCC Extension */ +#define llkbits __builtin_avr_llkbits /* GCC Extension */ +#define ullkbits __builtin_avr_ullkbits /* GCC Extension */ + +#endif /* sizeof (int) == 2 */ + + +/* 7.18a.6.7 Type-generic fixed-point functions. */ + +#define absfx __builtin_avr_absfx +#define roundfx __builtin_avr_roundfx +#define countlsfx __builtin_avr_countlsfx + #endif /* _AVRGCC_STDFIX_H */ diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog index c8ce975..c12303d 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,9 @@ +2013-02-08 Georg-Johann Lay <avr@gjlay.de> + + PR target/54222 + * gcc.target/avr/torture/builtins-4-roundfx.c: New test. + * gcc.target/avr/torture/builtins-5-countlsfx.c: New test. + 2013-02-07 Jakub Jelinek <jakub@redhat.com> PR c++/56241 diff --git a/gcc/testsuite/gcc.target/avr/torture/builtins-4-roundfx.c b/gcc/testsuite/gcc.target/avr/torture/builtins-4-roundfx.c new file mode 100644 index 0000000..6ad0775 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/builtins-4-roundfx.c @@ -0,0 +1,161 @@ +/* { dg-options "-std=gnu99" } */ +/* { dg-do run } */ + +#include <stdfix.h> + +extern void abort (void); + +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; + + +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 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; + + +#define DEFTEST1(T,FX) \ + T test1_##FX (T x, int rp) \ + { \ + return round##FX (x, rp); \ + } \ + \ + unsigned T test1_u##FX (unsigned T x, int rp) \ + { \ + return roundu##FX (x, rp); \ + } + +DEFTEST1 (short fract, hr) +DEFTEST1 (fract, r) +DEFTEST1 (long fract, lr) +DEFTEST1 (long long fract, llr) + +DEFTEST1 (short accum, hk) +DEFTEST1 (accum, k) + +DEFTEST1 (long accum, lk) +DEFTEST1 (long long accum, llk) + + +#define TEST2(FX, RP, VAL, ROUND) \ + { \ + if (round##FX (FX##bits (VAL), RP) != FX##bits (ROUND)) \ + abort(); \ + fx_##FX##_t (*f)(fx_##FX##_t,int) = round##FX; \ + asm ("" : "+r" (f)); \ + if (f (FX##bits (VAL), RP) != FX##bits (ROUND)) \ + abort(); \ + } + +static void test2hr (void) +{ + TEST2 (hr, 1, 0x7f, 0x40); + TEST2 (hr, 2, 0x7f, 0b1100000); + TEST2 (hr, 3, 0x7f, 0b1110000); + TEST2 (hr, 4, 0x7f, 0b1111000); + + TEST2 (uhr, 1, 0x7f, 0x80); + TEST2 (uhr, 2, 0x7f, 0x80); + TEST2 (uhr, 3, 0x7f, 0x80); + TEST2 (uhr, 4, 0x7f, 0x80); +} + +void test2k (void) +{ + TEST2 (k, 1, 0x7fffffff, 0x7fff8000 | 0b100000000000000); + TEST2 (k, 2, 0x7fffffff, 0x7fff8000 | 0b110000000000000); + TEST2 (k, 3, 0x7fffffff, 0x7fff8000 | 0b111000000000000); + TEST2 (k, 4, 0x7fffffff, 0x7fff8000 | 0b111100000000000); + + TEST2 (uk, 1, 0x7fffffff, 1ul << 31); + TEST2 (uk, 2, 0x7fffffff, 1ul << 31); + TEST2 (uk, 3, 0x7fffffff, 1ul << 31); + TEST2 (uk, 4, 0x7fffffff, 1ul << 31); +} + +#define DEFTEST3(FX, FBIT) \ + void test3##FX (void) \ + { \ + TEST2 (FX, FBIT-1, 0b01100, 0b01100); \ + TEST2 (FX, FBIT-2, 0b01100, 0b01100); \ + TEST2 (FX, FBIT-3, 0b01100, 0b10000); \ + TEST2 (FX, FBIT-4, 0b01100, 0b10000); \ + TEST2 (FX, FBIT-5, 0b01100, 0); \ + \ + if (FX##bits ((int_##FX##_t) -1) > 0) \ + return; \ + \ + TEST2 (FX, FBIT-1, -0b01100, -0b01100); \ + TEST2 (FX, FBIT-2, -0b01100, -0b01100); \ + TEST2 (FX, FBIT-3, -0b01100, -0b01000); \ + TEST2 (FX, FBIT-4, -0b01100, -0b10000); \ + TEST2 (FX, FBIT-5, -0b01100, -0b00000); \ + } + +DEFTEST3 (hr, SFRACT_FBIT) +DEFTEST3 (r, FRACT_FBIT) +DEFTEST3 (lr, LFRACT_FBIT) + +DEFTEST3 (uhr, USFRACT_FBIT) +DEFTEST3 (ur, UFRACT_FBIT) +DEFTEST3 (ulr, ULFRACT_FBIT) + +DEFTEST3 (hk, SACCUM_FBIT) +DEFTEST3 (k, ACCUM_FBIT) +DEFTEST3 (lk, LACCUM_FBIT) +DEFTEST3 (llk, LLACCUM_FBIT) + +DEFTEST3 (uhk, USACCUM_FBIT) +DEFTEST3 (uk, UACCUM_FBIT) +DEFTEST3 (ulk, ULACCUM_FBIT) +DEFTEST3 (ullk, ULLACCUM_FBIT) + +int main (void) +{ + test2hr(); + test2k(); + + test3hr(); + test3r(); + test3lr(); + + test3uhr(); + test3ur(); + test3ulr(); + + test3hk(); + test3k(); + test3lk(); + test3llk(); + + test3uhk(); + test3uk(); + test3ulk(); + test3ullk(); + + return 0; +} + diff --git a/gcc/testsuite/gcc.target/avr/torture/builtins-5-countlsfx.c b/gcc/testsuite/gcc.target/avr/torture/builtins-5-countlsfx.c new file mode 100644 index 0000000..b0ff5e3 --- /dev/null +++ b/gcc/testsuite/gcc.target/avr/torture/builtins-5-countlsfx.c @@ -0,0 +1,82 @@ +/* { dg-options "-std=gnu99" } */ +/* { dg-do run } */ + +#include <stdfix.h> + +extern void abort (void); + +#define DEFTEST1(T,FX) \ + int test1_##FX (T x) \ + { \ + return countls##FX (x); \ + } \ + \ + int test1_u##FX (unsigned T x) \ + { \ + return countlsu##FX (x); \ + } + +DEFTEST1 (short fract, hr) +DEFTEST1 (fract, r) +DEFTEST1 (long fract, lr) +DEFTEST1 (long long fract, llr) + +DEFTEST1 (short accum, hk) +DEFTEST1 (accum, k) +DEFTEST1 (long accum, lk) +DEFTEST1 (long long accum, llk) + + +#define TEST2P(FX, VAL, DD) \ + { \ + if (countls##FX (FX##bits (VAL)) != 8 * sizeof (0##FX) - DD) \ + abort(); \ + \ + if (countlsu##FX (u##FX##bits (VAL)) != 8 * sizeof (0u##FX) + 1 - DD) \ + abort(); \ + } + + +#define TEST2M(FX, VAL, DD) \ + { \ + if (countls##FX (FX##bits (VAL)) != 8 * sizeof (0##FX) - (DD)) \ + abort(); \ + \ + if (countlsu##FX (u##FX##bits (VAL)) != 0) \ + abort(); \ + } + + +#define TEST2PX(VAL, DD) \ + TEST2P (hr, VAL, DD); \ + TEST2P (r, VAL, DD); \ + TEST2P (lr, VAL, DD); \ + \ + TEST2P (hk, VAL, DD); \ + TEST2P (k, VAL, DD); \ + TEST2P (lk, VAL, DD); \ + TEST2P (llk, VAL, DD) + +#define TEST2MX(VAL, DD) \ + TEST2M (hr, VAL, DD); \ + TEST2M (r, VAL, DD); \ + TEST2M (lr, VAL, DD); \ + \ + TEST2M (hk, VAL, DD); \ + TEST2M (k, VAL, DD); \ + TEST2M (lk, VAL, DD); \ + TEST2M (llk, VAL, DD) + + +int main (void) +{ + TEST2PX (1, 2); + TEST2PX (2, 3); + TEST2PX (3, 3); + + TEST2MX (-1, 1); + TEST2MX (-2, 2); + TEST2MX (-3, 3); + + return 0; +} |