Fixed broken assembler. Removed support for old protected-mode hack
for running real-mode code on platforms that don't support vm86; the current CallRM->RMCB shortcut code should take care of all Wine-supplied RM APIs (such as DOSASPI) anyway.
This commit is contained in:
parent
b18dbd26c5
commit
0e823c56c3
98
msdos/dpmi.c
98
msdos/dpmi.c
@ -213,32 +213,24 @@ static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag )
|
|||||||
* real-mode call structure. */
|
* real-mode call structure. */
|
||||||
if (flag & 1) {
|
if (flag & 1) {
|
||||||
/* 32-bit DPMI client */
|
/* 32-bit DPMI client */
|
||||||
#if HAVE_FIXED_BROKEN_ASSEMBLER_BELOW
|
int _clobber;
|
||||||
int _clobber;
|
|
||||||
__asm__ __volatile__(
|
__asm__ __volatile__(
|
||||||
|
"pushl %%ebp\n"
|
||||||
"pushl %%es\n"
|
"pushl %%es\n"
|
||||||
"pushl %%ds\n"
|
"pushl %%ds\n"
|
||||||
"pushfl\n"
|
"pushfl\n"
|
||||||
"movl %5,%%es\n" /* BAD: we are pushing potential stack
|
"mov %7,%%es\n"
|
||||||
* parameters on an already modified
|
"mov %5,%%ds\n"
|
||||||
* stack
|
".byte 0x36; lcall *(%3)\n"
|
||||||
*/
|
|
||||||
"movl %4,%%ds\n"
|
|
||||||
"lcall %3\n"
|
|
||||||
"popl %%ds\n"
|
"popl %%ds\n"
|
||||||
"movl %%es,%0\n"
|
"mov %%es,%0\n"
|
||||||
"popl %%es\n"
|
"popl %%es\n"
|
||||||
: "=g" (es), "=D" (edi), "=S" (_clobber)
|
"popl %%ebp\n"
|
||||||
: "m" (rmcb->proc_ofs),
|
: "=d" (es), "=D" (edi), "=S" (_clobber), "=a" (_clobber), "=c" (_clobber)
|
||||||
"g" (ss), "g" (rmcb->regs_sel),
|
: "0" (ss), "2" (ESP_reg(context)),
|
||||||
"S" (ESP_reg(context)), "1" (rmcb->regs_ofs)
|
"4" (rmcb->regs_sel), "1" (rmcb->regs_ofs),
|
||||||
: "ecx", "edx", "ebp" );
|
"3" (&rmcb->proc_ofs)
|
||||||
/* BAD: uses too much registers which is starving the register
|
: "ebx" );
|
||||||
* alloc stage of gcc, especially in -fPIC.
|
|
||||||
*/
|
|
||||||
#else
|
|
||||||
FIXME("32 bit DPMI client unsupported.\n");
|
|
||||||
#endif
|
|
||||||
} else {
|
} else {
|
||||||
/* 16-bit DPMI client */
|
/* 16-bit DPMI client */
|
||||||
CONTEXT86 ctx = *context;
|
CONTEXT86 ctx = *context;
|
||||||
@ -248,6 +240,7 @@ static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag )
|
|||||||
ESI_reg(&ctx) = ESP_reg(context);
|
ESI_reg(&ctx) = ESP_reg(context);
|
||||||
ES_reg(&ctx) = rmcb->regs_sel;
|
ES_reg(&ctx) = rmcb->regs_sel;
|
||||||
EDI_reg(&ctx) = rmcb->regs_ofs;
|
EDI_reg(&ctx) = rmcb->regs_ofs;
|
||||||
|
/* FIXME: I'm pretty sure this isn't right */
|
||||||
Callbacks->CallRegisterShortProc(&ctx, 2);
|
Callbacks->CallRegisterShortProc(&ctx, 2);
|
||||||
es = ES_reg(&ctx);
|
es = ES_reg(&ctx);
|
||||||
edi = EDI_reg(&ctx);
|
edi = EDI_reg(&ctx);
|
||||||
@ -269,10 +262,6 @@ static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag )
|
|||||||
int DPMI_CallRMProc( CONTEXT86 *context, LPWORD stack, int args, int iret )
|
int DPMI_CallRMProc( CONTEXT86 *context, LPWORD stack, int args, int iret )
|
||||||
{
|
{
|
||||||
LPWORD stack16;
|
LPWORD stack16;
|
||||||
#ifndef MZ_SUPPORTED
|
|
||||||
WORD sel;
|
|
||||||
SEGPTR seg_addr;
|
|
||||||
#endif /* !MZ_SUPPORTED */
|
|
||||||
LPVOID addr = NULL; /* avoid gcc warning */
|
LPVOID addr = NULL; /* avoid gcc warning */
|
||||||
TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
|
TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
|
||||||
NE_MODULE *pModule = pTask ? NE_GetPtr( pTask->hModule ) : NULL;
|
NE_MODULE *pModule = pTask ? NE_GetPtr( pTask->hModule ) : NULL;
|
||||||
@ -320,18 +309,20 @@ callrmproc_again:
|
|||||||
while (CurrRMCB && (HIWORD(CurrRMCB->address) != CS_reg(context)))
|
while (CurrRMCB && (HIWORD(CurrRMCB->address) != CS_reg(context)))
|
||||||
CurrRMCB = CurrRMCB->next;
|
CurrRMCB = CurrRMCB->next;
|
||||||
|
|
||||||
#ifdef MZ_SUPPORTED
|
|
||||||
if (!(CurrRMCB || pModule->lpDosTask)) {
|
if (!(CurrRMCB || pModule->lpDosTask)) {
|
||||||
|
#ifdef MZ_SUPPORTED
|
||||||
FIXME("DPMI real-mode call using DOS VM task system, not fully tested!\n");
|
FIXME("DPMI real-mode call using DOS VM task system, not fully tested!\n");
|
||||||
TRACE("creating VM86 task\n");
|
TRACE("creating VM86 task\n");
|
||||||
if (!MZ_InitTask( MZ_AllocDPMITask( pModule->self ) )) {
|
if (!MZ_InitTask( MZ_AllocDPMITask( pModule->self ) )) {
|
||||||
ERR("could not setup VM86 task\n");
|
ERR("could not setup VM86 task\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
#else
|
||||||
|
ERR("Actual real-mode calls not supported on this architecture!\n");
|
||||||
|
return 1;
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
if (!already) {
|
if (!already) {
|
||||||
#ifdef MZ_SUPPORTED
|
|
||||||
if (!SS_reg(context)) {
|
if (!SS_reg(context)) {
|
||||||
alloc = 1; /* allocate default stack */
|
alloc = 1; /* allocate default stack */
|
||||||
stack16 = addr = DOSMEM_GetBlock( pModule->self, 64, (UINT16 *)&(SS_reg(context)) );
|
stack16 = addr = DOSMEM_GetBlock( pModule->self, 64, (UINT16 *)&(SS_reg(context)) );
|
||||||
@ -345,9 +336,6 @@ callrmproc_again:
|
|||||||
stack16 = CTX_SEG_OFF_TO_LIN(context, SS_reg(context), ESP_reg(context));
|
stack16 = CTX_SEG_OFF_TO_LIN(context, SS_reg(context), ESP_reg(context));
|
||||||
}
|
}
|
||||||
ESP_reg(context) -= (args + (iret?1:0)) * sizeof(WORD);
|
ESP_reg(context) -= (args + (iret?1:0)) * sizeof(WORD);
|
||||||
#else
|
|
||||||
stack16 = (LPWORD) CURRENT_STACK16;
|
|
||||||
#endif
|
|
||||||
stack16 -= args;
|
stack16 -= args;
|
||||||
if (args) memcpy(stack16, stack, args*sizeof(WORD) );
|
if (args) memcpy(stack16, stack, args*sizeof(WORD) );
|
||||||
/* push flags if iret */
|
/* push flags if iret */
|
||||||
@ -355,13 +343,11 @@ callrmproc_again:
|
|||||||
stack16--; args++;
|
stack16--; args++;
|
||||||
*stack16 = LOWORD(EFL_reg(context));
|
*stack16 = LOWORD(EFL_reg(context));
|
||||||
}
|
}
|
||||||
#ifdef MZ_SUPPORTED
|
|
||||||
/* push return address (return to interrupt wrapper) */
|
/* push return address (return to interrupt wrapper) */
|
||||||
*(--stack16) = DPMI_wrap_seg;
|
*(--stack16) = DPMI_wrap_seg;
|
||||||
*(--stack16) = 0;
|
*(--stack16) = 0;
|
||||||
/* adjust stack */
|
/* adjust stack */
|
||||||
ESP_reg(context) -= 2*sizeof(WORD);
|
ESP_reg(context) -= 2*sizeof(WORD);
|
||||||
#endif
|
|
||||||
already = 1;
|
already = 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -377,30 +363,12 @@ callrmproc_again:
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
#ifdef MZ_SUPPORTED
|
#ifdef MZ_SUPPORTED
|
||||||
#if 0 /* this was probably unnecessary */
|
|
||||||
/* push call address */
|
|
||||||
*(--stack16) = CS_reg(context);
|
|
||||||
*(--stack16) = LOWORD(EIP_reg(context));
|
|
||||||
/* adjust stack */
|
|
||||||
ESP_reg(context) -= 2*sizeof(WORD);
|
|
||||||
/* set initial CS:IP to the wrapper's "lret" */
|
|
||||||
CS_reg(context) = DPMI_wrap_seg;
|
|
||||||
EIP_reg(context) = 2;
|
|
||||||
#endif
|
|
||||||
TRACE("entering real mode...\n");
|
TRACE("entering real mode...\n");
|
||||||
DOSVM_Enter( context );
|
DOSVM_Enter( context );
|
||||||
TRACE("returned from real-mode call\n");
|
TRACE("returned from real-mode call\n");
|
||||||
#else
|
#else
|
||||||
addr = CTX_SEG_OFF_TO_LIN(context, CS_reg(context), EIP_reg(context));
|
/* we should never get here, but... */
|
||||||
sel = SELECTOR_AllocBlock( addr, 0x10000, SEGMENT_CODE, FALSE, FALSE );
|
ERR("cannot perform real-mode call\n");
|
||||||
seg_addr = PTR_SEG_OFF_TO_SEGPTR( sel, 0 );
|
|
||||||
|
|
||||||
CS_reg(context) = HIWORD(seg_addr);
|
|
||||||
EIP_reg(context) = LOWORD(seg_addr);
|
|
||||||
EBP_reg(context) = OFFSETOF( NtCurrentTeb()->cur_stack )
|
|
||||||
+ (WORD)&((STACK16FRAME*)0)->bp;
|
|
||||||
Callbacks->CallRegisterShortProc(context, args*sizeof(WORD));
|
|
||||||
SELECTOR_FreeBlock(sel, 1);
|
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
if (alloc) DOSMEM_FreeBlock( pModule->self, addr );
|
if (alloc) DOSMEM_FreeBlock( pModule->self, addr );
|
||||||
@ -468,15 +436,6 @@ static void CallRMProc( CONTEXT86 *context, int iret )
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static void WINAPI WINE_UNUSED RMCallbackProc( RMCB *rmcb )
|
|
||||||
{
|
|
||||||
/* This routine should call DPMI_CallRMCBProc, but we don't have the
|
|
||||||
register structure available - this is easily fixed by going through
|
|
||||||
a Win16 register relay instead of calling RMCallbackProc "directly",
|
|
||||||
but I won't bother at this time. */
|
|
||||||
FIXME("not properly supported on your architecture!\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
static RMCB *DPMI_AllocRMCB( void )
|
static RMCB *DPMI_AllocRMCB( void )
|
||||||
{
|
{
|
||||||
RMCB *NewRMCB = HeapAlloc(GetProcessHeap(), 0, sizeof(RMCB));
|
RMCB *NewRMCB = HeapAlloc(GetProcessHeap(), 0, sizeof(RMCB));
|
||||||
@ -484,7 +443,6 @@ static RMCB *DPMI_AllocRMCB( void )
|
|||||||
|
|
||||||
if (NewRMCB)
|
if (NewRMCB)
|
||||||
{
|
{
|
||||||
#ifdef MZ_SUPPORTED
|
|
||||||
LPVOID RMCBmem = DOSMEM_GetBlock(0, 4, &uParagraph);
|
LPVOID RMCBmem = DOSMEM_GetBlock(0, 4, &uParagraph);
|
||||||
LPBYTE p = RMCBmem;
|
LPBYTE p = RMCBmem;
|
||||||
|
|
||||||
@ -494,22 +452,6 @@ static RMCB *DPMI_AllocRMCB( void )
|
|||||||
the DPMI 0.9 spec states that if it doesn't, it will be called again */
|
the DPMI 0.9 spec states that if it doesn't, it will be called again */
|
||||||
*p++ = 0xeb;
|
*p++ = 0xeb;
|
||||||
*p++ = 0xfc; /* jmp RMCB */
|
*p++ = 0xfc; /* jmp RMCB */
|
||||||
#elif defined(__i386__)
|
|
||||||
LPVOID RMCBmem = DOSMEM_GetBlock(0, 15, &uParagraph);
|
|
||||||
LPBYTE p = RMCBmem;
|
|
||||||
|
|
||||||
*p++ = 0x68; /* pushl */
|
|
||||||
*(LPVOID *)p = NewRMCB;
|
|
||||||
p+=4;
|
|
||||||
*p++ = 0x9a; /* lcall */
|
|
||||||
*(FARPROC16 *)p = (FARPROC16)RMCallbackProc; /* FIXME: register relay */
|
|
||||||
p+=4;
|
|
||||||
*(WORD *)p = __get_cs();
|
|
||||||
p+=2;
|
|
||||||
*p++=0xc3; /* lret (FIXME?) */
|
|
||||||
#else
|
|
||||||
uParagraph = 0;
|
|
||||||
#endif
|
|
||||||
NewRMCB->address = MAKELONG(0, uParagraph);
|
NewRMCB->address = MAKELONG(0, uParagraph);
|
||||||
NewRMCB->next = FirstRMCB;
|
NewRMCB->next = FirstRMCB;
|
||||||
FirstRMCB = NewRMCB;
|
FirstRMCB = NewRMCB;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user