More portable .align directive.

Ignore -delay directive on ppc only.
Added code to call the dll constructors.
This commit is contained in:
Josh DuBois 2001-02-13 02:06:38 +00:00 committed by Alexandre Julliard
parent 4b1eb5171c
commit 0b64cfb3f7
7 changed files with 167 additions and 14 deletions

View File

@ -133,6 +133,8 @@ extern void fatal_perror( const char *msg, ... );
extern void warning( const char *msg, ... );
extern void dump_bytes( FILE *outfile, const unsigned char *data, int len,
const char *label, int constant );
extern int get_alignment(int alignBoundary);
extern void add_import_dll( const char *name, int delay );
extern void add_ignore_symbol( const char *name );
extern int resolve_imports( FILE *outfile );

View File

@ -397,7 +397,7 @@ static int output_immediate_imports( FILE *outfile )
fprintf( outfile, "#ifndef __GNUC__\nstatic void __asm__dummy_import(void) {\n#endif\n\n" );
pos = 20 * (nb_imm + 1); /* offset of imports.data from start of imports */
fprintf( outfile, "asm(\".data\\n\\t.align 8\\n\"\n" );
fprintf( outfile, "asm(\".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
for (i = 0; i < nb_imports; i++)
{
if (dll_imports[i]->delay) continue;
@ -436,6 +436,27 @@ static int output_immediate_imports( FILE *outfile )
fprintf( outfile, "ld [%%g1+%%o7], %%g1\\n\\t" );
fprintf( outfile, "jmp %%g1\\n\\trestore\\n" );
}
#elif defined(__PPC__)
fprintf(outfile, "\taddi 1, 1, -0x4\\n\"\n");
fprintf(outfile, "\t\"\\tstw 9, 0(1)\\n\"\n");
fprintf(outfile, "\t\"\\taddi 1, 1, -0x4\\n\"\n");
fprintf(outfile, "\t\"\\tstw 8, 0(1)\\n\"\n");
fprintf(outfile, "\t\"\\taddi 1, 1, -0x4\\n\"\n");
fprintf(outfile, "\t\"\\tstw 7, 0(1)\\n\"\n");
fprintf(outfile, "\t\"\\tlis 9,imports+%d@ha\\n\"\n", pos);
fprintf(outfile, "\t\"\\tla 8,imports+%d@l(9)\\n\"\n", pos);
fprintf(outfile, "\t\"\\tlwz 7, 0(8)\\n\"\n");
fprintf(outfile, "\t\"\\tmtctr 7\\n\"\n");
fprintf(outfile, "\t\"\\tlwz 7, 0(1)\\n\"\n");
fprintf(outfile, "\t\"\\taddi 1, 1, 0x4\\n\"\n");
fprintf(outfile, "\t\"\\tlwz 8, 0(1)\\n\"\n");
fprintf(outfile, "\t\"\\taddi 1, 1, 0x4\\n\"\n");
fprintf(outfile, "\t\"\\tlwz 9, 0(1)\\n\"\n");
fprintf(outfile, "\t\"\\taddi 1, 1, 0x4\\n\"\n");
fprintf(outfile, "\t\"\\tbctr\\n");
#else
#error You need to define import thunks for your architecture!
#endif
@ -563,7 +584,7 @@ static int output_delayed_imports( FILE *outfile )
fprintf( outfile, "static void __asm__dummy_delay_import(void) {\n" );
fprintf( outfile, "#endif\n" );
fprintf( outfile, "asm(\".align 8\\n\"\n" );
fprintf( outfile, "asm(\".align %d\\n\"\n", get_alignment(8) );
fprintf( outfile, " \"\\t" __ASM_FUNC("__wine_delay_load_asm") "\\n\"\n" );
fprintf( outfile, " \"" PREFIX "__wine_delay_load_asm:\\n\"\n" );
#if defined(__i386__)
@ -575,6 +596,8 @@ static int output_delayed_imports( FILE *outfile )
fprintf( outfile, " \"\\tcall __wine_delay_load\\n\"\n" );
fprintf( outfile, " \"\\tmov %%g1, %%o0\\n\"\n" );
fprintf( outfile, " \"\\tjmp %%o0\\n\\trestore\\n\"\n" );
#elif defined(__PPC__)
fprintf(outfile, "#error: DELAYED IMPORTS NOT SUPPORTED ON PPC!!!\n");
#else
#error You need to defined delayed import thunks for your architecture!
#endif
@ -594,6 +617,8 @@ static int output_delayed_imports( FILE *outfile )
#elif defined(__sparc__)
fprintf( outfile, " \"\\tset %d, %%g1\\n\"\n", (idx << 16) | j );
fprintf( outfile, " \"\\tb,a __wine_delay_load_asm\\n\"\n" );
#elif defined(__PPC__)
fprintf(outfile, "#error: DELAYED IMPORTS NOT SUPPORTED ON PPC!!!\n");
#else
#error You need to defined delayed import thunks for your architecture!
#endif
@ -601,7 +626,7 @@ static int output_delayed_imports( FILE *outfile )
idx++;
}
fprintf( outfile, "\n \".data\\n\\t.align 8\\n\"\n" );
fprintf( outfile, "\n \".data\\n\\t.align %d\\n\"\n", get_alignment(8) );
pos = nb_delayed * 32;
for (i = 0; i < nb_imports; i++)
{
@ -636,8 +661,11 @@ static int output_delayed_imports( FILE *outfile )
fprintf( outfile, "ld [%%g1+%%o7], %%g1\\n\\t" );
fprintf( outfile, "jmp %%g1\\n\\trestore\\n" );
}
#elif defined(__PPC__)
fprintf(outfile, "#error: DELAYED IMPORTS NOT SUPPORTED ON PPC!!!\n");
#else
#error You need to define import thunks for your architecture!
#error You need to define delayed import thunks for your architecture!
#endif
fprintf( outfile, "\"\n" );
}

