public inbox for gcc-patches@gcc.gnu.org
 help / color / mirror / Atom feed
* PATCH: x86_64-pc-mingw32 target for gcc
@ 2007-03-14 14:27 Kai Tietz
  2007-03-20 19:42 ` Richard Henderson
  2007-03-22  0:33 ` revised x86_64-pc-mingw32 patch Richard Henderson
  0 siblings, 2 replies; 33+ messages in thread
From: Kai Tietz @ 2007-03-14 14:27 UTC (permalink / raw)
  To: gcc-patches; +Cc: MinGW-dvlpr

[-- Attachment #1: Type: text/plain, Size: 5181 bytes --]

Hello,

I finished the register calling convention of the mingw32 x86_64 target 
and want now to send the complete patch for approval. I tried to have less 
whitespace changes as necessary.
I deceided to pack even the the new pragma commands "push_macro" and 
"pop_macro", because they are linked and the approval of a dependent patch 
takes a bit long. My prior patches to gcc folder are obsoleted by this 
one.
Also this patch contains a redefinition of the macro 
OUTGOING_REG_PARM_STACK_SPACE to have values zero or one. This is needed 
by the implementation in i386.c, because win64 have caller save stack 
logic.
The calling convention of win64 is a bit different to other i386 targets. 
The ABI uses 4 integer registers (rcx,rdx,r8,r9) for the first parameters, 
the first floating point registers are (xmm0,..xmm3) are shadowed in the 
standard registers on call input. Also the stack needed to save these 
registers have to be reserved by the caller. The va-args methods using 
this region to save the standard register and the treating of va_list is 
as for old win32 platforms.
Also to mark that MS defines the standard type ABI a bit diffent as gcc 
does. The type "long" remains on win64 of size 4 byte, but the long long 
is now also now by MS as 8 byte integer. The __int128 by MS is a integer 
type of mode(TI). This leads for C90 build to some warnings about the 
needed type "long long", because size_t, ptrdiff_t, etc. are longlong's.

I build the cross-compiler by using the following arguments: 
--target=x86_64-pc-mingw32 --disable-libstdcxx-pch --disable-nls 
--enable-languages=c,c++
        make all-gcc
        make install-gcc

The switch --disable-libstdcxx-pch is may not necessary for the pure 
cross-compiler, but I noticed a problem for huge files in pch on 
cygwin-shell. 

ChangeLog:

2007-03-14  Kai Tietz   <kai.tietz@onevision.com>

        * gcc/c-pragma.c (HANDLE_PRAGMA_PUSH_POP_MACRO): New
          (handle_pragma_push_macro): New
          (handle_pragma_pop_macro): New
          (init_pragma): Add new pragma command
        * gcc/config/i386/cygming.h: (DWARF2_DEBUGGING_INFO) for 
x86_64-mingw needs to be valued 1
          (DWARF2_UNWIND_INFO): Likewise
          (PREFERRED_DEBUGGING_TYPE): for x86_64-mingw it needs to be 
DWARF2_DEBUG by default
          (DBX_REGISTER_NUMBER): Have to use dbx64_register_map for 
x86_64-mingw
          (SIZE_TYPE): Needs to be "long long unsigned int" for 
x86_64-mingw
          (PTRDIFF_TYPE): Needs to be "long long int" for x86_64-mingw
          (POINTER_SIZE: Needs to be 64 for x86_64 mingw
          (HANDLE_PRAGMA_PUSH_POP_MACRO): New macro
          (TARGET_SUBTARGET_DEFAULT): Defined proper for x86_64-mingw
        * gcc/config/i386/cygwin.asm: Adjustments for target build of 
x86_64-mingw (and cygwin)
        * gcc/config/i386/i386.c: New calling convention and target 
support
        * gcc/config/i386/i386.h: Add new target
          (call_used_regs): Adjustments for target
          (REGPARM_MAX): Likewise
          (SSE_REGPARM_MAX): Likewise
          (LONG_TYPE_SIZE): Likewise
          (REG_PARM_STACK_SPACE): Likewise
          (OUTGOING_REG_PARM_STACK_SPACE): Added
        * gcc/config/i386/i386.md (allocate_stack64): New
        * gcc/config/i386/i386.opt (64BIT_MS_ABI): New
        * gcc/config/i386/mingw32.h: Adjustments for target x86_64-mingw
          (EXTRA_OS_CPP_BUILTINS): Added predefined macro 
_INTEGRAL_MAX_BITS with the value of bitsize of a pointer
          (WIN64,_WIN64,__MINGW64__): New predefined macros for 
x86_64-mingw target
          (STANDARD_INCLUDE_DIR,STANDARD_STARTFILE_PREFIX_1,): Include for 
x86_64-mingw from different place
        * gcc/config.build: Add x86_64-*-mingw32* target
        * gcc/config.gcc: Add x86_64-*-mingw32* target
        * gcc/config.host: Add x86_64-*-mingw32* target
        * gcc/explow.c: Enable allocate_stack64 and correct if clauses.
        * gcc/expr.c (OUTGOING_REG_PARM_STACK_SPACE): Changed definition 
and clauses
        * gcc/function.c (OUTGOING_REG_PARM_STACK_SPACE): Ditto
        * gcc/calls.c (OUTGOING_REG_PARM_STACK_SPACE): Ditto
        * gcc/config/iq2000/iq2000.h (OUTGOING_REG_PARM_STACK_SPACE): 
Ditto
        * gcc/config/mips/mips.h (OUTGOING_REG_PARM_STACK_SPACE): Ditto
        * gcc/config/mn10300/mn10300.h (OUTGOING_REG_PARM_STACK_SPACE): 
Ditto
        * gcc/config/mt/mt.h (OUTGOING_REG_PARM_STACK_SPACE): Ditto
        * gcc/config/pa/pa.h (OUTGOING_REG_PARM_STACK_SPACE): Ditto
        * gcc/config/rs6000/rs6000.h (OUTGOING_REG_PARM_STACK_SPACE): 
Ditto
        * gcc/config/score/score.h (OUTGOING_REG_PARM_STACK_SPACE): Ditto
        * gcc/config/spu/spu.h (OUTGOING_REG_PARM_STACK_SPACE): Ditto
        * gcc/config/v850/v850.h (OUTGOING_REG_PARM_STACK_SPACE): Ditto
        * gcc/unwind-generic.h (_uleb128_t): Adjust type for win64 target
          (_sleb128_t): Ditto
        * gcc/doc/tm.texi (OUTGOING_REG_PARM_STACK_SPACE): Adjust 
documentation
          (HANDLE_PRAGMA_PUSH_POP_MACRO): Add new
        * fixincludes/mkfixinc.sh: Add x86_64-mingw target
        * libgcc/config.host: Add support for an x86_64-mingw* target.

Regards,
 i.A. Kai Tietz


[-- Attachment #2: libgcc_config.host.diff.txt --]
[-- Type: text/plain, Size: 314 bytes --]

Index: libgcc/config.host
===================================================================
--- libgcc/config.host	(revision 122428)
+++ libgcc/config.host	(working copy)
@@ -360,6 +360,8 @@
 	;;
 i[34567]86-*-mingw32*)
 	;;
+x86_64-*-mingw32*)
+	;;
 i[34567]86-*-uwin*)
 	;;
 i[34567]86-*-interix3*)

[-- Attachment #3: fixincludes_mkfixinc.sh.diff.txt --]
[-- Type: text/plain, Size: 380 bytes --]

Index: fixincludes/mkfixinc.sh
===================================================================
--- fixincludes/mkfixinc.sh	(revision 122428)
+++ fixincludes/mkfixinc.sh	(working copy)
@@ -21,6 +21,7 @@
     i?86-*-pe | \
     i?86-*-cygwin* | \
     i?86-*-mingw32* | \
+    x86_64-*-mingw32* | \
     i?86-*-uwin* | \
     i?86-*-interix* | \
     *-*-vxworks* | \

[-- Attachment #4: diff.gcc.txt --]
[-- Type: text/plain, Size: 49149 bytes --]

diff -ubNr -X ../../excl.txt gcc/c-pragma.c ../../gcc/gcc/c-pragma.c
--- gcc/c-pragma.c	2007-03-13 17:16:18.526016500 +0100
+++ ../../gcc/gcc/c-pragma.c	2007-01-11 15:59:23.335477500 +0100
@@ -53,6 +53,20 @@
 
 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 @@
     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 @@
   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
diff -ubNr -X ../../excl.txt gcc/calls.c ../../gcc/gcc/calls.c
--- gcc/calls.c	2007-03-13 17:16:19.056732000 +0100
+++ ../../gcc/gcc/calls.c	2007-02-28 15:22:22.651143200 +0100
@@ -42,6 +42,11 @@
 #include "cgraph.h"
 #include "except.h"
 
+#ifndef OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 0
+#endif
+
+
 /* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits.  */
 #define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
 
@@ -1222,13 +1227,12 @@
 	    = size_binop (MAX_EXPR, args_size->var,
 			  ssize_int (reg_parm_stack_space));
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
 	  /* The area corresponding to register parameters is not to count in
 	     the size of the block we need.  So make the adjustment.  */
+	  if (!OUTGOING_REG_PARM_STACK_SPACE)
 	  args_size->var
 	    = size_binop (MINUS_EXPR, args_size->var,
 			  ssize_int (reg_parm_stack_space));
-#endif
 	}
     }
   else
@@ -1246,9 +1250,8 @@
       args_size->constant = MAX (args_size->constant,
 				 reg_parm_stack_space);
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
+      if (!OUTGOING_REG_PARM_STACK_SPACE)
       args_size->constant -= reg_parm_stack_space;
-#endif
     }
   return unadjusted_args_size;
 }
@@ -2026,10 +2029,8 @@
   reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
 #endif
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
-  if (reg_parm_stack_space > 0 && PUSH_ARGS)
+  if (!OUTGOING_REG_PARM_STACK_SPACE && reg_parm_stack_space > 0 && PUSH_ARGS)
     must_preallocate = 1;
-#endif
 
   /* Set up a place to return a structure.  */
 
@@ -2430,12 +2431,11 @@
 		     Another approach might be to try to reorder the argument
 		     evaluations to avoid this conflicting stack usage.  */
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
 		  /* Since we will be writing into the entire argument area,
 		     the map must be allocated for its entire size, not just
 		     the part that is the responsibility of the caller.  */
+		  if (!OUTGOING_REG_PARM_STACK_SPACE)
 		  needed += reg_parm_stack_space;
-#endif
 
 #ifdef ARGS_GROW_DOWNWARD
 		  highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
@@ -2531,12 +2531,8 @@
 	     an argument.  */
 	  if (stack_arg_under_construction)
 	    {
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
-	      rtx push_size = GEN_INT (reg_parm_stack_space
-				       + adjusted_args_size.constant);
-#else
-	      rtx push_size = GEN_INT (adjusted_args_size.constant);
-#endif
+	      rtx push_size = (!OUTGOING_REG_PARM_STACK_SPACE ? (GEN_INT (reg_parm_stack_space
+				       + adjusted_args_size.constant)) : (GEN_INT (adjusted_args_size.constant)));
 	      if (old_stack_level == 0)
 		{
 		  emit_stack_save (SAVE_BLOCK, &old_stack_level,
@@ -2706,11 +2702,9 @@
       /* If register arguments require space on the stack and stack space
 	 was not preallocated, allocate stack space here for arguments
 	 passed in registers.  */
-#ifdef OUTGOING_REG_PARM_STACK_SPACE
-      if (!ACCUMULATE_OUTGOING_ARGS
+      if (OUTGOING_REG_PARM_STACK_SPACE && !ACCUMULATE_OUTGOING_ARGS
 	  && must_preallocate == 0 && reg_parm_stack_space > 0)
 	anti_adjust_stack (GEN_INT (reg_parm_stack_space));
-#endif
 
       /* Pass the function the address in which to return a
 	 structure value.  */
@@ -3532,9 +3526,8 @@
   args_size.constant = MAX (args_size.constant,
 			    reg_parm_stack_space);
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
+  if (!OUTGOING_REG_PARM_STACK_SPACE)
   args_size.constant -= reg_parm_stack_space;
-#endif
 
   if (args_size.constant > current_function_outgoing_args_size)
     current_function_outgoing_args_size = args_size.constant;
@@ -3555,12 +3548,11 @@
 
       needed = args_size.constant;
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
       /* Since we will be writing into the entire argument area, the
 	 map must be allocated for its entire size, not just the part that
 	 is the responsibility of the caller.  */
+	  if (!OUTGOING_REG_PARM_STACK_SPACE)
       needed += reg_parm_stack_space;
-#endif
 
 #ifdef ARGS_GROW_DOWNWARD
       highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
diff -ubNr -X ../../excl.txt gcc/config/i386/cygming.h ../../gcc/gcc/config/i386/cygming.h
--- gcc/config/i386/cygming.h	2007-03-13 17:17:26.749411600 +0100
+++ ../../gcc/gcc/config/i386/cygming.h	2007-01-29 10:52:55.861644600 +0100
@@ -21,18 +21,31 @@
 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
 
 #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])
+                                ? (TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n]) \
+                                : (TARGET_64BIT ? dbx64_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 +110,17 @@
 #undef MATH_LIBRARY
 #define MATH_LIBRARY ""
 
-#define SIZE_TYPE "unsigned int"
-#define PTRDIFF_TYPE "int"
+#define SIZE_TYPE (TARGET_64BIT ? (TARGET_64BIT_MS_ABI ? "long long unsigned int" : "long unsigned int") : "unsigned int")
+#define PTRDIFF_TYPE (TARGET_64BIT ? (TARGET_64BIT_MS_ABI ? "long long int" : "long int") : "int")
 #define WCHAR_TYPE_SIZE 16
 #define WCHAR_TYPE "short unsigned int"
+#define POINTER_SIZE (TARGET_64BIT ? 64 : 32)
 
 \f
 /* 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 *
@@ -194,10 +210,15 @@
    returns float values in the 387 and needs stack probes.
    We also align doubles to 64-bits for MSVC default compatibility.  */
 
+#if TARGET_64BIT_DEFAULT
+#undef TARGET_SUBTARGET_DEFAULT
+#define TARGET_SUBTARGET_DEFAULT \
+	(MASK_64BIT | MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_64BIT | MASK_64BIT_MS_ABI)
+#else
 #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)
+#endif
 
 /* This is how to output an assembler line
    that says to advance the location counter
@@ -266,7 +287,9 @@
 /* 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 +398,8 @@
 #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
diff -ubNr -X ../../excl.txt gcc/config/i386/cygwin.asm ../../gcc/gcc/config/i386/cygwin.asm
--- gcc/config/i386/cygwin.asm	2007-03-12 15:33:15.313756900 +0100
+++ ../../gcc/gcc/config/i386/cygwin.asm	2007-03-14 12:54:49.848147900 +0100
@@ -44,6 +44,7 @@
 	.global	__alloca
 ___chkstk:
 __alloca:
+#ifndef _WIN64
 	pushl  %ecx		/* save temp */
 	movl   %esp,%ecx	/* get sp */
 	addl   $0x8,%ecx	/* and point to return addr */
@@ -65,4 +66,27 @@
 	movl   (%eax),%ecx	/* recover saved temp */
 	movl   4(%eax),%eax	/* get return address */
 	jmp    *%eax	
+#else
+	pushq  %rdx		/* save temp */
+	movq   %rsp,%rdx	/* get sp */
+	addq   $0x10,%rdx	/* and point to return addr */
+
+probe: 	cmpq   $0x1000,%rcx	/* > 4k ?*/
+	jb    done		
+
+	subq   $0x1000,%rdx  		/* yes, move pointer down 4k*/
+	orq    $0x0,(%rdx)   		/* probe there */
+	subq   $0x1000,%rcx  	 	/* decrement count */
+	jmp    probe           	 	/* and do it again */
+
+done: 	subq   %rcx,%rdx	   
+	orq    $0x0,(%rdx)	/* less that 4k, just peek here */
+
+	movq   %rsp,%rax
+	movq   %rdx,%rsp	/* decrement stack */
+
+	movq   (%rax),%rdx	/* recover saved temp */
+	movq   8(%rax),%rax	/* get return address */
+	jmp    *%rax	
+#endif
 #endif
diff -ubNr -X ../../excl.txt gcc/config/i386/i386.c ../../gcc/gcc/config/i386/i386.c
--- gcc/config/i386/i386.c	2007-03-14 09:11:03.690147900 +0100
+++ ../../gcc/gcc/config/i386/i386.c	2007-03-14 12:20:47.773063500 +0100
@@ -1277,9 +1277,15 @@
   FIRST_REX_INT_REG /*R8 */, FIRST_REX_INT_REG + 1 /*R9 */
 };
 
+static int const x86_64_ms_abi_int_parameter_registers[6] =
+{
+  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.  */
@@ -2086,7 +2092,7 @@
     {
       ix86_cmodel = CM_32;
       if (TARGET_64BIT)
-	ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
+	ix86_cmodel = (TARGET_64BIT_MS_ABI ? (flag_pic ? CM_MEDIUM_PIC : CM_MEDIUM) : (flag_pic ? CM_SMALL_PIC : CM_SMALL));
     }
   if (ix86_asm_string != 0)
     {
@@ -2867,7 +2873,7 @@
       return NULL_TREE;
     }
 
-  if (TARGET_64BIT)
+  if (TARGET_64BIT && !TARGET_64BIT_MS_ABI)
     {
       warning (OPT_Wattributes, "%qs attribute ignored",
 	       IDENTIFIER_POINTER (name));
@@ -2984,7 +2990,7 @@
 	}
 
       /* Use register calling convention for local functions when possible.  */
-      if (!TARGET_64BIT && !user_convention && decl
+      if ((!TARGET_64BIT || TARGET_64BIT_MS_ABI) && !user_convention && decl
 	  && flag_unit_at_a_time && !profile_flag)
 	{
 	  struct cgraph_local_info *i = cgraph_local_info (decl);
@@ -3113,8 +3119,8 @@
   int rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE);
 
   /* Cdecl functions override -mrtd, and never pop the stack.  */
-  if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) {
-
+  if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype)))
+    {
     /* Stdcall and fastcall functions will pop the stack if not
        variable args.  */
     if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))
@@ -3130,7 +3136,7 @@
 
   /* Lose any fake structure return argument if it is passed on the stack.  */
   if (aggregate_value_p (TREE_TYPE (funtype), fundecl)
-      && !TARGET_64BIT
+      && (!TARGET_64BIT || TARGET_64BIT_MS_ABI)
       && !KEEP_AGGREGATE_RETURN_POINTER)
     {
       int nregs = ix86_function_regparm (funtype, fundecl);
@@ -3149,6 +3155,7 @@
 ix86_function_arg_regno_p (int regno)
 {
   int i;
+  const int *x86_64_int_parameter_registers_ptr;
   if (!TARGET_64BIT)
     {
       if (TARGET_MACHO)
@@ -3174,10 +3181,15 @@
         return true;
     }
   /* RAX is used as hidden argument to va_arg functions.  */
-  if (!regno)
+  if (!TARGET_64BIT_MS_ABI && !regno)
     return true;
+  if (TARGET_64BIT_MS_ABI)
+    x86_64_int_parameter_registers_ptr = x86_64_ms_abi_int_parameter_registers;
+  else
+    x86_64_int_parameter_registers_ptr = x86_64_int_parameter_registers;
+
   for (i = 0; i < REGPARM_MAX; i++)
-    if (regno == x86_64_int_parameter_registers[i])
+    if (regno == x86_64_int_parameter_registers_ptr[i])
       return true;
   return false;
 }
@@ -3276,6 +3288,13 @@
 		  cum->fastcall = 0;
 		  cum->float_in_sse = 0;
 		}
+	      else if(TARGET_64BIT_MS_ABI)
+	        {
+		  cum->mmx_nregs = 0;
+		  cum->warn_mmx = 0;
+		  cum->fastcall = 0;
+		  cum->float_in_sse = 1;
+		}
 	      cum->maybe_vaarg = true;
 	    }
 	}
@@ -3339,9 +3358,42 @@
 
 static rtx
 gen_reg_or_parallel (enum machine_mode mode, enum machine_mode orig_mode,
-		     unsigned int regno)
+		     unsigned int regno,const int **intreg)
 {
-  rtx tmp;
+  rtx tmp,tmp2;
+  if (TARGET_64BIT_MS_ABI && intreg)
+    {
+      enum machine_mode shadow_mode= SImode;
+      int shadow=-1;
+
+      if (regno >= FIRST_SSE_REG && regno<=LAST_SSE_REG)
+        {
+          shadow=regno-FIRST_SSE_REG; shadow_mode=DImode;
+        }
+      else if (regno >= FIRST_MMX_REG && regno <= LAST_MMX_REG)
+        shadow=regno-FIRST_MMX_REG;
+      if (shadow!=-1)
+        {
+          shadow=**intreg; intreg[0]++;
+          if (orig_mode != BLKmode)
+            {
+              tmp = gen_rtx_REG (orig_mode, regno);
+              tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp, const0_rtx);
+              tmp2= gen_rtx_REG (shadow_mode, (unsigned int) shadow);
+              tmp2 = gen_rtx_EXPR_LIST (VOIDmode, tmp2, const0_rtx);
+              tmp = gen_rtx_PARALLEL (orig_mode, gen_rtvec (2, tmp, tmp2));
+            }
+          else
+            {
+              tmp = gen_rtx_REG (mode, regno);
+              tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp, const0_rtx);
+              tmp2= gen_rtx_REG (shadow_mode, (unsigned int) shadow);
+              tmp2 = gen_rtx_EXPR_LIST (VOIDmode, tmp2, const0_rtx);
+              tmp = gen_rtx_PARALLEL (orig_mode, gen_rtvec (2, tmp, tmp2));
+            }
+          return tmp;
+	}
+    }
 
   if (orig_mode != BLKmode)
     tmp = gen_rtx_REG (orig_mode, regno);
@@ -3703,11 +3755,15 @@
       case X86_64_INTEGER_CLASS:
       case X86_64_INTEGERSI_CLASS:
 	(*int_nregs)++;
+	if (TARGET_64BIT_MS_ABI)
+	  (*sse_nregs)++;
 	break;
       case X86_64_SSE_CLASS:
       case X86_64_SSESF_CLASS:
       case X86_64_SSEDF_CLASS:
 	(*sse_nregs)++;
+	if (TARGET_64BIT_MS_ABI)
+	  (*int_nregs)++;
 	break;
       case X86_64_NO_CLASS:
       case X86_64_SSEUP_CLASS:
@@ -3746,7 +3802,7 @@
   int i;
   int nexps = 0;
   int needed_sseregs, needed_intregs;
-  rtx exp[MAX_CLASSES];
+  rtx exp[MAX_CLASSES*2];
   rtx ret;
 
   n = classify_argument (mode, type, class, 0);
@@ -3819,7 +3875,7 @@
       case X86_64_SSE_CLASS:
       case X86_64_SSESF_CLASS:
       case X86_64_SSEDF_CLASS:
-	return gen_reg_or_parallel (mode, orig_mode, SSE_REGNO (sse_regno));
+	return gen_reg_or_parallel (mode, orig_mode, SSE_REGNO (sse_regno),&intreg);
       case X86_64_X87_CLASS:
       case X86_64_COMPLEX_X87_CLASS:
 	return gen_rtx_REG (mode, FIRST_STACK_REG);
@@ -3831,7 +3887,20 @@
       }
   if (n == 2 && class[0] == X86_64_SSE_CLASS && class[1] == X86_64_SSEUP_CLASS
       && mode != BLKmode)
+    {
+      if (TARGET_64BIT_MS_ABI)
+        {
+          rtx tmp,tmp2;
+          tmp = gen_rtx_REG (mode, SSE_REGNO (sse_regno));
+          tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp, const0_rtx);
+          tmp2= gen_rtx_REG (DImode, intreg[0]);
+          tmp2 = gen_rtx_EXPR_LIST (VOIDmode, tmp2, const0_rtx);
+          tmp = gen_rtx_PARALLEL (mode, gen_rtvec (2, tmp, tmp2));
+          return tmp;
+        }
     return gen_rtx_REG (mode, SSE_REGNO (sse_regno));
+    }
+
   if (n == 2
       && class[0] == X86_64_X87_CLASS && class[1] == X86_64_X87UP_CLASS)
     return gen_rtx_REG (XFmode, FIRST_STACK_REG);
@@ -3864,6 +3933,7 @@
 					       gen_rtx_REG (tmpmode, *intreg),
 					       GEN_INT (i*8));
 	    intreg++;
+	    if (TARGET_64BIT_MS_ABI) sse_regno++;
 	    break;
 	  case X86_64_SSESF_CLASS:
 	    exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
@@ -3871,6 +3941,13 @@
 							    SSE_REGNO (sse_regno)),
 					       GEN_INT (i*8));
 	    sse_regno++;
+	    if (TARGET_64BIT_MS_ABI)
+	      {
+	        exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
+	        				   gen_rtx_REG (DImode, *intreg),
+	        				   GEN_INT (i*8));
+	        intreg++;
+	      }
 	    break;
 	  case X86_64_SSEDF_CLASS:
 	    exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
@@ -3878,6 +3955,11 @@
 							    SSE_REGNO (sse_regno)),
 					       GEN_INT (i*8));
 	    sse_regno++;
+	    if (TARGET_64BIT_MS_ABI)
+	      {
+	        exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode, gen_rtx_REG (DImode, *intreg),GEN_INT (i*8));
+	        intreg++;
+	      }
 	    break;
 	  case X86_64_SSE_CLASS:
 	    if (i < n - 1 && class[i + 1] == X86_64_SSEUP_CLASS)
@@ -3891,6 +3973,11 @@
 	    if (tmpmode == TImode)
 	      i++;
 	    sse_regno++;
+	    if (TARGET_64BIT_MS_ABI)
+	      {
+	        exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,gen_rtx_REG (tmpmode, *intreg),GEN_INT (i*8));
+	        intreg++;
+	      }
 	    break;
 	  default:
 	    gcc_unreachable ();
@@ -4040,6 +4127,7 @@
   int bytes =
     (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
   int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+  const int *x86_64_int_parameter_registers_ptr;
   static bool warnedsse, warnedmmx;
 
   /* To simplify the code below, represent vector types with a vector mode
@@ -4052,7 +4140,7 @@
      any AL settings.  */
   if (mode == VOIDmode)
     {
-      if (TARGET_64BIT)
+      if (TARGET_64BIT && !TARGET_64BIT_MS_ABI)
 	return GEN_INT (cum->maybe_vaarg
 			? (cum->sse_nregs < 0
 			   ? SSE_REGPARM_MAX
@@ -4062,10 +4150,16 @@
 	return constm1_rtx;
     }
   if (TARGET_64BIT)
+    {
+      if (TARGET_64BIT_MS_ABI)
+	x86_64_int_parameter_registers_ptr = x86_64_ms_abi_int_parameter_registers;
+      else
+	x86_64_int_parameter_registers_ptr = x86_64_int_parameter_registers;
     ret = construct_container (mode, orig_mode, type, 0, cum->nregs,
 			       cum->sse_nregs,
-			       &x86_64_int_parameter_registers [cum->regno],
+			         &x86_64_int_parameter_registers_ptr [cum->regno],
 			       cum->sse_regno);
+    }
   else
     switch (mode)
       {
@@ -4089,7 +4183,7 @@
 	       smaller arguments to ECX and EDX.  */
 	    if (cum->fastcall)
 	      {
-	        if (mode == BLKmode || mode == DImode)
+	        if (mode == BLKmode || (mode == DImode && !TARGET_64BIT))
 	          break;
 
 	        /* ECX not EAX is the first allocated register.  */
@@ -4123,7 +4217,7 @@
 	      }
 	    if (cum->sse_nregs)
 	      ret = gen_reg_or_parallel (mode, orig_mode,
-					 cum->sse_regno + FIRST_SSE_REG);
+					 cum->sse_regno + FIRST_SSE_REG,NULL);
 	  }
 	break;
       case V8QImode:
@@ -4140,7 +4234,7 @@
 	      }
 	    if (cum->mmx_nregs)
 	      ret = gen_reg_or_parallel (mode, orig_mode,
-					 cum->mmx_regno + FIRST_MMX_REG);
+					 cum->mmx_regno + FIRST_MMX_REG,NULL);
 	  }
 	break;
       }
@@ -4507,7 +4601,7 @@
   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);
@@ -4560,9 +4654,29 @@
   tree fntype;
   int stdarg_p;
   int i;
+  const int *x86_64_int_parameter_registers_ptr;
 
-  if (!TARGET_64BIT)
+  if (!TARGET_64BIT || TARGET_64BIT_MS_ABI)
+    {
+       if (TARGET_64BIT_MS_ABI)
+	 {
+	   if (!no_rtl)
+	     save_area = frame_pointer_rtx;
+
+	   set = get_varargs_alias_set ();
+	   x86_64_int_parameter_registers_ptr = x86_64_ms_abi_int_parameter_registers;
+	   for (i = 0; i < ix86_regparm; i++)
+	     {
+	       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);
+	       emit_move_insn (mem, gen_rtx_REG (Pmode,
+						 x86_64_int_parameter_registers_ptr[i]));
+	     }
+         }
     return;
+    }
 
   if (! cfun->va_list_gpr_size && ! cfun->va_list_fpr_size)
     return;
@@ -4588,6 +4702,11 @@
 
   set = get_varargs_alias_set ();
 
+  if (TARGET_64BIT_MS_ABI)
+    x86_64_int_parameter_registers_ptr = x86_64_ms_abi_int_parameter_registers;
+  else
+    x86_64_int_parameter_registers_ptr = x86_64_int_parameter_registers;
+
   for (i = next_cum.regno;
        i < ix86_regparm
        && i < next_cum.regno + cfun->va_list_gpr_size / UNITS_PER_WORD;
@@ -4598,7 +4717,7 @@
       MEM_NOTRAP_P (mem) = 1;
       set_mem_alias_set (mem, set);
       emit_move_insn (mem, gen_rtx_REG (Pmode,
-					x86_64_int_parameter_registers[i]));
+					x86_64_int_parameter_registers_ptr[i]));
     }
 
   if (next_cum.sse_nregs && cfun->va_list_fpr_size)
@@ -4660,7 +4779,7 @@
   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;
@@ -4743,7 +4862,7 @@
   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));
@@ -5350,9 +5469,18 @@
 	  ASM_OUTPUT_LABEL (asm_out_file, name);
 	}
 
+      if(!TARGET_64BIT)
+        {
       xops[0] = gen_rtx_REG (SImode, regno);
       xops[1] = gen_rtx_MEM (SImode, stack_pointer_rtx);
       output_asm_insn ("mov{l}\t{%1, %0|%0, %1}", xops);
+	 }
+       else
+         {
+	    xops[0] = gen_rtx_REG (DImode, regno);
+	    xops[1] = gen_rtx_MEM (DImode, stack_pointer_rtx);
+	    output_asm_insn ("mov{q}\t{%1, %0|%0, %1}", xops);
+         }
       output_asm_insn ("ret", xops);
     }
 
@@ -5935,11 +6063,11 @@
   else
     {
       /* Only valid for Win32.  */
-      rtx eax = gen_rtx_REG (SImode, 0);
+      rtx eax = gen_rtx_REG ((TARGET_64BIT ? DImode : SImode), 0);
       bool eax_live = ix86_eax_live_at_start_p ();
       rtx t;
 
-      gcc_assert (!TARGET_64BIT);
+      gcc_assert (!TARGET_64BIT || TARGET_64BIT_MS_ABI);
 
       if (eax_live)
 	{
@@ -5965,7 +6093,7 @@
 			       - 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 ((!TARGET_64BIT ? SImode : DImode), t));
 	}
     }
 
@@ -6220,13 +6348,22 @@
 	  rtx ecx = gen_rtx_REG (SImode, 2);
 
 	  /* There is no "pascal" calling convention in 64bit ABI.  */
-	  gcc_assert (!TARGET_64BIT);
+	  gcc_assert (!TARGET_64BIT || TARGET_64BIT_MS_ABI);
 
+	  if(!TARGET_64BIT)
+	    {
 	  emit_insn (gen_popsi1 (ecx));
 	  emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx, popc));
 	  emit_jump_insn (gen_return_indirect_internal (ecx));
 	}
       else
+	    {
+	      emit_insn (gen_popdi1 (ecx));
+	      emit_insn (gen_adddi3 (stack_pointer_rtx, stack_pointer_rtx, popc));
+	      emit_jump_insn (gen_return_indirect_internal (ecx));
+	    }
+	}
+      else
 	emit_jump_insn (gen_return_pop_internal (popc));
     }
   else
@@ -9431,9 +9568,16 @@
   gcc_assert (reload_completed);
 
   /* Avoid HImode and its attendant prefix byte.  */
+  if(!TARGET_64BIT)
+    {
   if (GET_MODE_SIZE (GET_MODE (dest)) < 4)
     dest = gen_rtx_REG (SImode, REGNO (dest));
-
+    }
+  else
+    {
+      if (GET_MODE_SIZE (GET_MODE (dest)) < 8)
+        dest = gen_rtx_REG (DImode, REGNO (dest));
+    }
   tmp = gen_rtx_SET (VOIDmode, dest, const0_rtx);
 
   /* This predicate should match that for movsi_xor and movdi_xor_rex64.  */
