Index: trunk/src/gcc/gcc/config/i386/emx.c
===================================================================
--- trunk/src/gcc/gcc/config/i386/emx.c	(revision 641)
+++ trunk/src/gcc/gcc/config/i386/emx.c	(revision 645)
@@ -30,7 +30,5 @@
 #include "toplev.h"
 #include "flags.h"
-
-/* Prototypes */
-static const char *gen_stdcall_suffix (tree);
+#include "i386-protos.h"
 
 /* The size of the target's pointer type.  */
@@ -100,163 +98,138 @@
 #endif
 
-tree ix86_handle_vacpp_attribute (tree *node, tree name, tree args,
-  int flags, bool *no_add_attrs)
-{
-  tree id, type, context;
-  size_t sl;
+int emx_c_set_decl_assembler_name (tree decl)
+{
+  static int recurse;
   const char *oldsym;
   char *newsym;
-
-  DUMP (*node);
-
-  switch (TREE_CODE (*node))
-    {
-      case FUNCTION_DECL:
-        /* This is the core of attribute handling. Every other code is
-           designed so that we end up with a function declaration and
-           an attached attribute (either optlink or system).
-           This is the only part which is changing the mangling. */
-
-        type = TREE_TYPE (*node);
-
-        if (ix86_check_append_attr (type, name, no_add_attrs))
-          break;
-
-        if (is_attribute_p ("system", name))
+  size_t sl;
+  tree id, type;
+  int rc = 1;
+
+  /* Sometimes we recursively call DECL_ASSEMBLER_NAME to apply the default
+     mangling rules for current compiler. */
+  if (recurse)
+    return 0;
+
+  recurse++;
+
+  type = TREE_TYPE (decl);
+
+  if (lookup_attribute ("system", TYPE_ATTRIBUTES (type)))
+    {
+      /* Here we mangle _System functions as defined by IBM specs.
+         The function always gets its name as-is (unless it is a method,
+         which is a undefined case as VACPP always use _Optlink for methods,
+         at least that's what I have understood from the docs). */
+
+      oldsym = IDENTIFIER_POINTER (DECL_NAME (decl));
+
+      /* Specifying '*' as first symbol character tells gcc (see varasm.c,
+         function assemble_name()) to output the label as-is rather than
+         invoking the ASM_OUTPUT_LABELREF macro (which prepends a underscore) */
+
+      sl = strlen (oldsym);
+      newsym = xmalloc (sl + 2);
+      newsym [0] = '*';
+      memcpy (newsym + 1, oldsym, sl + 1);
+
+      SET_DECL_ASSEMBLER_NAME (decl, get_identifier (newsym));
+
+      dfprintf ((stderr, "dbg: system %s -> %s\n", oldsym, newsym));
+    }
+  else if (lookup_attribute ("optlink", TYPE_ATTRIBUTES (type)))
+    {
+      /* At the moment we're only implementing OS/2 VAC linking
+         compatibility for the C language. This means that no leading
+         underscore.
+         For C++ we are not compatible. It doesn't make that much sense
+         either since we're not VFT compatible either. For simplicity
+         and safety we are removing the leading underscore from the
+         default mangled names to catch invalid declarations in the
+         linking. */
+
+      id = DECL_ASSEMBLER_NAME (decl);
+
+      /* Remove the leading underscore. */
+      oldsym = IDENTIFIER_POINTER (id);
+      sl = strlen (oldsym);
+      newsym = xmalloc (sl + 2);
+      newsym [0] = '*';
+      memcpy (newsym + 1, oldsym, sl + 1);
+
+      XEXP (DECL_RTL (decl), 0) = gen_rtx (SYMBOL_REF, Pmode,
+        IDENTIFIER_POINTER (get_identifier (newsym)));
+
+      dfprintf ((stderr, "dbg: optlink %s -> %s\n", oldsym, newsym));
+    }
+  else if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (type)))
+    {
+      /* Mangle decl as the former assembler name modified with a
+         suffix consisting of an atsign (@) followed by the number of bytes of
+         arguments */
+
+      int total = 0;
+
+      /* If function does not have ellipsis as last argument, count total args size */
+      if (TYPE_ARG_TYPES (type))
+        if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (type))) == void_type_node)
           {
-            /* Here we mangle _System functions as defined by IBM specs.
-               The function always gets its name as-is (unless it is a method,
-               which is a undefined case as VACPP always use _Optlink for methods,
-               at least that's what I have understood from the docs). */
-            /* @todo: verify the class detection here! Does it require use of
-                CLASSTYPE_DECLARED_CLASS (meaning it doesn't apply to plain
-                structs/unions) ? */
-            if (   TREE_CODE (type) != METHOD_TYPE
-                && (   !(context = DECL_CONTEXT (*node))
-                    || (   TREE_CODE (context) != RECORD_TYPE
-                        && TREE_CODE (context) != UNION_TYPE)))
+            tree formal_type = TYPE_ARG_TYPES (type);
+
+            while (TREE_VALUE (formal_type) != void_type_node)
               {
-                oldsym = IDENTIFIER_POINTER (DECL_NAME (*node));
-                /* Specifying '*' as first symbol character tells gcc (see varasm.c,
-                   function assemble_name()) to output the label as-is rather than
-                   invoking the ASM_OUTPUT_LABELREF macro (which prepends a underscore) */
-                sl = strlen (oldsym);
-                newsym = xmalloc (sl + 2);
-                newsym [0] = '*';
-                memcpy (newsym + 1, oldsym, sl + 1);
-                SET_DECL_ASSEMBLER_NAME (*node, get_identifier (newsym));
-                dfprintf((stderr, "dbg: system %s -> %s\n", oldsym, newsym));
+                int parm_size = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
+                /* Must round up to include padding.  This is done the same
+                   way as in store_one_arg.  */
+                parm_size = ((parm_size + PARM_BOUNDARY - 1) / PARM_BOUNDARY * PARM_BOUNDARY);
+                total += parm_size;
+                formal_type = TREE_CHAIN (formal_type);
               }
           }
-        else if (is_attribute_p ("optlink", name))
-          {
-            /* At the moment we're only implementing OS/2 VAC linking
-               compatibility for the C language. This means that no leading
-               underscore.
-               For C++ we are not compatible. It doesn't make that much sense
-               either since we're not VFT compatible either. For simplicity
-               and safety we are removing the leading underscore from the
-               default mangled names to catch invalid declarations in the
-               linking. */
-
-            id = DECL_ASSEMBLER_NAME (*node);
-            /* Remove the leading underscore. */
-            oldsym = IDENTIFIER_POINTER (id);
-            sl = strlen (oldsym);
-            newsym = xmalloc (sl + 2);
-            newsym [0] = '*';
-            memcpy (newsym + 1, oldsym, sl + 1);
-            XEXP (DECL_RTL (*node), 0) = gen_rtx (SYMBOL_REF, Pmode,
-              IDENTIFIER_POINTER (get_identifier (newsym)));
-            dfprintf ((stderr, "dbg: optlink %s -> %s\n", oldsym, newsym));
-          }
-        else /* Internal error!!! */
-          {
-            warning ("unexpected attribute `%s' in ix86_handle_vacpp_attribute()",
-                     IDENTIFIER_POINTER (name));
-            *no_add_attrs = true;
-            break;
-          }
-
-        /* The attribute should really be attached to our _TYPE
-           rather than to the _DECL. */
-        TYPE_ATTRIBUTES (type) = chainon (TYPE_ATTRIBUTES (type),
-                                          tree_cons (name, args, NULL_TREE));
-        *no_add_attrs = true;
-        break;
-
-      /* Only function declarations needs mangling changes, however other
-         declarations involving function types needs to get the parameter
-         passing right. */
-      /*case CONST_DECL: ?? */
-        /* Is this possible - make testcase. */
-      /*case PARM_DECL: ?? */
-        /* Is this possible - make testcase. */
-      case VAR_DECL:
-        /* Function pointer variable. */
-      case FIELD_DECL:
-        /* Struct, union or class member declaration. Same handling as
-           type declarations. */
-      case TYPE_DECL:
-        /* If this is a type declaration with our attribute, we allow it
-           only if it is a pointer-to-a-function type or a function type. */
-        type = TREE_TYPE (*node);
-        if (TREE_CODE (type) == POINTER_TYPE)
-          type = TREE_TYPE(type);
-        if (   TREE_CODE (type) == FUNCTION_TYPE
-            || TREE_CODE (type) == METHOD_TYPE)
-          {
-            if (ix86_check_append_attr (type, name, no_add_attrs))
-              break;
-
-            /* Attach the attribute to the (FUNCTION|METHOD)_TYPE node */
-            TYPE_ATTRIBUTES (type) = chainon (TYPE_ATTRIBUTES (type),
-                                              tree_cons (name, args, NULL_TREE));
-            *no_add_attrs = true;
-            break;
-          }
-        warning ("`%s' attribute only applies to functions and function types",
-                 IDENTIFIER_POINTER (name));
-        *no_add_attrs = true;
-        break;
-
-
-      /* For types involving functions we need to convince decl_attributes
-         (and its callers) to supply a declaration in case the mangling needs
-         to be changed. */
-      case POINTER_TYPE:
-        /* We allow:
-           This being the return type of a function which is coming soon.
-           This being a function pointer which declaration is coming next.
-           Everything else is considered inappropriate use of the attribute. */
-        if (   !(flags & ATTR_FLAG_FUNCTION_NEXT)
-            && (    !(flags & ATTR_FLAG_DECL_NEXT)
-                ||  !(type = TREE_TYPE (*node))
-                || (   TREE_CODE (type) != FUNCTION_TYPE
-                    && TREE_CODE (type) != METHOD_TYPE)))
-        {
-            warning ("`%s' attribute only applies to functions and function types",
-                     IDENTIFIER_POINTER (name));
-            *no_add_attrs = true;
-            break;
-        }
-        /* fall thru */
-      case FUNCTION_TYPE:
-      case METHOD_TYPE:
-        /* This branch is taken when a function/method type is encountered.
-           We defer attribute handling until we get the complete declaration */
-#if 0 /* bird: This fixes optlink/tst4.c and doesn't seem to break anything.
-               If set to true we are in some cases imposing _Optlink onto following
-               declarations. This is weird stuff! */
-        *no_add_attrs = true;
-#endif
-        return tree_cons (name, args, NULL_TREE);
-
-      default:
-        warning ("`%s' attribute only applies to functions and function types (code=%d)",
-                 IDENTIFIER_POINTER (name), TREE_CODE (*node));
-        *no_add_attrs = true;
-        break;
-    }
+
+      id = DECL_ASSEMBLER_NAME (decl);
+      oldsym = IDENTIFIER_POINTER (id);
+      newsym = xmalloc (strlen (oldsym) + 10);
+      sprintf (newsym, "%s@%d", oldsym, total / BITS_PER_UNIT);
+
+      XEXP (DECL_RTL (decl), 0) =
+        gen_rtx (SYMBOL_REF, Pmode, IDENTIFIER_POINTER (get_identifier (newsym)));
+
+      dfprintf ((stderr, "dbg: stdcall %s -> %s\n", oldsym, newsym));
+    }
+  else
+    rc = 0;
+
+  recurse--;
+  return rc;
+}
+
+tree emx_handle_vacpp_attribute (tree *node, tree name, tree args,
+  int flags, bool *no_add_attrs)
+{
+  (void) args;
+  (void) flags;
+
+  DUMP (*node);
+
+  if (TREE_CODE (*node) != FUNCTION_TYPE
+      && TREE_CODE (*node) != METHOD_TYPE
+      && TREE_CODE (*node) != FIELD_DECL
+      && TREE_CODE (*node) != TYPE_DECL)
+    {
+      warning ("`%s' attribute only applies to functions",
+	       IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  if (TARGET_64BIT)
+    {
+      warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
+      *no_add_attrs = true;
+    }
+
+  /* Check if the attributes are compatible */
+  if (ix86_check_append_attr (*node, name, no_add_attrs))
+    return NULL_TREE;
 
   return NULL_TREE;
@@ -292,77 +265,2 @@
   }
 }
-
-/* Return string which is the former assembler name modified with a
-   suffix consisting of an atsign (@) followed by the number of bytes of
-   arguments */
-
-static const char *
-gen_stdcall_suffix (tree decl)
-{
-  int total = 0;
-  /* ??? This probably should use XSTR (XEXP (DECL_RTL (decl), 0), 0) instead
-     of DECL_ASSEMBLER_NAME.  */
-  const char *asmname = IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (decl));
-  char *newsym;
-
-  if (TYPE_ARG_TYPES (TREE_TYPE (decl)))
-    if (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (decl))))
-        == void_type_node)
-      {
-	tree formal_type = TYPE_ARG_TYPES (TREE_TYPE (decl));
-
-	while (TREE_VALUE (formal_type) != void_type_node)
-	  {
-	    int parm_size
-	      = TREE_INT_CST_LOW (TYPE_SIZE (TREE_VALUE (formal_type)));
-	    /* Must round up to include padding.  This is done the same
-	       way as in store_one_arg.  */
-	    parm_size = ((parm_size + PARM_BOUNDARY - 1)
-			 / PARM_BOUNDARY * PARM_BOUNDARY);
-	    total += parm_size;
-	    formal_type = TREE_CHAIN (formal_type);
-	  }
-      }
-
-  newsym = xmalloc (strlen (asmname) + 10);
-  sprintf (newsym, "%s@%d", asmname, total/BITS_PER_UNIT);
-  return IDENTIFIER_POINTER (get_identifier (newsym));
-}
-
-/* Cover function to implement ENCODE_SECTION_INFO.
-   Note that this could be implemented much better by doing the
-   stdcall mangling like optlink and system, but unfortunately */
-
-void
-emx_encode_section_info (tree decl)
-{
-  /* The default ENCODE_SECTION_INFO from i386.h */
-  if (flag_pic)
-    {
-      rtx rtl = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
-                 ? TREE_CST_RTL (decl) : DECL_RTL (decl));
-
-      if (GET_CODE (rtl) == MEM)
-        {
-          if (TARGET_DEBUG_ADDR
-              && TREE_CODE_CLASS (TREE_CODE (decl)) == 'd')
-            {
-              fprintf (stderr, "Encode %s, public = %d\n",
-                       IDENTIFIER_POINTER (DECL_NAME (decl)),
-                       TREE_PUBLIC (decl));
-            }
-
-          SYMBOL_REF_FLAG (XEXP (rtl, 0))
-            = (TREE_CODE_CLASS (TREE_CODE (decl)) != 'd'
-               || ! TREE_PUBLIC (decl));
-        }
-    }
-
-  /* If declaring a function, mangle it if it's stdcall */
-  if (TREE_CODE (decl) == FUNCTION_DECL)
-    {
-      if (lookup_attribute ("stdcall", TYPE_ATTRIBUTES (TREE_TYPE (decl))))
-        XEXP (DECL_RTL (decl), 0) =
-          gen_rtx (SYMBOL_REF, Pmode, gen_stdcall_suffix (decl));
-    }
-}
Index: trunk/src/gcc/gcc/config/i386/emx.h
===================================================================
--- trunk/src/gcc/gcc/config/i386/emx.h	(revision 641)
+++ trunk/src/gcc/gcc/config/i386/emx.h	(revision 645)
@@ -92,13 +92,21 @@
 
 /* This function handles both _System and _Optlink attributes */
