revised**2 x86_64-pc-mingw32 patch

Richard Henderson rth@redhat.com
Tue Mar 27 23:48:00 GMT 2007


Thanks to Kai for providing a set of w64 header files, so that I
could cross-compile libgcc and libstdc++.

This fixes up a number of mistakes in the calling convention code,
which were causing ICEs and the like.

I've also fixed the place in the thunk code that was still emitting
the @GOTPCREL references.  I insist that flag_pic should be set,
as that enables the use of rip-relative addressing for most symbols,
which is definitely desirable for win64 code.


r~
-------------- next part --------------
--- gcc/c-pragma.c	(revision 123278)
+++ gcc/c-pragma.c	(local)
@@ -53,6 +53,20 @@ typedef struct align_stack GTY(())
 
 static GTY(()) struct align_stack * alignment_stack;
 
+#ifdef HANDLE_PRAGMA_PUSH_POP_MACRO
+static void handle_pragma_push_macro (cpp_reader *);
+static void handle_pragma_pop_macro (cpp_reader *);
+#endif
+
+typedef struct sPragmaMacro GTY(())
+{
+	char *name;
+	char *value;
+	struct sPragmaMacro *prev;
+} sPragmaMacro;
+static GTY(()) struct sPragmaMacro *theMacroList = NULL;
+
+
 #ifdef HANDLE_PRAGMA_PACK
 static void handle_pragma_pack (cpp_reader *);
 
@@ -132,6 +146,133 @@ pop_alignment (tree id)
     GCC_BAD ("#pragma pack(pop[, id], <n>) is not supported on this target")
 #endif /* HANDLE_PRAGMA_PACK_PUSH_POP */
 
+#ifdef HANDLE_PRAGMA_PUSH_POP_MACRO
+
+/*
+  #pragma push_macro("MACRO_NAME")
+  #pragma pop_macro("MACRO_NAME")
+*/
+static void
+handle_pragma_push_macro (cpp_reader *ARG_UNUSED (dummy))
+{
+  tree x, id = 0;
+  enum cpp_ttype token;
+
+  if (pragma_lex (&x) != CPP_OPEN_PAREN)
+    GCC_BAD ("missing %<(%> after %<#pragma push_macro%> - ignored");
+  token = pragma_lex (&id);
+  if (token == CPP_CLOSE_PAREN)
+    {
+	  /* Silently ignore */
+	  id = 0;
+    }
+  else if (token != CPP_STRING)
+    {
+	  GCC_BAD ("invalid constant in %<#pragma push_macro%> - ignored");
+    }
+  else
+    {
+	  id = (TREE_STRING_LENGTH (id) > 1 ? id : NULL);
+	  token = pragma_lex (&x);
+	  if (token != CPP_CLOSE_PAREN)
+	    {
+		  GCC_BAD ("missing %<)%> after %<#pragma push_macro%> - ignored");
+	    }
+	  else if (pragma_lex (&x) != CPP_EOF)
+	    {
+		  warning (OPT_Wpragmas, "junk at end of %<#pragma push_macro%>");
+		  while(pragma_lex (&x) != CPP_EOF)
+		    ;
+	    }
+  }
+  if (id)
+    {
+	  sPragmaMacro *c;
+	  const char *macroname = TREE_STRING_POINTER (id);
+
+	  if (cpp_defined (dummy,(const unsigned char *) macroname, strlen (macroname)))
+	    {
+		  const char *val;
+
+		  val = cpp_macro_definition (dummy, cpp_lookup (dummy, (const unsigned char *)macroname, strlen (macroname)));
+		  c = (sPragmaMacro *) ggc_alloc (sizeof(sPragmaMacro) + strlen (macroname) + strlen (val) + 4);
+		  c->name = (char *)&c[1];
+		  c->value = &c->name[strlen (macroname) + 1];
+		  strcpy (c->name, macroname);
+		  strcpy (&c->value[0], val);
+		  if (c->value[strlen (c->value) - 1] == '\n')
+		  c->value[strlen (c->value) - 1] = 0;
+		  c->prev = theMacroList;
+		  theMacroList = c;
+	    }
+	  else
+	    {
+		  c = (sPragmaMacro *) ggc_alloc (sizeof(sPragmaMacro) + strlen (macroname) + 4);
+		  c->name = (char*)&c[1];
+		  c->value = NULL;
+		  strcpy (c->name, macroname);
+		  c->prev = theMacroList;
+		  theMacroList = c;
+	    }
+    }
+}
+
+static void handle_pragma_pop_macro(cpp_reader *ARG_UNUSED (dummy))
+{
+  tree x, id = 0;
+  enum cpp_ttype token;
+
+  if (pragma_lex (&x) != CPP_OPEN_PAREN)
+    GCC_BAD ("missing %<(%> after %<#pragma pop_macro%> - ignored");
+  token = pragma_lex (&id);
+  if (token == CPP_CLOSE_PAREN)
+    {
+	  /* Silently ignore */
+    }
+  else if(token != CPP_STRING)
+    {
+	  GCC_BAD ("invalid constant in %<#pragma pop_macro%> - ignored");
+    }
+  else
+    {
+	  id = (TREE_STRING_LENGTH (id) > 1 ? id : NULL);
+	  token = pragma_lex (&x);
+	  if (token != CPP_CLOSE_PAREN)
+	    {
+		  GCC_BAD ("missing %<)%> after %<#pragma pop_macro%> - ignored");
+	    }
+	  else if (pragma_lex (&x) != CPP_EOF)
+		  warning (OPT_Wpragmas, "junk at end of %<#pragma pop_macro%>");
+  }
+  if(id)
+    {
+	  sPragmaMacro *p = NULL, *c = theMacroList;
+	  const char *macroname = TREE_STRING_POINTER (id);
+
+	  while(c != NULL)
+	    {
+		  if(!strcmp (macroname, c->name))
+		    {
+			  char s[4096];
+			  sprintf (s, "\n\n#undef %s\n", c->name);
+			  if (c->value)
+			    {
+				  sprintf (s + strlen (s), "#define %s\n", c->value);
+				  cpp_push_buffer (dummy,s, strlen (s), true);
+				}
+			  else
+			  	  cpp_push_buffer(dummy, s, strlen(s), true);
+			  if(!p) theMacroList = c->prev;
+			  else p->prev = c->prev;
+			  break;
+			}
+		  c = (p = c)->prev;
+		}
+	}
+}
+
+#endif /* HANDLE_PRAGMA_PUSH_POP_MACRO */
+
 /* #pragma pack ()
    #pragma pack (N)
 
@@ -819,6 +960,10 @@ init_pragma (void)
   c_register_pragma (0, "pack", handle_pragma_pack);
 #endif
 #endif
+#ifdef HANDLE_PRAGMA_PUSH_POP_MACRO
+  c_register_pragma (0 ,"push_macro", handle_pragma_push_macro);
+  c_register_pragma (0 ,"pop_macro", handle_pragma_pop_macro);
+#endif
 #ifdef HANDLE_PRAGMA_WEAK
   c_register_pragma (0, "weak", handle_pragma_weak);
 #endif
--- gcc/config/i386/cygming.h	(revision 123278)
+++ gcc/config/i386/cygming.h	(local)
@@ -21,18 +21,35 @@ along with GCC; see the file COPYING.  I
 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 Boston, MA 02110-1301, USA.  */
 
+#if TARGET_64BIT_DEFAULT
+#ifndef DWARF2_DEBUGGING_INFO
+#define DWARF2_DEBUGGING_INFO 1
+#endif
+#ifndef DWARF2_UNWIND_INFO
+#define DWARF2_UNWIND_INFO 1
+#endif
+#endif
+
 #define DBX_DEBUGGING_INFO 1
 #define SDB_DEBUGGING_INFO 1
 #undef PREFERRED_DEBUGGING_TYPE
+#if TARGET_64BIT_DEFAULT
+#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
+#else
 #define PREFERRED_DEBUGGING_TYPE DBX_DEBUG
