More portable .align directive.
Ignore -delay directive on ppc only.
Added code to call the dll constructors.
diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index ecddcf6..c0ef04a 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -133,6 +133,8 @@
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 7b9d581..1373599 100644
--- a/tools/winebuild/import.c
+++ b/tools/winebuild/import.c
@@ -397,7 +397,7 @@
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 @@
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 @@
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 @@
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 @@
#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 @@
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 @@
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 033826c..b3a68c8 100644
--- a/tools/winebuild/parser.c
+++ b/tools/winebuild/parser.c
@@ -591,8 +591,13 @@
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 d999753..b9a5488 100644
--- a/tools/winebuild/relay.c
+++ b/tools/winebuild/relay.c
@@ -92,7 +92,7 @@
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 @@
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 @@
/* 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 @@
/* 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 @@
/* 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 71672d5..bdf6d44 100644
--- a/tools/winebuild/spec16.c
+++ b/tools/winebuild/spec16.c
@@ -800,6 +800,10 @@
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 2651fc2..694a99b 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -117,7 +117,7 @@
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 @@
/* 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 @@
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 @@
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 @@
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 @@
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 be6db98..93944e7 100644
--- a/tools/winebuild/utils.c
+++ b/tools/winebuild/utils.c
@@ -116,3 +116,104 @@
}
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
+}