View File

@ -591,8 +591,13 @@ SPEC_TYPE ParseTopLevel( FILE *file )
name = GetToken(0);
if (!strcmp(name, "delay"))
{
name = GetToken(0);
#ifndef __PPC__
delay = 1;
#else
warning( "The 'delay' option is not yet supported on the PPC. 'delay' will be ignored.\n");
#endif /* __PPC__ */
}
else fatal_error( "Unknown option '%s' for import directive\n", name );
}

View File

@ -92,7 +92,7 @@ static void BuildCallFrom16Core( FILE *outfile, int reg_func, int thunk, int sho
char *name = thunk? "thunk" : reg_func? "regs" : short_ret? "word" : "long";
/* Function header */
fprintf( outfile, "\n\t.align 4\n" );
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
#ifdef USE_STABS
fprintf( outfile, ".stabs \"__wine_call_from_16_%s:F1\",36,0,0," PREFIX "__wine_call_from_16_%s\n", name, name);
#endif
@ -448,7 +448,7 @@ static void BuildCallTo16Core( FILE *outfile, int short_ret, int reg_func )
short_ret? "word" : "long";
/* Function header */
fprintf( outfile, "\n\t.align 4\n" );
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
#ifdef USE_STABS
fprintf( outfile, ".stabs \"wine_call_to_16_%s:F1\",36,0,0," PREFIX "wine_call_to_16_%s\n",
name, name);
@ -725,7 +725,7 @@ static void BuildRet16Func( FILE *outfile )
/* Declare the return address and data selector variables */
fprintf( outfile, "\n\t.align 4\n" );
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
fprintf( outfile, "\t.globl " PREFIX "CallTo16_DataSelector\n" );
fprintf( outfile, PREFIX "CallTo16_DataSelector:\t.long 0\n" );
fprintf( outfile, "\t.globl " PREFIX "CallTo16_RetAddr\n" );
@ -830,7 +830,7 @@ static void BuildCallTo32CBClient( FILE *outfile, BOOL isEx )
/* Function header */
fprintf( outfile, "\n\t.align 4\n" );
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
#ifdef USE_STABS
fprintf( outfile, ".stabs \"CALL32_%s:F1\",36,0,0," PREFIX "CALL32_%s\n",
name, name );
@ -1019,7 +1019,7 @@ static void BuildCallFrom32Regs( FILE *outfile )
/* Function header */
fprintf( outfile, "\n\t.align 4\n" );
fprintf( outfile, "\n\t.align %d\n", get_alignment(4) );
#ifdef USE_STABS
fprintf( outfile, ".stabs \"CALL32_Regs:F1\",36,0,0," PREFIX "CALL32_Regs\n" );
#endif

View File

@ -800,6 +800,10 @@ void BuildSpec16File( FILE *outfile )
fprintf( outfile, " \"\\tcall " PREFIX "__wine_spec_%s_init\\n\"\n", DLLName );
fprintf( outfile, " \"\\tnop\\n\"\n" );
fprintf( outfile, " \"\\t.previous\\n\");\n" );
#elif defined(__PPC__)
fprintf( outfile, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" );
fprintf( outfile, " \"\\tbl " PREFIX "__wine_spec_%s_init\\n\"\n", DLLName );
fprintf( outfile, " \"\\t.previous\\n\");\n" );
#else
#error You need to define the DLL constructor for your architecture
#endif

View File

@ -117,7 +117,7 @@ static int output_exports( FILE *outfile, int nr_exports )
if (!nr_exports) return 0;
fprintf( outfile, "asm(\".data\\n\"\n" );
fprintf( outfile, " \"\\t.align 4\\n\"\n" );
fprintf( outfile, " \"\\t.align %d\\n\"\n", get_alignment(4) );
fprintf( outfile, " \"" PREFIX "__wine_spec_exports:\\n\"\n" );
/* export directory header */
@ -194,7 +194,7 @@ static int output_exports( FILE *outfile, int nr_exports )
/* output the function names */
fprintf( outfile, " \"\\t.text\\n\"\n" );
fprintf( outfile, " \"\\t.text 1\\n\"\n" );
fprintf( outfile, " \"__wine_spec_exp_names:\\n\"\n" );
for (i = 0; i < nb_names; i++)
fprintf( outfile, " \"\\t" STRING " \\\"%s\\\"\\n\"\n", Names[i]->name );
@ -226,7 +226,7 @@ static int output_exports( FILE *outfile, int nr_exports )
if (odp && odp->type == TYPE_FORWARD)
fprintf( outfile, " \"\\t" STRING " \\\"%s\\\"\\n\"\n", odp->link_name );
}
fprintf( outfile, " \"\\t.align 4\\n\"\n" );
fprintf( outfile, " \"\\t.align %d\\n\"\n", get_alignment(4) );
total_size += (fwd_size + 3) & ~3;
}
@ -402,12 +402,13 @@ static void output_register_funcs( FILE *outfile )
if (odp->type != TYPE_REGISTER) continue;
name = make_internal_name( odp, "regs" );
fprintf( outfile,
"asm(\".align 4\\n\\t\"\n"
"asm(\".align %d\\n\\t\"\n"
" \"" __ASM_FUNC("%s") "\\n\\t\"\n"
" \"" PREFIX "%s:\\n\\t\"\n"
" \"call " PREFIX "CALL32_Regs\\n\\t\"\n"
" \".long " PREFIX "%s\\n\\t\"\n"
" \".byte %d,%d\");\n",
get_alignment(4),
name, name, odp->link_name,
4 * strlen(odp->u.func.arg_types), 4 * strlen(odp->u.func.arg_types) );
}
@ -448,7 +449,7 @@ void BuildSpec32File( FILE *outfile )
fprintf( outfile, "extern char pe_header[];\n" );
fprintf( outfile, "asm(\".section .text\\n\\t\"\n" );
fprintf( outfile, " \".align %ld\\n\"\n", page_size );
fprintf( outfile, " \".align %d\\n\"\n", get_alignment(page_size) );
fprintf( outfile, " \"pe_header:\\t.fill %ld,1,0\\n\\t\");\n", page_size );
fprintf( outfile, "static const char dllname[] = \"%s\";\n\n", DLLName );
@ -693,6 +694,18 @@ void BuildSpec32File( FILE *outfile )
fprintf( outfile, " \"\\tnop\\n\"\n" );
fprintf( outfile, " \"\\t.previous\\n\");\n" );
}
#elif defined(__PPC__)
fprintf( outfile, "asm(\"\\t.section\t.init ,\\\"ax\\\"\\n\"\n" );
fprintf( outfile, " \"\\tbl " PREFIX "__wine_spec_%s_init\\n\"\n",
DLLName );
fprintf( outfile, " \"\\t.previous\\n\");\n" );
if (nr_debug)
{
fprintf( outfile, "asm(\"\\t.section\t.fini ,\\\"ax\\\"\\n\"\n" );
fprintf( outfile, " \"\\tbl " PREFIX "__wine_spec_%s_fini\\n\"\n",
DLLName );
fprintf( outfile, " \"\\t.previous\\n\");\n" );
}
#else
#error You need to define the DLL constructor for your architecture
#endif