-extern tree ix86_handle_vacpp_attribute PARAMS ((tree *, tree, tree, int, _Bool *));
+extern tree emx_handle_vacpp_attribute PARAMS ((tree *, tree, tree, int, _Bool *));
 
 /* We want the _System attribute */
 #define TARGET_SYSTEM_DECL_ATTRIBUTES
-#define ix86_handle_system_attribute ix86_handle_vacpp_attribute
+#define ix86_handle_system_attribute emx_handle_vacpp_attribute
 
 /* We want the _Optlink attribute */
 #define TARGET_OPTLINK_DECL_ATTRIBUTES
-#define ix86_handle_optlink_attribute ix86_handle_vacpp_attribute
+#define ix86_handle_optlink_attribute emx_handle_vacpp_attribute
+
+/* Do our own mangling on some kinds of decls */
+extern int emx_c_set_decl_assembler_name PARAMS ((tree));
+#define TARGET_C_SET_DECL_ASSEMBLER_NAME(decl) \
+  emx_c_set_decl_assembler_name (decl)
+#define TARGET_CXX_SET_DECL_ASSEMBLER_NAME(decl) \
+  (DECL_LANG_SPECIFIC(decl) && DECL_FUNCTION_MEMBER_P (decl) ? 0 : \
+   emx_c_set_decl_assembler_name (decl))
 
 /* This macros will stick a label to exception table for current file,
@@ -183,14 +191,8 @@
 *******************************************************************/
 
