1 /* 2 * Fast486 386/486 CPU Emulation Library 3 * fast486.h 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 #ifndef _FAST486_H_ 23 #define _FAST486_H_ 24 25 #pragma once 26 27 /* DEFINES ********************************************************************/ 28 29 #ifndef FASTCALL 30 #define FASTCALL __fastcall 31 #endif 32 33 #define FAST486_CHAR_MIN (-128) 34 #define FAST486_CHAR_MAX (127) 35 #define FAST486_SHORT_MIN (-32768L) 36 #define FAST486_SHORT_MAX (32767L) 37 #define FAST486_LONG_MIN (-2147483648LL) 38 #define FAST486_LONG_MAX (2147483647LL) 39 40 #define FAST486_NUM_GEN_REGS 8 41 #define FAST486_NUM_SEG_REGS 6 42 #define FAST486_NUM_CTRL_REGS 3 43 #define FAST486_NUM_DBG_REGS 6 44 #define FAST486_NUM_FPU_REGS 8 45 46 #define FAST486_CR0_PE (1 << 0) 47 #define FAST486_CR0_MP (1 << 1) 48 #define FAST486_CR0_EM (1 << 2) 49 #define FAST486_CR0_TS (1 << 3) 50 #define FAST486_CR0_ET (1 << 4) 51 #define FAST486_CR0_NE (1 << 5) 52 #define FAST486_CR0_WP (1 << 16) 53 #define FAST486_CR0_AM (1 << 18) 54 #define FAST486_CR0_NW (1 << 29) 55 #define FAST486_CR0_CD (1 << 30) 56 #define FAST486_CR0_PG (1 << 31) 57 58 #define FAST486_DR4_B0 (1 << 0) 59 #define FAST486_DR4_B1 (1 << 1) 60 #define FAST486_DR4_B2 (1 << 2) 61 #define FAST486_DR4_B3 (1 << 3) 62 #define FAST486_DR4_BD (1 << 13) 63 #define FAST486_DR4_BS (1 << 14) 64 #define FAST486_DR4_BT (1 << 15) 65 66 #define FAST486_DR5_L0 (1 << 0) 67 #define FAST486_DR5_G0 (1 << 1) 68 #define FAST486_DR5_L1 (1 << 2) 69 #define FAST486_DR5_G1 (1 << 3) 70 #define FAST486_DR5_L2 (1 << 4) 71 #define FAST486_DR5_G2 (1 << 5) 72 #define FAST486_DR5_L3 (1 << 6) 73 #define FAST486_DR5_G3 (1 << 7) 74 #define FAST486_DR5_LE (1 << 8) 75 #define FAST486_DR5_GE (1 << 9) 76 #define FAST486_DR5_GD (1 << 13) 77 78 #define FAST486_DBG_BREAK_EXEC 0 79 #define FAST486_DBG_BREAK_WRITE 1 80 #define FAST486_DBG_BREAK_READWRITE 3 81 82 #define FAST486_DR4_RESERVED 0xFFFF1FF0 83 #define FAST486_DR5_RESERVED 0x0000DC00 84 85 #define FAST486_TSS_16_SIGNATURE 0x01 86 #define FAST486_LDT_SIGNATURE 0x02 87 #define FAST486_BUSY_TSS_16_SIGNATURE 0x03 88 #define FAST486_CALL_GATE_16_SIGNATURE 0x04 89 #define FAST486_TASK_GATE_SIGNATURE 0x05 90 #define FAST486_IDT_INT_GATE 0x06 91 #define FAST486_IDT_TRAP_GATE 0x07 92 #define FAST486_TSS_SIGNATURE 0x09 93 #define FAST486_BUSY_TSS_SIGNATURE 0x0B 94 #define FAST486_CALL_GATE_SIGNATURE 0x0C 95 #define FAST486_IDT_INT_GATE_32 0x0E 96 #define FAST486_IDT_TRAP_GATE_32 0x0F 97 98 #define FAST486_PREFIX_SEG (1 << 0) 99 #define FAST486_PREFIX_OPSIZE (1 << 1) 100 #define FAST486_PREFIX_ADSIZE (1 << 2) 101 #define FAST486_PREFIX_LOCK (1 << 3) 102 #define FAST486_PREFIX_REPNZ (1 << 4) 103 #define FAST486_PREFIX_REP (1 << 5) 104 105 #define FAST486_FPU_DEFAULT_CONTROL 0x037F 106 107 #define FAST486_PAGE_SIZE 4096 108 #define FAST486_CACHE_SIZE 32 109 110 /* 111 * These are condiciones sine quibus non that should be respected, because 112 * otherwise when fetching DWORDs you would read extra garbage bytes 113 * (by reading outside of the prefetch buffer). The prefetch cache must 114 * also not cross a page boundary. 115 */ 116 C_ASSERT((FAST486_CACHE_SIZE >= sizeof(ULONG)) 117 && (FAST486_CACHE_SIZE <= FAST486_PAGE_SIZE)); 118 119 struct _FAST486_STATE; 120 typedef struct _FAST486_STATE FAST486_STATE, *PFAST486_STATE; 121 122 typedef enum _FAST486_GEN_REGS 123 { 124 FAST486_REG_EAX, 125 FAST486_REG_ECX, 126 FAST486_REG_EDX, 127 FAST486_REG_EBX, 128 FAST486_REG_ESP, 129 FAST486_REG_EBP, 130 FAST486_REG_ESI, 131 FAST486_REG_EDI 132 } FAST486_GEN_REGS, *PFAST486_GEN_REGS; 133 134 typedef enum _FAST486_SEG_REGS 135 { 136 FAST486_REG_ES, 137 FAST486_REG_CS, 138 FAST486_REG_SS, 139 FAST486_REG_DS, 140 FAST486_REG_FS, 141 FAST486_REG_GS 142 } FAST486_SEG_REGS, *PFAST486_SEG_REGS; 143 144 typedef enum _FAST486_CTRL_REGS 145 { 146 FAST486_REG_CR0 = 0, 147 FAST486_REG_CR2 = 1, 148 FAST486_REG_CR3 = 2, 149 } FAST486_CTRL_REGS, *PFAST486_CTRL_REGS; 150 151 typedef enum _FAST486_DBG_REGS 152 { 153 FAST486_REG_DR0 = 0, 154 FAST486_REG_DR1 = 1, 155 FAST486_REG_DR2 = 2, 156 FAST486_REG_DR3 = 3, 157 FAST486_REG_DR4 = 4, 158 FAST486_REG_DR5 = 5, 159 FAST486_REG_DR6 = 4, // alias to DR4 160 FAST486_REG_DR7 = 5 // alias to DR5 161 } FAST486_DBG_REGS, *PFAST486_DBG_REGS; 162 163 typedef enum _FAST486_EXCEPTIONS 164 { 165 FAST486_EXCEPTION_DE = 0x00, 166 FAST486_EXCEPTION_DB = 0x01, 167 FAST486_EXCEPTION_BP = 0x03, 168 FAST486_EXCEPTION_OF = 0x04, 169 FAST486_EXCEPTION_BR = 0x05, 170 FAST486_EXCEPTION_UD = 0x06, 171 FAST486_EXCEPTION_NM = 0x07, 172 FAST486_EXCEPTION_DF = 0x08, 173 FAST486_EXCEPTION_TS = 0x0A, 174 FAST486_EXCEPTION_NP = 0x0B, 175 FAST486_EXCEPTION_SS = 0x0C, 176 FAST486_EXCEPTION_GP = 0x0D, 177 FAST486_EXCEPTION_PF = 0x0E, 178 FAST486_EXCEPTION_MF = 0x10, 179 FAST486_EXCEPTION_AC = 0x11, 180 FAST486_EXCEPTION_MC = 0x12 181 } FAST486_EXCEPTIONS, *PFAST486_EXCEPTIONS; 182 183 typedef 184 VOID 185 (FASTCALL *FAST486_MEM_READ_PROC) 186 ( 187 PFAST486_STATE State, 188 ULONG Address, 189 PVOID Buffer, 190 ULONG Size 191 ); 192 193 typedef 194 VOID 195 (FASTCALL *FAST486_MEM_WRITE_PROC) 196 ( 197 PFAST486_STATE State, 198 ULONG Address, 199 PVOID Buffer, 200 ULONG Size 201 ); 202 203 typedef 204 VOID 205 (FASTCALL *FAST486_IO_READ_PROC) 206 ( 207 PFAST486_STATE State, 208 USHORT Port, 209 PVOID Buffer, 210 ULONG DataCount, 211 UCHAR DataSize 212 ); 213 214 typedef 215 VOID 216 (FASTCALL *FAST486_IO_WRITE_PROC) 217 ( 218 PFAST486_STATE State, 219 USHORT Port, 220 PVOID Buffer, 221 ULONG DataCount, 222 UCHAR DataSize 223 ); 224 225 typedef 226 VOID 227 (FASTCALL *FAST486_BOP_PROC) 228 ( 229 PFAST486_STATE State, 230 UCHAR BopCode 231 ); 232 233 typedef 234 UCHAR 235 (FASTCALL *FAST486_INT_ACK_PROC) 236 ( 237 PFAST486_STATE State 238 ); 239 240 typedef 241 VOID 242 (FASTCALL *FAST486_FPU_PROC) 243 ( 244 PFAST486_STATE State 245 ); 246 247 typedef union _FAST486_REG 248 { 249 union 250 { 251 struct 252 { 253 UCHAR LowByte; 254 UCHAR HighByte; 255 }; 256 USHORT LowWord; 257 }; 258 ULONG Long; 259 } FAST486_REG, *PFAST486_REG; 260 261 typedef struct _FAST486_SEG_REG 262 { 263 USHORT Selector; 264 265 /* Descriptor cache */ 266 ULONG Accessed : 1; 267 ULONG ReadWrite : 1; 268 ULONG DirConf : 1; 269 ULONG Executable : 1; 270 ULONG SystemType : 1; 271 ULONG Rpl : 2; 272 ULONG Dpl : 2; 273 ULONG Present : 1; 274 ULONG Size : 1; 275 ULONG Limit; 276 ULONG Base; 277 } FAST486_SEG_REG, *PFAST486_SEG_REG; 278 279 typedef struct _FAST486_LDT_REG 280 { 281 USHORT Selector; 282 ULONG Base; 283 ULONG Limit; 284 } FAST486_LDT_REG, *PFAST486_LDT_REG; 285 286 typedef struct _FAST486_TASK_REG 287 { 288 USHORT Selector; 289 ULONG Base; 290 ULONG Limit; 291 BOOLEAN Modern; 292 } FAST486_TASK_REG, *PFAST486_TASK_REG; 293 294 #include <pshpack1.h> 295 296 typedef struct 297 { 298 ULONG Limit : 16; 299 ULONG Base : 16; 300 ULONG BaseMid : 8; 301 ULONG Accessed : 1; 302 ULONG ReadWrite : 1; 303 ULONG DirConf : 1; 304 ULONG Executable : 1; 305 ULONG SystemType : 1; 306 ULONG Dpl : 2; 307 ULONG Present : 1; 308 ULONG LimitHigh : 4; 309 ULONG Avl : 1; 310 ULONG Reserved : 1; 311 ULONG Size : 1; 312 ULONG Granularity : 1; 313 ULONG BaseHigh : 8; 314 } FAST486_GDT_ENTRY, *PFAST486_GDT_ENTRY; 315 316 /* Verify the structure size */ 317 C_ASSERT(sizeof(FAST486_GDT_ENTRY) == sizeof(ULONGLONG)); 318 319 typedef struct 320 { 321 ULONG Limit : 16; 322 ULONG Base : 16; 323 ULONG BaseMid : 8; 324 ULONG Signature : 5; 325 ULONG Dpl : 2; 326 ULONG Present : 1; 327 ULONG LimitHigh : 4; 328 ULONG Avl : 1; 329 ULONG Reserved : 2; 330 ULONG Granularity : 1; 331 ULONG BaseHigh : 8; 332 } FAST486_SYSTEM_DESCRIPTOR, *PFAST486_SYSTEM_DESCRIPTOR; 333 334 /* Verify the structure size */ 335 C_ASSERT(sizeof(FAST486_SYSTEM_DESCRIPTOR) == sizeof(ULONGLONG)); 336 337 typedef struct 338 { 339 ULONG Offset : 16; 340 ULONG Selector : 16; 341 ULONG ParamCount : 5; 342 ULONG Reserved : 3; 343 ULONG Type : 4; 344 ULONG SystemType : 1; 345 ULONG Dpl : 2; 346 ULONG Present : 1; 347 ULONG OffsetHigh : 16; 348 } FAST486_CALL_GATE, *PFAST486_CALL_GATE; 349 350 /* Verify the structure size */ 351 C_ASSERT(sizeof(FAST486_CALL_GATE) == sizeof(ULONGLONG)); 352 353 typedef struct 354 { 355 ULONG Offset : 16; 356 ULONG Selector : 16; 357 ULONG Zero : 8; 358 ULONG Type : 4; 359 ULONG Storage : 1; 360 ULONG Dpl : 2; 361 ULONG Present : 1; 362 ULONG OffsetHigh : 16; 363 } FAST486_IDT_ENTRY, *PFAST486_IDT_ENTRY; 364 365 /* Verify the structure size */ 366 C_ASSERT(sizeof(FAST486_IDT_ENTRY) == sizeof(ULONGLONG)); 367 368 typedef struct _FAST486_TSS 369 { 370 ULONG Link; 371 ULONG Esp0; 372 ULONG Ss0; 373 ULONG Esp1; 374 ULONG Ss1; 375 ULONG Esp2; 376 ULONG Ss2; 377 ULONG Cr3; 378 ULONG Eip; 379 ULONG Eflags; 380 ULONG Eax; 381 ULONG Ecx; 382 ULONG Edx; 383 ULONG Ebx; 384 ULONG Esp; 385 ULONG Ebp; 386 ULONG Esi; 387 ULONG Edi; 388 ULONG Es; 389 ULONG Cs; 390 ULONG Ss; 391 ULONG Ds; 392 ULONG Fs; 393 ULONG Gs; 394 ULONG Ldtr; 395 ULONG IopbOffset; 396 } FAST486_TSS, *PFAST486_TSS; 397 398 typedef struct _FAST486_LEGACY_TSS 399 { 400 USHORT Link; 401 USHORT Sp0; 402 USHORT Ss0; 403 USHORT Sp1; 404 USHORT Ss1; 405 USHORT Sp2; 406 USHORT Ss2; 407 USHORT Ip; 408 USHORT Flags; 409 USHORT Ax; 410 USHORT Cx; 411 USHORT Dx; 412 USHORT Bx; 413 USHORT Sp; 414 USHORT Bp; 415 USHORT Si; 416 USHORT Di; 417 USHORT Es; 418 USHORT Cs; 419 USHORT Ss; 420 USHORT Ds; 421 USHORT Ldtr; 422 } FAST486_LEGACY_TSS, *PFAST486_LEGACY_TSS; 423 424 #include <poppack.h> 425 426 typedef struct _FAST486_TABLE_REG 427 { 428 USHORT Size; 429 ULONG Address; 430 } FAST486_TABLE_REG, *PFAST486_TABLE_REG; 431 432 typedef union _FAST486_FLAGS_REG 433 { 434 USHORT LowWord; 435 ULONG Long; 436 437 struct 438 { 439 ULONG Cf : 1; 440 ULONG AlwaysSet : 1; 441 ULONG Pf : 1; 442 ULONG Reserved0 : 1; 443 ULONG Af : 1; 444 ULONG Reserved1 : 1; 445 ULONG Zf : 1; 446 ULONG Sf : 1; 447 ULONG Tf : 1; 448 ULONG If : 1; 449 ULONG Df : 1; 450 ULONG Of : 1; 451 ULONG Iopl : 2; 452 ULONG Nt : 1; 453 ULONG Reserved2 : 1; 454 ULONG Rf : 1; 455 ULONG Vm : 1; 456 ULONG Ac : 1; 457 458 // ULONG Reserved : 13; 459 }; 460 } FAST486_FLAGS_REG, *PFAST486_FLAGS_REG; 461 462 typedef struct _FAST486_FPU_DATA_REG 463 { 464 ULONGLONG Mantissa; 465 USHORT Exponent; 466 UCHAR Sign; 467 } FAST486_FPU_DATA_REG, *PFAST486_FPU_DATA_REG; 468 469 typedef const FAST486_FPU_DATA_REG *PCFAST486_FPU_DATA_REG; 470 471 typedef union _FAST486_FPU_STATUS_REG 472 { 473 USHORT Value; 474 475 struct 476 { 477 ULONG Ie : 1; 478 ULONG De : 1; 479 ULONG Ze : 1; 480 ULONG Oe : 1; 481 ULONG Ue : 1; 482 ULONG Pe : 1; 483 ULONG Sf : 1; 484 ULONG Es : 1; 485 ULONG Code0 : 1; 486 ULONG Code1 : 1; 487 ULONG Code2 : 1; 488 ULONG Top : 3; 489 ULONG Code3 : 1; 490 ULONG Busy : 1; 491 }; 492 } FAST486_FPU_STATUS_REG, *PFAST486_FPU_STATUS_REG; 493 494 typedef union _FAST486_FPU_CONTROL_REG 495 { 496 USHORT Value; 497 498 struct 499 { 500 ULONG Im : 1; 501 ULONG Dm : 1; 502 ULONG Zm : 1; 503 ULONG Om : 1; 504 ULONG Um : 1; 505 ULONG Pm : 1; 506 ULONG Reserved : 2; 507 ULONG Pc : 2; 508 ULONG Rc : 2; 509 ULONG Inf : 1; 510 // ULONG Reserved1 : 3; 511 }; 512 } FAST486_FPU_CONTROL_REG, *PFAST486_FPU_CONTROL_REG; 513 514 struct _FAST486_STATE 515 { 516 FAST486_MEM_READ_PROC MemReadCallback; 517 FAST486_MEM_WRITE_PROC MemWriteCallback; 518 FAST486_IO_READ_PROC IoReadCallback; 519 FAST486_IO_WRITE_PROC IoWriteCallback; 520 FAST486_BOP_PROC BopCallback; 521 FAST486_INT_ACK_PROC IntAckCallback; 522 FAST486_FPU_PROC FpuCallback; 523 FAST486_REG GeneralRegs[FAST486_NUM_GEN_REGS]; 524 FAST486_SEG_REG SegmentRegs[FAST486_NUM_SEG_REGS]; 525 FAST486_REG InstPtr, SavedInstPtr; 526 FAST486_REG SavedStackPtr; 527 FAST486_FLAGS_REG Flags; 528 FAST486_TABLE_REG Gdtr, Idtr; 529 FAST486_LDT_REG Ldtr; 530 FAST486_TASK_REG TaskReg; 531 UCHAR Cpl; 532 ULONG ControlRegisters[FAST486_NUM_CTRL_REGS]; 533 ULONG DebugRegisters[FAST486_NUM_DBG_REGS]; 534 ULONG ExceptionCount; 535 ULONG PrefixFlags; 536 FAST486_SEG_REGS SegmentOverride; 537 BOOLEAN Halted; 538 BOOLEAN IntSignaled; 539 BOOLEAN DoNotInterrupt; 540 PULONG Tlb; 541 BOOLEAN TlbEmpty; 542 #ifndef FAST486_NO_PREFETCH 543 BOOLEAN PrefetchValid; 544 ULONG PrefetchAddress; 545 UCHAR PrefetchCache[FAST486_CACHE_SIZE]; 546 #endif 547 #ifndef FAST486_NO_FPU 548 FAST486_FPU_DATA_REG FpuRegisters[FAST486_NUM_FPU_REGS]; 549 FAST486_FPU_STATUS_REG FpuStatus; 550 FAST486_FPU_CONTROL_REG FpuControl; 551 USHORT FpuTag; 552 FAST486_REG FpuLastInstPtr; 553 USHORT FpuLastCodeSel; 554 FAST486_REG FpuLastOpPtr; 555 USHORT FpuLastDataSel; 556 #endif 557 }; 558 559 /* FUNCTIONS ******************************************************************/ 560 561 VOID 562 NTAPI 563 Fast486Initialize(PFAST486_STATE State, 564 FAST486_MEM_READ_PROC MemReadCallback, 565 FAST486_MEM_WRITE_PROC MemWriteCallback, 566 FAST486_IO_READ_PROC IoReadCallback, 567 FAST486_IO_WRITE_PROC IoWriteCallback, 568 FAST486_BOP_PROC BopCallback, 569 FAST486_INT_ACK_PROC IntAckCallback, 570 FAST486_FPU_PROC FpuCallback, 571 PULONG Tlb); 572 573 VOID 574 NTAPI 575 Fast486Reset(PFAST486_STATE State); 576 577 VOID 578 NTAPI 579 Fast486Continue(PFAST486_STATE State); 580 581 VOID 582 NTAPI 583 Fast486StepInto(PFAST486_STATE State); 584 585 VOID 586 NTAPI 587 Fast486StepOver(PFAST486_STATE State); 588 589 VOID 590 NTAPI 591 Fast486StepOut(PFAST486_STATE State); 592 593 VOID 594 NTAPI 595 Fast486DumpState(PFAST486_STATE State); 596 597 VOID 598 NTAPI 599 Fast486InterruptSignal(PFAST486_STATE State); 600 601 VOID 602 NTAPI 603 Fast486ExecuteAt(PFAST486_STATE State, USHORT Segment, ULONG Offset); 604 605 VOID 606 NTAPI 607 Fast486SetStack(PFAST486_STATE State, USHORT Segment, ULONG Offset); 608 609 VOID 610 NTAPI 611 Fast486SetSegment 612 ( 613 PFAST486_STATE State, 614 FAST486_SEG_REGS Segment, 615 USHORT Selector 616 ); 617 618 VOID 619 NTAPI 620 Fast486Rewind(PFAST486_STATE State); 621 622 #endif // _FAST486_H_ 623 624 /* EOF */ 625