+#endif
+
+#undef TARGET_64BIT_MS_ABI
+#define TARGET_64BIT_MS_ABI TARGET_64BIT
 
 #ifdef HAVE_GAS_PE_SECREL32_RELOC
 #define DWARF2_DEBUGGING_INFO 1
 
 #undef DBX_REGISTER_NUMBER
-#define DBX_REGISTER_NUMBER(n) (write_symbols == DWARF2_DEBUG   \
-                                ? svr4_dbx_register_map[n]      \
-                                : dbx_register_map[n])
+#define DBX_REGISTER_NUMBER(n)				\
+  (TARGET_64BIT ? dbx64_register_map[n]			\
+   : (write_symbols == DWARF2_DEBUG			\
+      ? svr4_dbx_register_map[n] : dbx_register_map[n]))
 
 /* Use section relative relocations for debugging offsets.  Unlike
    other targets that fake this by putting the section VMA at 0, PE
@@ -97,14 +114,32 @@ Boston, MA 02110-1301, USA.  */
 #undef MATH_LIBRARY
 #define MATH_LIBRARY ""
 
-#define SIZE_TYPE "unsigned int"
-#define PTRDIFF_TYPE "int"
+#define SIZE_TYPE (TARGET_64BIT ? "long long unsigned int" : "unsigned int")
+#define PTRDIFF_TYPE (TARGET_64BIT ? "long long int" : "int")
+
 #define WCHAR_TYPE_SIZE 16
 #define WCHAR_TYPE "short unsigned int"
 
+/* Windows64 continues to use a 32-bit long type.  */
+#undef LONG_TYPE_SIZE
+#define LONG_TYPE_SIZE 32
+
+#undef REG_PARM_STACK_SPACE
+#define REG_PARM_STACK_SPACE(FNDECL) (TARGET_64BIT_MS_ABI ? 32 : 0)
+
+#undef OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE (TARGET_64BIT_MS_ABI ? 1 : 0)
+
+#undef REGPARM_MAX
+#define REGPARM_MAX (TARGET_64BIT_MS_ABI ? 4 : 3)
+
+#undef SSE_REGPARM_MAX
+#define SSE_REGPARM_MAX (TARGET_64BIT_MS_ABI ? 4 : TARGET_SSE ? 3 : 0)
 
 /* Enable parsing of #pragma pack(push,<n>) and #pragma pack(pop).  */
 #define HANDLE_PRAGMA_PACK_PUSH_POP 1
+/* Enable push_macro & pop_macro */
+#define HANDLE_PRAGMA_PUSH_POP_MACRO 1
 
 union tree_node;
 #define TREE union tree_node *
@@ -185,19 +220,21 @@ do {							\
 } while (0)
 
 
-/* Emit code to check the stack when allocating more that 4000
+/* Emit code to check the stack when allocating more than 4000
    bytes in one go.  */
-
 #define CHECK_STACK_LIMIT 4000
 
+#undef STACK_BOUNDARY
+#define STACK_BOUNDARY	(TARGET_64BIT_MS_ABI ? 128 : BITS_PER_WORD)
+
 /* By default, target has a 80387, uses IEEE compatible arithmetic,
    returns float values in the 387 and needs stack probes.
    We also align doubles to 64-bits for MSVC default compatibility.  */
 
 #undef TARGET_SUBTARGET_DEFAULT
 #define TARGET_SUBTARGET_DEFAULT \
-   (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE \
-    | MASK_ALIGN_DOUBLE)
+	(MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS \
+	 | MASK_STACK_PROBE | MASK_ALIGN_DOUBLE)
 
 /* This is how to output an assembler line
    that says to advance the location counter
@@ -266,7 +303,9 @@ extern void i386_pe_unique_section (TREE
 /* DWARF2 Unwinding doesn't work with exception handling yet.  To make
    it work, we need to build a libgcc_s.dll, and dcrt0.o should be
    changed to call __register_frame_info/__deregister_frame_info.  */
+#ifndef DWARF2_UNWIND_INFO
 #define DWARF2_UNWIND_INFO 0
+#endif
 
 /* Don't assume anything about the header files.  */
 #define NO_IMPLICIT_EXTERN_C
