diff mbox

[avr] PR51345: Restore -mtiny-stack semantics

Message ID 4F71A597.5000202@gjlay.de
State New
Headers show

Commit Message

Georg-Johann Lay March 27, 2012, 11:33 a.m. UTC
This patch fixes a problem with the -mtiny-stack option:

Architectures avr2 and avr25 mix targets with 8-bit SP and 16-bit SP so that
-mtiny-stack is no good for multilib selection:

If a frame pointer has to be set up from an 8-bit SP it is a difference if
there is no SP_H or of the SP is just treated as if it was 8 bits wide.

In the first case the high byte must be set to 0. In the second case SP_H can
be read.

That is: The patch uses the size of hard SP for multilib selection and
generation. The user-settable -mtiny-stack is used for size of soft SP for
optimization purposes, but does not influence multilib selection or generation
or how FP is deduced from SP.

Notable changes are:

-mtiny-stack is no more a multilib option and its semantics restored as was
before PR51345 introduced multilibs for 8-bit SP targets.

Multilib selection is performed by a new undocumented option -msp8. This option
is only used internally and need not to be specified on the command line. -msp8
is injected by DRIVER_SELF_SPECS as needed.

There is no avr-specific multilib_raw[] needed any more. This turns
genmultilib.awk considerably more easy and better to maintain. Much code could
be kicked off.

-print-multi-lib results are clean now. With the prior approach,
-print-multi-lib printed phantom configurations like

    tiny-stack;@mmcu=at90s2313
    avr25/tiny-stack;@mmcu=attiny13

which could confuse libc implementations like newlib or AVR-Libc during their
configure stage as they evaluate -print-multilib-lib.

Now -print-multi-lib yields

.;
avr25;@mmcu=avr25
avr3;@mmcu=avr3
avr31;@mmcu=avr31
avr35;@mmcu=avr35
avr4;@mmcu=avr4
avr5;@mmcu=avr5
avr51;@mmcu=avr51
avr6;@mmcu=avr6
avrxmega2;@mmcu=avrxmega2
avrxmega4;@mmcu=avrxmega4
avrxmega5;@mmcu=avrxmega5
avrxmega6;@mmcu=avrxmega6
avrxmega7;@mmcu=avrxmega7
tiny-stack;@msp8
avr25/tiny-stack;@mmcu=avr25@msp8

which is perfect and clean. As you can see, the multilib directory structure is
/unchanged/ i.e. their names are still
    ./avr25/tiny-stack
etc.

Ok for trunk?

Johann

	PR target/52737
	* contrib/gcc_update (files_and_dependencies):
	Remove gcc/config/avr/t-multilib from touch data.

gcc/
	PR target/52737
	* config.gcc (tm_file): Remove avr/multilib.h.

	* doc/invoke.texi (AVR Options): Adjust
	documentation of -mtiny-stack.

	* config/avr/genmultilib.awk: Remove code to generate multilib.h.
	(BEGIN): Use -msp8 as multilib option instead of -mtiny-stack.
	* config/avr/t-avr: Remove generation of multilib.h.
	* config/avr/t-multilib: Regenerate.
	* config/avr/multilib.h: Remove.
	* config/avr/avr.opt (-msp8): New option.
	(avr_sp8): New variable.
	* config/avr/driver-avr.c (avr_device_to_sp8): New function.
	* config/avr/avr.h (AVR_HAVE_SPH): New define.
	(AVR_HAVE_8BIT_SP): Also set by avr_sp8 i.e. -msp8.
	(avr_device_to_sp8): New prototype.
	(EXTRA_SPEC_FUNCTIONS): Add { "device_to_sp8", avr_device_to_sp8 }
	(DRIVER_SELF_SPECS): New define.
	* config/avr/avr-c.c (avr_cpu_cpp_builtins): New built-in defines:
	__AVR_SP8__, __AVR_HAVE_SPH__.
	* config/avr/avr.c (output_movhi): Use AVR_HAVE_SPH instead of
	AVR_HAVE_8BIT_SP to decide if SP_H is present.
	(avr_file_start): Ditto.
	
libgcc/
	PR target/52737
	* config/avr/lib1funcs.S: Use __AVR_HAVE_SPH__ for SP_H checks
	instead of __AVR_HAVE_8BIT_SP__.

Comments

