[avr] PR92055: Add switches to enable 64-bit [long] double.
diff mbox series

Message ID 5DBB585D.1090108@gjlay.de
State New
Headers show
Series
  • [avr] PR92055: Add switches to enable 64-bit [long] double.
Related show

Commit Message

Georg-Johann Lay Oct. 31, 2019, 9:55 p.m. UTC
Hi, this adds the possibility to enable IEEE compatible double
and long double support in avr-gcc.

It supports 2 configure options

--with-double={32|64|32,64|64,32}
--with-long-double={32|64|32,64|64,32|double}

which select the default layout of these types and also chose
which mutlilib variants are built and available.

These two config option map to the new compiler options
-mdouble= and -mlong-double= which are new multilib options.

The patch only deals with option handling and multilib bits,
it does not add any double functionality.  The double support
functions are supposed to be provided by avr-libc which also hosts
all the float stuff, including __addsf3 etc.

Ok for trunk?

Johann


gcc/
	Support 64-bit double and 64-bit long double configurations.

	PR target/92055
	* config.gcc (tm_defines) [avr]: Set from --with-double=,
	--with-long-double=.
	* config/avr/t-multilib: Remove.
	* config/avr/t-avr: Output of genmultilib.awk is now fully
	dynamically generated and no more part of the repo.
	(HAVE_DOUBLE_MULTILIB, HAVE_LONG_DOUBLE_MULTILIB): New variables.
	Pass them down to...
	* config/avr/genmultilib.awk: ...here and handle them.
	* gcc/config/avr/avr.opt (-mdouble=, avr_double). New option and var.
	(-mlong-double=, avr_long_double). New option and var.
	* common/config/avr/avr-common.c (opts.h): Include.
	(diagnostic.h): Include.
	(TARGET_OPTION_OPTIMIZATION_TABLE) <-mdouble=>: Set default as
	requested by --with-double=.
	<-mlong-double=>: Set default as requested by --with-long-double=.
	(TARGET_OPTION_OPTIMIZATION_TABLE) <-mdouble=, -mlong-double=>:
	Set default as requested by --with-double=
	(TARGET_HANDLE_OPTION): Define to this...
	(avr_handle_option): ...new hook worker.
	* config/avr/avr.h (DOUBLE_TYPE_SIZE): Define to avr_double.
	(LONG_DOUBLE_TYPE_SIZE): Define to avr_long_double.
	(avr_double_lib): New proto for spec function.
	(EXTRA_SPEC_FUNCTIONS) <double-lib>: Add.
	(DRIVER_SELF_SPECS): Call %:double-lib.
	* config/avr/avr.c (avr_option_override): Assert
	sizeof(long double) >= sizeof(double) for the target.
	* config/avr/avr-c.c (avr_cpu_cpp_builtins)
	[__HAVE_DOUBLE_MULTILIB__, __HAVE_LONG_DOUBLE_MULTILIB__]
	[__HAVE_DOUBLE64__, __HAVE_DOUBLE32__, __DEFAULT_DOUBLE__=]
	[__HAVE_LONG_DOUBLE64__, __HAVE_LONG_DOUBLE32__]
	[__HAVE_LONG_DOUBLE_IS_DOUBLE__, __DEFAULT_LONG_DOUBLE__=]:
	New built-in defined depending on --with-double=, --with-long-double=.
	* config/avr/driver-avr.c (avr_double_lib): New spec function.
	* doc/invoke.tex (AVR Options) <-mdouble=,-mlong-double=>: Doc.

libgcc/
	Support 64-bit double and 64-bit long double configurations.

	PR target/92055
	* config/avr/t-avr (HOST_LIBGCC2_CFLAGS): Only add -DF=SF if
	long double is a 32-bit type.
	* config/avr/t-avrlibc: Copy double64 and long-double64
	multilib(s) from the vanilla one.
	* config/avr/t-copy-libgcc: New Makefile snip.

Comments

Georg-Johann Lay Nov. 6, 2019, 10:39 a.m. UTC | #1
Ping #1

Am 31.10.19 um 22:55 schrieb Georg-Johann Lay:
> Hi, this adds the possibility to enable IEEE compatible double
> and long double support in avr-gcc.
> 
> It supports 2 configure options
> 
> --with-double={32|64|32,64|64,32}
> --with-long-double={32|64|32,64|64,32|double}
> 
> which select the default layout of these types and also chose
> which mutlilib variants are built and available.
> 
> These two config option map to the new compiler options
> -mdouble= and -mlong-double= which are new multilib options.
> 
> The patch only deals with option handling and multilib bits,
> it does not add any double functionality.  The double support
> functions are supposed to be provided by avr-libc which also hosts
> all the float stuff, including __addsf3 etc.
> 
> Ok for trunk?
> 
> Johann
> 
> 
> gcc/
>      Support 64-bit double and 64-bit long double configurations.
> 
>      PR target/92055
>      * config.gcc (tm_defines) [avr]: Set from --with-double=,
>      --with-long-double=.
>      * config/avr/t-multilib: Remove.
>      * config/avr/t-avr: Output of genmultilib.awk is now fully
>      dynamically generated and no more part of the repo.
>      (HAVE_DOUBLE_MULTILIB, HAVE_LONG_DOUBLE_MULTILIB): New variables.
>      Pass them down to...
>      * config/avr/genmultilib.awk: ...here and handle them.
>      * gcc/config/avr/avr.opt (-mdouble=, avr_double). New option and var.
>      (-mlong-double=, avr_long_double). New option and var.
>      * common/config/avr/avr-common.c (opts.h): Include.
>      (diagnostic.h): Include.
>      (TARGET_OPTION_OPTIMIZATION_TABLE) <-mdouble=>: Set default as
>      requested by --with-double=.
>      <-mlong-double=>: Set default as requested by 
> --with-long-double=.
>      (TARGET_OPTION_OPTIMIZATION_TABLE) <-mdouble=, -mlong-double=>:
>      Set default as requested by --with-double=
>      (TARGET_HANDLE_OPTION): Define to this...
>      (avr_handle_option): ...new hook worker.
>      * config/avr/avr.h (DOUBLE_TYPE_SIZE): Define to avr_double.
>      (LONG_DOUBLE_TYPE_SIZE): Define to avr_long_double.
>      (avr_double_lib): New proto for spec function.
>      (EXTRA_SPEC_FUNCTIONS) <double-lib>: Add.
>      (DRIVER_SELF_SPECS): Call %:double-lib.
>      * config/avr/avr.c (avr_option_override): Assert
>      sizeof(long double) >= sizeof(double) for the target.
>      * config/avr/avr-c.c (avr_cpu_cpp_builtins)
>      [__HAVE_DOUBLE_MULTILIB__, __HAVE_LONG_DOUBLE_MULTILIB__]
>      [__HAVE_DOUBLE64__, __HAVE_DOUBLE32__, __DEFAULT_DOUBLE__=]
>      [__HAVE_LONG_DOUBLE64__, __HAVE_LONG_DOUBLE32__]
>      [__HAVE_LONG_DOUBLE_IS_DOUBLE__, __DEFAULT_LONG_DOUBLE__=]:
>      New built-in defined depending on --with-double=, --with-long-double=.
>      * config/avr/driver-avr.c (avr_double_lib): New spec function.
>      * doc/invoke.tex (AVR Options) <-mdouble=,-mlong-double=>: Doc.
> 
> libgcc/
>      Support 64-bit double and 64-bit long double configurations.
> 
>      PR target/92055
>      * config/avr/t-avr (HOST_LIBGCC2_CFLAGS): Only add -DF=SF if
>      long double is a 32-bit type.
>      * config/avr/t-avrlibc: Copy double64 and long-double64
>      multilib(s) from the vanilla one.
>      * config/avr/t-copy-libgcc: New Makefile snip.
Georg-Johann Lay Nov. 6, 2019, 3:05 p.m. UTC | #2
Am 06.11.19 um 11:39 schrieb Georg-Johann Lay:
> Ping #1
> 
> Am 31.10.19 um 22:55 schrieb Georg-Johann Lay:
>> Hi, this adds the possibility to enable IEEE compatible double
>> and long double support in avr-gcc.
>>
>> It supports 2 configure options
>>
>> --with-double={32|64|32,64|64,32}
>> --with-long-double={32|64|32,64|64,32|double}
>>
>> which select the default layout of these types and also chose
>> which mutlilib variants are built and available.
>>
>> These two config option map to the new compiler options
>> -mdouble= and -mlong-double= which are new multilib options.
>>
>> The patch only deals with option handling and multilib bits,
>> it does not add any double functionality.  The double support
>> functions are supposed to be provided by avr-libc which also hosts
>> all the float stuff, including __addsf3 etc.
>>
>> Ok for trunk?
>>
>> Johann

