Sync to Wine-20050930:
Alexandre Julliard <julliard@winehq.org>
- Generate 16-bit spec files as assembly code too.
- Output the resource data in assembly too.
- Factor out a couple of useful helper functions.
- Store RVAs instead of pointers wherever possible in the generated NT
  header and directories.
- Output constant strings in a more appropriate section than .text.
- Make sure that values of absolute symbols fit in 16 bits.
- Implemented import thunks for x86-64.
- Generate stub functions directly in assembly.
- Moved stub function generation to import.c. Added a get_stub_name
  function to ensure naming consistency.
- Now that everything is done in assembly in the spec file, directly
  generate a .s file to bypass gcc inefficiency with large data
  structures.
- Added support for 64-bit format NT header and export/import tables.
- Now that we have to be able to run the assembler from winebuild, added
  an option to generate a .spec.o file in a single step.
  Added --save-temps and --verbose options for easier debugging.
- Added an entry point routine for native drivers.
- Added a bit of framework for future x86_64 support.
- Create an assembly file with all undefined symbols and add it to the
  link command so that the symbols show up in the final undefined list.
  Use that list to create thunks for all exported but undefined symbols,
  to make sure all export RVAs point somewhere inside the module.
- Take into account -noname functions when checking for duplicate export
  names. Fixed a couple of issues found by the stricter check.
- Generate the NT header in assembly instead of using a C structure.
- Don't remove ignored symbols from the undefined list, simply skip them
  when resolving imports.
  Added get_temp_file_name utility function.
- Fixed stack offset of %eax register.
- Output the delayed import table using assembly too.
- Added a common function to declare global symbols, and make them
  hidden on platforms that support it.
- Fixed a number of pointer to integer conversions that wouldn't work
  right on a 64-bit platform.
- Output the import directory using assembly instead of C structures.
- Defined a proper structure for debug channels.
  Also put all the function pointers inside a structure and added
  __wine_dbg_set_functions to change them instead of exporting the
  pointers directly.
- Moved return value handling to the individual relay thunks so that we
  only need one version of wine_call_from_16.
  Patch the wine_call_from_16 address along with the cs value directly
  in the 16-bit code segment to avoid the need for special magic in the
  import thunks.
- Moved the spec file init function and constructor to winecrt0.
- Make the users of wine_call_from_32_regs save %eax so that we don't
  need a special hack in the import thunk.
  Added a get_pc_thunk_eax function to simplify the code a bit.
- Get rid of the debug channels support.
Modified: trunk/reactos/lib/shdocvw/shdocvw.spec
Modified: trunk/reactos/lib/shlwapi/shlwapi.spec
Modified: trunk/reactos/tools/winebuild/build.h
Modified: trunk/reactos/tools/winebuild/import.c
Modified: trunk/reactos/tools/winebuild/main.c
Modified: trunk/reactos/tools/winebuild/parser.c
Modified: trunk/reactos/tools/winebuild/relay.c
Modified: trunk/reactos/tools/winebuild/res16.c
Modified: trunk/reactos/tools/winebuild/res32.c
Modified: trunk/reactos/tools/winebuild/spec16.c
Modified: trunk/reactos/tools/winebuild/spec32.c
Modified: trunk/reactos/tools/winebuild/utils.c
Modified: trunk/reactos/tools/winebuild/winebuild.man.in
Modified: trunk/reactos/tools/winebuild/winglue.h

Modified: trunk/reactos/lib/shdocvw/shdocvw.spec
--- trunk/reactos/lib/shdocvw/shdocvw.spec	2005-10-08 11:26:13 UTC (rev 18324)
+++ trunk/reactos/lib/shdocvw/shdocvw.spec	2005-10-08 12:18:07 UTC (rev 18325)
@@ -65,7 +65,7 @@
 185 stub -noname FireEvent_Quit
 187 stub -noname SHDGetPageLocation
 188 stub -noname SHIEErrorMsgBox
-189 stub -noname IEGetDisplayName
+189 stub @ # FIXME: same as ordinal 148
 190 stub -noname SHRunIndirectRegClientCommandForward
 191 stub -noname SHIsRegisteredClient
 192 stub -noname SHGetHistoryPIDL

Modified: trunk/reactos/lib/shlwapi/shlwapi.spec
--- trunk/reactos/lib/shlwapi/shlwapi.spec	2005-10-08 11:26:13 UTC (rev 18324)
+++ trunk/reactos/lib/shlwapi/shlwapi.spec	2005-10-08 12:18:07 UTC (rev 18325)
@@ -493,8 +493,8 @@
 493 stub -noname SHPropertyBag_ReadType
 494 stub -noname SHPropertyBag_ReadStr
 495 stub -noname SHPropertyBag_WriteStr
-496 stub -noname SHPropertyBag_ReadInt
-497 stub -noname SHPropertyBag_WriteInt
+496 stub -noname SHPropertyBag_ReadLONG
+497 stub -noname SHPropertyBag_WriteLONG
 498 stub -noname SHPropertyBag_ReadBOOLOld
 499 stub -noname SHPropertyBag_WriteBOOL
 
@@ -531,7 +531,7 @@
 535 stub -noname SHPropertyBag_Delete
 536 stub -noname IUnknown_QueryServicePropertyBag
 537 stub -noname SHBoolSystemParametersInfo
-538 stub -noname IUnknown_QueryServicePropertyBag
+538 stub -noname IUnknown_QueryServiceForWebBrowserApp
 539 stub -noname IUnknown_ShowBrowserBar
 540 stub -noname SHInvokeCommandOnContextMenu
 541 stub -noname SHInvokeCommandsOnContextMen

