8e039333587b1e2877ecaabb4a6ac0c94961866a
[reactos.git] / subsystems / ntvdm / int32.c
1 /*
2 * COPYRIGHT: GPL - See COPYING in the top level directory
3 * PROJECT: ReactOS Virtual DOS Machine
4 * FILE: int32.c
5 * PURPOSE: 32-bit Interrupt Handlers
6 * PROGRAMMERS: Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 * Hermes Belusca-Maito (hermes.belusca@sfr.fr)
8 */
9
10 /* INCLUDES *******************************************************************/
11
12 #define NDEBUG
13
14 #include "emulator.h"
15 #include "int32.h"
16
17 #include "bop.h"
18 #include "bios.h"
19
20 /* PRIVATE VARIABLES **********************************************************/
21
22 LPCWSTR ExceptionName[] =
23 {
24 L"Division By Zero",
25 L"Debug",
26 L"Unexpected Error",
27 L"Breakpoint",
28 L"Integer Overflow",
29 L"Bound Range Exceeded",
30 L"Invalid Opcode",
31 L"FPU Not Available"
32 };
33
34 /*
35 * This is the list of registered 32-bit Interrupt handlers.
36 */
37 EMULATOR_INT32_PROC Int32Proc[EMULATOR_MAX_INT32_NUM] = { NULL };
38
39 /* PUBLIC FUNCTIONS ***********************************************************/
40
41 VOID WINAPI Exception(BYTE ExceptionNumber, LPWORD Stack)
42 {
43 WORD CodeSegment, InstructionPointer;
44 PBYTE Opcode;
45
46 ASSERT(ExceptionNumber < 8);
47
48 /* Get the CS:IP */
49 InstructionPointer = Stack[STACK_IP];
50 CodeSegment = Stack[STACK_CS];
51 Opcode = (PBYTE)SEG_OFF_TO_PTR(CodeSegment, InstructionPointer);
52
53 /* Display a message to the user */
54 DisplayMessage(L"Exception: %s occured at %04X:%04X\n"
55 L"Opcode: %02X %02X %02X %02X %02X %02X %02X %02X %02X %02X",
56 ExceptionName[ExceptionNumber],
57 CodeSegment,
58 InstructionPointer,
59 Opcode[0],
60 Opcode[1],
61 Opcode[2],
62 Opcode[3],
63 Opcode[4],
64 Opcode[5],
65 Opcode[6],
66 Opcode[7],
67 Opcode[8],
68 Opcode[9]);
69
70 /* Stop the VDM */
71 VdmRunning = FALSE;
72 return;
73 }
74
75 #if 0
76 VOID WINAPI IrqDispatch(BYTE IrqNumber, LPWORD Stack)
77 {
78 /* Check if this was an PIC IRQ */
79 if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8)
80 {
81 /* It was an IRQ from the master PIC */
82 BiosHandleIrq(IntNum - BIOS_PIC_MASTER_INT, Stack);
83 }
84 else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8)
85 {
86 /* It was an IRQ from the slave PIC */
87 BiosHandleIrq(IntNum - BIOS_PIC_SLAVE_INT + 8, Stack);
88 }
89
90 return;
91 }
92 #endif
93
94 VOID WINAPI Int32Dispatch(LPWORD Stack)
95 {
96 BYTE IntNum;
97
98 /* Get the interrupt number */
99 IntNum = LOBYTE(Stack[STACK_INT_NUM]);
100
101 /* Check if this was an exception */
102 if (IntNum < 8)
103 {
104 Exception(IntNum, Stack);
105 return;
106 }
107
108 /* Check if this was an PIC IRQ */
109 if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8)
110 {
111 /* It was an IRQ from the master PIC */
112 BiosHandleIrq(IntNum - BIOS_PIC_MASTER_INT, Stack);
113 return;
114 }
115 else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8)
116 {
117 /* It was an IRQ from the slave PIC */
118 BiosHandleIrq(IntNum - BIOS_PIC_SLAVE_INT + 8, Stack);
119 return;
120 }
121
122 /* Call the 32-bit Interrupt handler */
123 if (Int32Proc[IntNum] != NULL)
124 Int32Proc[IntNum](Stack);
125 else
126 DPRINT1("Unhandled 32-bit interrupt: 0x%02X\n", IntNum);
127 }
128
129 VOID WINAPI InitializeInt32(WORD BiosSegment)
130 {
131 USHORT i;
132 WORD Offset = 0;
133
134 LPDWORD IntVecTable = (LPDWORD)BaseAddress;
135 LPBYTE BiosCode = (LPBYTE)SEG_OFF_TO_PTR(BiosSegment, 0);
136
137 /* Generate ISR stubs and fill the IVT */
138 for (i = 0x00; i <= 0xFF; i++)
139 {
140 IntVecTable[i] = MAKELONG(Offset, BiosSegment);
141
142 BiosCode[Offset++] = 0xFB; // sti
143
144 BiosCode[Offset++] = 0x6A; // push i
145 BiosCode[Offset++] = (UCHAR)i;
146
147 BiosCode[Offset++] = 0x6A; // push 0
148 BiosCode[Offset++] = 0x00;
149
150 // BOP_SEQ:
151 BiosCode[Offset++] = 0xF8; // clc
152
153 BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence
154 BiosCode[Offset++] = HIBYTE(EMULATOR_BOP);
155 BiosCode[Offset++] = EMULATOR_CTRL_BOP; // Control BOP
156 BiosCode[Offset++] = CTRL_BOP_INT32; // 32-bit Interrupt dispatcher
157
158 BiosCode[Offset++] = 0x73; // jnc EXIT (offset +3)
159 BiosCode[Offset++] = 0x03;
160
161 // HACK: The following instruction should be HLT!
162 BiosCode[Offset++] = 0x90; // nop
163
164 BiosCode[Offset++] = 0xEB; // jmp BOP_SEQ (offset -10)
165 BiosCode[Offset++] = 0xF6;
166
167 // EXIT:
168 BiosCode[Offset++] = 0x83; // add sp, 4
169 BiosCode[Offset++] = 0xC4;
170 BiosCode[Offset++] = 0x04;
171
172 BiosCode[Offset++] = 0xCF; // iret
173 }
174 }
175
176 VOID WINAPI RegisterInt32(BYTE IntNumber, EMULATOR_INT32_PROC IntHandler)
177 {
178 Int32Proc[IntNumber] = IntHandler;
179 }
180
181 /* EOF */