Patchwork [avr] Ad PR 54222: Add roundfx, countlsfx to stdfix.h

login
register
mail settings
Submitter Georg-Johann Lay
Date Feb. 7, 2013, 4:42 p.m.
Message ID <5113D983.2000002@gjlay.de>
Download mbox | patch
Permalink /patch/218953/
State New
Headers show

Comments

Georg-Johann Lay - Feb. 7, 2013, 4:42 p.m.
This patch adds more fixed-point features from embedded-C:

- roundfx rounding functions
- countlsfx bit counting functions
- add implementations of builtins so that an implementation / symbol is
  available when the address of such a function is taken

The stdfix.h header is cleaned up and just contains defines that map the
available embedded-C functions to their builtin like

#define roundr   __builtin_avr_roundr

Reasoning is

1) Is is possible to take the address of roundr

2) Some builtins might print diagnostics.  If the functions in
   stdfix.h were implemented as inline functions, the diagnose
   will point to the implementation in stdfix.h but not to the
   used code that uses the builtin with odd values.

I found no way to get the location of the argument; EXPR_LOCATION won't work,
and emitting a warning during built-in folding will show at locations more or
less randomly distributed (depending on pass) around the correct location...

The type-generic functions are implemented by overloading them.

A new, avr-specific C source is added to libgcc that is used to compile objects
to be added to libgcc.a.  The objects are compiled by iterating over the
source, which is not possible with LIB2ADD.  That is: With LIB2ADD, there would
be a bunch of new C modules, one for each function.  The new iteration scheme
is similar to iterating over libgcc sources like lib1funcs.S, fp-bit.c,
fixed-bit.c, etc.

The new test cases pass but they need the following patch to work correctly:

http://gcc.gnu.org/ml/gcc-patches/2013-02/msg00313.html

This is pending review.

Ok for trunk?

Johann


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.
Denis Chertykov - Feb. 8, 2013, 6:06 a.m.
2013/2/7 Georg-Johann Lay <avr@gjlay.de>:
> This patch adds more fixed-point features from embedded-C:
>
> - roundfx rounding functions
> - countlsfx bit counting functions
> - add implementations of builtins so that an implementation / symbol is
>   available when the address of such a function is taken
>
> The stdfix.h header is cleaned up and just contains defines that map the
> available embedded-C functions to their builtin like
>
> #define roundr   __builtin_avr_roundr
>
> Reasoning is
>
> 1) Is is possible to take the address of roundr
>
> 2) Some builtins might print diagnostics.  If the functions in
>    stdfix.h were implemented as inline functions, the diagnose
>    will point to the implementation in stdfix.h but not to the
>    used code that uses the builtin with odd values.
>
> I found no way to get the location of the argument; EXPR_LOCATION won't work,
> and emitting a warning during built-in folding will show at locations more or
> less randomly distributed (depending on pass) around the correct location...
>
> The type-generic functions are implemented by overloading them.
>
> A new, avr-specific C source is added to libgcc that is used to compile objects
> to be added to libgcc.a.  The objects are compiled by iterating over the
> source, which is not possible with LIB2ADD.  That is: With LIB2ADD, there would
> be a bunch of new C modules, one for each function.  The new iteration scheme
> is similar to iterating over libgcc sources like lib1funcs.S, fp-bit.c,
> fixed-bit.c, etc.
>
> The new test cases pass but they need the following patch to work correctly:
>
> http://gcc.gnu.org/ml/gcc-patches/2013-02/msg00313.html
>
> This is pending review.
>
> Ok for trunk?
>
> Johann
>
>
> 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.
>
>

Approved.

Denis.

Patch

Index: gcc/config/avr/avr-fixed.md
===================================================================
--- gcc/config/avr/avr-fixed.md	(revision 195736)
+++ gcc/config/avr/avr-fixed.md	(working copy)
@@ -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 @@  (define_insn "*<code><mode>3.call"
   "%~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")])