Modified: trunk/reactos/tools/winebuild/build.h
--- trunk/reactos/tools/winebuild/build.h	2005-10-08 11:26:13 UTC (rev 18324)
+++ trunk/reactos/tools/winebuild/build.h	2005-10-08 12:18:07 UTC (rev 18325)
@@ -63,14 +63,13 @@
 
 typedef struct
 {
-    int value;
+    unsigned short value;
 } ORD_ABS;
 
 typedef struct
 {
     ORD_TYPE    type;
     int         ordinal;
-    int         offset;
     int         lineno;
     int         flags;
     char       *name;         /* public name of this function */
@@ -110,7 +109,7 @@
 
 enum target_cpu
 {
-    CPU_x86, CPU_SPARC, CPU_ALPHA, CPU_POWERPC
+    CPU_x86, CPU_x86_64, CPU_SPARC, CPU_ALPHA, CPU_POWERPC
 };
 
 enum target_platform
@@ -131,6 +130,7 @@
 #define FLAG_PRIVATE   0x40  /* function is private (cannot be imported) */
 
 #define FLAG_FORWARD   0x80  /* function is a forwarded name */
+#define FLAG_EXT_LINK  0x100 /* function links to an external symbol */
 
   /* Offset of a structure field relative to the start of the struct */
 #define STRUCTOFFSET(type,field) ((int)&((type *)0)->field)
@@ -169,22 +169,28 @@
    __attribute__ ((__format__ (__printf__, 1, 2)));
 extern void warning( const char *msg, ... )
    __attribute__ ((__format__ (__printf__, 1, 2)));
+extern char *get_temp_file_name( const char *prefix, const char *suffix );
 extern void output_standard_file_header( FILE *outfile );
 extern FILE *open_input_file( const char *srcdir, const char *name );
 extern void close_input_file( FILE *file );
-extern void dump_bytes( FILE *outfile, const unsigned char *data, int len,
-                        const char *label, int constant );
+extern void dump_bytes( FILE *outfile, const void *buffer, unsigned int size );
 extern int remove_stdcall_decoration( char *name );
+extern void assemble_file( const char *src_file, const char *obj_file );
 extern DLLSPEC *alloc_dll_spec(void);
 extern void free_dll_spec( DLLSPEC *spec );
 extern const char *make_c_identifier( const char *str );
+extern const char *get_stub_name( const ORDDEF *odp, const DLLSPEC *spec );
 extern unsigned int get_alignment(unsigned int align);
 extern unsigned int get_page_size(void);
+extern unsigned int get_ptr_size(void);
 extern const char *asm_name( const char *func );
 extern const char *func_declaration( const char *func );
-extern const char *func_size( const char *func );
+extern const char *asm_globl( const char *func );
+extern const char *get_asm_ptr_keyword(void);
 extern const char *get_asm_string_keyword(void);
 extern const char *get_asm_short_keyword(void);
+extern const char *get_asm_string_section(void);
+extern void output_function_size( FILE *outfile, const char *name );
 
 extern void add_import_dll( const char *name, const char *filename );
 extern void add_delayed_import( const char *name );
@@ -192,48 +198,43 @@
 extern void add_extra_ld_symbol( const char *name );
 extern void read_undef_symbols( DLLSPEC *spec, char **argv );
 extern int resolve_imports( DLLSPEC *spec );
-extern int output_imports( FILE *outfile, DLLSPEC *spec, int *nb_delayed );
-extern void output_import_thunks( FILE *outfile, DLLSPEC *spec );
+extern int has_imports(void);
+extern void output_get_pc_thunk( FILE *outfile );
+extern void output_stubs( FILE *outfile, DLLSPEC *spec );
+extern void output_imports( FILE *outfile, DLLSPEC *spec );
 extern int load_res32_file( const char *name, DLLSPEC *spec );
 extern void output_resources( FILE *outfile, DLLSPEC *spec );
 extern void load_res16_file( const char *name, DLLSPEC *spec );
-extern unsigned int get_res16_data_size( DLLSPEC *spec, unsigned int res_offset,
-                                         unsigned int alignment );
-extern unsigned int output_res16_data( unsigned char **ret_buf, DLLSPEC *spec,
-                                       unsigned int res_offset, unsigned int alignment );
-extern unsigned int get_res16_directory_size( DLLSPEC *spec );
-extern unsigned int output_res16_directory( unsigned char **ret_buf, DLLSPEC *spec,
-                                            unsigned int res_offset, unsigned int alignment );
-extern void output_dll_init( FILE *outfile, const char *constructor, const char *destructor );
+extern void output_res16_data( FILE *outfile, DLLSPEC *spec );
+extern void output_res16_directory( FILE *outfile, DLLSPEC *spec, const char *header_name );
 
 extern void BuildRelays16( FILE *outfile );
 extern void BuildRelays32( FILE *outfile );
 extern void BuildSpec16File( FILE *outfile, DLLSPEC *spec );
 extern void BuildSpec32File( FILE *outfile, DLLSPEC *spec );
 extern void BuildDef32File( FILE *outfile, DLLSPEC *spec );
-extern void BuildDebugFile( FILE *outfile, const char *srcdir, char **argv );
 extern void BuildPedllFile( FILE *outfile, DLLSPEC *spec );
 
 extern int parse_spec_file( FILE *file, DLLSPEC *spec );
 extern int parse_def_file( FILE *file, DLLSPEC *spec );
-extern int parse_debug_channels( const char *srcdir, const char *filename );
 
 /* global variables */
 
 extern int current_line;
 extern int UsePIC;
-extern int nb_debug_channels;
 extern int nb_lib_paths;
 extern int nb_errors;
 extern int display_warnings;
 extern int kill_at;
+extern int verbose;
+extern int save_temps;
 
 extern char *input_file_name;
 extern char *spec_file_name;
 extern const char *output_file_name;
-extern char **debug_channels;
 extern char **lib_path;
 
+extern char *as_command;
 extern char *ld_command;
 extern char *nm_command;
 

Modified: trunk/reactos/tools/winebuild/import.c
--- trunk/reactos/tools/winebuild/import.c	2005-10-08 11:26:13 UTC (rev 18324)
+++ trunk/reactos/tools/winebuild/import.c	2005-10-08 12:18:07 UTC (rev 18325)
@@ -66,9 +66,8 @@
 static struct name_table ignore_symbols;   /* list of symbols to ignore */
 static struct name_table extra_ld_symbols; /* list of extra symbols that ld should resolve */
 static struct name_table delayed_imports;  /* list of delayed import dlls */
+static struct name_table ext_link_imports; /* list of external symbols to link to */
 
-static char *ld_tmp_file;  /* ld temp file name */
-
 static struct import **dll_imports = NULL;
 static int nb_imports = 0;      /* number of imported dlls (delayed or not) */
 static int nb_delayed = 0;      /* number of delayed dlls */
@@ -210,12 +209,6 @@
     return res ? *res : NULL;
 }
 
-inline static void output_function_size( FILE *outfile, const char *name )
-{
-    const char *size = func_size( name );
-    if (size[0]) fprintf( outfile, "    \"\\t%s\\n\"\n", size );
-}
-
 /* free an import structure */
 static void free_imports( struct import *imp )
 {
@@ -226,12 +219,6 @@
     free( imp );
 }
 
-/* remove the temp file at exit */
-static void remove_ld_tmp_file(void)
-{
-    if (ld_tmp_file) unlink( ld_tmp_file );
-}
-
 /* check whether a given dll is imported in delayed mode */
 static int is_delayed_import( const char *name )
 {
@@ -458,6 +445,14 @@
     if (imp->delay) total_delayed++;
 }
 
+/* get the default entry point for a given spec file */
+static const char *get_default_entry_point( const DLLSPEC *spec )
+{
+    if (spec->characteristics & IMAGE_FILE_DLL) return "__wine_spec_dll_entry";
+    if (spec->subsystem == IMAGE_SUBSYSTEM_NATIVE) return "__wine_spec_drv_entry";
+    return "__wine_spec_exe_entry";
+}
+
 /* check if the spec file exports any stubs */
 static int has_stubs( const DLLSPEC *spec )
 {
@@ -470,14 +465,6 @@
     return 0;
 }
 
-/* get the default entry point for a given spec file */
-static const char *get_default_entry_point( const DLLSPEC *spec )
-{
-    if (spec->characteristics & IMAGE_FILE_DLL) return "__wine_spec_dll_entry";
-    if (spec->subsystem == IMAGE_SUBSYSTEM_NATIVE) return "DriverEntry";
-    return "__wine_spec_exe_entry";
-}
-
 /* add the extra undefined symbols that will be contained in the generated spec file itself */
 static void add_extra_undef_symbols( DLLSPEC *spec )
 {
@@ -507,35 +494,69 @@
     return 1;
 }
 
-/* combine a list of object files with ld into a single object file */
-/* returns the name of the combined file */
-static const char *ldcombine_files( char **argv )
+/* flag the dll exports that link to an undefined symbol */
+static void check_undefined_exports( DLLSPEC *spec )
 {
-    unsigned int i, len = 0;
-    char *cmd, *p;
-    int fd, err;
+    int i;
 
-    if (output_file_name && output_file_name[0])
+    for (i = 0; i < spec->nb_entry_points; i++)
     {
-        ld_tmp_file = xmalloc( strlen(output_file_name) + 10 );
-        strcpy( ld_tmp_file, output_file_name );
-        strcat( ld_tmp_file, ".XXXXXX.o" );
+        ORDDEF *odp = &spec->entry_points[i];
+        if (odp->type == TYPE_STUB) continue;
+        if (odp->flags & FLAG_FORWARD) continue;
+        if (find_name( odp->link_name, &undef_symbols ))
+        {
+            odp->flags |= FLAG_EXT_LINK;
+            add_name( &ext_link_imports, odp->link_name );
+        }
     }
-    else ld_tmp_file = xstrdup( "/tmp/winebuild.tmp.XXXXXX.o" );
+}
 
-    if ((fd = mkstemps( ld_tmp_file, 2 ) == -1)) fatal_error( "could not generate a temp file\n" );
-    close( fd );
-    atexit( remove_ld_tmp_file );
+/* create a .o file that references all the undefined symbols we want to resolve */
+static char *create_undef_symbols_file( DLLSPEC *spec )
+{
+    char *as_file, *obj_file;
+    unsigned int i;
+    FILE *f;
 
+    as_file = get_temp_file_name( output_file_name, ".s" );
+    if (!(f = fopen( as_file, "w" ))) fatal_error( "Cannot create %s\n", as_file );
+    fprintf( f, "\t.data\n" );
+
+    for (i = 0; i < spec->nb_entry_points; i++)
+    {
+        ORDDEF *odp = &spec->entry_points[i];
+        if (odp->type == TYPE_STUB) continue;
+        if (odp->flags & FLAG_FORWARD) continue;
+        fprintf( f, "\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->link_name) );
+    }
+    for (i = 0; i < extra_ld_symbols.count; i++)
+        fprintf( f, "\t%s %s\n", get_asm_ptr_keyword(), asm_name(extra_ld_symbols.names[i]) );
+    fclose( f );
+
+    obj_file = get_temp_file_name( output_file_name, ".o" );
+    assemble_file( as_file, obj_file );
+    return obj_file;
+}
+
+/* combine a list of object files with ld into a single object file */
+/* returns the name of the combined file */
+static const char *ldcombine_files( DLLSPEC *spec, char **argv )
+{
+    unsigned int i, len = 0;
+    char *cmd, *p, *ld_tmp_file, *undef_file;
+    int err;
+
+    undef_file = create_undef_symbols_file( spec );
+    len += strlen(undef_file) + 1;
+    ld_tmp_file = get_temp_file_name( output_file_name, ".o" );
     if (!ld_command) ld_command = xstrdup("ld");
-    for (i = 0; i < extra_ld_symbols.count; i++) len += strlen(extra_ld_symbols.names[i]) + 5;
     for (i = 0; argv[i]; i++) len += strlen(argv[i]) + 1;
     cmd = p = xmalloc( len + strlen(ld_tmp_file) + 8 + strlen(ld_command)  );
-    p += sprintf( cmd, "%s -r -o %s", ld_command, ld_tmp_file );
-    for (i = 0; i < extra_ld_symbols.count; i++)
-        p += sprintf( p, " -u %s", asm_name(extra_ld_symbols.names[i]) );
+    p += sprintf( cmd, "%s -r -o %s %s", ld_command, ld_tmp_file, undef_file );
     for (i = 0; argv[i]; i++)
         p += sprintf( p, " %s", argv[i] );
+    if (verbose) fprintf( stderr, "%s\n", cmd );
     err = system( cmd );
     if (err) fatal_error( "%s -r failed with status %d\n", ld_command, err );
     free( cmd );
@@ -558,7 +579,7 @@
     strcpy( name_prefix, asm_name("") );
     prefix_len = strlen( name_prefix );
 
-    name = ldcombine_files( argv );
+    name = ldcombine_files( spec, argv );
 
     if (!nm_command) nm_command = xstrdup("nm");
     cmd = xmalloc( strlen(nm_command) + strlen(name) + 5 );
@@ -581,25 +602,14 @@
     free( cmd );
 }
 
-static void remove_ignored_symbols(void)
-{
-    unsigned int i;
-
-    if (!ignore_symbols.size) init_ignored_symbols();
-    sort_names( &ignore_symbols );
-    for (i = 0; i < undef_symbols.count; i++)
-    {
-        if (find_name( undef_symbols.names[i], &ignore_symbols ))
-            remove_name( &undef_symbols, i-- );
-    }
-}
-
 /* resolve the imports for a Win32 module */
 int resolve_imports( DLLSPEC *spec )
 {
     unsigned int i, j, removed;
+    ORDDEF *odp;
 
-    remove_ignored_symbols();
+    if (!ignore_symbols.size) init_ignored_symbols();
+    sort_names( &ignore_symbols );
 
     for (i = 0; i < nb_imports; i++)
     {
@@ -607,7 +617,8 @@
 
         for (j = removed = 0; j < undef_symbols.count; j++)
         {
-            ORDDEF *odp = find_export( undef_symbols.names[j], imp->exports, imp->nb_exports );
+            if (find_name( undef_symbols.names[j], &ignore_symbols )) continue;
+            odp = find_export( undef_symbols.names[j], imp->exports, imp->nb_exports );
             if (odp)
             {
                 add_import_func( imp, odp );
@@ -623,186 +634,199 @@
             i--;
         }
     }
+
+    sort_names( &undef_symbols );
+    check_undefined_exports( spec );
+
     return 1;
 }
 
+/* output the get_pc thunk if needed */
+void output_get_pc_thunk( FILE *outfile )
+{
+    if (target_cpu != CPU_x86) return;
+    if (!UsePIC) return;
+    fprintf( outfile, "\n\t.text\n" );
+    fprintf( outfile, "\t.align %d\n", get_alignment(4) );
+    fprintf( outfile, "\t%s\n", func_declaration("__wine_spec_get_pc_thunk_eax") );
+    fprintf( outfile, "%s:\n", asm_name("__wine_spec_get_pc_thunk_eax") );
+    fprintf( outfile, "\tpopl %%eax\n" );
+    fprintf( outfile, "\tpushl %%eax\n" );
+    fprintf( outfile, "\tret\n" );
+    output_function_size( outfile, "__wine_spec_get_pc_thunk_eax" );
+}
+
 /* output a single import thunk */
 static void output_import_thunk( FILE *outfile, const char *name, const char *table, int pos )
 {
-    fprintf( outfile, "    \"\\t.align %d\\n\"\n", get_alignment(4) );
-    fprintf( outfile, "    \"\\t%s\\n\"\n", func_declaration(name) );
-    fprintf( outfile, "    \"\\t.globl %s\\n\"\n", asm_name(name) );
-    fprintf( outfile, "    \"%s:\\n\"\n", asm_name(name) );
+    fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
+    fprintf( outfile, "\t%s\n", func_declaration(name) );
+    fprintf( outfile, "%s\n", asm_globl(name) );
 
     switch(target_cpu)
     {
     case CPU_x86:
         if (!UsePIC)
         {
-            if (strstr( name, "__wine_call_from_16" )) fprintf( outfile, "    \"\\t.byte 0x2e\\n\"\n" );
-            fprintf( outfile, "    \"\\tjmp *(%s+%d)\\n\"\n", asm_name(table), pos );
+            fprintf( outfile, "\tjmp *(%s+%d)\n", table, pos );
         }
         else
         {
-            if (!strcmp( name, "__wine_call_from_32_regs" ))
-            {
-                /* special case: need to preserve all registers */
-                fprintf( outfile, "    \"\\tpushl %%eax\\n\"\n" );
-                fprintf( outfile, "    \"\\tcall .L__wine_spec_%s\\n\"\n", name );
-                fprintf( outfile, "    \".L__wine_spec_%s:\\n\"\n", name );
-                fprintf( outfile, "    \"\\tpopl %%eax\\n\"\n" );
-                if (!strcmp( name, "__wine_call_from_16_regs" ))
-                    fprintf( outfile, "    \"\\t.byte 0x2e\\n\"\n" );
-                fprintf( outfile, "    \"\\tmovl %s+%d-.L__wine_spec_%s(%%eax),%%eax\\n\"\n",
-                         asm_name(table), pos, name );
-                fprintf( outfile, "    \"\\txchgl %%eax,(%%esp)\\n\"\n" );
-                fprintf( outfile, "    \"\\tret\\n\"\n" );
-            }
-            else if (!strcmp( name, "__wine_call_from_16_regs" ))
-            {
-                /* special case: need to preserve all registers */
-                fprintf( outfile, "    \"\\tpushl %%eax\\n\"\n" );
-                fprintf( outfile, "    \"\\tpushl %%ecx\\n\"\n" );
-                fprintf( outfile, "    \"\\tcall .L__wine_spec_%s\\n\"\n", name );
-                fprintf( outfile, "    \".L__wine_spec_%s:\\n\"\n", name );
-                fprintf( outfile, "    \"\\tpopl %%eax\\n\"\n" );
-                fprintf( outfile, "    \"\\t.byte 0x2e\\n\"\n" );
-                fprintf( outfile, "    \"\\tmovl %s+%d-.L__wine_spec_%s(%%eax),%%eax\\n\"\n",
-                         asm_name(table), pos, name );
-                fprintf( outfile, "    \"\\tmovzwl %%sp, %%ecx\\n\"\n" );
-                fprintf( outfile, "    \"\\t.byte 0x36\\n\"\n" );
-                fprintf( outfile, "    \"\\txchgl %%eax,4(%%ecx)\\n\"\n" );
-                fprintf( outfile, "    \"\\tpopl %%ecx\\n\"\n" );
-                fprintf( outfile, "    \"\\tret\\n\"\n" );
-            }
-            else
-            {
-                fprintf( outfile, "    \"\\tcall .L__wine_spec_%s\\n\"\n", name );
-                fprintf( outfile, "    \".L__wine_spec_%s:\\n\"\n", name );
-                fprintf( outfile, "    \"\\tpopl %%eax\\n\"\n" );
-                if (strstr( name, "__wine_call_from_16" ))
-                    fprintf( outfile, "    \"\\t.byte 0x2e\\n\"\n" );
-                fprintf( outfile, "    \"\\tjmp *%s+%d-.L__wine_spec_%s(%%eax)\\n\"\n",
-                         asm_name(table), pos, name );
-            }
+            fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
+            fprintf( outfile, "1:\tjmp *%s+%d-1b(%%eax)\n", table, pos );
         }
         break;
+    case CPU_x86_64:
+        fprintf( outfile, "\tjmpq *%s+%d(%%rip)\n", table, pos );
+        break;
     case CPU_SPARC:
         if ( !UsePIC )
         {
-            fprintf( outfile, "    \"\\tsethi %%hi(%s+%d), %%g1\\n\"\n", table, pos );
-            fprintf( outfile, "    \"\\tld [%%g1+%%lo(%s+%d)], %%g1\\n\"\n", table, pos );
-            fprintf( outfile, "    \"\\tjmp %%g1\\n\\tnop\\n\"\n" );
+            fprintf( outfile, "\tsethi %%hi(%s+%d), %%g1\n", table, pos );
+            fprintf( outfile, "\tld [%%g1+%%lo(%s+%d)], %%g1\n", table, pos );
+            fprintf( outfile, "\tjmp %%g1\n" );
+            fprintf( outfile, "\tnop\n" );
         }
         else
         {
             /* Hmpf.  Stupid sparc assembler always interprets global variable
                names as GOT offsets, so we have to do it the long way ... */
-            fprintf( outfile, "    \"\\tsave %%sp, -96, %%sp\\n\"\n" );
-            fprintf( outfile, "    \"0:\\tcall 1f\\n\\tnop\\n\"\n" );
-            fprintf( outfile, "    \"1:\\tsethi %%hi(%s+%d-0b), %%g1\\n\"\n", table, pos );
-            fprintf( outfile, "    \"\\tor %%g1, %%lo(%s+%d-0b), %%g1\\n\"\n", table, pos );
-            fprintf( outfile, "    \"\\tld [%%g1+%%o7], %%g1\\n\"\n" );
-            fprintf( outfile, "    \"\\tjmp %%g1\\n\\trestore\\n\"\n" );
+            fprintf( outfile, "\tsave %%sp, -96, %%sp\n" );
+            fprintf( outfile, "0:\tcall 1f\n" );
+            fprintf( outfile, "\tnop\n" );
+            fprintf( outfile, "1:\tsethi %%hi(%s+%d-0b), %%g1\n", table, pos );
+            fprintf( outfile, "\tor %%g1, %%lo(%s+%d-0b), %%g1\n", table, pos );
+            fprintf( outfile, "\tld [%%g1+%%o7], %%g1\n" );
+            fprintf( outfile, "\tjmp %%g1\n" );
+            fprintf( outfile, "\trestore\n" );
         }
         break;
     case CPU_ALPHA:
-        fprintf( outfile, "    \"\\tlda $0,%s\\n\"\n", table );
-        fprintf( outfile, "    \"\\tlda $0,%d($0)\\n\"\n", pos);
-        fprintf( outfile, "    \"\\tjmp $31,($0)\\n\"\n" );
+        fprintf( outfile, "\tlda $0,%s\n", table );
+        fprintf( outfile, "\tlda $0,%d($0)\n", pos );
+        fprintf( outfile, "\tjmp $31,($0)\n" );
         break;
     case CPU_POWERPC:
-        fprintf(outfile, "    \"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg(1), ppc_reg(1));
-        fprintf(outfile, "    \"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg(9), ppc_reg(1));
-        fprintf(outfile, "    \"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg(1), ppc_reg(1));
-        fprintf(outfile, "    \"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg(8), ppc_reg(1));
-        fprintf(outfile, "    \"\\taddi %s, %s, -0x4\\n\"\n", ppc_reg(1), ppc_reg(1));
-        fprintf(outfile, "    \"\\tstw  %s, 0(%s)\\n\"\n",    ppc_reg(7), ppc_reg(1));
+        fprintf( outfile, "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
+        fprintf( outfile, "\tstw  %s, 0(%s)\n",    ppc_reg(9), ppc_reg(1) );
+        fprintf( outfile, "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
+        fprintf( outfile, "\tstw  %s, 0(%s)\n",    ppc_reg(8), ppc_reg(1) );
+        fprintf( outfile, "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
+        fprintf( outfile, "\tstw  %s, 0(%s)\n",    ppc_reg(7), ppc_reg(1) );
         if (target_platform == PLATFORM_APPLE)
         {
-            fprintf(outfile, "    \"\\tlis %s, ha16(%s+%d)\\n\"\n",
-                    ppc_reg(9), asm_name(table), pos);
-            fprintf(outfile, "    \"\\tla  %s, lo16(%s+%d)(%s)\\n\"\n",
-                    ppc_reg(8), asm_name(table), pos, ppc_reg(9));
+            fprintf( outfile, "\tlis %s, ha16(%s+%d)\n", ppc_reg(9), table, pos );
+            fprintf( outfile, "\tla  %s, lo16(%s+%d)(%s)\n", ppc_reg(8), table, pos, ppc_reg(9) );
         }
         else
         {
-            fprintf(outfile, "    \"\\tlis %s, (%s+%d)@hi\\n\"\n",
-                    ppc_reg(9), asm_name(table), pos);
-            fprintf(outfile, "    \"\\tla  %s, (%s+%d)@l(%s)\\n\"\n",
-                    ppc_reg(8), asm_name(table), pos, ppc_reg(9));
+            fprintf( outfile, "\tlis %s, (%s+%d)@hi\n", ppc_reg(9), table, pos );
+            fprintf( outfile, "\tla  %s, (%s+%d)@l(%s)\n", ppc_reg(8), table, pos, ppc_reg(9) );
         }
-        fprintf(outfile, "    \"\\tlwz  %s, 0(%s)\\n\"\n", ppc_reg(7), ppc_reg(8));
-        fprintf(outfile, "    \"\\tmtctr %s\\n\"\n", ppc_reg(7));
-        fprintf(outfile, "    \"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg(7), ppc_reg(1));
-        fprintf(outfile, "    \"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg(1), ppc_reg(1));
-        fprintf(outfile, "    \"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg(8), ppc_reg(1));
-        fprintf(outfile, "    \"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg(1), ppc_reg(1));
-        fprintf(outfile, "    \"\\tlwz  %s, 0(%s)\\n\"\n",   ppc_reg(9), ppc_reg(1));
-        fprintf(outfile, "    \"\\taddi %s, %s, 0x4\\n\"\n", ppc_reg(1), ppc_reg(1));
-        fprintf(outfile, "    \"\\tbctr\\n\"\n");
+        fprintf( outfile, "\tlwz  %s, 0(%s)\n", ppc_reg(7), ppc_reg(8) );
+        fprintf( outfile, "\tmtctr %s\n", ppc_reg(7) );
+        fprintf( outfile, "\tlwz  %s, 0(%s)\n",   ppc_reg(7), ppc_reg(1) );
+        fprintf( outfile, "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
+        fprintf( outfile, "\tlwz  %s, 0(%s)\n",   ppc_reg(8), ppc_reg(1) );
+        fprintf( outfile, "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
+        fprintf( outfile, "\tlwz  %s, 0(%s)\n",   ppc_reg(9), ppc_reg(1) );
+        fprintf( outfile, "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
+        fprintf( outfile, "\tbctr\n" );
         break;
     }
     output_function_size( outfile, name );
 }
 
+/* check if we need an import directory */
+int has_imports(void)
+{
+    return (nb_imports - nb_delayed) > 0;
+}
+
 /* output the import table of a Win32 module */
-static int output_immediate_imports( FILE *outfile )
+static void output_immediate_imports( FILE *outfile )
 {
-    int i, j, nb_imm = nb_imports - nb_delayed;
+    int i, j;
+    const char *dll_name;
 
-    if (!nb_imm) return 0;
+    if (nb_imports == nb_delayed) return;  /* no immediate imports */
 
     /* main import header */
 
-    fprintf( outfile, "\nstatic struct {\n" );
-    fprintf( outfile, "  struct {\n" );
-    fprintf( outfile, "    void        *OriginalFirstThunk;\n" );
-    fprintf( outfile, "    unsigned int TimeDateStamp;\n" );
-    fprintf( outfile, "    unsigned int ForwarderChain;\n" );
-    fprintf( outfile, "    const char  *Name;\n" );
-    fprintf( outfile, "    void        *FirstThunk;\n" );
-    fprintf( outfile, "  } imp[%d];\n", nb_imm+1 );
-    fprintf( outfile, "  const char *data[%d];\n",
-             total_imports - total_delayed + nb_imm );
-    fprintf( outfile, "} imports = {\n  {\n" );
+    fprintf( outfile, "\n/* import table */\n" );
+    fprintf( outfile, "\n\t.data\n" );
+    fprintf( outfile, "\t.align %d\n", get_alignment(4) );
+    fprintf( outfile, ".L__wine_spec_imports:\n" );
 
     /* list of dlls */
 
     for (i = j = 0; i < nb_imports; i++)
     {
         if (dll_imports[i]->delay) continue;
-        fprintf( outfile, "    { 0, 0, 0, \"%s\", &imports.data[%d] },\n",
-                 dll_imports[i]->spec->file_name, j );
+        dll_name = make_c_identifier( dll_imports[i]->spec->file_name );
+        fprintf( outfile, "\t.long 0\n" );     /* OriginalFirstThunk */
+        fprintf( outfile, "\t.long 0\n" );     /* TimeDateStamp */
+        fprintf( outfile, "\t.long 0\n" );     /* ForwarderChain */
+        fprintf( outfile, "\t.long .L__wine_spec_import_name_%s-.L__wine_spec_rva_base\n", /* Name */
+                 dll_name );
+        fprintf( outfile, "\t.long .L__wine_spec_import_data_ptrs+%d-.L__wine_spec_rva_base\n",  /* FirstThunk */
+                 j * get_ptr_size() );
         j += dll_imports[i]->nb_imports + 1;
     }
+    fprintf( outfile, "\t.long 0\n" );     /* OriginalFirstThunk */
+    fprintf( outfile, "\t.long 0\n" );     /* TimeDateStamp */
+    fprintf( outfile, "\t.long 0\n" );     /* ForwarderChain */
+    fprintf( outfile, "\t.long 0\n" );     /* Name */
+    fprintf( outfile, "\t.long 0\n" );     /* FirstThunk */
 
-    fprintf( outfile, "    { 0, 0, 0, 0, 0 },\n" );
-    fprintf( outfile, "  },\n  {\n" );
+    fprintf( outfile, "\n\t.align %d\n", get_alignment(get_ptr_size()) );
+    fprintf( outfile, ".L__wine_spec_import_data_ptrs:\n" );
+    for (i = 0; i < nb_imports; i++)
+    {
+        if (dll_imports[i]->delay) continue;
+        dll_name = make_c_identifier( dll_imports[i]->spec->file_name );
+        for (j = 0; j < dll_imports[i]->nb_imports; j++)
+        {
+            ORDDEF *odp = dll_imports[i]->imports[j];
+            if (!(odp->flags & FLAG_NONAME))
+                fprintf( outfile, "\t%s .L__wine_spec_import_data_%s_%s-.L__wine_spec_rva_base\n",
+                         get_asm_ptr_keyword(), dll_name, odp->name );
+            else
+            {
+                if (get_ptr_size() == 8)
+                    fprintf( outfile, "\t.quad 0x800000000000%04x\n", odp->ordinal );
+                else
+                    fprintf( outfile, "\t.long 0x8000%04x\n", odp->ordinal );
+            }
+        }
+        fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
+    }
+    fprintf( outfile, ".L__wine_spec_imports_end:\n" );
 
-    /* list of imported functions */
-
     for (i = 0; i < nb_imports; i++)
     {
         if (dll_imports[i]->delay) continue;
-        fprintf( outfile, "    /* %s */\n", dll_imports[i]->spec->file_name );
+        dll_name = make_c_identifier( dll_imports[i]->spec->file_name );
         for (j = 0; j < dll_imports[i]->nb_imports; j++)
         {
             ORDDEF *odp = dll_imports[i]->imports[j];
             if (!(odp->flags & FLAG_NONAME))
             {
-                unsigned short ord = odp->ordinal;
-                fprintf( outfile, "    \"\\%03o\\%03o%s\",\n",
-                         *(unsigned char *)&ord, *((unsigned char *)&ord + 1), odp->name );
+                fprintf( outfile, "\t.align %d\n", get_alignment(2) );
+                fprintf( outfile, ".L__wine_spec_import_data_%s_%s:\n", dll_name, odp->name );
+                fprintf( outfile, "\t%s %d\n", get_asm_short_keyword(), odp->ordinal );
+                fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), odp->name );
             }
-            else
-                fprintf( outfile, "    (char *)%d,\n", odp->ordinal );
         }
-        fprintf( outfile, "    0,\n" );
     }
-    fprintf( outfile, "  }\n};\n\n" );
 
-    return nb_imm;
+    for (i = 0; i < nb_imports; i++)
+    {
+        if (dll_imports[i]->delay) continue;
+        dll_name = make_c_identifier( dll_imports[i]->spec->file_name );
+        fprintf( outfile, ".L__wine_spec_import_name_%s:\n\t%s \"%s\"\n",
+                 dll_name, get_asm_string_keyword(), dll_imports[i]->spec->file_name );
+    }
 }
 
 /* output the import thunks of a Win32 module */
@@ -814,35 +838,66 @@
 
     if (!nb_imm) return;
 
-    pos = (sizeof(void *) + 2*sizeof(unsigned int) + sizeof(const char *) + sizeof(void *)) *
-            (nb_imm + 1);  /* offset of imports.data from start of imports */
-    fprintf( outfile, "/* immediate import thunks */\n" );
-    fprintf( outfile, "asm(\".text\\n\\t.align %d\\n\"\n", get_alignment(8) );
-    fprintf( outfile, "    \"%s:\\n\"\n", asm_name(import_thunks));
+    fprintf( outfile, "\n/* immediate import thunks */\n\n" );
+    fprintf( outfile, "\t.text\n" );
+    fprintf( outfile, "\t.align %d\n", get_alignment(8) );
+    fprintf( outfile, "%s:\n", asm_name(import_thunks));
 
-    for (i = 0; i < nb_imports; i++)
+    for (i = pos = 0; i < nb_imports; i++)
     {
         if (dll_imports[i]->delay) continue;
-        for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += sizeof(const char *))
+        for (j = 0; j < dll_imports[i]->nb_imports; j++, pos += get_ptr_size())
         {
             ORDDEF *odp = dll_imports[i]->imports[j];
             output_import_thunk( outfile, odp->name ? odp->name : odp->export_name,
-                                 "imports", pos );
+                                 ".L__wine_spec_import_data_ptrs", pos );
         }
-        pos += 4;
+        pos += get_ptr_size();
     }
     output_function_size( outfile, import_thunks );
-    fprintf( outfile, ");\n" );
 }
 
 /* output the delayed import table of a Win32 module */
-static int output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
+static void output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
 {
     int i, j;
 
-    if (!nb_delayed) return 0;
+    if (!nb_delayed) return;
 
-    fprintf( outfile, "static void *__wine_delay_imp_hmod[%d];\n", nb_delayed );
+    fprintf( outfile, "\n/* delayed imports */\n\n" );
+    fprintf( outfile, "\t.data\n" );
+    fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
+    fprintf( outfile, "%s\n", asm_globl("__wine_spec_delay_imports") );
+
+    /* list of dlls */
+
+    for (i = j = 0; i < nb_imports; i++)
+    {
+        if (!dll_imports[i]->delay) continue;
+        fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* grAttrs */
+        fprintf( outfile, "\t%s .L__wine_delay_name_%d\n",       /* szName */
+                 get_asm_ptr_keyword(), i );
+        fprintf( outfile, "\t%s .L__wine_delay_modules+%d\n",    /* phmod */
+                 get_asm_ptr_keyword(), i * get_ptr_size() );
+        fprintf( outfile, "\t%s .L__wine_delay_IAT+%d\n",        /* pIAT */
+                 get_asm_ptr_keyword(), j * get_ptr_size() );
+        fprintf( outfile, "\t%s .L__wine_delay_INT+%d\n",        /* pINT */
+                 get_asm_ptr_keyword(), j * get_ptr_size() );
+        fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* pBoundIAT */
+        fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* pUnloadIAT */
+        fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* dwTimeStamp */
+        j += dll_imports[i]->nb_imports;
+    }
+    fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* grAttrs */
+    fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* szName */
+    fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* phmod */
+    fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* pIAT */
+    fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* pINT */
+    fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* pBoundIAT */
+    fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* pUnloadIAT */
+    fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );   /* dwTimeStamp */
+
+    fprintf( outfile, "\n.L__wine_delay_IAT:\n" );
     for (i = 0; i < nb_imports; i++)
     {
         if (!dll_imports[i]->delay) continue;
@@ -850,61 +905,52 @@
         {
             ORDDEF *odp = dll_imports[i]->imports[j];
             const char *name = odp->name ? odp->name : odp->export_name;
-            fprintf( outfile, "void __wine_delay_imp_%d_%s();\n", i, name );
+            fprintf( outfile, "\t%s .L__wine_delay_imp_%d_%s\n",
+                     get_asm_ptr_keyword(), i, name );
         }
     }
-    fprintf( outfile, "\n" );
-    fprintf( outfile, "struct {\n" );
-    fprintf( outfile, "  struct ImgDelayDescr {\n" );
-    fprintf( outfile, "    unsigned int  grAttrs;\n" );
-    fprintf( outfile, "    const char   *szName;\n" );
-    fprintf( outfile, "    void        **phmod;\n" );
-    fprintf( outfile, "    void        **pIAT;\n" );
-    fprintf( outfile, "    const char  **pINT;\n" );
-    fprintf( outfile, "    void*         pBoundIAT;\n" );
-    fprintf( outfile, "    void*         pUnloadIAT;\n" );
-    fprintf( outfile, "    unsigned long dwTimeStamp;\n" );
-    fprintf( outfile, "  } imp[%d];\n", nb_delayed + 1 );
-    fprintf( outfile, "  void         *IAT[%d];\n", total_delayed );
-    fprintf( outfile, "  const char   *INT[%d];\n", total_delayed );
-    fprintf( outfile, "} __wine_spec_delay_imports = {\n" );
-    fprintf( outfile, "  {\n" );
-    for (i = j = 0; i < nb_imports; i++)
-    {
-        if (!dll_imports[i]->delay) continue;
-        fprintf( outfile, "    { 0, \"%s\", &__wine_delay_imp_hmod[%d], &__wine_spec_delay_imports.IAT[%d], &__wine_spec_delay_imports.INT[%d], 0, 0, 0 },\n",
-                 dll_imports[i]->spec->file_name, i, j, j );
-        j += dll_imports[i]->nb_imports;
-    }
-    fprintf( outfile, "  },\n  {\n" );
+
+    fprintf( outfile, "\n.L__wine_delay_INT:\n" );
     for (i = 0; i < nb_imports; i++)
     {
         if (!dll_imports[i]->delay) continue;
-        fprintf( outfile, "    /* %s */\n", dll_imports[i]->spec->file_name );
         for (j = 0; j < dll_imports[i]->nb_imports; j++)
         {
             ORDDEF *odp = dll_imports[i]->imports[j];
-            const char *name = odp->name ? odp->name : odp->export_name;
-            fprintf( outfile, "    &__wine_delay_imp_%d_%s,\n", i, name );
+            if (!odp->name)
+                fprintf( outfile, "\t%s %d\n", get_asm_ptr_keyword(), odp->ordinal );
+            else
+                fprintf( outfile, "\t%s .L__wine_delay_data_%d_%s\n",
+                         get_asm_ptr_keyword(), i, odp->name );
         }
     }
-    fprintf( outfile, "  },\n  {\n" );
+
+    fprintf( outfile, "\n.L__wine_delay_modules:\n" );
     for (i = 0; i < nb_imports; i++)
     {
+        if (dll_imports[i]->delay) fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
+    }
+
+    for (i = 0; i < nb_imports; i++)
+    {
         if (!dll_imports[i]->delay) continue;
-        fprintf( outfile, "    /* %s */\n", dll_imports[i]->spec->file_name );
+        fprintf( outfile, ".L__wine_delay_name_%d:\n", i );
+        fprintf( outfile, "\t%s \"%s\"\n",
+                 get_asm_string_keyword(), dll_imports[i]->spec->file_name );
+    }
+
+    for (i = 0; i < nb_imports; i++)
+    {
+        if (!dll_imports[i]->delay) continue;
         for (j = 0; j < dll_imports[i]->nb_imports; j++)
         {
             ORDDEF *odp = dll_imports[i]->imports[j];
-            if (!odp->name)
-                fprintf( outfile, "    (char *)%d,\n", odp->ordinal );
-            else
-                fprintf( outfile, "    \"%s\",\n", odp->name );
+            if (!odp->name) continue;
+            fprintf( outfile, ".L__wine_delay_data_%d_%s:\n", i, odp->name );
+            fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), odp->name );
         }
     }
-    fprintf( outfile, "  }\n};\n\n" );
-
-    return nb_delayed;
+    output_function_size( outfile, "__wine_spec_delay_imports" );
 }
 
 /* output the delayed import thunks of a Win32 module */
@@ -916,107 +962,123 @@
 
     if (!nb_delayed) return;
 
-    fprintf( outfile, "/* delayed import thunks */\n" );
-    fprintf( outfile, "asm(\".text\\n\"\n" );
-    fprintf( outfile, "    \"\\t.align %d\\n\"\n", get_alignment(8) );
-    fprintf( outfile, "    \"%s:\\n\"\n", asm_name(delayed_import_loaders));
-    fprintf( outfile, "    \"\\t%s\\n\"\n", func_declaration("__wine_delay_load_asm") );
-    fprintf( outfile, "    \"%s:\\n\"\n", asm_name("__wine_delay_load_asm") );
+    fprintf( outfile, "\n/* delayed import thunks */\n\n" );
+    fprintf( outfile, "\t.text\n" );
+    fprintf( outfile, "\t.align %d\n", get_alignment(8) );
+    fprintf( outfile, "%s:\n", asm_name(delayed_import_loaders));
+    fprintf( outfile, "\t%s\n", func_declaration("__wine_delay_load_asm") );
+    fprintf( outfile, "%s:\n", asm_name("__wine_delay_load_asm") );
     switch(target_cpu)
     {
     case CPU_x86:
-        fprintf( outfile, "    \"\\tpushl %%ecx\\n\\tpushl %%edx\\n\\tpushl %%eax\\n\"\n" );
-        fprintf( outfile, "    \"\\tcall %s\\n\"\n", asm_name("__wine_spec_delay_load") );
-        fprintf( outfile, "    \"\\tpopl %%edx\\n\\tpopl %%ecx\\n\\tjmp *%%eax\\n\"\n" );
+        fprintf( outfile, "\tpushl %%ecx\n" );
+        fprintf( outfile, "\tpushl %%edx\n" );
+        fprintf( outfile, "\tpushl %%eax\n" );
+        fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_delay_load") );
+        fprintf( outfile, "\tpopl %%edx\n" );
+        fprintf( outfile, "\tpopl %%ecx\n" );
+        fprintf( outfile, "\tjmp *%%eax\n" );
         break;
+    case CPU_x86_64:
+        fprintf( outfile, "\tpushq %%rdi\n" );
+        fprintf( outfile, "\tsubq $8,%%rsp\n" );
+        fprintf( outfile, "\tmovq %%r11,%%rdi\n" );
+        fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_delay_load") );
+        fprintf( outfile, "\taddq $8,%%rsp\n" );
+        fprintf( outfile, "\tpopq %%rdi\n" );
+        fprintf( outfile, "\tjmp *%%rax\n" );
+        break;
     case CPU_SPARC:
-        fprintf( outfile, "    \"\\tsave %%sp, -96, %%sp\\n\"\n" );
-        fprintf( outfile, "    \"\\tcall %s\\n\"\n", asm_name("__wine_spec_delay_load") );
-        fprintf( outfile, "    \"\\tmov %%g1, %%o0\\n\"\n" );
-        fprintf( outfile, "    \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
+        fprintf( outfile, "\tsave %%sp, -96, %%sp\n" );
+        fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_delay_load") );
+        fprintf( outfile, "\tmov %%g1, %%o0\n" );
+        fprintf( outfile, "\tjmp %%o0\n" );
+        fprintf( outfile, "\trestore\n" );
         break;
     case CPU_ALPHA:
-        fprintf( outfile, "    \"\\tjsr $26,%s\\n\"\n", asm_name("__wine_spec_delay_load") );
-        fprintf( outfile, "    \"\\tjmp $31,($0)\\n\"\n" );
+        fprintf( outfile, "\tjsr $26,%s\n", asm_name("__wine_spec_delay_load") );
+        fprintf( outfile, "\tjmp $31,($0)\n" );
         break;
     case CPU_POWERPC:
         if (target_platform == PLATFORM_APPLE) extra_stack_storage = 56;
 
         /* Save all callee saved registers into a stackframe. */
-        fprintf( outfile, "    \"\\tstwu %s, -%d(%s)\\n\"\n",ppc_reg(1), 48+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg(3),  4+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg(4),  8+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg(12),40+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tstwu %s, -%d(%s)\n",ppc_reg(1), 48+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(3),  4+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(4),  8+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(12),40+extra_stack_storage, ppc_reg(1));
 
         /* r0 -> r3 (arg1) */
-        fprintf( outfile, "    \"\\tmr %s, %s\\n\"\n", ppc_reg(3), ppc_reg(0));
+        fprintf( outfile, "\tmr %s, %s\n", ppc_reg(3), ppc_reg(0));
 
         /* save return address */
-        fprintf( outfile, "    \"\\tmflr %s\\n\"\n", ppc_reg(0));
-        fprintf( outfile, "    \"\\tstw  %s, %d(%s)\\n\"\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tmflr %s\n", ppc_reg(0));
+        fprintf( outfile, "\tstw  %s, %d(%s)\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
 
         /* Call the __wine_delay_load function, arg1 is arg1. */
-        fprintf( outfile, "    \"\\tbl %s\\n\"\n", asm_name("__wine_spec_delay_load") );
+        fprintf( outfile, "\tbl %s\n", asm_name("__wine_spec_delay_load") );
 
         /* Load return value from call into ctr register */
-        fprintf( outfile, "    \"\\tmtctr %s\\n\"\n", ppc_reg(3));
+        fprintf( outfile, "\tmtctr %s\n", ppc_reg(3));
 
         /* restore all saved registers and drop stackframe. */
-        fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg(3),  4+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg(4),  8+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tlwz  %s, %d(%s)\\n\"\n", ppc_reg(12),40+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(3),  4+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(4),  8+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tlwz  %s, %d(%s)\n", ppc_reg(12),40+extra_stack_storage, ppc_reg(1));
 
         /* Load return value from call into return register */
-        fprintf( outfile, "    \"\\tlwz  %s,  %d(%s)\\n\"\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
-        fprintf( outfile, "    \"\\tmtlr %s\\n\"\n", ppc_reg(0));
-        fprintf( outfile, "    \"\\taddi %s, %s, %d\\n\"\n", ppc_reg(1), ppc_reg(1),  48+extra_stack_storage);
+        fprintf( outfile, "\tlwz  %s,  %d(%s)\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
+        fprintf( outfile, "\tmtlr %s\n", ppc_reg(0));
+        fprintf( outfile, "\taddi %s, %s, %d\n", ppc_reg(1), ppc_reg(1),  48+extra_stack_storage);
 
         /* branch to ctr register. */
-        fprintf( outfile, "    \"bctr\\n\"\n");
+        fprintf( outfile, "\tbctr\n");
         break;
     }
     output_function_size( outfile, "__wine_delay_load_asm" );
+    fprintf( outfile, "\n" );
 
     for (i = idx = 0; i < nb_imports; i++)
     {
         if (!dll_imports[i]->delay) continue;
         for (j = 0; j < dll_imports[i]->nb_imports; j++)
         {
-            char buffer[128];
             ORDDEF *odp = dll_imports[i]->imports[j];
             const char *name = odp->name ? odp->name : odp->export_name;
 
[truncated at 1000 lines; 4033 more skipped]