2 * Fast486 386/486 CPU Emulation Library
5 * Copyright (C) 2015 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version 2
10 * of the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
22 /* INCLUDES *******************************************************************/
34 /* DEFAULT CALLBACKS **********************************************************/
38 Fast486MemReadCallback(PFAST486_STATE State
, ULONG Address
, PVOID Buffer
, ULONG Size
)
40 UNREFERENCED_PARAMETER(State
);
41 RtlMoveMemory(Buffer
, UlongToPtr(Address
), Size
);
46 Fast486MemWriteCallback(PFAST486_STATE State
, ULONG Address
, PVOID Buffer
, ULONG Size
)
48 UNREFERENCED_PARAMETER(State
);
49 RtlMoveMemory(UlongToPtr(Address
), Buffer
, Size
);
54 Fast486IoReadCallback(PFAST486_STATE State
, USHORT Port
, PVOID Buffer
, ULONG DataCount
, UCHAR DataSize
)
56 UNREFERENCED_PARAMETER(State
);
57 UNREFERENCED_PARAMETER(Port
);
58 UNREFERENCED_PARAMETER(Buffer
);
59 UNREFERENCED_PARAMETER(DataCount
);
60 UNREFERENCED_PARAMETER(DataSize
);
65 Fast486IoWriteCallback(PFAST486_STATE State
, USHORT Port
, PVOID Buffer
, ULONG DataCount
, UCHAR DataSize
)
67 UNREFERENCED_PARAMETER(State
);
68 UNREFERENCED_PARAMETER(Port
);
69 UNREFERENCED_PARAMETER(Buffer
);
70 UNREFERENCED_PARAMETER(DataCount
);
71 UNREFERENCED_PARAMETER(DataSize
);
76 Fast486BopCallback(PFAST486_STATE State
, UCHAR BopCode
)
78 UNREFERENCED_PARAMETER(State
);
79 UNREFERENCED_PARAMETER(BopCode
);
84 Fast486IntAckCallback(PFAST486_STATE State
)
86 UNREFERENCED_PARAMETER(State
);
88 /* Return something... defaulted to single-step interrupt */
94 Fast486FpuCallback(PFAST486_STATE State
)
96 UNREFERENCED_PARAMETER(State
);
99 /* PUBLIC FUNCTIONS ***********************************************************/
103 Fast486Initialize(PFAST486_STATE State
,
104 FAST486_MEM_READ_PROC MemReadCallback
,
105 FAST486_MEM_WRITE_PROC MemWriteCallback
,
106 FAST486_IO_READ_PROC IoReadCallback
,
107 FAST486_IO_WRITE_PROC IoWriteCallback
,
108 FAST486_BOP_PROC BopCallback
,
109 FAST486_INT_ACK_PROC IntAckCallback
,
110 FAST486_FPU_PROC FpuCallback
,
113 /* Set the callbacks (or use default ones if some are NULL) */
114 State
->MemReadCallback
= (MemReadCallback
? MemReadCallback
: Fast486MemReadCallback
);
115 State
->MemWriteCallback
= (MemWriteCallback
? MemWriteCallback
: Fast486MemWriteCallback
);
116 State
->IoReadCallback
= (IoReadCallback
? IoReadCallback
: Fast486IoReadCallback
);
117 State
->IoWriteCallback
= (IoWriteCallback
? IoWriteCallback
: Fast486IoWriteCallback
);
118 State
->BopCallback
= (BopCallback
? BopCallback
: Fast486BopCallback
);
119 State
->IntAckCallback
= (IntAckCallback
? IntAckCallback
: Fast486IntAckCallback
);
120 State
->FpuCallback
= (FpuCallback
? FpuCallback
: Fast486FpuCallback
);
122 /* Set the TLB (if given) */
131 Fast486Reset(PFAST486_STATE State
)
135 /* Save the callbacks and TLB */
136 FAST486_MEM_READ_PROC MemReadCallback
= State
->MemReadCallback
;
137 FAST486_MEM_WRITE_PROC MemWriteCallback
= State
->MemWriteCallback
;
138 FAST486_IO_READ_PROC IoReadCallback
= State
->IoReadCallback
;
139 FAST486_IO_WRITE_PROC IoWriteCallback
= State
->IoWriteCallback
;
140 FAST486_BOP_PROC BopCallback
= State
->BopCallback
;
141 FAST486_INT_ACK_PROC IntAckCallback
= State
->IntAckCallback
;
142 FAST486_FPU_PROC FpuCallback
= State
->FpuCallback
;
143 PULONG Tlb
= State
->Tlb
;
145 /* Clear the entire structure */
146 RtlZeroMemory(State
, sizeof(*State
));
148 /* Initialize the registers */
149 State
->Flags
.AlwaysSet
= 1;
150 State
->InstPtr
.LowWord
= 0xFFF0;
152 /* Set the CPL to 0 */
155 /* Initialize segments */
156 for (i
= 0; i
< FAST486_NUM_SEG_REGS
; i
++)
158 State
->SegmentRegs
[i
].Selector
= 0;
159 State
->SegmentRegs
[i
].Base
= 0;
160 State
->SegmentRegs
[i
].Limit
= 0xFFFF;
161 State
->SegmentRegs
[i
].Present
= TRUE
;
162 State
->SegmentRegs
[i
].ReadWrite
= TRUE
;
163 State
->SegmentRegs
[i
].Executable
= FALSE
;
164 State
->SegmentRegs
[i
].DirConf
= FALSE
;
165 State
->SegmentRegs
[i
].SystemType
= 1; // Segment descriptor
166 State
->SegmentRegs
[i
].Dpl
= 0;
167 State
->SegmentRegs
[i
].Size
= FALSE
; // 16-bit
170 /* Initialize the code segment */
171 State
->SegmentRegs
[FAST486_REG_CS
].Executable
= TRUE
;
172 State
->SegmentRegs
[FAST486_REG_CS
].Selector
= 0xF000;
173 State
->SegmentRegs
[FAST486_REG_CS
].Base
= 0xFFFF0000;
175 /* Initialize the IDT */
176 State
->Idtr
.Size
= 0x3FF;
177 State
->Idtr
.Address
= 0;
179 #ifndef FAST486_NO_FPU
181 State
->ControlRegisters
[FAST486_REG_CR0
] |= FAST486_CR0_ET
;
183 /* Initialize the FPU control and tag registers */
184 State
->FpuControl
.Value
= FAST486_FPU_DEFAULT_CONTROL
;
185 State
->FpuStatus
.Value
= 0;
186 State
->FpuTag
= 0xFFFF;
189 /* Restore the callbacks and TLB */
190 State
->MemReadCallback
= MemReadCallback
;
191 State
->MemWriteCallback
= MemWriteCallback
;
192 State
->IoReadCallback
= IoReadCallback
;
193 State
->IoWriteCallback
= IoWriteCallback
;
194 State
->BopCallback
= BopCallback
;
195 State
->IntAckCallback
= IntAckCallback
;
196 State
->FpuCallback
= FpuCallback
;
200 Fast486FlushTlb(State
);
205 Fast486InterruptSignal(PFAST486_STATE State
)
207 State
->IntSignaled
= TRUE
;
212 Fast486ExecuteAt(PFAST486_STATE State
, USHORT Segment
, ULONG Offset
)
214 /* Load the new CS */
215 if (!Fast486LoadSegment(State
, FAST486_REG_CS
, Segment
))
217 /* An exception occurred, let the handler execute instead */
222 State
->InstPtr
.Long
= Offset
;
227 Fast486SetStack(PFAST486_STATE State
, USHORT Segment
, ULONG Offset
)
229 /* Load the new SS */
230 if (!Fast486LoadSegment(State
, FAST486_REG_SS
, Segment
))
232 /* An exception occurred, let the handler execute instead */
237 State
->GeneralRegs
[FAST486_REG_ESP
].Long
= Offset
;
242 Fast486SetSegment(PFAST486_STATE State
,
243 FAST486_SEG_REGS Segment
,
246 /* Call the internal function */
247 Fast486LoadSegment(State
, Segment
, Selector
);
252 Fast486Rewind(PFAST486_STATE State
)
254 /* This function is used when an instruction has been interrupted remotely */
255 State
->PrefixFlags
= 0;
256 State
->InstPtr
.Long
= State
->SavedInstPtr
.Long
;
258 #ifndef FAST486_NO_PREFETCH
259 State
->PrefetchValid
= FALSE
;