diff --git a/gcc/ChangeLog.x32 b/gcc/ChangeLog.x32
new file mode 100644
index 0000000..45a63a7
--- /dev/null
+++ b/gcc/ChangeLog.x32
@@ -0,0 +1,22 @@
+2011-01-19  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* config/linux.h (UCLIBC_DYNAMIC_LINKERX32): New.
+	(BIONIC_DYNAMIC_LINKERX32): Likewise.
+	(LINUX_DYNAMIC_LINKERX32): Likewise.
+
+	* config/i386/linux64.h (GLIBC_DYNAMIC_LINKERX32): New.
+	(ASM_SPEC): Support -mx32.
+	(LINK_SPEC): Likewise.
+
+	* config/i386/i386.c (override_options): Turn on
+	OPTION_MASK_ISA_64BIT for TARGET_X32.  Only allow small and
+	small PIC models for TARGET_X32.
+
+	* config/i386/i386.h (TARGET_X32): New.
+	(TARGET_LP64): Likewise.
+	(LONG_TYPE_SIZE): Likewise.
+	(POINTER_SIZE): Likewise.
+	(POINTERS_EXTEND_UNSIGNED): Likewise.
+
+	* config/i386/i386.opt (m64): Negate -mx32.
+	(mx32): New.
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index f5843de..6e14e59 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -3380,6 +3380,9 @@ ix86_option_override_internal (bool main_args_p)
   SUBSUBTARGET_OVERRIDE_OPTIONS;
 #endif
 
+  if (TARGET_X32)
+    ix86_isa_flags |= OPTION_MASK_ISA_64BIT;
+
   /* -fPIC is the default for x86_64.  */
   if (TARGET_MACHO && TARGET_64BIT)
     flag_pic = 2;
@@ -3523,6 +3526,11 @@ ix86_option_override_internal (bool main_args_p)
   if ((TARGET_64BIT == 0) != (ix86_cmodel == CM_32))
     error ("code model %qs not supported in the %s bit mode",
 	   ix86_cmodel_string, TARGET_64BIT ? "64" : "32");
+  if (ix86_cmodel != CM_SMALL
+      && ix86_cmodel != CM_SMALL_PIC
+      && TARGET_X32)
+    error ("code model %qs not supported in x32 mode",
+	   ix86_cmodel_string);
   if ((TARGET_64BIT != 0) != ((ix86_isa_flags & OPTION_MASK_ISA_64BIT) != 0))
     sorry ("%i-bit mode not compiled in",
 	   (ix86_isa_flags & OPTION_MASK_ISA_64BIT) ? 64 : 32);
diff --git a/gcc/config/i386/i386.h b/gcc/config/i386/i386.h
index f14a95d..4fa5892 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
@@ -653,6 +655,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
@@ -1782,6 +1786,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 85362d7..7142854 100644
--- a/gcc/config/i386/i386.opt
+++ b/gcc/config/i386/i386.opt
@@ -273,9 +273,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 b68c40f..b962a64 100644
--- a/gcc/config/i386/linux64.h
+++ b/gcc/config/i386/linux64.h
@@ -61,6 +61,7 @@ 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 "/lib32/ld-linux-x32.so.2"
 
 #if TARGET_64BIT_DEFAULT
 #define SPEC_32 "m32"
@@ -71,17 +72,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 " LINUX_DYNAMIC_LINKER32 "} \
-      %{" SPEC_64 ":-dynamic-linker " LINUX_DYNAMIC_LINKER64 "}} \
+      %{" SPEC_32 ":%{!mx32:-dynamic-linker " LINUX_DYNAMIC_LINKER32 "}} \
+      %{" SPEC_64 ":%{!mx32:-dynamic-linker " LINUX_DYNAMIC_LINKER64 "}} \
+      %{mx32:-dynamic-linker " LINUX_DYNAMIC_LINKERX32 "}} \
     %{static:-static}}"
 
 /* Similar to standard Linux, but adding -ffast-math support.  */
diff --git a/gcc/config/linux.h b/gcc/config/linux.h
index 00b4f1c..f72f8e5 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 LINUX_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 LINUX_DYNAMIC_LINKER64						\
   CHOOSE_DYNAMIC_LINKER (GLIBC_DYNAMIC_LINKER64, UCLIBC_DYNAMIC_LINKER64, \
 			 BIONIC_DYNAMIC_LINKER64)
+#define LINUX_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/libgcc/ChangeLog.x32 b/libgcc/ChangeLog.x32
new file mode 100644
index 0000000..d5c2af7
--- /dev/null
+++ b/libgcc/ChangeLog.x32
@@ -0,0 +1,6 @@
+2010-01-19  H.J. Lu  <hongjiu.lu@intel.com>
+
+	* config/i386/64/sfp-machine.h (_FP_W_TYPE): Always use _WIN64
+	version.
+	(_FP_WS_TYPE): Likewise.
+	(_FP_I_TYPE): Likewise.
diff --git a/libgcc/config/i386/64/sfp-machine.h b/libgcc/config/i386/64/sfp-machine.h
index 5adf6db..5debf5a 100644
--- a/libgcc/config/i386/64/sfp-machine.h
+++ b/libgcc/config/i386/64/sfp-machine.h
@@ -1,14 +1,8 @@
 #define _FP_W_TYPE_SIZE		64
 
-#ifdef _WIN64
- #define _FP_W_TYPE		unsigned long long
- #define _FP_WS_TYPE		signed long long
- #define _FP_I_TYPE		long long
-#else
- #define _FP_W_TYPE		unsigned long
- #define _FP_WS_TYPE		signed long
- #define _FP_I_TYPE		long
-#endif
+#define _FP_W_TYPE		unsigned long long
+#define _FP_WS_TYPE		signed long long
+#define _FP_I_TYPE		long long
 
 typedef int TItype __attribute__ ((mode (TI)));
 typedef unsigned int UTItype __attribute__ ((mode (TI)));