@@ -19550,7 +19694,13 @@
   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 *x86_64_int_parameter_registers_ptr;
+
+      if (TARGET_64BIT_MS_ABI)
+        x86_64_int_parameter_registers_ptr = x86_64_ms_abi_int_parameter_registers;
+      else
+        x86_64_int_parameter_registers_ptr = x86_64_int_parameter_registers;
+      return gen_rtx_REG (DImode, x86_64_int_parameter_registers_ptr[n]);
     }
 
   if (ix86_function_regparm (type, function) > 0)
@@ -19569,14 +19719,14 @@
 	  int regno = 0;
 	  if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
 	    regno = 2;
-	  return gen_rtx_REG (SImode, regno);
+	  return gen_rtx_REG ((TARGET_64BIT ? DImode : SImode), regno);
 	}
     }
 
   if (aggregate_value_p (TREE_TYPE (type), type))
-    return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
+    return gen_rtx_MEM ((TARGET_64BIT ? DImode : SImode), plus_constant (stack_pointer_rtx, 8)); /* Should this be 16 for 64-bit ? */
   else
-    return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4));
+    return gen_rtx_MEM ((TARGET_64BIT ? DImode : SImode), plus_constant (stack_pointer_rtx, 4)); /* Should this be 8 for 64-bit ? */
 }
 
 /* Determine whether x86_output_mi_thunk can succeed.  */
@@ -19630,7 +19780,10 @@
       /* Put the this parameter into %eax.  */
       xops[0] = this;
       xops[1] = this_reg = gen_rtx_REG (Pmode, 0);
+      if(Pmode==SImode)
       output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
+      else
+        output_asm_insn ("mov{q}\t{%0, %1|%1, %0}", xops);
     }
   else
     this_reg = NULL_RTX;
@@ -19667,7 +19820,7 @@
 	  if (lookup_attribute ("fastcall",
 	      TYPE_ATTRIBUTES (TREE_TYPE (function))))
 	    tmp_regno = 0 /* EAX */;
-	  tmp = gen_rtx_REG (SImode, tmp_regno);
+	  tmp = gen_rtx_REG ((TARGET_64BIT ? DImode : SImode), tmp_regno);
 	}
 
       xops[0] = gen_rtx_MEM (Pmode, this_reg);
@@ -19735,7 +19888,7 @@
 	else
 #endif /* TARGET_MACHO */
 	{
-	  tmp = gen_rtx_REG (SImode, 2 /* ECX */);
+	  tmp = gen_rtx_REG ((TARGET_64BIT ? DImode : SImode), 2 /* ECX */);
 	  output_set_got (tmp, NULL_RTX);
 
 	  xops[1] = tmp;
diff -ubNr -X ../../excl.txt gcc/config/i386/i386.h ../../gcc/gcc/config/i386/i386.h
--- gcc/config/i386/i386.h	2007-03-14 09:11:01.336928400 +0100
+++ ../../gcc/gcc/config/i386/i386.h	2007-03-14 08:25:38.814825100 +0100
@@ -669,7 +669,7 @@
 #define SHORT_TYPE_SIZE 16
 #define INT_TYPE_SIZE 32
 #define FLOAT_TYPE_SIZE 32
-#define LONG_TYPE_SIZE BITS_PER_WORD
+#define LONG_TYPE_SIZE (TARGET_64BIT_MS_ABI ? 32 : BITS_PER_WORD)
 #define DOUBLE_TYPE_SIZE 64
 #define LONG_LONG_TYPE_SIZE 64
 
@@ -978,6 +978,9 @@
 	  reg_names[i] = "";						\
 	for (i = FIRST_REX_SSE_REG; i <= LAST_REX_SSE_REG; i++)		\
 	  reg_names[i] = "";						\
+      }	else if(TARGET_64BIT_MS_ABI) {					\
+        call_used_regs[4 /*RSI*/] = 0;                                  \
+        call_used_regs[5 /*RDI*/] = 0;                                  \
       }									\
   } while (0)
 
@@ -1511,7 +1514,9 @@
    This space can be allocated by the caller, or be a part of the
    machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says
    which.  */
-#define REG_PARM_STACK_SPACE(FNDECL) 0
+#define REG_PARM_STACK_SPACE(FNDECL) (TARGET_64BIT_MS_ABI ? 32 : 0)
+
+#define OUTGOING_REG_PARM_STACK_SPACE (TARGET_64BIT_MS_ABI ? 1 : 0)
 
 /* Value is the number of bytes of arguments automatically
    popped when returning from a subroutine call.
@@ -1844,9 +1849,9 @@
    is also used as the pic register in ELF.  So for now, don't allow more than
    3 registers to be passed in registers.  */
 
-#define REGPARM_MAX (TARGET_64BIT ? 6 : 3)
+#define REGPARM_MAX (TARGET_64BIT ? (TARGET_64BIT_MS_ABI ? 4 : 6) : 3)
 
-#define SSE_REGPARM_MAX (TARGET_64BIT ? 8 : (TARGET_SSE ? 3 : 0))
+#define SSE_REGPARM_MAX (TARGET_64BIT ? (TARGET_64BIT_MS_ABI ? 4 : 8) : (TARGET_SSE ? 3 : 0))
 
 #define MMX_REGPARM_MAX (TARGET_64BIT ? 0 : (TARGET_MMX ? 3 : 0))
 
diff -ubNr -X ../../excl.txt gcc/config/i386/i386.md ../../gcc/gcc/config/i386/i386.md
--- gcc/config/i386/i386.md	2007-03-12 15:33:13.701519000 +0100
+++ ../../gcc/gcc/config/i386/i386.md	2007-03-13 10:54:33.597015500 +0100
@@ -2065,7 +2065,7 @@
 
     default:
       gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
-      if (get_attr_mode (insn) == MODE_SI)
+      if (get_attr_mode (insn) == MODE_SI && !TARGET_64BIT_MS_ABI)
 	return "mov{l}\t{%k1, %k0|%k0, %k1}";
       else if (which_alternative == 2)
 	return "movabs{q}\t{%1, %0|%0, %1}";
@@ -19712,13 +19712,36 @@
 			   operands[1]));
   else
 #endif
-    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode,
+    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (Pmode,
 							    operands[1])));
 
   emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
   DONE;
 })
 
+(define_expand "allocate_stack64"
+  [(parallel [(set (match_operand:DI 0 "register_operand" "=r")
+		   (minus:SI (reg:DI SP_REG)
+			     (match_operand:DI 1 "general_operand" "")))
+	      (clobber (reg:CC FLAGS_REG))])
+   (parallel [(set (reg:DI SP_REG)
+		   (minus:DI (reg:DI SP_REG) (match_dup 1)))
+	      (clobber (reg:CC FLAGS_REG))])]
+  "TARGET_STACK_PROBE"
+{
+#ifdef CHECK_STACK_LIMIT
+  if (GET_CODE (operands[1]) == CONST_INT
+      && INTVAL (operands[1]) < CHECK_STACK_LIMIT)
+    emit_insn (gen_subdi3 (stack_pointer_rtx, stack_pointer_rtx,
+			   operands[1]));
+  else 
+#endif
+    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (DImode,
+							    operands[1])));
+  emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
+  DONE;
+})
+
 (define_expand "builtin_setjmp_receiver"
   [(label_ref (match_operand 0 "" ""))]
   "!TARGET_64BIT && flag_pic"
diff -ubNr -X ../../excl.txt gcc/config/i386/i386.opt ../../gcc/gcc/config/i386/i386.opt
--- gcc/config/i386/i386.opt	2007-03-14 09:11:01.867654500 +0100
+++ ../../gcc/gcc/config/i386/i386.opt	2007-03-14 08:25:39.335475100 +0100
@@ -263,3 +263,6 @@
 
 ;; Support Athlon 3Dnow builtins
 Mask(3DNOW_A)
+
+;; Support MS64 ABI
+Mask(64BIT_MS_ABI)
diff -ubNr -X ../../excl.txt gcc/config/i386/mingw32.h ../../gcc/gcc/config/i386/mingw32.h
--- gcc/config/i386/mingw32.h	2007-03-13 17:17:36.322891200 +0100
+++ ../../gcc/gcc/config/i386/mingw32.h	2007-02-28 14:51:30.160813200 +0100
@@ -21,7 +21,11 @@
 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 @@
       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 @@
 
 /* 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
@@ -109,6 +129,9 @@
 #undef WINT_TYPE
 #define WINT_TYPE "short unsigned int"
 
+#undef POINTER_SIZE
+#define POINTER_SIZE (TARGET_64BIT ? 64 : 32)
+
 /* mingw32 uses the  -mthreads option to enable thread support.  */
 #undef GOMP_SELF_SPECS
 #define GOMP_SELF_SPECS "%{fopenmp: -mthreads}"
diff -ubNr -X ../../excl.txt gcc/config/iq2000/iq2000.h ../../gcc/gcc/config/iq2000/iq2000.h
--- gcc/config/iq2000/iq2000.h	2007-03-13 17:18:02.900312600 +0100
+++ ../../gcc/gcc/config/iq2000/iq2000.h	2007-02-28 15:21:35.064810000 +0100
@@ -375,7 +375,7 @@
 
 #define REG_PARM_STACK_SPACE(FNDECL) 0
 
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
 
diff -ubNr -X ../../excl.txt gcc/config/mips/mips.h ../../gcc/gcc/config/mips/mips.h
--- gcc/config/mips/mips.h	2007-03-13 17:18:45.851184500 +0100
+++ ../../gcc/gcc/config/mips/mips.h	2007-03-12 10:55:30.049481100 +0100
@@ -1807,7 +1807,7 @@
    If `ACCUMULATE_OUTGOING_ARGS' is also defined, the only effect
    of this macro is to determine whether the space is included in
    `current_function_outgoing_args_size'.  */
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 #define STACK_BOUNDARY (TARGET_NEWABI ? 128 : 64)
 \f
diff -ubNr -X ../../excl.txt gcc/config/mn10300/mn10300.h ../../gcc/gcc/config/mn10300/mn10300.h
--- gcc/config/mn10300/mn10300.h	2007-03-13 17:18:06.765761900 +0100
+++ ../../gcc/gcc/config/mn10300/mn10300.h	2007-02-28 14:53:10.904457500 +0100
@@ -529,7 +529,7 @@
 /* We use d0/d1 for passing parameters, so allocate 8 bytes of space
    for a register flushback area.  */
 #define REG_PARM_STACK_SPACE(DECL) 8
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 #define ACCUMULATE_OUTGOING_ARGS 1
 
 /* So we can allocate space for return pointers once for the function
diff -ubNr -X ../../excl.txt gcc/config/mt/mt.h ../../gcc/gcc/config/mt/mt.h
--- gcc/config/mt/mt.h	2007-03-13 17:18:04.602709600 +0100
+++ ../../gcc/gcc/config/mt/mt.h	2007-02-28 14:53:28.780161500 +0100
@@ -533,7 +533,7 @@
 
 /* Define this if it is the responsibility of the caller to
    allocate the area reserved for arguments passed in registers.  */
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 /* The number of register assigned to holding function arguments.  */
 #define MT_NUM_ARG_REGS        4
diff -ubNr -X ../../excl.txt gcc/config/pa/pa.h ../../gcc/gcc/config/pa/pa.h
--- gcc/config/pa/pa.h	2007-03-13 17:18:41.414893900 +0100
+++ ../../gcc/gcc/config/pa/pa.h	2007-02-28 15:21:53.160108000 +0100
@@ -602,7 +602,7 @@
 
 /* Define this if the above stack space is to be considered part of the
    space allocated by the caller.  */
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 /* Keep the stack pointer constant throughout the function.
    This is both an optimization and a necessity: longjmp
diff -ubNr -X ../../excl.txt gcc/config/rs6000/rs6000.h ../../gcc/gcc/config/rs6000/rs6000.h
--- gcc/config/rs6000/rs6000.h	2007-03-13 17:18:20.575343700 +0100
+++ ../../gcc/gcc/config/rs6000/rs6000.h	2007-02-28 15:21:44.798418000 +0100
@@ -1277,7 +1277,7 @@
 
 /* Define this if the above stack space is to be considered part of the
    space allocated by the caller.  */
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 /* This is the difference between the logical top of stack and the actual sp.
 
diff -ubNr -X ../../excl.txt gcc/config/score/score.h ../../gcc/gcc/config/score/score.h
--- gcc/config/score/score.h	2007-03-13 17:18:28.556661100 +0100
+++ ../../gcc/gcc/config/score/score.h	2007-02-28 14:54:34.834041500 +0100
@@ -534,7 +534,7 @@
    If `ACCUMULATE_OUTGOING_ARGS' is also defined, the only effect
    of this macro is to determine whether the space is included in
    `current_function_outgoing_args_size'.  */
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 #define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
 
diff -ubNr -X ../../excl.txt gcc/config/spu/spu.h ../../gcc/gcc/config/spu/spu.h
--- gcc/config/spu/spu.h	2007-03-13 17:17:16.615142400 +0100
+++ ../../gcc/gcc/config/spu/spu.h	2007-02-28 15:21:03.340458000 +0100
@@ -337,7 +337,7 @@
 
 #define REG_PARM_STACK_SPACE(FNDECL) 0
 
-#define OUTGOING_REG_PARM_STACK_SPACE 
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) (0)
 
diff -ubNr -X ../../excl.txt gcc/config/v850/v850.h ../../gcc/gcc/config/v850/v850.h
--- gcc/config/v850/v850.h	2007-03-13 17:18:59.911121300 +0100
+++ ../../gcc/gcc/config/v850/v850.h	2007-02-28 14:55:11.945925500 +0100
@@ -626,7 +626,7 @@
 
 /* Define this if the above stack space is to be considered part of the
    space allocated by the caller.  */
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 /* 1 if N is a possible register number for function argument passing.  */
 
diff -ubNr -X ../../excl.txt gcc/config.build ../../gcc/gcc/config.build
--- gcc/config.build	2007-03-12 15:36:49.301038500 +0100
+++ ../../gcc/gcc/config.build	2007-01-10 11:35:30.000000000 +0100
@@ -77,7 +77,7 @@
     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
     ;;
diff -ubNr -X ../../excl.txt gcc/config.gcc ../../gcc/gcc/config.gcc
--- gcc/config.gcc	2007-03-12 15:36:41.760496500 +0100
+++ ../../gcc/gcc/config.gcc	2007-03-13 10:54:45.193544300 +0100
@@ -1343,7 +1343,7 @@
 		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"
diff -ubNr -X ../../excl.txt gcc/config.host ../../gcc/gcc/config.host
--- gcc/config.host	2007-03-12 15:36:42.591658500 +0100
+++ ../../gcc/gcc/config.host	2007-03-02 08:12:17.372895800 +0100
@@ -168,7 +168,7 @@
     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
diff -ubNr -X ../../excl.txt gcc/doc/tm.texi ../../gcc/gcc/doc/tm.texi
--- gcc/doc/tm.texi	2007-03-12 11:48:46.727669400 +0100
+++ ../../gcc/gcc/doc/tm.texi	2007-03-12 10:52:12.499986600 +0100
@@ -3730,7 +3730,7 @@
 @c something, not sure if it looks good.  --mew 10feb93
 
 @defmac OUTGOING_REG_PARM_STACK_SPACE
-Define this if it is the responsibility of the caller to allocate the area
+Define this to one if it is the responsibility of the caller to allocate the area
 reserved for arguments passed in registers.
 
 If @code{ACCUMULATE_OUTGOING_ARGS} is defined, this macro controls
@@ -9719,6 +9719,18 @@
 @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
diff -ubNr -X ../../excl.txt gcc/explow.c ../../gcc/gcc/explow.c
--- gcc/explow.c	2007-03-13 17:16:26.086209000 +0100
+++ ../../gcc/gcc/explow.c	2007-02-28 14:34:11.717512200 +0100
@@ -1240,13 +1240,25 @@
 	 be valid for the operand.  For operand 1, convert to the
 	 proper mode and validate.  */
       if (mode == VOIDmode)
+        {
+#if defined(HAVE_allocate_stack64) && defined(TARGET_64BIT)
+	      mode = insn_data[((!HAVE_allocate_stack64 || !TARGET_64BIT) ? (int) CODE_FOR_allocate_stack : (int) CODE_FOR_allocate_stack64)].operand[1].mode;
+#else
 	mode = insn_data[(int) CODE_FOR_allocate_stack].operand[1].mode;
+#endif
+        }
 
+#if defined(HAVE_allocate_stack64) && defined(TARGET_64BIT)
+      pred = insn_data[((!HAVE_allocate_stack64 || !TARGET_64BIT) ? (int) CODE_FOR_allocate_stack : (int) CODE_FOR_allocate_stack64)].operand[1].predicate;
+#else
       pred = insn_data[(int) CODE_FOR_allocate_stack].operand[1].predicate;
+#endif
       if (pred && ! ((*pred) (size, mode)))
 	size = copy_to_mode_reg (mode, convert_to_mode (mode, size, 1));
 
-      emit_insn (gen_allocate_stack (target, size));
+      if(mode == DImode)
+      	emit_insn (gen_allocate_stack64(target,size));
+      else emit_insn (gen_allocate_stack (target, size));
     }
   else
 #endif
diff -ubNr -X ../../excl.txt gcc/expr.c ../../gcc/gcc/expr.c
--- gcc/expr.c	2007-03-13 17:14:46.598320900 +0100
+++ ../../gcc/gcc/expr.c	2007-03-02 14:50:25.697905000 +0100
@@ -54,6 +54,10 @@
 #include "target.h"
 #include "timevar.h"
 
+#ifndef OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 0
+#endif
+
 /* Decide whether a function's arguments should be processed
    from first to last or from last to first.
 
@@ -1237,8 +1241,8 @@
 
   /* If registers go on the stack anyway, any argument is sure to clobber
      an outgoing argument.  */