View File

@ -116,3 +116,104 @@ void dump_bytes( FILE *outfile, const unsigned char *data, int len,
}
fprintf( outfile, "\n};\n" );
}
/*****************************************************************
* Function: get_alignment
*
* Description:
* According to the info page for gas, the .align directive behaves
* differently on different systems. On some architectures, the
* argument of a .align directive is the number of bytes to pad to, so
* to align on an 8-byte boundary you'd say
* .align 8
* On other systems, the argument is "the number of low-order zero bits
* that the location counter must have after advancement." So to
* align on an 8-byte boundary you'd say
* .align 3
*
* The reason gas is written this way is that it's trying to mimick
* native assemblers for the various architectures it runs on. gas
* provides other directives that work consistantly across
* architectures, but of course we want to work on all arches with or
* without gas. Hence this function.
*
*
* Parameters:
* alignBoundary -- the number of bytes to align to.
* If we're on an architecture where
* the assembler requires a 'number
* of low-order zero bits' as a
* .align argument, then this number
* must be a power of 2.
*
*/
int get_alignment(int alignBoundary)
{
#ifdef __PPC__
int n = 0;
switch(alignBoundary)
{
case 2:
n = 1;
break;
case 4:
n = 2;
break;
case 8:
n = 3;
break;
case 16:
n = 4;
break;
case 32:
n = 5;
break;
case 64:
n = 6;
break;
case 128:
n = 7;
break;
case 256:
n = 8;
break;
case 512:
n = 9;
break;
case 1024:
n = 10;
break;
case 2048:
n = 11;
break;
case 4096:
n = 12;
break;
case 8192:
n = 13;
break;
case 16384:
n = 14;
break;
case 32768:
n = 15;
break;
case 65536:
n = 16;
break;
default:
fatal_error("Alignment to %d-byte boundary not supported on this architecture.\n",
alignBoundary);
}
return n;
#elif defined(__i386__) || defined(__sparc__)
return alignBoundary;
#else
#error "How does the '.align' assembler directive work on your architecture?"
#endif
}