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);
         }