-/* Define this macro if references to a symbol must be treated
-   differently depending on something about the variable or
-   function named by the symbol (such as what section it is in). */
-#undef ENCODE_SECTION_INFO
-#define ENCODE_SECTION_INFO(DECL) emx_encode_section_info (DECL)
-extern void emx_encode_section_info PARAMS ((tree));
-
-/* This macro gets just the user-specified name
-   out of the string in a SYMBOL_REF.  Discard
-   trailing @[NUM] encoded by ENCODE_SECTION_INFO.  */
+/* This macro gets just the user-specified name out of the string
+   in a SYMBOL_REF. Discard trailing @[NUM] encoded by ENCODE_SECTION_INFO.
+   This is used to generate unique section names from function names
+   (if -ffunction-sections is given).  */
 #undef  STRIP_NAME_ENCODING
 #define STRIP_NAME_ENCODING(VAR,SYMBOL_NAME)				\
Index: trunk/src/gcc/gcc/config/i386/i386.c
===================================================================
--- trunk/src/gcc/gcc/config/i386/i386.c	(revision 641)
+++ trunk/src/gcc/gcc/config/i386/i386.c	(revision 645)
@@ -1288,9 +1288,9 @@
 #ifdef TARGET_SYSTEM_DECL_ATTRIBUTES
   /* System says the function is extern "C" and is not underscored. */