Index: gcc/config/avr/builtins.def
===================================================================
--- gcc/config/avr/builtins.def	(revision 195736)
+++ gcc/config/avr/builtins.def	(working copy)
@@ -61,12 +61,109 @@  DEF_BUILTIN (FLASH_SEGMENT, 1, char_ftyp
 
 /* 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)
Index: gcc/config/avr/stdfix.h
===================================================================
--- gcc/config/avr/stdfix.h	(revision 195736)
+++ gcc/config/avr/stdfix.h	(working copy)
@@ -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_
 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_
 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.  */
+
+#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 */
+
+#endif /* sizeof (int) == 2 */
+
+
+/* 7.18a.6.3  The fixed-point round functions.  */
+
+/* The Embedded-C paper specifies results only for rounding points
+
+       0 < RP < FBIT
+  
+   As an extension, the following functions work as expected
+   with rounding points
+
+       -IBIT < RP < FBIT
+ 
+   For example, rounding an accum with a rounding point of -1 will
+   result in an even integer value.  */
+
+#define roundhr  __builtin_avr_roundhr
+#define roundr   __builtin_avr_roundr
+#define roundlr  __builtin_avr_roundlr
 
+#define rounduhr __builtin_avr_rounduhr
+#define roundur  __builtin_avr_roundur
+#define roundulr __builtin_avr_roundulr
 
-/* 7.18a.6.2 The fixed-point absolute value functions. */
+#define roundhk  __builtin_avr_roundhk
+#define roundk   __builtin_avr_roundk
 
-/* short fract (hr): abshr */
+#define rounduhk __builtin_avr_rounduhk
+#define rounduk  __builtin_avr_rounduk
 
-static __inline__ __attribute__((__always_inline__))
-short fract abshr (const short fract __q)
-{
-  return __builtin_avr_abshr (__q);
-}
+#if __SIZEOF_INT__ == 2
+
+#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
 
-/* fract (r): absr */
+#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 */
 
-static __inline__ __attribute__((__always_inline__))
-fract absr (const fract __q)
-{
-  return __builtin_avr_absr (__q);
-}
+#endif /* sizeof (int) == 2 */
 
-/* long fract (lr): abslr */
 
-static __inline__ __attribute__((__always_inline__))
-long fract abslr (const long fract __q)
-{
-  return __builtin_avr_abslr (__q);
-}
+/* 7.18a.6.5  The bitwise fixed-point to integer conversion functions. */
 
-/* short accum (hk): abshk */
+#define bitshr  __builtin_avr_bitshr
+#define bitsr   __builtin_avr_bitsr
+#define bitslr  __builtin_avr_bitslr
 
-static __inline__ __attribute__((__always_inline__))
-short accum abshk (const short accum __q)
-{
-  return __builtin_avr_abshk (__q);
-}
+#define bitsuhr __builtin_avr_bitsuhr
+#define bitsur  __builtin_avr_bitsur
+#define bitsulr __builtin_avr_bitsulr
 
-/* accum (k): absk */
+#define bitshk  __builtin_avr_bitshk
+#define bitsk   __builtin_avr_bitsk
 
-static __inline__ __attribute__((__always_inline__))
-accum absk (const accum __q)
-{
-  return __builtin_avr_absk (__q);
-}
+#define bitsuhk __builtin_avr_bitsuhk
+#define bitsuk  __builtin_avr_bitsuk
 
 #if __SIZEOF_INT__ == 2
 
-/* long long fract (llr): absllr */
+#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
 
-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 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
 
-/* long long fract (llr): bitsllr, bitsullr, llrbits, ullrbits */
+#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.  */
 
-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;
-}
+#define absfx     __builtin_avr_absfx
+#define roundfx   __builtin_avr_roundfx
+#define countlsfx __builtin_avr_countlsfx
 
-#endif /* __SIZEOF_INT__ == 2 */
 #endif /* _AVRGCC_STDFIX_H */
