4 * Copyright 2002 Jukka Heinonen
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22 #include "wine/debug.h"
23 #include "wine/winbase16.h"
25 WINE_DEFAULT_DEBUG_CHANNEL(int);
27 static FARPROC16 DOSVM_Vectors16[256];
28 static FARPROC48 DOSVM_Vectors48[256];
29 static const INTPROC DOSVM_VectorsBuiltin[] =
33 /* 08 */ 0, DOSVM_Int09Handler, 0, 0,
35 /* 10 */ DOSVM_Int10Handler, DOSVM_Int11Handler, DOSVM_Int12Handler, DOSVM_Int13Handler,
36 /* 14 */ 0, DOSVM_Int15Handler, DOSVM_Int16Handler, DOSVM_Int17Handler,
37 /* 18 */ 0, 0, DOSVM_Int1aHandler, 0,
39 /* 20 */ DOSVM_Int20Handler, DOSVM_Int21Handler, 0, 0,
40 /* 24 */ 0, DOSVM_Int25Handler, DOSVM_Int26Handler, 0,
41 /* 28 */ 0, DOSVM_Int29Handler, DOSVM_Int2aHandler, 0,
42 /* 2C */ 0, 0, 0, DOSVM_Int2fHandler,
43 /* 30 */ 0, DOSVM_Int31Handler, 0, DOSVM_Int33Handler,
44 /* 34 */ DOSVM_Int34Handler, DOSVM_Int35Handler, DOSVM_Int36Handler, DOSVM_Int37Handler,
45 /* 38 */ DOSVM_Int38Handler, DOSVM_Int39Handler, DOSVM_Int3aHandler, DOSVM_Int3bHandler,
46 /* 3C */ DOSVM_Int3cHandler, DOSVM_Int3dHandler, DOSVM_Int3eHandler, 0,
47 /* 40 */ 0, DOSVM_Int41Handler, 0, 0,
49 /* 48 */ 0, 0, 0, DOSVM_Int4bHandler,
54 /* 5C */ DOSVM_Int5cHandler, 0, 0, 0,
56 /* 64 */ 0, 0, 0, DOSVM_Int67Handler
60 /**********************************************************************
61 * DOSVM_DefaultHandler
63 * Default interrupt handler. This will be used to emulate all
64 * interrupts that don't have their own interrupt handler.
66 void WINAPI DOSVM_DefaultHandler( CONTEXT86 *context )
71 /**********************************************************************
74 * Simple DOSRELAY that interprets its argument as INTPROC and calls it.
76 static void DOSVM_IntProcRelay( CONTEXT86 *context, LPVOID data )
78 INTPROC proc = (INTPROC)data;
83 /**********************************************************************
86 * This routine is used to make default int25 and int26 handlers leave the
87 * original eflags into stack. In order to do this, stack is manipulated
88 * so that it actually contains two copies of eflags, one of which is
89 * popped during return from interrupt handler.
91 static void DOSVM_PushFlags( CONTEXT86 *context, BOOL islong, BOOL isstub )
95 DWORD *stack = CTX_SEG_OFF_TO_LIN(context,
98 context->Esp += -4; /* One item will be added to stack. */
104 stack += 2; /* Pop ip and cs. */
105 *(--stack) = context->EFlags;
110 *(--stack) = context->EFlags;
114 WORD *stack = CTX_SEG_OFF_TO_LIN(context,
117 ADD_LOWORD( context->Esp, -2 ); /* One item will be added to stack. */
123 stack += 2; /* Pop ip and cs. */
124 *(--stack) = LOWORD(context->EFlags);
129 *(--stack) = LOWORD(context->EFlags);
134 /**********************************************************************
135 * DOSVM_EmulateInterruptPM
137 * Emulate software interrupt in 16-bit or 32-bit protected mode.
138 * Called from signal handler when intXX opcode is executed.
140 * Pushes interrupt frame to stack and changes instruction
141 * pointer to interrupt handler.
143 void WINAPI DOSVM_EmulateInterruptPM( CONTEXT86 *context, BYTE intnum )
145 if (context->SegCs == DOSVM_dpmi_segments->dpmi_sel)
147 DOSVM_BuildCallFrame( context,
149 DOSVM_RawModeSwitchHandler );
151 else if (context->SegCs == DOSVM_dpmi_segments->relay_code_sel)
154 * This must not be called using DOSVM_BuildCallFrame.
156 DOSVM_RelayHandler( context );
158 else if (context->SegCs == DOSVM_dpmi_segments->int48_sel)
160 if (intnum == 0x25 || intnum == 0x26)
161 DOSVM_PushFlags( context, TRUE, TRUE );
163 DOSVM_BuildCallFrame( context,
165 DOSVM_GetBuiltinHandler(intnum) );
167 else if (context->SegCs == DOSVM_dpmi_segments->int16_sel)
169 if (intnum == 0x25 || intnum == 0x26)
170 DOSVM_PushFlags( context, FALSE, TRUE );
172 DOSVM_BuildCallFrame( context,
174 DOSVM_GetBuiltinHandler(intnum) );
176 else if(DOSVM_IsDos32())
178 FARPROC48 addr = DOSVM_GetPMHandler48( intnum );
180 if (addr.selector == DOSVM_dpmi_segments->int48_sel)
182 if (intnum == 0x25 || intnum == 0x26)
183 DOSVM_PushFlags( context, TRUE, FALSE );
185 DOSVM_BuildCallFrame( context,
187 DOSVM_GetBuiltinHandler(intnum) );
191 DWORD *stack = CTX_SEG_OFF_TO_LIN(context,
195 /* Push the flags and return address on the stack */
196 *(--stack) = context->EFlags;
197 *(--stack) = context->SegCs;
198 *(--stack) = context->Eip;
201 /* Jump to the interrupt handler */
202 context->SegCs = addr.selector;
203 context->Eip = addr.offset;
208 FARPROC16 addr = DOSVM_GetPMHandler16( intnum );
210 if (SELECTOROF(addr) == DOSVM_dpmi_segments->int16_sel)
212 if (intnum == 0x25 || intnum == 0x26)
213 DOSVM_PushFlags( context, FALSE, FALSE );
215 DOSVM_BuildCallFrame( context,
217 DOSVM_GetBuiltinHandler(intnum) );
221 WORD *stack = CTX_SEG_OFF_TO_LIN(context,
225 /* Push the flags and return address on the stack */
226 *(--stack) = LOWORD(context->EFlags);
227 *(--stack) = context->SegCs;
228 *(--stack) = LOWORD(context->Eip);
229 ADD_LOWORD( context->Esp, -6 );
231 /* Jump to the interrupt handler */
232 context->SegCs = HIWORD(addr);
233 context->Eip = LOWORD(addr);
238 /**********************************************************************
241 * Return the real mode interrupt vector for a given interrupt.
243 FARPROC16 DOSVM_GetRMHandler( BYTE intnum )
245 return ((FARPROC16*)0)[intnum];
248 /**********************************************************************
251 * Set the real mode interrupt handler for a given interrupt.
253 void DOSVM_SetRMHandler( BYTE intnum, FARPROC16 handler )
255 TRACE("Set real mode interrupt vector %02x <- %04x:%04x\n",
256 intnum, HIWORD(handler), LOWORD(handler) );
257 ((FARPROC16*)0)[intnum] = handler;
261 /**********************************************************************
262 * DOSVM_GetPMHandler16
264 * Return the protected mode interrupt vector for a given interrupt.
266 FARPROC16 DOSVM_GetPMHandler16( BYTE intnum )
268 if (!DOSVM_Vectors16[intnum])
270 FARPROC16 proc = (FARPROC16)MAKESEGPTR( DOSVM_dpmi_segments->int16_sel,
272 DOSVM_Vectors16[intnum] = proc;
274 return DOSVM_Vectors16[intnum];
278 /**********************************************************************
279 * DOSVM_SetPMHandler16
281 * Set the protected mode interrupt handler for a given interrupt.
283 void DOSVM_SetPMHandler16( BYTE intnum, FARPROC16 handler )
285 TRACE("Set protected mode interrupt vector %02x <- %04x:%04x\n",
286 intnum, HIWORD(handler), LOWORD(handler) );
287 DOSVM_Vectors16[intnum] = handler;
290 /**********************************************************************
291 * DOSVM_GetPMHandler48
293 * Return the protected mode interrupt vector for a given interrupt.
294 * Used to get 48-bit pointer for 32-bit interrupt handlers in DPMI32.
296 FARPROC48 DOSVM_GetPMHandler48( BYTE intnum )
298 if (!DOSVM_Vectors48[intnum].selector)
300 DOSVM_Vectors48[intnum].selector = DOSVM_dpmi_segments->int48_sel;
301 DOSVM_Vectors48[intnum].offset = 6 * intnum;
303 return DOSVM_Vectors48[intnum];
306 /**********************************************************************
307 * DOSVM_SetPMHandler48
309 * Set the protected mode interrupt handler for a given interrupt.
310 * Used to set 48-bit pointer for 32-bit interrupt handlers in DPMI32.
312 void DOSVM_SetPMHandler48( BYTE intnum, FARPROC48 handler )
314 TRACE("Set 32-bit protected mode interrupt vector %02x <- %04x:%08lx\n",
315 intnum, handler.selector, handler.offset );
316 DOSVM_Vectors48[intnum] = handler;
319 /**********************************************************************
320 * DOSVM_GetBuiltinHandler
322 * Return Wine interrupt handler procedure for a given interrupt.
324 INTPROC DOSVM_GetBuiltinHandler( BYTE intnum )
326 if (intnum < sizeof(DOSVM_VectorsBuiltin)/sizeof(INTPROC)) {
327 INTPROC proc = DOSVM_VectorsBuiltin[intnum];
332 WARN("int%x not implemented, returning dummy handler\n", intnum );
333 return DOSVM_DefaultHandler;
336 /**********************************************************************
337 * DOSVM_CallBuiltinHandler
339 * Execute Wine interrupt handler procedure.
341 void WINAPI DOSVM_CallBuiltinHandler( CONTEXT86 *context, BYTE intnum )
343 INTPROC proc = DOSVM_GetBuiltinHandler( intnum );