-  { "system",    0, 0, false, false, false, ix86_handle_system_attribute },
+  { "system",    0, 0, false, true,  true,  ix86_handle_system_attribute },
 #endif
 #ifdef TARGET_OPTLINK_DECL_ATTRIBUTES
   /* Optlink is like regparm with a few differences */
-  { "optlink",   0, 0, false, false, false, ix86_handle_optlink_attribute },
+  { "optlink",   0, 0, false, true,  true,  ix86_handle_optlink_attribute },
 #endif
   { NULL,        0, 0, false, false, false, NULL }
@@ -1739,15 +1739,25 @@
     {
 #ifdef TARGET_OPTLINK_DECL_ATTRIBUTES
-      /* Count conforming arguments for optlink */
-      int cfarg_count = 0;
+      if (cum->optlink)
+      {
+        /* Only arguments until the ellipsis are passed in registers. Count them. */
+        cum->nregs = 0;
+        cum->fpu_nregs = 0;
+        /* The total size of arguments passed in registers can be up to 12 dwords.
+           Float types count for their real size (e.g. float for 1 dword, double
+           for 2 dwords, long double for 4 dwords). */
+        cum->ec_slots = 12;
+      }
 #endif
-
       for (param = (fntype) ? TYPE_ARG_TYPES (fntype) : 0;
 	   param != 0; param = next_param)
 	{
 #ifdef TARGET_OPTLINK_DECL_ATTRIBUTES
-          if (INTEGRAL_TYPE_P (TREE_VALUE (param))
-           || POINTER_TYPE_P (TREE_VALUE (param)))
-            cfarg_count++;
+          if (cum->optlink)
+            if (INTEGRAL_TYPE_P (TREE_VALUE (param))
+             || POINTER_TYPE_P (TREE_VALUE (param)))
+              cum->nregs++;
+            else if (TREE_CODE (TREE_VALUE (param)) == REAL_TYPE)
+              cum->fpu_nregs++;
 #endif
 	  next_param = TREE_CHAIN (param);
@@ -1755,9 +1765,7 @@
 	    {
 #ifdef TARGET_OPTLINK_DECL_ATTRIBUTES
-              /* Visual Age docs says that the params preceeding the
-                 ellipsis still are passed in registers. */
-              if (cum->optlink)
-                cum->nregs = cfarg_count > 3 ? 3 : cfarg_count;
-              else
+              /* _Optlink calling convention says all args until the ellipsis
+                 are passed in registers, and all varargs on the stack. */
+              if (!cum->optlink)
 #endif
 	      if (!TARGET_64BIT)
@@ -1766,4 +1774,15 @@
 	    }
 	}
+
+#ifdef TARGET_OPTLINK_DECL_ATTRIBUTES
+      /* Limit number of registers to pass arguments as in _Optlink specification */
+      if (cum->optlink)
+        {
+          if (cum->nregs > 3)
+            cum->nregs = 3;
+          if (cum->fpu_nregs > 4)
+            cum->fpu_nregs = 4;
+        }
+#endif
     }
   if ((!fntype && !libname)
@@ -2324,5 +2343,9 @@
   else
     {
-      if (TARGET_SSE && mode == TImode)
+      if (TARGET_SSE && mode == TImode
+#ifdef TARGET_OPTLINK_DECL_ATTRIBUTES
+          && !cum->optlink
+#endif
+         )
 	{
 	  cum->sse_words += words;
@@ -2341,11 +2364,56 @@
           /* Optlink functions never pass aggregates in registers
              (they are pushed on the stack, and the registers are
-             preserved for following parameters). Unfortunately GCC
-             optimizes short structures to SImode or DImode, thus
-             this detection works only for large structs. */
-          if (cum->optlink
-           && !(INTEGRAL_TYPE_P (type)
-             || POINTER_TYPE_P (type)))
-            return;
+             preserved for following parameters). */
+          if (cum->optlink)
+            {
+              /* If out of eyecatcher slots, do nothing */
+              if (!cum->ec_slots)
+                return;
+
+              if (INTEGRAL_TYPE_P (type)
+               || POINTER_TYPE_P (type))
+                {
+                  /* Integer types takes one slot in eyecatcher */
+                  cum->ec_slots--;
+                }
+              else if (TREE_CODE (type) == REAL_TYPE)
+                {
+                  /* Fixed-point parameters are passed in FPU registers */
+                  if (cum->fpu_nregs)
+                    {
+                      cum->fpu_nregs--;
+                      cum->fpu_regno++;
+                      regstack_first_undef_reg = FIRST_FLOAT_REG + cum->fpu_regno;
+                      /* Args passed in FPU stack takes one eyecatcher slot */
+                      cum->ec_slots--;
+                    }
+                  else
+                    {
+                      /* FPU args passed on RT stack takes 1/2/4 slots */
+                      cum->ec_slots -= words;
+                    }
+
+                  /* The case with ec_slots <= 0 will be catched a little lates */
+                  if (cum->ec_slots > 0)
+                    return;
+                }
+              else
+                {
+                  /* This is nor a integer, address or float parameter.
+                     Pass it on the stack but count its size in eyecatcher. */
+                  cum->ec_slots -= words;
+                  if (cum->ec_slots > 0)
+                    return;
+                }
+
+              /* If we're out of eyecatcher slots, pass the arg on the stack */
+              if (cum->ec_slots <= 0)
+                {
+                  cum->ec_slots = 0;
+                  cum->nregs = 0;
+                  cum->fpu_nregs = 0;
+                  return;
+                }
+            }
 #endif
 	  cum->nregs -= words;
@@ -2406,44 +2474,73 @@
 			       cum->sse_regno);
   else
-    switch (mode)
-      {
-	/* For now, pass fp/complex values on the stack.  */
-      default:
-	break;
-
-      case BLKmode:
+    {
 #ifdef TARGET_OPTLINK_DECL_ATTRIBUTES
-        if (cum->optlink)
-          break;
-        /* fall through */
+      /* For optlink calling convention, don't pass anything other than
+         integral types and floats through registers. */
+      if (!cum->optlink
+          || INTEGRAL_TYPE_P (type)
+          || POINTER_TYPE_P (type)
+          || (TREE_CODE (type) == REAL_TYPE))
 #endif
-      case DImode:
-      case SImode:
-      case HImode:
-      case QImode:
-	if (words <= cum->nregs)
+      switch (mode)
+        {
+  	/* For now, pass fp/complex values on the stack.  */
+        default:
+  	break;
+
+#if defined TARGET_OPTLINK_DECL_ATTRIBUTES && defined NOT_WORKING_YET
+        case QFmode:
+        case HFmode:
+        case TQFmode:
+        case SFmode:
+        case DFmode:
+        case XFmode:
+        case TFmode:
+        if (cum->fpu_nregs && cum->optlink && cum->ec_slots)
+          {
+            /* Pass first four floating-point args in FPU registers */
+            ret = gen_rtx (PARALLEL, mode, rtvec_alloc (2));
+            XVECEXP (ret, 0, 0) = gen_rtx (EXPR_LIST, VOIDmode,
+                                           NULL_RTX, const0_rtx);
+            XVECEXP (ret, 0, 1) = gen_rtx (EXPR_LIST, VOIDmode,
+                                           gen_rtx (REG, mode, FIRST_FLOAT_REG + cum->fpu_regno),
+                                           const0_rtx);
+          }
+        break;
+#endif
+
+        case BLKmode:
+        case DImode:
+        case SImode:
+        case HImode:
+        case QImode:
+  	if (words <= cum->nregs)
 #ifdef TARGET_OPTLINK_DECL_ATTRIBUTES
-          /* Optlink specs says that the parameter is passed in a register
-             and space on the stack is reserved for it as well (which is not
-             filled). Currently GCC will pass the parameter *both* in register
-             and stack; this is suboptimal but is compatible. */
           if (cum->optlink)
             {
-              ret = gen_rtx (PARALLEL, mode, rtvec_alloc (2));
-              XVECEXP (ret, 0, 0) = gen_rtx (EXPR_LIST, VOIDmode,
-                                             NULL_RTX, const0_rtx);
-              XVECEXP (ret, 0, 1) = gen_rtx (EXPR_LIST, VOIDmode,
-                                             gen_rtx (REG, mode, cum->regno),
-                                             const0_rtx);
+              if (cum->ec_slots)
+                {
+                  /* Optlink specs says that the parameter is passed in a register
+                     and space on the stack is reserved for it as well (which is not
+                     filled). Currently GCC will pass the parameter *both* in register
+                     and stack; this is suboptimal but is compatible. */
+                  ret = gen_rtx (PARALLEL, mode, rtvec_alloc (2));
+                  XVECEXP (ret, 0, 0) = gen_rtx (EXPR_LIST, VOIDmode,
+                                                 NULL_RTX, const0_rtx);
+                  XVECEXP (ret, 0, 1) = gen_rtx (EXPR_LIST, VOIDmode,
+                                                 gen_rtx (REG, mode, cum->regno),
+                                                 const0_rtx);
+                }
             }
           else
 #endif
-	  ret = gen_rtx_REG (mode, cum->regno);
+	    ret = gen_rtx_REG (mode, cum->regno);
 	break;
-      case TImode:
+        case TImode:
 	if (cum->sse_nregs)
 	  ret = gen_rtx_REG (mode, cum->sse_regno);
 	break;
-      }
+        }
+   }
 
   if (TARGET_DEBUG_ARG)
Index: trunk/src/gcc/gcc/config/i386/i386.h
===================================================================
--- trunk/src/gcc/gcc/config/i386/i386.h	(revision 641)
+++ trunk/src/gcc/gcc/config/i386/i386.h	(revision 645)
@@ -1692,5 +1692,8 @@
   int maybe_vaarg;		/* true for calls to possibly vardic fncts.  */
 #ifdef EMX
-  int optlink;                  /* nonzero if optlink (vs. regparm) */
+  int fpu_regno;		/* next available FPU register number */
+  int fpu_nregs;		/* # registers available for passing */
+  int ec_slots;			/* # eyecatcher slots left (see optlink specs) */
+  int optlink;			/* nonzero if optlink (vs. regparm) */
 #endif /* EMX */
 } CUMULATIVE_ARGS;