Index: gcc/config/avr/avr.md
===================================================================
--- gcc/config/avr/avr.md	(revision 195736)
+++ gcc/config/avr/avr.md	(working copy)
@@ -68,6 +68,7 @@  (define_c_enum "unspec"
    UNSPEC_COPYSIGN
    UNSPEC_IDENTITY
    UNSPEC_INSERT_BITS
+   UNSPEC_ROUND
    ])
 
 (define_c_enum "unspecv"
Index: gcc/config/avr/avr-c.c
===================================================================
--- gcc/config/avr/avr-c.c	(revision 195736)
+++ gcc/config/avr/avr-c.c	(working copy)
@@ -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;
 }
 
 
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c	(revision 195736)
+++ gcc/config/avr/avr.c	(working copy)
@@ -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_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];
Index: libgcc/config/avr/lib2-object.mk
===================================================================
--- libgcc/config/avr/lib2-object.mk	(revision 0)
+++ libgcc/config/avr/lib2-object.mk	(revision 0)
@@ -0,0 +1,23 @@ 
+# This file is included several times in a row, once for each element of
+# $(iter-items).  On each inclusion, we advance $o to the next element.
+# $(iter-labels) and $(iter-flags) are also advanced.
+# This works similar to $(srcdir)/siditi-object.mk.
+
+o := $(firstword $(iter-items))
+iter-items := $(filter-out $o,$(iter-items))
+
+$o-label := $(firstword $(iter-labels))
+iter-labels := $(wordlist 2,$(words $(iter-labels)),$(iter-labels))
+
+$o-flag := $(firstword $(iter-flags))
+iter-flags := $(wordlist 2,$(words $(iter-flags)),$(iter-flags))
+
+$o$(objext): %$(objext): $(srcdir)/config/avr/lib2funcs.c
+	$(gcc_compile) -DL_$($*-label) -DL_LABEL=$($*-label) $($*-flag) \
+		-c $< $(vis_hide)
+
+ifeq ($(enable_shared),yes)
+$(o)_s$(objext): %_s$(objext): $(srcdir)/config/avr/lib2funcs.c
+	$(gcc_s_compile) -DL_$($*-label) -DL_LABEL=$($*-label) $($*-flag) \
+		-c $<
+endif
Index: libgcc/config/avr/lib1funcs-fixed.S
===================================================================
--- libgcc/config/avr/lib1funcs-fixed.S	(revision 195736)
+++ libgcc/config/avr/lib1funcs-fixed.S	(working copy)
@@ -959,6 +959,28 @@  ENDF __udivusa3
 
 
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Saturation, 1 Byte
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; First Argument and Return Register
+#define A0  24
+
+#if defined (L_ssabs_1)
+DEFUN __ssabs_1
+    sbrs    A0, 7
+    ret
+    neg     A0
+    sbrc    A0,7
+    dec     A0
+    ret
+ENDF __ssabs_1
+#endif /* L_ssabs_1 */
+
+#undef A0
+
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 ;; Saturation, 2 Bytes
 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
@@ -1176,3 +1198,509 @@  ENDF __sssub_8
 #undef B5
 #undef B6
 #undef B7
