diff --git a/msdos/dpmi.c b/msdos/dpmi.c index 0b5927c45f4d3b758b48782c9d7903a4c65fa0cf..ed1bc70ff4efee934ec269771ed425ba3a6f3f42 100644 --- a/msdos/dpmi.c +++ b/msdos/dpmi.c @@ -183,6 +183,66 @@ static void INT_SetRealModeContext( REALMODECALL *call, CONTEXT86 *context ) call->ss = SS_reg(context); } +void DPMI_CallRMCB32(RMCB *rmcb, UINT16 ss, DWORD esp, UINT16*es, DWORD*edi) +#if 0 /* original code, which early gccs puke on */ +{ + int _clobber; + __asm__ __volatile__( + "pushl %%ebp\n" + "pushl %%ebx\n" + "pushl %%es\n" + "pushl %%ds\n" + "pushfl\n" + "mov %7,%%es\n" + "mov %5,%%ds\n" + ".byte 0x36, 0xff, 0x18\n" /* lcall *%ss:(%eax) */ + "popl %%ds\n" + "mov %%es,%0\n" + "popl %%es\n" + "popl %%ebx\n" + "popl %%ebp\n" + : "=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 @@ -197,10 +257,11 @@ static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag ) } else { #ifdef __i386__ UINT16 ss,es; - DWORD edi; + 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"); @@ -213,36 +274,18 @@ static void DPMI_CallRMCBProc( CONTEXT86 *context, RMCB *rmcb, WORD flag ) * real-mode call structure. */ if (flag & 1) { /* 32-bit DPMI client */ - int _clobber; - __asm__ __volatile__( - "pushl %%ebp\n" - "pushl %%ebx\n" - "pushl %%es\n" - "pushl %%ds\n" - "pushfl\n" - "mov %7,%%es\n" - "mov %5,%%ds\n" - ".byte 0x36, 0xff, 0x18\n" /* lcall *%ss:(%eax) */ - "popl %%ds\n" - "mov %%es,%0\n" - "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)), - "4" (rmcb->regs_sel), "1" (rmcb->regs_ofs), - "3" (&rmcb->proc_ofs) ); + 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); }