2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
5 * PURPOSE: 16 and 32-bit Callbacks Support
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
10 /* INCLUDES *******************************************************************/
20 /* PRIVATE VARIABLES **********************************************************/
23 * This is the list of registered 32-bit Interrupt handlers.
25 EMULATOR_INT32_PROC Int32Proc
[EMULATOR_MAX_INT32_NUM
] = { NULL
};
28 #define BOP_CONTROL 0xFF // Control BOP Handler
29 #define BOP_CONTROL_DEFFUNC 0x00 // Default Control BOP Function
31 /* 32-bit Interrupt dispatcher function code for the Control BOP Handler */
32 #define BOP_CONTROL_INT32 0xFF
35 #define BOP(num) LOBYTE(EMULATOR_BOP), HIBYTE(EMULATOR_BOP), (num)
36 #define UnSimulate16(trap) \
38 *(PUSHORT)(trap) = EMULATOR_BOP; \
39 (trap) += sizeof(USHORT); \
40 *(trap) = BOP_UNSIMULATE; \
42 // #define UnSimulate16 MAKELONG(EMULATOR_BOP, BOP_UNSIMULATE) // BOP(BOP_UNSIMULATE)
44 #define CALL16_TRAMPOLINE_SIZE (1 * sizeof(ULONGLONG))
45 #define INT16_TRAMPOLINE_SIZE (1 * sizeof(ULONGLONG))
50 // If you modify the code stubs here, think also
51 // about updating them in int32.c too!!
54 /* 16-bit generic interrupt code for calling a 32-bit interrupt handler */
59 /* Push the value of the interrupt to be called */
60 0x6A, 0xFF, // push i (patchable to 0x6A, 0xIntNum)
62 /* The BOP Sequence */
65 BOP(BOP_CONTROL
), // Control BOP
66 BOP_CONTROL_INT32
, // 32-bit Interrupt dispatcher
68 0x73, 0x04, // jnc EXIT (offset +4)
72 // HACK: The following instruction should be HLT!
75 0xEB, 0xF5, // jmp BOP_SEQ (offset -11)
78 0x44, 0x44, // inc sp, inc sp
82 /* PUBLIC FUNCTIONS ***********************************************************/
85 InitializeContext(IN PCALLBACK16 Context
,
89 Context
->TrampolineFarPtr
= MAKELONG(Offset
, Segment
);
90 Context
->Segment
= Segment
;
91 Context
->NextOffset
= Offset
+ max(CALL16_TRAMPOLINE_SIZE
,
92 INT16_TRAMPOLINE_SIZE
);
96 Call16(IN USHORT Segment
,
100 USHORT OrgCS
= getCS();
101 USHORT OrgIP
= getIP();
103 /* Set the new CS:IP */
107 DPRINT("Call16(%04X:%04X)\n", Segment
, Offset
);
109 /* Start CPU simulation */
120 RegisterCallback16(IN ULONG FarPtr
,
121 IN LPBYTE CallbackCode
,
122 IN SIZE_T CallbackSize
,
123 OUT PSIZE_T CodeSize OPTIONAL
)
125 LPBYTE CodeStart
= (LPBYTE
)FAR_POINTER(FarPtr
);
126 LPBYTE Code
= CodeStart
;
128 SIZE_T OurCodeSize
= CallbackSize
;
130 if (CallbackCode
== NULL
) CallbackSize
= 0;
134 /* 16-bit interrupt code */
135 RtlCopyMemory(Code
, CallbackCode
, CallbackSize
);
136 Code
+= CallbackSize
;
139 /* Return the real size of the code if needed */
140 if (CodeSize
) *CodeSize
= OurCodeSize
; // == (ULONG_PTR)Code - (ULONG_PTR)CodeStart;
142 // /* Return the entry-point address for 32-bit calls */
143 // return (ULONG_PTR)(CodeStart + CallbackSize);
148 RunCallback16(IN PCALLBACK16 Context
,
151 PUCHAR TrampolineBase
= (PUCHAR
)FAR_POINTER(Context
->TrampolineFarPtr
);
152 PUCHAR Trampoline
= TrampolineBase
;
153 UCHAR OldTrampoline
[CALL16_TRAMPOLINE_SIZE
];
155 /* Save the old trampoline */
156 ((PULONGLONG
)&OldTrampoline
)[0] = ((PULONGLONG
)TrampolineBase
)[0];
158 DPRINT1("RunCallback16(0x%p)\n", FarPtr
);
160 /* Build the generic entry-point for 16-bit far calls */
161 *Trampoline
++ = 0x9A; // Call far seg:off
162 *(PULONG
)Trampoline
= FarPtr
;
163 Trampoline
+= sizeof(ULONG
);
164 UnSimulate16(Trampoline
);
166 /* Perform the call */
167 Call16(HIWORD(Context
->TrampolineFarPtr
),
168 LOWORD(Context
->TrampolineFarPtr
));
170 /* Restore the old trampoline */
171 ((PULONGLONG
)TrampolineBase
)[0] = ((PULONGLONG
)&OldTrampoline
)[0];
177 RegisterInt16(IN ULONG FarPtr
,
179 IN LPBYTE CallbackCode
,
180 IN SIZE_T CallbackSize
,
181 OUT PSIZE_T CodeSize OPTIONAL
)
183 /* Get a pointer to the IVT and set the corresponding entry (far pointer) */
184 LPDWORD IntVecTable
= (LPDWORD
)SEG_OFF_TO_PTR(0x0000, 0x0000);
185 IntVecTable
[IntNumber
] = FarPtr
;
187 /* Register the 16-bit callback */
188 return RegisterCallback16(FarPtr
,
195 RegisterInt32(IN ULONG FarPtr
,
197 IN EMULATOR_INT32_PROC IntHandler
,
198 OUT PSIZE_T CodeSize OPTIONAL
)
200 /* Array for holding our copy of the 16-bit interrupt callback */
201 BYTE IntCallback
[sizeof(Int16To32
)/sizeof(BYTE
)];
203 /* Check whether the 32-bit interrupt was already registered */
205 if (Int32Proc
[IntNumber
] != NULL
)
207 DPRINT1("RegisterInt32: Interrupt 0x%X already registered!\n", IntNumber
);
212 /* Register the 32-bit interrupt handler */
213 Int32Proc
[IntNumber
] = IntHandler
;
215 /* Copy the generic 16-bit interrupt callback and patch it */
216 RtlCopyMemory(IntCallback
, Int16To32
, sizeof(Int16To32
));
217 IntCallback
[2] = IntNumber
;
219 /* Register the 16-bit interrupt callback */
220 return RegisterInt16(FarPtr
,
228 Int32Call(IN PCALLBACK16 Context
,
231 PUCHAR TrampolineBase
= (PUCHAR
)FAR_POINTER(Context
->TrampolineFarPtr
);
232 PUCHAR Trampoline
= TrampolineBase
;
233 UCHAR OldTrampoline
[INT16_TRAMPOLINE_SIZE
];
235 DPRINT("Int32Call(0x%X)\n", IntNumber
);
237 /* Save the old trampoline */
238 ((PULONGLONG
)&OldTrampoline
)[0] = ((PULONGLONG
)TrampolineBase
)[0];
240 /* Build the generic entry-point for 16-bit calls */
241 if (IntNumber
== 0x03)
243 /* We are redefining for INT 03h */
244 *Trampoline
++ = 0xCC; // Call INT 03h
245 /** *Trampoline++ = 0x90; // nop **/
249 /* Normal interrupt */
250 *Trampoline
++ = 0xCD; // Call INT XXh
251 *Trampoline
++ = IntNumber
;
253 UnSimulate16(Trampoline
);
255 /* Perform the call */
256 Call16(HIWORD(Context
->TrampolineFarPtr
),
257 LOWORD(Context
->TrampolineFarPtr
));
259 /* Restore the old trampoline */
260 ((PULONGLONG
)TrampolineBase
)[0] = ((PULONGLONG
)&OldTrampoline
)[0];
265 VOID WINAPI
Int32Dispatch(LPWORD Stack
)
267 /* Get the interrupt number */
268 BYTE IntNum
= LOBYTE(Stack
[STACK_INT_NUM
]);
270 /* Call the 32-bit Interrupt handler */
271 if (Int32Proc
[IntNum
] != NULL
)
272 Int32Proc
[IntNum
](Stack
);
274 DPRINT1("Unhandled 32-bit interrupt: 0x%02X, AX = 0x%04X\n", IntNum
, getAX());
277 static VOID WINAPI
ControlBop(LPWORD Stack
)
279 /* Get the Function Number and skip it */
280 BYTE FuncNum
= *(PBYTE
)SEG_OFF_TO_PTR(getCS(), getIP());
283 if (FuncNum
== BOP_CONTROL_INT32
)
284 Int32Dispatch(Stack
);
286 // DPRINT1("Unassigned Control BOP Function: 0x%02X\n", FuncNum);
287 DisplayMessage(L
"Unassigned Control BOP Function: 0x%02X\n", FuncNum
);
290 VOID
InitializeCallbacks(VOID
)
292 /* Register the Control BOP */
293 RegisterBop(BOP_CONTROL
, ControlBop
);