..and here is the addendum that documents the new configure options.

Index: gcc/doc/install.texi
===================================================================
--- gcc/doc/install.texi	(revision 277236)
+++ gcc/doc/install.texi	(working copy)
@@ -2277,15 +2277,45 @@ omitted from @file{libgcc.a} on the assu
  @samp{newlib}.

  @item --with-avrlibc
-Specifies that @samp{AVR-Libc} is
-being used as the target C library.  This causes float support
+Only supported for the AVR target. Specifies that @samp{AVR-Libc} is
+being used as the target C@tie{} library.  This causes float support
  functions like @code{__addsf3} to be omitted from @file{libgcc.a} on
  the assumption that it will be provided by @file{libm.a}.  For more
  technical details, cf. @uref{http://gcc.gnu.org/PR54461,,PR54461}.
-This option is only supported for the AVR target.  It is not supported for
+It is not supported for
  RTEMS configurations, which currently use newlib.  The option is
  supported since version 4.7.2 and is the default in 4.8.0 and newer.

+@item --with-double=@{32|64|32,64|64,32@}
+@itemx --with-long-double=@{32|64|32,64|64,32|double@}
+Only supported for the AVR target since version@tie{}10.
+Specify the default layout available for the C/C++ @samp{double}
+and @samp{long double} type, respectively. The following rules apply:
+@itemize
+@item
+The first value after the @samp{=} specifies the default layout (in bits)
+of the type and also the default for the @option{-mdouble=} resp.
+@option{-mlong-double=} compiler option.
+@item
+If more than one value is specified, respective multilib variants are
+available, and  @option{-mdouble=} resp. @option{-mlong-double=} acts
+as a multilib option.
+@item
+If @option{--with-long-double=double} is specified, @samp{double} and
+@samp{long double} will have the same layout.
+@item
+If the configure option is not set, it defaults to @samp{32} which
+is compatible with older versions of the compiler that use non-standard
+32-bit types for @samp{double} and @samp{long double}.
+@end itemize
+Not all combinations of @option{--with-double=} and
+@option{--with-long-double=} are valid.  For example, the combination
+@option{--with-double=32,64} @option{--with-long-double=32} will be
+rejected because the first option specifies the availability of
+multilibs for @samp{double}, whereas the second option implies
+that @samp{long double} --- and hence also @samp{double} --- is always
+32@tie{}bits wide.
+
  @item --with-nds32-lib=@var{library}
  Specifies that @var{library} setting is used for building @file{libgcc.a}.
  Currently, the valid @var{library} is @samp{newlib} or @samp{mculib}.
Jeff Law Nov. 6, 2019, 10:32 p.m. UTC | #3
On 10/31/19 3:55 PM, Georg-Johann Lay wrote:
> Hi, this adds the possibility to enable IEEE compatible double
> and long double support in avr-gcc.
> 
> It supports 2 configure options
> 
> --with-double={32|64|32,64|64,32}
> --with-long-double={32|64|32,64|64,32|double}
> 
> which select the default layout of these types and also chose
> which mutlilib variants are built and available.
> 
> These two config option map to the new compiler options
> -mdouble= and -mlong-double= which are new multilib options.
> 
> The patch only deals with option handling and multilib bits,
> it does not add any double functionality.  The double support
> functions are supposed to be provided by avr-libc which also hosts
> all the float stuff, including __addsf3 etc.
> 
> Ok for trunk?
> 
> Johann
> 
> 
> gcc/
>     Support 64-bit double and 64-bit long double configurations.
> 
>     PR target/92055
>     * config.gcc (tm_defines) [avr]: Set from --with-double=,
>     --with-long-double=.
>     * config/avr/t-multilib: Remove.
>     * config/avr/t-avr: Output of genmultilib.awk is now fully
>     dynamically generated and no more part of the repo.
>     (HAVE_DOUBLE_MULTILIB, HAVE_LONG_DOUBLE_MULTILIB): New variables.
>     Pass them down to...
>     * config/avr/genmultilib.awk: ...here and handle them.
>     * gcc/config/avr/avr.opt (-mdouble=, avr_double). New option and var.
>     (-mlong-double=, avr_long_double). New option and var.
>     * common/config/avr/avr-common.c (opts.h): Include.
>     (diagnostic.h): Include.
>     (TARGET_OPTION_OPTIMIZATION_TABLE) <-mdouble=>: Set default as
>     requested by --with-double=.
>     <-mlong-double=>: Set default as requested by --with-long-double=.
> 
>     (TARGET_OPTION_OPTIMIZATION_TABLE) <-mdouble=, -mlong-double=>:
>     Set default as requested by --with-double=
>     (TARGET_HANDLE_OPTION): Define to this...
>     (avr_handle_option): ...new hook worker.
>     * config/avr/avr.h (DOUBLE_TYPE_SIZE): Define to avr_double.
>     (LONG_DOUBLE_TYPE_SIZE): Define to avr_long_double.
>     (avr_double_lib): New proto for spec function.
>     (EXTRA_SPEC_FUNCTIONS) <double-lib>: Add.
>     (DRIVER_SELF_SPECS): Call %:double-lib.
>     * config/avr/avr.c (avr_option_override): Assert
>     sizeof(long double) >= sizeof(double) for the target.
>     * config/avr/avr-c.c (avr_cpu_cpp_builtins)
>     [__HAVE_DOUBLE_MULTILIB__, __HAVE_LONG_DOUBLE_MULTILIB__]
>     [__HAVE_DOUBLE64__, __HAVE_DOUBLE32__, __DEFAULT_DOUBLE__=]
>     [__HAVE_LONG_DOUBLE64__, __HAVE_LONG_DOUBLE32__]
>     [__HAVE_LONG_DOUBLE_IS_DOUBLE__, __DEFAULT_LONG_DOUBLE__=]:
>     New built-in defined depending on --with-double=, --with-long-double=.
>     * config/avr/driver-avr.c (avr_double_lib): New spec function.
>     * doc/invoke.tex (AVR Options) <-mdouble=,-mlong-double=>: Doc.
> 
> libgcc/
>     Support 64-bit double and 64-bit long double configurations.
> 
>     PR target/92055
>     * config/avr/t-avr (HOST_LIBGCC2_CFLAGS): Only add -DF=SF if
>     long double is a 32-bit type.
>     * config/avr/t-avrlibc: Copy double64 and long-double64
>     multilib(s) from the vanilla one.
>     * config/avr/t-copy-libgcc: New Makefile snip.
> 
OK
jeff
Martin Liška Nov. 7, 2019, 9:41 a.m. UTC | #4
Hello.

I've noticed quite some GNU coding style violations with your patch.
Please next time, use something like:

$ git diff HEAD~ > /tmp/patch && ./contrib/check_GNU_style.py /tmp/patch

Thanks,
Martin
Georg-Johann Lay Nov. 7, 2019, 12:39 p.m. UTC | #5
Am 07.11.19 um 10:41 schrieb Martin Liška:
> Hello.
> 
> I've noticed quite some GNU coding style violations with your patch.
> Please next time, use something like:
> 
> $ git diff HEAD~ > /tmp/patch && ./contrib/check_GNU_style.py /tmp/patch
> 
> Thanks,
> Martin
> 

hm, I am actually using GNU style with Emacs...

You mean the lines > 80 chars in config.gcc?

I assumed that is no issue because there are already quite some lines 
that don't follow the < 80 rule.

Johann
Martin Liška Nov. 7, 2019, 12:49 p.m. UTC | #6
On 11/7/19 1:39 PM, Georg-Johann Lay wrote:
> Am 07.11.19 um 10:41 schrieb Martin Liška:
>> Hello.
>>
>> I've noticed quite some GNU coding style violations with your patch.
>> Please next time, use something like:
>>
>> $ git diff HEAD~ > /tmp/patch && ./contrib/check_GNU_style.py /tmp/patch
>>
>> Thanks,
>> Martin
>>
> 
> hm, I am actually using GNU style with Emacs...
> 
> You mean the lines > 80 chars in config.gcc?
> 
> I assumed that is no issue because there are already quite some lines that don't follow the < 80 rule.

That's fine. I'm mainly talking about:

=== ERROR type #1: blocks of 8 spaces should be replaced with tabs (45 error(s)) ===
gcc/common/config/avr/avr-common.c:78:0:████████████████   const struct cl_decoded_option *decoded, location_t loc)
gcc/common/config/avr/avr-common.c:86:0:████████{
gcc/common/config/avr/avr-common.c:88:0:████████  error_at (loc, "option %<-mdouble=64%> is only available if "
gcc/common/config/avr/avr-common.c:89:0:████████████████    "configured %<--with-double={64|64,32|32,64}%>");
gcc/common/config/avr/avr-common.c:91:0:████████  opts->x_avr_long_double = 64;
gcc/common/config/avr/avr-common.c:92:0:████████}
gcc/common/config/avr/avr-common.c:94:0:████████{
...

Martin

> 
> Johann
>
Georg-Johann Lay Nov. 7, 2019, 12:57 p.m. UTC | #7
Am 07.11.19 um 13:49 schrieb Martin Liška:
> On 11/7/19 1:39 PM, Georg-Johann Lay wrote:
>> Am 07.11.19 um 10:41 schrieb Martin Liška:
>>> Hello.
>>>
>>> I've noticed quite some GNU coding style violations with your patch.
>>> Please next time, use something like:
>>>
>>> $ git diff HEAD~ > /tmp/patch && ./contrib/check_GNU_style.py /tmp/patch
>>>
>>> Thanks,
>>> Martin
>>>
>>
>> hm, I am actually using GNU style with Emacs...
>>
>> You mean the lines > 80 chars in config.gcc?
>>
>> I assumed that is no issue because there are already quite some lines 
>> that don't follow the < 80 rule.
> 
> That's fine. I'm mainly talking about:
> 
> === ERROR type #1: blocks of 8 spaces should be replaced with tabs (45 
> error(s)) ===
> gcc/common/config/avr/avr-common.c:78:0:████████████████   const struct 
> cl_decoded_option *decoded, location_t loc)
> gcc/common/config/avr/avr-common.c:86:0:████████{
> gcc/common/config/avr/avr-common.c:88:0:████████  error_at (loc, "option 
> %<-mdouble=64%> is only available if "
> gcc/common/config/avr/avr-common.c:89:0:████████████████    "configured 
> %<--with-double={64|64,32|32,64}%>");
> gcc/common/config/avr/avr-common.c:91:0:████████  
> opts->x_avr_long_double = 64;
> gcc/common/config/avr/avr-common.c:92:0:████████}
> gcc/common/config/avr/avr-common.c:94:0:████████{
> ...
> 
> Martin

My intention was to avoid a mixup of TABs and spaces mode, because
the avr backend is indented with spaces. So the indentation picks
up the style from the context (just like ypi would do it in Python
to avoid dreaded mixing of tabs ans spaces). Tabyfying the complete
sources is also something which I didn't consider, because that
makes porting much harder...

Johann
Georg-Johann Lay Nov. 25, 2019, 4:29 p.m. UTC | #8
Am 06.11.19 um 23:32 schrieb Jeff Law:
> On 10/31/19 3:55 PM, Georg-Johann Lay wrote:
>> Hi, this adds the possibility to enable IEEE compatible double
>> and long double support in avr-gcc.
>>
>> It supports 2 configure options
>>
>> --with-double={32|64|32,64|64,32}
>> --with-long-double={32|64|32,64|64,32|double}
>>
>> which select the default layout of these types and also chose
>> which mutlilib variants are built and available.
>>
>> These two config option map to the new compiler options
>> -mdouble= and -mlong-double= which are new multilib options.
>>
>> The patch only deals with option handling and multilib bits,
>> it does not add any double functionality.  The double support
>> functions are supposed to be provided by avr-libc which also hosts
>> all the float stuff, including __addsf3 etc.
>>
>> Ok for trunk?
>>
>> Johann
>>
>>
>> gcc/
>>      Support 64-bit double and 64-bit long double configurations.
>>
>>      PR target/92055
>>      * config.gcc (tm_defines) [avr]: Set from --with-double=,
>>      --with-long-double=.
>>      * config/avr/t-multilib: Remove.
>>      * config/avr/t-avr: Output of genmultilib.awk is now fully
>>      dynamically generated and no more part of the repo.
>>      (HAVE_DOUBLE_MULTILIB, HAVE_LONG_DOUBLE_MULTILIB): New variables.
>>      Pass them down to...
>>      * config/avr/genmultilib.awk: ...here and handle them.
>>      * gcc/config/avr/avr.opt (-mdouble=, avr_double). New option and var.
>>      (-mlong-double=, avr_long_double). New option and var.
>>      * common/config/avr/avr-common.c (opts.h): Include.
>>      (diagnostic.h): Include.
>>      (TARGET_OPTION_OPTIMIZATION_TABLE) &lt;-mdouble=&gt;: Set default as
>>      requested by --with-double=.
>>      &lt;-mlong-double=&gt;: Set default as requested by --with-long-double=.
>>
>>      (TARGET_OPTION_OPTIMIZATION_TABLE) &lt;-mdouble=, -mlong-double=&gt;:
>>      Set default as requested by --with-double=
>>      (TARGET_HANDLE_OPTION): Define to this...
>>      (avr_handle_option): ...new hook worker.
>>      * config/avr/avr.h (DOUBLE_TYPE_SIZE): Define to avr_double.
>>      (LONG_DOUBLE_TYPE_SIZE): Define to avr_long_double.
>>      (avr_double_lib): New proto for spec function.
>>      (EXTRA_SPEC_FUNCTIONS) &lt;double-lib&gt;: Add.
>>      (DRIVER_SELF_SPECS): Call %:double-lib.
>>      * config/avr/avr.c (avr_option_override): Assert
>>      sizeof(long double) &gt;= sizeof(double) for the target.
>>      * config/avr/avr-c.c (avr_cpu_cpp_builtins)
>>      [__HAVE_DOUBLE_MULTILIB__, __HAVE_LONG_DOUBLE_MULTILIB__]
>>      [__HAVE_DOUBLE64__, __HAVE_DOUBLE32__, __DEFAULT_DOUBLE__=]
>>      [__HAVE_LONG_DOUBLE64__, __HAVE_LONG_DOUBLE32__]
>>      [__HAVE_LONG_DOUBLE_IS_DOUBLE__, __DEFAULT_LONG_DOUBLE__=]:
>>      New built-in defined depending on --with-double=, --with-long-double=.
>>      * config/avr/driver-avr.c (avr_double_lib): New spec function.
>>      * doc/invoke.tex (AVR Options) &lt;-mdouble=,-mlong-double=&gt;: Doc.
>>
>> libgcc/
>>      Support 64-bit double and 64-bit long double configurations.
>>
>>      PR target/92055
>>      * config/avr/t-avr (HOST_LIBGCC2_CFLAGS): Only add -DF=SF if
>>      long double is a 32-bit type.
>>      * config/avr/t-avrlibc: Copy double64 and long-double64
>>      multilib(s) from the vanilla one.
>>      * config/avr/t-copy-libgcc: New Makefile snip.
>>
> OK
> jeff

Hi, I applied the following patch which also treats -m[long-]double=32 
as multilib options provided the default is -m[long-]double=64.  It 
changes the t-multilib-avr build script (and the options that are fed in).

Applied as SVN r278668.

Johann


gcc/
	Build double32 / long-double32 multilibs if needed.

	PR target/92055
	* config/avr/t-avr:
	(HAVE_DOUBLE_MULTILIB, HAVE_LONG_DOUBLE_MULTILIB): Remove vars.
	(HAVE_DOUBLE32, HAVE_LONG_DOUBLE32, WITH_LONG_DOUBLE)
	(HAVE_DOUBLE64, HAVE_LONG_DOUBLE64, WITH_DOUBLE): Set from
	tm_defines and pass to genmultilib.awk.
	* config/avr/genmultilib.awk: Use these variables to add double32
	and / or long-double32 multilib(s) as needed.
	* config/avr/driver-avr.c (avr_double_lib): Adjust comment.

Patch
diff mbox series

Index: gcc/common/config/avr/avr-common.c
===================================================================
--- gcc/common/config/avr/avr-common.c	(revision 277236)
+++ gcc/common/config/avr/avr-common.c	(working copy)
@@ -23,6 +23,8 @@ 
 #include "tm.h"
 #include "common/common-target.h"
 #include "common/common-target-def.h"
+#include "opts.h"
+#include "diagnostic.h"
 
 /* Implement TARGET_OPTION_OPTIMIZATION_TABLE.  */
 static const struct default_options avr_option_optimization_table[] =
@@ -43,9 +45,97 @@  static const struct default_options avr_
        performance decrease. For the AVR though, disallowing data races
        introduces additional code in LIM and increases reg pressure.  */
     { OPT_LEVELS_ALL, OPT_fallow_store_data_races, NULL, 1 },
+
+#if defined (WITH_DOUBLE64)
+    { OPT_LEVELS_ALL, OPT_mdouble_, NULL, 64 },
+#elif defined (WITH_DOUBLE32)
+    { OPT_LEVELS_ALL, OPT_mdouble_, NULL, 32 },
+#else
+#error "align this with config.gcc"
+#endif
+
+#if defined (WITH_LONG_DOUBLE64)
+    { OPT_LEVELS_ALL, OPT_mlong_double_, NULL, 64 },
+#elif defined (WITH_LONG_DOUBLE32)
+    { OPT_LEVELS_ALL, OPT_mlong_double_, NULL, 32 },
+#else
+#error "align this with config.gcc"
+#endif
+
     { OPT_LEVELS_NONE, 0, NULL, 0 }
   };
 
+
+/* Implement `TARGET_HANDLE_OPTION'.  */
+
+static bool
+avr_handle_option (struct gcc_options *opts, struct gcc_options*,
+                   const struct cl_decoded_option *decoded, location_t loc)
+{
+  int value = decoded->value;
+
+  switch (decoded->opt_index)
+    {
+    case OPT_mdouble_:
+      if (value == 64)
+        {
+#if !defined (HAVE_DOUBLE64)
+          error_at (loc, "option %<-mdouble=64%> is only available if "
+                    "configured %<--with-double={64|64,32|32,64}%>");
+#endif
+          opts->x_avr_long_double = 64;
+        }
+      else if (value == 32)
+        {
+#if !defined (HAVE_DOUBLE32)
+          error_at (loc, "option %<-mdouble=32%> is only available if "
+                    "configured %<--with-double={|32|32,64|64,32}%>");
+#endif
+        }
+      else
+        gcc_unreachable();
+
+#if defined (HAVE_LONG_DOUBLE_IS_DOUBLE)
+      opts->x_avr_long_double = value;
+#endif
+      break; // -mdouble=
+
+    case OPT_mlong_double_:
+      if (value == 64)
+        {
+#if !defined (HAVE_LONG_DOUBLE64)
+          error_at (loc, "option %<-mlong-double=64%> is only available if "
+                    "configured %<--with-long-double={64|64,32|32,64}%>, "
+                    "or %<--with-long-double=double%> together with "
+                    "%<--with-double={64|64,32|32,64}%>");
+#endif
+        }
+      else if (value == 32)
+        {
+#if !defined (HAVE_LONG_DOUBLE32)
+          error_at (loc, "option %<-mlong-double=32%> is only available if "
+                    "configured %<--with-long-double={|32|32,64|64,32}%>, "
+                    "or %<--with-long-double=double%> together with "
+                    "%<--with-double={|32|32,64|64,32}%>");
+#endif
+          opts->x_avr_double = 32;
+        }
+      else
+        gcc_unreachable();
+
+#if defined (HAVE_LONG_DOUBLE_IS_DOUBLE)
+      opts->x_avr_double = value;
+#endif
+      break; // -mlong-double=
+    }
+
+  return true;
+}
+
+
+#undef TARGET_HANDLE_OPTION
+#define TARGET_HANDLE_OPTION avr_handle_option
+
 #undef TARGET_OPTION_OPTIMIZATION_TABLE
 #define TARGET_OPTION_OPTIMIZATION_TABLE avr_option_optimization_table
 
Index: gcc/config/avr/avr-c.c
===================================================================
--- gcc/config/avr/avr-c.c	(revision 277236)
+++ gcc/config/avr/avr-c.c	(working copy)
@@ -390,6 +390,55 @@  start address.  This macro shall be used
   cpp_define (pfile, "__WITH_AVRLIBC__");
 #endif /* WITH_AVRLIBC */
 
+  // From configure --with-double={|32|32,64|64,32|64}
+
+#ifdef HAVE_DOUBLE_MULTILIB
+  cpp_define (pfile, "__HAVE_DOUBLE_MULTILIB__");
+#endif
+
+#ifdef HAVE_DOUBLE64
+  cpp_define (pfile, "__HAVE_DOUBLE64__");
+#endif
+
+#ifdef HAVE_DOUBLE32
+  cpp_define (pfile, "__HAVE_DOUBLE32__");
+#endif
+
+#if defined (WITH_DOUBLE64)
+  cpp_define (pfile, "__DEFAULT_DOUBLE__=64");
+#elif defined (WITH_DOUBLE32)
+  cpp_define (pfile, "__DEFAULT_DOUBLE__=32");
+#else
+#error "align this with config.gcc"
+#endif
+
+  // From configure --with-long-double={|32|32,64|64,32|64|double}
+
+#ifdef HAVE_LONG_DOUBLE_MULTILIB
+  cpp_define (pfile, "__HAVE_LONG_DOUBLE_MULTILIB__");
+#endif
+
+#ifdef HAVE_LONG_DOUBLE64
+  cpp_define (pfile, "__HAVE_LONG_DOUBLE64__");
+#endif
+
+#ifdef HAVE_LONG_DOUBLE32
+  cpp_define (pfile, "__HAVE_LONG_DOUBLE32__");
+#endif
+
+#ifdef HAVE_LONG_DOUBLE_IS_DOUBLE
+  cpp_define (pfile, "__HAVE_LONG_DOUBLE_IS_DOUBLE__");
+#endif
+
+#if defined (WITH_LONG_DOUBLE64)
+  cpp_define (pfile, "__DEFAULT_LONG_DOUBLE__=64");
+#elif defined (WITH_LONG_DOUBLE32)
+  cpp_define (pfile, "__DEFAULT_LONG_DOUBLE__=32");
+#else
+#error "align this with config.gcc"
+#endif
+
+  
   /* Define builtin macros so that the user can easily query whether
      non-generic address spaces (and which) are supported or not.
      This is only supported for C.  For C++, a language extension is needed
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c	(revision 277236)
+++ gcc/config/avr/avr.c	(working copy)
@@ -768,6 +768,9 @@  avr_option_override (void)
   if (!avr_set_core_architecture())
     return;
 
+  /* Sould be set by avr-common.c */
+  gcc_assert (avr_long_double >= avr_double);
+
   /* RAM addresses of some SFRs common to all devices in respective arch. */
 
   /* SREG: Status Register containing flags like I (global IRQ) */
Index: gcc/config/avr/avr.h
===================================================================
--- gcc/config/avr/avr.h	(revision 277236)
+++ gcc/config/avr/avr.h	(working copy)
@@ -140,8 +140,9 @@  These two properties are reflected by bu
 #define LONG_TYPE_SIZE (INT_TYPE_SIZE == 8 ? 16 : 32)
 #define LONG_LONG_TYPE_SIZE (INT_TYPE_SIZE == 8 ? 32 : 64)
 #define FLOAT_TYPE_SIZE 32
-#define DOUBLE_TYPE_SIZE 32
-#define LONG_DOUBLE_TYPE_SIZE 32
+#define DOUBLE_TYPE_SIZE (avr_double)
+#define LONG_DOUBLE_TYPE_SIZE (avr_long_double)
+
 #define LONG_LONG_ACCUM_TYPE_SIZE 64
 
 #define DEFAULT_SIGNED_CHAR 1
@@ -507,8 +508,10 @@  typedef struct avr_args
     (LENGTH = avr_adjust_insn_length (INSN, LENGTH))
 
 extern const char *avr_devicespecs_file (int, const char**);
+extern const char *avr_double_lib (int, const char**);
 
-#define EXTRA_SPEC_FUNCTIONS                                   \
+#define EXTRA_SPEC_FUNCTIONS                            \
+  { "double-lib", avr_double_lib },                     \
   { "device-specs-file", avr_devicespecs_file },
 
 /* Driver self specs has lmited functionality w.r.t. '%s' for dynamic specs.
@@ -516,7 +519,8 @@  extern const char *avr_devicespecs_file
    is used to diagnose problems with reading the specs file.  */
 
 #undef  DRIVER_SELF_SPECS
-#define DRIVER_SELF_SPECS                       \
+#define DRIVER_SELF_SPECS                               \
+  " %:double-lib(%{m*:m%*})"                            \
   " %:device-specs-file(device-specs%s %{mmcu=*:%*})"
 
 /* No libstdc++ for now.  Empty string doesn't work.  */
Index: gcc/config/avr/avr.opt
===================================================================
--- gcc/config/avr/avr.opt	(revision 277236)
+++ gcc/config/avr/avr.opt	(working copy)
@@ -115,6 +115,24 @@  mabsdata
 Target Report Mask(ABSDATA)
 Assume that all data in static storage can be accessed by LDS / STS.  This option is only useful for reduced Tiny devices.
 
+mdouble=
+Target Report Joined RejectNegative Var(avr_double) Init(0) Enum(avr_bits_e)
+mdouble=<BITS>	Use <BITS> bits wide double type.
+
+mlong-double=
+Target Report Joined RejectNegative Var(avr_long_double) Init(0) Enum(avr_bits_e)
+mlong-double=<BITS>	Use <BITS> bits wide long double type.
+
 nodevicelib
 Driver Target Report RejectNegative
 Do not link against the device-specific library lib<MCU>.a.
+
+Enum
+Name(avr_bits_e) Type(int)
+Available BITS selections:
+
+EnumValue
+Enum(avr_bits_e) String(32)  Value(32)
+
+EnumValue
+Enum(avr_bits_e) String(64) Value(64)
Index: gcc/config/avr/driver-avr.c
===================================================================
--- gcc/config/avr/driver-avr.c	(revision 277236)
+++ gcc/config/avr/driver-avr.c	(working copy)
@@ -111,3 +111,60 @@  avr_devicespecs_file (int argc, const ch
 #endif
                  NULL);
 }
+
+
+/* Re-build the -mdouble= and -mlong-double= options.  This is needed
+   because multilib selection is based on the physical presence of an
+   option on the command line, which is not the case for, say, when the
+   double=64 multilib is to be selected by --with-double=64 but the user
+   does not specify -mdouble=64 explicitly.  */
+
+const char*
+avr_double_lib (int argc, const char **argv)
+{
+#if defined (WITH_DOUBLE64)
+  int dbl = 64;
+#elif defined (WITH_DOUBLE32)
+  int dbl = 32;
+#else
+#error "align this with config.gcc"
+#endif
+
+#if defined (WITH_LONG_DOUBLE64)
+  int ldb = 64;
+#elif defined (WITH_LONG_DOUBLE32)
+  int ldb = 32;
+#else
+#error "align this with config.gcc"
+#endif
+
+  for (int i = 0; i < argc; i++)
+    {
+      if (strcmp (argv[i], "mdouble=32") == 0)
+        {
+          dbl = 32;
+#ifdef HAVE_LONG_DOUBLE_IS_DOUBLE
+          ldb = dbl;
+#endif
+        }
+      else if (strcmp (argv[i], "mdouble=64") == 0)
+        {
+          ldb = dbl = 64;
+        }
+      else if (strcmp (argv[i], "mlong-double=32") == 0)
+        {
+          ldb = dbl = 32;
+        }
+      else if (strcmp (argv[i], "mlong-double=64") == 0)
+        {
+          ldb = 64;
+#ifdef HAVE_LONG_DOUBLE_IS_DOUBLE
+          dbl = ldb;
+#endif
+        }
+    }
+
+  return concat (" %<mdouble=* -mdouble=", dbl == 32 ? "32" : "64",
+                 " %<mlong-double=* -mlong-double=", ldb == 32 ? "32" : "64",
+                 NULL);
+}
Index: gcc/config/avr/genmultilib.awk
===================================================================
--- gcc/config/avr/genmultilib.awk	(revision 277236)
+++ gcc/config/avr/genmultilib.awk	(working copy)
@@ -38,15 +38,26 @@  BEGIN {
     dir_rcall = "short-calls"
     opt_rcall = "mshort-calls"
 
+    dir_double64 = "double64"
+    opt_double64 = "mdouble=64"
+
+    dir_long_double64 = "long-double64"
+    opt_long_double64 = "mlong-double=64"
+
     #    awk Variable         Makefile Variable  
     #  ------------------------------------------
     #    m_options     <->    MULTILIB_OPTIONS
     #    m_dirnames    <->    MULTILIB_DIRNAMES
     #    m_required    <->    MULTILIB_REQUIRED
+    #    m_reuse       <->    MULTILIB_REUSE
     m_sep = ""
     m_options    = "\nMULTILIB_OPTIONS = "
     m_dirnames   = "\nMULTILIB_DIRNAMES ="
     m_required   = "\nMULTILIB_REQUIRED ="
+    m_reuse      = "\nMULTILIB_REUSE ="
+
+    have_double_multi = (HAVE_DOUBLE_MULTILIB == "HAVE_DOUBLE_MULTILIB")
+    have_long_double_multi = (HAVE_LONG_DOUBLE_MULTILIB == "HAVE_LONG_DOUBLE_MULTILIB")
 }
 
 ##################################################################
