Moved some system dependencies to loader/dos/dosvm.c. Implemented
[wine/gsoc_dplay.git] / loader / dos / dosvm.c
blob93d8338d2485018d439f0bf07ec9a83267ff0c1a
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 "debugger.h"
25 #include "module.h"
26 #include "task.h"
27 #include "ldt.h"
28 #include "dosexe.h"
30 #ifdef MZ_SUPPORTED
32 #include <sys/mman.h>
33 #include <sys/vm86.h>
35 static void DOSVM_Dump( LPDOSTASK lpDosTask, int fn,
36 struct vm86plus_struct*VM86 )
38 unsigned iofs;
39 BYTE*inst;
40 int x;
42 switch (VM86_TYPE(fn)) {
43 case VM86_SIGNAL:
44 printf("Trapped signal\n"); break;
45 case VM86_UNKNOWN:
46 printf("Trapped unhandled GPF\n"); break;
47 case VM86_INTx:
48 printf("Trapped INT %02x\n",VM86_ARG(fn)); break;
49 case VM86_STI:
50 printf("Trapped STI\n"); break;
51 case VM86_PICRETURN:
52 printf("Trapped due to pending PIC request\n"); break;
53 case VM86_TRAP:
54 printf("Trapped debug request\n"); break;
56 #define REGS VM86->regs
57 fprintf(stderr,"AX=%04lX CX=%04lX DX=%04lX BX=%04lX\n",REGS.eax,REGS.ebx,REGS.ecx,REGS.edx);
58 fprintf(stderr,"SI=%04lX DI=%04lX SP=%04lX BP=%04lX\n",REGS.esi,REGS.edi,REGS.esp,REGS.ebp);
59 fprintf(stderr,"CS=%04X DS=%04X ES=%04X SS=%04X\n",REGS.cs,REGS.ds,REGS.es,REGS.ss);
60 fprintf(stderr,"EIP=%04lX EFLAGS=%08lX\n",REGS.eip,REGS.eflags);
62 iofs=((DWORD)REGS.cs<<4)+REGS.eip;
63 #undef REGS
64 inst=(BYTE*)lpDosTask->img+iofs;
65 printf("Opcodes:");
66 for (x=0; x<8; x++) printf(" %02x",inst[x]);
67 printf("\n");
69 exit(0);
72 static int DOSVM_Int(int vect, PCONTEXT context )
74 /* moved to INT_RealModeInterrupt in msdos/interrupts.c */
75 INT_RealModeInterrupt(vect,context);
76 return 0;
79 #define CV CP(eax,Eax); CP(ecx,Ecx); CP(edx,Edx); CP(ebx,Ebx); \
80 CP(esi,Esi); CP(edi,Edi); CP(esp,Esp); CP(ebp,Ebp); \
81 CP(cs,SegCs); CP(ds,SegDs); CP(es,SegEs); \
82 CP(ss,SegSs); CP(fs,SegFs); CP(gs,SegGs); \
83 CP(eip,Eip); CP(eflags,EFlags)
85 static int DOSVM_Process( LPDOSTASK lpDosTask, int fn,
86 struct vm86plus_struct*VM86 )
88 CONTEXT context;
89 int ret=0;
91 #define CP(x,y) context.y = VM86->regs.x
92 CV;
93 #undef CP
94 (void*)V86BASE(&context)=lpDosTask->img;
96 switch (VM86_TYPE(fn)) {
97 case VM86_SIGNAL:
98 printf("Trapped signal\n");
99 ret=-1; break;
100 case VM86_UNKNOWN: /* unhandled GPF */
101 DOSVM_Dump(lpDosTask,fn,VM86);
102 ctx_debug(SIGSEGV,&context);
103 break;
104 case VM86_INTx:
105 TRACE(int,"DOS EXE calls INT %02x with AX=%04lx\n",VM86_ARG(fn),context.Eax);
106 ret=DOSVM_Int(VM86_ARG(fn),&context); break;
107 case VM86_STI:
108 break;
109 case VM86_PICRETURN:
110 printf("Trapped due to pending PIC request\n"); break;
111 case VM86_TRAP:
112 ctx_debug(SIGTRAP,&context);
113 break;
114 default:
115 DOSVM_Dump(lpDosTask,fn,VM86);
118 #define CP(x,y) VM86->regs.x = context.y
120 #undef CP
121 return ret;
124 int DOSVM_Enter( PCONTEXT context )
126 TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
127 NE_MODULE *pModule = NE_GetPtr( pTask->hModule );
128 LPDOSTASK lpDosTask;
129 struct vm86plus_struct VM86;
130 int stat;
132 GlobalUnlock16( GetCurrentTask() );
133 if (!pModule) {
134 ERR(module,"No task is currently active!\n");
135 return -1;
137 if (!pModule->lpDosTask) {
138 /* no VM86 (dosmod) task is currently running, start one */
139 if ((lpDosTask = calloc(1, sizeof(DOSTASK))) == NULL)
140 return 0;
141 lpDosTask->hModule=pModule->self;
142 stat=MZ_InitMemory(lpDosTask,pModule);
143 if (stat>=32) stat=MZ_InitTask(lpDosTask);
144 if (stat<32) {
145 free(lpDosTask);
146 return -1;
148 pModule->lpDosTask = lpDosTask;
149 pModule->dos_image = lpDosTask->img;
150 /* Note: we're leaving it running after this, in case we need it again,
151 as this minimizes the overhead of starting it up every time...
152 it will be killed automatically when the current task terminates */
153 } else lpDosTask=pModule->lpDosTask;
155 if (context) {
156 #define CP(x,y) VM86.regs.x = context->y
158 #undef CP
159 } else {
160 /* initial setup */
161 memset(&VM86,0,sizeof(VM86));
162 VM86.regs.cs=lpDosTask->init_cs;
163 VM86.regs.eip=lpDosTask->init_ip;
164 VM86.regs.ss=lpDosTask->init_ss;
165 VM86.regs.esp=lpDosTask->init_sp;
166 VM86.regs.ds=lpDosTask->psp_seg;
167 VM86.regs.es=lpDosTask->psp_seg;
168 /* hmm, what else do we need? */
171 /* main exchange loop */
172 stat = VM86_ENTER;
173 do {
174 /* transmit VM86 structure to dosmod task */
175 if (write(lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat))
176 return -1;
177 if (write(lpDosTask->write_pipe,&VM86,sizeof(VM86))!=sizeof(VM86))
178 return -1;
179 /* wait for response */
180 do {
181 if (read(lpDosTask->read_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
182 if ((errno==EINTR)||(errno==EAGAIN)) continue;
183 return -1;
185 } while (0);
186 do {
187 if (read(lpDosTask->read_pipe,&VM86,sizeof(VM86))!=sizeof(VM86)) {
188 if ((errno==EINTR)||(errno==EAGAIN)) continue;
189 return -1;
191 } while (0);
192 /* got response */
193 } while (DOSVM_Process(lpDosTask,stat,&VM86)>=0);
195 if (context) {
196 #define CP(x,y) context->y = VM86.regs.x
198 #undef CP
200 return 0;
203 #else /* !MZ_SUPPORTED */
205 int DOSVM_Enter( PCONTEXT context )
207 ERR(module,"DOS realmode not supported on this architecture!\n");
208 return -1;
211 #endif