diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h index ecddcf6143d..c0ef04a4d69 100644 --- a/tools/winebuild/build.h +++ b/tools/winebuild/build.h @@ -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 ); diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 7b9d58120bf..1373599ef50 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -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" ); } diff --git a/tools/winebuild/parser.c b/tools/winebuild/parser.c index 033826c1683..b3a68c8dc9b 100644 --- a/tools/winebuild/parser.c +++ b/tools/winebuild/parser.c @@ -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 ); } diff --git a/tools/winebuild/relay.c b/tools/winebuild/relay.c index d999753d8de..b9a54888bd5 100644 --- a/tools/winebuild/relay.c +++ b/tools/winebuild/relay.c @@ -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 diff --git a/tools/winebuild/spec16.c b/tools/winebuild/spec16.c index 71672d561aa..bdf6d44ed1e 100644 --- a/tools/winebuild/spec16.c +++ b/tools/winebuild/spec16.c @@ -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 diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c index 2651fc2048d..694a99b4bdc 100644 --- a/tools/winebuild/spec32.c +++ b/tools/winebuild/spec32.c @@ -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 diff --git a/tools/winebuild/utils.c b/tools/winebuild/utils.c index be6db981575..93944e7b528 100644 --- a/tools/winebuild/utils.c +++ b/tools/winebuild/utils.c @@ -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 +}