/* * Copyright (C) 2002-2005 The DOSBox Team * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ /* $Id: cpu.cpp,v 1.73 2005-08-15 13:43:44 c2woody Exp $ */ #include #include "dosbox.h" #include "cpu.h" #include "memory.h" #include "debug.h" #include "mapper.h" #include "setup.h" #include "paging.h" #include "support.h" Bitu DEBUG_EnableDebugger(void); #if 1 #undef LOG #define LOG(X,Y) #endif CPU_Regs cpu_regs; CPUBlock cpu; Segments Segs; Bits CPU_Cycles = 0; Bits CPU_CycleLeft = 0; Bits CPU_CycleMax = 2500; Bits CPU_CycleUp = 0; Bits CPU_CycleDown = 0; CPU_Decoder * cpudecoder; void CPU_Core_Full_Init(void); void CPU_Core_Normal_Init(void); void CPU_Core_Simple_Init(void); void CPU_Core_Dyn_X86_Init(void); /* In debug mode exceptions are tested and dosbox exits when * a unhandled exception state is detected. * USE CHECK_EXCEPT to raise an exception in that case to see if that exception * solves the problem. * * In non-debug mode dosbox doesn't do detection (and hence doesn't crash at * that point). (game might crash later due to the unhandled exception) */ #if C_DEBUG // #define CPU_CHECK_EXCEPT 1 // #define CPU_CHECK_IGNORE 1 /* Use CHECK_EXCEPT when something doesn't work to see if a exception is * needed that isn't enabled by default.*/ #else /* NORMAL NO CHECKING => More Speed */ #define CPU_CHECK_IGNORE 1 #endif /* C_DEBUG */ #if defined(CPU_CHECK_IGNORE) #define CPU_CHECK_COND(cond,msg,exc,sel) { \ cond; \ } #elif defined(CPU_CHECK_EXCEPT) #define CPU_CHECK_COND(cond,msg,exc,sel) { \ if (cond) { \ CPU_Exception(exc,sel); \ return; \ } \ } #else #define CPU_CHECK_COND(cond,msg,exc,sel) { \ if (cond) E_Exit(msg); \ } #endif void CPU_Push16(Bitu value) { Bit32u new_esp=(reg_esp&~cpu.stack.mask)|((reg_esp-2)&cpu.stack.mask); mem_writew(SegPhys(ss) + (new_esp & cpu.stack.mask) ,value); reg_esp=new_esp; } void CPU_Push32(Bitu value) { Bit32u new_esp=(reg_esp&~cpu.stack.mask)|((reg_esp-4)&cpu.stack.mask); mem_writed(SegPhys(ss) + (new_esp & cpu.stack.mask) ,value); reg_esp=new_esp; } Bitu CPU_Pop16(void) { Bitu val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask)); reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp+2)&cpu.stack.mask); return val; } Bitu CPU_Pop32(void) { Bitu val=mem_readd(SegPhys(ss) + (reg_esp & cpu.stack.mask)); reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp+4)&cpu.stack.mask); return val; } PhysPt SelBase(Bitu sel) { if (cpu.cr0 & CR0_PROTECTION) { Descriptor desc; cpu.gdt.GetDescriptor(sel,desc); return desc.GetBase(); } else { return sel<<4; } } void CPU_SetFlags(Bitu word,Bitu mask) { reg_flags=(reg_flags & ~mask)|(word & mask)|2|FLAG_ID; cpu.direction=1-((reg_flags & FLAG_DF) >> 9); } bool CPU_PrepareException(Bitu which,Bitu error) { cpu.exception.which=which; cpu.exception.error=error; return true; } bool CPU_CLI(void) { if (cpu.pmode && ((!GETFLAG(VM) && (GETFLAG_IOPL0)) mask &= (~FLAG_IOPL); if (cpu.pmode && !GETFLAG(VM) && (GETFLAG_IOPL0; Segs.val[cs]=new_cs; break; default: E_Exit("Task switch CS Type %d",cs_desc.Type()); } } CPU_SetSegGeneral(es,new_es); CPU_SetSegGeneral(ss,new_ss); CPU_SetSegGeneral(ds,new_ds); CPU_SetSegGeneral(fs,new_fs); CPU_SetSegGeneral(gs,new_gs); if (!cpu_tss.SetSelector(new_tss_selector)) LOG(LOG_CPU,LOG_NORMAL)("TaskSwitch: set tss selector %X failed",new_tss_selector); cpu_tss.desc.SetBusy(true); // LOG_MSG("Task CPL %X CS:%X IP:%X SS:%X SP:%X eflags %x",cpu.cpl,SegValue(cs),reg_eip,SegValue(ss),reg_esp,reg_flags); return true; } bool CPU_IO_Exception(Bitu port,Bitu size) { if (cpu.pmode && ((GETFLAG_IOPLcpu_tss.limit) goto doexception; where=cpu_tss.base+ofs+(port/8); Bitu map=mem_readw(where); Bitu mask=(0xffff>>(16-size)) << (port&7); if (map & mask) goto doexception; } return false; doexception: LOG(LOG_CPU,LOG_NORMAL)("IO Exception port %X",port); return CPU_PrepareException(EXCEPTION_GP,0); } void CPU_Exception(Bitu which,Bitu error ) { // LOG_MSG("Exception %d error %x",which,error); cpu.exception.error=error; CPU_Interrupt(which,CPU_INT_EXCEPTION | ((which>=8) ? CPU_INT_HAS_ERROR : 0),reg_eip); } const char* translateVXDid(Bitu nr) { switch (nr) { case 0x0001: return "VMM"; // Virtual Machine Manager case 0x0002: return "DEBUG"; case 0x0003: return "VPICD"; // Virtual PIC Device case 0x0004: return "VDMAD"; // Virtual DMA Device case 0x0005: return "VTD"; // Virtual Timer Device case 0x0006: return "V86MMGR"; // Virtual Device case 0x0007: return "PageSwap"; case 0x000A: return "VDD"; // Virtual Display Device case 0x000C: return "VMD"; // Virtual Mouse Device case 0x000D: return "VKD"; // Virtual Keyboard Device case 0x000E: return "VCD"; // Virtual COMM Device case 0x0010: return "IOS"; // BlockDev / IOS case 0x0011: return "VMCPD"; case 0x0012: return "EBIOS"; case 0x0015: return "DOSMGR"; case 0x0017: return "SHELL"; case 0x0018: return "VMPoll"; case 0x001A: return "DOSNET"; case 0x001B: return "VFD"; case 0x001C: return "LoadHi"; case 0x0020: return "Int13"; case 0x0021: return "PAGEFILE"; case 0x0026: return "VPOWERD"; case 0x0027: return "VXDLDR"; case 0x002A: return "VWIN32"; case 0x002B: return "VCOMM"; case 0x0033: return "CONFIGMG"; case 0x0036: return "VFBACKUP"; case 0x0037: return "VMINI"; case 0x0040: return "IFSMgr"; case 0x0041: return "VCDFSD"; case 0x0048: return "PERF"; case 0x011F: return "VFLATD"; case 0x0446: return "VADLIB"; case 0x044a: return "mmdevldr"; case 0x0484: return "IfsMgr"; case 0x048B: return "VCACHE"; case 0x357E: return "DSOUND"; default: return "unknown"; } } const char* translateVXDservice(Bitu nr, Bitu sv) { switch (nr) { case 0x0001: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "get current VM handle"; case 0x0002 : return "test current VM handle"; case 0x0003 : return "get system VM handle"; case 0x0004 : return "test system VM handle"; case 0x0005 : return "validate VM handle"; case 0x0006 : return "get VMM reenter count"; case 0x0007 : return "begin reentrant execution"; case 0x0008 : return "end reentrant execution"; case 0x0009 : return "install V86 breakpoint"; case 0x000A : return "remove V86 breakpoint"; case 0x000B : return "allocate V86 callback"; case 0x000C : return "allocation PM callback"; case 0x000D : return "call when VM returns"; case 0x000E : return "schedule global event"; case 0x000F : return "schedule VM event"; case 0x0010 : return "call global event"; case 0x0011 : return "call VM event"; case 0x0012 : return "cancel global event"; case 0x0013 : return "cancel VM event"; case 0x0014 : return "call priority VM event"; case 0x0015 : return "cancel priority VM event"; case 0x0016 : return "get NMI handler address"; case 0x0017 : return "set NMI handler address"; case 0x0018 : return "hook NMI event"; case 0x0019 : return "call when VM interrupts enabled"; case 0x001A : return "enable VM interrupts"; case 0x001B : return "disable VM interrupts"; case 0x001C : return "map flat"; case 0x001D : return "map linear to VM address"; case 0x001E : return "adjust execution priority"; case 0x001F : return "begin critical section"; case 0x0020 : return "end critical section"; case 0x0021 : return "end critical section and suspend"; case 0x0022 : return "claim critical section"; case 0x0023 : return "release critical section"; case 0x0024 : return "call when not critical"; case 0x0025 : return "create semaphore"; case 0x0026 : return "destroy semaphore"; case 0x0027 : return "wait on semaphore"; case 0x0028 : return "signal semaphore"; case 0x0029 : return "get critical section status"; case 0x002A : return "call when task switched"; case 0x002B : return "suspend VM"; case 0x002C : return "resume VM"; case 0x002D : return "no-fail resume VM"; case 0x002E : return "nuke VM"; case 0x002F : return "crash current VM"; case 0x0030 : return "get execution focus"; case 0x0031 : return "set execution focus"; case 0x0032 : return "get time slice priority"; case 0x0033 : return "set time slice priority"; case 0x0034 : return "get time slice granularity"; case 0x0035 : return "set time slice granularity"; case 0x0036 : return "get time slice information"; case 0x0037 : return "adjust execution time"; case 0x0038 : return "release time slice"; case 0x0039 : return "wake up VM"; case 0x003A : return "call when idle"; case 0x003B : return "get next VM handle"; case 0x003C : return "set global timeout"; case 0x003D : return "set VM timeout"; case 0x003E : return "cancel timeout"; case 0x003F : return "get system time"; case 0x0040 : return "get VM execution time"; case 0x0041 : return "hook V86 interrupt chain"; case 0x0042 : return "get V86 interrupt vector"; case 0x0043 : return "set V86 interrupt vector"; case 0x0044 : return "get PM interrupt vector"; case 0x0045 : return "set PM interrupt vector"; case 0x0046 : return "simulate interrupt"; case 0x0047 : return "simulate IRET"; case 0x0048 : return "simulate far call"; case 0x0049 : return "simulate far jump"; case 0x004A : return "simulate far RET"; case 0x004B : return "simulate far RET N"; case 0x004C : return "build interrupt stack frame"; case 0x004D : return "simulate push"; case 0x004E : return "simulate pop"; case 0x004F : return "_HeapAllocate"; case 0x0050 : return "_HeapReAllocate"; case 0x0051 : return "_HeapFree"; case 0x0052 : return "_HeapGetSize"; case 0x0053 : return "_PageAllocate"; case 0x0054 : return "_PageReAllocate"; case 0x0055 : return "_PageFree"; case 0x0056 : return "_PageLock"; case 0x0057 : return "_PageUnLock"; case 0x0058 : return "_PageGetSizeAddr"; case 0x0059 : return "_PageGetAllocInfo"; case 0x005A : return "_GetFreePageCount"; case 0x005B : return "_GetSysPageCount"; case 0x005C : return "_GetVMPgCount"; case 0x005D : return "_MapIntoV86"; case 0x005E : return "_PhysIntoV86"; case 0x005F : return "_TestGlobalV86Mem"; case 0x0060 : return "_ModifyPageBits"; case 0x0061 : return "copy page table"; case 0x0062 : return "map linear into V86"; case 0x0063 : return "linear page lock"; case 0x0064 : return "linear page unlock"; case 0x0065 : return "_SetResetV86Pageabl"; case 0x0066 : return "_GetV86PageableArray"; case 0x0067 : return "_PageCheckLinRange"; case 0x0068 : return "page out dirty pages"; case 0x0069 : return "discard pages"; case 0x006A : return "_GetNulPageHandle"; case 0x006B : return "get first V86 page"; case 0x006C : return "map physical address to linear address"; case 0x006D : return "_GetAppFlatDSAlias"; case 0x006E : return "_SelectorMapFlat"; case 0x006F : return "_GetDemandPageInfo"; case 0x0070 : return "_GetSetPageOutCount"; case 0x0071 : return "hook V86 page"; case 0x0072 : return "assign device V86 pages"; case 0x0073 : return "deassign device V86 pages"; case 0x0074 : return "get array of V86 pages for device"; case 0x0075 : return "_SetNULPageAddr"; case 0x0076 : return "allocate GDT selector"; case 0x0077 : return "free GDT selector"; case 0x0078 : return "allocate LDT selector"; case 0x0079 : return "free LDT selector"; case 0x007A : return "_BuildDescriptorDWORDs"; case 0x007B : return "get descriptor"; case 0x007C : return "set descriptor"; case 0x007D : return "toggle HMA"; case 0x007E : return "get fault hook addresses"; case 0x007F : return "hook V86 fault"; case 0x0080 : return "hook PM fault"; case 0x0081 : return "hook VMM fault"; case 0x0082 : return "begin nested V86 execution"; case 0x0083 : return "begin nested execution"; case 0x0084 : return "execute V86-mode interrupt"; case 0x0085 : return "resume execution"; case 0x0086 : return "end nested execution"; case 0x0087 : return "allocate PM application callback area"; case 0x0088 : return "get current PM application callback area"; case 0x0089 : return "set V86 execution mode"; case 0x008A : return "set PM execution mode"; case 0x008B : return "begin using locked PM stack"; case 0x008C : return "end using locked PM stack"; case 0x008D : return "save client state"; case 0x008E : return "restore client state"; case 0x008F : return "execute VxD interrupt"; case 0x0090 : return "hook device service"; case 0x0091 : return "hook device V86 API"; case 0x0092 : return "hook device PM API"; case 0x0093 : return "system control (see also #02657)"; case 0x0094 : return "simulate I/O"; case 0x0095 : return "install multiple I/O handlers"; case 0x0096 : return "install I/O handler"; case 0x0097 : return "enable global trapping"; case 0x0098 : return "enable local trapping"; case 0x0099 : return "disable global trapping"; case 0x009A : return "disable local trapping"; case 0x009B : return "create list"; case 0x009C : return "destroy list"; case 0x009D : return "allocate list"; case 0x009E : return "attach list"; case 0x009F : return "attach list tail"; case 0x00A0 : return "insert into list"; case 0x00A1 : return "remove from list"; case 0x00A2 : return "deallocate list"; case 0x00A3 : return "get first item in list"; case 0x00A4 : return "get next item in list"; case 0x00A5 : return "remove first item in list"; case 0x00A6 : return "add instance item"; case 0x00A7 : return "allocate device callback area"; case 0x00A8 : return "allocate global V86 data area"; case 0x00A9 : return "allocate temporary V86 data area"; case 0x00AA : return "free temporary V86 data area"; case 0x00AB : return "get decimal integer from profile"; case 0x00AC : return "convert decimal string to integer"; case 0x00AD : return "get fixed-point number from profile"; case 0x00AE : return "convert fixed-point string"; case 0x00AF : return "get hex integer from profile"; case 0x00B0 : return "convert hex string to integer"; case 0x00B1 : return "get boolean value from profile"; case 0x00B2 : return "convert boolean string"; case 0x00B3 : return "get string from profile"; case 0x00B4 : return "get next string from profile"; case 0x00B5 : return "get environment string"; case 0x00B6 : return "get exec path"; case 0x00B7 : return "get configuration directory"; case 0x00B8 : return "open file"; case 0x00B9 : return "get PSP segment"; case 0x00BA : return "get DOS vectors"; case 0x00BB : return "get machine information"; case 0x00BC : return "get/set HMA information"; case 0x00BD : return "set system exit code"; case 0x00BE : return "fatal error handler"; case 0x00BF : return "fatal memory error"; case 0x00C0 : return "update system clock"; case 0x00C1 : return "test if debugger installed"; case 0x00C2 : return "output debugger string"; case 0x00C3 : return "output debugger character"; case 0x00C4 : return "input debugger character"; case 0x00C5 : return "debugger convert hex to binary"; case 0x00C6 : return "debugger convert hex to decimal"; case 0x00C7 : return "debugger test if valid handle"; case 0x00C8 : return "validate client pointer"; case 0x00C9 : return "test reentry"; case 0x00CA : return "queue debugger string"; case 0x00CB : return "log procedure call"; case 0x00CC : return "debugger test current VM"; case 0x00CD : return "get PM interrupt type"; case 0x00CE : return "set PM interrupt type"; case 0x00CF : return "get last updated system time"; case 0x00D0 : return "get last updated VM execution time"; case 0x00D1 : return "test if double-byte character-set lead byte"; case 0x00D2 : return "_AddFreePhysPage"; case 0x00D3 : return "_PageResetHandlePAddr"; case 0x00D4 : return "_SetLastV86Page"; case 0x00D5 : return "_GetLastV86Page"; case 0x00D6 : return "_MapFreePhysReg"; case 0x00D7 : return "_UnmapFreePhysReg"; case 0x00D8 : return "_XchgFreePhysReg"; case 0x00D9 : return "_SetFreePhysRegCalBk"; case 0x00DA : return "get next arena (MCB)"; case 0x00DB : return "get name of ugly TSR"; case 0x00DC : return "get debug options"; case 0x00DD : return "set physical HMA alias"; case 0x00DE : return "_GetGlblRng0V86IntBase"; case 0x00DF : return "add global V86 data area"; case 0x00E0 : return "get/set detailed VM error"; case 0x00E1 : return "Is_Debug_Chr"; case 0x00E2 : return "clear monochrome screen"; case 0x00E3 : return "output character to mono screen"; case 0x00E4 : return "output string to mono screen"; case 0x00E5 : return "set current position on mono screen"; case 0x00E6 : return "get current position on mono screen"; case 0x00E7 : return "get character from mono screen"; case 0x00E8 : return "locate byte in ROM"; case 0x00E9 : return "hook invalid page fault"; case 0x00EA : return "unhook invalid page fault"; case 0x00EB : return "set delete on exit file"; case 0x00EC : return "close VM"; case 0x00ED : return "Enable_Touch_1st_Meg"; case 0x00EE : return "Disable_Touch_1st_Meg"; case 0x00EF : return "install exception handler"; case 0x00F0 : return "remove exception handler"; case 0x00F1 : return "Get_Crit_Status_No_Block"; case 0x00F2 : return "_Schedule_VM_RTI_Event"; case 0x00F3 : return "_Trace_Out_Service"; case 0x00F4 : return "_Debug_Out_Service"; case 0x00F5 : return "_Debug_Flags_Service"; case 0x00F6 : return "VMM add import module name"; case 0x00F7 : return "VMM Add DDB"; case 0x00F8 : return "VMM Remove DDB"; case 0x00F9 : return "get thread time slice priority"; case 0x00FA : return "set thread time slice priority"; case 0x00FB : return "schedule thread event"; case 0x00FC : return "cancel thread event"; case 0x00FD : return "set thread timeout"; case 0x00FE : return "set asynchronous timeout"; case 0x00FF : return "_AllocatreThreadDataSlot"; case 0x0100 : return "_FreeThreadDataSlot"; case 0x0101 : return "create Mutex"; case 0x0102 : return "destroy Mutex"; case 0x0103 : return "get Mutex owner"; case 0x0104 : return "call when thread switched"; case 0x0105 : return "create thread"; case 0x0106 : return "start thread"; case 0x0107 : return "terminate thread"; case 0x0108 : return "get current thread handle"; case 0x0109 : return "test current thread handle"; case 0x010A : return "Get_Sys_Thread_Handle"; case 0x010B : return "Test_Sys_Thread_Handle"; case 0x010C : return "Validate_Thread_Handle"; case 0x010D : return "Get_Initial_Thread_Handle"; case 0x010E : return "Test_Initial_Thread_Handle"; case 0x010F : return "Debug_Test_Valid_Thread_Handle"; case 0x0110 : return "Debug_Test_Cur_Thread"; case 0x0111 : return "VMM_GetSystemInitState"; case 0x0112 : return "Cancel_Call_When_Thread_Switched"; case 0x0113 : return "Get_Next_Thread_Handle"; case 0x0114 : return "Adjust_Thread_Exec_Priority"; case 0x0115 : return "_Deallocate_Device_CB_Area"; case 0x0116 : return "Remove_IO_Handler"; case 0x0117 : return "Remove_Mult_IO_Handlers"; case 0x0118 : return "unhook V86 interrupt chain"; case 0x0119 : return "unhook V86 fault handler"; case 0x011A : return "unhook PM fault handler"; case 0x011B : return "unhook VMM fault handler"; case 0x011C : return "unhook device service"; case 0x011D : return "_PageReserve"; case 0x011E : return "_PageCommit"; case 0x011F : return "_PageDecommit"; case 0x0120 : return "_PagerRegister"; case 0x0121 : return "_PagerQuery"; case 0x0122 : return "_PagerDeregister"; case 0x0123 : return "_ContextCreate"; case 0x0124 : return "_ContextDestroy"; case 0x0125 : return "_PageAttach"; case 0x0126 : return "_PageFlush"; case 0x0127 : return "_SignalID"; case 0x0128 : return "_PageCommitPhys"; case 0x0129 : return "_Register_Win32_Services"; case 0x012A : return "Cancel_Call_When_Not_Critical"; case 0x012B : return "Cancel_Call_When_Idle"; case 0x012C : return "Cancel_Call_When_Task_Switched"; case 0x012D : return "_Debug_Printf_Service"; case 0x012E : return "enter Mutex"; case 0x012F : return "leave Mutex"; case 0x0130 : return "simulate VM I/O"; case 0x0131 : return "Signal_Semaphore_No_Switch"; case 0x0132 : return "_MMSwitchContext"; case 0x0133 : return "_MMModifyPermissions"; case 0x0134 : return "_MMQuery"; case 0x0135 : return "_EnterMustComplete"; case 0x0136 : return "_LeaveMustComplete"; case 0x0137 : return "_ResumeExecMustComplete"; case 0x0138 : return "get thread termination status"; case 0x0139 : return "_GetInstanceInfo"; case 0x013A : return "_ExecIntMustComplete"; case 0x013B : return "_ExecVxDIntMustComplete"; case 0x013C : return "begin V86 serialization"; case 0x013D : return "unhook V86 page"; case 0x013E : return "VMM_GetVxDLocationList"; case 0x013F : return "VMM_GetDDBList: get start of VxD chain"; case 0x0140 : return "unhook NMI event"; case 0x0141 : return "Get_Instanced_V86_Int_Vector"; case 0x0142 : return "get or set real DOS PSP"; case 0x0143 : return "call priority thread event"; case 0x0144 : return "Get_System_Time_Address"; case 0x0145 : return "Get_Crit_Status_Thread"; case 0x0146 : return "Get_DDB"; case 0x0147 : return "Directed_Sys_Control"; case 0x0148 : return "_RegOpenKey"; case 0x0149 : return "_RegCloseKey"; case 0x014A : return "_RegCreateKey"; case 0x014B : return "_RegDeleteKey"; case 0x014C : return "_RegEnumKey"; case 0x014D : return "_RegQueryValue"; case 0x014E : return "_RegSetValue"; case 0x014F : return "_RegDeleteValue"; case 0x0150 : return "_RegEnumValue"; case 0x0151 : return "_RegQueryValueEx"; case 0x0152 : return "_RegSetValueEx"; case 0x0153 : return "_CallRing3"; case 0x0154 : return "Exec_PM_Int"; case 0x0155 : return "_RegFlushKey"; case 0x0156 : return "_PageCommitContig"; case 0x0157 : return "_GetCurrentContext"; case 0x0158 : return "_LocalizeSprintf"; case 0x0159 : return "_LocalizeStackSprintf"; case 0x015A : return "Call_Restricted_Event"; case 0x015B : return "Cancel_Restricted_Event"; case 0x015C : return "Register_PEF_Provider"; case 0x015D : return "_GetPhysPageInfo"; case 0x015E : return "_RegQueryInfoKey"; case 0x015F : return "MemArb_Reserve_Pages"; case 0x0160 : return "Time_Slice_Sys_VM_Idle"; case 0x0161 : return "Time_Slice_Sleep"; case 0x0162 : return "Boost_With_Decay"; case 0x0163 : return "Set_Inversion_Pri"; case 0x0164 : return "Reset_Inversion_Pri"; case 0x0165 : return "Release_Inversion_Pri"; case 0x0166 : return "Get_Thread_Win32_Pri"; case 0x0167 : return "Set_Thread_Win32_Pri"; case 0x0168 : return "Set_Thread_Static_Boost"; case 0x0169 : return "Set_VM_Static_Boost"; case 0x016A : return "Release_Inversion_Pri_ID"; case 0x016B : return "Attach_Thread_To_Group"; case 0x016C : return "Detach_Thread_From_Group"; case 0x016D : return "Set_Group_Static_Boost"; case 0x016E : return "_GetRegistryPath"; case 0x016F : return "_GetRegistryKey"; case 0x0170 : return "_CleanupNestedExec"; case 0x0171 : return "_RegRemapPreDefKey"; case 0x0172 : return "End_V86_Serialization"; case 0x0173 : return "_Assert_Range"; case 0x0174 : return "_Sprintf"; case 0x0175 : return "_PageChangePager"; case 0x0176 : return "_RegCreateDynKey"; case 0x0177 : return "RegQMulti"; case 0x0178 : return "Boost_Thread_With_VM"; case 0x0179 : return "Get_Boot_Flags"; case 0x017A : return "Set_Boot_Flags"; case 0x017B : return "_lstrcpyn"; case 0x017C : return "_lstrlen"; case 0x017D : return "_lmemcpy"; case 0x017E : return "_GetVxDName"; case 0x017F : return "Force_Mutexes_Free"; case 0x0180 : return "Restore_Forced_Mutexes"; case 0x0181 : return "_AddReclaimableItem"; case 0x0182 : return "_SetReclaimableItem"; case 0x0183 : return "_EnumReclaimableItem"; case 0x0184 : return "Time_Slice_Wake_Sys_VM"; case 0x0185 : return "VMM_Replace_Global_Environment"; case 0x0186 : return "Begin_Non_Serial_Nest_V86_Exec"; case 0x0187 : return "Get_Nest_Exec_Status"; case 0x0188 : return "Open_Boot_Log"; case 0x0189 : return "Write_Boot_Log"; case 0x018A : return "Close_Boot_Log"; case 0x018B : return "EnableDisable_Boot_Log"; case 0x018C : return "_Call_On_My_Stack"; case 0x018D : return "Get_Inst_V86_Int_Vec_Base"; case 0x018E : return "_lstrcmpi"; case 0x018F : return "_strupr"; case 0x0190 : return "Log_Fault_Call_Out"; case 0x0191 : return "_AtEventTime"; default: return "dunnoSV"; } case 0x0002: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "DEBUG_Fault"; case 0x0002 : return "DEBUG_CheckFault"; case 0x0003 : return "DEBUG_LoadSyms"; default: return "dunnoSV"; } case 0x0003: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "virtualize IRQ"; case 0x0002 : return "set interrupt request"; case 0x0003 : return "clear interrupt request"; case 0x0004 : return "physical EOI"; case 0x0005 : return "get complete status"; case 0x0006 : return "get status"; case 0x0007 : return "test physical request"; case 0x0008 : return "physically mask"; case 0x0009 : return "physically unmask"; case 0x000A : return "set automatic masking"; case 0x000B : return "get IRQ complete status"; case 0x000C : return "convert handle to IRQ"; case 0x000D : return "convert IRQ to interrupt"; case 0x000E : return "convert interrupt to IRQ"; case 0x000F : return "call on hardware interrupt"; case 0x0010 : return "force default owner"; case 0x0011 : return "force default behavior"; case 0x0012 : return "VPICD_Auto_Mask_At_Inst_Swap"; case 0x0013 : return "VPICD_Begin_Inst_Page_Swap"; case 0x0014 : return "VPICD_End_Inst_Page_Swap"; case 0x0015 : return "VPICD_Virtual_EOI"; case 0x0016 : return "VPICD_Get_Virtualization_Count"; case 0x0017 : return "VPICD_Post_Sys_Critical_Init"; case 0x0018 : return "VPICD_VM_SlavePIC_Mask_Change"; default: return "dunnoSV"; } case 0x0004: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "virtualize channel"; case 0x0002 : return "get region information"; case 0x0003 : return "set region information"; case 0x0004 : return "get virtual state"; case 0x0005 : return "set virtual state"; case 0x0006 : return "set physical state"; case 0x0007 : return "mask channel"; case 0x0008 : return "unmask channel"; case 0x0009 : return "lock DMA region"; case 0x000A : return "unlock DMA region"; case 0x000B : return "scatter lock"; case 0x000C : return "scatter unlock"; case 0x000D : return "reserve buffer space"; case 0x000E : return "request buffer"; case 0x000F : return "release buffer"; case 0x0010 : return "copy to buffer"; case 0x0011 : return "copy from buffer"; case 0x0012 : return "default handler"; case 0x0013 : return "disable translation"; case 0x0014 : return "enable translation"; case 0x0015 : return "get EISA address mode"; case 0x0016 : return "set EISA address mode"; case 0x0017 : return "unlock DMA region (ND)"; case 0x0018 : return "VDMAD_Phys_Mask_Channel"; case 0x0019 : return "VDMAD_Phys_Unmask_Channel"; case 0x001A : return "VDMAD_Unvirtualize_Channel"; case 0x001B : return "VDMAD_Set_IO_Address"; case 0x001C : return "VDMAD_Get_Phys_Count"; case 0x001D : return "VDMAD_Get_Phys_Status"; case 0x001E : return "VDMAD_Get_Max_Phys_Page"; case 0x001F : return "VDMAD_Set_Channel_Callbacks"; case 0x0020 : return "VDMAD_Get_Virt_Count"; case 0x0021 : return "VDMAD_Set_Virt_Count"; default: return "dunnoSV"; } case 0x0005: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "update system clock"; case 0x0002 : return "get interrupt period"; case 0x0003 : return "begin minimum interrupt period"; case 0x0004 : return "end minimum interrupt period"; case 0x0005 : return "disable trapping"; case 0x0006 : return "enable trapping"; case 0x0007 : return "get real time"; case 0x0008 : return "VTD_Get_Date_And_Time"; case 0x0009 : return "VTD_Adjust_VM_Count"; case 0x000A : return "VTD_Delay"; default: return "dunnoSV"; } case 0x0006: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "allocate V86 pages"; case 0x0002 : return "set EMS and XMS limits"; case 0x0003 : return "get EMS and XMS limits"; case 0x0004 : return "set mapping information"; case 0x0005 : return "get mapping information"; case 0x0006 : return "Xlat API"; case 0x0007 : return "load client pointer"; case 0x0008 : return "allocate buffer"; case 0x0009 : return "free buffer"; case 0x000A : return "get Xlat buffer state"; case 0x000B : return "set Xlat buffer state"; case 0x000C : return "get VM flat selector"; case 0x000D : return "map pages"; case 0x000E : return "free page map region"; case 0x000F : return "_LocalGlobalReg"; case 0x0010 : return "get page status"; case 0x0011 : return "set local A20"; case 0x0012 : return "reset base pages"; case 0x0013 : return "set available mapped pages"; case 0x0014 : return "V86MMGR_NoUMBInitCalls"; case 0x0015 : return "V86MMGR_Get_EMS_XMS_Avail"; case 0x0016 : return "V86MMGR_Toggle_HMA"; case 0x0017 : return "V86MMGR_Dev_Init"; case 0x0018 : return "V86MMGR_Alloc_UM_Page"; default: return "dunnoSV"; } case 0x0007: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "test create"; case 0x0002 : return "create swap file"; case 0x0003 : return "destroy swap file"; case 0x0004 : return "in"; case 0x0005 : return "out"; case 0x0006 : return "test if I/O valid"; case 0x0007 : return "Read_Or_Write"; case 0x0008 : return "Grow_File"; case 0x0009 : return "Init_File"; default: return "dunnoSV"; } case 0x000a: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "PIF state"; case 0x0002 : return "get GrabRtn"; case 0x0003 : return "hide cursor"; case 0x0004 : return "set VM type"; case 0x0005 : return "get ModTime"; case 0x0006 : return "set HCurTrk"; case 0x0007 : return "message clear screen"; case 0x0008 : return "message foreground color"; case 0x0009 : return "message background color"; case 0x000A : return "message output text"; case 0x000B : return "message set cursor position"; case 0x000C : return "query access"; case 0x000D : return "VDD_Check_Update_Soon"; case 0x000E : return "VDD_Get_Mini_Dispatch_Table"; case 0x000F : return "VDD_Register_Virtual_Port"; case 0x0010 : return "VDD_Get_VM_Info"; case 0x0011 : return "VDD_Get_Special_VM_IDs"; case 0x0012 : return "VDD_Register_Extra_Screen_Selector"; case 0x0013 : return "VDD_Takeover_VGA_Port"; default: return "dunnoSV"; } case 0x000c: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "set mouse type"; case 0x0002 : return "get mouse owner"; case 0x0003 : return "VMOUSE_Post_Pointer_Message"; case 0x0004 : return "VMOUSE_Set_Cursor_Proc"; case 0x0005 : return "VMOUSE_Call_Cursor_Proc"; case 0x0006 : return "VMOUSE_Set_Mouse_Data~Get_Mouse_Data"; case 0x0007 : return "VMOUSE_Manipulate_Pointer_Message"; case 0x0008 : return "VMOUSE_Set_Middle_Button"; case 0x0009 : return "VMD_Set_Middle_Button"; case 0x000A : return "VMD_Enable_Disable_Mouse_Events"; case 0x000B : return "VMD_Post_Absolute_Pointer_Message"; default: return "dunnoSV"; } case 0x000d: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "define hotkey"; case 0x0002 : return "remove hotkey"; case 0x0003 : return "locally enable hotkey"; case 0x0004 : return "locally disable hotkey"; case 0x0005 : return "reflect hotkey"; case 0x0006 : return "cancel hotkey state"; case 0x0007 : return "force keys"; case 0x0008 : return "get keyboard owner"; case 0x0009 : return "define paste mode"; case 0x000A : return "start pasting"; case 0x000B : return "cancel paste"; case 0x000C : return "get message key"; case 0x000D : return "peek message key"; case 0x000E : return "flush message key queue"; case 0x000F : return "VKD_Enable_Keyboard"; case 0x0010 : return "VKD_Disable_Keyboard"; case 0x0011 : return "VKD_Get_Shift_State"; case 0x0012 : return "VKD_Filter_Keyboard_Input"; case 0x0013 : return "VKD_Put_Byte"; case 0x0014 : return "VKD_Set_Shift_State"; default: return "dunnoSV"; } case 0x000e: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "set port global"; case 0x0002 : return "get focus"; case 0x0003 : return "virtualize port"; case 0x0004 : return "VCD_Acquire_Port"; case 0x0005 : return "VCD_Free_Port"; case 0x0006 : return "VCD_Acquire_Port_Windows_Style"; case 0x0007 : return "VCD_Free_Port_Windows_Style"; case 0x0008 : return "VCD_Steal_Port_Windows_Style"; case 0x0009 : return "VCD_Find_COM_Index"; case 0x000A : return "VCD_Set_Port_Global_Special"; case 0x000B : return "VCD_Virtualize_Port_Dynamic"; case 0x000C : return "VCD_Unvirtualize_Port_Dynamic"; default: return "dunnoSV"; } case 0x0010: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "register device"; case 0x0002 : return "find INT 13 drive"; case 0x0003 : return "get device list"; case 0x0004 : return "send command"; case 0x0005 : return "command complete"; case 0x0006 : return "synchronous command"; case 0x0007 : return "IOS_Register"; case 0x0008 : return "IOS_Requestor_Service"; case 0x0009 : return "IOS_Exclusive_Access"; case 0x000A : return "IOS_Send_Next_Command"; case 0x000B : return "IOS_Set_Async_Time_Out"; case 0x000C : return "IOS_Signal_Semaphore_No_Switch"; case 0x000D : return "IOSIdleStatus"; case 0x000E : return "IOSMapIORSToI24"; case 0x000F : return "IOSMapIORSToI21"; case 0x0010 : return "PrintLog"; default: return "dunnoSV"; } case 0x0011: switch (sv & 0x7fff) { case 0x0000 : return "get_version"; case 0x0001 : return "get_virt_state"; case 0x0002 : return "set_virt_state"; case 0x0003 : return "get_cr0_state"; case 0x0004 : return "set_cr0_state"; case 0x0005 : return "get_thread_state"; case 0x0006 : return "set_thread_state"; case 0x0007 : return "get_FP_instruction_size"; case 0x0008 : return "set_thread_precision"; default: return "dunnoSV"; } case 0x0012: switch (sv & 0x7fff) { case 0x0000 : return "get EBIOS version"; case 0x0001 : return "get unused memory"; default: return "dunnoSV"; } case 0x0015: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "set exec VM data"; case 0x0002 : return "coyp VM drive state"; case 0x0003 : return "execute VM"; case 0x0004 : return "get InDOS pointer"; case 0x0005 : return "add device"; case 0x0006 : return "remove device"; case 0x0007 : return "instance device"; case 0x0008 : return "get DOS critical status"; case 0x0009 : return "enable InDOS polling"; case 0x000A : return "backfill allowed"; case 0x000B : return "LocalGlobalReg"; case 0x000C : return "Init_UMB_Area"; case 0x000D : return "Begin_V86_App"; case 0x000E : return "End_V86_App"; case 0x000F : return "Alloc_Local_Sys_VM_Mem"; case 0x0010 : return "DOSMGR_Grow_CDSs"; case 0x0011 : return "DOSMGR_Translate_Server_DOS_Call"; case 0x0012 : return "DOSMGR_MMGR_PSP_Change_Notifier"; default: return "dunnoSV"; } case 0x0017: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "resolve contention"; case 0x0002 : return "event"; case 0x0003 : return "SYSMODAL message"; case 0x0004 : return "message"; case 0x0005 : return "get VM information"; case 0x0006 : return "_SHELL_PostMessage"; case 0x0007 : return "_SHELL_WinExec"; case 0x0008 : return "_SHELL_CallDll"; case 0x0009 : return "SHELL_OpenClipboard"; case 0x000A : return "SHELL_SetClipboardData"; case 0x000B : return "SHELL_GetClipboardData"; case 0x000C : return "SHELL_CloseClipboard"; case 0x000D : return "_SHELL_Install_Taskman_Hooks"; case 0x000E : return "SHELL_Hook_Properties"; case 0x000F : return "SHELL_Unhook_Properties"; case 0x0010 : return "SHELL_OEMKeyScan"; case 0x0011 : return "SHELL_Update_User_Activity"; case 0x0012 : return "_SHELL_UnhookSystemBroadcast"; case 0x0013 : return "_SHELL_LocalAllocEx"; case 0x0014 : return "_SHELL_LocalFree"; case 0x0015 : return "_SHELL_LoadLibrary"; case 0x0016 : return "_SHELL_FreeLibrary"; case 0x0017 : return "_SHELL_GetProcAddress"; case 0x0018 : return "_SHELL_CallDll"; case 0x0019 : return "_SHELL_SuggestSingleMSDOSMode"; case 0x001A : return "SHELL_CheckHotkeyAllowed"; case 0x001B : return "_SHELL_GetDOSAppInfo"; default: return "dunnoSV"; } case 0x0018: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "enable/disable"; case 0x0002 : return "reset detection"; case 0x0003 : return "check idle"; default: return "dunnoSV"; } case 0x001a: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "send FILESYSCHANGE"; case 0x0002 : return "do PSP adjust"; default: return "dunnoSV"; } case 0x001b: case 0x001c: switch (sv & 0x7fff) { case 0x0000 : return "get version"; default: return "dunnoSV"; } case 0x0021: switch (sv & 0x7fff) { case 0x0000 : return "get version"; case 0x0001 : return "init file"; case 0x0002 : return "clean up"; case 0x0003 : return "grow file"; case 0x0004 : return "read or write"; case 0x0005 : return "cancel"; case 0x0006 : return "test I/O valid"; case 0x0007 : return "Get_Size_Info"; case 0x0008 : return "Set_Async_Manager"; case 0x0009 : return "Call_Async_Manager"; default: return "dunnoSV"; } case 0x0027: switch (sv & 0x7fff) { case 0x0000 : return "VXDLDR_Get_Version"; case 0x0001 : return "VXDLDR_LoadDevice"; case 0x0002 : return "VXDLDR_UnloadDevice"; case 0x0003 : return "VXDLDR_DevInitSucceeded"; case 0x0004 : return "VXDLDR_DevInitFailed"; case 0x0005 : return "VXDLDR_GetDeviceList"; case 0x0006 : return "VXDLDR_UnloadMe"; case 0x0007 : return "PELDR_LoadModule"; case 0x0008 : return "PELDR_GetModuleHandle"; case 0x0009 : return "PELDR_GetModuleUsage"; case 0x000A : return "PELDR_GetEntryPoint"; case 0x000B : return "PELDR_GetProcAddress"; case 0x000C : return "PELDR_AddExportTable"; case 0x000D : return "PELDR_RemoveExportTable"; case 0x000E : return "PELDR_FreeModule"; case 0x000F : return "VXDLDR_Notify"; case 0x0010 : return "_PELDR_InitCompleted"; case 0x0011 : return "_PELDR_LoadModuleEx"; default: return "dunnoSV"; } case 0x002A: switch (sv & 0x7fff) { case 0x0000 : return "VWin32_Get_Version"; case 0x0001 : return "VWin32_Wake_For_Event"; case 0x0002 : return "_VWIN32_QueueUserApc"; case 0x0003 : return "_VWIN32_Get_Thread_Context"; case 0x0004 : return "_VWIN32_Set_Thread_Context"; case 0x0005 : return "_VWIN32_CopyMem"; case 0x0006 : return "_VWIN32_BlockForTermination"; case 0x0007 : return "_VWIN32_Emulate_Npx"; case 0x0008 : return "_VWIN32_CheckDelayedNpxTrap"; case 0x0009 : return "VWIN32_EnterCrstR0"; case 0x000A : return "VWIN32_LeaveCrstR0"; case 0x000B : return "_VWIN32_FaultPopup"; case 0x000C : return "VWIN32_GetContextHandle"; case 0x000D : return "VWIN32_GetCurrentProcessHandle"; case 0x000E : return "_VWIN32_SetWin32Event"; case 0x000F : return "_VWIN32_PulseWin32Event"; case 0x0010 : return "_VWIN32_ResetWin32Event"; case 0x0011 : return "_VWIN32_WaitSingleObject"; case 0x0012 : return "_VWIN32_WaitMultipleObjects"; case 0x0013 : return "_VWIN32_CreateRing0Thread"; case 0x0014 : return "_VWIN32_CloseVxDHandle"; case 0x0015 : return "VWIN32_ActiveTimeBiasSet"; case 0x0016 : return "VWIN32_GetCurrentDirectory"; case 0x0017 : return "VWIN32_BlueScreenPopup"; case 0x0018 : return "VWIN32_TerminateApp"; case 0x0019 : return "_VWIN32_QueueKernelAPC"; case 0x001A : return "VWIN32_SysErrorBox"; case 0x001B : return "_VWIN32_IsClientWin32"; case 0x001C : return "VWIN32_IFSRIPWhenLev2Taken"; default: return "dunnoSV"; } case 0x002b: switch (sv & 0x7fff) { case 0x0000 : return "VCOMM_Get_Version"; case 0x0001 : return "_VCOMM_Register_Port_Driver"; case 0x0002 : return "_VCOMM_Acquire_Port"; case 0x0003 : return "_VCOMM_Release_Port"; case 0x0004 : return "_VCOMM_OpenComm"; case 0x0005 : return "_VCOMM_SetCommState"; case 0x0006 : return "_VCOMM_GetCommState"; case 0x0007 : return "_VCOMM_SetupComm"; case 0x0008 : return "_VCOMM_TransmitCommChar"; case 0x0009 : return "_VCOMM_CloseComm"; case 0x000A : return "_VCOMM_GetCommQueueStatus"; case 0x000B : return "_VCOMM_ClearCommError"; case 0x000C : return "_VCOMM_GetModemStatus"; case 0x000D : return "_VCOMM_GetCommProperties"; case 0x000E : return "_VCOMM_EscapeCommFunction"; case 0x000F : return "_VCOMM_PurgeComm"; case 0x0010 : return "_VCOMM_SetCommEventMask"; case 0x0011 : return "_VCOMM_GetCommEventMask"; case 0x0012 : return "_VCOMM_WriteComm"; case 0x0013 : return "_VCOMM_ReadComm"; case 0x0014 : return "_VCOMM_EnableCommNotification"; case 0x0015 : return "_VCOMM_GetLastError"; case 0x0016 : return "_VCOMM_Steal_Port"; case 0x0017 : return "_VCOMM_SetReadCallBack"; case 0x0018 : return "_VCOMM_SetWriteCallBack"; case 0x0019 : return "_VCOMM_GetSetCommTimeouts"; case 0x001A : return "_VCOMM_SetWriteRequest"; case 0x001B : return "_VCOMM_SetReadRequest"; case 0x001C : return "_VCOMM_Dequeue_Request"; case 0x001D : return "_VCOMM_Dequeue_Request"; case 0x001E : return "_VCOMM_Enumerate_DevNodes"; case 0x001F : return "VCOMM_Map_Win32DCB_To_Ring0"; case 0x0020 : return "VCOMM_Map_Ring0DCB_To_Win32"; case 0x0021 : return "_VCOMM_Get_Contention_Handler"; case 0x0022 : return "_VCOMM_Map_Name_To_Resource"; default: return "dunnoSV"; } case 0x0033: switch (sv & 0x7fff) { case 0x0000 : return "_CONFIGMG_Get_Version"; case 0x0001 : return "_CONFIGMG_Initialize"; case 0x0002 : return "_CONFIGMG_Locate_DevNode"; case 0x0003 : return "_CONFIGMG_Get_Parent"; case 0x0004 : return "_CONFIGMG_Get_Child"; case 0x0005 : return "_CONFIGMG_Get_Sibling"; case 0x0006 : return "_CONFIGMG_Get_Device_ID_Size"; case 0x0007 : return "_CONFIGMG_Get_Device_ID"; case 0x0008 : return "_CONFIGMG_Get_Depth"; case 0x0009 : return "_CONFIGMG_Get_Private_DWord"; case 0x000A : return "_CONFIGMG_Set_Private_DWord"; case 0x000B : return "_CONFIGMG_Create_DevNode"; case 0x000C : return "_CONFIGMG_Query_Remove_SubTree"; case 0x000D : return "_CONFIGMG_Remove_SubTree"; case 0x000E : return "_CONFIGMG_Register_Device_Driver"; case 0x000F : return "_CONFIGMG_Register_Enumerator"; case 0x0010 : return "_CONFIGMG_Register_Arbitrator"; case 0x0011 : return "_CONFIGMG_Deregister_Arbitrator"; case 0x0012 : return "_CONFIGMG_Query_Arbitrator_Free_Size"; case 0x0013 : return "_CONFIGMG_Query_Arbitrator_Free_Data"; case 0x0014 : return "_CONFIGMG_Sort_NodeList"; case 0x0015 : return "_CONFIGMG_Yield"; case 0x0016 : return "_CONFIGMG_Lock"; case 0x0017 : return "_CONFIGMG_Unlock"; case 0x0018 : return "_CONFIGMG_Add_Empty_Log_Conf"; case 0x0019 : return "_CONFIGMG_Free_Log_Conf"; case 0x001A : return "_CONFIGMG_Get_First_Log_Conf"; case 0x001B : return "_CONFIGMG_Get_Next_Log_Conf"; case 0x001C : return "_CONFIGMG_Add_Res_Des"; case 0x001D : return "_CONFIGMG_Modify_Res_Des"; case 0x001E : return "_CONFIGMG_Free_Res_Des"; case 0x001F : return "_CONFIGMG_Get_Next_Res_Des"; case 0x0020 : return "_CONFIGMG_Get_Performance_Info"; case 0x0021 : return "_CONFIGMG_Get_Res_Des_Data_Size"; case 0x0022 : return "_CONFIGMG_Get_Res_Des_Data"; case 0x0023 : return "_CONFIGMG_Process_Events_Now"; case 0x0024 : return "_CONFIGMG_Create_Range_List"; case 0x0025 : return "_CONFIGMG_Add_Range"; case 0x0026 : return "_CONFIGMG_Delete_Range"; case 0x0027 : return "_CONFIGMG_Test_Range_Available"; case 0x0028 : return "_CONFIGMG_Dup_Range_List"; case 0x0029 : return "_CONFIGMG_Free_Range_List"; case 0x002A : return "_CONFIGMG_Invert_Range_List"; case 0x002B : return "_CONFIGMG_Intersect_Range_List"; case 0x002C : return "_CONFIGMG_First_Range"; case 0x002D : return "_CONFIGMG_Next_Range"; case 0x002E : return "_CONFIGMG_Dump_Range_List"; case 0x002F : return "_CONFIGMG_Load_DLVxDs"; case 0x0030 : return "_CONFIGMG_Get_DDBs"; case 0x0031 : return "_CONFIGMG_Get_CRC_CheckSum"; case 0x0032 : return "_CONFIGMG_Register_DevLoader"; case 0x0033 : return "_CONFIGMG_Reenumerate_DevNode"; case 0x0034 : return "_CONFIGMG_Setup_DevNode"; case 0x0035 : return "_CONFIGMG_Reset_Children_Marks"; case 0x0036 : return "_CONFIGMG_Get_DevNode_Status"; case 0x0037 : return "_CONFIGMG_Remove_Unmarked_Children"; case 0x0038 : return "_CONFIGMG_ISAPNP_To_CM"; case 0x0039 : return "_CONFIGMG_CallBack_Device_Driver"; case 0x003A : return "_CONFIGMG_CallBack_Enumerator"; case 0x003B : return "_CONFIGMG_Get_Alloc_Log_Conf"; case 0x003C : return "_CONFIGMG_Get_DevNode_Key_Size"; case 0x003D : return "_CONFIGMG_Get_DevNode_Key"; case 0x003E : return "_CONFIGMG_Read_Registry_Value"; case 0x003F : return "_CONFIGMG_Write_Registry_Value"; case 0x0040 : return "_CONFIGMG_Disable_DevNode"; case 0x0041 : return "_CONFIGMG_Enable_DevNode"; case 0x0042 : return "_CONFIGMG_Move_DevNode"; case 0x0043 : return "_CONFIGMG_Set_Bus_Info"; case 0x0044 : return "_CONFIGMG_Get_Bus_Info"; case 0x0045 : return "_CONFIGMG_Set_HW_Prof"; case 0x0046 : return "_CONFIGMG_Recompute_HW_Prof"; case 0x0047 : return "_CONFIGMG_Query_Change_HW_Prof"; case 0x0048 : return "_CONFIGMG_Get_Device_Driver_Private_DWord"; case 0x0049 : return "_CONFIGMG_Set_Device_Driver_Private_DWord"; case 0x004A : return "_CONFIGMG_Get_HW_Prof_Flags"; case 0x004B : return "_CONFIGMG_Set_HW_Prof_Flags"; case 0x004C : return "_CONFIGMG_Read_Registry_Log_Confs"; case 0x004D : return "_CONFIGMG_Run_Detection"; case 0x004E : return "_CONFIGMG_Call_At_Appy_Time"; case 0x004F : return "_CONFIGMG_Fail_Change_HW_Prof"; case 0x0050 : return "_CONFIGMG_Set_Private_Problem"; case 0x0051 : return "_CONFIGMG_Debug_DevNode"; case 0x0052 : return "_CONFIGMG_Get_Hardware_Profile_Info"; case 0x0053 : return "_CONFIGMG_Register_Enumerator_Function"; case 0x0054 : return "_CONFIGMG_Call_Enumerator_Function"; case 0x0055 : return "_CONFIGMG_Add_ID"; case 0x0056 : return "_CONFIGMG_Find_Range"; case 0x0057 : return "_CONFIGMG_Get_Global_State"; case 0x0058 : return "_CONFIGMG_Broadcast_Device_Change_Message"; case 0x0059 : return "_CONFIGMG_Call_DevNode_Handler"; case 0x005A : return "_CONFIGMG_Remove_Reinsert_All"; default: return "dunnoSV"; } case 0x048B: switch (sv & 0x7fff) { case 0x0000 : return "VXDLDR_Get_Version"; case 0x0001 : return "VCACHE_Register"; case 0x0002 : return "VCACHE_GetSize"; case 0x0003 : return "VCACHE_CheckAvail"; case 0x0004 : return "VCACHE_FindBlock"; case 0x0005 : return "VCACHE_FreeBlock"; case 0x0006 : return "VCACHE_MakeMRU"; case 0x0007 : return "VCACHE_Hold"; case 0x0008 : return "VCACHE_Unhold"; case 0x0009 : return "VCACHE_Enum"; case 0x000A : return "VCACHE_TestHandle"; case 0x000B : return "VCACHE_VerifySums"; case 0x000C : return "VCACHE_RecalcSums"; case 0x000D : return "VCACHE_TestHold"; case 0x000E : return "VCACHE_GetStats"; case 0x000F : return "VCache_Deregister"; case 0x0010 : return "VCache_AdjustMinimum"; case 0x0011 : return "VCache_SwapBuffers"; case 0x0012 : return "VCache_RelinquishPage"; case 0x0013 : return "VCache_UseThisPage"; case 0x0014 : return "_VCache_CreateLookupCache"; case 0x0015 : return "_VCache_CloseLookupCache"; case 0x0016 : return "_VCache_DeleteLookupCache"; case 0x0017 : return "_VCache_Lookup"; case 0x0018 : return "_VCache_UpdateLookup"; default: return "dunnoSV"; } default: return "dunnoNR"; } } Bit8u lastint; void CPU_Interrupt(Bitu num,Bitu type,Bitu oldeip) { lastint=num; // if ((num!=0x16) && (num!=0x1a) && (num!=0x28) && (num!=0x2a) && (num!=0x13)) LOG_MSG("INT %x EAX:%04X ECX:%04X EDX:%04X EBX:%04X CS:%04X EIP:%08X SS:%04X ESP:%08X",num,reg_eax,reg_ecx,reg_edx,reg_ebx,SegValue(cs),reg_eip,SegValue(ss),reg_esp); if ((num==0x20) && (cpu.pmode)) { PhysPt csip20 = SegPhys(cs)+reg_eip; Bitu sv = mem_readw(csip20+2); Bitu nr = mem_readw(csip20+4); LOG_MSG("VxD service %s, %s (%X:%X)",translateVXDid(nr),translateVXDservice(nr,sv),nr,sv); } #if C_DEBUG switch (num) { case 0xcd: #if C_HEAVY_DEBUG LOG(LOG_CPU,LOG_ERROR)("Call to interrupt 0xCD this is BAD"); DEBUG_HeavyWriteLogInstruction(); #endif E_Exit("Call to interrupt 0xCD this is BAD"); case 0x03: if (DEBUG_Breakpoint()) { CPU_Cycles=0; return; } }; #endif if (!cpu.pmode) { /* Save everything on a 16-bit stack */ CPU_Push16(reg_flags & 0xffff); CPU_Push16(SegValue(cs)); CPU_Push16(oldeip); SETFLAGBIT(IF,false); SETFLAGBIT(TF,false); /* Get the new CS:IP from vector table */ PhysPt base=cpu.idt.GetBase(); reg_eip=mem_readw(base+(num << 2)); Segs.val[cs]=mem_readw(base+(num << 2)+2); Segs.phys[cs]=Segs.val[cs]<<4; cpu.code.big=false; return; } else { /* Protected Mode Interrupt */ if ((reg_flags & FLAG_VM) && (type&CPU_INT_SOFTWARE) && !(type&CPU_INT_NOIOPLCHECK)) { // LOG_MSG("Software int in v86, AH %X IOPL %x",reg_ah,(reg_flags & FLAG_IOPL) >>12); if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) { CPU_Exception(EXCEPTION_GP,0); return; } } Descriptor gate; if (!cpu.idt.GetDescriptor(num<<3,gate)) { // zone66 CPU_Exception(EXCEPTION_GP,num*8+2+(type&CPU_INT_SOFTWARE)?0:1); return; } if ((type&CPU_INT_SOFTWARE) && (gate.DPL()cpu.cpl, "Interrupt to higher privilege", EXCEPTION_GP,(gate_sel & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1) switch (cs_desc.Type()) { case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: if (cs_dpl0", EXCEPTION_GP,gate_sel & 0xfffc) Bitu n_ss,n_esp; Bitu o_ss,o_esp; o_ss=SegValue(ss); o_esp=reg_esp; cpu_tss.Get_SSx_ESPx(cs_dpl,n_ss,n_esp); CPU_CHECK_COND((n_ss & 0xfffc)==0, "INT:Gate with SS zero selector", EXCEPTION_TS,(type&CPU_INT_SOFTWARE)?0:1) Descriptor n_ss_desc; CPU_CHECK_COND(!cpu.gdt.GetDescriptor(n_ss,n_ss_desc), "INT:Gate with SS beyond limit", EXCEPTION_TS,(n_ss & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1) CPU_CHECK_COND(((n_ss & 3)!=cs_dpl) || (n_ss_desc.DPL()!=cs_dpl), "INT:Inner level with CS_DPL!=SS_DPL and SS_RPL", EXCEPTION_TS,(n_ss & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1) // check if stack segment is a writable data segment switch (n_ss_desc.Type()) { case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: break; default: E_Exit("INT:Inner level:Stack segment not writable."); // or #TS(ss_sel+EXT) } CPU_CHECK_COND(!n_ss_desc.saved.seg.p, "INT:Inner level with nonpresent SS", EXCEPTION_SS,(n_ss & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1) // commit point Segs.phys[ss]=n_ss_desc.GetBase(); Segs.val[ss]=n_ss; if (n_ss_desc.Big()) { cpu.stack.big=true; cpu.stack.mask=0xffffffff; reg_esp=n_esp; } else { cpu.stack.big=false; cpu.stack.mask=0xffff; reg_sp=n_esp & 0xffff; } cpu.cpl=cs_dpl; if (gate.Type() & 0x8) { /* 32-bit Gate */ if (reg_flags & FLAG_VM) { CPU_Push32(SegValue(gs));SegSet16(gs,0x0); CPU_Push32(SegValue(fs));SegSet16(fs,0x0); CPU_Push32(SegValue(ds));SegSet16(ds,0x0); CPU_Push32(SegValue(es));SegSet16(es,0x0); } CPU_Push32(o_ss); CPU_Push32(o_esp); } else { /* 16-bit Gate */ if (reg_flags & FLAG_VM) E_Exit("V86 to 16-bit gate"); CPU_Push16(o_ss); CPU_Push16(o_esp); } // LOG_MSG("INT:Gate to inner level SS:%X SP:%X",n_ss,n_esp); goto do_interrupt; } if (cs_dpl!=cpu.cpl) E_Exit("Non-conforming intra privilege INT with DPL!=CPL"); case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA: case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: /* Prepare stack for gate to same priviledge */ CPU_CHECK_COND(!cs_desc.saved.seg.p, "INT:Same level:CS segment not present", EXCEPTION_NP,(gate_sel & 0xfffc)+(type&CPU_INT_SOFTWARE)?0:1) if ((reg_flags & FLAG_VM) && (cs_dpl0; reg_eip=gate_off; if (!(gate.Type()&1)) SETFLAGBIT(IF,false); SETFLAGBIT(TF,false); SETFLAGBIT(NT,false); SETFLAGBIT(VM,false); LOG(LOG_CPU,LOG_NORMAL)("INT:Gate to %X:%X big %d %s",gate_sel,gate_off,cs_desc.Big(),gate.Type() & 0x8 ? "386" : "286"); return; } case DESC_TASK_GATE: CPU_SwitchTask(gate.GetSelector(),TSwitch_CALL_INT,oldeip); if (type & CPU_INT_HAS_ERROR) { //TODO Be sure about this, seems somewhat unclear if (cpu_tss.is386) CPU_Push32(cpu.exception.error); else CPU_Push16(cpu.exception.error); } return; default: E_Exit("Illegal descriptor type %X for int %X",gate.Type(),num); } } assert(1); return ; // make compiler happy } void CPU_IRET(bool use32,Bitu oldeip) { if (!cpu.pmode) { /* RealMode IRET */ if (use32) { reg_eip=CPU_Pop32(); SegSet16(cs,CPU_Pop32()); CPU_SetFlags(CPU_Pop32(),FMASK_ALL); } else { reg_eip=CPU_Pop16(); SegSet16(cs,CPU_Pop16()); CPU_SetFlags(CPU_Pop16(),FMASK_ALL & 0xffff); } cpu.code.big=false; return; } else { /* Protected mode IRET */ if (reg_flags & FLAG_VM) { if ((reg_flags & FLAG_IOPL)!=FLAG_IOPL) { // win3.x e CPU_Exception(EXCEPTION_GP,0); return; } else { if (use32) { reg_eip=CPU_Pop32(); SegSet16(cs,CPU_Pop32()); /* IOPL can not be modified in v86 mode by IRET */ CPU_SetFlags(CPU_Pop32(),FMASK_NORMAL|FLAG_NT); } else { reg_eip=CPU_Pop16(); SegSet16(cs,CPU_Pop16()); /* IOPL can not be modified in v86 mode by IRET */ CPU_SetFlags(CPU_Pop16(),FMASK_NORMAL|FLAG_NT); } cpu.code.big=false; return; } } /* Check if this is task IRET */ if (GETFLAG(NT)) { if (GETFLAG(VM)) E_Exit("Pmode IRET with VM bit set"); CPU_CHECK_COND(!cpu_tss.IsValid(), "TASK Iret without valid TSS", EXCEPTION_TS,cpu_tss.selector & 0xfffc) if (!cpu_tss.desc.IsBusy()) LOG(LOG_CPU,LOG_ERROR)("TASK Iret:TSS not busy"); Bitu back_link=cpu_tss.Get_back(); CPU_SwitchTask(back_link,TSwitch_IRET,oldeip); return; } Bitu n_cs_sel,n_eip,n_flags; if (use32) { // commit point n_eip=CPU_Pop32(); n_cs_sel=CPU_Pop32() & 0xffff; n_flags=CPU_Pop32(); if ((n_flags & FLAG_VM) && (cpu.cpl==0)) { reg_eip=n_eip & 0xffff; Bitu n_ss,n_esp,n_es,n_ds,n_fs,n_gs; n_esp=CPU_Pop32(); n_ss=CPU_Pop32() & 0xffff; n_es=CPU_Pop32() & 0xffff; n_ds=CPU_Pop32() & 0xffff; n_fs=CPU_Pop32() & 0xffff; n_gs=CPU_Pop32() & 0xffff; CPU_SetFlags(n_flags,FMASK_ALL | FLAG_VM); cpu.cpl=3; CPU_SetSegGeneral(ss,n_ss); CPU_SetSegGeneral(es,n_es); CPU_SetSegGeneral(ds,n_ds); CPU_SetSegGeneral(fs,n_fs); CPU_SetSegGeneral(gs,n_gs); reg_esp=n_esp; cpu.code.big=false; SegSet16(cs,n_cs_sel); LOG(LOG_CPU,LOG_NORMAL)("IRET:Back to V86: CS:%X IP %X SS:%X SP %X FLAGS:%X",SegValue(cs),reg_eip,SegValue(ss),reg_esp,reg_flags); return; } if (n_flags & FLAG_VM) E_Exit("IRET from pmode to v86 with CPL!=0"); } else { n_eip=CPU_Pop16(); n_cs_sel=CPU_Pop16(); n_flags=(reg_flags & 0xffff0000) | CPU_Pop16(); if (n_flags & FLAG_VM) E_Exit("VM Flag in 16-bit iret"); } CPU_CHECK_COND((n_cs_sel & 0xfffc)==0, "IRET:CS selector zero", EXCEPTION_GP,0) Bitu n_cs_rpl=n_cs_sel & 3; Descriptor n_cs_desc; CPU_CHECK_COND(!cpu.gdt.GetDescriptor(n_cs_sel,n_cs_desc), "IRET:CS selector beyond limits", EXCEPTION_GP,n_cs_sel & 0xfffc) CPU_CHECK_COND(n_cs_rpln_cs_rpl, "IRET:C:DPL>RPL", EXCEPTION_GP,n_cs_sel & 0xfffc) break; default: E_Exit("IRET:Illegal descriptor type %X",n_cs_desc.Type()); } CPU_CHECK_COND(!n_cs_desc.saved.seg.p, "IRET with nonpresent code segment", EXCEPTION_NP,n_cs_sel & 0xfffc) if (n_cs_rpl==cpu.cpl) { /* Return to same level */ Segs.phys[cs]=n_cs_desc.GetBase(); cpu.code.big=n_cs_desc.Big()>0; Segs.val[cs]=n_cs_sel; reg_eip=n_eip; Bitu mask=cpu.cpl ? (FMASK_NORMAL | FLAG_NT) : FMASK_ALL; if (GETFLAG_IOPL0; Segs.val[cs]=n_cs_sel; Bitu mask=cpu.cpl ? (FMASK_NORMAL | FLAG_NT) : FMASK_ALL; if (GETFLAG_IOPLdesc.DPL()) CPU_SetSegGeneral(es,0); break; default: break; } cpu.gdt.GetDescriptor(SegValue(ds),desc); switch (desc.Type()) { case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(ds,0); break; default: break; } cpu.gdt.GetDescriptor(SegValue(fs),desc); switch (desc.Type()) { case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(fs,0); break; default: break; } cpu.gdt.GetDescriptor(SegValue(gs),desc); switch (desc.Type()) { case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(gs,0); break; default: break; } LOG(LOG_CPU,LOG_NORMAL)("IRET:Outer level:%X:%X big %d",n_cs_sel,n_eip,cpu.code.big); } return; } } void CPU_JMP(bool use32,Bitu selector,Bitu offset,Bitu oldeip) { if (!cpu.pmode || (reg_flags & FLAG_VM)) { if (!use32) { reg_eip=offset&0xffff; } else { reg_eip=offset; } SegSet16(cs,selector); cpu.code.big=false; return; } else { CPU_CHECK_COND((selector & 0xfffc)==0, "JMP:CS selector zero", EXCEPTION_GP,0) Bitu rpl=selector & 3; Descriptor desc; CPU_CHECK_COND(!cpu.gdt.GetDescriptor(selector,desc), "JMP:CS beyond limits", EXCEPTION_GP,selector & 0xfffc) switch (desc.Type()) { case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: CPU_CHECK_COND(rpl>cpu.cpl, "JMP:NC:RPL>CPL", EXCEPTION_GP,selector & 0xfffc) CPU_CHECK_COND(cpu.cpl!=desc.DPL(), "JMP:NC:RPL != DPL", EXCEPTION_GP,selector & 0xfffc) LOG(LOG_CPU,LOG_NORMAL)("JMP:Code:NC to %X:%X big %d",selector,offset,desc.Big()); goto CODE_jmp; case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA: case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: LOG(LOG_CPU,LOG_NORMAL)("JMP:Code:C to %X:%X big %d",selector,offset,desc.Big()); CPU_CHECK_COND(cpu.cpl0; Segs.val[cs]=(selector & 0xfffc) | cpu.cpl; reg_eip=offset; return; case DESC_386_TSS_A: CPU_CHECK_COND(desc.DPL()cpu.cpl, "CALL:CODE:NC:RPL>CPL", EXCEPTION_GP,selector & 0xfffc) CPU_CHECK_COND(call.DPL()!=cpu.cpl, "CALL:CODE:NC:DPL!=CPL", EXCEPTION_GP,selector & 0xfffc) LOG(LOG_CPU,LOG_NORMAL)("CALL:CODE:NC to %X:%X",selector,offset); goto call_code; case DESC_CODE_N_C_A:case DESC_CODE_N_C_NA: case DESC_CODE_R_C_A:case DESC_CODE_R_C_NA: CPU_CHECK_COND(call.DPL()>cpu.cpl, "CALL:CODE:C:DPL>CPL", EXCEPTION_GP,selector & 0xfffc) LOG(LOG_CPU,LOG_NORMAL)("CALL:CODE:C to %X:%X",selector,offset); call_code: if (!call.saved.seg.p) { // borland extender (RTM) CPU_Exception(EXCEPTION_NP,selector & 0xfffc); return; } // commit point if (!use32) { CPU_Push16(SegValue(cs)); CPU_Push16(oldeip); reg_eip=offset & 0xffff; } else { CPU_Push32(SegValue(cs)); CPU_Push32(oldeip); reg_eip=offset; } Segs.phys[cs]=call.GetBase(); cpu.code.big=call.Big()>0; Segs.val[cs]=(selector & 0xfffc) | cpu.cpl; return; case DESC_386_CALL_GATE: case DESC_286_CALL_GATE: { CPU_CHECK_COND(call.DPL()cpu.cpl, "CALL:Gate:CS DPL>CPL", EXCEPTION_GP,n_cs_sel & 0xfffc) Bitu n_cs_rpl = n_cs_sel & 3; Bitu n_eip = call.GetOffset(); switch (n_cs_desc.Type()) { case DESC_CODE_N_NC_A:case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A:case DESC_CODE_R_NC_NA: /* Check if we goto inner priviledge */ if (n_cs_dpl < cpu.cpl) { CPU_CHECK_COND(!n_cs_desc.saved.seg.p, "CALL:Gate:CS not present", EXCEPTION_NP,n_cs_sel & 0xfffc) /* Get new SS:ESP out of TSS */ Bitu n_ss_sel,n_esp; Descriptor n_ss_desc; cpu_tss.Get_SSx_ESPx(n_cs_dpl,n_ss_sel,n_esp); CPU_CHECK_COND((n_ss_sel & 0xfffc)==0, "CALL:Gate:NC:SS selector zero", EXCEPTION_TS,0) CPU_CHECK_COND(!cpu.gdt.GetDescriptor(n_ss_sel,n_ss_desc), "CALL:Gate:Invalid SS selector", EXCEPTION_TS,n_ss_sel & 0xfffc) CPU_CHECK_COND(((n_ss_sel & 3)!=n_cs_desc.DPL()) || (n_ss_desc.DPL()!=n_cs_desc.DPL()), "CALL:Gate:Invalid SS selector privileges", EXCEPTION_TS,n_ss_sel & 0xfffc) switch (n_ss_desc.Type()) { case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: // writable data segment break; default: E_Exit("Call:Gate:SS no writable data segment"); // or #TS(ss_sel) } CPU_CHECK_COND(!n_ss_desc.saved.seg.p, "CALL:Gate:Stack segment not present", EXCEPTION_SS,n_ss_sel & 0xfffc) /* Load the new SS:ESP and save data on it */ Bitu o_esp = reg_esp; Bitu o_ss = SegValue(ss); PhysPt o_stack = SegPhys(ss)+(reg_esp & cpu.stack.mask); // catch pagefaults if (call.saved.gate.paramcount&31) { if (call.Type()==DESC_386_CALL_GATE) { for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--) mem_readd(o_stack+i*4); } else { for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--) mem_readw(o_stack+i*2); } } // commit point Segs.val[ss]=n_ss_sel; Segs.phys[ss]=n_ss_desc.GetBase(); if (n_ss_desc.Big()) { cpu.stack.big=true; cpu.stack.mask=0xffffffff; reg_esp=n_esp; } else { cpu.stack.big=false; cpu.stack.mask=0xffff; reg_sp=n_esp & 0xffff; } cpu.cpl = n_cs_desc.DPL(); Bit16u oldcs = SegValue(cs); /* Switch to new CS:EIP */ Segs.phys[cs] = n_cs_desc.GetBase(); Segs.val[cs] = (n_cs_sel & 0xfffc) | cpu.cpl; cpu.code.big = n_cs_desc.Big()>0; reg_eip = n_eip; if (!use32) reg_eip&=0xffff; if (call.Type()==DESC_386_CALL_GATE) { CPU_Push32(o_ss); //save old stack CPU_Push32(o_esp); if (call.saved.gate.paramcount&31) for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--) CPU_Push32(mem_readd(o_stack+i*4)); CPU_Push32(oldcs); CPU_Push32(oldeip); } else { CPU_Push16(o_ss); //save old stack CPU_Push16(o_esp); if (call.saved.gate.paramcount&31) for (Bits i=(call.saved.gate.paramcount&31)-1;i>=0;i--) CPU_Push16(mem_readw(o_stack+i*2)); CPU_Push16(oldcs); CPU_Push16(oldeip); } break; } else if (n_cs_dpl > cpu.cpl) E_Exit("CALL:GATE:CS DPL>CPL"); // or #GP(sel) case DESC_CODE_N_C_A:case DESC_CODE_N_C_NA: case DESC_CODE_R_C_A:case DESC_CODE_R_C_NA: // zrdx extender if (call.Type()==DESC_386_CALL_GATE) { CPU_Push32(SegValue(cs)); CPU_Push32(oldeip); } else { CPU_Push16(SegValue(cs)); CPU_Push16(oldeip); } /* Switch to new CS:EIP */ Segs.phys[cs] = n_cs_desc.GetBase(); Segs.val[cs] = (n_cs_sel & 0xfffc) | cpu.cpl; cpu.code.big = n_cs_desc.Big()>0; reg_eip = n_eip; if (!use32) reg_eip&=0xffff; break; default: E_Exit("CALL:GATE:CS no executable segment"); } } /* Call Gates */ break; case DESC_386_TSS_A: CPU_CHECK_COND(call.DPL()cpu.cpl, "RET to C segment of higher privilege", EXCEPTION_GP,selector & 0xfffc) break; default: E_Exit("RET from illegal descriptor type %X",desc.Type()); } RET_same_level: if (!desc.saved.seg.p) { // borland extender (RTM) CPU_Exception(EXCEPTION_NP,selector & 0xfffc); return; } // commit point if (!use32) { offset=CPU_Pop16(); selector=CPU_Pop16(); } else { offset=CPU_Pop32(); selector=CPU_Pop32() & 0xffff; } Segs.phys[cs]=desc.GetBase(); cpu.code.big=desc.Big()>0; Segs.val[cs]=selector; reg_eip=offset; if (cpu.stack.big) { reg_esp+=bytes; } else { reg_sp+=bytes; } LOG(LOG_CPU,LOG_NORMAL)("RET - Same level to %X:%X RPL %X DPL %X",selector,offset,rpl,desc.DPL()); return; } else { /* Return to outer level */ switch (desc.Type()) { case DESC_CODE_N_NC_A:case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A:case DESC_CODE_R_NC_NA: CPU_CHECK_COND(desc.DPL()!=rpl, "RET to outer NC segment with DPL!=RPL", EXCEPTION_GP,selector & 0xfffc) break; case DESC_CODE_N_C_A:case DESC_CODE_N_C_NA: case DESC_CODE_R_C_A:case DESC_CODE_R_C_NA: CPU_CHECK_COND(desc.DPL()>rpl, "RET to outer C segment with DPL>RPL", EXCEPTION_GP,selector & 0xfffc) break; default: E_Exit("RET from illegal descriptor type %X",desc.Type()); // or #GP(selector) } CPU_CHECK_COND(!desc.saved.seg.p, "RET:Outer level:CS not present", EXCEPTION_NP,selector & 0xfffc) // commit point Bitu n_esp,n_ss; if (use32) { offset=CPU_Pop32(); selector=CPU_Pop32() & 0xffff; reg_esp+=bytes; n_esp = CPU_Pop32(); n_ss = CPU_Pop32() & 0xffff; } else { offset=CPU_Pop16(); selector=CPU_Pop16(); reg_esp+=bytes; n_esp = CPU_Pop16(); n_ss = CPU_Pop16(); } CPU_CHECK_COND((n_ss & 0xfffc)==0, "RET to outer level with SS selector zero", EXCEPTION_GP,0) Descriptor n_ss_desc; CPU_CHECK_COND(!cpu.gdt.GetDescriptor(n_ss,n_ss_desc), "RET:SS beyond limits", EXCEPTION_GP,n_ss & 0xfffc) CPU_CHECK_COND(((n_ss & 3)!=rpl) || (n_ss_desc.DPL()!=rpl), "RET to outer segment with invalid SS privileges", EXCEPTION_GP,n_ss & 0xfffc) switch (n_ss_desc.Type()) { case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: break; default: E_Exit("RET:SS selector type no writable data segment"); // or #GP(selector) } CPU_CHECK_COND(!n_ss_desc.saved.seg.p, "RET:Stack segment not present", EXCEPTION_SS,n_ss & 0xfffc) cpu.cpl = rpl; Segs.phys[cs]=desc.GetBase(); cpu.code.big=desc.Big()>0; Segs.val[cs]=(selector&0xfffc) | cpu.cpl; reg_eip=offset; Segs.val[ss]=n_ss; Segs.phys[ss]=n_ss_desc.GetBase(); if (n_ss_desc.Big()) { cpu.stack.big=true; cpu.stack.mask=0xffffffff; reg_esp=n_esp+bytes; } else { cpu.stack.big=false; cpu.stack.mask=0xffff; reg_sp=(n_esp & 0xffff)+bytes; } Descriptor desc; cpu.gdt.GetDescriptor(SegValue(es),desc); switch (desc.Type()) { case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(es,0); break; default: break; } cpu.gdt.GetDescriptor(SegValue(ds),desc); switch (desc.Type()) { case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(ds,0); break; default: break; } cpu.gdt.GetDescriptor(SegValue(fs),desc); switch (desc.Type()) { case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(fs,0); break; default: break; } cpu.gdt.GetDescriptor(SegValue(gs),desc); switch (desc.Type()) { case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: if (cpu.cpl>desc.DPL()) CPU_SetSegGeneral(gs,0); break; default: break; } // LOG(LOG_MISC,LOG_ERROR)("RET - Higher level to %X:%X RPL %X DPL %X",selector,offset,rpl,desc.DPL()); return; } LOG(LOG_CPU,LOG_NORMAL)("Prot ret %X:%X",selector,offset); return; } assert(1); } void CPU_SLDT(Bitu & selector) { selector=cpu.gdt.SLDT(); } bool CPU_LLDT(Bitu selector) { if (!cpu.gdt.LLDT(selector)) { LOG(LOG_CPU,LOG_ERROR)("LLDT failed, selector=%X",selector); return true; } LOG(LOG_CPU,LOG_NORMAL)("LDT Set to %X",selector); return false; } void CPU_STR(Bitu & selector) { selector=cpu_tss.selector; } bool CPU_LTR(Bitu selector) { if ((selector & 0xfffc)==0) { cpu_tss.SetSelector(selector); return false; } TSS_Descriptor desc; if ((selector & 4) || (!cpu.gdt.GetDescriptor(selector,desc))) { LOG(LOG_CPU,LOG_ERROR)("LTR failed, selector=%X",selector); return CPU_PrepareException(EXCEPTION_GP,selector); } if ((desc.Type()==DESC_286_TSS_A) || (desc.Type()==DESC_386_TSS_A)) { if (!desc.saved.seg.p) { LOG(LOG_CPU,LOG_ERROR)("LTR failed, selector=%X (not present)",selector); return CPU_PrepareException(EXCEPTION_NP,selector); } if (!cpu_tss.SetSelector(selector)) E_Exit("LTR failed, selector=%X",selector); cpu_tss.desc.SetBusy(true); } else { /* Descriptor was no available TSS descriptor */ LOG(LOG_CPU,LOG_NORMAL)("LTR failed, selector=%X (type=%X)",selector,desc.Type()); return CPU_PrepareException(EXCEPTION_GP,selector); } return false; } Bitu gdt_count=0; void CPU_LGDT(Bitu limit,Bitu base) { LOG(LOG_CPU,LOG_NORMAL)("GDT Set to base:%X limit:%X count %d",base,limit,gdt_count++); cpu.gdt.SetLimit(limit); cpu.gdt.SetBase(base); // if (gdt_count>20) DEBUG_EnableDebugger(); // DEBUG_EnableDebugger(); } void CPU_LIDT(Bitu limit,Bitu base) { LOG(LOG_CPU,LOG_NORMAL)("IDT Set to base:%X limit:%X",base,limit); cpu.idt.SetLimit(limit); cpu.idt.SetBase(base); } void CPU_SGDT(Bitu & limit,Bitu & base) { limit=cpu.gdt.GetLimit(); base=cpu.gdt.GetBase(); } void CPU_SIDT(Bitu & limit,Bitu & base) { limit=cpu.idt.GetLimit(); base=cpu.idt.GetBase(); } void CPU_SET_CRX(Bitu cr,Bitu value) { switch (cr) { case 0: { Bitu changed=cpu.cr0 ^ value; if (!changed) return; cpu.cr0=value; if (value & CR0_PROTECTION) { cpu.pmode=true; LOG(LOG_CPU,LOG_NORMAL)("Protected mode"); PAGING_Enable((value & CR0_PAGING)>0); } else { cpu.pmode=false; if (value & CR0_PAGING) LOG_MSG("Paging requested without PE=1"); PAGING_Enable(false); LOG(LOG_CPU,LOG_NORMAL)("Real mode"); } break; } case 2: paging.cr2=value; break; case 3: PAGING_SetDirBase(value); break; default: LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV CR%d,%X",cr,value); break; } } bool CPU_WRITE_CRX(Bitu cr,Bitu value) { /* Check if privileged to access control registers */ if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0); if ((cr==1) || (cr>4)) return CPU_PrepareException(EXCEPTION_UD,0); CPU_SET_CRX(cr,value); return false; } Bitu CPU_GET_CRX(Bitu cr) { switch (cr) { case 0: return cpu.cr0; case 2: return paging.cr2; case 3: return PAGING_GetDirBase() & 0xfffff000; default: LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV XXX, CR%d",cr); break; } return 0; } bool CPU_READ_CRX(Bitu cr,Bit32u & retvalue) { /* Check if privileged to access control registers */ if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0); if ((cr==1) || (cr>4)) return CPU_PrepareException(EXCEPTION_UD,0); retvalue=CPU_GET_CRX(cr); return false; } bool CPU_WRITE_DRX(Bitu dr,Bitu value) { /* Check if privileged to access control registers */ if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0); switch (dr) { case 0: case 1: case 2: case 3: cpu.drx[dr]=value; break; case 4: case 6: cpu.drx[6]=(value|0xffff0ff0) & 0xffffefff; break; case 5: case 7: cpu.drx[7]=(value|0x400) & 0xffff2fff; break; default: LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV DR%d,%X",dr,value); break; } return false; } bool CPU_READ_DRX(Bitu dr,Bit32u & retvalue) { /* Check if privileged to access control registers */ if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0); switch (dr) { case 0: case 1: case 2: case 3: case 6: case 7: retvalue=cpu.drx[dr]; break; case 4: retvalue=cpu.drx[6]; break; case 5: retvalue=cpu.drx[7]; break; default: LOG(LOG_CPU,LOG_ERROR)("Unhandled MOV XXX, DR%d",dr); retvalue=0; break; } return false; } void CPU_SMSW(Bitu & word) { word=cpu.cr0; } Bitu CPU_LMSW(Bitu word) { if (cpu.pmode && (cpu.cpl>0)) return CPU_PrepareException(EXCEPTION_GP,0); word&=0xf; if (cpu.cr0 & 1) word|=1; word|=(cpu.cr0&0xfffffff0); CPU_SET_CRX(0,word); return false; } void CPU_ARPL(Bitu & dest_sel,Bitu src_sel) { if ((dest_sel & 3) < (src_sel & 3)) { dest_sel=(dest_sel & 0xfffc) + (src_sel & 3); // dest_sel|=0xff3f0000; SETFLAGBIT(ZF,true); } else { SETFLAGBIT(ZF,false); } } void CPU_LAR(Bitu selector,Bitu & ar) { if (selector == 0) { SETFLAGBIT(ZF,false); return; } Descriptor desc;Bitu rpl=selector & 3; if (!cpu.gdt.GetDescriptor(selector,desc)){ SETFLAGBIT(ZF,false); return; } switch (desc.Type()){ case DESC_CODE_N_C_A: case DESC_CODE_N_C_NA: case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: break; case DESC_286_INT_GATE: case DESC_286_TRAP_GATE: { case DESC_386_INT_GATE: case DESC_386_TRAP_GATE: SETFLAGBIT(ZF,false); return; } case DESC_LDT: case DESC_TASK_GATE: case DESC_286_TSS_A: case DESC_286_TSS_B: case DESC_286_CALL_GATE: case DESC_386_TSS_A: case DESC_386_TSS_B: case DESC_386_CALL_GATE: case DESC_DATA_EU_RO_NA: case DESC_DATA_EU_RO_A: case DESC_DATA_EU_RW_NA: case DESC_DATA_EU_RW_A: case DESC_DATA_ED_RO_NA: case DESC_DATA_ED_RO_A: case DESC_DATA_ED_RW_NA: case DESC_DATA_ED_RW_A: case DESC_CODE_N_NC_A: case DESC_CODE_N_NC_NA: case DESC_CODE_R_NC_A: case DESC_CODE_R_NC_NA: if (desc.DPL()desc.DPL()) || (cpu.cpl>desc.DPL())) { // extreme pinball return CPU_PrepareException(EXCEPTION_GP,value & 0xfffc); } break; case DESC_CODE_R_C_A: case DESC_CODE_R_C_NA: break; default: // gabriel knight return CPU_PrepareException(EXCEPTION_GP,value & 0xfffc); } if (!desc.saved.seg.p) { // win return CPU_PrepareException(EXCEPTION_NP,value & 0xfffc); } Segs.val[seg]=value; Segs.phys[seg]=desc.GetBase(); } return false; } } bool CPU_PopSeg(SegNames seg,bool use32) { Bitu val=mem_readw(SegPhys(ss) + (reg_esp & cpu.stack.mask)); if (CPU_SetSegGeneral(seg,val)) return true; Bitu addsp=use32?0x04:0x02; reg_esp=(reg_esp&~cpu.stack.mask)|((reg_esp+addsp)&cpu.stack.mask); return false; } void CPU_CPUID(void) { switch (reg_eax) { case 0: /* Vendor ID String and maximum level? */ reg_eax=1; /* Maximum level */ reg_ebx='G' | ('e' << 8) | ('n' << 16) | ('u'<< 24); reg_edx='i' | ('n' << 8) | ('e' << 16) | ('I'<< 24); reg_ecx='n' | ('t' << 8) | ('e' << 16) | ('l'<< 24); break; case 1: /* get processor type/family/model/stepping and feature flags */ reg_eax=0x402; /* intel 486 sx? */ reg_ebx=0; /* Not Supported */ reg_ecx=0; /* No features */ reg_edx=1; /* FPU */ break; default: LOG(LOG_CPU,LOG_ERROR)("Unhandled CPUID Function %x",reg_eax); break; } } static Bits HLT_Decode(void) { /* Once an interrupt occurs, it should change cpu core */ if (reg_eip!=cpu.hlt.eip || SegValue(cs) != cpu.hlt.cs) { cpudecoder=cpu.hlt.old_decoder; } else { CPU_Cycles=0; } return 0; } void CPU_HLT(Bitu oldeip) { reg_eip=oldeip; CPU_Cycles=0; cpu.hlt.cs=SegValue(cs); cpu.hlt.eip=reg_eip; cpu.hlt.old_decoder=cpudecoder; cpudecoder=&HLT_Decode; } void CPU_ENTER(bool use32,Bitu bytes,Bitu level) { level&=0x1f; Bitu sp_index=reg_esp&cpu.stack.mask; Bitu bp_index=reg_ebp&cpu.stack.mask; if (!use32) { sp_index-=2; mem_writew(SegPhys(ss)+sp_index,reg_bp); reg_bp=(Bit16u)(reg_esp-2); if (level) { for (Bitu i=1;i(configuration); reg_eax=0; reg_ebx=0; reg_ecx=0; reg_edx=0; reg_edi=0; reg_esi=0; reg_ebp=0; reg_esp=0; SegSet16(cs,0); SegSet16(ds,0); SegSet16(es,0); SegSet16(fs,0); SegSet16(gs,0); SegSet16(ss,0); CPU_SetFlags(FLAG_IF,FMASK_ALL); //Enable interrupts cpu.cr0=0xffffffff; CPU_SET_CRX(0,0); //Initialize cpu.code.big=false; cpu.stack.mask=0xffff; cpu.stack.big=false; cpu.idt.SetBase(0); cpu.idt.SetLimit(1023); for (Bitu i=0; i<7; i++) cpu.drx[i]=0; cpu.drx[6]=0xffff1ff0; cpu.drx[7]=0x00000400; /* Init the cpu cores */ CPU_Core_Normal_Init(); CPU_Core_Simple_Init(); CPU_Core_Full_Init(); #if (C_DYNAMIC_X86) CPU_Core_Dyn_X86_Init(); #endif MAPPER_AddHandler(CPU_CycleDecrease,MK_f11,MMOD1,"cycledown","Dec Cycles"); MAPPER_AddHandler(CPU_CycleIncrease,MK_f12,MMOD1,"cycleup" ,"Inc Cycles"); Change_Config(configuration); CPU_JMP(false,0,0,0); //Setup the first cpu core } bool Change_Config(Section* newconfig){ Section_prop * section=static_cast(newconfig); CPU_CycleLeft=0;//needed ? CPU_Cycles=0; CPU_CycleMax=section->Get_int("cycles");; CPU_CycleUp=section->Get_int("cycleup"); CPU_CycleDown=section->Get_int("cycledown"); const char * core=section->Get_string("core"); cpudecoder=&CPU_Core_Normal_Run; if (!strcasecmp(core,"normal")) { cpudecoder=&CPU_Core_Normal_Run; } else if (!strcasecmp(core,"simple")) { cpudecoder=&CPU_Core_Simple_Run; } else if (!strcasecmp(core,"full")) { cpudecoder=&CPU_Core_Full_Run; } #if (C_DYNAMIC_X86) else if (!strcasecmp(core,"dynamic")) { cpudecoder=&CPU_Core_Dyn_X86_Run; } #endif else { LOG_MSG("CPU:Unknown core type %s, switcing back to normal.",core); } if(CPU_CycleMax <= 0) CPU_CycleMax = 2500; if(CPU_CycleUp <= 0) CPU_CycleUp = 500; if(CPU_CycleDown <= 0) CPU_CycleDown = 20; GFX_SetTitle(CPU_CycleMax,-1,false); return true; } ~CPU(){ /* empty */}; }; static CPU * test; void CPU_ShutDown(Section* sec) { delete test; } void CPU_Init(Section* sec) { test = new CPU(sec); sec->AddDestroyFunction(&CPU_ShutDown,true); } //initialize static members bool CPU::inited=false;