1 /* 2 * Fast486 386/486 CPU Emulation Library 3 * fast486.c 4 * 5 * Copyright (C) 2015 Aleksandar Andrejevic <theflash AT sdf DOT lonestar DOT org> 6 * 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. 11 * 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. 16 * 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. 20 */ 21 22 /* INCLUDES *******************************************************************/ 23 24 #include <windef.h> 25 26 // #define NDEBUG 27 #include <debug.h> 28 29 #include <fast486.h> 30 #include "common.h" 31 #include "opcodes.h" 32 #include "fpu.h" 33 34 /* DEFAULT CALLBACKS **********************************************************/ 35 36 static VOID 37 FASTCALL 38 Fast486MemReadCallback(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size) 39 { 40 UNREFERENCED_PARAMETER(State); 41 RtlMoveMemory(Buffer, (PVOID)Address, Size); 42 } 43 44 static VOID 45 FASTCALL 46 Fast486MemWriteCallback(PFAST486_STATE State, ULONG Address, PVOID Buffer, ULONG Size) 47 { 48 UNREFERENCED_PARAMETER(State); 49 RtlMoveMemory((PVOID)Address, Buffer, Size); 50 } 51 52 static VOID 53 FASTCALL 54 Fast486IoReadCallback(PFAST486_STATE State, USHORT Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize) 55 { 56 UNREFERENCED_PARAMETER(State); 57 UNREFERENCED_PARAMETER(Port); 58 UNREFERENCED_PARAMETER(Buffer); 59 UNREFERENCED_PARAMETER(DataCount); 60 UNREFERENCED_PARAMETER(DataSize); 61 } 62 63 static VOID 64 FASTCALL 65 Fast486IoWriteCallback(PFAST486_STATE State, USHORT Port, PVOID Buffer, ULONG DataCount, UCHAR DataSize) 66 { 67 UNREFERENCED_PARAMETER(State); 68 UNREFERENCED_PARAMETER(Port); 69 UNREFERENCED_PARAMETER(Buffer); 70 UNREFERENCED_PARAMETER(DataCount); 71 UNREFERENCED_PARAMETER(DataSize); 72 } 73 74 static VOID 75 FASTCALL 76 Fast486BopCallback(PFAST486_STATE State, UCHAR BopCode) 77 { 78 UNREFERENCED_PARAMETER(State); 79 UNREFERENCED_PARAMETER(BopCode); 80 } 81 82 static UCHAR 83 FASTCALL 84 Fast486IntAckCallback(PFAST486_STATE State) 85 { 86 UNREFERENCED_PARAMETER(State); 87 88 /* Return something... defaulted to single-step interrupt */ 89 return 0x01; 90 } 91 92 static VOID 93 FASTCALL 94 Fast486FpuCallback(PFAST486_STATE State) 95 { 96 UNREFERENCED_PARAMETER(State); 97 } 98 99 /* PUBLIC FUNCTIONS ***********************************************************/ 100 101 VOID 102 NTAPI 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, 111 PULONG Tlb) 112 { 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 ); 121 122 /* Set the TLB (if given) */ 123 State->Tlb = Tlb; 124 125 /* Reset the CPU */ 126 Fast486Reset(State); 127 } 128 129 VOID 130 NTAPI 131 Fast486Reset(PFAST486_STATE State) 132 { 133 FAST486_SEG_REGS i; 134 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; 144 145 /* Clear the entire structure */ 146 RtlZeroMemory(State, sizeof(*State)); 147 148 /* Initialize the registers */ 149 State->Flags.AlwaysSet = 1; 150 State->InstPtr.LowWord = 0xFFF0; 151 152 /* Set the CPL to 0 */ 153 State->Cpl = 0; 154 155 /* Initialize segments */ 156 for (i = 0; i < FAST486_NUM_SEG_REGS; i++) 157 { 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 168 } 169 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; 174 175 /* Initialize the IDT */ 176 State->Idtr.Size = 0x3FF; 177 State->Idtr.Address = 0; 178 179 #ifndef FAST486_NO_FPU 180 /* Initialize CR0 */ 181 State->ControlRegisters[FAST486_REG_CR0] |= FAST486_CR0_ET; 182 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; 187 #endif 188 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; 197 State->Tlb = Tlb; 198 199 /* Flush the TLB */ 200 Fast486FlushTlb(State); 201 } 202 203 VOID 204 NTAPI 205 Fast486InterruptSignal(PFAST486_STATE State) 206 { 207 State->IntSignaled = TRUE; 208 } 209 210 VOID 211 NTAPI 212 Fast486ExecuteAt(PFAST486_STATE State, USHORT Segment, ULONG Offset) 213 { 214 /* Load the new CS */ 215 if (!Fast486LoadSegment(State, FAST486_REG_CS, Segment)) 216 { 217 /* An exception occurred, let the handler execute instead */ 218 return; 219 } 220 221 /* Set the new IP */ 222 State->InstPtr.Long = Offset; 223 } 224 225 VOID 226 NTAPI 227 Fast486SetStack(PFAST486_STATE State, USHORT Segment, ULONG Offset) 228 { 229 /* Load the new SS */ 230 if (!Fast486LoadSegment(State, FAST486_REG_SS, Segment)) 231 { 232 /* An exception occurred, let the handler execute instead */ 233 return; 234 } 235 236 /* Set the new SP */ 237 State->GeneralRegs[FAST486_REG_ESP].Long = Offset; 238 } 239 240 VOID 241 NTAPI 242 Fast486SetSegment(PFAST486_STATE State, 243 FAST486_SEG_REGS Segment, 244 USHORT Selector) 245 { 246 /* Call the internal function */ 247 Fast486LoadSegment(State, Segment, Selector); 248 } 249 250 VOID 251 NTAPI 252 Fast486Rewind(PFAST486_STATE State) 253 { 254 /* This function is used when an instruction has been interrupted remotely */ 255 State->PrefixFlags = 0; 256 State->InstPtr.Long = State->SavedInstPtr.Long; 257 258 #ifndef FAST486_NO_PREFETCH 259 State->PrefetchValid = FALSE; 260 #endif 261 } 262 263 /* EOF */ 264