Patchwork replace LIBGCC2_WORDS_BIG_ENDIAN with __BYTE_ORDER__

login
register
mail settings
Submitter Nathan Froyd
Date Oct. 14, 2010, 1:52 a.m.
Message ID <20101014015219.GV24720@nightcrawler>
Download mbox | patch
Permalink /patch/67765/
State New
Headers show

Comments

Nathan Froyd - Oct. 14, 2010, 1:52 a.m.
The patch below is a reworking of the patch posted here:

http://gcc.gnu.org/ml/gcc-patches/2010-10/msg01081.html

to take into account the need for documentation in cpp.texi and to use a
__BYTE_ORDER__-based scheme.  I am a little uncertain about the use of
__BYTE_ORDER__ etc. as at least:

http://gcc.gnu.org/ml/gcc-help/2007-07/msg00342.html

suggests that there may be systems in the wild already using that.
glibc obviously does not, and the *BSDs, Solaris, VxWorks, and
newlib-based targets don't seem to, either.

I don't know about HP-UX, IRIX, OSF/1, or AIX.  Steve, Rainer and David,
could you please confirm that GCC defining __BYTE_ORDER__ et al will not
interfere with system headers on those targets with which you are
familiar?

Testing in progress on x86_64-unknown-linux-gnu.  OK to commit?

-Nathan