@@ -130,7 +141,26 @@  BEGIN {
 	# leading "mmcu=avr2/" in order not to confuse genmultilib.
 	gsub (/^mmcu=avr2\//, "", opts)
 	if (opts != "mmcu=avr2")
+	{
 	    m_required = m_required " \\\n\t" opts
+	    if (have_double_multi && have_long_double_multi)
+	    {
+		m_required = m_required " \\\n\t" opts "/" opt_double64
+		m_required = m_required " \\\n\t" opts "/" opt_long_double64
+
+		# -mlong-double=64 -mdouble=64 is the same as -mdouble=64,
+		# hence add a respective reuse.
+		d_opts  = opts "/" opt_double64
+		d_reuse = opts "/" opt_double64 "/" opt_long_double64
+		gsub (/=/, ".", d_opts)
+		gsub (/=/, ".", d_reuse)
+		m_reuse = m_reuse " \\\n\t" d_opts "=" d_reuse
+	    }
+	    else if (have_double_multi)
+		m_required = m_required " \\\n\t" opts "/" opt_double64
+	    else if (have_long_double_multi)
+		m_required = m_required " \\\n\t" opts "/" opt_long_double64
+	}
     }
 }
 
@@ -143,9 +173,37 @@  END {
     # Output that Stuff
     ############################################################
 
-    # Intended Target: ./gcc/config/avr/t-multilib
+    # Intended Target: $(top_builddir)/gcc/t-multilib-avr
+
+    if (have_double_multi && have_long_double_multi)
+    {
+	print m_options  " " opt_tiny " " opt_rcall " " opt_double64 "/" opt_long_double64
+	print m_dirnames " " dir_tiny " " dir_rcall " " dir_double64 " " dir_long_double64
+	# Notice that the ./double64 and ./long-double64 variants cannot
+	# be copied by t-avrlibc because the . default multilib is built
+	# after all the others.
+	m_required = m_required " \\\n\t" opt_double64
+	m_required = m_required " \\\n\t" opt_long_double64
+	m_reuse = m_reuse " \\\n\tmdouble.64=mdouble.64/mlong-double.64"
+    }
+    else if (have_double_multi)
+    {
+	print m_options  " " opt_tiny " " opt_rcall " " opt_double64
+	print m_dirnames " " dir_tiny " " dir_rcall " " dir_double64
+	m_required = m_required " \\\n\t" opt_double64
+    }
+    else if (have_long_double_multi)
+    {
+	print m_options  " " opt_tiny " " opt_rcall " " opt_long_double64
+	print m_dirnames " " dir_tiny " " dir_rcall " " dir_long_double64
+	m_required = m_required " \\\n\t" opt_long_double64
+    }
+    else
+    {
+	print m_options  " " opt_tiny " " opt_rcall
+	print m_dirnames " " dir_tiny " " dir_rcall
+    }
 
-    print m_options  " " opt_tiny " " opt_rcall
-    print m_dirnames " " dir_tiny " " dir_rcall
     print m_required
+    print m_reuse
 }