Index: trunk/src/gcc/gcc/cp/except.c
===================================================================
--- trunk/src/gcc/gcc/cp/except.c	(revision 641)
+++ trunk/src/gcc/gcc/cp/except.c	(revision 645)
@@ -806,5 +806,9 @@
 
   id = DECL_ASSEMBLER_NAME (fn);
-#ifdef EMX
+#ifdef TARGET_CXX_SET_DECL_ASSEMBLER_NAME
+  /* Actually the above is a bug. We can't mangle correctly unless we
+     have a complete decl. Until then, as a partial fix, reset the
+     mangled name to NULL so that next DECL_ASSEMBLER_NAME calls
+     mangler again, now with a complete decl. */
   SET_DECL_ASSEMBLER_NAME(fn, NULL_TREE);
 #endif
Index: trunk/src/gcc/gcc/cp/mangle.c
===================================================================
--- trunk/src/gcc/gcc/cp/mangle.c	(revision 641)
+++ trunk/src/gcc/gcc/cp/mangle.c	(revision 645)
@@ -73,4 +73,9 @@
 # define MANGLE_TRACE(FN, INPUT)
 # define MANGLE_TRACE_TREE(FN, NODE)
+#endif
+
+/* Provide a dummy target-specific name mangling hook */
+#ifndef TARGET_CXX_SET_DECL_ASSEMBLER_NAME
+#define TARGET_CXX_SET_DECL_ASSEMBLER_NAME(decl) 0
 #endif
 