Denis Chertykov March 27, 2012, 5:49 p.m. UTC | #1
2012/3/27 Georg-Johann Lay <avr@gjlay.de>:
> This patch fixes a problem with the -mtiny-stack option:
>
> Architectures avr2 and avr25 mix targets with 8-bit SP and 16-bit SP so that
> -mtiny-stack is no good for multilib selection:
>
> If a frame pointer has to be set up from an 8-bit SP it is a difference if
> there is no SP_H or of the SP is just treated as if it was 8 bits wide.
>
> In the first case the high byte must be set to 0. In the second case SP_H can
> be read.
>
> That is: The patch uses the size of hard SP for multilib selection and
> generation. The user-settable -mtiny-stack is used for size of soft SP for
> optimization purposes, but does not influence multilib selection or generation
> or how FP is deduced from SP.
>
> Notable changes are:
>
> -mtiny-stack is no more a multilib option and its semantics restored as was
> before PR51345 introduced multilibs for 8-bit SP targets.
>
> Multilib selection is performed by a new undocumented option -msp8. This option
> is only used internally and need not to be specified on the command line. -msp8
> is injected by DRIVER_SELF_SPECS as needed.
>
> There is no avr-specific multilib_raw[] needed any more. This turns
> genmultilib.awk considerably more easy and better to maintain. Much code could
> be kicked off.
>
> -print-multi-lib results are clean now. With the prior approach,
> -print-multi-lib printed phantom configurations like
>
>    tiny-stack;@mmcu=at90s2313
>    avr25/tiny-stack;@mmcu=attiny13
>
> which could confuse libc implementations like newlib or AVR-Libc during their
> configure stage as they evaluate -print-multilib-lib.
>
> Now -print-multi-lib yields
>
> .;
> avr25;@mmcu=avr25
> avr3;@mmcu=avr3
> avr31;@mmcu=avr31
> avr35;@mmcu=avr35
> avr4;@mmcu=avr4
> avr5;@mmcu=avr5
> avr51;@mmcu=avr51
> avr6;@mmcu=avr6
> avrxmega2;@mmcu=avrxmega2
> avrxmega4;@mmcu=avrxmega4
> avrxmega5;@mmcu=avrxmega5
> avrxmega6;@mmcu=avrxmega6
> avrxmega7;@mmcu=avrxmega7
> tiny-stack;@msp8
> avr25/tiny-stack;@mmcu=avr25@msp8
>
> which is perfect and clean. As you can see, the multilib directory structure is
> /unchanged/ i.e. their names are still
>    ./avr25/tiny-stack
> etc.
>
> Ok for trunk?
>
> Johann
>
>        PR target/52737
>        * contrib/gcc_update (files_and_dependencies):
>        Remove gcc/config/avr/t-multilib from touch data.
>
> gcc/
>        PR target/52737
>        * config.gcc (tm_file): Remove avr/multilib.h.
>
>        * doc/invoke.texi (AVR Options): Adjust
>        documentation of -mtiny-stack.
>
>        * config/avr/genmultilib.awk: Remove code to generate multilib.h.
>        (BEGIN): Use -msp8 as multilib option instead of -mtiny-stack.
>        * config/avr/t-avr: Remove generation of multilib.h.
>        * config/avr/t-multilib: Regenerate.
>        * config/avr/multilib.h: Remove.
>        * config/avr/avr.opt (-msp8): New option.
>        (avr_sp8): New variable.
>        * config/avr/driver-avr.c (avr_device_to_sp8): New function.
>        * config/avr/avr.h (AVR_HAVE_SPH): New define.
>        (AVR_HAVE_8BIT_SP): Also set by avr_sp8 i.e. -msp8.
>        (avr_device_to_sp8): New prototype.
>        (EXTRA_SPEC_FUNCTIONS): Add { "device_to_sp8", avr_device_to_sp8 }
>        (DRIVER_SELF_SPECS): New define.
>        * config/avr/avr-c.c (avr_cpu_cpp_builtins): New built-in defines:
>        __AVR_SP8__, __AVR_HAVE_SPH__.
>        * config/avr/avr.c (output_movhi): Use AVR_HAVE_SPH instead of
>        AVR_HAVE_8BIT_SP to decide if SP_H is present.
>        (avr_file_start): Ditto.
>
> libgcc/
>        PR target/52737
>        * config/avr/lib1funcs.S: Use __AVR_HAVE_SPH__ for SP_H checks
>        instead of __AVR_HAVE_8BIT_SP__.
>
>
>

Approved.

Denis.
diff mbox

Patch

Index: contrib/gcc_update
===================================================================
--- contrib/gcc_update	(revision 185858)
+++ contrib/gcc_update	(working copy)
@@ -83,7 +83,6 @@  gcc/config/arm/arm-tune.md: gcc/config/a
 gcc/config/arm/arm-tables.opt: gcc/config/arm/arm-arches.def gcc/config/arm/arm-cores.def gcc/config/arm/arm-fpus.def gcc/config/arm/genopt.sh
 gcc/config/avr/avr-tables.opt: gcc/config/avr/avr-mcus.def gcc/config/avr/genopt.sh
 gcc/config/avr/t-multilib: gcc/config/avr/avr-mcus.def gcc/config/avr/genmultilib.awk
-gcc/config/avr/multilib.h: gcc/config/avr/avr-mcus.def gcc/config/avr/genmultilib.awk
 gcc/config/c6x/c6x-tables.opt: gcc/config/c6x/c6x-isas.def gcc/config/c6x/genopt.sh
 gcc/config/c6x/c6x-sched.md: gcc/config/c6x/c6x-sched.md.in gcc/config/c6x/gensched.sh
 gcc/config/c6x/c6x-mult.md: gcc/config/c6x/c6x-mult.md.in gcc/config/c6x/genmult.sh
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 185858)
+++ gcc/config.gcc	(working copy)
@@ -898,13 +898,13 @@  arm*-wince-pe*)
 	extra_objs="pe.o"
 	;;
 avr-*-rtems*)
-	tm_file="elfos.h avr/elf.h avr/avr.h avr/multilib.h dbxelf.h avr/rtems.h rtems.h newlib-stdint.h"
+	tm_file="elfos.h avr/elf.h avr/avr.h dbxelf.h avr/rtems.h rtems.h newlib-stdint.h"
 	tmake_file="avr/t-avr avr/t-multilib t-rtems avr/t-rtems"
 	extra_gcc_objs="driver-avr.o avr-devices.o"
 	extra_objs="avr-devices.o avr-log.o"
 	;;
 avr-*-*)
-	tm_file="elfos.h avr/elf.h avr/avr.h avr/multilib.h dbxelf.h newlib-stdint.h"
+	tm_file="elfos.h avr/elf.h avr/avr.h dbxelf.h newlib-stdint.h"
 	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 185858)
+++ gcc/doc/invoke.texi	(working copy)
@@ -11131,8 +11131,7 @@  sbiw r26, const   ; X -= const
 
 @item -mtiny-stack
 @opindex mtiny-stack
-Only use the lower 8@tie{}bits of the stack pointer and assume that the high
-byte of SP is always zero.
+Only change the lower 8@tie{}bits of the stack pointer.
 @end table
 
 @subsubsection @code{EIND} and Devices with more than 128 Ki Bytes of Flash
Index: libgcc/config/avr/lib1funcs.S
===================================================================
--- libgcc/config/avr/lib1funcs.S	(revision 185858)
+++ libgcc/config/avr/lib1funcs.S	(working copy)
@@ -25,7 +25,9 @@  see the files COPYING3 and COPYING.RUNTI
 #define __zero_reg__ r1
 #define __tmp_reg__ r0
 #define __SREG__ 0x3f
+#if defined (__AVR_HAVE_SPH__)
 #define __SP_H__ 0x3e
+#endif
 #define __SP_L__ 0x3d
 #define __RAMPZ__ 0x3B
 #define __EIND__  0x3C
@@ -1258,7 +1260,7 @@  ENDF __divmodsi4
 
 #if defined (__AVR_HAVE_JMP_CALL__)
 #   define SPEED_DIV 8
-#elif defined (__AVR_HAVE_MOVW__) && !defined (__AVR_HAVE_8BIT_SP__)
+#elif defined (__AVR_HAVE_MOVW__) && defined (__AVR_HAVE_SPH__)
 #   define SPEED_DIV 16
 #else
 #   define SPEED_DIV 0
@@ -1540,10 +1542,10 @@  DEFUN  __divdi3_moddi3
 
 4:  ;; Epilogue: Restore the Z = 12 Registers and return
     in r28, __SP_L__
-#if defined (__AVR_HAVE_8BIT_SP__)
-    clr r29
-#else
+#if defined (__AVR_HAVE_SPH__)
     in r29, __SP_H__
+#else
+    clr r29
 #endif /* #SP = 8/16 */
     ldi r30, 12
     XJMP __epilogue_restores__ + ((18 - 12) * 2)
@@ -1691,7 +1693,7 @@  DEFUN __prologue_saves__
 	push r17
 	push r28
 	push r29
-#if defined (__AVR_HAVE_8BIT_SP__)
+#if !defined (__AVR_HAVE_SPH__)
 	in	r28,__SP_L__
 	sub	r28,r26
 	out	__SP_L__,r28
@@ -1747,7 +1749,7 @@  DEFUN __epilogue_restores__
 	ldd	r16,Y+4
 	ldd	r17,Y+3
 	ldd	r26,Y+2
-#if defined (__AVR_HAVE_8BIT_SP__)
+#if !defined (__AVR_HAVE_SPH__)
 	ldd	r29,Y+1
 	add	r28,r30
 	out	__SP_L__,r28
Index: gcc/config/avr/t-multilib
===================================================================
--- gcc/config/avr/t-multilib	(revision 185858)
+++ gcc/config/avr/t-multilib	(working copy)
@@ -21,57 +21,53 @@ 
 # 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=avrxmega4/mmcu=avrxmega5/mmcu=avrxmega6/mmcu=avrxmega7 mtiny-stack
