diff mbox

PATCH [1/n]: Add initial -x32 support

Message ID 20110605195441.GA1225@intel.com
State New
Headers show

Commit Message

H.J. Lu June 5, 2011, 7:54 p.m. UTC
Hi,

I'd like to start submitting a series of patches to enable x32:

https://sites.google.com/site/x32abi/

The GCC x32 branch is very stable. There are no unexpected failures in
C, C++, Fortran and Objective C testsuites.  SPEC CPU 2K/2006 compile
and run correctly at -O2 and -O3. 

More than 90% of changes are in x86 backend.  This is the first patch to
support x32.  By default, x32 is disabled and x32 run-time support
isn't required.  OK for trunk?

Thanks.


H.J.
---
2011-06-05  H.J. Lu  <hongjiu.lu@intel.com>

	* config.gcc: Support --enable-x32/--enable-ia32 for x86 Linux
	targets.

	* configure.ac: Support --enable-x32/--enable-ia32.
	* configure: Regenerated.

	* config/i386/gnu-user64.h (ASM_SPEC): Support x32.
	(LINK_SPEC): Likewise.
	(TARGET_THREAD_SSP_OFFSET): Likewise.
	(TARGET_THREAD_SPLIT_STACK_OFFSET): Likewise.

	* config/i386/i386.h (TARGET_X32): New.
	(TARGET_LP64): New.
	(LONG_TYPE_SIZE): Likewise.
	(POINTER_SIZE): Likewise.
	(POINTERS_EXTEND_UNSIGNED): Likewise.

	* config/i386/i386.opt (mx32): New.

	* config/i386/linux64.h (GLIBC_DYNAMIC_LINKERX32): New.

	* config/i386/t-linux64-x32: New.
	* config/i386/t-linuxx32: Likewise.

	* config/linux.h (UCLIBC_DYNAMIC_LINKERX32): New.
	(BIONIC_DYNAMIC_LINKERX32): Likewise.
	(GNU_USER_DYNAMIC_LINKERX32): Likewise.

	* doc/invoke.texi: Document -mx32.

Comments

Uros Bizjak June 6, 2011, 3:47 p.m. UTC | #1
On Sun, Jun 5, 2011 at 9:54 PM, H.J. Lu <hongjiu.lu@intel.com> wrote:

> I'd like to start submitting a series of patches to enable x32:
>
> https://sites.google.com/site/x32abi/
>
> The GCC x32 branch is very stable. There are no unexpected failures in
> C, C++, Fortran and Objective C testsuites.  SPEC CPU 2K/2006 compile
> and run correctly at -O2 and -O3.
>
> More than 90% of changes are in x86 backend.  This is the first patch to
> support x32.  By default, x32 is disabled and x32 run-time support
> isn't required.  OK for trunk?

I'd suggest to first post for review and later commit target
independent fixes in the middle-end, then fixes/improvements in
generic i386 parts and at last strict x32 target stuff. IIRC, ther are
many inconsistencies w.r.t. ptr_size != size of Pmode in both,
middle-end and generic i386 parts, and this way I hope we will avoid
problems if change in lower layers is based on wrong assumptions.

I also suggest to rename t-linuxx32 to t-linux-x32.

Thanks,
Uros.
Joseph Myers June 7, 2011, 3:47 p.m. UTC | #2
On Sun, 5 Jun 2011, H.J. Lu wrote:

> 	* config.gcc: Support --enable-x32/--enable-ia32 for x86 Linux
> 	targets.
> 
> 	* configure.ac: Support --enable-x32/--enable-ia32.
> 	* configure: Regenerated.

New configure options need documenting in install.texi.

>  #undef ASM_SPEC
> -#define ASM_SPEC "%{" SPEC_32 ":--32} %{" SPEC_64 ":--64} \
> +#define ASM_SPEC "%{" SPEC_32 ":%{!mx32:--32}} %{" \
> + SPEC_64 ":%{!mx32:--64}} %{mx32:--x32} \
>   %{!mno-sse2avx:%{mavx:-msse2avx}} %{msse2avx:%{!mavx:-msse2avx}}"