Index: gcc/config/avr/t-avr
===================================================================
--- gcc/config/avr/t-avr	(revision 277236)
+++ gcc/config/avr/t-avr	(working copy)
@@ -16,6 +16,9 @@ 
 # along with GCC; see the file COPYING3.  If not see
 # <http://www.gnu.org/licenses/>.
 
+HAVE_DOUBLE_MULTILIB = $(findstring HAVE_DOUBLE_MULTILIB, $(tm_defines))
+HAVE_LONG_DOUBLE_MULTILIB = $(findstring HAVE_LONG_DOUBLE_MULTILIB, $(tm_defines))
+
 PASSES_EXTRA += $(srcdir)/config/avr/avr-passes.def
 
 driver-avr.o: $(srcdir)/config/avr/driver-avr.c \
@@ -93,9 +96,14 @@  install-device-specs: s-device-specs ins
 # MULTILIB_OPTIONS
 # MULTILIB_DIRNAMES
 # MULTILIB_REQUIRED
+# MULTILIB_REUSE
 
-s-mlib: $(srcdir)/config/avr/t-multilib
+multilib.h Makefile s-mlib: t-multilib-avr
 
-$(srcdir)/config/avr/t-multilib: $(srcdir)/config/avr/genmultilib.awk \
+t-multilib-avr: $(srcdir)/config/avr/genmultilib.awk \
 				 $(AVR_MCUS)