+MULTILIB_OPTIONS = mmcu=avr2/mmcu=avr25/mmcu=avr3/mmcu=avr31/mmcu=avr35/mmcu=avr4/mmcu=avr5/mmcu=avr51/mmcu=avr6/mmcu=avrxmega2/mmcu=avrxmega4/mmcu=avrxmega5/mmcu=avrxmega6/mmcu=avrxmega7 msp8
 
 MULTILIB_DIRNAMES =  avr2 avr25 avr3 avr31 avr35 avr4 avr5 avr51 avr6 avrxmega2 avrxmega4 avrxmega5 avrxmega6 avrxmega7 tiny-stack avr25/tiny-stack
 
 MULTILIB_EXCEPTIONS = \
-	mmcu=avr3/mtiny-stack \
-	mmcu=avr31/mtiny-stack \
-	mmcu=avr35/mtiny-stack \
-	mmcu=avr4/mtiny-stack \
-	mmcu=avr5/mtiny-stack \
-	mmcu=avr51/mtiny-stack \
-	mmcu=avr6/mtiny-stack \
-	mmcu=avrxmega2/mtiny-stack \
-	mmcu=avrxmega4/mtiny-stack \
-	mmcu=avrxmega5/mtiny-stack \
-	mmcu=avrxmega6/mtiny-stack \
-	mmcu=avrxmega7/mtiny-stack
+	mmcu=avr3/msp8 \
+	mmcu=avr31/msp8 \
+	mmcu=avr35/msp8 \
+	mmcu=avr4/msp8 \
+	mmcu=avr5/msp8 \
+	mmcu=avr51/msp8 \
+	mmcu=avr6/msp8 \
+	mmcu=avrxmega2/msp8 \
+	mmcu=avrxmega4/msp8 \
+	mmcu=avrxmega5/msp8 \
+	mmcu=avrxmega6/msp8 \
+	mmcu=avrxmega7/msp8
 
 MULTILIB_MATCHES = \
-	mmcu?at90s2313=mmcu?at90s2313 \
-	mmcu?at90s2323=mmcu?at90s2323 \
-	mmcu?at90s2333=mmcu?at90s2333 \
-	mmcu?at90s2343=mmcu?at90s2343 \
-	mmcu?attiny22=mmcu?attiny22 \
-	mmcu?attiny26=mmcu?attiny26 \
-	mmcu?at90s4433=mmcu?at90s4433 \
+	mmcu?avr2=mmcu?at90s2313 \
+	mmcu?avr2=mmcu?at90s2323 \
+	mmcu?avr2=mmcu?at90s2333 \
+	mmcu?avr2=mmcu?at90s2343 \
+	mmcu?avr2=mmcu?attiny22 \
+	mmcu?avr2=mmcu?attiny26 \
+	mmcu?avr2=mmcu?at90s4414 \
+	mmcu?avr2=mmcu?at90s4433 \
+	mmcu?avr2=mmcu?at90s4434 \
+	mmcu?avr2=mmcu?at90s8515 \
+	mmcu?avr2=mmcu?at90c8534 \
+	mmcu?avr2=mmcu?at90s8535 \
 	mmcu?avr25=mmcu?ata6289 \
-	mmcu?attiny13=mmcu?attiny13 \
 	mmcu?avr25=mmcu?attiny13 \
-	mmcu?attiny13a=mmcu?attiny13a \
 	mmcu?avr25=mmcu?attiny13a \
-	mmcu?attiny2313=mmcu?attiny2313 \
 	mmcu?avr25=mmcu?attiny2313 \
-	mmcu?attiny2313a=mmcu?attiny2313a \
 	mmcu?avr25=mmcu?attiny2313a \
-	mmcu?attiny24=mmcu?attiny24 \
 	mmcu?avr25=mmcu?attiny24 \
-	mmcu?attiny24a=mmcu?attiny24a \
 	mmcu?avr25=mmcu?attiny24a \
 	mmcu?avr25=mmcu?attiny4313 \
 	mmcu?avr25=mmcu?attiny44 \
 	mmcu?avr25=mmcu?attiny44a \
 	mmcu?avr25=mmcu?attiny84 \
 	mmcu?avr25=mmcu?attiny84a \
-	mmcu?attiny25=mmcu?attiny25 \
 	mmcu?avr25=mmcu?attiny25 \
 	mmcu?avr25=mmcu?attiny45 \
 	mmcu?avr25=mmcu?attiny85 \
-	mmcu?attiny261=mmcu?attiny261 \
 	mmcu?avr25=mmcu?attiny261 \
