Modified Win32 register function handling.

diff --git a/include/stackframe.h b/include/stackframe.h
index 41fac08..73177c9 100644
--- a/include/stackframe.h
+++ b/include/stackframe.h
@@ -91,24 +91,19 @@
     teb->cur_stack += size;
 }
 
-#ifdef __i386__
 /* Push a DWORD on the 32-bit stack */
-static inline void WINE_UNUSED stack32_push( CONTEXT *context, DWORD val )
+static inline void WINE_UNUSED stack32_push( CONTEXT86 *context, DWORD val )
 {
     ESP_reg(context) -= sizeof(DWORD);
     *(DWORD *)ESP_reg(context) = val;
 }
 
 /* Pop a DWORD from the 32-bit stack */
-static inline DWORD WINE_UNUSED stack32_pop( CONTEXT *context )
+static inline DWORD WINE_UNUSED stack32_pop( CONTEXT86 *context )
 {
     DWORD ret = *(DWORD *)ESP_reg(context);
     ESP_reg(context) += sizeof(DWORD);
     return ret;
 }
-#endif  /* __i386__ */
-
-/* Win32 register functions */
-#define REGS_FUNC(name) __regs_##name
 
 #endif /* __WINE_STACKFRAME_H */
diff --git a/include/winnt.h b/include/winnt.h
index 5bc9df1..e00a560 100644
--- a/include/winnt.h
+++ b/include/winnt.h
@@ -561,6 +561,8 @@
 
 typedef struct _CONTEXT
 {
+    DWORD ContextFlags;
+
     /* These are selected by CONTEXT_INTEGER */
     DWORD g0;
     DWORD g1;
@@ -664,6 +666,63 @@
 #define ISV86(context)       (EFL_reg(context) & 0x00020000)
 #define V86BASE(context)     ((context)->Dr7) /* ugly */
 
+
+/* Macros to retrieve the current context */
+
+#ifdef __i386__
+#define _DEFINE_REGS_ENTRYPOINT( name, fn, args ) \
+  __asm__(".align 4\n\t"                         \
+          ".globl " #name "\n\t"                 \
+          ".type " #name ",@function\n\t"        \
+          #name ":\n\t"                          \
+          "call CALL32_Regs\n\t"                 \
+          ".long " #fn "\n\t"                    \
+          ".byte " #args ", " #args "\n\t");
+
+#define DEFINE_REGS_ENTRYPOINT_0( name, fn ) \
+  _DEFINE_REGS_ENTRYPOINT( name, fn, 0 )
+#define DEFINE_REGS_ENTRYPOINT_1( name, fn, t1 ) \
+  _DEFINE_REGS_ENTRYPOINT( name, fn, 4 )
+#define DEFINE_REGS_ENTRYPOINT_2( name, fn, t1, t2 ) \
+  _DEFINE_REGS_ENTRYPOINT( name, fn, 8 )
+#define DEFINE_REGS_ENTRYPOINT_3( name, fn, t1, t2, t3 ) \
+  _DEFINE_REGS_ENTRYPOINT( name, fn, 12 )
+#define DEFINE_REGS_ENTRYPOINT_4( name, fn, t1, t2, t3, t4 ) \
+  _DEFINE_REGS_ENTRYPOINT( name, fn, 16 )
+
+#endif  /* __i386__ */
+
+#ifdef __sparc__
+/* FIXME: use getcontext() to retrieve full context */
+#define _GET_CONTEXT \
+    CONTEXT context;   \
+    do { memset(&context, 0, sizeof(CONTEXT));            \
+         context.ContextFlags = CONTEXT_CONTROL;          \
+         context.pc = (DWORD)__builtin_return_address(0); \
+       } while (0)
+
+#define DEFINE_REGS_ENTRYPOINT_0( name, fn ) \
+  void WINAPI name ( void ) \
+  { _GET_CONTEXT; fn( &context ); }
+#define DEFINE_REGS_ENTRYPOINT_1( name, fn, t1 ) \
+  void WINAPI name ( t1 a1 ) \
+  { _GET_CONTEXT; fn( a1, &context ); }
+#define DEFINE_REGS_ENTRYPOINT_2( name, fn, t1, t2 ) \
+  void WINAPI name ( t1 a1, t2 a2 ) \
+  { _GET_CONTEXT; fn( a1, a2, &context ); }
+#define DEFINE_REGS_ENTRYPOINT_3( name, fn, t1, t2, t3 ) \
+  void WINAPI name ( t1 a1, t2 a2, t3 a3 ) \
+  { _GET_CONTEXT; fn( a1, a2, a3, &context ); }
+#define DEFINE_REGS_ENTRYPOINT_4( name, fn, t1, t2, t3, t4 ) \
+  void WINAPI name ( t1 a1, t2 a2, t3 a3, t4 a4 ) \
+  { _GET_CONTEXT; fn( a1, a2, a3, a4, &context ); }
+
+#endif /* __sparc__ */
+
+#ifndef DEFINE_REGS_ENTRYPOINT_0
+#error You need to define DEFINE_REGS_ENTRYPOINT macros for your CPU
+#endif
+
 #ifdef __i386__
 # define GET_IP(context) ((LPVOID)(context)->Eip)
 #endif
diff --git a/tools/build.c b/tools/build.c
index 1e375a5..88def0a 100644
--- a/tools/build.c
+++ b/tools/build.c
@@ -472,6 +472,13 @@
     if ((odp->type == TYPE_STDCALL) && !i)
         odp->type = TYPE_CDECL; /* stdcall is the same as cdecl for 0 args */
     strcpy(odp->u.func.link_name, GetToken());
+
+    /* Ignore Win32 'register' routines on non-Intel archs */
+#ifndef __i386__
+    if ( odp->type == TYPE_REGISTER && SpecType == SPEC_WIN32 )
+        odp->type = TYPE_INVALID;
+#endif
+
     return 0;
 }
 
@@ -1024,7 +1031,7 @@
 static int BuildSpec32File( char * specfile, FILE *outfile )
 {
     ORDDEF *odp;
-    int i, nb_names, fwd_size = 0;
+    int i, nb_names, fwd_size = 0, have_regs = FALSE;
 
     fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n\n",
              specfile );
@@ -1041,33 +1048,6 @@
                  i, DLLName, i );
     }
 
-    /* Output code for all register functions */
-
-    fprintf( outfile, "#ifdef __i386__\n" );
-    fprintf( outfile, "#ifndef __GNUC__\n" );
-    fprintf( outfile, "static void __asm__dummy() {\n" );
-    fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
-    for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
-    {
-        if (odp->type != TYPE_REGISTER) continue;
-        fprintf( outfile,
-                 "__asm__(\".align 4\\n\\t\"\n"
-                 "        \".globl " PREFIX "%s\\n\\t\"\n"
-                 "        \".type " PREFIX "%s,@function\\n\\t\"\n"
-                 "        \"" PREFIX "%s:\\n\\t\"\n"
-                 "        \"call " PREFIX "CALL32_Regs\\n\\t\"\n"
-                 "        \".long " PREFIX "__regs_%s\\n\\t\"\n"
-                 "        \".byte %d,%d\");\n",
-                 odp->u.func.link_name, odp->u.func.link_name,
-                 odp->u.func.link_name, odp->u.func.link_name,
-                 4 * strlen(odp->u.func.arg_types),
-                 4 * strlen(odp->u.func.arg_types) );
-    }
-    fprintf( outfile, "#ifndef __GNUC__\n" );
-    fprintf( outfile, "}\n" );
-    fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
-    fprintf( outfile, "#endif /* defined(__i386__) */\n" );
-
     /* Output the DLL functions prototypes */
 
     for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
@@ -1077,7 +1057,6 @@
         case TYPE_EXTERN:
             fprintf( outfile, "extern void %s();\n", odp->u.ext.link_name );
             break;
-        case TYPE_REGISTER:
         case TYPE_STDCALL:
         case TYPE_VARARGS:
         case TYPE_CDECL:
@@ -1086,6 +1065,10 @@
         case TYPE_FORWARD:
             fwd_size += strlen(odp->u.fwd.link_name) + 1;
             break;
+        case TYPE_REGISTER:
+            fprintf( outfile, "extern void __regs_%d();\n", i );
+            have_regs = TRUE;
+            break;
         case TYPE_INVALID:
         case TYPE_STUB:
             break;
@@ -1100,6 +1083,32 @@
     if (DLLInitFunc[0]) fprintf( outfile, "extern void %s();\n", DLLInitFunc );
 
 
+    /* Output code for all register functions */
+
+    if ( have_regs )
+    { 
+        fprintf( outfile, "#ifndef __GNUC__\n" );
+        fprintf( outfile, "static void __asm__dummy() {\n" );
+        fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
+        for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
+        {
+            if (odp->type != TYPE_REGISTER) continue;
+            fprintf( outfile,
+                     "__asm__(\".align 4\\n\\t\"\n"
+                     "        \".type " PREFIX "__regs_%d,@function\\n\\t\"\n"
+                     "        \"" PREFIX "__regs_%d:\\n\\t\"\n"
+                     "        \"call " PREFIX "CALL32_Regs\\n\\t\"\n"
+                     "        \".long " PREFIX "%s\\n\\t\"\n"
+                     "        \".byte %d,%d\");\n",
+                     i, i, odp->u.func.link_name,
+                     4 * strlen(odp->u.func.arg_types),
+                     4 * strlen(odp->u.func.arg_types) );
+        }
+        fprintf( outfile, "#ifndef __GNUC__\n" );
+        fprintf( outfile, "}\n" );
+        fprintf( outfile, "#endif /* !defined(__GNUC__) */\n" );
+    }
+
     /* Output the DLL functions table */
 
     fprintf( outfile, "\nstatic const ENTRYPOINT32 Functions[%d] =\n{\n",
@@ -1114,7 +1123,6 @@
         case TYPE_EXTERN:
             fprintf( outfile, "    %s", odp->u.ext.link_name );
             break;
-        case TYPE_REGISTER:
         case TYPE_STDCALL:
         case TYPE_VARARGS:
         case TYPE_CDECL:
@@ -1123,6 +1131,9 @@
         case TYPE_STUB:
             fprintf( outfile, "    __stub_%d", i );
             break;
+        case TYPE_REGISTER:
+            fprintf( outfile, "    __regs_%d", i );
+            break;
         case TYPE_FORWARD:
             fprintf( outfile, "    (ENTRYPOINT32)\"%s\"", odp->u.fwd.link_name );
             break;