@@ -375,8 +414,8 @@ extern int i386_pe_dllimport_name_p (con
 #define TARGET_USE_LOCAL_THUNK_ALIAS_P(DECL) (!DECL_ONE_ONLY (DECL))
 
 #define SUBTARGET_ATTRIBUTE_TABLE \
-  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */ \
   { "selectany", 0, 0, true, false, false, ix86_handle_selectany_attribute }
+  /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
 
 /*  mcount() does not need a counter variable.  */
 #undef NO_PROFILE_COUNTERS
--- gcc/config/i386/cygwin.asm	(revision 123278)
+++ gcc/config/i386/cygwin.asm	(local)
@@ -42,27 +42,66 @@
 
 	.global ___chkstk
 	.global	__alloca
+#ifndef _WIN64
 ___chkstk:
 __alloca:
-	pushl  %ecx		/* save temp */
-	movl   %esp,%ecx	/* get sp */
-	addl   $0x8,%ecx	/* and point to return addr */
-
-probe: 	cmpl   $0x1000,%eax	/* > 4k ?*/
-	jb    done		
-
-	subl   $0x1000,%ecx  		/* yes, move pointer down 4k*/
-	orl    $0x0,(%ecx)   		/* probe there */
-	subl   $0x1000,%eax  	 	/* decrement count */
-	jmp    probe           	 	/* and do it again */
-
-done: 	subl   %eax,%ecx	   
-	orl    $0x0,(%ecx)	/* less that 4k, just peek here */
-
-	movl   %esp,%eax
-	movl   %ecx,%esp	/* decrement stack */
-
-	movl   (%eax),%ecx	/* recover saved temp */
-	movl   4(%eax),%eax	/* get return address */
-	jmp    *%eax	
+	pushl	%ecx		/* save temp */
+	leal	8(%esp), %ecx	/* point past return addr */
+	cmpl	$0x1000, %eax	/* > 4k ?*/
+	jb	Ldone
+
+Lprobe:
+	subl	$0x1000, %ecx  		/* yes, move pointer down 4k*/
+	orl	$0x0, (%ecx)   		/* probe there */
+	subl	$0x1000, %eax  	 	/* decrement count */
+	cmpl	$0x1000, %eax
+	ja	Lprobe         	 	/* and do it again */
+
+Ldone:
+	subl	%eax, %ecx	   
+	orl	$0x0, (%ecx)	/* less than 4k, just peek here */
+
+	movl	%esp, %eax	/* save old stack pointer */
+	movl	%ecx, %esp	/* decrement stack */
+	movl	(%eax), %ecx	/* recover saved temp */
+	movl	4(%eax), %eax	/* recover return address */
+
+	/* Push the return value back.  Doing this instead of just
+	   jumping to %eax preserves the cached call-return stack
+	   used by most modern processors.  */
+	pushl	%eax
+	ret
+#else
+/* __alloca is a normal function call, which uses %rcx as the argument.  */
+__alloca:
+	movq	%rcx, %rax
+	/* FALLTHRU */
+
+/* ___chkstk is a *special* function call, which uses %rax as the argument.
+   We avoid clobbering the 4 integer argument registers, %rcx, %rdx, 
+   %r8 and %r9, which leaves us with %rax, %r10, and %r11 to use.  */
+___chkstk:
+	popq	%r11		/* pop return address */
+	movq	%rsp, %r10	/* get sp */
+	cmpq	$0x1000, %rax	/* > 4k ?*/
+	jb	Ldone
+
+Lprobe:
+	subq	$0x1000, %r10  		/* yes, move pointer down 4k*/
+	orl	$0x0, (%r10)   		/* probe there */
+	subq	$0x1000, %rax  	 	/* decrement count */
+	cmpq	$0x1000, %rax
+	ja	Lprobe         	 	/* and do it again */
+
+Ldone:
+	subq	%rax, %r10
+	orl	$0x0, (%r10)	/* less than 4k, just peek here */
+	movq	%r10, %rsp	/* decrement stack */
+
+	/* Push the return value back.  Doing this instead of just
+	   jumping to %r11 preserves the cached call-return stack
+	   used by most modern processors.  */
+	pushq	%r11
+	ret
+#endif
 #endif
--- gcc/config/i386/gthr-win32.c	(revision 123278)
+++ gcc/config/i386/gthr-win32.c	(local)
@@ -102,7 +102,8 @@ __gthr_win32_once (__gthread_once_t *onc
    C++ EH. Mingw uses a thread-support DLL to work-around this problem.  */
 
 int
-__gthr_win32_key_create (__gthread_key_t *key, void (*dtor) (void *))
+__gthr_win32_key_create (__gthread_key_t *key,
+			 void (*dtor) (void *) __attribute__((unused)))
 {
   int status = 0;
   DWORD tls_index = TlsAlloc ();
--- gcc/config/i386/i386-protos.h	(revision 123278)
+++ gcc/config/i386/i386-protos.h	(local)
@@ -251,3 +251,4 @@ extern enum rtx_code ix86_fp_compare_cod
 extern rtx construct_plt_address (rtx);
 #endif
 extern int asm_preferred_eh_data_format (int, int);
+extern HOST_WIDE_INT ix86_GOT_alias_set (void);
--- gcc/config/i386/i386.c	(revision 123278)
+++ gcc/config/i386/i386.c	(local)
@@ -1304,9 +1304,15 @@ static int const x86_64_int_parameter_re
   FIRST_REX_INT_REG /*R8 */, FIRST_REX_INT_REG + 1 /*R9 */
 };
 
+static int const x86_64_ms_abi_int_parameter_registers[4] =
+{
+  2 /*RCX*/, 1 /*RDX*/,
+  FIRST_REX_INT_REG /*R8 */, FIRST_REX_INT_REG + 1 /*R9 */
+};
+
 static int const x86_64_int_return_registers[4] =
 {
-  0 /*RAX*/, 1 /*RDI*/, 5 /*RDI*/, 4 /*RSI*/
+  0 /*RAX*/, 1 /*RDX*/, 5 /*RDI*/, 4 /*RSI*/
 };
 
 /* The "default" register map used in 64bit mode.  */
@@ -1849,9 +1855,12 @@ override_options (void)
     }
   else
     {
-      ix86_cmodel = CM_32;
-      if (TARGET_64BIT)
+      if (TARGET_64BIT_MS_ABI)
+	ix86_cmodel = CM_SMALL_PIC, flag_pic = true;
+      else if (TARGET_64BIT)
 	ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
+      else
+        ix86_cmodel = CM_32;
     }
   if (ix86_asm_string != 0)
     {
@@ -1973,15 +1982,16 @@ override_options (void)
   /* Validate -mregparm= value.  */
   if (ix86_regparm_string)
     {
+      if (TARGET_64BIT)
+	warning (0, "-mregparm is ignored in 64-bit mode");
       i = atoi (ix86_regparm_string);
       if (i < 0 || i > REGPARM_MAX)
 	error ("-mregparm=%d is not between 0 and %d", i, REGPARM_MAX);
       else
 	ix86_regparm = i;
     }
-  else
-   if (TARGET_64BIT)
-     ix86_regparm = REGPARM_MAX;
+  if (TARGET_64BIT)
+    ix86_regparm = REGPARM_MAX;
 
   /* If the user has provided any of the -malign-* options,
      warn and use that value only if -falign-* is not set.
@@ -2127,18 +2137,16 @@ override_options (void)
 
   if (TARGET_64BIT)
     {
-      if (TARGET_ALIGN_DOUBLE)
-	error ("-malign-double makes no sense in the 64bit mode");
       if (TARGET_RTD)
-	error ("-mrtd calling convention not supported in the 64bit mode");
+	warning (0, "-mrtd is ignored in 64bit mode");
 
       /* Enable by default the SSE and MMX builtins.  Do allow the user to
 	 explicitly disable any of these.  In particular, disabling SSE and
 	 MMX for kernel code is extremely useful.  */
       target_flags
-	|= ((MASK_SSE2 | MASK_SSE | MASK_MMX | MASK_128BIT_LONG_DOUBLE)
+	|= ((MASK_SSE2 | MASK_SSE | MASK_MMX | TARGET_SUBTARGET64_DEFAULT)
 	    & ~target_flags_explicit);
-     }
+    }
   else
     {
       /* i386 ABI does not specify red zone.  It still makes sense to use it
@@ -2637,8 +2645,10 @@ ix86_handle_cconv_attribute (tree *node,
 
   if (TARGET_64BIT)
     {
-      warning (OPT_Wattributes, "%qs attribute ignored",
-	       IDENTIFIER_POINTER (name));
+      /* Do not warn when emulating the MS ABI.  */
+      if (!TARGET_64BIT_MS_ABI)
+	warning (OPT_Wattributes, "%qs attribute ignored",
+	         IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
       return NULL_TREE;
     }
@@ -2925,6 +2935,7 @@ bool
 ix86_function_arg_regno_p (int regno)
 {
   int i;
+  const int *parm_regs;
 
   if (!TARGET_64BIT)
     {
@@ -2952,11 +2963,15 @@ ix86_function_arg_regno_p (int regno)
     }
 
   /* RAX is used as hidden argument to va_arg functions.  */
-  if (regno == 0)
+  if (!TARGET_64BIT_MS_ABI && regno == 0)
     return true;
 
+  if (TARGET_64BIT_MS_ABI)
+    parm_regs = x86_64_ms_abi_int_parameter_registers;
+  else
+    parm_regs = x86_64_int_parameter_registers;
   for (i = 0; i < REGPARM_MAX; i++)
-    if (regno == x86_64_int_parameter_registers[i])
+    if (regno == parm_regs[i])
       return true;
   return false;
 }
@@ -3734,6 +3749,21 @@ function_arg_advance_64 (CUMULATIVE_ARGS
     cum->words += words;
 }
 
+static void
+function_arg_advance_ms_64 (CUMULATIVE_ARGS *cum, HOST_WIDE_INT bytes,
+			    HOST_WIDE_INT words)
+{
+  /* Otherwise, this should be passed indirect.  */
+  gcc_assert (bytes == 1 || bytes == 2 || bytes == 4 || bytes == 8);
+
+  cum->words += words;
+  if (cum->nregs > 0)
+    {
+      cum->nregs -= 1;
+      cum->regno += 1;
+    }
+}
+
 void
 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 		      tree type, int named ATTRIBUTE_UNUSED)
@@ -3749,7 +3779,9 @@ function_arg_advance (CUMULATIVE_ARGS *c
   if (type)
     mode = type_natural_mode (type);
 
-  if (TARGET_64BIT)
+  if (TARGET_64BIT_MS_ABI)
+    function_arg_advance_ms_64 (cum, bytes, words);
+  else if (TARGET_64BIT)
     function_arg_advance_64 (cum, mode, type, words);
   else
     function_arg_advance_32 (cum, mode, type, bytes, words);
@@ -3880,9 +3912,47 @@ function_arg_64 (CUMULATIVE_ARGS *cum, e
 			      cum->sse_regno);
 }
 
+static rtx
+function_arg_ms_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+		    enum machine_mode orig_mode, int named)
+{
+  unsigned int regno;
+
+  /* Avoid the AL settings for the Unix64 ABI.  */
+  if (mode == VOIDmode)
+    return constm1_rtx;
+
+  /* If we've run out of registers, it goes on the stack.  */
+  if (cum->nregs == 0)
+    return NULL_RTX;
+
+  regno = x86_64_ms_abi_int_parameter_registers[cum->regno];
+
+  /* Only floating point modes are passed in anything but integer regs.  */
+  if (mode == SFmode || mode == DFmode)
+    {
+      if (named)
+	regno = cum->regno + FIRST_SSE_REG;
+      else
+	{
+	  rtx t1, t2;
+
+	  /* Unnamed floating parameters are passed in both the
+	     SSE and integer registers.  */
+	  t1 = gen_rtx_REG (mode, cum->regno + FIRST_SSE_REG);
+	  t2 = gen_rtx_REG (mode, regno);
+	  t1 = gen_rtx_EXPR_LIST (VOIDmode, t1, const0_rtx);
+	  t2 = gen_rtx_EXPR_LIST (VOIDmode, t2, const0_rtx);
+	  return gen_rtx_PARALLEL (mode, gen_rtvec (2, t1, t2));
+	}
+    }
+
+  return gen_reg_or_parallel (mode, orig_mode, regno);
+}
+
 rtx
 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode omode,