-#if defined (REG_PARM_STACK_SPACE) && defined (OUTGOING_REG_PARM_STACK_SPACE)
-  {
+#if defined (REG_PARM_STACK_SPACE)
+  if(OUTGOING_REG_PARM_STACK_SPACE) {
     tree fn = emit_block_move_libcall_fn (false);
     (void) fn;
     if (REG_PARM_STACK_SPACE (fn) != 0)
diff -ubNr -X ../../excl.txt gcc/function.c ../../gcc/gcc/function.c
--- gcc/function.c	2007-03-13 17:16:06.399668000 +0100
+++ ../../gcc/gcc/function.c	2007-03-07 12:10:14.732360700 +0100
@@ -65,6 +65,11 @@
 #include "predict.h"
 #include "vecprim.h"
 
+#ifndef OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 0
+#endif
+
+
 #ifndef LOCAL_ALIGNMENT
 #define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
 #endif
@@ -1211,12 +1216,11 @@
    `current_function_outgoing_args_size'.  Nevertheless, we must allow
    for it when allocating stack dynamic objects.  */
 
-#if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
+#if defined(REG_PARM_STACK_SPACE)
 #define STACK_DYNAMIC_OFFSET(FNDECL)	\
 ((ACCUMULATE_OUTGOING_ARGS						      \
-  ? (current_function_outgoing_args_size + REG_PARM_STACK_SPACE (FNDECL)) : 0)\
+  ? (current_function_outgoing_args_size + (OUTGOING_REG_PARM_STACK_SPACE ? 0 : REG_PARM_STACK_SPACE (FNDECL))) : 0)\
  + (STACK_POINTER_OFFSET))						      \
-
 #else
 #define STACK_DYNAMIC_OFFSET(FNDECL)	\
 ((ACCUMULATE_OUTGOING_ARGS ? current_function_outgoing_args_size : 0)	      \
diff -ubNr -X ../../excl.txt gcc/unwind-generic.h ../../gcc/gcc/unwind-generic.h
--- gcc/unwind-generic.h	2007-03-13 17:16:54.654724500 +0100
+++ ../../gcc/gcc/unwind-generic.h	2007-03-01 15:33:23.362035800 +0100
@@ -252,8 +252,13 @@
   typedef long long _sleb128_t;
   typedef unsigned long long _uleb128_t;
 #else
+#ifdef _WIN64
+  typedef int _sleb128_t __attribute__ ((mode (TI)));
+  typedef unsigned int _uleb128_t __attribute__ ((mode (TI)));
+#else
   #error "long long data type is needed to define _sleb128_t"
 #endif
+#endif
 #else
   typedef long _sleb128_t;
   typedef unsigned long _uleb128_t;
=

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PATCH: x86_64-pc-mingw32 target for gcc
  2007-03-14 14:27 PATCH: x86_64-pc-mingw32 target for gcc Kai Tietz
@ 2007-03-20 19:42 ` Richard Henderson
  2007-03-21 10:35   ` Kai Tietz
  2007-03-21 12:13   ` Kai Tietz
  2007-03-22  0:33 ` revised x86_64-pc-mingw32 patch Richard Henderson
  1 sibling, 2 replies; 33+ messages in thread
From: Richard Henderson @ 2007-03-20 19:42 UTC (permalink / raw)
  To: Kai Tietz; +Cc: gcc-patches, MinGW-dvlpr

On Wed, Mar 14, 2007 at 02:50:00PM +0100, Kai Tietz wrote:
> I deceided to pack even the the new pragma commands "push_macro" and 
> "pop_macro", because they are linked and the approval of a dependent patch 
> takes a bit long.

No, you need to keep these patches separate.  There's no way
I'll approve them all as a unit.

> +typedef struct sPragmaMacro GTY(())
> +{
> +	char *name;
> +	char *value;
> +	struct sPragmaMacro *prev;
> +} sPragmaMacro;
> +static GTY(()) struct sPragmaMacro *theMacroList = NULL;

This does not follow the gnu coding conventions for identifiers.

> +  if (token == CPP_CLOSE_PAREN)
> +    {
> +	  /* Silently ignore */
> +	  id = 0;
> +    }

Bad indentation.  Lots of it in here.  Also beware of braces
with one dependant statement.

> +	  else if (pragma_lex (&x) != CPP_EOF)
> +	    {
> +		  warning (OPT_Wpragmas, "junk at end of %<#pragma push_macro%>");
> +		  while(pragma_lex (&x) != CPP_EOF)
> +		    ;
> +	    }

Why the loop?  None of the other pragma handers use one.

> +		  val = cpp_macro_definition (dummy, cpp_lookup (dummy, (const unsigned char *)macroname, strlen (macroname)));

TREE_STRING_LENGTH instead of strlen on macroname.

> +			  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);

Eh?  Can't you use cpp_define and cpp_undef, rather than
cpp_push_buffer nonsense?

> +#ifndef OUTGOING_REG_PARM_STACK_SPACE
> +#define OUTGOING_REG_PARM_STACK_SPACE 0
> +#endif

This belongs in defaults.h.

> +  if (!OUTGOING_REG_PARM_STACK_SPACE && reg_parm_stack_space > 0 && PUSH_ARGS)

Wrap long lines.

> -#ifndef OUTGOING_REG_PARM_STACK_SPACE
> -	      rtx push_size = GEN_INT (reg_parm_stack_space
> -				       + adjusted_args_size.constant);
> -#else
> -	      rtx push_size = GEN_INT (adjusted_args_size.constant);
> -#endif
> +	      rtx push_size = (!OUTGOING_REG_PARM_STACK_SPACE ? (GEN_INT (reg_parm_stack_space
> +				       + adjusted_args_size.constant)) : (GEN_INT (adjusted_args_size.constant)));

Long lines.  This could be better written as

	rtx push_size = GEN_INT (adjusted_args_size.constant
				 + (OUTGOING_REG_PARM_STACK_SPACE ? 0
				    : reg_parm_stack_space));

>  #define DBX_REGISTER_NUMBER(n) (write_symbols == DWARF2_DEBUG   \
> -                                ? svr4_dbx_register_map[n]      \
> -                                : dbx_register_map[n])
> +                                ? (TARGET_64BIT ? dbx64_register_map[n] : svr4_dbx_register_map[n]) \
> +                                : (TARGET_64BIT ? dbx64_register_map[n] : dbx_register_map[n]))

Long lines.

> -#define SIZE_TYPE "unsigned int"
> -#define PTRDIFF_TYPE "int"
> +#define SIZE_TYPE (TARGET_64BIT ? (TARGET_64BIT_MS_ABI ? "long long unsigned int" : "long unsigned int") : "unsigned int")

Why does mingw size_type have to depend on TARGET_64BIT_MS_ABI?
Why wouldn't you define it as "unsigned long long" all the time
for 64-bit?  This seems a point of unnecessary confusion.

Similarly PTRDIFF_TYPE.

> +	pushq  %rdx		/* save temp */

Surely you can find a call-clobbered register to use,
and don't need to save anything.  Perhaps r10?

> +	movq   %rsp,%rdx	/* get sp */
> +	addq   $0x10,%rdx	/* and point to return addr */

	leaq	0x10(%rsp), %rdx

> +	orq    $0x0,(%rdx)   		/* probe there */

Using orl would be smaller, and just as effective.

> -	ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
> +	ix86_cmodel = (TARGET_64BIT_MS_ABI ? (flag_pic ? CM_MEDIUM_PIC : CM_MEDIUM) : (flag_pic ? CM_SMALL_PIC : CM_SMALL));

Long lines, and I *really* don't like nested ?: when it can be avoided.

	if (TARGET_64BIT_MS_ABI)
	  {
	    ix86_cmodel = CM_SMALL_PIC;
	    flag_pic = 1;
	  }
	else
	  ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;

And I think we should discuss the small vs medium thing more; from the
discussion, I think the above will probably work for you.

> -  if (TARGET_64BIT)
> +  if (TARGET_64BIT && !TARGET_64BIT_MS_ABI)
>      {
>        warning (OPT_Wattributes, "%qs attribute ignored",

I don't see any reference to stdcall and other such markers in the
Win64 documentation.  Are they supposed to be accepted and discarded
without comments?  Because I think quite a lot of your changes to 
make them be "handled" in some way is wrong.

>        /* Use register calling convention for local functions when possible.  */
> -      if (!TARGET_64BIT && !user_convention && decl
> +      if ((!TARGET_64BIT || TARGET_64BIT_MS_ABI) && !user_convention && decl

TARGET_64BIT_MS_ABI already uses a register calling convention.
I don't see the point of this change at all.

>    /* Lose any fake structure return argument if it is passed on the stack.  */
>    if (aggregate_value_p (TREE_TYPE (funtype), fundecl)
> -      && !TARGET_64BIT
> +      && (!TARGET_64BIT || TARGET_64BIT_MS_ABI)
>        && !KEEP_AGGREGATE_RETURN_POINTER)

Likewise.

> +  const int *x86_64_int_parameter_registers_ptr;

Please use a more sensible name for this, like "parameter_regs".
As is, one expects is to be a pointer to x86_64_int_parameter_registers,
which isn't (necessarily) true.

> @@ -3339,9 +3358,42 @@
>  
>  static rtx
>  gen_reg_or_parallel (enum machine_mode mode, enum machine_mode orig_mode,
> -		     unsigned int regno)
> +		     unsigned int regno,const int **intreg)

You've got the calling convention code completely wrong.

You shouldn't be reusing construct_container, or any of the other
x86_64 unix routines.  The ms conventions are *vastly* different,
and simpler.

> @@ -19630,7 +19780,10 @@
>        /* Put the this parameter into %eax.  */
>        xops[0] = this;
>        xops[1] = this_reg = gen_rtx_REG (Pmode, 0);
> +      if(Pmode==SImode)
>        output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
> +      else
> +        output_asm_insn ("mov{q}\t{%0, %1|%1, %0}", xops);
>      }

This is surely wrong, since x86_this_parameter should
always return a register, and this path should never
be taken.

>    else
>      this_reg = NULL_RTX;
> @@ -19667,7 +19820,7 @@
>  	  if (lookup_attribute ("fastcall",
>  	      TYPE_ATTRIBUTES (TREE_TYPE (function))))
>  	    tmp_regno = 0 /* EAX */;
> -	  tmp = gen_rtx_REG (SImode, tmp_regno);
> +	  tmp = gen_rtx_REG ((TARGET_64BIT ? DImode : SImode), tmp_regno);

Likewise.

>  	}
>  
>        xops[0] = gen_rtx_MEM (Pmode, this_reg);
> @@ -19735,7 +19888,7 @@
>  	else
>  #endif /* TARGET_MACHO */
>  	{
> -	  tmp = gen_rtx_REG (SImode, 2 /* ECX */);
> +	  tmp = gen_rtx_REG ((TARGET_64BIT ? DImode : SImode), 2 /* ECX */);

Note that this code is already protected by TARGET_64BIT above.

> -#define LONG_TYPE_SIZE BITS_PER_WORD
> +#define LONG_TYPE_SIZE (TARGET_64BIT_MS_ABI ? 32 : BITS_PER_WORD)

This should be changed in cygming.h, not in i386.h.

>        gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
> -      if (get_attr_mode (insn) == MODE_SI)
> +      if (get_attr_mode (insn) == MODE_SI && !TARGET_64BIT_MS_ABI)
>  	return "mov{l}\t{%k1, %k0|%k0, %k1}";

Definitely wrong.  The point here is to use "movl $N, %eax" to 
load the 32-bit constant N, reserving movabsq for true 64-bit 
constants.

>  #endif
> -    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode,
> +    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (Pmode,
>  							    operands[1])));

Good, but not quite far enough.

> +(define_expand "allocate_stack64"

Bad.  This would never be used.

(define_expand "allocate_stack"
  [(match_operand 0 "register_operand" "")
   (match_operand 1 "general_operand" "")]
  "TARGET_STACK_PROBE"
{
#ifdef CHECK_STACK_LIMIT
  if (CONST_INT_P (operands[1])
      && INTVAL (operands[1]) < CHECK_STACK_LIMIT)
    {
      rtx x;
      x = expand_simple_binop (Pmode, MINUS, stack_pointer_rtx,
			       operands[1], stack_pointer_rtx,
			       1, OPTAB_DIRECT);
      gcc_assert (x == stack_pointer_rtx);
    }
  else
#endif
    emit_insn (gen_allocate_stack_worker (force_reg (Pmode, operands[1])));

  emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
  DONE;
})

You also need to define STACK_SIZE_MODE as Pmode.  This can be done
in i386.h.

> +;; Support MS64 ABI
> +Mask(64BIT_MS_ABI)

There is no reason why this needs to be a bit in target_flags.
In fact, those are kinda rare, so we should *not* use one.

For the moment, I suggest simply using

#define TARGET_64BIT_MS_ABI  0

in i386.h, and

#undef TARGET_64BIT_MS_ABI
#define TARGET_64BIT_MS_ABI  TARGET_64BIT

in cygmingw.h.

> +	  if(TARGET_64BIT_MS_ABI) {					\
> +	  } else {							\

GNU coding standards.

> +#undef POINTER_SIZE
> +#define POINTER_SIZE (TARGET_64BIT ? 64 : 32)

This is identical to the default definition, and unneeded.

> +#ifdef _WIN64
> +  typedef int _sleb128_t __attribute__ ((mode (TI)));
> +  typedef unsigned int _uleb128_t __attribute__ ((mode (TI)));

This is incorrect.  You don't need a 128-bit type here.


r~

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PATCH: x86_64-pc-mingw32 target for gcc
  2007-03-20 19:42 ` Richard Henderson
@ 2007-03-21 10:35   ` Kai Tietz
  2007-03-21 18:06     ` Richard Henderson
  2007-03-21 12:13   ` Kai Tietz
  1 sibling, 1 reply; 33+ messages in thread
From: Kai Tietz @ 2007-03-21 10:35 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, MinGW-dvlpr

Richard Henderson <rth@redhat.com> wrote on 20.03.2007 20:23:50:

> No, you need to keep these patches separate.  There's no way
> I'll approve them all as a unit.

It is allready seperated.

> This does not follow the gnu coding conventions for identifiers.

In the updated patch this names are changed.

> Bad indentation.  Lots of it in here.  Also beware of braces
> with one dependant statement.

I corrected this in the updated patch allready, too.

> Why the loop?  None of the other pragma handers use one.

> Eh?  Can't you use cpp_define and cpp_undef, rather than
> cpp_push_buffer nonsense?
I tried, but the do not worked as expected, there for I used the brute 
force variant. The fixed array size I replaced in the updated patch 
allready to use alloca for buffer size.

> > +#ifndef OUTGOING_REG_PARM_STACK_SPACE
> > +#define OUTGOING_REG_PARM_STACK_SPACE 0
> > +#endif
>
> This belongs in defaults.h.

This is true.
 
> > -#define SIZE_TYPE "unsigned int"
> > -#define PTRDIFF_TYPE "int"
> > +#define SIZE_TYPE (TARGET_64BIT ? (TARGET_64BIT_MS_ABI ? "long 
> long unsigned int" : "long unsigned int") : "unsigned int")
>
> Why does mingw size_type have to depend on TARGET_64BIT_MS_ABI?
> Why wouldn't you define it as "unsigned long long" all the time
> for 64-bit?  This seems a point of unnecessary confusion.
Because the type is different to TARGET_64BIT. Linux uses integer type of 
long for 8 byte size, but for MS the long type remains a 4 byte integer. 
The type for x86 code uses the int type for pointer size representation. 
May you are compiling a cross where headers are shared ?
> Similarly PTRDIFF_TYPE.
Same as above.

> > +   pushq  %rdx      /* save temp */
> 
> Surely you can find a call-clobbered register to use,
> and don't need to save anything.  Perhaps r10?
> 
> > +   movq   %rsp,%rdx   /* get sp */
> > +   addq   $0x10,%rdx   /* and point to return addr */
> 
>    leaq   0x10(%rsp), %rdx
> 
> > +   orq    $0x0,(%rdx)         /* probe there */
> 
> Using orl would be smaller, and just as effective.

Yes, the cygwin alloca implementation is just a first implementation and 
can be optimized for sure. The most important thing of this rough 
implementation is, that the incoming register as argument is rcx, not rax, 
as for x86. Feel free to optimize it.

> > -   ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
> > +   ix86_cmodel = (TARGET_64BIT_MS_ABI ? (flag_pic ? CM_MEDIUM_PIC
> : CM_MEDIUM) : (flag_pic ? CM_SMALL_PIC : CM_SMALL));
> 
> Long lines, and I *really* don't like nested ?: when it can be avoided.
> 
>    if (TARGET_64BIT_MS_ABI)
>      {
>        ix86_cmodel = CM_SMALL_PIC;
>        flag_pic = 1;
>      }
>    else
>      ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
> 
> And I think we should discuss the small vs medium thing more; from the
> discussion, I think the above will probably work for you.

The small model or even the medium PIC models, have currently a lack by 
using for a constant address push defined within near objects the wrong 
address memonics, because the code (at least for dll's) may needs to be 
rebased.
E.g: gcc produces currently direct address moves as "movl LC0, si", which 
isn't rebase save. There are two diffent solutions for that, first is 
using a large model for it - so it gets movq LC0, rsi -, or using rip 
based addressing - as "lea (LCO-.+rip), rsi".

> > -  if (TARGET_64BIT)
> > +  if (TARGET_64BIT && !TARGET_64BIT_MS_ABI)
> >      {
> >        warning (OPT_Wattributes, "%qs attribute ignored",
> 
> I don't see any reference to stdcall and other such markers in the
> Win64 documentation.  Are they supposed to be accepted and discarded
> without comments?  Because I think quite a lot of your changes to 
> make them be "handled" in some way is wrong.

True but as the fastcall issue is equivalent to standard calling 
convention it doesn't hurt. Sure in next update, the fastcall, have to be 
removed from support for this ABI.

> >        /* Use register calling convention for local functions when
> possible.  */
> > -      if (!TARGET_64BIT && !user_convention && decl
> > +      if ((!TARGET_64BIT || TARGET_64BIT_MS_ABI) && !
> user_convention && decl
> 
> TARGET_64BIT_MS_ABI already uses a register calling convention.
> I don't see the point of this change at all.
Same as above. I prevent to enter the linux part of calling conventions 
for this case. A simple short-cut.

> >    /* Lose any fake structure return argument if it is passed on 
> the stack.  */
> >    if (aggregate_value_p (TREE_TYPE (funtype), fundecl)
> > -      && !TARGET_64BIT
> > +      && (!TARGET_64BIT || TARGET_64BIT_MS_ABI)
> >        && !KEEP_AGGREGATE_RETURN_POINTER)
> 
Likewise.
 
> >  static rtx
> >  gen_reg_or_parallel (enum machine_mode mode, enum machine_mode 
orig_mode,
> > -           unsigned int regno)
> > +           unsigned int regno,const int **intreg)
> 
> You've got the calling convention code completely wrong.
As I see from my native gcc, things with calling convention are doing even 
for floating points very well. ?

> You shouldn't be reusing construct_container, or any of the other
> x86_64 unix routines.  The ms conventions are *vastly* different,
> and simpler.
No quite true AFAIK.

> > @@ -19630,7 +19780,10 @@
> >        /* Put the this parameter into %eax.  */
> >        xops[0] = this;
> >        xops[1] = this_reg = gen_rtx_REG (Pmode, 0);
> > +      if(Pmode==SImode)
> >        output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
> > +      else
> > +        output_asm_insn ("mov{q}\t{%0, %1|%1, %0}", xops);
> >      }
> 
> This is surely wrong, since x86_this_parameter should
> always return a register, and this path should never
> be taken.

Yes, as far as I see, this path isn't taken at all. This change is 
irrelevant.

> >    else
> >      this_reg = NULL_RTX;
> > @@ -19667,7 +19820,7 @@
> >       if (lookup_attribute ("fastcall",
> >           TYPE_ATTRIBUTES (TREE_TYPE (function))))
> >         tmp_regno = 0 /* EAX */;
> > -     tmp = gen_rtx_REG (SImode, tmp_regno);
> > +     tmp = gen_rtx_REG ((TARGET_64BIT ? DImode : SImode), tmp_regno);
> 
Likewise.
 
> >     }
> > 
> >        xops[0] = gen_rtx_MEM (Pmode, this_reg);
> > @@ -19735,7 +19888,7 @@
> >     else
> >  #endif /* TARGET_MACHO */
> >     {
> > -     tmp = gen_rtx_REG (SImode, 2 /* ECX */);
> > +     tmp = gen_rtx_REG ((TARGET_64BIT ? DImode : SImode), 2 /* ECX 
*/);
> 
> Note that this code is already protected by TARGET_64BIT above.

I agree.

> > -#define LONG_TYPE_SIZE BITS_PER_WORD
> > +#define LONG_TYPE_SIZE (TARGET_64BIT_MS_ABI ? 32 : BITS_PER_WORD)
> 
> This should be changed in cygming.h, not in i386.h.
> 
> >        gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P 
(operands[1]));
> > -      if (get_attr_mode (insn) == MODE_SI)
> > +      if (get_attr_mode (insn) == MODE_SI && !TARGET_64BIT_MS_ABI)
> >     return "mov{l}\t{%k1, %k0|%k0, %k1}";
> 
> Definitely wrong.  The point here is to use "movl $N, %eax" to 
> load the 32-bit constant N, reserving movabsq for true 64-bit 
> constants.
See above about pic code.

> >  #endif
> > -    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode,
> > +    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (Pmode,
> >                           operands[1])));
> 
> Good, but not quite far enough.
> 
> > +(define_expand "allocate_stack64"
> 
> Bad.  This would never be used.
> 
> (define_expand "allocate_stack"
>   [(match_operand 0 "register_operand" "")
>    (match_operand 1 "general_operand" "")]
>   "TARGET_STACK_PROBE"
> {
> #ifdef CHECK_STACK_LIMIT
>   if (CONST_INT_P (operands[1])
>       && INTVAL (operands[1]) < CHECK_STACK_LIMIT)
>     {
>       rtx x;
>       x = expand_simple_binop (Pmode, MINUS, stack_pointer_rtx,
>                 operands[1], stack_pointer_rtx,
>                 1, OPTAB_DIRECT);
>       gcc_assert (x == stack_pointer_rtx);
>     }
>   else
> #endif
>     emit_insn (gen_allocate_stack_worker (force_reg (Pmode, 
operands[1])));
> 
>   emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
>   DONE;
> })
> 
> You also need to define STACK_SIZE_MODE as Pmode.  This can be done
> in i386.h.
Why ? It is defined by default in expr.h to word_mode, which fits fine.

> > +;; Support MS64 ABI
> > +Mask(64BIT_MS_ABI)
> 
> There is no reason why this needs to be a bit in target_flags.
> In fact, those are kinda rare, so we should *not* use one.
> 
> For the moment, I suggest simply using
> 
> #define TARGET_64BIT_MS_ABI  0
> 
> in i386.h, and
> 
> #undef TARGET_64BIT_MS_ABI
> #define TARGET_64BIT_MS_ABI  TARGET_64BIT
> 
> in cygmingw.h.
> 
> > +     if(TARGET_64BIT_MS_ABI) {               \
> > +     } else {                     \
May this is a good solution for the problem, because the other idea is to 
make a code model out of this ABI.

> > +#undef POINTER_SIZE
> > +#define POINTER_SIZE (TARGET_64BIT ? 64 : 32)
No, it is defined by default to BITS_PER_WORD, which is in fact a word of 
type long and not a type of long long as needed.

> This is identical to the default definition, and unneeded.
> 
> > +#ifdef _WIN64
> > +  typedef int _sleb128_t __attribute__ ((mode (TI)));
> > +  typedef unsigned int _uleb128_t __attribute__ ((mode (TI)));
> 
> This is incorrect.  You don't need a 128-bit type here.
You are right, a long long (8-byte value) should be enough.

I got the suggestion to pack the new pragma commands within libcpp, which 
makes from my opionion sense too. What do you think about that ?

Thank you for your reviewing and your hard work.
(Sorry, this trailer I am recommented to use it)
Cheers,
 i.A. Kai Tietz

------------------------------------------------------------------------------------------
  OneVision Software Entwicklungs GmbH & Co. KG
  Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg
  Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com
  Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050
  Handelsregister: HRA 6744, Amtsgericht Regensburg
  Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH
  Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg
  Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: 
Ulrike Döhler, Manuela Kluger


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PATCH: x86_64-pc-mingw32 target for gcc
  2007-03-20 19:42 ` Richard Henderson
  2007-03-21 10:35   ` Kai Tietz
@ 2007-03-21 12:13   ` Kai Tietz
  2007-03-21 17:04     ` Richard Henderson
  1 sibling, 1 reply; 33+ messages in thread
From: Kai Tietz @ 2007-03-21 12:13 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, MinGW-dvlpr

Richard Henderson <rth@redhat.com> wrote on 20.03.2007 20:23:50:

> > -  if (TARGET_64BIT)
> > +  if (TARGET_64BIT && !TARGET_64BIT_MS_ABI)
> >      {
> >        warning (OPT_Wattributes, "%qs attribute ignored",
> 
> I don't see any reference to stdcall and other such markers in the
> Win64 documentation.  Are they supposed to be accepted and discarded
> without comments?  Because I think quite a lot of your changes to 
> make them be "handled" in some way is wrong.

They are treated. For more information about this, please re-read the MSDN 
about these keywords. Attribute "__fastcall" is ignored but language 
feature. "__stdcall" is needed for all win32 api functions, as for the x86 
version. And of course the __cdecl specifier is known to x86_64 too, as 
for the x86 version. But you are right, that the special treating for 
"__fastcall" is redudant to the x86_64 standard calling convention.
 
> Please use a more sensible name for this, like "parameter_regs".
> As is, one expects is to be a pointer to x86_64_int_parameter_registers,
> which isn't (necessarily) true.
Yes, because it is a local which helds the pointer to 
x86_64_int_parameter_registers (in linux case) or the pointer to 

Regards,
 i.A. Kai Tietz

------------------------------------------------------------------------------------------
  OneVision Software Entwicklungs GmbH & Co. KG
  Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg
  Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com
  Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050
  Handelsregister: HRA 6744, Amtsgericht Regensburg
  Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH
  Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg
  Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: 
Ulrike Döhler, Manuela Kluger


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PATCH: x86_64-pc-mingw32 target for gcc
  2007-03-21 12:13   ` Kai Tietz
@ 2007-03-21 17:04     ` Richard Henderson
  2007-03-21 17:37       ` Kai Tietz
  2007-03-21 18:02       ` Kai Tietz
  0 siblings, 2 replies; 33+ messages in thread
From: Richard Henderson @ 2007-03-21 17:04 UTC (permalink / raw)
  To: Kai Tietz; +Cc: gcc-patches, MinGW-dvlpr

On Wed, Mar 21, 2007 at 12:47:40PM +0100, Kai Tietz wrote:
> They are treated. For more information about this, please re-read the MSDN 
> about these keywords.

I don't see anything in the MSDN that specifies that these keywords
apply to the 64-bit version.  Their language is very 32-bit specific,
which to me implies that they don't apply.

> "__stdcall" is needed for all win32 api functions, as for the x86 
> version.

Huh?  You still call win32 functions from win64?  Curious...



r~

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PATCH: x86_64-pc-mingw32 target for gcc
  2007-03-21 17:04     ` Richard Henderson
@ 2007-03-21 17:37       ` Kai Tietz
  2007-03-21 18:18         ` Richard Henderson
  2007-03-21 18:02       ` Kai Tietz
  1 sibling, 1 reply; 33+ messages in thread
From: Kai Tietz @ 2007-03-21 17:37 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, MinGW-dvlpr

Richard Henderson <rth@redhat.com> wrote on 21.03.2007 16:32:34:

> On Wed, Mar 21, 2007 at 12:47:40PM +0100, Kai Tietz wrote:
> > They are treated. For more information about this, please re-read the 
MSDN 
> > about these keywords.
> 
> I don't see anything in the MSDN that specifies that these keywords
> apply to the 64-bit version.  Their language is very 32-bit specific,
> which to me implies that they don't apply.

Please, read http://msdn2.microsoft.com/de-de/library/zxk0tw93(VS.80).aspx
and may further. Especially the fact that the called function pops the 
stack on return remains even for _WIN64. I build allready a working native 
XP64 version of gcc, and it is that way, otherwise it would end before 
reaching gcc main ;)

> > "__stdcall" is needed for all win32 api functions, as for the x86 
> > version.
> 
> Huh?  You still call win32 functions from win64?  Curious...

Yes, the XP64 & Vista target uses still in most cases the win32 API 
definitions, as to read in MSDN ...

Regards,
 i.A. Kai Tietz

------------------------------------------------------------------------------------------
  OneVision Software Entwicklungs GmbH & Co. KG
  Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg
  Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com
  Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050
  Handelsregister: HRA 6744, Amtsgericht Regensburg
  Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH
  Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg
  Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: 
Ulrike Döhler, Manuela Kluger


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PATCH: x86_64-pc-mingw32 target for gcc
  2007-03-21 17:04     ` Richard Henderson
  2007-03-21 17:37       ` Kai Tietz
@ 2007-03-21 18:02       ` Kai Tietz
  1 sibling, 0 replies; 33+ messages in thread
From: Kai Tietz @ 2007-03-21 18:02 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches, MinGW-dvlpr

Richard Henderson <rth@redhat.com> wrote on 21.03.2007 16:32:34:

> On Wed, Mar 21, 2007 at 12:47:40PM +0100, Kai Tietz wrote:
> > They are treated. For more information about this, please re-read the 
MSDN 
> > about these keywords.

By checking for kernel32.dll for return with stack-adjustment, I see there 
is none 8()
Upps, why it worked ?!?

Sorry for the ignorance, but it seems to be, that these specifiers as 
stdcall, etc. are meaning-less, but need to supported as keyword it self. 
Sorry for blaming you.

Regards,
 i.A. Kai Tietz

------------------------------------------------------------------------------------------
  OneVision Software Entwicklungs GmbH & Co. KG
  Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg
  Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com
  Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050
  Handelsregister: HRA 6744, Amtsgericht Regensburg
  Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH
  Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg
  Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: 
Ulrike Döhler, Manuela Kluger


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PATCH: x86_64-pc-mingw32 target for gcc
  2007-03-21 10:35   ` Kai Tietz
@ 2007-03-21 18:06     ` Richard Henderson
  0 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2007-03-21 18:06 UTC (permalink / raw)
  To: Kai Tietz; +Cc: gcc-patches, MinGW-dvlpr

On Wed, Mar 21, 2007 at 10:20:17AM +0100, Kai Tietz wrote:
> >    if (TARGET_64BIT_MS_ABI)
> >      {
> >        ix86_cmodel = CM_SMALL_PIC;
> >        flag_pic = 1;
> >      }
> >    else
> >      ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
> > 
> > And I think we should discuss the small vs medium thing more; from the
> > discussion, I think the above will probably work for you.
> 
> The small model or even the medium PIC models, have currently a lack by 
> using for a constant address push defined within near objects the wrong 
> address memonics, because the code (at least for dll's) may needs to be 
> rebased.
> E.g: gcc produces currently direct address moves as "movl LC0, si", which 
> isn't rebase save. There are two diffent solutions for that, first is 
> using a large model for it - so it gets movq LC0, rsi -, or using rip 
> based addressing - as "lea (LCO-.+rip), rsi".

Notice that I forced flag_pic to be true.  That will force gcc 
to use rip-relative addressing for these constant addresses.

Please do try to understand what I'm explaining to you.

> > >        /* Use register calling convention for local functions when
> > possible.  */
> > > -      if (!TARGET_64BIT && !user_convention && decl
> > > +      if ((!TARGET_64BIT || TARGET_64BIT_MS_ABI) && !
> > user_convention && decl
> > 
> > TARGET_64BIT_MS_ABI already uses a register calling convention.
> > I don't see the point of this change at all.
> Same as above. I prevent to enter the linux part of calling conventions 
> for this case. A simple short-cut.

No, you didn't.  You *entered* the 32-bit part unnecessarily.
You took a long-cut.

> Likewise.

Likewise.

> As I see from my native gcc, things with calling convention are doing even 
> for floating points very well. ?

I guarantee it's wrong.  Look for instance at example func4 
in the calling convention documentation:

  void func4(__m64 a, __m128 b, struct C c, float d);

You currently generate:

        movq    _c(%rip), %rax
        movq    _b(%rip), %rdx
        movq    $1082130432, %r8
        movq    _a(%rip), %rcx
        movss   LC0(%rip), %xmm2
        movdqa  _b(%rip), %xmm1
        movq    %rax, 32(%rsp)
        movq    _c+8(%rip), %rax
        movq    _a(%rip), %xmm0
        movq    %rax, 40(%rsp)
        movq    _c+16(%rip), %rax
        movq    %rax, 48(%rsp)
        movq    _c+24(%rip), %rax
        movq    %rax, 56(%rsp)
        movq    _c+32(%rip), %rax
        movq    %rax, 64(%rsp)
        call    _func4

All 4 arguments are passed incorrectly.

  (1) a is being passed in rcx and xmm0, instead of just rcx.
  (2) b is being passed (halfway) in rdx, and entirely in xmm1,
      instead it should be passed indirectly as a pointer.
  (3) c is being passed on the stack, instead of indirectly as
      a pointer.
  (4) d is passed in xmm2 instead of xmm3.

I repeat: you should *not* reuse any of the x86-64 unix code.

> > > -      if (get_attr_mode (insn) == MODE_SI)
> > > +      if (get_attr_mode (insn) == MODE_SI && !TARGET_64BIT_MS_ABI)
> > >     return "mov{l}\t{%k1, %k0|%k0, %k1}";
> > 
> > Definitely wrong.  The point here is to use "movl $N, %eax" to 
> > load the 32-bit constant N, reserving movabsq for true 64-bit 
> > constants.
> See above about pic code.

You're still wrong.  The instruction was selected to be SImode,
so therefore an SImode instruction should be used.  

If you think it should be a DImode instruction, then the change
must be to the selection code, and not here.  But I also continue
to beleve that you're wrong about all the pic stuff.

> No, it is defined by default to BITS_PER_WORD, which is in fact a word of 
> type long and not a type of long long as needed.

No, you're confused as to what WORD means.  You'll find that it's

i386.h:		#define UNITS_PER_WORD (TARGET_64BIT ? 8 : 4)
defaults.h:	#define BITS_PER_WORD (BITS_PER_UNIT * UNITS_PER_WORD)

And of course 8 * 8 == 64.

> I got the suggestion to pack the new pragma commands within libcpp, which 
> makes from my opionion sense too. What do you think about that ?

It would certainly make sense to at least have some support for those
pragmas in libcpp, since you might be able to avoid parsing the macro
definitions twice.  You'd be able to push and pop their tokenized forms.

I don't think you should move the actual parsing of the pragma there; 
that should be left in c-pragma.c.


r~

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: PATCH: x86_64-pc-mingw32 target for gcc
  2007-03-21 17:37       ` Kai Tietz
@ 2007-03-21 18:18         ` Richard Henderson
  0 siblings, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2007-03-21 18:18 UTC (permalink / raw)
  To: Kai Tietz; +Cc: gcc-patches

On Wed, Mar 21, 2007 at 05:36:28PM +0100, Kai Tietz wrote:
> > I don't see anything in the MSDN that specifies that these keywords
> > apply to the 64-bit version.  Their language is very 32-bit specific,
> > which to me implies that they don't apply.
> 
> Please, read http://msdn2.microsoft.com/de-de/library/zxk0tw93(VS.80).aspx
> and may further.

I did so:

 # On Itanium Processor Family (IPF) and x64 processors,
 # __stdcall is accepted and ignored by the compiler;

I see the same "accepted and ignored" language for __fastcall.

> Especially the fact that the called function pops the 
> stack on return remains even for _WIN64.

I don't see that explicitly mentioned in the win64 calling conventions
section.  I'd be hesitant to believe it though; it seems to conflict
with this bit from the Stack Allocation section:

  # The stack will always be maintained 16-byte aligned, except within
  # the prolog (for example, after the return address is pushed) ...

If we were popping the arguments, I'd expect

  void f5(int a, int b, int c, int d, int e)

to leave the stack mis-aligned, since it would need to pop 8 bytes of
arguments.



r~


PS: Please stop cc'ing the closed mingw list, none of the gcc
developers can post back to it, and we'll keep getting nasty
bounce messages.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* revised x86_64-pc-mingw32 patch
  2007-03-14 14:27 PATCH: x86_64-pc-mingw32 target for gcc Kai Tietz
  2007-03-20 19:42 ` Richard Henderson
@ 2007-03-22  0:33 ` Richard Henderson
  2007-03-22 13:02   ` Kai Tietz
                     ` (2 more replies)
  1 sibling, 3 replies; 33+ messages in thread
From: Richard Henderson @ 2007-03-22  0:33 UTC (permalink / raw)
  To: Kai Tietz; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 323 bytes --]

Try the following patch.  It fixes up the calling abi problems,
and gives a stab at fixing the flag_pic sorts of problems.

I do have one question: can I assume that given

  extern int i;
  int f(void) { return i; }

that "i" *cannot* be resolved from a dllimport?  If not,
what does VC++ do with the generated code?


r~

[-- Attachment #2: z --]
[-- Type: text/plain, Size: 83963 bytes --]

--- gcc/c-pragma.c	(revision 123123)
+++ 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/calls.c	(revision 123123)
+++ gcc/calls.c	(local)
@@ -42,6 +42,11 @@ Software Foundation, 51 Franklin Street,
 #include "cgraph.h"
 #include "except.h"
 
+#ifndef OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 0
+#endif
+
+
 /* Like PREFERRED_STACK_BOUNDARY but in units of bytes, not bits.  */
 #define STACK_BYTES (PREFERRED_STACK_BOUNDARY / BITS_PER_UNIT)
 
@@ -1222,13 +1227,12 @@ compute_argument_block_size (int reg_par
 	    = size_binop (MAX_EXPR, args_size->var,
 			  ssize_int (reg_parm_stack_space));
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
 	  /* The area corresponding to register parameters is not to count in
 	     the size of the block we need.  So make the adjustment.  */
+	  if (!OUTGOING_REG_PARM_STACK_SPACE)
 	  args_size->var
 	    = size_binop (MINUS_EXPR, args_size->var,
 			  ssize_int (reg_parm_stack_space));
-#endif
 	}
     }
   else
@@ -1246,9 +1250,8 @@ compute_argument_block_size (int reg_par
       args_size->constant = MAX (args_size->constant,
 				 reg_parm_stack_space);
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
+      if (!OUTGOING_REG_PARM_STACK_SPACE)
       args_size->constant -= reg_parm_stack_space;
-#endif
     }
   return unadjusted_args_size;
 }
@@ -2026,10 +2029,8 @@ expand_call (tree exp, rtx target, int i
   reg_parm_stack_space = REG_PARM_STACK_SPACE (fndecl);
 #endif
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
-  if (reg_parm_stack_space > 0 && PUSH_ARGS)
+  if (!OUTGOING_REG_PARM_STACK_SPACE && reg_parm_stack_space > 0 && PUSH_ARGS)
     must_preallocate = 1;
-#endif
 
   /* Set up a place to return a structure.  */
 
@@ -2430,12 +2431,11 @@ expand_call (tree exp, rtx target, int i
 		     Another approach might be to try to reorder the argument
 		     evaluations to avoid this conflicting stack usage.  */
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
 		  /* Since we will be writing into the entire argument area,
 		     the map must be allocated for its entire size, not just
 		     the part that is the responsibility of the caller.  */
+		  if (!OUTGOING_REG_PARM_STACK_SPACE)
 		  needed += reg_parm_stack_space;
-#endif
 
 #ifdef ARGS_GROW_DOWNWARD
 		  highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
@@ -2531,12 +2531,8 @@ expand_call (tree exp, rtx target, int i
 	     an argument.  */
 	  if (stack_arg_under_construction)
 	    {
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
-	      rtx push_size = GEN_INT (reg_parm_stack_space
-				       + adjusted_args_size.constant);
-#else
-	      rtx push_size = GEN_INT (adjusted_args_size.constant);
-#endif
+	      rtx push_size = (!OUTGOING_REG_PARM_STACK_SPACE ? (GEN_INT (reg_parm_stack_space
+				       + adjusted_args_size.constant)) : (GEN_INT (adjusted_args_size.constant)));
 	      if (old_stack_level == 0)
 		{
 		  emit_stack_save (SAVE_BLOCK, &old_stack_level,
@@ -2706,11 +2702,9 @@ expand_call (tree exp, rtx target, int i
       /* If register arguments require space on the stack and stack space
 	 was not preallocated, allocate stack space here for arguments
 	 passed in registers.  */
-#ifdef OUTGOING_REG_PARM_STACK_SPACE
-      if (!ACCUMULATE_OUTGOING_ARGS
+      if (OUTGOING_REG_PARM_STACK_SPACE && !ACCUMULATE_OUTGOING_ARGS
 	  && must_preallocate == 0 && reg_parm_stack_space > 0)
 	anti_adjust_stack (GEN_INT (reg_parm_stack_space));
-#endif
 
       /* Pass the function the address in which to return a
 	 structure value.  */
@@ -3532,9 +3526,8 @@ emit_library_call_value_1 (int retval, r
   args_size.constant = MAX (args_size.constant,
 			    reg_parm_stack_space);
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
+  if (!OUTGOING_REG_PARM_STACK_SPACE)
   args_size.constant -= reg_parm_stack_space;
-#endif
 
   if (args_size.constant > current_function_outgoing_args_size)
     current_function_outgoing_args_size = args_size.constant;
@@ -3555,12 +3548,11 @@ emit_library_call_value_1 (int retval, r
 
       needed = args_size.constant;
 
-#ifndef OUTGOING_REG_PARM_STACK_SPACE
       /* Since we will be writing into the entire argument area, the
 	 map must be allocated for its entire size, not just the part that
 	 is the responsibility of the caller.  */
+	  if (!OUTGOING_REG_PARM_STACK_SPACE)
       needed += reg_parm_stack_space;
-#endif
 
 #ifdef ARGS_GROW_DOWNWARD
       highest_outgoing_arg_in_use = MAX (initial_highest_arg_in_use,
--- gcc/config/i386/cygming.h	(revision 123123)
+++ 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,28 @@ 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"
 
 \f
+#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)
+\f
 /* 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 +216,26 @@ do {							\
 } while (0)
 
 \f
-/* 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
+#if TARGET_64BIT_DEFAULT
+#define TARGET_SUBTARGET_DEFAULT \
+	(MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS)
+#else
 #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)
+#endif
 
 /* This is how to output an assembler line
    that says to advance the location counter
@@ -266,7 +304,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 +415,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 123123)
+++ gcc/config/i386/cygwin.asm	(local)
@@ -44,6 +44,7 @@
 	.global	__alloca
 ___chkstk:
 __alloca:
+#ifndef _WIN64
 	pushl  %ecx		/* save temp */
 	movl   %esp,%ecx	/* get sp */
 	addl   $0x8,%ecx	/* and point to return addr */
@@ -65,4 +66,27 @@ done: 	subl   %eax,%ecx	   
 	movl   (%eax),%ecx	/* recover saved temp */
 	movl   4(%eax),%eax	/* get return address */
 	jmp    *%eax	
+#else
+	pushq  %rdx		/* save temp */
+	movq   %rsp,%rdx	/* get sp */
+	addq   $0x10,%rdx	/* and point to return addr */
+
+probe: 	cmpq   $0x1000,%rcx	/* > 4k ?*/
+	jb    done		
+
+	subq   $0x1000,%rdx  		/* yes, move pointer down 4k*/
+	orq    $0x0,(%rdx)   		/* probe there */
+	subq   $0x1000,%rcx  	 	/* decrement count */
+	jmp    probe           	 	/* and do it again */
+
+done: 	subq   %rcx,%rdx	   
+	orq    $0x0,(%rdx)	/* less that 4k, just peek here */
+
+	movq   %rsp,%rax
+	movq   %rdx,%rsp	/* decrement stack */
+
+	movq   (%rax),%rdx	/* recover saved temp */
+	movq   8(%rax),%rax	/* get return address */
+	jmp    *%rax	
+#endif
 #endif
--- gcc/config/i386/i386-protos.h	(revision 123123)
+++ gcc/config/i386/i386-protos.h	(local)
@@ -179,7 +179,6 @@ extern void init_cumulative_args (CUMULA
 extern rtx function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
 extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode,
 				  tree, int);
-extern rtx ix86_function_value (tree, tree, bool);
 #endif
 
 #endif
@@ -252,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 123123)
+++ 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.  */
@@ -1512,7 +1518,6 @@ static void ix86_emit_save_regs (void);
 static void ix86_emit_save_regs_using_mov (rtx, HOST_WIDE_INT);
 static void ix86_emit_restore_regs_using_mov (rtx, HOST_WIDE_INT, int);
 static void ix86_output_function_epilogue (FILE *, HOST_WIDE_INT);
-static HOST_WIDE_INT ix86_GOT_alias_set (void);
 static void ix86_adjust_counter (rtx, HOST_WIDE_INT);
 static void ix86_expand_strlensi_unroll_1 (rtx, rtx, rtx);
 static int ix86_issue_rate (void);
@@ -1562,7 +1567,6 @@ static int ix86_function_regparm (tree, 
 const struct attribute_spec ix86_attribute_table[];
 static bool ix86_function_ok_for_sibcall (tree, tree);
 static tree ix86_handle_cconv_attribute (tree *, tree, tree, int, bool *);
-static int ix86_value_regno (enum machine_mode, tree, tree);
 static bool contains_128bit_aligned_vector_p (tree);
 static rtx ix86_struct_value_rtx (tree, int);
 static bool ix86_ms_bitfield_layout_p (tree);
@@ -1584,6 +1588,7 @@ static rtx ix86_internal_arg_pointer (vo
 static void ix86_dwarf_handle_frame_unspec (const char *, rtx, int);
 static bool ix86_expand_vector_init_one_nonzero (bool, enum machine_mode,
 						 rtx, rtx, int);
+static rtx ix86_function_value (tree, tree, bool);
 
 /* This function is only used on Solaris.  */
 static void i386_solaris_elf_named_section (const char *, unsigned int, tree)
@@ -2115,9 +2120,15 @@ override_options (void)
     }
   else
     {
-      ix86_cmodel = CM_32;
-      if (TARGET_64BIT)
+      if (TARGET_64BIT_MS_ABI)
+	{
+	  ix86_cmodel = CM_SMALL_PIC;
+	  flag_pic = 1;
+	}
+      else if (TARGET_64BIT)
 	ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
+      else
+        ix86_cmodel = CM_32;
     }
   if (ix86_asm_string != 0)
     {
@@ -2239,15 +2250,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.
@@ -2900,8 +2912,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;
     }
@@ -2997,69 +3011,64 @@ ix86_function_regparm (tree type, tree d
 {
   tree attr;
   int regparm = ix86_regparm;
-  bool user_convention = false;
 
-  if (!TARGET_64BIT)
-    {
-      attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
-      if (attr)
-	{
-	  regparm = TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
-	  user_convention = true;
-	}
+  if (TARGET_64BIT)
+    return regparm;
 
-      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
-	{
-	  regparm = 2;
-	  user_convention = true;
-	}
+  attr = lookup_attribute ("regparm", TYPE_ATTRIBUTES (type));
+  if (attr)
+    return TREE_INT_CST_LOW (TREE_VALUE (TREE_VALUE (attr)));
+
+  if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (type)))
+    return 2;
 
-      /* Use register calling convention for local functions when possible.  */
-      if (!TARGET_64BIT && !user_convention && decl
-	  && flag_unit_at_a_time && !profile_flag)
+  /* Use register calling convention for local functions when possible.  */
+  if (decl && flag_unit_at_a_time && !profile_flag)
+    {
+      struct cgraph_local_info *i = cgraph_local_info (decl);
+      if (i && i->local)
 	{
-	  struct cgraph_local_info *i = cgraph_local_info (decl);
-	  if (i && i->local)
-	    {
-	      int local_regparm, globals = 0, regno;
+	  int local_regparm, globals = 0, regno;
+	  struct function *f;
 
-	      /* Make sure no regparm register is taken by a global register
-		 variable.  */
-	      for (local_regparm = 0; local_regparm < 3; local_regparm++)
-		if (global_regs[local_regparm])
-		  break;
-	      /* We can't use regparm(3) for nested functions as these use
-		 static chain pointer in third argument.  */
-	      if (local_regparm == 3
-		  && decl_function_context (decl)
-		  && !DECL_NO_STATIC_CHAIN (decl))
-		local_regparm = 2;
-	      /* If the function realigns its stackpointer, the
-		 prologue will clobber %ecx.  If we've already
-		 generated code for the callee, the callee
-		 DECL_STRUCT_FUNCTION is gone, so we fall back to
-		 scanning the attributes for the self-realigning
-		 property.  */
-	      if ((DECL_STRUCT_FUNCTION (decl)
-		   && DECL_STRUCT_FUNCTION (decl)->machine->force_align_arg_pointer)
-		  || (!DECL_STRUCT_FUNCTION (decl)
-		      && lookup_attribute (ix86_force_align_arg_pointer_string,
-					   TYPE_ATTRIBUTES (TREE_TYPE (decl)))))
-		local_regparm = 2;
-	      /* Each global register variable increases register preassure,
-		 so the more global reg vars there are, the smaller regparm
-		 optimization use, unless requested by the user explicitly.  */
-	      for (regno = 0; regno < 6; regno++)
-		if (global_regs[regno])
-		  globals++;
-	      local_regparm
-		= globals < local_regparm ? local_regparm - globals : 0;
+	  /* Make sure no regparm register is taken by a
+	     global register variable.  */
+	  for (local_regparm = 0; local_regparm < 3; local_regparm++)
+	    if (global_regs[local_regparm])
+	      break;
 
-	      if (local_regparm > regparm)
-		regparm = local_regparm;
-	    }
+	  /* We can't use regparm(3) for nested functions as these use
+	     static chain pointer in third argument.  */
+	  if (local_regparm == 3
+	      && decl_function_context (decl)
+	      && !DECL_NO_STATIC_CHAIN (decl))
+	    local_regparm = 2;
+
+	  /* If the function realigns its stackpointer, the prologue will
+	     clobber %ecx.  If we've already generated code for the callee,
+	     the callee DECL_STRUCT_FUNCTION is gone, so we fall back to
+	     scanning the attributes for the self-realigning property.  */
+	  f = DECL_STRUCT_FUNCTION (decl);
+	  if (local_regparm == 3
+	      && (f ? !!f->machine->force_align_arg_pointer
+		  : !!lookup_attribute (ix86_force_align_arg_pointer_string,
+					TYPE_ATTRIBUTES (TREE_TYPE (decl)))))
+	    local_regparm = 2;
+
+	  /* Each global register variable increases register preassure,
+	     so the more global reg vars there are, the smaller regparm
+	     optimization use, unless requested by the user explicitly.  */
+	  for (regno = 0; regno < 6; regno++)
+	    if (global_regs[regno])
+	      globals++;
+	  local_regparm
+	    = globals < local_regparm ? local_regparm - globals : 0;
+
+	  if (local_regparm > regparm)
+	    regparm = local_regparm;
 	}
     }
+
   return regparm;
 }
 
@@ -3071,11 +3080,12 @@ ix86_function_regparm (tree type, tree d
 static int
 ix86_function_sseregparm (tree type, tree decl)
 {
+  gcc_assert (!TARGET_64BIT);
+
   /* Use SSE registers to pass SFmode and DFmode arguments if requested
      by the sseregparm attribute.  */
   if (TARGET_SSEREGPARM
-      || (type
-	  && lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type))))
+      || (type && lookup_attribute ("sseregparm", TYPE_ATTRIBUTES (type))))
     {
       if (!TARGET_SSE)
 	{
@@ -3092,10 +3102,8 @@ ix86_function_sseregparm (tree type, tre
     }
 
   /* For local functions, pass up to SSE_REGPARM_MAX SFmode
-     (and DFmode for SSE2) arguments in SSE registers,
-     even for 32-bit targets.  */
-  if (!TARGET_64BIT && decl
-      && TARGET_SSE_MATH && flag_unit_at_a_time && !profile_flag)
+     (and DFmode for SSE2) arguments in SSE registers.  */
+  if (decl && TARGET_SSE_MATH && flag_unit_at_a_time && !profile_flag)
     {
       struct cgraph_local_info *i = cgraph_local_info (decl);
       if (i && i->local)
@@ -3121,6 +3129,19 @@ ix86_eax_live_at_start_p (void)
   return REGNO_REG_SET_P (ENTRY_BLOCK_PTR->il.rtl->global_live_at_end, 0);
 }
 
+/* Return true if TYPE has a variable argument list.  */
+
+static bool
+type_has_variadic_args_p (tree type)
+{
+  tree t;
+
+  for (t = TYPE_ARG_TYPES (type); t; t = TREE_CHAIN (t))
+    if (t == void_list_node)
+      return false;
+  return true;
+}
+
 /* Value is the number of bytes of arguments automatically
    popped when returning from a subroutine call.
    FUNDECL is the declaration node of the function (as a tree),
@@ -3141,32 +3162,33 @@ ix86_eax_live_at_start_p (void)
 int
 ix86_return_pops_args (tree fundecl, tree funtype, int size)
 {
-  int rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE);
+  int rtd;
+
+  /* None of the 64-bit ABIs pop arguments.  */
+  if (TARGET_64BIT)
+    return 0;
+
+  rtd = TARGET_RTD && (!fundecl || TREE_CODE (fundecl) != IDENTIFIER_NODE);
 
   /* Cdecl functions override -mrtd, and never pop the stack.  */
-  if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype))) {
+  if (! lookup_attribute ("cdecl", TYPE_ATTRIBUTES (funtype)))
+    {
+      /* Stdcall and fastcall functions will pop the stack if not
+         variable args.  */
+      if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))
+          || lookup_attribute ("fastcall", TYPE_ATTRIBUTES (funtype)))
+	rtd = 1;
 
-    /* Stdcall and fastcall functions will pop the stack if not
-       variable args.  */
-    if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (funtype))
-        || lookup_attribute ("fastcall", TYPE_ATTRIBUTES (funtype)))
-      rtd = 1;
-
-    if (rtd
-        && (TYPE_ARG_TYPES (funtype) == NULL_TREE
-	    || (TREE_VALUE (tree_last (TYPE_ARG_TYPES (funtype)))
-		== void_type_node)))
-      return size;
-  }
+      if (rtd && ! type_has_variadic_args_p (funtype))
+	return size;
+    }
 
   /* Lose any fake structure return argument if it is passed on the stack.  */
   if (aggregate_value_p (TREE_TYPE (funtype), fundecl)
-      && !TARGET_64BIT
       && !KEEP_AGGREGATE_RETURN_POINTER)
     {
       int nregs = ix86_function_regparm (funtype, fundecl);
-
-      if (!nregs)
+      if (nregs == 0)
 	return GET_MODE_SIZE (Pmode);
     }
 
@@ -3180,6 +3202,8 @@ bool
 ix86_function_arg_regno_p (int regno)
 {
   int i;
+  const int *parm_regs;
+
   if (!TARGET_64BIT)
     {
       if (TARGET_MACHO)
@@ -3204,11 +3228,17 @@ ix86_function_arg_regno_p (int regno)
           && (regno < FIRST_SSE_REG + SSE_REGPARM_MAX))
         return true;
     }
+
   /* RAX is used as hidden argument to va_arg functions.  */
-  if (!regno)
+  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;
 }
@@ -3238,24 +3268,7 @@ init_cumulative_args (CUMULATIVE_ARGS *c
 		      rtx libname,	/* SYMBOL_REF of library name or 0 */
 		      tree fndecl)
 {
-  static CUMULATIVE_ARGS zero_cum;
-  tree param, next_param;
-
-  if (TARGET_DEBUG_ARG)
-    {
-      fprintf (stderr, "\ninit_cumulative_args (");
-      if (fntype)
-	fprintf (stderr, "fntype code = %s, ret code = %s",
-		 tree_code_name[(int) TREE_CODE (fntype)],
-		 tree_code_name[(int) TREE_CODE (TREE_TYPE (fntype))]);
-      else
-	fprintf (stderr, "no fntype");
-
-      if (libname)
-	fprintf (stderr, ", libname = %s", XSTR (libname, 0));
-    }
-
-  *cum = zero_cum;
+  memset (cum, 0, sizeof (*cum));
 
   /* Set up the number of registers to use for passing arguments.  */
   cum->nregs = ix86_regparm;
@@ -3265,60 +3278,39 @@ init_cumulative_args (CUMULATIVE_ARGS *c
     cum->mmx_nregs = MMX_REGPARM_MAX;
   cum->warn_sse = true;
   cum->warn_mmx = true;
-  cum->maybe_vaarg = false;
+  cum->maybe_vaarg = (fntype ? type_has_variadic_args_p (fntype) : !libname);
 
-  /* Use ecx and edx registers if function has fastcall attribute,
-     else look for regparm information.  */
-  if (fntype && !TARGET_64BIT)
+  if (!TARGET_64BIT)
     {
-      if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
-	{
-	  cum->nregs = 2;
-	  cum->fastcall = 1;
+      /* If there are variable arguments, then we won't pass anything
+         in registers in 32-bit mode. */
+      if (cum->maybe_vaarg)
+	{
+	  cum->nregs = 0;
+	  cum->sse_nregs = 0;
+	  cum->mmx_nregs = 0;
+	  cum->warn_sse = 0;
+	  cum->warn_mmx = 0;
+	  return;
 	}
-      else
-	cum->nregs = ix86_function_regparm (fntype, fndecl);
-    }
-
-  /* Set up the number of SSE registers used for passing SFmode
-     and DFmode arguments.  Warn for mismatching ABI.  */
-  cum->float_in_sse = ix86_function_sseregparm (fntype, fndecl);
-
-  /* Determine if this function has variable arguments.  This is
-     indicated by the last argument being 'void_type_mode' if there
-     are no variable arguments.  If there are variable arguments, then
-     we won't pass anything in registers in 32-bit mode. */
 
-  if (cum->nregs || cum->mmx_nregs || cum->sse_nregs)
-    {
-      for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
-	   param != 0; param = next_param)
+      /* Use ecx and edx registers if function has fastcall attribute,
+	 else look for regparm information.  */
+      if (fntype)
 	{
-	  next_param = TREE_CHAIN (param);
-	  if (next_param == 0 && TREE_VALUE (param) != void_type_node)
+	  if (lookup_attribute ("fastcall", TYPE_ATTRIBUTES (fntype)))
 	    {
-	      if (!TARGET_64BIT)
-		{
-		  cum->nregs = 0;
-		  cum->sse_nregs = 0;
-		  cum->mmx_nregs = 0;
-		  cum->warn_sse = 0;
-		  cum->warn_mmx = 0;
-		  cum->fastcall = 0;
-		  cum->float_in_sse = 0;
-		}
-	      cum->maybe_vaarg = true;
+	      cum->nregs = 2;
+	      cum->fastcall = 1;
 	    }
+	  else
+	    cum->nregs = ix86_function_regparm (fntype, fndecl);
 	}
-    }
-  if ((!fntype && !libname)
-      || (fntype && !TYPE_ARG_TYPES (fntype)))
-    cum->maybe_vaarg = true;
-
-  if (TARGET_DEBUG_ARG)
-    fprintf (stderr, ", nregs=%d )\n", cum->nregs);
 
-  return;
+      /* Set up the number of SSE registers used for passing SFmode
+	 and DFmode arguments.  Warn for mismatching ABI.  */
+      cum->float_in_sse = ix86_function_sseregparm (fntype, fndecl);
+    }
 }
 
 /* Return the "natural" mode for TYPE.  In most cases, this is just TYPE_MODE.
@@ -3781,20 +3773,6 @@ construct_container (enum machine_mode m
   rtx ret;
 
   n = classify_argument (mode, type, class, 0);
-  if (TARGET_DEBUG_ARG)
-    {
-      if (!n)
-	fprintf (stderr, "Memory class\n");
-      else
-	{
-	  fprintf (stderr, "Classes:");
-	  for (i = 0; i < n; i++)
-	    {
-	      fprintf (stderr, " %s", x86_64_reg_class_name[class[i]]);
-	    }
-	   fprintf (stderr, "\n");
-	}
-    }
   if (!n)
     return NULL;
   if (!examine_argument (mode, type, in_return, &needed_intregs,
@@ -3863,6 +3841,7 @@ construct_container (enum machine_mode m
   if (n == 2 && class[0] == X86_64_SSE_CLASS && class[1] == X86_64_SSEUP_CLASS
       && mode != BLKmode)
     return gen_rtx_REG (mode, SSE_REGNO (sse_regno));
+
   if (n == 2
       && class[0] == X86_64_X87_CLASS && class[1] == X86_64_X87UP_CLASS)
     return gen_rtx_REG (XFmode, FIRST_STACK_REG);
@@ -3938,117 +3917,143 @@ construct_container (enum machine_mode m
   return ret;
 }
 
-/* Update the data in CUM to advance over an argument
-   of mode MODE and data type TYPE.
-   (TYPE is null for libcalls where that information may not be available.)  */
+/* Update the data in CUM to advance over an argument of mode MODE
+   and data type TYPE.  (TYPE is null for libcalls where that information
+   may not be available.)  */
 
-void
-function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
-		      tree type, int named)
+static void
+function_arg_advance_32 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+			 tree type, HOST_WIDE_INT bytes, HOST_WIDE_INT words)
 {
-  int bytes =
-    (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
-  int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
-
-  if (type)
-    mode = type_natural_mode (type);
-
-  if (TARGET_DEBUG_ARG)
-    fprintf (stderr, "function_adv (sz=%d, wds=%2d, nregs=%d, ssenregs=%d, "
-	     "mode=%s, named=%d)\n\n",
-	     words, cum->words, cum->nregs, cum->sse_nregs,
-	     GET_MODE_NAME (mode), named);
-
-  if (TARGET_64BIT)
-    {
-      int int_nregs, sse_nregs;
-      if (!examine_argument (mode, type, 0, &int_nregs, &sse_nregs))
-	cum->words += words;
-      else if (sse_nregs <= cum->sse_nregs && int_nregs <= cum->nregs)
-	{
-	  cum->nregs -= int_nregs;
-	  cum->sse_nregs -= sse_nregs;
-	  cum->regno += int_nregs;
-	  cum->sse_regno += sse_nregs;
-	}
-      else
-	cum->words += words;
-    }
-  else
+  switch (mode)
     {
-      switch (mode)
-	{
-	default:
-	  break;
+    default:
+      break;
 
-	case BLKmode:
-	  if (bytes < 0)
-	    break;
-	  /* FALLTHRU */
+    case BLKmode:
+      if (bytes < 0)
+	break;
+      /* FALLTHRU */
 
-	case DImode:
-	case SImode:
-	case HImode:
-	case QImode:
-	  cum->words += words;
-	  cum->nregs -= words;
-	  cum->regno += words;
+    case DImode:
+    case SImode:
+    case HImode:
+    case QImode:
+      cum->words += words;
+      cum->nregs -= words;
+      cum->regno += words;
 
-	  if (cum->nregs <= 0)
-	    {
-	      cum->nregs = 0;
-	      cum->regno = 0;
-	    }
-	  break;
+      if (cum->nregs <= 0)
+	{
+	  cum->nregs = 0;
+	  cum->regno = 0;
+	}
+      break;
 
-	case DFmode:
-	  if (cum->float_in_sse < 2)
-	    break;
-	case SFmode:
-	  if (cum->float_in_sse < 1)
-	    break;
-	  /* FALLTHRU */
+    case DFmode:
+      if (cum->float_in_sse < 2)
+	break;
+    case SFmode:
+      if (cum->float_in_sse < 1)
+	break;
+      /* FALLTHRU */
 
-	case TImode:
-	case V16QImode:
-	case V8HImode:
-	case V4SImode:
-	case V2DImode:
-	case V4SFmode:
-	case V2DFmode:
-	  if (!type || !AGGREGATE_TYPE_P (type))
+    case TImode:
+    case V16QImode:
+    case V8HImode:
+    case V4SImode:
+    case V2DImode:
+    case V4SFmode:
+    case V2DFmode:
+      if (!type || !AGGREGATE_TYPE_P (type))
+	{
+	  cum->sse_words += words;
+	  cum->sse_nregs -= 1;
+	  cum->sse_regno += 1;
+	  if (cum->sse_nregs <= 0)
 	    {
-	      cum->sse_words += words;
-	      cum->sse_nregs -= 1;
-	      cum->sse_regno += 1;
-	      if (cum->sse_nregs <= 0)
-		{
-		  cum->sse_nregs = 0;
-		  cum->sse_regno = 0;
-		}
+	      cum->sse_nregs = 0;
+	      cum->sse_regno = 0;
 	    }
-	  break;
+	}
+      break;
 
-	case V8QImode:
-	case V4HImode:
-	case V2SImode:
-	case V2SFmode:
-	  if (!type || !AGGREGATE_TYPE_P (type))
+    case V8QImode:
+    case V4HImode:
+    case V2SImode:
+    case V2SFmode:
+      if (!type || !AGGREGATE_TYPE_P (type))
+	{
+	  cum->mmx_words += words;
+	  cum->mmx_nregs -= 1;
+	  cum->mmx_regno += 1;
+	  if (cum->mmx_nregs <= 0)
 	    {
-	      cum->mmx_words += words;
-	      cum->mmx_nregs -= 1;
-	      cum->mmx_regno += 1;
-	      if (cum->mmx_nregs <= 0)
-		{
-		  cum->mmx_nregs = 0;
-		  cum->mmx_regno = 0;
-		}
+	      cum->mmx_nregs = 0;
+	      cum->mmx_regno = 0;
 	    }
-	  break;
 	}
+      break;
     }
 }
 
+static void
+function_arg_advance_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+			 tree type, HOST_WIDE_INT words)
+{
+  int int_nregs, sse_nregs;
+
+  if (!examine_argument (mode, type, 0, &int_nregs, &sse_nregs))
+    cum->words += words;
+  else if (sse_nregs <= cum->sse_nregs && int_nregs <= cum->nregs)
+    {
+      cum->nregs -= int_nregs;
+      cum->sse_nregs -= sse_nregs;
+      cum->regno += int_nregs;
+      cum->sse_regno += sse_nregs;
+    }
+  else
+    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)
+{
+  HOST_WIDE_INT bytes, words;
+
+  if (mode == BLKmode)
+    bytes = int_size_in_bytes (type);
+  else
+    bytes = GET_MODE_SIZE (mode);
+  words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+
+  if (type)
+    mode = type_natural_mode (type);
+
+  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);
+}
+
 /* Define where to put the arguments to a function.
    Value is zero to push the argument on the stack,
    or a hard register in which to store the argument.
@@ -4062,135 +4067,180 @@ function_arg_advance (CUMULATIVE_ARGS *c
    NAMED is nonzero if this argument is a named parameter
     (otherwise it is an extra parameter matching an ellipsis).  */
 
-rtx
-function_arg (CUMULATIVE_ARGS *cum, enum machine_mode orig_mode,
-	      tree type, int named)
+static rtx
+function_arg_32 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+		 enum machine_mode orig_mode, tree type,
+		 HOST_WIDE_INT bytes, HOST_WIDE_INT words)
 {
-  enum machine_mode mode = orig_mode;
-  rtx ret = NULL_RTX;
-  int bytes =
-    (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
-  int words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
   static bool warnedsse, warnedmmx;
 
-  /* To simplify the code below, represent vector types with a vector mode
-     even if MMX/SSE are not active.  */
-  if (type && TREE_CODE (type) == VECTOR_TYPE)
-    mode = type_natural_mode (type);
-
-  /* Handle a hidden AL argument containing number of registers for varargs
-     x86-64 functions.  For i386 ABI just return constm1_rtx to avoid
-     any AL settings.  */
+  /* Avoid the AL settings for the Unix64 ABI.  */
   if (mode == VOIDmode)
+    return constm1_rtx;
+
+  switch (mode)
     {
-      if (TARGET_64BIT)
-	return GEN_INT (cum->maybe_vaarg
-			? (cum->sse_nregs < 0
-			   ? SSE_REGPARM_MAX
-			   : cum->sse_regno)
-			: -1);
-      else
-	return constm1_rtx;
-    }
-  if (TARGET_64BIT)
-    ret = construct_container (mode, orig_mode, type, 0, cum->nregs,
-			       cum->sse_nregs,
-			       &x86_64_int_parameter_registers [cum->regno],
-			       cum->sse_regno);
-  else
-    switch (mode)
-      {
-	/* For now, pass fp/complex values on the stack.  */
-      default:
+    default:
+      break;
+
+    case BLKmode:
+      if (bytes < 0)
 	break;
+      /* FALLTHRU */
+    case DImode:
+    case SImode:
+    case HImode:
+    case QImode:
+      if (words <= cum->nregs)
+	{
+	  int regno = cum->regno;
 
-      case BLKmode:
-	if (bytes < 0)
-	  break;
-	/* FALLTHRU */
-      case DImode:
-      case SImode:
-      case HImode:
-      case QImode:
-	if (words <= cum->nregs)
-	  {
-	    int regno = cum->regno;
+	  /* Fastcall allocates the first two DWORD (SImode) or
+	     smaller arguments to ECX and EDX.  */
+	  if (cum->fastcall)
+	    {
+	      if (mode == BLKmode || mode == DImode)
+	        break;
 
-	    /* Fastcall allocates the first two DWORD (SImode) or
-	       smaller arguments to ECX and EDX.  */
-	    if (cum->fastcall)
-	      {
-	        if (mode == BLKmode || mode == DImode)
-	          break;
+	      /* ECX not EAX is the first allocated register.  */
+	      if (regno == 0)
+		regno = 2;
+	    }
+	  return gen_rtx_REG (mode, regno);
+	}
+      break;
 
-	        /* ECX not EAX is the first allocated register.  */
-	        if (regno == 0)
-		  regno = 2;
-	      }
-	    ret = gen_rtx_REG (mode, regno);
-	  }
-	break;
-      case DFmode:
-	if (cum->float_in_sse < 2)
-	  break;
-      case SFmode:
-	if (cum->float_in_sse < 1)
-	  break;
-	/* FALLTHRU */
-      case TImode:
-      case V16QImode:
-      case V8HImode:
-      case V4SImode:
-      case V2DImode:
-      case V4SFmode:
-      case V2DFmode:
-	if (!type || !AGGREGATE_TYPE_P (type))
-	  {
-	    if (!TARGET_SSE && !warnedsse && cum->warn_sse)
-	      {
-		warnedsse = true;
-		warning (0, "SSE vector argument without SSE enabled "
-			 "changes the ABI");
-	      }
-	    if (cum->sse_nregs)
-	      ret = gen_reg_or_parallel (mode, orig_mode,
-					 cum->sse_regno + FIRST_SSE_REG);
-	  }
+    case DFmode:
+      if (cum->float_in_sse < 2)
 	break;
-      case V8QImode:
-      case V4HImode:
-      case V2SImode:
-      case V2SFmode:
-	if (!type || !AGGREGATE_TYPE_P (type))
-	  {
-	    if (!TARGET_MMX && !warnedmmx && cum->warn_mmx)
-	      {
-		warnedmmx = true;
-		warning (0, "MMX vector argument without MMX enabled "
-			 "changes the ABI");
-	      }
-	    if (cum->mmx_nregs)
-	      ret = gen_reg_or_parallel (mode, orig_mode,
-					 cum->mmx_regno + FIRST_MMX_REG);
-	  }
+    case SFmode:
+      if (cum->float_in_sse < 1)
 	break;
-      }
+      /* FALLTHRU */
+    case TImode:
+    case V16QImode:
+    case V8HImode:
+    case V4SImode:
+    case V2DImode:
+    case V4SFmode:
+    case V2DFmode:
+      if (!type || !AGGREGATE_TYPE_P (type))
+	{
+	  if (!TARGET_SSE && !warnedsse && cum->warn_sse)
+	    {
+	      warnedsse = true;
+	      warning (0, "SSE vector argument without SSE enabled "
+		       "changes the ABI");
+	    }
+	  if (cum->sse_nregs)
+	    return gen_reg_or_parallel (mode, orig_mode,
+				        cum->sse_regno + FIRST_SSE_REG);
+	}
+      break;
 
-  if (TARGET_DEBUG_ARG)
-    {
-      fprintf (stderr,
-	       "function_arg (size=%d, wds=%2d, nregs=%d, mode=%4s, named=%d, ",
-	       words, cum->words, cum->nregs, GET_MODE_NAME (mode), named);
+    case V8QImode:
+    case V4HImode:
+    case V2SImode:
+    case V2SFmode:
+      if (!type || !AGGREGATE_TYPE_P (type))
+	{
+	  if (!TARGET_MMX && !warnedmmx && cum->warn_mmx)
+	    {
+	      warnedmmx = true;
+	      warning (0, "MMX vector argument without MMX enabled "
+		       "changes the ABI");
+	    }
+	  if (cum->mmx_nregs)
+	    return gen_reg_or_parallel (mode, orig_mode,
+				        cum->mmx_regno + FIRST_MMX_REG);
+	}
+      break;
+    }
+
+  return NULL_RTX;
+}
+
+static rtx
+function_arg_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+		 enum machine_mode orig_mode, tree type)
+{
+  /* Handle a hidden AL argument containing number of registers
+     for varargs x86-64 functions.  */
+  if (mode == VOIDmode)
+    return GEN_INT (cum->maybe_vaarg
+		    ? (cum->sse_nregs < 0
+		       ? SSE_REGPARM_MAX
+		       : cum->sse_regno)
+		    : -1);
+
+  return construct_container (mode, orig_mode, type, 0, cum->nregs,
+			      cum->sse_nregs,
+			      &x86_64_int_parameter_registers [cum->regno],
+			      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;
 
-      if (ret)
-	print_simple_rtl (stderr, ret);
+  /* 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
-	fprintf (stderr, ", stack");
+	{
+	  rtx t1, t2;
 
-      fprintf (stderr, " )\n");
+	  /* 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 ret;
+  return gen_reg_or_parallel (mode, orig_mode, regno);
+}
+
+rtx
+function_arg (CUMULATIVE_ARGS *cum, enum machine_mode omode,
+	      tree type, int named)
+{
+  enum machine_mode mode = omode;
+  HOST_WIDE_INT bytes, words;
+
+  if (mode == BLKmode)
+    bytes = int_size_in_bytes (type);
+  else
+    bytes = GET_MODE_SIZE (mode);
+  words = (bytes + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
+
+  /* To simplify the code below, represent vector types with a vector mode
+     even if MMX/SSE are not active.  */
+  if (type && TREE_CODE (type) == VECTOR_TYPE)
+    mode = type_natural_mode (type);
+
+  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);
 }
 
 /* A C expression that indicates when an argument must be passed by
@@ -4204,15 +4254,35 @@ ix86_pass_by_reference (CUMULATIVE_ARGS 
 			enum machine_mode mode ATTRIBUTE_UNUSED,
 			tree type, bool named ATTRIBUTE_UNUSED)
 {
-  if (!TARGET_64BIT)
-    return 0;
-
-  if (type && int_size_in_bytes (type) == -1)
+  if (TARGET_64BIT_MS_ABI)
     {
-      if (TARGET_DEBUG_ARG)
-	fprintf (stderr, "function_arg_pass_by_reference\n");
-      return 1;
+      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);
+	    }
+	}
+
+      /* ??? How to handle long double?  */
+      if (mode == XFmode)
+	return false;
+
+      /* __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;
 }
@@ -4278,104 +4348,206 @@ ix86_function_arg_boundary (enum machine
     align = PARM_BOUNDARY;
   if (!TARGET_64BIT)
     {
-      /* i386 ABI defines all arguments to be 4 byte aligned.  We have to
-	 make an exception for SSE modes since these require 128bit
-	 alignment.
+      /* i386 ABI defines all arguments to be 4 byte aligned.  We have to
+	 make an exception for SSE modes since these require 128bit
+	 alignment.
+
+	 The handling here differs from field_alignment.  ICC aligns MMX
+	 arguments to 4 byte boundaries, while structure fields are aligned
+	 to 8 byte boundaries.  */
+      if (!TARGET_SSE)
+	align = PARM_BOUNDARY;
+      else if (!type)
+	{
+	  if (!SSE_REG_MODE_P (mode))
+	    align = PARM_BOUNDARY;
+	}
+      else
+	{
+	  if (!contains_128bit_aligned_vector_p (type))
+	    align = PARM_BOUNDARY;
+	}
+    }
+  if (align > 128)
+    align = 128;
+  return align;
+}
+
+/* Return true if N is a possible register number of function value.  */
+
+bool
+ix86_function_value_regno_p (int regno)
+{
+  switch (regno)
+    {
+    case 0:
+      return true;
+
+    case FIRST_FLOAT_REG:
+      return TARGET_FLOAT_RETURNS_IN_80387;
+
+    case FIRST_SSE_REG:
+      return TARGET_SSE;
+
+    case FIRST_MMX_REG:
+      if (TARGET_MACHO || TARGET_64BIT)
+	return false;
+      return TARGET_MMX;
+    }
+
+  return false;
+}
+
+/* Define how to find the value returned by a function.
+   VALTYPE is the data type of the value (as a tree).
+   If the precise function being called is known, FUNC is its FUNCTION_DECL;
+   otherwise, FUNC is 0.  */
+
+static rtx
+function_value_32 (enum machine_mode orig_mode, enum machine_mode mode,
+		   tree fntype, tree fn)
+{
+  unsigned int regno;
+
+  /* 8-byte vector modes in %mm0. See ix86_return_in_memory for where
+     we normally prevent this case when mmx is not available.  However
+     some ABIs may require the result to be returned like DImode.  */
+  if (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 8)
+    regno = TARGET_MMX ? FIRST_MMX_REG : 0;
+
+  /* 16-byte vector modes in %xmm0.  See ix86_return_in_memory for where
+     we prevent this case when sse is not available.  However some ABIs
+     may require the result to be returned like integer TImode.  */
+  else if (mode == TImode
+	   || (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 16))
+    regno = TARGET_SSE ? FIRST_SSE_REG : 0;
+
+  /* Decimal floating point values can go in %eax, unlike other float modes.  */
+  else if (DECIMAL_FLOAT_MODE_P (mode))
+    regno = 0;
+
+  /* Most things go in %eax, except (unless -mno-fp-ret-in-387) fp values.  */
+  else if (!SCALAR_FLOAT_MODE_P (mode) || !TARGET_FLOAT_RETURNS_IN_80387)
+    regno = 0;
+
+  /* Floating point return values in %st(0), except for local functions when
+     SSE math is enabled or for functions with sseregparm attribute.  */
+  else
+    {
+      regno = FIRST_FLOAT_REG;
 
-	 The handling here differs from field_alignment.  ICC aligns MMX
-	 arguments to 4 byte boundaries, while structure fields are aligned
-	 to 8 byte boundaries.  */
-      if (!TARGET_SSE)
-	align = PARM_BOUNDARY;
-      else if (!type)
+      if ((fn || fntype) && (mode == SFmode || mode == DFmode))
 	{
-	  if (!SSE_REG_MODE_P (mode))
-	    align = PARM_BOUNDARY;
+	  int sse_level = ix86_function_sseregparm (fntype, fn);
+	  if ((sse_level >= 1 && mode == SFmode)
+	      || (sse_level == 2 && mode == DFmode))
+	    regno = FIRST_SSE_REG;
 	}
-      else
+    }
+
+  return gen_rtx_REG (orig_mode, regno);
+}
+
+static rtx
+function_value_64 (enum machine_mode orig_mode, enum machine_mode mode,
+		   tree valtype)
+{
+  rtx ret;
+
+  /* Handle libcalls, which don't provide a type node.  */
+  if (valtype == NULL)
+    {
+      switch (mode)
 	{
-	  if (!contains_128bit_aligned_vector_p (type))
-	    align = PARM_BOUNDARY;
+	case SFmode:
+	case SCmode:
+	case DFmode:
+	case DCmode:
+	case TFmode:
+	case SDmode:
+	case DDmode:
+	case TDmode:
+	  return gen_rtx_REG (mode, FIRST_SSE_REG);
+	case XFmode:
+	case XCmode:
+	  return gen_rtx_REG (mode, FIRST_FLOAT_REG);
+	case TCmode:
+	  return NULL;
+	default:
+	  return gen_rtx_REG (mode, 0);
 	}
     }
-  if (align > 128)
-    align = 128;
-  return align;
+
+  ret = construct_container (mode, orig_mode, valtype, 1,
+			     REGPARM_MAX, SSE_REGPARM_MAX,
+			     x86_64_int_return_registers, 0);
+
+  /* For zero sized structures, construct_container returns NULL, but we
+     need to keep rest of compiler happy by returning meaningful value.  */
+  if (!ret)
+    ret = gen_rtx_REG (orig_mode, 0);
+
+  return ret;
 }
 
-/* Return true if N is a possible register number of function value.  */
-bool
-ix86_function_value_regno_p (int regno)
+static rtx
+function_value_ms_64 (enum machine_mode orig_mode, enum machine_mode mode)
 {
-  if (TARGET_MACHO)
-    {
-      if (!TARGET_64BIT)
-        {
-          return ((regno) == 0
-                  || ((regno) == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387)
-                  || ((regno) == FIRST_SSE_REG && TARGET_SSE));
-        }
-      return ((regno) == 0 || (regno) == FIRST_FLOAT_REG
-              || ((regno) == FIRST_SSE_REG && TARGET_SSE)
-              || ((regno) == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387));
-      }
-  else
-    {
-      if (regno == 0
-          || (regno == FIRST_FLOAT_REG && TARGET_FLOAT_RETURNS_IN_80387)
-          || (regno == FIRST_SSE_REG && TARGET_SSE))
-        return true;
+  unsigned int regno = 0;
 
-      if (!TARGET_64BIT
-          && (regno == FIRST_MMX_REG && TARGET_MMX))
-	    return true;
+  if (mode == SFmode || mode == DFmode)
+    regno = FIRST_SSE_REG;
+  else if (VECTOR_MODE_P (mode) || GET_MODE_SIZE (mode) == 16)
+    regno = FIRST_SSE_REG;
+  else if (mode == XFmode)
+    /* ??? How to handle long double?  */
+    regno = FIRST_FLOAT_REG;
+  
+  return gen_rtx_REG (orig_mode, regno);
+}
 
-      return false;
-    }
+static rtx
+ix86_function_value_1 (tree valtype, tree fntype_or_decl,
+		       enum machine_mode orig_mode, enum machine_mode mode)
+{
+  tree fn, fntype;
+
+  fn = NULL_TREE;
+  if (fntype_or_decl && DECL_P (fntype_or_decl))
+    fn = fntype_or_decl;
+  fntype = fn ? TREE_TYPE (fn) : fntype_or_decl;
+
+  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);
 }
 