-	$(AWK) -f $< $< $(AVR_MCUS) > $@
+	$(AWK)	-v HAVE_DOUBLE_MULTILIB=$(HAVE_DOUBLE_MULTILIB) \
+		-v HAVE_LONG_DOUBLE_MULTILIB=$(HAVE_LONG_DOUBLE_MULTILIB) \
+		-f $< $< $(AVR_MCUS) > $@
+
+include t-multilib-avr
Index: gcc/config/avr/t-multilib
===================================================================
--- gcc/config/avr/t-multilib	(revision 277236)
+++ gcc/config/avr/t-multilib	(nonexistent)
@@ -1,46 +0,0 @@ 
-# Auto-generated Makefile Snip
-# Generated by    : ./gcc/config/avr/genmultilib.awk
-# Generated from  : ./gcc/config/avr/avr-mcus.def
-# Used by         : tmake_file from Makefile and genmultilib
-
-# Copyright (C) 2011-2019 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.
-#
-# You should have received a copy of the GNU General Public License
-# along with GCC; see the file COPYING3.  If not see
-# <http://www.gnu.org/licenses/>.
-
-MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6/mmcu=avrxmega2/mmcu=avrxmega3/mmcu=avrxmega4/mmcu=avrxmega5/mmcu=avrxmega6/mmcu=avrxmega7/mmcu=avrtiny msp8 mshort-calls
-
-MULTILIB_DIRNAMES = avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega2 avrxmega3 avrxmega4 avrxmega5 avrxmega6 avrxmega7 avrtiny tiny-stack short-calls
-
-MULTILIB_REQUIRED = \
-	msp8 \
-	mmcu=avr25 \
-	mmcu=avr25/msp8 \
-	mmcu=avr3 \
-	mmcu=avr31 \
-	mmcu=avr35 \
-	mmcu=avr4 \
-	mmcu=avr5 \
-	mmcu=avr51 \
-	mmcu=avr6 \
-	mmcu=avrxmega2 \
-	mmcu=avrxmega3/mshort-calls \
-	mmcu=avrxmega3 \
-	mmcu=avrxmega4 \
-	mmcu=avrxmega5 \
-	mmcu=avrxmega6 \
-	mmcu=avrxmega7 \
-	mmcu=avrtiny
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 277236)
+++ gcc/config.gcc	(working copy)
@@ -1287,6 +1287,88 @@  avr-*-*)
 	    tm_file="${tm_file} ${cpu_type}/avrlibc.h"
 	    tm_defines="${tm_defines} WITH_AVRLIBC"
 	fi