-	      tree type, int named ATTRIBUTE_UNUSED)
+	      tree type, int named)
 {
   enum machine_mode mode = omode;
   HOST_WIDE_INT bytes, words;
@@ -3898,7 +3968,9 @@ function_arg (CUMULATIVE_ARGS *cum, enum
   if (type && TREE_CODE (type) == VECTOR_TYPE)
     mode = type_natural_mode (type);
 
-  if (TARGET_64BIT)
+  if (TARGET_64BIT_MS_ABI)
+    return function_arg_ms_64 (cum, mode, omode, named);
+  else if (TARGET_64BIT)
     return function_arg_64 (cum, mode, omode, type);
   else
     return function_arg_32 (cum, mode, omode, type, bytes, words);
@@ -3915,7 +3987,30 @@ ix86_pass_by_reference (CUMULATIVE_ARGS 
 			enum machine_mode mode ATTRIBUTE_UNUSED,
 			tree type, bool named ATTRIBUTE_UNUSED)
 {
-  if (TARGET_64BIT && type && int_size_in_bytes (type) == -1)
+  if (TARGET_64BIT_MS_ABI)
+    {
+      if (type)
+	{
+	  /* Arrays are passed by reference.  */
+	  if (TREE_CODE (type) == ARRAY_TYPE)
+	    return true;
+
+	  if (AGGREGATE_TYPE_P (type))
+	    {
+	      /* Structs/unions of sizes other than 8, 16, 32, or 64 bits
+	         are passed by reference.  */
+	      int el2 = exact_log2 (int_size_in_bytes (type));
+	      return !(el2 >= 0 && el2 <= 3);
+	    }
+	}
+
+      /* __m128 is passed by reference.  */
+      /* ??? How to handle complex?  For now treat them as structs,
+	 and pass them by reference if they're too large.  */
+      if (GET_MODE_SIZE (mode) > 8)
+	return true;
+    }
+  else if (TARGET_64BIT && type && int_size_in_bytes (type) == -1)
     return 1;
 
   return 0;
@@ -4018,6 +4113,8 @@ ix86_function_value_regno_p (int regno)
       return true;
 
     case FIRST_FLOAT_REG:
+      if (TARGET_64BIT_MS_ABI)
+	return false;
       return TARGET_FLOAT_RETURNS_IN_80387;
 
     case FIRST_SSE_REG:
@@ -4125,6 +4222,19 @@ function_value_64 (enum machine_mode ori
 }
 
 static rtx
+function_value_ms_64 (enum machine_mode orig_mode, enum machine_mode mode)
+{
+  unsigned int regno = 0;
+
+  if (mode == SFmode || mode == DFmode)
+    regno = FIRST_SSE_REG;
+  else if (VECTOR_MODE_P (mode) || GET_MODE_SIZE (mode) == 16)
+    regno = FIRST_SSE_REG;
+
+  return gen_rtx_REG (orig_mode, regno);
+}
+
+static rtx
 ix86_function_value_1 (tree valtype, tree fntype_or_decl,
 		       enum machine_mode orig_mode, enum machine_mode mode)
 {
@@ -4135,7 +4245,9 @@ ix86_function_value_1 (tree valtype, tre
     fn = fntype_or_decl;
   fntype = fn ? TREE_TYPE (fn) : fntype_or_decl;
 
-  if (TARGET_64BIT)
+  if (TARGET_64BIT_MS_ABI)
+    return function_value_ms_64 (orig_mode, mode);
+  else if (TARGET_64BIT)
     return function_value_64 (orig_mode, mode, valtype);
   else
     return function_value_32 (orig_mode, mode, fntype, fn);
@@ -4207,12 +4319,27 @@ return_in_memory_64 (tree type, enum mac
   return !examine_argument (mode, type, 1, &needed_intregs, &needed_sseregs);
 }
 
+static int
+return_in_memory_ms_64 (tree type, enum machine_mode mode)
+{
+  HOST_WIDE_INT size = int_size_in_bytes (type);
+
+  /* __m128 and friends are returned in xmm0.  */
+  if (size == 16 && VECTOR_MODE_P (mode))
+    return 0;
+
+  /* Otherwise, the size must be exactly in [1248].  */
+  return (size != 1 && size != 2 && size != 4 && size != 8);
+}
+
 int
 ix86_return_in_memory (tree type)
 {
   enum machine_mode mode = type_natural_mode (type);
 
-  if (TARGET_64BIT)
+  if (TARGET_64BIT_MS_ABI)
+    return return_in_memory_ms_64 (type, mode);
+  else if (TARGET_64BIT)
     return return_in_memory_64 (type, mode);
   else
     return return_in_memory_32 (type, mode);
@@ -4273,7 +4400,7 @@ ix86_build_builtin_va_list (void)
   tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl;
 
   /* For i386 we use plain pointer to argument area.  */
-  if (!TARGET_64BIT)
+  if (!TARGET_64BIT || TARGET_64BIT_MS_ABI)
     return build_pointer_type (char_type_node);
 
   record = (*lang_hooks.types.make_type) (RECORD_TYPE);
@@ -4393,6 +4520,27 @@ setup_incoming_varargs_64 (CUMULATIVE_AR
 }
 
 static void
+setup_incoming_varargs_ms_64 (CUMULATIVE_ARGS *cum)
+{
+  int set = get_varargs_alias_set ();
+  int i;
+
+  for (i = cum->regno; i < REGPARM_MAX; i++)
+    {
+      rtx reg, mem;
+
+      mem = gen_rtx_MEM (Pmode,
+			 plus_constant (virtual_incoming_args_rtx,
+					i * UNITS_PER_WORD));
+      MEM_NOTRAP_P (mem) = 1;
+      set_mem_alias_set (mem, set);
+
+      reg = gen_rtx_REG (Pmode, x86_64_ms_abi_int_parameter_registers[i]);
+      emit_move_insn (mem, reg);
+    }
+}
+
+static void
 ix86_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 			     tree type, int *pretend_size ATTRIBUTE_UNUSED,
 			     int no_rtl)
@@ -4419,7 +4567,10 @@ ix86_setup_incoming_varargs (CUMULATIVE_
   if (stdarg_p)
     function_arg_advance (&next_cum, mode, type, 1);
 
-  setup_incoming_varargs_64 (&next_cum);
+  if (TARGET_64BIT_MS_ABI)
+    setup_incoming_varargs_ms_64 (&next_cum);
+  else
+    setup_incoming_varargs_64 (&next_cum);
 }
 
 /* Implement va_start.  */
@@ -4433,7 +4584,7 @@ ix86_va_start (tree valist, rtx nextarg)
   tree type;
 
   /* Only 64bit target needs something special.  */
-  if (!TARGET_64BIT)
+  if (!TARGET_64BIT || TARGET_64BIT_MS_ABI)
     {
       std_expand_builtin_va_start (valist, nextarg);
       return;
@@ -4512,7 +4663,7 @@ ix86_gimplify_va_arg (tree valist, tree 
   enum machine_mode nat_mode;
 
   /* Only 64bit target needs something special.  */
-  if (!TARGET_64BIT)
+  if (!TARGET_64BIT || TARGET_64BIT_MS_ABI)
     return std_gimplify_va_arg_expr (valist, type, pre_p, post_p);
 
   f_gpr = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
@@ -5704,21 +5855,30 @@ ix86_expand_prologue (void)
   else
     {
       /* Only valid for Win32.  */
-      rtx eax = gen_rtx_REG (SImode, 0);
-      bool eax_live = ix86_eax_live_at_start_p ();
+      rtx eax = gen_rtx_REG (Pmode, 0);
+      bool eax_live;
       rtx t;
 
-      gcc_assert (!TARGET_64BIT);
+      gcc_assert (!TARGET_64BIT || TARGET_64BIT_MS_ABI);
+
+      if (TARGET_64BIT_MS_ABI)
+	eax_live = false;
+      else
+	eax_live = ix86_eax_live_at_start_p ();
 
       if (eax_live)
 	{
 	  emit_insn (gen_push (eax));
-	  allocate -= 4;
+	  allocate -= UNITS_PER_WORD;
 	}
 
       emit_move_insn (eax, GEN_INT (allocate));
 
-      insn = emit_insn (gen_allocate_stack_worker (eax));
+      if (TARGET_64BIT)
+	insn = gen_allocate_stack_worker_64 (eax);
+      else
+	insn = gen_allocate_stack_worker_32 (eax);
+      insn = emit_insn (insn);
       RTX_FRAME_RELATED_P (insn) = 1;
       t = gen_rtx_PLUS (Pmode, stack_pointer_rtx, GEN_INT (-allocate));
       t = gen_rtx_SET (VOIDmode, stack_pointer_rtx, t);
@@ -5734,7 +5894,7 @@ ix86_expand_prologue (void)
 			       - frame.nregs * UNITS_PER_WORD);
 	  else
 	    t = plus_constant (stack_pointer_rtx, allocate);
-	  emit_move_insn (eax, gen_rtx_MEM (SImode, t));
+	  emit_move_insn (eax, gen_rtx_MEM (Pmode, t));
 	}
     }
 
@@ -5988,7 +6148,7 @@ ix86_expand_epilogue (int style)
 	{
 	  rtx ecx = gen_rtx_REG (SImode, 2);
 
-	  /* There is no "pascal" calling convention in 64bit ABI.  */
+	  /* There is no "pascal" calling convention in any 64bit ABI.  */
 	  gcc_assert (!TARGET_64BIT);
 
 	  emit_insn (gen_popsi1 (ecx));
@@ -6411,6 +6571,10 @@ legitimate_pic_operand_p (rtx x)
 
     case SYMBOL_REF:
     case LABEL_REF:
+      /* ??? Hack.  See legitimize_pic_address re dllimports.  */
+      if (TARGET_64BIT_MS_ABI)
+	return true;
+
       return legitimate_pic_address_disp_p (x);
 
     default:
@@ -6776,7 +6940,7 @@ legitimate_address_p (enum machine_mode 
 
 /* Return a unique alias set for the GOT.  */
 
-static HOST_WIDE_INT
+HOST_WIDE_INT
 ix86_GOT_alias_set (void)
 {
   static HOST_WIDE_INT set = -1;
@@ -6822,6 +6986,13 @@ legitimize_pic_address (rtx orig, rtx re
 
   if (TARGET_64BIT && legitimate_pic_address_disp_p (addr))
     new = addr;
+
+  /* ??? What are we supposed to do with variables that are dllimported
+     but not properly marked as such?  For now, hard-code the full 
+     64-bit address and assume it'll be fixed up.  */
+  else if (TARGET_64BIT_MS_ABI)
+    new = force_reg (Pmode, addr);
+
   else if (TARGET_64BIT
 	   && ix86_cmodel != CM_SMALL_PIC
 	   && gotoff_operand (addr, Pmode))
@@ -7406,7 +7577,8 @@ output_pic_addr_const (FILE *file, rtx x
 #endif
 	  assemble_name (file, name);
 	}
-      if (!TARGET_MACHO && code == 'P' && ! SYMBOL_REF_LOCAL_P (x))
+      if (!TARGET_MACHO && !TARGET_64BIT_MS_ABI
+	  && code == 'P' && ! SYMBOL_REF_LOCAL_P (x))
 	fputs ("@PLT", file);
       break;
 
@@ -9181,7 +9353,6 @@ ix86_expand_clear (rtx dest)
   /* Avoid HImode and its attendant prefix byte.  */
   if (GET_MODE_SIZE (GET_MODE (dest)) < 4)
     dest = gen_rtx_REG (SImode, REGNO (dest));
-
   tmp = gen_rtx_SET (VOIDmode, dest, const0_rtx);
 
   /* This predicate should match that for movsi_xor and movdi_xor_rex64.  */
@@ -19387,37 +19558,29 @@ static rtx
 x86_this_parameter (tree function)
 {
   tree type = TREE_TYPE (function);
+  bool aggr = aggregate_value_p (TREE_TYPE (type), type) != 0;
 
   if (TARGET_64BIT)
     {
-      int n = aggregate_value_p (TREE_TYPE (type), type) != 0;
-      return gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
+      const int *parm_regs;
+
+      if (TARGET_64BIT_MS_ABI)
+        parm_regs = x86_64_ms_abi_int_parameter_registers;
+      else
+        parm_regs = x86_64_int_parameter_registers;
+      return gen_rtx_REG (DImode, parm_regs[aggr]);
     }
 
-  if (ix86_function_regparm (type, function) > 0)
+  if (ix86_function_regparm (type, function) > 0
+      && !type_has_variadic_args_p (type))
     {
-      tree parm;
-
-      parm = TYPE_ARG_TYPES (type);
-      /* Figure out whether or not the function has a variable number of
-	 arguments.  */
-      for (; parm; parm = TREE_CHAIN (parm))
-	if (TREE_VALUE (parm) == void_type_node)
-	  break;
-      /* If not, the this parameter is in the first argument.  */
-      if (parm)
-	{
-	  int regno = 0;
-	  if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
-	    regno = 2;
-	  return gen_rtx_REG (SImode, regno);
-	}
+      int regno = 0;
+      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
+	regno = 2;
+      return gen_rtx_REG (SImode, regno);
     }
 
-  if (aggregate_value_p (TREE_TYPE (type), type))
-    return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
-  else
-    return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4));
+  return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, aggr ? 8 : 4));
 }
 
 /* Determine whether x86_output_mi_thunk can succeed.  */
@@ -19506,7 +19669,7 @@ x86_output_mi_thunk (FILE *file ATTRIBUT
 	{
 	  int tmp_regno = 2 /* ECX */;
 	  if (lookup_attribute ("fastcall",
-	      TYPE_ATTRIBUTES (TREE_TYPE (function))))
+				TYPE_ATTRIBUTES (TREE_TYPE (function))))
 	    tmp_regno = 0 /* EAX */;
 	  tmp = gen_rtx_REG (SImode, tmp_regno);
 	}
@@ -19546,7 +19709,9 @@ x86_output_mi_thunk (FILE *file ATTRIBUT
   xops[0] = XEXP (DECL_RTL (function), 0);
   if (TARGET_64BIT)
     {
-      if (!flag_pic || (*targetm.binds_local_p) (function))
+      /* ??? HACK, targetm.binds_local_p should return true for MS_ABI.  */
+      if (TARGET_64BIT_MS_ABI
+	  || !flag_pic || (*targetm.binds_local_p) (function))
 	output_asm_insn ("jmp\t%P0", xops);
       else
 	{
@@ -19624,20 +19789,16 @@ void
 x86_function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
 {
   if (TARGET_64BIT)
-    if (flag_pic)
-      {
+    {
 #ifndef NO_PROFILE_COUNTERS
-	fprintf (file, "\tleaq\t%sP%d@(%%rip),%%r11\n", LPREFIX, labelno);
+      fprintf (file, "\tleaq\t%sP%d@(%%rip),%%r11\n", LPREFIX, labelno);
 #endif
+
+      if (!TARGET_64BIT_MS_ABI && flag_pic)
 	fprintf (file, "\tcall\t*%s@GOTPCREL(%%rip)\n", MCOUNT_NAME);
-      }
-    else
-      {
-#ifndef NO_PROFILE_COUNTERS
-	fprintf (file, "\tmovq\t$%sP%d,%%r11\n", LPREFIX, labelno);
-#endif
+      else
 	fprintf (file, "\tcall\t%s\n", MCOUNT_NAME);
-      }
+    }
   else if (flag_pic)
     {
 #ifndef NO_PROFILE_COUNTERS
--- gcc/config/i386/i386.h	(revision 123278)
+++ gcc/config/i386/i386.h	(local)
@@ -20,6 +20,21 @@ along with GCC; see the file COPYING.  I
 the Free Software Foundation, 51 Franklin Street, Fifth Floor,
 Boston, MA 02110-1301, USA.  */
 
+/* The purpose of this file is to define the characteristics of the i386,
+   independent of assembler syntax or operating system.
+
+   Three other files build on this one to describe a specific assembler syntax:
+   bsd386.h, att386.h, and sun386.h.
+
+   The actual tm.h file for a particular system should include
+   this file, and then the file for the appropriate assembler syntax.
+
+   Many macros that specify assembler syntax are omitted entirely from
+   this file because they really belong in the files for particular
+   assemblers.  These include RP, IP, LPREFIX, PUT_OP_SIZE, USE_STAR,
+   ADDR_BEG, ADDR_END, PRINT_IREG, PRINT_SCALE, PRINT_B_I_S, and many
+   that start with ASM_ or end in ASM_OP.  */
+
 #include "config/vxworks-dummy.h"
 
 /* Algorithm to expand string function with.  */
@@ -34,7 +49,9 @@ enum stringop_alg
    loop,
    unrolled_loop
 };
+
 #define NAX_STRINGOP_ALGS 4
+
 /* Specify what algorithm to use for stringops on known size.
    When size is unknown, the UNKNOWN_SIZE alg is used.  When size is
    known at compile time or estimated via feedback, the SIZE array
@@ -43,8 +60,7 @@ enum stringop_alg
    For example initializer:
     {{256, loop}, {-1, rep_prefix_4_byte}}		
    will use loop for blocks smaller or equal to 256 bytes, rep prefix will
-   be used otherwise.
-*/
+   be used otherwise.  */
 struct stringop_algs
 {
   const enum stringop_alg unknown_size;
@@ -54,21 +70,6 @@ struct stringop_algs
   } size [NAX_STRINGOP_ALGS];
 };
 
-/* The purpose of this file is to define the characteristics of the i386,
-   independent of assembler syntax or operating system.
-
-   Three other files build on this one to describe a specific assembler syntax:
-   bsd386.h, att386.h, and sun386.h.
-
-   The actual tm.h file for a particular system should include
-   this file, and then the file for the appropriate assembler syntax.
-
-   Many macros that specify assembler syntax are omitted entirely from
-   this file because they really belong in the files for particular
-   assemblers.  These include RP, IP, LPREFIX, PUT_OP_SIZE, USE_STAR,
-   ADDR_BEG, ADDR_END, PRINT_IREG, PRINT_SCALE, PRINT_B_I_S, and many
-   that start with ASM_ or end in ASM_OP.  */
-
 /* Define the specific costs for a given cpu */
 
 struct processor_costs {
@@ -369,11 +370,17 @@ extern int x86_prefetch_sse;
    the frame pointer in leaf functions.  */
 #define TARGET_DEFAULT 0
 
+/* Extra bits to force on w/ 64-bit mode.  */
+#define TARGET_SUBTARGET64_DEFAULT 0
+
 /* This is not really a target flag, but is done this way so that
    it's analogous to similar code for Mach-O on PowerPC.  darwin.h
    redefines this to 1.  */
 #define TARGET_MACHO 0
 
+/* Likewise, for the Windows 64-bit ABI.  */
+#define TARGET_64BIT_MS_ABI 0
+
 /* Subtargets may reset this to 1 in order to enable 96-bit long double
    with the rounding mode forced to 53 bits.  */
 #define TARGET_96_ROUND_53_LONG_DOUBLE 0
@@ -995,6 +1002,11 @@ do {									\
 	for (i = FIRST_REX_SSE_REG; i <= LAST_REX_SSE_REG; i++)		\
 	  reg_names[i] = "";						\
       }									\
+    if (TARGET_64BIT_MS_ABI)						\
+      {									\
+        call_used_regs[4 /*RSI*/] = 0;                                  \
+        call_used_regs[5 /*RDI*/] = 0;                                  \
+      }									\
   } while (0)
 
 /* Return number of consecutive hard regs needed starting at reg REGNO
--- gcc/config/i386/i386.md	(revision 123278)
+++ gcc/config/i386/i386.md	(local)
@@ -19611,86 +19611,56 @@
   [(set_attr "type" "alu,lea")
    (set_attr "mode" "DI")])
 
-(define_expand "allocate_stack_worker"
-  [(match_operand:SI 0 "register_operand" "")]
-  "TARGET_STACK_PROBE"
-{
-  if (reload_completed)
-    {
-      if (TARGET_64BIT)
-	emit_insn (gen_allocate_stack_worker_rex64_postreload (operands[0]));
-      else
-	emit_insn (gen_allocate_stack_worker_postreload (operands[0]));
-    }
-  else
-    {
-      if (TARGET_64BIT)
-	emit_insn (gen_allocate_stack_worker_rex64 (operands[0]));
-      else
-	emit_insn (gen_allocate_stack_worker_1 (operands[0]));
-    }
-  DONE;
-})
-
-(define_insn "allocate_stack_worker_1"
-  [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")]
-    UNSPECV_STACK_PROBE)
+(define_insn "allocate_stack_worker_32"
+  [(set (match_operand:SI 0 "register_operand" "+a")
+	(unspec_volatile:SI [(match_dup 0)] UNSPECV_STACK_PROBE))
    (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0)))
-   (clobber (match_scratch:SI 1 "=0"))
    (clobber (reg:CC FLAGS_REG))]
   "!TARGET_64BIT && TARGET_STACK_PROBE"
   "call\t__alloca"
   [(set_attr "type" "multi")
    (set_attr "length" "5")])
 
-(define_expand "allocate_stack_worker_postreload"
-  [(parallel [(unspec_volatile:SI [(match_operand:SI 0 "register_operand" "a")]
-				    UNSPECV_STACK_PROBE)
-	      (set (reg:SI SP_REG) (minus:SI (reg:SI SP_REG) (match_dup 0)))
-	      (clobber (match_dup 0))
-	      (clobber (reg:CC FLAGS_REG))])]
-  ""
-  "")
-
-(define_insn "allocate_stack_worker_rex64"
-  [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")]
-    UNSPECV_STACK_PROBE)
+(define_insn "allocate_stack_worker_64"
+  [(set (match_operand:DI 0 "register_operand" "=a")
+	(unspec_volatile:DI [(match_dup 0)] UNSPECV_STACK_PROBE))
    (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0)))
-   (clobber (match_scratch:DI 1 "=0"))
+   (clobber (reg:DI R10_REG))
+   (clobber (reg:DI R11_REG))
    (clobber (reg:CC FLAGS_REG))]
   "TARGET_64BIT && TARGET_STACK_PROBE"
-  "call\t__alloca"
+  "call\t___chkstk"
   [(set_attr "type" "multi")
    (set_attr "length" "5")])
 
-(define_expand "allocate_stack_worker_rex64_postreload"
-  [(parallel [(unspec_volatile:DI [(match_operand:DI 0 "register_operand" "a")]
-				    UNSPECV_STACK_PROBE)
-	      (set (reg:DI SP_REG) (minus:DI (reg:DI SP_REG) (match_dup 0)))
-	      (clobber (match_dup 0))
-	      (clobber (reg:CC FLAGS_REG))])]
-  ""
-  "")
-
 (define_expand "allocate_stack"
-  [(parallel [(set (match_operand:SI 0 "register_operand" "=r")
-		   (minus:SI (reg:SI SP_REG)
-			     (match_operand:SI 1 "general_operand" "")))
-	      (clobber (reg:CC FLAGS_REG))])
-   (parallel [(set (reg:SI SP_REG)
-		   (minus:SI (reg:SI SP_REG) (match_dup 1)))
-	      (clobber (reg:CC FLAGS_REG))])]
+  [(match_operand 0 "register_operand" "")
+   (match_operand 1 "general_operand" "")]
   "TARGET_STACK_PROBE"
 {
-#ifdef CHECK_STACK_LIMIT
-  if (CONST_INT_P (operands[1])
+  rtx x;
+
+#ifndef CHECK_STACK_LIMIT
+#define CHECK_STACK_LIMIT 0
+#endif
+
+  if (CHECK_STACK_LIMIT && CONST_INT_P (operands[1])
       && INTVAL (operands[1]) < CHECK_STACK_LIMIT)
-    emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
-			   operands[1]));
+    {
+      x = expand_simple_binop (Pmode, MINUS, stack_pointer_rtx, operands[1],
+			       stack_pointer_rtx, 0, OPTAB_DIRECT);
+      if (x != stack_pointer_rtx)
+	emit_move_insn (stack_pointer_rtx, x);
+    }
   else
-#endif
-    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode,
-							    operands[1])));
+    {
+      x = copy_to_mode_reg (Pmode, operands[1]);
+      if (TARGET_64BIT)
+	x = gen_allocate_stack_worker_64 (x);
+      else
+	x = gen_allocate_stack_worker_32 (x);
+      emit_insn (x);
+    }
 
   emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
   DONE;
--- gcc/config/i386/i386elf.h	(revision 123278)
+++ gcc/config/i386/i386elf.h	(local)
@@ -27,11 +27,6 @@ Boston, MA 02110-1301, USA.  */
 
 #define TARGET_VERSION fprintf (stderr, " (i386 bare ELF target)");
 
-/* By default, target has a 80387, uses IEEE compatible arithmetic,
-   and returns float values in the 387.  */
-
-#define TARGET_SUBTARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS)
-
 /* The ELF ABI for the i386 says that records and unions are returned
    in memory.  */
 
--- gcc/config/i386/mingw32.h	(revision 123278)
+++ gcc/config/i386/mingw32.h	(local)
@@ -21,7 +21,11 @@ the Free Software Foundation, 51 Frankli
 Boston, MA 02110-1301, USA.  */
 
 #undef TARGET_VERSION
-#define TARGET_VERSION fprintf (stderr, " (x86 MinGW)"); 
+#if TARGET_64BIT_DEFAULT
+#define TARGET_VERSION fprintf (stderr,"(x86_64 MinGW");
+#else
+#define TARGET_VERSION fprintf (stderr," (x86 MinGW)");
+#endif
 
 /* See i386/crtdll.h for an alternative definition.  */
 #define EXTRA_OS_CPP_BUILTINS()					\
@@ -32,13 +36,25 @@ Boston, MA 02110-1301, USA.  */
       builtin_define ("_WIN32");				\
       builtin_define_std ("WIN32");				\
       builtin_define_std ("WINNT");				\
+	  if(TARGET_64BIT_MS_ABI) {					\
+	  builtin_define ("__MINGW64__");			\
+	  builtin_define_with_value("_INTEGRAL_MAX_BITS","64",0); \
+	  builtin_define_std ("WIN64");				\
+	  builtin_define_std ("_WIN64");			\
+	  } else {									\
+	  builtin_define_with_value("_INTEGRAL_MAX_BITS","32",0); \
+	  }	\
     }								\
   while (0)
 
 /* Override the standard choice of /usr/include as the default prefix
    to try when searching for header files.  */
 #undef STANDARD_INCLUDE_DIR
+#if TARGET_64BIT_DEFAULT
+#define STANDARD_INCLUDE_DIR "/mingw/include64"
+#else
 #define STANDARD_INCLUDE_DIR "/mingw/include"
+#endif
 #undef STANDARD_INCLUDE_COMPONENT
 #define STANDARD_INCLUDE_COMPONENT "MINGW"
 
@@ -71,8 +87,12 @@ Boston, MA 02110-1301, USA.  */
 
 /* Override startfile prefix defaults.  */
 #ifndef STANDARD_STARTFILE_PREFIX_1
+#if TARGET_64BIT_DEFAULT
+#define STANDARD_STARTFILE_PREFIX_1 "/mingw/lib64/"
+#else
 #define STANDARD_STARTFILE_PREFIX_1 "/mingw/lib/"
 #endif
+#endif
 #ifndef STANDARD_STARTFILE_PREFIX_2
 #define STANDARD_STARTFILE_PREFIX_2 ""
 #endif
--- gcc/config/i386/predicates.md	(revision 123278)
+++ gcc/config/i386/predicates.md	(local)
@@ -344,7 +344,7 @@
 
 ;; Return nonzero if OP is nonmemory operand acceptable by movabs patterns.
 (define_predicate "x86_64_movabs_operand"
-  (if_then_else (match_test "!TARGET_64BIT || !flag_pic")
+  (if_then_else (match_test "TARGET_64BIT_MS_ABI || !flag_pic")
     (match_operand 0 "nonmemory_operand")
     (ior (match_operand 0 "register_operand")
 	 (and (match_operand 0 "const_double_operand")
--- gcc/config/i386/unix.h	(revision 123278)
+++ gcc/config/i386/unix.h	(local)
@@ -61,5 +61,10 @@ Boston, MA 02110-1301, USA.  */
 
 /* By default, target has a 80387, uses IEEE compatible arithmetic,
    and returns float values in the 387.  */
+#define TARGET_SUBTARGET_DEFAULT \
+	(MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS)
 
-#define TARGET_SUBTARGET_DEFAULT (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS)
+/* By default, 64-bit mode uses 128-bit long double.  */
+#undef TARGET_SUBTARGET64_DEFAULT
+#define TARGET_SUBTARGET64_DEFAULT \
+	MASK_128BIT_LONG_DOUBLE
--- gcc/config/i386/winnt.c	(revision 123278)
+++ gcc/config/i386/winnt.c	(local)
@@ -277,8 +277,11 @@ i386_pe_mark_dllimport (tree decl)
   idp = get_identifier (newname);
 
   symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
-  SET_SYMBOL_REF_DECL (symref, decl);
-  newrtl = gen_rtx_MEM (Pmode,symref);
+  SYMBOL_REF_FLAGS (symref) = SYMBOL_FLAG_LOCAL;
+
+  newrtl = gen_const_mem (Pmode, symref);
+  set_mem_alias_set (newrtl, ix86_GOT_alias_set ());
+
   XEXP (DECL_RTL (decl), 0) = newrtl;
 
   DECL_DLLIMPORT_P (decl) = 1;
--- gcc/config.build	(revision 123278)
+++ gcc/config.build	(local)
@@ -77,7 +77,7 @@ case $build in
     build_xm_file=i386/xm-cygwin.h
     build_exeext=.exe
     ;;
-  i[34567]86-*-mingw32*)
+  i[34567]86-*-mingw32* | x86_64-*-mingw32)
     build_xm_file=i386/xm-mingw32.h
     build_exeext=.exe
     ;;
--- gcc/config.gcc	(revision 123278)
+++ gcc/config.gcc	(local)
@@ -1343,7 +1343,7 @@ i[34567]86-*-pe | i[34567]86-*-cygwin*)
 		thread_file='posix'
 	fi
 	;;
-i[34567]86-*-mingw32*)
+i[34567]86-*-mingw32* | x86_64-*-mingw32*)
 	tm_file="${tm_file} i386/unix.h i386/bsd.h i386/gas.h dbxcoff.h i386/cygming.h i386/mingw32.h"
 	xm_file=i386/xm-mingw32.h
 	tmake_file="i386/t-cygming i386/t-mingw32"
--- gcc/config.host	(revision 123278)
+++ gcc/config.host	(local)
@@ -168,7 +168,7 @@ case ${host} in
     host_xmake_file="${host_xmake_file} i386/x-cygwin"
     host_exeext=.exe
     ;;
-  i[34567]86-*-mingw32*)
+  i[34567]86-*-mingw32* | x86_64-*-mingw32*)
     host_xm_file=i386/xm-mingw32.h
     host_xmake_file="${host_xmake_file} i386/x-mingw32"
     host_exeext=.exe
--- gcc/doc/tm.texi	(revision 123278)
+++ gcc/doc/tm.texi	(local)
@@ -9719,6 +9719,18 @@ This must be a value that would also be 
 @samp{#pragma pack()} (that is, a small power of two).
 @end defmac
 
+@findex #pragma
+@findex pragma
+@defmac HANDLE_PRAGMA_PUSH_POP_MACRO
+Define this macro if you want to support the Win32 style pragmas
+@samp{#pragma push_macro(macro-name-as-string)} and @samp{#pragma
+pop_macro(macro-name-as-string)}.  The @samp{#pragma push_macro(
+macro-name-as-string)} pragma saves the named macro and via
+@samp{#pragma pop_macro(macro-name-as-string)} it will return to the
+previous value.
+@end defmac
+
+
 @defmac DOLLARS_IN_IDENTIFIERS
 Define this macro to control use of the character @samp{$} in
 identifier names for the C family of languages.  0 means @samp{$} is
--- gcc/emutls.c	(revision 123278)
+++ gcc/emutls.c	(local)
@@ -48,6 +48,12 @@ struct __emutls_object
   void *templ;
 };
 
+struct __emutls_array
+{
+  pointer size;
+  void **data[];
+};
+
 #ifdef __GTHREADS
 #ifdef __GTHREAD_MUTEX_INIT
 static __gthread_mutex_t emutls_mutex = __GTHREAD_MUTEX_INIT;
@@ -60,15 +66,16 @@ static pointer emutls_size;
 static void
 emutls_destroy (void *ptr)
 {
-  void ***arr = (void ***) ptr;
-  unsigned long int size = (unsigned long int) arr[0];
-  ++arr;
-  while (--size)
-    {
-      if (*arr)
-	free ((*arr)[-1]);
-      ++arr;
+  struct __emutls_array *arr = ptr;
+  pointer size = arr->size;
+  pointer i;
+
+  for (i = 0; i < size; ++i)
+    {
+      if (arr->data[i])
+	free (arr->data[i][-1]);
     }
+
   free (ptr);
 }
 
@@ -130,9 +137,9 @@ __emutls_get_address (struct __emutls_ob
 #ifndef __GTHREADS
   abort ();
 #else
-  pointer offset;
+  pointer offset = obj->loc.offset;
 
-  if (__builtin_expect (obj->loc.offset == 0, 0))
+  if (__builtin_expect (offset == 0, 0))
     {
       static __gthread_once_t once = __GTHREAD_ONCE_INIT;
       __gthread_once (&once, emutls_init);
@@ -141,37 +148,37 @@ __emutls_get_address (struct __emutls_ob
       obj->loc.offset = offset;
       __gthread_mutex_unlock (&emutls_mutex);
     }
-  else
-    offset = obj->loc.offset;
 
-  void **arr = (void **) __gthread_getspecific (emutls_key);
+  struct __emutls_array *arr = __gthread_getspecific (emutls_key);
   if (__builtin_expect (arr == NULL, 0))
     {
       pointer size = offset + 32;
       arr = calloc (size, sizeof (void *));
       if (arr == NULL)
 	abort ();
-      arr[0] = (void *) size;
+      arr->size = size;
       __gthread_setspecific (emutls_key, (void *) arr);
     }
-  else if (__builtin_expect (offset >= (pointer) arr[0], 0))
+  else if (__builtin_expect (offset >= arr->size, 0))
     {
-      pointer orig_size = (pointer) arr[0];
+      pointer orig_size = arr->size;
       pointer size = orig_size * 2;
       if (offset >= size)
 	size = offset + 32;
       arr = realloc (arr, size * sizeof (void *));
       if (arr == NULL)
 	abort ();
-      memset (arr + orig_size, 0, (size - orig_size) * sizeof (void *));
+      arr->size = size;
+      memset (arr->data + orig_size - 1, 0,
+	      (size - orig_size) * sizeof (void *));
       __gthread_setspecific (emutls_key, (void *) arr);
     }
 
-  void *ret = arr[offset];
+  void *ret = arr->data[offset - 1];
   if (__builtin_expect (ret == NULL, 0))
     {
       ret = emutls_alloc (obj);
-      arr[offset] = ret;
+      arr->data[offset - 1] = ret;
     }
   return ret;
 #endif
--- gcc/gthr-win32.h	(revision 123278)
+++ gcc/gthr-win32.h	(local)
@@ -562,7 +562,8 @@ __gthread_once (__gthread_once_t *once, 
    leaks, especially in threaded applications making extensive use of
    C++ EH. Mingw uses a thread-support DLL to work-around this problem.  */
 static inline int
-__gthread_key_create (__gthread_key_t *key, void (*dtor) (void *))
+__gthread_key_create (__gthread_key_t *key,
+		      void (*dtor) (void *) __attribute__((unused)))
 {
   int status = 0;
   DWORD tls_index = TlsAlloc ();
--- gcc/unwind-generic.h	(revision 123278)
+++ gcc/unwind-generic.h	(local)
@@ -247,16 +247,14 @@ extern void * _Unwind_FindEnclosingFunct
    except when a unsigned long data type on the target machine is not
    capable of storing a pointer.  */
 
-#if __SIZEOF_LONG__ < __SIZEOF_POINTER__
-#ifdef HAVE_LONG_LONG
+#if __SIZEOF_LONG__ >= __SIZEOF_POINTER__
+  typedef long _sleb128_t;
+  typedef unsigned long _uleb128_t;
+#elif __SIZEOF_LONG_LONG__ >= __SIZEOF_POINTER__
   typedef long long _sleb128_t;
   typedef unsigned long long _uleb128_t;
 #else
-  #error "long long data type is needed to define _sleb128_t"
-#endif
-#else
-  typedef long _sleb128_t;
-  typedef unsigned long _uleb128_t;
+# error "What type shall we use for _sleb128_t?"
 #endif
 
 #ifdef __cplusplus
--- libgcc/config.host	(revision 123278)
+++ libgcc/config.host	(local)
@@ -364,7 +364,7 @@ i[4567]86-wrs-vxworks|i[4567]86-wrs-vxwo
 	;;
 i[34567]86-*-pe | i[34567]86-*-cygwin*)
 	;;
-i[34567]86-*-mingw32*)
+i[34567]86-*-mingw32* | x86_64-*-mingw*)
 	;;
 i[34567]86-*-uwin*)
 	;;
--- libstdc++-v3/include/bits/locale_facets.tcc	(revision 123278)
+++ libstdc++-v3/include/bits/locale_facets.tcc	(local)
@@ -1314,7 +1314,7 @@ _GLIBCXX_BEGIN_LDBL_NAMESPACE
       __io.flags((__flags & __fmt) | (ios_base::hex | ios_base::showbase));
 
       __s = _M_insert_int(__s, __io, __fill,
-			  reinterpret_cast<unsigned long>(__v));
+			  reinterpret_cast<intptr_t>(__v));
       __io.flags(__flags);
       return __s;
     }


More information about the Gcc-patches mailing list