This looks wrong.  You should define SPEC_32, SPEC_64 and SPEC_X32 to be 
the three mutually exclusive cases, then use those three here and in other 
specs without any nesting.

>  Generate code for a 32-bit or 64-bit environment.
> -The 32-bit environment sets int, long and pointer to 32 bits and
> +The -m32 option sets int, long and pointer to 32 bits and

@option{-m32}.  Likewise later in this paragraph for various option names.
Joseph Myers June 7, 2011, 3:59 p.m. UTC | #3
An additional comment on the specs: OPTION_DEFAULT_SPECS needs updating 
(-mx32 should use the --with-arch-64 etc. settings).
H.J. Lu June 7, 2011, 6:52 p.m. UTC | #4
On Tue, Jun 7, 2011 at 8:47 AM, Joseph S. Myers <joseph@codesourcery.com> wrote:
> On Sun, 5 Jun 2011, H.J. Lu wrote:
>
>>       * config.gcc: Support --enable-x32/--enable-ia32 for x86 Linux
>>       targets.
>>
>>       * configure.ac: Support --enable-x32/--enable-ia32.
>>       * configure: Regenerated.
>
> New configure options need documenting in install.texi.

I will fix it.

>>  #undef ASM_SPEC
>> -#define ASM_SPEC "%{" SPEC_32 ":--32} %{" SPEC_64 ":--64} \
>> +#define ASM_SPEC "%{" SPEC_32 ":%{!mx32:--32}} %{" \
>> + SPEC_64 ":%{!mx32:--64}} %{mx32:--x32} \
>>   %{!mno-sse2avx:%{mavx:-msse2avx}} %{msse2avx:%{!mavx:-msse2avx}}"
>
> This looks wrong.  You should define SPEC_32, SPEC_64 and SPEC_X32 to be
> the three mutually exclusive cases, then use those three here and in other
> specs without any nesting.

I thought about it when I started working on it.  But I couldn't find a way
to do it properly.  What we have are

#if TARGET_64BIT_DEFAULT
#define SPEC_32 "m32"
#define SPEC_64 "!m32"
#else
#define SPEC_32 "!m64"
#define SPEC_64 "m64"
#endif

I don't know how  to make -mx32, -m32 and -m64 mutually exclusive with
GCC spec processing in GCC driver.

>>  Generate code for a 32-bit or 64-bit environment.
>> -The 32-bit environment sets int, long and pointer to 32 bits and
>> +The -m32 option sets int, long and pointer to 32 bits and
>
> @option{-m32}.  Likewise later in this paragraph for various option names.
>

I will fix it.

Thanks.
H.J. Lu June 7, 2011, 6:56 p.m. UTC | #5
On Tue, Jun 7, 2011 at 8:59 AM, Joseph S. Myers <joseph@codesourcery.com> wrote:
> An additional comment on the specs: OPTION_DEFAULT_SPECS needs updating
> (-mx32 should use the --with-arch-64 etc. settings).
>

The current x32 branch works like this:

[hjl@gnu-6 gcc]$  ./xgcc -B./ -v -O /tmp/x.i -S
Reading specs from ./specs
COLLECT_GCC=./xgcc
COLLECT_LTO_WRAPPER=./lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: /export/gnu/import/git/gcc-x32/configure
--enable-languages=c --disable-bootstrap --prefix=/usr/gcc-4.7.0-x32
--with-local-prefix=/usr/local --enable-gnu-indirect-function
--enable-x32 --with-arch-32=atom --with-cpu-64=corei7
--enable-cloog-backend=isl --with-ppl-include=/opt/gnu/include
--with-ppl-lib=/opt/gnu/lib64 --with-cloog-include=/opt/gnu/include
--with-cloog-lib=/opt/gnu/lib64 --with-fpmath=sse
Thread model: posix
gcc version 4.7.0 20110607 (experimental) (GCC)
COLLECT_GCC_OPTIONS='-B' './' '-v' '-O' '-S' '-mtune=corei7' '-march=x86-64'
 ./cc1 -fpreprocessed /tmp/x.i -quiet -dumpbase x.i -mtune=corei7