@@ -2272,7 +2277,12 @@
      tree decl;
 {
-  tree id = get_identifier (mangle_decl_string (decl));
-
-  SET_DECL_ASSEMBLER_NAME (decl, id);
+  tree id;
+
+  if (!TARGET_CXX_SET_DECL_ASSEMBLER_NAME (decl))
+    {
+      id = get_identifier (mangle_decl_string (decl));
+
+      SET_DECL_ASSEMBLER_NAME (decl, id);
+    }
 }
 
Index: trunk/src/gcc/gcc/reg-stack.c
===================================================================
--- trunk/src/gcc/gcc/reg-stack.c	(revision 641)
+++ trunk/src/gcc/gcc/reg-stack.c	(revision 645)
@@ -232,4 +232,11 @@
 /* Used to initialize uninitialized registers.  */
 static rtx nan;
+
+/* The first undefined stack register at the beginning of this function.
+   This variable is set from machine-dependent code when placing certain
+   function arguments in stack registers at function entry, in this case
+   the variable is set to first stack register that has undefined contents
+   at the beginning of function. */
+int regstack_first_undef_reg = FIRST_STACK_REG;
 
 /* Forward declarations */
@@ -2440,5 +2447,5 @@
       int reg, top = -1;
 
-      for (reg = LAST_STACK_REG; reg >= FIRST_STACK_REG; --reg)
+      for (reg = LAST_STACK_REG; reg >= regstack_first_undef_reg; --reg)
 	if (TEST_HARD_REG_BIT (bi->stack_in.reg_set, reg))
 	  {
@@ -2447,11 +2454,21 @@
 	    bi->stack_in.reg[++top] = reg;
 
-	    init = gen_rtx_SET (VOIDmode,
-				FP_MODE_REG (FIRST_STACK_REG, SFmode),
-				nan);
-	    insert_insn_on_edge (init, e);
-	    inserted = 1;
+            init = gen_rtx_SET (VOIDmode,
+                                FP_MODE_REG (FIRST_STACK_REG, SFmode),
+                                nan);
+            insert_insn_on_edge (init, e);
+            inserted = 1;
 	  }
 