-/* Define how to find the value returned by a function.
-   VALTYPE is the data type of the value (as a tree).
-   If the precise function being called is known, FUNC is its FUNCTION_DECL;
-   otherwise, FUNC is 0.  */
-rtx
+static rtx
 ix86_function_value (tree valtype, tree fntype_or_decl,
 		     bool outgoing ATTRIBUTE_UNUSED)
 {
-  enum machine_mode natmode = type_natural_mode (valtype);
+  enum machine_mode mode, orig_mode;
 
-  if (TARGET_64BIT)
-    {
-      rtx ret = construct_container (natmode, TYPE_MODE (valtype), valtype,
-				     1, REGPARM_MAX, SSE_REGPARM_MAX,
-				     x86_64_int_return_registers, 0);
-      /* For zero sized structures, construct_container return NULL, but we
-	 need to keep rest of compiler happy by returning meaningful value.  */
-      if (!ret)
-	ret = gen_rtx_REG (TYPE_MODE (valtype), 0);
-      return ret;
-    }
-  else
-    {
-      tree fn = NULL_TREE, fntype;
-      if (fntype_or_decl
-	  && DECL_P (fntype_or_decl))
-        fn = fntype_or_decl;
-      fntype = fn ? TREE_TYPE (fn) : fntype_or_decl;
-      return gen_rtx_REG (TYPE_MODE (valtype),
-			  ix86_value_regno (natmode, fn, fntype));
-    }
+  orig_mode = TYPE_MODE (valtype);
+  mode = type_natural_mode (valtype);
+  return ix86_function_value_1 (valtype, fntype_or_decl, orig_mode, mode);
 }
 