+
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Rounding Helpers
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+#ifdef L_mask1
+
+#define AA 24
+#define CC 25
+
+;; R25 = 1 << (R24 & 7)
+;; CC  = 1 << (AA  & 7)
+;; Clobbers: None
+DEFUN __mask1
+    ;; CC = 2 ^ AA.1
+    ldi     CC, 1 << 2
+    sbrs    AA, 1
+    ldi     CC, 1 << 0
+    ;; CC *= 2 ^ AA.0
+    sbrc    AA, 0
+    lsl     CC
+    ;; CC *= 2 ^ AA.2
+    sbrc    AA, 2
+    swap    CC
+    ret
+ENDF __mask1
+
+#undef AA
+#undef CC
+#endif /* L_mask1 */
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+;; The rounding point. Any bits smaller than
+;; 2^{-RP} will be cleared.
+#define RP R24
+
+#define A0 22
+#define A1 A0 + 1
+
+#define C0 24
+#define C1 C0 + 1
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Rounding, 1 Byte
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+#ifdef L_roundqq3
+
+;; R24 = round (R22, R24)
+;; Clobbers: R22, __tmp_reg__
+DEFUN  __roundqq3
+    mov     __tmp_reg__, C1
+    subi    RP, __QQ_FBIT__ - 1
+    neg     RP
+    ;; R25 = 1 << RP  (Total offset is FBIT-1 - RP)
+    XCALL   __mask1
+    mov     C0, C1
+    ;; Add-Saturate 2^{-RP-1}
+    add     A0, C0
+    brvc 0f
+    ldi     A0, 0x7f
+0:  ;; Mask out bits beyond RP
+    lsl     C0
+    neg     C0
+    and     C0, A0
+    mov     C1, __tmp_reg__
+    ret
+ENDF  __roundqq3
+#endif /* L_roundqq3 */
+
+#ifdef L_rounduqq3
+
+;; R24 = round (R22, R24)
+;; Clobbers: R22, __tmp_reg__
+DEFUN  __rounduqq3
+    mov     __tmp_reg__, C1
+    subi    RP, __UQQ_FBIT__ - 1
+    neg     RP
+    ;; R25 = 1 << RP  (Total offset is FBIT-1 - RP)
+    XCALL   __mask1
+    mov     C0, C1
+    ;; Add-Saturate 2^{-RP-1}
+    add     A0, C0
+    brcc 0f
+    ldi     A0, 0xff
+0:  ;; Mask out bits beyond RP
+    lsl     C0
+    neg     C0
+    and     C0, A0
+    mov     C1, __tmp_reg__
+    ret
+ENDF  __rounduqq3
+#endif /* L_rounduqq3 */
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Rounding, 2 Bytes
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+#ifdef L_addmask_2
+
+;; [ R25:R24 =  1 << (R24 & 15)
+;;   R23:R22 += 1 << (R24 & 15) ]
+;; SREG is set according to the addition
+DEFUN __addmask_2
+    ;; R25 = 1 << (R24 & 7)
+    XCALL   __mask1
+    cpi     RP, 1 << 3
+    sbc     C0, C0
+    ;; Swap C0 and C1 if RP.3 was set
+    and     C0, C1
+    eor     C1, C0
+    ;; Finally, add the power-of-two:  A[] += C[]
+    add     A0, C0
+    adc     A1, C1
+    ret
+ENDF  __addmask_2
+#endif /* L_addmask_2 */
+
+#ifdef L_round_s2
+
+;; R25:R24 = round (R23:R22, R24)
+;; Clobbers: R23, R22
+DEFUN  __roundhq3
+    subi    RP, __HQ_FBIT__ - __HA_FBIT__
+ENDF   __roundhq3
+DEFUN  __roundha3
+    subi    RP, __HA_FBIT__ - 1
+    neg     RP
+    ;; [ R25:R24  = 1 << (FBIT-1 - RP)
+    ;;   R23:R22 += 1 << (FBIT-1 - RP) ]
+    XCALL   __addmask_2
+    XJMP    __round_s2_const
+ENDF  __roundha3
+
+#endif /* L_round_s2 */
+
+#ifdef L_round_u2
+
+;; R25:R24 = round (R23:R22, R24)
+;; Clobbers: R23, R22
+DEFUN  __rounduhq3
+    subi    RP, __UHQ_FBIT__ - __UHA_FBIT__
+ENDF   __rounduhq3
+DEFUN  __rounduha3
+    subi    RP, __UHA_FBIT__ - 1
+    neg     RP
+    ;; [ R25:R24  = 1 << (FBIT-1 - RP)
+    ;;   R23:R22 += 1 << (FBIT-1 - RP) ]
+    XCALL   __addmask_2
+    XJMP    __round_u2_const 
+ENDF  __rounduha3
+
+#endif /* L_round_u2 */
+
+
+#ifdef L_round_2_const
+
+;; Helpers for 2 byte wide rounding
+
+DEFUN  __round_s2_const
+    brvc 2f
+    ldi     A1, 0x7f
+    rjmp 1f
+    ;; FALLTHRU (Barrier)
+ENDF  __round_s2_const
+
+DEFUN __round_u2_const
+    brcc 2f
+    ldi     A1, 0xff
+1:
+    ldi     A0, 0xff
+2:
+    ;; Saturation is performed now.
+    ;; Currently, we have C[] = 2^{-RP-1}
+    ;; C[] = 2^{-RP}
+    lsl     C0
+    rol     C1
+    ;;      
+    NEG2    C0
+    ;; Clear the bits beyond the rounding point.
+    and     C0, A0
+    and     C1, A1
+    ret
+ENDF  __round_u2_const
+
+#endif /* L_round_2_const */
+
+#undef A0
+#undef A1
+#undef C0
+#undef C1
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Rounding, 4 Bytes
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+#define A0 18
+#define A1 A0 + 1
+#define A2 A0 + 2
+#define A3 A0 + 3
+
+#define C0 22
+#define C1 C0 + 1
+#define C2 C0 + 2
+#define C3 C0 + 3
+
+#ifdef L_addmask_4
+
+;; [ R25:R22 =  1 << (R24 & 31)
+;;   R21:R18 += 1 << (R24 & 31) ]
+;; SREG is set according to the addition
+DEFUN __addmask_4
+    ;; R25 = 1 << (R24 & 7)
+    XCALL   __mask1
+    cpi     RP, 1 << 4
+    sbc     C0, C0
+    sbc     C1, C1
+    ;; Swap C2 with C3 if RP.3 is not set
+    cpi     RP, 1 << 3
+    sbc     C2, C2
+    and     C2, C3
+    eor     C3, C2
+    ;; Swap C3:C2 with C1:C0 if RP.4 is not set
+    and     C0, C2  $  eor     C2, C0
+    and     C1, C3  $  eor     C3, C1
+    ;; Finally, add the power-of-two:  A[] += C[]
+    add     A0, C0
+    adc     A1, C1
+    adc     A2, C2
+    adc     A3, C3
+    ret
+ENDF  __addmask_4
+#endif /* L_addmask_4 */
+
+#ifdef L_round_s4
+
+;; R25:R22 = round (R21:R18, R24)
+;; Clobbers: R18...R21
+DEFUN  __roundsq3
+    subi    RP, __SQ_FBIT__ - __SA_FBIT__
+ENDF   __roundsq3
+DEFUN  __roundsa3
+    subi    RP, __SA_FBIT__ - 1
+    neg     RP
+    ;; [ R25:R22  = 1 << (FBIT-1 - RP)
+    ;;   R21:R18 += 1 << (FBIT-1 - RP) ]
+    XCALL   __addmask_4
+    XJMP    __round_s4_const
+ENDF  __roundsa3
+
+#endif /* L_round_s4 */
+
+#ifdef L_round_u4
+
+;; R25:R22 = round (R21:R18, R24)
+;; Clobbers: R18...R21
+DEFUN  __roundusq3
+    subi    RP, __USQ_FBIT__ - __USA_FBIT__
+ENDF   __roundusq3
+DEFUN  __roundusa3
+    subi    RP, __USA_FBIT__ - 1
+    neg     RP
+    ;; [ R25:R22  = 1 << (FBIT-1 - RP)
+    ;;   R21:R18 += 1 << (FBIT-1 - RP) ]
+    XCALL   __addmask_4
+    XJMP    __round_u4_const 
+ENDF  __roundusa3
+
+#endif /* L_round_u4 */
+
+
+#ifdef L_round_4_const
+
+;; Helpers for 4 byte wide rounding
+
+DEFUN  __round_s4_const
+    brvc 2f
+    ldi     A3, 0x7f
+    rjmp 1f
+    ;; FALLTHRU (Barrier)
+ENDF  __round_s4_const
+
+DEFUN __round_u4_const
+    brcc 2f
+    ldi     A3, 0xff
+1:
+    ldi     A2, 0xff
+    ldi     A1, 0xff
+    ldi     A0, 0xff
+2:
+    ;; Saturation is performed now.
+    ;; Currently, we have C[] = 2^{-RP-1}
+    ;; C[] = 2^{-RP}
+    lsl     C0
+    rol     C1
+    rol     C2
+    rol     C3
+    XCALL   __negsi2
+    ;; Clear the bits beyond the rounding point.
+    and     C0, A0
+    and     C1, A1
+    and     C2, A2
+    and     C3, A3
+    ret
+ENDF  __round_u4_const
+
+#endif /* L_round_4_const */
+
+#undef A0
+#undef A1
+#undef A2
+#undef A3
+#undef C0
+#undef C1
+#undef C2
+#undef C3
+
+#undef RP
+
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+;; Rounding, 8 Bytes
+;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+
+#define RP     16
+#define FBITm1 31
+
+#define C0 18
+#define C1 C0 + 1
+#define C2 C0 + 2
+#define C3 C0 + 3
+#define C4 C0 + 4
+#define C5 C0 + 5
+#define C6 C0 + 6
+#define C7 C0 + 7
+
+#define A0 16
+#define A1 17
+#define A2 26
+#define A3 27
+#define A4 28
+#define A5 29
+#define A6 30
+#define A7 31
+
+
+#ifdef L_rounddq3
+;; R25:R18 = round (R25:R18, R16)
+;; Clobbers: ABI
+DEFUN  __rounddq3
+    ldi     FBITm1, __DQ_FBIT__ - 1
+    clt
+    XJMP    __round_x8
+ENDF  __rounddq3
+#endif /* L_rounddq3 */
+
+#ifdef L_roundudq3
+;; R25:R18 = round (R25:R18, R16)
+;; Clobbers: ABI
+DEFUN  __roundudq3
+    ldi     FBITm1, __UDQ_FBIT__ - 1
+    set
+    XJMP    __round_x8
+ENDF  __roundudq3
+#endif /* L_roundudq3 */
+
+#ifdef L_roundda3
+;; R25:R18 = round (R25:R18, R16)
+;; Clobbers: ABI
+DEFUN  __roundda3
+    ldi     FBITm1, __DA_FBIT__ - 1
+    clt
+    XJMP    __round_x8
+ENDF  __roundda3
+#endif /* L_roundda3 */
+
+#ifdef L_rounduda3
+;; R25:R18 = round (R25:R18, R16)
+;; Clobbers: ABI
+DEFUN  __rounduda3
+    ldi     FBITm1, __UDA_FBIT__ - 1
+    set
+    XJMP    __round_x8
+ENDF  __rounduda3
+#endif /* L_rounduda3 */
+
+#ifdef L_roundta3
+;; R25:R18 = round (R25:R18, R16)
+;; Clobbers: ABI
+DEFUN  __roundta3
+    ldi     FBITm1, __TA_FBIT__ - 1
+    clt
+    XJMP    __round_x8
+ENDF  __roundta3
+#endif /* L_roundta3 */
+
+#ifdef L_rounduta3
+;; R25:R18 = round (R25:R18, R16)
+;; Clobbers: ABI
+DEFUN  __rounduta3
+    ldi     FBITm1, __UTA_FBIT__ - 1
+    set
+    XJMP    __round_x8
+ENDF  __rounduta3
+#endif /* L_rounduta3 */
+
+
+#ifdef L_round_x8
+DEFUN __round_x8
+    push r16
+    push r17
+    push r28
+    push r29
+    ;; Compute log2 of addend from rounding point
+    sub     RP, FBITm1
+    neg     RP
+    ;; Move input to work register A[]
+    push    C0
+    mov     A1, C1
+    wmov    A2, C2
+    wmov    A4, C4
+    wmov    A6, C6
+    ;; C[] = 1 << (FBIT-1 - RP)
+    XCALL   __clr_8
+    inc     C0
+    XCALL   __ashldi3
+    pop     A0
+    ;; A[] += C[]
+    add     A0, C0
+    adc     A1, C1
+    adc     A2, C2
+    adc     A3, C3
+    adc     A4, C4
+    adc     A5, C5
+    adc     A6, C6
+    adc     A7, C7
+    brts    1f
+    ;; Signed
+    brvc    3f
+    ;; Signed overflow: A[] = 0x7f...
+    brvs    2f
+1:  ;; Unsigned
+    brcc    3f
+    ;; Unsigned overflow: A[] = 0xff...
+2:  ldi     A7, 0xff
+    ldi     A6, 0xff
+    wmov    A0, A6
+    wmov    A2, A6
+    wmov    A4, A6
+    bld     A7, 7
+3:
+    ;;  C[] = -C[] - C[]
+    push    A0
+    ldi     r16, 1
+    XCALL   __ashldi3
+    pop     A0
+    XCALL   __negdi2
+    ;; Clear the bits beyond the rounding point.
+    and     C0, A0
+    and     C1, A1
+    and     C2, A2
+    and     C3, A3
+    and     C4, A4
+    and     C5, A5
+    and     C6, A6
+    and     C7, A7
+    ;; Epilogue
+    pop r29
+    pop r28
+    pop r17
+    pop r16
+    ret
+ENDF  __round_x8
+
+#endif /* L_round_x8 */
+
+#undef A0
+#undef A1
+#undef A2
+#undef A3
+#undef A4
+#undef A5
+#undef A6
+#undef A7
+
+#undef C0
+#undef C1
+#undef C2
+#undef C3
+#undef C4
+#undef C5
+#undef C6
+#undef C7
+
+#undef RP
+#undef FBITm1
+
+
+;; Supply implementations / symbols for the bit-banging functions
+;; __builtin_avr_bitsfx and __builtin_avr_fxbits
+#ifdef L_ret
+DEFUN __ret
+    ret
+ENDF  __ret
+#endif /* L_ret */
Index: libgcc/config/avr/lib1funcs.S
===================================================================
--- libgcc/config/avr/lib1funcs.S	(revision 195736)
+++ libgcc/config/avr/lib1funcs.S	(working copy)
@@ -1684,12 +1684,12 @@  DEFUN  __divdi3_moddi3
 
 ENDF __divdi3_moddi3
 