+	case y${with_double} in
+	    y | y32)
+		avr_double=32
+		tm_defines="${tm_defines} HAVE_DOUBLE32"
+		;;
+	    y64)
+		avr_double=64
+		tm_defines="${tm_defines} HAVE_DOUBLE64"
+		;;
+	    y64,32)
+		avr_double=64
+		avr_double_multilib=1
+		tm_defines="${tm_defines} HAVE_DOUBLE32"
+		tm_defines="${tm_defines} HAVE_DOUBLE64"
+		tm_defines="${tm_defines} HAVE_DOUBLE_MULTILIB"
+		;;
+	    y32,64)
+		avr_double=32
+		avr_double_multilib=1
+		tm_defines="${tm_defines} HAVE_DOUBLE32"
+		tm_defines="${tm_defines} HAVE_DOUBLE64"
+		tm_defines="${tm_defines} HAVE_DOUBLE_MULTILIB"
+		;;
+	    *)
+		echo "Error: --with-double= can only be used with: '32', '32,64', '64,32', '64'" 1>&2
+		exit 1
+		;;
+	esac
+	case y${with_long_double} in
+	    y | y32)
+		avr_long_double=32
+		tm_defines="${tm_defines} HAVE_LONG_DOUBLE32"
+		;;
+	    y64)
+		avr_long_double=64
+		tm_defines="${tm_defines} HAVE_LONG_DOUBLE64"
+		;;
+	    y64,32)
+		avr_long_double=64
+		avr_long_double_multilib=1
+		tm_defines="${tm_defines} HAVE_LONG_DOUBLE32"
+		tm_defines="${tm_defines} HAVE_LONG_DOUBLE64"
+		tm_defines="${tm_defines} HAVE_LONG_DOUBLE_MULTILIB"
+		;;
+	    y32,64)
+		avr_long_double=32
+		avr_long_double_multilib=1
+		tm_defines="${tm_defines} HAVE_LONG_DOUBLE32"
+		tm_defines="${tm_defines} HAVE_LONG_DOUBLE64"
+		tm_defines="${tm_defines} HAVE_LONG_DOUBLE_MULTILIB"
+		;;
+	    ydouble)
+		avr_long_double=${avr_double}
+		tm_defines="${tm_defines} HAVE_LONG_DOUBLE_IS_DOUBLE"
+		if test y${avr_double_multilib} = y1; then
+		    tm_defines="${tm_defines} HAVE_LONG_DOUBLE32"
+		    tm_defines="${tm_defines} HAVE_LONG_DOUBLE64"
+		else
+		    tm_defines="${tm_defines} HAVE_LONG_DOUBLE${avr_long_double}"
+		fi
+		;;
+	    *)
+		echo "Error: --with-long_double= can only be used with: '32', '32,64', '64,32', '64', 'double'" 1>&2
+		exit 1
+		;;
+	esac
+	if test ${avr_long_double}x${avr_long_double_multilib}y${avr_double_multilib}z = 32xy1z; then
+	    if test y${with_long_double} != ydouble; then
+		echo "Error: --with-double=${with_double} requests a multilib for double, but long double is always 32 bits wide due to --with-long-double=${with_long_double}" 1>&2
+		exit 1
+	    fi
+	fi
+	if test ${avr_double}x${avr_long_double_multilib}y${avr_double_multilib}z = 64x1yz; then
+	    echo "Error: --with-long-double=${with_long_double} requests a multilib for long double, but double is always 64 bits wide due to --with-double=64" 1>&2
+	    exit 1
+	fi
+	if test y${avr_double}${avr_long_double} = y6432; then
+	    echo "Error: double default of 64 bits from --with-double=${with_double} conflicts with default of 32 bits for long double from --with-long-double=${with_long_double}" 1>&2
+	    exit 1
+	fi
+	tm_defines="${tm_defines} WITH_DOUBLE${avr_double}"
+	tm_defines="${tm_defines} WITH_LONG_DOUBLE${avr_long_double}"
 	tmake_file="${tmake_file} avr/t-avr avr/t-multilib"
 	use_gcc_stdint=wrap
 	extra_gcc_objs="driver-avr.o avr-devices.o"
