Make a global asm helper function to handle 32-bit RMCB calls, so we

don't need those complex constraints either.
This commit is contained in:
Ove Kaaven 2000-07-28 20:18:25 +00:00 committed by Alexandre Julliard
parent a5bb5ea2c3
commit 3939b6d9dd
1 changed files with 66 additions and 23 deletions

View File

@ -183,36 +183,9 @@ static void INT_SetRealModeContext( REALMODECALL *call, CONTEXT86 *context )
call->ss = SS_reg(context);
}
/**********************************************************************
* DPMI_CallRMCBProc
*
* This routine does the hard work of calling a callback procedure.
*/
static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag )
void DPMI_CallRMCB32(RMCB *rmcb, UINT16 ss, DWORD esp, UINT16*es, DWORD*edi)
#if 0 /* original code, which early gccs puke on */
{
if (IS_SELECTOR_SYSTEM( rmcb->proc_sel )) {
/* Wine-internal RMCB, call directly */
((RMCBPROC)rmcb->proc_ofs)(context);
} else {
#ifdef __i386__
UINT16 ss,es;
DWORD edi;
INT_SetRealModeContext((REALMODECALL *)PTR_SEG_OFF_TO_LIN( rmcb->regs_sel, rmcb->regs_ofs ), context);
ss = SELECTOR_AllocBlock( DOSMEM_MemoryBase(0) + (DWORD)(SS_reg(context)<<4), 0x10000, SEGMENT_DATA, FALSE, FALSE );
FIXME("untested!\n");
/* The called proc ends with an IRET, and takes these parameters:
* DS:ESI = pointer to real-mode SS:SP
* ES:EDI = pointer to real-mode call structure
* It returns:
* ES:EDI = pointer to real-mode call structure (may be a copy)
* It is the proc's responsibility to change the return CS:IP in the
* real-mode call structure. */
if (flag & 1) {
/* 32-bit DPMI client */
int _clobber;
__asm__ __volatile__(
"pushl %%ebp\n"
@ -228,21 +201,91 @@ static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag )
"popl %%es\n"
"popl %%ebx\n"
"popl %%ebp\n"
: "=d" (es), "=D" (edi), "=S" (_clobber), "=a" (_clobber), "=c" (_clobber)
: "0" (ss), "2" (ESP_reg(context)),
: "=d" (*es), "=D" (*edi), "=S" (_clobber), "=a" (_clobber), "=c" (_clobber)
: "0" (ss), "2" (esp),
"4" (rmcb->regs_sel), "1" (rmcb->regs_ofs),
"3" (&rmcb->proc_ofs) );
}
#else /* code generated by a gcc new enough */
;
__ASM_GLOBAL_FUNC(DPMI_CallRMCB32,
"pushl %ebp\n\t"
"movl %esp,%ebp\n\t"
"subl $0x10,%esp\n\t"
"pushl %edi\n\t"
"pushl %esi\n\t"
"movl 0x8(%ebp),%eax\n\t"
"movl 0x10(%ebp),%esi\n\t"
"movl 0xc(%ebp),%edx\n\t"
"movl 0x10(%eax),%ecx\n\t"
"movl 0xc(%eax),%edi\n\t"
"addl $0x4,%eax\n\t"
"movl %eax,-0x8(%ebp)\n\t"
"pushl %ebp\n\t"
"pushl %ebx\n\t"
"pushl %es\n\t"
"pushl %ds\n\t"
"pushfl\n\t"
"mov %cx,%es\n\t"
"mov %dx,%ds\n\t"
".byte 0x36, 0xff, 0x18\n\t" /* lcall *%ss:(%eax) */
"popl %ds\n\t"
"mov %es,%dx\n\t"
"popl %es\n\t"
"popl %ebx\n\t"
"popl %ebp\n\t"
"movl 0x14(%ebp),%eax\n\t"
"movw %dx,(%eax)\n\t"
"movl 0x18(%ebp),%edx\n\t"
"movl %edi,(%edx)\n\t"
"popl %esi\n\t"
"popl %edi\n\t"
"leave\n\t"
"ret")
#endif
/**********************************************************************
* DPMI_CallRMCBProc
*
* This routine does the hard work of calling a callback procedure.
*/
static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag )
{
if (IS_SELECTOR_SYSTEM( rmcb->proc_sel )) {
/* Wine-internal RMCB, call directly */
((RMCBPROC)rmcb->proc_ofs)(context);
} else {
#ifdef __i386__
UINT16 ss,es;
DWORD esp,edi;
INT_SetRealModeContext((REALMODECALL *)PTR_SEG_OFF_TO_LIN( rmcb->regs_sel, rmcb->regs_ofs ), context);
ss = SELECTOR_AllocBlock( DOSMEM_MemoryBase(0) + (DWORD)(SS_reg(context)<<4), 0x10000, SEGMENT_DATA, FALSE, FALSE );
esp = ESP_reg(context);
FIXME("untested!\n");
/* The called proc ends with an IRET, and takes these parameters:
* DS:ESI = pointer to real-mode SS:SP
* ES:EDI = pointer to real-mode call structure
* It returns:
* ES:EDI = pointer to real-mode call structure (may be a copy)
* It is the proc's responsibility to change the return CS:IP in the
* real-mode call structure. */
if (flag & 1) {
/* 32-bit DPMI client */
DPMI_CallRMCB32(rmcb, ss, esp, &es, &edi);
} else {
/* 16-bit DPMI client */
CONTEXT86 ctx = *context;
CS_reg(&ctx) = rmcb->proc_sel;
EIP_reg(&ctx) = rmcb->proc_ofs;
DS_reg(&ctx) = ss;
ESI_reg(&ctx) = ESP_reg(context);
ESI_reg(&ctx) = esp;
ES_reg(&ctx) = rmcb->regs_sel;
EDI_reg(&ctx) = rmcb->regs_ofs;
/* FIXME: I'm pretty sure this isn't right */
Callbacks->CallRegisterShortProc(&ctx, 2);
/* FIXME: I'm pretty sure this isn't right - should push flags first */
Callbacks->CallRegisterShortProc(&ctx, 0);
es = ES_reg(&ctx);
edi = EDI_reg(&ctx);
}