-march=x86-64 -auxbase x -O -version -o x.s
GNU C (GCC) version 4.7.0 20110607 (experimental) (x86_64-unknown-linux-gnu)
	compiled by GNU C version 4.6.0 20110509 (Red Hat 4.6.0-7), GMP
version 4.3.2, MPFR version 3.0.0, MPC version 0.8.3-dev
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
GNU C (GCC) version 4.7.0 20110607 (experimental) (x86_64-unknown-linux-gnu)
	compiled by GNU C version 4.6.0 20110509 (Red Hat 4.6.0-7), GMP
version 4.3.2, MPFR version 3.0.0, MPC version 0.8.3-dev
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
Compiler executable checksum: 4ce06b87a1cd6526b31d62b0b2a64ecd
COMPILER_PATH=./
LIBRARY_PATH=./:/lib/../lib64/:/usr/lib/../lib64/:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-B' './' '-v' '-O' '-S' '-mtune=corei7' '-march=x86-64'
[hjl@gnu-6 gcc]$  ./xgcc -B./ -v -O /tmp/x.i -S -mx32
Reading specs from ./specs
COLLECT_GCC=./xgcc
COLLECT_LTO_WRAPPER=./lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: /export/gnu/import/git/gcc-x32/configure
--enable-languages=c --disable-bootstrap --prefix=/usr/gcc-4.7.0-x32
--with-local-prefix=/usr/local --enable-gnu-indirect-function
--enable-x32 --with-arch-32=atom --with-cpu-64=corei7
--enable-cloog-backend=isl --with-ppl-include=/opt/gnu/include
--with-ppl-lib=/opt/gnu/lib64 --with-cloog-include=/opt/gnu/include
--with-cloog-lib=/opt/gnu/lib64 --with-fpmath=sse
Thread model: posix
gcc version 4.7.0 20110607 (experimental) (GCC)
COLLECT_GCC_OPTIONS='-B' './' '-v' '-O' '-S' '-mx32' '-mtune=corei7'
'-march=x86-64'
 ./cc1 -fpreprocessed /tmp/x.i -quiet -dumpbase x.i -mx32
-mtune=corei7 -march=x86-64 -auxbase x -O -version -o x.s
GNU C (GCC) version 4.7.0 20110607 (experimental) (x86_64-unknown-linux-gnu)
	compiled by GNU C version 4.6.0 20110509 (Red Hat 4.6.0-7), GMP
version 4.3.2, MPFR version 3.0.0, MPC version 0.8.3-dev
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
GNU C (GCC) version 4.7.0 20110607 (experimental) (x86_64-unknown-linux-gnu)
	compiled by GNU C version 4.6.0 20110509 (Red Hat 4.6.0-7), GMP
