Generate stub functions directly in assembly.

diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index 87c69f8..afb4c63 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -177,6 +177,7 @@
 extern int remove_stdcall_decoration( char *name );
 extern DLLSPEC *alloc_dll_spec(void);
 extern void free_dll_spec( DLLSPEC *spec );
+extern int has_stubs( const DLLSPEC *spec );
 extern const char *make_c_identifier( const char *str );
 extern unsigned int get_alignment(unsigned int align);
 extern unsigned int get_page_size(void);
diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c
index d2406e3..c3f1307 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -454,18 +454,6 @@
     if (imp->delay) total_delayed++;
 }
 
-/* check if the spec file exports any stubs */
-static int has_stubs( const DLLSPEC *spec )
-{
-    int i;
-    for (i = 0; i < spec->nb_entry_points; i++)
-    {
-        ORDDEF *odp = &spec->entry_points[i];
-        if (odp->type == TYPE_STUB) return 1;
-    }
-    return 0;
-}
-
 /* get the default entry point for a given spec file */
 static const char *get_default_entry_point( const DLLSPEC *spec )
 {
diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c
index 5c3e749..4e166c7 100644
--- a/tools/winebuild/parser.c
+++ b/tools/winebuild/parser.c
@@ -368,6 +368,7 @@
 {
     odp->u.func.arg_types[0] = '\0';
     odp->link_name = xstrdup("");
+    odp->flags |= FLAG_I386;  /* don't bother generating stubs for Winelib */
     return 1;
 }
 
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index 8b181e3..8c4659a 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -270,38 +270,62 @@
 
 
 /*******************************************************************
- *         output_stub_funcs
+ *         output_stubs
  *
  * Output the functions for stub entry points
 */
-static void output_stub_funcs( FILE *outfile, DLLSPEC *spec )
+static void output_stubs( FILE *outfile, DLLSPEC *spec )
 {
-    int i;
+    const char *name, *exp_name;
+    int i, pos;
 
-    for (i = 0; i < spec->nb_entry_points; i++)
+    if (!has_stubs( spec )) return;
+
+    fprintf( outfile, "asm(\".text\\n\"\n" );
+
+    for (i = pos = 0; i < spec->nb_entry_points; i++)
     {
         ORDDEF *odp = &spec->entry_points[i];
         if (odp->type != TYPE_STUB) continue;
-        fprintf( outfile, "#ifdef __GNUC__\n" );
-        fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func ) __attribute__((noreturn));\n" );
-        fprintf( outfile, "#else\n" );
-        fprintf( outfile, "extern void __wine_spec_unimplemented_stub( const char *module, const char *func );\n" );
-        fprintf( outfile, "#endif\n\n" );
-        break;
+
+        name = make_internal_name( odp, spec, "stub" );
+        exp_name = odp->name ? odp->name : odp->export_name;
+        fprintf( outfile, "    \"\\t.align %d\\n\"\n", get_alignment(4) );
+        fprintf( outfile, "    \"\\t%s\\n\"\n", func_declaration(name) );
+        fprintf( outfile, "    \"%s:\\n\"\n", asm_name(name) );
+        fprintf( outfile, "    \"\\tcall .L__wine_stub_getpc_%d\\n\"\n", i );
+        fprintf( outfile, "    \".L__wine_stub_getpc_%d:\\n\"\n", i );
+        fprintf( outfile, "    \"\\tpopl %%eax\\n\"\n" );
+        if (exp_name)
+        {
+            fprintf( outfile, "    \"\\tleal .L__wine_stub_strings+%d-.L__wine_stub_getpc_%d(%%eax),%%ecx\\n\"\n",
+                     pos, i );
+            fprintf( outfile, "    \"\\tpushl %%ecx\\n\"\n" );
+            pos += strlen(exp_name) + 1;
+        }
+        else
+            fprintf( outfile, "    \"\\tpushl $%d\\n\"\n", odp->ordinal );
+        fprintf( outfile, "    \"\\tleal %s-.L__wine_stub_getpc_%d(%%eax),%%ecx\\n\"\n",
+                 asm_name("__wine_spec_file_name"), i );
+        fprintf( outfile, "    \"\\tpushl %%ecx\\n\"\n" );
+        fprintf( outfile, "    \"\\tcall %s\\n\"\n", asm_name("__wine_spec_unimplemented_stub") );
+        fprintf( outfile, "    \"\\t%s\\n\"\n", func_size(name) );
     }
 
-    for (i = 0; i < spec->nb_entry_points; i++)
+    if (pos)
     {
-        const ORDDEF *odp = &spec->entry_points[i];
-        if (odp->type != TYPE_STUB) continue;
-        fprintf( outfile, "void %s(void) ", make_internal_name( odp, spec, "stub" ) );
-        if (odp->name)
-            fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%s\"); }\n", odp->name );
-        else if (odp->export_name)
-            fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%s\"); }\n", odp->export_name );
-        else
-            fprintf( outfile, "{ __wine_spec_unimplemented_stub(__wine_spec_file_name, \"%d\"); }\n", odp->ordinal );
+        fprintf( outfile, "    \".L__wine_stub_strings:\\n\"\n" );
+        for (i = 0; i < spec->nb_entry_points; i++)
+        {
+            ORDDEF *odp = &spec->entry_points[i];
+            if (odp->type != TYPE_STUB) continue;
+            exp_name = odp->name ? odp->name : odp->export_name;
+            if (exp_name)
+                fprintf( outfile, "    \"\\t%s \\\"%s\\\"\\n\"\n", get_asm_string_keyword(), exp_name );
+        }
     }
+
+    fprintf( outfile, ");\n" );
 }
 
 
@@ -434,8 +458,6 @@
 
     fprintf( outfile, "const char __wine_spec_file_name[] = \"%s\";\n", spec->file_name );
 
-    output_stub_funcs( outfile, spec );
-
     /* Output the resources */
 
     resources_size = output_resources( outfile, spec );
@@ -542,6 +564,7 @@
     fprintf( outfile, "    \"\\t.long 0,0\\n\"\n" );  /* DataDirectory[15] */
     fprintf( outfile, ");\n" );
 
+    output_stubs( outfile, spec );
     output_exports( outfile, spec );
     output_imports( outfile, spec );
     output_dll_init( outfile, "__wine_spec_init_ctor", NULL );
diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c
index 0b5bc7d..22d105c 100644
--- a/tools/winebuild/utils.c
+++ b/tools/winebuild/utils.c
@@ -297,6 +297,23 @@
 
 
 /*******************************************************************
+ *         has_stubs
+ *
+ * Check if the spec file exports any stubs
+ */
+int has_stubs( const DLLSPEC *spec )
+{
+    int i;
+    for (i = 0; i < spec->nb_entry_points; i++)
+    {
+        ORDDEF *odp = &spec->entry_points[i];
+        if (odp->type == TYPE_STUB) return 1;
+    }
+    return 0;
+}
+
+
+/*******************************************************************
  *         make_c_identifier
  *
  * Map a string to a valid C identifier.