Commit 7662ea10 authored by Alexandre Julliard's avatar Alexandre Julliard

Made register and interrupt flags instead of entry point types, so

that we can have both stdcall and cdecl register functions. Changed 16-bit .spec.c file generation to avoid including builtin16.h.
parent 99ed342d
......@@ -228,9 +228,9 @@ $(SUBDIRS:%=%/__uninstall__): dummy
# Misc. rules
$(SPEC_SRCS:.spec=.spec.c): $(WINEBUILD) $(TOPSRCDIR)/include/builtin16.h
$(SPEC_SRCS:.spec=.spec.c): $(WINEBUILD)
$(GLUE:.c=.glue.c): $(WINEBUILD) $(TOPSRCDIR)/include/builtin16.h
$(GLUE:.c=.glue.c): $(WINEBUILD)
$(RC_SRCS:.rc=.res): $(WRC)
......
......@@ -61,8 +61,8 @@ rsrc version16.res
52 pascal16 FreeProcInstance(segptr) FreeProcInstance16
53 stub CallProcInstance
54 pascal16 GetInstanceData(word word word) GetInstanceData16
55 register Catch(ptr) Catch16
56 register Throw(ptr word) Throw16
55 pascal -register Catch(ptr) Catch16
56 pascal -register Throw(ptr word) Throw16
57 pascal16 GetProfileInt(str str s_word) GetProfileInt16
58 pascal16 GetProfileString(str str str ptr word) GetProfileString16
59 pascal16 WriteProfileString(str str str) WriteProfileString16
......@@ -98,7 +98,7 @@ rsrc version16.res
88 pascal lstrcpy(segptr str) lstrcpy16
89 pascal lstrcat(segstr str) lstrcat16
90 pascal16 lstrlen(str) lstrlen16
91 register InitTask() InitTask16
91 pascal -register InitTask() InitTask16
92 pascal GetTempDrive(word) GetTempDrive
93 pascal16 GetCodeHandle(segptr) GetCodeHandle16
94 pascal16 DefineHandleTable(word) DefineHandleTable16
......@@ -109,14 +109,14 @@ rsrc version16.res
99 stub GetLPErrMode
100 pascal16 ValidateCodeSegments() KERNEL_nop
101 stub NoHookDosCall
102 register DOS3Call() DOS3Call
103 register NetBIOSCall() NetBIOSCall16
102 pascal -register DOS3Call() DOS3Call
103 pascal -register NetBIOSCall() NetBIOSCall16
104 pascal16 GetCodeInfo(segptr ptr) GetCodeInfo16
105 pascal16 GetExeVersion() GetExeVersion16
106 pascal SetSwapAreaSize(word) SetSwapAreaSize16
107 pascal16 SetErrorMode(word) SetErrorMode16
108 pascal16 SwitchStackTo(word word word) SwitchStackTo16 # STO in W2.0
109 register SwitchStackBack() SwitchStackBack16 # SBACK in W2.0
109 pascal -register SwitchStackBack() SwitchStackBack16 # SBACK in W2.0
110 pascal PatchCodeHandle(word) PatchCodeHandle16
111 pascal GlobalWire(word) GlobalWire16
112 pascal16 GlobalUnWire(word) GlobalUnWire16
......@@ -211,7 +211,7 @@ rsrc version16.res
200 pascal16 ValidateFreeSpaces() KERNEL_nop
201 stub ReplaceInst
202 stub RegisterPtrace
203 register DebugBreak() DebugBreak16
203 pascal -register DebugBreak() DebugBreak16
204 stub SwapRecording
205 stub CVWBreak
206 pascal16 AllocSelectorArray(word) AllocSelectorArray16
......@@ -274,7 +274,7 @@ rsrc version16.res
324 pascal16 LogError(word ptr) LogError16
325 pascal16 LogParamError(word ptr ptr) LogParamError16
326 pascal16 IsRomFile(word) IsRomFile16
327 register K327() HandleParamError
327 pascal -register K327() HandleParamError
328 pascal16 _DebugOutput() _DebugOutput
329 pascal16 K329(str word) DebugFillBuffer
332 variable THHOOK(0 0 0 0 0 0 0 0)
......@@ -313,7 +313,7 @@ rsrc version16.res
360 pascal16 OpenFileEx(str ptr word) OpenFile16
361 pascal16 PIGLET_361() KERNEL_nop
362 stub ThunkTerminateProcess
365 register GlobalChangeLockCount(word word) GlobalChangeLockCount16
365 pascal -register GlobalChangeLockCount(word word) GlobalChangeLockCount16
# 403-404 are common to all versions
......@@ -382,8 +382,8 @@ rsrc version16.res
469 stub WOAGimmeTitle
470 stub WOADestroyConsole
471 pascal GetCurrentProcessId() GetCurrentProcessId
472 register MapHInstLS() MapHInstLS
473 register MapHInstSL() MapHInstSL
472 pascal -register MapHInstLS() MapHInstLS
473 pascal -register MapHInstSL() MapHInstSL
474 pascal CloseW32Handle(long) CloseHandle
475 pascal16 GetTEBSelectorFS() GetTEBSelectorFS16
476 pascal ConvertToGlobalHandle(long) ConvertToGlobalHandle
......@@ -482,7 +482,7 @@ rsrc version16.res
601 stub FreeCodeAlias
602 pascal16 GetDummyModuleHandleDS() GetDummyModuleHandleDS16
603 stub KERNEL_603 # OutputDebugString (?)
604 register CBClientGlueSL() CBClientGlueSL
604 pascal -register CBClientGlueSL() CBClientGlueSL
# FIXME: 605 is duplicate of 562
605 pascal AllocSLThunkletCallback_dup(long long) AllocSLThunkletCallback16
# FIXME: 606 is duplicate of 561
......@@ -502,16 +502,16 @@ rsrc version16.res
617 pascal16 GetMenu32Size(ptr) GetMenu32Size16
618 pascal16 GetDialog32Size(ptr) GetDialog32Size16
619 pascal16 RegisterCBClient(word segptr long) RegisterCBClient16
620 register CBClientThunkSL() CBClientThunkSL
621 register CBClientThunkSLEx() CBClientThunkSLEx
620 pascal -register CBClientThunkSL() CBClientThunkSL
621 pascal -register CBClientThunkSLEx() CBClientThunkSLEx
622 pascal16 UnRegisterCBClient(word segptr long) UnRegisterCBClient16
623 pascal16 InitCBClient(long) InitCBClient16
624 pascal SetFastQueue(long long) SetFastQueue16
625 pascal GetFastQueue() GetFastQueue16
626 stub SmashEnvironment
627 pascal16 IsBadFlatReadWritePtr(segptr long word) IsBadFlatReadWritePtr16
630 register C16ThkSL() C16ThkSL
631 register C16ThkSL01() C16ThkSL01
630 pascal -register C16ThkSL() C16ThkSL
631 pascal -register C16ThkSL01() C16ThkSL01
651 pascal ThunkConnect16(str str word long ptr str word) ThunkConnect16
652 stub IsThreadId
653 stub OkWithKernelToChangeUsers
......@@ -529,7 +529,7 @@ rsrc version16.res
701 stub SSOnBigStack
702 stub SSCall
703 stub CallProc32WFix
704 register SSConfirmSmallStack() SSConfirmSmallStack
704 pascal -register SSConfirmSmallStack() SSConfirmSmallStack
# Win95 krnl386.exe also exports ordinals 802-864,
......
......@@ -16,7 +16,6 @@
#include "winerror.h"
#include "wine/winbase16.h"
#include "builtin16.h"
#include "callback.h"
#include "debugtools.h"
#include "flatthunk.h"
......@@ -28,6 +27,11 @@
DEFAULT_DEBUG_CHANNEL(thunk);
#ifdef __i386__
extern void __wine_call_from_16_thunk();
#else
static void __wine_call_from_16_thunk() { }
#endif
/***********************************************************************
* *
......
......@@ -2,7 +2,7 @@ name win87em
type win16
owner kernel32
1 register _fpMath() WIN87_fpmath
1 pascal -register _fpMath() WIN87_fpmath
3 pascal16 __WinEm87Info(ptr word) WIN87_WinEm87Info
4 pascal16 __WinEm87Restore(ptr word) WIN87_WinEm87Restore
5 pascal16 __WinEm87Save(ptr word) WIN87_WinEm87Save
......@@ -4,4 +4,4 @@ owner kernel32
1 stub WINDEBUG
2 stub WEP
3 register WinNotify() WinNotify16
3 pascal -register WinNotify() WinNotify16
......@@ -3,43 +3,43 @@ type win16
owner kernel32
# Interrupt vectors 0-255 are ordinals 100-355
# The 'interrupt' keyword takes care of the flags pushed on the stack by the interrupt
117 interrupt INT_Int11Handler() INT_Int11Handler
118 interrupt INT_Int12Handler() INT_Int12Handler
119 interrupt INT_Int13Handler() INT_Int13Handler
121 interrupt INT_Int15Handler() INT_Int15Handler
126 interrupt INT_Int1aHandler() INT_Int1aHandler
132 interrupt INT_Int20Handler() INT_Int20Handler
133 interrupt INT_Int21Handler() DOS3Call
# The '-interrupt' keyword takes care of the flags pushed on the stack by the interrupt
117 pascal -interrupt INT_Int11Handler() INT_Int11Handler
118 pascal -interrupt INT_Int12Handler() INT_Int12Handler
119 pascal -interrupt INT_Int13Handler() INT_Int13Handler
121 pascal -interrupt INT_Int15Handler() INT_Int15Handler
126 pascal -interrupt INT_Int1aHandler() INT_Int1aHandler
132 pascal -interrupt INT_Int20Handler() INT_Int20Handler
133 pascal -interrupt INT_Int21Handler() DOS3Call
# Note: int 25 and 26 don't pop the flags from the stack
137 register INT_Int25Handler() INT_Int25Handler
138 register INT_Int26Handler() INT_Int26Handler
142 interrupt INT_Int2aHandler() INT_Int2aHandler
147 interrupt INT_Int2fHandler() INT_Int2fHandler
149 interrupt INT_Int31Handler() INT_Int31Handler
161 interrupt INT_Int3dHandler() INT_Int3dHandler
165 interrupt INT_Int41Handler() INT_Int41Handler
175 interrupt INT_Int4bHandler() INT_Int4bHandler
192 interrupt INT_Int5cHandler() NetBIOSCall16
137 pascal -register INT_Int25Handler() INT_Int25Handler
138 pascal -register INT_Int26Handler() INT_Int26Handler
142 pascal -interrupt INT_Int2aHandler() INT_Int2aHandler
147 pascal -interrupt INT_Int2fHandler() INT_Int2fHandler
149 pascal -interrupt INT_Int31Handler() INT_Int31Handler
161 pascal -interrupt INT_Int3dHandler() INT_Int3dHandler
165 pascal -interrupt INT_Int41Handler() INT_Int41Handler
175 pascal -interrupt INT_Int4bHandler() INT_Int4bHandler
192 pascal -interrupt INT_Int5cHandler() NetBIOSCall16
# default handler for unimplemented interrupts
356 interrupt INT_DefaultHandler() INT_DefaultHandler
356 pascal -interrupt INT_DefaultHandler() INT_DefaultHandler
# VxDs. The first Vxd is at 400
#
#400+VXD_ID register <VxD handler>() <VxD handler>
#400+VXD_ID pascal -register <VxD handler>() <VxD handler>
#
401 register VXD_VMM() VXD_VMM
405 register VXD_Timer() VXD_Timer
409 register VXD_Reboot() VXD_Reboot
410 register VXD_VDD() VXD_VDD
412 register VXD_VMD() VXD_VMD
414 register VXD_Comm() VXD_Comm
#415 register VXD_Printer() VXD_Printer
423 register VXD_Shell() VXD_Shell
433 register VXD_PageFile() VXD_PageFile
438 register VXD_APM() VXD_APM
439 register VXD_VXDLoader() VXD_VXDLoader
445 register VXD_Win32s() VXD_Win32s
451 register VXD_ConfigMG() VXD_ConfigMG
455 register VXD_Enable() VXD_Enable
1490 register VXD_TimerAPI() VXD_TimerAPI
401 pascal -register VXD_VMM() VXD_VMM
405 pascal -register VXD_Timer() VXD_Timer
409 pascal -register VXD_Reboot() VXD_Reboot
410 pascal -register VXD_VDD() VXD_VDD
412 pascal -register VXD_VMD() VXD_VMD
414 pascal -register VXD_Comm() VXD_Comm
#415 pascal -register VXD_Printer() VXD_Printer
423 pascal -register VXD_Shell() VXD_Shell
433 pascal -register VXD_PageFile() VXD_PageFile
438 pascal -register VXD_APM() VXD_APM
439 pascal -register VXD_VXDLoader() VXD_VXDLoader
445 pascal -register VXD_Win32s() VXD_Win32s
451 pascal -register VXD_ConfigMG() VXD_ConfigMG
455 pascal -register VXD_Enable() VXD_Enable
1490 pascal -register VXD_TimerAPI() VXD_TimerAPI
......@@ -878,11 +878,11 @@ debug_channels (atom cdrom console debug delayhlp dll dosfs dosmem file fixup
@ stub __eGetStatusWord
@ stdcall -ret64 _alldiv(long long long long) _alldiv
@ stdcall -ret64 _allmul(long long long long) _allmul
@ register -i386 _alloca_probe() NTDLL_alloca_probe
@ stdcall -register -i386 _alloca_probe() NTDLL_alloca_probe
@ stdcall -ret64 _allrem(long long long long) _allrem
@ stdcall -ret64 _aulldiv(long long long long) _aulldiv
@ stdcall -ret64 _aullrem(long long long long) _aullrem
@ register -i386 _chkstk() NTDLL_chkstk
@ stdcall -register -i386 _chkstk() NTDLL_chkstk
@ stub _fltused
@ cdecl _ftol() NTDLL__ftol
@ cdecl _itoa(long ptr long) _itoa
......
......@@ -21,6 +21,16 @@
DEFAULT_DEBUG_CHANNEL(module);
typedef struct
{
void *module_start; /* 32-bit address of the module data */
int module_size; /* Size of the module data */
void *code_start; /* 32-bit address of DLL code */
void *data_start; /* 32-bit address of DLL data */
const char *owner; /* 32-bit dll that contains this dll */
const void *rsrc; /* resources data */
} BUILTIN16_DESCRIPTOR;
/* Table of all built-in DLLs */
#define MAX_DLLS 50
......@@ -168,63 +178,6 @@ HMODULE16 BUILTIN_LoadModule( LPCSTR name )
/***********************************************************************
* BUILTIN_GetEntryPoint16
*
* Return the ordinal, name, and type info corresponding to a CS:IP address.
* This is used only by relay debugging.
*/
LPCSTR BUILTIN_GetEntryPoint16( STACK16FRAME *frame, LPSTR name, WORD *pOrd )
{
WORD i, max_offset;
register BYTE *p;
NE_MODULE *pModule;
ET_BUNDLE *bundle;
ET_ENTRY *entry;
if (!(pModule = NE_GetPtr( FarGetOwner16( GlobalHandle16( frame->module_cs ) ))))
return NULL;
max_offset = 0;
*pOrd = 0;
bundle = (ET_BUNDLE *)((BYTE *)pModule + pModule->entry_table);
do
{
entry = (ET_ENTRY *)((BYTE *)bundle+6);
for (i = bundle->first + 1; i <= bundle->last; i++)
{
if ((entry->offs < frame->entry_ip)
&& (entry->segnum == 1) /* code segment ? */
&& (entry->offs >= max_offset))
{
max_offset = entry->offs;
*pOrd = i;
}
entry++;
}
} while ( (bundle->next)
&& (bundle = (ET_BUNDLE *)((BYTE *)pModule+bundle->next)));
/* Search for the name in the resident names table */
/* (built-in modules have no non-resident table) */
p = (BYTE *)pModule + pModule->name_table;
while (*p)
{
p += *p + 1 + sizeof(WORD);
if (*(WORD *)(p + *p + 1) == *pOrd) break;
}
sprintf( name, "%.*s.%d: %.*s",
*((BYTE *)pModule + pModule->name_table),
(char *)pModule + pModule->name_table + 1,
*pOrd, *p, (char *)(p + 1) );
/* Retrieve type info string */
return *(LPCSTR *)((LPBYTE)MapSL( MAKESEGPTR( frame->module_cs, frame->callfrom_ip )) + 4);
}
/***********************************************************************
* __wine_register_dll_16 (KERNEL32.@)
*
* Register a built-in DLL descriptor.
......
......@@ -13,9 +13,10 @@
struct _CONTEXT86;
struct _STACK16FRAME;
#ifdef __i386__
#include "pshpack1.h"
#ifdef __i386__
typedef struct
{
WORD pushw_bp; /* pushw %bp */
......@@ -32,45 +33,51 @@ typedef struct
BYTE lcall; /* lcall __FLATCS__:glue */
void *glue;
WORD flatcs;
BYTE prefix; /* lret $nArgs */
BYTE lret;
WORD lret; /* lret $nArgs */
WORD nArgs;
LPCSTR profile; /* profile string */
DWORD arg_types[2]; /* type of each argument */
} CALLFROM16;
#include "poppack.h"
#else
typedef struct
{
void (*target)();
int callfrom16;
WORD call; /* call CALLFROM16 */
short callfrom16;
} ENTRYPOINT16;
typedef struct
{
LPCSTR profile;
WORD lret; /* lret $nArgs */
WORD nArgs;
DWORD arg_types[2]; /* type of each argument */
} CALLFROM16;
#endif
typedef struct
#include "poppack.h"
/* argument type flags for relay debugging */
enum arg_types
{
void *module_start; /* 32-bit address of the module data */
int module_size; /* Size of the module data */
void *code_start; /* 32-bit address of DLL code */
void *data_start; /* 32-bit address of DLL data */
const char *owner; /* 32-bit dll that contains this dll */
const void *rsrc; /* resources data */
} BUILTIN16_DESCRIPTOR;
ARG_NONE = 0, /* indicates end of arg list */
ARG_WORD, /* unsigned word */
ARG_SWORD, /* signed word */
ARG_LONG, /* long or segmented pointer */
ARG_PTR, /* linear pointer */
ARG_STR, /* linear pointer to null-terminated string */
ARG_SEGSTR /* segmented pointer to null-terminated string */
};
/* flags added to arg_types[0] */
#define ARG_RET16 0x80000000 /* function returns 16-bit value */
#define ARG_REGISTER 0x40000000 /* function is register */
extern HMODULE16 BUILTIN_LoadModule( LPCSTR name );
extern LPCSTR BUILTIN_GetEntryPoint16( struct _STACK16FRAME *frame, LPSTR name, WORD *pOrd );
extern void __wine_register_dll_16( const BUILTIN16_DESCRIPTOR *descr );
extern WORD __wine_call_from_16_word();
extern LONG __wine_call_from_16_long();
extern void __wine_call_from_16_regs();
extern void __wine_call_from_16_thunk();
#endif /* __WINE_BUILTIN16_H */
......@@ -157,83 +157,65 @@ static inline void RELAY_PrintArgs( int *args, int nb_args, unsigned int typemas
}
typedef LONGLONG (*LONGLONG_CPROC)();
typedef LONGLONG WINAPI (*LONGLONG_FARPROC)();
/***********************************************************************
* RELAY_CallFrom32
*
* Stack layout on entry to this function:
* ... ...
* (esp+12) arg2
* (esp+8) arg1
* (esp+4) ret_addr
* (esp) return addr to relay code
* call_cdecl_function
*/
static LONGLONG RELAY_CallFrom32( int ret_addr, ... )
static LONGLONG call_cdecl_function( LONGLONG_CPROC func, int nb_args, const int *args )
{
LONGLONG ret;
char buffer[80];
BOOL ret64;
int *args = &ret_addr + 1;
/* Relay addr is the return address for this function */
BYTE *relay_addr = (BYTE *)__builtin_return_address(0);
DEBUG_ENTRY_POINT *relay = (DEBUG_ENTRY_POINT *)(relay_addr - 5);
WORD nb_args = relay->args / sizeof(int);
get_entry_point( buffer, relay );
DPRINTF( "%08lx:Call %s(", GetCurrentThreadId(), buffer );
RELAY_PrintArgs( args, nb_args, relay->argtypes );
DPRINTF( ") ret=%08x\n", ret_addr );
ret64 = (relay->argtypes & 0x80000000) && (nb_args < 16);
if (relay->ret == 0xc3) /* cdecl */
{
LONGLONG (*cfunc)() = relay->orig;
switch(nb_args)
{
case 0: ret = cfunc(); break;
case 1: ret = cfunc(args[0]); break;
case 2: ret = cfunc(args[0],args[1]); break;
case 3: ret = cfunc(args[0],args[1],args[2]); break;
case 4: ret = cfunc(args[0],args[1],args[2],args[3]); break;
case 5: ret = cfunc(args[0],args[1],args[2],args[3],args[4]); break;
case 6: ret = cfunc(args[0],args[1],args[2],args[3],args[4],
case 0: ret = func(); break;
case 1: ret = func(args[0]); break;
case 2: ret = func(args[0],args[1]); break;
case 3: ret = func(args[0],args[1],args[2]); break;
case 4: ret = func(args[0],args[1],args[2],args[3]); break;
case 5: ret = func(args[0],args[1],args[2],args[3],args[4]); break;
case 6: ret = func(args[0],args[1],args[2],args[3],args[4],
args[5]); break;
case 7: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
case 7: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
args[6]); break;
case 8: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
case 8: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7]); break;
case 9: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
case 9: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8]); break;
case 10: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
case 10: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8],args[9]); break;
case 11: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
case 11: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8],args[9],args[10]); break;
case 12: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
case 12: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8],args[9],args[10],
args[11]); break;
case 13: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
case 13: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8],args[9],args[10],args[11],
args[12]); break;
case 14: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
case 14: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8],args[9],args[10],args[11],
args[12],args[13]); break;
case 15: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
case 15: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8],args[9],args[10],args[11],
args[12],args[13],args[14]); break;
case 16: ret = cfunc(args[0],args[1],args[2],args[3],args[4],args[5],
case 16: ret = func(args[0],args[1],args[2],args[3],args[4],args[5],
args[6],args[7],args[8],args[9],args[10],args[11],
args[12],args[13],args[14],args[15]); break;
default:
ERR( "Unsupported nb of args %d\n", nb_args );
assert(FALSE);
}
}
else /* stdcall */
{
LONGLONG_FARPROC func = relay->orig;
return ret;
}
/***********************************************************************
* call_stdcall_function
*/
static LONGLONG call_stdcall_function( LONGLONG_FARPROC func, int nb_args, const int *args )
{
LONGLONG ret;
switch(nb_args)
{
case 0: ret = func(); break;
......@@ -273,7 +255,48 @@ static LONGLONG RELAY_CallFrom32( int ret_addr, ... )
ERR( "Unsupported nb of args %d\n", nb_args );
assert(FALSE);
}
return ret;
}
/***********************************************************************
* RELAY_CallFrom32
*
* Stack layout on entry to this function:
* ... ...
* (esp+12) arg2
* (esp+8) arg1
* (esp+4) ret_addr
* (esp) return addr to relay code
*/
static LONGLONG RELAY_CallFrom32( int ret_addr, ... )
{
LONGLONG ret;
char buffer[80];
BOOL ret64;
int *args = &ret_addr + 1;
/* Relay addr is the return address for this function */
BYTE *relay_addr = (BYTE *)__builtin_return_address(0);
DEBUG_ENTRY_POINT *relay = (DEBUG_ENTRY_POINT *)(relay_addr - 5);
WORD nb_args = relay->args / sizeof(int);
get_entry_point( buffer, relay );
DPRINTF( "%08lx:Call %s(", GetCurrentThreadId(), buffer );
RELAY_PrintArgs( args, nb_args, relay->argtypes );
DPRINTF( ") ret=%08x\n", ret_addr );
ret64 = (relay->argtypes & 0x80000000) && (nb_args < 16);
if (relay->ret == 0xc3) /* cdecl */
{
ret = call_cdecl_function( (LONGLONG_CPROC)relay->orig, nb_args, args );
}
else /* stdcall */
{
ret = call_stdcall_function( (LONGLONG_FARPROC)relay->orig, nb_args, args );
}
if (ret64)
DPRINTF( "%08lx:Ret %s() retval=%08x%08x ret=%08x\n",
GetCurrentThreadId(),
......@@ -303,7 +326,7 @@ void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context )
{
char buffer[80];
int* args;
FARPROC func;
int args_copy[17];
BYTE *entry_point;
BYTE *relay_addr = *((BYTE **)context->Esp - 1);
......@@ -319,7 +342,6 @@ void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context )
entry_point = (BYTE *)relay->orig;
assert( *entry_point == 0xe8 /* lcall */ );
func = *(FARPROC *)(entry_point + 5);
get_entry_point( buffer, relay );
......@@ -335,36 +357,16 @@ void WINAPI RELAY_DoCallFrom32Regs( CONTEXT86 *context )
context->SegEs, context->SegGs, context->EFlags );
/* Now call the real function */
switch(nb_args)
memcpy( args_copy, args, nb_args * sizeof(args[0]) );
args_copy[nb_args] = (int)context; /* append context argument */
if (relay->ret == 0xc3) /* cdecl */
{
case 0: func(context); break;
case 1: func(args[0],context); break;
case 2: func(args[0],args[1],context); break;
case 3: func(args[0],args[1],args[2],context); break;
case 4: func(args[0],args[1],args[2],args[3],context); break;
case 5: func(args[0],args[1],args[2],args[3],args[4],context); break;
case 6: func(args[0],args[1],args[2],args[3],args[4],args[5],context); break;
case 7: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],context); break;
case 8: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],context); break;
case 9: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],
context); break;
case 10: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],
args[9],context); break;
case 11: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],
args[9],args[10],context); break;
case 12: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],
args[9],args[10],args[11],context); break;
case 13: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],
args[9],args[10],args[11],args[12],context); break;
case 14: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],
args[9],args[10],args[11],args[12],args[13],context); break;
case 15: func(args[0],args[1],args[2],args[3],args[4],args[5],args[6],args[7],args[8],
args[9],args[10],args[11],args[12],args[13],args[14],context); break;
case 16: func(args[0],args[1],args[2],args[3],args[4],args[5], args[6],args[7],args[8],
args[9],args[10],args[11],args[12],args[13],args[14],args[15],context); break;
default:
ERR( "Unsupported nb of args %d\n", nb_args );
assert(FALSE);
call_cdecl_function( *(LONGLONG_CPROC *)(entry_point + 5), nb_args+1, args_copy );
}
else /* stdcall */
{
call_stdcall_function( *(LONGLONG_FARPROC *)(entry_point + 5), nb_args+1, args_copy );
}
DPRINTF( "%08lx:Ret %s() retval=%08lx ret=%08lx fs=%04lx\n",
......
......@@ -79,6 +79,8 @@ The supported flags are:
traces (Win32 only).
"-ret64": the function returns a 64-bit value (Win32 only).
"-i386": the entry point is only available on i386 platforms.
"-register": the function uses CPU register to pass arguments.
"-interrupt": the function is an interrupt handler routine.
Lines whose first character is a '#' will be ignored as comments.
......@@ -105,8 +107,6 @@ instead of "EXPORTNAME" for ordinal-only exports.
"FUNCTYPE" should be one of:
- "pascal16" for a Win16 function returning a 16-bit value
- "pascal" for a Win16 function returning a 32-bit value
- "register" for a function using CPU register to pass arguments
- "interrupt" for a Win16 interrupt handler routine
- "stdcall" for a normal Win32 function
- "cdecl" for a Win32 function using the C calling convention
- "varargs" for a Win32 function taking a variable number of arguments
......
......@@ -40,8 +40,6 @@ typedef enum
TYPE_PASCAL_16, /* pascal function with 16-bit return (Win16) */
TYPE_PASCAL, /* pascal function with 32-bit return (Win16) */
TYPE_ABS, /* absolute value (Win16) */
TYPE_REGISTER, /* register function */
TYPE_INTERRUPT, /* interrupt handler function (Win16) */
TYPE_STUB, /* unimplemented stub */
TYPE_STDCALL, /* stdcall function (Win32) */
TYPE_CDECL, /* cdecl function (Win32) */
......@@ -106,6 +104,8 @@ typedef struct
#define FLAG_NORELAY 0x02 /* don't use relay debugging for this function */
#define FLAG_RET64 0x04 /* function returns a 64-bit value */
#define FLAG_I386 0x08 /* function is i386 only */
#define FLAG_REGISTER 0x10 /* use register calling convention */
#define FLAG_INTERRUPT 0x20 /* function is an interrupt handler */
/* Offset of a structure field relative to the start of the struct */
#define STRUCTOFFSET(type,field) ((int)&((type *)0)->field)
......
......@@ -250,8 +250,11 @@ static void add_extra_undef_symbols(void)
for (i = 0; i < nb_entry_points; i++)
{
ORDDEF *odp = EntryPoints[i];
if (odp->type != TYPE_REGISTER) continue;
if (odp->flags & FLAG_REGISTER)
{
ADD_SYM( "__wine_call_from_32_regs" );
break;
}
}
if (count)
......
......@@ -35,8 +35,6 @@ static const char * const TypeNames[TYPE_NBTYPES] =
"pascal16", /* TYPE_PASCAL_16 */
"pascal", /* TYPE_PASCAL */
"equate", /* TYPE_ABS */
"register", /* TYPE_REGISTER */
"interrupt", /* TYPE_INTERRUPT */
"stub", /* TYPE_STUB */
"stdcall", /* TYPE_STDCALL */
"cdecl", /* TYPE_CDECL */
......@@ -51,6 +49,8 @@ static const char * const FlagNames[] =
"norelay", /* FLAG_NORELAY */
"ret64", /* FLAG_RET64 */
"i386", /* FLAG_I386 */
"register", /* FLAG_REGISTER */
"interrupt", /* FLAG_INTERRUPT */
NULL
};
......@@ -214,6 +214,8 @@ static void ParseExportFunction( ORDDEF *odp )
case SPEC_WIN32:
if ((odp->type == TYPE_PASCAL) || (odp->type == TYPE_PASCAL_16))
fatal_error( "'pascal' not supported for Win32\n" );
if (odp->flags & FLAG_INTERRUPT)
fatal_error( "'interrupt' not supported for Win32\n" );
break;
default:
break;
......@@ -303,29 +305,6 @@ static void ParseStub( ORDDEF *odp )
/*******************************************************************
* ParseInterrupt
*
* Parse an 'interrupt' definition.
*/
static void ParseInterrupt( ORDDEF *odp )
{
const char *token;
if (SpecType == SPEC_WIN32)
fatal_error( "'interrupt' not supported for Win32\n" );
token = GetToken(0);
if (*token != '(') fatal_error( "Expected '(' got '%s'\n", token );
token = GetToken(0);
if (*token != ')') fatal_error( "Expected ')' got '%s'\n", token );
odp->u.func.arg_types[0] = '\0';
odp->link_name = xstrdup( GetToken(0) );
}
/*******************************************************************
* ParseExtern
*
* Parse an 'extern' definition.
......@@ -423,7 +402,6 @@ static void ParseOrdinal(int ordinal)
case TYPE_VARIABLE:
ParseVariable( odp );
break;
case TYPE_REGISTER:
case TYPE_PASCAL_16:
case TYPE_PASCAL:
case TYPE_STDCALL:
......@@ -431,9 +409,6 @@ static void ParseOrdinal(int ordinal)
case TYPE_CDECL:
ParseExportFunction( odp );
break;
case TYPE_INTERRUPT:
ParseInterrupt( odp );
break;
case TYPE_ABS:
ParseEquate( odp );
break;
......
......@@ -159,14 +159,12 @@ static int output_exports( FILE *outfile, int nr_exports )
case TYPE_STDCALL:
case TYPE_VARARGS:
case TYPE_CDECL:
fprintf( outfile, " \"\\t.long " PREFIX "%s\\n\"\n", odp->link_name);
fprintf( outfile, " \"\\t.long " PREFIX "%s\\n\"\n",
(odp->flags & FLAG_REGISTER) ? make_internal_name(odp,"regs") : odp->link_name );
break;
case TYPE_STUB:
fprintf( outfile, " \"\\t.long " PREFIX "%s\\n\"\n", make_internal_name( odp, "stub" ) );
break;
case TYPE_REGISTER:
fprintf( outfile, " \"\\t.long " PREFIX "%s\\n\"\n", make_internal_name( odp, "regs" ) );
break;
case TYPE_VARIABLE:
fprintf( outfile, " \"\\t.long " PREFIX "%s\\n\"\n", make_internal_name( odp, "var" ) );
break;
......@@ -239,14 +237,13 @@ static int output_exports( FILE *outfile, int nr_exports )
for (i = Base; i <= Limit; i++)
{
ORDDEF *odp = Ordinals[i];
unsigned int j, mask = 0;
unsigned int j, args, mask = 0;
const char *name;
/* skip non-existent entry points */
if (!odp) goto ignore;
/* skip non-functions */
if ((odp->type != TYPE_STDCALL) &&
(odp->type != TYPE_CDECL) &&
(odp->type != TYPE_REGISTER)) goto ignore;
if ((odp->type != TYPE_STDCALL) && (odp->type != TYPE_CDECL)) goto ignore;
/* skip norelay entry points */
if (odp->flags & FLAG_NORELAY) goto ignore;
......@@ -257,31 +254,26 @@ static int output_exports( FILE *outfile, int nr_exports )
}
if ((odp->flags & FLAG_RET64) && (j < 16)) mask |= 0x80000000;
name = odp->link_name;
args = strlen(odp->u.func.arg_types) * sizeof(int);
if (odp->flags & FLAG_REGISTER)
{
name = make_internal_name( odp, "regs" );
args |= 0x8000;
}
switch(odp->type)
{
case TYPE_STDCALL:
fprintf( outfile, " \"\\tjmp " PREFIX "%s\\n\"\n", odp->link_name );
fprintf( outfile, " \"\\tret $%d\\n\"\n",
strlen(odp->u.func.arg_types) * sizeof(int) );
fprintf( outfile, " \"\\t.long " PREFIX "%s,0x%08x\\n\"\n",
odp->link_name, mask );
fprintf( outfile, " \"\\tjmp " PREFIX "%s\\n\"\n", name );
fprintf( outfile, " \"\\tret $0x%04x\\n\"\n", args );
fprintf( outfile, " \"\\t.long " PREFIX "%s,0x%08x\\n\"\n", name, mask );
break;
case TYPE_CDECL:
fprintf( outfile, " \"\\tjmp " PREFIX "%s\\n\"\n", odp->link_name );
fprintf( outfile, " \"\\tret\\n\"\n" );
fprintf( outfile, " \"\\t.short %d\\n\"\n",
strlen(odp->u.func.arg_types) * sizeof(int) );
fprintf( outfile, " \"\\t.long " PREFIX "%s,0x%08x\\n\"\n",
odp->link_name, mask );
break;
case TYPE_REGISTER:
fprintf( outfile, " \"\\tjmp " PREFIX "%s\\n\"\n",
make_internal_name( odp, "regs" ) );
fprintf( outfile, " \"\\tjmp " PREFIX "%s\\n\"\n", name );
fprintf( outfile, " \"\\tret\\n\"\n" );
fprintf( outfile, " \"\\t.short 0x%04x\\n\"\n",
0x8000 | strlen(odp->u.func.arg_types) * sizeof(int) );
fprintf( outfile, " \"\\t.long " PREFIX "%s,0x%08x\\n\"\n",
make_internal_name( odp, "regs" ), mask );
fprintf( outfile, " \"\\t.short 0x%04x\\n\"\n", args );
fprintf( outfile, " \"\\t.long " PREFIX "%s,0x%08x\\n\"\n", name, mask );
break;
default:
assert(0);
......@@ -401,7 +393,8 @@ static void output_register_funcs( FILE *outfile )
for (i = 0; i < nb_entry_points; i++)
{
ORDDEF *odp = EntryPoints[i];
if (odp->type != TYPE_REGISTER) continue;
if (odp->type != TYPE_STDCALL && odp->type != TYPE_CDECL) continue;
if (!(odp->flags & FLAG_REGISTER)) continue;
name = make_internal_name( odp, "regs" );
fprintf( outfile,
"asm(\".align %d\\n\\t\"\n"
......@@ -412,7 +405,8 @@ static void output_register_funcs( FILE *outfile )
" \".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) );
strlen(odp->u.func.arg_types) * sizeof(int),
(odp->type == TYPE_CDECL) ? 0 : (strlen(odp->u.func.arg_types) * sizeof(int)) );
}
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment