Commit 71580499 authored by Alexandre Julliard's avatar Alexandre Julliard

winebuild: Added output() function to properly deal with write errors.

parent 05001b1c
......@@ -154,11 +154,13 @@ extern void error( const char *msg, ... )
__attribute__ ((__format__ (__printf__, 1, 2)));
extern void warning( const char *msg, ... )
__attribute__ ((__format__ (__printf__, 1, 2)));
extern int output( const char *format, ... )
__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 void output_standard_file_header(void);
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 void *buffer, unsigned int size );
extern void dump_bytes( 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);
......@@ -176,8 +178,8 @@ extern const char *get_asm_string_keyword(void);
extern const char *get_asm_short_keyword(void);
extern const char *get_asm_rodata_section(void);
extern const char *get_asm_string_section(void);
extern void output_function_size( FILE *outfile, const char *name );
extern void output_gnu_stack_note( FILE *outfile );
extern void output_function_size( const char *name );
extern void output_gnu_stack_note(void);
extern void add_import_dll( const char *name, const char *filename );
extern void add_delayed_import( const char *name );
......@@ -187,20 +189,20 @@ extern void read_undef_symbols( DLLSPEC *spec, char **argv );
extern int resolve_imports( DLLSPEC *spec );
extern int has_imports(void);
extern int has_relays( DLLSPEC *spec );
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 void output_get_pc_thunk(void);
extern void output_stubs( DLLSPEC *spec );
extern void output_imports( DLLSPEC *spec );
extern int load_res32_file( const char *name, DLLSPEC *spec );
extern void output_resources( FILE *outfile, DLLSPEC *spec );
extern void output_resources( DLLSPEC *spec );
extern void load_res16_file( const char *name, DLLSPEC *spec );
extern void output_res16_data( FILE *outfile, DLLSPEC *spec );
extern void output_res16_directory( FILE *outfile, DLLSPEC *spec, const char *header_name );
extern void output_res16_data( DLLSPEC *spec );
extern void output_res16_directory( 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 BuildRelays16(void);
extern void BuildRelays32(void);
extern void BuildSpec16File( DLLSPEC *spec );
extern void BuildSpec32File( DLLSPEC *spec );
extern void BuildDef32File( DLLSPEC *spec );
extern int parse_spec_file( FILE *file, DLLSPEC *spec );
extern int parse_def_file( FILE *file, DLLSPEC *spec );
......@@ -219,6 +221,7 @@ extern int link_ext_symbols;
extern char *input_file_name;
extern char *spec_file_name;
extern FILE *output_file;
extern const char *output_file_name;
extern char **lib_path;
......
......@@ -592,99 +592,99 @@ int resolve_imports( DLLSPEC *spec )
}
/* output the get_pc thunk if needed */
void output_get_pc_thunk( FILE *outfile )
void output_get_pc_thunk(void)
{
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( "\n\t.text\n" );
output( "\t.align %d\n", get_alignment(4) );
output( "\t%s\n", func_declaration("__wine_spec_get_pc_thunk_eax") );
output( "%s:\n", asm_name("__wine_spec_get_pc_thunk_eax") );
output( "\tpopl %%eax\n" );
output( "\tpushl %%eax\n" );
output( "\tret\n" );
output_function_size( "__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 )
static void output_import_thunk( const char *name, const char *table, int pos )
{
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) );
output( "\n\t.align %d\n", get_alignment(4) );
output( "\t%s\n", func_declaration(name) );
output( "%s\n", asm_globl(name) );
switch(target_cpu)
{
case CPU_x86:
if (!UsePIC)
{
fprintf( outfile, "\tjmp *(%s+%d)\n", table, pos );
output( "\tjmp *(%s+%d)\n", table, pos );
}
else
{
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
fprintf( outfile, "1:\tjmp *%s+%d-1b(%%eax)\n", table, pos );
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
output( "1:\tjmp *%s+%d-1b(%%eax)\n", table, pos );
}
break;
case CPU_x86_64:
fprintf( outfile, "\tjmpq *%s+%d(%%rip)\n", table, pos );
output( "\tjmpq *%s+%d(%%rip)\n", table, pos );
break;
case CPU_SPARC:
if ( !UsePIC )
{
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" );
output( "\tsethi %%hi(%s+%d), %%g1\n", table, pos );
output( "\tld [%%g1+%%lo(%s+%d)], %%g1\n", table, pos );
output( "\tjmp %%g1\n" );
output( "\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" );
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" );
output( "\tsave %%sp, -96, %%sp\n" );
output( "0:\tcall 1f\n" );
output( "\tnop\n" );
output( "1:\tsethi %%hi(%s+%d-0b), %%g1\n", table, pos );
output( "\tor %%g1, %%lo(%s+%d-0b), %%g1\n", table, pos );
output( "\tld [%%g1+%%o7], %%g1\n" );
output( "\tjmp %%g1\n" );
output( "\trestore\n" );
}
break;
case CPU_ALPHA:
fprintf( outfile, "\tlda $0,%s\n", table );
fprintf( outfile, "\tlda $0,%d($0)\n", pos );
fprintf( outfile, "\tjmp $31,($0)\n" );
output( "\tlda $0,%s\n", table );
output( "\tlda $0,%d($0)\n", pos );
output( "\tjmp $31,($0)\n" );
break;
case CPU_POWERPC:
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) );
output( "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
output( "\tstw %s, 0(%s)\n", ppc_reg(9), ppc_reg(1) );
output( "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
output( "\tstw %s, 0(%s)\n", ppc_reg(8), ppc_reg(1) );
output( "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1) );
output( "\tstw %s, 0(%s)\n", ppc_reg(7), ppc_reg(1) );
if (target_platform == PLATFORM_APPLE)
{
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) );
output( "\tlis %s, ha16(%s+%d)\n", ppc_reg(9), table, pos );
output( "\tla %s, lo16(%s+%d)(%s)\n", ppc_reg(8), table, pos, ppc_reg(9) );
}
else
{
fprintf( outfile, "\tlis %s, (%s+%d)@h\n", ppc_reg(9), table, pos );
fprintf( outfile, "\tla %s, (%s+%d)@l(%s)\n", ppc_reg(8), table, pos, ppc_reg(9) );
output( "\tlis %s, (%s+%d)@h\n", ppc_reg(9), table, pos );
output( "\tla %s, (%s+%d)@l(%s)\n", ppc_reg(8), table, pos, ppc_reg(9) );
}
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" );
output( "\tlwz %s, 0(%s)\n", ppc_reg(7), ppc_reg(8) );
output( "\tmtctr %s\n", ppc_reg(7) );
output( "\tlwz %s, 0(%s)\n", ppc_reg(7), ppc_reg(1) );
output( "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
output( "\tlwz %s, 0(%s)\n", ppc_reg(8), ppc_reg(1) );
output( "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
output( "\tlwz %s, 0(%s)\n", ppc_reg(9), ppc_reg(1) );
output( "\taddi %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1) );
output( "\tbctr\n" );
break;
}
output_function_size( outfile, name );
output_function_size( name );
}
/* check if we need an import directory */
......@@ -694,7 +694,7 @@ int has_imports(void)
}
/* output the import table of a Win32 module */
static void output_immediate_imports( FILE *outfile )
static void output_immediate_imports(void)
{
int i, j;
const char *dll_name;
......@@ -703,10 +703,10 @@ static void output_immediate_imports( FILE *outfile )
/* main import header */
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" );
output( "\n/* import table */\n" );
output( "\n\t.data\n" );
output( "\t.align %d\n", get_alignment(4) );
output( ".L__wine_spec_imports:\n" );
/* list of dlls */
......@@ -714,23 +714,23 @@ static void output_immediate_imports( FILE *outfile )
{
if (dll_imports[i]->delay) continue;
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 */
output( "\t.long 0\n" ); /* OriginalFirstThunk */
output( "\t.long 0\n" ); /* TimeDateStamp */
output( "\t.long 0\n" ); /* ForwarderChain */
output( "\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 */
output( "\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, "\n\t.align %d\n", get_alignment(get_ptr_size()) );
fprintf( outfile, ".L__wine_spec_import_data_ptrs:\n" );
output( "\t.long 0\n" ); /* OriginalFirstThunk */
output( "\t.long 0\n" ); /* TimeDateStamp */
output( "\t.long 0\n" ); /* ForwarderChain */
output( "\t.long 0\n" ); /* Name */
output( "\t.long 0\n" ); /* FirstThunk */
output( "\n\t.align %d\n", get_alignment(get_ptr_size()) );
output( ".L__wine_spec_import_data_ptrs:\n" );
for (i = 0; i < nb_imports; i++)
{
if (dll_imports[i]->delay) continue;
......@@ -739,19 +739,19 @@ static void output_immediate_imports( FILE *outfile )
{
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",
output( "\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 );
output( "\t.quad 0x800000000000%04x\n", odp->ordinal );
else
fprintf( outfile, "\t.long 0x8000%04x\n", odp->ordinal );
output( "\t.long 0x8000%04x\n", odp->ordinal );
}
}
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
output( "\t%s 0\n", get_asm_ptr_keyword() );
}
fprintf( outfile, ".L__wine_spec_imports_end:\n" );
output( ".L__wine_spec_imports_end:\n" );
for (i = 0; i < nb_imports; i++)
{
......@@ -762,10 +762,10 @@ static void output_immediate_imports( FILE *outfile )
ORDDEF *odp = dll_imports[i]->imports[j];
if (!(odp->flags & FLAG_NONAME))
{
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 );
output( "\t.align %d\n", get_alignment(2) );
output( ".L__wine_spec_import_data_%s_%s:\n", dll_name, odp->name );
output( "\t%s %d\n", get_asm_short_keyword(), odp->ordinal );
output( "\t%s \"%s\"\n", get_asm_string_keyword(), odp->name );
}
}
}
......@@ -774,13 +774,13 @@ static void output_immediate_imports( FILE *outfile )
{
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",
output( ".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 */
static void output_immediate_import_thunks( FILE *outfile )
static void output_immediate_import_thunks(void)
{
int i, j, pos;
int nb_imm = nb_imports - nb_delayed;
......@@ -788,10 +788,10 @@ static void output_immediate_import_thunks( FILE *outfile )
if (!nb_imm) return;
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));
output( "\n/* immediate import thunks */\n\n" );
output( "\t.text\n" );
output( "\t.align %d\n", get_alignment(8) );
output( "%s:\n", asm_name(import_thunks));
for (i = pos = 0; i < nb_imports; i++)
{
......@@ -799,56 +799,56 @@ static void output_immediate_import_thunks( FILE *outfile )
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,
output_import_thunk( odp->name ? odp->name : odp->export_name,
".L__wine_spec_import_data_ptrs", pos );
}
pos += get_ptr_size();
}
output_function_size( outfile, import_thunks );
output_function_size( import_thunks );
}
/* output the delayed import table of a Win32 module */
static void output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
static void output_delayed_imports( const DLLSPEC *spec )
{
int i, j, mod;
if (!nb_delayed) return;
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") );
output( "\n/* delayed imports */\n\n" );
output( "\t.data\n" );
output( "\t.align %d\n", get_alignment(get_ptr_size()) );
output( "%s\n", asm_globl("__wine_spec_delay_imports") );
/* list of dlls */
for (i = j = mod = 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 */
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* grAttrs */
output( "\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 */
output( "\t%s .L__wine_delay_modules+%d\n", /* phmod */
get_asm_ptr_keyword(), mod * get_ptr_size() );
fprintf( outfile, "\t%s .L__wine_delay_IAT+%d\n", /* pIAT */
output( "\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 */
output( "\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 */
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pBoundIAT */
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pUnloadIAT */
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* dwTimeStamp */
j += dll_imports[i]->nb_imports;
mod++;
}
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" );
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* grAttrs */
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* szName */
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* phmod */
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pIAT */
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pINT */
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pBoundIAT */
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* pUnloadIAT */
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* dwTimeStamp */
output( "\n.L__wine_delay_IAT:\n" );
for (i = 0; i < nb_imports; i++)
{
if (!dll_imports[i]->delay) continue;
......@@ -856,12 +856,12 @@ static void output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
{
ORDDEF *odp = dll_imports[i]->imports[j];
const char *name = odp->name ? odp->name : odp->export_name;
fprintf( outfile, "\t%s .L__wine_delay_imp_%d_%s\n",
output( "\t%s .L__wine_delay_imp_%d_%s\n",
get_asm_ptr_keyword(), i, name );
}
}
fprintf( outfile, "\n.L__wine_delay_INT:\n" );
output( "\n.L__wine_delay_INT:\n" );
for (i = 0; i < nb_imports; i++)
{
if (!dll_imports[i]->delay) continue;
......@@ -869,24 +869,24 @@ static void output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
{
ORDDEF *odp = dll_imports[i]->imports[j];
if (!odp->name)
fprintf( outfile, "\t%s %d\n", get_asm_ptr_keyword(), odp->ordinal );
output( "\t%s %d\n", get_asm_ptr_keyword(), odp->ordinal );
else
fprintf( outfile, "\t%s .L__wine_delay_data_%d_%s\n",
output( "\t%s .L__wine_delay_data_%d_%s\n",
get_asm_ptr_keyword(), i, odp->name );
}
}
fprintf( outfile, "\n.L__wine_delay_modules:\n" );
output( "\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() );
if (dll_imports[i]->delay) output( "\t%s 0\n", get_asm_ptr_keyword() );
}
for (i = 0; i < nb_imports; i++)
{
if (!dll_imports[i]->delay) continue;
fprintf( outfile, ".L__wine_delay_name_%d:\n", i );
fprintf( outfile, "\t%s \"%s\"\n",
output( ".L__wine_delay_name_%d:\n", i );
output( "\t%s \"%s\"\n",
get_asm_string_keyword(), dll_imports[i]->spec->file_name );
}
......@@ -897,15 +897,15 @@ static void output_delayed_imports( FILE *outfile, const DLLSPEC *spec )
{
ORDDEF *odp = dll_imports[i]->imports[j];
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 );
output( ".L__wine_delay_data_%d_%s:\n", i, odp->name );
output( "\t%s \"%s\"\n", get_asm_string_keyword(), odp->name );
}
}
output_function_size( outfile, "__wine_spec_delay_imports" );
output_function_size( "__wine_spec_delay_imports" );
}
/* output the delayed import thunks of a Win32 module */
static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
static void output_delayed_import_thunks( const DLLSPEC *spec )
{
int i, idx, j, pos, extra_stack_storage = 0;
static const char delayed_import_loaders[] = "__wine_spec_delayed_import_loaders";
......@@ -913,105 +913,105 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
if (!nb_delayed) return;
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") );
output( "\n/* delayed import thunks */\n\n" );
output( "\t.text\n" );
output( "\t.align %d\n", get_alignment(8) );
output( "%s:\n", asm_name(delayed_import_loaders));
output( "\t%s\n", func_declaration("__wine_delay_load_asm") );
output( "%s:\n", asm_name("__wine_delay_load_asm") );
switch(target_cpu)
{
case CPU_x86:
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" );
output( "\tpushl %%ecx\n" );
output( "\tpushl %%edx\n" );
output( "\tpushl %%eax\n" );
output( "\tcall %s\n", asm_name("__wine_spec_delay_load") );
output( "\tpopl %%edx\n" );
output( "\tpopl %%ecx\n" );
output( "\tjmp *%%eax\n" );
break;
case CPU_x86_64:
fprintf( outfile, "\tpushq %%rdi\n" );
fprintf( outfile, "\tpushq %%rsi\n" );
fprintf( outfile, "\tpushq %%rdx\n" );
fprintf( outfile, "\tpushq %%rcx\n" );
fprintf( outfile, "\tpushq %%r8\n" );
fprintf( outfile, "\tpushq %%r9\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 %%r9\n" );
fprintf( outfile, "\tpopq %%r8\n" );
fprintf( outfile, "\tpopq %%rcx\n" );
fprintf( outfile, "\tpopq %%rdx\n" );
fprintf( outfile, "\tpopq %%rsi\n" );
fprintf( outfile, "\tpopq %%rdi\n" );
fprintf( outfile, "\tjmp *%%rax\n" );
output( "\tpushq %%rdi\n" );
output( "\tpushq %%rsi\n" );
output( "\tpushq %%rdx\n" );
output( "\tpushq %%rcx\n" );
output( "\tpushq %%r8\n" );
output( "\tpushq %%r9\n" );
output( "\tsubq $8,%%rsp\n" );
output( "\tmovq %%r11,%%rdi\n" );
output( "\tcall %s\n", asm_name("__wine_spec_delay_load") );
output( "\taddq $8,%%rsp\n" );
output( "\tpopq %%r9\n" );
output( "\tpopq %%r8\n" );
output( "\tpopq %%rcx\n" );
output( "\tpopq %%rdx\n" );
output( "\tpopq %%rsi\n" );
output( "\tpopq %%rdi\n" );
output( "\tjmp *%%rax\n" );
break;
case CPU_SPARC:
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" );
output( "\tsave %%sp, -96, %%sp\n" );
output( "\tcall %s\n", asm_name("__wine_spec_delay_load") );
output( "\tmov %%g1, %%o0\n" );
output( "\tjmp %%o0\n" );
output( "\trestore\n" );
break;
case CPU_ALPHA:
fprintf( outfile, "\tjsr $26,%s\n", asm_name("__wine_spec_delay_load") );
fprintf( outfile, "\tjmp $31,($0)\n" );
output( "\tjsr $26,%s\n", asm_name("__wine_spec_delay_load") );
output( "\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",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));
output( "\tstwu %s, -%d(%s)\n",ppc_reg(1), 48+extra_stack_storage, ppc_reg(1));
output( "\tstw %s, %d(%s)\n", ppc_reg(3), 4+extra_stack_storage, ppc_reg(1));
output( "\tstw %s, %d(%s)\n", ppc_reg(4), 8+extra_stack_storage, ppc_reg(1));
output( "\tstw %s, %d(%s)\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
output( "\tstw %s, %d(%s)\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
output( "\tstw %s, %d(%s)\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
output( "\tstw %s, %d(%s)\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
output( "\tstw %s, %d(%s)\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
output( "\tstw %s, %d(%s)\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
output( "\tstw %s, %d(%s)\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
output( "\tstw %s, %d(%s)\n", ppc_reg(12),40+extra_stack_storage, ppc_reg(1));
/* r0 -> r3 (arg1) */
fprintf( outfile, "\tmr %s, %s\n", ppc_reg(3), ppc_reg(0));
output( "\tmr %s, %s\n", ppc_reg(3), ppc_reg(0));
/* save return address */
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));
output( "\tmflr %s\n", ppc_reg(0));
output( "\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", asm_name("__wine_spec_delay_load") );
output( "\tbl %s\n", asm_name("__wine_spec_delay_load") );
/* Load return value from call into ctr register */
fprintf( outfile, "\tmtctr %s\n", ppc_reg(3));
output( "\tmtctr %s\n", ppc_reg(3));
/* restore all saved registers and drop stackframe. */
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));
output( "\tlwz %s, %d(%s)\n", ppc_reg(3), 4+extra_stack_storage, ppc_reg(1));
output( "\tlwz %s, %d(%s)\n", ppc_reg(4), 8+extra_stack_storage, ppc_reg(1));
output( "\tlwz %s, %d(%s)\n", ppc_reg(5), 12+extra_stack_storage, ppc_reg(1));
output( "\tlwz %s, %d(%s)\n", ppc_reg(6), 16+extra_stack_storage, ppc_reg(1));
output( "\tlwz %s, %d(%s)\n", ppc_reg(7), 20+extra_stack_storage, ppc_reg(1));
output( "\tlwz %s, %d(%s)\n", ppc_reg(8), 24+extra_stack_storage, ppc_reg(1));
output( "\tlwz %s, %d(%s)\n", ppc_reg(9), 28+extra_stack_storage, ppc_reg(1));
output( "\tlwz %s, %d(%s)\n", ppc_reg(10),32+extra_stack_storage, ppc_reg(1));
output( "\tlwz %s, %d(%s)\n", ppc_reg(11),36+extra_stack_storage, ppc_reg(1));
output( "\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", 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);
output( "\tlwz %s, %d(%s)\n", ppc_reg(0), 44+extra_stack_storage, ppc_reg(1));
output( "\tmtlr %s\n", ppc_reg(0));
output( "\taddi %s, %s, %d\n", ppc_reg(1), ppc_reg(1), 48+extra_stack_storage);
/* branch to ctr register. */
fprintf( outfile, "\tbctr\n");
output( "\tbctr\n");
break;
}
output_function_size( outfile, "__wine_delay_load_asm" );
fprintf( outfile, "\n" );
output_function_size( "__wine_delay_load_asm" );
output( "\n" );
for (i = idx = 0; i < nb_imports; i++)
{
......@@ -1021,25 +1021,25 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
ORDDEF *odp = dll_imports[i]->imports[j];
const char *name = odp->name ? odp->name : odp->export_name;
fprintf( outfile, ".L__wine_delay_imp_%d_%s:\n", i, name );
output( ".L__wine_delay_imp_%d_%s:\n", i, name );
switch(target_cpu)
{
case CPU_x86:
fprintf( outfile, "\tmovl $%d, %%eax\n", (idx << 16) | j );
fprintf( outfile, "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
output( "\tmovl $%d, %%eax\n", (idx << 16) | j );
output( "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
break;
case CPU_x86_64:
fprintf( outfile, "\tmovq $%d,%%r11\n", (idx << 16) | j );
fprintf( outfile, "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
output( "\tmovq $%d,%%r11\n", (idx << 16) | j );
output( "\tjmp %s\n", asm_name("__wine_delay_load_asm") );
break;
case CPU_SPARC:
fprintf( outfile, "\tset %d, %%g1\n", (idx << 16) | j );
fprintf( outfile, "\tb,a %s\n", asm_name("__wine_delay_load_asm") );
output( "\tset %d, %%g1\n", (idx << 16) | j );
output( "\tb,a %s\n", asm_name("__wine_delay_load_asm") );
break;
case CPU_ALPHA:
fprintf( outfile, "\tlda $0,%d($31)\n", j);
fprintf( outfile, "\tldah $0,%d($0)\n", idx);
fprintf( outfile, "\tjmp $31,%s\n", asm_name("__wine_delay_load_asm") );
output( "\tlda $0,%d($31)\n", j);
output( "\tldah $0,%d($0)\n", idx);
output( "\tjmp $31,%s\n", asm_name("__wine_delay_load_asm") );
break;
case CPU_POWERPC:
switch(target_platform)
......@@ -1047,24 +1047,24 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
case PLATFORM_APPLE:
/* On Darwin we can use r0 and r2 */
/* Upper part in r2 */
fprintf( outfile, "\tlis %s, %d\n", ppc_reg(2), idx);
output( "\tlis %s, %d\n", ppc_reg(2), idx);
/* Lower part + r2 -> r0, Note we can't use r0 directly */
fprintf( outfile, "\taddi %s, %s, %d\n", ppc_reg(0), ppc_reg(2), j);
fprintf( outfile, "\tb %s\n", asm_name("__wine_delay_load_asm") );
output( "\taddi %s, %s, %d\n", ppc_reg(0), ppc_reg(2), j);
output( "\tb %s\n", asm_name("__wine_delay_load_asm") );
break;
default:
/* On linux we can't use r2 since r2 is not a scratch register (hold the TOC) */
/* Save r13 on the stack */
fprintf( outfile, "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1));
fprintf( outfile, "\tstw %s, 0(%s)\n", ppc_reg(13), ppc_reg(1));
output( "\taddi %s, %s, -0x4\n", ppc_reg(1), ppc_reg(1));
output( "\tstw %s, 0(%s)\n", ppc_reg(13), ppc_reg(1));
/* Upper part in r13 */
fprintf( outfile, "\tlis %s, %d\n", ppc_reg(13), idx);
output( "\tlis %s, %d\n", ppc_reg(13), idx);
/* Lower part + r13 -> r0, Note we can't use r0 directly */
fprintf( outfile, "\taddi %s, %s, %d\n", ppc_reg(0), ppc_reg(13), j);
output( "\taddi %s, %s, %d\n", ppc_reg(0), ppc_reg(13), j);
/* Restore r13 */
fprintf( outfile, "\tstw %s, 0(%s)\n", ppc_reg(13), ppc_reg(1));
fprintf( outfile, "\taddic %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1));
fprintf( outfile, "\tb %s\n", asm_name("__wine_delay_load_asm") );
output( "\tstw %s, 0(%s)\n", ppc_reg(13), ppc_reg(1));
output( "\taddic %s, %s, 0x4\n", ppc_reg(1), ppc_reg(1));
output( "\tb %s\n", asm_name("__wine_delay_load_asm") );
break;
}
break;
......@@ -1072,25 +1072,25 @@ static void output_delayed_import_thunks( FILE *outfile, const DLLSPEC *spec )
}
idx++;
}
output_function_size( outfile, delayed_import_loaders );
output_function_size( delayed_import_loaders );
fprintf( outfile, "\n\t.align %d\n", get_alignment(get_ptr_size()) );
fprintf( outfile, "%s:\n", asm_name(delayed_import_thunks));
output( "\n\t.align %d\n", get_alignment(get_ptr_size()) );
output( "%s:\n", asm_name(delayed_import_thunks));
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 += get_ptr_size())
{
ORDDEF *odp = dll_imports[i]->imports[j];
output_import_thunk( outfile, odp->name ? odp->name : odp->export_name,
output_import_thunk( odp->name ? odp->name : odp->export_name,
".L__wine_delay_IAT", pos );
}
}
output_function_size( outfile, delayed_import_thunks );
output_function_size( delayed_import_thunks );
}
/* output import stubs for exported entry points that link to external symbols */
static void output_external_link_imports( FILE *outfile, DLLSPEC *spec )
static void output_external_link_imports( DLLSPEC *spec )
{
unsigned int i, pos;
......@@ -1105,25 +1105,25 @@ static void output_external_link_imports( FILE *outfile, DLLSPEC *spec )
remove_name( &ext_link_imports, i-- );
}
fprintf( outfile, "\n/* external link thunks */\n\n" );
fprintf( outfile, "\t.data\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
fprintf( outfile, ".L__wine_spec_external_links:\n" );
output( "\n/* external link thunks */\n\n" );
output( "\t.data\n" );
output( "\t.align %d\n", get_alignment(get_ptr_size()) );
output( ".L__wine_spec_external_links:\n" );
for (i = 0; i < ext_link_imports.count; i++)
fprintf( outfile, "\t%s %s\n", get_asm_ptr_keyword(), asm_name(ext_link_imports.names[i]) );
output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name(ext_link_imports.names[i]) );
fprintf( outfile, "\n\t.text\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
fprintf( outfile, "%s:\n", asm_name("__wine_spec_external_link_thunks") );
output( "\n\t.text\n" );
output( "\t.align %d\n", get_alignment(get_ptr_size()) );
output( "%s:\n", asm_name("__wine_spec_external_link_thunks") );
for (i = pos = 0; i < ext_link_imports.count; i++)
{
char buffer[256];
sprintf( buffer, "__wine_spec_ext_link_%s", ext_link_imports.names[i] );
output_import_thunk( outfile, buffer, ".L__wine_spec_external_links", pos );
output_import_thunk( buffer, ".L__wine_spec_external_links", pos );
pos += get_ptr_size();
}
output_function_size( outfile, "__wine_spec_external_link_thunks" );
output_function_size( "__wine_spec_external_link_thunks" );
}
/*******************************************************************
......@@ -1131,15 +1131,15 @@ static void output_external_link_imports( FILE *outfile, DLLSPEC *spec )
*
* Output the functions for stub entry points
*/
void output_stubs( FILE *outfile, DLLSPEC *spec )
void output_stubs( DLLSPEC *spec )
{
const char *name, *exp_name;
int i, pos;
if (!has_stubs( spec )) return;
fprintf( outfile, "\n/* stub functions */\n\n" );
fprintf( outfile, "\t.text\n" );
output( "\n/* stub functions */\n\n" );
output( "\t.text\n" );
for (i = pos = 0; i < spec->nb_entry_points; i++)
{
......@@ -1148,64 +1148,64 @@ void output_stubs( FILE *outfile, DLLSPEC *spec )
name = get_stub_name( odp, spec );
exp_name = odp->name ? odp->name : odp->export_name;
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
fprintf( outfile, "\t%s\n", func_declaration(name) );
fprintf( outfile, "%s:\n", asm_name(name) );
fprintf( outfile, "\tsubl $4,%%esp\n" );
output( "\t.align %d\n", get_alignment(4) );
output( "\t%s\n", func_declaration(name) );
output( "%s:\n", asm_name(name) );
output( "\tsubl $4,%%esp\n" );
if (UsePIC)
{
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
fprintf( outfile, "1:" );
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
output( "1:" );
if (exp_name)
{
fprintf( outfile, "\tleal .L__wine_stub_strings+%d-1b(%%eax),%%ecx\n", pos );
fprintf( outfile, "\tpushl %%ecx\n" );
output( "\tleal .L__wine_stub_strings+%d-1b(%%eax),%%ecx\n", pos );
output( "\tpushl %%ecx\n" );
pos += strlen(exp_name) + 1;
}
else
fprintf( outfile, "\tpushl $%d\n", odp->ordinal );
fprintf( outfile, "\tleal .L__wine_spec_file_name-1b(%%eax),%%ecx\n" );
fprintf( outfile, "\tpushl %%ecx\n" );
output( "\tpushl $%d\n", odp->ordinal );
output( "\tleal .L__wine_spec_file_name-1b(%%eax),%%ecx\n" );
output( "\tpushl %%ecx\n" );
}
else
{
if (exp_name)
{
fprintf( outfile, "\tpushl $.L__wine_stub_strings+%d\n", pos );
output( "\tpushl $.L__wine_stub_strings+%d\n", pos );
pos += strlen(exp_name) + 1;
}
else
fprintf( outfile, "\tpushl $%d\n", odp->ordinal );
fprintf( outfile, "\tpushl $.L__wine_spec_file_name\n" );
output( "\tpushl $%d\n", odp->ordinal );
output( "\tpushl $.L__wine_spec_file_name\n" );
}
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") );
output_function_size( outfile, name );
output( "\tcall %s\n", asm_name("__wine_spec_unimplemented_stub") );
output_function_size( name );
}
if (pos)
{
fprintf( outfile, "\t%s\n", get_asm_string_section() );
fprintf( outfile, ".L__wine_stub_strings:\n" );
output( "\t%s\n", get_asm_string_section() );
output( ".L__wine_stub_strings:\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", get_asm_string_keyword(), exp_name );
output( "\t%s \"%s\"\n", get_asm_string_keyword(), exp_name );
}
}
}
/* output the import and delayed import tables of a Win32 module */
void output_imports( FILE *outfile, DLLSPEC *spec )
void output_imports( DLLSPEC *spec )
{
output_immediate_imports( outfile );
output_delayed_imports( outfile, spec );
output_immediate_import_thunks( outfile );
output_delayed_import_thunks( outfile, spec );
output_external_link_imports( outfile, spec );
output_immediate_imports();
output_delayed_imports( spec );
output_immediate_import_thunks();
output_delayed_import_thunks( spec );
output_external_link_imports( spec );
if (nb_imports || ext_link_imports.count || has_stubs(spec) || has_relays(spec))
output_get_pc_thunk( outfile );
output_get_pc_thunk();
}
......@@ -75,6 +75,7 @@ char **lib_path = NULL;
char *input_file_name = NULL;
char *spec_file_name = NULL;
FILE *output_file = NULL;
const char *output_file_name = NULL;
static const char *output_file_source_name;
......@@ -82,7 +83,6 @@ char *as_command = NULL;
char *ld_command = NULL;
char *nm_command = NULL;
static FILE *output_file;
static int nb_res_files;
static char **res_files;
......@@ -597,11 +597,11 @@ int main(int argc, char **argv)
case SPEC_WIN16:
if (argv[0])
fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
BuildSpec16File( output_file, spec );
BuildSpec16File( spec );
break;
case SPEC_WIN32:
read_undef_symbols( spec, argv );
BuildSpec32File( output_file, spec );
BuildSpec32File( spec );
break;
default: assert(0);
}
......@@ -613,22 +613,22 @@ int main(int argc, char **argv)
load_import_libs( argv );
if (spec_file_name && !parse_input_file( spec )) break;
read_undef_symbols( spec, argv );
BuildSpec32File( output_file, spec );
BuildSpec32File( spec );
break;
case MODE_DEF:
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
if (spec->type == SPEC_WIN16) fatal_error( "Cannot yet build .def file for 16-bit dlls\n" );
if (!spec_file_name) fatal_error( "missing .spec file\n" );
if (!parse_input_file( spec )) break;
BuildDef32File( output_file, spec );
BuildDef32File( spec );
break;
case MODE_RELAY16:
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
BuildRelays16( output_file );
BuildRelays16();
break;
case MODE_RELAY32:
if (argv[0]) fatal_error( "file argument '%s' not allowed in this mode\n", argv[0] );
BuildRelays32( output_file );
BuildRelays32();
break;
default:
usage(1);
......@@ -637,7 +637,7 @@ int main(int argc, char **argv)
if (nb_errors) exit(1);
if (output_file_name)
{
fclose( output_file );
if (fclose( output_file ) < 0) fatal_perror( "fclose" );
if (output_file_source_name) assemble_file( output_file_source_name, output_file_name );
output_file_name = NULL;
}
......
......@@ -50,11 +50,11 @@
/* fix this if the ntdll_thread_regs structure is changed */
#define GS_OFFSET 0x1b0 /* STRUCTOFFSET(TEB,SpareBytes1) + STRUCTOFFSET(ntdll_thread_regs,gs) */
static void function_header( FILE *outfile, const char *name )
static void function_header( const char *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) );
output( "\n\t.align %d\n", get_alignment(4) );
output( "\t%s\n", func_declaration(name) );
output( "%s\n", asm_globl(name) );
}
......@@ -125,74 +125,73 @@ static void function_header( FILE *outfile, const char *name )
* (sp-20) long saved edx
* (sp-24) long saved previous stack
*/
static void BuildCallFrom16Core( FILE *outfile, int reg_func, int thunk )
static void BuildCallFrom16Core( int reg_func, int thunk )
{
/* Function header */
if (thunk) function_header( outfile, "__wine_call_from_16_thunk" );
else if (reg_func) function_header( outfile, "__wine_call_from_16_regs" );
else function_header( outfile, "__wine_call_from_16" );
if (thunk) function_header( "__wine_call_from_16_thunk" );
else if (reg_func) function_header( "__wine_call_from_16_regs" );
else function_header( "__wine_call_from_16" );
/* Create STACK16FRAME (except STACK32FRAME link) */
fprintf( outfile, "\tpushw %%gs\n" );
fprintf( outfile, "\tpushw %%fs\n" );
fprintf( outfile, "\tpushw %%es\n" );
fprintf( outfile, "\tpushw %%ds\n" );
fprintf( outfile, "\tpushl %%ebp\n" );
fprintf( outfile, "\tpushl %%ecx\n" );
fprintf( outfile, "\tpushl %%edx\n" );
output( "\tpushw %%gs\n" );
output( "\tpushw %%fs\n" );
output( "\tpushw %%es\n" );
output( "\tpushw %%ds\n" );
output( "\tpushl %%ebp\n" );
output( "\tpushl %%ecx\n" );
output( "\tpushl %%edx\n" );
/* Save original EFlags register */
if (reg_func) fprintf( outfile, "\tpushfl\n" );
if (reg_func) output( "\tpushfl\n" );
if ( UsePIC )
{
fprintf( outfile, "\tcall 1f\n" );
fprintf( outfile, "1:\tpopl %%ecx\n" );
fprintf( outfile, "\t.byte 0x2e\n\tmovl %s-1b(%%ecx),%%edx\n",
asm_name("CallTo16_DataSelector") );
output( "\tcall 1f\n" );
output( "1:\tpopl %%ecx\n" );
output( "\t.byte 0x2e\n\tmovl %s-1b(%%ecx),%%edx\n", asm_name("CallTo16_DataSelector") );
}
else
fprintf( outfile, "\t.byte 0x2e\n\tmovl %s,%%edx\n", asm_name("CallTo16_DataSelector") );
output( "\t.byte 0x2e\n\tmovl %s,%%edx\n", asm_name("CallTo16_DataSelector") );
/* Load 32-bit segment registers */
fprintf( outfile, "\tmovw %%dx, %%ds\n" );
fprintf( outfile, "\tmovw %%dx, %%es\n" );
output( "\tmovw %%dx, %%ds\n" );
output( "\tmovw %%dx, %%es\n" );
if ( UsePIC )
fprintf( outfile, "\tmovw %s-1b(%%ecx), %%fs\n", asm_name("CallTo16_TebSelector") );
output( "\tmovw %s-1b(%%ecx), %%fs\n", asm_name("CallTo16_TebSelector") );
else
fprintf( outfile, "\tmovw %s, %%fs\n", asm_name("CallTo16_TebSelector") );
output( "\tmovw %s, %%fs\n", asm_name("CallTo16_TebSelector") );
fprintf( outfile, "\t.byte 0x64\n\tmov (%d),%%gs\n", GS_OFFSET );
output( "\t.byte 0x64\n\tmov (%d),%%gs\n", GS_OFFSET );
/* Translate STACK16FRAME base to flat offset in %edx */
fprintf( outfile, "\tmovw %%ss, %%dx\n" );
fprintf( outfile, "\tandl $0xfff8, %%edx\n" );
fprintf( outfile, "\tshrl $1, %%edx\n" );
output( "\tmovw %%ss, %%dx\n" );
output( "\tandl $0xfff8, %%edx\n" );
output( "\tshrl $1, %%edx\n" );
if (UsePIC)
{
fprintf( outfile, "\taddl wine_ldt_copy_ptr-1b(%%ecx),%%edx\n" );
fprintf( outfile, "\tmovl (%%edx), %%edx\n" );
output( "\taddl wine_ldt_copy_ptr-1b(%%ecx),%%edx\n" );
output( "\tmovl (%%edx), %%edx\n" );
}
else
fprintf( outfile, "\tmovl %s(%%edx), %%edx\n", asm_name("wine_ldt_copy") );
fprintf( outfile, "\tmovzwl %%sp, %%ebp\n" );
fprintf( outfile, "\tleal %d(%%ebp,%%edx), %%edx\n", reg_func ? 0 : -4 );
output( "\tmovl %s(%%edx), %%edx\n", asm_name("wine_ldt_copy") );
output( "\tmovzwl %%sp, %%ebp\n" );
output( "\tleal %d(%%ebp,%%edx), %%edx\n", reg_func ? 0 : -4 );
/* Get saved flags into %ecx */
if (reg_func) fprintf( outfile, "\tpopl %%ecx\n" );
if (reg_func) output( "\tpopl %%ecx\n" );
/* Get the 32-bit stack pointer from the TEB and complete STACK16FRAME */
fprintf( outfile, "\t.byte 0x64\n\tmovl (%d), %%ebp\n", STACKOFFSET );
fprintf( outfile, "\tpushl %%ebp\n" );
output( "\t.byte 0x64\n\tmovl (%d), %%ebp\n", STACKOFFSET );
output( "\tpushl %%ebp\n" );
/* Switch stacks */
fprintf( outfile, "\t.byte 0x64\n\tmovw %%ss, (%d)\n", STACKOFFSET + 2 );
fprintf( outfile, "\t.byte 0x64\n\tmovw %%sp, (%d)\n", STACKOFFSET );
fprintf( outfile, "\tpushl %%ds\n" );
fprintf( outfile, "\tpopl %%ss\n" );
fprintf( outfile, "\tmovl %%ebp, %%esp\n" );
fprintf( outfile, "\taddl $%d, %%ebp\n", STACK32OFFSET(ebp) );
output( "\t.byte 0x64\n\tmovw %%ss, (%d)\n", STACKOFFSET + 2 );
output( "\t.byte 0x64\n\tmovw %%sp, (%d)\n", STACKOFFSET );
output( "\tpushl %%ds\n" );
output( "\tpopl %%ss\n" );
output( "\tmovl %%ebp, %%esp\n" );
output( "\taddl $%d, %%ebp\n", STACK32OFFSET(ebp) );
/* At this point:
......@@ -209,32 +208,32 @@ static void BuildCallFrom16Core( FILE *outfile, int reg_func, int thunk )
if ( thunk )
{
/* Set up registers as expected and call thunk */
fprintf( outfile, "\tleal %d(%%edx), %%ebx\n", (int)sizeof(STACK16FRAME)-22 );
fprintf( outfile, "\tleal -4(%%esp), %%ebp\n" );
output( "\tleal %d(%%edx), %%ebx\n", (int)sizeof(STACK16FRAME)-22 );
output( "\tleal -4(%%esp), %%ebp\n" );
fprintf( outfile, "\tcall *%d(%%edx)\n", STACK16OFFSET(entry_point) );
output( "\tcall *%d(%%edx)\n", STACK16OFFSET(entry_point) );
/* Switch stack back */
fprintf( outfile, "\t.byte 0x64\n\tmovw (%d), %%ss\n", STACKOFFSET+2 );
fprintf( outfile, "\t.byte 0x64\n\tmovzwl (%d), %%esp\n", STACKOFFSET );
fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
output( "\t.byte 0x64\n\tmovw (%d), %%ss\n", STACKOFFSET+2 );
output( "\t.byte 0x64\n\tmovzwl (%d), %%esp\n", STACKOFFSET );
output( "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
/* Restore registers and return directly to caller */
fprintf( outfile, "\taddl $8, %%esp\n" );
fprintf( outfile, "\tpopl %%ebp\n" );
fprintf( outfile, "\tpopw %%ds\n" );
fprintf( outfile, "\tpopw %%es\n" );
fprintf( outfile, "\tpopw %%fs\n" );
fprintf( outfile, "\tpopw %%gs\n" );
fprintf( outfile, "\taddl $20, %%esp\n" );
fprintf( outfile, "\txorb %%ch, %%ch\n" );
fprintf( outfile, "\tpopl %%ebx\n" );
fprintf( outfile, "\taddw %%cx, %%sp\n" );
fprintf( outfile, "\tpush %%ebx\n" );
fprintf( outfile, "\t.byte 0x66\n" );
fprintf( outfile, "\tlret\n" );
output( "\taddl $8, %%esp\n" );
output( "\tpopl %%ebp\n" );
output( "\tpopw %%ds\n" );
output( "\tpopw %%es\n" );
output( "\tpopw %%fs\n" );
output( "\tpopw %%gs\n" );
output( "\taddl $20, %%esp\n" );
output( "\txorb %%ch, %%ch\n" );
output( "\tpopl %%ebx\n" );
output( "\taddw %%cx, %%sp\n" );
output( "\tpush %%ebx\n" );
output( "\t.byte 0x66\n" );
output( "\tlret\n" );
return;
}
......@@ -243,132 +242,131 @@ static void BuildCallFrom16Core( FILE *outfile, int reg_func, int thunk )
/* Build register CONTEXT */
if ( reg_func )
{
fprintf( outfile, "\tsubl $%d, %%esp\n", (int)sizeof(CONTEXT86) );
fprintf( outfile, "\tmovl %%ecx, %d(%%esp)\n", CONTEXTOFFSET(EFlags) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Eax) );
fprintf( outfile, "\tmovl %%ebx, %d(%%esp)\n", CONTEXTOFFSET(Ebx) );
fprintf( outfile, "\tmovl %%esi, %d(%%esp)\n", CONTEXTOFFSET(Esi) );
fprintf( outfile, "\tmovl %%edi, %d(%%esp)\n", CONTEXTOFFSET(Edi) );
fprintf( outfile, "\tmovl %d(%%edx), %%eax\n", STACK16OFFSET(ebp) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Ebp) );
fprintf( outfile, "\tmovl %d(%%edx), %%eax\n", STACK16OFFSET(ecx) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Ecx) );
fprintf( outfile, "\tmovl %d(%%edx), %%eax\n", STACK16OFFSET(edx) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Edx) );
fprintf( outfile, "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(ds) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegDs) );
fprintf( outfile, "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(es) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegEs) );
fprintf( outfile, "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(fs) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegFs) );
fprintf( outfile, "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(gs) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegGs) );
fprintf( outfile, "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(cs) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegCs) );
fprintf( outfile, "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(ip) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Eip) );
fprintf( outfile, "\t.byte 0x64\n\tmovzwl (%d), %%eax\n", STACKOFFSET+2 );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegSs) );
fprintf( outfile, "\t.byte 0x64\n\tmovzwl (%d), %%eax\n", STACKOFFSET );
fprintf( outfile, "\taddl $%d, %%eax\n", STACK16OFFSET(ip) );
fprintf( outfile, "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Esp) );
output( "\tsubl $%d, %%esp\n", (int)sizeof(CONTEXT86) );
output( "\tmovl %%ecx, %d(%%esp)\n", CONTEXTOFFSET(EFlags) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Eax) );
output( "\tmovl %%ebx, %d(%%esp)\n", CONTEXTOFFSET(Ebx) );
output( "\tmovl %%esi, %d(%%esp)\n", CONTEXTOFFSET(Esi) );
output( "\tmovl %%edi, %d(%%esp)\n", CONTEXTOFFSET(Edi) );
output( "\tmovl %d(%%edx), %%eax\n", STACK16OFFSET(ebp) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Ebp) );
output( "\tmovl %d(%%edx), %%eax\n", STACK16OFFSET(ecx) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Ecx) );
output( "\tmovl %d(%%edx), %%eax\n", STACK16OFFSET(edx) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Edx) );
output( "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(ds) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegDs) );
output( "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(es) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegEs) );
output( "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(fs) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegFs) );
output( "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(gs) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegGs) );
output( "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(cs) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegCs) );
output( "\tmovzwl %d(%%edx), %%eax\n", STACK16OFFSET(ip) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Eip) );
output( "\t.byte 0x64\n\tmovzwl (%d), %%eax\n", STACKOFFSET+2 );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(SegSs) );
output( "\t.byte 0x64\n\tmovzwl (%d), %%eax\n", STACKOFFSET );
output( "\taddl $%d, %%eax\n", STACK16OFFSET(ip) );
output( "\tmovl %%eax, %d(%%esp)\n", CONTEXTOFFSET(Esp) );
#if 0
fprintf( outfile, "\tfsave %d(%%esp)\n", CONTEXTOFFSET(FloatSave) );
output( "\tfsave %d(%%esp)\n", CONTEXTOFFSET(FloatSave) );
#endif
/* Push address of CONTEXT86 structure -- popped by the relay routine */
fprintf( outfile, "\tmovl %%esp,%%eax\n" );
fprintf( outfile, "\tandl $~15,%%esp\n" );
fprintf( outfile, "\tsubl $4,%%esp\n" );
fprintf( outfile, "\tpushl %%eax\n" );
output( "\tmovl %%esp,%%eax\n" );
output( "\tandl $~15,%%esp\n" );
output( "\tsubl $4,%%esp\n" );
output( "\tpushl %%eax\n" );
}
else
{
fprintf( outfile, "\tsubl $8,%%esp\n" );
fprintf( outfile, "\tandl $~15,%%esp\n" );
fprintf( outfile, "\taddl $8,%%esp\n" );
output( "\tsubl $8,%%esp\n" );
output( "\tandl $~15,%%esp\n" );
output( "\taddl $8,%%esp\n" );
}
/* Call relay routine (which will call the API entry point) */
fprintf( outfile, "\tleal %d(%%edx), %%eax\n", (int)sizeof(STACK16FRAME) );
fprintf( outfile, "\tpushl %%eax\n" );
fprintf( outfile, "\tpushl %d(%%edx)\n", STACK16OFFSET(entry_point) );
fprintf( outfile, "\tcall *%d(%%edx)\n", STACK16OFFSET(relay) );
output( "\tleal %d(%%edx), %%eax\n", (int)sizeof(STACK16FRAME) );
output( "\tpushl %%eax\n" );
output( "\tpushl %d(%%edx)\n", STACK16OFFSET(entry_point) );
output( "\tcall *%d(%%edx)\n", STACK16OFFSET(relay) );
if ( reg_func )
{
fprintf( outfile, "\tleal -%d(%%ebp), %%ebx\n",
(int)sizeof(CONTEXT) + STACK32OFFSET(ebp) );
output( "\tleal -%d(%%ebp), %%ebx\n", (int)sizeof(CONTEXT) + STACK32OFFSET(ebp) );
/* Switch stack back */
fprintf( outfile, "\t.byte 0x64\n\tmovw (%d), %%ss\n", STACKOFFSET+2 );
fprintf( outfile, "\t.byte 0x64\n\tmovzwl (%d), %%esp\n", STACKOFFSET );
fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
output( "\t.byte 0x64\n\tmovw (%d), %%ss\n", STACKOFFSET+2 );
output( "\t.byte 0x64\n\tmovzwl (%d), %%esp\n", STACKOFFSET );
output( "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
/* Get return address to CallFrom16 stub */
fprintf( outfile, "\taddw $%d, %%sp\n", STACK16OFFSET(callfrom_ip)-4 );
fprintf( outfile, "\tpopl %%eax\n" );
fprintf( outfile, "\tpopl %%edx\n" );
output( "\taddw $%d, %%sp\n", STACK16OFFSET(callfrom_ip)-4 );
output( "\tpopl %%eax\n" );
output( "\tpopl %%edx\n" );
/* Restore all registers from CONTEXT */
fprintf( outfile, "\tmovw %d(%%ebx), %%ss\n", CONTEXTOFFSET(SegSs) );
fprintf( outfile, "\tmovl %d(%%ebx), %%esp\n", CONTEXTOFFSET(Esp) );
fprintf( outfile, "\taddl $4, %%esp\n" ); /* room for final return address */
fprintf( outfile, "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(SegCs) );
fprintf( outfile, "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(Eip) );
fprintf( outfile, "\tpushl %%edx\n" );
fprintf( outfile, "\tpushl %%eax\n" );
fprintf( outfile, "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(EFlags) );
fprintf( outfile, "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegDs) );
fprintf( outfile, "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegEs) );
fprintf( outfile, "\tpopl %%es\n" );
fprintf( outfile, "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegFs) );
fprintf( outfile, "\tpopl %%fs\n" );
fprintf( outfile, "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegGs) );
fprintf( outfile, "\tpopl %%gs\n" );
fprintf( outfile, "\tmovl %d(%%ebx), %%ebp\n", CONTEXTOFFSET(Ebp) );
fprintf( outfile, "\tmovl %d(%%ebx), %%esi\n", CONTEXTOFFSET(Esi) );
fprintf( outfile, "\tmovl %d(%%ebx), %%edi\n", CONTEXTOFFSET(Edi) );
fprintf( outfile, "\tmovl %d(%%ebx), %%eax\n", CONTEXTOFFSET(Eax) );
fprintf( outfile, "\tmovl %d(%%ebx), %%edx\n", CONTEXTOFFSET(Edx) );
fprintf( outfile, "\tmovl %d(%%ebx), %%ecx\n", CONTEXTOFFSET(Ecx) );
fprintf( outfile, "\tmovl %d(%%ebx), %%ebx\n", CONTEXTOFFSET(Ebx) );
fprintf( outfile, "\tpopl %%ds\n" );
fprintf( outfile, "\tpopfl\n" );
fprintf( outfile, "\tlret\n" );
output( "\tmovw %d(%%ebx), %%ss\n", CONTEXTOFFSET(SegSs) );
output( "\tmovl %d(%%ebx), %%esp\n", CONTEXTOFFSET(Esp) );
output( "\taddl $4, %%esp\n" ); /* room for final return address */
output( "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(SegCs) );
output( "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(Eip) );
output( "\tpushl %%edx\n" );
output( "\tpushl %%eax\n" );
output( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(EFlags) );
output( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegDs) );
output( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegEs) );
output( "\tpopl %%es\n" );
output( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegFs) );
output( "\tpopl %%fs\n" );
output( "\tpushl %d(%%ebx)\n", CONTEXTOFFSET(SegGs) );
output( "\tpopl %%gs\n" );
output( "\tmovl %d(%%ebx), %%ebp\n", CONTEXTOFFSET(Ebp) );
output( "\tmovl %d(%%ebx), %%esi\n", CONTEXTOFFSET(Esi) );
output( "\tmovl %d(%%ebx), %%edi\n", CONTEXTOFFSET(Edi) );
output( "\tmovl %d(%%ebx), %%eax\n", CONTEXTOFFSET(Eax) );
output( "\tmovl %d(%%ebx), %%edx\n", CONTEXTOFFSET(Edx) );
output( "\tmovl %d(%%ebx), %%ecx\n", CONTEXTOFFSET(Ecx) );
output( "\tmovl %d(%%ebx), %%ebx\n", CONTEXTOFFSET(Ebx) );
output( "\tpopl %%ds\n" );
output( "\tpopfl\n" );
output( "\tlret\n" );
}
else
{
/* Switch stack back */
fprintf( outfile, "\t.byte 0x64\n\tmovw (%d), %%ss\n", STACKOFFSET+2 );
fprintf( outfile, "\t.byte 0x64\n\tmovzwl (%d), %%esp\n", STACKOFFSET );
fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
output( "\t.byte 0x64\n\tmovw (%d), %%ss\n", STACKOFFSET+2 );
output( "\t.byte 0x64\n\tmovzwl (%d), %%esp\n", STACKOFFSET );
output( "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
/* Restore registers */
fprintf( outfile, "\tpopl %%edx\n" );
fprintf( outfile, "\tpopl %%ecx\n" );
fprintf( outfile, "\tpopl %%ebp\n" );
fprintf( outfile, "\tpopw %%ds\n" );
fprintf( outfile, "\tpopw %%es\n" );
fprintf( outfile, "\tpopw %%fs\n" );
fprintf( outfile, "\tpopw %%gs\n" );
output( "\tpopl %%edx\n" );
output( "\tpopl %%ecx\n" );
output( "\tpopl %%ebp\n" );
output( "\tpopw %%ds\n" );
output( "\tpopw %%es\n" );
output( "\tpopw %%fs\n" );
output( "\tpopw %%gs\n" );
/* Return to return stub which will return to caller */
fprintf( outfile, "\tlret $12\n" );
output( "\tlret $12\n" );
}
if (thunk) output_function_size( outfile, "__wine_call_from_16_thunk" );
else if (reg_func) output_function_size( outfile, "__wine_call_from_16_regs" );
else output_function_size( outfile, "__wine_call_from_16" );
if (thunk) output_function_size( "__wine_call_from_16_thunk" );
else if (reg_func) output_function_size( "__wine_call_from_16_regs" );
else output_function_size( "__wine_call_from_16" );
}
......@@ -391,44 +389,44 @@ static void BuildCallFrom16Core( FILE *outfile, int reg_func, int thunk )
* or else set to default values. The target routine address is either
* given directly or taken from the CONTEXT86.
*/
static void BuildCallTo16Core( FILE *outfile, int reg_func )
static void BuildCallTo16Core( int reg_func )
{
const char *name = reg_func ? "wine_call_to_16_regs" : "wine_call_to_16";
/* Function header */
function_header( outfile, name );
function_header( name );
/* Function entry sequence */
fprintf( outfile, "\tpushl %%ebp\n" );
fprintf( outfile, "\tmovl %%esp, %%ebp\n" );
output( "\tpushl %%ebp\n" );
output( "\tmovl %%esp, %%ebp\n" );
/* Save the 32-bit registers */
fprintf( outfile, "\tpushl %%ebx\n" );
fprintf( outfile, "\tpushl %%esi\n" );
fprintf( outfile, "\tpushl %%edi\n" );
fprintf( outfile, "\t.byte 0x64\n\tmov %%gs,(%d)\n", GS_OFFSET );
output( "\tpushl %%ebx\n" );
output( "\tpushl %%esi\n" );
output( "\tpushl %%edi\n" );
output( "\t.byte 0x64\n\tmov %%gs,(%d)\n", GS_OFFSET );
/* Setup exception frame */
fprintf( outfile, "\t.byte 0x64\n\tpushl (%d)\n", STACKOFFSET );
fprintf( outfile, "\tpushl 16(%%ebp)\n" ); /* handler */
fprintf( outfile, "\t.byte 0x64\n\tpushl (0)\n" );
fprintf( outfile, "\t.byte 0x64\n\tmovl %%esp,(0)\n" );
output( "\t.byte 0x64\n\tpushl (%d)\n", STACKOFFSET );
output( "\tpushl 16(%%ebp)\n" ); /* handler */
output( "\t.byte 0x64\n\tpushl (0)\n" );
output( "\t.byte 0x64\n\tmovl %%esp,(0)\n" );
/* Call the actual CallTo16 routine (simulate a lcall) */
fprintf( outfile, "\tpushl %%cs\n" );
fprintf( outfile, "\tcall .L%s\n", name );
output( "\tpushl %%cs\n" );
output( "\tcall .L%s\n", name );
/* Remove exception frame */
fprintf( outfile, "\t.byte 0x64\n\tpopl (0)\n" );
fprintf( outfile, "\taddl $4, %%esp\n" );
fprintf( outfile, "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
output( "\t.byte 0x64\n\tpopl (0)\n" );
output( "\taddl $4, %%esp\n" );
output( "\t.byte 0x64\n\tpopl (%d)\n", STACKOFFSET );
if ( !reg_func )
{
/* Convert return value */
fprintf( outfile, "\tandl $0xffff,%%eax\n" );
fprintf( outfile, "\tshll $16,%%edx\n" );
fprintf( outfile, "\torl %%edx,%%eax\n" );
output( "\tandl $0xffff,%%eax\n" );
output( "\tshll $16,%%edx\n" );
output( "\torl %%edx,%%eax\n" );
}
else
{
......@@ -442,94 +440,94 @@ static void BuildCallTo16Core( FILE *outfile, int reg_func )
* at the cost of a somewhat less efficient return path.]
*/
fprintf( outfile, "\tmovl %d(%%esp), %%edi\n", STACK32OFFSET(target) - STACK32OFFSET(edi));
output( "\tmovl %d(%%esp), %%edi\n", STACK32OFFSET(target) - STACK32OFFSET(edi));
/* everything above edi has been popped already */
fprintf( outfile, "\tmovl %%eax, %d(%%edi)\n", CONTEXTOFFSET(Eax) );
fprintf( outfile, "\tmovl %%ebx, %d(%%edi)\n", CONTEXTOFFSET(Ebx) );
fprintf( outfile, "\tmovl %%ecx, %d(%%edi)\n", CONTEXTOFFSET(Ecx) );
fprintf( outfile, "\tmovl %%edx, %d(%%edi)\n", CONTEXTOFFSET(Edx) );
fprintf( outfile, "\tmovl %%ebp, %d(%%edi)\n", CONTEXTOFFSET(Ebp) );
fprintf( outfile, "\tmovl %%esi, %d(%%edi)\n", CONTEXTOFFSET(Esp) );
output( "\tmovl %%eax, %d(%%edi)\n", CONTEXTOFFSET(Eax) );
output( "\tmovl %%ebx, %d(%%edi)\n", CONTEXTOFFSET(Ebx) );
output( "\tmovl %%ecx, %d(%%edi)\n", CONTEXTOFFSET(Ecx) );
output( "\tmovl %%edx, %d(%%edi)\n", CONTEXTOFFSET(Edx) );
output( "\tmovl %%ebp, %d(%%edi)\n", CONTEXTOFFSET(Ebp) );
output( "\tmovl %%esi, %d(%%edi)\n", CONTEXTOFFSET(Esp) );
/* The return glue code saved %esp into %esi */
}
/* Restore the 32-bit registers */
fprintf( outfile, "\tpopl %%edi\n" );
fprintf( outfile, "\tpopl %%esi\n" );
fprintf( outfile, "\tpopl %%ebx\n" );
output( "\tpopl %%edi\n" );
output( "\tpopl %%esi\n" );
output( "\tpopl %%ebx\n" );
/* Function exit sequence */
fprintf( outfile, "\tpopl %%ebp\n" );
fprintf( outfile, "\tret $12\n" );
output( "\tpopl %%ebp\n" );
output( "\tret $12\n" );
/* Start of the actual CallTo16 routine */
fprintf( outfile, ".L%s:\n", name );
output( ".L%s:\n", name );
/* Switch to the 16-bit stack */
fprintf( outfile, "\tmovl %%esp,%%edx\n" );
fprintf( outfile, "\t.byte 0x64\n\tmovw (%d),%%ss\n", STACKOFFSET + 2);
fprintf( outfile, "\t.byte 0x64\n\tmovw (%d),%%sp\n", STACKOFFSET );
fprintf( outfile, "\t.byte 0x64\n\tmovl %%edx,(%d)\n", STACKOFFSET );
output( "\tmovl %%esp,%%edx\n" );
output( "\t.byte 0x64\n\tmovw (%d),%%ss\n", STACKOFFSET + 2);
output( "\t.byte 0x64\n\tmovw (%d),%%sp\n", STACKOFFSET );
output( "\t.byte 0x64\n\tmovl %%edx,(%d)\n", STACKOFFSET );
/* Make %bp point to the previous stackframe (built by CallFrom16) */
fprintf( outfile, "\tmovzwl %%sp,%%ebp\n" );
fprintf( outfile, "\tleal %d(%%ebp),%%ebp\n", STACK16OFFSET(bp) );
output( "\tmovzwl %%sp,%%ebp\n" );
output( "\tleal %d(%%ebp),%%ebp\n", STACK16OFFSET(bp) );
/* Add the specified offset to the new sp */
fprintf( outfile, "\tsubw %d(%%edx), %%sp\n", STACK32OFFSET(nb_args) );
output( "\tsubw %d(%%edx), %%sp\n", STACK32OFFSET(nb_args) );
if (reg_func)
{
/* Push the called routine address */
fprintf( outfile, "\tmovl %d(%%edx),%%edx\n", STACK32OFFSET(target) );
fprintf( outfile, "\tpushw %d(%%edx)\n", CONTEXTOFFSET(SegCs) );
fprintf( outfile, "\tpushw %d(%%edx)\n", CONTEXTOFFSET(Eip) );
output( "\tmovl %d(%%edx),%%edx\n", STACK32OFFSET(target) );
output( "\tpushw %d(%%edx)\n", CONTEXTOFFSET(SegCs) );
output( "\tpushw %d(%%edx)\n", CONTEXTOFFSET(Eip) );
/* Get the registers */
fprintf( outfile, "\tpushw %d(%%edx)\n", CONTEXTOFFSET(SegDs) );
fprintf( outfile, "\tpushl %d(%%edx)\n", CONTEXTOFFSET(SegEs) );
fprintf( outfile, "\tpopl %%es\n" );
fprintf( outfile, "\tpushl %d(%%edx)\n", CONTEXTOFFSET(SegFs) );
fprintf( outfile, "\tpopl %%fs\n" );
fprintf( outfile, "\tpushl %d(%%edx)\n", CONTEXTOFFSET(SegGs) );
fprintf( outfile, "\tpopl %%gs\n" );
fprintf( outfile, "\tmovl %d(%%edx),%%ebp\n", CONTEXTOFFSET(Ebp) );
fprintf( outfile, "\tmovl %d(%%edx),%%esi\n", CONTEXTOFFSET(Esi) );
fprintf( outfile, "\tmovl %d(%%edx),%%edi\n", CONTEXTOFFSET(Edi) );
fprintf( outfile, "\tmovl %d(%%edx),%%eax\n", CONTEXTOFFSET(Eax) );
fprintf( outfile, "\tmovl %d(%%edx),%%ebx\n", CONTEXTOFFSET(Ebx) );
fprintf( outfile, "\tmovl %d(%%edx),%%ecx\n", CONTEXTOFFSET(Ecx) );
fprintf( outfile, "\tmovl %d(%%edx),%%edx\n", CONTEXTOFFSET(Edx) );
output( "\tpushw %d(%%edx)\n", CONTEXTOFFSET(SegDs) );
output( "\tpushl %d(%%edx)\n", CONTEXTOFFSET(SegEs) );
output( "\tpopl %%es\n" );
output( "\tpushl %d(%%edx)\n", CONTEXTOFFSET(SegFs) );
output( "\tpopl %%fs\n" );
output( "\tpushl %d(%%edx)\n", CONTEXTOFFSET(SegGs) );
output( "\tpopl %%gs\n" );
output( "\tmovl %d(%%edx),%%ebp\n", CONTEXTOFFSET(Ebp) );
output( "\tmovl %d(%%edx),%%esi\n", CONTEXTOFFSET(Esi) );
output( "\tmovl %d(%%edx),%%edi\n", CONTEXTOFFSET(Edi) );
output( "\tmovl %d(%%edx),%%eax\n", CONTEXTOFFSET(Eax) );
output( "\tmovl %d(%%edx),%%ebx\n", CONTEXTOFFSET(Ebx) );
output( "\tmovl %d(%%edx),%%ecx\n", CONTEXTOFFSET(Ecx) );
output( "\tmovl %d(%%edx),%%edx\n", CONTEXTOFFSET(Edx) );
/* Get the 16-bit ds */
fprintf( outfile, "\tpopw %%ds\n" );
output( "\tpopw %%ds\n" );
}
else /* not a register function */
{
/* Push the called routine address */
fprintf( outfile, "\tpushl %d(%%edx)\n", STACK32OFFSET(target) );
output( "\tpushl %d(%%edx)\n", STACK32OFFSET(target) );
/* Set %fs and %gs to the value saved by the last CallFrom16 */
fprintf( outfile, "\tpushw %d(%%ebp)\n", STACK16OFFSET(fs)-STACK16OFFSET(bp) );
fprintf( outfile, "\tpopw %%fs\n" );
fprintf( outfile, "\tpushw %d(%%ebp)\n", STACK16OFFSET(gs)-STACK16OFFSET(bp) );
fprintf( outfile, "\tpopw %%gs\n" );
output( "\tpushw %d(%%ebp)\n", STACK16OFFSET(fs)-STACK16OFFSET(bp) );
output( "\tpopw %%fs\n" );
output( "\tpushw %d(%%ebp)\n", STACK16OFFSET(gs)-STACK16OFFSET(bp) );
output( "\tpopw %%gs\n" );
/* Set %ds and %es (and %ax just in case) equal to %ss */
fprintf( outfile, "\tmovw %%ss,%%ax\n" );
fprintf( outfile, "\tmovw %%ax,%%ds\n" );
fprintf( outfile, "\tmovw %%ax,%%es\n" );
output( "\tmovw %%ss,%%ax\n" );
output( "\tmovw %%ax,%%ds\n" );
output( "\tmovw %%ax,%%es\n" );
}
/* Jump to the called routine */
fprintf( outfile, "\t.byte 0x66\n" );
fprintf( outfile, "\tlret\n" );
output( "\t.byte 0x66\n" );
output( "\tlret\n" );
/* Function footer */
output_function_size( outfile, name );
output_function_size( name );
}
......@@ -538,34 +536,34 @@ static void BuildCallTo16Core( FILE *outfile, int reg_func )
*
* Build the return code for 16-bit callbacks
*/
static void BuildRet16Func( FILE *outfile )
static void BuildRet16Func(void)
{
function_header( outfile, "__wine_call_to_16_ret" );
function_header( "__wine_call_to_16_ret" );
/* Save %esp into %esi */
fprintf( outfile, "\tmovl %%esp,%%esi\n" );
output( "\tmovl %%esp,%%esi\n" );
/* Restore 32-bit segment registers */
fprintf( outfile, "\t.byte 0x2e\n\tmovl %s", asm_name("CallTo16_DataSelector") );
fprintf( outfile, "-%s,%%edi\n", asm_name("__wine_call16_start") );
fprintf( outfile, "\tmovw %%di,%%ds\n" );
fprintf( outfile, "\tmovw %%di,%%es\n" );
output( "\t.byte 0x2e\n\tmovl %s", asm_name("CallTo16_DataSelector") );
output( "-%s,%%edi\n", asm_name("__wine_call16_start") );
output( "\tmovw %%di,%%ds\n" );
output( "\tmovw %%di,%%es\n" );
fprintf( outfile, "\t.byte 0x2e\n\tmov %s", asm_name("CallTo16_TebSelector") );
fprintf( outfile, "-%s,%%fs\n", asm_name("__wine_call16_start") );
output( "\t.byte 0x2e\n\tmov %s", asm_name("CallTo16_TebSelector") );
output( "-%s,%%fs\n", asm_name("__wine_call16_start") );
fprintf( outfile, "\t.byte 0x64\n\tmov (%d),%%gs\n", GS_OFFSET );
output( "\t.byte 0x64\n\tmov (%d),%%gs\n", GS_OFFSET );
/* Restore the 32-bit stack */
fprintf( outfile, "\tmovw %%di,%%ss\n" );
fprintf( outfile, "\t.byte 0x64\n\tmovl (%d),%%esp\n", STACKOFFSET );
output( "\tmovw %%di,%%ss\n" );
output( "\t.byte 0x64\n\tmovl (%d),%%esp\n", STACKOFFSET );
/* Return to caller */
fprintf( outfile, "\tlret\n" );
output_function_size( outfile, "__wine_call_to_16_ret" );
output( "\tlret\n" );
output_function_size( "__wine_call_to_16_ret" );
}
......@@ -659,77 +657,77 @@ static void BuildRet16Func( FILE *outfile )
* (ebp+4) ret addr
* (ebp) ebp
*/
static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
static void BuildCallTo32CBClient( BOOL isEx )
{
function_header( outfile, isEx ? "CALL32_CBClientEx" : "CALL32_CBClient" );
function_header( isEx ? "CALL32_CBClientEx" : "CALL32_CBClient" );
/* Entry code */
fprintf( outfile, "\tpushl %%ebp\n" );
fprintf( outfile, "\tmovl %%esp,%%ebp\n" );
fprintf( outfile, "\tpushl %%edi\n" );
fprintf( outfile, "\tpushl %%esi\n" );
fprintf( outfile, "\tpushl %%ebx\n" );
output( "\tpushl %%ebp\n" );
output( "\tmovl %%esp,%%ebp\n" );
output( "\tpushl %%edi\n" );
output( "\tpushl %%esi\n" );
output( "\tpushl %%ebx\n" );
/* Get pointer to temporary area and save the 32-bit stack pointer */
fprintf( outfile, "\tmovl 16(%%ebp), %%ebx\n" );
fprintf( outfile, "\tleal -8(%%esp), %%eax\n" );
output( "\tmovl 16(%%ebp), %%ebx\n" );
output( "\tleal -8(%%esp), %%eax\n" );
if ( !isEx )
fprintf( outfile, "\tmovl %%eax, -8(%%ebx)\n" );
output( "\tmovl %%eax, -8(%%ebx)\n" );
else
fprintf( outfile, "\tmovl %%eax, 12(%%ebx)\n" );
output( "\tmovl %%eax, 12(%%ebx)\n" );
/* Set up registers and call CBClient relay stub (simulating a far call) */
fprintf( outfile, "\tmovl 20(%%ebp), %%esi\n" );
fprintf( outfile, "\tmovl (%%esi), %%esi\n" );
output( "\tmovl 20(%%ebp), %%esi\n" );
output( "\tmovl (%%esi), %%esi\n" );
fprintf( outfile, "\tmovl 8(%%ebp), %%eax\n" );
fprintf( outfile, "\tmovl 12(%%ebp), %%ebp\n" );
output( "\tmovl 8(%%ebp), %%eax\n" );
output( "\tmovl 12(%%ebp), %%ebp\n" );
fprintf( outfile, "\tpushl %%cs\n" );
fprintf( outfile, "\tcall *%%eax\n" );
output( "\tpushl %%cs\n" );
output( "\tcall *%%eax\n" );
/* Return new esi value to caller */
fprintf( outfile, "\tmovl 32(%%esp), %%edi\n" );
fprintf( outfile, "\tmovl %%esi, (%%edi)\n" );
output( "\tmovl 32(%%esp), %%edi\n" );
output( "\tmovl %%esi, (%%edi)\n" );
/* Return argument size to caller */
if ( isEx )
{
fprintf( outfile, "\tmovl 36(%%esp), %%ebx\n" );
fprintf( outfile, "\tmovl %%ebp, (%%ebx)\n" );
output( "\tmovl 36(%%esp), %%ebx\n" );
output( "\tmovl %%ebp, (%%ebx)\n" );
}
/* Restore registers and return */
fprintf( outfile, "\tpopl %%ebx\n" );
fprintf( outfile, "\tpopl %%esi\n" );
fprintf( outfile, "\tpopl %%edi\n" );
fprintf( outfile, "\tpopl %%ebp\n" );
fprintf( outfile, "\tret\n" );
output_function_size( outfile, isEx ? "CALL32_CBClientEx" : "CALL32_CBClient" );
output( "\tpopl %%ebx\n" );
output( "\tpopl %%esi\n" );
output( "\tpopl %%edi\n" );
output( "\tpopl %%ebp\n" );
output( "\tret\n" );
output_function_size( isEx ? "CALL32_CBClientEx" : "CALL32_CBClient" );
/* '16-bit' return stub */
function_header( outfile, isEx ? "CALL32_CBClientEx_Ret" : "CALL32_CBClient_Ret" );
function_header( isEx ? "CALL32_CBClientEx_Ret" : "CALL32_CBClient_Ret" );
if ( !isEx )
{
fprintf( outfile, "\tmovzwl %%sp, %%ebx\n" );
fprintf( outfile, "\tlssl %%ss:-16(%%ebx), %%esp\n" );
output( "\tmovzwl %%sp, %%ebx\n" );
output( "\tlssl %%ss:-16(%%ebx), %%esp\n" );
}
else
{
fprintf( outfile, "\tmovzwl %%bp, %%ebx\n" );
fprintf( outfile, "\tsubw %%bp, %%sp\n" );
fprintf( outfile, "\tmovzwl %%sp, %%ebp\n" );
fprintf( outfile, "\tlssl %%ss:-12(%%ebx), %%esp\n" );
output( "\tmovzwl %%bp, %%ebx\n" );
output( "\tsubw %%bp, %%sp\n" );
output( "\tmovzwl %%sp, %%ebp\n" );
output( "\tlssl %%ss:-12(%%ebx), %%esp\n" );
}
fprintf( outfile, "\tlret\n" );
output_function_size( outfile, isEx ? "CALL32_CBClientEx_Ret" : "CALL32_CBClient_Ret" );
output( "\tlret\n" );
output_function_size( isEx ? "CALL32_CBClientEx_Ret" : "CALL32_CBClient_Ret" );
}
......@@ -758,114 +756,114 @@ static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
* pointer on return (with the return address and arguments already
* removed).
*/
static void BuildCallFrom32Regs( FILE *outfile )
static void BuildCallFrom32Regs(void)
{
static const int STACK_SPACE = 128 + sizeof(CONTEXT86);
/* Function header */
function_header( outfile, "__wine_call_from_32_regs" );
function_header( "__wine_call_from_32_regs" );
/* Allocate some buffer space on the stack */
fprintf( outfile, "\tpushl %%ebp\n" );
fprintf( outfile, "\tmovl %%esp,%%ebp\n ");
fprintf( outfile, "\tleal -%d(%%esp), %%esp\n", STACK_SPACE + 4 /* for context arg */);
output( "\tpushl %%ebp\n" );
output( "\tmovl %%esp,%%ebp\n ");
output( "\tleal -%d(%%esp), %%esp\n", STACK_SPACE + 4 /* for context arg */);
/* Build the context structure */
fprintf( outfile, "\tpushfl\n" );
fprintf( outfile, "\tpopl %%eax\n" );
fprintf( outfile, "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(EFlags) - STACK_SPACE );
fprintf( outfile, "\tmovl 0(%%ebp),%%eax\n" );
fprintf( outfile, "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Ebp) - STACK_SPACE );
fprintf( outfile, "\tmovl 8(%%ebp),%%eax\n" );
fprintf( outfile, "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Eax) - STACK_SPACE );
fprintf( outfile, "\tmovl %%ebx,%d(%%ebp)\n", CONTEXTOFFSET(Ebx) - STACK_SPACE );
fprintf( outfile, "\tmovl %%ecx,%d(%%ebp)\n", CONTEXTOFFSET(Ecx) - STACK_SPACE );
fprintf( outfile, "\tmovl %%edx,%d(%%ebp)\n", CONTEXTOFFSET(Edx) - STACK_SPACE );
fprintf( outfile, "\tmovl %%esi,%d(%%ebp)\n", CONTEXTOFFSET(Esi) - STACK_SPACE );
fprintf( outfile, "\tmovl %%edi,%d(%%ebp)\n", CONTEXTOFFSET(Edi) - STACK_SPACE );
fprintf( outfile, "\txorl %%eax,%%eax\n" );
fprintf( outfile, "\tmovw %%cs,%%ax\n" );
fprintf( outfile, "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegCs) - STACK_SPACE );
fprintf( outfile, "\tmovw %%es,%%ax\n" );
fprintf( outfile, "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegEs) - STACK_SPACE );
fprintf( outfile, "\tmovw %%fs,%%ax\n" );
fprintf( outfile, "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegFs) - STACK_SPACE );
fprintf( outfile, "\tmovw %%gs,%%ax\n" );
fprintf( outfile, "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegGs) - STACK_SPACE );
fprintf( outfile, "\tmovw %%ss,%%ax\n" );
fprintf( outfile, "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegSs) - STACK_SPACE );
fprintf( outfile, "\tmovw %%ds,%%ax\n" );
fprintf( outfile, "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegDs) - STACK_SPACE );
fprintf( outfile, "\tmovw %%ax,%%es\n" ); /* set %es equal to %ds just in case */
fprintf( outfile, "\tmovl $0x%x,%%eax\n", CONTEXT86_FULL );
fprintf( outfile, "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(ContextFlags) - STACK_SPACE );
fprintf( outfile, "\tmovl 12(%%ebp),%%eax\n" ); /* Get %eip at time of call */
fprintf( outfile, "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Eip) - STACK_SPACE );
output( "\tpushfl\n" );
output( "\tpopl %%eax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(EFlags) - STACK_SPACE );
output( "\tmovl 0(%%ebp),%%eax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Ebp) - STACK_SPACE );
output( "\tmovl 8(%%ebp),%%eax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Eax) - STACK_SPACE );
output( "\tmovl %%ebx,%d(%%ebp)\n", CONTEXTOFFSET(Ebx) - STACK_SPACE );
output( "\tmovl %%ecx,%d(%%ebp)\n", CONTEXTOFFSET(Ecx) - STACK_SPACE );
output( "\tmovl %%edx,%d(%%ebp)\n", CONTEXTOFFSET(Edx) - STACK_SPACE );
output( "\tmovl %%esi,%d(%%ebp)\n", CONTEXTOFFSET(Esi) - STACK_SPACE );
output( "\tmovl %%edi,%d(%%ebp)\n", CONTEXTOFFSET(Edi) - STACK_SPACE );
output( "\txorl %%eax,%%eax\n" );
output( "\tmovw %%cs,%%ax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegCs) - STACK_SPACE );
output( "\tmovw %%es,%%ax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegEs) - STACK_SPACE );
output( "\tmovw %%fs,%%ax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegFs) - STACK_SPACE );
output( "\tmovw %%gs,%%ax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegGs) - STACK_SPACE );
output( "\tmovw %%ss,%%ax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegSs) - STACK_SPACE );
output( "\tmovw %%ds,%%ax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(SegDs) - STACK_SPACE );
output( "\tmovw %%ax,%%es\n" ); /* set %es equal to %ds just in case */
output( "\tmovl $0x%x,%%eax\n", CONTEXT86_FULL );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(ContextFlags) - STACK_SPACE );
output( "\tmovl 12(%%ebp),%%eax\n" ); /* Get %eip at time of call */
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Eip) - STACK_SPACE );
/* Transfer the arguments */
fprintf( outfile, "\tmovl 4(%%ebp),%%ebx\n" ); /* get relay code addr */
fprintf( outfile, "\tmovzbl 4(%%ebx),%%ecx\n" ); /* fetch number of args to copy */
fprintf( outfile, "\tsubl %%ecx,%%esp\n" );
fprintf( outfile, "\tandl $~15,%%esp\n" );
fprintf( outfile, "\tleal 16(%%ebp),%%esi\n" ); /* get %esp at time of call */
fprintf( outfile, "\tmovl %%esp,%%edi\n" );
fprintf( outfile, "\tshrl $2,%%ecx\n" );
fprintf( outfile, "\tjz 1f\n" );
fprintf( outfile, "\tcld\n" );
fprintf( outfile, "\trep\n\tmovsl\n" ); /* copy args */
fprintf( outfile, "1:\tleal %d(%%ebp),%%eax\n", -STACK_SPACE ); /* get addr of context struct */
fprintf( outfile, "\tmovl %%eax,(%%edi)\n" ); /* and pass it as extra arg */
fprintf( outfile, "\tmovzbl 5(%%ebx),%%eax\n" ); /* fetch number of args to remove */
fprintf( outfile, "\tleal 16(%%ebp,%%eax),%%eax\n" );
fprintf( outfile, "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Esp) - STACK_SPACE );
output( "\tmovl 4(%%ebp),%%ebx\n" ); /* get relay code addr */
output( "\tmovzbl 4(%%ebx),%%ecx\n" ); /* fetch number of args to copy */
output( "\tsubl %%ecx,%%esp\n" );
output( "\tandl $~15,%%esp\n" );
output( "\tleal 16(%%ebp),%%esi\n" ); /* get %esp at time of call */
output( "\tmovl %%esp,%%edi\n" );
output( "\tshrl $2,%%ecx\n" );
output( "\tjz 1f\n" );
output( "\tcld\n" );
output( "\trep\n\tmovsl\n" ); /* copy args */
output( "1:\tleal %d(%%ebp),%%eax\n", -STACK_SPACE ); /* get addr of context struct */
output( "\tmovl %%eax,(%%edi)\n" ); /* and pass it as extra arg */
output( "\tmovzbl 5(%%ebx),%%eax\n" ); /* fetch number of args to remove */
output( "\tleal 16(%%ebp,%%eax),%%eax\n" );
output( "\tmovl %%eax,%d(%%ebp)\n", CONTEXTOFFSET(Esp) - STACK_SPACE );
/* Call the entry point */
fprintf( outfile, "\taddl (%%ebx),%%ebx\n" );
fprintf( outfile, "\tcall *%%ebx\n" );
fprintf( outfile, "\tleal -%d(%%ebp),%%ecx\n", STACK_SPACE );
output( "\taddl (%%ebx),%%ebx\n" );
output( "\tcall *%%ebx\n" );
output( "\tleal -%d(%%ebp),%%ecx\n", STACK_SPACE );
/* Restore the context structure */
fprintf( outfile, "2:\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegEs) );
fprintf( outfile, "\tpopl %%es\n" );
fprintf( outfile, "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegFs) );
fprintf( outfile, "\tpopl %%fs\n" );
fprintf( outfile, "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegGs) );
fprintf( outfile, "\tpopl %%gs\n" );
fprintf( outfile, "\tmovl %d(%%ecx),%%edi\n", CONTEXTOFFSET(Edi) );
fprintf( outfile, "\tmovl %d(%%ecx),%%esi\n", CONTEXTOFFSET(Esi) );
fprintf( outfile, "\tmovl %d(%%ecx),%%edx\n", CONTEXTOFFSET(Edx) );
fprintf( outfile, "\tmovl %d(%%ecx),%%ebx\n", CONTEXTOFFSET(Ebx) );
fprintf( outfile, "\tmovl %d(%%ecx),%%eax\n", CONTEXTOFFSET(Eax) );
fprintf( outfile, "\tmovl %d(%%ecx),%%ebp\n", CONTEXTOFFSET(Ebp) );
fprintf( outfile, "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegSs) );
fprintf( outfile, "\tpopl %%ss\n" );
fprintf( outfile, "\tmovl %d(%%ecx),%%esp\n", CONTEXTOFFSET(Esp) );
fprintf( outfile, "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(EFlags) );
fprintf( outfile, "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegCs) );
fprintf( outfile, "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(Eip) );
fprintf( outfile, "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegDs) );
fprintf( outfile, "\tmovl %d(%%ecx),%%ecx\n", CONTEXTOFFSET(Ecx) );
fprintf( outfile, "\tpopl %%ds\n" );
fprintf( outfile, "\tiret\n" );
output_function_size( outfile, "__wine_call_from_32_regs" );
function_header( outfile, "__wine_call_from_32_restore_regs" );
fprintf( outfile, "\tmovl 4(%%esp),%%ecx\n" );
fprintf( outfile, "\tjmp 2b\n" );
output_function_size( outfile, "__wine_call_from_32_restore_regs" );
output( "2:\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegEs) );
output( "\tpopl %%es\n" );
output( "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegFs) );
output( "\tpopl %%fs\n" );
output( "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegGs) );
output( "\tpopl %%gs\n" );
output( "\tmovl %d(%%ecx),%%edi\n", CONTEXTOFFSET(Edi) );
output( "\tmovl %d(%%ecx),%%esi\n", CONTEXTOFFSET(Esi) );
output( "\tmovl %d(%%ecx),%%edx\n", CONTEXTOFFSET(Edx) );
output( "\tmovl %d(%%ecx),%%ebx\n", CONTEXTOFFSET(Ebx) );
output( "\tmovl %d(%%ecx),%%eax\n", CONTEXTOFFSET(Eax) );
output( "\tmovl %d(%%ecx),%%ebp\n", CONTEXTOFFSET(Ebp) );
output( "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegSs) );
output( "\tpopl %%ss\n" );
output( "\tmovl %d(%%ecx),%%esp\n", CONTEXTOFFSET(Esp) );
output( "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(EFlags) );
output( "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegCs) );
output( "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(Eip) );
output( "\tpushl %d(%%ecx)\n", CONTEXTOFFSET(SegDs) );
output( "\tmovl %d(%%ecx),%%ecx\n", CONTEXTOFFSET(Ecx) );
output( "\tpopl %%ds\n" );
output( "\tiret\n" );
output_function_size( "__wine_call_from_32_regs" );
function_header( "__wine_call_from_32_restore_regs" );
output( "\tmovl 4(%%esp),%%ecx\n" );
output( "\tjmp 2b\n" );
output_function_size( "__wine_call_from_32_restore_regs" );
}
......@@ -885,38 +883,34 @@ static void BuildCallFrom32Regs( FILE *outfile )
* On entry to function, fs register points to a valid TEB.
* On exit from function, stack will be popped.
*/
static void BuildPendingEventCheck( FILE *outfile )
static void BuildPendingEventCheck(void)
{
/* Function header */
function_header( outfile, "DPMI_PendingEventCheck" );
function_header( "DPMI_PendingEventCheck" );
/* Check for pending events. */
fprintf( outfile, "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n",
STRUCTOFFSET(TEB,vm86_pending) );
fprintf( outfile, "\tje %s\n", asm_name("DPMI_PendingEventCheck_Cleanup") );
fprintf( outfile, "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n",
STRUCTOFFSET(TEB,dpmi_vif) );
fprintf( outfile, "\tje %s\n", asm_name("DPMI_PendingEventCheck_Cleanup") );
output( "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n", STRUCTOFFSET(TEB,vm86_pending) );
output( "\tje %s\n", asm_name("DPMI_PendingEventCheck_Cleanup") );
output( "\t.byte 0x64\n\ttestl $0xffffffff,(%d)\n", STRUCTOFFSET(TEB,dpmi_vif) );
output( "\tje %s\n", asm_name("DPMI_PendingEventCheck_Cleanup") );
/* Process pending events. */
fprintf( outfile, "\tsti\n" );
output( "\tsti\n" );
/* Start cleanup. Restore fs register. */
fprintf( outfile, "%s\n", asm_globl("DPMI_PendingEventCheck_Cleanup") );
fprintf( outfile, "\tpopw %%fs\n" );
output( "%s\n", asm_globl("DPMI_PendingEventCheck_Cleanup") );
output( "\tpopw %%fs\n" );
/* Return from function. */
fprintf( outfile, "%s\n", asm_globl("DPMI_PendingEventCheck_Return") );
fprintf( outfile, "\tiret\n" );
output( "%s\n", asm_globl("DPMI_PendingEventCheck_Return") );
output( "\tiret\n" );
output_function_size( outfile, "DPMI_PendingEventCheck" );
output_function_size( "DPMI_PendingEventCheck" );
}
......@@ -925,59 +919,59 @@ static void BuildPendingEventCheck( FILE *outfile )
*
* Build all the 16-bit relay callbacks
*/
void BuildRelays16( FILE *outfile )
void BuildRelays16(void)
{
if (target_cpu != CPU_x86)
{
fprintf( outfile, "/* File not used with this architecture. Do not edit! */\n\n" );
output( "/* File not used with this architecture. Do not edit! */\n\n" );
return;
}
/* File header */
fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
fprintf( outfile, "\t.text\n" );
output( "/* File generated automatically. Do not edit! */\n\n" );
output( "\t.text\n" );
fprintf( outfile, "%s:\n\n", asm_name("__wine_spec_thunk_text_16") );
output( "%s:\n\n", asm_name("__wine_spec_thunk_text_16") );
fprintf( outfile, "%s\n", asm_globl("__wine_call16_start") );
output( "%s\n", asm_globl("__wine_call16_start") );
/* Standard CallFrom16 routine */
BuildCallFrom16Core( outfile, FALSE, FALSE );
BuildCallFrom16Core( FALSE, FALSE );
/* Register CallFrom16 routine */
BuildCallFrom16Core( outfile, TRUE, FALSE );
BuildCallFrom16Core( TRUE, FALSE );
/* C16ThkSL CallFrom16 routine */
BuildCallFrom16Core( outfile, FALSE, TRUE );
BuildCallFrom16Core( FALSE, TRUE );
/* Standard CallTo16 routine */
BuildCallTo16Core( outfile, 0 );
BuildCallTo16Core( 0 );
/* Register CallTo16 routine */
BuildCallTo16Core( outfile, 1 );
BuildCallTo16Core( 1 );
/* Standard CallTo16 return stub */
BuildRet16Func( outfile );
BuildRet16Func();
/* CBClientThunkSL routine */
BuildCallTo32CBClient( outfile, FALSE );
BuildCallTo32CBClient( FALSE );
/* CBClientThunkSLEx routine */
BuildCallTo32CBClient( outfile, TRUE );
BuildCallTo32CBClient( TRUE );
/* Pending DPMI events check stub */
BuildPendingEventCheck( outfile );
BuildPendingEventCheck();
fprintf( outfile, "%s\n", asm_globl("__wine_call16_end") );
output_function_size( outfile, "__wine_spec_thunk_text_16" );
output( "%s\n", asm_globl("__wine_call16_end") );
output_function_size( "__wine_spec_thunk_text_16" );
/* Declare the return address and data selector variables */
fprintf( outfile, "\n\t.data\n\t.align %d\n", get_alignment(4) );
fprintf( outfile, "%s\n\t.long 0\n", asm_globl("CallTo16_DataSelector") );
fprintf( outfile, "%s\n\t.long 0\n", asm_globl("CallTo16_TebSelector") );
if (UsePIC) fprintf( outfile, "wine_ldt_copy_ptr:\t.long %s\n", asm_name("wine_ldt_copy") );
output_gnu_stack_note( outfile );
output( "\n\t.data\n\t.align %d\n", get_alignment(4) );
output( "%s\n\t.long 0\n", asm_globl("CallTo16_DataSelector") );
output( "%s\n\t.long 0\n", asm_globl("CallTo16_TebSelector") );
if (UsePIC) output( "wine_ldt_copy_ptr:\t.long %s\n", asm_name("wine_ldt_copy") );
output_gnu_stack_note();
}
/*******************************************************************
......@@ -985,23 +979,23 @@ void BuildRelays16( FILE *outfile )
*
* Build all the 32-bit relay callbacks
*/
void BuildRelays32( FILE *outfile )
void BuildRelays32(void)
{
if (target_cpu != CPU_x86)
{
fprintf( outfile, "/* File not used with this architecture. Do not edit! */\n\n" );
output( "/* File not used with this architecture. Do not edit! */\n\n" );
return;
}
/* File header */
fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
fprintf( outfile, "\t.text\n" );
fprintf( outfile, "%s:\n\n", asm_name("__wine_spec_thunk_text_32") );
output( "/* File generated automatically. Do not edit! */\n\n" );
output( "\t.text\n" );
output( "%s:\n\n", asm_name("__wine_spec_thunk_text_32") );
/* 32-bit register entry point */
BuildCallFrom32Regs( outfile );
BuildCallFrom32Regs();
output_function_size( outfile, "__wine_spec_thunk_text_32" );
output_gnu_stack_note( outfile );
output_function_size( "__wine_spec_thunk_text_32" );
output_gnu_stack_note();
}
......@@ -242,16 +242,16 @@ static void free_resource_tree( struct res_tree *tree )
}
/* output a string preceded by its length */
static void output_string( FILE *outfile, const char *str )
static void output_string( const char *str )
{
unsigned int i, len = strlen(str);
fprintf( outfile, "\t.byte 0x%02x", len );
for (i = 0; i < len; i++) fprintf( outfile, ",0x%02x", (unsigned char)str[i] );
fprintf( outfile, " /* %s */\n", str );
output( "\t.byte 0x%02x", len );
for (i = 0; i < len; i++) output( ",0x%02x", (unsigned char)str[i] );
output( " /* %s */\n", str );
}
/* output the resource data */
void output_res16_data( FILE *outfile, DLLSPEC *spec )
void output_res16_data( DLLSPEC *spec )
{
const struct resource *res;
unsigned int i;
......@@ -260,14 +260,14 @@ void output_res16_data( FILE *outfile, DLLSPEC *spec )
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
{
fprintf( outfile, ".L__wine_spec_resource_%u:\n", i );
dump_bytes( outfile, res->data, res->data_size );
fprintf( outfile, ".L__wine_spec_resource_%u_end:\n", i );
output( ".L__wine_spec_resource_%u:\n", i );
dump_bytes( res->data, res->data_size );
output( ".L__wine_spec_resource_%u_end:\n", i );
}
}
/* output the resource definitions */
void output_res16_directory( FILE *outfile, DLLSPEC *spec, const char *header_name )
void output_res16_directory( DLLSPEC *spec, const char *header_name )
{
unsigned int i, j;
struct res_tree *tree;
......@@ -276,38 +276,38 @@ void output_res16_directory( FILE *outfile, DLLSPEC *spec, const char *header_na
tree = build_resource_tree( spec );
fprintf( outfile, "\n.L__wine_spec_ne_rsrctab:\n" );
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* alignment */
output( "\n.L__wine_spec_ne_rsrctab:\n" );
output( "\t%s 0\n", get_asm_short_keyword() ); /* alignment */
/* type and name structures */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str)
fprintf( outfile, "\t%s .L__wine_spec_restype_%u-.L__wine_spec_ne_rsrctab\n",
output( "\t%s .L__wine_spec_restype_%u-.L__wine_spec_ne_rsrctab\n",
get_asm_short_keyword(), i );
else
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), type->type->id | 0x8000 );
output( "\t%s 0x%04x\n", get_asm_short_keyword(), type->type->id | 0x8000 );
fprintf( outfile, "\t%s %u,0,0\n", get_asm_short_keyword(), type->nb_names );
output( "\t%s %u,0,0\n", get_asm_short_keyword(), type->nb_names );
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
{
fprintf( outfile, "\t%s .L__wine_spec_resource_%u-%s\n",
output( "\t%s .L__wine_spec_resource_%u-%s\n",
get_asm_short_keyword(), res - spec->resources, header_name );
fprintf( outfile, "\t%s .L__wine_spec_resource_%u_end-.L__wine_spec_resource_%u\n",
output( "\t%s .L__wine_spec_resource_%u_end-.L__wine_spec_resource_%u\n",
get_asm_short_keyword(), res - spec->resources, res - spec->resources );
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), res->memopt );
output( "\t%s 0x%04x\n", get_asm_short_keyword(), res->memopt );
if (res->name.str)
fprintf( outfile, "\t%s .L__wine_spec_resname_%u_%u-.L__wine_spec_ne_rsrctab\n",
output( "\t%s .L__wine_spec_resname_%u_%u-.L__wine_spec_ne_rsrctab\n",
get_asm_short_keyword(), i, j );
else
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), res->name.id | 0x8000 );
output( "\t%s 0x%04x\n", get_asm_short_keyword(), res->name.id | 0x8000 );
fprintf( outfile, "\t%s 0,0\n", get_asm_short_keyword() );
output( "\t%s 0,0\n", get_asm_short_keyword() );
}
}
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* terminator */
output( "\t%s 0\n", get_asm_short_keyword() ); /* terminator */
/* name strings */
......@@ -315,19 +315,19 @@ void output_res16_directory( FILE *outfile, DLLSPEC *spec, const char *header_na
{
if (type->type->str)
{
fprintf( outfile, ".L__wine_spec_restype_%u:\n", i );
output_string( outfile, type->type->str );
output( ".L__wine_spec_restype_%u:\n", i );
output_string( type->type->str );
}
for (j = 0, res = type->res; j < type->nb_names; j++, res++)
{
if (res->name.str)
{
fprintf( outfile, ".L__wine_spec_resname_%u_%u:\n", i, j );
output_string( outfile, res->name.str );
output( ".L__wine_spec_resname_%u_%u:\n", i, j );
output_string( res->name.str );
}
}
}
fprintf( outfile, "\t.byte 0\n" ); /* names terminator */
output( "\t.byte 0\n" ); /* names terminator */
free_resource_tree( tree );
}
......@@ -316,29 +316,29 @@ static void free_resource_tree( struct res_tree *tree )
}
/* output a Unicode string */
static void output_string( FILE *outfile, const WCHAR *name )
static void output_string( const WCHAR *name )
{
int i, len = strlenW(name);
fprintf( outfile, "\t%s 0x%04x", get_asm_short_keyword(), len );
for (i = 0; i < len; i++) fprintf( outfile, ",0x%04x", name[i] );
fprintf( outfile, " /* " );
for (i = 0; i < len; i++) fprintf( outfile, "%c", isprint((char)name[i]) ? (char)name[i] : '?' );
fprintf( outfile, " */\n" );
output( "\t%s 0x%04x", get_asm_short_keyword(), len );
for (i = 0; i < len; i++) output( ",0x%04x", name[i] );
output( " /* " );
for (i = 0; i < len; i++) output( "%c", isprint((char)name[i]) ? (char)name[i] : '?' );
output( " */\n" );
}
/* output a resource directory */
static inline void output_res_dir( FILE *outfile, unsigned int nb_names, unsigned int nb_ids )
static inline void output_res_dir( unsigned int nb_names, unsigned int nb_ids )
{
fprintf( outfile, "\t.long 0\n" ); /* Characteristics */
fprintf( outfile, "\t.long 0\n" ); /* TimeDateStamp */
fprintf( outfile, "\t%s 0,0\n", /* Major/MinorVersion */
output( "\t.long 0\n" ); /* Characteristics */
output( "\t.long 0\n" ); /* TimeDateStamp */
output( "\t%s 0,0\n", /* Major/MinorVersion */
get_asm_short_keyword() );
fprintf( outfile, "\t%s %u,%u\n", /* NumberOfNamed/IdEntries */
output( "\t%s %u,%u\n", /* NumberOfNamed/IdEntries */
get_asm_short_keyword(), nb_names, nb_ids );
}
/* output the resource definitions */
void output_resources( FILE *outfile, DLLSPEC *spec )
void output_resources( DLLSPEC *spec )
{
int k, nb_id_types;
unsigned int i, n, offset, data_offset;
......@@ -388,19 +388,19 @@ void output_resources( FILE *outfile, DLLSPEC *spec )
/* output the resource directories */
fprintf( outfile, "\n/* resources */\n\n" );
fprintf( outfile, "\t.data\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
fprintf( outfile, ".L__wine_spec_resources:\n" );
output( "\n/* resources */\n\n" );
output( "\t.data\n" );
output( "\t.align %d\n", get_alignment(get_ptr_size()) );
output( ".L__wine_spec_resources:\n" );
output_res_dir( outfile, tree->nb_types - nb_id_types, nb_id_types );
output_res_dir( tree->nb_types - nb_id_types, nb_id_types );
/* dump the type directory */
offset = RESDIR_SIZE( tree->nb_types );
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
fprintf( outfile, "\t.long 0x%08x,0x%08x\n",
output( "\t.long 0x%08x,0x%08x\n",
type->name_offset, offset | 0x80000000 );
offset += RESDIR_SIZE( type->nb_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
......@@ -414,22 +414,22 @@ void output_resources( FILE *outfile, DLLSPEC *spec )
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
output_res_dir( outfile, type->nb_names - type->nb_id_names, type->nb_id_names );
output_res_dir( type->nb_names - type->nb_id_names, type->nb_id_names );
offset += RESDIR_SIZE( type->nb_names );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
fprintf( outfile, "\t.long 0x%08x,0x%08x\n",
output( "\t.long 0x%08x,0x%08x\n",
name->name_offset, offset | 0x80000000 );
offset += RESDIR_SIZE( name->nb_languages );
}
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
{
output_res_dir( outfile, 0, name->nb_languages );
output_res_dir( 0, name->nb_languages );
for (k = 0, res = name->res; k < name->nb_languages; k++, res++)
{
unsigned int entry_offset = (res - spec->resources) * sizeof(IMAGE_RESOURCE_DATA_ENTRY);
fprintf( outfile, "\t.long 0x%08x,0x%08x\n", res->lang, data_offset + entry_offset );
output( "\t.long 0x%08x,0x%08x\n", res->lang, data_offset + entry_offset );
}
}
}
......@@ -437,28 +437,28 @@ void output_resources( FILE *outfile, DLLSPEC *spec )
/* dump the resource data entries */
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
fprintf( outfile, "\t.long .L__wine_spec_res_%d-.L__wine_spec_rva_base,%u,0,0\n",
output( "\t.long .L__wine_spec_res_%d-.L__wine_spec_rva_base,%u,0,0\n",
i, res->data_size );
/* dump the name strings */
for (i = 0, type = tree->types; i < tree->nb_types; i++, type++)
{
if (type->type->str) output_string( outfile, type->type->str );
if (type->type->str) output_string( type->type->str );
for (n = 0, name = type->names; n < type->nb_names; n++, name++)
if (name->name->str) output_string( outfile, name->name->str );
if (name->name->str) output_string( name->name->str );
}
/* resource data */
for (i = 0, res = spec->resources; i < spec->nb_resources; i++, res++)
{
fprintf( outfile, "\n\t.align %d\n", get_alignment(get_ptr_size()) );
fprintf( outfile, ".L__wine_spec_res_%d:\n", i );
dump_bytes( outfile, res->data, res->data_size );
output( "\n\t.align %d\n", get_alignment(get_ptr_size()) );
output( ".L__wine_spec_res_%d:\n", i );
dump_bytes( res->data, res->data_size );
}
fprintf( outfile, ".L__wine_spec_resources_end:\n" );
fprintf( outfile, "\t.byte 0\n" );
output( ".L__wine_spec_resources_end:\n" );
output( "\t.byte 0\n" );
free_resource_tree( tree );
}
......@@ -54,31 +54,31 @@ static inline int is_function( const ORDDEF *odp )
*
* Output entries for individual symbols in the entry table.
*/
static void output_entries( FILE *outfile, DLLSPEC *spec, int first, int count )
static void output_entries( DLLSPEC *spec, int first, int count )
{
int i;
for (i = 0; i < count; i++)
{
ORDDEF *odp = spec->ordinals[first + i];
fprintf( outfile, "\t.byte 0x03\n" ); /* flags: exported & public data */
output( "\t.byte 0x03\n" ); /* flags: exported & public data */
switch (odp->type)
{
case TYPE_CDECL:
case TYPE_PASCAL:
case TYPE_VARARGS:
case TYPE_STUB:
fprintf( outfile, "\t%s .L__wine_%s_%u-.L__wine_spec_code_segment\n",
output( "\t%s .L__wine_%s_%u-.L__wine_spec_code_segment\n",
get_asm_short_keyword(),
make_c_identifier(spec->dll_name), first + i );
break;
case TYPE_VARIABLE:
fprintf( outfile, "\t%s .L__wine_%s_%u-.L__wine_spec_data_segment\n",
output( "\t%s .L__wine_%s_%u-.L__wine_spec_data_segment\n",
get_asm_short_keyword(),
make_c_identifier(spec->dll_name), first + i );
break;
case TYPE_ABS:
fprintf( outfile, "\t%s 0x%04x /* %s */\n",
output( "\t%s 0x%04x /* %s */\n",
get_asm_short_keyword(), odp->u.abs.value, odp->name );
break;
default:
......@@ -91,7 +91,7 @@ static void output_entries( FILE *outfile, DLLSPEC *spec, int first, int count )
/*******************************************************************
* output_entry_table
*/
static void output_entry_table( FILE *outfile, DLLSPEC *spec )
static void output_entry_table( DLLSPEC *spec )
{
int i, prev = 0, prev_sel = -1, bundle_count = 0;
......@@ -126,10 +126,10 @@ static void output_entry_table( FILE *outfile, DLLSPEC *spec )
/* flush previous bundle */
if (bundle_count)
{
fprintf( outfile, "\t/* %s.%d - %s.%d */\n",
output( "\t/* %s.%d - %s.%d */\n",
spec->dll_name, prev - bundle_count + 1, spec->dll_name, prev );
fprintf( outfile, "\t.byte 0x%02x,0x%02x\n", bundle_count, prev_sel );
output_entries( outfile, spec, prev - bundle_count + 1, bundle_count );
output( "\t.byte 0x%02x,0x%02x\n", bundle_count, prev_sel );
output_entries( spec, prev - bundle_count + 1, bundle_count );
}
if (prev + 1 != i)
......@@ -137,10 +137,10 @@ static void output_entry_table( FILE *outfile, DLLSPEC *spec )
int skip = i - (prev + 1);
while (skip > 255)
{
fprintf( outfile, "\t.byte 0xff,0x00\n" );
output( "\t.byte 0xff,0x00\n" );
skip -= 255;
}
fprintf( outfile, "\t.byte 0x%02x,0x00\n", skip );
output( "\t.byte 0x%02x,0x00\n", skip );
}
bundle_count = 0;
......@@ -153,24 +153,24 @@ static void output_entry_table( FILE *outfile, DLLSPEC *spec )
/* flush last bundle */
if (bundle_count)
{
fprintf( outfile, "\t.byte 0x%02x,0x%02x\n", bundle_count, prev_sel );
output_entries( outfile, spec, prev - bundle_count + 1, bundle_count );
output( "\t.byte 0x%02x,0x%02x\n", bundle_count, prev_sel );
output_entries( spec, prev - bundle_count + 1, bundle_count );
}
fprintf( outfile, "\t.byte 0x00\n" );
output( "\t.byte 0x00\n" );
}
/*******************************************************************
* output_resident_name
*/
static void output_resident_name( FILE *outfile, const char *string, int ordinal )
static void output_resident_name( const char *string, int ordinal )
{
unsigned int i, len = strlen(string);
fprintf( outfile, "\t.byte 0x%02x", len );
for (i = 0; i < len; i++) fprintf( outfile, ",0x%02x", (unsigned char)toupper(string[i]) );
fprintf( outfile, " /* %s */\n", string );
fprintf( outfile, "\t%s %u\n", get_asm_short_keyword(), ordinal );
output( "\t.byte 0x%02x", len );
for (i = 0; i < len; i++) output( ",0x%02x", (unsigned char)toupper(string[i]) );
output( " /* %s */\n", string );
output( "\t%s %u\n", get_asm_short_keyword(), ordinal );
}
......@@ -283,7 +283,7 @@ static int get_function_argsize( const ORDDEF *odp )
* the same as for normal functions, but in addition the CONTEXT86 pointer
* filled with the current register values is passed to the 32-bit routine.
*/
static void output_call16_function( FILE *outfile, ORDDEF *odp )
static void output_call16_function( ORDDEF *odp )
{
char name[256];
int i, pos, stack_words;
......@@ -293,41 +293,41 @@ static void output_call16_function( FILE *outfile, ORDDEF *odp )
sprintf( name, ".L__wine_spec_call16_%s", get_relay_name(odp) );
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
fprintf( outfile, "\t%s\n", func_declaration(name) );
fprintf( outfile, "%s:\n", name );
fprintf( outfile, "\tpushl %%ebp\n" );
fprintf( outfile, "\tmovl %%esp,%%ebp\n" );
output( "\t.align %d\n", get_alignment(4) );
output( "\t%s\n", func_declaration(name) );
output( "%s:\n", name );
output( "\tpushl %%ebp\n" );
output( "\tmovl %%esp,%%ebp\n" );
stack_words = 2;
if (needs_ldt)
{
fprintf( outfile, "\tpushl %%esi\n" );
output( "\tpushl %%esi\n" );
stack_words++;
if (UsePIC)
{
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
fprintf( outfile, "1:\tmovl wine_ldt_copy_ptr-1b(%%eax),%%esi\n" );
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
output( "1:\tmovl wine_ldt_copy_ptr-1b(%%eax),%%esi\n" );
}
else
fprintf( outfile, "\tmovl $%s,%%esi\n", asm_name("wine_ldt_copy") );
output( "\tmovl $%s,%%esi\n", asm_name("wine_ldt_copy") );
}
/* preserve 16-byte stack alignment */
stack_words += strlen(args);
if ((odp->flags & FLAG_REGISTER) || (odp->type == TYPE_VARARGS)) stack_words++;
if (stack_words % 4) fprintf( outfile, "\tsubl $%d,%%esp\n", 16 - 4 * (stack_words % 4) );
if (stack_words % 4) output( "\tsubl $%d,%%esp\n", 16 - 4 * (stack_words % 4) );
if (args[0] || odp->type == TYPE_VARARGS)
fprintf( outfile, "\tmovl 12(%%ebp),%%ecx\n" ); /* args */
output( "\tmovl 12(%%ebp),%%ecx\n" ); /* args */
if (odp->flags & FLAG_REGISTER)
{
fprintf( outfile, "\tpushl 16(%%ebp)\n" ); /* context */
output( "\tpushl 16(%%ebp)\n" ); /* context */
}
else if (odp->type == TYPE_VARARGS)
{
fprintf( outfile, "\tleal %d(%%ecx),%%eax\n", argsize );
fprintf( outfile, "\tpushl %%eax\n" ); /* va_list16 */
output( "\tleal %d(%%ecx),%%eax\n", argsize );
output( "\tpushl %%eax\n" ); /* va_list16 */
}
pos = (odp->type == TYPE_PASCAL) ? 0 : argsize;
......@@ -337,33 +337,33 @@ static void output_call16_function( FILE *outfile, ORDDEF *odp )
{
case 'w': /* word */
if (odp->type != TYPE_PASCAL) pos -= 2;
fprintf( outfile, "\tmovzwl %d(%%ecx),%%eax\n", pos );
fprintf( outfile, "\tpushl %%eax\n" );
output( "\tmovzwl %d(%%ecx),%%eax\n", pos );
output( "\tpushl %%eax\n" );
if (odp->type == TYPE_PASCAL) pos += 2;
break;
case 's': /* s_word */
if (odp->type != TYPE_PASCAL) pos -= 2;
fprintf( outfile, "\tmovswl %d(%%ecx),%%eax\n", pos );
fprintf( outfile, "\tpushl %%eax\n" );
output( "\tmovswl %d(%%ecx),%%eax\n", pos );
output( "\tpushl %%eax\n" );
if (odp->type == TYPE_PASCAL) pos += 2;
break;
case 'l': /* long or segmented pointer */
case 'T': /* segmented pointer to null-terminated string */
if (odp->type != TYPE_PASCAL) pos -= 4;
fprintf( outfile, "\tpushl %d(%%ecx)\n", pos );
output( "\tpushl %d(%%ecx)\n", pos );
if (odp->type == TYPE_PASCAL) pos += 4;
break;
case 'p': /* linear pointer */
case 't': /* linear pointer to null-terminated string */
if (odp->type != TYPE_PASCAL) pos -= 4;
fprintf( outfile, "\tmovzwl %d(%%ecx),%%edx\n", pos + 2 ); /* sel */
fprintf( outfile, "\tshr $3,%%edx\n" );
fprintf( outfile, "\tmovzwl %d(%%ecx),%%eax\n", pos ); /* offset */
fprintf( outfile, "\taddl (%%esi,%%edx,4),%%eax\n" );
fprintf( outfile, "\tpushl %%eax\n" );
output( "\tmovzwl %d(%%ecx),%%edx\n", pos + 2 ); /* sel */
output( "\tshr $3,%%edx\n" );
output( "\tmovzwl %d(%%ecx),%%eax\n", pos ); /* offset */
output( "\taddl (%%esi,%%edx,4),%%eax\n" );
output( "\tpushl %%eax\n" );
if (odp->type == TYPE_PASCAL) pos += 4;
break;
......@@ -372,13 +372,13 @@ static void output_call16_function( FILE *outfile, ORDDEF *odp )
}
}
fprintf( outfile, "\tcall *8(%%ebp)\n" );
output( "\tcall *8(%%ebp)\n" );
if (needs_ldt) fprintf( outfile, "\tmovl -4(%%ebp),%%esi\n" );
if (needs_ldt) output( "\tmovl -4(%%ebp),%%esi\n" );
fprintf( outfile, "\tleave\n" );
fprintf( outfile, "\tret\n" );
output_function_size( outfile, name );
output( "\tleave\n" );
output( "\tret\n" );
output_function_size( name );
}
......@@ -450,72 +450,72 @@ static int sort_func_list( ORDDEF **list, int count,
*
* Output the dll initialization code.
*/
static void output_init_code( FILE *outfile, const DLLSPEC *spec, const char *header_name )
static void output_init_code( const DLLSPEC *spec, const char *header_name )
{
char name[80];
sprintf( name, ".L__wine_spec_%s_init", make_c_identifier(spec->dll_name) );
fprintf( outfile, "\n/* dll initialization code */\n\n" );
fprintf( outfile, "\t.text\n" );
fprintf( outfile, "\t.align 4\n" );
fprintf( outfile, "\t%s\n", func_declaration(name) );
fprintf( outfile, "%s:\n", name );
fprintf( outfile, "subl $4,%%esp\n" );
output( "\n/* dll initialization code */\n\n" );
output( "\t.text\n" );
output( "\t.align 4\n" );
output( "\t%s\n", func_declaration(name) );
output( "%s:\n", name );
output( "subl $4,%%esp\n" );
if (UsePIC)
{
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
fprintf( outfile, "1:\tleal .L__wine_spec_file_name-1b(%%eax),%%ecx\n" );
fprintf( outfile, "\tpushl %%ecx\n" );
fprintf( outfile, "\tleal %s-1b(%%eax),%%ecx\n", header_name );
fprintf( outfile, "\tpushl %%ecx\n" );
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
output( "1:\tleal .L__wine_spec_file_name-1b(%%eax),%%ecx\n" );
output( "\tpushl %%ecx\n" );
output( "\tleal %s-1b(%%eax),%%ecx\n", header_name );
output( "\tpushl %%ecx\n" );
}
else
{
fprintf( outfile, "\tpushl $.L__wine_spec_file_name\n" );
fprintf( outfile, "\tpushl $%s\n", header_name );
output( "\tpushl $.L__wine_spec_file_name\n" );
output( "\tpushl $%s\n", header_name );
}
fprintf( outfile, "\tcall %s\n", asm_name("__wine_dll_register_16") );
fprintf( outfile, "\taddl $12,%%esp\n" );
fprintf( outfile, "\tret\n" );
output_function_size( outfile, name );
output( "\tcall %s\n", asm_name("__wine_dll_register_16") );
output( "\taddl $12,%%esp\n" );
output( "\tret\n" );
output_function_size( name );
sprintf( name, ".L__wine_spec_%s_fini", make_c_identifier(spec->dll_name) );
fprintf( outfile, "\t.align 4\n" );
fprintf( outfile, "\t%s\n", func_declaration(name) );
fprintf( outfile, "%s:\n", name );
fprintf( outfile, "subl $8,%%esp\n" );
output( "\t.align 4\n" );
output( "\t%s\n", func_declaration(name) );
output( "%s:\n", name );
output( "subl $8,%%esp\n" );
if (UsePIC)
{
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
fprintf( outfile, "1:\tleal %s-1b(%%eax),%%ecx\n", header_name );
fprintf( outfile, "\tpushl %%ecx\n" );
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
output( "1:\tleal %s-1b(%%eax),%%ecx\n", header_name );
output( "\tpushl %%ecx\n" );
}
else
{
fprintf( outfile, "\tpushl $%s\n", header_name );
output( "\tpushl $%s\n", header_name );
}
fprintf( outfile, "\tcall %s\n", asm_name("__wine_dll_unregister_16") );
fprintf( outfile, "\taddl $12,%%esp\n" );
fprintf( outfile, "\tret\n" );
output_function_size( outfile, name );
output( "\tcall %s\n", asm_name("__wine_dll_unregister_16") );
output( "\taddl $12,%%esp\n" );
output( "\tret\n" );
output_function_size( name );
if (target_platform == PLATFORM_APPLE)
{
fprintf( outfile, "\t.mod_init_func\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
fprintf( outfile, "\t.long .L__wine_spec_%s_init\n", make_c_identifier(spec->dll_name) );
fprintf( outfile, "\t.mod_term_func\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
fprintf( outfile, "\t.long .L__wine_spec_%s_fini\n", make_c_identifier(spec->dll_name) );
output( "\t.mod_init_func\n" );
output( "\t.align %d\n", get_alignment(4) );
output( "\t.long .L__wine_spec_%s_init\n", make_c_identifier(spec->dll_name) );
output( "\t.mod_term_func\n" );
output( "\t.align %d\n", get_alignment(4) );
output( "\t.long .L__wine_spec_%s_fini\n", make_c_identifier(spec->dll_name) );
}
else
{
fprintf( outfile, "\t.section \".init\",\"ax\"\n" );
fprintf( outfile, "\tcall .L__wine_spec_%s_init\n", make_c_identifier(spec->dll_name) );
fprintf( outfile, "\t.section \".fini\",\"ax\"\n" );
fprintf( outfile, "\tcall .L__wine_spec_%s_fini\n", make_c_identifier(spec->dll_name) );
output( "\t.section \".init\",\"ax\"\n" );
output( "\tcall .L__wine_spec_%s_init\n", make_c_identifier(spec->dll_name) );
output( "\t.section \".fini\",\"ax\"\n" );
output( "\tcall .L__wine_spec_%s_fini\n", make_c_identifier(spec->dll_name) );
}
}
......@@ -525,7 +525,7 @@ static void output_init_code( FILE *outfile, const DLLSPEC *spec, const char *he
*
* Build a Win16 assembly file from a spec file.
*/
void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
void BuildSpec16File( DLLSPEC *spec )
{
ORDDEF **typelist;
int i, j, nb_funcs;
......@@ -533,7 +533,7 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
/* File header */
output_standard_file_header( outfile );
output_standard_file_header();
if (!spec->dll_name) /* set default name from file name */
{
......@@ -558,130 +558,130 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
/* Output the module structure */
sprintf( header_name, "__wine_spec_%s_dos_header", make_c_identifier(spec->dll_name) );
fprintf( outfile, "\n/* module data */\n\n" );
fprintf( outfile, "\t.data\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
fprintf( outfile, "%s:\n", header_name );
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), /* e_magic */
output( "\n/* module data */\n\n" );
output( "\t.data\n" );
output( "\t.align %d\n", get_alignment(4) );
output( "%s:\n", header_name );
output( "\t%s 0x%04x\n", get_asm_short_keyword(), /* e_magic */
IMAGE_DOS_SIGNATURE );
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_cblp */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_cp */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_crlc */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_cparhdr */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_minalloc */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_maxalloc */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_ss */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_sp */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_csum */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_ip */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_cs */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_lfarlc */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_ovno */
fprintf( outfile, "\t%s 0,0,0,0\n", get_asm_short_keyword() ); /* e_res */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_oemid */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* e_oeminfo */
fprintf( outfile, "\t%s 0,0,0,0,0,0,0,0,0,0\n", get_asm_short_keyword() ); /* e_res2 */
fprintf( outfile, "\t.long .L__wine_spec_ne_header-%s\n", header_name ); /* e_lfanew */
fprintf( outfile, ".L__wine_spec_ne_header:\n" );
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), /* ne_magic */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_cblp */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_cp */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_crlc */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_cparhdr */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_minalloc */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_maxalloc */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_ss */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_sp */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_csum */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_ip */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_cs */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_lfarlc */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_ovno */
output( "\t%s 0,0,0,0\n", get_asm_short_keyword() ); /* e_res */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_oemid */
output( "\t%s 0\n", get_asm_short_keyword() ); /* e_oeminfo */
output( "\t%s 0,0,0,0,0,0,0,0,0,0\n", get_asm_short_keyword() ); /* e_res2 */
output( "\t.long .L__wine_spec_ne_header-%s\n", header_name ); /* e_lfanew */
output( ".L__wine_spec_ne_header:\n" );
output( "\t%s 0x%04x\n", get_asm_short_keyword(), /* ne_magic */
IMAGE_OS2_SIGNATURE );
fprintf( outfile, "\t.byte 0\n" ); /* ne_ver */
fprintf( outfile, "\t.byte 0\n" ); /* ne_rev */
fprintf( outfile, "\t%s .L__wine_spec_ne_enttab-.L__wine_spec_ne_header\n", /* ne_enttab */
output( "\t.byte 0\n" ); /* ne_ver */
output( "\t.byte 0\n" ); /* ne_rev */
output( "\t%s .L__wine_spec_ne_enttab-.L__wine_spec_ne_header\n", /* ne_enttab */
get_asm_short_keyword() );
fprintf( outfile, "\t%s .L__wine_spec_ne_enttab_end-.L__wine_spec_ne_enttab\n", /* ne_cbenttab */
output( "\t%s .L__wine_spec_ne_enttab_end-.L__wine_spec_ne_enttab\n", /* ne_cbenttab */
get_asm_short_keyword() );
fprintf( outfile, "\t.long 0\n" ); /* ne_crc */
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), /* ne_flags */
output( "\t.long 0\n" ); /* ne_crc */
output( "\t%s 0x%04x\n", get_asm_short_keyword(), /* ne_flags */
NE_FFLAGS_SINGLEDATA | NE_FFLAGS_LIBMODULE );
fprintf( outfile, "\t%s 2\n", get_asm_short_keyword() ); /* ne_autodata */
fprintf( outfile, "\t%s %u\n", get_asm_short_keyword(), spec->heap_size ); /* ne_heap */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_stack */
fprintf( outfile, "\t.long 0\n" ); /* ne_csip */
fprintf( outfile, "\t.long 0\n" ); /* ne_sssp */
fprintf( outfile, "\t%s 2\n", get_asm_short_keyword() ); /* ne_cseg */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_cmod */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_cbnrestab */
fprintf( outfile, "\t%s .L__wine_spec_ne_segtab-.L__wine_spec_ne_header\n", /* ne_segtab */
output( "\t%s 2\n", get_asm_short_keyword() ); /* ne_autodata */
output( "\t%s %u\n", get_asm_short_keyword(), spec->heap_size ); /* ne_heap */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_stack */
output( "\t.long 0\n" ); /* ne_csip */
output( "\t.long 0\n" ); /* ne_sssp */
output( "\t%s 2\n", get_asm_short_keyword() ); /* ne_cseg */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cmod */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cbnrestab */
output( "\t%s .L__wine_spec_ne_segtab-.L__wine_spec_ne_header\n", /* ne_segtab */
get_asm_short_keyword() );
fprintf( outfile, "\t%s .L__wine_spec_ne_rsrctab-.L__wine_spec_ne_header\n", /* ne_rsrctab */
output( "\t%s .L__wine_spec_ne_rsrctab-.L__wine_spec_ne_header\n", /* ne_rsrctab */
get_asm_short_keyword() );
fprintf( outfile, "\t%s .L__wine_spec_ne_restab-.L__wine_spec_ne_header\n", /* ne_restab */
output( "\t%s .L__wine_spec_ne_restab-.L__wine_spec_ne_header\n", /* ne_restab */
get_asm_short_keyword() );
fprintf( outfile, "\t%s .L__wine_spec_ne_modtab-.L__wine_spec_ne_header\n", /* ne_modtab */
output( "\t%s .L__wine_spec_ne_modtab-.L__wine_spec_ne_header\n", /* ne_modtab */
get_asm_short_keyword() );
fprintf( outfile, "\t%s .L__wine_spec_ne_imptab-.L__wine_spec_ne_header\n", /* ne_imptab */
output( "\t%s .L__wine_spec_ne_imptab-.L__wine_spec_ne_header\n", /* ne_imptab */
get_asm_short_keyword() );
fprintf( outfile, "\t.long 0\n" ); /* ne_nrestab */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_cmovent */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_align */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_cres */
fprintf( outfile, "\t.byte 0x%02x\n", NE_OSFLAGS_WINDOWS ); /* ne_exetyp */
fprintf( outfile, "\t.byte 0x%02x\n", NE_AFLAGS_FASTLOAD ); /* ne_flagsothers */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_pretthunks */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_psegrefbytes */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_swaparea */
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() ); /* ne_expver */
output( "\t.long 0\n" ); /* ne_nrestab */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cmovent */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_align */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_cres */
output( "\t.byte 0x%02x\n", NE_OSFLAGS_WINDOWS ); /* ne_exetyp */
output( "\t.byte 0x%02x\n", NE_AFLAGS_FASTLOAD ); /* ne_flagsothers */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_pretthunks */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_psegrefbytes */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_swaparea */
output( "\t%s 0\n", get_asm_short_keyword() ); /* ne_expver */
/* segment table */
fprintf( outfile, "\n.L__wine_spec_ne_segtab:\n" );
output( "\n.L__wine_spec_ne_segtab:\n" );
/* code segment entry */
fprintf( outfile, "\t%s .L__wine_spec_code_segment-%s\n", /* filepos */
output( "\t%s .L__wine_spec_code_segment-%s\n", /* filepos */
get_asm_short_keyword(), header_name );
fprintf( outfile, "\t%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment\n", /* size */
output( "\t%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment\n", /* size */
get_asm_short_keyword() );
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), NE_SEGFLAGS_32BIT ); /* flags */
fprintf( outfile, "\t%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment\n", /* minsize */
output( "\t%s 0x%04x\n", get_asm_short_keyword(), NE_SEGFLAGS_32BIT ); /* flags */
output( "\t%s .L__wine_spec_code_segment_end-.L__wine_spec_code_segment\n", /* minsize */
get_asm_short_keyword() );
/* data segment entry */
fprintf( outfile, "\t%s .L__wine_spec_data_segment-%s\n", /* filepos */
output( "\t%s .L__wine_spec_data_segment-%s\n", /* filepos */
get_asm_short_keyword(), header_name );
fprintf( outfile, "\t%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment\n", /* size */
output( "\t%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment\n", /* size */
get_asm_short_keyword() );
fprintf( outfile, "\t%s 0x%04x\n", get_asm_short_keyword(), NE_SEGFLAGS_DATA ); /* flags */
fprintf( outfile, "\t%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment\n", /* minsize */
output( "\t%s 0x%04x\n", get_asm_short_keyword(), NE_SEGFLAGS_DATA ); /* flags */
output( "\t%s .L__wine_spec_data_segment_end-.L__wine_spec_data_segment\n", /* minsize */
get_asm_short_keyword() );
/* resource directory */
output_res16_directory( outfile, spec, header_name );
output_res16_directory( spec, header_name );
/* resident names table */
fprintf( outfile, "\n\t.align %d\n", get_alignment(2) );
fprintf( outfile, ".L__wine_spec_ne_restab:\n" );
output_resident_name( outfile, spec->dll_name, 0 );
output( "\n\t.align %d\n", get_alignment(2) );
output( ".L__wine_spec_ne_restab:\n" );
output_resident_name( spec->dll_name, 0 );
for (i = 1; i <= spec->limit; i++)
{
ORDDEF *odp = spec->ordinals[i];
if (!odp || !odp->name[0]) continue;
output_resident_name( outfile, odp->name, i );
output_resident_name( odp->name, i );
}
fprintf( outfile, "\t.byte 0\n" );
output( "\t.byte 0\n" );
/* imported names table */
fprintf( outfile, "\n\t.align %d\n", get_alignment(2) );
fprintf( outfile, ".L__wine_spec_ne_modtab:\n" );
fprintf( outfile, ".L__wine_spec_ne_imptab:\n" );
fprintf( outfile, "\t.byte 0,0\n" );
output( "\n\t.align %d\n", get_alignment(2) );
output( ".L__wine_spec_ne_modtab:\n" );
output( ".L__wine_spec_ne_imptab:\n" );
output( "\t.byte 0,0\n" );
/* entry table */
fprintf( outfile, "\n.L__wine_spec_ne_enttab:\n" );
output_entry_table( outfile, spec );
fprintf( outfile, ".L__wine_spec_ne_enttab_end:\n" );
output( "\n.L__wine_spec_ne_enttab:\n" );
output_entry_table( spec );
output( ".L__wine_spec_ne_enttab_end:\n" );
/* code segment */
fprintf( outfile, "\n\t.align %d\n", get_alignment(2) );
fprintf( outfile, ".L__wine_spec_code_segment:\n" );
output( "\n\t.align %d\n", get_alignment(2) );
output( ".L__wine_spec_code_segment:\n" );
for ( i = 0; i < nb_funcs; i++ )
{
......@@ -709,9 +709,9 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
}
if (typelist[i]->type == TYPE_VARARGS) arg_types[j / 10] |= ARG_VARARG << (3 * (j % 10));
fprintf( outfile, ".L__wine_spec_callfrom16_%s:\n", get_callfrom16_name(typelist[i]) );
fprintf( outfile, "\tpushl $.L__wine_spec_call16_%s\n", get_relay_name(typelist[i]) );
fprintf( outfile, "\tlcall $0,$0\n" );
output( ".L__wine_spec_callfrom16_%s:\n", get_callfrom16_name(typelist[i]) );
output( "\tpushl $.L__wine_spec_call16_%s\n", get_relay_name(typelist[i]) );
output( "\tlcall $0,$0\n" );
if (typelist[i]->flags & FLAG_REGISTER)
{
......@@ -719,91 +719,91 @@ void BuildSpec16File( FILE *outfile, DLLSPEC *spec )
}
else if (typelist[i]->flags & FLAG_RET16)
{
fprintf( outfile, "\torw %%ax,%%ax\n" );
fprintf( outfile, "\tnop\n" ); /* so that the lretw is aligned */
output( "\torw %%ax,%%ax\n" );
output( "\tnop\n" ); /* so that the lretw is aligned */
nop_words = 2;
}
else
{
fprintf( outfile, "\tshld $16,%%eax,%%edx\n" );
fprintf( outfile, "\torl %%eax,%%eax\n" );
output( "\tshld $16,%%eax,%%edx\n" );
output( "\torl %%eax,%%eax\n" );
nop_words = 1;
}
if (argsize)
{
fprintf( outfile, "\tlretw $%u\n", argsize );
output( "\tlretw $%u\n", argsize );
nop_words--;
}
else fprintf( outfile, "\tlretw\n" );
else output( "\tlretw\n" );
if (nop_words) fprintf( outfile, "\t%s\n", nop_sequence[nop_words-1] );
if (nop_words) output( "\t%s\n", nop_sequence[nop_words-1] );
/* the movl is here so that the code contains only valid instructions, */
/* it's never actually executed, we only care about the arg_types[] values */
fprintf( outfile, "\t%s 0x86c7\n", get_asm_short_keyword() );
fprintf( outfile, "\t.long 0x%08x,0x%08x\n", arg_types[0], arg_types[1] );
output( "\t%s 0x86c7\n", get_asm_short_keyword() );
output( "\t.long 0x%08x,0x%08x\n", arg_types[0], arg_types[1] );
}
for (i = 0; i <= spec->limit; i++)
{
ORDDEF *odp = spec->ordinals[i];
if (!odp || !is_function( odp )) continue;
fprintf( outfile, ".L__wine_%s_%u:\n", make_c_identifier(spec->dll_name), i );
fprintf( outfile, "\tpushw %%bp\n" );
fprintf( outfile, "\tpushl $%s\n",
output( ".L__wine_%s_%u:\n", make_c_identifier(spec->dll_name), i );
output( "\tpushw %%bp\n" );
output( "\tpushl $%s\n",
asm_name( odp->type == TYPE_STUB ? get_stub_name( odp, spec ) : odp->link_name ));
fprintf( outfile, "\tcallw .L__wine_spec_callfrom16_%s\n", get_callfrom16_name( odp ) );
output( "\tcallw .L__wine_spec_callfrom16_%s\n", get_callfrom16_name( odp ) );
}
fprintf( outfile, ".L__wine_spec_code_segment_end:\n" );
output( ".L__wine_spec_code_segment_end:\n" );
/* data segment */
fprintf( outfile, "\n.L__wine_spec_data_segment:\n" );
fprintf( outfile, "\t.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n" ); /* instance data */
output( "\n.L__wine_spec_data_segment:\n" );
output( "\t.byte 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0\n" ); /* instance data */
for (i = 0; i <= spec->limit; i++)
{
ORDDEF *odp = spec->ordinals[i];
if (!odp || odp->type != TYPE_VARIABLE) continue;
fprintf( outfile, ".L__wine_%s_%u:\n", make_c_identifier(spec->dll_name), i );
fprintf( outfile, "\t.long " );
output( ".L__wine_%s_%u:\n", make_c_identifier(spec->dll_name), i );
output( "\t.long " );
for (j = 0; j < odp->u.var.n_values-1; j++)
fprintf( outfile, "0x%08x,", odp->u.var.values[j] );
fprintf( outfile, "0x%08x\n", odp->u.var.values[j] );
output( "0x%08x,", odp->u.var.values[j] );
output( "0x%08x\n", odp->u.var.values[j] );
}
fprintf( outfile, ".L__wine_spec_data_segment_end:\n" );
output( ".L__wine_spec_data_segment_end:\n" );
/* resource data */
if (spec->nb_resources)
{
fprintf( outfile, "\n.L__wine_spec_resource_data:\n" );
output_res16_data( outfile, spec );
output( "\n.L__wine_spec_resource_data:\n" );
output_res16_data( spec );
}
fprintf( outfile, "\t.byte 0\n" ); /* make sure the last symbol points to something */
output( "\t.byte 0\n" ); /* make sure the last symbol points to something */
/* relay functions */
nb_funcs = sort_func_list( typelist, nb_funcs, relay_type_compare );
if (nb_funcs)
{
fprintf( outfile, "\n/* relay functions */\n\n" );
fprintf( outfile, "\t.text\n" );
for ( i = 0; i < nb_funcs; i++ ) output_call16_function( outfile, typelist[i] );
fprintf( outfile, "\t.data\n" );
fprintf( outfile, "wine_ldt_copy_ptr:\n" );
fprintf( outfile, "\t.long %s\n", asm_name("wine_ldt_copy") );
output( "\n/* relay functions */\n\n" );
output( "\t.text\n" );
for ( i = 0; i < nb_funcs; i++ ) output_call16_function( typelist[i] );
output( "\t.data\n" );
output( "wine_ldt_copy_ptr:\n" );
output( "\t.long %s\n", asm_name("wine_ldt_copy") );
}
fprintf( outfile, "\n\t%s\n", get_asm_string_section() );
fprintf( outfile, ".L__wine_spec_file_name:\n" );
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
output( "\n\t%s\n", get_asm_string_section() );
output( ".L__wine_spec_file_name:\n" );
output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
output_stubs( outfile, spec );
output_get_pc_thunk( outfile );
output_init_code( outfile, spec, header_name );
output_gnu_stack_note( outfile );
output_stubs( spec );
output_get_pc_thunk();
output_init_code( spec, header_name );
output_gnu_stack_note();
free( typelist );
}
......@@ -68,30 +68,30 @@ int has_relays( DLLSPEC *spec )
*
* Output entry points for relay debugging
*/
static void output_relay_debug( FILE *outfile, DLLSPEC *spec )
static void output_relay_debug( DLLSPEC *spec )
{
unsigned int i, j, args, flags;
/* first the table of entry point offsets */
fprintf( outfile, "\t%s\n", get_asm_rodata_section() );
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
fprintf( outfile, ".L__wine_spec_relay_entry_point_offsets:\n" );
output( "\t%s\n", get_asm_rodata_section() );
output( "\t.align %d\n", get_alignment(4) );
output( ".L__wine_spec_relay_entry_point_offsets:\n" );
for (i = spec->base; i <= spec->limit; i++)
{
ORDDEF *odp = spec->ordinals[i];
if (needs_relay( odp ))
fprintf( outfile, "\t.long .L__wine_spec_relay_entry_point_%d-__wine_spec_relay_entry_points\n", i );
output( "\t.long .L__wine_spec_relay_entry_point_%d-__wine_spec_relay_entry_points\n", i );
else
fprintf( outfile, "\t.long 0\n" );
output( "\t.long 0\n" );
}
/* then the table of argument types */
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
fprintf( outfile, ".L__wine_spec_relay_arg_types:\n" );
output( "\t.align %d\n", get_alignment(4) );
output( ".L__wine_spec_relay_arg_types:\n" );
for (i = spec->base; i <= spec->limit; i++)
{
......@@ -106,14 +106,14 @@ static void output_relay_debug( FILE *outfile, DLLSPEC *spec )
if (odp->u.func.arg_types[j] == 'W') mask |= 2<< (j*2);
}
}
fprintf( outfile, "\t.long 0x%08x\n", mask );
output( "\t.long 0x%08x\n", mask );
}
/* then the relay thunks */
fprintf( outfile, "\t.text\n" );
fprintf( outfile, "__wine_spec_relay_entry_points:\n" );
fprintf( outfile, "\tnop\n" ); /* to avoid 0 offset */
output( "\t.text\n" );
output( "__wine_spec_relay_entry_points:\n" );
output( "\tnop\n" ); /* to avoid 0 offset */
for (i = spec->base; i <= spec->limit; i++)
{
......@@ -121,39 +121,39 @@ static void output_relay_debug( FILE *outfile, DLLSPEC *spec )
if (!needs_relay( odp )) continue;
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
fprintf( outfile, ".L__wine_spec_relay_entry_point_%d:\n", i );
output( "\t.align %d\n", get_alignment(4) );
output( ".L__wine_spec_relay_entry_point_%d:\n", i );
if (odp->flags & FLAG_REGISTER)
fprintf( outfile, "\tpushl %%eax\n" );
output( "\tpushl %%eax\n" );
else
fprintf( outfile, "\tpushl %%esp\n" );
output( "\tpushl %%esp\n" );
args = strlen(odp->u.func.arg_types);
flags = 0;
if (odp->flags & FLAG_RET64) flags |= 1;
if (odp->type == TYPE_STDCALL) flags |= 2;
fprintf( outfile, "\tpushl $%u\n", (flags << 24) | (args << 16) | (i - spec->base) );
output( "\tpushl $%u\n", (flags << 24) | (args << 16) | (i - spec->base) );
if (UsePIC)
{
fprintf( outfile, "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
fprintf( outfile, "1:\tleal .L__wine_spec_relay_descr-1b(%%eax),%%eax\n" );
output( "\tcall %s\n", asm_name("__wine_spec_get_pc_thunk_eax") );
output( "1:\tleal .L__wine_spec_relay_descr-1b(%%eax),%%eax\n" );
}
else fprintf( outfile, "\tmovl $.L__wine_spec_relay_descr,%%eax\n" );
fprintf( outfile, "\tpushl %%eax\n" );
else output( "\tmovl $.L__wine_spec_relay_descr,%%eax\n" );
output( "\tpushl %%eax\n" );
if (odp->flags & FLAG_REGISTER)
{
fprintf( outfile, "\tcall *8(%%eax)\n" );
output( "\tcall *8(%%eax)\n" );
}
else
{
fprintf( outfile, "\tcall *4(%%eax)\n" );
output( "\tcall *4(%%eax)\n" );
if (odp->type == TYPE_STDCALL)
fprintf( outfile, "\tret $%u\n", args * get_ptr_size() );
output( "\tret $%u\n", args * get_ptr_size() );
else
fprintf( outfile, "\tret\n" );
output( "\tret\n" );
}
}
}
......@@ -163,46 +163,46 @@ static void output_relay_debug( FILE *outfile, DLLSPEC *spec )
*
* Output the export table for a Win32 module.
*/
static void output_exports( FILE *outfile, DLLSPEC *spec )
static void output_exports( DLLSPEC *spec )
{
int i, fwd_size = 0;
int nr_exports = spec->base <= spec->limit ? spec->limit - spec->base + 1 : 0;
if (!nr_exports) return;
fprintf( outfile, "\n/* export table */\n\n" );
fprintf( outfile, "\t.data\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
fprintf( outfile, ".L__wine_spec_exports:\n" );
output( "\n/* export table */\n\n" );
output( "\t.data\n" );
output( "\t.align %d\n", get_alignment(4) );
output( ".L__wine_spec_exports:\n" );
/* export directory header */
fprintf( outfile, "\t.long 0\n" ); /* Characteristics */
fprintf( outfile, "\t.long 0\n" ); /* TimeDateStamp */
fprintf( outfile, "\t.long 0\n" ); /* MajorVersion/MinorVersion */
fprintf( outfile, "\t.long .L__wine_spec_exp_names-.L__wine_spec_rva_base\n" ); /* Name */
fprintf( outfile, "\t.long %u\n", spec->base ); /* Base */
fprintf( outfile, "\t.long %u\n", nr_exports ); /* NumberOfFunctions */
fprintf( outfile, "\t.long %u\n", spec->nb_names ); /* NumberOfNames */
fprintf( outfile, "\t.long .L__wine_spec_exports_funcs-.L__wine_spec_rva_base\n" ); /* AddressOfFunctions */
output( "\t.long 0\n" ); /* Characteristics */
output( "\t.long 0\n" ); /* TimeDateStamp */
output( "\t.long 0\n" ); /* MajorVersion/MinorVersion */
output( "\t.long .L__wine_spec_exp_names-.L__wine_spec_rva_base\n" ); /* Name */
output( "\t.long %u\n", spec->base ); /* Base */
output( "\t.long %u\n", nr_exports ); /* NumberOfFunctions */
output( "\t.long %u\n", spec->nb_names ); /* NumberOfNames */
output( "\t.long .L__wine_spec_exports_funcs-.L__wine_spec_rva_base\n" ); /* AddressOfFunctions */
if (spec->nb_names)
{
fprintf( outfile, "\t.long .L__wine_spec_exp_name_ptrs-.L__wine_spec_rva_base\n" ); /* AddressOfNames */
fprintf( outfile, "\t.long .L__wine_spec_exp_ordinals-.L__wine_spec_rva_base\n" ); /* AddressOfNameOrdinals */
output( "\t.long .L__wine_spec_exp_name_ptrs-.L__wine_spec_rva_base\n" ); /* AddressOfNames */
output( "\t.long .L__wine_spec_exp_ordinals-.L__wine_spec_rva_base\n" ); /* AddressOfNameOrdinals */
}
else
{
fprintf( outfile, "\t.long 0\n" ); /* AddressOfNames */
fprintf( outfile, "\t.long 0\n" ); /* AddressOfNameOrdinals */
output( "\t.long 0\n" ); /* AddressOfNames */
output( "\t.long 0\n" ); /* AddressOfNameOrdinals */
}
/* output the function pointers */
fprintf( outfile, "\n.L__wine_spec_exports_funcs:\n" );
output( "\n.L__wine_spec_exports_funcs:\n" );
for (i = spec->base; i <= spec->limit; i++)
{
ORDDEF *odp = spec->ordinals[i];
if (!odp) fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
if (!odp) output( "\t%s 0\n", get_asm_ptr_keyword() );
else switch(odp->type)
{
case TYPE_EXTERN:
......@@ -211,21 +211,21 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
case TYPE_CDECL:
if (odp->flags & FLAG_FORWARD)
{
fprintf( outfile, "\t%s .L__wine_spec_forwards+%u\n", get_asm_ptr_keyword(), fwd_size );
output( "\t%s .L__wine_spec_forwards+%u\n", get_asm_ptr_keyword(), fwd_size );
fwd_size += strlen(odp->link_name) + 1;
}
else if (odp->flags & FLAG_EXT_LINK)
{
fprintf( outfile, "\t%s %s_%s\n",
output( "\t%s %s_%s\n",
get_asm_ptr_keyword(), asm_name("__wine_spec_ext_link"), odp->link_name );
}
else
{
fprintf( outfile, "\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->link_name) );
output( "\t%s %s\n", get_asm_ptr_keyword(), asm_name(odp->link_name) );
}
break;
case TYPE_STUB:
fprintf( outfile, "\t%s %s\n", get_asm_ptr_keyword(),
output( "\t%s %s\n", get_asm_ptr_keyword(),
asm_name( get_stub_name( odp, spec )) );
break;
default:
......@@ -239,68 +239,68 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
int namepos = strlen(spec->file_name) + 1;
fprintf( outfile, "\n.L__wine_spec_exp_name_ptrs:\n" );
output( "\n.L__wine_spec_exp_name_ptrs:\n" );
for (i = 0; i < spec->nb_names; i++)
{
fprintf( outfile, "\t.long .L__wine_spec_exp_names+%u-.L__wine_spec_rva_base\n", namepos );
output( "\t.long .L__wine_spec_exp_names+%u-.L__wine_spec_rva_base\n", namepos );
namepos += strlen(spec->names[i]->name) + 1;
}
/* output the function ordinals */
fprintf( outfile, "\n.L__wine_spec_exp_ordinals:\n" );
output( "\n.L__wine_spec_exp_ordinals:\n" );
for (i = 0; i < spec->nb_names; i++)
{
fprintf( outfile, "\t%s %d\n",
output( "\t%s %d\n",
get_asm_short_keyword(), spec->names[i]->ordinal - spec->base );
}
if (spec->nb_names % 2)
{
fprintf( outfile, "\t%s 0\n", get_asm_short_keyword() );
output( "\t%s 0\n", get_asm_short_keyword() );
}
}
/* output the export name strings */
fprintf( outfile, "\n.L__wine_spec_exp_names:\n" );
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
output( "\n.L__wine_spec_exp_names:\n" );
output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
for (i = 0; i < spec->nb_names; i++)
fprintf( outfile, "\t%s \"%s\"\n",
output( "\t%s \"%s\"\n",
get_asm_string_keyword(), spec->names[i]->name );
/* output forward strings */
if (fwd_size)
{
fprintf( outfile, "\n.L__wine_spec_forwards:\n" );
output( "\n.L__wine_spec_forwards:\n" );
for (i = spec->base; i <= spec->limit; i++)
{
ORDDEF *odp = spec->ordinals[i];
if (odp && (odp->flags & FLAG_FORWARD))
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), odp->link_name );
output( "\t%s \"%s\"\n", get_asm_string_keyword(), odp->link_name );
}
}
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
fprintf( outfile, ".L__wine_spec_exports_end:\n" );
output( "\t.align %d\n", get_alignment(get_ptr_size()) );
output( ".L__wine_spec_exports_end:\n" );
/* output relays */
/* we only support relay debugging on i386 */
if (target_cpu != CPU_x86)
{
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() );
output( "\t%s 0\n", get_asm_ptr_keyword() );
return;
}
fprintf( outfile, ".L__wine_spec_relay_descr:\n" );
fprintf( outfile, "\t%s 0xdeb90001\n", get_asm_ptr_keyword() ); /* magic */
fprintf( outfile, "\t%s 0,0\n", get_asm_ptr_keyword() ); /* relay funcs */
fprintf( outfile, "\t%s 0\n", get_asm_ptr_keyword() ); /* private data */
fprintf( outfile, "\t%s __wine_spec_relay_entry_points\n", get_asm_ptr_keyword() );
fprintf( outfile, "\t%s .L__wine_spec_relay_entry_point_offsets\n", get_asm_ptr_keyword() );
fprintf( outfile, "\t%s .L__wine_spec_relay_arg_types\n", get_asm_ptr_keyword() );
output( ".L__wine_spec_relay_descr:\n" );
output( "\t%s 0xdeb90001\n", get_asm_ptr_keyword() ); /* magic */
output( "\t%s 0,0\n", get_asm_ptr_keyword() ); /* relay funcs */
output( "\t%s 0\n", get_asm_ptr_keyword() ); /* private data */
output( "\t%s __wine_spec_relay_entry_points\n", get_asm_ptr_keyword() );
output( "\t%s .L__wine_spec_relay_entry_point_offsets\n", get_asm_ptr_keyword() );
output( "\t%s .L__wine_spec_relay_arg_types\n", get_asm_ptr_keyword() );
output_relay_debug( outfile, spec );
output_relay_debug( spec );
}
......@@ -309,33 +309,33 @@ static void output_exports( FILE *outfile, DLLSPEC *spec )
*
* Output code for calling a dll constructor.
*/
static void output_asm_constructor( FILE *outfile, const char *constructor )
static void output_asm_constructor( const char *constructor )
{
if (target_platform == PLATFORM_APPLE)
{
/* Mach-O doesn't have an init section */
fprintf( outfile, "\n\t.mod_init_func\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(4) );
fprintf( outfile, "\t.long %s\n", asm_name(constructor) );
output( "\n\t.mod_init_func\n" );
output( "\t.align %d\n", get_alignment(4) );
output( "\t.long %s\n", asm_name(constructor) );
}
else
{
fprintf( outfile, "\n\t.section \".init\",\"ax\"\n" );
output( "\n\t.section \".init\",\"ax\"\n" );
switch(target_cpu)
{
case CPU_x86:
case CPU_x86_64:
fprintf( outfile, "\tcall %s\n", asm_name(constructor) );
output( "\tcall %s\n", asm_name(constructor) );
break;
case CPU_SPARC:
fprintf( outfile, "\tcall %s\n", asm_name(constructor) );
fprintf( outfile, "\tnop\n" );
output( "\tcall %s\n", asm_name(constructor) );
output( "\tnop\n" );
break;
case CPU_ALPHA:
fprintf( outfile, "\tjsr $26,%s\n", asm_name(constructor) );
output( "\tjsr $26,%s\n", asm_name(constructor) );
break;
case CPU_POWERPC:
fprintf( outfile, "\tbl %s\n", asm_name(constructor) );
output( "\tbl %s\n", asm_name(constructor) );
break;
}
}
......@@ -347,32 +347,32 @@ static void output_asm_constructor( FILE *outfile, const char *constructor )
*
* Build a Win32 C file from a spec file.
*/
void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
void BuildSpec32File( DLLSPEC *spec )
{
int machine = 0;
unsigned int page_size = get_page_size();
resolve_imports( spec );
output_standard_file_header( outfile );
output_standard_file_header();
/* Reserve some space for the PE header */
fprintf( outfile, "\t.text\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(page_size) );
fprintf( outfile, "__wine_spec_pe_header:\n" );
output( "\t.text\n" );
output( "\t.align %d\n", get_alignment(page_size) );
output( "__wine_spec_pe_header:\n" );
if (target_platform == PLATFORM_APPLE)
fprintf( outfile, "\t.space 65536\n" );
output( "\t.space 65536\n" );
else
fprintf( outfile, "\t.skip 65536\n" );
output( "\t.skip 65536\n" );
/* Output the NT header */
fprintf( outfile, "\n\t.data\n" );
fprintf( outfile, "\t.align %d\n", get_alignment(get_ptr_size()) );
fprintf( outfile, "%s\n", asm_globl("__wine_spec_nt_header") );
fprintf( outfile, ".L__wine_spec_rva_base:\n" );
output( "\n\t.data\n" );
output( "\t.align %d\n", get_alignment(get_ptr_size()) );
output( "%s\n", asm_globl("__wine_spec_nt_header") );
output( ".L__wine_spec_rva_base:\n" );
fprintf( outfile, "\t.long 0x%04x\n", IMAGE_NT_SIGNATURE ); /* Signature */
output( "\t.long 0x%04x\n", IMAGE_NT_SIGNATURE ); /* Signature */
switch(target_cpu)
{
case CPU_x86: machine = IMAGE_FILE_MACHINE_I386; break;
......@@ -381,105 +381,105 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
case CPU_ALPHA: machine = IMAGE_FILE_MACHINE_ALPHA; break;
case CPU_SPARC: machine = IMAGE_FILE_MACHINE_UNKNOWN; break;
}
fprintf( outfile, "\t%s 0x%04x\n", /* Machine */
output( "\t%s 0x%04x\n", /* Machine */
get_asm_short_keyword(), machine );
fprintf( outfile, "\t%s 0\n", /* NumberOfSections */
output( "\t%s 0\n", /* NumberOfSections */
get_asm_short_keyword() );
fprintf( outfile, "\t.long 0\n" ); /* TimeDateStamp */
fprintf( outfile, "\t.long 0\n" ); /* PointerToSymbolTable */
fprintf( outfile, "\t.long 0\n" ); /* NumberOfSymbols */
fprintf( outfile, "\t%s %d\n", /* SizeOfOptionalHeader */
output( "\t.long 0\n" ); /* TimeDateStamp */
output( "\t.long 0\n" ); /* PointerToSymbolTable */
output( "\t.long 0\n" ); /* NumberOfSymbols */
output( "\t%s %d\n", /* SizeOfOptionalHeader */
get_asm_short_keyword(),
get_ptr_size() == 8 ? IMAGE_SIZEOF_NT_OPTIONAL64_HEADER : IMAGE_SIZEOF_NT_OPTIONAL32_HEADER );
fprintf( outfile, "\t%s 0x%04x\n", /* Characteristics */
output( "\t%s 0x%04x\n", /* Characteristics */
get_asm_short_keyword(), spec->characteristics );
fprintf( outfile, "\t%s 0x%04x\n", /* Magic */
output( "\t%s 0x%04x\n", /* Magic */
get_asm_short_keyword(),
get_ptr_size() == 8 ? IMAGE_NT_OPTIONAL_HDR64_MAGIC : IMAGE_NT_OPTIONAL_HDR32_MAGIC );
fprintf( outfile, "\t.byte 0\n" ); /* MajorLinkerVersion */
fprintf( outfile, "\t.byte 0\n" ); /* MinorLinkerVersion */
fprintf( outfile, "\t.long 0\n" ); /* SizeOfCode */
fprintf( outfile, "\t.long 0\n" ); /* SizeOfInitializedData */
fprintf( outfile, "\t.long 0\n" ); /* SizeOfUninitializedData */
output( "\t.byte 0\n" ); /* MajorLinkerVersion */
output( "\t.byte 0\n" ); /* MinorLinkerVersion */
output( "\t.long 0\n" ); /* SizeOfCode */
output( "\t.long 0\n" ); /* SizeOfInitializedData */
output( "\t.long 0\n" ); /* SizeOfUninitializedData */
/* note: we expand the AddressOfEntryPoint field on 64-bit by overwriting the BaseOfCode field */
fprintf( outfile, "\t%s %s\n", /* AddressOfEntryPoint */
output( "\t%s %s\n", /* AddressOfEntryPoint */
get_asm_ptr_keyword(), asm_name(spec->init_func) );
if (get_ptr_size() == 4)
{
fprintf( outfile, "\t.long 0\n" ); /* BaseOfCode */
fprintf( outfile, "\t.long 0\n" ); /* BaseOfData */
output( "\t.long 0\n" ); /* BaseOfCode */
output( "\t.long 0\n" ); /* BaseOfData */
}
fprintf( outfile, "\t%s __wine_spec_pe_header\n", /* ImageBase */
output( "\t%s __wine_spec_pe_header\n", /* ImageBase */
get_asm_ptr_keyword() );
fprintf( outfile, "\t.long %u\n", page_size ); /* SectionAlignment */
fprintf( outfile, "\t.long %u\n", page_size ); /* FileAlignment */
fprintf( outfile, "\t%s 1,0\n", /* Major/MinorOperatingSystemVersion */
output( "\t.long %u\n", page_size ); /* SectionAlignment */
output( "\t.long %u\n", page_size ); /* FileAlignment */
output( "\t%s 1,0\n", /* Major/MinorOperatingSystemVersion */
get_asm_short_keyword() );
fprintf( outfile, "\t%s 0,0\n", /* Major/MinorImageVersion */
output( "\t%s 0,0\n", /* Major/MinorImageVersion */
get_asm_short_keyword() );
fprintf( outfile, "\t%s %u,%u\n", /* Major/MinorSubsystemVersion */
output( "\t%s %u,%u\n", /* Major/MinorSubsystemVersion */
get_asm_short_keyword(), spec->subsystem_major, spec->subsystem_minor );
fprintf( outfile, "\t.long 0\n" ); /* Win32VersionValue */
fprintf( outfile, "\t.long %s-.L__wine_spec_rva_base\n", /* SizeOfImage */
output( "\t.long 0\n" ); /* Win32VersionValue */
output( "\t.long %s-.L__wine_spec_rva_base\n", /* SizeOfImage */
asm_name("_end") );
fprintf( outfile, "\t.long %u\n", page_size ); /* SizeOfHeaders */
fprintf( outfile, "\t.long 0\n" ); /* CheckSum */
fprintf( outfile, "\t%s 0x%04x\n", /* Subsystem */
output( "\t.long %u\n", page_size ); /* SizeOfHeaders */
output( "\t.long 0\n" ); /* CheckSum */
output( "\t%s 0x%04x\n", /* Subsystem */
get_asm_short_keyword(), spec->subsystem );
fprintf( outfile, "\t%s 0\n", /* DllCharacteristics */
output( "\t%s 0\n", /* DllCharacteristics */
get_asm_short_keyword() );
fprintf( outfile, "\t%s %u,%u\n", /* SizeOfStackReserve/Commit */
output( "\t%s %u,%u\n", /* SizeOfStackReserve/Commit */
get_asm_ptr_keyword(), (spec->stack_size ? spec->stack_size : 1024) * 1024, page_size );
fprintf( outfile, "\t%s %u,%u\n", /* SizeOfHeapReserve/Commit */
output( "\t%s %u,%u\n", /* SizeOfHeapReserve/Commit */
get_asm_ptr_keyword(), (spec->heap_size ? spec->heap_size : 1024) * 1024, page_size );
fprintf( outfile, "\t.long 0\n" ); /* LoaderFlags */
fprintf( outfile, "\t.long 16\n" ); /* NumberOfRvaAndSizes */
output( "\t.long 0\n" ); /* LoaderFlags */
output( "\t.long 16\n" ); /* NumberOfRvaAndSizes */
if (spec->base <= spec->limit) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT] */
fprintf( outfile, "\t.long .L__wine_spec_exports-.L__wine_spec_rva_base,"
output( "\t.long .L__wine_spec_exports-.L__wine_spec_rva_base,"
".L__wine_spec_exports_end-.L__wine_spec_exports\n" );
else
fprintf( outfile, "\t.long 0,0\n" );
output( "\t.long 0,0\n" );
if (has_imports()) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT] */
fprintf( outfile, "\t.long .L__wine_spec_imports-.L__wine_spec_rva_base,"
output( "\t.long .L__wine_spec_imports-.L__wine_spec_rva_base,"
".L__wine_spec_imports_end-.L__wine_spec_imports\n" );
else
fprintf( outfile, "\t.long 0,0\n" );
output( "\t.long 0,0\n" );
if (spec->nb_resources) /* DataDirectory[IMAGE_DIRECTORY_ENTRY_RESOURCE] */
fprintf( outfile, "\t.long .L__wine_spec_resources-.L__wine_spec_rva_base,"
output( "\t.long .L__wine_spec_resources-.L__wine_spec_rva_base,"
".L__wine_spec_resources_end-.L__wine_spec_resources\n" );
else
fprintf( outfile, "\t.long 0,0\n" );
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[3] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[4] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[5] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[6] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[7] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[8] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[9] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[10] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[11] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[12] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[13] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[14] */
fprintf( outfile, "\t.long 0,0\n" ); /* DataDirectory[15] */
fprintf( outfile, "\n\t%s\n", get_asm_string_section() );
fprintf( outfile, "%s\n", asm_globl("__wine_spec_file_name") );
fprintf( outfile, ".L__wine_spec_file_name:\n" );
fprintf( outfile, "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
output( "\t.long 0,0\n" );
output( "\t.long 0,0\n" ); /* DataDirectory[3] */
output( "\t.long 0,0\n" ); /* DataDirectory[4] */
output( "\t.long 0,0\n" ); /* DataDirectory[5] */
output( "\t.long 0,0\n" ); /* DataDirectory[6] */
output( "\t.long 0,0\n" ); /* DataDirectory[7] */
output( "\t.long 0,0\n" ); /* DataDirectory[8] */
output( "\t.long 0,0\n" ); /* DataDirectory[9] */
output( "\t.long 0,0\n" ); /* DataDirectory[10] */
output( "\t.long 0,0\n" ); /* DataDirectory[11] */
output( "\t.long 0,0\n" ); /* DataDirectory[12] */
output( "\t.long 0,0\n" ); /* DataDirectory[13] */
output( "\t.long 0,0\n" ); /* DataDirectory[14] */
output( "\t.long 0,0\n" ); /* DataDirectory[15] */
output( "\n\t%s\n", get_asm_string_section() );
output( "%s\n", asm_globl("__wine_spec_file_name") );
output( ".L__wine_spec_file_name:\n" );
output( "\t%s \"%s\"\n", get_asm_string_keyword(), spec->file_name );
if (target_platform == PLATFORM_APPLE)
fprintf( outfile, "\t.lcomm %s,4\n", asm_name("_end") );
output_stubs( outfile, spec );
output_exports( outfile, spec );
output_imports( outfile, spec );
output_resources( outfile, spec );
output_asm_constructor( outfile, "__wine_spec_init_ctor" );
output_gnu_stack_note( outfile );
output( "\t.lcomm %s,4\n", asm_name("_end") );
output_stubs( spec );
output_exports( spec );
output_imports( spec );
output_resources( spec );
output_asm_constructor( "__wine_spec_init_ctor" );
output_gnu_stack_note();
}
......@@ -488,20 +488,19 @@ void BuildSpec32File( FILE *outfile, DLLSPEC *spec )
*
* Build a Win32 def file from a spec file.
*/
void BuildDef32File( FILE *outfile, DLLSPEC *spec )
void BuildDef32File( DLLSPEC *spec )
{
const char *name;
int i, total;
if (spec_file_name)
fprintf( outfile, "; File generated automatically from %s; do not edit!\n\n",
output( "; File generated automatically from %s; do not edit!\n\n",
spec_file_name );
else
fprintf( outfile, "; File generated automatically; do not edit!\n\n" );
output( "; File generated automatically; do not edit!\n\n" );
fprintf(outfile, "LIBRARY %s\n\n", spec->file_name);
fprintf(outfile, "EXPORTS\n");
output( "LIBRARY %s\n\n", spec->file_name);
output( "EXPORTS\n");
/* Output the exports and relay entry points */
......@@ -520,7 +519,7 @@ void BuildDef32File( FILE *outfile, DLLSPEC *spec )
if (odp->type == TYPE_STUB) continue;
fprintf(outfile, " %s", name);
output( " %s", name );
switch(odp->type)
{
......@@ -531,31 +530,31 @@ void BuildDef32File( FILE *outfile, DLLSPEC *spec )
case TYPE_CDECL:
/* try to reduce output */
if(strcmp(name, odp->link_name) || (odp->flags & FLAG_FORWARD))
fprintf(outfile, "=%s", odp->link_name);
output( "=%s", odp->link_name );
break;
case TYPE_STDCALL:
{
int at_param = strlen(odp->u.func.arg_types) * get_ptr_size();
if (!kill_at) fprintf(outfile, "@%d", at_param);
if (!kill_at) output( "@%d", at_param );
if (odp->flags & FLAG_FORWARD)
{
fprintf(outfile, "=%s", odp->link_name);
output( "=%s", odp->link_name );
}
else if (strcmp(name, odp->link_name)) /* try to reduce output */
{
fprintf(outfile, "=%s", odp->link_name);
if (!kill_at) fprintf(outfile, "@%d", at_param);
output( "=%s", odp->link_name );
if (!kill_at) output( "@%d", at_param );
}
break;
}
default:
assert(0);
}
fprintf( outfile, " @%d", odp->ordinal );
if (!odp->name) fprintf( outfile, " NONAME" );
if (is_data) fprintf( outfile, " DATA" );
if (odp->flags & FLAG_PRIVATE) fprintf( outfile, " PRIVATE" );
fprintf( outfile, "\n" );
output( " @%d", odp->ordinal );
if (!odp->name) output( " NONAME" );
if (is_data) output( " DATA" );
if (odp->flags & FLAG_PRIVATE) output( " PRIVATE" );
output( "\n" );
}
if (!total) warning( "%s: Import library doesn't export anything\n", spec->file_name );
}
......@@ -162,6 +162,18 @@ void warning( const char *msg, ... )
va_end( valist );
}
int output( const char *format, ... )
{
int ret;
va_list valist;
va_start( valist, format );
ret = vfprintf( output_file, format, valist );
va_end( valist );
if (ret < 0) fatal_perror( "Output error" );
return ret;
}
/* get a name for a temp file, automatically cleaned up on exit */
char *get_temp_file_name( const char *prefix, const char *suffix )
{
......@@ -193,31 +205,29 @@ char *get_temp_file_name( const char *prefix, const char *suffix )
}
/* output a standard header for generated files */
void output_standard_file_header( FILE *outfile )
void output_standard_file_header(void)
{
if (spec_file_name)
fprintf( outfile, "/* File generated automatically from %s; do not edit! */\n",
spec_file_name );
output( "/* File generated automatically from %s; do not edit! */\n", spec_file_name );
else
fprintf( outfile, "/* File generated automatically; do not edit! */\n" );
fprintf( outfile,
"/* This file can be copied, modified and distributed without restriction. */\n\n" );
output( "/* File generated automatically; do not edit! */\n" );
output( "/* This file can be copied, modified and distributed without restriction. */\n\n" );
}
/* dump a byte stream into the assembly code */
void dump_bytes( FILE *outfile, const void *buffer, unsigned int size )
void dump_bytes( const void *buffer, unsigned int size )
{
unsigned int i;
const unsigned char *ptr = buffer;
if (!size) return;
fprintf( outfile, "\t.byte " );
output( "\t.byte " );
for (i = 0; i < size - 1; i++, ptr++)
{
if ((i % 16) == 15) fprintf( outfile, "0x%02x\n\t.byte ", *ptr );
else fprintf( outfile, "0x%02x,", *ptr );
if ((i % 16) == 15) output( "0x%02x\n\t.byte ", *ptr );
else output( "0x%02x,", *ptr );
}
fprintf( outfile, "0x%02x\n", *ptr );
output( "0x%02x\n", *ptr );
}
......@@ -520,7 +530,7 @@ const char *func_declaration( const char *func )
}
/* output a size declaration for an assembly function */
void output_function_size( FILE *outfile, const char *name )
void output_function_size( const char *name )
{
switch (target_platform)
{
......@@ -528,13 +538,13 @@ void output_function_size( FILE *outfile, const char *name )
case PLATFORM_WINDOWS:
break;
default:
fprintf( outfile, "\t.size %s, .-%s\n", name, name );
output( "\t.size %s, .-%s\n", name, name );
break;
}
}
/* output the GNU note for non-exec stack */
void output_gnu_stack_note( FILE *outfile )
void output_gnu_stack_note(void)
{
switch (target_platform)
{
......@@ -542,7 +552,7 @@ void output_gnu_stack_note( FILE *outfile )
case PLATFORM_APPLE:
break;
default:
fprintf( outfile, "\t.section .note.GNU-stack,\"\",@progbits\n" );
output( "\t.section .note.GNU-stack,\"\",@progbits\n" );
break;
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment