Release 980927
[wine.git] / loader / dos / dosvm.c
blob2223a08b07d7078efa7b32f67f008095d400304d
1 /*
2 * DOS Virtual Machine
4 * Copyright 1998 Ove Kåven
6 * This code hasn't been completely cleaned up yet.
7 */
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <string.h>
12 #include <errno.h>
13 #include <fcntl.h>
14 #include <signal.h>
15 #include <unistd.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include "windows.h"
19 #include "winbase.h"
20 #include "winnt.h"
21 #include "msdos.h"
22 #include "miscemu.h"
23 #include "debug.h"
24 #include "module.h"
25 #include "task.h"
26 #include "ldt.h"
27 #include "dosexe.h"
29 #ifdef MZ_SUPPORTED
31 static void DOSVM_Dump( LPDOSTASK lpDosTask)
33 unsigned iofs;
34 BYTE*inst;
35 int x;
37 switch (VM86_TYPE(lpDosTask->fn)) {
38 case VM86_SIGNAL:
39 printf("Trapped signal\n"); break;
40 case VM86_UNKNOWN:
41 printf("Trapped unhandled GPF\n"); break;
42 case VM86_INTx:
43 printf("Trapped INT %02x\n",VM86_ARG(lpDosTask->fn)); break;
44 case VM86_STI:
45 printf("Trapped STI\n"); break;
46 case VM86_PICRETURN:
47 printf("Trapped due to pending PIC request\n"); break;
48 case VM86_TRAP:
49 printf("Trapped debug request\n"); break;
51 #define REGS lpDosTask->VM86.regs
52 fprintf(stderr,"AX=%04lX CX=%04lX DX=%04lX BX=%04lX\n",REGS.eax,REGS.ebx,REGS.ecx,REGS.edx);
53 fprintf(stderr,"SI=%04lX DI=%04lX SP=%04lX BP=%04lX\n",REGS.esi,REGS.edi,REGS.esp,REGS.ebp);
54 fprintf(stderr,"CS=%04X DS=%04X ES=%04X SS=%04X\n",REGS.cs,REGS.ds,REGS.es,REGS.ss);
55 fprintf(stderr,"EIP=%04lX EFLAGS=%08lX\n",REGS.eip,REGS.eflags);
57 iofs=((DWORD)REGS.cs<<4)+REGS.eip;
58 #undef REGS
59 inst=(BYTE*)lpDosTask->img+iofs;
60 printf("Opcodes:");
61 for (x=0; x<8; x++) printf(" %02x",inst[x]);
62 printf("\n");
64 exit(0);
67 static int DOSVM_Int(int vect, PCONTEXT context )
69 /* moved to INT_RealModeInterrupt in msdos/interrupts.c */
70 INT_RealModeInterrupt(vect,context);
71 return 0;
74 #define CV CP(eax,Eax); CP(ecx,Ecx); CP(edx,Edx); CP(ebx,Ebx); \
75 CP(esi,Esi); CP(edi,Edi); CP(esp,Esp); CP(ebp,Ebp); \
76 CP(cs,SegCs); CP(ds,SegDs); CP(es,SegEs); \
77 CP(ss,SegSs); CP(fs,SegFs); CP(gs,SegGs); \
78 CP(eip,Eip); CP(eflags,EFlags)
80 int DOSVM_Process( LPDOSTASK lpDosTask )
82 CONTEXT context;
83 int ret=0;
85 #define CP(x,y) context.y = lpDosTask->VM86.regs.x
86 CV;
87 #undef CP
88 (void*)V86BASE(&context)=lpDosTask->img;
90 switch (VM86_TYPE(lpDosTask->fn)) {
91 case VM86_SIGNAL:
92 printf("Trapped signal\n");
93 ret=-1; break;
94 case VM86_UNKNOWN: /* unhandled GPF */
95 DOSVM_Dump(lpDosTask);
96 ctx_debug(SIGSEGV,&context);
97 break;
98 case VM86_INTx:
99 TRACE(int,"DOS EXE calls INT %02x with AX=%04lx\n",VM86_ARG(lpDosTask->fn),context.Eax);
100 ret=DOSVM_Int(VM86_ARG(lpDosTask->fn),&context); break;
101 case VM86_STI:
102 break;
103 case VM86_PICRETURN:
104 printf("Trapped due to pending PIC request\n"); break;
105 case VM86_TRAP:
106 ctx_debug(SIGTRAP,&context);
107 break;
108 default:
109 DOSVM_Dump(lpDosTask);
112 lpDosTask->fn=VM86_ENTER;
113 #define CP(x,y) lpDosTask->VM86.regs.x = context.y
115 #undef CP
116 return ret;
119 int DOSVM_Enter( PCONTEXT context )
121 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
122 NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
123 LPDOSTASK lpDosTask;
124 int stat;
126 GlobalUnlock16( GetCurrentTask() );
127 if (!pModule) {
128 ERR(module,"No task is currently active!\n");
129 return -1;
131 if (!pModule->lpDosTask) {
132 /* no VM86 (dosmod) task is currently running, start one */
133 if ((lpDosTask = calloc(1, sizeof(DOSTASK))) == NULL)
134 return 0;
135 lpDosTask->hModule=pModule->self;
136 stat=MZ_InitMemory(lpDosTask,pModule);
137 if (stat>=32) stat=MZ_InitTask(lpDosTask);
138 if (stat<32) {
139 free(lpDosTask);
140 return -1;
142 pModule->lpDosTask = lpDosTask;
143 pModule->dos_image = lpDosTask->img;
144 /* Note: we're leaving it running after this, in case we need it again,
145 as this minimizes the overhead of starting it up every time...
146 it will be killed automatically when the current task terminates */
147 } else lpDosTask=pModule->lpDosTask;
149 if (context) {
150 #define CP(x,y) lpDosTask->VM86.regs.x = context->y
152 #undef CP
155 /* main loop */
156 while ((stat = MZ_RunModule(lpDosTask)) >= 0)
157 if (stat > 0 && DOSVM_Process(lpDosTask) < 0)
158 break;
160 if (context) {
161 #define CP(x,y) context->y = lpDosTask->VM86.regs.x
163 #undef CP
165 return 0;
168 #else /* !MZ_SUPPORTED */
170 int DOSVM_Enter( PCONTEXT context )
172 ERR(module,"DOS realmode not supported on this architecture!\n");
173 return -1;
176 #endif