2 * Copyright 1993 Robert J. Amstadt
3 * Copyright 1995 Martin von Loewis
4 * Copyright 1995, 1996 Alexandre Julliard
5 * Copyright 1997 Eric Youngdale
18 #include "selectors.h"
20 #ifdef NEED_UNDERSCORE_PREFIX
26 #if defined(__GNUC__) && !defined(__svr4__)
35 TYPE_BYTE, /* byte variable */
36 TYPE_WORD, /* word variable */
37 TYPE_LONG, /* long variable */
38 TYPE_PASCAL_16, /* pascal function with 16-bit return (Win16) */
39 TYPE_PASCAL, /* pascal function with 32-bit return (Win16) */
40 TYPE_REGISTER, /* register function */
41 TYPE_ABS, /* absolute value */
42 TYPE_RETURN, /* simple return value function */
43 TYPE_STUB, /* unimplemented stub */
44 TYPE_STDCALL, /* stdcall function (Win32) */
45 TYPE_CDECL, /* cdecl function (Win32) */
46 TYPE_VARARGS, /* varargs function (Win32) */
47 TYPE_EXTERN, /* external symbol (Win32) */
51 static const char * const TypeNames[TYPE_NBTYPES] =
54 "byte", /* TYPE_BYTE */
55 "word", /* TYPE_WORD */
56 "long", /* TYPE_LONG */
57 "pascal16", /* TYPE_PASCAL_16 */
58 "pascal", /* TYPE_PASCAL */
59 "register", /* TYPE_REGISTER */
60 "equate", /* TYPE_ABS */
61 "return", /* TYPE_RETURN */
62 "stub", /* TYPE_STUB */
63 "stdcall", /* TYPE_STDCALL */
64 "cdecl", /* TYPE_CDECL */
65 "varargs", /* TYPE_VARARGS */
66 "extern" /* TYPE_EXTERN */
69 #define MAX_ORDINALS 1299
71 /* Callback function used for stub functions */
72 #define STUB_CALLBACK \
73 ((SpecType == SPEC_WIN16) ? "RELAY_Unimplemented16": "RELAY_Unimplemented32")
133 static ORDDEF OrdinalDefinitions[MAX_ORDINALS];
135 static SPEC_TYPE SpecType = SPEC_INVALID;
136 static char DLLName[80];
137 static char DLLFileName[80];
139 int Base = MAX_ORDINALS;
144 char *ParseBuffer = NULL;
149 static int debugging = 1;
151 /* Offset of register relative to the start of the CONTEXT struct */
152 #define CONTEXTOFFSET(reg) ((int)&((CONTEXT *)0)->reg)
154 static void *xmalloc (size_t size)
158 res = malloc (size ? size : 1);
161 fprintf (stderr, "Virtual memory exhausted.\n");
168 static void *xrealloc (void *ptr, size_t size)
170 void *res = realloc (ptr, size);
173 fprintf (stderr, "Virtual memory exhausted.\n");
180 static int IsNumberString(char *s)
189 static char *strupper(char *s)
193 for(p = s; *p != '\0'; p++)
199 static char * GetTokenInLine(void)
204 if (ParseNext != ParseBuffer)
206 if (ParseSaveChar == '\0')
208 *ParseNext = ParseSaveChar;
212 * Remove initial white space.
214 for (p = ParseNext; isspace(*p); p++)
217 if ((*p == '\0') || (*p == '#'))
224 if (*token != '(' && *token != ')')
225 while (*p != '\0' && *p != '(' && *p != ')' && !isspace(*p))
235 static char * GetToken(void)
239 if (ParseBuffer == NULL)
241 ParseBuffer = xmalloc(512);
242 ParseNext = ParseBuffer;
246 if (fgets(ParseBuffer, 511, SpecFp) == NULL)
248 if (ParseBuffer[0] != '#')
253 while ((token = GetTokenInLine()) == NULL)
255 ParseNext = ParseBuffer;
259 if (fgets(ParseBuffer, 511, SpecFp) == NULL)
261 if (ParseBuffer[0] != '#')
270 /*******************************************************************
273 * Parse a variable definition.
275 static int ParseVariable( ORDDEF *odp )
280 int value_array_size;
282 char *token = GetToken();
285 fprintf(stderr, "%s:%d: Expected '(' got '%s'\n",
286 SpecName, Line, token);
291 value_array_size = 25;
292 value_array = xmalloc(sizeof(*value_array) * value_array_size);
294 while ((token = GetToken()) != NULL)
299 value_array[n_values++] = strtol(token, &endptr, 0);
300 if (n_values == value_array_size)
302 value_array_size += 25;
303 value_array = xrealloc(value_array,
304 sizeof(*value_array) * value_array_size);
307 if (endptr == NULL || *endptr != '\0')
309 fprintf(stderr, "%s:%d: Expected number value, got '%s'\n",
310 SpecName, Line, token);
317 fprintf(stderr, "%s:%d: End of file in variable declaration\n",
322 odp->u.var.n_values = n_values;
323 odp->u.var.values = xrealloc(value_array, sizeof(*value_array) * n_values);
329 /*******************************************************************
330 * ParseExportFunction
332 * Parse a function definition.
334 static int ParseExportFunction( ORDDEF *odp )
342 if (odp->type == TYPE_STDCALL)
344 fprintf( stderr, "%s:%d: 'stdcall' not supported for Win16\n",
348 if (odp->type == TYPE_CDECL)
350 fprintf( stderr, "%s:%d: 'cdecl' not supported for Win16\n",
356 if ((odp->type == TYPE_PASCAL) || (odp->type == TYPE_PASCAL_16))
358 fprintf( stderr, "%s:%d: 'pascal' not supported for Win32\n",
370 fprintf(stderr, "%s:%d: Expected '(' got '%s'\n",
371 SpecName, Line, token);
375 for (i = 0; i < sizeof(odp->u.func.arg_types)-1; i++)
381 if (!strcmp(token, "word"))
382 odp->u.func.arg_types[i] = 'w';
383 else if (!strcmp(token, "s_word"))
384 odp->u.func.arg_types[i] = 's';
385 else if (!strcmp(token, "long") || !strcmp(token, "segptr"))
386 odp->u.func.arg_types[i] = 'l';
387 else if (!strcmp(token, "ptr"))
388 odp->u.func.arg_types[i] = 'p';
389 else if (!strcmp(token, "str"))
390 odp->u.func.arg_types[i] = 't';
391 else if (!strcmp(token, "segstr"))
392 odp->u.func.arg_types[i] = 'T';
393 else if (!strcmp(token, "double"))
395 odp->u.func.arg_types[i++] = 'l';
396 odp->u.func.arg_types[i] = 'l';
400 fprintf(stderr, "%s:%d: Unknown variable type '%s'\n",
401 SpecName, Line, token);
404 if (SpecType == SPEC_WIN32)
406 if (strcmp(token, "long") &&
407 strcmp(token, "ptr") &&
408 strcmp(token, "double"))
410 fprintf( stderr, "%s:%d: Type '%s' not supported for Win32\n",
411 SpecName, Line, token );
416 if ((*token != ')') || (i >= sizeof(odp->u.func.arg_types)))
418 fprintf( stderr, "%s:%d: Too many arguments\n", SpecName, Line );
421 odp->u.func.arg_types[i] = '\0';
422 if ((odp->type == TYPE_STDCALL) && !i)
423 odp->type = TYPE_CDECL; /* stdcall is the same as cdecl for 0 args */
424 strcpy(odp->u.func.link_name, GetToken());
429 /*******************************************************************
432 * Parse an 'equate' definition.
434 static int ParseEquate( ORDDEF *odp )
438 char *token = GetToken();
439 int value = strtol(token, &endptr, 0);
440 if (endptr == NULL || *endptr != '\0')
442 fprintf(stderr, "%s:%d: Expected number value, got '%s'\n",
443 SpecName, Line, token);
447 odp->u.abs.value = value;
452 /*******************************************************************
455 * Parse a 'return' definition.
457 static int ParseReturn( ORDDEF *odp )
463 odp->u.ret.arg_size = strtol(token, &endptr, 0);
464 if (endptr == NULL || *endptr != '\0')
466 fprintf(stderr, "%s:%d: Expected number value, got '%s'\n",
467 SpecName, Line, token);
472 odp->u.ret.ret_value = strtol(token, &endptr, 0);
473 if (endptr == NULL || *endptr != '\0')
475 fprintf(stderr, "%s:%d: Expected number value, got '%s'\n",
476 SpecName, Line, token);
484 /*******************************************************************
487 * Parse a 'stub' definition.
489 static int ParseStub( ORDDEF *odp )
491 odp->u.func.arg_types[0] = '\0';
492 strcpy( odp->u.func.link_name, STUB_CALLBACK );
497 /*******************************************************************
500 * Parse an 'varargs' definition.
502 static int ParseVarargs( ORDDEF *odp )
506 if (SpecType == SPEC_WIN16)
508 fprintf( stderr, "%s:%d: 'varargs' not supported for Win16\n",
516 fprintf(stderr, "%s:%d: Expected '(' got '%s'\n",
517 SpecName, Line, token);
523 fprintf(stderr, "%s:%d: Expected ')' got '%s'\n",
524 SpecName, Line, token);
528 strcpy( odp->u.vargs.link_name, GetToken() );
533 /*******************************************************************
536 * Parse an 'extern' definition.
538 static int ParseExtern( ORDDEF *odp )
540 if (SpecType == SPEC_WIN16)
542 fprintf( stderr, "%s:%d: 'extern' not supported for Win16\n",
546 strcpy( odp->u.ext.link_name, GetToken() );
551 /*******************************************************************
554 * Parse an ordinal definition.
556 static int ParseOrdinal(int ordinal)
561 if (ordinal >= MAX_ORDINALS)
563 fprintf(stderr, "%s:%d: Ordinal number too large\n", SpecName, Line );
566 if (ordinal > Limit) Limit = ordinal;
567 if (ordinal < Base) Base = ordinal;
569 odp = &OrdinalDefinitions[ordinal];
570 if (!(token = GetToken()))
572 fprintf(stderr, "%s:%d: Expected type after ordinal\n", SpecName, Line);
576 for (odp->type = 0; odp->type < TYPE_NBTYPES; odp->type++)
577 if (TypeNames[odp->type] && !strcmp( token, TypeNames[odp->type] ))
580 if (odp->type >= TYPE_NBTYPES)
583 "%s:%d: Expected type after ordinal, found '%s' instead\n",
584 SpecName, Line, token );
588 if (!(token = GetToken()))
590 fprintf( stderr, "%s:%d: Expected name after type\n", SpecName, Line );
593 strcpy( odp->name, token );
601 return ParseVariable( odp );
607 return ParseExportFunction( odp );
609 return ParseEquate( odp );
611 return ParseReturn( odp );
613 return ParseStub( odp );
615 return ParseVarargs( odp );
617 return ParseExtern( odp );
619 fprintf( stderr, "Should not happen\n" );
625 /*******************************************************************
630 static int ParseTopLevel(void)
634 while ((token = GetToken()) != NULL)
636 if (strcmp(token, "name") == 0)
638 strcpy(DLLName, GetToken());
640 if (!DLLFileName[0]) sprintf( DLLFileName, "%s.DLL", DLLName );
642 else if (strcmp(token, "file") == 0)
644 strcpy(DLLFileName, GetToken());
645 strupper(DLLFileName);
647 else if (strcmp(token, "type") == 0)
650 if (!strcmp(token, "win16" )) SpecType = SPEC_WIN16;
651 else if (!strcmp(token, "win32" )) SpecType = SPEC_WIN32;
654 fprintf(stderr, "%s:%d: Type must be 'win16' or 'win32'\n",
659 else if (strcmp(token, "heap") == 0)
662 if (!IsNumberString(token))
664 fprintf(stderr, "%s:%d: Expected number after heap\n",
668 DLLHeapSize = atoi(token);
670 else if (IsNumberString(token))
675 ordinal = atoi(token);
676 if ((rv = ParseOrdinal(ordinal)) < 0)
682 "%s:%d: Expected name, id, length or ordinal\n",
692 /*******************************************************************
695 * Store a list of ints into a byte array.
697 static int StoreVariableCode( unsigned char *buffer, int size, ORDDEF *odp )
704 for (i = 0; i < odp->u.var.n_values; i++)
705 buffer[i] = odp->u.var.values[i];
708 for (i = 0; i < odp->u.var.n_values; i++)
709 ((unsigned short *)buffer)[i] = odp->u.var.values[i];
712 for (i = 0; i < odp->u.var.n_values; i++)
713 ((unsigned int *)buffer)[i] = odp->u.var.values[i];
716 return odp->u.var.n_values * size;
720 /*******************************************************************
723 * Dump a byte stream into the assembly code.
725 static void DumpBytes( FILE *outfile, const unsigned char *data, int len,
726 const char *section, const char *label_start )
729 if (section) fprintf( outfile, "\t%s\n", section );
730 if (label_start) fprintf( outfile, "%s:\n", label_start );
731 for (i = 0; i < len; i++)
733 if (!(i & 0x0f)) fprintf( outfile, "\t.byte " );
734 fprintf( outfile, "%d", *data++ );
736 fprintf( outfile, "%c", ((i & 0x0f) != 0x0f) ? ',' : '\n' );
738 fprintf( outfile, "\n" );
742 /*******************************************************************
745 * Build the in-memory representation of a 16-bit NE module, and dump it
746 * as a byte stream into the assembly code.
748 static int BuildModule16( FILE *outfile, int max_code_offset,
749 int max_data_offset )
755 SEGTABLEENTRY *pSegment;
762 * OFSTRUCT File information
763 * SEGTABLEENTRY Segment 1 (code)
764 * SEGTABLEENTRY Segment 2 (data)
765 * WORD[2] Resource table (empty)
766 * BYTE[2] Imported names (empty)
767 * BYTE[n] Resident names table
768 * BYTE[n] Entry table
771 buffer = xmalloc( 0x10000 );
773 pModule = (NE_MODULE *)buffer;
774 pModule->magic = IMAGE_OS2_SIGNATURE;
777 pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_BUILTIN | NE_FFLAGS_LIBMODULE;
779 pModule->heap_size = DLLHeapSize;
780 pModule->stack_size = 0;
785 pModule->seg_count = 2;
786 pModule->modref_count = 0;
787 pModule->nrname_size = 0;
788 pModule->modref_table = 0;
789 pModule->nrname_fpos = 0;
790 pModule->moveable_entries = 0;
791 pModule->alignment = 0;
792 pModule->truetype = 0;
793 pModule->os_flags = NE_OSFLAGS_WINDOWS;
794 pModule->misc_flags = 0;
795 pModule->dlls_to_init = 0;
796 pModule->nrname_handle = 0;
797 pModule->min_swap_area = 0;
798 pModule->expected_version = 0x030a;
799 pModule->pe_module = NULL;
801 pModule->self_loading_sel = 0;
803 /* File information */
805 pFileInfo = (OFSTRUCT *)(pModule + 1);
806 pModule->fileinfo = (int)pFileInfo - (int)pModule;
807 memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) );
808 pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName)
809 + strlen(DLLFileName);
810 strcpy( pFileInfo->szPathName, DLLFileName );
811 pstr = (char *)pFileInfo + pFileInfo->cBytes + 1;
815 pSegment = (SEGTABLEENTRY *)pstr;
816 pModule->seg_table = (int)pSegment - (int)pModule;
817 pSegment->filepos = 0;
818 pSegment->size = max_code_offset;
820 pSegment->minsize = max_code_offset;
821 pSegment->selector = 0;
824 pModule->dgroup_entry = (int)pSegment - (int)pModule;
825 pSegment->filepos = 0;
826 pSegment->size = max_data_offset;
827 pSegment->flags = NE_SEGFLAGS_DATA;
828 pSegment->minsize = max_data_offset;
829 pSegment->selector = 0;
834 pword = (WORD *)pSegment;
835 pModule->res_table = (int)pword - (int)pModule;
839 /* Imported names table */
841 pstr = (char *)pword;
842 pModule->import_table = (int)pstr - (int)pModule;
846 /* Resident names table */
848 pModule->name_table = (int)pstr - (int)pModule;
849 /* First entry is module name */
850 *pstr = strlen(DLLName );
851 strcpy( pstr + 1, DLLName );
854 pstr += sizeof(WORD);
855 /* Store all ordinals */
856 odp = OrdinalDefinitions + 1;
857 for (i = 1; i <= Limit; i++, odp++)
859 if (!odp->name[0]) continue;
860 *pstr = strlen( odp->name );
861 strcpy( pstr + 1, odp->name );
862 strupper( pstr + 1 );
865 pstr += sizeof(WORD);
871 pModule->entry_table = (int)pstr - (int)pModule;
873 odp = OrdinalDefinitions + 1;
874 for (i = 1; i <= Limit; i++, odp++)
885 selector = 1; /* Code selector */
891 selector = 2; /* Data selector */
895 selector = 0xfe; /* Constant selector */
899 selector = 0; /* Invalid selector */
903 /* create a new bundle if necessary */
904 if (!bundle || (bundle[0] >= 254) || (bundle[1] != selector))
908 bundle[1] = selector;
916 *(WORD *)pstr = odp->offset;
917 pstr += sizeof(WORD);
922 /* Dump the module content */
924 DumpBytes( outfile, (char *)pModule, (int)pstr - (int)pModule,
925 ".data", "Module_Start" );
926 return (int)pstr - (int)pModule;
930 /*******************************************************************
933 * Build the in-memory representation of a 32-bit pseudo-NE module, and dump it
934 * as a byte stream into the assembly code.
936 static int BuildModule32( FILE *outfile )
946 * OFSTRUCT File information
947 * SEGTABLEENTRY Segment table (empty)
948 * WORD[2] Resource table (empty)
949 * BYTE[2] Imported names (empty)
950 * BYTE[n] Resident names table (1 entry)
951 * BYTE[n] Entry table (empty)
954 buffer = xmalloc( 0x10000 );
956 pModule = (NE_MODULE *)buffer;
957 pModule->magic = IMAGE_OS2_SIGNATURE;
960 pModule->dgroup_entry = 0;
961 pModule->flags = NE_FFLAGS_SINGLEDATA | NE_FFLAGS_BUILTIN |
962 NE_FFLAGS_LIBMODULE | NE_FFLAGS_WIN32;
964 pModule->heap_size = DLLHeapSize;
965 pModule->stack_size = 0;
970 pModule->seg_count = 0;
971 pModule->modref_count = 0;
972 pModule->nrname_size = 0;
973 pModule->modref_table = 0;
974 pModule->nrname_fpos = 0;
975 pModule->moveable_entries = 0;
976 pModule->alignment = 0;
977 pModule->truetype = 0;
978 pModule->os_flags = NE_OSFLAGS_WINDOWS;
979 pModule->misc_flags = 0;
980 pModule->dlls_to_init = 0;
981 pModule->nrname_handle = 0;
982 pModule->min_swap_area = 0;
983 pModule->expected_version = 0x030a;
984 pModule->pe_module = NULL;
986 pModule->self_loading_sel = 0;
988 /* File information */
990 pFileInfo = (OFSTRUCT *)(pModule + 1);
991 pModule->fileinfo = (int)pFileInfo - (int)pModule;
992 memset( pFileInfo, 0, sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName) );
993 pFileInfo->cBytes = sizeof(*pFileInfo) - sizeof(pFileInfo->szPathName)
994 + strlen(DLLFileName);
995 strcpy( pFileInfo->szPathName, DLLFileName );
996 pstr = (char *)pFileInfo + pFileInfo->cBytes + 1;
1000 pModule->seg_table = (int)pstr - (int)pModule;
1002 /* Resource table */
1004 pword = (WORD *)pstr;
1005 pModule->res_table = (int)pword - (int)pModule;
1009 /* Imported names table */
1011 pstr = (char *)pword;
1012 pModule->import_table = (int)pstr - (int)pModule;
1016 /* Resident names table */
1018 pModule->name_table = (int)pstr - (int)pModule;
1019 /* First entry is module name */
1020 *pstr = strlen(DLLName );
1021 strcpy( pstr + 1, DLLName );
1024 pstr += sizeof(WORD);
1029 pModule->entry_table = (int)pstr - (int)pModule;
1032 /* Dump the module content */
1034 DumpBytes( outfile, (char *)pModule, (int)pstr - (int)pModule,
1035 ".data", "Module_Start" );
1036 return (int)pstr - (int)pModule;
1040 /*******************************************************************
1043 * Build a Win32 assembly file from a spec file.
1045 static int BuildSpec32File( char * specfile, FILE *outfile )
1048 int i, module_size, len;
1051 fprintf( outfile, "/* File generated automatically; do not edit! */\n" );
1052 fprintf( outfile, "\t.file\t\"%s\"\n", specfile );
1054 getcwd(buffer, sizeof(buffer));
1057 * The stabs help the internal debugger as they are an indication that it
1058 * is sensible to step into a thunk/trampoline.
1060 fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
1061 fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", specfile);
1064 fprintf( outfile, "\t.text\n" );
1065 fprintf( outfile, "\t.align 4\n" );
1066 fprintf( outfile, "Code_Start:\n\n" );
1068 for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
1079 fprintf( outfile, "/* %s.%d (%s) */\n", DLLName, i, odp->name);
1081 fprintf( outfile, ".stabs \"%s_%d:F1\",36,0,%d,%s_%d\n",
1082 DLLName, i, odp->lineno, DLLName, i);
1084 fprintf( outfile, "%s_%d:\n", DLLName, i );
1086 fprintf( outfile, ".stabn 68,0,%d,0\n", odp->lineno);
1088 fprintf( outfile, "\tpushl %%ebp\n" );
1089 fprintf( outfile, "\tpushl $" PREFIX "%s\n",odp->u.func.link_name);
1090 fprintf( outfile, "\tcall " PREFIX "CallFrom32_%s_%d\n",
1091 (odp->type == TYPE_REGISTER) ? "regs" :
1092 ((odp->type == TYPE_STDCALL) ? "stdcall" : "cdecl"),
1093 strlen(odp->u.func.arg_types));
1094 fprintf( outfile, "\tnop\n" );
1098 fprintf( outfile, "/* %s.%d (%s) */\n", DLLName, i, odp->name);
1100 fprintf( outfile, ".stabs \"%s_%d:F1\",36,0,%d,%s_%d\n",
1101 DLLName, i, odp->lineno, DLLName, i);
1103 fprintf( outfile, "%s_%d:\n", DLLName, i );
1105 fprintf( outfile, ".stabn 68,0,%d,0\n", odp->lineno);
1107 fprintf( outfile, "\tmovl $%d,%%eax\n", odp->u.ret.ret_value );
1108 if (odp->u.ret.arg_size)
1110 fprintf( outfile, "\tret $%d\n", odp->u.ret.arg_size );
1114 fprintf( outfile, "\tret\n" );
1115 fprintf( outfile, "\tnop\n" );
1116 fprintf( outfile, "\tnop\n" );
1121 fprintf( outfile, "/* %s.%d (%s) */\n", DLLName, i, odp->name);
1122 fprintf( outfile, "\t.data\n" );
1123 fprintf( outfile, "%s_%d:\n", DLLName, i );
1124 len = StoreVariableCode( buffer, 1, odp );
1125 DumpBytes( outfile, buffer, len, NULL, NULL );
1126 fprintf( outfile, "\t.text\n" );
1130 fprintf( outfile, "/* %s.%d (%s) */\n",
1131 DLLName, i, odp->name);
1132 fprintf( outfile, "\t.data\n" );
1133 fprintf( outfile, "%s_%d:\n", DLLName, i );
1134 len = StoreVariableCode( buffer, 2, odp );
1135 DumpBytes( outfile, buffer, len, NULL, NULL );
1136 fprintf( outfile, "\t.text\n" );
1140 fprintf( outfile, "/* %s.%d (%s) */\n",
1141 DLLName, i, odp->name);
1142 fprintf( outfile, "\t.data\n" );
1143 fprintf( outfile, "%s_%d:\n", DLLName, i );
1144 len = StoreVariableCode( buffer, 4, odp );
1145 DumpBytes( outfile, buffer, len, NULL, NULL );
1146 fprintf( outfile, "\t.text\n" );
1154 fprintf(stderr,"build: function type %d not available for Win32\n",
1160 module_size = BuildModule32( outfile );
1162 /* Output the DLL functions table for no debugging code */
1164 fprintf( outfile, "\t.text\n" );
1165 fprintf( outfile, "\t.align 4\n" );
1166 fprintf( outfile, "NoDbg_Functions:\n" );
1167 for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
1172 fprintf( outfile, "\t.long 0\n" );
1175 fprintf( outfile, "\t.long " PREFIX "%s\n",odp->u.vargs.link_name);
1178 fprintf( outfile, "\t.long " PREFIX "%s\n", odp->u.ext.link_name );
1182 fprintf( outfile, "\t.long " PREFIX "%s\n", odp->u.func.link_name);
1185 fprintf( outfile, "\t.long %s_%d\n", DLLName, i );
1190 /* Output the DLL functions table for debugging code */
1192 fprintf( outfile, "\t.text\n" );
1193 fprintf( outfile, "\t.align 4\n" );
1194 fprintf( outfile, "Functions:\n" );
1195 for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
1200 fprintf( outfile, "\t.long 0\n" );
1203 fprintf( outfile, "\t.long " PREFIX "%s\n",odp->u.vargs.link_name);
1206 fprintf( outfile, "\t.long " PREFIX "%s\n", odp->u.ext.link_name );
1209 fprintf( outfile, "\t.long %s_%d\n", DLLName, i );
1214 /* Output the DLL names table */
1216 fprintf( outfile, "FuncNames:\n" );
1217 for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
1219 if (odp->type == TYPE_INVALID) fprintf( outfile, "\t.long 0\n" );
1220 else fprintf( outfile, "\t.long Name_%d\n", i );
1223 /* Output the DLL names */
1225 for (i = Base, odp = OrdinalDefinitions + Base; i <= Limit; i++, odp++)
1227 if (odp->type != TYPE_INVALID)
1228 fprintf( outfile, "Name_%d:\t.ascii \"%s\\0\"\n", i, odp->name );
1231 /* Output the DLL descriptor */
1233 fprintf( outfile, "DLLName:\t.ascii \"%s\\0\"\n", DLLName );
1234 fprintf( outfile, "\t.align 4\n" );
1235 fprintf( outfile, "\t.globl " PREFIX "%s_Descriptor\n", DLLName );
1236 fprintf( outfile, PREFIX "%s_Descriptor:\n", DLLName );
1237 fprintf( outfile, "\t.long DLLName\n" ); /* Name */
1238 fprintf( outfile, "\t.long Module_Start\n" ); /* Module start */
1239 fprintf( outfile, "\t.long %d\n", module_size ); /* Module size */
1240 fprintf( outfile, "\t.long %d\n", Base ); /* Base */
1241 fprintf( outfile, "\t.long %d\n", Limit+1-Base ); /* Size */
1242 fprintf( outfile, "\t.long Code_Start\n" ); /* Code start */
1243 fprintf( outfile, "\t.long Functions\n" ); /* Functions */
1244 fprintf( outfile, "\t.long NoDbg_Functions\n" ); /* Funcs without debug*/
1245 fprintf( outfile, "\t.long FuncNames\n" ); /* Function names */
1247 fprintf( outfile, "\t.text\n");
1248 fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
1249 fprintf( outfile, ".Letext:\n");
1255 /*******************************************************************
1258 * Build a Win16 assembly file from a spec file.
1260 static int BuildSpec16File( char * specfile, FILE *outfile )
1264 int code_offset, data_offset, module_size;
1265 unsigned char *data;
1267 data = (unsigned char *)xmalloc( 0x10000 );
1268 memset( data, 0, 16 );
1271 fprintf( outfile, "/* File generated automatically; do not edit! */\n" );
1272 fprintf( outfile, "\t.text\n" );
1273 fprintf( outfile, "Code_Start:\n" );
1276 odp = OrdinalDefinitions;
1277 for (i = 0; i <= Limit; i++, odp++)
1282 odp->offset = 0xffff;
1286 odp->offset = LOWORD(odp->u.abs.value);
1290 odp->offset = data_offset;
1291 data_offset += StoreVariableCode( data + data_offset, 1, odp);
1295 odp->offset = data_offset;
1296 data_offset += StoreVariableCode( data + data_offset, 2, odp);
1300 odp->offset = data_offset;
1301 data_offset += StoreVariableCode( data + data_offset, 4, odp);
1305 fprintf( outfile,"/* %s.%d */\n", DLLName, i);
1306 fprintf( outfile,"\tmovw $%d,%%ax\n",LOWORD(odp->u.ret.ret_value));
1307 fprintf( outfile,"\tmovw $%d,%%dx\n",HIWORD(odp->u.ret.ret_value));
1308 fprintf( outfile,"\t.byte 0x66\n");
1309 if (odp->u.ret.arg_size != 0)
1310 fprintf( outfile, "\tlret $%d\n\n", odp->u.ret.arg_size);
1313 fprintf( outfile, "\tlret\n");
1314 fprintf( outfile, "\tnop\n");
1315 fprintf( outfile, "\tnop\n\n");
1317 odp->offset = code_offset;
1318 code_offset += 12; /* Assembly code is 12 bytes long */
1323 case TYPE_PASCAL_16:
1325 fprintf( outfile, "/* %s.%d */\n", DLLName, i);
1326 fprintf( outfile, "\tpushw %%bp\n" );
1327 fprintf( outfile, "\tpushl $" PREFIX "%s\n",odp->u.func.link_name);
1328 /* FreeBSD does not understand lcall, so do it the hard way */
1329 fprintf( outfile, "\t.byte 0x9a\n" );
1330 fprintf( outfile, "\t.long " PREFIX "CallFrom16_%s_%s\n",
1331 (odp->type == TYPE_REGISTER) ? "regs" :
1332 (odp->type == TYPE_PASCAL) ? "long" : "word",
1333 odp->u.func.arg_types );
1334 fprintf( outfile,"\t.byte 0x%02x,0x%02x\n", /* Some asms don't have .word */
1335 LOBYTE(WINE_CODE_SELECTOR), HIBYTE(WINE_CODE_SELECTOR) );
1336 fprintf( outfile, "\tnop\n" );
1337 fprintf( outfile, "\tnop\n\n" );
1338 odp->offset = code_offset;
1339 code_offset += 16; /* Assembly code is 16 bytes long */
1343 fprintf(stderr,"build: function type %d not available for Win16\n",
1349 if (!code_offset) /* Make sure the code segment is not empty */
1351 fprintf( outfile, "\t.byte 0\n" );
1355 /* Output data segment */
1357 DumpBytes( outfile, data, data_offset, NULL, "Data_Start" );
1359 /* Build the module */
1361 module_size = BuildModule16( outfile, code_offset, data_offset );
1363 /* Output the DLL descriptor */
1365 fprintf( outfile, "\t.text\n" );
1366 fprintf( outfile, "DLLName:\t.ascii \"%s\\0\"\n", DLLName );
1367 fprintf( outfile, "\t.align 4\n" );
1368 fprintf( outfile, "\t.globl " PREFIX "%s_Descriptor\n", DLLName );
1369 fprintf( outfile, PREFIX "%s_Descriptor:\n", DLLName );
1370 fprintf( outfile, "\t.long DLLName\n" ); /* Name */
1371 fprintf( outfile, "\t.long Module_Start\n" ); /* Module start */
1372 fprintf( outfile, "\t.long %d\n", module_size ); /* Module size */
1373 fprintf( outfile, "\t.long Code_Start\n" ); /* Code start */
1374 fprintf( outfile, "\t.long Data_Start\n" ); /* Data start */
1379 /*******************************************************************
1382 * Build an assembly file from a spec file.
1384 static int BuildSpecFile( FILE *outfile, char *specname )
1386 SpecName = specname;
1387 SpecFp = fopen( specname, "r");
1390 fprintf(stderr, "Could not open specification file, '%s'\n", specname);
1394 if (ParseTopLevel() < 0) return -1;
1399 return BuildSpec16File( specname, outfile );
1401 return BuildSpec32File( specname, outfile );
1403 fprintf( stderr, "%s: Missing 'type' declaration\n", specname );
1409 /*******************************************************************
1410 * BuildCall32LargeStack
1412 * Build the function used to switch to the original 32-bit stack
1413 * before calling a 32-bit function from 32-bit code. This is used for
1414 * functions that need a large stack, like X bitmaps functions.
1416 * The generated function has the following prototype:
1417 * int CALLTO32_LargeStack( int (*func)(), void *arg );
1426 static void BuildCall32LargeStack( FILE *outfile )
1428 /* Function header */
1430 fprintf( outfile, "\n\t.align 4\n" );
1432 fprintf( outfile, ".stabs \"CALLTO32_LargeStack:F1\",36,0,0," PREFIX "CALLTO32_LargeStack\n");
1434 fprintf( outfile, "\t.globl " PREFIX "CALLTO32_LargeStack\n" );
1435 fprintf( outfile, PREFIX "CALLTO32_LargeStack:\n" );
1439 fprintf( outfile, "\tpushl %%ebp\n" );
1440 fprintf( outfile, "\tmovl %%esp,%%ebp\n" );
1442 /* Retrieve the original 32-bit stack pointer and switch to it if any */
1444 fprintf( outfile, "\tmovl " PREFIX "IF1632_Original32_esp, %%eax\n" );
1445 fprintf( outfile, "\torl %%eax,%%eax\n" );
1446 fprintf( outfile, "\tje no_orig_esp\n" );
1447 fprintf( outfile, "\tmovl %%eax,%%esp\n" );
1448 fprintf( outfile, "no_orig_esp:\n" );
1450 /* Transfer the argument and call the function */
1452 fprintf( outfile, "\tpushl 12(%%ebp)\n" );
1453 fprintf( outfile, "\tcall 8(%%ebp)\n" );
1455 /* Restore registers and return */
1457 fprintf( outfile, "\tmovl %%ebp,%%esp\n" );
1458 fprintf( outfile, "\tpopl %%ebp\n" );
1459 fprintf( outfile, "\tret\n" );
1463 /*******************************************************************
1464 * TransferArgs16To32
1466 * Get the arguments from the 16-bit stack and push them on the 32-bit stack.
1467 * The 16-bit stack layout is:
1475 static int TransferArgs16To32( FILE *outfile, char *args )
1477 int i, pos16, pos32;
1479 /* Save ebx first */
1481 fprintf( outfile, "\tpushl %%ebx\n" );
1483 /* Get the 32-bit stack pointer */
1485 fprintf( outfile, "\tmovl " PREFIX "IF1632_Saved32_esp,%%ebx\n" );
1487 /* Copy the arguments */
1489 pos16 = 6; /* skip bp and return address */
1492 for (i = strlen(args); i > 0; i--)
1497 case 'w': /* word */
1498 fprintf( outfile, "\tmovzwl %d(%%ebp),%%eax\n", pos16 );
1499 fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n", pos32 );
1503 case 's': /* s_word */
1504 fprintf( outfile, "\tmovswl %d(%%ebp),%%eax\n", pos16 );
1505 fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n", pos32 );
1509 case 'l': /* long or segmented pointer */
1510 case 'T': /* segmented pointer to null-terminated string */
1511 fprintf( outfile, "\tmovl %d(%%ebp),%%eax\n", pos16 );
1512 fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n", pos32 );
1516 case 'p': /* linear pointer */
1517 case 't': /* linear pointer to null-terminated string */
1518 /* Get the selector */
1519 fprintf( outfile, "\tmovw %d(%%ebp),%%ax\n", pos16 + 2 );
1520 /* Get the selector base */
1521 fprintf( outfile, "\tandl $0xfff8,%%eax\n" );
1522 fprintf( outfile, "\tmovl " PREFIX "ldt_copy(%%eax),%%eax\n" );
1523 fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n", pos32 );
1524 /* Add the offset */
1525 fprintf( outfile, "\tmovzwl %d(%%ebp),%%eax\n", pos16 );
1526 fprintf( outfile, "\taddl %%eax,%d(%%ebx)\n", pos32 );
1531 fprintf( stderr, "Unknown arg type '%c'\n", args[i-1] );
1537 fprintf( outfile, "\tpopl %%ebx\n" );
1539 return pos16 - 6; /* Return the size of the 16-bit args */
1543 /*******************************************************************
1546 * Build the context structure on the 32-bit stack.
1548 static void BuildContext16( FILE *outfile )
1550 /* Save ebx first */
1552 fprintf( outfile, "\tpushl %%ebx\n" );
1554 /* Get the 32-bit stack pointer */
1556 fprintf( outfile, "\tmovl " PREFIX "IF1632_Saved32_esp,%%ebx\n" );
1558 /* Store the registers */
1560 fprintf( outfile, "\tpopl %d(%%ebx)\n", /* Get ebx from stack*/
1561 CONTEXTOFFSET(Ebx) - sizeof(CONTEXT) );
1562 fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
1563 CONTEXTOFFSET(Eax) - sizeof(CONTEXT) );
1564 fprintf( outfile, "\tmovl %%ecx,%d(%%ebx)\n",
1565 CONTEXTOFFSET(Ecx) - sizeof(CONTEXT) );
1566 fprintf( outfile, "\tmovl %%edx,%d(%%ebx)\n",
1567 CONTEXTOFFSET(Edx) - sizeof(CONTEXT) );
1568 fprintf( outfile, "\tmovl %%esi,%d(%%ebx)\n",
1569 CONTEXTOFFSET(Esi) - sizeof(CONTEXT) );
1570 fprintf( outfile, "\tmovl %%edi,%d(%%ebx)\n",
1571 CONTEXTOFFSET(Edi) - sizeof(CONTEXT) );
1573 fprintf( outfile, "\tmovzwl -10(%%ebp),%%eax\n" ); /* Get %ds from stack*/
1574 fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
1575 CONTEXTOFFSET(SegDs) - sizeof(CONTEXT) );
1576 fprintf( outfile, "\tmovzwl -6(%%ebp),%%eax\n" ); /* Get %es from stack*/
1577 fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
1578 CONTEXTOFFSET(SegEs) - sizeof(CONTEXT) );
1579 fprintf( outfile, "\tpushfl\n" );
1580 fprintf( outfile, "\tpopl %d(%%ebx)\n",
1581 CONTEXTOFFSET(EFlags) - sizeof(CONTEXT) );
1582 fprintf( outfile, "\tmovl -16(%%ebp),%%eax\n" ); /* Get %ebp from stack */
1583 fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
1584 CONTEXTOFFSET(Ebp) - sizeof(CONTEXT) );
1585 fprintf( outfile, "\tmovzwl 2(%%ebp),%%eax\n" ); /* Get %ip from stack */
1586 fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
1587 CONTEXTOFFSET(Eip) - sizeof(CONTEXT) );
1588 fprintf( outfile, "\tmovzwl 4(%%ebp),%%eax\n" ); /* Get %cs from stack */
1589 fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
1590 CONTEXTOFFSET(SegCs) - sizeof(CONTEXT) );
1591 fprintf( outfile, "\tmovw %%fs,%%ax\n" );
1592 fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
1593 CONTEXTOFFSET(SegFs) - sizeof(CONTEXT) );
1594 fprintf( outfile, "\tmovw %%gs,%%ax\n" );
1595 fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
1596 CONTEXTOFFSET(SegGs) - sizeof(CONTEXT) );
1597 fprintf( outfile, "\tmovw %%ss,%%ax\n" );
1598 fprintf( outfile, "\tmovl %%eax,%d(%%ebx)\n",
1599 CONTEXTOFFSET(SegSs) - sizeof(CONTEXT) );
1601 fprintf( outfile, "\tfsave %d(%%ebx)\n",
1602 CONTEXTOFFSET(FloatSave) - sizeof(CONTEXT) );
1607 /*******************************************************************
1610 * Restore the registers from the context structure
1612 static void RestoreContext16( FILE *outfile )
1614 /* Get the 32-bit stack pointer */
1616 fprintf( outfile, "\tmovl " PREFIX "IF1632_Saved32_esp,%%ebx\n" );
1618 /* Remove everything up to the return address from the 16-bit stack */
1620 fprintf( outfile, "\taddl $18,%%esp\n" );
1622 /* Restore the registers */
1624 fprintf( outfile, "\tmovl %d(%%ebx),%%ecx\n",
1625 CONTEXTOFFSET(Ecx) - sizeof(CONTEXT) );
1626 fprintf( outfile, "\tmovl %d(%%ebx),%%edx\n",
1627 CONTEXTOFFSET(Edx) - sizeof(CONTEXT) );
1628 fprintf( outfile, "\tmovl %d(%%ebx),%%esi\n",
1629 CONTEXTOFFSET(Esi) - sizeof(CONTEXT) );
1630 fprintf( outfile, "\tmovl %d(%%ebx),%%edi\n",
1631 CONTEXTOFFSET(Edi) - sizeof(CONTEXT) );
1632 fprintf( outfile, "\tmovl %d(%%ebx),%%ebp\n",
1633 CONTEXTOFFSET(Ebp) - sizeof(CONTEXT) );
1634 fprintf( outfile, "\tpushw %d(%%ebx)\n", /* Push new ds */
1635 CONTEXTOFFSET(SegDs) - sizeof(CONTEXT) );
1636 fprintf( outfile, "\tpushw %d(%%ebx)\n", /* Push new es */
1637 CONTEXTOFFSET(SegEs) - sizeof(CONTEXT) );
1638 fprintf( outfile, "\tpushl %d(%%ebx)\n",
1639 CONTEXTOFFSET(EFlags) - sizeof(CONTEXT) );
1640 fprintf( outfile, "\tpopfl\n" );
1641 fprintf( outfile, "\tmovl %d(%%ebx),%%eax\n",
1642 CONTEXTOFFSET(Eax) - sizeof(CONTEXT) );
1643 fprintf( outfile, "\tmovl %d(%%ebx),%%ebx\n",
1644 CONTEXTOFFSET(Ebx) - sizeof(CONTEXT) );
1645 fprintf( outfile, "\tpopw %%es\n" ); /* Set es */
1646 fprintf( outfile, "\tpopw %%ds\n" ); /* Set ds */
1650 /*******************************************************************
1651 * BuildCallFrom16Func
1653 * Build a 16-bit-to-Wine callback function. The syntax of the function
1654 * profile is: type_xxxxx, where 'type' is one of 'regs', 'word' or
1655 * 'long' and each 'x' is an argument ('w'=word, 's'=signed word,
1656 * 'l'=long, 'p'=linear pointer, 't'=linear pointer to null-terminated string,
1657 * 'T'=segmented pointer to null-terminated string).
1658 * For register functions, the arguments are ignored, but they are still
1659 * removed from the stack upon return.
1661 * Stack layout upon entry to the callback function:
1663 * (sp+18) word first 16-bit arg
1667 * (sp+8) long 32-bit entry point (used to store edx)
1668 * (sp+6) word high word of cs (always 0, used to store es)
1669 * (sp+4) word low word of cs of 16-bit entry point
1670 * (sp+2) word high word of ip (always 0, used to store ds)
1671 * (sp) word low word of ip of 16-bit entry point
1673 * Added on the stack:
1675 * (sp-6) word saved previous sp
1676 * (sp-8) word saved previous ss
1678 static void BuildCallFrom16Func( FILE *outfile, char *profile )
1683 char *args = profile + 5;
1685 /* Parse function type */
1687 if (!strncmp( "word_", profile, 5 )) short_ret = 1;
1688 else if (!strncmp( "regs_", profile, 5 )) reg_func = 1;
1689 else if (strncmp( "long_", profile, 5 ))
1691 fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
1695 /* Function header */
1697 fprintf( outfile, "\n\t.align 4\n" );
1699 fprintf( outfile, ".stabs \"CallFrom16_%s:F1\",36,0,0," PREFIX "CallFrom16_%s\n",
1702 fprintf( outfile, "\t.globl " PREFIX "CallFrom16_%s\n", profile );
1703 fprintf( outfile, PREFIX "CallFrom16_%s:\n", profile );
1705 /* Setup bp to point to its copy on the stack */
1707 fprintf( outfile, "\tpushl %%ebp\n" ); /* Save the full 32-bit ebp */
1708 fprintf( outfile, "\tmovzwl %%sp,%%ebp\n" );
1709 fprintf( outfile, "\taddw $16,%%bp\n" );
1711 /* Save 16-bit ds and es */
1713 /* Stupid FreeBSD assembler doesn't know these either */
1714 /* fprintf( outfile, "\tmovw %%ds,-10(%%ebp)\n" ); */
1715 fprintf( outfile, "\t.byte 0x66,0x8c,0x5d,0xf6\n" );
1716 /* fprintf( outfile, "\tmovw %%es,-6(%%ebp)\n" ); */
1717 fprintf( outfile, "\t.byte 0x66,0x8c,0x45,0xfa\n" );
1719 /* Restore 32-bit ds and es */
1721 fprintf( outfile, "\tpushl $0x%04x%04x\n",
1722 WINE_DATA_SELECTOR, WINE_DATA_SELECTOR );
1723 fprintf( outfile, "\tpopw %%ds\n" );
1724 fprintf( outfile, "\tpopw %%es\n" );
1727 /* Save the 16-bit stack */
1729 fprintf( outfile, "\tpushl " PREFIX "IF1632_Saved16_ss_sp\n" );
1731 fprintf( outfile,"\tdata16\n");
1733 fprintf( outfile, "\tmovw %%ss," PREFIX "IF1632_Saved16_ss_sp+2\n" );
1734 fprintf( outfile, "\tmovw %%sp," PREFIX "IF1632_Saved16_ss_sp\n" );
1736 /* Transfer the arguments */
1738 if (reg_func) BuildContext16( outfile );
1739 else if (*args) argsize = TransferArgs16To32( outfile, args );
1741 /* Get the address of the API function */
1743 fprintf( outfile, "\tmovl -4(%%ebp),%%eax\n" );
1745 /* If necessary, save %edx over the API function address */
1747 if (!reg_func && short_ret)
1748 fprintf( outfile, "\tmovl %%edx,-4(%%ebp)\n" );
1750 /* Switch to the 32-bit stack */
1752 fprintf( outfile, "\tmovl " PREFIX "IF1632_Saved32_esp,%%ebp\n" );
1753 fprintf( outfile, "\tpushw %%ds\n" );
1754 fprintf( outfile, "\tpopw %%ss\n" );
1755 fprintf( outfile, "\tleal -%d(%%ebp),%%esp\n",
1756 reg_func ? sizeof(CONTEXT) : 4 * strlen(args) );
1757 if (reg_func) /* Push the address of the context struct */
1758 fprintf( outfile, "\tpushl %%esp\n" );
1760 /* Setup %ebp to point to the previous stack frame (built by CallTo16) */
1762 fprintf( outfile, "\taddl $32,%%ebp\n" );
1764 /* Print the debug information before the call */
1768 fprintf( outfile, "\tpushl %%eax\n" );
1769 fprintf( outfile, "\tpushl $Profile_%s\n", profile );
1770 fprintf( outfile, "\tpushl $%d\n", reg_func ? 2 : (short_ret ? 1 : 0));
1771 fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallFrom16\n" );
1772 fprintf( outfile, "\tpopl %%eax\n" );
1773 fprintf( outfile, "\tpopl %%eax\n" );
1774 fprintf( outfile, "\tpopl %%eax\n" );
1777 /* Call the entry point */
1779 fprintf( outfile, "\tcall %%eax\n" );
1781 /* Print the debug information after the call */
1787 /* Push again the address of the context struct in case */
1788 /* it has been removed by an stdcall function */
1789 fprintf( outfile, "\tleal -%d(%%ebp),%%esp\n",
1790 sizeof(CONTEXT) + 32 );
1791 fprintf( outfile, "\tpushl %%esp\n" );
1793 fprintf( outfile, "\tpushl %%eax\n" );
1794 fprintf( outfile, "\tpushl $%d\n", reg_func ? 2 : (short_ret ? 1 : 0));
1795 fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallFrom16Ret\n" );
1796 fprintf( outfile, "\tpopl %%eax\n" );
1797 fprintf( outfile, "\tpopl %%eax\n" );
1801 /* Restore the value of the saved 32-bit stack pointer */
1803 fprintf( outfile, "\tleal -32(%%ebp),%%edx\n" );
1804 fprintf( outfile, "movl %%edx," PREFIX "IF1632_Saved32_esp\n" );
1807 /* Restore the 16-bit stack */
1810 fprintf( outfile, "\tdata16\n");
1812 fprintf( outfile, "\tmovw " PREFIX "IF1632_Saved16_ss_sp+2,%%ss\n" );
1813 fprintf( outfile, "\tmovw " PREFIX "IF1632_Saved16_ss_sp,%%sp\n" );
1814 fprintf( outfile, "\tpopl " PREFIX "IF1632_Saved16_ss_sp\n" );
1818 /* Calc the arguments size */
1834 fprintf( stderr, "Unknown arg type '%c'\n", *args );
1839 /* Restore registers from the context structure */
1840 RestoreContext16( outfile );
1844 /* Restore high 16 bits of ebp */
1845 fprintf( outfile, "\tpopl %%ebp\n" );
1847 /* Restore ds and es */
1848 fprintf( outfile, "\tincl %%esp\n" ); /* Remove ip */
1849 fprintf( outfile, "\tincl %%esp\n" );
1850 fprintf( outfile, "\tpopl %%edx\n" ); /* Remove cs and ds */
1851 fprintf( outfile, "\tmovw %%dx,%%ds\n" ); /* and restore ds */
1852 fprintf( outfile, "\tpopw %%es\n" ); /* Restore es */
1854 if (short_ret) fprintf( outfile, "\tpopl %%edx\n" ); /* Restore edx */
1857 /* Get the return value into dx:ax */
1858 fprintf( outfile, "\tmovl %%eax,%%edx\n" );
1859 fprintf( outfile, "\tshrl $16,%%edx\n" );
1860 /* Remove API entry point */
1861 fprintf( outfile, "\taddl $4,%%esp\n" );
1864 /* Restore low 16 bits of ebp */
1865 fprintf( outfile, "\tpopw %%bp\n" );
1868 /* Remove the arguments and return */
1872 fprintf( outfile, "\t.byte 0x66\n" );
1873 fprintf( outfile, "\tlret $%d\n", argsize );
1877 fprintf( outfile, "\t.byte 0x66\n" );
1878 fprintf( outfile, "\tlret\n" );
1883 /*******************************************************************
1886 * Build a Wine-to-16-bit callback function.
1888 * Stack frame of the callback function:
1892 * (ebp+8) func to call
1893 * (ebp+4) return address
1894 * (ebp) previous ebp
1896 * Prototypes for the CallTo16 functions:
1897 * extern WINAPI WORD CallTo16_word_xxx( FARPROC16 func, args... );
1898 * extern WINAPI LONG CallTo16_long_xxx( FARPROC16 func, args... );
1899 * extern WINAPI LONG CallTo16_wndp_xxx( FARPROC16 func, args... );
1900 * extern WINAPI void CallTo16_regs_( const CONTEXT *context );
1902 static void BuildCallTo16Func( FILE *outfile, char *profile )
1904 int window_proc = 0;
1907 char *args = profile + 5;
1909 if (!strncmp( "word_", profile, 5 )) short_ret = 1;
1910 else if (!strncmp( "regs_", profile, 5 )) reg_func = short_ret = 1;
1911 else if (!strncmp( "wndp_", profile, 5 )) window_proc = 1;
1912 else if (strncmp( "long_", profile, 5 ))
1914 fprintf( stderr, "Invalid function name '%s', ignored\n", profile );
1918 /* Function header */
1920 fprintf( outfile, "\n\t.align 4\n" );
1922 fprintf( outfile, ".stabs \"CallTo16_%s:F1\",36,0,0," PREFIX "CallTo16_%s\n",
1925 fprintf( outfile, "\t.globl " PREFIX "CallTo16_%s\n", profile );
1926 fprintf( outfile, PREFIX "CallTo16_%s:\n", profile );
1930 fprintf( outfile, "\tpushl %%ebp\n" );
1931 fprintf( outfile, "\tmovl %%esp,%%ebp\n" );
1933 /* Call the actual CallTo16 routine (simulate a lcall) */
1935 fprintf( outfile, "\tpushw $0\n" );
1936 fprintf( outfile, "\tpushw %%cs\n" );
1937 fprintf( outfile, "\tcall do_callto16_%s\n", profile );
1941 /* FIXME: this is a hack because of task.c */
1942 if (!strcmp( profile, "word_" ))
1944 fprintf( outfile, ".globl " PREFIX "CALLTO16_Restore\n" );
1945 fprintf( outfile, PREFIX "CALLTO16_Restore:\n" );
1947 fprintf( outfile, "\tpopl %%ebp\n" );
1948 fprintf( outfile, "\tret $%d\n", strlen(args) + 1 );
1950 /* Start of the actual CallTo16 routine */
1952 /* Save the 32-bit registers */
1954 fprintf( outfile, "do_callto16_%s:\n", profile );
1955 fprintf( outfile, "\tpushl %%ebx\n" );
1956 fprintf( outfile, "\tpushl %%ecx\n" );
1957 fprintf( outfile, "\tpushl %%edx\n" );
1958 fprintf( outfile, "\tpushl %%esi\n" );
1959 fprintf( outfile, "\tpushl %%edi\n" );
1961 /* Save the 32-bit stack */
1963 fprintf( outfile, "\tpushl " PREFIX "IF1632_Saved32_esp\n" );
1964 fprintf( outfile, "\tmovl %%esp," PREFIX "IF1632_Saved32_esp\n" );
1965 fprintf( outfile, "\tmovl %%ebp,%%ebx\n" );
1967 /* Print debugging info */
1971 /* Push the address of the first argument */
1972 fprintf( outfile, "\tleal 8(%%ebx),%%eax\n" );
1973 fprintf( outfile, "\tpushl $%d\n", reg_func ? -1 : strlen(args) );
1974 fprintf( outfile, "\tpushl %%eax\n" );
1975 fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallTo16\n" );
1976 fprintf( outfile, "\tpopl %%eax\n" );
1977 fprintf( outfile, "\tpopl %%eax\n" );
1980 /* Switch to the 16-bit stack */
1983 fprintf( outfile,"\tdata16\n");
1985 fprintf( outfile, "\tmovw " PREFIX "IF1632_Saved16_ss_sp+2,%%ss\n" );
1986 fprintf( outfile, "\tmovw " PREFIX "IF1632_Saved16_ss_sp,%%sp\n" );
1988 /* Transfer the arguments */
1992 /* Get the registers. ebx is handled later on. */
1993 fprintf( outfile, "\tmovl 8(%%ebx),%%ebx\n" );
1994 fprintf( outfile, "\tmovl %d(%%ebx),%%eax\n", CONTEXTOFFSET(SegEs) );
1995 fprintf( outfile, "\tmovw %%ax,%%es\n" );
1996 fprintf( outfile, "\tmovl %d(%%ebx),%%ebp\n", CONTEXTOFFSET(Ebp) );
1997 fprintf( outfile, "\tmovl %d(%%ebx),%%eax\n", CONTEXTOFFSET(Eax) );
1998 fprintf( outfile, "\tmovl %d(%%ebx),%%ecx\n", CONTEXTOFFSET(Ecx) );
1999 fprintf( outfile, "\tmovl %d(%%ebx),%%edx\n", CONTEXTOFFSET(Edx) );
2000 fprintf( outfile, "\tmovl %d(%%ebx),%%esi\n", CONTEXTOFFSET(Esi) );
2001 fprintf( outfile, "\tmovl %d(%%ebx),%%edi\n", CONTEXTOFFSET(Edi) );
2003 else /* not a register function */
2005 int pos = 12; /* first argument position */
2007 /* Make %bp point to the previous stackframe (built by CallFrom16) */
2008 fprintf( outfile, "\tmovzwl %%sp,%%ebp\n" );
2009 fprintf( outfile, "\taddw $20,%%bp\n" );
2015 case 'w': /* word */
2016 fprintf( outfile, "\tpushw %d(%%ebx)\n", pos );
2018 case 'l': /* long */
2019 fprintf( outfile, "\tpushl %d(%%ebx)\n", pos );
2022 fprintf( stderr, "Unexpected case '%c' in BuildCallTo16Func\n",
2029 /* Push the return address */
2031 fprintf( outfile, "\tpushl " PREFIX "CALLTO16_RetAddr_%s\n",
2032 short_ret ? "word" : "long" );
2036 /* Push the called routine address */
2038 fprintf( outfile, "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(SegCs) );
2039 fprintf( outfile, "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(Eip) );
2041 /* Get the 16-bit ds */
2043 fprintf( outfile, "\tpushw %d(%%ebx)\n", CONTEXTOFFSET(SegDs) );
2044 /* Get ebx from the 32-bit stack */
2045 fprintf( outfile, "\tmovl %d(%%ebx),%%ebx\n", CONTEXTOFFSET(Ebx) );
2046 fprintf( outfile, "\tpopw %%ds\n" );
2050 /* Push the called routine address */
2052 fprintf( outfile, "\tpushl 8(%%ebx)\n" );
2056 /* set ax to hInstance and initialize es and ds to ss */
2058 fprintf( outfile, "\tmovw -10(%%ebp),%%ax\n" );
2059 fprintf( outfile, "\tmovw %%ss, %%cx\n" );
2060 fprintf( outfile, "\tmovw %%cx, %%ds\n" );
2061 fprintf( outfile, "\tmovw %%cx, %%es\n" );
2065 /* Jump to the called routine */
2067 fprintf( outfile, "\t.byte 0x66\n" );
2068 fprintf( outfile, "\tlret\n" );
2072 /*******************************************************************
2075 * Build the return code for 16-bit callbacks
2077 static void BuildRet16Func( FILE *outfile )
2079 fprintf( outfile, "\t.globl " PREFIX "CALLTO16_Ret_word\n" );
2080 fprintf( outfile, "\t.globl " PREFIX "CALLTO16_Ret_long\n" );
2082 /* Put return value into eax */
2084 fprintf( outfile, PREFIX "CALLTO16_Ret_long:\n" );
2085 fprintf( outfile, "\tshll $16,%%edx\n" );
2086 fprintf( outfile, "\tmovw %%ax,%%dx\n" );
2087 fprintf( outfile, "\tmovl %%edx,%%eax\n" );
2088 fprintf( outfile, PREFIX "CALLTO16_Ret_word:\n" );
2090 /* Restore 32-bit segment registers */
2092 fprintf( outfile, "\tmovw $0x%04x,%%bx\n", WINE_DATA_SELECTOR );
2094 fprintf( outfile, "\tdata16\n");
2096 fprintf( outfile, "\tmovw %%bx,%%ds\n" );
2098 fprintf( outfile, "\tdata16\n");
2100 fprintf( outfile, "\tmovw %%bx,%%es\n" );
2102 fprintf( outfile, "\tdata16\n");
2104 fprintf( outfile, "\tmovw %%bx,%%ss\n" );
2106 /* Restore the 32-bit stack */
2108 fprintf( outfile, "\tmovl " PREFIX "IF1632_Saved32_esp,%%esp\n" );
2109 fprintf( outfile, "\tpopl " PREFIX "IF1632_Saved32_esp\n" );
2111 /* Restore the 32-bit registers */
2113 fprintf( outfile, "\tpopl %%edi\n" );
2114 fprintf( outfile, "\tpopl %%esi\n" );
2115 fprintf( outfile, "\tpopl %%edx\n" );
2116 fprintf( outfile, "\tpopl %%ecx\n" );
2117 fprintf( outfile, "\tpopl %%ebx\n" );
2119 /* Return to caller */
2121 /* fprintf( outfile, "\tpopl %%ebp\n" );*/
2122 fprintf( outfile, "\tlret\n" );
2124 /* Declare the return address variables */
2126 fprintf( outfile, "\t.data\n" );
2127 fprintf( outfile, "\t.globl " PREFIX "CALLTO16_RetAddr_word\n" );
2128 fprintf( outfile, "\t.globl " PREFIX "CALLTO16_RetAddr_long\n" );
2129 fprintf( outfile, PREFIX "CALLTO16_RetAddr_word:\t.long 0\n" );
2130 fprintf( outfile, PREFIX "CALLTO16_RetAddr_long:\t.long 0\n" );
2131 fprintf( outfile, "\t.text\n" );
2135 /*******************************************************************
2138 * Build the CONTEXT structure on the stack.
2140 static void BuildContext32( FILE *outfile )
2142 /* Build the context structure */
2144 fprintf( outfile, "\tpushw $0\n" );
2145 fprintf( outfile, "\tpushw %%ss\n" );
2146 fprintf( outfile, "\tpushl %%eax\n" ); /* %esp */
2147 fprintf( outfile, "\tpushfl\n" );
2148 fprintf( outfile, "\tpushw $0\n" );
2149 fprintf( outfile, "\tpushw %%cs\n" );
2150 fprintf( outfile, "\tsubl $8,%%esp\n" ); /* %eip + %ebp */
2152 fprintf( outfile, "\tpushl %%eax\n" );
2153 fprintf( outfile, "\tpushl %%ecx\n" );
2154 fprintf( outfile, "\tpushl %%edx\n" );
2155 fprintf( outfile, "\tpushl %%ebx\n" );
2156 fprintf( outfile, "\tpushl %%esi\n" );
2157 fprintf( outfile, "\tpushl %%edi\n" );
2159 fprintf( outfile, "\txorl %%eax,%%eax\n" );
2160 fprintf( outfile, "\tmovw %%ds,%%ax\n" );
2161 fprintf( outfile, "\tpushl %%eax\n" );
2162 fprintf( outfile, "\tmovw %%es,%%ax\n" );
2163 fprintf( outfile, "\tpushl %%eax\n" );
2164 fprintf( outfile, "\tmovw %%fs,%%ax\n" );
2165 fprintf( outfile, "\tpushl %%eax\n" );
2166 fprintf( outfile, "\tmovw %%gs,%%ax\n" );
2167 fprintf( outfile, "\tpushl %%eax\n" );
2169 fprintf( outfile, "\tsubl $%d,%%esp\n",
2170 sizeof(FLOATING_SAVE_AREA) + 6 * sizeof(DWORD) /* DR regs */ );
2171 fprintf( outfile, "\tpushl $0x0001001f\n" ); /* ContextFlags */
2173 fprintf( outfile, "\tfsave %d(%%esp)\n", CONTEXTOFFSET(FloatSave) );
2175 fprintf( outfile, "\tmovl 4(%%ebp),%%eax\n" ); /* %eip at time of call */
2176 fprintf( outfile, "\tmovl %%eax,%d(%%esp)\n", CONTEXTOFFSET(Eip) );
2177 fprintf( outfile, "\tmovl 0(%%ebp),%%eax\n" ); /* %ebp at time of call */
2178 fprintf( outfile, "\tmovl %%eax,%d(%%esp)\n", CONTEXTOFFSET(Ebp) );
2179 fprintf( outfile, "\tleal 8(%%ebp),%%eax\n" ); /* %esp at time of call */
2180 fprintf( outfile, "\tmovl %%eax,%d(%%esp)\n", CONTEXTOFFSET(Esp) );
2182 /* Push pointer to context */
2184 fprintf( outfile, "\tpushl %%esp\n" );
2188 /*******************************************************************
2191 * Restore the registers from the context structure.
2192 * All registers except %cs and %ss are restored.
2194 static void RestoreContext32( FILE *outfile )
2196 /* Restore the context structure */
2198 fprintf( outfile, "\tleal %d(%%ebp),%%esp\n", -sizeof(CONTEXT)-8 );
2199 fprintf( outfile, "\tfrstor %d(%%esp)\n", CONTEXTOFFSET(FloatSave) );
2201 /* Store flags over the relay addr */
2202 fprintf( outfile, "\tmovl %d(%%esp),%%eax\n", CONTEXTOFFSET(EFlags) );
2203 fprintf( outfile, "\tmovl %%eax,%d(%%esp)\n", sizeof(CONTEXT) );
2205 /* Get the new stack addr */
2206 fprintf( outfile, "\tmovl %d(%%esp),%%ebx\n", CONTEXTOFFSET(Esp) );
2208 /* Set eip and ebp value onto the new stack */
2209 fprintf( outfile, "\tmovl %d(%%esp),%%eax\n", CONTEXTOFFSET(Eip) );
2210 fprintf( outfile, "\tmovl %%eax,-4(%%ebx)\n" ); /* %eip at time of call */
2211 fprintf( outfile, "\tmovl %d(%%esp),%%eax\n", CONTEXTOFFSET(Ebp) );
2212 fprintf( outfile, "\tmovl %%eax,-8(%%ebx)\n" ); /* %ebp at time of call */
2214 /* Set ebp to point to the new stack */
2215 fprintf( outfile, "\tleal -8(%%ebx),%%ebp\n" );
2217 /* Restore all registers */
2218 fprintf( outfile, "\taddl $%d,%%esp\n",
2219 sizeof(FLOATING_SAVE_AREA) + 7 * sizeof(DWORD) );
2220 fprintf( outfile, "\tpopl %%eax\n" );
2221 fprintf( outfile, "\tmovw %%ax,%%gs\n" );
2222 fprintf( outfile, "\tpopl %%eax\n" );
2223 fprintf( outfile, "\tmovw %%ax,%%fs\n" );
2224 fprintf( outfile, "\tpopl %%eax\n" );
2225 fprintf( outfile, "\tmovw %%ax,%%es\n" );
2226 fprintf( outfile, "\tpopl %%eax\n" );
2227 fprintf( outfile, "\tmovw %%ax,%%ds\n" );
2229 fprintf( outfile, "\tpopl %%edi\n" );
2230 fprintf( outfile, "\tpopl %%esi\n" );
2231 fprintf( outfile, "\tpopl %%ebx\n" );
2232 fprintf( outfile, "\tpopl %%edx\n" );
2233 fprintf( outfile, "\tpopl %%ecx\n" );
2234 fprintf( outfile, "\tpopl %%eax\n" );
2236 fprintf( outfile, "\taddl $%d,%%esp\n",
2237 6 * sizeof(DWORD) /* %ebp + %eip + %cs + %efl + %esp + %ss */ );
2238 fprintf( outfile, "\tpopfl\n" );
2242 /*******************************************************************
2243 * BuildCallFrom32Func
2245 * Build a 32-bit-to-Wine call-back function.
2246 * 'args' is the number of dword arguments.
2254 * (ebp-4) entry point
2255 * (ebp-8) relay addr
2257 static void BuildCallFrom32Func( FILE *outfile, const char *profile )
2259 int args, stdcall, reg_func;
2261 if (!strncmp( profile, "stdcall", 7 ))
2265 args = atoi( profile + 8 );
2267 else if (!strncmp( profile, "cdecl", 5 ))
2269 stdcall = reg_func = 0;
2270 args = atoi( profile + 6 );
2272 else if (!strncmp( profile, "regs", 4 ))
2274 stdcall = reg_func = 1;
2275 args = atoi( profile + 5 );
2279 fprintf( stderr, "Invalid function profile '%s', ignored\n", profile );
2283 /* Function header */
2285 fprintf( outfile, "\n\t.align 4\n" );
2287 fprintf( outfile, ".stabs \"CallFrom32_%s:F1\",36,0,0," PREFIX "CallFrom32_%s\n",
2290 fprintf( outfile, "\t.globl " PREFIX "CallFrom32_%s\n", profile );
2291 fprintf( outfile, PREFIX "CallFrom32_%s:\n", profile );
2295 fprintf( outfile, "\tleal 8(%%esp),%%ebp\n" );
2297 /* Transfer the arguments */
2299 if (reg_func) BuildContext32( outfile );
2304 for (i = args; i > 0; i--)
2305 fprintf( outfile, "\tpushl %d(%%ebp)\n", 4 * i + 4 );
2309 /* Push the address of the arguments. The called function will */
2310 /* ignore this if it really takes no arguments. */
2311 fprintf( outfile, "\tleal 8(%%ebp),%%eax\n" );
2312 fprintf( outfile, "\tpushl %%eax\n" );
2318 fprintf( outfile, "\tmovw %%ds,%%ax\n" );
2319 fprintf( outfile, "\tmovw %%ax,%%es\n" );
2322 /* Print the debugging info */
2326 fprintf( outfile, "\tpushl $%d\n", /* Nb args */
2327 reg_func ? args | 0x80000000 : args);
2328 fprintf( outfile, "\tpushl %%ebp\n" );
2329 fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallFrom32\n" );
2330 fprintf( outfile, "\tadd $8, %%esp\n" );
2333 /* Call the function */
2335 fprintf( outfile, "\tcall -4(%%ebp)\n" );
2337 /* Print the debugging info */
2341 fprintf( outfile, "\tpushl %%eax\n" );
2342 fprintf( outfile, "\tpushl $%d\n", /* Nb args */
2343 reg_func ? args | 0x80000000 : args);
2344 fprintf( outfile, "\tpushl %%ebp\n" );
2345 fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallFrom32Ret\n" );
2346 fprintf( outfile, "\tpopl %%eax\n" );
2347 fprintf( outfile, "\tpopl %%eax\n" );
2348 fprintf( outfile, "\tpopl %%eax\n" );
2351 if (reg_func) RestoreContext32( outfile );
2353 fprintf( outfile, "\tmovl %%ebp,%%esp\n" );
2354 fprintf( outfile, "\tpopl %%ebp\n" );
2356 /* Return, removing arguments */
2358 if (args && stdcall) fprintf( outfile, "\tret $%d\n", args * 4 );
2359 else fprintf( outfile, "\tret\n" );
2363 /*******************************************************************
2366 * Build a Wine-to-32-bit callback function.
2368 * Stack frame of the callback function:
2372 * (ebp+8) func to call
2373 * (ebp+4) return address
2374 * (ebp) previous ebp
2376 * Prototype for the CallTo32 functions:
2377 * extern LONG CallTo32_nn( FARPROC32 func, args... );
2379 static void BuildCallTo32Func( FILE *outfile, int args )
2381 /* Function header */
2383 fprintf( outfile, "\n\t.align 4\n" );
2385 fprintf( outfile, ".stabs \"CallTo32_%d:F1\",36,0,0," PREFIX "CallTo32_%d\n",
2388 fprintf( outfile, "\t.globl " PREFIX "CallTo32_%d\n", args );
2389 fprintf( outfile, PREFIX "CallTo32_%d:\n", args );
2393 fprintf( outfile, "\tpushl %%ebp\n" );
2394 fprintf( outfile, "\tmovl %%esp,%%ebp\n" );
2396 /* Transfer arguments */
2401 for (i = args; i > 0; i--)
2402 fprintf( outfile, "\tpushl %d(%%ebp)\n", 4 * i + 8 );
2405 /* Print the debugging output */
2409 fprintf( outfile, "\tpushl $%d\n", args );
2410 fprintf( outfile, "\tpushl 8(%%ebp)\n" );
2411 fprintf( outfile, "\tcall " PREFIX "RELAY_DebugCallTo32\n" );
2412 fprintf( outfile, "\taddl $8,%%esp\n" );
2415 /* Call the function */
2417 fprintf( outfile, "\tcall 8(%%ebp)\n" );
2419 /* Return to Wine */
2421 fprintf( outfile, "\tmovl %%ebp,%%esp\n" );
2422 fprintf( outfile, "\tpopl %%ebp\n" );
2423 if (args) fprintf( outfile, "\tret $%d\n", args );
2424 else fprintf( outfile, "\tret\n" );
2428 /*******************************************************************
2431 * Build the spec files
2433 static int BuildSpec( FILE *outfile, int argc, char *argv[] )
2436 for (i = 2; i < argc; i++)
2437 if (BuildSpecFile( outfile, argv[i] ) < 0) return -1;
2442 /*******************************************************************
2445 * Build the 16-bit-to-Wine callbacks
2447 static int BuildCallFrom16( FILE *outfile, char * outname, int argc, char *argv[] )
2454 fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
2455 fprintf( outfile, "\t.text\n" );
2458 fprintf( outfile, "\t.file\t\"%s\"\n", outname );
2459 getcwd(buffer, sizeof(buffer));
2462 * The stabs help the internal debugger as they are an indication that it
2463 * is sensible to step into a thunk/trampoline.
2465 fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
2466 fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", outname);
2467 fprintf( outfile, "\t.text\n" );
2468 fprintf( outfile, "\t.align 4\n" );
2469 fprintf( outfile, "Code_Start:\n\n" );
2472 /* Build the callback functions */
2474 for (i = 2; i < argc; i++) BuildCallFrom16Func( outfile, argv[i] );
2476 /* Output the argument debugging strings */
2480 fprintf( outfile, "/* Argument strings */\n" );
2481 for (i = 2; i < argc; i++)
2483 fprintf( outfile, "Profile_%s:\n", argv[i] );
2484 fprintf( outfile, "\t.ascii \"%s\\0\"\n", argv[i] + 5 );
2489 fprintf( outfile, "\t.text\n");
2490 fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
2491 fprintf( outfile, ".Letext:\n");
2498 /*******************************************************************
2501 * Build the Wine-to-16-bit callbacks
2503 static int BuildCallTo16( FILE *outfile, char * outname, int argc, char *argv[] )
2510 fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
2511 fprintf( outfile, "\t.text\n" );
2514 fprintf( outfile, "\t.file\t\"%s\"\n", outname );
2515 getcwd(buffer, sizeof(buffer));
2518 * The stabs help the internal debugger as they are an indication that it
2519 * is sensible to step into a thunk/trampoline.
2521 fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
2522 fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", outname);
2523 fprintf( outfile, "\t.text\n" );
2524 fprintf( outfile, "\t.align 4\n" );
2525 fprintf( outfile, "Code_Start:\n\n" );
2528 fprintf( outfile, "\t.globl " PREFIX "CALLTO16_Start\n" );
2529 fprintf( outfile, PREFIX "CALLTO16_Start:\n" );
2531 /* Build the callback functions */
2533 for (i = 2; i < argc; i++) BuildCallTo16Func( outfile, argv[i] );
2535 /* Output the 16-bit return code */
2537 BuildRet16Func( outfile );
2539 fprintf( outfile, "\t.globl " PREFIX "CALLTO16_End\n" );
2540 fprintf( outfile, PREFIX "CALLTO16_End:\n" );
2543 fprintf( outfile, "\t.text\n");
2544 fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
2545 fprintf( outfile, ".Letext:\n");
2552 /*******************************************************************
2555 * Build the 32-bit-to-Wine callbacks
2557 static int BuildCallFrom32( FILE *outfile, char * outname, int argc, char *argv[] )
2564 fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
2565 fprintf( outfile, "\t.text\n" );
2568 fprintf( outfile, "\t.file\t\"%s\"\n", outname );
2569 getcwd(buffer, sizeof(buffer));
2572 * The stabs help the internal debugger as they are an indication that it
2573 * is sensible to step into a thunk/trampoline.
2575 fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
2576 fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", outname);
2577 fprintf( outfile, "\t.text\n" );
2578 fprintf( outfile, "\t.align 4\n" );
2579 fprintf( outfile, "Code_Start:\n\n" );
2582 /* Build the callback functions */
2584 for (i = 2; i < argc; i++) BuildCallFrom32Func( outfile, argv[i] );
2587 fprintf( outfile, "\t.text\n");
2588 fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
2589 fprintf( outfile, ".Letext:\n");
2596 /*******************************************************************
2599 * Build the Wine-to-32-bit callbacks
2601 static int BuildCallTo32( FILE *outfile, char * outname,
2602 int argc, char *argv[] )
2609 fprintf( outfile, "/* File generated automatically. Do not edit! */\n\n" );
2610 fprintf( outfile, "\t.text\n" );
2613 * Throw in a couple of stabs. The internal debugger doesn't really
2614 * care about trying to step through this crap, but we use the file
2615 * names as an indication that we should just step through it to whatever
2616 * is on the other side.
2619 fprintf( outfile, "\t.file\t\"%s\"\n", outname );
2620 getcwd(buffer, sizeof(buffer));
2623 * The stabs help the internal debugger as they are an indication that it
2624 * is sensible to step into a thunk/trampoline.
2626 fprintf( outfile, ".stabs \"%s/\",100,0,0,Code_Start\n", buffer);
2627 fprintf( outfile, ".stabs \"%s\",100,0,0,Code_Start\n", outname);
2628 fprintf( outfile, "\t.text\n" );
2629 fprintf( outfile, "\t.align 4\n" );
2630 fprintf( outfile, "Code_Start:\n\n" );
2633 /* Build the 32-bit large stack callback */
2635 BuildCall32LargeStack( outfile );
2637 /* Build the callback functions */
2639 for (i = 2; i < argc; i++) BuildCallTo32Func( outfile, atoi(argv[i]) );
2642 fprintf( outfile, "\t.text\n");
2643 fprintf( outfile, "\t.stabs \"\",100,0,0,.Letext\n");
2644 fprintf( outfile, ".Letext:\n");
2651 /*******************************************************************
2654 static void usage(void)
2656 fprintf(stderr, "usage: build [-o outfile] -spec SPECNAMES\n"
2657 " build [-o outfile] -callfrom16 FUNCTION_PROFILES\n"
2658 " build [-o outfile] -callto16 FUNCTION_PROFILES\n"
2659 " build [-o outfile] -callfrom32 FUNCTION_PROFILES\n"
2660 " build [-o outfile] -callto32 FUNCTION_PROFILES\n");
2665 /*******************************************************************
2668 int main(int argc, char **argv)
2670 char *outname = NULL;
2671 FILE *outfile = stdout;
2674 if (argc <= 2) usage();
2676 if (!strcmp( argv[1], "-o" ))
2681 if (argc <= 2) usage();
2682 if (!(outfile = fopen( outname, "w" )))
2684 fprintf( stderr, "Unable to create output file '%s'\n", outname );
2689 if (!strcmp( argv[1], "-spec" ))
2690 res = BuildSpec( outfile, argc, argv );
2691 else if (!strcmp( argv[1], "-callfrom16" ))
2692 res = BuildCallFrom16( outfile, outname, argc, argv );
2693 else if (!strcmp( argv[1], "-callto16" ))
2694 res = BuildCallTo16( outfile, outname, argc, argv );
2695 else if (!strcmp( argv[1], "-callfrom32" ))
2696 res = BuildCallFrom32( outfile, outname, argc, argv );
2697 else if (!strcmp( argv[1], "-callto32" ))
2698 res = BuildCallTo32( outfile, outname, argc, argv );