gcc/
	* cppbuiltin.c (define_builtin_macros_for_type_sizes): Define
	__BYTE_ORDER__, __LITTLE_ENDIAN__, __BIG_ENDIAN__, and
	__PDP_ENDIAN__.
	* libgcc2.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	(struct DWstruct): Define based on __BYTE_ORDER__.
	* config/fixed-bit.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	(struct INTstruct): Define based on __BYTE_ORDER__.
	* config/dfp-bit.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	(LIBGCC2_FLOAT_WORDS_BIG_ENDIAN): Test __BYTE_ORDER__.
	* system.h (LIBGCC2_WORDS_BIG_ENDIAN): Poison identifier.
	* config/arc/arc.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* config/arm/arm.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* config/ia64/ia64.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* config/iq2000/iq2000.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* config/lm32/lm32.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* config/m32r/m32r.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* config/mcore/mcore.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* config/mep/mep.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* config/mips/mips.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* config/rs6000/sysv4.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* config/rx/rx.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* config/score/score.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* config/sh/sh.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* config/sparc/sparc.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* config/xtensa/xtensa.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* doc/tm.texi.in (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	* doc/tm.texi: Regenerate.
	* doc/cpp.texi (__BYTE_ORDER__, __LITTLE_ENDIAN__): Document.
	(__BIG_ENDIAN__, __PDP_ENDIAN__): Likewise.

libdecnumber/
	* dconfig.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
	(LIBGCC2_FLOAT_WORDS_BIG_ENDIAN): Test __BYTE_ORDER__

libgcc/
	* config/libbid/bid_gcc_intrinsics.h (LIBGCC2_WORDS_BIG_ENDIAN):
	Delete.
	(LIBGCC2_FLOAT_WORDS_BIG_ENDIAN): Test __BYTE_ORDER__
Rainer Orth - Oct. 14, 2010, 11:22 a.m.
Nathan Froyd <froydnj@codesourcery.com> writes:

> I don't know about HP-UX, IRIX, OSF/1, or AIX.  Steve, Rainer and David,
> could you please confirm that GCC defining __BYTE_ORDER__ et al will not
> interfere with system headers on those targets with which you are
> familiar?

At least on IRIX 6.5 and Tru64 UNIX V5.1B, there's no instance of
__BYTE_ORDER__ in the system headers.  I'll fire off a bootstrap on both
targets with your patch to check if there's nothing amiss, though this
will take about two days.

	Rainer
David Edelsohn - Oct. 14, 2010, 2:47 p.m.
On Wed, Oct 13, 2010 at 9:52 PM, Nathan Froyd <froydnj@codesourcery.com> wrote:
> The patch below is a reworking of the patch posted here:
>
> http://gcc.gnu.org/ml/gcc-patches/2010-10/msg01081.html
>
> to take into account the need for documentation in cpp.texi and to use a
> __BYTE_ORDER__-based scheme.  I am a little uncertain about the use of
> __BYTE_ORDER__ etc. as at least:
>
> http://gcc.gnu.org/ml/gcc-help/2007-07/msg00342.html
>
> suggests that there may be systems in the wild already using that.
> glibc obviously does not, and the *BSDs, Solaris, VxWorks, and
> newlib-based targets don't seem to, either.
>
> I don't know about HP-UX, IRIX, OSF/1, or AIX.  Steve, Rainer and David,
> could you please confirm that GCC defining __BYTE_ORDER__ et al will not
> interfere with system headers on those targets with which you are
> familiar?

AIX uses the macro BYTE_ORDER but not __BYTE_ORDER__

- David
Richard Henderson - Oct. 14, 2010, 3:05 p.m.
On 10/13/2010 06:52 PM, Nathan Froyd wrote:
> 	* cppbuiltin.c (define_builtin_macros_for_type_sizes): Define
> 	__BYTE_ORDER__, __LITTLE_ENDIAN__, __BIG_ENDIAN__, and
> 	__PDP_ENDIAN__.
> 	* libgcc2.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	(struct DWstruct): Define based on __BYTE_ORDER__.
> 	* config/fixed-bit.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	(struct INTstruct): Define based on __BYTE_ORDER__.
> 	* config/dfp-bit.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	(LIBGCC2_FLOAT_WORDS_BIG_ENDIAN): Test __BYTE_ORDER__.
> 	* system.h (LIBGCC2_WORDS_BIG_ENDIAN): Poison identifier.
> 	* config/arc/arc.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* config/arm/arm.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* config/ia64/ia64.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* config/iq2000/iq2000.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* config/lm32/lm32.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* config/m32r/m32r.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* config/mcore/mcore.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* config/mep/mep.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* config/mips/mips.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* config/rs6000/sysv4.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* config/rx/rx.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* config/score/score.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* config/sh/sh.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* config/sparc/sparc.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* config/xtensa/xtensa.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* doc/tm.texi.in (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	* doc/tm.texi: Regenerate.
> 	* doc/cpp.texi (__BYTE_ORDER__, __LITTLE_ENDIAN__): Document.
> 	(__BIG_ENDIAN__, __PDP_ENDIAN__): Likewise.
> 
> libdecnumber/
> 	* dconfig.h (LIBGCC2_WORDS_BIG_ENDIAN): Delete.
> 	(LIBGCC2_FLOAT_WORDS_BIG_ENDIAN): Test __BYTE_ORDER__
> 
> libgcc/
> 	* config/libbid/bid_gcc_intrinsics.h (LIBGCC2_WORDS_BIG_ENDIAN):
> 	Delete.
> 	(LIBGCC2_FLOAT_WORDS_BIG_ENDIAN): Test __BYTE_ORDER__

Ok.

Based on the responses from Rainer and DJE, I don't expect any
major conflicts with system headers.

Thanks for the patience.


r~
Steve Ellcey - Oct. 14, 2010, 3:45 p.m.
On Wed, 2010-10-13 at 21:52 -0400, Nathan Froyd wrote:

> I don't know about HP-UX, IRIX, OSF/1, or AIX.  Steve, Rainer and David,
> could you please confirm that GCC defining __BYTE_ORDER__ et al will not
> interfere with system headers on those targets with which you are
> familiar?

HP-UX has uses of BYTE_ORDER in its headers but I don't see
__BYTE_ORDER__ used anywhere.

Steve Ellcey
sje@cup.hp.com
Joseph S. Myers - Oct. 14, 2010, 4:29 p.m.
On Wed, 13 Oct 2010, Nathan Froyd wrote:

> The patch below is a reworking of the patch posted here:
> 
> http://gcc.gnu.org/ml/gcc-patches/2010-10/msg01081.html
> 
> to take into account the need for documentation in cpp.texi and to use a
> __BYTE_ORDER__-based scheme.  I am a little uncertain about the use of
> __BYTE_ORDER__ etc. as at least:

This patch is definitely unsafe.  Not so much on account of __BYTE_ORDER__ 
(although codesearch.google.com shows plenty of matches for that), but on 
account of __BIG_ENDIAN__ and __LITTLE_ENDIAN__.  Those names are already 
predefined for various targets by GCC to indicate "this is big-endian" or 
"this is little-endian", so defining them unconditionally will break code 
(glibc's sysdeps/sh/bits/endian.h, for example) that expects those 
meanings.

Whatever macro you define for byte order, I think you can only safely 
define one macros, not others such as __BIG_ENDIAN__ or variants thereof.

> +(word) of the quantity, respectively.  If @code{__BYTE_ORDER__} is
> +equal to @code{__PDP_ENDIAN__}, then bytes in 16-bit words are laid
> +out in a little-endian fashion, whereas the 16-bit subwords of a
> +32-bit quantity are laid out in big-endian fashion.

Are you sure that 16-bit and 32-bit reflect exactly how the 
machine-independent code in GCC handles the target macros: does it really 
have those sizes hardcoded?
Richard Henderson - Oct. 14, 2010, 4:36 p.m.
On 10/14/2010 09:29 AM, Joseph S. Myers wrote:
> On Wed, 13 Oct 2010, Nathan Froyd wrote:
> 
>> The patch below is a reworking of the patch posted here:
>>
>> http://gcc.gnu.org/ml/gcc-patches/2010-10/msg01081.html
>>
>> to take into account the need for documentation in cpp.texi and to use a
>> __BYTE_ORDER__-based scheme.  I am a little uncertain about the use of
>> __BYTE_ORDER__ etc. as at least:
> 
> This patch is definitely unsafe.  Not so much on account of __BYTE_ORDER__ 
> (although codesearch.google.com shows plenty of matches for that), but on 
> account of __BIG_ENDIAN__ and __LITTLE_ENDIAN__.  Those names are already 
> predefined for various targets by GCC to indicate "this is big-endian" or 
> "this is little-endian", so defining them unconditionally will break code 
> (glibc's sysdeps/sh/bits/endian.h, for example) that expects those 
> meanings.

We could define __BYTE_ORDER_{BIG,LITTLE,PDP}_ENDIAN__ instead, surely?


r~
Joseph S. Myers - Oct. 14, 2010, 4:42 p.m.
On Thu, 14 Oct 2010, Richard Henderson wrote:

> On 10/14/2010 09:29 AM, Joseph S. Myers wrote:
> > On Wed, 13 Oct 2010, Nathan Froyd wrote:
> > 
> >> The patch below is a reworking of the patch posted here:
> >>
> >> http://gcc.gnu.org/ml/gcc-patches/2010-10/msg01081.html
> >>
> >> to take into account the need for documentation in cpp.texi and to use a
> >> __BYTE_ORDER__-based scheme.  I am a little uncertain about the use of
> >> __BYTE_ORDER__ etc. as at least:
> > 
> > This patch is definitely unsafe.  Not so much on account of __BYTE_ORDER__ 
> > (although codesearch.google.com shows plenty of matches for that), but on 
> > account of __BIG_ENDIAN__ and __LITTLE_ENDIAN__.  Those names are already 
> > predefined for various targets by GCC to indicate "this is big-endian" or 
> > "this is little-endian", so defining them unconditionally will break code 
> > (glibc's sysdeps/sh/bits/endian.h, for example) that expects those 
> > meanings.
> 
> We could define __BYTE_ORDER_{BIG,LITTLE,PDP}_ENDIAN__ instead, surely?

It does appear those names are not used in anything known to 
codesearch.google.com, although the variants without trailing underscores 
are.
Mike Stump - Oct. 14, 2010, 6:28 p.m.
On Oct 14, 2010, at 4:22 AM, Rainer Orth wrote:
> Nathan Froyd <froydnj@codesourcery.com> writes:
> 
>> I don't know about HP-UX, IRIX, OSF/1, or AIX.  Steve, Rainer and David,
>> could you please confirm that GCC defining __BYTE_ORDER__ et al will not
>> interfere with system headers on those targets with which you are
>> familiar?
> 
> At least on IRIX 6.5 and Tru64 UNIX V5.1B, there's no instance of
> __BYTE_ORDER__ in the system headers.

I was worried about darwin, I checked...  No instance there there...
Nathan Froyd - Oct. 18, 2010, 12:21 p.m.
On Thu, Oct 14, 2010 at 04:29:54PM +0000, Joseph S. Myers wrote:
> On Wed, 13 Oct 2010, Nathan Froyd wrote:
> > to take into account the need for documentation in cpp.texi and to use a
> > __BYTE_ORDER__-based scheme.  I am a little uncertain about the use of
> > __BYTE_ORDER__ etc. as at least:
> 
> This patch is definitely unsafe.  Not so much on account of __BYTE_ORDER__ 
> (although codesearch.google.com shows plenty of matches for that), but on 
> account of __BIG_ENDIAN__ and __LITTLE_ENDIAN__.

Thanks for pointing this out.  I will submit an updated patch.

> > +(word) of the quantity, respectively.  If @code{__BYTE_ORDER__} is
> > +equal to @code{__PDP_ENDIAN__}, then bytes in 16-bit words are laid
> > +out in a little-endian fashion, whereas the 16-bit subwords of a
> > +32-bit quantity are laid out in big-endian fashion.
> 
> Are you sure that 16-bit and 32-bit reflect exactly how the 
> machine-independent code in GCC handles the target macros: does it really 
> have those sizes hardcoded?

No idea; I doubt that it does.  Can we just ditch the pdp11 port? ;)

-Nathan
Mark Mitchell - Oct. 19, 2010, 5:51 p.m.
On 10/18/2010 5:21 AM, Nathan Froyd wrote:

> No idea; I doubt that it does.  Can we just ditch the pdp11 port? ;)

In all seriousness, why shouldn't we?  The usual response is that
someone out there somewhere is willing to maintain it.  But, are there
really enough users to make it worth it?
Paul Koning - Oct. 19, 2010, 6:07 p.m.
I'm indeed willing to keep maintaining it (though admittedly I haven't been all that active -- that may change a bit soon).  On the other hand, I'll admit that I don't know if there are all that many users.

	paul

On Oct 19, 2010, at 1:51 PM, Mark Mitchell wrote:

> On 10/18/2010 5:21 AM, Nathan Froyd wrote:
> 
>> No idea; I doubt that it does.  Can we just ditch the pdp11 port? ;)
> 
> In all seriousness, why shouldn't we?  The usual response is that
> someone out there somewhere is willing to maintain it.  But, are there
> really enough users to make it worth it?
> 
> -- 
> Mark Mitchell
> CodeSourcery
> mark@codesourcery.com
> (650) 331-3385 x713
Mark Mitchell - Oct. 19, 2010, 7:57 p.m.
On 10/19/2010 11:07 AM, Paul Koning wrote:

> I'm indeed willing to keep maintaining it (though admittedly I
> haven't been all that active -- that may change a bit soon).  On the
> other hand, I'll admit that I don't know if there are all that many
> users.

I certainly don't mean to criticize; a key idea for FOSS is that anyone
can make the software do what they want, and I'm all for people porting
GCC to whatever platform is of interest to them!

I'm just skeptical that maintaining PDP11 support in GCC is worthwhile
if it has any non-trivial cost for users without a stake in PDP11.  This
is a situation where it seems like it's a hassle, and given that my
inclination would be just to remove PDP11 support from GCC.
Paul Koning - Oct. 19, 2010, 8:05 p.m.
Thanks, and I understood your comments that way.

I don't see that there is a significant cost.  Yes, pdp11 is one of the few (though apparently not the only) platform that has mixed endian.  But that has very little impact (one example, curiously, being a 3 year old bug I just fixed...).

From what I recall, Nathan's original comment was triggered essentially by the question of what a "word" is in WORD_BIG_ENDIAN.  "Is it hardcoded" was the question that was asked.  I believe the answer is no, "WORD" is a register.  So in the case of the pdp11, where registers are 16 bits, mixed endian means 3412, but if one of the other mixed endian platforms has wider words (wider registers) then that doesn't carry over.

Isn't "WORD" a concept that occurs in many places?  And certainly the size of a word is not consistent across all platforms.  So I don't know that the existence of the pdp11 creates unique levels of pain here.

	paul

On Oct 19, 2010, at 3:57 PM, Mark Mitchell wrote:

> On 10/19/2010 11:07 AM, Paul Koning wrote:
> 
>> I'm indeed willing to keep maintaining it (though admittedly I
>> haven't been all that active -- that may change a bit soon).  On the
>> other hand, I'll admit that I don't know if there are all that many
>> users.
> 
> I certainly don't mean to criticize; a key idea for FOSS is that anyone
> can make the software do what they want, and I'm all for people porting
> GCC to whatever platform is of interest to them!
> 
> I'm just skeptical that maintaining PDP11 support in GCC is worthwhile
> if it has any non-trivial cost for users without a stake in PDP11.  This
> is a situation where it seems like it's a hassle, and given that my
> inclination would be just to remove PDP11 support from GCC.
> 
> -- 
> Mark Mitchell
> CodeSourcery
> mark@codesourcery.com
> (650) 331-3385 x713

Patch

diff --git a/gcc/config/arc/arc.h b/gcc/config/arc/arc.h
index f2d273d..bb47224 100644
--- a/gcc/config/arc/arc.h
+++ b/gcc/config/arc/arc.h
@@ -99,14 +99,6 @@  extern int arc_cpu_type;
    numbered.  */
 #define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN)
 
-/* Define this to set the endianness to use in libgcc2.c, which can
-   not depend on target_flags.  */
-#ifdef __big_endian__
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#endif
-
 /* Width of a word, in units (bytes).  */
 #define UNITS_PER_WORD 4
 
diff --git a/gcc/config/arm/arm.h b/gcc/config/arm/arm.h
index c8cbfa2..0764285 100644
--- a/gcc/config/arm/arm.h
+++ b/gcc/config/arm/arm.h
@@ -560,14 +560,6 @@  extern int arm_arch_hwdiv;
    This is always false, even when in big-endian mode.  */
 #define WORDS_BIG_ENDIAN  (BYTES_BIG_ENDIAN && ! TARGET_LITTLE_WORDS)
 
-/* LIBGCC2_WORDS_BIG_ENDIAN has to be a constant, so we define this based
-   on processor pre-defineds when compiling libgcc2.c.  */
-#if defined(__ARMEB__) && !defined(__ARMWEL__)
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#endif
-
 /* Define this if most significant word of doubles is the lowest numbered.
    The rules are different based on whether or not we use FPA-format,
    VFP-format or some other floating point co-processor's format doubles.  */
diff --git a/gcc/config/dfp-bit.h b/gcc/config/dfp-bit.h
index f093785..142c56b 100644
--- a/gcc/config/dfp-bit.h
+++ b/gcc/config/dfp-bit.h
@@ -33,12 +33,8 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "coretypes.h"
 #include "tm.h"
 
-#ifndef LIBGCC2_WORDS_BIG_ENDIAN
-#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
-#endif
-
 #ifndef LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
-#define LIBGCC2_FLOAT_WORDS_BIG_ENDIAN LIBGCC2_WORDS_BIG_ENDIAN
+#define LIBGCC2_FLOAT_WORDS_BIG_ENDIAN (__BYTE_ORDER__ != __LITTLE_ENDIAN__)
 #endif
 
 #ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
diff --git a/gcc/config/fixed-bit.h b/gcc/config/fixed-bit.h
index ce5b96e..b75da67 100644
--- a/gcc/config/fixed-bit.h
+++ b/gcc/config/fixed-bit.h
@@ -41,14 +41,6 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
    Ex: If we define FROM_QQ and TO_SI, the conversion from QQ to SI is
    generated.  */
 
-/* Permit the tm.h file to select the endianness to use just for this
-   file.  This is used when the endianness is determined when the
-   compiler is run.  */
-
-#ifndef LIBGCC2_WORDS_BIG_ENDIAN
-#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
-#endif
-
 #ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
 #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
 #endif
@@ -428,7 +420,7 @@  typedef int word_type __attribute__ ((mode (__word__)));
 /* The following defines are based on the previous defines.  */
 
 #if defined (HINT_C_TYPE)
-#if LIBGCC2_WORDS_BIG_ENDIAN
+#if __BYTE_ORDER__ != __LITTLE_ENDIAN__
   struct INTstruct {HINT_C_TYPE high, low;};
 #else
   struct INTstruct {HINT_C_TYPE low, high;};
diff --git a/gcc/config/ia64/ia64.h b/gcc/config/ia64/ia64.h
index 98e9b64..8605592 100644
--- a/gcc/config/ia64/ia64.h
+++ b/gcc/config/ia64/ia64.h
@@ -148,12 +148,6 @@  extern enum processor_type ia64_tune;
 
 #define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
 
-#if defined(__BIG_ENDIAN__)
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#endif
-
 #define UNITS_PER_WORD 8
 
 #define POINTER_SIZE (TARGET_ILP32 ? 32 : 64)
diff --git a/gcc/config/iq2000/iq2000.h b/gcc/config/iq2000/iq2000.h
index 6e670ba..05b02f7 100644
--- a/gcc/config/iq2000/iq2000.h
+++ b/gcc/config/iq2000/iq2000.h
@@ -76,7 +76,6 @@ 
 #define BITS_BIG_ENDIAN 		0
 #define BYTES_BIG_ENDIAN 		1 
 #define WORDS_BIG_ENDIAN 		1
-#define LIBGCC2_WORDS_BIG_ENDIAN	1
 #define BITS_PER_WORD 			32
 #define MAX_BITS_PER_WORD 		64
 #define UNITS_PER_WORD 			4
diff --git a/gcc/config/lm32/lm32.h b/gcc/config/lm32/lm32.h
index b0c2d59..afe9a6b 100644
--- a/gcc/config/lm32/lm32.h
+++ b/gcc/config/lm32/lm32.h
@@ -84,7 +84,6 @@ 
 #define BITS_BIG_ENDIAN 0
 #define BYTES_BIG_ENDIAN 1
 #define WORDS_BIG_ENDIAN 1
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
 
 #define BITS_PER_UNIT 8
 #define BITS_PER_WORD 32
diff --git a/gcc/config/m32r/m32r.h b/gcc/config/m32r/m32r.h
index d767cb9..7bfc975 100644
--- a/gcc/config/m32r/m32r.h
+++ b/gcc/config/m32r/m32r.h
@@ -328,12 +328,6 @@  extern enum m32r_sdata m32r_sdata;
    numbered.  */
 #define WORDS_BIG_ENDIAN (TARGET_LITTLE_ENDIAN == 0)
 
-/* Define this macro if WORDS_BIG_ENDIAN is not constant.  This must
-   be a constant value with the same meaning as WORDS_BIG_ENDIAN,
-   which will be used only when compiling libgcc2.c.  Typically the
-   value will be set based on preprocessor defines.  */
-/*#define LIBGCC2_WORDS_BIG_ENDIAN 1*/
-
 /* Width of a word, in units (bytes).  */
 #define UNITS_PER_WORD 4
 
diff --git a/gcc/config/mcore/mcore.h b/gcc/config/mcore/mcore.h
index a149eb1..8efe64f 100644
--- a/gcc/config/mcore/mcore.h
+++ b/gcc/config/mcore/mcore.h
@@ -106,12 +106,6 @@  extern char * mcore_current_function_name;
    numbered.  */
 #define WORDS_BIG_ENDIAN (! TARGET_LITTLE_END)
 
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#ifdef __MCORELE__
-#undef  LIBGCC2_WORDS_BIG_ENDIAN
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#endif
-
 #define MAX_BITS_PER_WORD 32
 
 /* Width of a word, in units (bytes).  */
diff --git a/gcc/config/mep/mep.h b/gcc/config/mep/mep.h
index 07f0c85..1f51aa9 100644
--- a/gcc/config/mep/mep.h
+++ b/gcc/config/mep/mep.h
@@ -167,12 +167,6 @@  crtbegin.o%s"
 #define BYTES_BIG_ENDIAN (TARGET_LITTLE_ENDIAN ? 0 : 1)
 #define WORDS_BIG_ENDIAN (TARGET_LITTLE_ENDIAN ? 0 : 1)
 
-#ifdef __LITTLE_ENDIAN__
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#endif
-
 #define UNITS_PER_WORD 4
 
 #define PROMOTE_MODE(MODE, UNSIGNEDP, TYPE)	\
diff --git a/gcc/config/mips/mips.h b/gcc/config/mips/mips.h
index 23dba7c..449c893 100644
--- a/gcc/config/mips/mips.h
+++ b/gcc/config/mips/mips.h
@@ -1290,14 +1290,6 @@  enum mips_code_readable_setting {
 #define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
 #define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
 
-/* Define this to set the endianness to use in libgcc2.c, which can
-   not depend on target_flags.  */
-#if !defined(MIPSEL) && !defined(__MIPSEL__)
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#endif
-
 #define MAX_BITS_PER_WORD 64
 
 /* Width of a word, in units (bytes).  */
diff --git a/gcc/config/rs6000/sysv4.h b/gcc/config/rs6000/sysv4.h
index 25584b2..6d88e32 100644
--- a/gcc/config/rs6000/sysv4.h
+++ b/gcc/config/rs6000/sysv4.h
@@ -258,14 +258,6 @@  do {									\
 #define	BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN)
 #define	WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN)
 
-/* Define this to set the endianness to use in libgcc2.c, which can
-   not depend on target_flags.  */
-#if !defined(__LITTLE_ENDIAN__) && !defined(__sun__)
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#endif
-
 /* Define cutoff for using external functions to save floating point.
    When optimizing for size, use external functions when profitable.  */
 #define FP_SAVE_INLINE(FIRST_REG) (optimize_size			\
diff --git a/gcc/config/rx/rx.h b/gcc/config/rx/rx.h
index 7da4de1..534da5f 100644
--- a/gcc/config/rx/rx.h
+++ b/gcc/config/rx/rx.h
@@ -96,12 +96,6 @@  extern enum rx_cpu_types  rx_cpu_type;
 #define BYTES_BIG_ENDIAN 		TARGET_BIG_ENDIAN_DATA
 #define WORDS_BIG_ENDIAN 		TARGET_BIG_ENDIAN_DATA
 
-#ifdef __RX_BIG_ENDIAN__
-#define LIBGCC2_WORDS_BIG_ENDIAN	1
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN	0
-#endif
-
 #define UNITS_PER_WORD 			4
 
 #define INT_TYPE_SIZE			32
diff --git a/gcc/config/score/score.h b/gcc/config/score/score.h
index 621f56e..a01ffed 100644
--- a/gcc/config/score/score.h
+++ b/gcc/config/score/score.h
@@ -106,14 +106,6 @@ 
 #define BYTES_BIG_ENDIAN       (TARGET_LITTLE_ENDIAN == 0)
 #define WORDS_BIG_ENDIAN       (TARGET_LITTLE_ENDIAN == 0)
 
-/* Define this to set the endianness to use in libgcc2.c, which can
-   not depend on target_flags.  */
-#if defined(__scorele__)
-#define LIBGCC2_WORDS_BIG_ENDIAN       0
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN       1
-#endif
-
 /* Width of a word, in units (bytes).  */
 #define UNITS_PER_WORD                 4
 
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 8f149dc..145f496 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -518,14 +518,6 @@  extern enum sh_divide_strategy_e sh_div_strategy;
    numbered.  */
 #define WORDS_BIG_ENDIAN (TARGET_LITTLE_ENDIAN == 0)
 
-/* Define this to set the endianness to use in libgcc2.c, which can
-   not depend on target_flags.  */
-#if defined(__LITTLE_ENDIAN__)
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#endif
-
 #define MAX_BITS_PER_WORD 64
 
 /* Width in bits of an `int'.  We want just 32-bits, even if words are
diff --git a/gcc/config/sparc/sparc.h b/gcc/config/sparc/sparc.h
index ccb7dca..1955e99 100644
--- a/gcc/config/sparc/sparc.h
+++ b/gcc/config/sparc/sparc.h
@@ -585,14 +585,6 @@  extern struct sparc_cpu_select sparc_select[];
    numbered.  */
 #define WORDS_BIG_ENDIAN 1
 
-/* Define this to set the endianness to use in libgcc2.c, which can
-   not depend on target_flags.  */
-#if defined (__LITTLE_ENDIAN__) || defined(__LITTLE_ENDIAN_DATA__)
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#endif
-
 #define MAX_BITS_PER_WORD	64
 
 /* Width of a word, in units (bytes).  */
diff --git a/gcc/config/xtensa/xtensa.h b/gcc/config/xtensa/xtensa.h
index 7dc22a2..435c21a 100644
--- a/gcc/config/xtensa/xtensa.h
+++ b/gcc/config/xtensa/xtensa.h
@@ -94,12 +94,6 @@  extern unsigned xtensa_current_frame_size;
 #define EXTRA_SPECS							\
   { "subtarget_cpp_spec", SUBTARGET_CPP_SPEC },
 
-#ifdef __XTENSA_EB__
-#define LIBGCC2_WORDS_BIG_ENDIAN 1
-#else
-#define LIBGCC2_WORDS_BIG_ENDIAN 0
-#endif
-
 /* Show we can debug even without a frame pointer.  */
 #define CAN_DEBUG_WITHOUT_FP
 
diff --git a/gcc/cppbuiltin.c b/gcc/cppbuiltin.c
index 89b0f41..28634a5 100644
--- a/gcc/cppbuiltin.c
+++ b/gcc/cppbuiltin.c
@@ -138,6 +138,24 @@  define_builtin_macros_for_type_sizes (cpp_reader *pfile)
   cpp_define_formatted (pfile, "__BIGGEST_ALIGNMENT__=%d",
 			BIGGEST_ALIGNMENT / BITS_PER_UNIT);
 
+  /* Define constants useful for implementing endian.h.  */
+  cpp_define (pfile, "__LITTLE_ENDIAN__=1234");
+  cpp_define (pfile, "__BIG_ENDIAN__=4321");
+  cpp_define (pfile, "__PDP_ENDIAN__=3412");
+
+  if (WORDS_BIG_ENDIAN == BYTES_BIG_ENDIAN)
+    cpp_define_formatted (pfile, "__BYTE_ORDER__=%s",
+			  (WORDS_BIG_ENDIAN
+			   ? "__BIG_ENDIAN__"
+			   : "__LITTLE_ENDIAN__"));
+  else
+    {
+      /* Assert that we're only dealing with the PDP11 case.  */
+      gcc_assert (!BYTES_BIG_ENDIAN && WORDS_BIG_ENDIAN);
+
+      cpp_define (pfile, "__BYTE_ORDER__=__PDP_ENDIAN__");
+    }
+
   /* ptr_type_node can't be used here since ptr_mode is only set when
      toplev calls backend_init which is not done with -E switch.  */
   cpp_define_formatted (pfile, "__SIZEOF_POINTER__=%d",
diff --git a/gcc/doc/cpp.texi b/gcc/doc/cpp.texi
index 7276b61..d14fa54 100644
--- a/gcc/doc/cpp.texi
+++ b/gcc/doc/cpp.texi
@@ -2265,6 +2265,29 @@  Defined to the number of bytes of the C standard data types: @code{int},
 @code{double}, @code{long double}, @code{size_t}, @code{wchar_t}, @code{wint_t}
 and @code{ptrdiff_t}.
 
+@item __BYTE_ORDER__
+@itemx __LITTLE_ENDIAN__
+@itemx __BIG_ENDIAN__
+@itemx __PDP_ENDIAN__
+@code{__BYTE_ORDER__} is defined to one of the values
+@code{__LITTLE_ENDIAN__}, @code{__BIG_ENDIAN__}, or
+@code{__PDP_ENDIAN__} to reflect the layout of multi-byte and
+multi-word quantities in memory.  If @code{__BYTE_ORDER__} is equal to
+@code{__LITTLE_ENDIAN__} or @code{__BIG_ENDIAN__}, then multi-byte and
+multi-word quantities are laid out identically: the byte (word) at the
+lowest address is the least significant or most significant byte
+(word) of the quantity, respectively.  If @code{__BYTE_ORDER__} is
+equal to @code{__PDP_ENDIAN__}, then bytes in 16-bit words are laid
+out in a little-endian fashion, whereas the 16-bit subwords of a
+32-bit quantity are laid out in big-endian fashion.
+
+You should use these macros for testing like this:
+
+@smallexample
+/* @r{Test for a little-endian machine} */
+#if __BYTE_ORDER__ == __LITTLE_ENDIAN__
+@end smallexample
+
 @item __DEPRECATED
 This macro is defined, with value 1, when compiling a C++ source file
 with warnings about deprecated constructs enabled.  These warnings are
diff --git a/gcc/doc/tm.texi b/gcc/doc/tm.texi
index a268617..ab4e893 100644
--- a/gcc/doc/tm.texi
+++ b/gcc/doc/tm.texi
@@ -938,13 +938,6 @@  order of words in memory is the same as the order in registers.  This
 macro need not be a constant.
 @end defmac
 
-@defmac LIBGCC2_WORDS_BIG_ENDIAN
-Define this macro if @code{WORDS_BIG_ENDIAN} is not constant.  This must be a
-constant value with the same meaning as @code{WORDS_BIG_ENDIAN}, which will be
-used only when compiling @file{libgcc2.c}.  Typically the value will be set
-based on preprocessor defines.
-@end defmac
-
 @defmac FLOAT_WORDS_BIG_ENDIAN
 Define this macro to have the value 1 if @code{DFmode}, @code{XFmode} or
 @code{TFmode} floating point numbers are stored in memory with the word
diff --git a/gcc/doc/tm.texi.in b/gcc/doc/tm.texi.in
index 74cf927..23fa032 100644
--- a/gcc/doc/tm.texi.in
+++ b/gcc/doc/tm.texi.in
@@ -936,13 +936,6 @@  order of words in memory is the same as the order in registers.  This
 macro need not be a constant.
 @end defmac
 
-@defmac LIBGCC2_WORDS_BIG_ENDIAN
-Define this macro if @code{WORDS_BIG_ENDIAN} is not constant.  This must be a
-constant value with the same meaning as @code{WORDS_BIG_ENDIAN}, which will be
-used only when compiling @file{libgcc2.c}.  Typically the value will be set
-based on preprocessor defines.
-@end defmac
-
 @defmac FLOAT_WORDS_BIG_ENDIAN
 Define this macro to have the value 1 if @code{DFmode}, @code{XFmode} or
 @code{TFmode} floating point numbers are stored in memory with the word
diff --git a/gcc/libgcc2.h b/gcc/libgcc2.h
index d2d86ef..c95e263 100644
--- a/gcc/libgcc2.h
+++ b/gcc/libgcc2.h
@@ -35,14 +35,6 @@  extern void __clear_cache (char *, char *);
 extern void __eprintf (const char *, const char *, unsigned int, const char *)
   __attribute__ ((__noreturn__));
 
-/* Permit the tm.h file to select the endianness to use just for this
-   file.  This is used when the endianness is determined when the
-   compiler is run.  */
-
-#ifndef LIBGCC2_WORDS_BIG_ENDIAN
-#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
-#endif
-
 #ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE
 #define LIBGCC2_LONG_DOUBLE_TYPE_SIZE LONG_DOUBLE_TYPE_SIZE
 #endif
@@ -407,9 +399,9 @@  extern TCtype __multc3 (TFtype, TFtype, TFtype, TFtype);
 #define int bogus_type
 
 /* DWstructs are pairs of Wtype values in the order determined by
-   LIBGCC2_WORDS_BIG_ENDIAN.  */
+   __BYTE_ORDER__.  */
 
-#if LIBGCC2_WORDS_BIG_ENDIAN
+#if __BYTE_ORDER__ != __LITTLE_ENDIAN__
   struct DWstruct {Wtype high, low;};
 #else
   struct DWstruct {Wtype low, high;};
diff --git a/gcc/system.h b/gcc/system.h
index 5131fed..ec0c796 100644
--- a/gcc/system.h
+++ b/gcc/system.h
@@ -785,7 +785,7 @@  extern void fancy_abort (const char *, int, const char *) ATTRIBUTE_NORETURN;
 	LANG_HOOKS_MISSING_ARGUMENT LANG_HOOKS_HASH_TYPES
 
 /* Hooks into libgcc2.  */
- #pragma GCC poison LIBGCC2_DOUBLE_TYPE_SIZE
+ #pragma GCC poison LIBGCC2_DOUBLE_TYPE_SIZE LIBGCC2_WORDS_BIG_ENDIAN
 
 /* Miscellaneous macros that are no longer used.  */
  #pragma GCC poison USE_MAPPED_LOCATION
diff --git a/libdecnumber/dconfig.h b/libdecnumber/dconfig.h
index 91aa334..f432377 100644
--- a/libdecnumber/dconfig.h
+++ b/libdecnumber/dconfig.h
@@ -28,12 +28,8 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "coretypes.h"
 #include "tm.h"
 
-#ifndef LIBGCC2_WORDS_BIG_ENDIAN
-#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
-#endif
-
 #ifndef LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
-#define LIBGCC2_FLOAT_WORDS_BIG_ENDIAN LIBGCC2_WORDS_BIG_ENDIAN
+#define LIBGCC2_FLOAT_WORDS_BIG_ENDIAN (__BYTE_ORDER__ != __LITTLE_ENDIAN__)
 #endif
 
 #if LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
diff --git a/libgcc/config/libbid/bid_gcc_intrinsics.h b/libgcc/config/libbid/bid_gcc_intrinsics.h
index f5bd8d0..5c5dbba 100644
--- a/libgcc/config/libbid/bid_gcc_intrinsics.h
+++ b/libgcc/config/libbid/bid_gcc_intrinsics.h
@@ -30,12 +30,8 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #include "coretypes.h"
 #include "tm.h"
 
-#ifndef LIBGCC2_WORDS_BIG_ENDIAN
-#define LIBGCC2_WORDS_BIG_ENDIAN WORDS_BIG_ENDIAN
-#endif
-
 #ifndef LIBGCC2_FLOAT_WORDS_BIG_ENDIAN
-#define LIBGCC2_FLOAT_WORDS_BIG_ENDIAN LIBGCC2_WORDS_BIG_ENDIAN
+#define LIBGCC2_FLOAT_WORDS_BIG_ENDIAN (__BYTE_ORDER__ != __LITTLE_ENDIAN__)
 #endif
 
 #ifndef LIBGCC2_LONG_DOUBLE_TYPE_SIZE