-/* Return true iff type is returned in memory.  */
-int
-ix86_return_in_memory (tree type)
+rtx
+ix86_libcall_value (enum machine_mode mode)
 {
-  int needed_intregs, needed_sseregs, size;
-  enum machine_mode mode = type_natural_mode (type);
+  return ix86_function_value_1 (NULL, NULL, mode, mode);
+}
 
-  if (TARGET_64BIT)
-    return !examine_argument (mode, type, 1, &needed_intregs, &needed_sseregs);
+/* Return true iff type is returned in memory.  */
+
+static int
+return_in_memory_32 (tree type, enum machine_mode mode)
+{
+  HOST_WIDE_INT size;
 
   if (mode == BLKmode)
     return 1;
@@ -4412,6 +4584,43 @@ ix86_return_in_memory (tree type)
   return 0;
 }
 
+static int
+return_in_memory_64 (tree type, enum machine_mode mode)
+{
+  int needed_intregs, needed_sseregs;
+  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;
+
+  /* ??? How to handle long double?  */
+  if (mode == XFmode)
+    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_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);
+}
+
 /* When returning SSE vector types, we have a choice of either
      (1) being abi incompatible with a -march switch, or
      (2) generating an error.
@@ -4428,7 +4637,7 @@ ix86_struct_value_rtx (tree type, int in
 {
   static bool warnedsse, warnedmmx;
 
-  if (type)
+  if (!TARGET_64BIT && type)
     {
       /* Look at the return type of the function, not the function type.  */
       enum machine_mode mode = TYPE_MODE (TREE_TYPE (type));
@@ -4458,77 +4667,6 @@ ix86_struct_value_rtx (tree type, int in
   return NULL;
 }
 
-/* Define how to find the value returned by a library function
-   assuming the value has mode MODE.  */
-rtx
-ix86_libcall_value (enum machine_mode mode)
-{
-  if (TARGET_64BIT)
-    {
-      switch (mode)
-	{
-	case SFmode:
-	case SCmode:
-	case DFmode:
-	case DCmode:
-	case TFmode:
-	case SDmode:
-	case DDmode:
-	case TDmode:
-	  return gen_rtx_REG (mode, FIRST_SSE_REG);
-	case XFmode:
-	case XCmode:
-	  return gen_rtx_REG (mode, FIRST_FLOAT_REG);
-	case TCmode:
-	  return NULL;
-	default:
-	  return gen_rtx_REG (mode, 0);
-	}
-    }
-  else
-    return gen_rtx_REG (mode, ix86_value_regno (mode, NULL, NULL));
-}
-
-/* Given a mode, return the register to use for a return value.  */
-
-static int
-ix86_value_regno (enum machine_mode mode, tree func, tree fntype)
-{
-  gcc_assert (!TARGET_64BIT);
-
-  /* 8-byte vector modes in %mm0. See ix86_return_in_memory for where
-     we normally prevent this case when mmx is not available.  However
-     some ABIs may require the result to be returned like DImode.  */
-  if (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 8)
-    return TARGET_MMX ? FIRST_MMX_REG : 0;
-
-  /* 16-byte vector modes in %xmm0.  See ix86_return_in_memory for where
-     we prevent this case when sse is not available.  However some ABIs
-     may require the result to be returned like integer TImode.  */
-  if (mode == TImode || (VECTOR_MODE_P (mode) && GET_MODE_SIZE (mode) == 16))
-    return TARGET_SSE ? FIRST_SSE_REG : 0;
-
-  /* Decimal floating point values can go in %eax, unlike other float modes.  */
-  if (DECIMAL_FLOAT_MODE_P (mode))
-    return 0;
-
-  /* Most things go in %eax, except (unless -mno-fp-ret-in-387) fp values.  */
-  if (!SCALAR_FLOAT_MODE_P (mode) || !TARGET_FLOAT_RETURNS_IN_80387)
-    return 0;
-
-  /* Floating point return values in %st(0), except for local functions when
-     SSE math is enabled or for functions with sseregparm attribute.  */
-  if ((func || fntype)
-      && (mode == SFmode || mode == DFmode))
-    {
-      int sse_level = ix86_function_sseregparm (fntype, func);
-      if ((sse_level >= 1 && mode == SFmode)
-	  || (sse_level == 2 && mode == DFmode))
-        return FIRST_SSE_REG;
-    }
-
-  return FIRST_FLOAT_REG;
-}
 \f
 /* Create the va_list data type.  */
 
@@ -4538,7 +4676,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);
@@ -4577,51 +4715,29 @@ ix86_build_builtin_va_list (void)
 /* Worker function for TARGET_SETUP_INCOMING_VARARGS.  */
 
 static void
-ix86_setup_incoming_varargs (CUMULATIVE_ARGS *cum, enum machine_mode mode,
-			     tree type, int *pretend_size ATTRIBUTE_UNUSED,
-			     int no_rtl)
+setup_incoming_varargs_64 (CUMULATIVE_ARGS *cum)
 {
-  CUMULATIVE_ARGS next_cum;
-  rtx save_area = NULL_RTX, mem;
+  rtx save_area, mem;
   rtx label;
   rtx label_ref;
   rtx tmp_reg;
   rtx nsse_reg;
   int set;
-  tree fntype;
-  int stdarg_p;
   int i;
 
-  if (!TARGET_64BIT)
-    return;
-
   if (! cfun->va_list_gpr_size && ! cfun->va_list_fpr_size)
     return;
 
   /* Indicate to allocate space on the stack for varargs save area.  */
   ix86_save_varrargs_registers = 1;
-
   cfun->stack_alignment_needed = 128;
 
-  fntype = TREE_TYPE (current_function_decl);
-  stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
-	      && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
-		  != void_type_node));
-
-  /* For varargs, we do not want to skip the dummy va_dcl argument.
-     For stdargs, we do want to skip the last named argument.  */
-  next_cum = *cum;
-  if (stdarg_p)
-    function_arg_advance (&next_cum, mode, type, 1);
-
-  if (!no_rtl)
-    save_area = frame_pointer_rtx;
-
+  save_area = frame_pointer_rtx;
   set = get_varargs_alias_set ();
 
-  for (i = next_cum.regno;
+  for (i = cum->regno;
        i < ix86_regparm
-       && i < next_cum.regno + cfun->va_list_gpr_size / UNITS_PER_WORD;
+       && i < cum->regno + cfun->va_list_gpr_size / UNITS_PER_WORD;
        i++)
     {
       mem = gen_rtx_MEM (Pmode,
@@ -4632,7 +4748,7 @@ ix86_setup_incoming_varargs (CUMULATIVE_
 					x86_64_int_parameter_registers[i]));
     }
 
-  if (next_cum.sse_nregs && cfun->va_list_fpr_size)
+  if (cum->sse_nregs && cfun->va_list_fpr_size)
     {
       /* Now emit code to save SSE registers.  The AX parameter contains number
 	 of SSE parameter registers used to call this function.  We use
@@ -4650,13 +4766,13 @@ ix86_setup_incoming_varargs (CUMULATIVE_
       emit_insn (gen_rtx_SET (VOIDmode, tmp_reg,
 			      gen_rtx_MULT (Pmode, nsse_reg,
 					    GEN_INT (4))));
-      if (next_cum.sse_regno)
+      if (cum->sse_regno)
 	emit_move_insn
 	  (nsse_reg,
 	   gen_rtx_CONST (DImode,
 			  gen_rtx_PLUS (DImode,
 					label_ref,
-					GEN_INT (next_cum.sse_regno * 4))));
+					GEN_INT (cum->sse_regno * 4))));
       else
 	emit_move_insn (nsse_reg, label_ref);
       emit_insn (gen_subdi3 (nsse_reg, nsse_reg, tmp_reg));
@@ -4675,9 +4791,62 @@ ix86_setup_incoming_varargs (CUMULATIVE_
 
       /* And finally do the dirty job!  */
       emit_insn (gen_sse_prologue_save (mem, nsse_reg,
-					GEN_INT (next_cum.sse_regno), label));
+					GEN_INT (cum->sse_regno), label));
+    }
+}
+
+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)
+{
+  CUMULATIVE_ARGS next_cum;
+  tree fntype;
+  int stdarg_p;
+
+  /* This argument doesn't appear to be used anymore.  Which is good,
+     because the old code here didn't suppress rtl generation.  */
+  gcc_assert (!no_rtl);
+
+  if (!TARGET_64BIT)
+    return;
+
+  fntype = TREE_TYPE (current_function_decl);
+  stdarg_p = (TYPE_ARG_TYPES (fntype) != 0
+	      && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
+		  != void_type_node));
+
+  /* For varargs, we do not want to skip the dummy va_dcl argument.
+     For stdargs, we do want to skip the last named argument.  */
+  next_cum = *cum;
+  if (stdarg_p)
+    function_arg_advance (&next_cum, mode, type, 1);
 
+  if (TARGET_64BIT_MS_ABI)
+    setup_incoming_varargs_ms_64 (&next_cum);
+  else
+    setup_incoming_varargs_64 (&next_cum);
 }
 
 /* Implement va_start.  */
@@ -4691,7 +4860,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;
@@ -4713,10 +4882,6 @@ ix86_va_start (tree valist, rtx nextarg)
   n_gpr = current_function_args_info.regno;
   n_fpr = current_function_args_info.sse_regno;
 
-  if (TARGET_DEBUG_ARG)
-    fprintf (stderr, "va_start: words = %d, n_gpr = %d, n_fpr = %d\n",
-	     (int) words, (int) n_gpr, (int) n_fpr);
-
   if (cfun->va_list_gpr_size)
     {
       type = TREE_TYPE (gpr);
@@ -4774,7 +4939,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));
@@ -5966,16 +6131,21 @@ 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));
@@ -5996,7 +6166,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));
 	}
     }
 
@@ -6250,7 +6420,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));
@@ -6713,6 +6883,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:
@@ -7092,7 +7266,7 @@ legitimate_address_p (enum machine_mode 
 \f
 /* 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;
@@ -7138,6 +7312,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))
@@ -7729,7 +7910,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;
 
@@ -9464,7 +9646,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.  */
@@ -19577,37 +19758,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.  */
@@ -19696,7 +19869,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);
 	}
--- gcc/config/i386/i386.h	(revision 123123)
+++ 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 {
@@ -374,6 +375,9 @@ extern int x86_prefetch_sse;
    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 +999,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 123123)
+++ gcc/config/i386/i386.md	(local)
@@ -19636,7 +19636,7 @@
    (set_attr "mode" "DI")])
 
 (define_expand "allocate_stack_worker"
-  [(match_operand:SI 0 "register_operand" "")]
+  [(match_operand 0 "register_operand" "")]
   "TARGET_STACK_PROBE"
 {
   if (reload_completed)
@@ -19697,23 +19697,23 @@
   "")
 
 (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])
       && INTVAL (operands[1]) < CHECK_STACK_LIMIT)
-    emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
-			   operands[1]));
+    {
+      rtx 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,
+    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (Pmode,
 							    operands[1])));
 
   emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
--- gcc/config/i386/mingw32.h	(revision 123123)
+++ 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 123123)
+++ 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/winnt.c	(revision 123123)
+++ 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/iq2000/iq2000.h	(revision 123123)
+++ gcc/config/iq2000/iq2000.h	(local)
@@ -375,7 +375,7 @@ enum reg_class
 
 #define REG_PARM_STACK_SPACE(FNDECL) 0
 
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) 0
 
--- gcc/config/mips/mips.h	(revision 123123)
+++ gcc/config/mips/mips.h	(local)
@@ -1807,7 +1807,7 @@ extern const enum reg_class mips_regno_t
    If `ACCUMULATE_OUTGOING_ARGS' is also defined, the only effect
    of this macro is to determine whether the space is included in
    `current_function_outgoing_args_size'.  */
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 #define STACK_BOUNDARY (TARGET_NEWABI ? 128 : 64)
 \f
--- gcc/config/mn10300/mn10300.h	(revision 123123)
+++ gcc/config/mn10300/mn10300.h	(local)
@@ -529,7 +529,7 @@ enum reg_class {
 /* We use d0/d1 for passing parameters, so allocate 8 bytes of space
    for a register flushback area.  */
 #define REG_PARM_STACK_SPACE(DECL) 8
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 #define ACCUMULATE_OUTGOING_ARGS 1
 
 /* So we can allocate space for return pointers once for the function
--- gcc/config/mt/mt.h	(revision 123123)
+++ gcc/config/mt/mt.h	(local)
@@ -533,7 +533,7 @@ extern struct mt_frame_info current_fram
 
 /* Define this if it is the responsibility of the caller to
    allocate the area reserved for arguments passed in registers.  */
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 /* The number of register assigned to holding function arguments.  */
 #define MT_NUM_ARG_REGS        4
--- gcc/config/pa/pa.h	(revision 123123)
+++ gcc/config/pa/pa.h	(local)
@@ -602,7 +602,7 @@ extern struct rtx_def *hppa_pic_save_rtx
 
 /* Define this if the above stack space is to be considered part of the
    space allocated by the caller.  */
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 /* Keep the stack pointer constant throughout the function.
    This is both an optimization and a necessity: longjmp
--- gcc/config/rs6000/rs6000.h	(revision 123123)
+++ gcc/config/rs6000/rs6000.h	(local)
@@ -1277,7 +1277,7 @@ extern enum rs6000_abi rs6000_current_ab
 
 /* Define this if the above stack space is to be considered part of the
    space allocated by the caller.  */
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 /* This is the difference between the logical top of stack and the actual sp.
 
--- gcc/config/score/score.h	(revision 123123)
+++ gcc/config/score/score.h	(local)
@@ -534,7 +534,7 @@ enum reg_class
    If `ACCUMULATE_OUTGOING_ARGS' is also defined, the only effect
    of this macro is to determine whether the space is included in
    `current_function_outgoing_args_size'.  */
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 #define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
 
--- gcc/config/spu/spu.h	(revision 123123)
+++ gcc/config/spu/spu.h	(local)
@@ -337,7 +337,7 @@ targetm.resolve_overloaded_builtin = spu
 
 #define REG_PARM_STACK_SPACE(FNDECL) 0
 
-#define OUTGOING_REG_PARM_STACK_SPACE 
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 #define RETURN_POPS_ARGS(FUNDECL,FUNTYPE,SIZE) (0)
 
--- gcc/config/v850/v850.h	(revision 123123)
+++ gcc/config/v850/v850.h	(local)
@@ -626,7 +626,7 @@ struct cum_arg { int nbytes; int anonymo
 
 /* Define this if the above stack space is to be considered part of the
    space allocated by the caller.  */
-#define OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 1
 
 /* 1 if N is a possible register number for function argument passing.  */
 
--- gcc/config.build	(revision 123123)
+++ 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 123123)
+++ 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 123123)
+++ 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 123123)
+++ gcc/doc/tm.texi	(local)
@@ -3730,7 +3730,7 @@ which.
 @c something, not sure if it looks good.  --mew 10feb93
 
 @defmac OUTGOING_REG_PARM_STACK_SPACE
-Define this if it is the responsibility of the caller to allocate the area
+Define this to one if it is the responsibility of the caller to allocate the area
 reserved for arguments passed in registers.
 
 If @code{ACCUMULATE_OUTGOING_ARGS} is defined, this macro controls
@@ -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/expr.c	(revision 123123)
+++ gcc/expr.c	(local)
@@ -54,6 +54,10 @@ Software Foundation, 51 Franklin Street,
 #include "target.h"
 #include "timevar.h"
 
+#ifndef OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 0
+#endif
+
 /* Decide whether a function's arguments should be processed
    from first to last or from last to first.
 
@@ -1237,8 +1241,8 @@ block_move_libcall_safe_for_call_parm (v
 
   /* If registers go on the stack anyway, any argument is sure to clobber
      an outgoing argument.  */
-#if defined (REG_PARM_STACK_SPACE) && defined (OUTGOING_REG_PARM_STACK_SPACE)
-  {
+#if defined (REG_PARM_STACK_SPACE)
+  if(OUTGOING_REG_PARM_STACK_SPACE) {
     tree fn = emit_block_move_libcall_fn (false);
     (void) fn;
     if (REG_PARM_STACK_SPACE (fn) != 0)
--- gcc/function.c	(revision 123123)
+++ gcc/function.c	(local)
@@ -65,6 +65,11 @@ Software Foundation, 51 Franklin Street,
 #include "predict.h"
 #include "vecprim.h"
 
+#ifndef OUTGOING_REG_PARM_STACK_SPACE
+#define OUTGOING_REG_PARM_STACK_SPACE 0
+#endif
+
+
 #ifndef LOCAL_ALIGNMENT
 #define LOCAL_ALIGNMENT(TYPE, ALIGNMENT) ALIGNMENT
 #endif
@@ -1211,12 +1216,12 @@ static int cfa_offset;
    `current_function_outgoing_args_size'.  Nevertheless, we must allow
    for it when allocating stack dynamic objects.  */
 
-#if defined(REG_PARM_STACK_SPACE) && ! defined(OUTGOING_REG_PARM_STACK_SPACE)
+#if defined(REG_PARM_STACK_SPACE)
 #define STACK_DYNAMIC_OFFSET(FNDECL)	\
 ((ACCUMULATE_OUTGOING_ARGS						      \
-  ? (current_function_outgoing_args_size + REG_PARM_STACK_SPACE (FNDECL)) : 0)\
- + (STACK_POINTER_OFFSET))						      \
-
+  ? (current_function_outgoing_args_size				      \
+     + (OUTGOING_REG_PARM_STACK_SPACE ? 0 : REG_PARM_STACK_SPACE (FNDECL)))   \
+  : 0) + (STACK_POINTER_OFFSET))
 #else
 #define STACK_DYNAMIC_OFFSET(FNDECL)	\
 ((ACCUMULATE_OUTGOING_ARGS ? current_function_outgoing_args_size : 0)	      \

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised x86_64-pc-mingw32 patch
  2007-03-22  0:33 ` revised x86_64-pc-mingw32 patch Richard Henderson
@ 2007-03-22 13:02   ` Kai Tietz
  2007-03-22 17:43     ` Richard Henderson
  2007-03-27 13:13   ` Kai Tietz
  2007-03-27 23:48   ` revised**2 " Richard Henderson
  2 siblings, 1 reply; 33+ messages in thread
From: Kai Tietz @ 2007-03-22 13:02 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches

Richard Henderson <rth@redhat.com> wrote on 22.03.2007 01:15:34:

> Try the following patch.  It fixes up the calling abi problems,
> and gives a stab at fixing the flag_pic sorts of problems.

Thanks, I am currently on to merge and test.

> I do have one question: can I assume that given
> 
>   extern int i;
>   int f(void) { return i; }
> 
> that "i" *cannot* be resolved from a dllimport?  If not,
> what does VC++ do with the generated code?

Yes the variable i can not be resolved by MS from a dllimport. If you 
would write
   extern __declspec(dllimport) int i;
   int f(void) { return i; }
than it is getting resolved.
If you use something like
   extern __declspec(dllimport) int i;
   int *my_i_ptr = &i;
   int f(void) { return *my_i_ptr; }

MS packs the initialization code for that into the pdata section and marks 
the initialization method within CRT$XCU (crt startup section executed by 
terminit) section, too.

I Noticed, that you disabled the TARGET_DEBUG_ARG if-case in funtion in 
init_cumulative_args. Was this by intension done ?

Regards,
 i.A. Kai Tietz

------------------------------------------------------------------------------------------
  OneVision Software Entwicklungs GmbH & Co. KG
  Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg
  Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com
  Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050
  Handelsregister: HRA 6744, Amtsgericht Regensburg
  Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH
  Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg
  Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: 
Ulrike Döhler, Manuela Kluger



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised x86_64-pc-mingw32 patch
  2007-03-22 13:02   ` Kai Tietz
@ 2007-03-22 17:43     ` Richard Henderson
  2007-03-23 10:02       ` Kai Tietz
                         ` (2 more replies)
  0 siblings, 3 replies; 33+ messages in thread
From: Richard Henderson @ 2007-03-22 17:43 UTC (permalink / raw)
  To: Kai Tietz; +Cc: gcc-patches

On Thu, Mar 22, 2007 at 11:44:56AM +0100, Kai Tietz wrote:
> >   extern int i;
> >   int f(void) { return i; }
> > 
> > that "i" *cannot* be resolved from a dllimport?  If not,
> > what does VC++ do with the generated code?
> 
> Yes the variable i can not be resolved by MS from a dllimport.

Excellent.  This means that dllimport can be *significantly* 
cleaned up in the gcc port.

> If you use something like
>    extern __declspec(dllimport) int i;
>    int *my_i_ptr = &i;
>    int f(void) { return *my_i_ptr; }
> 
> MS packs the initialization code for that into the pdata section and marks 
> the initialization method within CRT$XCU (crt startup section executed by 
> terminit) section, too.

Interesting.  I'll have to think about this one.  Presumably our
existing constructor support for mingw uses the same method?

> I Noticed, that you disabled the TARGET_DEBUG_ARG if-case in funtion in 
> init_cumulative_args. Was this by intension done ?

Yeah, I think such debuggings are pretty pointless.  It's far easier
to just run the compiler under gdb.


r~

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised x86_64-pc-mingw32 patch
  2007-03-22 17:43     ` Richard Henderson
@ 2007-03-23 10:02       ` Kai Tietz
  2007-03-23 15:51         ` Richard Henderson
  2007-03-23 13:48       ` Kai Tietz
  2007-03-26 10:55       ` Kai Tietz
  2 siblings, 1 reply; 33+ messages in thread
From: Kai Tietz @ 2007-03-23 10:02 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches

Hi,

I found current the following problems in your revised patch.
1) in function_arg_advance_ms_64: The XF registers are not treated proper.
  It seems, that the reuse of examine_argument for the ms abi - as I did - 
does it better. the SSE register
  treating isn't that easy for x86_64 ms abi case as assumed.
2) legitimize_pic_address: The case for TARGET_64BIT_MS_ABI is wrong.
3) Defaulting for x86_regparm has always to be REGPARM_MAX for this target

I am currently on to fix the calling convention issue and then prepare an 
updated patch for it.

Cheers,
 i.A. Kai Tietz

------------------------------------------------------------------------------------------
  OneVision Software Entwicklungs GmbH & Co. KG
  Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg
  Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com
  Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050
  Handelsregister: HRA 6744, Amtsgericht Regensburg
  Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH
  Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg
  Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: 
Ulrike Döhler, Manuela Kluger


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised x86_64-pc-mingw32 patch
  2007-03-22 17:43     ` Richard Henderson
  2007-03-23 10:02       ` Kai Tietz
@ 2007-03-23 13:48       ` Kai Tietz
  2007-03-26 10:55       ` Kai Tietz
  2 siblings, 0 replies; 33+ messages in thread
From: Kai Tietz @ 2007-03-23 13:48 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches

I found another problem with activation MASK_STACK_PROBE. Somewhere still 
a SImode occures which leads to an assert in expr.c:327.

Regards,
 i.A. Kai Tietz

------------------------------------------------------------------------------------------
  OneVision Software Entwicklungs GmbH & Co. KG
  Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg
  Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com
  Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050
  Handelsregister: HRA 6744, Amtsgericht Regensburg
  Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH
  Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg
  Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: 
Ulrike Döhler, Manuela Kluger


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised x86_64-pc-mingw32 patch
  2007-03-23 10:02       ` Kai Tietz
@ 2007-03-23 15:51         ` Richard Henderson
  2007-03-26 10:23           ` Kai Tietz
  2007-03-26 11:24           ` Kai Tietz
  0 siblings, 2 replies; 33+ messages in thread
From: Richard Henderson @ 2007-03-23 15:51 UTC (permalink / raw)
  To: Kai Tietz; +Cc: gcc-patches

On Fri, Mar 23, 2007 at 10:02:37AM +0100, Kai Tietz wrote:
> 1) in function_arg_advance_ms_64: The XF registers are not treated proper.

The MSDN documentation doesn't mention XFmode arguments at all.
You'll notice all the ??? comments to that effect in the code.

Are we mistaken in defining "long double" as XFmode?  Should it
in fact be DFmode, just like plain double?  Certainly the documented
default 64-bit rounding mode in the fpcr makes an XFmode long double
less than useful...

>   It seems, that the reuse of examine_argument for the ms abi - as I did - 
> does it better.  the SSE register treating isn't that easy for x86_64 ms
> abi case as assumed.

Nonsense.

> 2) legitimize_pic_address: The case for TARGET_64BIT_MS_ABI is wrong.

Yes, that's a hack.  I plan to rewrite dllimport handling for both
32 and 64-bit from scratch.

> 3) Defaulting for x86_regparm has always to be REGPARM_MAX for this target

... which I did for all 64-bit targets?  Why is this a bullet point?



r~

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised x86_64-pc-mingw32 patch
  2007-03-23 15:51         ` Richard Henderson
@ 2007-03-26 10:23           ` Kai Tietz
  2007-03-26 11:24           ` Kai Tietz
  1 sibling, 0 replies; 33+ messages in thread
From: Kai Tietz @ 2007-03-26 10:23 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches

Richard Henderson <rth@redhat.com> wrote on 23.03.2007 15:27:56:

> On Fri, Mar 23, 2007 at 10:02:37AM +0100, Kai Tietz wrote:
> > 1) in function_arg_advance_ms_64: The XF registers are not treated 
proper.
> 
> The MSDN documentation doesn't mention XFmode arguments at all.
> You'll notice all the ??? comments to that effect in the code.
> 
> Are we mistaken in defining "long double" as XFmode?  Should it
> in fact be DFmode, just like plain double?  Certainly the documented
> default 64-bit rounding mode in the fpcr makes an XFmode long double
> less than useful...

You are right, that the type "long double" is not defined by MS as a 
XFmode, it is a DFmode. But this was even true for 32-bit ABI, too. The 
mingw spend some effort to support the "long double" type as XFmode and 
for certain, this is not really MS compatible, but very helpful for math 
precision. Under 64-bit windows the x87 fpu and the MMX seem not to be 
used in ABI anymore. In MS doc it is even mentioned, that the use of them 
is forbidden in kernel mode applications and there is even no standard 
calling convention for these kind of registers as far as to read from 
MSDN.

> > 2) legitimize_pic_address: The case for TARGET_64BIT_MS_ABI is wrong.
> 
> Yes, that's a hack.  I plan to rewrite dllimport handling for both
> 32 and 64-bit from scratch.

> > 3) Defaulting for x86_regparm has always to be REGPARM_MAX for this 
target
> 
> ... which I did for all 64-bit targets?  Why is this a bullet point?
There is a warning for trying to set regparm, but a fallthrough ...

Also I noticed, that to any symbol "@GOTPCREL" is appended, which seems to 
be not proper for this target. I think this suffix simply shouldn't be 
emitted for this target.

If you are interested, I can provide you a header-set for 
x86_64-pc-mingw32 for test cases.

Regards,
 i.A. Kai Tietz

------------------------------------------------------------------------------------------
  OneVision Software Entwicklungs GmbH & Co. KG
  Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg
  Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com
  Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050
  Handelsregister: HRA 6744, Amtsgericht Regensburg
  Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH
  Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg
  Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: 
Ulrike Döhler, Manuela Kluger


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised x86_64-pc-mingw32 patch
  2007-03-22 17:43     ` Richard Henderson
  2007-03-23 10:02       ` Kai Tietz
  2007-03-23 13:48       ` Kai Tietz
@ 2007-03-26 10:55       ` Kai Tietz
  2 siblings, 0 replies; 33+ messages in thread
From: Kai Tietz @ 2007-03-26 10:55 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches

Hi,

The @GOTPCREL can not be used for currently for x86_64 minw32, because 
this target does not use elf-objects and gas supports this just for elf. 
May we could use therefore something as $(sym - .) instead of @GOTPCREL, 
or enable in gas the GOTPCREL keyword for coff (pe) objects.

Regards,
 i.A. Kai Tietz

------------------------------------------------------------------------------------------
  OneVision Software Entwicklungs GmbH & Co. KG
  Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg
  Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com
  Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050
  Handelsregister: HRA 6744, Amtsgericht Regensburg
  Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH
  Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg
  Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: 
Ulrike Döhler, Manuela Kluger


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised x86_64-pc-mingw32 patch
  2007-03-23 15:51         ` Richard Henderson
  2007-03-26 10:23           ` Kai Tietz
@ 2007-03-26 11:24           ` Kai Tietz
  1 sibling, 0 replies; 33+ messages in thread
From: Kai Tietz @ 2007-03-26 11:24 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches

Hi,

That the "pic" code generation is choosen, is a mistake, AFAIS. PE is 
position idenpendent. For 32-bit abi pic and PIC was allready turned off 
by this reason. See in cygming.h the subtraget overide option. Therefore 
the code model should be simply CM_SMALL and flag_pic should remain off. 

Regards,
 i.A. Kai Tietz

------------------------------------------------------------------------------------------
  OneVision Software Entwicklungs GmbH & Co. KG
  Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg
  Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com
  Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050
  Handelsregister: HRA 6744, Amtsgericht Regensburg
  Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH
  Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg
  Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: 
Ulrike Döhler, Manuela Kluger


^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised x86_64-pc-mingw32 patch
  2007-03-22  0:33 ` revised x86_64-pc-mingw32 patch Richard Henderson
  2007-03-22 13:02   ` Kai Tietz
@ 2007-03-27 13:13   ` Kai Tietz
  2007-03-27 16:07     ` Richard Henderson
  2007-03-27 23:48   ` revised**2 " Richard Henderson
  2 siblings, 1 reply; 33+ messages in thread
From: Kai Tietz @ 2007-03-27 13:13 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 1861 bytes --]

Richard Henderson <rth@redhat.com> wrote on 22.03.2007 01:15:34:

> Try the following patch.  It fixes up the calling abi problems,
> and gives a stab at fixing the flag_pic sorts of problems.
 
I tried your patch with a mingw64 runtime and had especially problems on 
floatings. Therefore I suggest the following code as replacement for 
yours. I built as cross on i386-linux and i386-cygwin and it seems to work 
fine.

The use of pic seems to be producing problems by the @GOTPCREL prefix, 
which the coff version of gas does not understand. But AFAIS we need not 
producing pic code, because coff (PE) is by architecture position 
independent. Just the patch in i386.md is necessary for having memonics 
with size to be relocated by PE loader.

The register calling convention is may easier than my suggested code looks 
like. May this can be eased dramatically, but this  adopted code of 
existing x86_64 ABI code solved all the floating point failures I had. 

I added the prototype for "ix86_GOT_alias_set" into i386-protos.h.

I think too, that it is worth to investigate for real pic code for minw32 
(without base relocations), but may we should first introducing this new 
mingw32 target ?

Regards,
 i.A. Kai Tietz