Index: gcc/doc/invoke.texi
===================================================================
--- gcc/doc/invoke.texi	(revision 277236)
+++ gcc/doc/invoke.texi	(working copy)
@@ -721,6 +721,7 @@  -imacros @var{file}  -imultilib @var{dir
 @gccoptlist{-mmcu=@var{mcu}  -mabsdata  -maccumulate-args @gol
 -mbranch-cost=@var{cost} @gol
 -mcall-prologues  -mgas-isr-prologues  -mint8 @gol
+-mdouble=@var{bits} -mlong-double=@var{bits} @gol
 -mn_flash=@var{size}  -mno-interrupts @gol
 -mmain-is-OS_task  -mrelax  -mrmw  -mstrict-X  -mtiny-stack @gol
 -mfract-convert-truncate @gol
@@ -18226,6 +18227,22 @@  integers. The default branch cost is 0.
 Functions prologues/epilogues are expanded as calls to appropriate
 subroutines.  Code size is smaller.
 
+@item -mdouble=@var{bits}
+@opindex mdouble
+Set the size (in bits) of the @code{double} type.  Valid values for
+@var{bits} are 32 and 64. This option is only available if the compiler
+is configured with @code{--with-double=32} or with @code{--with-double=64},
+and the argument of @code{--with-double=} specifies the default layout of
+@code{double}.
+
+@item -mlong-double=@var{bits}
+@opindex mlong-double
+Set the size (in bits) of the @code{long double} type.  Valid values for
+@var{bits} are 32 and 64. This option is only available if the compiler
+is configured with @code{--with-long-double=32} or with
+@code{--with-long-double=64}, and the argument of @code{--with-long-double=}
+specifies the default layout of @code{long double}.
+
 @item -mgas-isr-prologues
 @opindex mgas-isr-prologues
 Interrupt service routines (ISRs) may use the @code{__gcc_isr} pseudo
Index: libgcc/config/avr/t-avr
===================================================================
--- libgcc/config/avr/t-avr	(revision 277236)
+++ libgcc/config/avr/t-avr	(working copy)
@@ -112,10 +112,14 @@  LIB2FUNCS_EXCLUDE = \
 	_clrsbdi2 \
 
 
-# We do not have the DF type.
+ifeq ($(long_double_type_size),32)
+# We do not have the DFtype.
+HOST_LIBGCC2_CFLAGS += -DDF=SF
+endif
+
 # Most of the C functions in libgcc2 use almost all registers,
 # so use -mcall-prologues for smaller code size.
-HOST_LIBGCC2_CFLAGS += -DDF=SF -Dinhibit_libc -mcall-prologues -Os
+HOST_LIBGCC2_CFLAGS += -Dinhibit_libc -mcall-prologues -Os
 
 # Extra 16-bit integer functions.
 intfuncs16 = _absvXX2 _addvXX3 _subvXX3 _mulvXX3 _negvXX2 _clrsbXX2
Index: libgcc/config/avr/t-avrlibc
===================================================================
--- libgcc/config/avr/t-avrlibc	(revision 277236)
+++ libgcc/config/avr/t-avrlibc	(working copy)
@@ -64,3 +64,34 @@  LIB2FUNCS_EXCLUDE += \
 	_fixunssfsi _fixsfdi \
 	_fixunssfdi \
 	_floatdisf _floatundisf
+
+ifneq (,$(findstring avr,$(MULTISUBDIR)))
+
+# We are not in the avr2 (default) subdir, hence copying will work.
+# In default dir, copying won't work because the default multilib is
+# built after all the others.
+
+ifneq (,$(findstring double64,$(MULTISUBDIR)))
+
+# We are in double64/libgcc or long-double64/libgcc:
+# Just copy from the [long ]double=float multilib; we would remove any DFmode
+# bits from this multilib variant, anyway, because the current assumption
+# is that avr-libc hosts *all* the IEEE-double stuff.
+
+LIB2FUNCS_EXCLUDE := %
+LIB1ASMFUNCS :=
+libgcc-objects :=
+libgcov-objects :=
+objects :=
+
+t-copy-libgcc.dep: $(srcdir)/config/avr/t-copy-libgcc
+	-rm -f libgcc.a
+	-rm -f libgcov.a
+	cp $< $@
+
+libgcc.a libgcov.a libgcc_tm.h: t-copy-libgcc.dep
+
+Makefile: t-copy-libgcc.dep
+
+endif
+endif
Index: libgcc/config/avr/t-copy-libgcc
===================================================================
--- libgcc/config/avr/t-copy-libgcc	(nonexistent)
+++ libgcc/config/avr/t-copy-libgcc	(working copy)
@@ -0,0 +1,13 @@ 
+# Only used with --with-avrlibc & (-mlong-double=64 | -mdouble=64)
+#
+# Inserted at the end of Makefile by magic[tm].
+# We need this *after* Makefile's rules so we can override them.
+
+libgcc.a: ../../libgcc/libgcc.a
+	cp $< $@
+
+libgcov.a: ../../libgcc/libgcov.a
+	@:
+ifeq ($(enable_gcov),yes)
+	cp $< $@
+endif