version 4.3.2, MPFR version 3.0.0, MPC version 0.8.3-dev
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
Compiler executable checksum: 4ce06b87a1cd6526b31d62b0b2a64ecd
COMPILER_PATH=./
LIBRARY_PATH=./x32/:/lib/../libx32/:/usr/lib/../libx32/:./:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-B' './' '-v' '-O' '-S' '-mx32' '-mtune=corei7'
'-march=x86-64'
[hjl@gnu-6 gcc]$  ./xgcc -B./ -v -O /tmp/x.i -S -m32
Reading specs from ./specs
COLLECT_GCC=./xgcc
COLLECT_LTO_WRAPPER=./lto-wrapper
Target: x86_64-unknown-linux-gnu
Configured with: /export/gnu/import/git/gcc-x32/configure
--enable-languages=c --disable-bootstrap --prefix=/usr/gcc-4.7.0-x32
--with-local-prefix=/usr/local --enable-gnu-indirect-function
--enable-x32 --with-arch-32=atom --with-cpu-64=corei7
--enable-cloog-backend=isl --with-ppl-include=/opt/gnu/include
--with-ppl-lib=/opt/gnu/lib64 --with-cloog-include=/opt/gnu/include
--with-cloog-lib=/opt/gnu/lib64 --with-fpmath=sse
Thread model: posix
gcc version 4.7.0 20110607 (experimental) (GCC)
COLLECT_GCC_OPTIONS='-B' './' '-v' '-O' '-S' '-m32' '-mtune=generic'
'-march=atom'
 ./cc1 -fpreprocessed /tmp/x.i -quiet -dumpbase x.i -m32
-mtune=generic -march=atom -auxbase x -O -version -o x.s
GNU C (GCC) version 4.7.0 20110607 (experimental) (x86_64-unknown-linux-gnu)
	compiled by GNU C version 4.6.0 20110509 (Red Hat 4.6.0-7), GMP
version 4.3.2, MPFR version 3.0.0, MPC version 0.8.3-dev
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
GNU C (GCC) version 4.7.0 20110607 (experimental) (x86_64-unknown-linux-gnu)
	compiled by GNU C version 4.6.0 20110509 (Red Hat 4.6.0-7), GMP
version 4.3.2, MPFR version 3.0.0, MPC version 0.8.3-dev
GGC heuristics: --param ggc-min-expand=30 --param ggc-min-heapsize=4096
Compiler executable checksum: 4ce06b87a1cd6526b31d62b0b2a64ecd
COMPILER_PATH=./
LIBRARY_PATH=./32/:/lib/../lib/:/usr/lib/../lib/:./:/lib/:/usr/lib/
COLLECT_GCC_OPTIONS='-B' './' '-v' '-O' '-S' '-m32' '-mtune=generic'
'-march=atom'
[hjl@gnu-6 gcc]$

That is -mx32 takes the same default as -m64. It is the correct
behavior for -mx32.
Joseph Myers June 7, 2011, 7:16 p.m. UTC | #6
On Tue, 7 Jun 2011, H.J. Lu wrote:

> I thought about it when I started working on it.  But I couldn't find a way
> to do it properly.  What we have are
> 
> #if TARGET_64BIT_DEFAULT
> #define SPEC_32 "m32"
> #define SPEC_64 "!m32"
> #else
> #define SPEC_32 "!m64"
> #define SPEC_64 "m64"
> #endif
> 
> I don't know how  to make -mx32, -m32 and -m64 mutually exclusive with
> GCC spec processing in GCC driver.

The use of Negative in the .opt file means that only one such option will 
be visible for specs.  So you define specs such as "m64|mx32:;" to mean 
"neither -m64 nor -mx32 is passed (see the MIPS definitions of OPT_ARCH64 
and OPT_ARCH32, for example).
Joseph Myers June 7, 2011, 7:17 p.m. UTC | #7
On Tue, 7 Jun 2011, H.J. Lu wrote:

> That is -mx32 takes the same default as -m64. It is the correct
> behavior for -mx32.

I think it's only right in the case where -m64 is the default, and the 
specs for the case where -m32 is the default need changing to handle -mx32 
properly.
diff mbox

Patch

diff --git a/gcc/config.gcc b/gcc/config.gcc
index 624129b..24b4a57 100644
--- a/gcc/config.gcc
+++ b/gcc/config.gcc
@@ -1232,7 +1232,17 @@  i[34567]86-*-linux* | i[34567]86-*-kfreebsd*-gnu | i[34567]86-*-knetbsd*-gnu | i
 		if test x$enable_targets = xall; then
 			tm_file="${tm_file} i386/x86-64.h i386/gnu-user64.h i386/linux64.h"
 			tm_defines="${tm_defines} TARGET_BI_ARCH=1"
-			tmake_file="${tmake_file} i386/t-linux64"
+			case x${enable_x32}${enable_ia32} in
+			xyesyes)
+				tmake_file="${tmake_file} i386/t-linuxx32"
+				;;
+			xyesno)
+				tmake_file="${tmake_file} i386/t-linux64-x32"
+				;;
+			*)
+				tmake_file="${tmake_file} i386/t-linux64"
+				;;
+			esac
 			need_64bit_hwint=yes
 			need_64bit_isa=yes
 			case X"${with_cpu}" in
@@ -1270,7 +1280,18 @@  x86_64-*-linux* | x86_64-*-kfreebsd*-gnu | x86_64-*-knetbsd*-gnu)
 	x86_64-*-kfreebsd*-gnu) tm_file="${tm_file} kfreebsd-gnu.h i386/kfreebsd-gnu.h" ;;
 	x86_64-*-knetbsd*-gnu) tm_file="${tm_file} knetbsd-gnu.h" ;;
 	esac
-	tmake_file="${tmake_file} i386/t-linux64 i386/t-crtstuff i386/t-crtpc i386/t-crtfm t-dfprules"
+	case x${enable_x32}${enable_ia32} in
+	xyesyes)
+		tmake_file="${tmake_file} i386/t-linuxx32"
+		;;
+	xyesno)
+		tmake_file="${tmake_file} i386/t-linux64-x32"
+		;;
+	*)
+		tmake_file="${tmake_file} i386/t-linux64"
+		;;
+	esac
+	tmake_file="${tmake_file} i386/t-crtstuff i386/t-crtpc i386/t-crtfm t-dfprules"
 	;;
 i[34567]86-pc-msdosdjgpp*)
 	xm_file=i386/xm-djgpp.h
diff --git a/gcc/config/i386/gnu-user64.h b/gcc/config/i386/gnu-user64.h
index 3ece0fa..b99fb13 100644
--- a/gcc/config/i386/gnu-user64.h
+++ b/gcc/config/i386/gnu-user64.h
@@ -65,17 +65,20 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #endif
 
 #undef ASM_SPEC
-#define ASM_SPEC "%{" SPEC_32 ":--32} %{" SPEC_64 ":--64} \
+#define ASM_SPEC "%{" SPEC_32 ":%{!mx32:--32}} %{" \
+ SPEC_64 ":%{!mx32:--64}} %{mx32:--x32} \
  %{!mno-sse2avx:%{mavx:-msse2avx}} %{msse2avx:%{!mavx:-msse2avx}}"
 
 #undef	LINK_SPEC
-#define LINK_SPEC "%{" SPEC_64 ":-m elf_x86_64} %{" SPEC_32 ":-m elf_i386} \
+#define LINK_SPEC "%{" SPEC_64 ":%{!mx32:-m elf_x86_64}} %{" \
+  SPEC_32 ":%{!mx32:-m elf_i386}} %{mx32:-m elf32_x86_64} \
   %{shared:-shared} \
   %{!shared: \
     %{!static: \
       %{rdynamic:-export-dynamic} \
-      %{" SPEC_32 ":-dynamic-linker " GNU_USER_DYNAMIC_LINKER32 "} \
-      %{" SPEC_64 ":-dynamic-linker " GNU_USER_DYNAMIC_LINKER64 "}} \
+      %{" SPEC_32 ":%{!mx32:-dynamic-linker " GNU_USER_DYNAMIC_LINKER32 "}} \
+      %{" SPEC_64 ":%{!mx32:-dynamic-linker " GNU_USER_DYNAMIC_LINKER64 "}} \
+      %{mx32:-dynamic-linker " GNU_USER_DYNAMIC_LINKERX32 "}} \
     %{static:-static}}"
 
 /* Similar to standard GNU userspace, but adding -ffast-math support.  */
@@ -109,10 +112,13 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 #ifdef TARGET_LIBC_PROVIDES_SSP
 /* i386 glibc provides __stack_chk_guard in %gs:0x14,
+   x32 glibc provides it in %fs:0x18. 
    x86_64 glibc provides it in %fs:0x28.  */
-#define TARGET_THREAD_SSP_OFFSET	(TARGET_64BIT ? 0x28 : 0x14)
+#define TARGET_THREAD_SSP_OFFSET \
+  (TARGET_64BIT ? (TARGET_X32 ? 0x18 : 0x28) : 0x14)
 
 /* We steal the last transactional memory word.  */
 #define TARGET_CAN_SPLIT_STACK
-#define TARGET_THREAD_SPLIT_STACK_OFFSET (TARGET_64BIT ? 0x70 : 0x30)
+#define TARGET_THREAD_SPLIT_STACK_OFFSET \
+  (TARGET_64BIT ? (TARGET_X32 ? 0x40 : 0x70) : 0x30)
 #endif
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index 8badcbb..f9270de 100644
--- a/gcc/config/i386/i386.h
+++ b/gcc/config/i386/i386.h
@@ -42,6 +42,7 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 /* Redefines for option macros.  */
 
 #define TARGET_64BIT	OPTION_ISA_64BIT
+#define TARGET_X32	OPTION_ISA_X32
 #define TARGET_MMX	OPTION_ISA_MMX
 #define TARGET_3DNOW	OPTION_ISA_3DNOW
 #define TARGET_3DNOW_A	OPTION_ISA_3DNOW_A
@@ -72,6 +73,7 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define TARGET_RDRND	OPTION_ISA_RDRND
 #define TARGET_F16C	OPTION_ISA_F16C
 
+#define TARGET_LP64	(TARGET_64BIT && !TARGET_X32)
 
 /* SSE4.1 defines round instructions */
 #define	OPTION_MASK_ISA_ROUND	OPTION_MASK_ISA_SSE4_1
@@ -638,6 +640,8 @@  enum target_cpu_default
 
 #define SHORT_TYPE_SIZE 16
 #define INT_TYPE_SIZE 32
+#define LONG_TYPE_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
+#define POINTER_SIZE (TARGET_X32 ? 32 : BITS_PER_WORD)
 #define LONG_LONG_TYPE_SIZE 64
 #define FLOAT_TYPE_SIZE 32
 #define DOUBLE_TYPE_SIZE 64