------------------------------------------------------------------------------------------
  OneVision Software Entwicklungs GmbH & Co. KG
  Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg
  Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com
  Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050
  Handelsregister: HRA 6744, Amtsgericht Regensburg
  Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH
  Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg
  Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: 
Ulrike Döhler, Manuela Kluger



[-- Attachment #2: diff_gcc_mingw.txt --]
[-- Type: text/plain, Size: 45682 bytes --]

Index: doc/tm.texi
===================================================================
--- doc/tm.texi	(revision 123255)
+++ doc/tm.texi	(working copy)
@@ -9719,6 +9719,18 @@
 @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
Index: testsuite/gcc.dg/pragma-push_pop_macro.c
===================================================================
--- testsuite/gcc.dg/pragma-push_pop_macro.c	(revision 0)
+++ testsuite/gcc.dg/pragma-push_pop_macro.c	(revision 0)
@@ -0,0 +1,20 @@
+/* Prove that HANDLE_PRAGMA_PUSH_POP_MACRO handling works somewhat. */
+
+/* { dg-do run { target *-*-mingw* } } */
+
+extern void abort (void);
+
+#define TEXT1	"ABC"
+#define TEXT2	"DEF"
+
+main()
+{
+	if( sizeof( TEXT1 TEXT2 ) != 7) abort();
+#pragma push_macro("TEXT1")
+#undef TEXT1
+#define TEXT1	"ABCD"
+	if( sizeof( TEXT1 TEXT2 ) != 8)  abort()
+#pragma pop_macro("TEXT1")
+	if( sizeof( TEXT1 TEXT2 ) != 7)  abort()
+	return 0;
+}

Property changes on: testsuite/gcc.dg/pragma-push_pop_macro.c
___________________________________________________________________
Name: svn:executable
   + *

Index: c-pragma.c
===================================================================
--- c-pragma.c	(revision 123255)
+++ c-pragma.c	(working copy)
@@ -53,6 +53,20 @@
 
 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 def_pushpop_macro GTY(())
+{
+  char *name;
+  char *value;
+  struct def_pushpop_macro *prev;
+} def_pushpop_macro;
+static GTY(()) struct def_pushpop_macro *pushpop_macro_list = NULL;
+
+
 #ifdef HANDLE_PRAGMA_PACK
 static void handle_pragma_pack (cpp_reader *);
 
@@ -132,6 +146,157 @@
     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%>");
+          
+          /* Eat rest of line to prevent insertation errors.  */
+          while(pragma_lex (&x) != CPP_EOF)
+            ;
+        }
+    }
+  if (id)
+    {
+      def_pushpop_macro *c;
+      const char *macroname;
+      
+      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 = (def_pushpop_macro *) ggc_alloc (sizeof (def_pushpop_macro) + 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 = pushpop_macro_list;
+          pushpop_macro_list = c;
+        }
+      else
+        {
+          c = (def_pushpop_macro *) ggc_alloc (sizeof (def_pushpop_macro) + strlen (macroname) + 4);
+          c->name = (char*) &c[1];
+          c->value = NULL;
+          strcpy (c->name, macroname);
+          c->prev = pushpop_macro_list;
+          pushpop_macro_list = 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");
+
+          /* Eat rest of line to prevent insertation errors.  */
+          while(pragma_lex (&x) != CPP_EOF)
+            ;
+        }
+      else if (pragma_lex (&x) != CPP_EOF)
+        {
+          warning (OPT_Wpragmas, "junk at end of %<#pragma pop_macro%>");
+
+          /* Eat rest of line to prevent insertation errors.  */
+          while(pragma_lex (&x) != CPP_EOF)
+            ;
+        }
+    }
+  if (id)
+    {
+      def_pushpop_macro *p, *c;
+      const char *macroname;
+
+      p = NULL;
+      c = pushpop_macro_list;
+      macroname = TREE_STRING_POINTER (id);
+
+      while(c != NULL)
+        {
+          if (!strcmp (macroname, c->name))
+            {
+              char *s = alloca (strlen ("\n\n#undef %s\n") + strlen (c->name) + (c->value ? strlen(c->value) : 0) +
+			        strlen ("#define %s\n") + 1);
+              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)
+                pushpop_macro_list = 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 +984,10 @@
   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
Index: config.gcc
===================================================================
--- config.gcc	(revision 123255)
+++ config.gcc	(working copy)
@@ -1343,7 +1343,7 @@
 		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"
Index: config.host
===================================================================
--- config.host	(revision 123255)
+++ config.host	(working copy)
@@ -168,7 +168,7 @@
     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
Index: unwind-generic.h
===================================================================
--- unwind-generic.h	(revision 123255)
+++ unwind-generic.h	(working copy)
@@ -252,8 +252,13 @@
   typedef long long _sleb128_t;
   typedef unsigned long long _uleb128_t;
 #else
+#ifdef _WIN64
+  typedef long long _sleb128_t;
+  typedef unsigned long long _uleb128_t;
+#else
   #error "long long data type is needed to define _sleb128_t"
 #endif
+#endif
 #else
   typedef long _sleb128_t;
   typedef unsigned long _uleb128_t;
Index: config/i386/i386.h
===================================================================
--- config/i386/i386.h	(revision 123255)
+++ config/i386/i386.h	(working copy)
@@ -374,6 +374,9 @@
    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
@@ -685,7 +688,7 @@
 #define SHORT_TYPE_SIZE 16
 #define INT_TYPE_SIZE 32
 #define FLOAT_TYPE_SIZE 32
-#define LONG_TYPE_SIZE BITS_PER_WORD
+#define LONG_TYPE_SIZE (TARGET_64BIT_MS_ABI ? 32 : BITS_PER_WORD)
 #define DOUBLE_TYPE_SIZE 64
 #define LONG_LONG_TYPE_SIZE 64
 
@@ -848,6 +851,9 @@
    || ((MODE) == DFmode && (!TARGET_SSE2 || !TARGET_SSE_MATH))  \
    || (MODE) == XFmode)
 
+#undef STACK_SIZE_MODE
+#define STACK_SIZE_MODE Pmode
+
 /* Number of actual hardware registers.
    The hardware registers are assigned numbers for the compiler
    from 0 to just below FIRST_PSEUDO_REGISTER.
@@ -995,6 +1001,11 @@
 	for (i = FIRST_REX_SSE_REG; i <= LAST_REX_SSE_REG; i++)		\
 	  reg_names[i] = "";						\
       }									\
+    else 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
@@ -1527,7 +1538,8 @@
    This space can be allocated by the caller, or be a part of the
    machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says
    which.  */
-#define REG_PARM_STACK_SPACE(FNDECL) 0
+#define REG_PARM_STACK_SPACE(FNDECL) (TARGET_64BIT_MS_ABI ? 32 : 0)
+#define OUTGOING_REG_PARM_STACK_SPACE (TARGET_64BIT_MS_ABI ? 1 : 0)
 
 /* Value is the number of bytes of arguments automatically
    popped when returning from a subroutine call.
@@ -1860,9 +1872,9 @@
    is also used as the pic register in ELF.  So for now, don't allow more than
    3 registers to be passed in registers.  */
 
-#define REGPARM_MAX (TARGET_64BIT ? 6 : 3)
+#define REGPARM_MAX (TARGET_64BIT ? (TARGET_64BIT_MS_ABI ? 4 : 6) : 3)
 
-#define SSE_REGPARM_MAX (TARGET_64BIT ? 8 : (TARGET_SSE ? 3 : 0))
+#define SSE_REGPARM_MAX (TARGET_64BIT ? (TARGET_64BIT_MS_ABI ? 4 : 8) : (TARGET_SSE ? 3 : 0))
 
 #define MMX_REGPARM_MAX (TARGET_64BIT ? 0 : (TARGET_MMX ? 3 : 0))
 
@@ -1870,7 +1882,7 @@
 /* Specify the machine mode that this machine uses
    for the index in the tablejump instruction.  */
 #define CASE_VECTOR_MODE \
- (!TARGET_64BIT || (flag_pic && ix86_cmodel != CM_LARGE_PIC) ? SImode : DImode)
+ (!TARGET_64BIT || (flag_pic && ix86_cmodel != CM_LARGE_PIC && !TARGET_64BIT_MS_ABI) ? SImode : DImode)
 
 /* Define this as 1 if `char' should by default be signed; else as 0.  */
 #define DEFAULT_SIGNED_CHAR 1
Index: config/i386/cygming.h
===================================================================
--- config/i386/cygming.h	(revision 123255)
+++ config/i386/cygming.h	(working copy)
@@ -21,18 +21,34 @@
 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
 
 #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])
+                                ? (TARGET_64BIT ? dbx64_register_map[n] \
+                                   : svr4_dbx_register_map[n]) \
+                                : (TARGET_64BIT ? dbx64_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,15 +113,22 @@
 #undef MATH_LIBRARY
 #define MATH_LIBRARY ""
 
-#define SIZE_TYPE "unsigned int"
-#define PTRDIFF_TYPE "int"
+#undef TARGET_64BIT_MS_ABI
+#define TARGET_64BIT_MS_ABI TARGET_64BIT
+
+#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"
+#define POINTER_SIZE (TARGET_64BIT ? 64 : 32)
 
 \f
 /* 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 *
 \f
@@ -195,9 +218,13 @@
    We also align doubles to 64-bits for MSVC default compatibility.  */
 
 #undef TARGET_SUBTARGET_DEFAULT
+#if TARGET_64BIT_DEFAULT
 #define TARGET_SUBTARGET_DEFAULT \
-   (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE \
-    | MASK_ALIGN_DOUBLE)
+  (MASK_64BIT | MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS /* | MASK_STACK_PROBE */)
+#else
+#define TARGET_SUBTARGET_DEFAULT \
+  (MASK_80387 | MASK_IEEE_FP | MASK_FLOAT_RETURNS | MASK_STACK_PROBE | MASK_ALIGN_DOUBLE)
+#endif
 
 /* This is how to output an assembler line
    that says to advance the location counter
@@ -266,7 +293,9 @@
 /* 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 +404,8 @@
 #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
Index: config/i386/i386.md
===================================================================
--- config/i386/i386.md	(revision 123255)
+++ config/i386/i386.md	(working copy)
@@ -2047,7 +2047,7 @@
 
     default:
       gcc_assert (!flag_pic || LEGITIMATE_PIC_OPERAND_P (operands[1]));
-      if (get_attr_mode (insn) == MODE_SI)
+      if (get_attr_mode (insn) == MODE_SI && !TARGET_64BIT_MS_ABI)
 	return "mov{l}\t{%k1, %k0|%k0, %k1}";
       else if (which_alternative == 2)
 	return "movabs{q}\t{%1, %0|%0, %1}";
@@ -19612,7 +19612,7 @@
    (set_attr "mode" "DI")])
 
 (define_expand "allocate_stack_worker"
-  [(match_operand:SI 0 "register_operand" "")]
+  [(match_operand 0 "register_operand" "")]
   "TARGET_STACK_PROBE"
 {
   if (reload_completed)
@@ -19673,24 +19673,24 @@
   "")
 
 (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])
       && INTVAL (operands[1]) < CHECK_STACK_LIMIT)
-    emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
-			   operands[1]));
+    {
+      rtx 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])));
+    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (Pmode,
+					 		    operands[1])));
 
   emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
   DONE;
Index: config/i386/cygwin.asm
===================================================================
--- config/i386/cygwin.asm	(revision 123255)
+++ config/i386/cygwin.asm	(working copy)
@@ -44,6 +44,7 @@
 	.global	__alloca
 ___chkstk:
 __alloca:
+#ifndef _WIN64
 	pushl  %ecx		/* save temp */
 	movl   %esp,%ecx	/* get sp */
 	addl   $0x8,%ecx	/* and point to return addr */
@@ -65,4 +66,27 @@
 	movl   (%eax),%ecx	/* recover saved temp */
 	movl   4(%eax),%eax	/* get return address */
 	jmp    *%eax	
+#else
+	movq   %rdx,%r10        /* save temp */
+	movq   %rsp,%rdx	/* get sp */
+	addq   $0x10,%rdx	/* and point to return addr */
+
+probe: 	cmpq   $0x1000,%rcx	/* > 4k ?*/
+	jb    done
+
+	subq   $0x1000,%rdx  		/* yes, move pointer down 4k*/
+	orq    $0x0,(%rdx)   		/* probe there */
+	subq   $0x1000,%rcx  	 	/* decrement count */
+	jmp    probe           	 	/* and do it again */
+
+done: 	subq   %rcx,%rdx
+	orq    $0x0,(%rdx)	/* less that 4k, just peek here. Use quad to check high-byte too */
+
+	movq   %rsp,%rax
+	movq   %rdx,%rsp	/* decrement stack */
+
+	movq   %r10,%rdx	/* recover saved temp */
+	movq   (%rax),%rax	/* get return address */
+	jmp    *%rax	
 #endif
+#endif
Index: config/i386/predicates.md
===================================================================
--- config/i386/predicates.md	(revision 123255)
+++ config/i386/predicates.md	(working copy)
@@ -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 || TARGET_64BIT_MS_ABI || !flag_pic")
     (match_operand 0 "nonmemory_operand")
     (ior (match_operand 0 "register_operand")
 	 (and (match_operand 0 "const_double_operand")
Index: config/i386/winnt.c
===================================================================
--- config/i386/winnt.c	(revision 123255)
+++ config/i386/winnt.c	(working copy)
@@ -232,7 +232,11 @@
   idp = get_identifier (newname);
 
   symref = gen_rtx_SYMBOL_REF (Pmode, IDENTIFIER_POINTER (idp));
-  SET_SYMBOL_REF_DECL (symref, decl);
+  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) = symref;
 }
 
Index: config/i386/mingw32.h
===================================================================
--- config/i386/mingw32.h	(revision 123255)
+++ config/i386/mingw32.h	(working copy)
@@ -21,7 +21,11 @@
 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,28 @@
       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 +90,12 @@
 
 /* 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
@@ -109,6 +132,9 @@
 #undef WINT_TYPE
 #define WINT_TYPE "short unsigned int"
 
+#undef POINTER_SIZE
+#define POINTER_SIZE (TARGET_64BIT ? 64 : 32)
+
 /* mingw32 uses the  -mthreads option to enable thread support.  */
 #undef GOMP_SELF_SPECS
 #define GOMP_SELF_SPECS "%{fopenmp: -mthreads}"
Index: config/i386/i386-protos.h
===================================================================
--- config/i386/i386-protos.h	(revision 123255)
+++ config/i386/i386-protos.h	(working copy)
@@ -89,6 +89,7 @@
 extern int ix86_binary_operator_ok (enum rtx_code, enum machine_mode, rtx[]);
 extern void ix86_expand_unary_operator (enum rtx_code, enum machine_mode,
 					rtx[]);
+extern HOST_WIDE_INT ix86_GOT_alias_set (void);
 extern rtx ix86_build_const_vector (enum machine_mode, bool, rtx);
 extern void ix86_split_convert_uns_si_sse (rtx[]);
 extern void ix86_expand_convert_uns_didf_sse (rtx, rtx);
Index: config/i386/i386.c
===================================================================
--- config/i386/i386.c	(revision 123255)
+++ config/i386/i386.c	(working copy)
@@ -1304,9 +1304,15 @@
   FIRST_REX_INT_REG /*R8 */, FIRST_REX_INT_REG + 1 /*R9 */
 };
 
+static int const x86_64_ms_abi_int_parameter_registers[6] =
+{
+  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.  */
@@ -1851,7 +1857,17 @@
     {
       ix86_cmodel = CM_32;
       if (TARGET_64BIT)
-	ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
+	{
+	  if (TARGET_64BIT_MS_ABI)
+	    {
+	      ix86_cmodel = CM_SMALL; /* Seems to be wrong, should be CM_LARGE AFAICS */
+	      flag_pic = 0;
+	    }
+	  else
+	    {
+	      ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
+	    }
+	}
     }
   if (ix86_asm_string != 0)
     {
@@ -1973,11 +1989,19 @@
   /* Validate -mregparm= value.  */
   if (ix86_regparm_string)
     {
-      i = atoi (ix86_regparm_string);
-      if (i < 0 || i > REGPARM_MAX)
-	error ("-mregparm=%d is not between 0 and %d", i, REGPARM_MAX);
+      if (TARGET_64BIT_MS_ABI)
+	{
+	  warning (0, "-mregparm is ignored in mingw 64-bit mode");
+	  ix86_regparm = REGPARM_MAX;
+	}
       else
-	ix86_regparm = i;
+	{
+	  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)
@@ -2637,8 +2661,9 @@
 
   if (TARGET_64BIT)
     {
-      warning (OPT_Wattributes, "%qs attribute ignored",
-	       IDENTIFIER_POINTER (name));
+      if (!TARGET_64BIT_MS_ABI)
+        warning (OPT_Wattributes, "%qs attribute ignored",
+	         IDENTIFIER_POINTER (name));
       *no_add_attrs = true;
       return NULL_TREE;
     }
@@ -2925,6 +2950,7 @@
 ix86_function_arg_regno_p (int regno)
 {
   int i;
+  const int *parm_regs;
 
   if (!TARGET_64BIT)
     {
@@ -2952,11 +2978,16 @@
     }
 
   /* RAX is used as hidden argument to va_arg functions.  */
-  if (regno == 0)
+  if (!TARGET_64BIT_MS_ABI && !regno)
     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;
 }
@@ -2983,7 +3014,7 @@
 void
 init_cumulative_args (CUMULATIVE_ARGS *cum,  /* Argument info to initialize */
 		      tree fntype,	/* tree ptr for function decl */
-		      rtx libname,	/* SYMBOL_REF of library name or 0 */
+		      rtx libname ATTRIBUTE_UNUSED,  /* SYMBOL_REF of library name or 0 */
 		      tree fndecl)
 {
   memset (cum, 0, sizeof (*cum));
@@ -2996,7 +3027,7 @@
     cum->mmx_nregs = MMX_REGPARM_MAX;
   cum->warn_sse = true;
   cum->warn_mmx = true;
-  cum->maybe_vaarg = (fntype ? type_has_variadic_args_p (fntype) : !libname);
+  cum->maybe_vaarg = false;
 
   if (!TARGET_64BIT)
     {
@@ -3073,6 +3104,48 @@
   return mode;
 }
 
+static rtx
+gen_reg_or_parallel_ms_abi_64 (enum machine_mode mode, enum machine_mode orig_mode,
+		     unsigned int regno, unsigned int **intregs)
+{
+  rtx tmp;
+  if ((regno >= FIRST_SSE_REG && regno <= LAST_SSE_REG)
+      || (regno >= FIRST_MMX_REG && regno <= LAST_MMX_REG))
+    {
+      rtx tmp2;
+      unsigned int shadow_reg = **intregs; intregs[0]++;
+      enum machine_mode shadow_mode = (regno >= FIRST_SSE_REG && regno <= LAST_SSE_REG) ? DImode : SImode;
+      if (orig_mode != BLKmode)
+	{
+	  tmp = gen_rtx_REG (orig_mode, regno);
+	  tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp, const0_rtx);
+	  tmp2 = gen_rtx_REG (shadow_mode, shadow_reg);
+	  tmp2 = gen_rtx_EXPR_LIST (VOIDmode, tmp2, const0_rtx);
+	  tmp = gen_rtx_PARALLEL (orig_mode, gen_rtvec (2, tmp, tmp2));
+	}
+      else
+	{
+	  tmp = gen_rtx_REG (mode, regno);
+	  tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp, const0_rtx);
+	  tmp2 = gen_rtx_REG (shadow_mode, shadow_reg);
+	  tmp2 = gen_rtx_EXPR_LIST (VOIDmode, tmp2, const0_rtx);
+	  tmp = gen_rtx_PARALLEL (orig_mode, gen_rtvec (2, tmp, tmp2));
+	}
+      return tmp;
+    }
+  if (orig_mode != BLKmode)
+    tmp = gen_rtx_REG (orig_mode, regno);
+  else
+    {
+      tmp = gen_rtx_REG (mode, regno);
+      tmp = gen_rtx_EXPR_LIST (VOIDmode, tmp, const0_rtx);
+      tmp = gen_rtx_PARALLEL (orig_mode, gen_rtvec (1, tmp));
+    }
+
+  return tmp;
+}
+
+
 /* We want to pass a value in REGNO whose "natural" mode is MODE.  However,
    this may not agree with the mode that the type system has chosen for the
    register, which is ORIG_MODE.  If ORIG_MODE is not BLKmode, then we can
@@ -3466,6 +3539,200 @@
   return 1;
 }
 
+static int
+examine_argument_ms_abi_64 (enum machine_mode mode, tree type, int in_return,
+		  int *int_nregs)
+{
+  enum x86_64_reg_class class[MAX_CLASSES];
+  int n = classify_argument (mode, type, class, 0);
+
+  *int_nregs = 0;
+  if (!n)
+    return 0;
+  for (n--; n >= 0; n--)
+    switch (class[n])
+      {
+      case X86_64_INTEGER_CLASS:
+      case X86_64_INTEGERSI_CLASS:
+      case X86_64_SSE_CLASS:
+      case X86_64_SSESF_CLASS:
+      case X86_64_SSEDF_CLASS:
+	(*int_nregs)++;
+	break;
+      case X86_64_NO_CLASS:
+      case X86_64_SSEUP_CLASS:
+	break;
+      case X86_64_X87_CLASS:
+      case X86_64_X87UP_CLASS:
+	if (!in_return)
+	  return 0;
+	break;
+      case X86_64_COMPLEX_X87_CLASS:
+	return in_return ? 2 : 0;
+      case X86_64_MEMORY_CLASS:
+	gcc_unreachable ();
+      }
+  return 1;
+}
+
+/* Construct container for the argument used by GCC x64 ms abi interface.  See
+   FUNCTION_ARG for the detailed description.  */
+
+static rtx
+construct_container_ms_abi_64 (enum machine_mode mode, enum machine_mode orig_mode,
+		     tree type, int in_return, int nintregs,
+		     const int *intreg, int sse_regno)
+{
+  /* The following variables hold the static issued_error state.  */
+  static bool issued_x87_ret_error;
+
+  enum machine_mode tmpmode;
+  int bytes =
+    (mode == BLKmode) ? int_size_in_bytes (type) : (int) GET_MODE_SIZE (mode);
+  enum x86_64_reg_class class[MAX_CLASSES];
+  int n;
+  int i;
+  int nexps = 0;
+  int needed_intregs;
+  rtx exp[MAX_CLASSES*2];
+  rtx ret;
+
+  n = classify_argument (mode, type, class, 0);
+  if (!n)
+    return NULL;
+  if (!examine_argument_ms_abi_64 (mode, type, in_return, &needed_intregs))
+    return NULL;
+  if (needed_intregs > nintregs)
+    return NULL;
+
+  /* Likewise, error if the ABI requires us to return values in the
+     x87 registers and the user specified -mno-80387.  */
+  if (!TARGET_80387 && in_return)
+    for (i = 0; i < n; i++)
+      if (class[i] == X86_64_X87_CLASS
+	  || class[i] == X86_64_X87UP_CLASS
+	  || class[i] == X86_64_COMPLEX_X87_CLASS)
+	{
+	  if (!issued_x87_ret_error)
+	    {
+	      error ("x87 register return with x87 disabled");
+	      issued_x87_ret_error = true;
+	    }
+	  return NULL;
+	}
+
+  /* First construct simple cases.  Avoid SCmode, since we want to use
+     single register to pass this type.  */
+  if (n == 1 && mode != SCmode)
+    switch (class[0])
+      {
+      case X86_64_INTEGER_CLASS:
+      case X86_64_INTEGERSI_CLASS:
+	return gen_rtx_REG (mode, intreg[0]);
+      case X86_64_SSE_CLASS:
+      case X86_64_SSESF_CLASS:
+      case X86_64_SSEDF_CLASS:
+	return gen_reg_or_parallel_ms_abi_64 (mode, orig_mode, SSE_REGNO (sse_regno),(unsigned int **) &intreg);
+      case X86_64_X87_CLASS:
+      case X86_64_COMPLEX_X87_CLASS:
+	return gen_rtx_REG (mode, FIRST_STACK_REG);
+      case X86_64_NO_CLASS:
+	/* Zero sized array, struct or class.  */
+	return NULL;
+      default:
+	gcc_unreachable ();
+      }
+  if (n == 2 && class[0] == X86_64_SSE_CLASS && class[1] == X86_64_SSEUP_CLASS
+      && mode != BLKmode)
+    return gen_reg_or_parallel_ms_abi_64 (mode, orig_mode, SSE_REGNO (sse_regno), (unsigned int **) &intreg);
+
+  if (n == 2
+      && class[0] == X86_64_X87_CLASS && class[1] == X86_64_X87UP_CLASS)
+    return gen_rtx_REG (XFmode, FIRST_STACK_REG);
+  if (n == 2 && class[0] == X86_64_INTEGER_CLASS
+      && class[1] == X86_64_INTEGER_CLASS
+      && (mode == CDImode || mode == TImode || mode == TFmode)
+      && intreg[0] + 1 == intreg[1])
+    return gen_rtx_REG (mode, intreg[0]);
+
+  /* Otherwise figure out the entries of the PARALLEL.  */
+  for (i = 0; i < n; i++)
+    {
+      switch (class[i])
+        {
+	  case X86_64_NO_CLASS:
+	    break;
+	  case X86_64_INTEGER_CLASS:
+	  case X86_64_INTEGERSI_CLASS:
+	    /* Merge TImodes on aligned occasions here too.  */
+	    if (i * 8 + 8 > bytes)
+	      tmpmode = mode_for_size ((bytes - i * 8) * BITS_PER_UNIT, MODE_INT, 0);
+	    else if (class[i] == X86_64_INTEGERSI_CLASS)
+	      tmpmode = SImode;
+	    else
+	      tmpmode = DImode;
+	    /* We've requested 24 bytes we don't have mode for.  Use DImode.  */
+	    if (tmpmode == BLKmode)
+	      tmpmode = DImode;
+	    exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
+					       gen_rtx_REG (tmpmode, *intreg),
+					       GEN_INT (i*8));
+	    intreg++; sse_regno++;
+	    break;
+	  case X86_64_SSESF_CLASS:
+	    exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
+					       gen_rtx_REG (SFmode,
+							    SSE_REGNO (sse_regno)),
+					       GEN_INT (i*8));
+	    sse_regno++;
+	    exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
+					       gen_rtx_REG (DImode, *intreg),
+					       GEN_INT (i*8));
+	    intreg++;
+	    break;
+	  case X86_64_SSEDF_CLASS:
+	    exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
+					       gen_rtx_REG (DFmode,
+							    SSE_REGNO (sse_regno)),
+					       GEN_INT (i*8));
+	    sse_regno++;
+	    exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
+					       gen_rtx_REG (DImode, *intreg),
+					       GEN_INT (i*8));
+	    intreg++;
+	    break;
+	  case X86_64_SSE_CLASS:
+	    if (i < n - 1 && class[i + 1] == X86_64_SSEUP_CLASS)
+	      tmpmode = TImode;
+	    else
+	      tmpmode = DImode;
+	    exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
+					       gen_rtx_REG (tmpmode,
+							    SSE_REGNO (sse_regno)),
+					       GEN_INT (i*8));
+	    if (tmpmode == TImode)
+	      i++;
+	    sse_regno++;
+	    exp [nexps++] = gen_rtx_EXPR_LIST (VOIDmode,
+					       gen_rtx_REG (DImode, *intreg),
+					       GEN_INT (i*8));
+	    intreg++;
+	    break;
+	  default:
+	    gcc_unreachable ();
+	}
+    }
+
+  /* Empty aligned struct, union or class.  */
+  if (nexps == 0)
+    return NULL;
+
+  ret =  gen_rtx_PARALLEL (mode, rtvec_alloc (nexps));
+  for (i = 0; i < nexps; i++)
+    XVECEXP (ret, 0, i) = exp [i];
+  return ret;
+}
+
 /* Construct container for the argument used by GCC interface.  See
    FUNCTION_ARG for the detailed description.  */
 
@@ -3671,6 +3938,7 @@
     case DFmode:
       if (cum->float_in_sse < 2)
 	break;
+      /* FALLTHRU */
     case SFmode:
       if (cum->float_in_sse < 1)
 	break;
@@ -3734,6 +4002,24 @@
     cum->words += words;
 }
 
+static void
+function_arg_advance_ms_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+			    tree type, HOST_WIDE_INT words)
+{
+  int int_nregs;
+  if (!examine_argument_ms_abi_64 (mode, type, 0, &int_nregs))
+    cum->words += words;
+  else if(int_nregs <= cum->nregs)
+    {
+      cum->nregs -= int_nregs;
+      cum->regno += int_nregs;
+      cum->sse_nregs -= int_nregs;
+      cum->sse_regno += int_nregs;
+    }
+  else
+    cum->words += words;
+}
+
 void
 function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
 		      tree type, int named ATTRIBUTE_UNUSED)
@@ -3749,7 +4035,9 @@
   if (type)
     mode = type_natural_mode (type);
 
-  if (TARGET_64BIT)
+  if (TARGET_64BIT_MS_ABI)
+    function_arg_advance_ms_64 (cum, mode, type, words);
+  else if (TARGET_64BIT)
     function_arg_advance_64 (cum, mode, type, words);
   else
     function_arg_advance_32 (cum, mode, type, bytes, words);
@@ -3814,6 +4102,7 @@
     case DFmode:
       if (cum->float_in_sse < 2)
 	break;
+      /* FALLTHRU */
     case SFmode:
       if (cum->float_in_sse < 1)
 	break;
@@ -3880,6 +4169,19 @@
 			      cum->sse_regno);
 }
 
+static rtx
+function_arg_ms_64 (CUMULATIVE_ARGS *cum, enum machine_mode mode,
+		    enum machine_mode orig_mode, tree type)
+{
+  /* Avoid the AL settings for the Unix64 ABI.  */
+  if (mode == VOIDmode)
+    return constm1_rtx;
+
+  return construct_container_ms_abi_64 (mode, orig_mode, type, 0, cum->nregs,
+					&x86_64_ms_abi_int_parameter_registers[cum->regno],
+					cum->regno);
+}
+
 rtx
 function_arg (CUMULATIVE_ARGS *cum, enum machine_mode omode,
 	      tree type, int named ATTRIBUTE_UNUSED)
@@ -3898,7 +4200,9 @@
   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, type);
+  else if (TARGET_64BIT)
     return function_arg_64 (cum, mode, omode, type);
   else
     return function_arg_32 (cum, mode, omode, type, bytes, words);
@@ -4125,6 +4429,48 @@
 }
 
 static rtx
+function_value_ms_64 (enum machine_mode orig_mode, enum machine_mode mode,
+		   tree valtype)
+{
+  rtx ret;
+
+  /* Handle libcalls, which don't provide a type node.  */
+  if (valtype == NULL)
+    {
+      switch (mode)
+ 	{
+	case SFmode:
+	case SCmode:
+	case DFmode:
+	case DCmode:
+	case TFmode:
+	case SDmode:
+	case DDmode:
+	case TDmode:
+	  return gen_rtx_REG (mode, FIRST_SSE_REG);
+	case XFmode:
+	case XCmode:
+	  return gen_rtx_REG (mode, FIRST_FLOAT_REG);
+	case TCmode:
+	  return NULL;
+	default:
+	  return gen_rtx_REG (mode, 0);
+ 	}
+     }
+
+  ret = construct_container_ms_abi_64 (mode, orig_mode, valtype, 1,
+			     REGPARM_MAX,
+			     x86_64_int_return_registers, 0);
+
+  /* For zero sized structures, construct_container returns NULL, but we
+     need to keep rest of compiler happy by returning meaningful value.  */
+  if (!ret)
+    ret = gen_rtx_REG (orig_mode, 0);
+
+  return ret;
+}
+
+static rtx
 ix86_function_value_1 (tree valtype, tree fntype_or_decl,
 		       enum machine_mode orig_mode, enum machine_mode mode)
 {
@@ -4135,7 +4481,9 @@
     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, valtype);
+  else if (TARGET_64BIT)
     return function_value_64 (orig_mode, mode, valtype);
   else
     return function_value_32 (orig_mode, mode, fntype, fn);
@@ -4207,12 +4555,21 @@
   return !examine_argument (mode, type, 1, &needed_intregs, &needed_sseregs);
 }
 
+static int
+return_in_memory_ms_64 (tree type, enum machine_mode mode)
+{
+  int needed_intregs;
+  return !examine_argument_ms_abi_64 (mode, type, 1, &needed_intregs);
+}
+
 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);
@@ -4272,8 +4629,8 @@
 {
   tree f_gpr, f_fpr, f_ovf, f_sav, record, type_decl;
 
-  /* For i386 we use plain pointer to argument area.  */
-  if (!TARGET_64BIT)
+  /* For i386 and ms abi we use plain pointer to argument area.  */
+  if (!TARGET_64BIT || TARGET_64BIT_MS_ABI)
     return build_pointer_type (char_type_node);
 
   record = (*lang_hooks.types.make_type) (RECORD_TYPE);
@@ -4393,6 +4750,27 @@
 }
 
 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 +4797,10 @@
   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.  */
@@ -4432,8 +4813,8 @@
   tree gpr, fpr, ovf, sav, t;
   tree type;
 
