DOSBox-X
|
00001 /* 00002 * Copyright (C) 2002-2020 The DOSBox Team 00003 * 00004 * This program is free software; you can redistribute it and/or modify 00005 * it under the terms of the GNU General Public License as published by 00006 * the Free Software Foundation; either version 2 of the License, or 00007 * (at your option) any later version. 00008 * 00009 * This program is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 * GNU General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU General Public License along 00015 * with this program; if not, write to the Free Software Foundation, Inc., 00016 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 00017 */ 00018 00019 00020 #ifndef DOSBOX_CPU_H 00021 #define DOSBOX_CPU_H 00022 00023 #ifndef DOSBOX_DOSBOX_H 00024 #include "dosbox.h" 00025 #endif 00026 #ifndef DOSBOX_REGS_H 00027 #include "regs.h" 00028 #endif 00029 #ifndef DOSBOX_MEM_H 00030 #include "mem.h" 00031 #endif 00032 00033 #define CPU_AUTODETERMINE_NONE 0x00 00034 #define CPU_AUTODETERMINE_CORE 0x01 00035 #define CPU_AUTODETERMINE_CYCLES 0x02 00036 00037 #define CPU_AUTODETERMINE_SHIFT 0x02 00038 #define CPU_AUTODETERMINE_MASK 0x03 00039 00040 #define CPU_CYCLES_LOWER_LIMIT 200 00041 00042 00043 #define CPU_ARCHTYPE_MIXED 0xff 00044 #define CPU_ARCHTYPE_8086 0x05 00045 #define CPU_ARCHTYPE_80186 0x15 00046 #define CPU_ARCHTYPE_286 0x25 00047 #define CPU_ARCHTYPE_386 0x35 00048 #define CPU_ARCHTYPE_486OLD 0x40 00049 #define CPU_ARCHTYPE_486NEW 0x45 00050 #define CPU_ARCHTYPE_PENTIUM 0x50 00051 #define CPU_ARCHTYPE_PMMXSLOW 0x55 00052 #define CPU_ARCHTYPE_PPROSLOW 0x60 00053 00054 /* CPU Cycle Timing */ 00055 extern cpu_cycles_count_t CPU_Cycles; 00056 extern cpu_cycles_count_t CPU_CycleLeft; 00057 extern cpu_cycles_count_t CPU_CycleMax; 00058 extern cpu_cycles_count_t CPU_OldCycleMax; 00059 extern cpu_cycles_count_t CPU_CyclePercUsed; 00060 extern cpu_cycles_count_t CPU_CycleLimit; 00061 extern cpu_cycles_count_t CPU_IODelayRemoved; 00062 extern cpu_cycles_count_t CPU_CyclesSet; 00063 extern unsigned char CPU_AutoDetermineMode; 00064 extern char core_mode[16]; 00065 00066 extern bool CPU_CycleAutoAdjust; 00067 extern bool CPU_SkipCycleAutoAdjust; 00068 00069 extern bool enable_weitek; 00070 00071 extern unsigned char CPU_ArchitectureType; 00072 00073 extern unsigned int CPU_PrefetchQueueSize; 00074 00075 /* Some common Defines */ 00076 /* A CPU Handler */ 00077 typedef Bits (CPU_Decoder)(void); 00078 extern CPU_Decoder * cpudecoder; 00079 00080 Bits CPU_Core_Normal_Run(void); 00081 Bits CPU_Core_Normal_Trap_Run(void); 00082 Bits CPU_Core_Simple_Run(void); 00083 Bits CPU_Core_Simple_Trap_Run(void); 00084 Bits CPU_Core_Full_Run(void); 00085 Bits CPU_Core_Dyn_X86_Run(void); 00086 Bits CPU_Core_Dyn_X86_Trap_Run(void); 00087 Bits CPU_Core_Dynrec_Run(void); 00088 Bits CPU_Core_Dynrec_Trap_Run(void); 00089 Bits CPU_Core_Prefetch_Run(void); 00090 Bits CPU_Core_Prefetch_Trap_Run(void); 00091 00092 Bits CPU_Core286_Normal_Run(void); 00093 Bits CPU_Core286_Normal_Trap_Run(void); 00094 00095 Bits CPU_Core8086_Normal_Run(void); 00096 Bits CPU_Core8086_Normal_Trap_Run(void); 00097 00098 Bits CPU_Core286_Prefetch_Run(void); 00099 00100 Bits CPU_Core8086_Prefetch_Run(void); 00101 00102 void CPU_Enable_SkipAutoAdjust(void); 00103 void CPU_Disable_SkipAutoAdjust(void); 00104 void CPU_Reset_AutoAdjust(void); 00105 00106 00107 //CPU Stuff 00108 00109 extern Bit16u parity_lookup[256]; 00110 00111 void CPU_SetCPL(Bitu newcpl); 00112 bool CPU_LLDT(Bitu selector); 00113 bool CPU_LTR(Bitu selector); 00114 void CPU_LIDT(Bitu limit,Bitu base); 00115 void CPU_LGDT(Bitu limit,Bitu base); 00116 00117 Bitu CPU_STR(void); 00118 Bitu CPU_SLDT(void); 00119 Bitu CPU_SIDT_base(void); 00120 Bitu CPU_SIDT_limit(void); 00121 Bitu CPU_SGDT_base(void); 00122 Bitu CPU_SGDT_limit(void); 00123 00124 void CPU_ARPL(Bitu & dest_sel,Bitu src_sel); 00125 void CPU_LAR(Bitu selector,Bitu & ar); 00126 void CPU_LSL(Bitu selector,Bitu & limit); 00127 00128 void CPU_SET_CRX(Bitu cr,Bitu value); 00129 bool CPU_WRITE_CRX(Bitu cr,Bitu value); 00130 Bitu CPU_GET_CRX(Bitu cr); 00131 bool CPU_READ_CRX(Bitu cr,Bit32u & retvalue); 00132 00133 bool CPU_WRITE_DRX(Bitu dr,Bitu value); 00134 bool CPU_READ_DRX(Bitu dr,Bit32u & retvalue); 00135 00136 bool CPU_WRITE_TRX(Bitu tr,Bitu value); 00137 bool CPU_READ_TRX(Bitu tr,Bit32u & retvalue); 00138 00139 Bitu CPU_SMSW(void); 00140 bool CPU_LMSW(Bitu word); 00141 00142 void CPU_VERR(Bitu selector); 00143 void CPU_VERW(Bitu selector); 00144 00145 void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bit32u oldeip); 00146 void CPU_CALL(bool use32,Bitu selector,Bitu offset,Bit32u oldeip); 00147 void CPU_RET(bool use32,Bitu bytes,Bit32u oldeip); 00148 void CPU_IRET(bool use32,Bit32u oldeip); 00149 void CPU_HLT(Bit32u oldeip); 00150 00151 bool CPU_POPF(Bitu use32); 00152 bool CPU_PUSHF(Bitu use32); 00153 bool CPU_CLI(void); 00154 bool CPU_STI(void); 00155 00156 bool CPU_IO_Exception(Bitu port,Bitu size); 00157 00158 void CPU_ENTER(bool use32,Bitu bytes,Bitu level); 00159 void init_vm86_fake_io(); 00160 00161 #define CPU_INT_SOFTWARE 0x1 00162 #define CPU_INT_EXCEPTION 0x2 00163 #define CPU_INT_HAS_ERROR 0x4 00164 #define CPU_INT_NOIOPLCHECK 0x8 00165 00166 extern bool CPU_NMI_gate; 00167 extern bool CPU_NMI_active; 00168 extern bool CPU_NMI_pending; 00169 00170 extern bool do_seg_limits; 00171 00172 void CPU_Interrupt(Bitu num,Bitu type,Bit32u oldeip); 00173 void CPU_Check_NMI(); 00174 void CPU_Raise_NMI(); 00175 void CPU_NMI_Interrupt(); 00176 static INLINE void CPU_HW_Interrupt(Bitu num) { 00177 CPU_Interrupt(num,0,reg_eip); 00178 } 00179 static INLINE void CPU_SW_Interrupt(Bitu num,Bit32u oldeip) { 00180 CPU_Interrupt(num,CPU_INT_SOFTWARE,oldeip); 00181 } 00182 static INLINE void CPU_SW_Interrupt_NoIOPLCheck(Bitu num,Bit32u oldeip) { 00183 CPU_Interrupt(num,CPU_INT_SOFTWARE|CPU_INT_NOIOPLCHECK,oldeip); 00184 } 00185 00186 bool CPU_PrepareException(Bitu which,Bitu error); 00187 void CPU_Exception(Bitu which,Bitu error=0); 00188 00189 bool CPU_SetSegGeneral(SegNames seg,Bit16u value); 00190 bool CPU_PopSeg(SegNames seg,bool use32); 00191 00192 bool CPU_CPUID(void); 00193 Bit16u CPU_Pop16(void); 00194 Bit32u CPU_Pop32(void); 00195 void CPU_Push16(Bit16u value); 00196 void CPU_Push32(Bit32u value); 00197 00198 void CPU_SetFlags(Bitu word,Bitu mask); 00199 00200 00201 #define EXCEPTION_UD 6u 00202 #define EXCEPTION_DF 8u 00203 #define EXCEPTION_TS 10u 00204 #define EXCEPTION_NP 11u 00205 #define EXCEPTION_SS 12u 00206 #define EXCEPTION_GP 13u 00207 #define EXCEPTION_PF 14u 00208 00209 #define CR0_PROTECTION 0x00000001u 00210 #define CR0_MONITORPROCESSOR 0x00000002u 00211 #define CR0_FPUEMULATION 0x00000004u 00212 #define CR0_TASKSWITCH 0x00000008u 00213 #define CR0_FPUPRESENT 0x00000010u 00214 #define CR0_WRITEPROTECT 0x00010000u 00215 #define CR0_PAGING 0x80000000u 00216 00217 00218 // ********************************************************************* 00219 // Descriptor 00220 // ********************************************************************* 00221 00222 #define DESC_INVALID 0x00u 00223 #define DESC_286_TSS_A 0x01u 00224 #define DESC_LDT 0x02u 00225 #define DESC_286_TSS_B 0x03u 00226 #define DESC_286_CALL_GATE 0x04u 00227 #define DESC_TASK_GATE 0x05u 00228 #define DESC_286_INT_GATE 0x06u 00229 #define DESC_286_TRAP_GATE 0x07u 00230 00231 #define DESC_386_TSS_A 0x09u 00232 #define DESC_386_TSS_B 0x0bu 00233 #define DESC_386_CALL_GATE 0x0cu 00234 #define DESC_386_INT_GATE 0x0eu 00235 #define DESC_386_TRAP_GATE 0x0fu 00236 00237 /* EU/ED Expand UP/DOWN RO/RW Read Only/Read Write NA/A Accessed */ 00238 #define DESC_DATA_EU_RO_NA 0x10u 00239 #define DESC_DATA_EU_RO_A 0x11u 00240 #define DESC_DATA_EU_RW_NA 0x12u 00241 #define DESC_DATA_EU_RW_A 0x13u 00242 #define DESC_DATA_ED_RO_NA 0x14u 00243 #define DESC_DATA_ED_RO_A 0x15u 00244 #define DESC_DATA_ED_RW_NA 0x16u 00245 #define DESC_DATA_ED_RW_A 0x17u 00246 00247 /* N/R Readable NC/C Confirming A/NA Accessed */ 00248 #define DESC_CODE_N_NC_A 0x18u 00249 #define DESC_CODE_N_NC_NA 0x19u 00250 #define DESC_CODE_R_NC_A 0x1au 00251 #define DESC_CODE_R_NC_NA 0x1bu 00252 #define DESC_CODE_N_C_A 0x1cu 00253 #define DESC_CODE_N_C_NA 0x1du 00254 #define DESC_CODE_R_C_A 0x1eu 00255 #define DESC_CODE_R_C_NA 0x1fu 00256 00257 #ifdef _MSC_VER 00258 #pragma pack (1) 00259 #endif 00260 00261 struct S_Descriptor { 00262 #ifdef WORDS_BIGENDIAN 00263 Bit32u base_0_15 :16; 00264 Bit32u limit_0_15 :16; 00265 Bit32u base_24_31 :8; 00266 Bit32u g :1; 00267 Bit32u big :1; 00268 Bit32u r :1; 00269 Bit32u avl :1; 00270 Bit32u limit_16_19 :4; 00271 Bit32u p :1; 00272 Bit32u dpl :2; 00273 Bit32u type :5; 00274 Bit32u base_16_23 :8; 00275 #else 00276 Bit32u limit_0_15 :16; 00277 Bit32u base_0_15 :16; 00278 Bit32u base_16_23 :8; 00279 Bit32u type :5; 00280 Bit32u dpl :2; 00281 Bit32u p :1; 00282 Bit32u limit_16_19 :4; 00283 Bit32u avl :1; 00284 Bit32u r :1; 00285 Bit32u big :1; 00286 Bit32u g :1; 00287 Bit32u base_24_31 :8; 00288 #endif 00289 }GCC_ATTRIBUTE(packed); 00290 00291 struct G_Descriptor { 00292 #ifdef WORDS_BIGENDIAN 00293 Bit32u selector: 16; 00294 Bit32u offset_0_15 :16; 00295 Bit32u offset_16_31 :16; 00296 Bit32u p :1; 00297 Bit32u dpl :2; 00298 Bit32u type :5; 00299 Bit32u reserved :3; 00300 Bit32u paramcount :5; 00301 #else 00302 Bit32u offset_0_15 :16; 00303 Bit32u selector :16; 00304 Bit32u paramcount :5; 00305 Bit32u reserved :3; 00306 Bit32u type :5; 00307 Bit32u dpl :2; 00308 Bit32u p :1; 00309 Bit32u offset_16_31 :16; 00310 #endif 00311 } GCC_ATTRIBUTE(packed); 00312 00313 struct TSS_16 { 00314 Bit16u back; /* Back link to other task */ 00315 Bit16u sp0; /* The CK stack pointer */ 00316 Bit16u ss0; /* The CK stack selector */ 00317 Bit16u sp1; /* The parent KL stack pointer */ 00318 Bit16u ss1; /* The parent KL stack selector */ 00319 Bit16u sp2; /* Unused */ 00320 Bit16u ss2; /* Unused */ 00321 Bit16u ip; /* The instruction pointer */ 00322 Bit16u flags; /* The flags */ 00323 Bit16u ax, cx, dx, bx; /* The general purpose registers */ 00324 Bit16u sp, bp, si, di; /* The special purpose registers */ 00325 Bit16u es; /* The extra selector */ 00326 Bit16u cs; /* The code selector */ 00327 Bit16u ss; /* The application stack selector */ 00328 Bit16u ds; /* The data selector */ 00329 Bit16u ldt; /* The local descriptor table */ 00330 } GCC_ATTRIBUTE(packed); 00331 00332 struct TSS_32 { 00333 Bit32u back; /* Back link to other task */ 00334 Bit32u esp0; /* The CK stack pointer */ 00335 Bit32u ss0; /* The CK stack selector */ 00336 Bit32u esp1; /* The parent KL stack pointer */ 00337 Bit32u ss1; /* The parent KL stack selector */ 00338 Bit32u esp2; /* Unused */ 00339 Bit32u ss2; /* Unused */ 00340 Bit32u cr3; /* The page directory pointer */ 00341 Bit32u eip; /* The instruction pointer */ 00342 Bit32u eflags; /* The flags */ 00343 Bit32u eax, ecx, edx, ebx; /* The general purpose registers */ 00344 Bit32u esp, ebp, esi, edi; /* The special purpose registers */ 00345 Bit32u es; /* The extra selector */ 00346 Bit32u cs; /* The code selector */ 00347 Bit32u ss; /* The application stack selector */ 00348 Bit32u ds; /* The data selector */ 00349 Bit32u fs; /* And another extra selector */ 00350 Bit32u gs; /* ... and another one */ 00351 Bit32u ldt; /* The local descriptor table */ 00352 } GCC_ATTRIBUTE(packed); 00353 00354 #ifdef _MSC_VER 00355 #pragma pack() 00356 #endif 00357 class Descriptor 00358 { 00359 public: 00360 Descriptor() { saved.fill[0]=saved.fill[1]=0; } 00361 00362 void Load(PhysPt address); 00363 void Save(PhysPt address); 00364 00365 PhysPt GetBase (void) const { 00366 return (PhysPt)( 00367 ((PhysPt)saved.seg.base_24_31 << (PhysPt)24U) | 00368 ((PhysPt)saved.seg.base_16_23 << (PhysPt)16U) | 00369 (PhysPt)saved.seg.base_0_15); 00370 } 00371 bool GetExpandDown (void) { 00372 #if 0 00373 Bit32u limit_0_15 :16; 00374 Bit32u base_0_15 :16; 00375 Bit32u base_16_23 :8; 00376 Bit32u type :5; 00377 Bit32u dpl :2; 00378 Bit32u p :1; 00379 Bit32u limit_16_19 :4; 00380 Bit32u avl :1; 00381 Bit32u r :1; 00382 Bit32u big :1; 00383 Bit32u g :1; 00384 Bit32u base_24_31 :8; 00385 #endif 00386 if (!(saved.seg.type & 0x10)) /* must be storage type descriptor */ 00387 return false; 00388 00389 /* type: 1 0 E W A for data */ 00390 /* type: 1 1 C R A for code */ 00391 if (saved.seg.type & 0x08) 00392 return false; 00393 00394 /* it's data. return the 'E' bit */ 00395 return (saved.seg.type & 4) != 0; 00396 } 00397 Bitu GetLimit (void) const { 00398 const Bitu limit = ((Bitu)saved.seg.limit_16_19 << (Bitu)16U) | (Bitu)saved.seg.limit_0_15; 00399 if (saved.seg.g) return ((Bitu)limit << (Bitu)12U) | (Bitu)0xFFFU; 00400 return limit; 00401 } 00402 Bitu GetOffset(void) const { 00403 return ((Bitu)saved.gate.offset_16_31 << (Bitu)16U) | (Bitu)saved.gate.offset_0_15; 00404 } 00405 Bitu GetSelector(void) const { 00406 return saved.gate.selector; 00407 } 00408 Bitu Type(void) const { 00409 return saved.seg.type; 00410 } 00411 Bitu Conforming(void) const { 00412 return saved.seg.type & 8U; 00413 } 00414 Bitu DPL(void) const { 00415 return saved.seg.dpl; 00416 } 00417 Bitu Big(void) const { 00418 return saved.seg.big; 00419 } 00420 public: 00421 union { 00422 S_Descriptor seg; 00423 G_Descriptor gate; 00424 Bit32u fill[2]; 00425 } saved; 00426 }; 00427 00428 class DescriptorTable { 00429 public: 00430 PhysPt GetBase (void) const { return table_base; } 00431 Bitu GetLimit (void) const { return table_limit; } 00432 void SetBase (PhysPt _base) { table_base = _base; } 00433 void SetLimit (Bitu _limit) { table_limit= _limit; } 00434 00435 bool GetDescriptor (Bitu selector, Descriptor& desc) { 00436 selector&=~7U; 00437 if (selector>=table_limit) return false; 00438 desc.Load((PhysPt)(table_base+selector)); 00439 return true; 00440 } 00441 00442 virtual void SaveState( std::ostream& stream ); 00443 virtual void LoadState( std::istream& stream ); 00444 00445 00446 protected: 00447 PhysPt table_base; 00448 Bitu table_limit; 00449 }; 00450 00451 class GDTDescriptorTable : public DescriptorTable { 00452 public: 00453 bool GetDescriptor(Bitu selector, Descriptor& desc) { 00454 Bitu address=selector & ~7U; 00455 if (selector & 4U) { 00456 if (address>=ldt_limit) return false; 00457 desc.Load((PhysPt)(ldt_base+address)); 00458 return true; 00459 } else { 00460 if (address>=table_limit) return false; 00461 desc.Load((PhysPt)(table_base+address)); 00462 return true; 00463 } 00464 } 00465 bool SetDescriptor(Bitu selector, Descriptor& desc) { 00466 Bitu address=selector & ~7U; 00467 if (selector & 4U) { 00468 if (address>=ldt_limit) return false; 00469 desc.Save((PhysPt)(ldt_base+address)); 00470 return true; 00471 } else { 00472 if (address>=table_limit) return false; 00473 desc.Save((PhysPt)(table_base+address)); 00474 return true; 00475 } 00476 } 00477 Bitu SLDT(void) const { 00478 return ldt_value; 00479 } 00480 bool LLDT(Bitu value) { 00481 if ((value&0xfffc)==0) { 00482 ldt_value=0; 00483 ldt_base=0; 00484 ldt_limit=0; 00485 return true; 00486 } 00487 Descriptor desc; 00488 if (!GetDescriptor(value,desc)) return !CPU_PrepareException(EXCEPTION_GP,value); 00489 if (desc.Type()!=DESC_LDT) return !CPU_PrepareException(EXCEPTION_GP,value); 00490 if (!desc.saved.seg.p) return !CPU_PrepareException(EXCEPTION_NP,value); 00491 ldt_base=desc.GetBase(); 00492 ldt_limit=desc.GetLimit(); 00493 ldt_value=value; 00494 return true; 00495 } 00496 00497 virtual void SaveState( std::ostream& stream ); 00498 virtual void LoadState( std::istream& stream ); 00499 00500 private: 00501 PhysPt ldt_base; 00502 Bitu ldt_limit; 00503 Bitu ldt_value; 00504 }; 00505 00506 class TSS_Descriptor : public Descriptor { 00507 public: 00508 Bitu IsBusy(void) const { 00509 return saved.seg.type & 2; 00510 } 00511 Bitu Is386(void) const { 00512 return saved.seg.type & 8; 00513 } 00514 void SetBusy(const bool busy) { 00515 if (busy) saved.seg.type|=(2U); 00516 else saved.seg.type&=(~2U); /* -Wconversion cannot silence without hard-coding ~2U & 0x1F */ 00517 } 00518 }; 00519 00520 00521 struct CPUBlock { 00522 Bitu cpl; /* Current Privilege */ 00523 Bitu mpl; 00524 Bitu cr0; 00525 bool pmode; /* Is Protected mode enabled */ 00526 GDTDescriptorTable gdt; 00527 DescriptorTable idt; 00528 struct { 00529 Bitu cr0_and; 00530 Bitu cr0_or; 00531 Bitu eflags; 00532 } masks; 00533 struct { 00534 Bit32u mask,notmask; 00535 bool big; 00536 } stack; 00537 struct { 00538 bool big; 00539 } code; 00540 struct { 00541 Bitu cs,eip; 00542 CPU_Decoder * old_decoder; 00543 } hlt; 00544 struct { 00545 Bitu which,error; 00546 } exception; 00547 Bits direction; 00548 bool trap_skip; 00549 Bit32u drx[8]; 00550 Bit32u trx[8]; 00551 }; 00552 00553 extern CPUBlock cpu; 00554 00555 static INLINE void CPU_SetFlagsd(const Bitu word) { 00556 const Bitu mask=cpu.cpl ? FMASK_NORMAL : FMASK_ALL; 00557 CPU_SetFlags(word,mask); 00558 } 00559 00560 static INLINE void CPU_SetFlagsw(const Bitu word) { 00561 const Bitu mask=(cpu.cpl ? FMASK_NORMAL : FMASK_ALL) & 0xffff; 00562 CPU_SetFlags(word,mask); 00563 } 00564 00565 Bitu CPU_ForceV86FakeIO_In(Bitu port,Bitu len); 00566 void CPU_ForceV86FakeIO_Out(Bitu port,Bitu val,Bitu len); 00567 00568 #endif