-	mmcu?attiny261a=mmcu?attiny261a \
 	mmcu?avr25=mmcu?attiny261a \
 	mmcu?avr25=mmcu?attiny461 \
 	mmcu?avr25=mmcu?attiny461a \
Index: gcc/config/avr/avr.opt
===================================================================
--- gcc/config/avr/avr.opt	(revision 185858)
+++ gcc/config/avr/avr.opt	(working copy)
@@ -73,3 +73,7 @@  Accumulate outgoing function arguments a
 mstrict-X
 Target Report Var(avr_strict_X) Init(0)
 When accessing RAM, use X as imposed by the hardware, i.e. just use pre-decrement, post-increment and indirect addressing with the X register.  Without this option, the compiler may assume that there is an addressing mode X+const similar to Y+const and Z+const and emit instructions to emulate such an addressing mode for X.
+
+;; For rationale behind -msp8 see explanation in avr.h.
+msp8
+Target Report RejectNegative Undocumented Var(avr_sp8) Init(0)
Index: gcc/config/avr/avr-c.c
===================================================================
--- gcc/config/avr/avr-c.c	(revision 185858)
+++ gcc/config/avr/avr-c.c	(working copy)
@@ -128,6 +128,12 @@  avr_cpu_cpp_builtins (struct cpp_reader
   else
     cpp_define (pfile, "__AVR_HAVE_16BIT_SP__");
 
+  if (avr_sp8)
+    cpp_define (pfile, "__AVR_SP8__");
+
+  if (AVR_HAVE_SPH)
+    cpp_define (pfile, "__AVR_HAVE_SPH__");
+
   if (TARGET_NO_INTERRUPTS)
     cpp_define (pfile, "__NO_INTERRUPTS__");
 
Index: gcc/config/avr/t-avr
===================================================================
--- gcc/config/avr/t-avr	(revision 185858)
+++ gcc/config/avr/t-avr	(working copy)
@@ -49,16 +49,10 @@  $(srcdir)/config/avr/avr-tables.opt: $(s
 # MULTILIB_MATCHES
 $(srcdir)/config/avr/t-multilib: s-avr-mlib; @true
 
-# Override multilib_raw[] from multilib.h
-$(srcdir)/config/avr/multilib.h: s-avr-mlib; @true
-
 s-mlib: $(srcdir)/config/avr/t-multilib
 
 s-avr-mlib: $(srcdir)/config/avr/genmultilib.awk $(AVR_MCUS)
 	$(AWK) -f $< -v FORMAT=Makefile   $< $(AVR_MCUS) > tmp-avr-mlib
-	$(AWK) -f $< -v FORMAT=multilib.h $< $(AVR_MCUS) > tmp-avr-mlib.h
-	$(SHELL) $(srcdir)/../move-if-change \
-		tmp-avr-mlib.h 	$(srcdir)/config/avr/multilib.h
 	$(SHELL) $(srcdir)/../move-if-change \
 		tmp-avr-mlib 	$(srcdir)/config/avr/t-multilib
 	$(STAMP) $@
Index: gcc/config/avr/genmultilib.awk
===================================================================
--- gcc/config/avr/genmultilib.awk	(revision 185858)
+++ gcc/config/avr/genmultilib.awk	(working copy)
@@ -26,9 +26,6 @@ 
 # FORMAT = "Makefile": Generate Makefile Snipet that sets some
 #                      MULTILIB_* Variables as needed.
 #
-# FORMAT = "multilib.h": Generate C Header intended to override
-#                      (parts of) multilib.h used in gcc.c.
-#
 ##################################################################
 
 BEGIN {
@@ -41,7 +38,7 @@  BEGIN {
 
     mtiny[0] = ""
     mtiny[1] = "tiny-stack"
-    option["tiny-stack"] = "mtiny-stack"
+    option["tiny-stack"] = "msp8"
 }
 
 ##################################################################
@@ -54,18 +51,6 @@  BEGIN {
 	next
     else if (comment == 1)
     {
-	if (FORMAT == "multilib.h")
-	{
-	    print "/*"
-	    print "   Auto-generated C header"
-	    print "   Generated by    : ./gcc/config/avr/genmultilib.awk"
-	    print "   Generated from  : ./gcc/config/avr/avr-mcus.def"
-	    print "   Used by         : ./gcc/gcc.c via tm.h"
-	    print "   Purpose         : Override multilib_raw[] from multilib.h"
-	    print "*/"
-	    print "/*"
-	}
-
 	if (FORMAT == "Makefile")
 	{
 	    print "# Auto-generated Makefile Snip"
@@ -78,15 +63,12 @@  BEGIN {
 
     comment = 2;
 
-    if (FORMAT == "multilib.h")
-	gsub ("#", "  ")
-
     print
 }
 
 /^$/ {
-    if (comment && FORMAT == "multilib.h")
-	print "*/"
+    # The first empty line stops copy-pasting the GPL comments
+    # from this file to the generated file.
 
     comment = 0
 }
@@ -144,7 +126,6 @@  BEGIN {
 #    m_dirnames    <->    MULTILIB_DIRNAMES           "
 #    m_exceptions  <->    MULTILIB_EXCEPTIONS         "
 #    m_matches     <->    MULTILIB_MATCHES            "
-#    m_raw         <->    avr_multilib_raw         multilib.h
 #
 ##################################################################
 
@@ -154,11 +135,9 @@  END {
     m_exceptions = "\nMULTILIB_EXCEPTIONS ="
     m_matches    = "\nMULTILIB_MATCHES ="
 
-    m_raw = ""
-
     ##############################################################
     # Compose MULTILIB_OPTIONS.  This represents the Cross-Product
-    #    (avr2, avr25, ...) x mtiny-stack
+    #    (avr2, avr25, ...) x msp8
 
     sep = ""
     for (c = 0; c < n_cores; c++)
@@ -167,54 +146,25 @@  END {
 	sep = "/"
     }
 
-    # The ... x mtiny-stack
+    # The ... x msp8
     m_options = m_options " " option[mtiny[1]]
 
     ##############################################################
     # Map Device to its multilib
 
-    # All Mappings that cannot be represented by GCC's genmultilib
-    # Machinery must be handcrafted.
-
-    dot_excludes = ""
-    m_raw_sp8 = ""
-
     for (t = 0; t < n_mcu; t++)
     {
 	core = toCore[mcu[t]]
 	
-	if (tiny_stack[mcu[t]] == 1)
-	{
-	    if (core == "avr2")
-		dir = mtiny[1]
-	    else
-		dir = core "/" mtiny[1]
-
-	    m_raw_sp8 = m_raw_sp8 "  \"" dir " " option[mcu[t]] ";\",\n"
-	    dot_excludes = dot_excludes " !" option[mcu[t]]
-
-	    line = option[mcu[t]] ":" option[mcu[t]]
-	    gsub ("=", "?", line)
-	    gsub (":", "=", line)
-
-	    m_matches = m_matches " \\\n\t" line
-	}
-
-	# The SP = 16 Devices are vanilla: Do the same as
-	# MULTILIB_MATCHES would yield.  Don't list avr2 (default)
-
-	if (core != "avr2")
-	{
-	    line = option[core] ":" option[mcu[t]]
-	    gsub ("=", "?", line)
-	    gsub (":", "=", line)
+	line = option[core] ":" option[mcu[t]]
+	gsub ("=", "?", line)
+	gsub (":", "=", line)
 
-	    m_matches = m_matches " \\\n\t" line
-	}
+	m_matches = m_matches " \\\n\t" line
     }
 
     ####################################################################
-    # Compose MULTILIB_DIRNAMES, MULTILIB_EXEPTIONS and avr_multilib_raw
+    # Compose MULTILIB_DIRNAMES and MULTILIB_EXEPTIONS
 
     n_mtiny = 2
     for (t = 0; t < n_mtiny; t++)
@@ -248,38 +198,6 @@  END {
 
 	    if (core != "avr2" || mtiny[t] == "")
 		m_dirnames = m_dirnames " " mdir
-
-	    # Remainder deals with avr_multilib_raw Entries.
-	    # Each Entry looks like
-	    #     "multilib-dir option-to-match !option-to-avoid-match;"
-	    # for Example:
-	    #     "avr25/tiny-stack !mmcu=avr2 mmcu=avr25 !mmcu=avr3 ... mtiny-stack;"
-
-	    if (mdir == "")
-		mdir = "."
-
-	    line = mdir
-
-	    for (s = 0; s < n_cores; s++)
-	    {
-		if (cores[s] == core)
-		    line = line " " option[cores[s]]
-		else
-		    line = line " !" option[cores[s]]
-	    }
-
-	    if (tiny_stack[core] != 0)
-	    {
-		if (mtiny[t] == "")
-		    line = line " !" option[mtiny[1]]
-		else
-		    line = line " " option[mtiny[1]]
-	    }
-
-	    if (mdir == ".")
-		line = line dot_excludes
-
-	    m_raw = m_raw "  \"" line ";\",\n"
 	}
 
     ############################################################
@@ -295,21 +213,4 @@  END {
 	print m_exceptions
 	print m_matches
     }
-
-    if (FORMAT == "multilib.h")
-    {
-	# Intended Target: ./gcc/config/avr/multilib.h
-
-	print "#if defined NULL && !defined AVR_MULTILIB_H"
-	print "#define AVR_MULTILIB_H"
-
-	print "static const char* const avr_multilib_raw[] = {"
-	print m_raw_sp8
-	print m_raw
-	print "  NULL\n};"
-
-	print "#undef  multilib_raw"
-	print "#define multilib_raw avr_multilib_raw"
-	print "#endif /* AVR_MULTILIB_H */"
-    }
 }
Index: gcc/config/avr/driver-avr.c
===================================================================
--- gcc/config/avr/driver-avr.c	(revision 185858)
+++ gcc/config/avr/driver-avr.c	(working copy)
@@ -112,3 +112,24 @@  avr_device_to_devicelib (int argc, const
   return concat ("-l", avr_current_device->library_name, NULL);
 }
 
+const char*
+avr_device_to_sp8 (int argc, const char **argv)
+{
+  if (0 == argc)
+    return NULL;
+
+  avr_set_current_device (argv[0]);
+
+  /* Leave "avr2" and "avr25" alone.  These two architectures are
+     the only ones that mix devices with 8-bit SP and 16-bit SP.
+     -msp8 is set by mmultilib machinery.  */
+
+  if (avr_current_device->macro == NULL
+      && (avr_current_device->arch == ARCH_AVR2
+          || avr_current_device->arch == ARCH_AVR25))
+    return "";
+
+  return avr_current_device->short_sp
+    ? "-msp8"
+    : "%<msp8";
+}
Index: gcc/config/avr/multilib.h
===================================================================
--- gcc/config/avr/multilib.h	(revision 185858)
+++ gcc/config/avr/multilib.h	(working copy)
@@ -1,70 +0,0 @@ 
-/*
-   Auto-generated C header
-   Generated by    : ./gcc/config/avr/genmultilib.awk
-   Generated from  : ./gcc/config/avr/avr-mcus.def
-   Used by         : ./gcc/gcc.c via tm.h
-   Purpose         : Override multilib_raw[] from multilib.h
-*/
-/*
-   Copyright (C) 2011 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/>.
-*/
-#if defined NULL && !defined AVR_MULTILIB_H
-#define AVR_MULTILIB_H
-static const char* const avr_multilib_raw[] = {
-  "tiny-stack mmcu=at90s2313;",
-  "tiny-stack mmcu=at90s2323;",
-  "tiny-stack mmcu=at90s2333;",
-  "tiny-stack mmcu=at90s2343;",
-  "tiny-stack mmcu=attiny22;",
-  "tiny-stack mmcu=attiny26;",
-  "tiny-stack mmcu=at90s4433;",
-  "avr25/tiny-stack mmcu=attiny13;",
-  "avr25/tiny-stack mmcu=attiny13a;",
-  "avr25/tiny-stack mmcu=attiny2313;",
-  "avr25/tiny-stack mmcu=attiny2313a;",
-  "avr25/tiny-stack mmcu=attiny24;",
-  "avr25/tiny-stack mmcu=attiny24a;",
-  "avr25/tiny-stack mmcu=attiny25;",
-  "avr25/tiny-stack mmcu=attiny261;",
-  "avr25/tiny-stack mmcu=attiny261a;",
-
-  ". !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7 !mtiny-stack !mmcu=at90s2313 !mmcu=at90s2323 !mmcu=at90s2333 !mmcu=at90s2343 !mmcu=attiny22 !mmcu=attiny26 !mmcu=at90s4433 !mmcu=attiny13 !mmcu=attiny13a !mmcu=attiny2313 !mmcu=attiny2313a !mmcu=attiny24 !mmcu=attiny24a !mmcu=attiny25 !mmcu=attiny261 !mmcu=attiny261a;",
-  "avr2 mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7 !mtiny-stack;",
-  "avr25 !mmcu=avr2 mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7 !mtiny-stack;",
-  "avr3 !mmcu=avr2 !mmcu=avr25 mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;",
-  "avr31 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;",
-  "avr35 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;",
-  "avr4 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;",
-  "avr5 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;",
-  "avr51 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;",
-  "avr6 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;",
-  "avrxmega2 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;",
-  "avrxmega4 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;",
-  "avrxmega5 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7;",
-  "avrxmega6 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 mmcu=avrxmega6 !mmcu=avrxmega7;",
-  "avrxmega7 !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 mmcu=avrxmega7;",
-  "tiny-stack !mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7 mtiny-stack;",
-  "avr2/tiny-stack mmcu=avr2 !mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7 mtiny-stack;",
-  "avr25/tiny-stack !mmcu=avr2 mmcu=avr25 !mmcu=avr3 !mmcu=avr31 !mmcu=avr35 !mmcu=avr4 !mmcu=avr5 !mmcu=avr51 !mmcu=avr6 !mmcu=avrxmega2 !mmcu=avrxmega4 !mmcu=avrxmega5 !mmcu=avrxmega6 !mmcu=avrxmega7 mtiny-stack;",
-
-  NULL
-};
-#undef  multilib_raw
-#define multilib_raw avr_multilib_raw
-#endif /* AVR_MULTILIB_H */
Index: gcc/config/avr/avr.c
===================================================================
--- gcc/config/avr/avr.c	(revision 185858)
+++ gcc/config/avr/avr.c	(working copy)
@@ -963,7 +963,7 @@  avr_prologue_setup_frame (HOST_WIDE_INT
             {
               /* Don't error so that insane code from newlib still compiles
                  and does not break building newlib.  As PR51345 is implemented
-                 now, there are multilib variants with -mtiny-stack.
+                 now, there are multilib variants with -msp8.
                  
                  If user wants sanity checks he can use -Wstack-usage=
                  or similar options.
@@ -2774,7 +2774,7 @@  output_movhi (rtx insn, rtx xop[], int *
             }
           else if (test_hard_reg_class (STACK_REG, src))
             {
-              return AVR_HAVE_8BIT_SP
+              return !AVR_HAVE_SPH
                 ? avr_asm_len ("in %A0,__SP_L__" CR_TAB
                                "clr %B0", xop, plen, -2)
                 
@@ -7341,7 +7341,7 @@  avr_file_start (void)
 
   /* Print I/O addresses of some SFRs used with IN and OUT.  */
 
-  if (!AVR_HAVE_8BIT_SP)
+  if (AVR_HAVE_SPH)
     fprintf (asm_out_file, "__SP_H__ = 0x%02x\n", avr_addr.sp_h - sfr_offset);
 
   fprintf (asm_out_file, "__SP_L__ = 0x%02x\n", avr_addr.sp_l - sfr_offset);
Index: gcc/config/avr/avr.h
===================================================================
--- gcc/config/avr/avr.h	(revision 185858)
+++ gcc/config/avr/avr.h	(working copy)
@@ -188,7 +188,26 @@  enum
 #define AVR_HAVE_RAMPZ (avr_current_arch->have_elpm             \
                         || avr_current_arch->have_rampd)
 #define AVR_HAVE_EIJMP_EICALL (avr_current_arch->have_eijmp_eicall)
-#define AVR_HAVE_8BIT_SP (avr_current_device->short_sp || TARGET_TINY_STACK)
+
+/* Handling of 8-bit SP versus 16-bit SP is as follows:
+
+   -msp8 is used internally to select the right multilib for targets with
+   8-bit SP.  -msp8 is set automatically by DRIVER_SELF_SPECS for devices
+   with 8-bit SP or by multilib generation machinery.  If a frame pointer is
+   needed and SP is only 8 bits wide, SP is zero-extended to get FP.
+
+   TARGET_TINY_STACK is triggered by -mtiny-stack which is a user option.
+   This option has no effect on multilib selection.  It serves to save some
+   bytes on 16-bit SP devices by only changing SP_L and leaving SP_H alone.
+
+   These two properties are reflected by built-in macros __AVR_SP8__ resp.
+   __AVR_HAVE_8BIT_SP__ and __AVR_HAVE_16BIT_SP__.  During multilib generation
+   there is always __AVR_SP8__ == __AVR_HAVE_8BIT_SP__.  */
+
+#define AVR_HAVE_8BIT_SP                                                \
+  (avr_current_device->short_sp || TARGET_TINY_STACK || avr_sp8)
+
+#define AVR_HAVE_SPH (!avr_sp8)
 
 #define AVR_2_BYTE_PC (!AVR_HAVE_EIJMP_EICALL)
 #define AVR_3_BYTE_PC (AVR_HAVE_EIJMP_EICALL)
@@ -577,13 +596,16 @@  extern const char *avr_device_to_arch (i
 extern const char *avr_device_to_data_start (int argc, const char **argv);
 extern const char *avr_device_to_startfiles (int argc, const char **argv);
 extern const char *avr_device_to_devicelib (int argc, const char **argv);
+extern const char *avr_device_to_sp8 (int argc, const char **argv);
 
-#define EXTRA_SPEC_FUNCTIONS \
-  { "device_to_arch", avr_device_to_arch }, \
+#define EXTRA_SPEC_FUNCTIONS                            \
+  { "device_to_arch", avr_device_to_arch },             \
   { "device_to_data_start", avr_device_to_data_start }, \
-  { "device_to_startfile", avr_device_to_startfiles }, \
-  { "device_to_devicelib", avr_device_to_devicelib },
+  { "device_to_startfile", avr_device_to_startfiles },  \
+  { "device_to_devicelib", avr_device_to_devicelib },   \
+  { "device_to_sp8", avr_device_to_sp8 },
 
+#define DRIVER_SELF_SPECS " %:device_to_sp8(%{mmcu=*:%*}) "
 #define CPP_SPEC ""
 
 #define CC1_SPEC ""