-  /* Only 64bit target needs something special.  */
-  if (!TARGET_64BIT)
+  /* Only 64bit none ms abi target needs something special.  */
+  if (!TARGET_64BIT || TARGET_64BIT_MS_ABI)
     {
       std_expand_builtin_va_start (valist, nextarg);
       return;
@@ -4511,8 +4892,8 @@
   tree ptrtype;
   enum machine_mode nat_mode;
 
-  /* Only 64bit target needs something special.  */
-  if (!TARGET_64BIT)
+  /* Only 64bit non ms abi target needs something special.  */
+  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));
@@ -5119,9 +5500,19 @@
 	  ASM_OUTPUT_LABEL (asm_out_file, name);
 	}
 
-      xops[0] = gen_rtx_REG (SImode, regno);
-      xops[1] = gen_rtx_MEM (SImode, stack_pointer_rtx);
-      output_asm_insn ("mov{l}\t{%1, %0|%0, %1}", xops);
+      if(!TARGET_64BIT)
+        {
+          xops[0] = gen_rtx_REG (SImode, regno);
+          xops[1] = gen_rtx_MEM (SImode, stack_pointer_rtx);
+          output_asm_insn ("mov{l}\t{%1, %0|%0, %1}", xops);
+        }
+      else
+        {
+          xops[0] = gen_rtx_REG (DImode, regno);
+          xops[1] = gen_rtx_MEM (DImode, stack_pointer_rtx);
+          output_asm_insn ("mov{q}\t{%1, %0|%0, %1}", xops);
+        }
+      
       output_asm_insn ("ret", xops);
     }
 
@@ -5704,16 +6095,21 @@
   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 -= (TARGET_64BIT_MS_ABI ? 8 : UNITS_PER_WORD);
 	}
 
       emit_move_insn (eax, GEN_INT (allocate));
@@ -5734,7 +6130,7 @@
 			       - 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 +6384,7 @@
 	{
 	  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));
@@ -6776,7 +7172,7 @@
 \f
 /* 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;
@@ -7406,7 +7802,8 @@
 #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;
 
@@ -9179,8 +9576,8 @@
   gcc_assert (reload_completed);
 
   /* Avoid HImode and its attendant prefix byte.  */
-  if (GET_MODE_SIZE (GET_MODE (dest)) < 4)
-    dest = gen_rtx_REG (SImode, REGNO (dest));
+  if (GET_MODE_SIZE (GET_MODE (dest)) < GET_MODE_SIZE (Pmode))
+    dest = gen_rtx_REG (Pmode, REGNO (dest));
 
   tmp = gen_rtx_SET (VOIDmode, dest, const0_rtx);
 
@@ -19387,11 +19784,16 @@
 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)
@@ -19471,7 +19873,10 @@
       /* Put the this parameter into %eax.  */
       xops[0] = this;
       xops[1] = this_reg = gen_rtx_REG (Pmode, 0);
-      output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
+      if(Pmode==SImode)
+        output_asm_insn ("mov{l}\t{%0, %1|%1, %0}", xops);
+      else
+        output_asm_insn ("mov{q}\t{%0, %1|%1, %0}", xops);
     }
   else
     this_reg = NULL_RTX;
@@ -19508,7 +19913,7 @@
 	  if (lookup_attribute ("fastcall",
 	      TYPE_ATTRIBUTES (TREE_TYPE (function))))
 	    tmp_regno = 0 /* EAX */;
-	  tmp = gen_rtx_REG (SImode, tmp_regno);
+	  tmp = gen_rtx_REG (Pmode, tmp_regno);
 	}
 
       xops[0] = gen_rtx_MEM (Pmode, this_reg);
@@ -19576,7 +19981,7 @@
 	else
 #endif /* TARGET_MACHO */
 	{
-	  tmp = gen_rtx_REG (SImode, 2 /* ECX */);
+	  tmp = gen_rtx_REG (Pmode, 2 /* ECX/RCX */);
 	  output_set_got (tmp, NULL_RTX);
 
 	  xops[1] = tmp;
Index: config.build
===================================================================
--- config.build	(revision 123255)
+++ config.build	(working copy)
@@ -77,7 +77,7 @@
     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
     ;;
=

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised x86_64-pc-mingw32 patch
  2007-03-27 13:13   ` Kai Tietz
@ 2007-03-27 16:07     ` Richard Henderson
  2007-03-27 16:32       ` Kai Tietz
  0 siblings, 1 reply; 33+ messages in thread
From: Richard Henderson @ 2007-03-27 16:07 UTC (permalink / raw)
  To: Kai Tietz; +Cc: gcc-patches

On Tue, Mar 27, 2007 at 12:50:06PM +0200, Kai Tietz wrote:
> I tried your patch with a mingw64 runtime and had especially problems on 
> floatings. Therefore I suggest the following code as replacement for 
> yours. I built as cross on i386-linux and i386-cygwin and it seems to work 
> fine.

You need to tell me *what* problems you had.

The documentation I read is really quite simple -- the code I
wrote should have been very close to correct.  If it isn't, you
need to show me test cases in which the output differs from VC++.

I certainly cannot accept your wholesale copying of the Unix
x86_64 code, which is *vastly* different to the MS ABI.


r~

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised x86_64-pc-mingw32 patch
  2007-03-27 16:07     ` Richard Henderson
@ 2007-03-27 16:32       ` Kai Tietz
  2007-03-27 17:13         ` Richard Henderson
  2007-03-27 17:21         ` Michael Matz
  0 siblings, 2 replies; 33+ messages in thread
From: Kai Tietz @ 2007-03-27 16:32 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches

Richard Henderson <rth@redhat.com> wrote on 27.03.2007 16:56:40:

> On Tue, Mar 27, 2007 at 12:50:06PM +0200, Kai Tietz wrote:
> > I tried your patch with a mingw64 runtime and had especially problems 
on 
> > floatings. Therefore I suggest the following code as replacement for 
> > yours. I built as cross on i386-linux and i386-cygwin and it seems to 
work 
> > fine.
> 
> You need to tell me *what* problems you had.

Problem one the @GOTPCREL issue as I wrote
>> The use of pic seems to be producing problems by the @GOTPCREL prefix, 
which the coff version of gas does not understand. But
>> AFAIS we need not producing pic code, because coff (PE) is by 
architecture position independent. Just the patch in i386.md is
>> necessary for having memonics with size to be relocated by PE loader.

Second one is the floating point issue while compiling libgcc as I wrote.
>> The register calling convention is may easier than my suggested code 
looks like. May this can be eased dramatically, but this
>> adopted code of existing x86_64 ABI code solved all the floating point 
failures I had. 

> I certainly cannot accept your wholesale copying of the Unix
> x86_64 code, which is *vastly* different to the MS ABI.

AFAIK, uses the x86_64 abi of MS the following general rules:
        a) Any function uses 4 general registers [RCX,RDX,R8,R9] (and do 
stack-safe too for them) as fast call.
        b) Any argument passed not having the size 1,2,4,8 have to be 
passed by memory reference.
        c) There is no splitting of larger values to multiple registers.
        d) The x87 register set is not used for passing.
        e) Floating point arguments are using XMM0L,XMM1L,XMM2L,XMM3L 
registers for fast call.
           For va_arg sake they are shadowed in the 4 general registers 
and shadow stack is reserved.
        f) Any parameter after the 4th is passed on stack.

AFAIK, MS does not have vector-types as a non structure type, nor does it 
have a TFmode "long double" type. My idea was just to provide these 
non-interferring types to gcc, to have faster code and easier support for 
allready existing gcc libraries. By the win32 and mingw32 header-set 
(beside of the non-MS complex and extended-doubles allready *very* gcc 
specific) no method passes a structure or a type bigger than 1,2,4, or 8 
bytes size.
Therefore I did not made out a good reason to fullfil the points b) and 
c). But may you can give me a hint, where this is so important ?
BTW what you call unix x86_64 code is more a reflection of the AMD x86_64 
abi from http://www.x86-64.org AFAICS.

Regards,
 i.A. Kai Tietz

------------------------------------------------------------------------------------------
  OneVision Software Entwicklungs GmbH & Co. KG
  Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg
  Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com
  Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050
  Handelsregister: HRA 6744, Amtsgericht Regensburg
  Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH
  Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg
  Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: 
Ulrike Döhler, Manuela Kluger



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised x86_64-pc-mingw32 patch
  2007-03-27 16:32       ` Kai Tietz
@ 2007-03-27 17:13         ` Richard Henderson
  2007-03-27 17:21         ` Michael Matz
  1 sibling, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2007-03-27 17:13 UTC (permalink / raw)
  To: Kai Tietz; +Cc: gcc-patches

On Tue, Mar 27, 2007 at 05:59:01PM +0200, Kai Tietz wrote:
> Second one is the floating point issue while compiling libgcc as I wrote.

No, you didn't write that.  You just said "problems".  If this
is just in libgcc, I can probably debug this myself.

> By the win32 and mingw32 header-set 
> (beside of the non-MS complex and extended-doubles allready *very* gcc 
> specific) no method passes a structure or a type bigger than 1,2,4, or 8 
> bytes size.
> Therefore I did not made out a good reason to fullfil the points b) and 
> c). But may you can give me a hint, where this is so important ?

One day you may find yourself using a 3rd party library that was compiled
by VC++, and which doesn't restrict itself to these limited types.  If 
gcc does not follow all of the rules to the letter, this won't work.

> BTW what you call unix x86_64 code is more a reflection of the AMD x86_64 
> abi from http://www.x86-64.org AFAICS.

Of course I know this.  However, it's also accurate to say that it's used
on unix, and not on windows.


r~

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised x86_64-pc-mingw32 patch
  2007-03-27 16:32       ` Kai Tietz
  2007-03-27 17:13         ` Richard Henderson
@ 2007-03-27 17:21         ` Michael Matz
  1 sibling, 0 replies; 33+ messages in thread
From: Michael Matz @ 2007-03-27 17:21 UTC (permalink / raw)
  To: Kai Tietz; +Cc: Richard Henderson, gcc-patches

Hi,

On Tue, 27 Mar 2007, Kai Tietz wrote:

> Therefore I did not made out a good reason to fullfil the points b) and 
> c). But may you can give me a hint, where this is so important ? BTW 
> what you call unix x86_64 code is more a reflection of the AMD x86_64 
> abi from http://www.x86-64.org AFAICS.

Yes, and that _is_ the unix ABI.  It would have been nice if it were _the_ 
x86-64 ABI, but MS chose to use something completely different, (while Mac 
OS uses some slight variation).  So calling it "unix" ABI makes sense.


Ciao,
Michael.

^ permalink raw reply	[flat|nested] 33+ messages in thread

* revised**2 x86_64-pc-mingw32 patch
  2007-03-22  0:33 ` revised x86_64-pc-mingw32 patch Richard Henderson
  2007-03-22 13:02   ` Kai Tietz
  2007-03-27 13:13   ` Kai Tietz
@ 2007-03-27 23:48   ` Richard Henderson
  2007-03-28 12:43     ` Kai Tietz
  2 siblings, 1 reply; 33+ messages in thread
From: Richard Henderson @ 2007-03-27 23:48 UTC (permalink / raw)
  To: Kai Tietz, gcc-patches

[-- Attachment #1: Type: text/plain, Size: 467 bytes --]

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~

[-- Attachment #2: z --]
[-- Type: text/plain, Size: 47782 bytes --]

--- 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
+\f
+#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)
 \f
 /* 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)
 
 \f
-/* 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 
 \f
 /* 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;
     }

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised**2 x86_64-pc-mingw32 patch
  2007-03-27 23:48   ` revised**2 " Richard Henderson
@ 2007-03-28 12:43     ` Kai Tietz
  2007-03-28 17:02       ` Richard Henderson
  0 siblings, 1 reply; 33+ messages in thread
From: Kai Tietz @ 2007-03-28 12:43 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches

Richard Henderson <rth@redhat.com> wrote on 28.03.2007 01:35:54:

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

I nearly commit this patch, but one point in "function_arg_ms_64" is not 
proper. There is no intepretation of named arguments in MS abi.  Floating 
type parameters need register duplications in any case, otherwise 
functions using va_list - as printf and so on - will fail. See in msdn the 
va_list calling convention as reference.

After patching this issue, I could bootstap the cross-compile on 
i386-pc-cygwin (after patching the gengtype sigF) and on i386-pc-linux.

Regards,
 i.A. Kai Tietz

------------------------------------------------------------------------------------------
  OneVision Software Entwicklungs GmbH & Co. KG
  Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg
  Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com
  Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050
  Handelsregister: HRA 6744, Amtsgericht Regensburg
  Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH
  Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg
  Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: 
Ulrike Döhler, Manuela Kluger



^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised**2 x86_64-pc-mingw32 patch
  2007-03-28 12:43     ` Kai Tietz
@ 2007-03-28 17:02       ` Richard Henderson
  2007-03-28 17:13         ` Richard Henderson
  0 siblings, 1 reply; 33+ messages in thread
From: Richard Henderson @ 2007-03-28 17:02 UTC (permalink / raw)
  To: Kai Tietz; +Cc: gcc-patches

On Wed, Mar 28, 2007 at 02:22:21PM +0200, Kai Tietz wrote:
> I nearly commit this patch, but one point in "function_arg_ms_64" is not 
> proper. There is no intepretation of named arguments in MS abi.

Yes there is.

Under "Parameter Passing":

 # Floating-point and double-precision arguments are passed ...
 # with the integer slot that would normally be used for that
 # cardinal slot being ignored ....

Under "Varargs":

 # For floating-point values only, both the integer and the floating-point
 # register will contain the float value ...

Notice "ignored" in the first part and "will contain" in the
second part.  MS clearly distinguishes between functions without
and with variadic arguments.


Something is wrong though, "named" isn't being set properly; I'll
investigate this.


r~

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised**2 x86_64-pc-mingw32 patch
  2007-03-28 17:02       ` Richard Henderson
@ 2007-03-28 17:13         ` Richard Henderson
  2007-03-29 13:01           ` Kai Tietz
  0 siblings, 1 reply; 33+ messages in thread
From: Richard Henderson @ 2007-03-28 17:13 UTC (permalink / raw)
  To: Kai Tietz, gcc-patches

On Wed, Mar 28, 2007 at 09:30:42AM -0700, Richard Henderson wrote:
> Something is wrong though, "named" isn't being set properly; I'll
> investigate this.

Add 

#undef TARGET_STRICT_ARGUMENT_NAMING
#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true

near the end of i386.c.  The other i386 abis ignore the value
of "named", so it won't affect them in any way, so we don't
need to make this hook depend on TARGET_64BIT_MS_ABI.


r~

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised**2 x86_64-pc-mingw32 patch
  2007-03-28 17:13         ` Richard Henderson
@ 2007-03-29 13:01           ` Kai Tietz
  2007-03-30 21:43             ` revised #pragma push_macro feature Richard Henderson
  2007-03-30 22:29             ` revised**2 x86_64-pc-mingw32 patch Richard Henderson
  0 siblings, 2 replies; 33+ messages in thread
From: Kai Tietz @ 2007-03-29 13:01 UTC (permalink / raw)
  To: Richard Henderson; +Cc: gcc-patches

[-- Attachment #1: Type: text/plain, Size: 5353 bytes --]

Richard Henderson <rth@redhat.com> wrote on 28.03.2007 18:42:26:

> Add 
> 
> #undef TARGET_STRICT_ARGUMENT_NAMING
> #define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
> 
> near the end of i386.c.  The other i386 abis ignore the value
> of "named", so it won't affect them in any way, so we don't
> need to make this hook depend on TARGET_64BIT_MS_ABI.

Great, it works AFAICS fine ;)

I changed the c-pragma.c part to be more GNAT style compliant and add a 
test-case for "#pragma pop_macro" and "#pragma push_macro".
Also I added a patch to libiberty/strerror.c to be compilable with w64 
include headers.

New ChangeLog entries are:

2007-03-29  Richard Henderson  <rth@redhat.com>
            Kai Tietz  <kai.tietz@onevision.com>

        * gcc/config.host: Add x86_64-*-mingw32* target.
        * gcc/config.build: Ditto.
        * gcc/config.gcc: Ditto.
        * libgcc/config.host: Add support for an x86_64-mingw* target.
        * gcc/doc/tm.texi: (HANDLE_PRAGMA_PUSH_POP_MACRO): Add new.
        * gcc/gthr-win32.h: (__gthread_key_create): Mark arg dtor as 
unused.
        * gcc/gthr-win32.c: (__gthread_key_create): Mark arg dtor as 
unused.
        * gcc/testsuite/gcc.dg/pragma-push_pop_macro.c: New test-case.
        * gcc/c-pragma.c (HANDLE_PRAGMA_PUSH_POP_MACRO): New.
          (handle_pragma_push_macro): New.
          (handle_pragma_pop_macro): New.
          (init_pragma): Add new pragma command.
          (def_pragma_macro): New type for macro pile.
          (macro_list): New static var for chain macro pile.
        * gcc/emutls.c: (__emutls_array): Change size to type pointer.
          (emutls_destroy): Changed to avoid "unsigned long int" cast.
          (__emutls_get_address): Ditto.
        * gcc/unwind-generic.h (_uleb128_t): Handle case 
__SIZEOF_LONG_LONG__
          >= __SIZEOF_POINTER__.
          (_sleb128_t): Ditto.
        * gcc/config/i386/i386.h: Move and adjust comments.
          (TARGET_SUBTARGET64_DEFAULT): New macro default to zero.
          (TARGET_64BIT_MS_ABI): New macro default to zero.
          (call_used_regs): Adjustments for target.
        * gcc/config/i386/cygming.h: (DWARF2_DEBUGGING_INFO) for 
x86_64-mingw needs to be
            set to valued 1.
          (DWARF2_UNWIND_INFO): Likewise
          (PREFERRED_DEBUGGING_TYPE): for x86_64-mingw it needs to be set 
to DWARF2_DEBUG
            as default.
          (DBX_REGISTER_NUMBER): Have to use dbx64_register_map for 
x86_64-mingw.
          (SIZE_TYPE): Needs to be "long long unsigned int" for 
x86_64-mingw.
          (PTRDIFF_TYPE): Needs to be "long long int" for x86_64-mingw.
          (POINTER_SIZE: Needs to be 64 for x86_64 mingw.
          (LONG_TYPE_SIZE): Force 32-bit for a long.
          (OUTGOING_REG_PARM_STACK_SPACE): Added.
          (TARGET_SUBTARGET_DEFAULT): Defined proper for x86_64-mingw.
          (REGPARM_MAX): Likewise.
          (SSE_REGPARM_MAX): Likewise.
          (LONG_TYPE_SIZE): Likewise.
          (REG_PARM_STACK_SPACE): Likewise.
          (STACK_BOUNDARY): Likewise.
          (SUBTARGET_ATTRIBUTE_TABLE): Move comment outside of macro 
definition.
          (HANDLE_PRAGMA_PUSH_POP_MACRO): New macro
        * gcc/config/i386/i386.md (allocate_stack): Merge 32-bit and 
64-bit support.
        * gcc/config/i386/predicates.md: (x86_64_movabs_operand): Adjust 
for new target.
        * gcc/config/i386/cygwin.asm: Adjustments for target build of 
x86_64-mingw (and cygwin).
        * gcc/config/i386/i386elf.h: (TARGET_SUBTARGET_DEFAULT): Removed.
        * gcc/config/i386/unix.h: (TARGET_SUBTARGET_DEFAULT): Added.
          (TARGET_SUBTARGET64_DEFAULT): New.
        * gcc/config/i386/winnt.c: (i386_pe_mark_dllimport): 64-bit mode 
support.
        * gcc/config/i386/i386.c: New calling convention and target 
support.
          (ix86_GOT_alias_set): Make from gobal scope available.
        * gcc/config/i386/mingw32.h: Adjustments for target x86_64-mingw.
          (EXTRA_OS_CPP_BUILTINS): Added predefined macro 
_INTEGRAL_MAX_BITS with the value of
            bitsize of a pointer.
          (WIN64,_WIN64,__MINGW64__): New predefined macros for 
x86_64-mingw target
          (STANDARD_INCLUDE_DIR,STANDARD_STARTFILE_PREFIX_1,): Include for 
x86_64-mingw from
            different place.
        * gcc/config/i386/i386-protos.h: Proto for ix86_GOT_alias_set 
added.
        * fixincludes/mkfixinc.sh: Add x86_64-mingw target.
        * libstdc++-v3/include/bits/locale_facets.tcc: Fixed integer 
pointer mismatch.
        * libiberty/strerror.c: Ensure sys_nerr and sys_errlist is not 
used as macro version.

Regards,
 i.A. Kai Tietz



------------------------------------------------------------------------------------------
  OneVision Software Entwicklungs GmbH & Co. KG
  Dr.-Leo-Ritter-Straße 9 - 93049 Regensburg
  Tel: +49.(0)941.78004.0 - Fax: +49.(0)941.78004.489 - www.OneVision.com
  Commerzbank Regensburg - BLZ 750 400 62 - Konto 6011050
  Handelsregister: HRA 6744, Amtsgericht Regensburg
  Komplementärin: OneVision Software Entwicklungs Verwaltungs GmbH
  Dr.-Leo-Ritter-Straße 9 – 93049 Regensburg
  Handelsregister: HRB 8932, Amtsgericht Regensburg - Geschäftsführer: 
Ulrike Döhler, Manuela Kluger


[-- Attachment #2: a.txt --]
[-- Type: text/plain, Size: 51980 bytes --]

Index: libgcc/config.host
===================================================================
--- libgcc/config.host	(revision 123324)
+++ libgcc/config.host	(working copy)
@@ -364,8 +364,10 @@
 	;;
 i[34567]86-*-pe | i[34567]86-*-cygwin*)
 	;;
-i[34567]86-*-mingw32*)
+i[34567]86-*-mingw32* | x86_64-*-mingw*)
 	;;
+x86_64-*-mingw32*)
+	;;
 i[34567]86-*-uwin*)
 	;;
 i[34567]86-*-interix3*)
Index: gcc/doc/tm.texi
===================================================================
--- gcc/doc/tm.texi	(revision 123324)
+++ gcc/doc/tm.texi	(working copy)
@@ -9719,6 +9719,18 @@
 @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
Index: gcc/gthr-win32.h
===================================================================
--- gcc/gthr-win32.h	(revision 123324)
+++ gcc/gthr-win32.h	(working copy)
@@ -562,7 +562,8 @@
    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 ();
Index: gcc/testsuite/gcc.dg/pragma-push_pop_macro.c
===================================================================
--- gcc/testsuite/gcc.dg/pragma-push_pop_macro.c	(revision 0)
+++ gcc/testsuite/gcc.dg/pragma-push_pop_macro.c	(revision 0)
@@ -0,0 +1,20 @@
+/* Prove that HANDLE_PRAGMA_PUSH_POP_MACRO handling works somewhat. */
+
+/* { dg-do run { target *-*-mingw* } } */
+
+extern void abort (void);
+
+#define TEXT1	"ABC"
+#define TEXT2	"DEF"
+
+main()
+{
+	if( sizeof( TEXT1 TEXT2 ) != 7) abort();
+#pragma push_macro("TEXT1")
+#undef TEXT1
+#define TEXT1	"ABCD"
+	if( sizeof( TEXT1 TEXT2 ) != 8)  abort()
+#pragma pop_macro("TEXT1")
+	if( sizeof( TEXT1 TEXT2 ) != 7)  abort()
+	return 0;
+}

Property changes on: gcc/testsuite/gcc.dg/pragma-push_pop_macro.c
___________________________________________________________________
Name: svn:executable
   + *

Index: gcc/c-pragma.c
===================================================================
--- gcc/c-pragma.c	(revision 123324)
+++ gcc/c-pragma.c	(working copy)
@@ -53,6 +53,20 @@
 
 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 def_pragma_macro GTY(())
+{
+  char *name;
+  char *value;
+  struct def_pragma_macro *prev;
+} def_pragma_macro;
+static GTY(()) struct def_pragma_macro *macro_list = NULL;
+
+
 #ifdef HANDLE_PRAGMA_PACK
 static void handle_pragma_pack (cpp_reader *);
 
@@ -132,6 +146,151 @@
     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");
+          if (token != CPP_EOF)
+            while(pragma_lex (&x) != CPP_EOF)
+              ;
+        }
+      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)
+    {
+      def_pragma_macro *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 = (def_pragma_macro *) ggc_alloc (sizeof(def_pragma_macro) + 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 = macro_list;
+	  macro_list = c;
+	}
+      else
+        {
+          c = (def_pragma_macro *) ggc_alloc (sizeof(def_pragma_macro) + strlen (macroname) + 4);
+          c->name = (char*)&c[1];
+          c->value = NULL;
+          strcpy (c->name, macroname);
+          c->prev = macro_list;
+          macro_list = 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");
+          if (token != CPP_EOF)
+            while(pragma_lex (&x) != CPP_EOF)
+              ;
+        }
+      else if (pragma_lex (&x) != CPP_EOF)
+        {
+          warning (OPT_Wpragmas, "junk at end of %<#pragma pop_macro%>");
+          while(pragma_lex (&x) != CPP_EOF)
+            ;
+        }
+    }
+  if(id)
+    {
+      def_pragma_macro *p = NULL, *c = macro_list;
+      const char *macroname = TREE_STRING_POINTER (id);
+      
+      while(c != NULL)
+        {
+          if(!strcmp (macroname, c->name))
+            {
+              /* FIX: should be replaced by alloca */
+              char s[8192];
+              
+              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)
+                macro_list = 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 +978,10 @@
   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
Index: gcc/emutls.c
===================================================================
--- gcc/emutls.c	(revision 123324)
+++ gcc/emutls.c	(working copy)
@@ -48,6 +48,12 @@
   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 void
 emutls_destroy (void *ptr)
 {
-  void ***arr = (void ***) ptr;
-  unsigned long int size = (unsigned long int) arr[0];
-  ++arr;
-  while (--size)
+  struct __emutls_array *arr = ptr;
+  pointer size = arr->size;
+  pointer i;
+
+  for (i = 0; i < size; ++i)
     {
-      if (*arr)
-	free ((*arr)[-1]);
-      ++arr;
+      if (arr->data[i])
+	free (arr->data[i][-1]);
     }
+
   free (ptr);
 }
 
@@ -130,9 +137,9 @@
 #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 @@
       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
Index: gcc/config.gcc
===================================================================
--- gcc/config.gcc	(revision 123324)
+++ gcc/config.gcc	(working copy)
@@ -1343,7 +1343,7 @@
 		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"
Index: gcc/config.host
===================================================================
--- gcc/config.host	(revision 123324)
+++ gcc/config.host	(working copy)
@@ -168,7 +168,7 @@
     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
Index: gcc/unwind-generic.h
===================================================================
--- gcc/unwind-generic.h	(revision 123324)
+++ gcc/unwind-generic.h	(working copy)
@@ -247,17 +247,15 @@
    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"
+# error "What type shall we use for _sleb128_t?"
 #endif
-#else
-  typedef long _sleb128_t;
-  typedef unsigned long _uleb128_t;
-#endif
 
 #ifdef __cplusplus
 }
Index: gcc/config/i386/i386.h
===================================================================
--- gcc/config/i386/i386.h	(revision 123324)
+++ gcc/config/i386/i386.h	(working copy)
@@ -20,6 +20,21 @@
 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 @@
    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 @@
    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 @@
   } 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 {
@@ -372,11 +373,17 @@
    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
@@ -998,6 +1005,11 @@
 	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
Index: gcc/config/i386/cygming.h
===================================================================
--- gcc/config/i386/cygming.h	(revision 123324)
+++ gcc/config/i386/cygming.h	(working copy)
@@ -21,18 +21,35 @@
 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 @@
 #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
 \f
+#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)
+\f
 /* 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 @@
 } while (0)
 
 \f
-/* 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 @@
 /* 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 @@
 #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
Index: gcc/config/i386/i386.md
===================================================================
--- gcc/config/i386/i386.md	(revision 123324)
+++ gcc/config/i386/i386.md	(working copy)
@@ -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;
Index: gcc/config/i386/cygwin.asm
===================================================================
--- gcc/config/i386/cygwin.asm	(revision 123324)
+++ gcc/config/i386/cygwin.asm	(working copy)
@@ -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 */
+	pushl	%ecx		/* save temp */
+	leal	8(%esp), %ecx	/* point past return addr */
+	cmpl	$0x1000, %eax	/* > 4k ?*/
+	jb	Ldone
 
-probe: 	cmpl   $0x1000,%eax	/* > 4k ?*/
-	jb    done		
+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 */
 
-	subl   $0x1000,%ecx  		/* yes, move pointer down 4k*/
-	orl    $0x0,(%ecx)   		/* probe there */
-	subl   $0x1000,%eax  	 	/* decrement count */
-	jmp    probe           	 	/* and do it again */
+Ldone:
+	subl	%eax, %ecx	   
+	orl	$0x0, (%ecx)	/* less than 4k, just peek here */
 
-done: 	subl   %eax,%ecx	   
-	orl    $0x0,(%ecx)	/* less that 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 */
 
-	movl   %esp,%eax
-	movl   %ecx,%esp	/* decrement stack */
+	/* 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 */
 
-	movl   (%eax),%ecx	/* recover saved temp */
-	movl   4(%eax),%eax	/* get return address */
-	jmp    *%eax	
+/* ___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
Index: gcc/config/i386/predicates.md
===================================================================
--- gcc/config/i386/predicates.md	(revision 123324)
+++ gcc/config/i386/predicates.md	(working copy)
@@ -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")
Index: gcc/config/i386/gthr-win32.c
===================================================================
--- gcc/config/i386/gthr-win32.c	(revision 123324)
+++ gcc/config/i386/gthr-win32.c	(working copy)
@@ -102,7 +102,8 @@
    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 ();
Index: gcc/config/i386/i386elf.h
===================================================================
--- gcc/config/i386/i386elf.h	(revision 123324)
+++ gcc/config/i386/i386elf.h	(working copy)
@@ -27,11 +27,6 @@
 
 #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.  */
 
Index: gcc/config/i386/unix.h
===================================================================
--- gcc/config/i386/unix.h	(revision 123324)
+++ gcc/config/i386/unix.h	(working copy)
@@ -61,5 +61,10 @@
 
 /* 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
Index: gcc/config/i386/winnt.c
===================================================================
--- gcc/config/i386/winnt.c	(revision 123324)
+++ gcc/config/i386/winnt.c	(working copy)
@@ -277,8 +277,11 @@
   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;
Index: gcc/config/i386/mingw32.h
===================================================================
--- gcc/config/i386/mingw32.h	(revision 123324)
+++ gcc/config/i386/mingw32.h	(working copy)
@@ -21,7 +21,11 @@
 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 @@
       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 @@
 
 /* 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
Index: gcc/config/i386/i386-protos.h
===================================================================
--- gcc/config/i386/i386-protos.h	(revision 123324)
+++ gcc/config/i386/i386-protos.h	(working copy)
@@ -251,3 +251,4 @@
 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);
Index: gcc/config/i386/i386.c
===================================================================
--- gcc/config/i386/i386.c	(revision 123324)
+++ gcc/config/i386/i386.c	(working copy)
@@ -1308,9 +1308,15 @@
   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.  */
@@ -1857,9 +1863,12 @@
     }
   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)
     {
@@ -1981,15 +1990,16 @@
   /* 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.
@@ -2135,18 +2145,16 @@
 
   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
@@ -2645,8 +2653,10 @@
 
   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;
     }
@@ -2933,6 +2943,7 @@
 ix86_function_arg_regno_p (int regno)
 {
   int i;
+  const int *parm_regs;
 
   if (!TARGET_64BIT)
     {
@@ -2960,11 +2971,15 @@
     }
 
   /* 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;
 }
@@ -3742,6 +3757,21 @@
     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)
@@ -3757,7 +3787,9 @@
   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);
@@ -3888,9 +3920,47 @@
 			      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;
@@ -3906,7 +3976,9 @@
   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);
@@ -3923,7 +3995,30 @@
 			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;
@@ -4026,6 +4121,8 @@
       return true;
 
     case FIRST_FLOAT_REG:
+      if (TARGET_64BIT_MS_ABI)
+	return false;
       return TARGET_FLOAT_RETURNS_IN_80387;
 
     case FIRST_SSE_REG:
@@ -4133,6 +4230,19 @@
 }
 
 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)
 {
@@ -4143,7 +4253,9 @@
     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);
@@ -4215,12 +4327,27 @@
   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);
@@ -4281,7 +4408,7 @@
   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);
@@ -4401,6 +4528,27 @@
 }
 
 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)
@@ -4427,7 +4575,10 @@
   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.  */
@@ -4441,7 +4592,7 @@
   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;
@@ -4519,8 +4670,8 @@
   tree ptrtype;
   enum machine_mode nat_mode;
 
-  /* Only 64bit target needs something special.  */
-  if (!TARGET_64BIT)
+  /* Only 64bit no ms targets needs something special.  */
+  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));
@@ -5712,21 +5863,30 @@
   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);
@@ -5742,7 +5902,7 @@
 			       - 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));
 	}
     }
 
@@ -5996,7 +6156,7 @@
 	{
 	  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));
@@ -6419,6 +6579,10 @@
 
     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:
@@ -6784,7 +6948,7 @@
 \f
 /* 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;
@@ -6830,6 +6994,13 @@
 
   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))
@@ -7414,7 +7585,8 @@
 #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;
 
@@ -9189,7 +9361,6 @@
   /* 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.  */
@@ -19395,37 +19566,29 @@
 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.  */
@@ -19514,7 +19677,7 @@
 	{
 	  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);
 	}
@@ -19554,7 +19717,9 @@
   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
 	{
@@ -19632,20 +19797,16 @@
 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
@@ -21729,6 +21890,9 @@
 #undef TARGET_FUNCTION_VALUE
 #define TARGET_FUNCTION_VALUE ix86_function_value
 
+#undef TARGET_STRICT_ARGUMENT_NAMING
+#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
+
 struct gcc_target targetm = TARGET_INITIALIZER;
 \f
 #include "gt-i386.h"
Index: gcc/config.build
===================================================================
--- gcc/config.build	(revision 123324)
+++ gcc/config.build	(working copy)
@@ -77,7 +77,7 @@
     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
     ;;
Index: libstdc++-v3/include/bits/locale_facets.tcc
===================================================================
--- libstdc++-v3/include/bits/locale_facets.tcc	(revision 123324)
+++ libstdc++-v3/include/bits/locale_facets.tcc	(working copy)
@@ -1314,7 +1314,7 @@
       __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;
     }
Index: libiberty/strerror.c
===================================================================
--- libiberty/strerror.c	(revision 123324)
+++ libiberty/strerror.c	(working copy)
@@ -468,8 +468,13 @@
 static const char **sys_errlist;
 
 #else
-
+#ifdef sys_nerr
+#undef sys_nerr
+#endif
 extern int sys_nerr;
+#ifdef sys_errlist
+#undef sys_errlist
+#endif
 extern char *sys_errlist[];
 
 #endif
=

^ permalink raw reply	[flat|nested] 33+ messages in thread

* revised #pragma push_macro feature
  2007-03-29 13:01           ` Kai Tietz
@ 2007-03-30 21:43             ` Richard Henderson
  2007-03-30 22:42               ` Rafael Espindola
                                 ` (2 more replies)
  2007-03-30 22:29             ` revised**2 x86_64-pc-mingw32 patch Richard Henderson
  1 sibling, 3 replies; 33+ messages in thread
From: Richard Henderson @ 2007-03-30 21:43 UTC (permalink / raw)
  To: Kai Tietz; +Cc: gcc-patches

I've rearranged and committed the push_macro feature.

Notable changes: hash table for the pushed macros, rather
than searching a single linked list.  Support from libcpp
to save/restore a pre-parsed cpp_macro structure, rather
than pushing this through the lexer again.


r~

libcpp/
        * directives.c (lex_macro_node_from_str): New.
        (cpp_push_definition, cpp_pop_definition): New.
        * include/cpplib.h (cpp_push_definition, cpp_pop_definition): Declare.
gcc/
        * c-pragma.c (struct def_pragma_macro_value): New.
        (struct def_pragma_macro): New.
        (pushed_macro_table): New.
        (dpm_hash, dpm_eq): New.
        (handle_pragma_push_macro, handle_pragma_pop_macro): New.
        (init_pragma): Install them.
        * doc/tm.texi (HANDLE_PRAGMA_PUSH_POP_MACRO): New.

--- gcc/c-pragma.c	(revision 123372)
+++ gcc/c-pragma.c	(local)
@@ -245,6 +245,144 @@ handle_pragma_pack (cpp_reader * ARG_UNU
 }
 #endif  /* HANDLE_PRAGMA_PACK */
 
+struct def_pragma_macro_value GTY(())
+{
+  struct def_pragma_macro_value *prev;
+  cpp_macro *value;
+};
+
+struct def_pragma_macro GTY(())
+{
+  hashval_t hash;
+  const char *name;
+  struct def_pragma_macro_value value;
+};
+
+static GTY((param_is (struct def_pragma_macro))) htab_t pushed_macro_table;
+
+#ifdef HANDLE_PRAGMA_PUSH_POP_MACRO
+/* Hash table control functions for pushed_macro_table.  */
+static hashval_t
+dpm_hash (const void *p)
+{
+  return ((const struct def_pragma_macro *)p)->hash;
+}
+
+static int
+dpm_eq (const void *pa, const void *pb)
+{
+  const struct def_pragma_macro *a = pa, *b = pb;
+  return a->hash == b->hash && strcmp (a->name, b->name) == 0;
+}
+
+/* #pragma push_macro("MACRO_NAME")
+   #pragma pop_macro("MACRO_NAME") */
+
+static void
+handle_pragma_push_macro (cpp_reader *reader)
+{
+  tree x, id = 0;
+  enum cpp_ttype token;
+  struct def_pragma_macro dummy, *c;
+  const char *macroname;
+  void **slot;
+
+  if (pragma_lex (&x) != CPP_OPEN_PAREN)
+    GCC_BAD ("missing %<(%> after %<#pragma push_macro%> - ignored");
+
+  token = pragma_lex (&id);
+
+  /* Silently ignore */
+  if (token == CPP_CLOSE_PAREN)
+    return;
+  if (token != CPP_STRING)
+    GCC_BAD ("invalid constant in %<#pragma push_macro%> - ignored");
+
+  if (pragma_lex (&x) != CPP_CLOSE_PAREN)
+    GCC_BAD ("missing %<)%> after %<#pragma push_macro%> - ignored");
+
+  if (pragma_lex (&x) != CPP_EOF)
+    warning (OPT_Wpragmas, "junk at end of %<#pragma push_macro%>");
+
+  /* Check for empty string, and silently ignore.  */
+  if (TREE_STRING_LENGTH (id) < 1)
+    return;
+  macroname = TREE_STRING_POINTER (id);
+
+  if (pushed_macro_table == NULL)
+    pushed_macro_table = htab_create_ggc (15, dpm_hash, dpm_eq, 0);
+
+  dummy.hash = htab_hash_string (macroname);
+  dummy.name = macroname;
+  slot = htab_find_slot_with_hash (pushed_macro_table, &dummy,
+				   dummy.hash, INSERT);
+  c = *slot;
+  if (c == NULL)
+    {
+      *slot = c = ggc_alloc (sizeof (struct def_pragma_macro));
+      c->hash = dummy.hash;
+      c->name = ggc_alloc_string (macroname, TREE_STRING_LENGTH (id) - 1);
+      c->value.prev = NULL;
+    }
+  else
+    {
+      struct def_pragma_macro_value *v;
+      v = ggc_alloc (sizeof (struct def_pragma_macro_value));
+      *v = c->value;
+      c->value.prev = v;
+    }
+
+  c->value.value = cpp_push_definition (reader, macroname);
+}
+
+static void
+handle_pragma_pop_macro (cpp_reader *reader)
+{
+  tree x, id = 0;
+  enum cpp_ttype token;
+  struct def_pragma_macro dummy, *c;
+  const char *macroname;
+  void **slot;
+
+  if (pragma_lex (&x) != CPP_OPEN_PAREN)
+    GCC_BAD ("missing %<(%> after %<#pragma pop_macro%> - ignored");
+
+  token = pragma_lex (&id);
+
+  /* Silently ignore */
+  if (token == CPP_CLOSE_PAREN)
+    return;
+  if (token != CPP_STRING)
+    GCC_BAD ("invalid constant in %<#pragma pop_macro%> - ignored");
+
+  if (pragma_lex (&x) != CPP_CLOSE_PAREN)
+    GCC_BAD ("missing %<)%> after %<#pragma pop_macro%> - ignored");
+
+  if (pragma_lex (&x) != CPP_EOF)
+    warning (OPT_Wpragmas, "junk at end of %<#pragma pop_macro%>");
+
+  /* Check for empty string, and silently ignore.  */
+  if (TREE_STRING_LENGTH (id) < 1)
+    return;
+  macroname = TREE_STRING_POINTER (id);
+
+  dummy.hash = htab_hash_string (macroname);
+  dummy.name = macroname;
+  slot = htab_find_slot_with_hash (pushed_macro_table, &dummy,
+				   dummy.hash, NO_INSERT);
+  if (slot == NULL)
+    return;
+  c = *slot;
+
+  cpp_pop_definition (reader, c->name, c->value.value);
+
+  if (c->value.prev)
+    c->value = *c->value.prev;
+  else
+    htab_clear_slot (pushed_macro_table, slot);
+}
+#endif /* HANDLE_PRAGMA_PUSH_POP_MACRO */
+
 static GTY(()) tree pending_weaks;
 
 #ifdef HANDLE_PRAGMA_WEAK
@@ -819,6 +957,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/testsuite/gcc.dg/pragma-push_macro-1.c	(revision 123372)
+++ gcc/testsuite/gcc.dg/pragma-push_macro-1.c	(local)
@@ -0,0 +1,26 @@
+/* Prove that HANDLE_PRAGMA_PUSH_POP_MACRO handling works somewhat. */
+
+/* { dg-do link { target *-*-mingw* } } */
+
+#define TEXT1  "ABC"
+#define TEXT2  "DEF"
+
+int main()
+{
+  if (__builtin_strcmp (TEXT1 TEXT2, "ABCDEF") != 0)
+    link_error ();
+
+#pragma push_macro("TEXT1")
+#undef TEXT1
+#define TEXT1  "XYZ"
+
+  if (__builtin_strcmp (TEXT1 TEXT2, "XYZDEF") != 0)
+    link_error ();
+
+#pragma pop_macro("TEXT1")
+
+  if (__builtin_strcmp (TEXT1 TEXT2, "ABCDEF") != 0)
+    link_error ();
+
+  return 0;
+}
--- libcpp/directives.c	(revision 123372)
+++ libcpp/directives.c	(local)
@@ -2078,6 +2078,65 @@ cpp_undef (cpp_reader *pfile, const char
   run_directive (pfile, T_UNDEF, buf, len);
 }
 
+/* Like lex_macro_node, but read the input from STR.  */
+static cpp_hashnode *
+lex_macro_node_from_str (cpp_reader *pfile, const char *str)
+{
+  size_t len = strlen (str);
+  uchar *buf = (char *) alloca (len + 1);
+  cpp_hashnode *node;
+
+  memcpy (buf, str, len);
+  buf[len] = '\n';
+  cpp_push_buffer (pfile, buf, len, true);
+  node = lex_macro_node (pfile, true);
+  _cpp_pop_buffer (pfile);
+
+  return node;
+}
+
+/* If STR is a defined macro, return its definition node, else return NULL.  */
+cpp_macro *
+cpp_push_definition (cpp_reader *pfile, const char *str)
+{
+  cpp_hashnode *node = lex_macro_node_from_str (pfile, str);
+  if (node && node->type == NT_MACRO)
+    return node->value.macro;
+  else
+    return NULL;
+}
+
+/* Replace a previous definition DFN of the macro STR.  If DFN is NULL,
+   then the macro should be undefined.  */
+void
+cpp_pop_definition (cpp_reader *pfile, const char *str, cpp_macro *dfn)
+{
+  cpp_hashnode *node = lex_macro_node_from_str (pfile, str);
+  if (node == NULL)
+    return;
+
+  if (node->type == NT_MACRO)
+    {
+      if (pfile->cb.undef)
+	pfile->cb.undef (pfile, pfile->directive_line, node);
+      if (CPP_OPTION (pfile, warn_unused_macros))
+	_cpp_warn_if_unused_macro (pfile, node, NULL);
+    }
+  if (node->type != NT_VOID)
+    _cpp_free_definition (node);
+
+  if (dfn)
+    {
+      node->type = NT_MACRO;
+      node->value.macro = dfn;
+      if (! ustrncmp (NODE_NAME (node), DSC ("__STDC_")))
+	node->flags |= NODE_WARN;
+
+      if (pfile->cb.define)
+	pfile->cb.define (pfile, pfile->directive_line, node);
+    }
+}
+
 /* Process the string STR as if it appeared as the body of a #assert.  */
 void
 cpp_assert (cpp_reader *pfile, const char *str)
--- libcpp/include/cpplib.h	(revision 123372)
+++ libcpp/include/cpplib.h	(local)
@@ -704,6 +704,9 @@ extern void cpp_assert (cpp_reader *, co
 extern void cpp_undef (cpp_reader *, const char *);
 extern void cpp_unassert (cpp_reader *, const char *);
 
+extern cpp_macro *cpp_push_definition (cpp_reader *, const char *);
+extern void cpp_pop_definition (cpp_reader *, const char *, cpp_macro *);
+
 /* Undefine all macros and assertions.  */
 extern void cpp_undef_all (cpp_reader *);
 
--- gcc/doc/tm.texi	(revision 123372)
+++ 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

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised**2 x86_64-pc-mingw32 patch
  2007-03-29 13:01           ` Kai Tietz
  2007-03-30 21:43             ` revised #pragma push_macro feature Richard Henderson
@ 2007-03-30 22:29             ` Richard Henderson
  1 sibling, 0 replies; 33+ messages in thread
From: Richard Henderson @ 2007-03-30 22:29 UTC (permalink / raw)
  To: Kai Tietz; +Cc: gcc-patches

Committed as follows.


r~

+2007-03-30  Richard Henderson  <rth@redhat.com>
+	    Kai Tietz  <kai.tietz@onevision.com>
+
+	* config/i386/cygming.h (DWARF2_DEBUGGING_INFO): Enable by
+	default for 64-bit.
+	(PREFERRED_DEBUGGING_TYPE): Prefer dwarf2 for 64-bit.
+	(TARGET_64BIT_MS_ABI): New.
+	(DBX_REGISTER_NUMBER): Handle 64-bit.
+	(SIZE_TYPE, PTRDIFF_TYPE): Use long long for 64-bit.
+	(LONG_TYPE_SIZE): Force to 32.
+	(REG_PARM_STACK_SPACE): New.
+	(OUTGOING_REG_PARM_STACK_SPACE): New.
+	(REGPARM_MAX, SSE_REGPARM_MAX): New.
+	(HANDLE_PRAGMA_PUSH_POP_MACRO): New.
+	(STACK_BOUNDARY): Use 128 for 64-bit.
+	* config/i386/cygwin.asm: Use push/ret to preserve call stack.
+	Add 64-bit implementation.
+	* config/i386/gthr-win32.c (__gthr_win32_key_create): Mark dtor
+	argument unused.
+	* config/i386/i386.c (x86_64_ms_abi_int_parameter_registers): New.
+	(override_options): Set ix86_cmodel for TARGET_64BIT_MS_ABI.
+	Warn for -mregparm, -mrtd in 64-bit mode; force ix86_regparm
+	for 64-bit; use TARGET_SUBTARGET64_DEFAULT.
+	(ix86_handle_cconv_attribute): Don't warn when ignoring if
+	TARGET_64BIT_MS_ABI.
+	(ix86_function_arg_regno_p): Handle TARGET_64BIT_MS_ABI.
+	(ix86_pass_by_reference): Likewise.
+	(ix86_function_value_regno_p): Likewise.
+	(ix86_build_builtin_va_list): Likewise.
+	(ix86_va_start, ix86_gimplify_va_arg): Likewise.
+	(function_arg_advance_ms_64): New.
+	(function_arg_advance): Call it.
+	(function_arg_ms_64): New.
+	(function_arg): Call it.
+	(function_value_ms_64): New.
+	(ix86_function_value_1): Call it.
+	(return_in_memory_ms_64): New.
+	(ix86_return_in_memory): Call it.
+	(setup_incoming_varargs_ms_64): New.
+	(ix86_setup_incoming_varargs): Call it.
+	(ix86_expand_prologue): Handle 64-bit stack probing.
+	(legitimize_pic_address): Handle TARGET_64BIT_MS_ABI.
+	(output_pic_addr_const): Likewise.
+	(x86_this_parameter): Likewise.
+	(x86_output_mi_thunk): Likewise.
+	(x86_function_profiler): Likewise.
+	(TARGET_STRICT_ARGUMENT_NAMING): New.
+	* config/i386/i386.h (TARGET_SUBTARGET64_DEFAULT): New.
+	(TARGET_64BIT_MS_ABI): New.
+	(CONDITIONAL_REGISTER_USAGE): Handle TARGET_64BIT_MS_ABI.
+	* config/i386/i386.md (allocate_stack_worker): Remove.
+	(allocate_stack_worker_32): Rename from allocate_stack_worker_1;
+	describe the clobber of eax without a match_scratch.
+	(allocate_stack_worker_postreload): Remove.
+	(allocate_stack_worker_64): Rename from allocate_stack_worker_rex64;
+	describe the clobbers of rax, r10, r11 properly; use __chkstk symbol.
+	(allocate_stack_worker_rex64_postreload): Remove.
+	(allocate_stack): Handle 64-bit.
+	* config/i386/i386elf (TARGET_SUBTARGET_DEFAULT): Remove.
+	* config/i386/mingw32.h (TARGET_VERSION): Set correctly for 64-bit.
+	(EXTRA_OS_CPP_BUILTINS): Handle 64-bit.
+	(STANDARD_INCLUDE_DIR): Handle TARGET_64BIT_DEFAULT.
+	(STANDARD_STARTFILE_PREFIX_1): Likewise.
+	* config/i386/unix.h (TARGET_SUBTARGET64_DEFAULT): New.
+	* config.build (x86_64-*-mingw*): New host.
+	* config.host (x86_64-*-mingw*): New host.
+	* config.gcc (x86_64-*-mingw*): New target.
+	* gthr-win32.h (__gthread_key_create): Mark dtor unused.

--- gcc/config/i386/cygming.h	(revision 123380)
+++ 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
+\f
+#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)
 \f
 /* 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 *
@@ -166,19 +201,21 @@ do {							\
 } while (0)
 
 \f
-/* 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
@@ -245,7 +282,9 @@ do {							\
 /* 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
@@ -346,8 +385,8 @@ do {							\
 #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 123380)
+++ 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 123380)
+++ 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.c	(revision 123380)
+++ gcc/config/i386/i386.c	(local)
@@ -1308,9 +1308,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.  */
@@ -1857,9 +1863,16 @@ override_options (void)
     }
   else
     {
-      ix86_cmodel = CM_32;
-      if (TARGET_64BIT)
+      /* For TARGET_64BIT_MS_ABI, force pic on, in order to enable the
+	 use of rip-relative addressing.  This eliminates fixups that
+	 would otherwise be needed if this object is to be placed in a
+	 DLL, and is essentially just as efficient as direct addressing.  */
+      if (TARGET_64BIT_MS_ABI)
+	ix86_cmodel = CM_SMALL_PIC, flag_pic = 1;
+      else if (TARGET_64BIT)
 	ix86_cmodel = flag_pic ? CM_SMALL_PIC : CM_SMALL;
+      else
+        ix86_cmodel = CM_32;
     }
   if (ix86_asm_string != 0)
     {
@@ -1981,15 +1994,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.
@@ -2135,18 +2149,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
@@ -2644,8 +2656,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;
     }
@@ -2932,6 +2946,7 @@ bool
 ix86_function_arg_regno_p (int regno)
 {
   int i;
+  const int *parm_regs;
 
   if (!TARGET_64BIT)
     {
@@ -2959,11 +2974,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;
 }
@@ -3741,6 +3760,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)
@@ -3756,7 +3790,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);
@@ -3887,9 +3923,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 (TARGET_SSE && (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;
@@ -3905,7 +3979,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);
@@ -3922,7 +3998,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;
@@ -4025,6 +4124,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:
@@ -4132,6 +4233,22 @@ 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 (TARGET_SSE)
+    {
+      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)
 {
@@ -4142,7 +4259,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);
@@ -4214,12 +4333,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);
@@ -4280,7 +4414,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);
@@ -4400,6 +4534,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)
@@ -4426,7 +4581,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.  */
@@ -4440,7 +4598,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;
@@ -4519,7 +4677,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));
@@ -5711,21 +5869,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);
@@ -5741,7 +5908,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));
 	}
     }
 
@@ -5995,7 +6162,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));
@@ -6848,7 +7015,8 @@ legitimize_pic_address (rtx orig, rtx re
 	addr = XEXP (addr, 0);
       if (GET_CODE (addr) == PLUS)
 	  {
-            new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)), UNSPEC_GOTOFF);
+            new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)),
+				  UNSPEC_GOTOFF);
 	    new = gen_rtx_PLUS (Pmode, new, XEXP (addr, 1));
 	  }
 	else
@@ -6879,7 +7047,8 @@ legitimize_pic_address (rtx orig, rtx re
 	addr = XEXP (addr, 0);
       if (GET_CODE (addr) == PLUS)
 	  {
-            new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)), UNSPEC_GOTOFF);
+            new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, XEXP (addr, 0)),
+				  UNSPEC_GOTOFF);
 	    new = gen_rtx_PLUS (Pmode, new, XEXP (addr, 1));
 	  }
 	else
@@ -6898,6 +7067,11 @@ legitimize_pic_address (rtx orig, rtx re
 	      see gotoff_operand.  */
 	   || (TARGET_VXWORKS_RTP && GET_CODE (addr) == LABEL_REF))
     {
+      /* Given that we've already handled dllimport variables separately
+	 in legitimize_address, and all other variables should satisfy
+	 legitimate_pic_address_disp_p, we should never arrive here.  */
+      gcc_assert (!TARGET_64BIT_MS_ABI);
+
       if (TARGET_64BIT && ix86_cmodel != CM_LARGE_PIC)
 	{
 	  new = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, addr), UNSPEC_GOTPCREL);
@@ -7505,7 +7679,8 @@ output_pic_addr_const (FILE *file, rtx x
 	{
 	  const char *name = XSTR (x, 0);
 
-	  /* Mark the decl as referenced so that cgraph will output the function.  */
+	  /* Mark the decl as referenced so that cgraph will
+	     output the function.  */
 	  if (SYMBOL_REF_DECL (x))
 	    mark_decl_referenced (SYMBOL_REF_DECL (x));
 
@@ -7516,7 +7691,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;
 
@@ -9291,7 +9467,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.  */
@@ -19508,37 +19683,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.  */
@@ -19627,7 +19794,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);
 	}
@@ -19669,6 +19836,10 @@ x86_output_mi_thunk (FILE *file ATTRIBUT
     {
       if (!flag_pic || (*targetm.binds_local_p) (function))
 	output_asm_insn ("jmp\t%P0", xops);
+      /* All thunks should be in the same object as their target,
+	 and thus binds_local_p should be true.  */
+      else if (TARGET_64BIT_MS_ABI)
+	gcc_unreachable ();
       else
 	{
 	  tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, xops[0]), UNSPEC_GOTPCREL);
@@ -19745,20 +19916,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
@@ -21817,6 +21984,8 @@ static const struct attribute_spec ix86_
 #define TARGET_INTERNAL_ARG_POINTER ix86_internal_arg_pointer
 #undef TARGET_DWARF_HANDLE_FRAME_UNSPEC
 #define TARGET_DWARF_HANDLE_FRAME_UNSPEC ix86_dwarf_handle_frame_unspec
+#undef TARGET_STRICT_ARGUMENT_NAMING
+#define TARGET_STRICT_ARGUMENT_NAMING hook_bool_CUMULATIVE_ARGS_true
 
 #undef TARGET_GIMPLIFY_VA_ARG_EXPR
 #define TARGET_GIMPLIFY_VA_ARG_EXPR ix86_gimplify_va_arg
--- gcc/config/i386/i386.h	(revision 123380)
+++ 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 {
@@ -372,11 +373,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
@@ -998,6 +1005,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 123380)
+++ 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 123380)
+++ 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 123380)
+++ 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,28 @@ 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 +90,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/unix.h	(revision 123380)
+++ 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.build	(revision 123380)
+++ 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-*-mingw*)
     build_xm_file=i386/xm-mingw32.h
     build_exeext=.exe
     ;;
--- gcc/config.gcc	(revision 123380)
+++ 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 123380)
+++ 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-*-mingw*)
     host_xm_file=i386/xm-mingw32.h
     host_xmake_file="${host_xmake_file} i386/x-mingw32"
     host_exeext=.exe
--- gcc/gthr-win32.h	(revision 123380)
+++ 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 ();
--- libgcc/ChangeLog	(revision 123380)
+++ libgcc/ChangeLog	(local)
@@ -1,3 +1,7 @@
+2007-02-30  Kai Tietz  <kai.tietz@onevision.com>
+
+	* config.host (x86_64-*-mingw*): New target.
+
 2007-03-23  Michael Meissner  <michael.meissner@amd.com>
 	    H.J. Lu  <hongjiu.lu@intel.com>
 
--- libgcc/config.host	(revision 123380)
+++ 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*)
 	;;

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised #pragma push_macro feature
  2007-03-30 21:43             ` revised #pragma push_macro feature Richard Henderson
@ 2007-03-30 22:42               ` Rafael Espindola
  2007-03-30 23:23               ` Steven Bosscher
  2007-03-31  4:13               ` Michael Meissner
  2 siblings, 0 replies; 33+ messages in thread
From: Rafael Espindola @ 2007-03-30 22:42 UTC (permalink / raw)
  To: Richard Henderson, Kai Tietz, gcc-patches

On 3/30/07, Richard Henderson <rth@redhat.com> wrote:
> I've rearranged and committed the push_macro feature.
>
> Notable changes: hash table for the pushed macros, rather
> than searching a single linked list.  Support from libcpp
> to save/restore a pre-parsed cpp_macro structure, rather
> than pushing this through the lexer again.
>
I think that this patch broke bootstrap on i686:

/usr/local/google/home/espindola/20/gcc/build/./prev-gcc/xgcc
-B/usr/local/google/home/espindola/20/gcc/build/./prev-gcc/
-B/usr/local/i686-pc-linux-gnu/bin/  -I../../trunk/libcpp -I.
-I../../trunk/libcpp/../include -I../../trunk/libcpp/include  -O2 -g
-fomit-frame-pointer -W -Wall -Wwrite-strings -Wstrict-prototypes
-Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute
-pedantic -Wno-long-long -Werror -I../../trunk/libcpp -I.
-I../../trunk/libcpp/../include -I../../trunk/libcpp/include  -c -o
directives.o -MT directives.o -MMD -MP -MF .deps/directives.Po
../../trunk/libcpp/directives.c
cc1: warnings being treated as errors
../../trunk/libcpp/directives.c: In function 'lex_macro_node_from_str':
../../trunk/libcpp/directives.c:2086: error: pointer targets in
initialization differ in signedness
make[3]: *** [directives.o] Error 1

Cheers,
Rafael

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised #pragma push_macro feature
  2007-03-30 21:43             ` revised #pragma push_macro feature Richard Henderson
  2007-03-30 22:42               ` Rafael Espindola
@ 2007-03-30 23:23               ` Steven Bosscher
  2007-03-31  4:13               ` Michael Meissner
  2 siblings, 0 replies; 33+ messages in thread
From: Steven Bosscher @ 2007-03-30 23:23 UTC (permalink / raw)
  To: gcc-patches; +Cc: Richard Henderson, Kai Tietz

On Friday 30 March 2007 23:16, Richard Henderson wrote:
> I've rearranged and committed the push_macro feature.

Is there documentation for the user, too?

Gr.
Steven

^ permalink raw reply	[flat|nested] 33+ messages in thread

* Re: revised #pragma push_macro feature
  2007-03-30 21:43             ` revised #pragma push_macro feature Richard Henderson
  2007-03-30 22:42               ` Rafael Espindola
  2007-03-30 23:23               ` Steven Bosscher
@ 2007-03-31  4:13               ` Michael Meissner
  2 siblings, 0 replies; 33+ messages in thread
From: Michael Meissner @ 2007-03-31  4:13 UTC (permalink / raw)
  To: Richard Henderson, Kai Tietz, gcc-patches

On Fri, Mar 30, 2007 at 05:16:18PM -0400, Richard Henderson wrote:
> I've rearranged and committed the push_macro feature.
> 
> Notable changes: hash table for the pushed macros, rather
> than searching a single linked list.  Support from libcpp
> to save/restore a pre-parsed cpp_macro structure, rather
> than pushing this through the lexer again.
> 
> 
> r~
> 
> libcpp/
>         * directives.c (lex_macro_node_from_str): New.
>         (cpp_push_definition, cpp_pop_definition): New.
>         * include/cpplib.h (cpp_push_definition, cpp_pop_definition): Declare.
> gcc/
>         * c-pragma.c (struct def_pragma_macro_value): New.
>         (struct def_pragma_macro): New.
>         (pushed_macro_table): New.
>         (dpm_hash, dpm_eq): New.
>         (handle_pragma_push_macro, handle_pragma_pop_macro): New.
>         (init_pragma): Install them.
>         * doc/tm.texi (HANDLE_PRAGMA_PUSH_POP_MACRO): New.

I'm seeing the following error when bootstrapping the compiler on my Fedora
Core 6 systems (both 32-bit and 64-bit):

make[3]: Entering directory `/data/fsf-build/trunk/libcpp'
/data/meissner/fsf-build/trunk/./prev-gcc/xgcc -B/data/meissner/fsf-build/trunk/./prev-gcc/ -B/proj/gcc/fsf-install/trunk/x86_64-unknown-linux-gnu/bin/  -I/proj/gcc/fsf-src/trunk/libcpp -I. -I/proj/gcc/fsf-src/trunk/libcpp/../include -I/proj/gcc/fsf-src/trunk/libcpp/include  -g -O2 -W -Wall -Wwrite-strings -Wstrict-prototypes -Wmissing-prototypes -Wold-style-definition -Wmissing-format-attribute -pedantic -Wno-long-long -Werror -I/proj/gcc/fsf-src/trunk/libcpp -I. -I/proj/gcc/fsf-src/trunk/libcpp/../include -I/proj/gcc/fsf-src/trunk/libcpp/include  -c -o directives.o -MT directives.o -MMD -MP -MF .deps/directives.Po /proj/gcc/fsf-src/trunk/libcpp/directives.c
cc1: warnings being treated as errors
/proj/gcc/fsf-src/trunk/libcpp/directives.c: In function #lex_macro_node_from_str#:
/proj/gcc/fsf-src/trunk/libcpp/directives.c:2086: error: pointer targets in initialization differ in signedness
make[3]: *** [directives.o] Error 1
make[3]: Leaving directory `/data/fsf-build/trunk/libcpp'
make[2]: *** [all-stage2-libcpp] Error 2
make[2]: Leaving directory `/data/fsf-build/trunk'
make[1]: *** [stage2-bubble] Error 2
make[1]: Leaving directory `/data/fsf-build/trunk'
make: *** [all] Error 2

I took the liberty of checking in the following patch as obvious:

2007-03-30  Michael Meissner  <michael.meissner@amd.com>

	* directives.c (lex_macro_node_from_str): Fix alloca call to be
	type correct.

--- libcpp/directives.c.~1~	2007-03-30 17:56:32.000000000 -0400
+++ libcpp/directives.c	2007-03-30 18:38:04.000000000 -0400
@@ -2083,7 +2083,7 @@ static cpp_hashnode *
 lex_macro_node_from_str (cpp_reader *pfile, const char *str)
 {
   size_t len = strlen (str);
-  uchar *buf = (char *) alloca (len + 1);
+  uchar *buf = (uchar *) alloca (len + 1);
   cpp_hashnode *node;
 
   memcpy (buf, str, len);

-- 
Michael Meissner, AMD
90 Central Street, MS 83-29, Boxborough, MA, 01719, USA
michael.meissner@amd.com


^ permalink raw reply	[flat|nested] 33+ messages in thread

end of thread, other threads:[~2007-03-30 22:42 UTC | newest]

Thread overview: 33+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2007-03-14 14:27 PATCH: x86_64-pc-mingw32 target for gcc Kai Tietz
2007-03-20 19:42 ` Richard Henderson
2007-03-21 10:35   ` Kai Tietz
2007-03-21 18:06     ` Richard Henderson
2007-03-21 12:13   ` Kai Tietz
2007-03-21 17:04     ` Richard Henderson
2007-03-21 17:37       ` Kai Tietz
2007-03-21 18:18         ` Richard Henderson
2007-03-21 18:02       ` Kai Tietz
2007-03-22  0:33 ` revised x86_64-pc-mingw32 patch Richard Henderson
2007-03-22 13:02   ` Kai Tietz
2007-03-22 17:43     ` Richard Henderson
2007-03-23 10:02       ` Kai Tietz
2007-03-23 15:51         ` Richard Henderson
2007-03-26 10:23           ` Kai Tietz
2007-03-26 11:24           ` Kai Tietz
2007-03-23 13:48       ` Kai Tietz
2007-03-26 10:55       ` Kai Tietz
2007-03-27 13:13   ` Kai Tietz
2007-03-27 16:07     ` Richard Henderson
2007-03-27 16:32       ` Kai Tietz
2007-03-27 17:13         ` Richard Henderson
2007-03-27 17:21         ` Michael Matz
2007-03-27 23:48   ` revised**2 " Richard Henderson
2007-03-28 12:43     ` Kai Tietz
2007-03-28 17:02       ` Richard Henderson
2007-03-28 17:13         ` Richard Henderson
2007-03-29 13:01           ` Kai Tietz
2007-03-30 21:43             ` revised #pragma push_macro feature Richard Henderson
2007-03-30 22:42               ` Rafael Espindola
2007-03-30 23:23               ` Steven Bosscher
2007-03-31  4:13               ` Michael Meissner
2007-03-30 22:29             ` revised**2 x86_64-pc-mingw32 patch Richard Henderson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).