@@ -1743,6 +1747,13 @@  do {							\
    between pointers and any other objects of this machine mode.  */
 #define Pmode (TARGET_64BIT ? DImode : SImode)
 
+/* A C expression whose value is zero if pointers that need to be extended
+   from being `POINTER_SIZE' bits wide to `Pmode' are sign-extended and
+   greater then zero if they are zero-extended and less then zero if the
+   ptr_extend instruction should be used.  */
+
+#define POINTERS_EXTEND_UNSIGNED 1
+
 /* A function address in a call instruction
    is a byte address (for indexing purposes)
    so give the MEM rtx a byte's mode.  */
diff --git a/gcc/config/i386/i386.opt b/gcc/config/i386/i386.opt
index 21e0def..2c8fe8f 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -398,9 +398,13 @@  Target RejectNegative Negative(m64) Report InverseMask(ISA_64BIT) Var(ix86_isa_f
 Generate 32bit i386 code
 
 m64
-Target RejectNegative Negative(m32) Report Mask(ISA_64BIT) Var(ix86_isa_flags) Save
+Target RejectNegative Negative(mx32) Report Mask(ISA_64BIT) Var(ix86_isa_flags) Save
 Generate 64bit x86-64 code
 
+mx32
+Target RejectNegative Negative(m32) Report Mask(ISA_X32) Var(ix86_isa_flags) Save
+Generate 32bit x86-64 code
+
 mmmx
 Target Report Mask(ISA_MMX) Var(ix86_isa_flags) Save
 Support MMX built-in functions
diff --git a/gcc/config/i386/linux64.h b/gcc/config/i386/linux64.h
index 9bf7eab..78c9c8e 100644
--- a/gcc/config/i386/linux64.h
+++ b/gcc/config/i386/linux64.h
@@ -26,3 +26,4 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 
 #define GLIBC_DYNAMIC_LINKER32 "/lib/ld-linux.so.2"
 #define GLIBC_DYNAMIC_LINKER64 "/lib64/ld-linux-x86-64.so.2"
+#define GLIBC_DYNAMIC_LINKERX32 "/libx32/ld-linux-x32.so.2"
diff --git a/gcc/config/i386/t-linux64-x32 b/gcc/config/i386/t-linux64-x32
new file mode 100644
index 0000000..3a4d1de
--- /dev/null
+++ b/gcc/config/i386/t-linux64-x32
@@ -0,0 +1,34 @@ 
+# 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/>.
+
+# To support x86-64 and x32 libraries, the directory structrue
+# should be:
+#
+# 	/lib64 has x86-64 libraries.
+# 	/libx32 has x32 libraries.
+#
+MULTILIB_OPTIONS = m64/mx32
+MULTILIB_DIRNAMES = 64 x32
+MULTILIB_OSDIRNAMES = ../lib64 ../libx32
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o \
+		     crtbeginT.o crtprec32.o crtprec64.o crtprec80.o \
+		     crtfastmath.o
diff --git a/gcc/config/i386/t-linuxx32 b/gcc/config/i386/t-linuxx32
new file mode 100644
index 0000000..92acf91
--- /dev/null
+++ b/gcc/config/i386/t-linuxx32
@@ -0,0 +1,42 @@ 
+# 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/>.
+
+# On Debian, Ubuntu and other derivative distributions, the 32bit libraries
+# are found in /lib32 and /usr/lib32, /lib64 and /usr/lib64 are symlinks to
+# /lib and /usr/lib, while other distributions install libraries into /lib64
+# and /usr/lib64.  The LSB does not enforce the use of /lib64 and /usr/lib64,
+# it doesn't tell anything about the 32bit libraries on those systems.  Set
+# MULTILIB_OSDIRNAMES according to what is found on the target.
+
+# To support i386, x86-64 and x32 libraries, the directory structrue
+# should be:
+#
+# 	/lib has i386 libraries.
+# 	/lib64 has x86-64 libraries.
+# 	/libx32 has x32 libraries.
+#
+MULTILIB_OPTIONS = m64/m32/mx32
+MULTILIB_DIRNAMES = 64 32 x32
+MULTILIB_OSDIRNAMES = ../lib64 $(if $(wildcard $(shell echo $(SYSTEM_HEADER_DIR))/../../usr/lib32),../lib32,../lib) ../libx32
+
+LIBGCC = stmp-multilib
+INSTALL_LIBGCC = install-multilib
+
+EXTRA_MULTILIB_PARTS=crtbegin.o crtend.o crtbeginS.o crtendS.o \
+		     crtbeginT.o crtprec32.o crtprec64.o crtprec80.o \
+		     crtfastmath.o
diff --git a/gcc/config/linux.h b/gcc/config/linux.h
index fc897b1..dbbeea5 100644
--- a/gcc/config/linux.h
+++ b/gcc/config/linux.h
@@ -77,9 +77,11 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define UCLIBC_DYNAMIC_LINKER "/lib/ld-uClibc.so.0"
 #define UCLIBC_DYNAMIC_LINKER32 "/lib/ld-uClibc.so.0"
 #define UCLIBC_DYNAMIC_LINKER64 "/lib/ld64-uClibc.so.0"
+#define UCLIBC_DYNAMIC_LINKERX32 "/lib/ldx32-uClibc.so.0"
 #define BIONIC_DYNAMIC_LINKER "/system/bin/linker"
 #define BIONIC_DYNAMIC_LINKER32 "/system/bin/linker"
 #define BIONIC_DYNAMIC_LINKER64 "/system/bin/linker64"
+#define BIONIC_DYNAMIC_LINKERX32 "/system/bin/linkerx32"
 
 #define GNU_USER_DYNAMIC_LINKER						\
   CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER, UCLIBC_DYNAMIC_LINKER,	\
@@ -90,6 +92,9 @@  see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see
 #define GNU_USER_DYNAMIC_LINKER64					\
   CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER64, UCLIBC_DYNAMIC_LINKER64, \
 			 BIONIC_DYNAMIC_LINKER64)
+#define GNU_USER_DYNAMIC_LINKERX32					\
+  CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKERX32, UCLIBC_DYNAMIC_LINKERX32, \
+			 BIONIC_DYNAMIC_LINKERX32)
 
 /* Determine whether the entire c99 runtime
    is present in the runtime library.  */