+#endif /* L_divdi3 */
+
 #undef R_cnt
 #undef SS
 #undef NN
 
-#endif /* L_divdi3 */
-
 .section .text.libgcc, "ax", @progbits
 
 #define TT __tmp_reg__
Index: libgcc/config/avr/lib2funcs.c
===================================================================
--- libgcc/config/avr/lib2funcs.c	(revision 0)
+++ libgcc/config/avr/lib2funcs.c	(revision 0)
@@ -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 */
Index: libgcc/config/avr/t-avr
===================================================================
--- libgcc/config/avr/t-avr	(revision 195736)
+++ libgcc/config/avr/t-avr	(working copy)
@@ -75,13 +75,24 @@  LIB1ASMFUNCS += \
 	_divsa3 _udivusa3 \
 	_clr_8 \
 	_ssneg_2 _ssneg_4 _ssneg_8 \
-	_ssabs_2 _ssabs_4 _ssabs_8 \
+	_ssabs_1 _ssabs_2 _ssabs_4 _ssabs_8 \
 	_ssadd_8 _sssub_8 \
-	_usadd_8 _ussub_8
+	_usadd_8 _ussub_8 \
+	_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 \
+
 
 LIB2FUNCS_EXCLUDE = \
 	_moddi3 _umoddi3 \