+      /* All registers that are valid on function entry should be
+         marked as such. ??? Possibly we should do it in flow.c ??? */
+      for (reg = regstack_first_undef_reg - 1; reg >= FIRST_STACK_REG; --reg)
+	{
+          bi->stack_in.reg[++top] = reg;
+        }
+
+      /* At the start of next block we cannot assume anything about
+         stack register contents.  */
+      regstack_first_undef_reg = FIRST_STACK_REG;
       bi->stack_in.top = top;
     }
Index: trunk/src/gcc/gcc/rtl.h
===================================================================
--- trunk/src/gcc/gcc/rtl.h	(revision 641)
+++ trunk/src/gcc/gcc/rtl.h	(revision 645)
@@ -2007,4 +2007,5 @@
 /* In reg-stack.c */
 #ifdef BUFSIZ
+extern int regstack_first_undef_reg;
 extern void reg_to_stack		PARAMS ((rtx, FILE *));
 #endif
Index: trunk/src/gcc/gcc/tree.c
===================================================================
--- trunk/src/gcc/gcc/tree.c	(revision 641)
+++ trunk/src/gcc/gcc/tree.c	(revision 645)
@@ -47,4 +47,9 @@
 #include "target.h"
 #include "langhooks.h"
+
+/* Provide a dummy target-specific name mangling hook */
+#ifndef TARGET_C_SET_DECL_ASSEMBLER_NAME
+#define TARGET_C_SET_DECL_ASSEMBLER_NAME(decl) 0
+#endif
 
 #define obstack_chunk_alloc xmalloc
@@ -206,10 +211,15 @@
 	      || DECL_EXTERNAL (decl) 
 	      || TREE_PUBLIC (decl))))
-    /* By default, assume the name to use in assembly code is the
-       same as that used in the source language.  (That's correct
-       for C, and GCC used to set DECL_ASSEMBLER_NAME to the same
-       value as DECL_NAME in build_decl, so this choice provides
-       backwards compatibility with existing front-ends.  */
-    SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
+    {
+      /* Some targets may want to apply special mangling depending
+         on certain attributes etc (e.g. stdcall). */
+      if (!TARGET_C_SET_DECL_ASSEMBLER_NAME (decl))
+        /* By default, assume the name to use in assembly code is the
+           same as that used in the source language.  (That's correct
+           for C, and GCC used to set DECL_ASSEMBLER_NAME to the same
+           value as DECL_NAME in build_decl, so this choice provides
+           backwards compatibility with existing front-ends.  */
+        SET_DECL_ASSEMBLER_NAME (decl, DECL_NAME (decl));
+    }
   else
     /* Nobody should ever be asking for the DECL_ASSEMBLER_NAME of