diff --git a/gcc/configure.ac b/gcc/configure.ac
index 5e41479..a421746 100644
--- a/gcc/configure.ac
+++ b/gcc/configure.ac
@@ -611,6 +611,16 @@  AC_ARG_ENABLE(multilib,
 [], [enable_multilib=yes])
 AC_SUBST(enable_multilib)
 
+# With x32 support
+AC_ARG_ENABLE(x32,
+[  --enable-x32            enable x32 library support for multiple ABIs],
+[], [enable_x32=no])
+
+# With ia32 support
+AC_ARG_ENABLE(ia32,
+[  --enable-ia32           enable ia32 library support for multiple ABIs],
+[], [enable_ia32=yes])
+
 # Enable __cxa_atexit for C++.
 AC_ARG_ENABLE(__cxa_atexit,
 [AS_HELP_STRING([--enable-__cxa_atexit], [enable __cxa_atexit for C++])],
diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
index a069042..12080ca 100644
--- a/gcc/doc/invoke.texi
+++ b/gcc/doc/invoke.texi
@@ -609,7 +609,7 @@  Objective-C and Objective-C++ Dialects}.
 -mpc32 -mpc64 -mpc80 -mstackrealign @gol
 -momit-leaf-frame-pointer  -mno-red-zone -mno-tls-direct-seg-refs @gol
 -mcmodel=@var{code-model} -mabi=@var{name} @gol
--m32  -m64 -mlarge-data-threshold=@var{num} @gol
+-m32 -m64 -mx32 -mlarge-data-threshold=@var{num} @gol
 -msse2avx -mfentry -m8bit-idiv @gol
 -mavx256-split-unaligned-load -mavx256-split-unaligned-store}
 
@@ -12824,14 +12824,18 @@  on AMD x86-64 processors in 64-bit environments.
 @table @gcctabopt
 @item -m32
 @itemx -m64
+@itemx -mx32
 @opindex m32
 @opindex m64
+@opindex mx32
 Generate code for a 32-bit or 64-bit environment.
-The 32-bit environment sets int, long and pointer to 32 bits and
+The -m32 option sets int, long and pointer to 32 bits and
 generates code that runs on any i386 system.
-The 64-bit environment sets int to 32 bits and long and pointer
-to 64 bits and generates code for AMD's x86-64 architecture. For
-darwin only the -m64 option turns off the @option{-fno-pic} and
+The -m64 option sets int to 32 bits and long and pointer
+to 64 bits and generates code for AMD's x86-64 architecture.
+The -mx32 option sets int, long and pointer to 32 bits and generates
+code for AMD's x86-64 architecture.
+For darwin only the -m64 option turns off the @option{-fno-pic} and
 @option{-mdynamic-no-pic} options.
 
 @item -mno-red-zone