-	_clz
+	_clz \
+	_clrsbdi2 \
+
 
 # We do not have the DF type.
 # Most of the C functions in libgcc2 use almost all registers,
@@ -106,13 +117,84 @@  ifeq ($(enable_shared),yes)
 libgcc-s-objects += $(patsubst %,%_s$(objext),$(hiintfuncs16))
 endif
 
-
-# Filter out supported conversions from fixed-bit.c
-# Also filter out TQ and UTQ.
+###
 
 conv_XY=$(conv)$(mode1)$(mode2)
 func_X=$(func)$(mode)
 
+# Compile C functions from lib2funcs.c and add them to libgcc.a.
+#
+# Some functions which are not performance.critical are more convenient
+# to implement in C than in assembler.  Most of them serve as implementation
+# for AVR-specific builtins in the case where the address of a builtin
+# function is taken or if there is no insn that implements the builtin.
+#
+# We don't use LIB2ADD because we want to iterate over the source for
+# different modes, fixed-point suffixes, etc.  See iter-labels and L_LABEL.
+# iter-label will get one more underscore in order to avoid too short
+# labels like -DLk and we use -DL_k instead.
+
+# Build roundFX functions from lib2funcs.c
+
+round_suffix :=  hr r lr uhr ur ulr  \
+		 hk k    uhk uk 
+round_funcs  := $(foreach func,_round,\
+		$(foreach mode,$(round_suffix),$(func_X)))
+
+iter-items  := $(round_funcs)
+iter-labels := $(round_suffix)
+iter-flags  := $(patsubst %,-DL_round,$(iter-items))
+
+include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
+
+libgcc-objects += $(patsubst %,%$(objext),$(round_funcs))
+
+# Build clrsbXX functions from lib2funcs.c
+
+clrsb_modes := qi di
+clrsb_funcs := $(foreach func,_clrsb,\
+	       $(foreach mode,$(clrsb_modes),$(func_X)))
+
+iter-items  := $(clrsb_funcs)
+iter-labels := $(clrsb_funcs)
+iter-flags  := $(patsubst %,-DL_clrsb,$(iter-items))
+
+include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
+
+libgcc-objects += $(patsubst %,%$(objext),$(clrsb_funcs))
+
+# Build signed countlsFX functions from lib2funcs.c
+
+countls_modes := qi hi si di
+countls_funcs := $(foreach func,_countls,\
+		 $(foreach mode,$(countls_modes),$(func_X)))
+
+iter-items  := $(countls_funcs)
+iter-labels := $(countls_modes)
+iter-flags  := $(patsubst %,-DL_countls,$(iter-items))
+
+include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
+
+libgcc-objects += $(patsubst %,%$(objext),$(countls_funcs))
+
+# Build unsigned countlsFX functions from lib2funcs.c
+
+countlsu_modes := qi hi si di
+countlsu_funcs := $(foreach func,_countlsu,\
+		  $(foreach mode,$(countlsu_modes),$(func_X)))
+
+iter-items  := $(countlsu_funcs)
+iter-labels := $(countlsu_modes)
+iter-flags  := $(patsubst %,-DL_countlsu,$(iter-items))
+
+include $(srcdir)/empty.mk $(patsubst %,$(srcdir)/config/avr/lib2-object.mk,$(iter-items))
+
+libgcc-objects += $(patsubst %,%$(objext),$(countlsu_funcs))
+
+
+# Filter out supported conversions from fixed-bit.c
+# Also filter out TQ and UTQ.
+
 # Conversions supported by the compiler
 
 convf_modes =	 QI UQI QQ UQQ \
Index: gcc/testsuite/gcc.target/avr/torture/builtins-4-roundfx.c
===================================================================
--- gcc/testsuite/gcc.target/avr/torture/builtins-4-roundfx.c	(revision 0)
+++ gcc/testsuite/gcc.target/avr/torture/builtins-4-roundfx.c	(revision 0)
@@ -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;
+}
+
Index: gcc/testsuite/gcc.target/avr/torture/builtins-5-countlsfx.c
===================================================================
--- gcc/testsuite/gcc.target/avr/torture/builtins-5-countlsfx.c	(revision 0)
+++ gcc/testsuite/gcc.target/avr/torture/builtins-5-countlsfx.c	(revision 0)
@@ -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;
+}