Index: . =================================================================== --- . (révision 59666) +++ . (copie de travail) Modification de propriétés sur . ___________________________________________________________________ Modified: svn:mergeinfo Fusionné /branches/ntvdm:r59241-59666 Index: dll/win32/kernel32/client/proc.c =================================================================== --- dll/win32/kernel32/client/proc.c (révision 59666) +++ dll/win32/kernel32/client/proc.c (copie de travail) @@ -49,9 +49,11 @@ RegisterWaitForInputIdle(WaitForInputIdleType lpfnRegisterWaitForInputIdle); #define CMD_STRING L"cmd /c " +#define NTVDM_STRING L"\\ntvdm.exe" /* FUNCTIONS ****************************************************************/ +// NOTE: Code duplicated from BasepDuplicateAndWriteHandle VOID WINAPI StuffStdHandle(IN HANDLE ProcessHandle, @@ -60,35 +62,31 @@ { NTSTATUS Status; HANDLE DuplicatedHandle; - SIZE_T NumberOfBytesWritten; + SIZE_T Dummy; - /* If there is no handle to duplicate, return immediately */ - if (!StandardHandle) return; - /* Duplicate the handle */ Status = NtDuplicateObject(NtCurrentProcess(), StandardHandle, ProcessHandle, &DuplicatedHandle, - 0, - 0, - DUPLICATE_SAME_ACCESS | - DUPLICATE_SAME_ATTRIBUTES); - if (!NT_SUCCESS(Status)) return; - - /* Write it */ - NtWriteVirtualMemory(ProcessHandle, - Address, - &DuplicatedHandle, - sizeof(HANDLE), - &NumberOfBytesWritten); + 0, 0, + DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES); + if (NT_SUCCESS(Status)) + { + /* Write it */ + NtWriteVirtualMemory(ProcessHandle, + Address, + &DuplicatedHandle, + sizeof(HANDLE), + &Dummy); + } } BOOLEAN WINAPI -BuildSubSysCommandLine(IN LPCWSTR SubsystemName, - IN LPCWSTR ApplicationName, - IN LPCWSTR CommandLine, +BuildSubSysCommandLine(IN LPWSTR SubsystemName, + IN LPWSTR ApplicationName, + IN LPWSTR CommandLine, OUT PUNICODE_STRING SubsysCommandLine) { UNICODE_STRING CommandLineString, ApplicationNameString; @@ -187,9 +185,9 @@ NTSTATUS WINAPI -BasepIsProcessAllowed(IN LPWSTR ApplicationName) +BasepIsProcessAllowed(IN PCHAR ApplicationName) { - NTSTATUS Status, Status1; + NTSTATUS Status; PWCHAR Buffer; UINT Length; HMODULE TrustLibrary; @@ -253,22 +251,19 @@ else { /* Other systems have a registry entry for this */ - Status1 = NtOpenKey(&KeyHandle, KEY_READ, &KeyAttributes); - if (NT_SUCCESS(Status1)) + Status = NtOpenKey(&KeyHandle, KEY_READ, &KeyAttributes); + if (NT_SUCCESS(Status)) { /* Close it, we'll query it through Rtl */ NtClose(KeyHandle); /* Do the query, which will call a special callback */ - Status = RtlQueryRegistryValues(RTL_REGISTRY_CONTROL, + Status = RtlQueryRegistryValues(2, L"Session Manager", BasepAppCertTable, - NULL, - NULL); - if (Status == STATUS_OBJECT_NAME_NOT_FOUND) - { - Status = STATUS_SUCCESS; - } + 0, + 0); + if (Status == 0xC0000034) Status = STATUS_SUCCESS; } } @@ -525,6 +520,237 @@ return STATUS_SUCCESS; } +/* + * Creates the first Thread in a Proces + */ +HANDLE +WINAPI +BasepCreateFirstThread(HANDLE ProcessHandle, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + PSECTION_IMAGE_INFORMATION SectionImageInfo, + PCLIENT_ID ClientId, + DWORD dwCreationFlags) +{ + NTSTATUS Status; + OBJECT_ATTRIBUTES LocalObjectAttributes; + POBJECT_ATTRIBUTES ObjectAttributes; + CONTEXT Context; + INITIAL_TEB InitialTeb; + HANDLE hThread; + BASE_API_MESSAGE ApiMessage; + PBASE_CREATE_PROCESS CreateProcessRequest = &ApiMessage.Data.CreateProcessRequest; + + DPRINT("BasepCreateFirstThread. hProcess: %lx\n", ProcessHandle); + + /* Create the Thread's Stack */ + BaseCreateStack(ProcessHandle, + SectionImageInfo->MaximumStackSize, + SectionImageInfo->CommittedStackSize, + &InitialTeb); + + /* Create the Thread's Context */ + BaseInitializeContext(&Context, + NtCurrentPeb(), + SectionImageInfo->TransferAddress, + InitialTeb.StackBase, + 0); + + /* Convert the thread attributes */ + ObjectAttributes = BaseFormatObjectAttributes(&LocalObjectAttributes, + lpThreadAttributes, + NULL); + + /* Create the Kernel Thread Object */ + Status = NtCreateThread(&hThread, + THREAD_ALL_ACCESS, + ObjectAttributes, + ProcessHandle, + ClientId, + &Context, + &InitialTeb, + TRUE); + if (!NT_SUCCESS(Status)) + { + return NULL; + } + + /* Fill out the request to notify CSRSS */ + CreateProcessRequest->ClientId = *ClientId; + CreateProcessRequest->ProcessHandle = ProcessHandle; + CreateProcessRequest->ThreadHandle = hThread; + CreateProcessRequest->CreationFlags = dwCreationFlags; + + /* + * For GUI applications we turn on the 2nd bit. This also allows + * us to know whether or not this is a GUI or a TUI application. + */ + if (IMAGE_SUBSYSTEM_WINDOWS_GUI == SectionImageInfo->SubSystemType) + { + CreateProcessRequest->ProcessHandle = (HANDLE) + ((ULONG_PTR)CreateProcessRequest->ProcessHandle | 2); + } + + /* Call CSR */ + Status = CsrClientCallServer((PCSR_API_MESSAGE)&ApiMessage, + NULL, + CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, BasepCreateProcess), + sizeof(BASE_CREATE_PROCESS)); + if (!NT_SUCCESS(Status)) + { + DPRINT1("Failed to tell CSRSS about new process: %lx\n", Status); + return NULL; + } + + /* Success */ + return hThread; +} + +/* + * Converts ANSI to Unicode Environment + */ +PVOID +WINAPI +BasepConvertUnicodeEnvironment(OUT SIZE_T* EnvSize, + IN PVOID lpEnvironment) +{ + PCHAR pcScan; + ANSI_STRING AnsiEnv; + UNICODE_STRING UnicodeEnv; + NTSTATUS Status; + + DPRINT("BasepConvertUnicodeEnvironment\n"); + + /* Scan the environment to calculate its Unicode size */ + AnsiEnv.Buffer = pcScan = (PCHAR)lpEnvironment; + while (*pcScan) + { + pcScan += strlen(pcScan) + 1; + } + + /* Create our ANSI String */ + if (pcScan == (PCHAR)lpEnvironment) + { + AnsiEnv.Length = 2 * sizeof(CHAR); + } + else + { + + AnsiEnv.Length = (USHORT)((ULONG_PTR)pcScan - (ULONG_PTR)lpEnvironment + sizeof(CHAR)); + } + AnsiEnv.MaximumLength = AnsiEnv.Length + 1; + + /* Allocate memory for the Unicode Environment */ + UnicodeEnv.Buffer = NULL; + *EnvSize = AnsiEnv.MaximumLength * sizeof(WCHAR); + Status = NtAllocateVirtualMemory(NtCurrentProcess(), + (PVOID)&UnicodeEnv.Buffer, + 0, + EnvSize, + MEM_COMMIT, + PAGE_READWRITE); + /* Failure */ + if (!NT_SUCCESS(Status)) + { + SetLastError(Status); + *EnvSize = 0; + return NULL; + } + + /* Use the allocated size */ + UnicodeEnv.MaximumLength = (USHORT)*EnvSize; + + /* Convert */ + RtlAnsiStringToUnicodeString(&UnicodeEnv, &AnsiEnv, FALSE); + return UnicodeEnv.Buffer; +} + +/* + * Converts a Win32 Priority Class to NT + */ +ULONG +WINAPI +BasepConvertPriorityClass(IN ULONG dwCreationFlags) +{ + ULONG ReturnClass; + + if(dwCreationFlags & IDLE_PRIORITY_CLASS) + { + ReturnClass = PROCESS_PRIORITY_CLASS_IDLE; + } + else if(dwCreationFlags & BELOW_NORMAL_PRIORITY_CLASS) + { + ReturnClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL; + } + else if(dwCreationFlags & NORMAL_PRIORITY_CLASS) + { + ReturnClass = PROCESS_PRIORITY_CLASS_NORMAL; + } + else if(dwCreationFlags & ABOVE_NORMAL_PRIORITY_CLASS) + { + ReturnClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL; + } + else if(dwCreationFlags & HIGH_PRIORITY_CLASS) + { + ReturnClass = PROCESS_PRIORITY_CLASS_HIGH; + } + else if(dwCreationFlags & REALTIME_PRIORITY_CLASS) + { + /* Check for Privilege First */ + if (BasepIsRealtimeAllowed(TRUE)) + { + ReturnClass = PROCESS_PRIORITY_CLASS_REALTIME; + } + else + { + ReturnClass = PROCESS_PRIORITY_CLASS_HIGH; + } + } + else + { + ReturnClass = PROCESS_PRIORITY_CLASS_INVALID; + } + + return ReturnClass; +} + +/* + * Duplicates a standard handle and writes it where requested. + */ +// NOTE: Code duplicated from StuffStdHandle +VOID +WINAPI +BasepDuplicateAndWriteHandle(IN HANDLE ProcessHandle, + IN HANDLE StandardHandle, + IN PHANDLE Address) +{ + NTSTATUS Status; + HANDLE DuplicatedHandle; + SIZE_T Dummy; + + DPRINT("BasepDuplicateAndWriteHandle. hProcess: %lx, Handle: %lx," + "Address: %p\n", ProcessHandle, StandardHandle, Address); + + /* Don't touch Console Handles */ + if (IsConsoleHandle(StandardHandle)) return; + + /* Duplicate the handle */ + Status = NtDuplicateObject(NtCurrentProcess(), + StandardHandle, + ProcessHandle, + &DuplicatedHandle, + 0, 0, + DUPLICATE_SAME_ACCESS | DUPLICATE_SAME_ATTRIBUTES); + if (NT_SUCCESS(Status)) + { + /* Write it */ + NtWriteVirtualMemory(ProcessHandle, + Address, + &DuplicatedHandle, + sizeof(HANDLE), + &Dummy); + } +} + BOOLEAN WINAPI BasePushProcessParameters(IN ULONG ParameterFlags, @@ -629,8 +855,6 @@ /* Create the Parameter Block */ ProcessParameters = NULL; - DPRINT1("Image Name: %wZ Dll Path: %wZ current directory: %wZ, CmdLine: %wZ, Title: %wZ, Desktop: %wZ, Shell: %wZ, Runtime: %wZ\n", - &ImageName, &DllPath, &CurrentDirectory, &CommandLine, &Title, &Desktop, &Shell, &Runtime); Status = RtlCreateProcessParameters(&ProcessParameters, &ImageName, &DllPath, @@ -769,16 +993,16 @@ ProcessParameters->ConsoleFlags = 1; } - /* Check if there's a .local file present */ + /* See if the first 1MB should be reserved */ if (ParameterFlags & 1) { - ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_LOCAL_DLL_PATH; + ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_1MB; } - /* Check if we failed to open the IFEO key */ + /* See if the first 16MB should be reserved */ if (ParameterFlags & 2) { - ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_IMAGE_KEY_MISSING; + ProcessParameters->Flags |= RTL_USER_PROCESS_PARAMETERS_RESERVE_16MB; } /* Allocate memory for the parameter block */ @@ -872,7 +1096,7 @@ if (ProcessParameters) RtlDestroyProcessParameters(ProcessParameters); return Result; FailPath: - DPRINT1("Failure to create process parameters: %lx\n", Status); + DPRINT1("Failure to create proecss parameters: %lx\n", Status); BaseSetLastNTError(Status); Result = FALSE; goto Quickie; @@ -2257,1570 +2481,548 @@ return FALSE; } - -#define AddToHandle(x,y) (x) = (HANDLE)((ULONG_PTR)(x) | (y)); -#define RemoveFromHandle(x,y) (x) = (HANDLE)((ULONG_PTR)(x) & ~(y)); -C_ASSERT(PROCESS_PRIORITY_CLASS_REALTIME == (PROCESS_PRIORITY_CLASS_HIGH + 1)); - /* * @implemented */ BOOL WINAPI -CreateProcessInternalW(IN HANDLE hUserToken, - IN LPCWSTR lpApplicationName, - IN LPWSTR lpCommandLine, - IN LPSECURITY_ATTRIBUTES lpProcessAttributes, - IN LPSECURITY_ATTRIBUTES lpThreadAttributes, - IN BOOL bInheritHandles, - IN DWORD dwCreationFlags, - IN LPVOID lpEnvironment, - IN LPCWSTR lpCurrentDirectory, - IN LPSTARTUPINFOW lpStartupInfo, - IN LPPROCESS_INFORMATION lpProcessInformation, - OUT PHANDLE hNewToken) +CreateProcessInternalW(HANDLE hToken, + LPCWSTR lpApplicationName, + LPWSTR lpCommandLine, + LPSECURITY_ATTRIBUTES lpProcessAttributes, + LPSECURITY_ATTRIBUTES lpThreadAttributes, + BOOL bInheritHandles, + DWORD dwCreationFlags, + LPVOID lpEnvironment, + LPCWSTR lpCurrentDirectory, + LPSTARTUPINFOW lpStartupInfo, + LPPROCESS_INFORMATION lpProcessInformation, + PHANDLE hNewToken) { - // - // Core variables used for creating the initial process and thread - // - SECURITY_ATTRIBUTES LocalThreadAttributes, LocalProcessAttributes; + NTSTATUS Status; + PROCESS_PRIORITY_CLASS PriorityClass; + BOOLEAN FoundQuotes = FALSE; + BOOLEAN QuotesNeeded = FALSE; + BOOLEAN CmdLineIsAppName = FALSE; + UNICODE_STRING ApplicationName = { 0, 0, NULL }; OBJECT_ATTRIBUTES LocalObjectAttributes; POBJECT_ATTRIBUTES ObjectAttributes; - SECTION_IMAGE_INFORMATION ImageInformation; - IO_STATUS_BLOCK IoStatusBlock; + HANDLE hSection = NULL, hProcess = NULL, hThread = NULL, hDebug = NULL; + SECTION_IMAGE_INFORMATION SectionImageInfo; + LPWSTR CurrentDirectory = NULL; + LPWSTR CurrentDirectoryPart; + PROCESS_BASIC_INFORMATION ProcessBasicInfo; + STARTUPINFOW StartupInfo; + ULONG Dummy; + LPWSTR BatchCommandLine; + ULONG CmdLineLength; + UNICODE_STRING CommandLineString; + PWCHAR Extension; + LPWSTR QuotedCmdLine = NULL; + LPWSTR ScanString; + LPWSTR NullBuffer = NULL; + LPWSTR NameBuffer = NULL; + WCHAR SaveChar = 0; + ULONG RetVal; + UINT Error = 0; + UINT Length; + BOOLEAN SearchDone = FALSE; + BOOLEAN Escape = FALSE; CLIENT_ID ClientId; - ULONG NoWindow, RegionSize, StackSize, ImageMachine, ErrorCode, Flags; - ULONG ParameterFlags, PrivilegeValue, HardErrorMode, ErrorResponse; - ULONG_PTR ErrorParameters[2]; - BOOLEAN InJob, SaferNeeded, UseLargePages, HavePrivilege; - BOOLEAN QuerySection, SkipSaferAndAppCompat; - CONTEXT Context; - BASE_API_MESSAGE CsrMsg; - PBASE_CREATE_PROCESS CreateProcessMsg; - PCSR_CAPTURE_BUFFER CaptureBuffer; - PVOID BaseAddress, PrivilegeState, RealTimePrivilegeState; - HANDLE DebugHandle, TokenHandle, JobHandle, KeyHandle, ThreadHandle; - HANDLE FileHandle, SectionHandle, ProcessHandle; - ULONG ResumeCount; - PROCESS_PRIORITY_CLASS PriorityClass; - NTSTATUS Status, Status1, ImageDbgStatus; - PPEB Peb, RemotePeb; - PTEB Teb; - INITIAL_TEB InitialTeb; - PVOID TibValue; - PIMAGE_NT_HEADERS NtHeaders; - STARTUPINFOW StartupInfo; - PRTL_USER_PROCESS_PARAMETERS ProcessParameters; - UNICODE_STRING DebuggerString; - BOOL Result; - // - // Variables used for command-line and argument parsing - // - PCHAR pcScan; - SIZE_T n; - WCHAR SaveChar; - ULONG Length, CurdirLength, CmdQuoteLength; - ULONG CmdLineLength, ResultSize; - PWCHAR QuotedCmdLine, AnsiCmdCommand, ExtBuffer, CurrentDirectory; - PWCHAR NullBuffer, ScanString, NameBuffer, SearchPath, DebuggerCmdLine; - ANSI_STRING AnsiEnv; - UNICODE_STRING UnicodeEnv, PathName; - BOOLEAN SearchRetry, QuotesNeeded, CmdLineIsAppName, HasQuotes; + PPEB OurPeb = NtCurrentPeb(); + PPEB RemotePeb; + SIZE_T EnvSize = 0; + BOOL Ret = FALSE; + WCHAR VdmPath[MAX_PATH]; - // - // Variables used for Fusion/SxS (Side-by-Side Assemblies) - // - RTL_PATH_TYPE SxsPathType, PathType; -#if _SXS_SUPPORT_ENABLED_ - PRTL_BUFFER ByteBuffer; - PRTL_UNICODE_STRING_BUFFER ThisBuffer, Buffer, SxsStaticBuffers[5]; - PRTL_UNICODE_STRING_BUFFER* BufferHead, SxsStringBuffer; - RTL_UNICODE_STRING_BUFFER SxsWin32ManifestPath, SxsNtManifestPath; - RTL_UNICODE_STRING_BUFFER SxsWin32PolicyPath, SxsNtPolicyPath; - RTL_UNICODE_STRING_BUFFER SxsWin32AssemblyDirectory; - BASE_MSG_SXS_HANDLES MappedHandles, Handles, FileHandles; - PVOID CapturedStrings[3]; - SXS_WIN32_NT_PATH_PAIR ExePathPair, ManifestPathPair, PolicyPathPair; - SXS_OVERRIDE_MANIFEST OverrideMannifest; - UNICODE_STRING FreeString, SxsNtExePath; - PWCHAR SxsConglomeratedBuffer, StaticBuffer; - ULONG ConglomeratedBufferSizeBytes, StaticBufferSize, i; -#endif - ULONG FusionFlags; + /* FIXME should process + * HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options + * key (see http://blogs.msdn.com/oldnewthing/archive/2005/12/19/505449.aspx) + */ - // - // Variables used for path conversion (and partially Fusion/SxS) - // - PWCHAR FilePart, PathBuffer, FreeBuffer; - BOOLEAN TranslationStatus; - RTL_RELATIVE_NAME_U SxsWin32RelativePath; - UNICODE_STRING PathBufferString, SxsWin32ExePath; + DPRINT("CreateProcessW: lpApplicationName: %S lpCommandLine: %S" + " lpEnvironment: %p lpCurrentDirectory: %S dwCreationFlags: %lx\n", + lpApplicationName, lpCommandLine, lpEnvironment, lpCurrentDirectory, + dwCreationFlags); - // - // Variables used by Application Compatibility (and partially Fusion/SxS) - // - PVOID AppCompatSxsData, AppCompatData; - ULONG AppCompatSxsDataSize, AppCompatDataSize; - // - // Variables used by VDM (Virtual Dos Machine) and WOW32 (16-bit Support) - // - ULONG BinarySubType, VdmBinaryType, VdmTask, VdmReserve; - ULONG VdmUndoLevel; - BOOLEAN UseVdmReserve; - HANDLE VdmWaitObject; - ANSI_STRING VdmAnsiEnv; - UNICODE_STRING VdmString, VdmUnicodeEnv; - BOOLEAN IsWowApp; - PBASE_CHECK_VDM VdmMsg; - - /* Zero out the initial core variables and handles */ - QuerySection = FALSE; - InJob = FALSE; - SkipSaferAndAppCompat = FALSE; - ParameterFlags = 0; - Flags = 0; - DebugHandle = NULL; - JobHandle = NULL; - TokenHandle = NULL; - FileHandle = NULL; - SectionHandle = NULL; - ProcessHandle = NULL; - ThreadHandle = NULL; - BaseAddress = (PVOID)1; - - /* Zero out initial SxS and Application Compatibility state */ - AppCompatData = NULL; - AppCompatDataSize = 0; - AppCompatSxsData = NULL; - AppCompatSxsDataSize = 0; - CaptureBuffer = NULL; -#if _SXS_SUPPORT_ENABLED_ - SxsConglomeratedBuffer = NULL; -#endif - FusionFlags = 0; - - /* Zero out initial parsing variables -- others are initialized later */ - DebuggerCmdLine = NULL; - PathBuffer = NULL; - SearchPath = NULL; - NullBuffer = 0; - FreeBuffer = NULL; - NameBuffer = NULL; - CurrentDirectory = NULL; - FilePart = NULL; - DebuggerString.Buffer = NULL; - HasQuotes = FALSE; - QuotedCmdLine = NULL; - - /* Zero out initial VDM state */ - VdmAnsiEnv.Buffer = NULL; - VdmUnicodeEnv.Buffer = NULL; - VdmString.Buffer = NULL; - VdmTask = 0; - VdmUndoLevel = 0; - VdmBinaryType = 0; - VdmReserve = 0; - VdmWaitObject = NULL; - UseVdmReserve = FALSE; - IsWowApp = FALSE; - - /* Set message structures */ - CreateProcessMsg = &CsrMsg.Data.CreateProcessRequest; - VdmMsg = &CsrMsg.Data.CheckVdm; - - /* Clear the more complex structures by zeroing out their entire memory */ - RtlZeroMemory(&Context, sizeof(Context)); -#if _SXS_SUPPORT_ENABLED_ - RtlZeroMemory(&FileHandles, sizeof(FileHandles)); - RtlZeroMemory(&MappedHandles, sizeof(MappedHandles)); - RtlZeroMemory(&Handles, sizeof(Handles)); -#endif - RtlZeroMemory(&CreateProcessMsg->Sxs, sizeof(CreateProcessMsg->Sxs)); - RtlZeroMemory(&LocalProcessAttributes, sizeof(LocalProcessAttributes)); - RtlZeroMemory(&LocalThreadAttributes, sizeof(LocalThreadAttributes)); - - /* Zero out output arguments as well */ - RtlZeroMemory(lpProcessInformation, sizeof(*lpProcessInformation)); - if (hNewToken) *hNewToken = NULL; - - /* Capture the special window flag */ - NoWindow = dwCreationFlags & CREATE_NO_WINDOW; - dwCreationFlags &= ~CREATE_NO_WINDOW; - -#if _SXS_SUPPORT_ENABLED_ - /* Setup the SxS static string arrays and buffers */ - SxsStaticBuffers[0] = &SxsWin32ManifestPath; - SxsStaticBuffers[1] = &SxsWin32PolicyPath; - SxsStaticBuffers[2] = &SxsWin32AssemblyDirectory; - SxsStaticBuffers[3] = &SxsNtManifestPath; - SxsStaticBuffers[4] = &SxsNtPolicyPath; - ExePathPair.Win32 = &SxsWin32ExePath; - ExePathPair.Nt = &SxsNtExePath; - ManifestPathPair.Win32 = &SxsWin32ManifestPath.String; - ManifestPathPair.Nt = &SxsNtManifestPath.String; - PolicyPathPair.Win32 = &SxsWin32PolicyPath.String; - PolicyPathPair.Nt = &SxsNtPolicyPath.String; -#endif - - DPRINT1("CreateProcessInternalW: %S %S %lx\n", lpApplicationName, lpCommandLine, dwCreationFlags); - - /* Finally, set our TEB and PEB */ - Teb = NtCurrentTeb(); - Peb = NtCurrentPeb(); - - /* This combination is illegal (see MSDN) */ - if ((dwCreationFlags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE)) == - (DETACHED_PROCESS | CREATE_NEW_CONSOLE)) + /* Flags we don't handle yet */ + if (dwCreationFlags & CREATE_SEPARATE_WOW_VDM) { - DPRINT1("Invalid flag combo used\n"); - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; + DPRINT1("CREATE_SEPARATE_WOW_VDM not handled\n"); } - - /* Convert the priority class */ - if (dwCreationFlags & IDLE_PRIORITY_CLASS) + if (dwCreationFlags & CREATE_SHARED_WOW_VDM) { - PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_IDLE; + DPRINT1("CREATE_SHARED_WOW_VDM not handled\n"); } - else if (dwCreationFlags & BELOW_NORMAL_PRIORITY_CLASS) + if (dwCreationFlags & CREATE_FORCEDOS) { - PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_BELOW_NORMAL; + DPRINT1("CREATE_FORCEDOS not handled\n"); } - else if (dwCreationFlags & NORMAL_PRIORITY_CLASS) + + /* Fail on this flag, it's only valid with the WithLogonW function */ + if (dwCreationFlags & CREATE_PRESERVE_CODE_AUTHZ_LEVEL) { - PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_NORMAL; + DPRINT1("Invalid flag used\n"); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; } - else if (dwCreationFlags & ABOVE_NORMAL_PRIORITY_CLASS) - { - PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_ABOVE_NORMAL; - } - else if (dwCreationFlags & HIGH_PRIORITY_CLASS) - { - PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH; - } - else if (dwCreationFlags & REALTIME_PRIORITY_CLASS) - { - PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_HIGH; - PriorityClass.PriorityClass += (BasepIsRealtimeAllowed(FALSE) != NULL); - } - else - { - PriorityClass.PriorityClass = PROCESS_PRIORITY_CLASS_INVALID; - } - /* Done with the priority masks, so get rid of them */ - PriorityClass.Foreground = FALSE; - dwCreationFlags &= ~(NORMAL_PRIORITY_CLASS | - IDLE_PRIORITY_CLASS | - HIGH_PRIORITY_CLASS | - REALTIME_PRIORITY_CLASS | - BELOW_NORMAL_PRIORITY_CLASS | - ABOVE_NORMAL_PRIORITY_CLASS); - - /* You cannot request both a shared and a separate WoW VDM */ - if ((dwCreationFlags & CREATE_SEPARATE_WOW_VDM) && - (dwCreationFlags & CREATE_SHARED_WOW_VDM)) + /* This combination is illegal (see MSDN) */ + if ((dwCreationFlags & (DETACHED_PROCESS | CREATE_NEW_CONSOLE)) == + (DETACHED_PROCESS | CREATE_NEW_CONSOLE)) { - /* Fail such nonsensical attempts */ - DPRINT1("Invalid WOW flags\n"); + DPRINT1("Invalid flag combo used\n"); SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } - else if (!(dwCreationFlags & CREATE_SHARED_WOW_VDM) && - (BaseStaticServerData->DefaultSeparateVDM)) - { - /* A shared WoW VDM was not requested but system enforces separation */ - dwCreationFlags |= CREATE_SEPARATE_WOW_VDM; - } - /* If a shared WoW VDM is used, make sure the process isn't in a job */ - if (!(dwCreationFlags & CREATE_SEPARATE_WOW_VDM) && - (NtIsProcessInJob(NtCurrentProcess(), NULL))) + /* Another illegal combo */ + if ((dwCreationFlags & (CREATE_SEPARATE_WOW_VDM | CREATE_SHARED_WOW_VDM)) == + (CREATE_SEPARATE_WOW_VDM | CREATE_SHARED_WOW_VDM)) { - /* Remove the shared flag and add the separate flag */ - dwCreationFlags = (dwCreationFlags &~ CREATE_SHARED_WOW_VDM) | - CREATE_SEPARATE_WOW_VDM; + DPRINT1("Invalid flag combo used\n"); + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; } - /* Convert the environment */ - if ((lpEnvironment) && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)) + if (lpCurrentDirectory) { - /* Scan the environment to calculate its Unicode size */ - AnsiEnv.Buffer = pcScan = (PCHAR)lpEnvironment; - while ((*pcScan) || (*(pcScan + 1))) ++pcScan; - - /* Create our ANSI String */ - AnsiEnv.Length = pcScan - (PCHAR)lpEnvironment + sizeof(ANSI_NULL); - AnsiEnv.MaximumLength = AnsiEnv.Length + sizeof(ANSI_NULL); - - /* Allocate memory for the Unicode Environment */ - UnicodeEnv.Buffer = NULL; - RegionSize = AnsiEnv.MaximumLength * sizeof(WCHAR); - Status = NtAllocateVirtualMemory(NtCurrentProcess(), - (PVOID)&UnicodeEnv.Buffer, - 0, - &RegionSize, - MEM_COMMIT, - PAGE_READWRITE); - if (!NT_SUCCESS(Status)) + if ((GetFileAttributesW(lpCurrentDirectory) == INVALID_FILE_ATTRIBUTES) || + !(GetFileAttributesW(lpCurrentDirectory) & FILE_ATTRIBUTE_DIRECTORY)) { - /* Fail */ - BaseSetLastNTError(Status); + SetLastError(ERROR_DIRECTORY); return FALSE; } + } - /* Use the allocated size and convert */ - UnicodeEnv.MaximumLength = RegionSize; - Status = RtlAnsiStringToUnicodeString(&UnicodeEnv, &AnsiEnv, FALSE); - if (!NT_SUCCESS(Status)) + /* + * We're going to modify and mask out flags and stuff in lpStartupInfo, + * so we'll use our own local copy for that. + */ + StartupInfo = *lpStartupInfo; + + /* FIXME: Use default Separate/Shared VDM Flag */ + + /* If we are inside a Job, use Separate VDM so it won't escape the Job */ + if (!(dwCreationFlags & CREATE_SEPARATE_WOW_VDM)) + { + if (NtIsProcessInJob(NtCurrentProcess(), NULL)) { - /* Fail */ - NtFreeVirtualMemory(NtCurrentProcess(), - (PVOID)&UnicodeEnv.Buffer, - &RegionSize, - MEM_RELEASE); - BaseSetLastNTError(Status); - return FALSE; + /* Remove the shared flag and add the separate flag. */ + dwCreationFlags = (dwCreationFlags &~ CREATE_SHARED_WOW_VDM) | + CREATE_SEPARATE_WOW_VDM; } + } - /* Now set the Unicode environment as the environment string pointer */ - lpEnvironment = UnicodeEnv.Buffer; + /* Get the path to the VDM host */ + Length = GetSystemDirectoryW(VdmPath, MAX_PATH - wcslen(NTVDM_STRING)); + if ((Length == 0) || (Length >= MAX_PATH - wcslen(NTVDM_STRING))) + { + /* System path not found for some reason, fail */ + SetLastError(ERROR_INVALID_NAME); + return FALSE; } + wcscat(VdmPath, NTVDM_STRING); - /* Make a copy of the caller's startup info since we'll modify it */ - StartupInfo = *lpStartupInfo; - - /* Check if private data is being sent on the same channel as std handles */ + /* + * According to some sites, ShellExecuteEx uses an undocumented flag to + * send private handle data (such as HMONITOR or HICON). See: + * www.catch22.net/tuts/undoc01.asp. This implies that we can't use the + * standard handles anymore since we'd be overwriting this private data + */ if ((StartupInfo.dwFlags & STARTF_USESTDHANDLES) && (StartupInfo.dwFlags & (STARTF_USEHOTKEY | STARTF_SHELLPRIVATE))) { - /* Cannot use the std handles since we have monitor/hotkey values */ StartupInfo.dwFlags &= ~STARTF_USESTDHANDLES; } - /* If there's a debugger, or we have to launch cmd.exe, we go back here */ -AppNameRetry: - /* New iteration -- free any existing name buffer */ - if (NameBuffer) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer); - NameBuffer = NULL; - } + /* Start by zeroing out the fields */ + RtlZeroMemory(lpProcessInformation, sizeof(PROCESS_INFORMATION)); - /* New iteration -- free any existing free buffer */ - if (FreeBuffer) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, FreeBuffer); - FreeBuffer = NULL; - } + /* Easy stuff first, convert the process priority class */ + PriorityClass.Foreground = FALSE; + PriorityClass.PriorityClass = (UCHAR)BasepConvertPriorityClass(dwCreationFlags); - /* New iteration -- close any existing file handle */ - if (FileHandle) + if (lpCommandLine) { - NtClose(FileHandle); - FileHandle = NULL; + /* Search for escape sequences */ + ScanString = lpCommandLine; + while (NULL != (ScanString = wcschr(ScanString, L'^'))) + { + ScanString++; + if (*ScanString == L'\"' || *ScanString == L'^' || *ScanString == L'\\') + { + Escape = TRUE; + break; + } + } } - /* Set the initial parsing state. This code can loop -- don't move this! */ - ErrorCode = 0; - SearchRetry = TRUE; - QuotesNeeded = FALSE; - CmdLineIsAppName = FALSE; - - /* First check if we don't have an application name */ + /* Get the application name and do all the proper formating necessary */ +GetAppName: + /* See if we have an application name (oh please let us have one!) */ if (!lpApplicationName) { - /* This should be the first time we attempt creating one */ - ASSERT(NameBuffer == NULL); - - /* Allocate a buffer to hold it */ + /* The fun begins */ NameBuffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, MAX_PATH * sizeof(WCHAR)); - if (!NameBuffer) + if (NameBuffer == NULL) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); - Result = FALSE; - goto Quickie; + goto Cleanup; } - /* Initialize the application name and our parsing parameters */ - lpApplicationName = NullBuffer = ScanString = lpCommandLine; + /* This is all we have to work with :( */ + lpApplicationName = lpCommandLine; - /* Check for an initial quote*/ - if (*lpCommandLine == L'\"') + /* Initialize our friends at the beginning */ + NullBuffer = (LPWSTR)lpApplicationName; + ScanString = (LPWSTR)lpApplicationName; + + /* We will start by looking for a quote */ + if (*ScanString == L'\"') { - /* We found a quote, keep searching for another one */ - SearchRetry = FALSE; - ScanString++; - lpApplicationName = ScanString; - while (*ScanString) - { - /* Have we found the terminating quote? */ - if (*ScanString == L'\"') - { - /* We're done, get out of here */ - NullBuffer = ScanString; - HasQuotes = TRUE; - break; - } + /* That was quick */ + SearchDone = TRUE; - /* Keep searching for the quote */ - ScanString++; - NullBuffer = ScanString; - } + /* Advance past quote */ + ScanString++; + lpApplicationName = ScanString; + + /* Find the closing quote */ + while (*ScanString) + { + if (*ScanString == L'\"' && *(ScanString - 1) != L'^') + { + /* Found it */ + NullBuffer = ScanString; + FoundQuotes = TRUE; + break; + } + + /* Keep looking */ + ScanString++; + NullBuffer = ScanString; + } } else { -StartScan: - /* We simply make the application name be the command line*/ + /* No quotes, so we'll be looking for white space */ + WhiteScan: + /* Reset the pointer */ lpApplicationName = lpCommandLine; + + /* Find whitespace of Tab */ while (*ScanString) { - /* Check if it starts with a space or tab */ - if ((*ScanString == L' ') || (*ScanString == L'\t')) + if (*ScanString == ' ' || *ScanString == '\t') { - /* Break out of the search loop */ + /* Found it */ NullBuffer = ScanString; break; } - /* Keep searching for a space or tab */ + /* Keep looking */ ScanString++; NullBuffer = ScanString; } } - /* We have found the end of the application name, terminate it */ + /* Set the Null Buffer */ SaveChar = *NullBuffer; *NullBuffer = UNICODE_NULL; - /* New iteration -- free any existing saved path */ - if (SearchPath) - { - RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath); - SearchPath = NULL; - } - - /* Now compute the final EXE path based on the name */ - SearchPath = BaseComputeProcessExePath((LPWSTR)lpApplicationName); - DPRINT1("Search Path: %S\n", SearchPath); - if (!SearchPath) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - Result = FALSE; - goto Quickie; - } - - /* And search for the executable in the search path */ - Length = SearchPathW(SearchPath, + /* Do a search for the file */ + DPRINT("Ready for SearchPathW: %S\n", lpApplicationName); + RetVal = SearchPathW(NULL, lpApplicationName, L".exe", MAX_PATH, NameBuffer, - NULL); + NULL) * sizeof(WCHAR); - /* Did we find it? */ - if ((Length) && (Length < MAX_PATH)) + /* Did it find something? */ + if (RetVal) { /* Get file attributes */ - CurdirLength = GetFileAttributesW(NameBuffer); - if ((CurdirLength != 0xFFFFFFFF) && - (CurdirLength & FILE_ATTRIBUTE_DIRECTORY)) + ULONG Attributes = GetFileAttributesW(NameBuffer); + if (Attributes & FILE_ATTRIBUTE_DIRECTORY) { - /* This was a directory, fail later on */ - Length = 0; + /* Give it a length of 0 to fail, this was a directory. */ + RetVal = 0; } else { /* It's a file! */ - Length++; + RetVal += sizeof(WCHAR); } } - DPRINT1("Length: %lx Buffer: %S\n", Length, NameBuffer); + /* Now check if we have a file, and if the path size is OK */ + if (!RetVal || RetVal >= (MAX_PATH * sizeof(WCHAR))) + { + ULONG PathType; + HANDLE hFile; - /* Check if there was a failure in SearchPathW */ - if ((Length) && (Length < MAX_PATH)) - { - /* Everything looks good, restore the name */ - *NullBuffer = SaveChar; - lpApplicationName = NameBuffer; - } - else - { - /* Check if this was a relative path, which would explain it */ + /* We failed, try to get the Path Type */ + DPRINT("SearchPathW failed. Retval: %ld\n", RetVal); PathType = RtlDetermineDosPathNameType_U(lpApplicationName); + + /* If it's not relative, try to get the error */ if (PathType != RtlPathTypeRelative) { /* This should fail, and give us a detailed LastError */ - FileHandle = CreateFileW(lpApplicationName, - GENERIC_READ, - FILE_SHARE_READ | - FILE_SHARE_WRITE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL); - if (FileHandle != INVALID_HANDLE_VALUE) + hFile = CreateFileW(lpApplicationName, + GENERIC_READ, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + /* Did it actually NOT fail? */ + if (hFile != INVALID_HANDLE_VALUE) { - /* It worked? Return a generic error */ - CloseHandle(FileHandle); - FileHandle = NULL; + /* Fake the error */ + CloseHandle(hFile); BaseSetLastNTError(STATUS_OBJECT_NAME_NOT_FOUND); } } else { - /* Path was absolute, which means it doesn't exist */ + /* Immediately set the error */ BaseSetLastNTError(STATUS_OBJECT_NAME_NOT_FOUND); } /* Did we already fail once? */ - if (ErrorCode) + if (Error) { - /* Set the error code */ - SetLastError(ErrorCode); + SetLastError(Error); } else { /* Not yet, cache it */ - ErrorCode = GetLastError(); + Error = GetLastError(); } /* Put back the command line */ *NullBuffer = SaveChar; lpApplicationName = NameBuffer; - /* It's possible there's whitespace in the directory name */ - if (!(*ScanString) || !(SearchRetry)) + /* + * If the search isn't done and we still have cmdline + * then start over. Ex: c:\ha ha ha\haha.exe + */ + if (*ScanString && !SearchDone) { - /* Not the case, give up completely */ - Result = FALSE; - goto Quickie; - } + /* Move in the buffer */ + ScanString++; + NullBuffer = ScanString; - /* There are spaces, so keep trying the next possibility */ - ScanString++; - NullBuffer = ScanString; + /* We will have to add a quote, since there is a space*/ + QuotesNeeded = TRUE; - /* We will have to add a quote, since there is a space */ - QuotesNeeded = TRUE; - HasQuotes = TRUE; - goto StartScan; - } - } - else if (!(lpCommandLine) || !(*lpCommandLine)) - { - /* We don't have a command line, so just use the application name */ - CmdLineIsAppName = TRUE; - lpCommandLine = (LPWSTR)lpApplicationName; - } + /* And we will also fake the fact we found one */ + FoundQuotes = TRUE; - /* Convert the application name to its NT path */ - TranslationStatus = RtlDosPathNameToRelativeNtPathName_U(lpApplicationName, - &PathName, - NULL, - &SxsWin32RelativePath); - if (!TranslationStatus) - { - /* Path must be invaild somehow, bail out */ - DPRINT1("Path translation for SxS failed\n"); - SetLastError(ERROR_PATH_NOT_FOUND); - Result = FALSE; - goto Quickie; - } + /* Start over */ + goto WhiteScan; + } - /* Setup the buffer that needs to be freed at the end */ - ASSERT(FreeBuffer == NULL); - FreeBuffer = PathName.Buffer; - - /* Check what kind of path the application is, for SxS (Fusion) purposes */ - RtlInitUnicodeString(&SxsWin32ExePath, lpApplicationName); - SxsPathType = RtlDetermineDosPathNameType_U(lpApplicationName); - if ((SxsPathType != RtlPathTypeDriveAbsolute) && - (SxsPathType != RtlPathTypeLocalDevice) && - (SxsPathType != RtlPathTypeRootLocalDevice) && - (SxsPathType != RtlPathTypeUncAbsolute)) - { - /* Relative-type path, get the full path */ - RtlInitEmptyUnicodeString(&PathBufferString, NULL, 0); - Status = RtlGetFullPathName_UstrEx(&SxsWin32ExePath, - NULL, - &PathBufferString, - NULL, - NULL, - NULL, - &SxsPathType, - NULL); - if (!NT_SUCCESS(Status)) - { - /* Fail the rest of the create */ - RtlReleaseRelativeName(&SxsWin32RelativePath); - BaseSetLastNTError(Status); - Result = FALSE; - goto Quickie; + /* We totally failed */ + goto Cleanup; } - /* Use this full path as the SxS path */ - SxsWin32ExePath = PathBufferString; - PathBuffer = PathBufferString.Buffer; - PathBufferString.Buffer = NULL; - DPRINT1("SxS Path: %S\n", PathBuffer); + /* Put back the command line */ + *NullBuffer = SaveChar; + lpApplicationName = NameBuffer; + DPRINT("SearchPathW suceeded (%ld): %S\n", RetVal, NameBuffer); } - - /* Also set the .EXE path based on the path name */ -#if _SXS_SUPPORT_ENABLED_ - SxsNtExePath = PathName; -#endif - if (SxsWin32RelativePath.RelativeName.Length) + else if (!lpCommandLine || *lpCommandLine == UNICODE_NULL) { - /* If it's relative, capture the relative name */ - PathName = SxsWin32RelativePath.RelativeName; + /* We have an app name (good!) but no command line */ + CmdLineIsAppName = TRUE; + lpCommandLine = (LPWSTR)lpApplicationName; } - else - { - /* Otherwise, it's absolute, make sure no relative dir is used */ - SxsWin32RelativePath.ContainingDirectory = NULL; - } - /* Now use the path name, and the root path, to try opening the app */ - DPRINT1("Path: %wZ. Dir: %lx\n", &PathName, SxsWin32RelativePath.ContainingDirectory); - InitializeObjectAttributes(&LocalObjectAttributes, - &PathName, - OBJ_CASE_INSENSITIVE, - SxsWin32RelativePath.ContainingDirectory, - NULL); - Status = NtOpenFile(&FileHandle, - SYNCHRONIZE | - FILE_READ_ATTRIBUTES | - FILE_READ_DATA | - FILE_EXECUTE, - &LocalObjectAttributes, - &IoStatusBlock, - FILE_SHARE_READ | FILE_SHARE_DELETE, - FILE_SYNCHRONOUS_IO_NONALERT | - FILE_NON_DIRECTORY_FILE); - if (!NT_SUCCESS(Status)) - { - /* Try to open the app just for execute purposes instead */ - Status = NtOpenFile(&FileHandle, - SYNCHRONIZE | FILE_EXECUTE, - &LocalObjectAttributes, - &IoStatusBlock, - FILE_SHARE_READ | FILE_SHARE_DELETE, - FILE_SYNCHRONOUS_IO_NONALERT | - FILE_NON_DIRECTORY_FILE); - } + /* At this point the name has been toyed with enough to be openable */ + Status = BasepMapFile(lpApplicationName, &hSection, &ApplicationName); - /* Cleanup in preparation for failure or success */ - RtlReleaseRelativeName(&SxsWin32RelativePath); + /* Check for failure */ if (!NT_SUCCESS(Status)) { - /* Failure path, try to understand why */ - DPRINT1("Open file failed: %lx\n", Status); - if (RtlIsDosDeviceName_U(lpApplicationName)) - { - /* If a device is being executed, return this special error code */ - SetLastError(ERROR_BAD_DEVICE); - Result = FALSE; - goto Quickie; - } - else - { - /* Otherwise return the converted NT error code */ - BaseSetLastNTError(Status); - Result = FALSE; - goto Quickie; - } - } - - /* Did the caller specify a desktop? */ - if (!StartupInfo.lpDesktop) - { - /* Use the one from the current process */ - StartupInfo.lpDesktop = Peb->ProcessParameters->DesktopInfo.Buffer; - } - - /* Create a section for this file */ - Status = NtCreateSection(&SectionHandle, - SECTION_ALL_ACCESS, - NULL, - NULL, - PAGE_EXECUTE, - SEC_IMAGE, - FileHandle); - DPRINT1("Section status: %lx\n", Status); - if (NT_SUCCESS(Status)) - { - /* Are we running on Windows Embedded, Datacenter, Blade or Starter? */ - if (SharedUserData->SuiteMask & (VER_SUITE_EMBEDDEDNT | - VER_SUITE_DATACENTER | - VER_SUITE_PERSONAL | - VER_SUITE_BLADE)) - { - /* These SKUs do not allow running certain applications */ - Status = BasepCheckWebBladeHashes(FileHandle); - if (Status == STATUS_ACCESS_DENIED) - { - /* And this is one of them! */ - DPRINT1("Invalid Blade hashes!\n"); - SetLastError(ERROR_ACCESS_DISABLED_WEBBLADE); - Result = FALSE; - goto Quickie; - } - - /* Did we get some other failure? */ - if (!NT_SUCCESS(Status)) - { - /* If we couldn't check the hashes, assume nefariousness */ - DPRINT1("Tampered Blade hashes!\n"); - SetLastError(ERROR_ACCESS_DISABLED_WEBBLADE_TAMPER); - Result = FALSE; - goto Quickie; - } - } - - /* Now do Winsafer, etc, checks */ - Status = BasepIsProcessAllowed((LPWSTR)lpApplicationName); - if (!NT_SUCCESS(Status)) - { - /* Fail if we're not allowed to launch the process */ - DPRINT1("Process not allowed to launch: %lx\n", Status); - BaseSetLastNTError(Status); - if (SectionHandle) - { - NtClose(SectionHandle); - SectionHandle = NULL; - } - Result = FALSE; - goto Quickie; - } - - /* Is a DOS VDM being forced, but we already have a WOW32 instance ready? */ - if ((dwCreationFlags & CREATE_FORCEDOS) && - (BaseStaticServerData->IsWowTaskReady)) - { - /* This request can't be satisfied, instead, a separate VDM is needed */ - dwCreationFlags &= ~(CREATE_FORCEDOS | CREATE_SHARED_WOW_VDM); - dwCreationFlags |= CREATE_SEPARATE_WOW_VDM; - - /* Set a failure code, ask for VDM reservation */ - Status = STATUS_INVALID_IMAGE_WIN_16; - UseVdmReserve = TRUE; - - /* Close the current handle */ - NtClose(SectionHandle); - SectionHandle = NULL; - - /* Don't query the section later */ - QuerySection = FALSE; - } - } - - /* Did we already do these checks? */ - if (!SkipSaferAndAppCompat) - { - /* Is everything OK so far, OR do we have an non-MZ, non-DOS app? */ - if ((NT_SUCCESS(Status)) || - ((Status == STATUS_INVALID_IMAGE_NOT_MZ) && - !(BaseIsDosApplication(&PathName, Status)))) - { - /* Clear the machine type in case of failure */ - ImageMachine = 0; - - /* Clean any app compat data that may have accumulated */ - BasepFreeAppCompatData(AppCompatData, AppCompatSxsData); - AppCompatData = NULL; - AppCompatSxsData = NULL; - - /* Do we have a section? */ - if (SectionHandle) - { - /* Have we already queried it? */ - if (QuerySection) - { - /* Nothing to do */ - Status = STATUS_SUCCESS; - } - else - { - /* Get some information about the executable */ - Status = NtQuerySection(SectionHandle, - SectionImageInformation, - &ImageInformation, - sizeof(ImageInformation), - NULL); - } - - /* Do we have section information now? */ - if (NT_SUCCESS(Status)) - { - /* Don't ask for it again, save the machine type */ - QuerySection = TRUE; - ImageMachine = ImageInformation.Machine; - } - } - - /* Is there a reason/Shim we shouldn't run this application? */ - Status = BasepCheckBadapp(FileHandle, - FreeBuffer, - lpEnvironment, - ImageMachine, - &AppCompatData, - &AppCompatDataSize, - &AppCompatSxsData, - &AppCompatSxsDataSize, - &FusionFlags); - if (!NT_SUCCESS(Status)) - { - /* This is usually the status we get back */ - DPRINT1("App compat launch failure: %lx\n", Status); - if (Status == STATUS_ACCESS_DENIED) - { - /* Convert it to something more Win32-specific */ - SetLastError(ERROR_CANCELLED); - } - else - { - /* Some other error */ - BaseSetLastNTError(Status); - } - - /* Did we have a section? */ - if (SectionHandle) - { - /* Clean it up */ - NtClose(SectionHandle); - SectionHandle = NULL; - } - - /* Fail the call */ - Result = FALSE; - goto Quickie; - } - } - } - - //ASSERT((dwFusionFlags & ~SXS_APPCOMPACT_FLAG_APP_RUNNING_SAFEMODE) == 0); - - /* Have we already done, and do we need to do, SRP (WinSafer) checks? */ - if (!(SkipSaferAndAppCompat) && - ~(dwCreationFlags & CREATE_PRESERVE_CODE_AUTHZ_LEVEL)) - { - /* Assume yes */ - SaferNeeded = TRUE; + /* Could be a non-PE File */ switch (Status) { + /* Check if the Kernel tells us it's not even valid MZ */ case STATUS_INVALID_IMAGE_NE_FORMAT: case STATUS_INVALID_IMAGE_PROTECT: - case STATUS_INVALID_IMAGE_WIN_16: - case STATUS_FILE_IS_OFFLINE: - /* For all DOS, 16-bit, OS/2 images, we do*/ - break; - case STATUS_INVALID_IMAGE_NOT_MZ: - /* For invalid files, we don't, unless it's a .BAT file */ - if (BaseIsDosApplication(&PathName, Status)) break; - default: - /* Any other error codes we also don't */ - if (!NT_SUCCESS(Status)) - { - SaferNeeded = FALSE; - } - - /* But for success, we do */ - break; - } - - /* Okay, so what did the checks above result in? */ - if (SaferNeeded) - { - /* We have to call into the WinSafer library and actually check */ - Status = BasepCheckWinSaferRestrictions(hUserToken, - (LPWSTR)lpApplicationName, - FileHandle, - &InJob, - &TokenHandle, - &JobHandle); - if (Status == 0xFFFFFFFF) + /* If it's a DOS app, use VDM */ + if (BaseIsDosApplication(&ApplicationName, Status)) { - /* Back in 2003, they didn't have an NTSTATUS for this... */ - DPRINT1("WinSafer blocking process launch\n"); - SetLastError(ERROR_ACCESS_DISABLED_BY_POLICY); - Result = FALSE; - goto Quickie; + DPRINT1("Launching VDM...\n"); + RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer); + RtlFreeHeap(RtlGetProcessHeap(), 0, ApplicationName.Buffer); + return CreateProcessW(VdmPath, + (LPWSTR)((ULONG_PTR)lpApplicationName), /* FIXME: Buffer must be writable!!! */ + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + &StartupInfo, + lpProcessInformation); } + /* It's a batch file */ + Extension = &ApplicationName.Buffer[ApplicationName.Length / + sizeof(WCHAR) - 4]; - /* Other status codes are not-Safer related, just convert them */ - if (!NT_SUCCESS(Status)) + /* Make sure the extensions are correct */ + if (_wcsnicmp(Extension, L".bat", 4) && _wcsnicmp(Extension, L".cmd", 4)) { - DPRINT1("Error checking WinSafer: %lx\n", Status); - BaseSetLastNTError(Status); - Result = FALSE; - goto Quickie; + SetLastError(ERROR_BAD_EXE_FORMAT); + return FALSE; } - } - } - /* The last step is to figure out why the section object was not created */ - switch (Status) - { - case STATUS_INVALID_IMAGE_WIN_16: - /* 16-bit binary. Should we use WOW or does the caller force VDM? */ - if (!(dwCreationFlags & CREATE_FORCEDOS)) - { - /* Remember that we're launching WOW */ - IsWowApp = TRUE; + /* Calculate the length of the command line */ + CmdLineLength = wcslen(CMD_STRING) + wcslen(lpCommandLine) + 1; - /* Create the VDM environment, it's valid for WOW too */ - Result = BaseCreateVDMEnvironment(lpEnvironment, - &VdmAnsiEnv, - &VdmUnicodeEnv); - if (!Result) - { - DPRINT1("VDM environment for WOW app failed\n"); - goto Quickie; - } + /* If we found quotes, then add them into the length size */ + if (CmdLineIsAppName || FoundQuotes) CmdLineLength += 2; + CmdLineLength *= sizeof(WCHAR); - /* We're going to try this twice, so do a loop */ - while (TRUE) - { - /* Pick which kind of WOW mode we want to run in */ - VdmBinaryType = (dwCreationFlags & - CREATE_SEPARATE_WOW_VDM) ? - BINARY_TYPE_WOW : BINARY_TYPE_SEPARATE_WOW; - - /* Get all the VDM settings and current status */ - Status = BaseCheckVDM(VdmBinaryType, - lpApplicationName, - lpCommandLine, - lpCurrentDirectory, - &VdmAnsiEnv, - (PCSR_API_MESSAGE)VdmMsg, - &VdmTask, - dwCreationFlags, - &StartupInfo, - hUserToken); - - /* If it worked, no need to try again */ - if (NT_SUCCESS(Status)) break; - - /* Check if it's disallowed or if it's our second time */ - BaseSetLastNTError(Status); - if ((Status == STATUS_VDM_DISALLOWED) || - (VdmBinaryType == BINARY_TYPE_SEPARATE_WOW) || - (GetLastError() == ERROR_ACCESS_DENIED)) - { - /* Fail the call -- we won't try again */ - DPRINT1("VDM message failure for WOW: %lx\n", Status); - Result = FALSE; - goto Quickie; - } - - /* Try one more time, but with a separate WOW instance */ - dwCreationFlags |= CREATE_SEPARATE_WOW_VDM; - } - - /* Check which VDM state we're currently in */ - switch (VdmMsg->VDMState & (VDM_NOT_LOADED | - VDM_NOT_READY | - VDM_READY)) - { - case VDM_NOT_LOADED: - /* VDM is not fully loaded, so not that much to undo */ - VdmUndoLevel = VDM_UNDO_PARTIAL; - - /* Reset VDM reserve if needed */ - if (UseVdmReserve) VdmReserve = 1; - - /* Get the required parameters and names for launch */ - Result = BaseGetVdmConfigInfo(lpCommandLine, - VdmTask, - VdmBinaryType, - &VdmString, - &VdmReserve); - if (!Result) - { - DPRINT1("VDM Configuration failed for WOW\n"); - BaseSetLastNTError(Status); - goto Quickie; - } - - /* Update the command-line with the VDM one instead */ - lpCommandLine = VdmString.Buffer; - lpApplicationName = NULL; - - /* We don't want a console, detachment, nor a window */ - dwCreationFlags |= CREATE_NO_WINDOW; - dwCreationFlags &= ~(CREATE_NEW_CONSOLE | DETACHED_PROCESS); - - /* Force feedback on */ - StartupInfo.dwFlags |= STARTF_FORCEONFEEDBACK; - break; - - - case VDM_READY: - /* VDM is ready, so we have to undo everything */ - VdmUndoLevel = VDM_UNDO_REUSE; - - /* Check if CSRSS wants us to wait on VDM */ - VdmWaitObject = VdmMsg->WaitObjectForParent; - break; - - case VDM_NOT_READY: - /* Something is wrong with VDM, we'll fail the call */ - DPRINT1("VDM is not ready for WOW\n"); - SetLastError(ERROR_NOT_READY); - Result = FALSE; - goto Quickie; - - default: - break; - } - - /* Since to get NULL, we allocate from 0x1, account for this */ - VdmReserve--; - - /* This implies VDM is ready, so skip everything else */ - if (VdmWaitObject) goto VdmShortCircuit; - - /* Don't inherit handles since we're doing VDM now */ - bInheritHandles = FALSE; - - /* Had the user passed in environment? If so, destroy it */ - if ((lpEnvironment) && - !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)) - { - RtlDestroyEnvironment(lpEnvironment); - } - - /* We've already done all these checks, don't do them again */ - SkipSaferAndAppCompat = TRUE; - goto AppNameRetry; + /* Allocate space for the new command line */ + BatchCommandLine = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + CmdLineLength); + if (BatchCommandLine == NULL) + { + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto Cleanup; } - // There is no break here on purpose, so FORCEDOS drops down! - case STATUS_INVALID_IMAGE_PROTECT: - case STATUS_INVALID_IMAGE_NOT_MZ: - case STATUS_INVALID_IMAGE_NE_FORMAT: - /* We're launching an executable application */ - BinarySubType = BINARY_TYPE_EXE; - - /* We can drop here from other "cases" above too, so check */ - if ((Status == STATUS_INVALID_IMAGE_PROTECT) || - (Status == STATUS_INVALID_IMAGE_NE_FORMAT) || - (BinarySubType = BaseIsDosApplication(&PathName, Status))) + /* Build it */ + wcscpy(BatchCommandLine, CMD_STRING); + if (CmdLineIsAppName || FoundQuotes) { - /* We're launching a DOS application */ - VdmBinaryType = BINARY_TYPE_DOS; - - /* Based on the caller environment, create a VDM one */ - Result = BaseCreateVDMEnvironment(lpEnvironment, - &VdmAnsiEnv, - &VdmUnicodeEnv); - if (!Result) - { - DPRINT1("VDM environment for DOS failed\n"); - goto Quickie; - } - - /* Check the current state of the VDM subsystem */ - Status = BaseCheckVDM(VdmBinaryType | BinarySubType, - lpApplicationName, - lpCommandLine, - lpCurrentDirectory, - &VdmAnsiEnv, - (PCSR_API_MESSAGE)VdmMsg, - &VdmTask, - dwCreationFlags, - &StartupInfo, - NULL); - if (!NT_SUCCESS(Status)) - { - /* Failed to inquire about VDM, fail the call */ - DPRINT1("VDM message failure for DOS: %lx\n", Status); - BaseSetLastNTError(Status); - Result = FALSE; - goto Quickie; - }; - - /* Handle possible VDM states */ - switch (VdmMsg->VDMState & (VDM_NOT_LOADED | - VDM_NOT_READY | - VDM_READY)) - { - case VDM_NOT_LOADED: - /* If VDM is not loaded, we'll do a partial undo */ - VdmUndoLevel = VDM_UNDO_PARTIAL; - - /* A VDM process can't also be detached, so fail */ - if (dwCreationFlags & DETACHED_PROCESS) - { - DPRINT1("Detached process but no VDM, not allowed\n"); - SetLastError(ERROR_ACCESS_DENIED); - return FALSE; - } - - /* Get the required parameters and names for launch */ - Result = BaseGetVdmConfigInfo(lpCommandLine, - VdmTask, - VdmBinaryType, - &VdmString, - &VdmReserve); - if (!Result) - { - DPRINT1("VDM Configuration failed for DOS\n"); - BaseSetLastNTError(Status); - goto Quickie; - } - - /* Update the command-line to launch VDM instead */ - lpCommandLine = VdmString.Buffer; - lpApplicationName = NULL; - break; - - case VDM_READY: - /* VDM is ready, so we have to undo everything */ - VdmUndoLevel = VDM_UNDO_REUSE; - - /* Check if CSRSS wants us to wait on VDM */ - VdmWaitObject = VdmMsg->WaitObjectForParent; - break; - - case VDM_NOT_READY: - /* Something is wrong with VDM, we'll fail the call */ - DPRINT1("VDM is not ready for DOS\n"); - SetLastError(ERROR_NOT_READY); - Result = FALSE; - goto Quickie; - - default: - break; - } - - /* Since to get NULL, we allocate from 0x1, account for this */ - VdmReserve--; - - /* This implies VDM is ready, so skip everything else */ - if (VdmWaitObject) goto VdmShortCircuit; - - /* Don't inherit handles since we're doing VDM now */ - bInheritHandles = FALSE; - - /* Had the user passed in environment? If so, destroy it */ - if ((lpEnvironment) && - !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)) - { - RtlDestroyEnvironment(lpEnvironment); - } - - /* Use our VDM Unicode environment instead */ - lpEnvironment = VdmUnicodeEnv.Buffer; + wcscat(BatchCommandLine, L"\""); } - else + wcscat(BatchCommandLine, lpCommandLine); + if (CmdLineIsAppName || FoundQuotes) { - /* It's a batch file, get the extension */ - ExtBuffer = &PathName.Buffer[PathName.Length / sizeof(WCHAR) - 4]; - - /* Make sure the extensions are correct */ - if ((PathName.Length < (4 * sizeof(WCHAR))) || - ((_wcsnicmp(ExtBuffer, L".bat", 4)) && - (_wcsnicmp(ExtBuffer, L".cmd", 4)))) - { - DPRINT1("Invalid EXE, and not a batch or script file\n"); - SetLastError(ERROR_BAD_EXE_FORMAT); - Result = FALSE; - goto Quickie; - } - - /* Check if we need to account for quotes around the path */ - CmdQuoteLength = CmdLineIsAppName || HasQuotes; - if (!CmdLineIsAppName) - { - if (HasQuotes) CmdQuoteLength++; - } - else - { - CmdQuoteLength++; - } - - /* Calculate the length of the command line */ - CmdLineLength = wcslen(lpCommandLine); - CmdLineLength += wcslen(CMD_STRING); - CmdLineLength += CmdQuoteLength + sizeof(ANSI_NULL); - CmdLineLength *= sizeof(WCHAR); - - /* Allocate space for the new command line */ - AnsiCmdCommand = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - CmdLineLength); - if (!AnsiCmdCommand) - { - BaseSetLastNTError(STATUS_NO_MEMORY); - Result = FALSE; - goto Quickie; - } - - /* Build it */ - wcscpy(AnsiCmdCommand, CMD_STRING); - if ((CmdLineIsAppName) || (HasQuotes)) - { - wcscat(AnsiCmdCommand, L"\""); - } - wcscat(AnsiCmdCommand, lpCommandLine); - if ((CmdLineIsAppName) || (HasQuotes)) - { - wcscat(AnsiCmdCommand, L"\""); - } - - /* Create it as a Unicode String */ - RtlInitUnicodeString(&DebuggerString, AnsiCmdCommand); - - /* Set the command line to this */ - lpCommandLine = DebuggerString.Buffer; - lpApplicationName = NULL; - DPRINT1("Retrying with: %S\n", lpCommandLine); + wcscat(BatchCommandLine, L"\""); } - /* We've already done all these checks, don't do them again */ - SkipSaferAndAppCompat = TRUE; - goto AppNameRetry; + /* Create it as a Unicode String */ + RtlInitUnicodeString(&CommandLineString, BatchCommandLine); - case STATUS_INVALID_IMAGE_WIN_64: - /* 64-bit binaries are not allowed to run on 32-bit ReactOS */ - DPRINT1("64-bit binary, failing\n"); - SetLastError(ERROR_EXE_MACHINE_TYPE_MISMATCH); - Result = FALSE; - goto Quickie; + /* Set the command line to this */ + lpCommandLine = CommandLineString.Buffer; + lpApplicationName = NULL; - case STATUS_FILE_IS_OFFLINE: - /* Set the correct last error for this */ - DPRINT1("File is offline, failing\n"); - SetLastError(ERROR_FILE_OFFLINE); + /* Free memory */ + RtlFreeHeap(RtlGetProcessHeap(), 0, ApplicationName.Buffer); + ApplicationName.Buffer = NULL; + goto GetAppName; break; - default: - /* Any other error, convert it to a generic Win32 error */ - if (!NT_SUCCESS(Status)) - { - DPRINT1("Failed to create section: %lx\n", Status); - SetLastError(ERROR_BAD_EXE_FORMAT); - Result = FALSE; - goto Quickie; - } + case STATUS_INVALID_IMAGE_WIN_16: - /* Otherwise, this must be success */ - ASSERT(Status == STATUS_SUCCESS); - break; - } + /* It's a Win16 Image, use VDM */ + DPRINT1("Launching VDM...\n"); + RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer); + RtlFreeHeap(RtlGetProcessHeap(), 0, ApplicationName.Buffer); + return CreateProcessW(VdmPath, + (LPWSTR)((ULONG_PTR)lpApplicationName), /* FIXME: Buffer must be writable!!! */ + lpProcessAttributes, + lpThreadAttributes, + bInheritHandles, + dwCreationFlags, + lpEnvironment, + lpCurrentDirectory, + &StartupInfo, + lpProcessInformation); - /* Is this not a WOW application, but a WOW32 VDM was requested for it? */ - if (!(IsWowApp) && (dwCreationFlags & CREATE_SEPARATE_WOW_VDM)) - { - /* Ignore the nonsensical request */ - dwCreationFlags &= ~CREATE_SEPARATE_WOW_VDM; - } + case STATUS_OBJECT_NAME_NOT_FOUND: + case STATUS_OBJECT_PATH_NOT_FOUND: + BaseSetLastNTError(Status); + goto Cleanup; - /* Did we already check information for the section? */ - if (!QuerySection) - { - /* Get some information about the executable */ - Status = NtQuerySection(SectionHandle, - SectionImageInformation, - &ImageInformation, - sizeof(ImageInformation), - NULL); - if (!NT_SUCCESS(Status)) - { - /* We failed, bail out */ - DPRINT1("Section query failed\n"); - BaseSetLastNTError(Status); - Result = FALSE; - goto Quickie; + default: + /* Invalid Image Type */ + SetLastError(ERROR_BAD_EXE_FORMAT); + goto Cleanup; } - - /* Don't check this later */ - QuerySection = TRUE; } - /* Check if this was linked as a DLL */ - if (ImageInformation.ImageCharacteristics & IMAGE_FILE_DLL) + /* Use our desktop if we didn't get any */ + if (!StartupInfo.lpDesktop) { - /* These aren't valid images to try to execute! */ - DPRINT1("Trying to launch a DLL, failing\n"); - SetLastError(ERROR_BAD_EXE_FORMAT); - Result = FALSE; - goto Quickie; + StartupInfo.lpDesktop = OurPeb->ProcessParameters->DesktopInfo.Buffer; } - /* Don't let callers pass in this flag -- we'll only get it from IFRO */ - Flags &= ~PROCESS_CREATE_FLAGS_LARGE_PAGES; + /* FIXME: Check if Application is allowed to run */ - /* Clear the IFEO-missing flag, before we know for sure... */ - ParameterFlags &= ~2; + /* FIXME: Allow CREATE_SEPARATE only for WOW Apps, once we have that. */ - /* If the process is being debugged, only read IFEO if the PEB says so */ - if (!(dwCreationFlags & (DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS)) || - (NtCurrentPeb()->ReadImageFileExecOptions)) + /* Get some information about the executable */ + Status = NtQuerySection(hSection, + SectionImageInformation, + &SectionImageInfo, + sizeof(SectionImageInfo), + NULL); + if(!NT_SUCCESS(Status)) { - /* Let's do this! Attempt to open IFEO */ - Status1 = LdrOpenImageFileOptionsKey(&PathName, 0, &KeyHandle); - if (!NT_SUCCESS(Status1)) - { - /* We failed, set the flag so we store this in the parameters */ - if (Status1 == STATUS_OBJECT_NAME_NOT_FOUND) ParameterFlags |= 2; - } - else - { - /* Was this our first time going through this path? */ - if (!DebuggerCmdLine) - { - /* Allocate a buffer for the debugger path */ - DebuggerCmdLine = RtlAllocateHeap(RtlGetProcessHeap(), - 0, - MAX_PATH * sizeof(WCHAR)); - if (!DebuggerCmdLine) - { - /* Close IFEO on failure */ - Status1 = NtClose(KeyHandle); - ASSERT(NT_SUCCESS(Status1)); - - /* Fail the call */ - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - Result = FALSE; - goto Quickie; - } - } - - /* Now query for the debugger */ - Status1 = LdrQueryImageFileKeyOption(KeyHandle, - L"Debugger", - REG_SZ, - DebuggerCmdLine, - MAX_PATH * sizeof(WCHAR), - &ResultSize); - if (!(NT_SUCCESS(Status1)) || - (ResultSize < sizeof(WCHAR)) || - (DebuggerCmdLine[0] == UNICODE_NULL)) - { - /* If it's not there, or too small, or invalid, ignore it */ - RtlFreeHeap(RtlGetProcessHeap(), 0, DebuggerCmdLine); - DebuggerCmdLine = NULL; - } - - /* Also query if we should map with large pages */ - Status1 = LdrQueryImageFileKeyOption(KeyHandle, - L"UseLargePages", - REG_DWORD, - &UseLargePages, - sizeof(UseLargePages), - NULL); - if ((NT_SUCCESS(Status1)) && (UseLargePages)) - { - /* Do it! This is the only way this flag can be set */ - Flags |= PROCESS_CREATE_FLAGS_LARGE_PAGES; - } - - /* We're done with IFEO, can close it now */ - Status1 = NtClose(KeyHandle); - ASSERT(NT_SUCCESS(Status1)); - } + DPRINT1("Unable to get SectionImageInformation, status 0x%x\n", Status); + BaseSetLastNTError(Status); + goto Cleanup; } - /* Make sure the image was compiled for this processor */ - if ((ImageInformation.Machine < SharedUserData->ImageNumberLow) || - (ImageInformation.Machine > SharedUserData->ImageNumberHigh)) + /* Don't execute DLLs */ + if (SectionImageInfo.ImageCharacteristics & IMAGE_FILE_DLL) { - /* It was not -- raise a hard error */ - ErrorResponse = ResponseOk; - ErrorParameters[0] = (ULONG_PTR)&PathName; - NtRaiseHardError(STATUS_IMAGE_MACHINE_TYPE_MISMATCH_EXE, - 1, - 1, - ErrorParameters, - OptionOk, - &ErrorResponse); - if (Peb->ImageSubsystemMajorVersion <= 3) - { - /* If it's really old, return this error */ - SetLastError(ERROR_BAD_EXE_FORMAT); - } - else - { - /* Otherwise, return a more modern error */ - SetLastError(ERROR_EXE_MACHINE_TYPE_MISMATCH); - } - - /* Go to the failure path */ - DPRINT1("Invalid image architecture: %lx\n", ImageInformation.Machine); - Result = FALSE; - goto Quickie; + DPRINT1("Can't execute a DLL\n"); + SetLastError(ERROR_BAD_EXE_FORMAT); + goto Cleanup; } - /* Check if this isn't a Windows image */ - if ((ImageInformation.SubSystemType != IMAGE_SUBSYSTEM_WINDOWS_GUI) && - (ImageInformation.SubSystemType != IMAGE_SUBSYSTEM_WINDOWS_CUI)) - { - /* Get rid of section-related information since we'll retry */ - NtClose(SectionHandle); - SectionHandle = NULL; - QuerySection = FALSE; + /* FIXME: Check for Debugger */ - /* The only other non-Windows image type we support here is POSIX */ - if (ImageInformation.SubSystemType != IMAGE_SUBSYSTEM_POSIX_CUI) - { - /* Bail out if it's something else */ - SetLastError(ERROR_CHILD_NOT_COMPLETE); - Result = FALSE; - goto Quickie; - } + /* FIXME: Check if Machine Type and SubSys Version Match */ - /* Now build the command-line to have posix launch this image */ - Result = BuildSubSysCommandLine(L"POSIX /P ", - lpApplicationName, - lpCommandLine, - &DebuggerString); - if (!Result) - { - /* Bail out if that failed */ - DPRINT1("Subsystem command line failed\n"); - goto Quickie; - } - - /* And re-try launching the process, with the new command-line now */ - lpCommandLine = DebuggerString.Buffer; - lpApplicationName = NULL; - - /* We've already done all these checks, don't do them again */ - SkipSaferAndAppCompat = TRUE; - DPRINT1("Retrying with: %S\n", lpCommandLine); - goto AppNameRetry; - } - - /* Was this image built for a version of Windows whose images we can run? */ - Result = BasepIsImageVersionOk(ImageInformation.SubSystemMajorVersion, - ImageInformation.SubSystemMinorVersion); - if (!Result) + /* We don't support POSIX or anything else for now */ + if (IMAGE_SUBSYSTEM_WINDOWS_GUI != SectionImageInfo.SubSystemType && + IMAGE_SUBSYSTEM_WINDOWS_CUI != SectionImageInfo.SubSystemType) { - /* It was not, bail out */ - DPRINT1("Invalid subsystem version: %d.%d\n", - ImageInformation.SubSystemMajorVersion, - ImageInformation.SubSystemMinorVersion); - SetLastError(ERROR_BAD_EXE_FORMAT); - goto Quickie; + DPRINT1("Invalid subsystem %d\n", SectionImageInfo.SubSystemType); + /* + * Despite the name of the error code suggests, it corresponds to the + * well-known "The %1 application cannot be run in Win32 mode" message. + */ + SetLastError(ERROR_CHILD_NOT_COMPLETE); + goto Cleanup; } - /* Check if there is a debugger associated with the application */ - if (DebuggerCmdLine) + if (IMAGE_SUBSYSTEM_WINDOWS_GUI == SectionImageInfo.SubSystemType) { - /* Get the length of the command line */ - n = wcslen(lpCommandLine); - if (!n) - { - /* There's no command line, use the application name instead */ - lpCommandLine = (LPWSTR)lpApplicationName; - n = wcslen(lpCommandLine); - } - - /* Protect against overflow */ - if (n > UNICODE_STRING_MAX_CHARS) - { - BaseSetLastNTError(STATUS_NAME_TOO_LONG); - Result = FALSE; - goto Quickie; - } - - /* Now add the length of the debugger command-line */ - n += wcslen(DebuggerCmdLine); - - /* Again make sure we don't overflow */ - if (n > UNICODE_STRING_MAX_CHARS) - { - BaseSetLastNTError(STATUS_NAME_TOO_LONG); - Result = FALSE; - goto Quickie; - } - - /* Account for the quotes and space between the two */ - n += ((sizeof('""') * 2) + sizeof(' ')); - - /* Convert to bytes, and make sure we don't overflow */ - n *= sizeof(WCHAR); - if (n > UNICODE_STRING_MAX_BYTES) - { - BaseSetLastNTError(STATUS_NAME_TOO_LONG); - Result = FALSE; - goto Quickie; - } - - /* Allocate space for the string */ - DebuggerString.Buffer = RtlAllocateHeap(RtlGetProcessHeap(), 0, n); - if (!DebuggerString.Buffer) - { - SetLastError(ERROR_NOT_ENOUGH_MEMORY); - Result = FALSE; - goto Quickie; - } - - /* Set the length */ - RtlInitEmptyUnicodeString(&DebuggerString, - DebuggerString.Buffer, - n); - - /* Now perform the command line creation */ - ImageDbgStatus = RtlAppendUnicodeToString(&DebuggerString, - DebuggerCmdLine); - ASSERT(NT_SUCCESS(ImageDbgStatus)); - ImageDbgStatus = RtlAppendUnicodeToString(&DebuggerString, L" "); - ASSERT(NT_SUCCESS(ImageDbgStatus)); - ImageDbgStatus = RtlAppendUnicodeToString(&DebuggerString, lpCommandLine); - ASSERT(NT_SUCCESS(ImageDbgStatus)); - - /* Make sure it all looks nice */ - DbgPrint("BASE: Calling debugger with '%wZ'\n", &DebuggerString); - - /* Update the command line and application name */ - lpCommandLine = DebuggerString.Buffer; - lpApplicationName = NULL; - - /* Close all temporary state */ - NtClose(SectionHandle); - SectionHandle = NULL; - QuerySection = FALSE; - - /* Free all temporary memory */ - RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer); - NameBuffer = NULL; - RtlFreeHeap(RtlGetProcessHeap(), 0, FreeBuffer); - FreeBuffer = NULL; - RtlFreeHeap(RtlGetProcessHeap(), 0, DebuggerCmdLine); - DebuggerCmdLine = NULL; - DPRINT1("Retrying with: %S\n", lpCommandLine); - goto AppNameRetry; + /* Do not create a console for GUI applications */ + dwCreationFlags &= ~CREATE_NEW_CONSOLE; + dwCreationFlags |= DETACHED_PROCESS; } /* Initialize the process object attributes */ ObjectAttributes = BaseFormatObjectAttributes(&LocalObjectAttributes, - lpProcessAttributes, - NULL); - if ((hUserToken) && (lpProcessAttributes)) - { - /* Auggment them with information from the user */ + lpProcessAttributes, + NULL); - LocalProcessAttributes = *lpProcessAttributes; - LocalProcessAttributes.lpSecurityDescriptor = NULL; - ObjectAttributes = BaseFormatObjectAttributes(&LocalObjectAttributes, - &LocalProcessAttributes, - NULL); - } - /* Check if we're going to be debugged */ if (dwCreationFlags & DEBUG_PROCESS) { - /* Set process flag */ - Flags |= PROCESS_CREATE_FLAGS_BREAKAWAY; + /* FIXME: Set process flag */ } /* Check if we're going to be debugged */ @@ -3832,755 +3034,275 @@ { DPRINT1("Failed to connect to DbgUI!\n"); BaseSetLastNTError(Status); - Result = FALSE; - goto Quickie; + goto Cleanup; } /* Get the debug object */ - DebugHandle = DbgUiGetThreadDebugObject(); + hDebug = DbgUiGetThreadDebugObject(); /* Check if only this process will be debugged */ if (dwCreationFlags & DEBUG_ONLY_THIS_PROCESS) { /* Set process flag */ - Flags |= PROCESS_CREATE_FLAGS_NO_DEBUG_INHERIT; + hDebug = (HANDLE)((ULONG_PTR)hDebug | 0x1); } } - /* Set inherit flag */ - if (bInheritHandles) Flags |= PROCESS_CREATE_FLAGS_INHERIT_HANDLES; - - /* Check if the process should be created with large pages */ - HavePrivilege = FALSE; - PrivilegeState = NULL; - if (Flags & PROCESS_CREATE_FLAGS_LARGE_PAGES) - { - /* Acquire the required privilege so that the kernel won't fail the call */ - PrivilegeValue = SE_LOCK_MEMORY_PRIVILEGE; - Status = RtlAcquirePrivilege(&PrivilegeValue, TRUE, FALSE, &PrivilegeState); - if (NT_SUCCESS(Status)) - { - /* Remember to release it later */ - HavePrivilege = TRUE; - } - } - - /* Save the current TIB value since kernel overwrites it to store PEB */ - TibValue = Teb->NtTib.ArbitraryUserPointer; - - /* Tell the kernel to create the process */ - Status = NtCreateProcessEx(&ProcessHandle, - PROCESS_ALL_ACCESS, - ObjectAttributes, - NtCurrentProcess(), - Flags, - SectionHandle, - DebugHandle, - NULL, - InJob); - - /* Load the PEB address from the hacky location where the kernel stores it */ - RemotePeb = Teb->NtTib.ArbitraryUserPointer; - - /* And restore the old TIB value */ - Teb->NtTib.ArbitraryUserPointer = TibValue; - - /* Release the large page privilege if we had acquired it */ - if (HavePrivilege) RtlReleasePrivilege(PrivilegeState); - - /* And now check if the kernel failed to create the process */ + /* Create the Process */ + Status = NtCreateProcess(&hProcess, + PROCESS_ALL_ACCESS, + ObjectAttributes, + NtCurrentProcess(), + (BOOLEAN)bInheritHandles, + hSection, + hDebug, + NULL); if (!NT_SUCCESS(Status)) { - /* Go to failure path */ - DPRINT1("Failed to create process: %lx\n", Status); + DPRINT1("Unable to create process, status 0x%x\n", Status); BaseSetLastNTError(Status); - Result = FALSE; - goto Quickie; + goto Cleanup; } - /* Check if there is a priority class to set */ - if (PriorityClass.PriorityClass) + if (PriorityClass.PriorityClass != PROCESS_PRIORITY_CLASS_INVALID) { - /* Reset current privilege state */ - RealTimePrivilegeState = NULL; - - /* Is realtime priority being requested? */ - if (PriorityClass.PriorityClass == REALTIME_PRIORITY_CLASS) - { - /* Check if the caller has real-time access, and enable it if so */ - RealTimePrivilegeState = BasepIsRealtimeAllowed(TRUE); - } - - /* Set the new priority class and release the privilege */ - Status = NtSetInformationProcess(ProcessHandle, + /* Set new class */ + Status = NtSetInformationProcess(hProcess, ProcessPriorityClass, &PriorityClass, sizeof(PROCESS_PRIORITY_CLASS)); - if (RealTimePrivilegeState) RtlReleasePrivilege(RealTimePrivilegeState); - - /* Check if we failed to set the priority class */ - if (!NT_SUCCESS(Status)) + if(!NT_SUCCESS(Status)) { - /* Bail out on failure */ - DPRINT1("Failed to set priority class: %lx\n", Status); + DPRINT1("Unable to set new process priority, status 0x%x\n", Status); BaseSetLastNTError(Status); - Result = FALSE; - goto Quickie; + goto Cleanup; } } - /* Check if the caller wants the default error mode */ + /* Set Error Mode */ if (dwCreationFlags & CREATE_DEFAULT_ERROR_MODE) { - /* Set Error Mode to only fail on critical errors */ - HardErrorMode = SEM_FAILCRITICALERRORS; - NtSetInformationProcess(ProcessHandle, + ULONG ErrorMode = SEM_FAILCRITICALERRORS; + NtSetInformationProcess(hProcess, ProcessDefaultHardErrorMode, - &HardErrorMode, + &ErrorMode, sizeof(ULONG)); } - /* Check if this was a VDM binary */ - if (VdmBinaryType) - { - /* Update VDM by telling it the process has now been created */ - VdmWaitObject = ProcessHandle; - Result = BaseUpdateVDMEntry(VdmEntryUpdateProcess, - &VdmWaitObject, - VdmTask, - VdmBinaryType); - { - /* Bail out on failure */ - DPRINT1("Failed to update VDM with wait object\n"); - VdmWaitObject = NULL; - goto Quickie; - } - - /* At this point, a failure means VDM has to undo all the state */ - VdmUndoLevel |= VDM_UNDO_FULL; - } - - /* Check if VDM needed reserved low-memory */ - if (VdmReserve) - { - /* Reserve the requested allocation */ - Status = NtAllocateVirtualMemory(ProcessHandle, - &BaseAddress, - 0, - &VdmReserve, - MEM_RESERVE, - PAGE_EXECUTE_READWRITE); - if (!NT_SUCCESS(Status)) - { - /* Bail out on failure */ - DPRINT1("Failed to reserved memory for VDM: %lx\n", Status); - BaseSetLastNTError(Status); - Result = FALSE; - goto Quickie; - } - } - - /* Check if we've already queried information on the section */ - if (!QuerySection) - { - /* We haven't, so get some information about the executable */ - Status = NtQuerySection(SectionHandle, - SectionImageInformation, - &ImageInformation, - sizeof(ImageInformation), - NULL); - if (!NT_SUCCESS(Status)) - { - /* Bail out on failure */ - DPRINT1("Failed to query section: %lx\n", Status); - BaseSetLastNTError(Status); - Result = FALSE; - goto Quickie; - } - - /* If we encounter a restart, don't re-query this information again */ - QuerySection = TRUE; - } - - /* Do we need to apply SxS to this image? */ - if (!(ImageInformation.DllCharacteristics & IMAGE_DLLCHARACTERISTICS_NO_ISOLATION)) - { - /* Too bad, we don't support this yet */ - DPRINT1("Image should receive SxS Fusion Isolation\n"); - } - - /* There's some SxS flag that we need to set if fusion flags have 1 set */ - if (FusionFlags & 1) CreateProcessMsg->Sxs.Flags |= 0x10; - - /* Check if we have a current directory */ + /* Convert the directory to a full path */ if (lpCurrentDirectory) { - /* Allocate a buffer so we can keep a Unicode copy */ - DPRINT1("Current directory: %S\n", lpCurrentDirectory); + /* Allocate a buffer */ CurrentDirectory = RtlAllocateHeap(RtlGetProcessHeap(), 0, - (MAX_PATH * sizeof(WCHAR)) + - sizeof(UNICODE_NULL)); - if (!CurrentDirectory) + (MAX_PATH + 1) * sizeof(WCHAR)); + if (CurrentDirectory == NULL) { - /* Bail out if this failed */ - BaseSetLastNTError(STATUS_NO_MEMORY); - Result = FALSE; - goto Quickie; + DPRINT1("Cannot allocate memory for directory name\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto Cleanup; } - /* Get the length in Unicode */ - Length = GetFullPathNameW(lpCurrentDirectory, - MAX_PATH, - CurrentDirectory, - &FilePart); - if (Length > MAX_PATH) + /* Get the length */ + if (GetFullPathNameW(lpCurrentDirectory, + MAX_PATH, + CurrentDirectory, + &CurrentDirectoryPart) > MAX_PATH) { - /* The directory is too long, so bail out */ + DPRINT1("Directory name too long\n"); SetLastError(ERROR_DIRECTORY); - Result = FALSE; - goto Quickie; + goto Cleanup; } - - /* Make sure the directory is actually valid */ - CurdirLength = GetFileAttributesW(CurrentDirectory); - if ((CurdirLength == 0xffffffff) || - !(CurdirLength & FILE_ATTRIBUTE_DIRECTORY)) - { - /* It isn't, so bail out */ - DPRINT1("Current directory is invalid\n"); - SetLastError(ERROR_DIRECTORY); - Result = FALSE; - goto Quickie; - } } /* Insert quotes if needed */ - if ((QuotesNeeded) || (CmdLineIsAppName)) + if (QuotesNeeded || CmdLineIsAppName) { - /* Allocate our buffer, plus enough space for quotes and a NULL */ + /* Allocate a buffer */ QuotedCmdLine = RtlAllocateHeap(RtlGetProcessHeap(), 0, - (wcslen(lpCommandLine) * sizeof(WCHAR)) + - (2 * sizeof(L'\"') + sizeof(UNICODE_NULL))); - if (QuotedCmdLine) + (wcslen(lpCommandLine) + 2 + 1) * + sizeof(WCHAR)); + if (QuotedCmdLine == NULL) { - /* Copy the first quote */ - wcscpy(QuotedCmdLine, L"\""); + DPRINT1("Cannot allocate memory for quoted command line\n"); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto Cleanup; + } - /* Save the current null-character */ - if (QuotesNeeded) - { - SaveChar = *NullBuffer; - *NullBuffer = UNICODE_NULL; - } + /* Copy the first quote */ + wcscpy(QuotedCmdLine, L"\""); - /* Copy the command line and the final quote */ - wcscat(QuotedCmdLine, lpCommandLine); - wcscat(QuotedCmdLine, L"\""); - - /* Copy the null-char back */ - if (QuotesNeeded) - { - *NullBuffer = SaveChar; - wcscat(QuotedCmdLine, NullBuffer); - } - } - else + /* Save a null char */ + if (QuotesNeeded) { - /* We can't put quotes around the thing, so try it anyway */ - if (QuotesNeeded) QuotesNeeded = FALSE; - if (CmdLineIsAppName) CmdLineIsAppName = FALSE; + SaveChar = *NullBuffer; + *NullBuffer = UNICODE_NULL; } - } - /* Use isolation if needed */ - if (CreateProcessMsg->Sxs.Flags & 1) ParameterFlags |= 1; + /* Add the command line and the finishing quote */ + wcscat(QuotedCmdLine, lpCommandLine); + wcscat(QuotedCmdLine, L"\""); - /* Set the new command-line if needed */ - if ((QuotesNeeded) || (CmdLineIsAppName)) lpCommandLine = QuotedCmdLine; + /* Add the null char */ + if (QuotesNeeded) + { + *NullBuffer = SaveChar; + wcscat(QuotedCmdLine, NullBuffer); + } - /* Call the helper function in charge of RTL_USER_PROCESS_PARAMETERS */ - Result = BasePushProcessParameters(ParameterFlags, - ProcessHandle, - RemotePeb, - lpApplicationName, - CurrentDirectory, - lpCommandLine, - lpEnvironment, - &StartupInfo, - dwCreationFlags | NoWindow, - bInheritHandles, - IsWowApp ? IMAGE_SUBSYSTEM_WINDOWS_GUI: 0, - AppCompatData, - AppCompatDataSize); - if (!Result) - { - /* The remote process would have an undefined state, so fail the call */ - DPRINT1("BasePushProcessParameters failed\n"); - goto Quickie; + DPRINT("Quoted CmdLine: %S\n", QuotedCmdLine); } - /* Free the VDM command line string as it's no longer needed */ - RtlFreeUnicodeString(&VdmString); - VdmString.Buffer = NULL; - - /* Non-VDM console applications usually inherit handles unless specified */ - if (!(VdmBinaryType) && - !(bInheritHandles) && - !(StartupInfo.dwFlags & STARTF_USESTDHANDLES) && - !(dwCreationFlags & (CREATE_NO_WINDOW | - CREATE_NEW_CONSOLE | - DETACHED_PROCESS)) && - (ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_WINDOWS_CUI)) + if (Escape) { - /* Get the remote parameters */ - Status = NtReadVirtualMemory(ProcessHandle, - &RemotePeb->ProcessParameters, - &ProcessParameters, - sizeof(PRTL_USER_PROCESS_PARAMETERS), - NULL); - if (NT_SUCCESS(Status)) + if (QuotedCmdLine == NULL) { - /* Duplicate standard input unless it's a console handle */ - if (!IsConsoleHandle(Peb->ProcessParameters->StandardInput)) + QuotedCmdLine = RtlAllocateHeap(RtlGetProcessHeap(), + 0, + (wcslen(lpCommandLine) + 1) * sizeof(WCHAR)); + if (QuotedCmdLine == NULL) { - StuffStdHandle(ProcessHandle, - Peb->ProcessParameters->StandardInput, - &ProcessParameters->StandardInput); + SetLastError(ERROR_NOT_ENOUGH_MEMORY); + goto Cleanup; } + wcscpy(QuotedCmdLine, lpCommandLine); + } - /* Duplicate standard output unless it's a console handle */ - if (!IsConsoleHandle(Peb->ProcessParameters->StandardOutput)) + ScanString = QuotedCmdLine; + while (NULL != (ScanString = wcschr(ScanString, L'^'))) + { + ScanString++; + if (*ScanString == L'\"' || *ScanString == L'^' || *ScanString == L'\\') { - StuffStdHandle(ProcessHandle, - Peb->ProcessParameters->StandardOutput, - &ProcessParameters->StandardOutput); + memmove(ScanString-1, ScanString, wcslen(ScanString) * sizeof(WCHAR) + sizeof(WCHAR)); } - - /* Duplicate standard error unless it's a console handle */ - if (!IsConsoleHandle(Peb->ProcessParameters->StandardError)) - { - StuffStdHandle(ProcessHandle, - Peb->ProcessParameters->StandardError, - &ProcessParameters->StandardError); - } } } - /* Create the Thread's Stack */ - StackSize = max(256 * 1024, ImageInformation.MaximumStackSize); - Status = BaseCreateStack(ProcessHandle, - ImageInformation.CommittedStackSize, - StackSize, - &InitialTeb); - if (!NT_SUCCESS(Status)) - { - DPRINT1("Creating the thread stack failed: %lx\n", Status); - BaseSetLastNTError(Status); - Result = FALSE; - goto Quickie; - } + /* Get the Process Information */ + Status = NtQueryInformationProcess(hProcess, + ProcessBasicInformation, + &ProcessBasicInfo, + sizeof(ProcessBasicInfo), + NULL); - /* Create the Thread's Context */ - BaseInitializeContext(&Context, - Peb, - ImageInformation.TransferAddress, - InitialTeb.StackBase, - 0); - - /* Convert the thread attributes */ - ObjectAttributes = BaseFormatObjectAttributes(&LocalObjectAttributes, - lpThreadAttributes, - NULL); - if ((hUserToken) && (lpThreadAttributes)) + /* Convert the environment */ + if(lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)) { - /* If the caller specified a user token, zero the security descriptor */ - LocalThreadAttributes = *lpThreadAttributes; - LocalThreadAttributes.lpSecurityDescriptor = NULL; - ObjectAttributes = BaseFormatObjectAttributes(&LocalObjectAttributes, - &LocalThreadAttributes, - NULL); + lpEnvironment = BasepConvertUnicodeEnvironment(&EnvSize, lpEnvironment); + if (!lpEnvironment) goto Cleanup; } - /* Create the Kernel Thread Object */ - Status = NtCreateThread(&ThreadHandle, - THREAD_ALL_ACCESS, - ObjectAttributes, - ProcessHandle, - &ClientId, - &Context, - &InitialTeb, - TRUE); - if (!NT_SUCCESS(Status)) - { - /* A process is not allowed to exist without a main thread, so fail */ - DPRINT1("Creating the main thread failed: %lx\n", Status); - BaseSetLastNTError(Status); - Result = FALSE; - goto Quickie; - } + /* Create Process Environment */ + RemotePeb = ProcessBasicInfo.PebBaseAddress; + Ret = BasePushProcessParameters(0, + hProcess, + RemotePeb, + (LPWSTR)lpApplicationName, + CurrentDirectory, + (QuotesNeeded || CmdLineIsAppName || Escape) ? + QuotedCmdLine : lpCommandLine, + lpEnvironment, + &StartupInfo, + dwCreationFlags, + bInheritHandles, + 0, + NULL, + 0); + if (!Ret) goto Cleanup; - /* Begin filling out the CSRSS message, first with our IDs and handles */ - CreateProcessMsg->ProcessHandle = ProcessHandle; - CreateProcessMsg->ThreadHandle = ThreadHandle; - CreateProcessMsg->ClientId = ClientId; - - /* Write the remote PEB address and clear it locally, we no longer use it */ - CreateProcessMsg->PebAddressNative = RemotePeb; - CreateProcessMsg->PebAddressWow64 = (ULONG)RemotePeb; - RemotePeb = NULL; - - /* Now check what kind of architecture this image was made for */ - switch (ImageInformation.Machine) + /* Cleanup Environment */ + if (lpEnvironment && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)) { - /* IA32, IA64 and AMD64 are supported in Server 2003 */ - case IMAGE_FILE_MACHINE_I386: - CreateProcessMsg->ProcessorArchitecture = PROCESSOR_ARCHITECTURE_INTEL; - break; - case IMAGE_FILE_MACHINE_IA64: - CreateProcessMsg->ProcessorArchitecture = PROCESSOR_ARCHITECTURE_IA64; - break; - case IMAGE_FILE_MACHINE_AMD64: - CreateProcessMsg->ProcessorArchitecture = PROCESSOR_ARCHITECTURE_AMD64; - break; - - /* Anything else results in image unknown -- but no failure */ - default: - DbgPrint("kernel32: No mapping for ImageInformation.Machine == %04x\n", - ImageInformation.Machine); - CreateProcessMsg->ProcessorArchitecture = PROCESSOR_ARCHITECTURE_UNKNOWN; - break; + RtlDestroyEnvironment(lpEnvironment); } - /* Write the input creation flags except any debugger-related flags */ - CreateProcessMsg->CreationFlags = dwCreationFlags & - ~(DEBUG_PROCESS | DEBUG_ONLY_THIS_PROCESS); + /* Close the section */ + NtClose(hSection); + hSection = NULL; - /* CSRSS needs to know if this is a GUI app or not */ - if ((ImageInformation.SubSystemType == IMAGE_SUBSYSTEM_WINDOWS_GUI) || - (IsWowApp)) + /* Duplicate the handles if needed */ + if (!bInheritHandles && !(StartupInfo.dwFlags & STARTF_USESTDHANDLES) && + SectionImageInfo.SubSystemType == IMAGE_SUBSYSTEM_WINDOWS_CUI) { - /* - * For GUI apps we turn on the 2nd bit. This allow CSRSS server dlls - * (basesrv in particular) to know whether or not this is a GUI or a - * TUI application. - */ - AddToHandle(CreateProcessMsg->ProcessHandle, 2); + PRTL_USER_PROCESS_PARAMETERS RemoteParameters; - /* Also check if the parent is also a GUI process */ - NtHeaders = RtlImageNtHeader(GetModuleHandle(NULL)); - if ((NtHeaders) && - (NtHeaders->OptionalHeader.Subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI)) + /* Get the remote parameters */ + Status = NtReadVirtualMemory(hProcess, + &RemotePeb->ProcessParameters, + &RemoteParameters, + sizeof(PVOID), + NULL); + if (!NT_SUCCESS(Status)) { - /* Let it know that it should display the hourglass mouse cursor */ - AddToHandle(CreateProcessMsg->ProcessHandle, 1); + DPRINT1("Failed to read memory\n"); + goto Cleanup; } - } - /* For all apps, if this flag is on, the hourglass mouse cursor is shown */ - if (StartupInfo.dwFlags & STARTF_FORCEONFEEDBACK) - { - AddToHandle(CreateProcessMsg->ProcessHandle, 1); + /* Duplicate and write the handles */ + BasepDuplicateAndWriteHandle(hProcess, + OurPeb->ProcessParameters->StandardInput, + &RemoteParameters->StandardInput); + BasepDuplicateAndWriteHandle(hProcess, + OurPeb->ProcessParameters->StandardOutput, + &RemoteParameters->StandardOutput); + BasepDuplicateAndWriteHandle(hProcess, + OurPeb->ProcessParameters->StandardError, + &RemoteParameters->StandardError); } - /* Likewise, the opposite holds as well */ - if (StartupInfo.dwFlags & STARTF_FORCEOFFFEEDBACK) - { - RemoveFromHandle(CreateProcessMsg->ProcessHandle, 1); - } + /* Create the first thread */ + DPRINT("Creating thread for process (EntryPoint = 0x%p)\n", + SectionImageInfo.TransferAddress); + hThread = BasepCreateFirstThread(hProcess, + lpThreadAttributes, + &SectionImageInfo, + &ClientId, + dwCreationFlags); - /* Also store which kind of VDM app (if any) this is */ - CreateProcessMsg->VdmBinaryType = VdmBinaryType; - - /* And if it really is a VDM app... */ - if (VdmBinaryType) + if (hThread == NULL) { - /* Store the task ID and VDM console handle */ - CreateProcessMsg->hVDM = VdmTask ? 0 : Peb->ProcessParameters->ConsoleHandle; - CreateProcessMsg->VdmTask = VdmTask; + DPRINT1("Could not create Initial Thread\n"); + /* FIXME - set last error code */ + goto Cleanup; } - else if (VdmReserve) - { - /* Extended VDM, set a flag */ - CreateProcessMsg->VdmBinaryType |= BINARY_TYPE_WOW_EX; - } - /* Check if there's side-by-side assembly data associated with the process */ - if (CreateProcessMsg->Sxs.Flags) - { - /* This should not happen in ReactOS yet */ - DPRINT1("This is an SxS Message -- should not happen yet\n"); - BaseSetLastNTError(STATUS_NOT_IMPLEMENTED); - NtTerminateProcess(ProcessHandle, STATUS_NOT_IMPLEMENTED); - Result = FALSE; - goto Quickie; - } - - /* We are finally ready to call CSRSS to tell it about our new process! */ - CsrClientCallServer((PCSR_API_MESSAGE)&CsrMsg, - CaptureBuffer, - CSR_CREATE_API_NUMBER(BASESRV_SERVERDLL_INDEX, - BasepCreateProcess), - sizeof(*CreateProcessMsg)); - - /* CSRSS has returned, free the capture buffer now if we had one */ - if (CaptureBuffer) - { - CsrFreeCaptureBuffer(CaptureBuffer); - CaptureBuffer = NULL; - } - - /* Check if CSRSS failed to accept ownership of the new Windows process */ - if (!NT_SUCCESS(CsrMsg.Status)) - { - /* Terminate the process and enter failure path with the CSRSS status */ - DPRINT1("Failed to tell csrss about new process\n"); - BaseSetLastNTError(CsrMsg.Status); - NtTerminateProcess(ProcessHandle, CsrMsg.Status); - Result = FALSE; - goto Quickie; - } - - /* Check if we have a token due to Authz/Safer, not passed by the user */ - if ((TokenHandle) && !(hUserToken)) - { - /* Replace the process and/or thread token with the one from Safer */ - Status = BasepReplaceProcessThreadTokens(TokenHandle, - ProcessHandle, - ThreadHandle); - if (!NT_SUCCESS(Status)) - { - /* If this failed, kill the process and enter the failure path */ - DPRINT1("Failed to update process token: %lx\n", Status); - NtTerminateProcess(ProcessHandle, Status); - BaseSetLastNTError(Status); - Result = FALSE; - goto Quickie; - } - } - - /* Check if a job was associated with this process */ - if (JobHandle) - { - /* Bind the process and job together now */ - Status = NtAssignProcessToJobObject(JobHandle, ProcessHandle); - if (!NT_SUCCESS(Status)) - { - /* Kill the process and enter the failure path if binding failed */ - DPRINT1("Failed to assign process to job: %lx\n", Status); - NtTerminateProcess(ProcessHandle, STATUS_ACCESS_DENIED); - BaseSetLastNTError(Status); - Result = FALSE; - goto Quickie; - } - } - - /* Finally, resume the thread to actually get the process started */ if (!(dwCreationFlags & CREATE_SUSPENDED)) { - NtResumeThread(ThreadHandle, &ResumeCount); + NtResumeThread(hThread, &Dummy); } -VdmShortCircuit: - /* We made it this far, meaning we have a fully created process and thread */ - Result = TRUE; + /* Return Data */ + lpProcessInformation->dwProcessId = (DWORD)ClientId.UniqueProcess; + lpProcessInformation->dwThreadId = (DWORD)ClientId.UniqueThread; + lpProcessInformation->hProcess = hProcess; + lpProcessInformation->hThread = hThread; + DPRINT("hThread[%p]: %p inside hProcess[%p]: %p\n", hThread, + ClientId.UniqueThread, ClientId.UniqueProcess, hProcess); + hProcess = hThread = NULL; + Ret = TRUE; - /* Anyone doing a VDM undo should now undo everything, since we are done */ - if (VdmUndoLevel) VdmUndoLevel |= VDM_UNDO_COMPLETED; +Cleanup: + /* De-allocate heap strings */ + if (NameBuffer) RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer); + if (ApplicationName.Buffer) + RtlFreeHeap(RtlGetProcessHeap(), 0, ApplicationName.Buffer); + if (CurrentDirectory) RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDirectory); + if (QuotedCmdLine) RtlFreeHeap(RtlGetProcessHeap(), 0, QuotedCmdLine); - /* Having a VDM wait object implies this must be a VDM process */ - if (VdmWaitObject) + /* Kill any handles still alive */ + if (hSection) NtClose(hSection); + if (hThread) { - /* Check if it's a 16-bit separate WOW process */ - if (VdmBinaryType == BINARY_TYPE_SEPARATE_WOW) - { - /* OR-in the special flag to indicate this, and return to caller */ - AddToHandle(VdmWaitObject, 2); - lpProcessInformation->hProcess = VdmWaitObject; - - /* Check if this was a re-used VDM */ - if (VdmUndoLevel & VDM_UNDO_REUSE) - { - /* No Client ID should be returned in this case */ - ClientId.UniqueProcess = 0; - ClientId.UniqueThread = 0; - } - } - else - { - /* OR-in the special flag to indicate this is not a separate VDM */ - AddToHandle(VdmWaitObject, 1); - - /* Return handle to the caller */ - lpProcessInformation->hProcess = VdmWaitObject; - } - - /* Close the original process handle, since it's not needed for VDM */ - if (ProcessHandle) NtClose(ProcessHandle); + /* We don't know any more details than this */ + NtTerminateProcess(hProcess, STATUS_UNSUCCESSFUL); + NtClose(hThread); } - else - { - /* This is a regular process, so return the real process handle */ - lpProcessInformation->hProcess = ProcessHandle; - } + if (hProcess) NtClose(hProcess); - /* Return the rest of the process information based on what we have so far */ - lpProcessInformation->hThread = ThreadHandle; - lpProcessInformation->dwProcessId = HandleToUlong(ClientId.UniqueProcess); - lpProcessInformation->dwThreadId = HandleToUlong(ClientId.UniqueThread); - - /* NULL these out here so we know to treat this as a success scenario */ - ProcessHandle = NULL; - ThreadHandle = NULL; - -Quickie: - /* Free the debugger command line if one was allocated */ - if (DebuggerCmdLine) RtlFreeHeap(RtlGetProcessHeap(), 0, DebuggerCmdLine); - - /* Check if an SxS full path as queried */ - if (PathBuffer) - { - /* Reinitialize the executable path */ - RtlInitEmptyUnicodeString(&SxsWin32ExePath, NULL, 0); - SxsWin32ExePath.Length = 0; - - /* Free the path buffer */ - RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer); - } - -#if _SXS_SUPPORT_ENABLED_ - /* Check if this was a non-VDM process */ - if (!VdmBinaryType) - { - /* Then it must've had SxS data, so close the handles used for it */ - BasepSxsCloseHandles(&Handles); - BasepSxsCloseHandles(&FileHandles); - - /* Check if we built SxS byte buffers for this create process request */ - if (SxsConglomeratedBuffer) - { - /* Loop all of them */ - for (i = 0; i < 5; i++) - { - /* Check if this one was allocated */ - ThisBuffer = SxsStaticBuffers[i]; - if (ThisBuffer) - { - /* Get the underlying RTL_BUFFER structure */ - ByteBuffer = &ThisBuffer->ByteBuffer; - if ((ThisBuffer != (PVOID)-8) && (ByteBuffer->Buffer)) - { - /* Check if it was dynamic */ - if (ByteBuffer->Buffer != ByteBuffer->StaticBuffer) - { - /* Free it from the heap */ - FreeString.Buffer = (PWCHAR)ByteBuffer->Buffer; - RtlFreeUnicodeString(&FreeString); - } - - /* Reset the buffer to its static data */ - ByteBuffer->Buffer = ByteBuffer->StaticBuffer; - ByteBuffer->Size = ByteBuffer->StaticSize; - } - - /* Reset the string to the static buffer */ - RtlInitEmptyUnicodeString(&ThisBuffer->String, - (PWCHAR)ByteBuffer->StaticBuffer, - ByteBuffer->StaticSize); - if (ThisBuffer->String.Buffer) - { - /* Also NULL-terminate it */ - *ThisBuffer->String.Buffer = UNICODE_NULL; - } - } - } - } - } -#endif - /* Check if an environment was passed in */ - if ((lpEnvironment) && !(dwCreationFlags & CREATE_UNICODE_ENVIRONMENT)) - { - /* Destroy it */ - RtlDestroyEnvironment(lpEnvironment); - - /* If this was the VDM environment too, clear that as well */ - if (VdmUnicodeEnv.Buffer == lpEnvironment) VdmUnicodeEnv.Buffer = NULL; - lpEnvironment = NULL; - } - - /* Unconditionally free all the name parsing buffers we always allocate */ - RtlFreeHeap(RtlGetProcessHeap(), 0, QuotedCmdLine); - RtlFreeHeap(RtlGetProcessHeap(), 0, NameBuffer); - RtlFreeHeap(RtlGetProcessHeap(), 0, CurrentDirectory); - RtlFreeHeap(RtlGetProcessHeap(), 0, FreeBuffer); - - /* Close open file/section handles */ - if (FileHandle) NtClose(FileHandle); - if (SectionHandle) NtClose(SectionHandle); - - /* If we have a thread handle, this was a failure path */ - if (ThreadHandle) - { - /* So kill the process and close the thread handle */ - NtTerminateProcess(ProcessHandle, 0); - NtClose(ThreadHandle); - } - - /* If we have a process handle, this was a failure path, so close it */ - if (ProcessHandle) NtClose(ProcessHandle); - - /* Thread/process handles, if any, are now processed. Now close this one. */ - if (JobHandle) NtClose(JobHandle); - - /* Check if we had created a token */ - if (TokenHandle) - { - /* And if the user asked for one */ - if (hUserToken) - { - /* Then return it */ - *hNewToken = TokenHandle; - } - else - { - /* User didn't want it, so we used it temporarily -- close it */ - NtClose(TokenHandle); - } - } - - /* Free any temporary app compatibility data, it's no longer needed */ - BasepFreeAppCompatData(AppCompatData, AppCompatSxsData); - - /* Free a few strings. The API takes care of these possibly being NULL */ - RtlFreeUnicodeString(&VdmString); - RtlFreeUnicodeString(&DebuggerString); - - /* Check if we had built any sort of VDM environment */ - if ((VdmAnsiEnv.Buffer) || (VdmUnicodeEnv.Buffer)) - { - /* Free it */ - BaseDestroyVDMEnvironment(&VdmAnsiEnv, &VdmUnicodeEnv); - } - - /* Check if this was any kind of VDM application that we ended up creating */ - if ((VdmUndoLevel) && (!(VdmUndoLevel & VDM_UNDO_COMPLETED))) - { - /* Send an undo */ - BaseUpdateVDMEntry(VdmEntryUndo, - (PHANDLE)&VdmTask, - VdmUndoLevel, - VdmBinaryType); - - /* And close whatever VDM handle we were using for notifications */ - if (VdmWaitObject) NtClose(VdmWaitObject); - } - - /* Check if we ended up here with an allocated search path, and free it */ - if (SearchPath) RtlFreeHeap(RtlGetProcessHeap(), 0, SearchPath); - - /* Finally, return the API's result */ - return Result; + /* Return Success */ + return Ret; } /* @@ -4600,7 +3322,7 @@ LPPROCESS_INFORMATION lpProcessInformation) { /* Call the internal (but exported) version */ - return CreateProcessInternalW(NULL, + return CreateProcessInternalW(0, lpApplicationName, lpCommandLine, lpProcessAttributes, @@ -4768,7 +3490,7 @@ LPPROCESS_INFORMATION lpProcessInformation) { /* Call the internal (but exported) version */ - return CreateProcessInternalA(NULL, + return CreateProcessInternalA(0, lpApplicationName, lpCommandLine, lpProcessAttributes, Index: include/reactos/libs/softx86 =================================================================== --- include/reactos/libs/softx86 (révision 59666) +++ include/reactos/libs/softx86 (copie de travail) Modification de propriétés sur include/reactos/libs/softx86 ___________________________________________________________________ Added: bugtraq:url ## -0,0 +1 ## +http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID% \ No newline at end of property Added: bugtraq:message ## -0,0 +1 ## +See issue #%BUGID% for more details. \ No newline at end of property Added: tsvn:logminsize ## -0,0 +1 ## +10 \ No newline at end of property Added: bugtraq:logregex ## -0,0 +1,2 ## +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+) \ No newline at end of property Index: include/reactos/libs/softx86/softx86.h =================================================================== --- include/reactos/libs/softx86/softx86.h (révision 0) +++ include/reactos/libs/softx86/softx86.h (copie de travail) @@ -0,0 +1,550 @@ + +#ifndef SOFTX86_H +#define SOFTX86_H + +/* get the Softx86 configuration defines */ +#include + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +/// version composed as follows: H.LL.SSSS +// where: H = major version number (any length) +// L = minor version number (2 digits) +// S = sub-minor version number (4 digits) +// +// The context structure is only allowed to change if the major (high) +// version number changes. +// +// This is v0.00.0033 +#define SOFTX86_VERSION_HI 0 +#define SOFTX86_VERSION_LO 0 +#define SOFTX86_VERSION_SUBLO 33 + +#ifdef __MINGW32__ // MINGW + +typedef unsigned char sx86_ubyte; +typedef signed char sx86_sbyte; +typedef unsigned short int sx86_uword; +typedef signed short int sx86_sword; +typedef unsigned int sx86_udword; +typedef signed int sx86_sdword; +typedef unsigned long long int sx86_uldword; +typedef signed long long int sx86_sldword; + +#elif WIN32 // MSVC + +typedef unsigned char sx86_ubyte; +typedef signed char sx86_sbyte; +typedef unsigned short int sx86_uword; +typedef signed short int sx86_sword; +typedef unsigned int sx86_udword; +typedef signed int sx86_sdword; +typedef unsigned __int64 sx86_uldword; +typedef signed __int64 sx86_sldword; + +#else // GCC 3.xx.xx + +typedef unsigned char sx86_ubyte; +typedef signed char sx86_sbyte; +typedef unsigned short int sx86_uword; +typedef signed short int sx86_sword; +typedef unsigned int sx86_udword; +typedef signed int sx86_sdword; +typedef unsigned long long int sx86_uldword; +typedef signed long long int sx86_sldword; + +#endif + +/* NOTE: All registers contain the CPU values in native byte order NOT little + Endian byte order! When loading values from RAM always use + the SWAP_WORD_FROM_LE() macro! */ +typedef union { + sx86_udword val; /* the entire 32-bit register as a whole (i.e. EAX) */ + +#if SX86_BYTE_ORDER == LE + + struct __dummy_w { + sx86_uword lo; /* lower 16 bits of register (i.e. AX) */ + sx86_uword hi; /* upper 16 bits of register */ + } w; + + struct __dummy_b { + sx86_ubyte lo; /* lower 8 bits of register (i.e. AL) */ + sx86_ubyte hi; /* bits 8-15 of register (i.e. AH) */ + sx86_ubyte extra[2]; + } b; + +#elif SX86_BYTE_ORDER == BE /* member order reversed from LE because byte order reversed */ + + struct __dummy_w { + sx86_uword hi; /* upper 16 bits of register */ + sx86_uword lo; /* lower 16 bits of register (i.e. AX) */ + } w; + + struct __dummy_b { + sx86_ubyte extra[2]; + sx86_ubyte hi; /* bits 8-15 of register (i.e. AH) */ + sx86_ubyte lo; /* lower 8 bits of register (i.e. AL) */ + } b; + +#endif + +} softx86_regval; + +typedef struct { + sx86_uword val; /* visible to program---the value */ + sx86_udword cached_linear; /* hidden---linear address of segment */ + sx86_udword cached_limit; /* hidden---limit of segment */ +} softx86_segregval; + +/*============================================================================ + CPU state variables. + + All segment register values are handled in little endian order. + + WARNING: Also this structure will change over time to accomodate the + "hidden portions" of registers that, like the real thing, + are used to avoid recalculating values that hardly change + anyway (such as the segment register to linear address conversions). + + WARNING: This structure is likely to change constantly over time, do not + rely on this structure staying the same from version to version. + THE VERSION NUMBERS ARE THERE TO HELP YOU WITH THIS. + +04-21-2003: Jonathan Campbell + Registers are now represented by a C union rather than a word + value. This makes referring to upper and lower parts (i.e. + AL or AH in AX or AX in EAX) easier to code because the members + can be reordered based on the byte order of the platform we are + running on. Thanks to Paul Muller for this idea! + + All general-purpose registers are now stowed in one big array. + Use the constants SX86_REG_AX, SX86_REG_BX... to refer to it. +*/ + +/* This enumeration refers to indices within softx86_ctx.state.general_reg[] */ +enum softx86_genregidx16 { + SX86_REG_AX=0, + SX86_REG_CX, + SX86_REG_DX, + SX86_REG_BX, + SX86_REG_SP, + SX86_REG_BP, + SX86_REG_SI, + SX86_REG_DI, +}; + +/* This enumeration refers to indices within softx86_ctx.ptr_regs_8reg[], + which are set at run time to point to the representative portion of + softx86_ctx.state.general_reg[] */ +enum softx86_genregidx8 { + SX86_REG_AL=0, + SX86_REG_CL, + SX86_REG_DL, + SX86_REG_BL, + SX86_REG_AH, + SX86_REG_CH, + SX86_REG_DH, + SX86_REG_BH, +}; + +/* seg-reg IDs used in this library to refer to softx86_ctx.state.segment_reg[] */ +enum softx86_segregidx { + SX86_SREG_ES=0, + SX86_SREG_CS, + SX86_SREG_SS, + SX86_SREG_DS, +}; + +typedef struct { +/************************ VISIBLE REGISTERS ****************************/ +/*--------------------general purpose registers------------------------*/ + softx86_regval general_reg[8]; +/*-------------------------segment registers---------------------------*/ + softx86_segregval segment_reg[8]; +/*-----------------instruction and FLAGS registers---------------------*/ + softx86_regval reg_flags; + sx86_udword reg_ip; +/*-----------------control/machine state registers---------------------*/ + sx86_udword reg_cr0; +/************* INVISIBLE REGISTERS (FOR CACHING PURPOSES) **************/ +/*------------instruction pointer saved before execution---------------*/ + sx86_uword reg_cs_exec_initial; /* these are copied from CS:IP before executing an instruction */ + sx86_udword reg_ip_exec_initial; /* <------' */ +/*----------------instruction pointer for decompiler-------------------*/ + sx86_uword reg_cs_decompiler; + sx86_udword reg_ip_decompiler; +/*-------------------interrupt flags-----------------------------------*/ + sx86_ubyte int_hw_flag; /* flag to indicate hardware (external) interrupt pending */ + sx86_ubyte int_hw; /* if int_hw_flag==1, which interrupt is being signalled */ + sx86_ubyte int_nmi; /* flag to indicate NMI hardware (external) interrupt pending */ +/*-------------------other internal flags------------------------------*/ + sx86_ubyte rep_flag; /* 0=no REP loop, 1=REPNZ, 2=REPZ */ + sx86_ubyte is_segment_override; /* 1=segment override was encountered */ + sx86_uword segment_override; /* value of segment that overrides the default */ +} softx86_cpustate; + +typedef struct { +/* I/O */ + void (*on_read_memory) (/* softx86_ctx */ void* _ctx,sx86_udword address,sx86_ubyte *buf,int size); /* called to fetch from memory bytes from address
*/ + void (*on_read_io) (/* softx86_ctx */ void* _ctx,sx86_udword address,sx86_ubyte *buf,int size); /* called to fetch from I/O bytes from address
*/ + void (*on_write_memory) (/* softx86_ctx */ void* _ctx,sx86_udword address,sx86_ubyte *buf,int size); /* called to write to memory bytes from address
*/ + void (*on_write_io) (/* softx86_ctx */ void* _ctx,sx86_udword address,sx86_ubyte *buf,int size); /* called to write to I/O bytes from address
*/ +/* interrupts */ + void (*on_hw_int) (/* softx86_ctx */ void* _ctx,sx86_ubyte i); /* called when an external (to this library) interrupt occurs */ + void (*on_sw_int) (/* softx86_ctx */ void* _ctx,sx86_ubyte i); /* called when an internal (emulated software) interrupt occurs */ + void (*on_hw_int_ack) (/* softx86_ctx */ void* _ctx,sx86_ubyte i); /* called when the CPU (this library) acknowledges the interrupt */ + void (*on_nmi_int) (/* softx86_ctx */ void* _ctx); /* called when an external (to this library) NMI interrupt occurs */ + void (*on_nmi_int_ack) (/* softx86_ctx */ void* _ctx); /* called when the CPU (this library) acknowledges the NMI interrupt */ +/* host-to-CPU interaction */ + void (*on_idle_cycle) (/* softx86_ctx */ void* _ctx); /* called so host application can do finer-grained things during the execution of one instruction */ + void (*on_reset) (/* softx86_ctx */ void* _ctx); /* informs host application if CPU reset itself or has been reset */ +/* CPU-to-FPU interaction */ + int (*on_fpu_opcode_exec) (/* softx86_ctx */ void* _ctx86,/* softx87_ctx */ void* _ctx87,sx86_ubyte opcode); /* called when an FPU opcode is encountered during execution */ + int (*on_fpu_opcode_dec) (/* softx86_ctx */ void* _ctx86,/* softx87_ctx */ void* _ctx87,sx86_ubyte opcode,char buf[128]); /* called when an FPU opcode is encountered during decompile */ +} softx86_callbacks; + +#ifndef bswap16 +#define bswap16(x) (((x&0xFF)<<8) | ((x>>8)&0xFF)) +#endif //bswap16 + +/* segment to linear conversion routines */ +#define SEGMENT_TO_LINEAR(x) (x<<4) +#define SEGMENT_OFFSET_TO_LINEAR(s,o) (SEGMENT_TO_LINEAR(x)+o) + +/* force a given value to fit within the specified size */ +#define MASK_BYTE_SIZE(x) ((x) &= 0xFF) +#define MASK_WORD_SIZE(x) ((x) &= 0xFFFF) +#define MASK_DWORD_SIZE(x) ((x) &= 0xFFFFFFFFL) +#define FORCE_BYTE_SIZE(x) ((x) & 0xFF) +#define FORCE_WORD_SIZE(x) ((x) & 0xFFFF) +#define FORCE_DWORD_SIZE(x) ((x) & 0xFFFFFFFFL) + +/* sign-extending macros */ +#define SGNEXT8(x) ((x) | (((x) & 0x80) ? 0xFFFFFF00 : 0)) +#define SGNEXT16(x) ((x) | (((x) & 0x8000) ? 0xFFFF0000 : 0)) + +/*===================================================================================== + Softx86 bug structure + + This structure is used to contain variables related to the emulation of various + flaws and bugs in the CPU. + + Please do not modify these directly. +*/ +typedef struct { + sx86_ubyte preemptible_after_prefix; // 1=interrupts can occur between the prefix and the opcode (8088/8086 behavior) + sx86_ubyte decrement_sp_before_store; // 1=(E)SP is decremented before storing + sx86_ubyte mask_5bit_shiftcount; // 1=mask shift count to 5 bits (286+ behavior) +} softx86_bugs; + +/*===================================================================================== + Softx86 internal context structure + + This structure is used internally by softx86 +*/ +typedef struct { +#ifdef SX86_INSIDER +/* ------------------ if compiling softx86 library source code ---------------- */ + void* opcode_table; // main opcode table + void* opcode_table_sub_0Fh; // alternate opcode table for instructions that start with 0Fh + sx86_udword addr_mask; // used to limit addressing based on CPU level + int level; // which CPU are we emulating? + sx86_ubyte* ptr_regs_8reg[8]; // pointer table to 8-bit regs given reg value in opcode +#else +/* ----------------------- if compiling outsider source code ------------------- */ + void* nothing; +#endif +} softx86_internal; + +/*===================================================================================== + Softx86 context structure + + This structure is used to interact with the host application. +*/ +typedef struct { +// version + sx86_ubyte version_hi; + sx86_ubyte version_lo; + sx86_uword version_sublo; +// publicly viewable/modifiable standard vars + softx86_cpustate* state; + softx86_callbacks* callbacks; + softx86_bugs* bugs; +// private vars + softx86_internal* __private; +// linkage vars + void* ref_softx87_ctx; // link to context structure of softx87 +// "user-defined" vars (whatever the host application wants to carry with this context structure) + void* user; +} softx86_ctx; + +/* CPU emulation levels */ +#define SX86_CPULEVEL_8088 0 // 8088 +#define SX86_CPULEVEL_8086 1 // 8086 +#define SX86_CPULEVEL_80186 2 // 80186 +#define SX86_CPULEVEL_80286 3 // 80286 + +#define sx86_far_to_linear(ctx,seg,ofs) ((seg<<4)+ofs) + +void sx86_exec_full_modregrm_rw(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm,sx86_ubyte opswap,sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val),sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val)); +void sx86_exec_full_modregrm_ro(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm,sx86_ubyte opswap,sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val),sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val)); +void sx86_exec_full_modsregrm_rw(softx86_ctx* ctx,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm,sx86_ubyte opswap,sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val)); +void sx86_exec_full_modrmonly_rw(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte rm,sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src),sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src)); +void sx86_exec_full_modrmonly_rw_imm(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte rm,sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val),sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val),int sx); +void sx86_exec_full_modrmonly_rw_imm8(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte rm,sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val),sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val)); +void sx86_exec_full_modrmonly_ro_imm(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte rm,sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val),sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val),int sx); +void sx86_exec_full_modregrm_xchg(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm); +void sx86_exec_full_modregrm_lea(softx86_ctx* ctx,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm); +void sx86_exec_full_modrw_memx(softx86_ctx* ctx,sx86_ubyte mod,sx86_ubyte rm,int sz,void (*op64)(softx86_ctx* ctx,char *datz,int sz)); +void sx86_exec_full_modrmonly_memx(softx86_ctx* ctx,sx86_ubyte mod,sx86_ubyte rm,int sz,void (*op64)(softx86_ctx* ctx,char *datz,int sz)); +void sx86_exec_full_modrmonly_callfar(softx86_ctx* ctx,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte rm,void (*op16)(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs),void (*op32)(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs)); +void sx86_exec_full_modrmonly_ro(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte rm,sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src),sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src)); +void sx86_exec_full_modrmonly_wo(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte rm,sx86_ubyte (*op8)(softx86_ctx* ctx),sx86_uword (*op16)(softx86_ctx* ctx),sx86_udword (*op32)(softx86_ctx* ctx)); +void sx86_exec_full_modregrm_far(softx86_ctx* ctx,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm,sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs)); +void sx86_exec_full_modregrm_far_ro3(softx86_ctx* ctx,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm,sx86_sword (*op16)(softx86_ctx* ctx,sx86_sword idx,sx86_sword upper,sx86_sword lower),sx86_sdword (*op32)(softx86_ctx* ctx,sx86_sdword idx,sx86_sdword upper,sx86_sdword lower)); + +void sx86_dec_full_modrmonly(softx86_ctx* ctx,sx86_ubyte is_word,sx86_ubyte dat32,sx86_ubyte mod,sx86_ubyte rm,char* op1); +void sx86_dec_full_modregrm(softx86_ctx* cpu,sx86_ubyte is_word,sx86_ubyte dat32,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm,char* op1,char* op2); +void sx86_dec_full_modsregrm(softx86_ctx* cpu,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm,char* op1,char* op2); + +void softx86_bswap2(sx86_ubyte *x); +void softx86_bswap4(sx86_ubyte *x); + +#if SX86_BYTE_ORDER == LE +#define SWAP_WORD_FROM_LE(x) +#define SWAP_DWORD_FROM_LE(x) +#else +#define SWAP_WORD_FROM_LE(x) softx86_bswap2((sx86_ubyte*)(&x)); +#define SWAP_DWORD_FROM_LE(x) softx86_bswap4((sx86_ubyte*)(&x)); +#endif + +#define SWAP_WORD_TO_LE(x) SWAP_WORD_FROM_LE(x) +#define SWAP_DWORD_TO_LE(x) SWAP_DWORD_FROM_LE(x) + +/* API */ +int softx86_getversion(int *major,int *minor,int *subminor); +int softx86_init(softx86_ctx* ctx,int level); +int softx86_reset(softx86_ctx* ctx); +int softx86_free(softx86_ctx* ctx); +int softx86_step(softx86_ctx* ctx); +int softx86_decompile(softx86_ctx* ctx,char asmbuf[256]); +int softx86_decompile_exec_cs_ip(softx86_ctx* ctx); +/* API for stack */ +sx86_uword softx86_stack_popw(softx86_ctx* ctx); +void softx86_stack_discard_n(softx86_ctx* ctx,int bytez); +void softx86_stack_add_n(softx86_ctx* ctx,int bytez); +void softx86_stack_pushw(softx86_ctx* ctx,sx86_uword data); +/* API for CPU itself in terms of fetching data properly */ +int softx86_fetch(softx86_ctx* ctx,void *reserved,sx86_udword addr,void *buf,int sz); +int softx86_write(softx86_ctx* ctx,void *reserved,sx86_udword addr,void *buf,int sz); +sx86_ubyte softx86_fetch_exec_byte(softx86_ctx* ctx); +sx86_ubyte softx86_fetch_dec_byte(softx86_ctx* ctx); +/* API for setting segment register values */ +int softx86_setsegval(softx86_ctx* ctx,int sreg_id,sx86_udword x); +/* API for setting important pointers (NOTE: use these instead of directly + * modifying the register values please, as it will make future development + * of instruction queues, caches, and pipelines much easier to manage in + * terms of CS:IP and SS:SP) */ +int softx86_set_instruction_ptr(softx86_ctx* ctx,sx86_udword cs,sx86_udword ip); +int softx86_set_instruction_dec_ptr(softx86_ctx* ctx,sx86_udword cs,sx86_udword ip); +int softx86_set_stack_ptr(softx86_ctx* ctx,sx86_udword ss,sx86_udword sp); +int softx86_set_near_instruction_ptr(softx86_ctx* ctx,sx86_udword ip); +/* get an interrupt vector */ +int softx86_get_intvect(softx86_ctx* ctx,sx86_ubyte i,sx86_uword *seg,sx86_uword *ofs); +int softx86_set_intvect(softx86_ctx* ctx,sx86_ubyte i,sx86_uword seg,sx86_uword ofs); +/* save instruction pointer on stack, get int vector, set instruction pointer there */ +void softx86_go_int_frame(softx86_ctx* ctx,sx86_ubyte i); +/* generate stack frame and (optionally) set the instruction pointer */ +int softx86_make_simple_near_call(softx86_ctx* ctx,sx86_udword* ip); +int softx86_make_simple_far_call(softx86_ctx* ctx,sx86_udword* cs,sx86_udword* ip); +int softx86_make_simple_interrupt_call(softx86_ctx* ctx,sx86_udword* cs,sx86_udword* ip); +/* macros for more advanced versions of the above functions (param1, param2, etc... + refers to the number of parameters passed to the function). */ +/*---------------------- "typical" refers to the fact that most + ---------------------- C/C++ compilers for DOS and Win16 (ignoring + ---------------------- those that use the CPU registers) use + ---------------------- a simple calling convention where the + ---------------------- parameters are pushed onto the stack + ---------------------- in the opposite of the order they + ---------------------- appear in the parameter list. __pascal, __stdcall, + ---------------------- __cdecl, and the like all share this + ---------------------- apparently (the difference is how the + ---------------------- stack is cleaned up) */ +#define softx86_make_typical_near_call_param1(ctx,ip,p1)\ + softx86_stack_pushw(ctx,p1);\ + softx86_make_simple_near_call(ctx,ip); + +#define softx86_make_typical_near_call_param2(ctx,ip,p1,p2)\ + softx86_stack_pushw(ctx,p2);\ + softx86_stack_pushw(ctx,p1);\ + softx86_make_simple_near_call(ctx,ip); + +#define softx86_make_typical_near_call_param3(ctx,ip,p1,p2,p3)\ + softx86_stack_pushw(ctx,p3);\ + softx86_stack_pushw(ctx,p2);\ + softx86_stack_pushw(ctx,p1);\ + softx86_make_simple_near_call(ctx,ip); + +#define softx86_make_typical_near_call_param4(ctx,ip,p1,p2,p3,p4)\ + softx86_stack_pushw(ctx,p4);\ + softx86_stack_pushw(ctx,p3);\ + softx86_stack_pushw(ctx,p2);\ + softx86_stack_pushw(ctx,p1);\ + softx86_make_simple_near_call(ctx,ip); + + +#define softx86_make_typical_far_call_param1(ctx,cs,ip,p1)\ + softx86_stack_pushw(ctx,p1);\ + softx86_make_simple_far_call(ctx,cs,ip); + +#define softx86_make_typical_far_call_param2(ctx,cs,ip,p1,p2)\ + softx86_stack_pushw(ctx,p2);\ + softx86_stack_pushw(ctx,p1);\ + softx86_make_simple_far_call(ctx,cs,ip); + +#define softx86_make_typical_far_call_param3(ctx,cs,ip,p1,p2,p3)\ + softx86_stack_pushw(ctx,p3);\ + softx86_stack_pushw(ctx,p2);\ + softx86_stack_pushw(ctx,p1);\ + softx86_make_simple_far_call(ctx,cs,ip); + +#define softx86_make_typical_far_call_param4(ctx,cs,ip,p1,p2,p3,p4)\ + softx86_stack_pushw(ctx,p4);\ + softx86_stack_pushw(ctx,p3);\ + softx86_stack_pushw(ctx,p2);\ + softx86_stack_pushw(ctx,p1);\ + softx86_make_simple_far_call(ctx,cs,ip); + + +/* mask constants for CR0 (286+ compatible) */ +#define SX86_CR0_LMSW_MASK 0x0000000E +#define SX86_CR0FLAG_PE 0x00000001 +#define SX86_CR0FLAG_MP 0x00000002 +#define SX86_CR0FLAG_EM 0x00000004 +#define SX86_CR0FLAG_TS 0x00000008 +/* mask constants for CR0 (386+ compatible) */ +#define SX86_CR0FLAG_ET 0x00000010 +#define SX86_CR0FLAG_NE 0x00000020 +#define SX86_CR0FLAG_WP 0x00010000 +#define SX86_CR0FLAG_AM 0x00040000 +#define SX86_CR0FLAG_NW 0x20000000 +#define SX86_CR0FLAG_CD 0x40000000 +#define SX86_CR0FLAG_PG 0x80000000 + +/* mask constants for CPU flags */ +#define SX86_CPUFLAG_CARRY 0x00000001 +#define SX86_CPUFLAG_RESERVED_01 0x00000002 +#define SX86_CPUFLAG_PARITY 0x00000004 +#define SX86_CPUFLAG_RESERVED_03 0x00000008 +#define SX86_CPUFLAG_AUX 0x00000010 +#define SX86_CPUFLAG_RESERVED_05 0x00000020 +#define SX86_CPUFLAG_ZERO 0x00000040 +#define SX86_CPUFLAG_SIGN 0x00000080 +#define SX86_CPUFLAG_TRAP 0x00000100 +#define SX86_CPUFLAG_INTENABLE 0x00000200 +#define SX86_CPUFLAG_DIRECTIONREV 0x00000400 +#define SX86_CPUFLAG_OVERFLOW 0x00000800 +#define SX86_CPUFLAG_IOPL 0x00003000 +#define SX86_CPUFLAG_IOPLSET(x) (((x&3))<<12) +#define SX86_CPUFLAG_IOPLGET(x) ((x>>12)&3) +#define SX86_CPUFLAG_NESTEDTASK 0x00004000 +#define SX86_CPUFLAG_RESERVED_15 0x00008000 +#define SX86_CPUFLAG_RESUME 0x00010000 +#define SX86_CPUFLAG_V86 0x00020000 +#define SX86_CPUFLAG_ALIGNMENTCHK 0x00040000 +#define SX86_CPUFLAG_RESERVED_19 0x00080000 +#define SX86_CPUFLAG_RESERVED_20 0x00100000 +#define SX86_CPUFLAG_RESERVED_21 0x00200000 +#define SX86_CPUFLAG_RESERVED_22 0x00400000 +#define SX86_CPUFLAG_RESERVED_23 0x00800000 +#define SX86_CPUFLAG_RESERVED_24 0x01000000 +#define SX86_CPUFLAG_RESERVED_25 0x02000000 +#define SX86_CPUFLAG_RESERVED_26 0x04000000 +#define SX86_CPUFLAG_RESERVED_27 0x08000000 +#define SX86_CPUFLAG_RESERVED_28 0x10000000 +#define SX86_CPUFLAG_RESERVED_29 0x20000000 +#define SX86_CPUFLAG_RESERVED_30 0x40000000 +#define SX86_CPUFLAG_RESERVED_31 0x80000000 + +#define SX86_CPUFLAGBO_CARRY 0 +#define SX86_CPUFLAGBO_RESERVED_01 1 +#define SX86_CPUFLAGBO_PARITY 2 +#define SX86_CPUFLAGBO_RESERVED_03 3 +#define SX86_CPUFLAGBO_AUX 4 +#define SX86_CPUFLAGBO_RESERVED_05 5 +#define SX86_CPUFLAGBO_ZERO 6 +#define SX86_CPUFLAGBO_SIGN 7 +#define SX86_CPUFLAGBO_TRAP 8 +#define SX86_CPUFLAGBO_INTENABLE 9 +#define SX86_CPUFLAGBO_DIRECTIONREV 10 +#define SX86_CPUFLAGBO_OVERFLOW 11 +#define SX86_CPUFLAGBO_IOPL 12 +#define SX86_CPUFLAGBO_NESTEDTASK 14 +#define SX86_CPUFLAGBO_RESERVED_15 15 +#define SX86_CPUFLAGBO_RESUME 16 +#define SX86_CPUFLAGBO_V86 17 +#define SX86_CPUFLAGBO_ALIGNMENTCHK 18 +#define SX86_CPUFLAGBO_RESERVED_19 19 +#define SX86_CPUFLAGBO_RESERVED_20 20 +#define SX86_CPUFLAGBO_RESERVED_21 21 +#define SX86_CPUFLAGBO_RESERVED_22 22 +#define SX86_CPUFLAGBO_RESERVED_23 23 +#define SX86_CPUFLAGBO_RESERVED_24 24 +#define SX86_CPUFLAGBO_RESERVED_25 25 +#define SX86_CPUFLAGBO_RESERVED_26 26 +#define SX86_CPUFLAGBO_RESERVED_27 27 +#define SX86_CPUFLAGBO_RESERVED_28 28 +#define SX86_CPUFLAGBO_RESERVED_29 29 +#define SX86_CPUFLAGBO_RESERVED_30 30 +#define SX86_CPUFLAGBO_RESERVED_31 31 + +/* default callback functions within the library */ +void softx86_step_def_on_read_memory(void* _ctx,sx86_udword address,sx86_ubyte *buf,int size); +void softx86_step_def_on_read_io(void* _ctx,sx86_udword address,sx86_ubyte *buf,int size); +void softx86_step_def_on_write_memory(void* _ctx,sx86_udword address,sx86_ubyte *buf,int size); +void softx86_step_def_on_write_io(void* _ctx,sx86_udword address,sx86_ubyte *buf,int size); +void softx86_step_def_on_hw_int(void* _ctx,sx86_ubyte i); +void softx86_step_def_on_sw_int(void* _ctx,sx86_ubyte i); +void softx86_step_def_on_hw_int_ack(void* _ctx,sx86_ubyte i); +void softx86_step_def_on_idle_cycle(void* _ctx); +void softx86_step_def_on_nmi_int(void* _ctx); +void softx86_step_def_on_nmi_int_ack(void* _ctx); +int softx86_step_def_on_fpu_opcode_exec(void* _ctx86,void* _ctx87,sx86_ubyte opcode); +int softx86_step_def_on_fpu_opcode_dec(void* _ctx86,void* _ctx87,sx86_ubyte opcode,char buf[128]); +void softx86_step_def_on_reset(void* _ctx); + +/* external/internal/NMI interrupt generation and acknowledgement */ +int softx86_ext_hw_signal(softx86_ctx* ctx,sx86_ubyte i); +int softx86_ext_hw_ack(softx86_ctx* ctx); +int softx86_int_sw_signal(softx86_ctx* ctx,sx86_ubyte i); +int softx86_ext_hw_nmi_signal(softx86_ctx* ctx); +int softx86_ext_hw_nmi_ack(softx86_ctx* ctx); + +/* parity flag computation routines */ +int softx86_parity8(sx86_ubyte ret); +int softx86_parity16(sx86_uword ret); +int softx86_parity32(sx86_udword ret); +int softx86_parity64(sx86_uldword ret); + +/* bug emulation constants. each is meant to be unique. */ +#define SX86_BUG_PREEMPTIBLE_AFTER_PREFIX 0x12340500 +#define SX86_BUG_SP_DECREMENT_BEFORE_STORE 0x12340600 // specific to all prior to 286 +#define SX86_BUG_5BIT_SHIFTMASK 0x12340700 // 286+ behavior of masking shift count to 5 bits + +/* use this to change values in the bug emulation structure */ +int softx86_setbug(softx86_ctx* ctx,sx86_udword bug_id,sx86_ubyte on_off); + +/* mod/reg/rm unpacking */ +#define sx86_modregrm_unpack(mrr,mod,reg,rm) mod = (mrr>>6);\ + reg = (mrr>>3)&7;\ + rm = mrr&7; + +#ifdef __cplusplus +} +#endif //__cplusplus + +#endif //SOFTX86_H + Index: include/reactos/libs/softx86/softx86.h =================================================================== --- include/reactos/libs/softx86/softx86.h (révision 59666) +++ include/reactos/libs/softx86/softx86.h (copie de travail) Modification de propriétés sur include/reactos/libs/softx86/softx86.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: include/reactos/libs/softx86/softx86cfg.h =================================================================== --- include/reactos/libs/softx86/softx86cfg.h (révision 0) +++ include/reactos/libs/softx86/softx86cfg.h (copie de travail) @@ -0,0 +1,63 @@ +/* softx86cfg.h + * + * Configuration #defines for Softx86 emulation library. + * + * (C) 2003, 2004 Jonathan Campbell. + * + * If ENDIAN.H is present, this header file determines the native byte + * order from that. If WIN32 is defined, this header assumes little + * Endian since the Win32 environment exists only on the x86 platform. + * If neither happens, a set of #defines will be used that must be modified + * manually to fit your system. + * */ + +/* If we're being compiled with GCC and NOT MINGW assume Linux environment + and headers */ +#ifdef __GNUC__ +#ifndef __MINGW32__ +#include /* /usr/include/endian.h */ +#endif +#endif //__GNUC__ + +/* AUTODETECT USING ENDIAN.H UNDER LINUX */ +#ifdef _ENDIAN_H + +#if __BYTE_ORDER == __LITTLE_ENDIAN +#define SX86_BYTE_ORDER LE +#elif __BYTE_ORDER == __BIG_ENDIAN +#define SX86_BYTE_ORDER BE +#else +#error endian.h does not provide byte order! +// #define it here +#endif /* __BYTE_ORDER */ + +/* 32-bit Windows */ +#elif WIN32 + +/* comment this out if compiling with Microsoft Visual C++ 6.0 + and you have installed Service Pack 5. otherwise, you need + this so Softx86 can incorporate workarounds for error C2520: + "conversion from unsigned __int64 to double not implemented" */ +#define MSVC_CANT_CONVERT_UI64_TO_DOUBLE + +#define SX86_BYTE_ORDER LE + +/* 32-bit Windows, using MINGW */ +#elif __MINGW32__ + +#define SX86_BYTE_ORDER LE + +#else +/* WE HAVE NO IDEA, SO WHOEVER IS COMPILING THE LIBRARY AND DEPENDENT + * CODE NEEDS TO MODIFY THESE MANUALLY TO FIT THEIR PLATFORM */ + +/* comment this out when you have modified the #defines below */ +/* obviously when you are done this needs to be removed :) */ +#error Unable to auto-detect your platform! You must modify softx86cfg.h manually! + +/* modify these to your platform. acceptable values are LE and BE */ +#define SX86_BYTE_ORDER LE + +#endif + +#define SX86_INSIDER Index: include/reactos/libs/softx86/softx86cfg.h =================================================================== --- include/reactos/libs/softx86/softx86cfg.h (révision 59666) +++ include/reactos/libs/softx86/softx86cfg.h (copie de travail) Modification de propriétés sur include/reactos/libs/softx86/softx86cfg.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: include/reactos/libs/softx86/softx87.h =================================================================== --- include/reactos/libs/softx86/softx87.h (révision 0) +++ include/reactos/libs/softx86/softx87.h (copie de travail) @@ -0,0 +1,285 @@ + +#ifndef SOFTX87_H +#define SOFTX87_H + +/* get the Softx86 configuration defines and Softx86 headers */ +#include "softx86.h" +#include "softx86cfg.h" + +#ifdef __cplusplus +extern "C" { +#endif //__cplusplus + +/// version composed as follows: H.LL.SSSS +// where: H = major version number (any length) +// L = minor version number (2 digits) +// S = sub-minor version number (4 digits) +// +// This is v0.00.0033 +#define SOFTX87_VERSION_HI 0 +#define SOFTX87_VERSION_LO 0 +#define SOFTX87_VERSION_SUBLO 33 + +#ifdef __MINGW32__ // MINGW + +typedef unsigned char sx87_ubyte; +typedef signed char sx87_sbyte; +typedef unsigned short int sx87_uword; +typedef signed short int sx87_sword; +typedef unsigned int sx87_udword; +typedef signed int sx87_sdword; +typedef unsigned long long int sx87_uldword; +typedef signed long long int sx87_sldword; + +#elif WIN32 // MSVC + +typedef unsigned char sx87_ubyte; +typedef signed char sx87_sbyte; +typedef unsigned short int sx87_uword; +typedef signed short int sx87_sword; +typedef unsigned int sx87_udword; +typedef signed int sx87_sdword; +typedef unsigned __int64 sx87_uldword; +typedef signed __int64 sx87_sldword; + +#else // GCC 3.xx.xx + +typedef unsigned char sx87_ubyte; +typedef signed char sx87_sbyte; +typedef unsigned short int sx87_uword; +typedef signed short int sx87_sword; +typedef unsigned int sx87_udword; +typedef signed int sx87_sdword; +typedef unsigned long long int sx87_uldword; +typedef signed long long int sx87_sldword; + +#endif + +/* NOTE: Each FPU register is maintained in a format similar but not + quite the same as the 80-bit format documented by Intel to + be the "internal" format used by the FPU. + + We store the sign, mantissa, and exponent differently. + +Intel documents the 80-bit register to be stored like this: + +bit 79: sign +bits 64-78: exponent +bit 0-63: mantissa. + +This is referred to in their documentation as "double extended precision F.P" + */ +typedef struct { + sx86_uldword mantissa; + sx86_uword exponent; + sx86_ubyte sign_bit; +} softx87_reg80; + +/*============================================================================ + FPU state variables. + + WARNING: This structure is likely to change constantly over time, do not + rely on this structure staying the same from version to version. +*/ + +typedef struct { + sx86_udword offset; + sx86_uword segment; +} softx87_ptr; + +typedef struct { + sx86_uword status_word; /* status word */ + sx86_uword control_word; /* control word */ + sx86_uword tag_word; /* "TAG" word */ + softx87_ptr data_pointer; /* ? */ + softx87_ptr last_instruction; /* last instruction address */ + softx87_ptr last_instruction_memptr; /* last instruction memory reference */ + sx87_uword last_opcode; /* last FPU opcode */ + softx87_reg80 st[8]; /* registers ST(0) thru ST(7) */ +} softx87_fpustate; + +typedef struct { +/* I/O */ + void (*on_read_memory) (/* softx87_ctx */ void* _ctx,sx87_udword address,sx87_ubyte *buf,int size); /* called to fetch from memory bytes from address
*/ + void (*on_write_memory) (/* softx87_ctx */ void* _ctx,sx87_udword address,sx87_ubyte *buf,int size); /* called to write to memory bytes from address
*/ +/* callbacks to softx86 for fetching more opcodes */ + sx86_ubyte (*on_softx86_fetch_exec_byte) (softx86_ctx *ctx); + sx86_ubyte (*on_softx86_fetch_dec_byte) (softx86_ctx *ctx); + void (*on_sx86_exec_full_modrmonly_memx) (softx86_ctx *ctx,sx86_ubyte mod,sx86_ubyte rm,int sz,void (*op64)(softx86_ctx* ctx,char *datz,int sz)); + void (*on_sx86_exec_full_modrw_memx) (softx86_ctx* ctx,sx86_ubyte mod,sx86_ubyte rm,int sz,void (*op64)(softx86_ctx* ctx,char *datz,int sz)); + void (*on_sx86_dec_full_modrmonly) (softx86_ctx *ctx,sx86_ubyte is_word,sx86_ubyte dat32,sx86_ubyte mod,sx86_ubyte rm,char* op1); +} softx87_callbacks; + +/*===================================================================================== + Softx87 bug structure + + This structure is used to contain variables related to the emulation of various + flaws and bugs in the FPU. + + Please do not modify these directly. +*/ +typedef struct { + sx87_ubyte ip_ignores_prefix; // 1=8087 FPU behavior where FPU last instruction pointer ignores the 8086 prefixes +} softx87_bugs; + +/*===================================================================================== + Softx87 context structure + + This structure is used to interact with the host application. +*/ +typedef struct { +// version + sx87_ubyte version_hi; + sx87_ubyte version_lo; + sx87_uword version_sublo; +// other + softx87_fpustate state; + softx87_callbacks callbacks; + softx87_bugs bugs; + void* opcode_table; + int level; + softx86_ctx* ref_softx86; +} softx87_ctx; + +/* FPU emulation levels */ +#define SX87_FPULEVEL_8087 0 // 8088 +#define SX87_FPULEVEL_80287 1 // 80287 +#define SX87_FPULEVEL_80387 2 // 80387 +#define SX87_FPULEVEL_80487 3 // 80487 + +/* Types as returned by softx87_get_fpu_register_double() */ +#define SX87_FPU_NUMTYPE_NUMBER 0 // a number +#define SX87_FPU_NUMTYPE_NEGINF 1 // -infinity +#define SX87_FPU_NUMTYPE_POSINF 2 // +infinity +#define SX87_FPU_NUMTYPE_NAN 3 // NaN + +/* API */ +int softx87_getversion(int *major,int *minor,int *subminor); +int softx87_init(softx87_ctx* ctx,int level); +int softx87_reset(softx87_ctx* ctx); +int softx87_free(softx87_ctx* ctx); +double softx87_get_fpu_double(softx87_ctx* ctx,softx87_reg80 *reg,int *numtype); +void softx87_set_fpu_double(softx87_ctx* ctx,softx87_reg80 *reg,double val); +double softx87_get_fpu_register_double(softx87_ctx* ctx,int i,int *numtype); +void softx87_set_fpu_register_double(softx87_ctx* ctx,int i,double val); +void softx87_finit_setup(softx87_ctx* ctx); +/* callbacks intended for reference to softx86 */ +int softx87_on_fpu_opcode_exec(/* softx86_ctx */ void* _ctx86,/* softx87_ctx */ void* _ctx87,sx86_ubyte opcode); +int softx87_on_fpu_opcode_dec(/* softx86_ctx */ void* _ctx86,/* softx87_ctx */ void* _ctx87,sx86_ubyte opcode,char buf[128]); + +/* mask constants for FPU status */ +/*-----------exception flags----------*/ +#define SX87_FPUSTAT_INVALID_OP 0x0001 +#define SX87_FPUSTAT_DENORMAL 0x0002 +#define SX87_FPUSTAT_ZERO_DIVIDE 0x0004 +#define SX87_FPUSTAT_OVERFLOW 0x0008 +#define SX87_FPUSTAT_UNDERFLOW 0x0010 +#define SX87_FPUSTAT_PRECISION 0x0020 +/*-----------more flags---------------*/ +#define SX87_FPUSTAT_STACK_FAULT 0x0040 +#define SX87_FPUSTAT_ERROR_SUMMARY 0x0080 +/*-----------condition codes----------*/ +#define SX87_FPUSTAT_C0 0x0100 +#define SX87_FPUSTAT_C1 0x0200 +#define SX87_FPUSTAT_C2 0x0400 +#define SX87_FPUSTAT_TOP_MASK 0x3800 +#define SX87_FPUSTAT_TOP(x) (((x)>>11)&7) +#define SX87_FPUSTAT_TOP_SET(x,y) (x = (((x)&(~SX87_FPUSTAT_TOP_MASK)) | (((y)&7)<<11))) +#define SX87_FPUSTAT_C3 0x4000 +#define SX87_FPUSTAT_BUSY 0x8000 + +/* mask constants for FPU control word */ +/*-----------exception flags----------*/ +#define SX87_FPUCTRLW_INVALID_OP 0x0001 +#define SX87_FPUCTRLW_DENORMAL 0x0002 +#define SX87_FPUCTRLW_ZERO_DIVIDE 0x0004 +#define SX87_FPUCTRLW_OVERFLOW 0x0008 +#define SX87_FPUCTRLW_UNDERFLOW 0x0010 +#define SX87_FPUCTRLW_PRECISION 0x0020 +/*-----------precision control flag---*/ +#define SX87_FPUCTRLW_PCTL_MASK 0x0300 +#define SX87_FPUCTRLW_PCTL(x) (((x)>>8)&3) +#define SX87_FPUCTRLW_PCTL_SET(x,y) (x = (((x)&(~SX87_FPUCTRLW_PCTL_MASK)) | (((y)&3)<<8))) +/*-----------rounding control flag----*/ +#define SX87_FPUCTRLW_RNDCTL_MASK 0x0C00 +#define SX87_FPUCTRLW_RNDCTL(x) (((x)>>10)&3) +#define SX87_FPUCTRLW_RNDCTL_SET(x,y) (x = (((x)&(~SX87_FPUCTRLW_RNDCTL_MASK)) | (((y)&3)<<10))) +/*-----------infinity control flag----*/ +#define SX87_FPUCTRLW_INFCTL 0x1000 + +/* precision control flag values */ +#define SX87_FPUCTRLW_PCTL_24_BIT 0 +#define SX87_FPUCTRLW_PCTL_RESERVED_1 1 +#define SX87_FPUCTRLW_PCTL_53_BIT 2 +#define SX87_FPUCTRLW_PCTL_64_BIT 3 + +/* rounding control flag values */ +#define SX87_FPUCTRLW_RNDCTL_NEAREST 0 /* nearest */ +#define SX87_FPUCTRLW_RNDCTL_DOWNINF 1 /* down towards -inf */ +#define SX87_FPUCTRLW_RNDCTL_UPINF 2 /* down towards +inf */ +#define SX87_FPUCTRLW_RNDCTL_ZERO 3 /* towards zero (truncate) */ + +/* mask constants for FPU tag word */ +#define SX87_FPUTAGW_TAG(x,i) (((x)>>(i*2))&3) +#define SX87_FPUTAGW_TAG_SET(x,i,y) (x = (((x) & (~(3<<(i*2)))) | (((y)&3)<<(i*2)))) +#define SX87_FPUTAGVAL_VALID 0 +#define SX87_FPUTAGVAL_ZERO 1 +#define SX87_FPUTAGVAL_SPECIAL 2 +#define SX87_FPUTAGVAL_EMPTY 3 + +/* takes a ST(i) index and converts it to the true register index */ +#define SX87_FPU_ST(TOP,i) ((TOP+i)&7) + +/* default callback functions within the library */ +void softx87_step_def_on_read_memory(void* _ctx,sx87_udword address,sx87_ubyte *buf,int size); +void softx87_step_def_on_write_memory(void* _ctx,sx87_udword address,sx87_ubyte *buf,int size); +sx86_ubyte softx87_def_on_softx86_fetch_exec_byte(softx86_ctx* ctx); +sx86_ubyte softx87_def_on_softx86_fetch_dec_byte(softx86_ctx* ctx); +void softx87_on_sx86_exec_full_modrmonly_memx(softx86_ctx *ctx,sx86_ubyte mod,sx86_ubyte rm,int sz,void (*op64)(softx86_ctx* ctx,char *datz,int sz)); +void softx87_on_sx86_dec_full_modrmonly(softx86_ctx* ctx,sx86_ubyte is_word,sx86_ubyte dat32,sx86_ubyte mod,sx86_ubyte rm,char* op1); + +/* bug emulation constants. each is meant to be unique. */ +#define SX87_BUG_IP_IGNORES_PREFIX 0x56780100 + +/* use this to change values in the bug emulation structure */ +int softx87_setbug(softx87_ctx* ctx,sx87_udword bug_id,sx87_ubyte on_off); + +/* utility */ +void softx87_normalize(softx87_ctx* ctx,softx87_reg80 *val); + +/* loading/saving */ +void softx87_unpack_raw_int16(softx87_ctx* ctx,char *data,softx87_reg80 *v); +void softx87_unpack_raw_int32(softx87_ctx* ctx,char *data,softx87_reg80 *v); +void softx87_unpack_raw_fp32(softx87_ctx* ctx,char *data,softx87_reg80 *v); +void softx87_unpack_raw_fp64(softx87_ctx* ctx,char *data,softx87_reg80 *v); + +#ifdef __cplusplus +} +#endif //__cplusplus + +/* softx87_connect_to_CPU(context) + Connects Softx86 CPU to a Softx87 FPU. + This function assumes that you want the CPU and FPU to + share the same memory. Provided as a service for those + who don't want to manually link pointers together and such. */ +static inline int softx87_connect_to_CPU(softx86_ctx* cpu,softx87_ctx* fpu) +{ + if (!cpu || !fpu) return 0; + + cpu->ref_softx87_ctx = fpu; + fpu->ref_softx86 = cpu; + cpu->callbacks->on_fpu_opcode_exec = softx87_on_fpu_opcode_exec; + cpu->callbacks->on_fpu_opcode_dec = softx87_on_fpu_opcode_dec; + fpu->callbacks.on_read_memory = cpu->callbacks->on_read_memory; + fpu->callbacks.on_write_memory = cpu->callbacks->on_write_memory; + fpu->callbacks.on_softx86_fetch_dec_byte = softx86_fetch_dec_byte; + fpu->callbacks.on_softx86_fetch_exec_byte = softx86_fetch_exec_byte; + fpu->callbacks.on_sx86_dec_full_modrmonly = sx86_dec_full_modrmonly; + fpu->callbacks.on_sx86_exec_full_modrmonly_memx = sx86_exec_full_modrmonly_memx; + fpu->callbacks.on_sx86_exec_full_modrw_memx = sx86_exec_full_modrw_memx; + + return 1; +} + +#endif //SOFTX87_H + Index: include/reactos/libs/softx86/softx87.h =================================================================== --- include/reactos/libs/softx86/softx87.h (révision 59666) +++ include/reactos/libs/softx86/softx87.h (copie de travail) Modification de propriétés sur include/reactos/libs/softx86/softx87.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/CMakeLists.txt =================================================================== --- lib/3rdparty/CMakeLists.txt (révision 59666) +++ lib/3rdparty/CMakeLists.txt (copie de travail) @@ -9,6 +9,7 @@ add_subdirectory(libsamplerate) add_subdirectory(libwine) add_subdirectory(libxml2) +add_subdirectory(softx86) if(MSVC) add_subdirectory(stlport) endif() Index: lib/3rdparty/softx86 =================================================================== --- lib/3rdparty/softx86 (révision 59666) +++ lib/3rdparty/softx86 (copie de travail) Modification de propriétés sur lib/3rdparty/softx86 ___________________________________________________________________ Added: bugtraq:url ## -0,0 +1 ## +http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID% \ No newline at end of property Added: bugtraq:message ## -0,0 +1 ## +See issue #%BUGID% for more details. \ No newline at end of property Added: tsvn:logminsize ## -0,0 +1 ## +10 \ No newline at end of property Added: bugtraq:logregex ## -0,0 +1,2 ## +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+) \ No newline at end of property Index: lib/3rdparty/softx86/autodetect_nasm.sh =================================================================== --- lib/3rdparty/softx86/autodetect_nasm.sh (révision 0) +++ lib/3rdparty/softx86/autodetect_nasm.sh (copie de travail) @@ -0,0 +1,14 @@ +# /bin/sh + +nasm >/dev/null + +if [[ "$?" == "0" || "$?" == "1" ]]; then + echo "all: samples_all" >samples/Makefile.nasm + echo "NASM=nasm" >>samples/Makefile.nasm +else + echo "#nothing to do here" >samples/Makefile.nasm + echo "all:" >>samples/Makefile.nasm + echo -n -e "\t" >>samples/Makefile.nasm + echo "echo You do not have NASM... skipping sample build" >>samples/Makefile.nasm +fi + Index: lib/3rdparty/softx86/autodetect_nasm.sh =================================================================== --- lib/3rdparty/softx86/autodetect_nasm.sh (révision 59666) +++ lib/3rdparty/softx86/autodetect_nasm.sh (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/autodetect_nasm.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/autodetect_softx87.sh =================================================================== --- lib/3rdparty/softx86/autodetect_softx87.sh (révision 0) +++ lib/3rdparty/softx86/autodetect_softx87.sh (copie de travail) @@ -0,0 +1,9 @@ +# /bin/sh + +if [ -d ./softx87 ]; then + echo "INCLUDZ += -DSOFT87FPU" >softx86dbg/Makefile.softx87 + echo "LIBINCLUDZ += -lsoftx87" >>softx86dbg/Makefile.softx87 +else + echo "#nothing to do here" >softx86dbg/Makefile.softx87 +fi + Index: lib/3rdparty/softx86/autodetect_softx87.sh =================================================================== --- lib/3rdparty/softx86/autodetect_softx87.sh (révision 59666) +++ lib/3rdparty/softx86/autodetect_softx87.sh (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/autodetect_softx87.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/changes.txt =================================================================== --- lib/3rdparty/softx86/changes.txt (révision 0) +++ lib/3rdparty/softx86/changes.txt (copie de travail) @@ -0,0 +1,355 @@ +v0.00.0033: Jonathan Campbell + - Added helper function softx87_connect_to_CPU() + to ease CPU <=> FPU connection for programmers. + - Added softx86_set_intvect(). + - Added general API functions softx86_make_simple_near_call(), + softx86_make_simple_far_call(), softx86_make_simple_interrupt_call(), + to make it easier for the program to manually invoke + calls to program code within the virtual environment. + - Added FBLD and FBSTP emulation + - Added FLD1, FLDL2T and other constant-related FPU instruction emulation + - Added FCLEX & FSCALE emulation + - Added F2XM1 & FCOM emulation + - Added FDIV, FDIVR, and FICOM emulation + +v0.00.0032: Jonathan Campbell + - Using the 'u' command multiple times without + arguments now continues the decompiler from + where it left off, rather than restarting at + CS:IP + - Fixed a bug that caused Softx86dbg to crash if + run without an executable image to debug. + - Fixed a an error in the code that causes Softx86dbg + to crash when debugging a .COM file. See + http://sourceforge.net/tracker/index.php?func=detail&aid=919504&group_id=76259&atid=546548 + for details. + - Added code to stop emulation and alert the user + if the instruction pointer wanders into areas + that normally do not contain code (e.g. the + interrupt vector table, the BIOS data area, + adapter ROM areas, etc). + - Fixed up INT 21h AH=4Ch/AH=00h code that would + have otherwise failed if AL was anything but 00h. + - Cleaned up interrupt handler system in Softx86dbg. + +v0.00.0031: Jonathan Campbell + - Added command "!ramdump" to dump the entire 1MB + simulated RAM buffer to a file so you can then + examine it further with your favorite hex editor. + - Fixed coding mistake in .EXE relocation code that + caused corruption of the .EXE image, as well as + incorrect relocations + - Added check for .EXE files with funny entry point + values (e.g. 0xFFF0:0x0100) that ultimately translate + to valid offsets (such as the very beginning of the + resident area). Attempts to debug these previously + caused softx86dbg to crash. These EXEs were probably + converted from .COM images anyway. + - Fixed 'D' and 'U' command parsing bugs in softx86dbg + that failed to recognize first segment value + if it started with A-F (e.g. BF45:1233) + - Fixed incorrect assignment of DS and ES when + setting up .EXE emulated environment in + softx86dbg. DS and ES now point to PSP segment + instead of the first paragraph of the EXE + binary. + - Fixed bugs dealing with group 80h instructions + that are using an 8-bit sign-extended immediate + value with a 16-bit parameter. + - It turns out DOS DEBUG.EXE (at least the one + bundled with Windows XP) also supports multiple + steps with t followed by the number of steps. + The funny thing is that it assumes the number + is hexadecimal... whatever. + +v0.00.0030: Jonathan Campbell + - More FADD fixes + - Softx86dbg shows FPU contents in scientific notation + - Added FSUB, FSUBP emulation + - Added FABS, FCHS, FRNDINT + - Soft86 context structure modified so that the structure + itself stays the same size and format even if additions + are made to sub-structures + - Softx87 will no longer be distributed separately from + the main source tarball + - New documentation! + +v0.00.0029: Jonathan Campbell + - Fixes for FADD + - Integer -> float conversion now normalizes the values. + +v0.00.0028: Jonathan Campbell + - Added FADD, FADDP, FIADD 8087 instructions + +v0.00.0027: Jonathan Campbell + - Fixed LOCK decompiler not printing anything to the buffer. + - Enhanced FPU backend and started development on + Softx87, an 8087 FPU emulation engine designed to tie + into Softx86. + - Added FINIT, FNOP, FLD, FINCSTP, FDECSTP, FFREE + - install.sh is no longer regenerated + - More intelligent makefile now checks for presence of + NASM and softx87 source tree. If you didn't download + the softx87 code with softx86, softx86dbg is compiled + and built without 8087 emulation support. If you don't + have NASM the samples are not built and are skipped. + +v0.00.0026: Jonathan Campbell + - Added callback-based backend so that Softx86 can + hand FPU opcodes off to other libraries or subroutines + assigned to emulating the 80x87 FPU. If no callbacks + for this have been assigned Softx86 treats the opcode + as unknown. + - Added version information to the context structure. + - Fixed bug in softx86dbg's handling of the 'R' register + change command for the segment registers. + - Added callback for CPU resets. + +v0.00.0025: Jonathan Campbell + - Added group 3-1A (0xF6/0xF7 opcodes) TEST r/m, + NOT r/m, NEG r/m, MUL r/m, IMUL r/m, DIV r/m, IDIV r/m. + - Added LOOP/LOOPZ/LOOPNZ. + - Added ENTER/LEAVE. + - Added LES and LDS. + - Added BOUND. + - The entire 8086 instruction set is now implemented in + this library (at least the ones that Intel documents). + Let me know if I'm wrong. If this proves to be a sturdy + implementation I might re-release this as the official + v1.0 beta! Let me know if any undocumented instructions + should be implemented. + +v0.00.0024: Jonathan Campbell + - Added RCL and RCR + +v0.00.0023: Jonathan Campbell + - Added SHL, SHR, and SAR + - Added some helpful constants in softx86.h that can be used + in shifting operations to obtain specific bits in the FLAGS + register, like this: + + t = (ctx->stage.flags>>SX86_CPUFLAGBO_PARITY)&1; + + instead of: + + t = (ctx->stage.flags&SX86_CPUFLAG_PARITY)?1:0; + + - Added ROL, ROR + +v0.00.0022: Jonathan Campbell + - Added PUSHA, POPA, LOCK + +v0.00.0021: Jonathan Campbell + - Fixed major mistake in FAR CALL/INTERRUPT stack framing + code. Segment and offset values were pushed onto the + stack in the wrong order! + - Added CALL/JMP/CALL FAR/JMP FAR (0xFF /2 /3 /4 and /5) + - Added preliminary code to start supporting 80286 instructions. + softx86_init() now reports 8088/8086 emulation as stable, + since 80% of the instructions have been implemented anyway. + calling softx86_init() with SX86_CPULEVEL_80286 or + SX86_CPULEVEL_80186 is now legal. + - Fixed main Makefile. Somehow it got mixed up with another + Makefile. + +v0.00.0020: Jonathan Campbell + - Added FAQ. + - Fixed minor error in hypothetical I/O device at port 0x9A. + 16-bit data is now treated the same way that it would be if + written as 8-bit data. + - DOS 16-bit real-mode EXE loader. Now softx86dbg can debug + MS-DOS EXEs. + +v0.00.0019: Jonathan Campbell + - Added PUSHF/POPF. + - Added SAHF/LAHF---HA HA HA! LAHF! GET IT? :) + - Added CMPS and SCAS + - Updated instodo.txt to show some instructions that I forgot to + mention were implemented already. + - Fixed bug in REP loop code that continued looping even if + ZF flag failed condition. This caused many REPNE SCASB loops to + fail until it was fixed. + +v0.00.0018: Jonathan Campbell + - Fixed coding mistakes in segment prefix decoder (using >= not ==) + - Added REP/REPZ prefix handling + - Added MOVS, LODS, STOS + - README file rewritten + - Fixed SOFTX86DBG printing unshifted value ANDed from FLAGS for flag + states (e.g. should be ZF=1 not ZF=64). + - The 't' command under SOFTX86DBG now allows optional parameter to + specify how many instructions to step through before returning. For + example: + + t 27 + + means step through 27 instructions. + - Added the ability to compile Softx86 and Softx86dbg using MINGW and + Bloodshed Dev-C++ IDE. + +v0.00.0017: Jonathan Campbell + - Found a way to convince MSVC++ that Softx86 is a dependency of + Softx86dbg. Reorganized project files so that the static library + is a dependency of the DLL version, and the DLL version is a + dependency of Softx86dbg. The DLL version now exports symbols + from the compiled static library version instead of recompiling + the entire library to produce the DLL. + - Softx86dbg now has a pretty icon resource so you can easily + identify it under Windows :) + - Added JMP abs. direct far and CALL abs. direct far. + - Fixed FAR and INTERRUPT stack frame code that put segment and + offset values in the wrong order! + - Added JMP/CALL rel8/rel16. + +v0.00.0016: Jonathan Campbell + - Added TEST and XCHG. + - Added LEA (Load Effective Address) + - Added TEST08.ASM to test the TEST/XCHG instructions. + - Softx86dbg now shows CPU flags as CF=1, AF=0, etc. for clarity. + +v0.00.0015: Jonathan Campbell + - Added DAA, XLAT and DAS instructions. + - Fixed a few subtle bugs in AAA and AAS emulation where final result + was not masked with 0xF like it should have been. + - Fixed AAA/AAS/AAM/AAD instructions to properly set CPU flags like they + should. + +v0.00.0014: Jonathan Campbell + - Registers are now represented by a structure (a union really) + rather than 16-bit word values that are referred to directly with + Endian-sensitive code. I had never thought of using C/C++ unions + like this before... thanks goes to Paul Muller for bringing this + up. On the other hand... in the act of modifying all of the emulation + code to handle the new arrangement it's possible that I broke + something.... please let me know or fix it and e-mail the patch to + me. + - Added Jcc (JMP conditional) instructions (JCXZ,JA,JB,JL,JG,JP,JZ,JC...) + +v0.00.0013: Jonathan Campbell + - Added CMP and AND. + +v0.00.0012: Jonathan Campbell + - Added API call to "reset" the CPU. + - Added XOR. + - Added API call to get library version. This can be used when + linked to the shared library to determine the version and + whether or not it matches the #defines in softx86.h. + +v0.00.0011: Jonathan Campbell + - Fixed missing header file problems in MSVC++ project workspace + files caused by renaming config.h to softx86cfg.h. + - Fixed erroneous use of opcode functions where parameters were + switched from their intended meaning. In other words, the + executioneer functions were passing the destination as the + source and the source as the destination. This causes the + SUB and SBB instructions to add rather than subtract like + they should. + - Added SBB. + - Added INT 3, INT n, INTO. + - Added CPU interrupt handling (external and internal). + - Added bug emulation. + - Added host idle callback for finer emulation during the + execution of an instruction. + - Added CPU NMI code. + - Softx86dbg now allows you to change register values by + typing "r [regname]". + - Softx86dbg now has very primitive INT 20h and INT 21h + emulation. + - Added fix for COM loading code in softx86dbg that would + otherwise overrun the simulated RAM if the user were to + try to debug a very large file. + - More fixes; apparently whenever I transfer the tarball + back and forth between my Linux box and my Windows box + the install.sh script got munged with DOS \n\r sequences. + This apparently causes Bash to come up with really weird + error messages pointing to the functions and referring to + 'nstall.sh (wtf?!?). So from now on the Makefile automatically + generates install.sh when you type "make" for the first time + and removes install.sh file when you type "make distclean". + +v0.00.0010: Jonathan Campbell + - Added SUB and ADC. + - Added ADD r/m,imm. + - Make install improved, more intelligent, moved to install.sh + as a shell script that is called when you type "make install". + - Makefile script more intelligent, automatically creates "obj" + subdirectories now (and removes them on "make distclean"). + - Changed BYTE_ORDER #define in softx86.h so that it doesn't + conflict with headers in /usr/include. It is now called + SX86_BYTE_ORDER. + +v0.00.0009: Jonathan Campbell + - Added IN/OUT instruction emulation. + - Sample code to make use of IN/OUT and hypothetical + hardware adding logic with I/O ports that softx86dbg + provides for testing. + - Fixed erroneous AF (Aux flag) emulation for ADD. Found + out (and later found a reference to this in Intel's + 80286 documentation) that AF is set if the CPU, peforming + addition one 4-bit nibble at a time (a 16/32-bit + processor!?!) has to carry while adding the least + significant nibbles. For example: + 0x04 + 0x06 = 0x0A AF=0 + 0x08 + 0x08 = 0x10 AF=1 + 0x10 + 0xFF = 0x10F AF=0 + 0x1E + 0xFF = 0x11D AF=1 + +v0.00.0008: Jonathan Campbell + - Softx86 now compiles into a shared library for Linux and a + DLL for Win32. + +v0.00.0007: Jonathan Campbell + - More work on the mod/reg/rm decoder + - MOV [r/m],[segreg] and MOV AL/AX,[mem] implemented + - MOV [r/m],[imm] implemented + - More test assembly code + +v0.00.0006: Jonathan Campbell + - Apparently DOS DEBUG single-step command is 't', not 's'. + Sorry :) + - ADD mod/reg/rm and MOV mod/reg/rm implemented. + - ADD al,imm8 and ADD ax,imm16 implemented. + - Segment prefixes CS: DS: ES: and SS: now supported. + +v0.00.0005: Jonathan Campbell + - Installation of library and header files for Softx86 possible + via "make install" command (if you are root). + - Fixed some errors in README file, compiling instructions + clearer now. + +v0.00.0004: Jonathan Campbell + - Linux/GCC makefiles. + - Command line input written for Linux version. + - SoftX86 documentation reference and summary included in source + now. + - Library archive output of SoftX86 for Linux. + - More comments in softx86dbg to make it easier to understand. + +v0.00.0003: Jonathan Campbell + - More opcodes: RET n, RETF, RETF n, IRETD, HLT + - Removed alignment code, statements about 80x86 CPU always + accessing memory on aligned boundaries was wrong, based + on mis-interpretation of CPU diagrams. + - Instruction execution functions can now return value 3 + to indicate that the opcode was executed in full + completeness but that a looping operation is in effect and + that the instruction pointer should remain the same afterwards. + +v0.00.0002: Jonathan Campbell + - More one-byte opcodes added: CBW, CWDE, CWD, CDQ, CLC, + CLD, CLI, CMC, STC, STD, STI + - Made necessary additions to ? command in softx86dbg (now + it honestly tells you all commands supported). + - softx86dbg now heeds "warning" return value from libsoftx86 + and displays warning message. + +v0.00.0001: Jonathan Campbell + - Initial release + - One-byte opcodes added: AAA, AAS, PUSH [reg], POP [reg], + PUSH CS/DS/ES/SS, POP CS/DS/ES/SS, NOP + - Preliminary library interface design + - MSVC 6.0 project workspace files only---Linux Makefile + soon to come + - Program to test library with: softx86dbg + - Sample assembly code to test library with: + samples/test01.asm (NASM required to assemble) Index: lib/3rdparty/softx86/changes.txt =================================================================== --- lib/3rdparty/softx86/changes.txt (révision 59666) +++ lib/3rdparty/softx86/changes.txt (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/changes.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/CMakeLists.txt =================================================================== --- lib/3rdparty/softx86/CMakeLists.txt (révision 0) +++ lib/3rdparty/softx86/CMakeLists.txt (copie de travail) @@ -0,0 +1,3 @@ + +add_subdirectory(softx86) +add_subdirectory(softx87) Index: lib/3rdparty/softx86/CMakeLists.txt =================================================================== --- lib/3rdparty/softx86/CMakeLists.txt (révision 59666) +++ lib/3rdparty/softx86/CMakeLists.txt (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/CMakeLists.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/doc =================================================================== --- lib/3rdparty/softx86/doc (révision 59666) +++ lib/3rdparty/softx86/doc (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/doc ___________________________________________________________________ Added: bugtraq:url ## -0,0 +1 ## +http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID% \ No newline at end of property Added: bugtraq:message ## -0,0 +1 ## +See issue #%BUGID% for more details. \ No newline at end of property Added: tsvn:logminsize ## -0,0 +1 ## +10 \ No newline at end of property Added: bugtraq:logregex ## -0,0 +1,2 ## +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+) \ No newline at end of property Index: lib/3rdparty/softx86/doc/softx86.txt =================================================================== --- lib/3rdparty/softx86/doc/softx86.txt (révision 0) +++ lib/3rdparty/softx86/doc/softx86.txt (copie de travail) @@ -0,0 +1,546 @@ + +Softx86 - Stock Software Intel 80x86 emulation library + +Introduction +============ + +Softx86 is designed to be a simple library that one can +link into their program for 80x86 emulation purposes. +The primary goals of this project are: + +* accurate emulation +* reasonably sized memory footprint +* modular design that closely models the actual + hardware signals (Clocking, I/O, addressable + memory, #INT and #NMI) using callbacks + set up by the program + +The Softx86 library itself is designed to emulate ONLY +the CPU, none of the surrounding hardware. Just like +the real thing the program using Softx86 is responsible +for providing RAM, I/O, and #INT/#NMI signals as +appropriate, and making the necessary calls to cycle the CPU. + + ++-----------------------------------------------+ +| SOFTX86 LIBRARY IN A TYPICAL EMULATOR PROJECT | ++-----------------------------------------------+ + + + +-----------------------------------+ + | APPLICATION AS THE "MOTHERBOARD", | + | "POWER SUPPLY", "RAM", AND "I/O | + | DEVICES". | +------------------------------+ + | | | SOFTX86 LIBRARY AS THE "CPU" | + | MAIN LOOP | | | + | | | | CPU INSTRUCTION EXECUTIONEER | + | +-----------------------------------------------------------^ | | + | | | | | + | ADDRESSABLE RAM EMULATION<=====================(callback)==============| | + | | | | | + | I/O PORT EMULATION<============================(callback)==============/ | + | | | | + | INTERRUPT SIGNAL SOURCE | | | + | \/ \/ | | | + | #INT LINE MODERATOR --------------------->| #NMI handler | + | \/ | | | + | ---------------------------------------->| #INT handler | + | | | | + +-----------------------------------+ +------------------------------+ + + Softx86 is like a lone CPU, it needs a "motherboard" to interact with. + + +The Softx86 API uses context structures to represent +a CPU, rather than internal variables, so that +it is possible to emulate more than one CPU +simultaneously using the same library. This also +puts the CPU's entire state in one location for both +Softx86 and the application using it, so that use +of numerous API calls are generally not needed to get +or set the CPU state (although some members should +not be modified directly). + +STEP 1: CREATING A CPU +====================== + +To create a CPU, you first need to allocate a region +of memory of size sizeof(softx86_ctx). + +----- C example ----- +softx86_ctx* cpu; +cpu = (softx86_ctx*)(malloc(sizeof(softx86_ctx))); + +----- C++ example ----- +softx86_ctx* cpu; +cpu = new softx86_ctx; + +Using memset() to fill the contents of that area with NULL +is advised but not absolutely necessary. + +Then call API function softx86_init(), passing it the address +of the context structure and a constant from softx86.h +that represents which version of the 80x86 the context +structure represents. + +------ C/C++ example ----- +/* I want this CPU to act like a 80286. */ +/* Act appropriately if there is an error. */ +ser=softx86_init(cpu,SX86_CPULEVEL_80286); +if (ser == 0) { + printf("ERROR: Unable to initialize CPU\n"); + return 0; +} + +STEP 2: SET UP CALLBACKS +======================== + +You've made the CPU but now it needs to know who to call +for fetching RAM and I/O. Set that up now. + +WARNING: This is grossly oversimplified, not including code + to properly handle requests that fall outside the + 1MB range! YES IT CAN HAPPEN, ESPECIALLY IF EMULATING + THE 286 WHICH CAN ADDRESS 16MB! See Softx86dbg source + code for a better example! + +----- C/C++ example ----- +/* can hold the entire 1MB range supported by the 8086 */ +unsigned char BIG_HUNK[1024*1024]; + +/* called when reading memory */ +void on_read_memory(void* _ctx,sx86_udword address,sx86_ubyte *buf,int size) +{ + memcpy(buf,BIG_HUNK+address,size); +} + +/* called when writing memory */ +void on_write_memory(void* _ctx,sx86_udword address,sx86_ubyte *buf,int size) +{ + memcpy(BIG_HUNK+address,buf,size); +} + +/* called when reading an I/O port */ +void on_read_io(void* _ctx,sx86_udword address,sx86_ubyte *buf,int size) +{ + /* in this example there are no I/O ports */ + memset(buf,0xFF,size); +} + +/* called when writing an I/O port */ +void on_write_io(void* _ctx,sx86_udword address,sx86_ubyte *buf,int size) +{ + /* in this example there are no I/O ports */ +} + +/* function to set up the callbacks for given cpu */ +void setup_callbacks(softx86_ctx *cpu) +{ + cpu.callbacks->on_read_memory = on_read_memory; + cpu.callbacks->on_write_memory = on_write_memory; + cpu.callbacks->on_read_io = on_read_io; + cpu.callbacks->on_write_io = on_write_io; +} + +Once everything is set up, you must call softx86_reset() +to reset the CPU. + +----- C/C++ example ----- +softx86_reset(cpu); + +STEP 3: GIVE THE CPU SOMETHING TO EXECUTE +========================================= + +For the CPU to execute something it must have valid instructions. +There are many sources that these can be obtained, starting with +simple MS-DOS .COM executables (which can be found on any web site +dedicated to ancient DOS programs and games), or perhaps whatever +happens to be on the hard drive of that old dusty 286 in the corner, +although you can also find some on many Windows 95/98-based systems. +By .COM executables I DO NOT MEAN COM/OLE ActiveX controls! +Anyway, best results can be obtained by using a COM program that is +simple (doesn't rely too much on direct hardware access or performs +a simple function). + +Loading a COM executable into your program's simulated RAM should be +easy: + +----- C/C++ example ----- +void load_code() +{ + FILE *comfile; + + comfile = fopen("whatever.com","rb"); + if (!comfile) { + printf("Unable to load program!\n"); + return 0; + } + + /* remember BIG_HUNK[] ? */ + /* 0x100 offset because of PSP segment and such */ + /* CS:IP = 0x1000:0x0100 */ + /* (0x1000 << 4) + 0x100 = 0x10100 */ + fread(BIG_HUNK+0x10100,65280,1,comfile); + fclose(comfile); + + /* set up a PSP and such... */ + /* I'll leave it up to you as an exercise :) */ + + /* done */ + return 1; +} + +Now that there is code to execute, we need to tell the CPU where +to start executing. To do this, we must redirect the INSTRUCTION +POINTER. + +NOTE: The instruction pointer variables can be accessed directly + through the context structure to obtain the values and + the cached information (such as precalculated segment->linear + conversion). HOWEVER you must not modify these values + directly! + +----- C/C++ example ----- +softx86_set_instruction_ptr(cpu,0x1000,0x100); + +Depending on the program, it is most likely that you will want +to set up the stack pointer as well so that the program has a +usable stack. + +NOTE: The stack pointer must NOT be modified directly, although + the values can be readily obtained through the context + structure! + +----- C/C++ example ----- +softx86_set_stack_ptr(cpu,0x1000,0xFFF8); + +Many DOS programs assume that DOS will set the segment registers +so that CS = DS = ES. Set the segment registers appropriately: + +NOTE: The segment registers carry with them a cached copy of + various state information (limits, precalculated + segment->linear conversion, protected mode bits, etc). + They may be directly accessed through the context + structure but must not be modified directly! + +----- C/C++ example ----- +softx86_setsegval(cpu,SX86_SREG_DS,0x1000); /* set DS */ +softx86_setsegval(cpu,SX86_SREG_ES,0x1000); /* set ES */ + +STEP 4: CYCLING THE CPU +======================= + +Execution doesn't happen unless your program explicitly wants +it to happen, which it does by calling softx86_step(). For +each call to softx86_step(), one instruction is executed +and then control is returned to your program. The return +value indicates success or failure. + +----- C/C++ example ----- +x=softx86_step(cpu); +if (x == 0) { + printf("The CPU failed to execute or recognize an instruction\n"); +} + +During the call, softx86_step() is likely to call your +memory and I/O callback routines (in fact it's guaranteed). +When softx86_step() returns the instruction pointer values +and all registers affected will be updated according to +whatever instruction was executed. On return, the instruction +pointer points to the next instruction that will be executed, +or points to the offending instruction if an error occured. + + +* FOR MORE DETAILS REFER TO THE SOFTX86DBG SOURCE CODE, OR + E-MAIL ME AT jcampbell@mdjk.com. + + +FREEING/DISPOSING OF A CPU +========================== + +Disposing of a CPU is simple. Call softx86_free() +and then free the memory you allocated for that +structure. That's it. + +NOTE: It is very important to call softx86_free() + because Softx86 itself allocates memory + for CPU emulation purposes associated with + that CPU. Freeing the structure and not + calling softx86_free() may (very likely!) + result in memory leaks! + +----- C example ----- +softx86_free(cpu); +free(cpu); + +----- C/C++ example ---- +softx86_free(cpu); +delete cpu; + + +HOW TO SIGNAL AN EXTERNAL HARDWARE INTERRUPT +============================================ + +Use API call softx86_ext_hw_signal() to emulate an #INT +signal from hardware. + +NOTE: Do not assume that this function will succeed. + If softx86_ext_hw_signal() has already been called + but the CPU has not yet acknowledged the interrupt, + softx86_ext_hw_signal() will return 0 (error). + Otherwise, it will return 1 (success). If you plan + on emulating a platform with multiple interrupt + signals possible, consider writing a wrapper for + this call in your program that moderates the + signals somehow. For example, write a portion of + your program that emulates the Programmable + Interrupt Controller in IBM PC/XT/AT+ hardware, then + write a general function your code can call that + emulates IRQ signals being sent to the PIC. The PIC + emulator can then act as a moderator that uses this + function to pass the IRQ signals to the CPU. + +----- C/C++ example, signalling INT 9 (PC/XT/AT+ IRQ 1) from hardware ----- +int i,j; + +/* loop until we can signal the interrupt we want */ +/* ---or, until CPU failure */ +i=1; +j=0; +while (i && !j) { + i=softx86_step(cpu); + if (i) j=softx86_ext_hw_signal(cpu,9); +} + +HOW TO SIGNAL AN EXTERNAL NMI (NON-MASKABLE) HARDWARE INTERRUPT +=============================================================== + +Use API call softx86_ext_hw_nmi_signal() to emulate an +#NMI signal from hardware. + +NOTE: Do not assume that this function will succeed. + If #NMI has already been activated but the CPU + has not yet acknowledged the interrupt, this + function will return 0 (error). Otherwise, it + will return 1 (success). + +NOTE: This signal is processed immediately, even if + #INT is active. #NMI has higher priority than + #INT. + +----- C/C++ example, signalling NMI from hardware ----- +int i,j; + +/* loop until we can signal the interrupt we want */ +/* ---or, until CPU failure */ +i=1; +j=0; +while (i && !j) { + i=softx86_step(cpu); + if (i) j=softx86_ext_hw_nmi_signal(cpu); +} + +HOW TO FORCE SOFTWARE INTERRUPT +=============================== + +calling softx86_int_sw_signal() causes the CPU to branch to +an interrupt as if the INT instruction had just been executed +in the program. + +NOTE: If the CPU is in protected mode, this function may fail + if the interrupt is invalid according to the IDT or + GDT/LDT! + +----- C/C++ example, software interrupt INT 21h ----- +softx86_int_sw_signal(cpu,0x21); + +HOW TO USE THE DECOMPILER +========================= + +In addition to providing the ability to execute instructions, +Softx86 provides an alternate API call to decompile instructions +at an alternate instruction pointer referred to as the +"decompiler instruction pointer". + +First, you set the decompiler IP using +softx86_set_instruction_dec_ptr() or +softx86_decompile_exec_cs_ip(). + +NOTE: The decompiler instruction pointer, like the + CPU instruction pointer, MUST NOT BE MODIFIED + DIRECTLY! + +----- C/C++ example, setting decompile CS:IP to specific values ----- +sx86_udword seg,ofs; +softx86_set_instruction_dec_ptr(cpu,seg,ofs); + +----- C/C++ example, setting decompiler CS:IP == current instruction pointer ----- +softx86_decompile_exec_cs_ip(cpu); + +Then, you call softx86_decompile() for each instruction, providing +for it a char array that is 256 bytes wide or larger. + +----- C/C++ example, decompiling 10 instructions following CS:IP ----- +char asmbuf[256]; +int j; + +softx86_decompile_exec_cs_ip(cpu); +for (j=0;j < 10;j++) { + if (!softx86_decompile(cpu,asmbuf)) { + printf("*decompiler error!\n"); + j=10; /* terminate the loop */ + } + else { + printf("%s\n",asmbuf); + } +} + +HOW TO DETERMINE THE SOFTX86 VERSION +==================================== + +Obtaining the version of the Softx86 library your +program is using is simple. Have 3 integers ready +and call softx86_getversion() like this: + +int x,major,minor,subminor; + +x=softx86_getversion(&major,&minor,&subminor); +if (!x) { + printf("Unable to obtain version!\n"); + return 1; +} + +You can then determine if you're using the version +you were compiled for by matching them against the +constants (defined in softx86.h) SOFTX86_VERSION_HI, +SOFTX86_VERSION_LO, and SOFTX86_VERSION_SUBLO. + +if (major != SOFTX86_VERSION_HI || + minor != SOFTX86_VERSION_LO || + subminor != SOFTX86_VERSION_SUBLO) { + printf("ERROR: Version mismatch!\n"); + return 1; +} + +HOW TO CHANGE THE GENERAL REGISTERS +=================================== + +All of the general registers (AX,BX,CX,DX,SI,DI,BP,SP) +are of type softx86_regval, which is a union that allows +either partial or complete access of the contents +(no matter what the native byte order is). + +The general registers reside in +cpu->state.general_reg[], an array of softx86_regval +values which may be indexed using the constants defined in +softx86.h: + +SX86_REG_AX,SX86_REG_BX,SX86_REG_CX,SX86_REG_DX, +SX86_REG_SI,SX86_REG_DI,SX86_REG_BP,SX86_REG_SP. + +NOTE: You must not modify the SP register directly! + Use softx86_set_stack_ptr() + +Thus, you can read/modify AX like this: + +cpu->state.general_reg[SX86_REG_AX].w.lo + +or EAX like this: + +cpu->state.general_reg[SX86_REG_AX].val + +or AH like this: + +cpu->state.general_reg[SX86_REG_AX].b.hi + +*------------------------------------* +| softx86_regval union naming scheme | +*------------------------------------* +general_reg[idx].val = the entire 32 bit register (e.g. EAX) +general_reg[idx].w.lo = the lower 16 bit portion (e.g. AX bits 0-15) +general_reg[idx].w.hi = the upper 16 bit portion (bits 16-31) +general_reg[idx].b.lo = the lower 8 bit portion (e.g. AL bits 0-7) +general_reg[idx].b.hi = the upper 8 bit portion (e.g. AH bits 8-15) +general_reg[idx].b.extra[0] = bits 16-23 as a byte +general_reg[idx].b.extra[1] = bits 24-31 as a byte + +HOW TO CHANGE THE INSTRUCTION POINTER +===================================== + +The instruction pointer lies in cpu->state.reg_ip (IP) +and cpu->state.segment_reg[SX86_SREG_CS].val (CS). + +NOTE: You should NOT change this value directly! Use + softx86_set_instruction_ptr() or + softx86_set_near_instruction_ptr() instead! + Changing reg_ip directly may cause problems + with instruction prefetch emulation or + any portion of the code that caches the + instruction pointer. + +cpu->state.reg_ip is a DWORD value that represents the +current offset in the code segment. +cpu->state.segment_reg[SX86_SREG_CS].val represents the +actual value of the CS segment register, along with the +precalculated linear and limit values for the segment/selector. + +To change both CS and IP to known values, call +softx86_set_instruction_ptr() with the new CS:IP values. + +NOTE: softx86_set_instruction_ptr() and + softx86_set_near_instruction_ptr() will return + 0 (error) if the CS:IP values are invalid. + +----- C/C++ example ----- +x=softx86_set_instruction_ptr(cpu,0xF000,0xFFF0); +if (!x) { + printf("Failed to set instruction pointer!\n"); + return 1; +} + +If you only wish to change IP without changing CS, +you may call softx86_set_near_instruction_ptr(). + +----- C/C++ example ----- +x=softx86_set_near_instruction_ptr(cpu,0x100); +if (!x) { + printf("Failed to set instruction pointer!\n"); + return 1; +} + +HOW TO CHANGE THE SEGMENT REGISTERS +=================================== + +The segment registers are stored in the context structure +under cpu->state.segment_reg[] and are of type +softx86_segregval. softx86_segregval is a special structure +that holds the value of the register as well as hidden +cached values related to the segment register. + +typedef struct { + sx86_uword val; /* visible to program---the value */ + sx86_udword cached_linear; /* hidden---linear address of segment */ + sx86_udword cached_limit; /* hidden---limit of segment */ +} softx86_segregval; + +A particular segment value may be obtained by using +constants SX86_SREG_ES, SX86_SREG_CS, SX86_SREG_DS, +SX86_SREG_SS as indices to the array. + +NOTE: Do NOT modify these values directly. Use + softx86_setsegval() instead! + +To retrieve the current value in CS for example: + +segment = cpu->state.segment_reg[SX86_SREG_CS].val; + +To set the value of CS: + +x=softx86_setsegval(cpu,SX86_SREG_CS,0xF000); +if (!x) { + printf("Unable to set CS!\n"); + return 1; +} + +NOTE: softx86_setsegval() will return 0 (error) + if the CS value is invalid. Index: lib/3rdparty/softx86/doc/softx86.txt =================================================================== --- lib/3rdparty/softx86/doc/softx86.txt (révision 59666) +++ lib/3rdparty/softx86/doc/softx86.txt (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/doc/softx86.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/faq.txt =================================================================== --- lib/3rdparty/softx86/faq.txt (révision 0) +++ lib/3rdparty/softx86/faq.txt (copie de travail) @@ -0,0 +1,237 @@ +Frequently Asked Questions v0.00.0033 + +Q. When will Softx86 become a full-fledged PC emulator? + +A. It won't. It will however become a full-fledged Intel 80x86 CPU + clone that you can tie into your PC emulation software. + +Q. Where are the sample DOS binaries used to test the emulator? + +A. Prebuilt binaries are now distributed separately from the + source tarball. The source code is still provided, so you + can assemble them yourself if you have NASM (Netwide Assembler) + installed on your system. + +Q. How do I use softx86dbg? + +A. Bring up the command prompt (Windows or Linux), change to the + root directory of the source tree and type "bin/softx86dbg" + followed by a path to a DOS .COM executable. + + For example, to run samples/test11.com in the emulator, type: + + bin/softx86dbg samples/test11.com + + Linux users may benefit from running the statically linked + version (especially if they cannot "su root" and "make install") + because a previous version of the library installed in + /usr/local/lib might be incompatible with the latest version + of softx86dbg. You can run the statically linked version by + typing: + + bin/softx86dbg-static samples/test11.com + + softx86dbg will let you know if it couldn't load the file. + +Q. Softx86dbg is running and it found the COM file I want + to run. Now what? + + Softx86dbg more or less follows the DOS DEBUG.COM style + interface. For each step, the values of the registers + are shown. Commands are parsed one line at a time and + each command is entered as one or more letters. The + commands are: + + r [REGISTER] Change a register value + + r Show the register contents + + t Single-step (execute one instruction) + + q Quit + + d [[seg:]offset] Dump memory at given address. If no + address is given, ds:0x0000 is assumed. + If no segment value is given, the offset + is assumed to be within the current + data (DS) segment. + + u [[seg:]offset] Unassemble (disassemble) instructions + at given address. If no address is given, + disassembly starts at the current location + of the instruction pointer (CS:IP). If + no segment value is given, the offset is + assumed to be within the current code + (CS) segment. + + ? print help. + + Softx86dbg also recognizes commands that the original DOS DEBUG.COM + never had: + + t [x] Single-step times. In other words, + execute instructions then return. + UPDATE: It turns out DEBUG.COM for Windows + XP has this feature after all + + !reset Resets the virtual CPU. + + !ramdump Dumps the virtual RAM to a file named + 1MB_MEM.BIN + +Q. What kind of environment does Softx86dbg emulate? + +A. Softx86dbg emulates a very simple DOS-style environment. An INT 21h + interface is provided for the program to terminate by, and A simple + PSP structure is built for the program. Softx86dbg also demonstrates + the I/O port callback functions by emulating hypothetical hardware + that takes input and performs a simple calculation with it. + + When the program terminates through INT 21h, softx86dbg prints a + notice on the screen indicating that the program terminated. + +Q. How do I talk to the hypothetical hardware? + +A. Currently (as of v0.00.0020) there are two I/O ports that the + hardware exists on. + + Port 0x1234 is a simple register. Every time it is read, the value + is incremented by 0x22 or 0x2222 (depending on how much is read) + and then returned to the CPU. When written, the value is copied + verbatim to the register. + + Port 0x9A is a byte-sized register. When written, the value is + incremented by 1 and then stored in the register. Then read, + the value of the register is returned as-is. + + Since this can change in the future (not to mention conflicts with + actual PC hardware) do not rely on these I/O ports being emulated. + They are used only by samples/test04.com to test the I/O port + emulation of Softx86. + +Q. I wrote a program that uses Softx86. How do I make it execute + instructions? Is there a call that starts a background thread? + +A. Softx86 does not execute or decompile anything by itself. It expects + your program to execute instructions one at a time using + softx86_step(). + +Q. What is this "context structure" that every API function requires? + +A. The context structure represents one CPU and it's current state. + All registers, modes, caches, and such are stored in that state. + The design favors this over the use of static variables so that + one copy of libsoftx86 can potentially emulate several CPUs at + once. + + To "create" a CPU, allocate memory in your program for one + context structure and call softx86_init(). + +/* example of C code creating and initializing softx86 context structure */ + softx86_ctx* cpu; + + cpu = (softx86_ctx*)malloc(sizeof(softx86_ctx)); + memset(cpu,0,sizeof(softx86_ctx)); /* recommended, not strictly necessary */ + softx86_init(cpu); + +/* example of C++ code creating and initializing softx86 context structure */ + softx86_ctx* cpu; + + cpu = new softx86_ctx; + memset(cpu,0,sizeof(softx86_ctx)); /* recommended, not strictly necessary */ + softx86_init(cpu); + +/* example of C++ code pushing softx86 to the extreme by creating 32 separate CPUs */ + softx86_ctx* cpu; + int x; + + cpu = new softx86_ctx[32]; + memset(cpu,0,sizeof(softx86_ctx)*32); /* recommended, not strictly necessary */ + for (x=0;x < 32;x++) /* 32 brains are better than one! */ + softx86_init(&cpu[x]); + + The Softx86 API functions require this context structure so + that they know what CPU to perform the operation on and so that + they have access to the CPU state. To execute an instruction + on cpu0 and decompile something on cpu1, for example, you would + write: + + char cpu1_output[256]; + softx86_step(&cpu0); + softx86_decompile(&cpu1,cpu1_output); + + To delete a CPU and free the resources associated with it + (including caches stored in the context structure), pass + the context structure one last time to soft86_free(). + Once it has been freed by softx86_free() you may free + the memory used by the context structure itself (or + do whatever you want to it). + +/* example of C code freeing a CPU */ + softx86_free(cpu); + free(cpu); + cpu=NULL; + +/* example of C++ code freeing a CPU */ + softx86_free(cpu); + delete cpu; + cpu=NULL; + +/* example of hot-shot C++ code (above) freeing all 32 CPUs he created */ + int x; + + for (x=0;x < 32;x++) + softx86_free(&cpu[x]); + + delete cpu; + cpu=NULL; + +/* example of C code creating, freeing a CPU, then dancing on it's grave */ + char *ptr; + softx86_ctx* cpu; + + ptr = malloc(sizeof(softx86_ctx)); + cpu = (softx86_ctx*)ptr; + softx86_init(cpu); /* create CPU */ + softx86_step(cpu); /* execute something */ + softx86_free(cpu); /* you've served your purpose now get outta here! */ + strcpy(ptr, /* alright yeah! Now I can safely use the same area of memory */ + "Blah Blah Yadda Yadda"); /* to store funny weird ASCIIZ strings! Whoo! */ + free(ptr); /* but I have better things to do... */ + +Q. I get strange errors from make or Bash even though the scripts and Makefiles + look perfectly fine. + +A. The install.sh script may have gotten munged with DOS-style CR LF line breaks. + This seems to happen when I pack the source code into a .tar.gz tarball then + copy the tarball to my Windows machine and unpack it using WinZIP or 7-Zip. + It doesn't immediately seem broken because Notepad and Wordpad show it perfectly, + but when the extracted files are tar and gzip'd and moved back to the Linux box + to be tested, the problems show up almost immediately. Bash expects to see + only LF line breaks, which is why it panics the way it does. GNU Make as far + as I know is generally tolerant of DOS CR/LF sequences so perhaps the + Makefile is corrupt in some way. + + A quick fix can be done by changing to the directory containing Makefile and + install.sh and typing: + + dos2unix install.sh; dos2unix Makefile + + Bash shouldn't have any more problems. + NOTE: I've also found that WinZIP can't extract tar files properly if they + contain symlinks. 7-Zip does just fine. + +Q. There are all these makefiles to make a static library and a DLL. There are + also two makefiles to produce the same program: Softx86dbg. What's the point? + why are you doing this? + +A. Producing Softx86 as a static library AND a DLL allows software developers to + incorporate it into their programs in whatever flavor they like. Some people + especially those producting standalone programs, like statically linked + versions so that they don't have to deal with messy DLL dependencies or carry + extra luggage around with the main executable. Other developers, especially + those working on large projects, like modular designs so that DLLs and + resources can be loaded and unloaded dynamically (imagine a large project + that uses Softx86 as one of many emulation engines to simulate everything + ranging from a PC to a Z-80 to a Super-NES, for example). For these large + projects, Softx86 in DLL form is the best choice. Index: lib/3rdparty/softx86/faq.txt =================================================================== --- lib/3rdparty/softx86/faq.txt (révision 59666) +++ lib/3rdparty/softx86/faq.txt (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/faq.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/install.sh =================================================================== --- lib/3rdparty/softx86/install.sh (révision 0) +++ lib/3rdparty/softx86/install.sh (copie de travail) @@ -0,0 +1,76 @@ +# bin/bash +#--------------------------- +# install script for Softx86 +# (C) 2003 Jonathan Campbell +# +#--------------------------- +# this script automatically generated + +exit_if_failed() { + if [[ !( $? -eq 0 ) ]]; then exit 1; fi + return 0; +} + +installcopy2() { + echo "Installing Softx86 libraries+headers" + exit_if_failed + cp lib/libsoftx86.a /usr/lib/libsoftx86.a + exit_if_failed + cp lib/libsoftx86.so /usr/lib/libsoftx86.so + exit_if_failed + cp include/softx86.h /usr/include/softx86.h + exit_if_failed + cp include/softx86cfg.h /usr/include/softx86cfg.h + exit_if_failed + chmod 644 /usr/lib/libsoftx86.a + exit_if_failed + chmod 644 /usr/lib/libsoftx86.so + exit 0; +} + +install87copy2() { + echo "Installing Softx87 libraries+headers" + exit_if_failed + cp lib/libsoftx87.a /usr/lib/libsoftx87.a + exit_if_failed + cp lib/libsoftx87.so /usr/lib/libsoftx87.so + exit_if_failed + cp include/softx87.h /usr/include/softx87.h + exit_if_failed + chmod 644 /usr/lib/libsoftx87.a + exit_if_failed + chmod 644 /usr/lib/libsoftx87.so + exit 0; +} + +installcopy() { + if (installcopy2); + then echo "Installation done"; + else echo "Installation failed"; + fi + + return 0; +} + +install87copy() { + if (install87copy2); + then echo "Installation done"; + else echo "Installation failed"; + fi +} + +if [[ -f lib/libsoftx86.a && -f lib/libsoftx86.so ]]; +then installcopy; +else echo "You must build this project first"; +exit 0; +fi + +if [ -d softx87 ]; then + if [[ -f lib/libsoftx87.a && -f lib/libsoftx87.so ]]; + then install87copy; + else echo "You must build softx87 first"; + exit 0; + fi +fi + +#end Index: lib/3rdparty/softx86/install.sh =================================================================== --- lib/3rdparty/softx86/install.sh (révision 59666) +++ lib/3rdparty/softx86/install.sh (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/install.sh ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/instodo.txt =================================================================== --- lib/3rdparty/softx86/instodo.txt (révision 0) +++ lib/3rdparty/softx86/instodo.txt (copie de travail) @@ -0,0 +1,230 @@ + +A complete log of which instructions have been implemented so far: + +KEY: X = execution implemented + D = decompiler implemented + B = has known bugs + I = incomplete preliminary + ? = bug-free status not confirmed + - = not implemented + N = not handled if emulating that particular CPU + + INS OPCODE CONTRIBUTED TO BY 8086 8088 186 286 386 486 +==============|=============|======================|====|====|===|===|===|===| +ADD |0x00-0x03 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +ADD |0x04-0x05 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +PUSH ES |0x06 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +POP ES |0x07 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +OR |0x08-0x0B |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +OR |0x0C-0x0D |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +PUSH CS |0x0E |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +POP CS |0x0F |jcampbell@mdjk.com |XD? |XD? |N |N |N |N | +SMSW /4 |0x0F 0x01 /4 |jcampbell@mdjk.com |N |N |XD?|XD?|XD?|XD?| +LMSW /6 |0x0F 0x01 /6 |jcampbell@mdjk.com |N |N |XD?|XD?|XD?|XD?| +ADC |0x10-0x13 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +ADC |0x14-0x15 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +PUSH SS |0x16 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +POP SS |0x17 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SBB |0x18-0x1B |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SBB |0x1C-0x1D |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +PUSH DS |0x1E |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +POP DS |0x1F |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +AND |0x20-0x23 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +AND |0x24-0x25 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +ES: |0x26 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +DAA |0x27 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SUB |0x28-0x2B |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SUB |0x2C-0x2D |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +CS: |0x2E |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +DAS |0x2F |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +XOR |0x30-0x33 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +XOR |0x34-0x35 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SS: |0x36 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +AAA |0x37 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +CMP |0x38-0x3B |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +CMP |0x3C-0x3D |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +DS: |0x3E |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +AAS |0x3F |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +INC [reg] |0x40-0x47 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +DEC [reg] |0x48-0x4F |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +PUSH [reg] |0x50-0x57 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +POP [reg] |0x58-0x5F |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +PUSHA |0x60 |jcampbell@mdjk.com |N |XD? |XD?|XD?|XD?|XD?| +POPA |0x61 |jcampbell@mdjk.com |N |XD? |XD?|XD?|XD?|XD?| +BOUND reg,rm |0x62 |jcampbell@mdjk.com |N |XD? |XD?|XD?|XD?|XD?| +J [near] |0x70-0x7F |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +ADD rm,imm /0 |0x80-0x83 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +OR rm,imm /1 |0x80-0x83 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +ADC rm,imm /2 |0x80-0x83 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SBB rm,imm /3 |0x80-0x83 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +AND rm,imm /4 |0x80-0x83 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SUB rm,imm /5 |0x80-0x83 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +XOR rm,imm /6 |0x80-0x83 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +CMP rm,imm /7 |0x80-0x83 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +TEST reg,r/m |0x84-0x85 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +XCHG reg,r/m |0x86-0x87 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +MOV |0x88-0x8B |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +MOV [sreg] |0x8C |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +LEA reg,r/m |0x8D |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +MOV [sreg] |0x8E |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +POP mem rm /6 |0x8F /6 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +NOP/XCHG AX,AX|0x90 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +XCHG reg16,AX |0x91-0x97 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +CBW |0x98 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +CWD |0x99 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +CALL seg:ofs |0x9A |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +WAIT |0x9B |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +PUSHF |0x9C |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +POPF |0x9D |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +SAHF |0x9E |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +LAHF |0x9F |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +MOV |0xA0-0xA3 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +MOVS |0xA4-0xA5 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +CMPS |0xA6-0xA7 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +TEST |0xA8-0xA9 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +STOS |0xAA-0xAB |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +LODS |0xAC-0xAD |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SCAS |0xAE-0xAF |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +MOV |0xB0-0xB7 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +MOV |0xB8-0xBF |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +ROL rm,imm /0 |0xC0-0xC1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +ROR rm,imm /1 |0xC0-0xC1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +RCL rm,imm /2 |0xC0-0xC1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +RCR rm,imm /3 |0xC0-0xC1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SHL rm,imm /4 |0xC0-0xC1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SHR rm,imm /5 |0xC0-0xC1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SAR rm,imm /7 |0xC0-0xC1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +RET + POP n |0xC2 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +RET (near) |0xC3 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +LES reg,rm |0xC4 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +LDS reg,rm |0xC5 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +MOV |0xC6-0xC7 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +ENTER imm,imm |0xC8 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +LEAVE |0xC9 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +RETF + POP n |0xCA |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +RETF (far) |0xCB |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +INT 3h |0xCC |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +INT n |0xCD |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +INTO |0xCE |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +IRET |0xCF |jcampbell@mdjk.com |XD? |XD |XD |XD |XD |XD | +ROL rm,1 /0 |0xD0-0xD1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +ROR rm,1 /1 |0xD0-0xD1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +RCL rm,1 /2 |0xD0-0xD1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +RCR rm,1 /3 |0xD0-0xD1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SHL rm,1 /4 |0xD0-0xD1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SHR rm,1 /5 |0xD0-0xD1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SAR rm,1 /7 |0xD0-0xD1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +ROL rm,CL /0 |0xD2-0xD3 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +ROR rm,CL /1 |0xD2-0xD3 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +RCL rm,CL /2 |0xD2-0xD3 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +RCR rm,CL /3 |0xD2-0xD3 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SHL rm,CL /4 |0xD2-0xD3 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SHR rm,CL /5 |0xD2-0xD3 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +SAR rm,CL /7 |0xD2-0xD3 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +AAM |0xD4 |jcampbell@mdjk.com |XD? |XD |XD |XD |XD |XD | +AAD |0xD5 |jcampbell@mdjk.com |XD? |XD |XD |XD |XD |XD | +XLAT |0xD7 |jcampbell@mdjk.com |XD? |XD |XD |XD |XD |XD | +[FPU backend] |0xD8-0xDF |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +LOOPNZ |0xE0 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +LOOPZ |0xE1 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +LOOP |0xE2 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +JCXZ |0xE3 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +IN AL,imm |0xE4 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +IN AX,imm |0xE5 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +OUT AL,imm |0xE6 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +OUT AX,imm |0xE7 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +CALL rel16 |0xE8 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +JMP rel16 |0xE9 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +JMP seg:ofs |0xEA |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +JMP rel8 |0xEB |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +IN AL,DX |0xEC |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +IN AX,DX |0xED |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +OUT AL,DX |0xEE |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +OUT AX,DX |0xEF |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +LOCK |0xF0 |jcampbell@mdjk.com |XDI |XDI |XDI|XDI|XDI|XDI| +REPNZ |0xF2 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +REPZ |0xF3 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +HLT |0xF4 |jcampbell@mdjk.com |XDI |XDI |XDI|XDI|XDI|XDI| +CMC |0xF5 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +TEST rm,imm /0|0xF6-0xF7 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +NOT rm /2 |0xF6-0xF7 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +NEG rm /3 |0xF6-0xF7 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +MUL rm /4 |0xF6-0xF7 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +IMUL rm /5 |0xF6-0xF7 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +DIV rm /6 |0xF6-0xF7 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +IDIV rm /7 |0xF6-0xF7 |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +CLC |0xF8 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +STC |0xF9 |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +CLI |0xFA |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +STI |0xFB |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +CLD |0xFC |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +STD |0xFD |jcampbell@mdjk.com |XD |XD |XD |XD |XD |XD | +INC rm /0 |0xFE-0xFF |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +DEC rm /1 |0xFE-0xFF |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +CALL rm /2 |0xFF |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +JMP rm /3 |0xFF |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +CALL FAR rm /4|0xFF |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +JMP FAR rm /5 |0xFF |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| +PUSH mem rm /6|0xFF |jcampbell@mdjk.com |XD? |XD? |XD?|XD?|XD?|XD?| + +FPU INSTRUCTIONS + + INS OPCODE CONTRIBUTED TO BY 8087 287 387 487 +==============|===============|======================|====|===|===|===| +FADD mem32 |0xD8 /0 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FCOM mem32 |0xD8 /2 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FCOMP mem32 |0xD8 /3 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FSUB mem32 |0xD8 /4 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FDIV mem32 |0xD8 /6 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FDIVR mem32 |0xD8 /7 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FADD (0),(i) |0xD8 0xC0-0xC7 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FSUB (0),(i) |0xD8 0xE0-0xE7 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FDIV (0),(i) |0xD8 0xF0-0xF7 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FDIVR (0),(i) |0xD8 0xF8-0xFF |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FLD mem32 |0xD9 /0 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FLD ST(i) |0xD9 0xC0-0xC7 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FNOP |0xD9 0xD0 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FCHS |0xD9 0xE0 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FABS |0xD9 0xE1 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FLD1 |0xD9 0xE8 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FLDL2T |0xD9 0xE9 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FLDL2E |0xD9 0xEA |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FLDPI |0xD9 0xEB |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FLDLG2 |0xD9 0xEC |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FLDLN2 |0xD9 0xED |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FLDZ |0xD9 0xEE |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +F2XM1 |0xD9 0xF0 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FDECSTP |0xD9 0xF6 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FINCSTP |0xD9 0xF7 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FRNDINT |0xD9 0xFC |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FSCALE |0xD9 0xFD |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FIADD mem32 |0xDA /0 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FICOM mem32 |0xDA /2 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FICOMP mem32 |0xDA /3 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FISUB mem32 |0xDA /4 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FIDIV mem32 |0xDA /6 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FIDIVR mem32 |0xDA /7 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FCLEX |0xDB 0xE2 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FINIT |0xDB 0xE3 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FADD mem64 |0xDC /0 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FCOM mem64 |0xDC /2 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FCOMP mem64 |0xDC /3 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FSUB mem64 |0xDC /4 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FDIV mem64 |0xDC /6 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FDIVR mem64 |0xDC /7 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FADD (i),(0) |0xDC 0xC0-0xC7 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FDIVR (i),(0) |0xDC 0xF0-0xF7 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FDIV (i),(0) |0xDC 0xF8-0xFF |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FLD ST(i) |0xDD /0 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FFREE ST(i) |0xDD 0xC0-0xC7 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FIADD mem16 |0xDE /0 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FICOM mem16 |0xDE /2 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FICOMP mem16 |0xDE /3 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FIDIV mem16 |0xDE /6 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FIDIVR mem16 |0xDE /7 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FADDP (i),(0) |0xDE 0xC0-0xC7 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FCOMPP |0xDE 0xD9 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FSUBP (i),(0) |0xDE 0xE8-0xEF |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FDIVRP (i),(0)|0xDE 0xF0-0xF7 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FDIVP (i),(0) |0xDE 0xF8-0xFF |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| +FBLD mem80 |0xDF /4 |jcampbell@mdjk.com |XD? |XD?|XD?|XD?| Index: lib/3rdparty/softx86/instodo.txt =================================================================== --- lib/3rdparty/softx86/instodo.txt (révision 59666) +++ lib/3rdparty/softx86/instodo.txt (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/instodo.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/license.txt =================================================================== --- lib/3rdparty/softx86/license.txt (révision 0) +++ lib/3rdparty/softx86/license.txt (copie de travail) @@ -0,0 +1,340 @@ + GNU GENERAL PUBLIC LICENSE + Version 2, June 1991 + + Copyright (C) 1989, 1991 Free Software Foundation, Inc. + 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The licenses for most software are designed to take away your +freedom to share and change it. By contrast, the GNU General Public +License is intended to guarantee your freedom to share and change free +software--to make sure the software is free for all its users. This +General Public License applies to most of the Free Software +Foundation's software and to any other program whose authors commit to +using it. (Some other Free Software Foundation software is covered by +the GNU Library General Public License instead.) You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +this service if you wish), that you receive source code or can get it +if you want it, that you can change the software or use pieces of it +in new free programs; and that you know you can do these things. + + To protect your rights, we need to make restrictions that forbid +anyone to deny you these rights or to ask you to surrender the rights. +These restrictions translate to certain responsibilities for you if you +distribute copies of the software, or if you modify it. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must give the recipients all the rights that +you have. You must make sure that they, too, receive or can get the +source code. And you must show them these terms so they know their +rights. + + We protect your rights with two steps: (1) copyright the software, and +(2) offer you this license which gives you legal permission to copy, +distribute and/or modify the software. + + Also, for each author's protection and ours, we want to make certain +that everyone understands that there is no warranty for this free +software. If the software is modified by someone else and passed on, we +want its recipients to know that what they have is not the original, so +that any problems introduced by others will not reflect on the original +authors' reputations. + + Finally, any free program is threatened constantly by software +patents. We wish to avoid the danger that redistributors of a free +program will individually obtain patent licenses, in effect making the +program proprietary. To prevent this, we have made it clear that any +patent must be licensed for everyone's free use or not licensed at all. + + The precise terms and conditions for copying, distribution and +modification follow. + + GNU GENERAL PUBLIC LICENSE + TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION + + 0. This License applies to any program or other work which contains +a notice placed by the copyright holder saying it may be distributed +under the terms of this General Public License. The "Program", below, +refers to any such program or work, and a "work based on the Program" +means either the Program or any derivative work under copyright law: +that is to say, a work containing the Program or a portion of it, +either verbatim or with modifications and/or translated into another +language. (Hereinafter, translation is included without limitation in +the term "modification".) Each licensee is addressed as "you". + +Activities other than copying, distribution and modification are not +covered by this License; they are outside its scope. The act of +running the Program is not restricted, and the output from the Program +is covered only if its contents constitute a work based on the +Program (independent of having been made by running the Program). +Whether that is true depends on what the Program does. + + 1. You may copy and distribute verbatim copies of the Program's +source code as you receive it, in any medium, provided that you +conspicuously and appropriately publish on each copy an appropriate +copyright notice and disclaimer of warranty; keep intact all the +notices that refer to this License and to the absence of any warranty; +and give any other recipients of the Program a copy of this License +along with the Program. + +You may charge a fee for the physical act of transferring a copy, and +you may at your option offer warranty protection in exchange for a fee. + + 2. You may modify your copy or copies of the Program or any portion +of it, thus forming a work based on the Program, and copy and +distribute such modifications or work under the terms of Section 1 +above, provided that you also meet all of these conditions: + + a) You must cause the modified files to carry prominent notices + stating that you changed the files and the date of any change. + + b) You must cause any work that you distribute or publish, that in + whole or in part contains or is derived from the Program or any + part thereof, to be licensed as a whole at no charge to all third + parties under the terms of this License. + + c) If the modified program normally reads commands interactively + when run, you must cause it, when started running for such + interactive use in the most ordinary way, to print or display an + announcement including an appropriate copyright notice and a + notice that there is no warranty (or else, saying that you provide + a warranty) and that users may redistribute the program under + these conditions, and telling the user how to view a copy of this + License. (Exception: if the Program itself is interactive but + does not normally print such an announcement, your work based on + the Program is not required to print an announcement.) + +These requirements apply to the modified work as a whole. If +identifiable sections of that work are not derived from the Program, +and can be reasonably considered independent and separate works in +themselves, then this License, and its terms, do not apply to those +sections when you distribute them as separate works. But when you +distribute the same sections as part of a whole which is a work based +on the Program, the distribution of the whole must be on the terms of +this License, whose permissions for other licensees extend to the +entire whole, and thus to each and every part regardless of who wrote it. + +Thus, it is not the intent of this section to claim rights or contest +your rights to work written entirely by you; rather, the intent is to +exercise the right to control the distribution of derivative or +collective works based on the Program. + +In addition, mere aggregation of another work not based on the Program +with the Program (or with a work based on the Program) on a volume of +a storage or distribution medium does not bring the other work under +the scope of this License. + + 3. You may copy and distribute the Program (or a work based on it, +under Section 2) in object code or executable form under the terms of +Sections 1 and 2 above provided that you also do one of the following: + + a) Accompany it with the complete corresponding machine-readable + source code, which must be distributed under the terms of Sections + 1 and 2 above on a medium customarily used for software interchange; or, + + b) Accompany it with a written offer, valid for at least three + years, to give any third party, for a charge no more than your + cost of physically performing source distribution, a complete + machine-readable copy of the corresponding source code, to be + distributed under the terms of Sections 1 and 2 above on a medium + customarily used for software interchange; or, + + c) Accompany it with the information you received as to the offer + to distribute corresponding source code. (This alternative is + allowed only for noncommercial distribution and only if you + received the program in object code or executable form with such + an offer, in accord with Subsection b above.) + +The source code for a work means the preferred form of the work for +making modifications to it. For an executable work, complete source +code means all the source code for all modules it contains, plus any +associated interface definition files, plus the scripts used to +control compilation and installation of the executable. However, as a +special exception, the source code distributed need not include +anything that is normally distributed (in either source or binary +form) with the major components (compiler, kernel, and so on) of the +operating system on which the executable runs, unless that component +itself accompanies the executable. + +If distribution of executable or object code is made by offering +access to copy from a designated place, then offering equivalent +access to copy the source code from the same place counts as +distribution of the source code, even though third parties are not +compelled to copy the source along with the object code. + + 4. You may not copy, modify, sublicense, or distribute the Program +except as expressly provided under this License. Any attempt +otherwise to copy, modify, sublicense or distribute the Program is +void, and will automatically terminate your rights under this License. +However, parties who have received copies, or rights, from you under +this License will not have their licenses terminated so long as such +parties remain in full compliance. + + 5. You are not required to accept this License, since you have not +signed it. However, nothing else grants you permission to modify or +distribute the Program or its derivative works. These actions are +prohibited by law if you do not accept this License. Therefore, by +modifying or distributing the Program (or any work based on the +Program), you indicate your acceptance of this License to do so, and +all its terms and conditions for copying, distributing or modifying +the Program or works based on it. + + 6. Each time you redistribute the Program (or any work based on the +Program), the recipient automatically receives a license from the +original licensor to copy, distribute or modify the Program subject to +these terms and conditions. You may not impose any further +restrictions on the recipients' exercise of the rights granted herein. +You are not responsible for enforcing compliance by third parties to +this License. + + 7. If, as a consequence of a court judgment or allegation of patent +infringement or for any other reason (not limited to patent issues), +conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot +distribute so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you +may not distribute the Program at all. For example, if a patent +license would not permit royalty-free redistribution of the Program by +all those who receive copies directly or indirectly through you, then +the only way you could satisfy both it and this License would be to +refrain entirely from distribution of the Program. + +If any portion of this section is held invalid or unenforceable under +any particular circumstance, the balance of the section is intended to +apply and the section as a whole is intended to apply in other +circumstances. + +It is not the purpose of this section to induce you to infringe any +patents or other property right claims or to contest validity of any +such claims; this section has the sole purpose of protecting the +integrity of the free software distribution system, which is +implemented by public license practices. Many people have made +generous contributions to the wide range of software distributed +through that system in reliance on consistent application of that +system; it is up to the author/donor to decide if he or she is willing +to distribute software through any other system and a licensee cannot +impose that choice. + +This section is intended to make thoroughly clear what is believed to +be a consequence of the rest of this License. + + 8. If the distribution and/or use of the Program is restricted in +certain countries either by patents or by copyrighted interfaces, the +original copyright holder who places the Program under this License +may add an explicit geographical distribution limitation excluding +those countries, so that distribution is permitted only in or among +countries not thus excluded. In such case, this License incorporates +the limitation as if written in the body of this License. + + 9. The Free Software Foundation may publish revised and/or new versions +of the General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + +Each version is given a distinguishing version number. If the Program +specifies a version number of this License which applies to it and "any +later version", you have the option of following the terms and conditions +either of that version or of any later version published by the Free +Software Foundation. If the Program does not specify a version number of +this License, you may choose any version ever published by the Free Software +Foundation. + + 10. If you wish to incorporate parts of the Program into other free +programs whose distribution conditions are different, write to the author +to ask for permission. For software which is copyrighted by the Free +Software Foundation, write to the Free Software Foundation; we sometimes +make exceptions for this. Our decision will be guided by the two goals +of preserving the free status of all derivatives of our free software and +of promoting the sharing and reuse of software generally. + + NO WARRANTY + + 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY +FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN +OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES +PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED +OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF +MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS +TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE +PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, +REPAIR OR CORRECTION. + + 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR +REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, +INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING +OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED +TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY +YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER +PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE +POSSIBILITY OF SUCH DAMAGES. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +convey the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + 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 + + +Also add information on how to contact you by electronic and paper mail. + +If the program is interactive, make it output a short notice like this +when it starts in an interactive mode: + + Gnomovision version 69, Copyright (C) year name of author + Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, the commands you use may +be called something other than `show w' and `show c'; they could even be +mouse-clicks or menu items--whatever suits your program. + +You should also get your employer (if you work as a programmer) or your +school, if any, to sign a "copyright disclaimer" for the program, if +necessary. Here is a sample; alter the names: + + Yoyodyne, Inc., hereby disclaims all copyright interest in the program + `Gnomovision' (which makes passes at compilers) written by James Hacker. + + , 1 April 1989 + Ty Coon, President of Vice + +This General Public License does not permit incorporating your program into +proprietary programs. If your program is a subroutine library, you may +consider it more useful to permit linking proprietary applications with the +library. If this is what you want to do, use the GNU Library General +Public License instead of this License. Index: lib/3rdparty/softx86/license.txt =================================================================== --- lib/3rdparty/softx86/license.txt (révision 59666) +++ lib/3rdparty/softx86/license.txt (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/license.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/Makefile =================================================================== --- lib/3rdparty/softx86/Makefile (révision 0) +++ lib/3rdparty/softx86/Makefile (copie de travail) @@ -0,0 +1,56 @@ +# Linux makefile for compiling SOFTX86 +# (C) 2003 Jonathan Campbell all rights reserved. +# +# Requirements: +# GCC 3.xx +# NASM 0.95 and better +# +# This Makefile really just calls Make to compile sub-projects. + +# make it all +all:: __autodetect_softx87 __autodetect_nasm + make -C samples + make -C softx86 + if [ -d softx87 ]; then make -C softx87; fi + make -C softx86dbg + +# clean it all +clean:: __fake_makes + make -C samples clean + make -C softx86 clean + if [ -d softx87 ]; then make -C softx87 clean; fi + make -C softx86dbg clean + +# clean it all for distribution +distclean:: __fake_makes + make -C samples distclean + make -C softx86 distclean + if [ -d softx87 ]; then make -C softx87 distclean; fi + make -C softx86dbg distclean + rm -f softx86dbg/Makefile.softx86 + rm -f samples/Makefile.nasm + rm -f lib/*.exp # clean up excess files from MSVC++ + rm -f softx86.ncb + rm -f softx86.opt + +# copy libsoftx86 and friends to the /usr/include and /usr/lib directories. +install:: + if [ -f install.sh ]; then sh install.sh; fi + +# run shell script that looks for soft87 project source +# tree (to be extracted within this source tree) +__autodetect_softx87: + ./autodetect_softx87.sh + +# run shell script to look for NASM +__autodetect_nasm: + ./autodetect_nasm.sh + +# create temporary empty versions of the +# include Makefiles that some rely on +# so they work. They will be deleted when +# "make clean" or "make distclean" is finished +__fake_makes: + if [[ !( -f samples/Makefile.nasm ) ]]; then echo "# nothing" >samples/Makefile.nasm; fi + if [[ !( -f softx86dbg/Makefile.softx86 ) ]]; then echo "# nothing" >softx86dbg/Makefile.softx86; fi + Index: lib/3rdparty/softx86/Makefile =================================================================== --- lib/3rdparty/softx86/Makefile (révision 59666) +++ lib/3rdparty/softx86/Makefile (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/readme.txt =================================================================== --- lib/3rdparty/softx86/readme.txt (révision 0) +++ lib/3rdparty/softx86/readme.txt (copie de travail) @@ -0,0 +1,198 @@ +Softx86: Software x86 CPU emulator library v0.00.0032 + +UNPACKING THE SOURCE TARBALLS +============================= + +Softx86 is distributed as several tarballs. The base tarball, +softx86-vx.xx.xxxx, contains the source code for softx86 +itself. No prebuild binaries are provided. The other source +tarballs are meant to be obtained and then extracted in the +same directory that you extracted softx86 itself. + +The additional tarballs contain: +- The sample binaries, already assembled +- Prebuilt Win32 versions of the libraries + and softx86dbg in DLL and static form. + +The Softx86 make system automatically detects the +presence of the softx87 directory (which exists +only if you extracted the softx87 tarball correctly). +If it is found, makefiles are modified so that +softx86dbg is built and compiled to use it. + +as of v0.00.0030 the softx87 source tree is now +distributed with softx86. + +EXAMPLE OF UNPACKING THE ENTIRE SOFTX86 PROJECT: + +cd /usr/src +tar -xzf softx86-v0.00.0032 +cd softx86 +make +make install + +PLATFORMS SUPPORTED +=================== + +Softx86 is carefully written and maintained so that the same source +tree can be used to produce Win32 and Linux binaries as well as +Win32 DLLs and Linux shared libraries. Compiler-specific optimizations +are welcome though they will be separated with #ifdef...#else...#endif +statements and macros for full portability. Optimizations and code +organization sensitive to various characteristics of the platform can +be controlled via #defines in include/config.h. + +COMPILING FOR WIN32 +=================== + +To compile the Win32 versions you will need Microsoft Visual C++ 32-bit +for Visual Studio 6.0 or higher. Service pack 5 and the latest processor pack +are recommended but not required. + +From Visual Studio, select "open workspace" and open softx86.dsw. Select +"softx86 - release", then hilight both projects in the workspace window. +Right click and select "build selection only" from the popup menu. + +This should make the following files: + +bin/softx86dbg.exe Win32 console application (NOT DOS!) not unlike + DOS DEBUG to test softx86. + +lib/softx86.lib Static library of softx86. + +WARNING: The interfaces and structures can and will change! If you distribute + a binary version of your program that uses Softx86, later versions + may break your program! This is alpha software, the context structure + has not been finalized! + +To recompile the test COM programs, you will need the Win32 or DOS version of +NASM installed somewhere referred to in your PATH= variable or in the same +directory. + +COMPILING FOR LINUX +=================== + +To compile for Linux you will need GCC 3.2.xx or higher, NASM 0.98 or higher, +make 3.79 or higher, and GNU ld 2.13 or higher. + +If you extracted the source tarball over the source of older versions please +type "make distclean" to clean up the source tree. + +Type "make" to compile the entire project. +This will make the following files: + +bin/softx86dbg console application not unlike DOS DEBUG to test + softx86. + +bin/softx86dbg-static statically linked version of softx86dbg. + +lib/libsoftx86.a Static library of softx86. + +lib/libsoftx86.so Shared library of softx86. + +Then, super-user to or logon as "root" and type "make install". This +will run a bash shell script that copies libsoftx86.a and libsoftx86.so +to your /usr/lib directory. This script will also copy softx86.h and +softx86cfg.h to your /usr/include directory. If any errors occur during +the installation process the script will immediately exit with a message. + +WARNING: The interfaces and structures can and will change! If you distribute + a binary version of your program that uses Softx86, later versions + may break your program! This is alpha software, the context structure + has not been finalized! + +USING SOFTX86DBG +================ + +Softx86dbg is a DOS DEBUG-style debugger that uses Softx86. It allows +very simple debugging of COM executable binary images written for DOS. +It does *NOT* emulate directly from an assembly language listing! + +Softx86dbg does not load a COM image by default. You must specify one +on the command line. + +DESIGN GOALS +============ + +The goal of Softx86 is to eventually become a full functioning software +clone of the Intel 80x86 CPU. I want to stress, however, that this library is +intended to become exactly that and no more. The interface between this +library and the host application is designed so that this library is only +responsible for fetching data and executing/decompiling instructions; the host +application is responsible for emulating other aspects of the PC platform +hardware (i.e. system timer or keyboard controller) and providing the +simulated memory for the CPU to fetch data from or write data to, thus +this library can be used to emulate ANY platform or environment involving +some use of the x86. + +WHY NOT C++ +=========== + +I am writing the majority of this library in C (even though the softx86dbg +program is in fact written in C++) so that it can be linked to either C or +C++ programs (whatever your preference). Writing this library in C++ in +contrast would render it unusable for C programs or require the use of +"wrappers". + +HOW DOES THE LIBRARY INTERACT WITH THE HOST APPLICATION? +======================================================== + +The host application allocates memory for a "context structure" that +represents one CPU (of type struct softx86_ctx). The host app then calls +softx86_init() to initialize the memebrs of that structure, given a value +specifying which revision of the 80x86 to emulate. Once done, the host app +can use other library API functions like softx86_set_instruction_ptr() to +set the instruction pointer, register values, etc. + +The library CPU does not automatically start executing instructions on +it's own. It only executes instructions when the host app tells it to by +repeatedly calling softx86_step() per instruction. Thus, how fast the +software CPU runs is highly dependant on how efficient the host application +is. + +The library can (and will) request memory and I/O data from the host app +via callback function pointers contained within the context structure. There +is currently no API function to set them, it is assumed that the host +application will assign to them the address of functions within itself that +will fullfill the I/O request. + +There are currently four callback functions to the host app: + +void (*on_read_memory)(/* softx86_ctx */ void* _ctx, + sx86_udword address,sx86_ubyte *buf,int size); + +void (*on_read_io)(/* softx86_ctx */ void* _ctx,sx86_udword address, + sx86_ubyte *buf,int size); + +void (*on_write_memory)(/* softx86_ctx */ void* _ctx,sx86_udword address, + sx86_ubyte *buf,int size); + +void (*on_write_io)(/* softx86_ctx */ void* _ctx,sx86_udword address, + sx86_ubyte *buf,int size); + +on_read_memory: called when the CPU wants to fetch from simulated memory +on_write_memory: called when the CPU wants to store to simulated memory +on_read_io: called when the CPU wants to fetch from an I/O port + (typically the IN/INSB instruction) +on_write_io: called when the CPU wants to store to an I/O port + (typically the OUT/OUTSB instruction) + +SOFTX86 DOESN'T SUPPORT FPU INSTRUCTIONS BY ITSELF +================================================== + +Softx86 does not support FPU instructions by itself, +following the design of the original chip. Instead, +FPU opcodes are handed off to a callback function +which can then call an external library that functions +as the 8087. If the callback function is not assigned, +the FPU opcodes D8h thru DFh are treated as unknown and +invalid opcodes. + +/* this is called when the CPU is asked to execute an FPU opcode */ +int (*on_fpu_opcode_exec) + (/* softx86_ctx */void* _ctx,sx86_ubyte opcode); + +/* this is called when the CPU is asked to decompile an FPU opcode */ +int (*on_fpu_opcode_dec) + (/* softx86_ctx */void* _ctx,sx86_ubyte opcode,char buf[128]); + Index: lib/3rdparty/softx86/readme.txt =================================================================== --- lib/3rdparty/softx86/readme.txt (révision 59666) +++ lib/3rdparty/softx86/readme.txt (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/readme.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86 =================================================================== --- lib/3rdparty/softx86/softx86 (révision 59666) +++ lib/3rdparty/softx86/softx86 (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86 ___________________________________________________________________ Added: bugtraq:url ## -0,0 +1 ## +http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID% \ No newline at end of property Added: bugtraq:message ## -0,0 +1 ## +See issue #%BUGID% for more details. \ No newline at end of property Added: tsvn:logminsize ## -0,0 +1 ## +10 \ No newline at end of property Added: bugtraq:logregex ## -0,0 +1,2 ## +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+) \ No newline at end of property Index: lib/3rdparty/softx86/softx86.dsw =================================================================== --- lib/3rdparty/softx86/softx86.dsw (révision 0) +++ lib/3rdparty/softx86/softx86.dsw (copie de travail) @@ -0,0 +1,107 @@ +Microsoft Developer Studio Workspace File, Format Version 6.00 +# WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE! + +############################################################################### + +Project: "softx86_dll"=.\softx86\softx86_dll.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name softx86_static + End Project Dependency +}}} + +############################################################################### + +Project: "softx86_static"=.\softx86\softx86_static.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Project: "softx86dbg_dll"=.\softx86dbg\softx86dbg_dll.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name softx86_dll + End Project Dependency + Begin Project Dependency + Project_Dep_Name softx87_dll + End Project Dependency +}}} + +############################################################################### + +Project: "softx86dbg_static"=.\softx86dbg\softx86dbg_static.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name softx86_static + End Project Dependency + Begin Project Dependency + Project_Dep_Name softx87_static + End Project Dependency +}}} + +############################################################################### + +Project: "softx87_dll"=.\softx87\softx87_dll.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ + Begin Project Dependency + Project_Dep_Name softx87_static + End Project Dependency +}}} + +############################################################################### + +Project: "softx87_static"=.\softx87\softx87_static.dsp - Package Owner=<4> + +Package=<5> +{{{ +}}} + +Package=<4> +{{{ +}}} + +############################################################################### + +Global: + +Package=<5> +{{{ +}}} + +Package=<3> +{{{ +}}} + +############################################################################### + Index: lib/3rdparty/softx86/softx86.dsw =================================================================== --- lib/3rdparty/softx86/softx86.dsw (révision 59666) +++ lib/3rdparty/softx86/softx86.dsw (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86.dsw ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/aaa.c =================================================================== --- lib/3rdparty/softx86/softx86/aaa.c (révision 0) +++ lib/3rdparty/softx86/softx86/aaa.c (copie de travail) @@ -0,0 +1,284 @@ +/* + * aaa.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for AAA/AAD/AAM/AAS/DAA instructions. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "aaa.h" + +int Sfx86OpcodeExec_aaaseries(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0x27) { // DAA + sx86_ubyte al,nal; + + al = ctx->state->general_reg[SX86_REG_AX].b.lo; + if (((al&0x0F) > 9) || (ctx->state->reg_flags.val & SX86_CPUFLAG_AUX)) { + nal = (al&0xF)+6; + al += 6; +/* if addition to lower nibble overflowed... */ + if (nal >= 0x10) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + } + else { + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + } + + if (((al & 0xF0) > 0x90) || (ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY)) { + al += 0x60; + ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + } + else { + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + } + +/* "The OF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + +/* SF emulation */ + if (al & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* ZF emulation */ + if (!al) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* PF emulation */ + if (softx86_parity8(al)) ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + ctx->state->general_reg[SX86_REG_AX].b.lo = al; + return 1; + } + + if (opcode == 0x2F) { // DAS + sx86_ubyte al; + int nal; + + al = ctx->state->general_reg[SX86_REG_AX].b.lo; + if (((al&0x0F) > 9) || (ctx->state->reg_flags.val & SX86_CPUFLAG_AUX)) { + nal = (al&0xF)-6; + al -= 6; +/* if subtraction from lower nibble overflowed... */ + if (nal < 0) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + } + else { + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + } + + if ((al > 0x9F) || (ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY)) { + al -= 0x60; + ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + } + else { + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + } + +/* "The OF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + +/* SF emulation */ + if (al & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* ZF emulation */ + if (!al) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* PF emulation */ + if (softx86_parity8(al)) ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + ctx->state->general_reg[SX86_REG_AX].b.lo = al; + return 1; + } + + if (opcode == 0x37) { // AAA + sx86_ubyte ah,al; + + al = ctx->state->general_reg[SX86_REG_AX].b.lo; + ah = ctx->state->general_reg[SX86_REG_AX].b.hi; + + if (((al&0xF) > 9) || (ctx->state->reg_flags.val & SX86_CPUFLAG_AUX)) { + al += 6; ah++; + ctx->state->reg_flags.val |= (SX86_CPUFLAG_AUX | SX86_CPUFLAG_CARRY); + } + else { + ctx->state->reg_flags.val &= ~(SX86_CPUFLAG_AUX | SX86_CPUFLAG_CARRY); + } + + ctx->state->general_reg[SX86_REG_AX].b.hi = ah; + ctx->state->general_reg[SX86_REG_AX].b.lo = al & 0xF; + +/* "OF, SF, ZF, and PF flags are undefined" */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + + return 1; + } + + if (opcode == 0x3F) { // AAS + sx86_ubyte ah,al; + + al = ctx->state->general_reg[SX86_REG_AX].b.lo; + ah = ctx->state->general_reg[SX86_REG_AX].b.hi; + + if (((al&0xF) > 9) || (ctx->state->reg_flags.val & SX86_CPUFLAG_AUX)) { + al -= 6; ah--; + ctx->state->reg_flags.val |= (SX86_CPUFLAG_AUX | SX86_CPUFLAG_CARRY); + } + else { + ctx->state->reg_flags.val &= ~(SX86_CPUFLAG_AUX | SX86_CPUFLAG_CARRY); + } + + ctx->state->general_reg[SX86_REG_AX].b.hi = ah; + ctx->state->general_reg[SX86_REG_AX].b.lo = al & 0xF; + +/* "OF, SF, ZF, and PF flags are undefined" */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + + return 1; + } + + if (opcode == 0xD4) { // AAM + sx86_ubyte ah,al,x; + + x = softx86_fetch_exec_byte(ctx); + al = ctx->state->general_reg[SX86_REG_AX].b.lo; + + if (x == 0) { + /* TODO: signal division by zero exception */ + } + else { + al = al % x; + ah = al / x; + } + + ctx->state->general_reg[SX86_REG_AX].b.hi = ah; + ctx->state->general_reg[SX86_REG_AX].b.lo = al; + +/* SF emulation */ + if (al & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* ZF emulation */ + if (!al) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* PF emulation */ + if (softx86_parity8(al)) ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + +/* "The OF, AF and CF flags are undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + + return 1; + } + + if (opcode == 0xD5) { // AAD + sx86_ubyte ah,al,x; + + x = softx86_fetch_exec_byte(ctx); + al = ctx->state->general_reg[SX86_REG_AX].b.lo; + ah = ctx->state->general_reg[SX86_REG_AX].b.hi; + + al = (al + (ah * x)) & 0xFF; + ah = 0; + + ctx->state->general_reg[SX86_REG_AX].b.hi = ah; + ctx->state->general_reg[SX86_REG_AX].b.lo = al; + +/* SF emulation */ + if (al & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* ZF emulation */ + if (!al) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* PF emulation */ + if (softx86_parity8(al)) ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + +/* "The OF, AF and CF flags are undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_aaaseries(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + sx86_ubyte x; + + if (opcode == 0x27) { // DAA + strcpy(buf,"DAA"); + return 1; + } + + if (opcode == 0x2F) { // DAS + strcpy(buf,"DAS"); + return 1; + } + + if (opcode == 0x37) { // AAA + strcpy(buf,"AAA"); + return 1; + } + + if (opcode == 0x3F) { // AAS + strcpy(buf,"AAS"); + return 1; + } + + if (opcode == 0xD4) { // AAM + x = softx86_fetch_dec_byte(ctx); + if (x == 10) strcpy(buf,"AAM"); + else sprintf(buf,"AAM %d",x); + + return 1; + } + + if (opcode == 0xD5) { // AAD + x = softx86_fetch_dec_byte(ctx); + if (x == 10) strcpy(buf,"AAD"); + else sprintf(buf,"AAD %d",x); + + return 1; + } + + return 0; +} Index: lib/3rdparty/softx86/softx86/aaa.c =================================================================== --- lib/3rdparty/softx86/softx86/aaa.c (révision 59666) +++ lib/3rdparty/softx86/softx86/aaa.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/aaa.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/aaa.h =================================================================== --- lib/3rdparty/softx86/softx86/aaa.h (révision 0) +++ lib/3rdparty/softx86/softx86/aaa.h (copie de travail) @@ -0,0 +1,3 @@ + +int Sfx86OpcodeExec_aaaseries(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_aaaseries(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); Index: lib/3rdparty/softx86/softx86/aaa.h =================================================================== --- lib/3rdparty/softx86/softx86/aaa.h (révision 59666) +++ lib/3rdparty/softx86/softx86/aaa.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/aaa.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/add.c =================================================================== --- lib/3rdparty/softx86/softx86/add.c (révision 0) +++ lib/3rdparty/softx86/softx86/add.c (copie de travail) @@ -0,0 +1,1017 @@ +/* + * add.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for ADD/SUB/ADC/SBB/CMP instructions. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "add.h" + +sx86_ubyte op_add8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret; + +/* peform the addition */ + ret = src + val; + +/* if carry/overflow */ + if (ret < src) + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + else + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a + b = c, ((b AND 0Fh) + (a AND 0Fh) >= 0x10). + in other words, if the lowest nibbles added together overflow. */ + if (((val&0xF)+(src&0xF)) >= 0x10) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_add16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret; + +/* peform the addition */ + ret = src + val; + +/* if carry/overflow */ + if (ret < src) + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + else + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x8000) + ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a + b = c, ((b AND 0Fh) + (a AND 0Fh) >= 0x10). + in other words, if the lowest nibbles added together overflow. */ + if (((val&0xF)+(src&0xF)) >= 0x10) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_add32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret; + +/* peform the addition */ + ret = src + val; + +/* if carry/overflow */ + if (ret < src) + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + else + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) + ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a + b = c, ((b AND 0Fh) + (a AND 0Fh) >= 0x10). + in other words, if the lowest nibbles added together overflow. */ + if (((val&0xF)+(src&0xF)) >= 0x10) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_ubyte op_adc8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret,carry; + + carry = ((sx86_ubyte)(ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY))?1:0; + +/* special case: x + 0xFF + (carry=1) == x */ + if (carry && val == 0xFF) { +/* peform the addition */ + ret = val; + +/* it's a carry over */ + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + } + else { +/* peform the addition */ + ret = src + val + carry; + +/* if carry/overflow */ + if (ret < src) + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + else + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + } + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a + b = c, ((b AND 0Fh) + (a AND 0Fh) >= 0x10). + in other words, if the lowest nibbles added together overflow. */ + if (((val&0xF)+(src&0xF)) >= 0x10) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_adc16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret,carry; + + carry = ((sx86_ubyte)(ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY))?1:0; + +/* special case: x + 0xFFFF + (carry=1) == x */ + if (carry && val == 0xFFFF) { +/* peform the addition */ + ret = val; + +/* it's a carry over */ + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + } + else { +/* peform the addition */ + ret = src + val + carry; + +/* if carry/overflow */ + if (ret < src) + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + else + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + } + +/* if result treated as signed value is negative */ + if (ret & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a + b = c, ((b AND 0Fh) + (a AND 0Fh) >= 0x10). + in other words, if the lowest nibbles added together overflow. */ + if (((val&0xF)+(src&0xF)) >= 0x10) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_adc32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret,carry; + + carry = ((sx86_ubyte)(ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY))?1:0; + +/* special case: x + 0xFFFFFFFF + (carry=1) == x */ + if (carry && val == 0xFFFFFFFF) { +/* peform the addition */ + ret = val; + +/* it's a carry over */ + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + } + else { +/* peform the addition */ + ret = src + val + carry; + +/* if carry/overflow */ + if (ret < src) + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + else + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + } + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a + b = c, ((b AND 0Fh) + (a AND 0Fh) >= 0x10). + in other words, if the lowest nibbles added together overflow. */ + if (((val&0xF)+(src&0xF)) >= 0x10) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_ubyte op_sub8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret; + +/* peform the addition */ + ret = src - val; + +/* if carry */ + if (val > src) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + +/* if overflow */ + if (((src & 0x80) != (val & 0x80)) && ((src & 0x80) != (ret & 0x80))) + { + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + } + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a - b = c, ((a AND 0Fh) - (b AND 0Fh) < 0). + in other words, if the lowest nibbles subtracted cause a carry. */ + if ((val&0xF) > (src&0xF)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_sub16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret; + +/* peform the addition */ + ret = src - val; + +/* if carry */ + if (val > src) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + +/* if overflow */ + if (((src & 0x8000) != (val & 0x8000)) && ((src & 0x8000) != (ret & 0x8000))) + { + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + } + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + +/* if result treated as signed value is negative */ + if (ret & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a - b = c, ((a AND 0Fh) - (b AND 0Fh) < 0). + in other words, if the lowest nibbles subtracted cause a carry. */ + if ((val&0xF) > (src&0xF)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_sub32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret; + +/* peform the addition */ + ret = src - val; + +/* if carry */ + if (val > src) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + +/* if overflow */ + if (((src & 0x80000000) != (val & 0x80000000)) + && ((src & 0x80000000) != (ret & 0x80000000))) + { + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + } + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a - b = c, ((a AND 0Fh) - (b AND 0Fh) < 0). + in other words, if the lowest nibbles subtracted cause a carry. */ + if ((val&0xF) > (src&0xF)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_ubyte op_sbb8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret,carry; + + carry = ((sx86_ubyte)(ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY))?1:0; + +/* special case: x - 0xFF - (carry=1) == x */ + if (carry && val == 0xFF) { +/* peform the addition */ + ret = val; + +/* it's a carry over */ + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + } + else { +/* peform the addition */ + ret = src - (val + carry); + +/* if carry/overflow */ + if (ret > src) + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + else + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + } + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a - b = c, ((a AND 0Fh) - (b AND 0Fh) < 0). + in other words, if the lowest nibbles subtracted cause a carry. */ + if ((val&0xF) > (src&0xF)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_sbb16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret,carry; + + carry = ((sx86_ubyte)(ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY))?1:0; + +/* special case: x + 0xFFFF + (carry=1) == x */ + if (carry && val == 0xFFFF) { +/* peform the addition */ + ret = val; + +/* it's a carry over */ + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + } + else { +/* peform the addition */ + ret = src - (val + carry); + +/* if carry/overflow */ + if (ret > src) + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + else + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + } + +/* if result treated as signed value is negative */ + if (ret & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a - b = c, ((a AND 0Fh) - (b AND 0Fh) < 0). + in other words, if the lowest nibbles subtracted cause a carry. */ + if ((val&0xF) > (src&0xF)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_sbb32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret,carry; + + carry = ((sx86_ubyte)(ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY))?1:0; + +/* special case: x + 0xFFFFFFFF + (carry=1) == x */ + if (carry && val == 0xFFFFFFFF) { +/* peform the addition */ + ret = val; + +/* it's a carry over */ + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + } + else { +/* peform the addition */ + ret = src - (val + carry); + +/* if carry/overflow */ + if (ret > src) + ctx->state->reg_flags.val |= + (SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + else + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + } + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a - b = c, ((a AND 0Fh) - (b AND 0Fh) < 0). + in other words, if the lowest nibbles subtracted cause a carry. */ + if ((val&0xF) > (src&0xF)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +int Sfx86OpcodeExec_add(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFC) == 0x00) { // ADD reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // add from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_rw(ctx,w16,0,mod,reg, + rm,opswap,op_add8,op_add16,op_add32); + + return 1; + } + if (opcode == 0x04) { // ADD AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_exec_byte(ctx); + x = op_add8(ctx,ctx->state->general_reg[SX86_REG_AX].b.lo,x); + ctx->state->general_reg[SX86_REG_AX].b.lo = x; + return 1; + } + if (opcode == 0x05) { // ADD AX,imm16 + sx86_uword x; + + x = softx86_fetch_exec_byte(ctx); + x |= softx86_fetch_exec_byte(ctx) << 8; + x = op_add16(ctx,ctx->state->general_reg[SX86_REG_AX].w.lo,x); + ctx->state->general_reg[SX86_REG_AX].w.lo = x; + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_add(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFC) == 0x00) { // ADD reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // add from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,w16,0,mod,reg,rm,op1_tmp,op2_tmp); + + if (opswap) sprintf(buf,"ADD %s,%s",op2_tmp,op1_tmp); + else sprintf(buf,"ADD %s,%s",op1_tmp,op2_tmp); + return 1; + } + if (opcode == 0x04) { // ADD AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_dec_byte(ctx); + sprintf(buf,"ADD AL,%02Xh",x); + return 1; + } + if (opcode == 0x05) { // ADD AX,imm16 + sx86_uword x; + + x = softx86_fetch_dec_byte(ctx); + x |= softx86_fetch_dec_byte(ctx) << 8; + sprintf(buf,"ADD AX,%04Xh",x); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_adc(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFC) == 0x10) { // ADC reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // add from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_rw(ctx,w16,0,mod,reg, + rm,opswap,op_adc8,op_adc16,op_adc32); + + return 1; + } + if (opcode == 0x14) { // ADC AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_exec_byte(ctx); + x = op_adc8(ctx,ctx->state->general_reg[SX86_REG_AX].b.lo,x); + ctx->state->general_reg[SX86_REG_AX].b.lo = x; + return 1; + } + if (opcode == 0x15) { // ADC AX,imm16 + sx86_uword x; + + x = softx86_fetch_exec_byte(ctx); + x |= softx86_fetch_exec_byte(ctx) << 8; + x = op_adc16(ctx,ctx->state->general_reg[SX86_REG_AX].w.lo,x); + ctx->state->general_reg[SX86_REG_AX].w.lo = x; + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_adc(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFC) == 0x10) { // ADC reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // add from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,w16,0,mod,reg,rm,op1_tmp,op2_tmp); + + if (opswap) sprintf(buf,"ADC %s,%s",op2_tmp,op1_tmp); + else sprintf(buf,"ADC %s,%s",op1_tmp,op2_tmp); + return 1; + } + if (opcode == 0x14) { // ADC AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_dec_byte(ctx); + sprintf(buf,"ADC AL,%02Xh",x); + return 1; + } + if (opcode == 0x15) { // ADC AX,imm16 + sx86_uword x; + + x = softx86_fetch_dec_byte(ctx); + x |= softx86_fetch_dec_byte(ctx) << 8; + sprintf(buf,"ADC AX,%04Xh",x); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_sub(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFC) == 0x28) { // SUB reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // add from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_rw(ctx,w16,0,mod,reg, + rm,opswap,op_sub8,op_sub16,op_sub32); + + return 1; + } + if (opcode == 0x2C) { // SUB AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_exec_byte(ctx); + x = op_sub8(ctx,ctx->state->general_reg[SX86_REG_AX].b.lo,x); + ctx->state->general_reg[SX86_REG_AX].b.lo = x; + return 1; + } + if (opcode == 0x2D) { // SUB AX,imm16 + sx86_uword x; + + x = softx86_fetch_exec_byte(ctx); + x |= softx86_fetch_exec_byte(ctx) << 8; + x = op_sub16(ctx,ctx->state->general_reg[SX86_REG_AX].w.lo,x); + ctx->state->general_reg[SX86_REG_AX].w.lo = x; + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_sub(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFC) == 0x28) { // SUB reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // add from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,w16,0,mod,reg,rm,op1_tmp,op2_tmp); + + if (opswap) sprintf(buf,"SUB %s,%s",op2_tmp,op1_tmp); + else sprintf(buf,"SUB %s,%s",op1_tmp,op2_tmp); + return 1; + } + if (opcode == 0x2C) { // SUB AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_dec_byte(ctx); + sprintf(buf,"SUB AL,%02Xh",x); + return 1; + } + if (opcode == 0x2D) { // SUB AX,imm16 + sx86_uword x; + + x = softx86_fetch_dec_byte(ctx); + x |= softx86_fetch_dec_byte(ctx) << 8; + sprintf(buf,"SUB AX,%04Xh",x); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_sbb(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFC) == 0x18) { // SBB reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // add from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_rw(ctx,w16,0,mod,reg, + rm,opswap,op_sbb8,op_sbb16,op_sbb32); + + return 1; + } + if (opcode == 0x1C) { // SBB AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_exec_byte(ctx); + x = op_sbb8(ctx,ctx->state->general_reg[SX86_REG_AX].b.lo,x); + ctx->state->general_reg[SX86_REG_AX].b.lo = x; + return 1; + } + if (opcode == 0x1D) { // SBB AX,imm16 + sx86_uword x; + + x = softx86_fetch_exec_byte(ctx); + x |= softx86_fetch_exec_byte(ctx) << 8; + x = op_sbb16(ctx,ctx->state->general_reg[SX86_REG_AX].w.lo,x); + ctx->state->general_reg[SX86_REG_AX].w.lo = x; + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_sbb(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFC) == 0x18) { // SBB reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // add from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,w16,0,mod,reg,rm,op1_tmp,op2_tmp); + + if (opswap) sprintf(buf,"SBB %s,%s",op2_tmp,op1_tmp); + else sprintf(buf,"SBB %s,%s",op1_tmp,op2_tmp); + return 1; + } + if (opcode == 0x1C) { // SBB AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_dec_byte(ctx); + sprintf(buf,"SBB AL,%02Xh",x); + return 1; + } + if (opcode == 0x1D) { // SBB AX,imm16 + sx86_uword x; + + x = softx86_fetch_dec_byte(ctx); + x |= softx86_fetch_dec_byte(ctx) << 8; + sprintf(buf,"SBB AX,%04Xh",x); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_cmp(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFC) == 0x38) { // CMP reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // add from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_ro(ctx,w16,0,mod,reg, // we use the variant + rm,opswap,op_sub8,op_sub16,op_sub32); // that DOES NOT modify + // the destination + // register, since CMP + // is documented to + // perform subtraction + // in a temporary register + + return 1; + } + if (opcode == 0x3C) { // CMP AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_exec_byte(ctx); + op_sub8(ctx,ctx->state->general_reg[SX86_REG_AX].b.lo,x); + return 1; + } + if (opcode == 0x3D) { // CMP AX,imm16 + sx86_uword x; + + x = softx86_fetch_exec_byte(ctx); + x |= softx86_fetch_exec_byte(ctx) << 8; + op_sub16(ctx,ctx->state->general_reg[SX86_REG_AX].w.lo,x); + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_cmp(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFC) == 0x38) { // CMP reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // add from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,w16,0,mod,reg,rm,op1_tmp,op2_tmp); + + if (opswap) sprintf(buf,"CMP %s,%s",op2_tmp,op1_tmp); + else sprintf(buf,"CMP %s,%s",op1_tmp,op2_tmp); + return 1; + } + if (opcode == 0x3C) { // CMP AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_dec_byte(ctx); + sprintf(buf,"CMP AL,%02Xh",x); + return 1; + } + if (opcode == 0x3D) { // CMP AX,imm16 + sx86_uword x; + + x = softx86_fetch_dec_byte(ctx); + x |= softx86_fetch_dec_byte(ctx) << 8; + sprintf(buf,"CMP AX,%04Xh",x); + return 1; + } + + return 0; +} Index: lib/3rdparty/softx86/softx86/add.c =================================================================== --- lib/3rdparty/softx86/softx86/add.c (révision 59666) +++ lib/3rdparty/softx86/softx86/add.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/add.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/add.h =================================================================== --- lib/3rdparty/softx86/softx86/add.h (révision 0) +++ lib/3rdparty/softx86/softx86/add.h (copie de travail) @@ -0,0 +1,24 @@ + +int Sfx86OpcodeExec_adc(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_adc(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_add(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_add(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_sbb(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_sbb(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_sub(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_sub(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_cmp(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_cmp(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); + +sx86_ubyte op_adc8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_adc16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_adc32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); +sx86_ubyte op_add8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_add16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_add32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); +sx86_ubyte op_sbb8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_sbb16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_sbb32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); +sx86_ubyte op_sub8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_sub16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_sub32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); Index: lib/3rdparty/softx86/softx86/add.h =================================================================== --- lib/3rdparty/softx86/softx86/add.h (révision 59666) +++ lib/3rdparty/softx86/softx86/add.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/add.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/binops.c =================================================================== --- lib/3rdparty/softx86/softx86/binops.c (révision 0) +++ lib/3rdparty/softx86/softx86/binops.c (copie de travail) @@ -0,0 +1,2868 @@ +/* + * binops.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for XOR/OR/TEST instruction. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "binops.h" + +/************************************************** + ************** SAR 8/16/32 emulation ************* + **************************************************/ +sx86_ubyte op_sar8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret,osrc,sa; + int shic,oshic; + + if (ctx->bugs->mask_5bit_shiftcount) + oshic = val&0x1F; + else + oshic = val; + +/* Intel explicity documents that CF carries the bit that was + shifted out, and that all flags are untouched if CF=0. */ + if (!oshic) /* works for me... */ + return src; + +/* peform the operation. */ + shic = oshic; + osrc = src; + ret = src; + sa = (src&0x80)?(0xFF<<(8-shic)):0; + +/* WARNING: This code assumes shic != 0 */ + if (shic > 1) + ret >>= (shic-1); + +/* "The CF flag contains the value of the last bit shifted out..." */ + if (ret & 1) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + ret >>= 1; + ret |= sa; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST)" */ + if (osrc>>7) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_ubyte op_sar1_8(softx86_ctx* ctx,sx86_ubyte src) +{ + return op_sar8(ctx,src,1); +} + +sx86_ubyte op_sar_cl_8(softx86_ctx* ctx,sx86_ubyte src) +{ + return op_sar8(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +sx86_uword op_sar16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret,osrc; + int shic,oshic; + + if (ctx->bugs->mask_5bit_shiftcount) + oshic = val&0x1F; + else + oshic = val; + +/* Intel explicity documents that CF carries the bit that was + shifted out, and that all flags are untouched if CF=0. */ + if (!oshic) /* works for me... */ + return src; + +/* peform the operation. */ + shic = oshic; + osrc = src; + ret = src; + +/* WARNING: This code assumes shic != 0 */ + if (shic > 1) + ret >>= (shic-1); + +/* "The CF flag contains the value of the last bit shifted out..." */ + if (ret & 1) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + ret >>= 1; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST)" */ + if (osrc>>15) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_sar1_16(softx86_ctx* ctx,sx86_uword src) +{ + return op_sar16(ctx,src,1); +} + +sx86_uword op_sar_cl_16(softx86_ctx* ctx,sx86_uword src) +{ + return op_sar16(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +sx86_udword op_sar32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret,osrc; + int shic,oshic; + + if (ctx->bugs->mask_5bit_shiftcount) + oshic = val&0x1F; + else + oshic = val; + +/* Intel explicity documents that CF carries the bit that was + shifted out, and that all flags are untouched if CF=0. */ + if (!oshic) /* works for me... */ + return src; + +/* peform the operation. */ + shic = oshic; + osrc = src; + ret = src; + +/* WARNING: This code assumes shic != 0 */ + if (shic > 1) + ret >>= (shic-1); + +/* "The CF flag contains the value of the last bit shifted out..." */ + if (ret & 1) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + ret >>= 1; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST)" */ + if (osrc>>31) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity32(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_sar1_32(softx86_ctx* ctx,sx86_udword src) +{ + return op_sar32(ctx,src,1); +} + +sx86_udword op_sar_cl_32(softx86_ctx* ctx,sx86_udword src) +{ + return op_sar32(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +/************************************************** + ************** SHR 8/16/32 emulation ************* + **************************************************/ +sx86_ubyte op_shr8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret,osrc; + int shic,oshic; + + if (ctx->bugs->mask_5bit_shiftcount) + oshic = val&0x1F; + else + oshic = val; + +/* Intel explicity documents that CF carries the bit that was + shifted out, and that all flags are untouched if CF=0. */ + if (!oshic) /* works for me... */ + return src; + +/* peform the operation. */ + shic = oshic; + osrc = src; + ret = src; + +/* WARNING: This code assumes shic != 0 */ + if (shic > 1) + ret >>= (shic-1); + +/* "The CF flag contains the value of the last bit shifted out..." */ + if (ret & 1) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + ret >>= 1; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST)" */ + if (osrc>>7) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_ubyte op_shr1_8(softx86_ctx* ctx,sx86_ubyte src) +{ + return op_shr8(ctx,src,1); +} + +sx86_ubyte op_shr_cl_8(softx86_ctx* ctx,sx86_ubyte src) +{ + return op_shr8(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +sx86_uword op_shr16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret,osrc; + int shic,oshic; + + if (ctx->bugs->mask_5bit_shiftcount) + oshic = val&0x1F; + else + oshic = val; + +/* Intel explicity documents that CF carries the bit that was + shifted out, and that all flags are untouched if CF=0. */ + if (!oshic) /* works for me... */ + return src; + +/* peform the operation. */ + shic = oshic; + osrc = src; + ret = src; + +/* WARNING: This code assumes shic != 0 */ + if (shic > 1) + ret >>= (shic-1); + +/* "The CF flag contains the value of the last bit shifted out..." */ + if (ret & 1) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + ret >>= 1; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST)" */ + if (osrc>>15) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_shr1_16(softx86_ctx* ctx,sx86_uword src) +{ + return op_shr16(ctx,src,1); +} + +sx86_uword op_shr_cl_16(softx86_ctx* ctx,sx86_uword src) +{ + return op_shr16(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +sx86_udword op_shr32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret,osrc; + int shic,oshic; + + if (ctx->bugs->mask_5bit_shiftcount) + oshic = val&0x1F; + else + oshic = val; + +/* Intel explicity documents that CF carries the bit that was + shifted out, and that all flags are untouched if CF=0. */ + if (!oshic) /* works for me... */ + return src; + +/* peform the operation. */ + shic = oshic; + osrc = src; + ret = src; + +/* WARNING: This code assumes shic != 0 */ + if (shic > 1) + ret >>= (shic-1); + +/* "The CF flag contains the value of the last bit shifted out..." */ + if (ret & 1) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + ret >>= 1; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST)" */ + if (osrc>>31) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity32(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_shr1_32(softx86_ctx* ctx,sx86_udword src) +{ + return op_shr32(ctx,src,1); +} + +sx86_udword op_shr_cl_32(softx86_ctx* ctx,sx86_udword src) +{ + return op_shr32(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +/************************************************** + ************** SHL 8/16/32 emulation ************* + **************************************************/ +sx86_ubyte op_shl8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret; + int shic,oshic; + + if (ctx->bugs->mask_5bit_shiftcount) + oshic = val&0x1F; + else + oshic = val; + +/* Intel explicity documents that CF carries the bit that was + shifted out, and that all flags are untouched if CF=0. */ + if (!oshic) /* works for me... */ + return src; + +/* peform the operation. */ + shic = oshic; + ret = src; + +/* WARNING: This code assumes shic != 0 */ + if (shic > 1) + ret <<= (shic-1); + +/* "The CF flag contains the value of the last bit shifted out..." */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + ret <<= 1; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR CF" */ + if ((ret>>7)^((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_ubyte op_shl1_8(softx86_ctx* ctx,sx86_ubyte src) +{ + return op_shl8(ctx,src,1); +} + +sx86_ubyte op_shl_cl_8(softx86_ctx* ctx,sx86_ubyte src) +{ + return op_shl8(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +sx86_uword op_shl16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret; + int shic,oshic; + + if (ctx->bugs->mask_5bit_shiftcount) + oshic = val&0x1F; + else + oshic = val; + +/* Intel explicity documents that CF carries the bit that was + shifted out, and that all flags are untouched if CF=0. */ + if (!oshic) /* works for me... */ + return src; + +/* peform the operation. */ + shic = oshic; + ret = src; + +/* WARNING: This code assumes shic != 0 */ + if (shic > 1) + ret <<= (shic-1); + +/* "The CF flag contains the value of the last bit shifted out..." */ + if (ret & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + ret <<= 1; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR CF" */ + if ((ret>>15)^((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_shl1_16(softx86_ctx* ctx,sx86_uword src) +{ + return op_shl16(ctx,src,1); +} + +sx86_uword op_shl_cl_16(softx86_ctx* ctx,sx86_uword src) +{ + return op_shl16(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +sx86_udword op_shl32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret; + int shic,oshic; + + if (ctx->bugs->mask_5bit_shiftcount) + oshic = val&0x1F; + else + oshic = val; + +/* Intel explicity documents that CF carries the bit that was + shifted out, and that all flags are untouched if CF=0. */ + if (!oshic) /* works for me... */ + return src; + +/* peform the operation. */ + shic = oshic; + ret = src; + +/* WARNING: This code assumes shic != 0 */ + if (shic > 1) + ret <<= (shic-1); + +/* "The CF flag contains the value of the last bit shifted out..." */ + if (ret & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + ret <<= 1; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR CF" */ + if ((ret>>31)^((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity32(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_shl1_32(softx86_ctx* ctx,sx86_udword src) +{ + return op_shl32(ctx,src,1); +} + +sx86_udword op_shl_cl_32(softx86_ctx* ctx,sx86_udword src) +{ + return op_shl32(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +/************************************************** + ************** ROR 8/16/32 emulation ************* + **************************************************/ +sx86_ubyte op_ror8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret; + int shic,oshic; + + oshic = val&7; + if (!oshic) /* don't bother */ + return src; + +/* peform the operation. */ + shic = oshic; + ret = (src>>shic)|(src<<(8-shic)); + +/* "CF <- MSB(DEST)" */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR MSB - 1(DEST)" */ + if ((ret>>7)^((ret>>6)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_ubyte op_ror1_8(softx86_ctx* ctx,sx86_ubyte src) +{ + return op_ror8(ctx,src,1); +} + +sx86_ubyte op_ror_cl_8(softx86_ctx* ctx,sx86_ubyte src) +{ + return op_ror8(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +sx86_uword op_ror16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret; + int shic,oshic; + + oshic = val&15; + if (!oshic) /* don't bother */ + return src; + +/* peform the operation. */ + shic = oshic; + ret = (src>>shic)|(src<<(16-shic)); + +/* "CF <- MSB(DEST)" */ + if (ret & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR MSB - 1(DEST)" */ + if ((ret>>15)^((ret>>14)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_ror1_16(softx86_ctx* ctx,sx86_uword src) +{ + return op_ror16(ctx,src,1); +} + +sx86_uword op_ror_cl_16(softx86_ctx* ctx,sx86_uword src) +{ + return op_ror16(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +sx86_udword op_ror32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret; + int shic,oshic; + + oshic = val&31; + if (!oshic) /* don't bother */ + return src; + +/* peform the operation. */ + shic = oshic; + ret = (src>>shic)|(src<<(32-shic)); + +/* "CF <- MSB(DEST)" */ + if (ret & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR MSB - 1(DEST)" */ + if ((ret>>31)^((ret>>30)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity32(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_ror1_32(softx86_ctx* ctx,sx86_udword src) +{ + return op_ror32(ctx,src,1); +} + +sx86_udword op_ror_cl_32(softx86_ctx* ctx,sx86_udword src) +{ + return op_ror32(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +/************************************************** + ************** ROL 8/16/32 emulation ************* + **************************************************/ +sx86_ubyte op_rol8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret; + int shic,oshic; + + oshic = val&7; + if (!oshic) /* don't bother */ + return src; + +/* peform the operation. */ + shic = oshic; + ret = (src<>(8-shic)); + +/* "CF <- LSB(DEST)" */ + if (ret & 1) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR CF" */ + if ((ret>>7)^((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_ubyte op_rol1_8(softx86_ctx* ctx,sx86_ubyte src) +{ + return op_rol8(ctx,src,1); +} + +sx86_ubyte op_rol_cl_8(softx86_ctx* ctx,sx86_ubyte src) +{ + return op_rol8(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +sx86_uword op_rol16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret; + int shic,oshic; + + oshic = val&15; + if (!oshic) /* don't bother */ + return src; + +/* peform the operation. */ + shic = oshic; + ret = (src<>(16-shic)); + +/* "CF <- LSB(DEST)" */ + if (ret & 1) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR CF" */ + if ((ret>>15)^((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_rol1_16(softx86_ctx* ctx,sx86_uword src) +{ + return op_rol16(ctx,src,1); +} + +sx86_uword op_rol_cl_16(softx86_ctx* ctx,sx86_uword src) +{ + return op_rol16(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +sx86_udword op_rol32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret; + int shic,oshic; + + oshic = val&31; + if (!oshic) /* don't bother */ + return src; + +/* peform the operation. */ + shic = oshic; + ret = (src<>(32-shic)); + +/* "CF <- LSB(DEST)" */ + if (ret & 1) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR CF" */ + if ((ret>>31)^((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_rol1_32(softx86_ctx* ctx,sx86_udword src) +{ + return op_rol32(ctx,src,1); +} + +sx86_udword op_rol_cl_32(softx86_ctx* ctx,sx86_udword src) +{ + return op_rol32(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +/************************************************** + ************** RCL 8/16/32 emulation ************* + **************************************************/ +sx86_ubyte op_rcl8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret,cf; + int shic,oshic; + + oshic = val%9; /* 8 bits + CF */ + if (!oshic) /* don't bother */ + return src; + +/* peform the operation. */ + ret = src; + shic = oshic; + while (shic-- > 0) { + cf = ret>>7; + ret = (ret<<1)|((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1); + if (cf) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + } + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR CF" */ + if ((ret>>7)^((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_ubyte op_rcl1_8(softx86_ctx* ctx,sx86_ubyte src) +{ + return op_rcl8(ctx,src,1); +} + +sx86_ubyte op_rcl_cl_8(softx86_ctx* ctx,sx86_ubyte src) +{ + return op_rcl8(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +sx86_uword op_rcl16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret,cf; + int shic,oshic; + + oshic = val%17; /* 16 bits + CF */ + if (!oshic) /* don't bother */ + return src; + +/* peform the operation. */ + ret = src; + shic = oshic; + while (shic-- > 0) { + cf = ret>>15; + ret = (ret<<1)|((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1); + if (cf) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + } + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR CF" */ + if ((ret>>15)^((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_rcl1_16(softx86_ctx* ctx,sx86_uword src) +{ + return op_rcl16(ctx,src,1); +} + +sx86_uword op_rcl_cl_16(softx86_ctx* ctx,sx86_uword src) +{ + return op_rcl16(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +sx86_udword op_rcl32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret,cf; + int shic,oshic; + + oshic = val%33; /* 32 bits + CF */ + if (!oshic) /* don't bother */ + return src; + +/* peform the operation. */ + ret = src; + shic = oshic; + while (shic-- > 0) { + cf = ret>>31; + ret = (ret<<1)|((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1); + if (cf) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + } + +/* the OF flag follows some sort of bizarre logic */ + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR CF" */ + if ((ret>>31)^((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity32(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_rcl1_32(softx86_ctx* ctx,sx86_udword src) +{ + return op_rcl32(ctx,src,1); +} + +sx86_udword op_rcl_cl_32(softx86_ctx* ctx,sx86_udword src) +{ + return op_rcl32(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +/************************************************** + ************** RCR 8/16/32 emulation ************* + **************************************************/ +sx86_ubyte op_rcr8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret,cf; + int shic,oshic; + + oshic = val%9; /* 8 bits + CF */ + if (!oshic) /* don't bother */ + return src; + +/* the OF flag follows some sort of bizarre logic... and... + why is this done BEFORE the operation (according to + the pseudocode)? */ + ret = src; + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR CF" */ + if ((ret>>7)^((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* peform the operation. */ + shic = oshic; + while (shic-- > 0) { + cf = ret&1; + ret = (ret>>1)|(((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)<<7); + if (cf) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + } + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_ubyte op_rcr1_8(softx86_ctx* ctx,sx86_ubyte src) +{ + return op_rcr8(ctx,src,1); +} + +sx86_ubyte op_rcr_cl_8(softx86_ctx* ctx,sx86_ubyte src) +{ + return op_rcr8(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +sx86_uword op_rcr16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret,cf; + int shic,oshic; + + oshic = val%17; /* 16 bits + CF */ + if (!oshic) /* don't bother */ + return src; + +/* the OF flag follows some sort of bizarre logic... and... + why is this done BEFORE the operation (according to + the pseudocode)? */ + ret = src; + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR CF" */ + if ((ret>>15)^((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* peform the operation. */ + shic = oshic; + while (shic-- > 0) { + cf = ret&1; + ret = (ret>>1)|(((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)<<15); + if (cf) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + } + +/* if result treated as signed value is negative */ + if (ret & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_rcr1_16(softx86_ctx* ctx,sx86_uword src) +{ + return op_rcr16(ctx,src,1); +} + +sx86_uword op_rcr_cl_16(softx86_ctx* ctx,sx86_uword src) +{ + return op_rcr16(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +sx86_udword op_rcr32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret,cf; + int shic,oshic; + + oshic = val%33; /* 32 bits + CF */ + if (!oshic) /* don't bother */ + return src; + +/* the OF flag follows some sort of bizarre logic... and... + why is this done BEFORE the operation (according to + the pseudocode)? */ + ret = src; + if (oshic == 1) { +/* "OF <- MSB(DEST) XOR CF" */ + if ((ret>>31)^((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + else { +/* apparently undefined */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + } + +/* peform the operation. */ + shic = oshic; + while (shic-- > 0) { + cf = ret&1; + ret = (ret>>1)|(((ctx->state->reg_flags.val>>SX86_CPUFLAGBO_CARRY)&1)<<31); + if (cf) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + } + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity32(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_rcr1_32(softx86_ctx* ctx,sx86_udword src) +{ + return op_rcr32(ctx,src,1); +} + +sx86_udword op_rcr_cl_32(softx86_ctx* ctx,sx86_udword src) +{ + return op_rcr32(ctx,src,ctx->state->general_reg[SX86_REG_CX].b.lo); +} + +/************************************************** + ************** XOR 8/16/32 emulation ************* + **************************************************/ +sx86_ubyte op_xor8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret; + +/* peform the operation */ + ret = src ^ val; + +/* carry/overflow always cleared */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_xor16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret; + +/* peform the operation */ + ret = src ^ val; + +/* carry/overflow always cleared */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x8000) + ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_xor32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret; + +/* peform the operation */ + ret = src ^ val; + +/* carry/overflow always cleared */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) + ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity32(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +/************************************************** + ************** OR 8/16/32 emulation ************** + **************************************************/ +sx86_ubyte op_or8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret; + +/* peform the operation */ + ret = src | val; + +/* carry/overflow always cleared */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_or16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret; + +/* peform the operation */ + ret = src | val; + +/* carry/overflow always cleared */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x8000) + ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_or32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret; + +/* peform the operation */ + ret = src | val; + +/* carry/overflow always cleared */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) + ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity32(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +/************************************************** + ************** AND 8/16/32 emulation ************* + **************************************************/ +sx86_ubyte op_and8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret; + +/* peform the operation */ + ret = src & val; + +/* carry/overflow always cleared */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_and16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret; + +/* peform the operation */ + ret = src & val; + +/* carry/overflow always cleared */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x8000) + ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_and32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret; + +/* peform the operation */ + ret = src & val; + +/* carry/overflow always cleared */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) + ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity32(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +/************************************************** + ************* TEST 8/16/32 emulation ************* + **************************************************/ +/* apparently TEST is a lot like AND except for subtle differences... */ +sx86_ubyte op_test8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + sx86_ubyte ret; + +/* peform the operation */ + ret = src & val; + +/* carry/overflow always cleared */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit. + NOTE: Intel's documentation states that only the lower 8 bits + are used in setting PF. Odd... */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_test16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + sx86_uword ret; + +/* peform the operation */ + ret = src & val; + +/* carry/overflow always cleared */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x8000) + ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit. + NOTE: Intel's documentation states that only the lower 8 bits + are used in setting PF. Odd... */ + if (softx86_parity8((sx86_ubyte)ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_test32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + sx86_udword ret; + +/* peform the operation */ + ret = src & val; + +/* carry/overflow always cleared */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_CARRY | SX86_CPUFLAG_OVERFLOW); + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) + ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* quoting Intel: "The state of the AF flag is undefined"... */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit. + NOTE: Intel's documentation states that only the lower 8 bits + are used in setting PF. Odd... */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +/************************************************** + ************* NOT 8/16/32 emulation ************* + **************************************************/ +sx86_ubyte op_not8(softx86_ctx* ctx,sx86_ubyte src) +{ +/* peform the operation, no flags are affected */ + return (~src); +} + +sx86_uword op_not16(softx86_ctx* ctx,sx86_uword src) +{ +/* peform the operation, no flags are affected */ + return (~src); +} + +sx86_udword op_not32(softx86_ctx* ctx,sx86_udword src) +{ +/* peform the operation, no flags are affected */ + return (~src); +} + +/************************************************* + ************* NEG 8/16/32 emulation ************* + *************************************************/ +sx86_ubyte op_neg8(softx86_ctx* ctx,sx86_ubyte src) +{ + sx86_ubyte ret; + +/* peform the operation */ + ret = (~src)+1; /* binary equivalent of x = 0 - x */ + +/* carry set if operand was and still is 0 (since NEG 0 = 0) */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + +/* Intel isn't clear how the OF flag is set "according to the result" */ +/* perhaps this is a minor detail that most programmers and clone + chip makers overlook anyway... but here is my interpretation of it. + based on the assumption that the chip just inverts the bits then adds + +1. ((NOT 0) + 1) = 0x100, and 0x100 squeezed into 8 bits is 0x00 + with one bit that "overflowed". */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* Intel isn't clear on how this flag is set either. */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit. */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_neg16(softx86_ctx* ctx,sx86_uword src) +{ + sx86_uword ret; + +/* peform the operation */ + ret = (~src)+1; /* binary equivalent of x = 0 - x */ + +/* carry set if operand was and still is 0 (since NEG 0 = 0) */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + +/* Intel isn't clear how the OF flag is set "according to the result" */ +/* perhaps this is a minor detail that most programmers and clone + chip makers overlook anyway... but here is my interpretation of it. + based on the assumption that the chip just inverts the bits then adds + +1. ((NOT 0) + 1) = 0x10000, and 0x10000 squeezed into 16 bits is 0x00 + with one bit that "overflowed". */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + +/* if result treated as signed value is negative */ + if (ret & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* Intel isn't clear on how this flag is set either. */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit. */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_neg32(softx86_ctx* ctx,sx86_udword src) +{ + sx86_udword ret; + +/* peform the operation */ + ret = (~src)+1; /* binary equivalent of x = 0 - x */ + +/* carry set if operand was and still is 0 (since NEG 0 = 0) */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + +/* Intel isn't clear how the OF flag is set "according to the result" */ +/* perhaps this is a minor detail that most programmers and clone + chip makers overlook anyway... but here is my interpretation of it. + based on the assumption that the chip just inverts the bits then adds + +1. ((NOT 0) + 1) = 0x100000000, and 0x100000000 squeezed into 32 bits + is 0x00 with one bit that "overflowed". */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_OVERFLOW; + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* Intel isn't clear on how this flag is set either. */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit. */ + if (softx86_parity32(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +/************************************************* + ************* MUL 8/16/32 emulation ************* + *************************************************/ +sx86_ubyte op_mul8(softx86_ctx* ctx,sx86_ubyte src) +{ + sx86_uword result; + +/* peform the operation AX = AL * r/m8 */ + result = ((sx86_uword)ctx->state->general_reg[SX86_REG_AX].b.lo); + result *= ((sx86_uword)src); + +/* the result is stored into AX */ + ctx->state->general_reg[SX86_REG_AX].w.lo = result; + +/* OF and CF are set if the upper half is nonzero */ + if (result>>8) ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW | SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~(SX86_CPUFLAG_OVERFLOW | SX86_CPUFLAG_CARRY); + +/* Intel documents SF ZF AF and PF as "undefined" after this instruction. */ +/* We'll just set them anyway by the normal rules... */ +/* if result treated as signed value is negative */ + if (result & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!result) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* Whatever */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit. */ + if (softx86_parity16(result)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return src; /* this is called by sx86_exec_full_modrmonly_ro() so it doesn't matter */ +} + +sx86_uword op_mul16(softx86_ctx* ctx,sx86_uword src) +{ + sx86_udword result; + +/* peform the operation DX:AX = AX * r/m16 */ + result = ((sx86_udword)ctx->state->general_reg[SX86_REG_AX].w.lo); + result *= ((sx86_udword)src); + +/* the result is stored into DX:AX */ + ctx->state->general_reg[SX86_REG_AX].w.lo = (sx86_uword)(result&0xFFFF); + ctx->state->general_reg[SX86_REG_DX].w.lo = (sx86_uword)(result>>16); + +/* OF and CF are set if the upper half is nonzero */ + if (result>>16) ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW | SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~(SX86_CPUFLAG_OVERFLOW | SX86_CPUFLAG_CARRY); + +/* Intel documents SF ZF AF and PF as "undefined" after this instruction. */ +/* We'll just set them anyway by the normal rules... */ +/* if result treated as signed value is negative */ + if (result & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!result) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* Whatever */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit. */ + if (softx86_parity32(result)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return src; /* this is called by sx86_exec_full_modrmonly_ro() so it doesn't matter */ +} + +sx86_udword op_mul32(softx86_ctx* ctx,sx86_udword src) +{ + sx86_uldword result; + +/* peform the operation EDX:EAX = EAX * r/m32 */ + result = ((sx86_uldword)ctx->state->general_reg[SX86_REG_AX].val); + result *= ((sx86_uldword)src); + +/* the result is stored into EDX:EAX */ + ctx->state->general_reg[SX86_REG_AX].val = (sx86_udword)(result&0xFFFFFFFF); + ctx->state->general_reg[SX86_REG_DX].val = (sx86_udword)(result>>32); + +/* OF and CF are set if the upper half is nonzero */ + if (result>>32) ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW | SX86_CPUFLAG_CARRY; + else ctx->state->reg_flags.val &= ~(SX86_CPUFLAG_OVERFLOW | SX86_CPUFLAG_CARRY); + +/* Intel documents SF ZF AF and PF as "undefined" after this instruction. */ +/* We'll just set them anyway by the normal rules... */ +/* if result treated as signed value is negative */ + if (result & 0x8000000000000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!result) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* Whatever */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit. */ + if (softx86_parity64(result)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return src; /* this is called by sx86_exec_full_modrmonly_ro() so it doesn't matter */ +} + +/************************************************** + ************* IMUL 8/16/32 emulation ************* + **************************************************/ +sx86_ubyte op_imul8(softx86_ctx* ctx,sx86_ubyte src) +{ + sx86_sword result; + +/* peform the operation AX = AL * r/m8 */ + result = (sx86_sword)((sx86_sbyte)ctx->state->general_reg[SX86_REG_AX].b.lo); + result *= (sx86_sword)((sx86_sbyte)src); + +/* the result is stored into AX */ + ctx->state->general_reg[SX86_REG_AX].w.lo = result; + +/* OF and CF are set if the upper half is nonzero */ + if ((result>>8) == 0 || ((result>>8)&0xFF) == 0xFF) + ctx->state->reg_flags.val &= ~(SX86_CPUFLAG_OVERFLOW | SX86_CPUFLAG_CARRY); + else + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW | SX86_CPUFLAG_CARRY; + +/* Intel documents SF ZF AF and PF as "undefined" after this instruction. */ +/* We'll just set them anyway by the normal rules... */ +/* if result treated as signed value is negative */ + if (result & 0x8000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!result) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* Whatever */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit. */ + if (softx86_parity16(result)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return src; /* this is called by sx86_exec_full_modrmonly_ro() so it doesn't matter */ +} + +sx86_uword op_imul16(softx86_ctx* ctx,sx86_uword src) +{ + sx86_sdword result; + +/* peform the operation AX = AL * r/m8 */ + result = (sx86_sdword)((sx86_sword)ctx->state->general_reg[SX86_REG_AX].w.lo); + result *= (sx86_sdword)((sx86_sword)src); + +/* the result is stored into AX */ + ctx->state->general_reg[SX86_REG_AX].w.lo = (sx86_uword)(result&0xFFFF); + ctx->state->general_reg[SX86_REG_DX].w.lo = (sx86_uword)(result>>16); + +/* OF and CF are set if the upper half is nonzero */ + if ((result>>16) == 0 || ((result>>16)&0xFFFF) == 0xFFFF) + ctx->state->reg_flags.val &= ~(SX86_CPUFLAG_OVERFLOW | SX86_CPUFLAG_CARRY); + else + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW | SX86_CPUFLAG_CARRY; + +/* Intel documents SF ZF AF and PF as "undefined" after this instruction. */ +/* We'll just set them anyway by the normal rules... */ +/* if result treated as signed value is negative */ + if (result & 0x80000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!result) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* Whatever */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit. */ + if (softx86_parity32(result)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return src; /* this is called by sx86_exec_full_modrmonly_ro() so it doesn't matter */ +} + +sx86_udword op_imul32(softx86_ctx* ctx,sx86_udword src) +{ + sx86_sldword result; + +/* peform the operation AX = AL * r/m8 */ + result = (sx86_sldword)((sx86_sdword)ctx->state->general_reg[SX86_REG_AX].val); + result *= (sx86_sldword)((sx86_sdword)src); + +/* the result is stored into AX */ + ctx->state->general_reg[SX86_REG_AX].val = (sx86_uword)(result&0xFFFFFFFF); + ctx->state->general_reg[SX86_REG_DX].val = (sx86_uword)(result>>32); + +/* OF and CF are set if the upper half is nonzero */ + if ((result>>32) == 0 || ((result>>32)&0xFFFFFFFF) == 0xFFFFFFFF) + ctx->state->reg_flags.val &= ~(SX86_CPUFLAG_OVERFLOW | SX86_CPUFLAG_CARRY); + else + ctx->state->reg_flags.val |= SX86_CPUFLAG_OVERFLOW | SX86_CPUFLAG_CARRY; + +/* Intel documents SF ZF AF and PF as "undefined" after this instruction. */ +/* We'll just set them anyway by the normal rules... */ +/* if result treated as signed value is negative */ + if (result & 0x8000000000000000) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!result) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* Whatever */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit. */ + if (softx86_parity64(result)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return src; /* this is called by sx86_exec_full_modrmonly_ro() so it doesn't matter */ +} + +/************************************************* + ************* DIV 8/16/32 emulation ************* + *************************************************/ +sx86_ubyte op_div8(softx86_ctx* ctx,sx86_ubyte src) +{ + sx86_uword result; + +/* signal division overflow */ + if (src == 0) { + softx86_int_sw_signal(ctx,0); + return src; + } + +/* peform the operation AL = AX / r/m8 */ + result = ((sx86_uword)ctx->state->general_reg[SX86_REG_AX].w.lo) / ((sx86_uword)src); + +/* signal division overflow */ + if (result > 0xFF) { + softx86_int_sw_signal(ctx,0); + return src; + } + +/* the result is stored into AL, remainder in AH */ + ctx->state->general_reg[SX86_REG_AX].b.hi = + ((sx86_uword)ctx->state->general_reg[SX86_REG_AX].w.lo) % ((sx86_uword)src); + ctx->state->general_reg[SX86_REG_AX].b.lo = (sx86_ubyte)result; + +/* Apparently all the flags are undefined after this instruction. */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_SIGN | SX86_CPUFLAG_ZERO | SX86_CPUFLAG_AUX | SX86_CPUFLAG_PARITY); + + return src; /* this is called by sx86_exec_full_modrmonly_ro() so it doesn't matter */ +} + +sx86_uword op_div16(softx86_ctx* ctx,sx86_uword src) +{ + sx86_udword result; + +/* signal division overflow */ + if (src == 0) { + softx86_int_sw_signal(ctx,0); + return src; + } + +/* peform the operation AX = DX:AX / r/m16 */ + result = ((sx86_udword)ctx->state->general_reg[SX86_REG_AX].w.lo); + result |= ((sx86_udword)ctx->state->general_reg[SX86_REG_DX].w.lo)<<16; + result /= ((sx86_udword)src); + +/* signal division overflow */ + if (result > 0xFFFF) { + softx86_int_sw_signal(ctx,0); + return src; + } + +/* the result is stored into AX, remainder in DX */ + ctx->state->general_reg[SX86_REG_DX].w.lo = + ((sx86_uword)ctx->state->general_reg[SX86_REG_AX].w.lo) % ((sx86_uword)src); + ctx->state->general_reg[SX86_REG_AX].w.lo = (sx86_uword)result; + +/* Apparently all the flags are undefined after this instruction. */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_SIGN | SX86_CPUFLAG_ZERO | SX86_CPUFLAG_AUX | SX86_CPUFLAG_PARITY); + + return src; /* this is called by sx86_exec_full_modrmonly_ro() so it doesn't matter */ +} + +sx86_udword op_div32(softx86_ctx* ctx,sx86_udword src) +{ + sx86_uldword result; + +/* signal division overflow */ + if (src == 0) { + softx86_int_sw_signal(ctx,0); + return src; + } + +/* peform the operation AX = EDX:EAX / r/m32 */ + result = ((sx86_uldword)ctx->state->general_reg[SX86_REG_AX].val); + result |= ((sx86_uldword)ctx->state->general_reg[SX86_REG_DX].val)<<32; + result /= ((sx86_uldword)src); + +/* signal division overflow */ + if (result > 0xFFFFFFFFL) { + softx86_int_sw_signal(ctx,0); + return src; + } + +/* the result is stored into EAX, remainder in EDX */ + ctx->state->general_reg[SX86_REG_DX].val = + ((sx86_udword)ctx->state->general_reg[SX86_REG_AX].val) % ((sx86_udword)src); + ctx->state->general_reg[SX86_REG_AX].val = (sx86_udword)result; + +/* Apparently all the flags are undefined after this instruction. */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_SIGN | SX86_CPUFLAG_ZERO | SX86_CPUFLAG_AUX | SX86_CPUFLAG_PARITY); + + return src; /* this is called by sx86_exec_full_modrmonly_ro() so it doesn't matter */ +} + +/************************************************** + ************* IDIV 8/16/32 emulation ************* + **************************************************/ +sx86_ubyte op_idiv8(softx86_ctx* ctx,sx86_ubyte src) +{ + sx86_sword result; + +/* signal division overflow */ + if (src == 0) { + softx86_int_sw_signal(ctx,0); + return src; + } + +/* peform the operation AL = AX / r/m8 */ + result = ((sx86_sword)ctx->state->general_reg[SX86_REG_AX].w.lo) / ((sx86_sbyte)src); + +/* signal division overflow */ + if (result < -0x80 || result >= 0x80) { + softx86_int_sw_signal(ctx,0); + return src; + } + +/* the result is stored into AL, remainder in AH */ + ctx->state->general_reg[SX86_REG_AX].b.hi = + ((sx86_sword)ctx->state->general_reg[SX86_REG_AX].w.lo) % ((sx86_sbyte)src); + ctx->state->general_reg[SX86_REG_AX].b.lo = (sx86_ubyte)result; + +/* Apparently all the flags are undefined after this instruction. */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_SIGN | SX86_CPUFLAG_ZERO | SX86_CPUFLAG_AUX | SX86_CPUFLAG_PARITY); + + return src; /* this is called by sx86_exec_full_modrmonly_ro() so it doesn't matter */ +} + +sx86_uword op_idiv16(softx86_ctx* ctx,sx86_uword src) +{ + sx86_sdword result; + +/* signal division overflow */ + if (src == 0) { + softx86_int_sw_signal(ctx,0); + return src; + } + +/* peform the operation AX = DX:AX / r/m16 */ + result = ((sx86_sdword)ctx->state->general_reg[SX86_REG_AX].w.lo); + result |= ((sx86_sdword)ctx->state->general_reg[SX86_REG_DX].w.lo)<<16; + result /= ((sx86_sword)src); + +/* signal division overflow */ + if (result < -0x8000 || result >= 0x8000) { + softx86_int_sw_signal(ctx,0); + return src; + } + +/* the result is stored into AX, remainder in DX */ + ctx->state->general_reg[SX86_REG_DX].w.lo = + ((sx86_sword)ctx->state->general_reg[SX86_REG_AX].w.lo) % ((sx86_sword)src); + ctx->state->general_reg[SX86_REG_AX].w.lo = (sx86_uword)result; + +/* Apparently all the flags are undefined after this instruction. */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_SIGN | SX86_CPUFLAG_ZERO | SX86_CPUFLAG_AUX | SX86_CPUFLAG_PARITY); + + return src; /* this is called by sx86_exec_full_modrmonly_ro() so it doesn't matter */ +} + +sx86_udword op_idiv32(softx86_ctx* ctx,sx86_udword src) +{ + sx86_sldword result; + +/* signal division overflow */ + if (src == 0) { + softx86_int_sw_signal(ctx,0); + return src; + } + +/* peform the operation AX = EDX:EAX / r/m32 */ + result = ((sx86_sldword)ctx->state->general_reg[SX86_REG_AX].val); + result |= ((sx86_sldword)ctx->state->general_reg[SX86_REG_DX].val)<<32; + result /= ((sx86_sldword)src); + +/* signal division overflow */ + if (result < -0x80000000 || result >= 0x80000000) { + softx86_int_sw_signal(ctx,0); + return src; + } + +/* the result is stored into EAX, remainder in EDX */ + ctx->state->general_reg[SX86_REG_DX].val = + ((sx86_sdword)ctx->state->general_reg[SX86_REG_AX].val) % ((sx86_sdword)src); + ctx->state->general_reg[SX86_REG_AX].val = (sx86_sdword)result; + +/* Apparently all the flags are undefined after this instruction. */ + ctx->state->reg_flags.val &= + ~(SX86_CPUFLAG_SIGN | SX86_CPUFLAG_ZERO | SX86_CPUFLAG_AUX | SX86_CPUFLAG_PARITY); + + return src; /* this is called by sx86_exec_full_modrmonly_ro() so it doesn't matter */ +} + +int Sfx86OpcodeExec_xor(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFC) == 0x30) { // XOR reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // XOR from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_rw(ctx,w16,0,mod,reg, + rm,opswap,op_xor8,op_xor16,op_xor32); + + return 1; + } + if (opcode == 0x34) { // XOR AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_exec_byte(ctx); + x = op_xor8(ctx,ctx->state->general_reg[SX86_REG_AX].b.lo,x); + ctx->state->general_reg[SX86_REG_AX].b.lo = x; + return 1; + } + if (opcode == 0x35) { // XOR AX,imm16 + sx86_uword x; + + x = softx86_fetch_exec_byte(ctx); + x |= softx86_fetch_exec_byte(ctx) << 8; + x = op_xor16(ctx,ctx->state->general_reg[SX86_REG_AX].w.lo,x); + ctx->state->general_reg[SX86_REG_AX].w.lo = x; + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_xor(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFC) == 0x30) { // XOR reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // XOR from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,w16,0,mod,reg,rm,op1_tmp,op2_tmp); + + if (opswap) sprintf(buf,"XOR %s,%s",op2_tmp,op1_tmp); + else sprintf(buf,"XOR %s,%s",op1_tmp,op2_tmp); + return 1; + } + if (opcode == 0x34) { // XOR AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_dec_byte(ctx); + sprintf(buf,"XOR AL,%02Xh",x); + return 1; + } + if (opcode == 0x35) { // XOR AX,imm16 + sx86_uword x; + + x = softx86_fetch_dec_byte(ctx); + x |= softx86_fetch_dec_byte(ctx) << 8; + sprintf(buf,"XOR AX,%04Xh",x); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_or(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFC) == 0x08) { // OR reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // OR from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_rw(ctx,w16,0,mod,reg, + rm,opswap,op_or8,op_or16,op_or32); + + return 1; + } + if (opcode == 0x0C) { // OR AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_exec_byte(ctx); + x = op_or8(ctx,ctx->state->general_reg[SX86_REG_AX].b.lo,x); + ctx->state->general_reg[SX86_REG_AX].b.lo = x; + return 1; + } + if (opcode == 0x0D) { // OR AX,imm16 + sx86_uword x; + + x = softx86_fetch_exec_byte(ctx); + x |= softx86_fetch_exec_byte(ctx) << 8; + x = op_or16(ctx,ctx->state->general_reg[SX86_REG_AX].w.lo,x); + ctx->state->general_reg[SX86_REG_AX].w.lo = x; + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_or(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFC) == 0x08) { // OR reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // OR from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,w16,0,mod,reg,rm,op1_tmp,op2_tmp); + + if (opswap) sprintf(buf,"OR %s,%s",op2_tmp,op1_tmp); + else sprintf(buf,"OR %s,%s",op1_tmp,op2_tmp); + return 1; + } + if (opcode == 0x0C) { // OR AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_dec_byte(ctx); + sprintf(buf,"OR AL,%02Xh",x); + return 1; + } + if (opcode == 0x0D) { // OR AX,imm16 + sx86_uword x; + + x = softx86_fetch_dec_byte(ctx); + x |= softx86_fetch_dec_byte(ctx) << 8; + sprintf(buf,"OR AX,%04Xh",x); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_and(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFC) == 0x20) { // AND reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // AND from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_rw(ctx,w16,0,mod,reg, + rm,opswap,op_and8,op_and16,op_and32); + + return 1; + } + if (opcode == 0x24) { // AND AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_exec_byte(ctx); + x = op_and8(ctx,ctx->state->general_reg[SX86_REG_AX].b.lo,x); + ctx->state->general_reg[SX86_REG_AX].b.lo = x; + return 1; + } + if (opcode == 0x25) { // AND AX,imm16 + sx86_uword x; + + x = softx86_fetch_exec_byte(ctx); + x |= softx86_fetch_exec_byte(ctx) << 8; + x = op_and16(ctx,ctx->state->general_reg[SX86_REG_AX].w.lo,x); + ctx->state->general_reg[SX86_REG_AX].w.lo = x; + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_and(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFC) == 0x20) { // AND reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // AND from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,w16,0,mod,reg,rm,op1_tmp,op2_tmp); + + if (opswap) sprintf(buf,"AND %s,%s",op2_tmp,op1_tmp); + else sprintf(buf,"AND %s,%s",op1_tmp,op2_tmp); + return 1; + } + if (opcode == 0x24) { // AND AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_dec_byte(ctx); + sprintf(buf,"AND AL,%02Xh",x); + return 1; + } + if (opcode == 0x25) { // AND AX,imm16 + sx86_uword x; + + x = softx86_fetch_dec_byte(ctx); + x |= softx86_fetch_dec_byte(ctx) << 8; + sprintf(buf,"AND AX,%04Xh",x); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_test(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFE) == 0x84) { // TEST reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // TEST from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_ro(ctx,w16,0,mod,reg, // unlike AND, TEST does not + rm,opswap,op_test8,op_test16,op_test32); // modify the dest. operand + + return 1; + } + if (opcode == 0xA8) { // TEST AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_exec_byte(ctx); + op_test8(ctx,ctx->state->general_reg[SX86_REG_AX].b.lo,x); + return 1; + } + if (opcode == 0xA9) { // TEST AX,imm16 + sx86_uword x; + + x = softx86_fetch_exec_byte(ctx); + x |= softx86_fetch_exec_byte(ctx) << 8; + op_test16(ctx,ctx->state->general_reg[SX86_REG_AX].w.lo,x); + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_test(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFE) == 0x84) { // TEST reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // TEST from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,w16,0,mod,reg,rm,op1_tmp,op2_tmp); + + if (opswap) sprintf(buf,"TEST %s,%s",op2_tmp,op1_tmp); + else sprintf(buf,"TEST %s,%s",op1_tmp,op2_tmp); + return 1; + } + if (opcode == 0xA8) { // TEST AL,imm8 + sx86_ubyte x; + + x = softx86_fetch_dec_byte(ctx); + sprintf(buf,"TEST AL,%02Xh",x); + return 1; + } + if (opcode == 0xA9) { // TEST AX,imm16 + sx86_uword x; + + x = softx86_fetch_dec_byte(ctx); + x |= softx86_fetch_dec_byte(ctx) << 8; + sprintf(buf,"TEST AX,%04Xh",x); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_xchg(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFE) == 0x86) { // XCHG reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_xchg(ctx,w16,0,mod,reg,rm); + + return 1; + } + if ((opcode&0xF8) == 0x90) { // XCHG reg16,AX + sx86_uword tmp; + int ro; + +/* interesting fact: Apparently the opcode 0x90 that Intel documents as NOP (no-op) also + decodes to XCHG AX,AX (which does nothing anyway) */ + ro = opcode - 0x90; + tmp = ctx->state->general_reg[ro].w.lo; + ctx->state->general_reg[ro].w.lo = ctx->state->general_reg[SX86_REG_AX].w.lo; + ctx->state->general_reg[SX86_REG_AX].w.lo = tmp; + + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_xchg(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFE) == 0x86) { // XCHG reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,w16,0,mod,reg,rm,op1_tmp,op2_tmp); + + sprintf(buf,"XCHG %s,%s",op1_tmp,op2_tmp); // for this instruction either way works + return 1; + } + if ((opcode&0xF8) == 0x90) { // XCHG reg16,AX + sprintf(buf,"XCHG %s,AX",sx86_regs16[opcode-0x90]); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_lea(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0x8D) { // LEA reg,reg/mem + sx86_ubyte x; + sx86_ubyte mod,reg,rm; + + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_lea(ctx,0,mod,reg,rm); + + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_lea(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0x8D) { // LEA reg,reg/mem + sx86_ubyte x; + sx86_ubyte mod,reg,rm; + + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,1,0,mod,reg,rm,op1_tmp,op2_tmp); + + sprintf(buf,"LEA %s,%s",op2_tmp,op1_tmp); // for this instruction either way works + return 1; + } + + return 0; +} + +sx86_sword op_bound16(softx86_ctx* ctx,sx86_sword idx,sx86_sword upper,sx86_sword lower) +{ + if (idx >= lower && idx <= (upper+2)) { + /* everything is fine */ + return lower; + } + else { + /* reset instruction pointer */ + softx86_set_near_instruction_ptr(ctx,ctx->state->reg_ip_exec_initial); + /* signal BOUNDs exception */ + softx86_int_sw_signal(ctx,5); + } + + return lower; +} + +sx86_sdword op_bound32(softx86_ctx* ctx,sx86_sdword idx,sx86_sdword upper,sx86_sdword lower) +{ + if (idx >= lower && idx <= (upper+4)) { + /* everything is fine */ + return lower; + } + else { + /* reset instruction pointer */ + softx86_set_near_instruction_ptr(ctx,ctx->state->reg_ip_exec_initial); + /* signal BOUNDs exception */ + softx86_int_sw_signal(ctx,5); + } + + return lower; +} + +/* TODO: I get the impression that the BOUNDs instruction was not + part of the original 8086 instruction set. When was it added? */ +int Sfx86OpcodeExec_bound(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0x62 && ctx->__private->level >= SX86_CPULEVEL_8086) { // BOUND reg,mem + sx86_ubyte x; + sx86_ubyte mod,reg,rm; + + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_far_ro3(ctx,0,mod,reg,rm,op_bound16,op_bound32); + + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_bound(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0x62 && ctx->__private->level >= SX86_CPULEVEL_8086) { // BOUND reg,mem + sx86_ubyte x; + sx86_ubyte mod,reg,rm; + + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,1,0,mod,reg,rm,op1_tmp,op2_tmp); + + sprintf(buf,"BOUND %s,%s",op2_tmp,op1_tmp); // for this instruction either way works + return 1; + } + + return 0; +} Index: lib/3rdparty/softx86/softx86/binops.c =================================================================== --- lib/3rdparty/softx86/softx86/binops.c (révision 59666) +++ lib/3rdparty/softx86/softx86/binops.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/binops.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/binops.h =================================================================== --- lib/3rdparty/softx86/softx86/binops.h (révision 0) +++ lib/3rdparty/softx86/softx86/binops.h (copie de travail) @@ -0,0 +1,109 @@ + +sx86_ubyte op_shl8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_shl16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_shl32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); +sx86_ubyte op_shl1_8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_shl1_16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_shl1_32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_shl_cl_8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_shl_cl_16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_shl_cl_32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_shr8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_shr16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_shr32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); +sx86_ubyte op_shr1_8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_shr1_16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_shr1_32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_shr_cl_8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_shr_cl_16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_shr_cl_32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_sar8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_sar16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_sar32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); +sx86_ubyte op_sar1_8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_sar1_16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_sar1_32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_sar_cl_8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_sar_cl_16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_sar_cl_32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_rol8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_rol16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_rol32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); +sx86_ubyte op_rol1_8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_rol1_16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_rol1_32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_rol_cl_8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_rol_cl_16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_rol_cl_32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_ror8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_ror16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_ror32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); +sx86_ubyte op_ror1_8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_ror1_16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_ror1_32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_ror_cl_8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_ror_cl_16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_ror_cl_32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_rcl8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_rcl16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_rcl32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); +sx86_ubyte op_rcl1_8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_rcl1_16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_rcl1_32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_rcl_cl_8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_rcl_cl_16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_rcl_cl_32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_rcr8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_rcr16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_rcr32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); +sx86_ubyte op_rcr1_8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_rcr1_16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_rcr1_32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_rcr_cl_8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_rcr_cl_16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_rcr_cl_32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_or8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_or16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_or32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); +sx86_ubyte op_xor8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_xor16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_xor32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); +sx86_ubyte op_and8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_and16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_and32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); +sx86_ubyte op_test8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_test16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_test32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); +sx86_ubyte op_not8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_not16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_not32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_neg8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_neg16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_neg32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_mul8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_mul16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_mul32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_imul8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_imul16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_imul32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_div8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_div16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_div32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_idiv8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_idiv16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_idiv32(softx86_ctx* ctx,sx86_udword src); + +int Sfx86OpcodeExec_or(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_or(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_xor(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_xor(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_and(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_and(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_test(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_test(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_xchg(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_xchg(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_lea(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_lea(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_bound(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_bound(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); Index: lib/3rdparty/softx86/softx86/binops.h =================================================================== --- lib/3rdparty/softx86/softx86/binops.h (révision 59666) +++ lib/3rdparty/softx86/softx86/binops.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/binops.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/cbw.c =================================================================== --- lib/3rdparty/softx86/softx86/cbw.c (révision 0) +++ lib/3rdparty/softx86/softx86/cbw.c (copie de travail) @@ -0,0 +1,64 @@ +/* + * cbw.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for CBW/CWDE/CWD/CDQ instructions. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "cbw.h" + +int Sfx86OpcodeExec_cxex(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0x98) { // CBW/CWDE + if (ctx->state->general_reg[SX86_REG_AX].b.lo & 0x80) ctx->state->general_reg[SX86_REG_AX].w.lo |= 0xFF00; + else ctx->state->general_reg[SX86_REG_AX].b.hi = 0x00; + + return 1; + } + + if (opcode == 0x99) { // CWD/CDQ + if (ctx->state->general_reg[SX86_REG_AX].w.lo & 0x8000) ctx->state->general_reg[SX86_REG_DX].w.lo = 0xFFFF; + else ctx->state->general_reg[SX86_REG_DX].w.lo = 0x0000; + + return 1; + } + + + return 0; +} + +int Sfx86OpcodeDec_cxex(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0x98) { // CBW/CWDE + strcpy(buf,"CBW"); + return 1; + } + + if (opcode == 0x99) { // CWD/CDQ + strcpy(buf,"CWD"); + return 1; + } + + return 0; +} Index: lib/3rdparty/softx86/softx86/cbw.c =================================================================== --- lib/3rdparty/softx86/softx86/cbw.c (révision 59666) +++ lib/3rdparty/softx86/softx86/cbw.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/cbw.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/cbw.h =================================================================== --- lib/3rdparty/softx86/softx86/cbw.h (révision 0) +++ lib/3rdparty/softx86/softx86/cbw.h (copie de travail) @@ -0,0 +1,3 @@ + +int Sfx86OpcodeExec_cxex(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_cxex(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); Index: lib/3rdparty/softx86/softx86/cbw.h =================================================================== --- lib/3rdparty/softx86/softx86/cbw.h (révision 59666) +++ lib/3rdparty/softx86/softx86/cbw.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/cbw.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/clc.c =================================================================== --- lib/3rdparty/softx86/softx86/clc.c (révision 0) +++ lib/3rdparty/softx86/softx86/clc.c (copie de travail) @@ -0,0 +1,110 @@ +/* + * clc.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for CLC/CLD/CLI/CMC/STC/STD/STI instructions. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "clc.h" +#include "drooling_duh.h" + +int Sfx86OpcodeExec_clx(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0xF5) { // CMC + ctx->state->reg_flags.val ^= SX86_CPUFLAG_CARRY; + return 1; + } + + if (opcode == 0xF8) { // CLC + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_CARRY; + return 1; + } + + if (opcode == 0xF9) { // STC + ctx->state->reg_flags.val |= SX86_CPUFLAG_CARRY; + return 1; + } + + if (opcode == 0xFA) { // CLI + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_INTENABLE; + return 1; + } + + if (opcode == 0xFB) { // STI + ctx->state->reg_flags.val |= SX86_CPUFLAG_INTENABLE; + return 1; + } + + if (opcode == 0xFC) { // CLD + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_DIRECTIONREV; + return 1; + } + + if (opcode == 0xFD) { // STD + ctx->state->reg_flags.val |= SX86_CPUFLAG_DIRECTIONREV; + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_clx(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0xF5) { // CMC + strcpy(buf,"CMC"); + return 1; + } + + if (opcode == 0xF8) { // CLC + strcpy(buf,"CLC"); + return 1; + } + + if (opcode == 0xF9) { // STC + strcpy(buf,"STC"); + return 1; + } + + if (opcode == 0xFA) { // CLI + strcpy(buf,"CLI"); + return 1; + } + + if (opcode == 0xFB) { // STI + strcpy(buf,"STI"); + return 1; + } + + if (opcode == 0xFC) { // CLD + strcpy(buf,"CLD"); + return 1; + } + + if (opcode == 0xFD) { // STD + strcpy(buf,"STD"); + return 1; + } + + return 0; +} Index: lib/3rdparty/softx86/softx86/clc.c =================================================================== --- lib/3rdparty/softx86/softx86/clc.c (révision 59666) +++ lib/3rdparty/softx86/softx86/clc.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/clc.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/clc.h =================================================================== --- lib/3rdparty/softx86/softx86/clc.h (révision 0) +++ lib/3rdparty/softx86/softx86/clc.h (copie de travail) @@ -0,0 +1,3 @@ + +int Sfx86OpcodeExec_clx(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_clx(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); Index: lib/3rdparty/softx86/softx86/clc.h =================================================================== --- lib/3rdparty/softx86/softx86/clc.h (révision 59666) +++ lib/3rdparty/softx86/softx86/clc.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/clc.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/CMakeLists.txt =================================================================== --- lib/3rdparty/softx86/softx86/CMakeLists.txt (révision 0) +++ lib/3rdparty/softx86/softx86/CMakeLists.txt (copie de travail) @@ -0,0 +1,29 @@ + +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/softx86) + +list(APPEND SOURCE + aaa.c + add.c + binops.c + cbw.c + clc.c + drooling_duh.c + fpu.c + groupies.c + inc.c + interrupts.c + ioport.c + jumpy.c + mov.c + optable.c + prefixes.c + procframe.c + pushpop.c + shovel.c + softx86.c +### Uncomment the following files for dll compilation: +# softx86_dll.def +# softx86_dll.rc +) + +add_library(softx86 ${SOURCE}) Index: lib/3rdparty/softx86/softx86/CMakeLists.txt =================================================================== --- lib/3rdparty/softx86/softx86/CMakeLists.txt (révision 59666) +++ lib/3rdparty/softx86/softx86/CMakeLists.txt (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/CMakeLists.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/drooling_duh.c =================================================================== --- lib/3rdparty/softx86/softx86/drooling_duh.c (révision 0) +++ lib/3rdparty/softx86/softx86/drooling_duh.c (copie de travail) @@ -0,0 +1,60 @@ +/* + * drooling_duh.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for HLT/WAIT instructions. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "drooling_duh.h" + +int Sfx86OpcodeExec_duhhh(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0x9B) { // WAIT + return 1; + } + if (opcode == 0xF4) { // HLT +/* if an external interrupt pending, proceed */ + if (ctx->state->int_hw_flag || ctx->state->int_nmi) + return 1; +/* else, do not proceed */ + else + return 3; + } + + return 0; +} + +int Sfx86OpcodeDec_duhhh(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0x9B) { // WAIT + strcpy(buf,"WAIT"); + return 1; + } + if (opcode == 0xF4) { // HLT + strcpy(buf,"HLT"); + return 1; + } + + return 0; +} Index: lib/3rdparty/softx86/softx86/drooling_duh.c =================================================================== --- lib/3rdparty/softx86/softx86/drooling_duh.c (révision 59666) +++ lib/3rdparty/softx86/softx86/drooling_duh.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/drooling_duh.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/drooling_duh.h =================================================================== --- lib/3rdparty/softx86/softx86/drooling_duh.h (révision 0) +++ lib/3rdparty/softx86/softx86/drooling_duh.h (copie de travail) @@ -0,0 +1,3 @@ + +int Sfx86OpcodeExec_duhhh(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_duhhh(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); Index: lib/3rdparty/softx86/softx86/drooling_duh.h =================================================================== --- lib/3rdparty/softx86/softx86/drooling_duh.h (révision 59666) +++ lib/3rdparty/softx86/softx86/drooling_duh.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/drooling_duh.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/fpu.c =================================================================== --- lib/3rdparty/softx86/softx86/fpu.c (révision 0) +++ lib/3rdparty/softx86/softx86/fpu.c (copie de travail) @@ -0,0 +1,45 @@ +/* + * fpu.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Handles 80x87 FPU opcodes by passing them down through callbacks + * set up in application. + * + * The idea behind this is to handle these opcodes the same way the + * 8086, 80286, 80386, and some 80486s handled them by passing them + * off to an optional external FPU (possibly provided by another + * library similar to this). + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "fpu.h" + +int Sfx86OpcodeExec_fpuhandoff(sx86_ubyte opcode,softx86_ctx* ctx) +{ + return ctx->callbacks->on_fpu_opcode_exec(ctx,ctx->ref_softx87_ctx,opcode); +} + +int Sfx86OpcodeDec_fpuhandoff(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + return ctx->callbacks->on_fpu_opcode_dec(ctx,ctx->ref_softx87_ctx,opcode,buf); +} Index: lib/3rdparty/softx86/softx86/fpu.c =================================================================== --- lib/3rdparty/softx86/softx86/fpu.c (révision 59666) +++ lib/3rdparty/softx86/softx86/fpu.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/fpu.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/fpu.h =================================================================== --- lib/3rdparty/softx86/softx86/fpu.h (révision 0) +++ lib/3rdparty/softx86/softx86/fpu.h (copie de travail) @@ -0,0 +1,3 @@ + +int Sfx86OpcodeExec_fpuhandoff(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_fpuhandoff(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); Index: lib/3rdparty/softx86/softx86/fpu.h =================================================================== --- lib/3rdparty/softx86/softx86/fpu.h (révision 59666) +++ lib/3rdparty/softx86/softx86/fpu.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/fpu.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/groupies.c =================================================================== --- lib/3rdparty/softx86/softx86/groupies.c (révision 0) +++ lib/3rdparty/softx86/softx86/groupies.c (copie de travail) @@ -0,0 +1,764 @@ +/* + * groupies.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for instruction opcodes grouped by a common + * opcode and specified by the reg portion of the mod/reg/rm byte. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "groupies.h" +#include "optable.h" +#include "binops.h" +#include "add.h" +#include "mov.h" +#include "inc.h" + +sx86_uword op_ncall16(softx86_ctx* ctx,sx86_uword src) +{ + softx86_stack_pushw(ctx,ctx->state->reg_ip); + softx86_set_near_instruction_ptr(ctx,src); + return src; +} + +sx86_udword op_ncall32(softx86_ctx* ctx,sx86_udword src) +{ + softx86_stack_pushw(ctx,(ctx->state->reg_ip>>16)&0xFFFF); + softx86_stack_pushw(ctx,ctx->state->reg_ip&0xFFFF); + softx86_set_near_instruction_ptr(ctx,src); + return src; +} + +sx86_uword op_popmem16(softx86_ctx* ctx) +{ + return softx86_stack_popw(ctx); +} + +sx86_udword op_popmem32(softx86_ctx* ctx) +{ + sx86_udword d; + + d = ((sx86_udword)softx86_stack_popw(ctx)); + d |= ((sx86_udword)softx86_stack_popw(ctx))<<16; + return d; +} + +sx86_uword op_pushmem16(softx86_ctx* ctx,sx86_uword src) +{ + softx86_stack_pushw(ctx,src); + return src; +} + +sx86_udword op_pushmem32(softx86_ctx* ctx,sx86_udword src) +{ + softx86_stack_pushw(ctx,(src>>16)&0xFFFF); + softx86_stack_pushw(ctx,src&0xFFFF); + return src; +} + +sx86_uword op_njmp16(softx86_ctx* ctx,sx86_uword src) +{ + softx86_set_near_instruction_ptr(ctx,src); + return src; +} + +sx86_udword op_njmp32(softx86_ctx* ctx,sx86_udword src) +{ + softx86_set_near_instruction_ptr(ctx,src); + return src; +} + +void op_fcall16(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs) +{ + softx86_stack_pushw(ctx,ctx->state->segment_reg[SX86_SREG_CS].val); + softx86_stack_pushw(ctx,ctx->state->reg_ip); + softx86_set_instruction_ptr(ctx,seg,ofs); +} + +void op_fcall32(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs) +{ + softx86_stack_pushw(ctx,ctx->state->segment_reg[SX86_SREG_CS].val); + softx86_stack_pushw(ctx,ctx->state->reg_ip&0xFFFF); + softx86_stack_pushw(ctx,(ctx->state->reg_ip>>16)&0xFFFF); + softx86_set_instruction_ptr(ctx,seg,ofs); +} + +void op_fjmp16(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs) +{ + softx86_set_instruction_ptr(ctx,seg,ofs); +} + +void op_fjmp32(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs) +{ + softx86_set_instruction_ptr(ctx,seg,ofs); +} + +int Sfx86OpcodeExec_group80(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFC) == 0x80) { + sx86_ubyte x; + sx86_ubyte w16,sx; + sx86_ubyte mod,reg,rm; + sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); + sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val); + sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val); + + w16 = opcode&1; + sx = (opcode>>1)&1; + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + + if (reg == 0) { + op8 = op_add8; + op16 = op_add16; + op32 = op_add32; + } + else if (reg == 1) { + op8 = op_or8; + op16 = op_or16; + op32 = op_or32; + } + else if (reg == 2) { + op8 = op_adc8; + op16 = op_adc16; + op32 = op_adc32; + } + else if (reg == 3) { + op8 = op_sbb8; + op16 = op_sbb16; + op32 = op_sbb32; + } + else if (reg == 4) { + op8 = op_and8; + op16 = op_and16; + op32 = op_and32; + } + else if (reg == 5) { + op8 = op_sub8; + op16 = op_sub16; + op32 = op_sub32; + } + else if (reg == 6) { + op8 = op_xor8; + op16 = op_xor16; + op32 = op_xor32; + } + else if (reg == 7) { + op8 = op_sub8; /* CMP is like SUB except that the result */ + op16 = op_sub16; /* ends up in a temporary register, leaving */ + op32 = op_sub32; /* the original data untouched. */ + } + else { + return 0; + } + + if (reg == 7) /* CMP doesn't modify the dest. register... */ + sx86_exec_full_modrmonly_ro_imm(ctx,w16,0,mod,rm,op8,op16,op32,sx); + else + sx86_exec_full_modrmonly_rw_imm(ctx,w16,0,mod,rm,op8,op16,op32,sx); + + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_group80(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFC) == 0x80) { + sx86_ubyte x; + sx86_ubyte w16,sx; + sx86_ubyte mod,reg,rm; + sx86_uword imm16; + + w16 = opcode&1; + sx = (opcode>>1)&1; + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp); + + imm16 = softx86_fetch_dec_byte(ctx); + if (w16) + { + if (sx) + imm16 |= (imm16&0x80) ? 0xFF80 : 0; + else + imm16 |= softx86_fetch_dec_byte(ctx)<<8; + } + + if (reg == 0) sprintf(buf,"ADD %s,%04Xh",op1_tmp,imm16); + else if (reg == 1) sprintf(buf,"OR %s,%04Xh",op1_tmp,imm16); + else if (reg == 2) sprintf(buf,"ADC %s,%04Xh",op1_tmp,imm16); + else if (reg == 3) sprintf(buf,"SBB %s,%04Xh",op1_tmp,imm16); + else if (reg == 4) sprintf(buf,"AND %s,%04Xh",op1_tmp,imm16); + else if (reg == 5) sprintf(buf,"SUB %s,%04Xh",op1_tmp,imm16); + else if (reg == 6) sprintf(buf,"XOR %s,%04Xh",op1_tmp,imm16); + else if (reg == 7) sprintf(buf,"CMP %s,%04Xh",op1_tmp,imm16); + else return 0; + + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_groupC0(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFE) == 0xC0) { + sx86_ubyte x; + sx86_ubyte w16; + sx86_ubyte mod,reg,rm; + sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); + sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val); + sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val); + + w16 = (opcode&1); + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + + if (reg == 0) { + op8 = op_rol8; + op16 = op_rol16; + op32 = op_rol32; + } + else if (reg == 1) { + op8 = op_ror8; + op16 = op_ror16; + op32 = op_ror32; + } + else if (reg == 2) { + op8 = op_rcl8; + op16 = op_rcl16; + op32 = op_rcl32; + } + else if (reg == 3) { + op8 = op_rcr8; + op16 = op_rcr16; + op32 = op_rcr32; + } + else if (reg == 4) { + op8 = op_shl8; + op16 = op_shl16; + op32 = op_shl32; + } + else if (reg == 5) { + op8 = op_shr8; + op16 = op_shr16; + op32 = op_shr32; + } + else if (reg == 7) { + op8 = op_sar8; + op16 = op_sar16; + op32 = op_sar32; + } + else { + return 0; + } + + sx86_exec_full_modrmonly_rw_imm8(ctx,w16,0,mod,rm,op8,op16,op32); + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_groupC0(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFE) == 0xC0) { + sx86_ubyte x; + sx86_ubyte w16; + sx86_ubyte mod,reg,rm; + sx86_uword imm16; + + w16 = (opcode&1); + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp); + + imm16 = softx86_fetch_dec_byte(ctx); + + if (reg == 0) sprintf(buf,"ROL %s,%04Xh",op1_tmp,imm16); + else if (reg == 1) sprintf(buf,"ROR %s,%04Xh",op1_tmp,imm16); + else if (reg == 2) sprintf(buf,"RCL %s,%04Xh",op1_tmp,imm16); + else if (reg == 3) sprintf(buf,"RCR %s,%04Xh",op1_tmp,imm16); + else if (reg == 4) sprintf(buf,"SHL %s,%04Xh",op1_tmp,imm16); + else if (reg == 5) sprintf(buf,"SHR %s,%04Xh",op1_tmp,imm16); + else if (reg == 7) sprintf(buf,"SAR %s,%04Xh",op1_tmp,imm16); + else return 0; + + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_groupD0(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFE) == 0xD0 || (opcode&0xFE) == 0xD2) { + sx86_ubyte x; + sx86_ubyte w16; + sx86_ubyte mod,reg,rm; + sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src); + sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src); + sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src); + + w16 = (opcode&1); + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + + if (reg == 0) { + if ((opcode&0xFE) == 0xD2) { + op8 = op_rol_cl_8; + op16 = op_rol_cl_16; + op32 = op_rol_cl_32; + } + else { + op8 = op_rol1_8; + op16 = op_rol1_16; + op32 = op_rol1_32; + } + } + else if (reg == 1) { + if ((opcode&0xFE) == 0xD2) { + op8 = op_ror_cl_8; + op16 = op_ror_cl_16; + op32 = op_ror_cl_32; + } + else { + op8 = op_ror1_8; + op16 = op_ror1_16; + op32 = op_ror1_32; + } + } + else if (reg == 2) { + if ((opcode&0xFE) == 0xD2) { + op8 = op_rcl_cl_8; + op16 = op_rcl_cl_16; + op32 = op_rcl_cl_32; + } + else { + op8 = op_rcl1_8; + op16 = op_rcl1_16; + op32 = op_rcl1_32; + } + } + else if (reg == 3) { + if ((opcode&0xFE) == 0xD2) { + op8 = op_rcr_cl_8; + op16 = op_rcr_cl_16; + op32 = op_rcr_cl_32; + } + else { + op8 = op_rcr1_8; + op16 = op_rcr1_16; + op32 = op_rcr1_32; + } + } + else if (reg == 4) { + if ((opcode&0xFE) == 0xD2) { + op8 = op_shl_cl_8; + op16 = op_shl_cl_16; + op32 = op_shl_cl_32; + } + else { + op8 = op_shl1_8; + op16 = op_shl1_16; + op32 = op_shl1_32; + } + } + else if (reg == 5) { + if ((opcode&0xFE) == 0xD2) { + op8 = op_shr_cl_8; + op16 = op_shr_cl_16; + op32 = op_shr_cl_32; + } + else { + op8 = op_shr1_8; + op16 = op_shr1_16; + op32 = op_shr1_32; + } + } + else if (reg == 7) { + if ((opcode&0xFE) == 0xD2) { + op8 = op_sar_cl_8; + op16 = op_sar_cl_16; + op32 = op_sar_cl_32; + } + else { + op8 = op_sar1_8; + op16 = op_sar1_16; + op32 = op_sar1_32; + } + } + else { + return 0; + } + + sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op8,op16,op32); + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_groupD0(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFE) == 0xD0 || (opcode&0xFE) == 0xD2) { + sx86_ubyte x; + sx86_ubyte w16; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp); + + if ((opcode&0xFE) == 0xD2) { + if (reg == 0) sprintf(buf,"ROL %s,CL",op1_tmp); + else if (reg == 1) sprintf(buf,"ROR %s,CL",op1_tmp); + else if (reg == 2) sprintf(buf,"RCL %s,CL",op1_tmp); + else if (reg == 3) sprintf(buf,"RCR %s,CL",op1_tmp); + else if (reg == 4) sprintf(buf,"SHL %s,CL",op1_tmp); + else if (reg == 5) sprintf(buf,"SHR %s,CL",op1_tmp); + else if (reg == 7) sprintf(buf,"SAR %s,CL",op1_tmp); + else return 0; + } + else { + if (reg == 0) sprintf(buf,"ROL %s,1",op1_tmp); + else if (reg == 1) sprintf(buf,"ROR %s,1",op1_tmp); + else if (reg == 2) sprintf(buf,"RCL %s,1",op1_tmp); + else if (reg == 3) sprintf(buf,"RCR %s,1",op1_tmp); + else if (reg == 4) sprintf(buf,"SHL %s,1",op1_tmp); + else if (reg == 5) sprintf(buf,"SHR %s,1",op1_tmp); + else if (reg == 7) sprintf(buf,"SAR %s,1",op1_tmp); + else return 0; + } + + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_groupC6(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFE) == 0xC6) { + sx86_ubyte x; + sx86_ubyte w16; + sx86_ubyte mod,reg,rm; + sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); + sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val); + sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val); + + w16 = (opcode&1); + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + + if (reg == 0) { + op8 = op_mov8; + op16 = op_mov16; + op32 = op_mov32; + } + else { + return 0; + } + + sx86_exec_full_modrmonly_rw_imm(ctx,w16,0,mod,rm,op8,op16,op32,0); + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_groupC6(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFE) == 0xC6) { + sx86_ubyte x; + sx86_ubyte w16; + sx86_ubyte mod,reg,rm; + sx86_uword imm16; + + w16 = (opcode&1); + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp); + + imm16 = softx86_fetch_dec_byte(ctx); + if (w16) imm16 |= softx86_fetch_dec_byte(ctx)<<8; + + if (reg == 0) sprintf(buf,"MOV %s,%04Xh",op1_tmp,imm16); + else return 0; + + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_groupFE(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFE) == 0xFE) { + sx86_ubyte x; + sx86_ubyte w16; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + + if (reg == 0) { + sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op_inc8,op_inc16,op_inc32); + } + else if (reg == 1) { + sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op_dec8,op_dec16,op_dec32); + } + else if (reg >= 2) { + if (!w16) return 0; + + if (reg == 3 || reg == 5) { + void (*op16)(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs); + void (*op32)(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs); + + /* you cannot have a far address in registers */ + if (mod == 3) + return 0; + + if (reg == 3) { + op16 = op_fcall16; + op32 = op_fcall32; + } + else if (reg == 5) { + op16 = op_fjmp16; + op32 = op_fjmp32; + } + + sx86_exec_full_modrmonly_callfar(ctx,0,mod,rm,op16,op32); + } + else { + sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src); + sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src); + + if (reg == 2) { + op16 = op_ncall16; + op32 = op_ncall32; + } + else if (reg == 4) { + op16 = op_njmp16; + op32 = op_njmp32; + } + else if (reg == 6) { + op16 = op_pushmem16; + op32 = op_pushmem32; + } + else { + return 0; + } + + sx86_exec_full_modrmonly_ro(ctx,1,0,mod,rm,NULL,op16,op32); + } + } + + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_groupFE(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFE) == 0xFE) { + sx86_ubyte x; + sx86_ubyte w16; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp); + + if (reg == 0) sprintf(buf,"INC %s",op1_tmp); + else if (reg == 1) sprintf(buf,"DEC %s",op1_tmp); + else { + if (!w16) + return 0; + if (reg == 2) + sprintf(buf,"CALL %s",op1_tmp); + else if (reg == 3) + sprintf(buf,"CALL FAR %s",op1_tmp); + else if (reg == 4) + sprintf(buf,"JMP %s",op1_tmp); + else if (reg == 5) + sprintf(buf,"JMP FAR %s",op1_tmp); + else if (reg == 6) + sprintf(buf,"PUSH %s",op1_tmp); + else + return 0; + } + + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_group8F(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0x8F) { + sx86_ubyte x,mod,reg,rm; + sx86_uword (*op16)(softx86_ctx* ctx); + sx86_udword (*op32)(softx86_ctx* ctx); + + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + + if (reg == 0) { + op16 = op_popmem16; + op32 = op_popmem32; + } + else { + return 0; + } + + sx86_exec_full_modrmonly_wo(ctx,1,0,mod,rm,NULL,op16,op32); + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_group8F(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0x8F) { + sx86_ubyte x; + sx86_ubyte mod,reg,rm; + + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modrmonly(ctx,1,0,mod,rm,op1_tmp); + + if (reg == 0) sprintf(buf,"POP %s",op1_tmp); + else return 0; + + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_groupF6(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFE) == 0xF6) { + sx86_ubyte x; + sx86_ubyte w16; + sx86_ubyte mod,reg,rm; + sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src); + sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src); + sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src); + + w16 = (opcode&1); + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + + if (reg == 0) { + /* taken care of later */ + } + else if (reg == 2) { + /* taken care of later */ + } + else if (reg == 3) { + /* taken care of later */ + } + else if (reg == 4) { + op8 = op_mul8; + op16 = op_mul16; + op32 = op_mul32; + } + else if (reg == 5) { + op8 = op_imul8; + op16 = op_imul16; + op32 = op_imul32; + } + else if (reg == 6) { + op8 = op_div8; + op16 = op_div16; + op32 = op_div32; + } + else if (reg == 7) { + op8 = op_idiv8; /* CMP is like SUB except that the result */ + op16 = op_idiv16; /* ends up in a temporary register, leaving */ + op32 = op_idiv32; /* the original data untouched. */ + } + else { + return 0; + } + +/* TEST does not modify the dest. register... */ + if (reg == 0) + sx86_exec_full_modrmonly_ro_imm(ctx,w16,0,mod,rm,op_test8,op_test16,op_test32,0); +/* NOT and NEG only have one operand */ + else if (reg == 2) + sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op_not8,op_not16,op_not32); + else if (reg == 3) + sx86_exec_full_modrmonly_rw(ctx,w16,0,mod,rm,op_neg8,op_neg16,op_neg32); +/* everybody else (MUL/IMUL/DIV/IDIV) has one operand but modifies (E)AX */ + else + sx86_exec_full_modrmonly_ro(ctx,w16,0,mod,rm,op8,op16,op32); + + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_groupF6(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFE) == 0xF6) { + sx86_ubyte x; + sx86_ubyte w16; + sx86_ubyte mod,reg,rm; + sx86_uword imm16; + + w16 = (opcode&1); + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp); + + if (reg == 0) { + imm16 = softx86_fetch_dec_byte(ctx); + if (w16) imm16 |= softx86_fetch_dec_byte(ctx)<<8; + } + + if (reg == 0) sprintf(buf,"TEST %s,%04Xh",op1_tmp,imm16); + else if (reg == 2) sprintf(buf,"NOT %s",op1_tmp); + else if (reg == 3) sprintf(buf,"NEG %s",op1_tmp); + else if (reg == 4) sprintf(buf,"MUL %s",op1_tmp); + else if (reg == 5) sprintf(buf,"IMUL %s",op1_tmp); + else if (reg == 6) sprintf(buf,"DIV %s",op1_tmp); + else if (reg == 7) sprintf(buf,"IDIV %s",op1_tmp); + else return 0; + + return 1; + } + + return 0; +} + Index: lib/3rdparty/softx86/softx86/groupies.c =================================================================== --- lib/3rdparty/softx86/softx86/groupies.c (révision 59666) +++ lib/3rdparty/softx86/softx86/groupies.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/groupies.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/groupies.h =================================================================== --- lib/3rdparty/softx86/softx86/groupies.h (révision 0) +++ lib/3rdparty/softx86/softx86/groupies.h (copie de travail) @@ -0,0 +1,15 @@ + +int Sfx86OpcodeExec_group80(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_group80(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_group8F(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_group8F(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_groupC0(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_groupC0(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_groupC6(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_groupC6(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_groupD0(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_groupD0(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_groupF6(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_groupF6(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_groupFE(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_groupFE(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); Index: lib/3rdparty/softx86/softx86/groupies.h =================================================================== --- lib/3rdparty/softx86/softx86/groupies.h (révision 59666) +++ lib/3rdparty/softx86/softx86/groupies.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/groupies.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/inc.c =================================================================== --- lib/3rdparty/softx86/softx86/inc.c (révision 0) +++ lib/3rdparty/softx86/softx86/inc.c (copie de travail) @@ -0,0 +1,301 @@ +/* + * inc.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for the INC/DEC instructions. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "inc.h" + +sx86_ubyte op_dec8(softx86_ctx* ctx,sx86_ubyte src) +{ + sx86_ubyte ret; + +/* peform the subtraction */ + ret = src-1; + +/* apparently CF is not touched by this instruction */ + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a - b = c, ((a AND 0Fh) - (b AND 0Fh) < 0). + in other words, if the lowest nibbles subtracted cause carry. */ + if ((src&0xF) < 1) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_dec16(softx86_ctx* ctx,sx86_uword src) +{ + sx86_uword ret; + +/* peform the subtraction */ + ret = src-1; + +/* apparently CF is not touched by this instruction */ + +/* if result treated as signed value is negative */ + if (ret & 0x8000) + ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a - b = c, ((a AND 0Fh) - (b AND 0Fh) < 0). + in other words, if the lowest nibbles subtracted cause carry. */ + if ((src&0xF) < 1) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_dec32(softx86_ctx* ctx,sx86_udword src) +{ + sx86_udword ret; + +/* peform the subtraction */ + ret = src-1; + +/* apparently CF is not touched by this instruction */ + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) + ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a - b = c, ((a AND 0Fh) - (b AND 0Fh) < 0). + in other words, if the lowest nibbles subtracted cause carry. */ + if ((src&0xF) < 1) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_ubyte op_inc8(softx86_ctx* ctx,sx86_ubyte src) +{ + sx86_ubyte ret; + +/* peform the addition */ + ret = src+1; + +/* apparently CF is not touched by this instruction */ + +/* if result treated as signed value is negative */ + if (ret & 0x80) ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a + b = c, ((b AND 0Fh) + (a AND 0Fh) >= 0x10). + in other words, if the lowest nibbles added together overflow. */ + if ((1+(src&0xF)) >= 0x10) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity8(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_uword op_inc16(softx86_ctx* ctx,sx86_uword src) +{ + sx86_uword ret; + +/* peform the addition */ + ret = src+1; + +/* apparently CF is not touched by this instruction */ + +/* if result treated as signed value is negative */ + if (ret & 0x8000) + ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a + b = c, ((b AND 0Fh) + (a AND 0Fh) >= 0x10). + in other words, if the lowest nibbles added together overflow. */ + if ((1+(src&0xF)) >= 0x10) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +sx86_udword op_inc32(softx86_ctx* ctx,sx86_udword src) +{ + sx86_udword ret; + +/* peform the addition */ + ret = src+1; + +/* apparently CF is not touched by this instruction */ + +/* if result treated as signed value is negative */ + if (ret & 0x80000000) + ctx->state->reg_flags.val |= SX86_CPUFLAG_SIGN; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_SIGN; + +/* if result is zero */ + if (!ret) ctx->state->reg_flags.val |= SX86_CPUFLAG_ZERO; + else ctx->state->reg_flags.val &= ~SX86_CPUFLAG_ZERO; + +/* auxiliary flag emulation (not defined by Intel's documentation, but observed + from many trials in DEBUG on an old Pentium Pro 166MHz I have kickin' around + as a web server :) + + apparently aux is set if: + given operation a + b = c, ((b AND 0Fh) + (a AND 0Fh) >= 0x10). + in other words, if the lowest nibbles added together overflow. */ + if ((1+(src&0xF)) >= 0x10) + ctx->state->reg_flags.val |= SX86_CPUFLAG_AUX; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_AUX; + +/* finally, compute parity for parity bit */ + if (softx86_parity16(ret)) + ctx->state->reg_flags.val |= SX86_CPUFLAG_PARITY; + else + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_PARITY; + + return ret; +} + +int Sfx86OpcodeExec_inc(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xF8) == 0x40) { // INC [reg] + sx86_uword w,i; + + i = opcode-0x40; + w = ctx->state->general_reg[i].w.lo; + ctx->state->general_reg[i].w.lo = op_inc16(ctx,w); + return 1; + } + else if ((opcode&0xF8) == 0x48) { // DEC [reg] + sx86_uword w,i; + + i = opcode-0x48; + w = ctx->state->general_reg[i].w.lo; + ctx->state->general_reg[i].w.lo = op_dec16(ctx,w); + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_inc(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xF8) == 0x40) { // INC [reg] + sprintf(buf,"INC %s",sx86_regs16[opcode-0x40]); + return 1; + } + else if ((opcode&0xF8) == 0x48) { // DEC [reg] + sprintf(buf,"DEC %s",sx86_regs16[opcode-0x48]); + return 1; + } + + return 0; +} Index: lib/3rdparty/softx86/softx86/inc.c =================================================================== --- lib/3rdparty/softx86/softx86/inc.c (révision 59666) +++ lib/3rdparty/softx86/softx86/inc.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/inc.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/inc.h =================================================================== --- lib/3rdparty/softx86/softx86/inc.h (révision 0) +++ lib/3rdparty/softx86/softx86/inc.h (copie de travail) @@ -0,0 +1,10 @@ + +int Sfx86OpcodeExec_inc(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_inc(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); + +sx86_ubyte op_dec8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_dec16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_dec32(softx86_ctx* ctx,sx86_udword src); +sx86_ubyte op_inc8(softx86_ctx* ctx,sx86_ubyte src); +sx86_uword op_inc16(softx86_ctx* ctx,sx86_uword src); +sx86_udword op_inc32(softx86_ctx* ctx,sx86_udword src); Index: lib/3rdparty/softx86/softx86/inc.h =================================================================== --- lib/3rdparty/softx86/softx86/inc.h (révision 59666) +++ lib/3rdparty/softx86/softx86/inc.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/inc.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/interrupts.c =================================================================== --- lib/3rdparty/softx86/softx86/interrupts.c (révision 0) +++ lib/3rdparty/softx86/softx86/interrupts.c (copie de travail) @@ -0,0 +1,75 @@ +/* + * interrupts.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for the INT instruction. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "interrupts.h" + +int Sfx86OpcodeExec_int(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0xCC) { // INT 3 + softx86_int_sw_signal(ctx,3); + return 1; + } + else if (opcode == 0xCD) { // INT n + sx86_ubyte i; + + i = softx86_fetch_exec_byte(ctx); + softx86_int_sw_signal(ctx,i); + + return 1; + } + else if (opcode == 0xCE) { // INTO + if (ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW) { + softx86_int_sw_signal(ctx,4); + } + + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_int(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0xCC) { // INT 3 + strcpy(buf,"INT 3"); + return 1; + } + else if (opcode == 0xCD) { // INT n + sx86_ubyte i; + + i = softx86_fetch_dec_byte(ctx); + sprintf(buf,"INT %02Xh",i); + return 1; + } + else if (opcode == 0xCE) { // INTO + strcpy(buf,"INTO"); + return 1; + } + + return 0; +} Index: lib/3rdparty/softx86/softx86/interrupts.c =================================================================== --- lib/3rdparty/softx86/softx86/interrupts.c (révision 59666) +++ lib/3rdparty/softx86/softx86/interrupts.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/interrupts.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/interrupts.h =================================================================== --- lib/3rdparty/softx86/softx86/interrupts.h (révision 0) +++ lib/3rdparty/softx86/softx86/interrupts.h (copie de travail) @@ -0,0 +1,3 @@ + +int Sfx86OpcodeExec_int(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_int(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); Index: lib/3rdparty/softx86/softx86/interrupts.h =================================================================== --- lib/3rdparty/softx86/softx86/interrupts.h (révision 59666) +++ lib/3rdparty/softx86/softx86/interrupts.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/interrupts.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/ioport.c =================================================================== --- lib/3rdparty/softx86/softx86/ioport.c (révision 0) +++ lib/3rdparty/softx86/softx86/ioport.c (copie de travail) @@ -0,0 +1,169 @@ +/* + * ioport.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for IN/OUT instructions. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "ioport.h" + +int Sfx86OpcodeExec_io(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if ((opcode&0xFE) == 0xE4) { // IN AL/AX,imm8 + sx86_ubyte ionum; + sx86_ubyte w16; + +/* TODO: If emulating 386+ and protected/v86 mode check I/O permission bitmap */ + + w16 = (opcode&1); + ionum = softx86_fetch_exec_byte(ctx); // get imm8 + + if (w16) { /* NOTE: It is always assumed that it is in Little Endian */ + sx86_uword rw; + + ctx->callbacks->on_read_io(ctx,ionum,(sx86_ubyte*)(&rw),2); + SWAP_WORD_FROM_LE(rw); + ctx->state->general_reg[SX86_REG_AX].w.lo = rw; + } + else { + sx86_ubyte rb; + + ctx->callbacks->on_read_io(ctx,ionum,(sx86_ubyte*)(&rb),1); + ctx->state->general_reg[SX86_REG_AX].b.lo = rb; + } + + return 1; + } + else if ((opcode&0xFE) == 0xEC) { // IN AL/AX,DX + sx86_ubyte w16; + +/* TODO: If emulating 386+ and protected/v86 mode check I/O permission bitmap */ + + w16 = (opcode&1); + if (w16) { /* NOTE: It is always assumed that it is in Little Endian */ + sx86_uword rw; + + ctx->callbacks->on_read_io(ctx,ctx->state->general_reg[SX86_REG_DX].w.lo,(sx86_ubyte*)(&rw),2); + SWAP_WORD_FROM_LE(rw); + ctx->state->general_reg[SX86_REG_AX].w.lo = rw; + } + else { + sx86_ubyte rb; + + ctx->callbacks->on_read_io(ctx,ctx->state->general_reg[SX86_REG_DX].w.lo,(sx86_ubyte*)(&rb),1); + ctx->state->general_reg[SX86_REG_AX].b.lo = rb; + } + + return 1; + } + else if ((opcode&0xFE) == 0xE6) { // OUT AL/AX,imm8 + sx86_ubyte ionum; + sx86_ubyte w16; + +/* TODO: If emulating 386+ and protected/v86 mode check I/O permission bitmap */ + + w16 = (opcode&1); + ionum = softx86_fetch_exec_byte(ctx); // get imm8 + + if (w16) { /* NOTE: It is always assumed that it is in Little Endian */ + sx86_uword rw; + + rw = ctx->state->general_reg[SX86_REG_AX].w.lo; + SWAP_WORD_TO_LE(rw); + ctx->callbacks->on_write_io(ctx,ionum,(sx86_ubyte*)(&rw),2); + } + else { + sx86_ubyte rb; + + rb = ctx->state->general_reg[SX86_REG_AX].b.lo; + ctx->callbacks->on_write_io(ctx,ionum,(sx86_ubyte*)(&rb),1); + } + + return 1; + } + else if ((opcode&0xFE) == 0xEE) { // OUT AL/AX,DX + sx86_ubyte w16; + +/* TODO: If emulating 386+ and protected/v86 mode check I/O permission bitmap */ + + w16 = (opcode&1); + if (w16) { /* NOTE: It is always assumed that it is in Little Endian */ + sx86_uword rw; + + rw = ctx->state->general_reg[SX86_REG_AX].w.lo; + SWAP_WORD_TO_LE(rw); + ctx->callbacks->on_write_io(ctx,ctx->state->general_reg[SX86_REG_DX].w.lo,(sx86_ubyte*)(&rw),2); + } + else { + sx86_ubyte rb; + + rb = ctx->state->general_reg[SX86_REG_AX].b.lo; + ctx->callbacks->on_write_io(ctx,ctx->state->general_reg[SX86_REG_DX].w.lo,(sx86_ubyte*)(&rb),1); + } + + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_io(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFE) == 0xE4) { // IN AL/AX,imm8 + sx86_ubyte ionum; + sx86_ubyte w16; + + w16 = (opcode&1); + ionum = softx86_fetch_dec_byte(ctx); // get imm8 + + sprintf(buf,"IN %s,%02Xh",w16 ? "AX" : "AL",ionum); + return 1; + } + else if ((opcode&0xFE) == 0xEC) { // IN AL/AX,DX + sx86_ubyte w16; + + w16 = (opcode&1); + sprintf(buf,"IN %s,DX",w16 ? "AX" : "AL"); + return 1; + } + else if ((opcode&0xFE) == 0xE6) { // OUT AL/AX,imm8 + sx86_ubyte ionum; + sx86_ubyte w16; + + w16 = (opcode&1); + ionum = softx86_fetch_dec_byte(ctx); // get imm8 + + sprintf(buf,"OUT %02Xh,%s",ionum,w16 ? "AX" : "AL"); + return 1; + } + else if ((opcode&0xFE) == 0xEE) { // OUT AL/AX,DX + sx86_ubyte w16; + + w16 = (opcode&1); + sprintf(buf,"OUT DX,%s",w16 ? "AX" : "AL"); + return 1; + } + + return 0; +} Index: lib/3rdparty/softx86/softx86/ioport.c =================================================================== --- lib/3rdparty/softx86/softx86/ioport.c (révision 59666) +++ lib/3rdparty/softx86/softx86/ioport.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/ioport.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/ioport.h =================================================================== --- lib/3rdparty/softx86/softx86/ioport.h (révision 0) +++ lib/3rdparty/softx86/softx86/ioport.h (copie de travail) @@ -0,0 +1,3 @@ + +int Sfx86OpcodeExec_io(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_io(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); Index: lib/3rdparty/softx86/softx86/ioport.h =================================================================== --- lib/3rdparty/softx86/softx86/ioport.h (révision 59666) +++ lib/3rdparty/softx86/softx86/ioport.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/ioport.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/jumpy.c =================================================================== --- lib/3rdparty/softx86/softx86/jumpy.c (révision 0) +++ lib/3rdparty/softx86/softx86/jumpy.c (copie de travail) @@ -0,0 +1,358 @@ +/* + * jumpy.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for CALL/J instructions. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "jumpy.h" + +int Sfx86OpcodeExec_jc(sx86_ubyte opcode,softx86_ctx* ctx) +{ + int tf; + sx86_udword rel; + +/* Intel's tendancy to sort the instructions in their documentation alphabetically + by name instead of by opcode tends to distort the fact that all of these + opcodes (except for JCXZ) lie between 0x70 and 0x7F. */ + if (!(opcode == 0xE3 || ((opcode&0xF0) == 0x70))) return 0; + + rel = (sx86_udword)softx86_fetch_exec_byte(ctx); + if (rel & 0x80) rel |= 0xFFFFFF00; + rel += ctx->state->reg_ip; + rel &= 0xFFFF; + +/* JCXZ */ + if (opcode == 0xE3) + tf = (ctx->state->general_reg[SX86_REG_CX].w.lo == 0); +/* JO */ + else if (opcode == 0x70) + tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW); +/* JNO */ + else if (opcode == 0x71) + tf = !(ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW); +/* JC */ + else if (opcode == 0x72) + tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY); +/* JNC */ + else if (opcode == 0x73) + tf = !(ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY); +/* JZ */ + else if (opcode == 0x74) + tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO); +/* JNZ */ + else if (opcode == 0x75) + tf = !(ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO); +/* JBE */ + else if (opcode == 0x76) + tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO) || + (ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY); +/* JA */ + else if (opcode == 0x77) + tf = (!(ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO)) && + (!(ctx->state->reg_flags.val & SX86_CPUFLAG_CARRY)); +/* JS */ + else if (opcode == 0x78) + tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN); +/* JNS */ + else if (opcode == 0x79) + tf = !(ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN); +/* JP */ + else if (opcode == 0x7A) + tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_PARITY); +/* JNP */ + else if (opcode == 0x7B) + tf = !(ctx->state->reg_flags.val & SX86_CPUFLAG_PARITY); +/* JL */ + else if (opcode == 0x7C) + tf = (((ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN) ? 1 : 0) != + ((ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW) ? 1 : 0)); +/* JGE */ + else if (opcode == 0x7D) + tf = ((ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN) ? 1 : 0) == + ((ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW) ? 1 : 0); +/* JLE */ + else if (opcode == 0x7E) + tf = (((ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN) ? 1 : 0) != + ((ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW) ? 1 : 0) || + (ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO)); +/* JG */ + else if (opcode == 0x7F) + tf = (((ctx->state->reg_flags.val & SX86_CPUFLAG_SIGN) ? 1 : 0) == + ((ctx->state->reg_flags.val & SX86_CPUFLAG_OVERFLOW) ? 1 : 0) && + (!(ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO))); +/* should NOT be here !*/ + else + return 0; + +/* if condition met, go! */ + if (tf) + softx86_set_instruction_ptr(ctx,ctx->state->segment_reg[SX86_SREG_CS].val,rel); + + return 1; +} + +int Sfx86OpcodeDec_jc(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + sx86_udword rel; + +/* Intel's tendancy to sort the instructions in their documentation alphabetically + by name instead of by opcode tends to distort the fact that all of these + opcodes (except for JCXZ) lie between 0x70 and 0x7F. */ + if (!(opcode == 0xE3 || ((opcode&0xF0) == 0x70))) return 0; + + rel = (sx86_udword)softx86_fetch_dec_byte(ctx); + if (rel & 0x80) rel |= 0xFFFFFF00; + rel += ctx->state->reg_ip_decompiler; + rel &= 0xFFFF; + + if (opcode == 0xE3) + sprintf(buf,"JCXZ %04Xh",rel); + else if (opcode == 0x70) + sprintf(buf,"JO %04Xh",rel); + else if (opcode == 0x71) + sprintf(buf,"JNO %04Xh",rel); + else if (opcode == 0x72) + sprintf(buf,"JC %04Xh",rel); + else if (opcode == 0x73) + sprintf(buf,"JNC %04Xh",rel); + else if (opcode == 0x74) + sprintf(buf,"JZ %04Xh",rel); + else if (opcode == 0x75) + sprintf(buf,"JNZ %04Xh",rel); + else if (opcode == 0x76) + sprintf(buf,"JBE %04Xh",rel); + else if (opcode == 0x77) + sprintf(buf,"JA %04Xh",rel); + else if (opcode == 0x78) + sprintf(buf,"JS %04Xh",rel); + else if (opcode == 0x79) + sprintf(buf,"JNS %04Xh",rel); + else if (opcode == 0x7A) + sprintf(buf,"JP %04Xh",rel); + else if (opcode == 0x7B) + sprintf(buf,"JNP %04Xh",rel); + else if (opcode == 0x7C) + sprintf(buf,"JL %04Xh",rel); + else if (opcode == 0x7D) + sprintf(buf,"JGE %04Xh",rel); + else if (opcode == 0x7E) + sprintf(buf,"JLE %04Xh",rel); + else if (opcode == 0x7F) + sprintf(buf,"JG %04Xh",rel); +/* should NOT be here !*/ + else + return 0; + + return 1; +} + +int Sfx86OpcodeExec_call(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0x9A) { // CALL FAR seg:offs + sx86_uword seg,ofs; + + ofs = (sx86_uword)softx86_fetch_exec_byte(ctx); + ofs |= ((sx86_uword)softx86_fetch_exec_byte(ctx))<<8; + seg = (sx86_uword)softx86_fetch_exec_byte(ctx); + seg |= ((sx86_uword)softx86_fetch_exec_byte(ctx))<<8; + softx86_stack_pushw(ctx,ctx->state->segment_reg[SX86_SREG_CS].val); + softx86_stack_pushw(ctx,ctx->state->reg_ip); + softx86_set_instruction_ptr(ctx,seg,ofs); + return 1; + } + else if (opcode == 0xE8) { // CALL rel16 + int ofs; + + ofs = (int)softx86_fetch_exec_byte(ctx); + ofs |= ((int)softx86_fetch_exec_byte(ctx))<<8; + if (ofs & 0x8000) ofs -= 0x10000; + ofs += ctx->state->reg_ip; + ofs &= 0xFFFF; + softx86_stack_pushw(ctx,ctx->state->reg_ip); + softx86_set_near_instruction_ptr(ctx,(sx86_udword)ofs); + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_call(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0x9A) { // CALL FAR seg:offs + sx86_uword seg,ofs; + + ofs = (sx86_uword)softx86_fetch_dec_byte(ctx); + ofs |= ((sx86_uword)softx86_fetch_dec_byte(ctx))<<8; + seg = (sx86_uword)softx86_fetch_dec_byte(ctx); + seg |= ((sx86_uword)softx86_fetch_dec_byte(ctx))<<8; + sprintf(buf,"CALL FAR %04X:%04X",seg,ofs); + return 1; + } + else if (opcode == 0xE8) { // CALL rel16 + int ofs; + + ofs = (int)softx86_fetch_dec_byte(ctx); + ofs |= ((int)softx86_fetch_dec_byte(ctx))<<8; + if (ofs & 0x8000) ofs -= 0x10000; + ofs += ctx->state->reg_ip_decompiler; + ofs &= 0xFFFF; + sprintf(buf,"CALL %04X",ofs); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_jmp(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0xE9) { // JMP rel16 + int ofs; + + ofs = (int)softx86_fetch_exec_byte(ctx); + ofs |= ((int)softx86_fetch_exec_byte(ctx))<<8; + if (ofs & 0x8000) ofs -= 0x10000; + ofs += ctx->state->reg_ip; + ofs &= 0xFFFF; + softx86_set_near_instruction_ptr(ctx,(sx86_udword)ofs); + return 1; + } + else if (opcode == 0xEA) { // JMP FAR seg:offs + sx86_uword seg,ofs; + + ofs = (sx86_uword)softx86_fetch_exec_byte(ctx); + ofs |= ((sx86_uword)softx86_fetch_exec_byte(ctx))<<8; + seg = (sx86_uword)softx86_fetch_exec_byte(ctx); + seg |= ((sx86_uword)softx86_fetch_exec_byte(ctx))<<8; + softx86_set_instruction_ptr(ctx,seg,ofs); + return 1; + } + else if (opcode == 0xEB) { // JMP rel8 + int ofs; + + ofs = (int)softx86_fetch_exec_byte(ctx); + if (ofs & 0x80) ofs -= 0x100; + ofs += ctx->state->reg_ip; + ofs &= 0xFFFF; + softx86_set_near_instruction_ptr(ctx,(sx86_udword)ofs); + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_jmp(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0xE9) { // JMP rel16 + int ofs; + + ofs = (int)softx86_fetch_dec_byte(ctx); + ofs |= ((int)softx86_fetch_dec_byte(ctx))<<8; + if (ofs & 0x8000) ofs -= 0x10000; + ofs += ctx->state->reg_ip_decompiler; + ofs &= 0xFFFF; + sprintf(buf,"JMP %04X",ofs); + return 1; + } + else if (opcode == 0xEA) { // JMP FAR seg:offs + sx86_uword seg,ofs; + + ofs = (sx86_uword)softx86_fetch_dec_byte(ctx); + ofs |= ((sx86_uword)softx86_fetch_dec_byte(ctx))<<8; + seg = (sx86_uword)softx86_fetch_dec_byte(ctx); + seg |= ((sx86_uword)softx86_fetch_dec_byte(ctx))<<8; + sprintf(buf,"JMP FAR %04X:%04X",seg,ofs); + return 1; + } + else if (opcode == 0xEB) { // JMP rel8 + int ofs; + + ofs = (int)softx86_fetch_dec_byte(ctx); + if (ofs & 0x80) ofs -= 0x100; + ofs += ctx->state->reg_ip_decompiler; + ofs &= 0xFFFF; + sprintf(buf,"JMP %04X",ofs); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_loop(sx86_ubyte opcode,softx86_ctx* ctx) +{ + int tf; + sx86_udword rel; + + if (opcode < 0xE0 || opcode > 0xE2) return 0; + rel = (sx86_udword)softx86_fetch_exec_byte(ctx); + if (rel & 0x80) rel |= 0xFFFFFF00; + rel += ctx->state->reg_ip; + rel &= 0xFFFF; + + ctx->state->general_reg[SX86_REG_CX].w.lo--; + +/* LOOP */ + if (opcode == 0xE2) + tf = (ctx->state->general_reg[SX86_REG_CX].w.lo != 0); +/* LOOPZ */ + else if (opcode == 0xE1) + tf = (ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO) && + (ctx->state->general_reg[SX86_REG_CX].w.lo != 0); +/* LOOPNZ */ + else if (opcode == 0xE0) + tf = ((ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO) == 0) && + (ctx->state->general_reg[SX86_REG_CX].w.lo != 0); +/* should NOT be here !*/ + else + return 0; + +/* if condition met, go! */ + if (tf) + softx86_set_instruction_ptr(ctx,ctx->state->segment_reg[SX86_SREG_CS].val,rel); + + return 1; +} + +int Sfx86OpcodeDec_loop(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + sx86_udword rel; + + rel = (sx86_udword)softx86_fetch_dec_byte(ctx); + if (rel & 0x80) rel |= 0xFFFFFF00; + rel += ctx->state->reg_ip_decompiler; + rel &= 0xFFFF; + + if (opcode == 0xE2) + sprintf(buf,"LOOP %04Xh",rel); + else if (opcode == 0xE1) + sprintf(buf,"LOOPZ %04Xh",rel); + else if (opcode == 0xE0) + sprintf(buf,"LOOPNZ %04Xh",rel); +/* should NOT be here !*/ + else + return 0; + + return 1; +} + Index: lib/3rdparty/softx86/softx86/jumpy.c =================================================================== --- lib/3rdparty/softx86/softx86/jumpy.c (révision 59666) +++ lib/3rdparty/softx86/softx86/jumpy.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/jumpy.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/jumpy.h =================================================================== --- lib/3rdparty/softx86/softx86/jumpy.h (révision 0) +++ lib/3rdparty/softx86/softx86/jumpy.h (copie de travail) @@ -0,0 +1,9 @@ + +int Sfx86OpcodeExec_jc(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_jc(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_call(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_call(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_jmp(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_jmp(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_loop(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_loop(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); Index: lib/3rdparty/softx86/softx86/jumpy.h =================================================================== --- lib/3rdparty/softx86/softx86/jumpy.h (révision 59666) +++ lib/3rdparty/softx86/softx86/jumpy.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/jumpy.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/Makefile =================================================================== --- lib/3rdparty/softx86/softx86/Makefile (révision 0) +++ lib/3rdparty/softx86/softx86/Makefile (copie de travail) @@ -0,0 +1,93 @@ +# SOFTX86 Makefile for Linux/GCC 3.xx +# (C) 2003 Jonathan Campbell +# +# NOTE: Assumes subdirectory ./obj/ and places all object files there +# rather than mix them up with the source code. It's less messy +# that way. The only exception is the final output, softx86.o. + +all:: __obj ../lib/libsoftx86.a ../lib/libsoftx86.so + +ALL_OBJS = obj/aaa.o obj/add.o obj/cbw.o obj/clc.o obj/drooling_duh.o obj/optable.o obj/prefixes.o obj/procframe.o obj/pushpop.o obj/softx86.o obj/mov.o obj/ioport.o obj/inc.o obj/groupies.o obj/interrupts.o obj/binops.o obj/jumpy.o obj/shovel.o obj/fpu.o + +INCLUDZ = -I../include + +clean:: + rm -f $(ALL_OBJS) + +distclean:: clean + rm -f ../lib/libsoftx86.a + rm -f ../lib/libsoftx86.so + if [[ -d obj ]]; then rmdir obj; fi + if [[ -d Release ]]; then rm -R Release; fi # clean up mess + if [[ -d Debug ]]; then rm -R Debug; fi # made by MSVC++ + rm -f *.plg + rm -f *.opt + rm -f *.aps + +# make sure there is an "obj" subdirectory +__obj: + if [[ !(-d obj) ]]; then mkdir obj; fi + +../lib/libsoftx86.a: $(ALL_OBJS) + ld -aarchive -r -o ../lib/libsoftx86.a $(ALL_OBJS) + +../lib/libsoftx86.so: $(ALL_OBJS) + ld -shared -o ../lib/libsoftx86.so $(ALL_OBJS) + +obj/shovel.o: shovel.c + gcc $(INCLUDZ) -c -o obj/shovel.o shovel.c + +obj/jumpy.o: jumpy.c + gcc $(INCLUDZ) -c -o obj/jumpy.o jumpy.c + +obj/binops.o: binops.c + gcc $(INCLUDZ) -c -o obj/binops.o binops.c + +obj/interrupts.o: interrupts.c + gcc $(INCLUDZ) -c -o obj/interrupts.o interrupts.c + +obj/groupies.o: groupies.c + gcc $(INCLUDZ) -c -o obj/groupies.o groupies.c + +obj/aaa.o: aaa.c + gcc $(INCLUDZ) -c -o obj/aaa.o aaa.c + +obj/add.o: add.c + gcc $(INCLUDZ) -c -o obj/add.o add.c + +obj/cbw.o: cbw.c + gcc $(INCLUDZ) -c -o obj/cbw.o cbw.c + +obj/clc.o: clc.c + gcc $(INCLUDZ) -c -o obj/clc.o clc.c + +obj/drooling_duh.o: drooling_duh.c + gcc $(INCLUDZ) -c -o obj/drooling_duh.o drooling_duh.c + +obj/optable.o: optable.c + gcc $(INCLUDZ) -c -o obj/optable.o optable.c + +obj/prefixes.o: prefixes.c + gcc $(INCLUDZ) -c -o obj/prefixes.o prefixes.c + +obj/procframe.o: procframe.c + gcc $(INCLUDZ) -c -o obj/procframe.o procframe.c + +obj/pushpop.o: pushpop.c + gcc $(INCLUDZ) -c -o obj/pushpop.o pushpop.c + +obj/softx86.o: softx86.c + gcc $(INCLUDZ) -c -o obj/softx86.o softx86.c + +obj/mov.o: mov.c + gcc $(INCLUDZ) -c -o obj/mov.o mov.c + +obj/ioport.o: ioport.c + gcc $(INCLUDZ) -c -o obj/ioport.o ioport.c + +obj/inc.o: inc.c + gcc $(INCLUDZ) -c -o obj/inc.o inc.c + +obj/fpu.o: fpu.c + gcc $(INCLUDZ) -c -o obj/fpu.o fpu.c + Index: lib/3rdparty/softx86/softx86/Makefile =================================================================== --- lib/3rdparty/softx86/softx86/Makefile (révision 59666) +++ lib/3rdparty/softx86/softx86/Makefile (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/mov.c =================================================================== --- lib/3rdparty/softx86/softx86/mov.c (révision 0) +++ lib/3rdparty/softx86/softx86/mov.c (copie de travail) @@ -0,0 +1,385 @@ +/* + * add.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for MOV and XLAT instructions. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "mov.h" + +sx86_ubyte op_mov8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val) +{ + return val; +} + +sx86_uword op_mov16(softx86_ctx* ctx,sx86_uword src,sx86_uword val) +{ + return val; +} + +sx86_udword op_mov32(softx86_ctx* ctx,sx86_udword src,sx86_udword val) +{ + return val; +} + +int Sfx86OpcodeExec_mov(sx86_ubyte opcode,softx86_ctx* ctx) +{ + sx86_udword lo; + sx86_uword seg; + + if (!ctx->state->is_segment_override) + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + + if ((opcode&0xFC) == 0x88) { // MOV reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // mov from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_rw(ctx,w16,0,mod,reg, + rm,opswap,op_mov8,op_mov16,op_mov32); + + return 1; + } + else if (opcode == 0x8C || opcode == 0x8E) { // MOV reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte opswap; + sx86_ubyte mod,reg,rm; + + opswap = (opcode&2)>>1; // mov from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modsregrm_rw(ctx,mod,reg,rm,opswap,op_mov16); + + return 1; + } + else if ((opcode&0xFE) == 0xA0) { // MOV AL/AX,[mem] + sx86_uword o; + + o = softx86_fetch_exec_byte(ctx); + o |= softx86_fetch_exec_byte(ctx)<<8; + lo = sx86_far_to_linear(ctx,seg,o); + + if (opcode&1) { + sx86_uword mem; + + softx86_fetch(ctx,NULL,lo,&mem,2); + SWAP_WORD_FROM_LE(mem); + ctx->state->general_reg[SX86_REG_AX].w.lo = mem; + } + else { + sx86_ubyte mem; + + softx86_fetch(ctx,NULL,lo,&mem,1); + ctx->state->general_reg[SX86_REG_AX].b.lo = mem; + } + + return 1; + } + else if ((opcode&0xFE) == 0xA2) { // MOV [mem],AL/AX + sx86_uword o; + + o = softx86_fetch_exec_byte(ctx); + o |= softx86_fetch_exec_byte(ctx)<<8; + lo = sx86_far_to_linear(ctx,seg,o); + + if (opcode&1) { + sx86_uword mem; + + mem = ctx->state->general_reg[SX86_REG_AX].w.lo; + SWAP_WORD_TO_LE(mem); + softx86_write(ctx,NULL,lo,&mem,2); + } + else { + sx86_ubyte mem; + + mem = ctx->state->general_reg[SX86_REG_AX].b.lo; + softx86_write(ctx,NULL,lo,&mem,1); + } + + return 1; + } + else if ((opcode&0xF8) == 0xB0) { // MOV [reg = (opcode-0xB0)],imm8 + sx86_ubyte b; + + b = softx86_fetch_exec_byte(ctx); + *(ctx->__private->ptr_regs_8reg[opcode-0xB0]) = b; + return 1; + } + else if ((opcode&0xF8) == 0xB8) { // MOV [reg = (opcode-0xB8)],imm16 + sx86_uword w; + + w = softx86_fetch_exec_byte(ctx); + w |= softx86_fetch_exec_byte(ctx)<<8; + ctx->state->general_reg[opcode-0xB8].w.lo = w; + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_mov(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if ((opcode&0xFC) == 0x88) { // MOV reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte w16,opswap; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + opswap = (opcode&2)>>1; // mov from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,w16,0,mod,reg,rm,op1_tmp,op2_tmp); + + if (opswap) sprintf(buf,"MOV %s,%s",op2_tmp,op1_tmp); + else sprintf(buf,"MOV %s,%s",op1_tmp,op2_tmp); + return 1; + } + else if (opcode == 0x8C || opcode == 0x8E) { // MOV reg,reg/mem or reg/mem,reg + sx86_ubyte x; + sx86_ubyte opswap; + sx86_ubyte mod,reg,rm; + + opswap = (opcode&2)>>1; // mov from reg to r/m UNLESS this bit it set (then it's the other way around) + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modsregrm(ctx,mod,reg,rm,op1_tmp,op2_tmp); + + if (opswap) sprintf(buf,"MOV %s,%s",op2_tmp,op1_tmp); + else sprintf(buf,"MOV %s,%s",op1_tmp,op2_tmp); + return 1; + } + else if ((opcode&0xFE) == 0xA0) { // MOV AL/AX,[mem] + sx86_uword o; + + o = softx86_fetch_dec_byte(ctx); + o |= softx86_fetch_dec_byte(ctx)<<8; + sprintf(buf,"MOV %s,[%04Xh]",opcode == 0xA1 ? "AX" : "AL",o); + return 1; + } + else if ((opcode&0xFE) == 0xA2) { // MOV [mem],AL/AX + sx86_uword o; + + o = softx86_fetch_dec_byte(ctx); + o |= softx86_fetch_dec_byte(ctx)<<8; + sprintf(buf,"MOV [%04Xh],%s",o,opcode == 0xA3 ? "AX" : "AL"); + return 1; + } + else if ((opcode&0xF8) == 0xB0) { // MOV [reg = (opcode-0xB0)],imm8 + sx86_ubyte b; + + b = softx86_fetch_dec_byte(ctx); + sprintf(buf,"MOV %s,%02Xh",sx86_regs8[opcode-0xB0],b); + return 1; + } + else if ((opcode&0xF8) == 0xB8) { // MOV [reg = (opcode-0xB8)],imm16 + sx86_uword w; + + w = softx86_fetch_dec_byte(ctx); + w |= softx86_fetch_dec_byte(ctx)<<8; + sprintf(buf,"MOV %s,%04Xh",sx86_regs16[opcode-0xB8],w); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_xlat(sx86_ubyte opcode,softx86_ctx* ctx) +{ + sx86_uword seg; + + if (!ctx->state->is_segment_override) + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + + if (opcode == 0xD7) { // MOV reg,reg/mem or reg/mem,reg + sx86_ubyte d; + sx86_udword ofs; + + ofs = (sx86_udword)(ctx->state->general_reg[SX86_REG_BX].w.lo); + ofs += (sx86_udword)(ctx->state->general_reg[SX86_REG_AX].b.lo); + ofs &= 0xFFFF; + ofs = sx86_far_to_linear(ctx,seg,ofs); + + softx86_fetch(ctx,NULL,ofs,&d,1); + ctx->state->general_reg[SX86_REG_AX].b.lo = d; + + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_xlat(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0xD7) { // XLAT + strcpy(buf,"XLAT"); + return 1; + } + + return 0; +} + +sx86_uword op_les16(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs) +{ + softx86_setsegval(ctx,SX86_SREG_ES,seg); + return ofs; +} + +sx86_udword op_les32(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs) +{ + softx86_setsegval(ctx,SX86_SREG_ES,seg); + return ofs; +} + +sx86_uword op_lds16(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs) +{ + softx86_setsegval(ctx,SX86_SREG_DS,seg); + return ofs; +} + +sx86_udword op_lds32(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs) +{ + softx86_setsegval(ctx,SX86_SREG_DS,seg); + return ofs; +} + +int Sfx86OpcodeExec_les(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0xC4) { // LES + sx86_ubyte x; + sx86_ubyte mod,reg,rm; + + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_far(ctx,0,mod,reg,rm,op_les16,op_les32); + return 1; + } + if (opcode == 0xC5) { // LDS + sx86_ubyte x; + sx86_ubyte mod,reg,rm; + + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_exec_full_modregrm_far(ctx,0,mod,reg,rm,op_lds16,op_lds32); + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_les(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0xC4) { // LES + sx86_ubyte x; + sx86_ubyte mod,reg,rm; + + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,1,0,mod,reg,rm,op1_tmp,op2_tmp); + sprintf(buf,"LES %s,%s",op2_tmp,op1_tmp); + return 1; + } + if (opcode == 0xC5) { // LDS + sx86_ubyte x; + sx86_ubyte mod,reg,rm; + + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modregrm(ctx,1,0,mod,reg,rm,op1_tmp,op2_tmp); + sprintf(buf,"LDS %s,%s",op2_tmp,op1_tmp); + return 1; + } + + return 0; +} + +sx86_uword op_lmsw16(softx86_ctx* ctx,sx86_uword src) +{ +/* bit 0 can only be set, not reset (80286 method of PM) */ + ctx->state->reg_cr0 |= (src & SX86_CR0FLAG_PE); +/* bits 1-3 are only used here */ + ctx->state->reg_cr0 &= ~SX86_CR0_LMSW_MASK; + ctx->state->reg_cr0 |= (src & SX86_CR0_LMSW_MASK); +/* the return value doesn't matter */ + return 0; +} + +sx86_uword op_smsw16(softx86_ctx* ctx,sx86_uword src) +{ + return ((sx86_uword)ctx->state->reg_cr0); +} + +int Sfx86OpcodeExec_lmsw286(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0x01) { // LMSW [reg] + sx86_ubyte x; + sx86_ubyte mod,reg,rm; + + x = softx86_fetch_exec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + + if (reg == 4) + sx86_exec_full_modrmonly_rw(ctx,1,0,mod,rm,NULL,op_smsw16,NULL); + else if (reg == 6) + sx86_exec_full_modrmonly_ro(ctx,1,0,mod,rm,NULL,op_lmsw16,NULL); + else + return 0; + + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_lmsw286(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0x01) { // LMSW [reg] + sx86_ubyte x; + sx86_ubyte w16; + sx86_ubyte mod,reg,rm; + + w16 = (opcode&1); + x = softx86_fetch_dec_byte(ctx); // fetch mod/reg/rm + sx86_modregrm_unpack(x,mod,reg,rm); + sx86_dec_full_modrmonly(ctx,w16,0,mod,rm,op1_tmp); + + if (reg == 4) + sprintf(buf,"SMSW %s",op1_tmp); + else if (reg == 6) + sprintf(buf,"LMSW %s",op1_tmp); + else + return 0; + + return 1; + } + + return 0; +} Index: lib/3rdparty/softx86/softx86/mov.c =================================================================== --- lib/3rdparty/softx86/softx86/mov.c (révision 59666) +++ lib/3rdparty/softx86/softx86/mov.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/mov.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/mov.h =================================================================== --- lib/3rdparty/softx86/softx86/mov.h (révision 0) +++ lib/3rdparty/softx86/softx86/mov.h (copie de travail) @@ -0,0 +1,14 @@ + +int Sfx86OpcodeExec_mov(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_mov(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_xlat(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_xlat(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_les(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_les(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); + +int Sfx86OpcodeExec_lmsw286(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_lmsw286(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); + +sx86_ubyte op_mov8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_mov16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); +sx86_udword op_mov32(softx86_ctx* ctx,sx86_udword src,sx86_udword val); Index: lib/3rdparty/softx86/softx86/mov.h =================================================================== --- lib/3rdparty/softx86/softx86/mov.h (révision 59666) +++ lib/3rdparty/softx86/softx86/mov.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/mov.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/optable.c =================================================================== --- lib/3rdparty/softx86/softx86/optable.c (révision 0) +++ lib/3rdparty/softx86/softx86/optable.c (copie de travail) @@ -0,0 +1,683 @@ +/* + * optable.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Opcode jumptable. + * + * Allows the recognition of many opcodes without having to write approximately + * 500+ if...then...else statements which is a) inefficient and b) apparently can + * cause some compilers such as Microsoft C++ to crash during the compile stage with + * an error. Since it's a table, it can be referred to via a pointer that can be easily + * redirected to other opcode tables (i.e., one for the 8086, one for the 80286, etc.) + * without much hassle. + * + * The table contains two pointers: one for an "execute" function, and one for a + * "decompile" function. The execute function is given the context and the initial opcode. + * If more opcodes are needed the function calls softx86_fetch_exec_byte(). The decode + * function is also given the opcode but also a char[] array where it is expected to + * sprintf() or strcpy() the disassembled output. If that function needs more opcodes + * it calls softx86_fetch_dec_byte(). + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "pushpop.h" +#include "procframe.h" +#include "aaa.h" +#include "add.h" +#include "cbw.h" +#include "clc.h" +#include "drooling_duh.h" +#include "groupies.h" +#include "interrupts.h" +#include "ioport.h" +#include "inc.h" +#include "fpu.h" +#include "mov.h" +#include "prefixes.h" +#include "binops.h" +#include "jumpy.h" +#include "shovel.h" + +/* temporary buffers for decoding instruction parameters */ +char op1_tmp[32]; +char op2_tmp[32]; + +char *sx86_regs8[8] = { + "AL","CL","DL","BL","AH","CH","DH","BH"}; +char *sx86_regs16[8] = { + "AX","CX","DX","BX","SP","BP","SI","DI"}; +char *sx86_regs32[8] = { + "EAX","ECX","EDX","EBX","ESP","EBP","ESI","EDI"}; +char *sx86_regsaddr16_16[8] = { + "BX+SI","BX+DI","BP+SI","BP+DI","SI","DI","BP","BX"}; +char *sx86_segregs[8] = { + "ES","CS","SS","DS","?4","?5","?6","?7"}; + +static int Sfx86OpcodeExec_default(sx86_ubyte opcode,softx86_ctx* ctx) +{ + return 0; +} + +static int Sfx86OpcodeDec_default(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + buf[0]=0; + + return 0; +} + +int Sfx86OpcodeExec_nop(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode != 0x90) return 0; + return 1; +} + +int Sfx86OpcodeDec_nop(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode != 0x90) return 0; + strcpy(buf,"NOP"); + return 1; +} + +Sfx86OpcodeTable optab8086 = { +{ + {Sfx86OpcodeExec_add, Sfx86OpcodeDec_add}, /* 0x00 */ + {Sfx86OpcodeExec_add, Sfx86OpcodeDec_add}, /* 0x01 */ + {Sfx86OpcodeExec_add, Sfx86OpcodeDec_add}, /* 0x02 */ + {Sfx86OpcodeExec_add, Sfx86OpcodeDec_add}, /* 0x03 */ + {Sfx86OpcodeExec_add, Sfx86OpcodeDec_add}, /* 0x04 */ + {Sfx86OpcodeExec_add, Sfx86OpcodeDec_add}, /* 0x05 */ + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x06 */ + {Sfx86OpcodeExec_pop, Sfx86OpcodeDec_pop}, /* 0x07 */ + + {Sfx86OpcodeExec_or, Sfx86OpcodeDec_or}, /* 0x08 */ + {Sfx86OpcodeExec_or, Sfx86OpcodeDec_or}, /* 0x09 */ + {Sfx86OpcodeExec_or, Sfx86OpcodeDec_or}, /* 0x0A */ + {Sfx86OpcodeExec_or, Sfx86OpcodeDec_or}, /* 0x0B */ + {Sfx86OpcodeExec_or, Sfx86OpcodeDec_or}, /* 0x0C */ + {Sfx86OpcodeExec_or, Sfx86OpcodeDec_or}, /* 0x0D */ + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x0E */ + {Sfx86OpcodeExec_pop, Sfx86OpcodeDec_pop}, /* 0x0F */ + + {Sfx86OpcodeExec_adc, Sfx86OpcodeDec_adc}, /* 0x10 */ + {Sfx86OpcodeExec_adc, Sfx86OpcodeDec_adc}, /* 0x11 */ + {Sfx86OpcodeExec_adc, Sfx86OpcodeDec_adc}, /* 0x12 */ + {Sfx86OpcodeExec_adc, Sfx86OpcodeDec_adc}, /* 0x13 */ + {Sfx86OpcodeExec_adc, Sfx86OpcodeDec_adc}, /* 0x14 */ + {Sfx86OpcodeExec_adc, Sfx86OpcodeDec_adc}, /* 0x15 */ + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x16 */ + {Sfx86OpcodeExec_pop, Sfx86OpcodeDec_pop}, /* 0x17 */ + + {Sfx86OpcodeExec_sbb, Sfx86OpcodeDec_sbb}, /* 0x18 */ + {Sfx86OpcodeExec_sbb, Sfx86OpcodeDec_sbb}, /* 0x19 */ + {Sfx86OpcodeExec_sbb, Sfx86OpcodeDec_sbb}, /* 0x1A */ + {Sfx86OpcodeExec_sbb, Sfx86OpcodeDec_sbb}, /* 0x1B */ + {Sfx86OpcodeExec_sbb, Sfx86OpcodeDec_sbb}, /* 0x1C */ + {Sfx86OpcodeExec_sbb, Sfx86OpcodeDec_sbb}, /* 0x1D */ + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x1E */ + {Sfx86OpcodeExec_pop, Sfx86OpcodeDec_pop}, /* 0x1F */ + + {Sfx86OpcodeExec_and, Sfx86OpcodeDec_and}, /* 0x20 */ + {Sfx86OpcodeExec_and, Sfx86OpcodeDec_and}, /* 0x21 */ + {Sfx86OpcodeExec_and, Sfx86OpcodeDec_and}, /* 0x22 */ + {Sfx86OpcodeExec_and, Sfx86OpcodeDec_and}, /* 0x23 */ + {Sfx86OpcodeExec_and, Sfx86OpcodeDec_and}, /* 0x24 */ + {Sfx86OpcodeExec_and, Sfx86OpcodeDec_and}, /* 0x25 */ + {Sfx86OpcodeExec_segover, Sfx86OpcodeDec_segover}, /* 0x26 */ + {Sfx86OpcodeExec_aaaseries, Sfx86OpcodeDec_aaaseries}, /* 0x27 */ + + {Sfx86OpcodeExec_sub, Sfx86OpcodeDec_sub}, /* 0x28 */ + {Sfx86OpcodeExec_sub, Sfx86OpcodeDec_sub}, /* 0x29 */ + {Sfx86OpcodeExec_sub, Sfx86OpcodeDec_sub}, /* 0x2A */ + {Sfx86OpcodeExec_sub, Sfx86OpcodeDec_sub}, /* 0x2B */ + {Sfx86OpcodeExec_sub, Sfx86OpcodeDec_sub}, /* 0x2C */ + {Sfx86OpcodeExec_sub, Sfx86OpcodeDec_sub}, /* 0x2D */ + {Sfx86OpcodeExec_segover, Sfx86OpcodeDec_segover}, /* 0x2E */ + {Sfx86OpcodeExec_aaaseries, Sfx86OpcodeDec_aaaseries}, /* 0x2F */ + + {Sfx86OpcodeExec_xor, Sfx86OpcodeDec_xor}, /* 0x30 */ + {Sfx86OpcodeExec_xor, Sfx86OpcodeDec_xor}, /* 0x31 */ + {Sfx86OpcodeExec_xor, Sfx86OpcodeDec_xor}, /* 0x32 */ + {Sfx86OpcodeExec_xor, Sfx86OpcodeDec_xor}, /* 0x33 */ + {Sfx86OpcodeExec_xor, Sfx86OpcodeDec_xor}, /* 0x34 */ + {Sfx86OpcodeExec_xor, Sfx86OpcodeDec_xor}, /* 0x35 */ + {Sfx86OpcodeExec_segover, Sfx86OpcodeDec_segover}, /* 0x36 */ + {Sfx86OpcodeExec_aaaseries, Sfx86OpcodeDec_aaaseries}, /* 0x37 */ + + {Sfx86OpcodeExec_cmp, Sfx86OpcodeDec_cmp}, /* 0x38 */ + {Sfx86OpcodeExec_cmp, Sfx86OpcodeDec_cmp}, /* 0x39 */ + {Sfx86OpcodeExec_cmp, Sfx86OpcodeDec_cmp}, /* 0x3A */ + {Sfx86OpcodeExec_cmp, Sfx86OpcodeDec_cmp}, /* 0x3B */ + {Sfx86OpcodeExec_cmp, Sfx86OpcodeDec_cmp}, /* 0x3C */ + {Sfx86OpcodeExec_cmp, Sfx86OpcodeDec_cmp}, /* 0x3D */ + {Sfx86OpcodeExec_segover, Sfx86OpcodeDec_segover}, /* 0x3E */ + {Sfx86OpcodeExec_aaaseries, Sfx86OpcodeDec_aaaseries}, /* 0x3F */ + + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x40 */ + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x41 */ + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x42 */ + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x43 */ + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x44 */ + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x45 */ + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x46 */ + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x47 */ + + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x48 */ + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x49 */ + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x4A */ + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x4B */ + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x4C */ + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x4D */ + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x4E */ + {Sfx86OpcodeExec_inc, Sfx86OpcodeDec_inc}, /* 0x4F */ + + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x50 */ + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x51 */ + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x52 */ + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x53 */ + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x54 */ + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x55 */ + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x56 */ + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x57 */ + + {Sfx86OpcodeExec_pop, Sfx86OpcodeDec_pop}, /* 0x58 */ + {Sfx86OpcodeExec_pop, Sfx86OpcodeDec_pop}, /* 0x59 */ + {Sfx86OpcodeExec_pop, Sfx86OpcodeDec_pop}, /* 0x5A */ + {Sfx86OpcodeExec_pop, Sfx86OpcodeDec_pop}, /* 0x5B */ + {Sfx86OpcodeExec_pop, Sfx86OpcodeDec_pop}, /* 0x5C */ + {Sfx86OpcodeExec_pop, Sfx86OpcodeDec_pop}, /* 0x5D */ + {Sfx86OpcodeExec_pop, Sfx86OpcodeDec_pop}, /* 0x5E */ + {Sfx86OpcodeExec_pop, Sfx86OpcodeDec_pop}, /* 0x5F */ + + {Sfx86OpcodeExec_pusha, Sfx86OpcodeDec_pusha}, /* 0x60 */ + {Sfx86OpcodeExec_popa, Sfx86OpcodeDec_popa}, /* 0x61 */ + {Sfx86OpcodeExec_bound, Sfx86OpcodeDec_bound}, /* 0x62 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x63 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x64 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x65 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x66 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x67 */ + + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x68 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x69 */ + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x6A */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x6B */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x6C */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x6D */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x6E */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x6F */ + + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x70 */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x71 */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x72 */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x73 */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x74 */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x75 */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x76 */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x77 */ + + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x78 */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x79 */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x7A */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x7B */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x7C */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x7D */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x7E */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0x7F */ + + {Sfx86OpcodeExec_group80, Sfx86OpcodeDec_group80}, /* 0x80 */ + {Sfx86OpcodeExec_group80, Sfx86OpcodeDec_group80}, /* 0x81 */ + {Sfx86OpcodeExec_group80, Sfx86OpcodeDec_group80}, /* 0x82 */ + {Sfx86OpcodeExec_group80, Sfx86OpcodeDec_group80}, /* 0x83 */ + {Sfx86OpcodeExec_test, Sfx86OpcodeDec_test}, /* 0x84 */ + {Sfx86OpcodeExec_test, Sfx86OpcodeDec_test}, /* 0x85 */ + {Sfx86OpcodeExec_xchg, Sfx86OpcodeDec_xchg}, /* 0x86 */ + {Sfx86OpcodeExec_xchg, Sfx86OpcodeDec_xchg}, /* 0x87 */ + + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0x88 */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0x89 */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0x8A */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0x8B */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0x8C */ + {Sfx86OpcodeExec_lea, Sfx86OpcodeDec_lea}, /* 0x8D */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0x8E */ + {Sfx86OpcodeExec_group8F, Sfx86OpcodeDec_group8F}, /* 0x8F */ + + {Sfx86OpcodeExec_nop, Sfx86OpcodeDec_nop}, /* 0x90 */ + {Sfx86OpcodeExec_xchg, Sfx86OpcodeDec_xchg}, /* 0x91 */ + {Sfx86OpcodeExec_xchg, Sfx86OpcodeDec_xchg}, /* 0x92 */ + {Sfx86OpcodeExec_xchg, Sfx86OpcodeDec_xchg}, /* 0x93 */ + {Sfx86OpcodeExec_xchg, Sfx86OpcodeDec_xchg}, /* 0x94 */ + {Sfx86OpcodeExec_xchg, Sfx86OpcodeDec_xchg}, /* 0x95 */ + {Sfx86OpcodeExec_xchg, Sfx86OpcodeDec_xchg}, /* 0x96 */ + {Sfx86OpcodeExec_xchg, Sfx86OpcodeDec_xchg}, /* 0x97 */ + + {Sfx86OpcodeExec_cxex, Sfx86OpcodeDec_cxex}, /* 0x98 */ + {Sfx86OpcodeExec_cxex, Sfx86OpcodeDec_cxex}, /* 0x99 */ + {Sfx86OpcodeExec_call, Sfx86OpcodeDec_call}, /* 0x9A */ + {Sfx86OpcodeExec_duhhh, Sfx86OpcodeDec_duhhh}, /* 0x9B */ + {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x9C */ + {Sfx86OpcodeExec_pop, Sfx86OpcodeDec_pop}, /* 0x9D */ + {Sfx86OpcodeExec_ahf, Sfx86OpcodeDec_ahf}, /* 0x9E */ + {Sfx86OpcodeExec_ahf, Sfx86OpcodeDec_ahf}, /* 0x9F */ + + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xA0 */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xA1 */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xA2 */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xA3 */ + {Sfx86OpcodeExec_shovel, Sfx86OpcodeDec_shovel}, /* 0xA4 */ + {Sfx86OpcodeExec_shovel, Sfx86OpcodeDec_shovel}, /* 0xA5 */ + {Sfx86OpcodeExec_shovel, Sfx86OpcodeDec_shovel}, /* 0xA6 */ + {Sfx86OpcodeExec_shovel, Sfx86OpcodeDec_shovel}, /* 0xA7 */ + + {Sfx86OpcodeExec_test, Sfx86OpcodeDec_test}, /* 0xA8 */ + {Sfx86OpcodeExec_test, Sfx86OpcodeDec_test}, /* 0xA9 */ + {Sfx86OpcodeExec_shovel, Sfx86OpcodeDec_shovel}, /* 0xAA */ + {Sfx86OpcodeExec_shovel, Sfx86OpcodeDec_shovel}, /* 0xAB */ + {Sfx86OpcodeExec_shovel, Sfx86OpcodeDec_shovel}, /* 0xAC */ + {Sfx86OpcodeExec_shovel, Sfx86OpcodeDec_shovel}, /* 0xAD */ + {Sfx86OpcodeExec_shovel, Sfx86OpcodeDec_shovel}, /* 0xAE */ + {Sfx86OpcodeExec_shovel, Sfx86OpcodeDec_shovel}, /* 0xAF */ + + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xB0 */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xB1 */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xB2 */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xB3 */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xB4 */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xB5 */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xB6 */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xB7 */ + + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xB8 */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xB9 */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xBA */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xBB */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xBC */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xBD */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xBE */ + {Sfx86OpcodeExec_mov, Sfx86OpcodeDec_mov}, /* 0xBF */ + + {Sfx86OpcodeExec_groupC0, Sfx86OpcodeDec_groupC0}, /* 0xC0 */ + {Sfx86OpcodeExec_groupC0, Sfx86OpcodeDec_groupC0}, /* 0xC1 */ + {Sfx86OpcodeExec_returns, Sfx86OpcodeDec_returns}, /* 0xC2 */ + {Sfx86OpcodeExec_returns, Sfx86OpcodeDec_returns}, /* 0xC3 */ + {Sfx86OpcodeExec_les, Sfx86OpcodeDec_les}, /* 0xC4 */ + {Sfx86OpcodeExec_les, Sfx86OpcodeDec_les}, /* 0xC5 */ + {Sfx86OpcodeExec_groupC6, Sfx86OpcodeDec_groupC6}, /* 0xC6 */ + {Sfx86OpcodeExec_groupC6, Sfx86OpcodeDec_groupC6}, /* 0xC7 */ + + {Sfx86OpcodeExec_enterleave, Sfx86OpcodeDec_enterleave}, /* 0xC8 */ + {Sfx86OpcodeExec_enterleave, Sfx86OpcodeDec_enterleave}, /* 0xC9 */ + {Sfx86OpcodeExec_returns, Sfx86OpcodeDec_returns}, /* 0xCA */ + {Sfx86OpcodeExec_returns, Sfx86OpcodeDec_returns}, /* 0xCB */ + {Sfx86OpcodeExec_int, Sfx86OpcodeDec_int}, /* 0xCC */ + {Sfx86OpcodeExec_int, Sfx86OpcodeDec_int}, /* 0xCD */ + {Sfx86OpcodeExec_int, Sfx86OpcodeDec_int}, /* 0xCE */ + {Sfx86OpcodeExec_returns, Sfx86OpcodeDec_returns}, /* 0xCF */ + + {Sfx86OpcodeExec_groupD0, Sfx86OpcodeDec_groupD0}, /* 0xD0 */ + {Sfx86OpcodeExec_groupD0, Sfx86OpcodeDec_groupD0}, /* 0xD1 */ + {Sfx86OpcodeExec_groupD0, Sfx86OpcodeDec_groupD0}, /* 0xD2 */ + {Sfx86OpcodeExec_groupD0, Sfx86OpcodeDec_groupD0}, /* 0xD3 */ + {Sfx86OpcodeExec_aaaseries, Sfx86OpcodeDec_aaaseries}, /* 0xD4 */ + {Sfx86OpcodeExec_aaaseries, Sfx86OpcodeDec_aaaseries}, /* 0xD5 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0xD6 */ + {Sfx86OpcodeExec_xlat, Sfx86OpcodeDec_xlat}, /* 0xD7 */ + + {Sfx86OpcodeExec_fpuhandoff, Sfx86OpcodeDec_fpuhandoff}, /* 0xD8 */ + {Sfx86OpcodeExec_fpuhandoff, Sfx86OpcodeDec_fpuhandoff}, /* 0xD9 */ + {Sfx86OpcodeExec_fpuhandoff, Sfx86OpcodeDec_fpuhandoff}, /* 0xDA */ + {Sfx86OpcodeExec_fpuhandoff, Sfx86OpcodeDec_fpuhandoff}, /* 0xDB */ + {Sfx86OpcodeExec_fpuhandoff, Sfx86OpcodeDec_fpuhandoff}, /* 0xDC */ + {Sfx86OpcodeExec_fpuhandoff, Sfx86OpcodeDec_fpuhandoff}, /* 0xDD */ + {Sfx86OpcodeExec_fpuhandoff, Sfx86OpcodeDec_fpuhandoff}, /* 0xDE */ + {Sfx86OpcodeExec_fpuhandoff, Sfx86OpcodeDec_fpuhandoff}, /* 0xDF */ + + {Sfx86OpcodeExec_loop, Sfx86OpcodeDec_loop}, /* 0xE0 */ + {Sfx86OpcodeExec_loop, Sfx86OpcodeDec_loop}, /* 0xE1 */ + {Sfx86OpcodeExec_loop, Sfx86OpcodeDec_loop}, /* 0xE2 */ + {Sfx86OpcodeExec_jc, Sfx86OpcodeDec_jc}, /* 0xE3 */ + {Sfx86OpcodeExec_io, Sfx86OpcodeDec_io}, /* 0xE4 */ + {Sfx86OpcodeExec_io, Sfx86OpcodeDec_io}, /* 0xE5 */ + {Sfx86OpcodeExec_io, Sfx86OpcodeDec_io}, /* 0xE6 */ + {Sfx86OpcodeExec_io, Sfx86OpcodeDec_io}, /* 0xE7 */ + + {Sfx86OpcodeExec_call, Sfx86OpcodeDec_call}, /* 0xE8 */ + {Sfx86OpcodeExec_jmp, Sfx86OpcodeDec_jmp}, /* 0xE9 */ + {Sfx86OpcodeExec_jmp, Sfx86OpcodeDec_jmp}, /* 0xEA */ + {Sfx86OpcodeExec_jmp, Sfx86OpcodeDec_jmp}, /* 0xEB */ + {Sfx86OpcodeExec_io, Sfx86OpcodeDec_io}, /* 0xEC */ + {Sfx86OpcodeExec_io, Sfx86OpcodeDec_io}, /* 0xED */ + {Sfx86OpcodeExec_io, Sfx86OpcodeDec_io}, /* 0xEE */ + {Sfx86OpcodeExec_io, Sfx86OpcodeDec_io}, /* 0xEF */ + + {Sfx86OpcodeExec_lock, Sfx86OpcodeDec_lock}, /* 0xF0 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0xF1 */ + {Sfx86OpcodeExec_repetition, Sfx86OpcodeDec_repetition}, /* 0xF2 */ + {Sfx86OpcodeExec_repetition, Sfx86OpcodeDec_repetition}, /* 0xF3 */ + {Sfx86OpcodeExec_duhhh, Sfx86OpcodeDec_duhhh}, /* 0xF4 */ + {Sfx86OpcodeExec_clx, Sfx86OpcodeDec_clx}, /* 0xF5 */ + {Sfx86OpcodeExec_groupF6, Sfx86OpcodeDec_groupF6}, /* 0xF6 */ + {Sfx86OpcodeExec_groupF6, Sfx86OpcodeDec_groupF6}, /* 0xF7 */ + + {Sfx86OpcodeExec_clx, Sfx86OpcodeDec_clx}, /* 0xF8 */ + {Sfx86OpcodeExec_clx, Sfx86OpcodeDec_clx}, /* 0xF9 */ + {Sfx86OpcodeExec_clx, Sfx86OpcodeDec_clx}, /* 0xFA */ + {Sfx86OpcodeExec_clx, Sfx86OpcodeDec_clx}, /* 0xFB */ + {Sfx86OpcodeExec_clx, Sfx86OpcodeDec_clx}, /* 0xFC */ + {Sfx86OpcodeExec_clx, Sfx86OpcodeDec_clx}, /* 0xFD */ + {Sfx86OpcodeExec_groupFE, Sfx86OpcodeDec_groupFE}, /* 0xFE */ + {Sfx86OpcodeExec_groupFE, Sfx86OpcodeDec_groupFE}, /* 0xFF */ +}, +}; + +Sfx86OpcodeTable optab8086_0Fh = { +{ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_lmsw286, Sfx86OpcodeDec_lmsw286}, /* 0x01 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x00 */ +}, +}; Index: lib/3rdparty/softx86/softx86/optable.c =================================================================== --- lib/3rdparty/softx86/softx86/optable.c (révision 59666) +++ lib/3rdparty/softx86/softx86/optable.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/optable.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/optable.h =================================================================== --- lib/3rdparty/softx86/softx86/optable.h (révision 0) +++ lib/3rdparty/softx86/softx86/optable.h (copie de travail) @@ -0,0 +1,28 @@ + +// return value: +// 0 = opcode not recognized +// 1 = opcode recognized, parsing complete +// 2 = opcode recognized, more parsing needed (i.e., prefix) +typedef int (*Sfx86OpcodeExec)(sx86_ubyte opcode,softx86_ctx* ctx); +typedef int (*Sfx86OpcodeDec)(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); + +typedef struct { + Sfx86OpcodeExec exec; + Sfx86OpcodeDec dec; +} Sfx86Opcode; + +typedef struct { + Sfx86Opcode table[256]; +} Sfx86OpcodeTable; + +extern Sfx86OpcodeTable optab8086; +extern Sfx86OpcodeTable optab8086_0Fh; + +extern char op1_tmp[32]; +extern char op2_tmp[32]; + +extern char* sx86_regs8[8]; +extern char* sx86_regs16[8]; +extern char* sx86_regs32[8]; +extern char* sx86_regsaddr16_16[8]; +extern char* sx86_segregs[8]; Index: lib/3rdparty/softx86/softx86/optable.h =================================================================== --- lib/3rdparty/softx86/softx86/optable.h (révision 59666) +++ lib/3rdparty/softx86/softx86/optable.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/optable.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/prefixes.c =================================================================== --- lib/3rdparty/softx86/softx86/prefixes.c (révision 0) +++ lib/3rdparty/softx86/softx86/prefixes.c (copie de travail) @@ -0,0 +1,130 @@ +/* + * prefixes.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for segment override prefixes. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "prefixes.h" + +int Sfx86OpcodeExec_segover(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0x26) { // ES: + ctx->state->is_segment_override = 1; + ctx->state->segment_override = ctx->state->segment_reg[SX86_SREG_ES].val; + return 2; + } + if (opcode == 0x2E) { // CS: + ctx->state->is_segment_override = 1; + ctx->state->segment_override = ctx->state->segment_reg[SX86_SREG_CS].val; + return 2; + } + if (opcode == 0x36) { // SS: + ctx->state->is_segment_override = 1; + ctx->state->segment_override = ctx->state->segment_reg[SX86_SREG_SS].val; + return 2; + } + if (opcode == 0x3E) { // DS: + ctx->state->is_segment_override = 1; + ctx->state->segment_override = ctx->state->segment_reg[SX86_SREG_DS].val; + return 2; + } + + return 0; +} + +int Sfx86OpcodeDec_segover(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0x26) { // ES: + strcpy(buf,"ES: "); + return 2; + } + if (opcode == 0x2E) { // CS: + strcpy(buf,"CS: "); + return 2; + } + if (opcode == 0x36) { // SS: + strcpy(buf,"SS: "); + return 2; + } + if (opcode == 0x3E) { // DS: + strcpy(buf,"DS: "); + return 2; + } + + return 0; +} + +int Sfx86OpcodeExec_repetition(sx86_ubyte opcode,softx86_ctx* ctx) +{ +// you can't have REP REP MOSVB... +// it's not like "ICE ICE BABY" + if (ctx->state->rep_flag > 0) + return 0; + + if (opcode == 0xF3) { // REP/REPZ + ctx->state->rep_flag=2; + return 2; + } + if (opcode == 0xF2) { // REPNZ + ctx->state->rep_flag=1; + return 2; + } + + return 0; +} + +int Sfx86OpcodeDec_repetition(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0xF3) { // REP/REPZ + strcpy(buf,"REP "); + return 2; + } + if (opcode == 0xF2) { // REPNZ + strcpy(buf,"REPNZ "); + return 2; + } + + return 0; +} + +int Sfx86OpcodeExec_lock(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0xF0) { // LOCK + /* TODO: Do something with this... */ + return 2; + } + + return 0; +} + +int Sfx86OpcodeDec_lock(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0xF0) { // LOCK + strcpy(buf,"LOCK "); + return 2; + } + + return 0; +} Index: lib/3rdparty/softx86/softx86/prefixes.c =================================================================== --- lib/3rdparty/softx86/softx86/prefixes.c (révision 59666) +++ lib/3rdparty/softx86/softx86/prefixes.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/prefixes.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/prefixes.h =================================================================== --- lib/3rdparty/softx86/softx86/prefixes.h (révision 0) +++ lib/3rdparty/softx86/softx86/prefixes.h (copie de travail) @@ -0,0 +1,7 @@ + +int Sfx86OpcodeExec_segover(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_segover(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_repetition(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_repetition(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_lock(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_lock(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); Index: lib/3rdparty/softx86/softx86/prefixes.h =================================================================== --- lib/3rdparty/softx86/softx86/prefixes.h (révision 59666) +++ lib/3rdparty/softx86/softx86/prefixes.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/prefixes.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/procframe.c =================================================================== --- lib/3rdparty/softx86/softx86/procframe.c (révision 0) +++ lib/3rdparty/softx86/softx86/procframe.c (copie de travail) @@ -0,0 +1,171 @@ +/* + * procframe.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for RET/RETF/IRET instructions. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "procframe.h" + +int Sfx86OpcodeExec_returns(sx86_ubyte opcode,softx86_ctx* ctx) +{ + sx86_uword seg,ofs,flg; + + if (opcode == 0xC2) { // RET (near) + pop n bytes + sx86_uword popeye; + + popeye = softx86_fetch_exec_byte(ctx); + popeye |= softx86_fetch_exec_byte(ctx)<<8; + + ofs = softx86_stack_popw(ctx); + softx86_set_near_instruction_ptr(ctx,ofs); + softx86_stack_discard_n(ctx,(int)popeye); + return 1; + } + if (opcode == 0xC3) { // RET (near) + ofs = softx86_stack_popw(ctx); + softx86_set_near_instruction_ptr(ctx,ofs); + return 1; + } + if (opcode == 0xCA) { // RETF (far) + pop n bytes + sx86_uword popeye; + + popeye = softx86_fetch_exec_byte(ctx); + popeye |= softx86_fetch_exec_byte(ctx)<<8; + + ofs = softx86_stack_popw(ctx); + seg = softx86_stack_popw(ctx); + softx86_set_instruction_ptr(ctx,seg,ofs); + softx86_stack_discard_n(ctx,(int)popeye); + return 1; + } + if (opcode == 0xCB) { // RETF (far) + ofs = softx86_stack_popw(ctx); + seg = softx86_stack_popw(ctx); + softx86_set_instruction_ptr(ctx,seg,ofs); + return 1; + } + if (opcode == 0xCF) { // IRET/IRETD + ofs = softx86_stack_popw(ctx); + seg = softx86_stack_popw(ctx); + flg = softx86_stack_popw(ctx); + softx86_set_instruction_ptr(ctx,seg,ofs); + ctx->state->reg_flags.val = flg; + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_returns(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0xC2) { // RET (near) + pop n bytes + sx86_uword popeye; + popeye = softx86_fetch_dec_byte(ctx); + popeye |= softx86_fetch_dec_byte(ctx)<<8; + sprintf(buf,"RET 0x%02X",popeye); + return 1; + } + if (opcode == 0xC3) { // RET (near) + strcpy(buf,"RET"); + return 1; + } + if (opcode == 0xCA) { // RETF (far) + pop n bytes + sx86_uword popeye; + popeye = softx86_fetch_dec_byte(ctx); + popeye |= softx86_fetch_dec_byte(ctx)<<8; + sprintf(buf,"RETF 0x%02X",popeye); + return 1; + } + if (opcode == 0xCB) { // RETF (far) + strcpy(buf,"RETF"); + return 1; + } + if (opcode == 0xCF) { // IRET/IRETD + strcpy(buf,"IRET"); + return 1; + } + + return 0; +} + +/* TODO: What revision of the 8086 did ENTER and LEAVE first appear? */ +int Sfx86OpcodeExec_enterleave(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0xC8 && ctx->__private->level >= SX86_CPULEVEL_8086) { // ENTER + sx86_uword Size; + sx86_uword FrameTemp; + sx86_ubyte NestingLevel; + int i; + + Size = softx86_fetch_exec_byte(ctx); + Size |= softx86_fetch_exec_byte(ctx)<<8; + NestingLevel = softx86_fetch_exec_byte(ctx) & 31; + + softx86_stack_pushw(ctx,ctx->state->general_reg[SX86_REG_BP].w.lo); + FrameTemp = ctx->state->general_reg[SX86_REG_SP].w.lo; + + if (NestingLevel > 0) { + for (i=1;i < NestingLevel;i++) { + ctx->state->general_reg[SX86_REG_BP].w.lo -= 2; + softx86_stack_pushw(ctx,ctx->state->general_reg[SX86_REG_BP].w.lo); + } + + softx86_stack_pushw(ctx,FrameTemp); + } + + ctx->state->general_reg[SX86_REG_BP].w.lo = FrameTemp; + softx86_set_stack_ptr(ctx,ctx->state->segment_reg[SX86_SREG_SS].val,ctx->state->general_reg[SX86_REG_BP].w.lo - Size); + + return 1; + } + if (opcode == 0xC9 && ctx->__private->level >= SX86_CPULEVEL_8086) { // LEAVE + softx86_set_stack_ptr(ctx,ctx->state->segment_reg[SX86_SREG_SS].val,ctx->state->general_reg[SX86_REG_BP].w.lo); + ctx->state->general_reg[SX86_REG_BP].w.lo = softx86_stack_popw(ctx); + + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_enterleave(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0xC8 && ctx->__private->level >= SX86_CPULEVEL_8086) { + sx86_uword popeye; + sx86_ubyte imm; + + popeye = softx86_fetch_dec_byte(ctx); + popeye |= softx86_fetch_dec_byte(ctx)<<8; + imm = softx86_fetch_dec_byte(ctx); + sprintf(buf,"ENTER 0x%04X,0x%02X",popeye,imm); + return 1; + } + if (opcode == 0xC9 && ctx->__private->level >= SX86_CPULEVEL_8086) { + strcpy(buf,"LEAVE"); + return 1; + } + + return 0; +} Index: lib/3rdparty/softx86/softx86/procframe.c =================================================================== --- lib/3rdparty/softx86/softx86/procframe.c (révision 59666) +++ lib/3rdparty/softx86/softx86/procframe.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/procframe.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/procframe.h =================================================================== --- lib/3rdparty/softx86/softx86/procframe.h (révision 0) +++ lib/3rdparty/softx86/softx86/procframe.h (copie de travail) @@ -0,0 +1,5 @@ + +int Sfx86OpcodeExec_returns(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_returns(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_enterleave(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_enterleave(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); Index: lib/3rdparty/softx86/softx86/procframe.h =================================================================== --- lib/3rdparty/softx86/softx86/procframe.h (révision 59666) +++ lib/3rdparty/softx86/softx86/procframe.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/procframe.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/pushpop.c =================================================================== --- lib/3rdparty/softx86/softx86/pushpop.c (révision 0) +++ lib/3rdparty/softx86/softx86/pushpop.c (copie de travail) @@ -0,0 +1,346 @@ +/* + * pushpop.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for PUSH/POP/PUSHF/POPF/SAHF/LAHF instructions. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "pushpop.h" + +int Sfx86OpcodeExec_pop(sx86_ubyte opcode,softx86_ctx* ctx) +{ + sx86_uword val; + + if (opcode >= 0x58 && opcode <= 0x5F) { // POP [reg] + val = softx86_stack_popw(ctx); + ctx->state->general_reg[opcode-0x58].w.lo = val; + return 1; + } + + if (opcode == 0x1F) { // POP DS + val = softx86_stack_popw(ctx); + softx86_setsegval(ctx,SX86_SREG_DS,val); + return 1; + } + + if (opcode == 0x07) { // POP ES + val = softx86_stack_popw(ctx); + softx86_setsegval(ctx,SX86_SREG_ES,val); + return 1; + } + + if (opcode == 0x17) { // POP SS + val = softx86_stack_popw(ctx); + softx86_setsegval(ctx,SX86_SREG_SS,val); + return 1; + } + + if (opcode == 0x0F) { // POP CS (8086/8088 only) + if (ctx->__private->level <= SX86_CPULEVEL_80186) { + val = softx86_stack_popw(ctx); + softx86_setsegval(ctx,SX86_SREG_CS,val); + } + else { + Sfx86OpcodeTable* sop; + sx86_ubyte op2; + + /* leap into the second-level opcode table */ + sop = (Sfx86OpcodeTable*)ctx->__private->opcode_table_sub_0Fh; + op2 = softx86_fetch_exec_byte(ctx); + return sop->table[op2].exec(op2,ctx); + } + + return 1; + } + + if (opcode == 0x9D) { // POPF + ctx->state->reg_flags.w.lo = softx86_stack_popw(ctx); + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_pop(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode >= 0x58 && opcode <= 0x5F) { // POP [reg] + sprintf(buf,"POP %s",sx86_regs16[opcode-0x58]); + return 1; + } + + if (opcode == 0x1F) { // POP DS + strcpy(buf,"POP DS"); + return 1; + } + + if (opcode == 0x07) { // POP ES + strcpy(buf,"POP ES"); + return 1; + } + + if (opcode == 0x17) { // POP SS + strcpy(buf,"POP SS"); + return 1; + } + + if (opcode == 0x0F) { // POP CS (8086/8088 only) + if (ctx->__private->level <= SX86_CPULEVEL_80186) { + strcpy(buf,"POP CS"); + return 1; + } + else { + Sfx86OpcodeTable* sop; + sx86_ubyte op2; + + /* leap into the second-level opcode table */ + sop = (Sfx86OpcodeTable*)ctx->__private->opcode_table_sub_0Fh; + op2 = softx86_fetch_dec_byte(ctx); + return sop->table[op2].dec(op2,ctx,buf); + } + } + + if (opcode == 0x9D) { // POPF + strcpy(buf,"POPF"); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_push(sx86_ubyte opcode,softx86_ctx* ctx) +{ + sx86_uword val; + + if (opcode >= 0x50 && opcode <= 0x57) { // PUSH [reg] + if (opcode == 0x54 && ctx->bugs->decrement_sp_before_store) // 0x54 = (E)SP + val = ctx->state->general_reg[opcode-0x50].w.lo - 2; + else + val = ctx->state->general_reg[opcode-0x50].w.lo; + + softx86_stack_pushw(ctx,val); + return 1; + } + + if (opcode == 0x1E) { // PUSH DS + softx86_stack_pushw(ctx,ctx->state->segment_reg[SX86_SREG_DS].val); + return 1; + } + + if (opcode == 0x06) { // PUSH ES + softx86_stack_pushw(ctx,ctx->state->segment_reg[SX86_SREG_ES].val); + return 1; + } + + if (opcode == 0x16) { // PUSH SS + softx86_stack_pushw(ctx,ctx->state->segment_reg[SX86_SREG_SS].val); + return 1; + } + + if (opcode == 0x0E) { // PUSH CS + softx86_stack_pushw(ctx,ctx->state->segment_reg[SX86_SREG_CS].val); + return 1; + } + + if (opcode == 0x9C) { // PUSHF + softx86_stack_pushw(ctx,ctx->state->reg_flags.w.lo); + return 1; + } + + if (opcode == 0x6A) // PUSH imm8 + { + sx86_ubyte b = softx86_fetch_exec_byte(ctx); + softx86_stack_pushw(ctx, (sx86_uword)b); + return 1; + } + + if (opcode == 0x68) // PUSH imm16 + { + sx86_uword w = softx86_fetch_exec_byte(ctx); + w |= softx86_fetch_exec_byte(ctx) << 8; + softx86_stack_pushw(ctx, w); + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_push(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode >= 0x50 && opcode <= 0x57) { // PUSH [reg] + sprintf(buf,"PUSH %s",sx86_regs16[opcode-0x50]); + return 1; + } + + if (opcode == 0x1E) { // PUSH DS + strcpy(buf,"PUSH DS"); + return 1; + } + + if (opcode == 0x06) { // PUSH ES + strcpy(buf,"PUSH ES"); + return 1; + } + + if (opcode == 0x16) { // PUSH SS + strcpy(buf,"PUSH SS"); + return 1; + } + + if (opcode == 0x0E) { // PUSH CS + strcpy(buf,"PUSH CS"); + return 1; + } + + if (opcode == 0x9C) { // PUSHF + strcpy(buf,"PUSHF"); + return 1; + } + + if (opcode == 0x6A && ctx->__private->level >= SX86_CPULEVEL_80186) // PUSH imm8 + { + sx86_ubyte b = softx86_fetch_exec_byte(ctx); + sprintf(buf, "PUSH %02Xh", b); + return 1; + } + + if (opcode == 0x68 && ctx->__private->level >= SX86_CPULEVEL_80186) // PUSH imm16 + { + sx86_uword w = softx86_fetch_exec_byte(ctx); + w |= softx86_fetch_exec_byte(ctx) << 8; + sprintf(buf, "PUSH %04Xh", w); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_ahf(sx86_ubyte opcode,softx86_ctx* ctx) +{ + if (opcode == 0x9E) { // SAHF + ctx->state->reg_flags.b.lo &= ~0xD5; + ctx->state->reg_flags.b.lo |= (ctx->state->general_reg[SX86_REG_AX].b.hi&0xD5); + return 1; + } + + if (opcode == 0x9F) { // LAHF + ctx->state->general_reg[SX86_REG_AX].b.hi = ctx->state->reg_flags.b.lo; + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_ahf(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0x9E) { // SAHF + strcpy(buf,"SAHF"); + return 1; + } + + if (opcode == 0x9F) { // LAHF + strcpy(buf,"LAHF"); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_pusha(sx86_ubyte opcode,softx86_ctx* ctx) +{ +/* TODO: When did PUSHA/POPA really appear in the x86 instruction set? + Does this originate as far back as the original 8086? + Documentation seems to be scarce about this... */ + if (opcode == 0x60 && ctx->__private->level >= SX86_CPULEVEL_80186) { // PUSHA/PUSHAD + sx86_uword temp_sp; + + temp_sp = ctx->state->general_reg[SX86_REG_SP].w.lo; + softx86_stack_pushw(ctx,ctx->state->general_reg[SX86_REG_AX].w.lo); + softx86_stack_pushw(ctx,ctx->state->general_reg[SX86_REG_CX].w.lo); + softx86_stack_pushw(ctx,ctx->state->general_reg[SX86_REG_DX].w.lo); + softx86_stack_pushw(ctx,ctx->state->general_reg[SX86_REG_BX].w.lo); + +/* emulate bug in PUSHA that exist in CPUs prior to 286 */ + if (ctx->bugs->decrement_sp_before_store) + softx86_stack_pushw(ctx,ctx->state->general_reg[SX86_REG_SP].w.lo); + else + softx86_stack_pushw(ctx,temp_sp); + + softx86_stack_pushw(ctx,ctx->state->general_reg[SX86_REG_BP].w.lo); + softx86_stack_pushw(ctx,ctx->state->general_reg[SX86_REG_SI].w.lo); + softx86_stack_pushw(ctx,ctx->state->general_reg[SX86_REG_DI].w.lo); + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_pusha(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ +/* TODO: When did PUSHA/POPA really appear in the x86 instruction set? + Does this originate as far back as the original 8086? + Documentation seems to be scarce about this... */ + if (opcode == 0x60 && ctx->__private->level >= SX86_CPULEVEL_80186) { // PUSHA/PUSHAD + strcpy(buf,"PUSHA"); + return 1; + } + + return 0; +} + +int Sfx86OpcodeExec_popa(sx86_ubyte opcode,softx86_ctx* ctx) +{ +/* TODO: When did PUSHA/POPA really appear in the x86 instruction set? + Does this originate as far back as the original 8086? + Documentation seems to be scarce about this... */ + if (opcode == 0x61 && ctx->__private->level >= SX86_CPULEVEL_80186) { // POPA/POPAD + ctx->state->general_reg[SX86_REG_DI].w.lo = softx86_stack_popw(ctx); + ctx->state->general_reg[SX86_REG_SI].w.lo = softx86_stack_popw(ctx); + ctx->state->general_reg[SX86_REG_BP].w.lo = softx86_stack_popw(ctx); +/* TODO: all versions prior to the 286 had bugs storing SP... + does that also mean they were stupid enough to + restore it? anybody know? */ + softx86_stack_popw(ctx); + ctx->state->general_reg[SX86_REG_BX].w.lo = softx86_stack_popw(ctx); + ctx->state->general_reg[SX86_REG_DX].w.lo = softx86_stack_popw(ctx); + ctx->state->general_reg[SX86_REG_CX].w.lo = softx86_stack_popw(ctx); + ctx->state->general_reg[SX86_REG_AX].w.lo = softx86_stack_popw(ctx); + return 1; + } + + return 0; +} + +int Sfx86OpcodeDec_popa(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ +/* TODO: When did PUSHA/POPA really appear in the x86 instruction set? + Does this originate as far back as the original 8086? + Documentation seems to be scarce about this... */ + if (opcode == 0x61 && ctx->__private->level >= SX86_CPULEVEL_80186) { // POPA/POPAD + strcpy(buf,"POPA"); + return 1; + } + + return 0; +} + Index: lib/3rdparty/softx86/softx86/pushpop.c =================================================================== --- lib/3rdparty/softx86/softx86/pushpop.c (révision 59666) +++ lib/3rdparty/softx86/softx86/pushpop.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/pushpop.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/pushpop.h =================================================================== --- lib/3rdparty/softx86/softx86/pushpop.h (révision 0) +++ lib/3rdparty/softx86/softx86/pushpop.h (copie de travail) @@ -0,0 +1,11 @@ + +int Sfx86OpcodeExec_push(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_push(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_pop(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_pop(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_ahf(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_ahf(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_pusha(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_pusha(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); +int Sfx86OpcodeExec_popa(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_popa(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); Index: lib/3rdparty/softx86/softx86/pushpop.h =================================================================== --- lib/3rdparty/softx86/softx86/pushpop.h (révision 59666) +++ lib/3rdparty/softx86/softx86/pushpop.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/pushpop.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/resource.h =================================================================== --- lib/3rdparty/softx86/softx86/resource.h (révision 0) +++ lib/3rdparty/softx86/softx86/resource.h (copie de travail) @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by softx86_dll.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif Index: lib/3rdparty/softx86/softx86/resource.h =================================================================== --- lib/3rdparty/softx86/softx86/resource.h (révision 59666) +++ lib/3rdparty/softx86/softx86/resource.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/resource.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/shovel.c =================================================================== --- lib/3rdparty/softx86/softx86/shovel.c (révision 0) +++ lib/3rdparty/softx86/softx86/shovel.c (copie de travail) @@ -0,0 +1,335 @@ +/* + * shovel.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Decompiler and executioneer for MOVS, LODS, CMPS, SCAS, and STOS. + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include "optable.h" +#include "shovel.h" + +/* references to add.c */ +sx86_ubyte op_sub8(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val); +sx86_uword op_sub16(softx86_ctx* ctx,sx86_uword src,sx86_uword val); + +int Sfx86OpcodeExec_shovel(sx86_ubyte opcode,softx86_ctx* ctx) +{ + int sz,ecx_terminal,zflag_terminal; + int inc_esi,inc_edi,sto_edi,get_edi,df; + sx86_udword si,di,addr; + sx86_ubyte tmp8; + sx86_uword tmp16; + sx86_ubyte tmp8dst; + sx86_uword tmp16dst; + sx86_uword seg; + + if ((opcode&0xFE) == 0xA4) { // MOVS + if (opcode&1) sz = 2; + else sz = 1; + inc_esi = 1; + inc_edi = 1; + sto_edi = 1; + get_edi = 0; + } + else if ((opcode&0xFE) == 0xA6) { // CMPS + if (opcode&1) sz = 2; + else sz = 1; + inc_esi = 1; + inc_edi = 1; + sto_edi = 0; + get_edi = 1; /* CMPS compares ds:si and es:di */ + } + else if ((opcode&0xFE) == 0xAA) { // STOS + if (opcode&1) sz = 2; + else sz = 1; + inc_esi = 0; + inc_edi = 1; + sto_edi = 1; + get_edi = 0; + } + else if ((opcode&0xFE) == 0xAC) { // LODS + if (opcode&1) sz = 2; + else sz = 1; + inc_esi = 1; + inc_edi = 0; + sto_edi = 0; + get_edi = 0; + } + else if ((opcode&0xFE) == 0xAE) { // SCAS + if (opcode&1) sz = 2; + else sz = 1; + inc_esi = 0; + inc_edi = 1; + sto_edi = 0; + get_edi = 1; + } + else { + return 0; + } + +/* TODO: If 32-bit address override get full 32 bits */ + si = (sx86_udword)ctx->state->general_reg[SX86_REG_SI].w.lo; + di = (sx86_udword)ctx->state->general_reg[SX86_REG_DI].w.lo; + +/* [E]CX == 0 is a terminal condition if REP was encountered */ +/* the ZF flag can also be a terminal condition, depending on the opcode */ + if (ctx->state->rep_flag > 0) { + /* TODO: If 32-bit override present, use ECX not CX */ + ecx_terminal = (ctx->state->general_reg[SX86_REG_CX].w.lo == 0); + +/* some instructions don't take the ZF flag into account */ + if ((opcode&0xFE) == 0xA4) /* MOVS */ + zflag_terminal = 0; + else if ((opcode&0xFE) == 0xAA) /* STOS */ + zflag_terminal = 0; + else if ((opcode&0xFE) == 0xAC) /* LODS */ + zflag_terminal = 0; + else + zflag_terminal = 0; + } + else { + ecx_terminal = 0; + zflag_terminal = 0; + } + +/* are we in a REP loop terminal condition? */ + if (ecx_terminal) return 1; + if (zflag_terminal) return 1; + +/* get direction flag */ + df = (ctx->state->reg_flags.val & SX86_CPUFLAG_DIRECTIONREV); + +/* fetch from src */ + if (inc_esi) { + if (ctx->state->is_segment_override) + seg = ctx->state->segment_override; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + + addr = sx86_far_to_linear(ctx,seg,si); + if (sz == 2) { + tmp16=0; + softx86_fetch(ctx,NULL,addr,&tmp16,2); + SWAP_WORD_FROM_LE(tmp16); + if (df) si -= 2; + else si += 2; + } + else if (sz == 1) { + tmp8=0; + softx86_fetch(ctx,NULL,addr,&tmp8,1); + if (df) si--; + else si++; + } + } + +/* MOVS? */ + if ((opcode&0xFE) == 0xA4) { + tmp16dst = tmp16; + tmp8dst = tmp8; + } +/* LODSB? */ + else if (opcode == 0xAC) { + ctx->state->general_reg[SX86_REG_AX].b.lo = tmp8; + } +/* LODSW? */ + else if (opcode == 0xAD) { +/* TODO: 32-bit data override means LODSD not LODSW */ + ctx->state->general_reg[SX86_REG_AX].w.lo = tmp16; + } +/* STOSB? */ + else if (opcode == 0xAA) { + tmp8dst = ctx->state->general_reg[SX86_REG_AX].b.lo; + } +/* STOSW? */ + else if (opcode == 0xAB) { +/* TODO: 32-bit data override means LODSD not LODSW */ + tmp16dst = ctx->state->general_reg[SX86_REG_AX].w.lo; + } + +/* place in dst */ + if (inc_edi) { + if (ctx->state->is_segment_override) + seg = ctx->state->segment_override; + else + seg = ctx->state->segment_reg[SX86_SREG_ES].val; + + addr = sx86_far_to_linear(ctx,seg,di); + if (get_edi) { + if (sz == 2) { + tmp16dst=0; + softx86_fetch(ctx,NULL,addr,&tmp16dst,2); + SWAP_WORD_FROM_LE(tmp16dst); + } + else if (sz == 1) { + tmp8dst=0; + softx86_fetch(ctx,NULL,addr,&tmp8dst,1); + } + } + else if (sto_edi) { + if (sz == 2) { + SWAP_WORD_TO_LE(tmp16dst); + softx86_write(ctx,NULL,addr,&tmp16dst,2); + } + else if (sz == 1) { + softx86_write(ctx,NULL,addr,&tmp8dst,1); + } + } + + if (df) { + if (sz == 2) + di -= 2; + else if (sz == 1) + di--; + } + else { + if (sz == 2) + di += 2; + else if (sz == 1) + di++; + } + } + +/* CMPSB? */ + if (opcode == 0xA6) { + /* functions like this: */ + /* tmp8 = ds:si */ + /* tmp8dst = es:di */ + /* cmp tmp8,tmp8dst */ + op_sub8(ctx,tmp8,tmp8dst); + +/* update terminal condition now that ZF changed */ + if (ctx->state->rep_flag == 1) + zflag_terminal = (ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO); + else if (ctx->state->rep_flag == 2) + zflag_terminal = !(ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO); + } +/* CMPSW? */ + else if (opcode == 0xA7) { + /* functions like this: */ + /* tmp16 = ds:si */ + /* tmp16dst = es:di */ + /* cmp tmp16,tmp16dst */ + op_sub16(ctx,tmp16,tmp16dst); + +/* update terminal condition now that ZF changed */ + if (ctx->state->rep_flag == 1) + zflag_terminal = (ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO); + else if (ctx->state->rep_flag == 2) + zflag_terminal = !(ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO); + } +/* SCASB? */ + else if (opcode == 0xAE) { + /* functions like this: */ + /* tmp8 = AL */ + /* tmp8dst = es:di */ + /* cmp tmp8,tmp8dst */ + op_sub8(ctx,ctx->state->general_reg[SX86_REG_AX].b.lo,tmp8dst); + +/* update terminal condition now that ZF changed */ + if (ctx->state->rep_flag == 1) + zflag_terminal = (ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO); + else if (ctx->state->rep_flag == 2) + zflag_terminal = !(ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO); + } +/* SCASW? */ + else if (opcode == 0xAF) { + /* functions like this: */ + /* tmp16 = AL */ + /* tmp16dst = es:di */ + /* cmp tmp16,tmp16dst */ + op_sub16(ctx,ctx->state->general_reg[SX86_REG_AX].w.lo,tmp16dst); + +/* update terminal condition now that ZF changed */ + if (ctx->state->rep_flag == 1) + zflag_terminal = (ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO); + else if (ctx->state->rep_flag == 2) + zflag_terminal = !(ctx->state->reg_flags.val & SX86_CPUFLAG_ZERO); + } + +/* TODO: If 32-bit address override store full 32 bits */ + ctx->state->general_reg[SX86_REG_SI].w.lo = (sx86_uword)si; + ctx->state->general_reg[SX86_REG_DI].w.lo = (sx86_uword)di; + +/* TODO: If 32-bit data override decrement full 32 bits */ + if (ctx->state->rep_flag > 0) + ctx->state->general_reg[SX86_REG_CX].w.lo--; /* decrement [E]CX */ + +/* keep the REP loop going */ + if (ctx->state->rep_flag > 0) { +/* why execute this instruction again when we KNOW that [E]CX == 0? */ + /* TODO: If 32-bit override present, use ECX not CX */ + ecx_terminal = (ctx->state->general_reg[SX86_REG_CX].w.lo == 0); + + if (ecx_terminal) return 1; + else if (zflag_terminal) return 1; + else return 3; + } + + return 1; +} + +int Sfx86OpcodeDec_shovel(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]) +{ + if (opcode == 0xA4) { // MOVSB + strcpy(buf,"MOVSB "); + return 1; + } + if (opcode == 0xA5) { // MOVSW + strcpy(buf,"MOVSW "); + return 1; + } + if (opcode == 0xA6) { // CMPSB + strcpy(buf,"CMPSB "); + return 1; + } + if (opcode == 0xA7) { // CMPSW + strcpy(buf,"CMPSW "); + return 1; + } + if (opcode == 0xAA) { // STOSB + strcpy(buf,"STOSB "); + return 1; + } + if (opcode == 0xAB) { // STOSW + strcpy(buf,"STOSW "); + return 1; + } + if (opcode == 0xAC) { // LODSB + strcpy(buf,"LODSB "); + return 1; + } + if (opcode == 0xAD) { // LODSW + strcpy(buf,"LODSW "); + return 1; + } + if (opcode == 0xAE) { // SCASB + strcpy(buf,"SCASB "); + return 1; + } + if (opcode == 0xAF) { // SCASW + strcpy(buf,"SCASW "); + return 1; + } + + return 0; +} Index: lib/3rdparty/softx86/softx86/shovel.c =================================================================== --- lib/3rdparty/softx86/softx86/shovel.c (révision 59666) +++ lib/3rdparty/softx86/softx86/shovel.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/shovel.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/shovel.h =================================================================== --- lib/3rdparty/softx86/softx86/shovel.h (révision 0) +++ lib/3rdparty/softx86/softx86/shovel.h (copie de travail) @@ -0,0 +1,3 @@ + +int Sfx86OpcodeExec_shovel(sx86_ubyte opcode,softx86_ctx* ctx); +int Sfx86OpcodeDec_shovel(sx86_ubyte opcode,softx86_ctx* ctx,char buf[128]); Index: lib/3rdparty/softx86/softx86/shovel.h =================================================================== --- lib/3rdparty/softx86/softx86/shovel.h (révision 59666) +++ lib/3rdparty/softx86/softx86/shovel.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/shovel.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/softx86.c =================================================================== --- lib/3rdparty/softx86/softx86/softx86.c (révision 0) +++ lib/3rdparty/softx86/softx86/softx86.c (copie de travail) @@ -0,0 +1,2993 @@ +/* + * softx86.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Softx86 library API. + * + * Initialization, de-initialization, register modification, and default + * routines for callbacks (in case they weren't set by the host app). + * + * Internal to this library, there are also functions to take care of + * fetching the current opcode (as referred to by CS:IP), fetching + * the current opcode for the decompiler (as referred to by a separate + * pair CS:IP), and pushing/popping data to/from the stack (SS:SP). + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include +#include "optable.h" + +/* softx86_setsegment(context,segid,val) + Sets a segment register and all hidden register information */ +int softx86_setsegval(softx86_ctx* ctx,int sreg_id,sx86_udword x) +{ + if (sreg_id > 7 || sreg_id < 0) return 0; + +/* TODO: In 286/386 protected mode fetch limit from GDT/LDT */ + ctx->state->segment_reg[sreg_id].val = x; + ctx->state->segment_reg[sreg_id].cached_linear = SEGMENT_TO_LINEAR(x); + ctx->state->segment_reg[sreg_id].cached_limit = 0xFFFF; + + return 1; /* success */ +} + +/* softx86_reset(context) + Resets a CPU + + return value: + 0 = failed + 1 = success */ +int softx86_reset(softx86_ctx* ctx) +{ + if (!ctx) return 0; + + if (ctx->__private->level >= SX86_CPULEVEL_80286) + ctx->__private->addr_mask = 0xFFFFFF; /* 80286 24-bit addressing */ + else + ctx->__private->addr_mask = 0xFFFFF; /* 8086/8088/80186 20-bit addressing */ + + ctx->state->general_reg[SX86_REG_AX].val = 0; + ctx->state->general_reg[SX86_REG_BX].val = 0; + ctx->state->general_reg[SX86_REG_CX].val = 0; + ctx->state->general_reg[SX86_REG_DX].val = 0; + ctx->state->general_reg[SX86_REG_SI].val = 0; + ctx->state->general_reg[SX86_REG_DI].val = 0; + ctx->state->general_reg[SX86_REG_SP].val = 0; + ctx->state->general_reg[SX86_REG_BP].val = 0; + ctx->state->reg_flags.val = SX86_CPUFLAG_RESERVED_01; + softx86_setsegval(ctx,SX86_SREG_DS,0xF000); + softx86_setsegval(ctx,SX86_SREG_ES,0xF000); + softx86_setsegval(ctx,SX86_SREG_SS,0xF000); + + ctx->__private->ptr_regs_8reg[0] = (sx86_ubyte*)(&ctx->state->general_reg[SX86_REG_AX].b.lo); // AL + ctx->__private->ptr_regs_8reg[1] = (sx86_ubyte*)(&ctx->state->general_reg[SX86_REG_CX].b.lo); // CL + ctx->__private->ptr_regs_8reg[2] = (sx86_ubyte*)(&ctx->state->general_reg[SX86_REG_DX].b.lo); // DL + ctx->__private->ptr_regs_8reg[3] = (sx86_ubyte*)(&ctx->state->general_reg[SX86_REG_BX].b.lo); // BL + ctx->__private->ptr_regs_8reg[4] = (sx86_ubyte*)(&ctx->state->general_reg[SX86_REG_AX].b.hi); // AH + ctx->__private->ptr_regs_8reg[5] = (sx86_ubyte*)(&ctx->state->general_reg[SX86_REG_CX].b.hi); // CH + ctx->__private->ptr_regs_8reg[6] = (sx86_ubyte*)(&ctx->state->general_reg[SX86_REG_DX].b.hi); // DH + ctx->__private->ptr_regs_8reg[7] = (sx86_ubyte*)(&ctx->state->general_reg[SX86_REG_BX].b.hi); // BH + +/* initial CPU instruction pointer in BIOS area on older machines: 0xF000:0xFFF0 (as far as I know) */ + softx86_setsegval(ctx,SX86_SREG_CS,0xF000); + ctx->state->reg_ip = 0xFFF0; + ctx->state->int_hw_flag = 0; + ctx->state->int_nmi = 0; + +/* switch on/off bugs */ + ctx->bugs->preemptible_after_prefix = (ctx->__private->level <= SX86_CPULEVEL_8086)?1:0; + ctx->bugs->decrement_sp_before_store = (ctx->__private->level <= SX86_CPULEVEL_80186)?1:0; + ctx->bugs->mask_5bit_shiftcount = (ctx->__private->level >= SX86_CPULEVEL_80286)?1:0; + +/* CPU mode flags */ + ctx->state->reg_cr0 = 0; + +/* opcode table */ + ctx->__private->opcode_table = (void*)(&optab8086); + ctx->__private->opcode_table_sub_0Fh = (void*)(&optab8086_0Fh); + +/* we were just reset */ + ctx->callbacks->on_reset(ctx); + + return 1; /* success */ +} + +int softx86_getversion(int *major,int *minor,int *subminor) +{ + if (!minor || !major || !subminor) return 0; + + *major = SOFTX86_VERSION_HI; + *minor = SOFTX86_VERSION_LO; + *subminor = SOFTX86_VERSION_SUBLO; + return 1; +} + +/* softx86_init(context) + Initialize a CPU context structure. + + return value: + 0 = failed + 1 = success + 2 = beta development advisory (CPU level emulation not quite stable) */ +int softx86_init(softx86_ctx* ctx,int level) +{ + int ret; + + ret=1; + if (!ctx) return 0; + if (level > SX86_CPULEVEL_80286) return 0; /* we currently support up to the 80286 */ + if (level < 0) return 0; /* apparently the host wants an 80(-1)86? :) */ + if (level > SX86_CPULEVEL_8086) ret=2; /* 80186 or higher emulation is not stable yet */ + +/* set up pointers */ + ctx->__private = (softx86_internal*)malloc(sizeof(softx86_internal)); + ctx->bugs = (softx86_bugs*)malloc(sizeof(softx86_bugs)); + ctx->callbacks = (softx86_callbacks*)malloc(sizeof(softx86_callbacks)); + ctx->state = (softx86_cpustate*)malloc(sizeof(softx86_cpustate)); + if ((!ctx->__private) || (!ctx->bugs) || (!ctx->callbacks) || (!ctx->state)) { + softx86_free(ctx); + return 0; + } + +/* store settings */ + ctx->__private->level = level; + +/* store version in the structure */ + ctx->version_hi = SOFTX86_VERSION_HI; + ctx->version_lo = SOFTX86_VERSION_LO; + ctx->version_sublo = SOFTX86_VERSION_SUBLO; + +/* default callbacks */ + ctx->callbacks->on_read_io = softx86_step_def_on_read_io; + ctx->callbacks->on_read_memory = softx86_step_def_on_read_memory; + ctx->callbacks->on_write_io = softx86_step_def_on_write_io; + ctx->callbacks->on_write_memory = softx86_step_def_on_write_memory; + ctx->callbacks->on_hw_int = softx86_step_def_on_hw_int; + ctx->callbacks->on_hw_int_ack = softx86_step_def_on_hw_int_ack; + ctx->callbacks->on_sw_int = softx86_step_def_on_sw_int; + ctx->callbacks->on_idle_cycle = softx86_step_def_on_idle_cycle; + ctx->callbacks->on_nmi_int = softx86_step_def_on_nmi_int; + ctx->callbacks->on_nmi_int_ack = softx86_step_def_on_nmi_int_ack; + ctx->callbacks->on_fpu_opcode_dec = softx86_step_def_on_fpu_opcode_dec; + ctx->callbacks->on_fpu_opcode_exec = softx86_step_def_on_fpu_opcode_exec; + ctx->callbacks->on_reset = softx86_step_def_on_reset; + +/* default pointers */ + ctx->ref_softx87_ctx = NULL; + +/* now reset */ + if (!softx86_reset(ctx)) return 0; + + return ret; /* success */ +} + +/* softx86_free(context) + Free a CPU context structure */ +int softx86_free(softx86_ctx* ctx) +{ + if (!ctx) return 0; + if (ctx->__private) free(ctx->__private); + if (ctx->bugs) free(ctx->bugs); + if (ctx->callbacks) free(ctx->callbacks); + if (ctx->state) free(ctx->state); + ctx->__private = NULL; + ctx->bugs = NULL; + ctx->callbacks = NULL; + ctx->state = NULL; + return 1; /* success */ +} + +/* fetch byte at executioneer CS:IP, increment pointer */ +sx86_ubyte softx86_fetch_exec_byte(softx86_ctx* ctx) +{ + sx86_ubyte opcode; + + if (!ctx) return 0; + + softx86_fetch(ctx,NULL,ctx->state->segment_reg[SX86_SREG_CS].cached_linear+ctx->state->reg_ip,&opcode,1); + ctx->state->reg_ip++; +/* TODO: If IP passes 0xFFFF generate an exception */ + + return opcode; +} + +/* fetch byte at decompiler CS:IP, increment pointer */ +sx86_ubyte softx86_fetch_dec_byte(softx86_ctx* ctx) +{ + sx86_ubyte opcode; + + if (!ctx) return 0; + + softx86_fetch(ctx,NULL,SEGMENT_TO_LINEAR(ctx->state->reg_cs_decompiler)+(ctx->state->reg_ip_decompiler),&opcode,1); + ctx->state->reg_ip_decompiler++; + return opcode; +} + +/* retrieve a word value from the stack pointer SS:SP */ +sx86_uword softx86_stack_popw(softx86_ctx* ctx) +{ + sx86_uword data; + + if (!ctx) return 0; + +/* TODO: If SP == 0xFFFF generate an exception */ + softx86_fetch(ctx,NULL,ctx->state->segment_reg[SX86_SREG_SS].cached_linear+ctx->state->general_reg[SX86_REG_SP].w.lo,&data,2); + SWAP_WORD_FROM_LE(data); + ctx->state->general_reg[SX86_REG_SP].w.lo += 2; +/* TODO: If SP passes 0xFFFF generate an exception */ + + return data; +} + +/* discard n bytes from stack pointer SS:SP */ +void softx86_stack_discard_n(softx86_ctx* ctx,int bytez) +{ + if (!ctx) return; + + ctx->state->general_reg[SX86_REG_SP].w.lo += bytez; +/* TODO: If SP passes 0xFFFF generate an exception */ +} + +/* adds n bytes to stack pointer SS:SP */ +void softx86_stack_add_n(softx86_ctx* ctx,int bytez) +{ + if (!ctx) return; + + ctx->state->general_reg[SX86_REG_SP].w.lo -= bytez; +/* TODO: If SP passes 0xFFFF generate an exception */ +} + +/* store a word value to the stack pointer SS:SP */ +void softx86_stack_pushw(softx86_ctx* ctx,sx86_uword data) +{ + SWAP_WORD_TO_LE(data); +/* TODO: If SP == 0x0001 generate an exception */ + ctx->state->general_reg[SX86_REG_SP].w.lo -= 2; + softx86_write(ctx,NULL,ctx->state->segment_reg[SX86_SREG_SS].cached_linear+ctx->state->general_reg[SX86_REG_SP].w.lo,&data,2); +} + +/* set stack pointer SS:SP */ +int softx86_set_stack_ptr(softx86_ctx* ctx,sx86_udword ss,sx86_udword sp) +{ + if (!ctx) return 0; + +/* TODO: Check SS:SP for validity */ + ctx->state->general_reg[SX86_REG_SP].w.lo = sp; + softx86_setsegval(ctx,SX86_SREG_SS,ss); + + return 1; +} + +/* set executioneer CS:IP */ +int softx86_set_instruction_ptr(softx86_ctx* ctx,sx86_udword cs,sx86_udword ip) +{ + if (!ctx) return 0; + +/* TODO: Check CS:IP for validity */ + ctx->state->reg_ip = ip; + softx86_setsegval(ctx,SX86_SREG_CS,cs); + + return 1; +} + +/* set executioneer IP (not CS). used for emulating near jumps. */ +int softx86_set_near_instruction_ptr(softx86_ctx* ctx,sx86_udword ip) +{ + if (!ctx) return 0; + +/* TODO: Check IP for validity */ + ctx->state->reg_ip = ip; + + return 1; +} + +/* set decompiler CS:IP */ +int softx86_set_instruction_dec_ptr(softx86_ctx* ctx,sx86_udword cs,sx86_udword ip) +{ + if (!ctx) return 0; + +/* TODO: Check CS:IP for validity */ + ctx->state->reg_ip_decompiler = ip; + ctx->state->reg_cs_decompiler = cs; + + return 1; +} + +/* create a stack frame for simple near procedural calls and set the instruction pointer (if ip != NULL) */ +int softx86_make_simple_near_call(softx86_ctx* ctx,sx86_udword* ip) +{ + if (!ctx) return 0; + + softx86_stack_pushw(ctx,ctx->state->reg_ip); + if (ip != NULL) return softx86_set_near_instruction_ptr(ctx,*ip); + return 1; +} + +/* create a stack frame for simple far procedural calls and set the instruction pointer (if ip != NULL) */ +int softx86_make_simple_far_call(softx86_ctx* ctx,sx86_udword* cs,sx86_udword* ip) +{ + if (!ctx) return 0; + + softx86_stack_pushw(ctx,ctx->state->segment_reg[SX86_SREG_CS].val); + softx86_stack_pushw(ctx,ctx->state->reg_ip); + if (cs != NULL && ip != NULL) return softx86_set_instruction_ptr(ctx,*cs,*ip); + return 1; +} + +/* create a stack frame for simple interrupt procedural calls and set the instruction pointer (if ip != NULL) */ +int softx86_make_simple_interrupt_call(softx86_ctx* ctx,sx86_udword* cs,sx86_udword* ip) +{ + if (!ctx) return 0; + + softx86_stack_pushw(ctx,ctx->state->reg_flags.w.lo); + softx86_stack_pushw(ctx,ctx->state->segment_reg[SX86_SREG_CS].val); + softx86_stack_pushw(ctx,ctx->state->reg_ip); + if (cs != NULL && ip != NULL) return softx86_set_instruction_ptr(ctx,*cs,*ip); + return 1; +} + +/* retrieves an interrupt vector */ +int softx86_get_intvect(softx86_ctx* ctx,sx86_ubyte i,sx86_uword *seg,sx86_uword *ofs) +{ + sx86_uword _seg,_ofs; + sx86_udword o; + + if (!ctx) return 0; + +/* obtain the interrupt vector */ + o = (i<<2); + softx86_fetch(ctx,NULL,o,(void*)(&_ofs),2); + SWAP_WORD_FROM_LE(_ofs); + *ofs = _ofs; + + o += 2; + softx86_fetch(ctx,NULL,o,(void*)(&_seg),2); + SWAP_WORD_FROM_LE(_seg); + *seg = _seg; + + return 1; +} + +/* sets an interrupt vector */ +int softx86_set_intvect(softx86_ctx* ctx,sx86_ubyte i,sx86_uword seg,sx86_uword ofs) +{ + sx86_udword o; + + if (!ctx) return 0; + +/* obtain the interrupt vector */ + o = (i<<2); + SWAP_WORD_TO_LE(ofs); + softx86_write(ctx,NULL,o,(void*)(&ofs),2); + + o += 2; + SWAP_WORD_TO_LE(seg); + softx86_write(ctx,NULL,o,(void*)(&seg),2); + + return 1; +} + +/* create interrupt frame and manipulate registers */ +void softx86_go_int_frame(softx86_ctx* ctx,sx86_ubyte i) +{ + sx86_uword seg,ofs; + +/* get interrupt vector */ + if (!softx86_get_intvect(ctx,i,&seg,&ofs)) return; + +/* save old address */ + softx86_stack_pushw(ctx,ctx->state->reg_flags.val); + softx86_stack_pushw(ctx,ctx->state->segment_reg[SX86_SREG_CS].val); + softx86_stack_pushw(ctx,ctx->state->reg_ip); + +/* disable interrupts */ + ctx->state->reg_flags.val &= ~SX86_CPUFLAG_INTENABLE; + +/* go! */ + if (!softx86_set_instruction_ptr(ctx,seg,ofs)) return; +} + +/* enable/disable emulation of specific bugs. */ +int softx86_setbug(softx86_ctx* ctx,sx86_udword bug_id,sx86_ubyte on_off) +{ + if (bug_id == SX86_BUG_PREEMPTIBLE_AFTER_PREFIX) { + ctx->bugs->preemptible_after_prefix = on_off; + return 1; + } + else if (bug_id == SX86_BUG_SP_DECREMENT_BEFORE_STORE) { + ctx->bugs->decrement_sp_before_store = on_off; + } + + return 0; +} + +/* simulate external hardware interrupt from host app. */ +int softx86_ext_hw_signal(softx86_ctx* ctx,sx86_ubyte i) +{ + if (!ctx) return 0; + +/* make sure the poor CPU isn't getting deluged by interrupts. + as far as I know, every system using the x86 with an interrupt + system has some sort of moderator for the #int line. The x86 PC + platform for instance, has a "programmable interrupt controller" + that is responsible for handling 16 interrupt signals (IRQ 0 + thru 15) and presenting them one at a time to the CPU. */ + if (ctx->state->int_hw_flag) return 0; + + ctx->callbacks->on_hw_int(ctx,i); + ctx->state->int_hw_flag = 1; + ctx->state->int_hw = i; + + return 1; +} + +/* simulate external hardware NMI interrupt from host app. */ +int softx86_ext_hw_nmi_signal(softx86_ctx* ctx) +{ + if (!ctx) return 0; + +/* only one #NMI at a time! */ +/* TODO: Is the #NMI interrupt number fixed or variable? */ + if (ctx->state->int_nmi) return 0; + + ctx->state->int_nmi = 1; + ctx->callbacks->on_nmi_int(ctx); + + return 1; +} + +/* simulate internal software interrupt. */ +int softx86_int_sw_signal(softx86_ctx* ctx,sx86_ubyte i) +{ + if (!ctx) return 0; + + ctx->callbacks->on_sw_int(ctx,i); + softx86_go_int_frame(ctx,i); + + return 1; +} + +/* INTERNAL USE: used by this library to send acknowledgement back + to host application for the given interrupt signal. */ +int softx86_ext_hw_ack(softx86_ctx* ctx) +{ + if (!ctx) return 0; + if (!ctx->state->int_hw_flag) return 0; + + ctx->callbacks->on_hw_int_ack(ctx,ctx->state->int_hw); + ctx->state->int_hw_flag = 0; + ctx->state->int_hw = 0; + + return 1; +} + +/* INTERNAL USE: used by this library to send acknowledgement back + to host application for the given interrupt signal. */ +int softx86_ext_hw_nmi_ack(softx86_ctx* ctx) +{ + if (!ctx) return 0; + if (!ctx->state->int_nmi) return 0; + + ctx->callbacks->on_nmi_int_ack(ctx); + ctx->state->int_nmi = 0; + + return 1; +} + +/* softx86_step(context) + Executes ONE instruction at CS:IP + + return value: + 0 = failed + 1 = success */ +int softx86_step(softx86_ctx* ctx) +{ + Sfx86OpcodeTable* sop; + sx86_ubyte opcode; + int lp,x,restart,err,count; + int can_hwint; + + if (!ctx) return 0; + sop = (Sfx86OpcodeTable*)(ctx->__private->opcode_table); + if (!sop) return 0; + + ctx->state->is_segment_override = 0; + ctx->state->segment_override = 0; + ctx->state->rep_flag = 0; + ctx->state->reg_cs_exec_initial = ctx->state->segment_reg[SX86_SREG_CS].val; + ctx->state->reg_ip_exec_initial = ctx->state->reg_ip; + + lp = 1; + err = 0; + count = 16; + restart = 0; + can_hwint = 1; + while (lp && count-- > 0) { +/* if now is a good time to allow an interrupt and interrupts enabled, so be it */ + if (can_hwint || ctx->bugs->preemptible_after_prefix) { + if (ctx->state->int_nmi) { /* #NMI pin has priority */ + softx86_go_int_frame(ctx,2); + softx86_ext_hw_nmi_ack(ctx); + } + else if (ctx->state->reg_flags.val & SX86_CPUFLAG_INTENABLE) { + if (ctx->state->int_hw_flag) { + softx86_go_int_frame(ctx,ctx->state->int_hw); + softx86_ext_hw_ack(ctx); + } + } + + can_hwint=0; + } + +/* fetch opcode */ + opcode = softx86_fetch_exec_byte(ctx); +/* execute opcode */ + x = sop->table[opcode].exec(opcode,ctx); +/* what happened? */ + if (x == 0) { /* opcode not recognized? stop! */ + lp = 0; + restart = 1; + err = 1; + } + else if (x == 1) { /* opcode recognized? */ + lp = 0; + } + else if (x == 2) { /* opcode recognized but more parsing needed (i.e. instruction prefix)? */ + } + else if (x == 3) { /* opcode recognized, looping action in progress do not advance (i.e. REP MOVSB or HLT/WAIT)? */ + restart = 1; + lp = 0; + } + else { /* this indicates a bug in this library */ + lp = 0; + restart = 1; /* huh? */ + err = 1; + } + } + + if (count <= 0) { + err = 1; + restart = 1; + } + + if (restart) { + ctx->state->segment_reg[SX86_SREG_CS].val = ctx->state->reg_cs_exec_initial; + ctx->state->reg_ip = ctx->state->reg_ip_exec_initial; + } + + return !err; /* success */ +} + +/* softx86_decompile(context) + Decompiles ONE instruction at decoder CS:IP + + return value: + 0 = failed + 1 = success */ +int softx86_decompile(softx86_ctx* ctx,char asmbuf[256]) +{ + Sfx86OpcodeTable* sop; + sx86_ubyte opcode; + int lp,x,err,count,asmx; + char buf[256]; + + if (!ctx) return 0; + sop = (Sfx86OpcodeTable*)(ctx->__private->opcode_table); + if (!sop) return 0; + + lp = 1; + err = 0; + asmx = 0; + asmbuf[0] = 0; + count = 16; + while (lp && count-- > 0) { +/* fetch opcode */ + opcode = softx86_fetch_dec_byte(ctx); +/* execute opcode */ + x = sop->table[opcode].dec(opcode,ctx,buf); +/* what happened? */ + if (x == 0) { /* opcode not recognized? stop! */ + lp = 0; + err = 1; + } + else if (x == 1) { /* opcode recognized? */ + strcpy(asmbuf+asmx,buf); + lp = 0; + } + else if (x == 2) { /* opcode recognized but more parsing needed? */ + strcpy(asmbuf+asmx,buf); /* this is why asmbuf[] is 256 bytes :) */ + asmbuf += strlen(asmbuf+asmx); + } + else { /* this indicates a bug in this library */ + lp = 0; + err = 1; + } + } + + if (count <= 0) { + err = 1; + } + + return !err; /* success */ +} + +/* softx86_decompile_exec_cs_ip(context) + Point decompiler instructor ptr to where the executioneer CS:IP is */ +int softx86_decompile_exec_cs_ip(softx86_ctx* ctx) +{ + if (!ctx) return 0; + +/* set decompiler CS:IP to executioneer CS:IP */ + ctx->state->reg_cs_decompiler = ctx->state->segment_reg[SX86_SREG_CS].val; + ctx->state->reg_ip_decompiler = ctx->state->reg_ip; + + return 1; /* success */ +} + +/*-------------------------------------------------------------------------------- + default callbacks + --------------------------------------------------------------------------------*/ + +void softx86_step_def_on_read_memory(void* _ctx,sx86_udword address,sx86_ubyte *buf,int size) +{ + softx86_ctx *ctx = ((softx86_ctx*)_ctx); + if (!ctx || !buf || size < 1) return; + memset(buf,0xFF,size); +} + +void softx86_step_def_on_read_io(void* _ctx,sx86_udword address,sx86_ubyte *buf,int size) +{ + softx86_ctx *ctx = ((softx86_ctx*)_ctx); + if (!ctx || !buf || size < 1) return; + memset(buf,0xFF,size); +} + +void softx86_step_def_on_write_memory(void* _ctx,sx86_udword address,sx86_ubyte *buf,int size) +{ + softx86_ctx *ctx = ((softx86_ctx*)_ctx); + if (!ctx || !buf || size < 1) return; +} + +void softx86_step_def_on_write_io(void* _ctx,sx86_udword address,sx86_ubyte *buf,int size) +{ + softx86_ctx *ctx = ((softx86_ctx*)_ctx); + if (!ctx || !buf || size < 1) return; +} + +void softx86_step_def_on_hw_int(void* _ctx,sx86_ubyte i) +{ +} + +void softx86_step_def_on_sw_int(void* _ctx,sx86_ubyte i) +{ +} + +void softx86_step_def_on_hw_int_ack(void* _ctx,sx86_ubyte i) +{ +} + +void softx86_step_def_on_idle_cycle(void* _ctx) +{ +} + +void softx86_step_def_on_nmi_int(void* _ctx) +{ +} + +void softx86_step_def_on_nmi_int_ack(void* _ctx) +{ +} + +int softx86_step_def_on_fpu_opcode_exec(void* _ctx86,void* _ctx87,sx86_ubyte opcode) +{ + return 0; +} + +int softx86_step_def_on_fpu_opcode_dec(void* _ctx86,void* _ctx87,sx86_ubyte opcode,char buf[128]) +{ + return 0; +} + +void softx86_step_def_on_reset(/* softx86_ctx */ void* _ctx) +{ +} + +/*-------------------------------------------------------------------------------- + API for CPU itself to fetch data through a cache. + --------------------------------------------------------------------------------*/ +int softx86_fetch(softx86_ctx* ctx,void *reserved,sx86_udword addr,void *_buf,int sz) +{ + sx86_ubyte *buf = (sx86_ubyte*)(_buf); + int rsz; + sx86_udword raddr; + + if (!ctx || !buf || sz < 1) return 0; + + rsz = sz; + raddr = addr; + +/* TODO: fetching from cache can be implemented at this point, filling in by reassigning ratter, buf and rsz. */ + +/* save host application the aggrivation of dealing with 32-bit address wrap-arounds */ + if ((raddr+rsz) > 0 && (raddr+rsz) < rsz) { + ctx->callbacks->on_read_memory(ctx,raddr,buf,(sx86_udword)((0x100000000L-raddr)&0xFFFFFFFF)); + raddr += (sx86_udword)((0x100000000L-raddr)&0xFFFFFFFF); + rsz -= (sx86_udword)((0x100000000L-raddr)&0xFFFFFFFF); + buf += (sx86_udword)((0x100000000L-raddr)&0xFFFFFFFF); + ctx->callbacks->on_read_memory(ctx,raddr,buf,rsz); + return 1; + } + + ctx->callbacks->on_read_memory(ctx,raddr,buf,rsz); + + return 1; +} + +int softx86_write(softx86_ctx* ctx,void *reserved,sx86_udword addr,void *_buf,int sz) +{ + sx86_ubyte *buf = (sx86_ubyte*)(_buf); + int rsz; + sx86_udword raddr; + + if (!ctx || !buf || sz < 1) return 0; + + rsz = sz; + raddr = addr; + +/* TODO: writing to/through the cache can be implemented at this point, filling in by reassigning ratter, buf and rsz. */ + +/* save host application the aggrivation of dealing with 32-bit address wrap-arounds */ + if ((raddr+rsz) > 0 && (raddr+rsz) < rsz) { + ctx->callbacks->on_write_memory(ctx,raddr,buf,(sx86_udword)((0x100000000L-raddr)&0xFFFFFFFF)); + raddr += (sx86_udword)((0x100000000L-raddr)&0xFFFFFFFF); + rsz -= (sx86_udword)((0x100000000L-raddr)&0xFFFFFFFF); + buf += (sx86_udword)((0x100000000L-raddr)&0xFFFFFFFF); + ctx->callbacks->on_write_memory(ctx,raddr,buf,rsz); + return 1; + } + + ctx->callbacks->on_write_memory(ctx,raddr,buf,rsz); + + return 1; +} + +void softx86_bswap2(sx86_ubyte *x) +{ + sx86_ubyte t; + + t=x[0]; x[0]=x[1]; x[1]=t; +} + +void softx86_bswap4(sx86_ubyte *x) +{ + sx86_ubyte t; + + t=x[0]; x[0]=x[3]; x[3]=t; + t=x[1]; x[1]=x[2]; x[2]=t; +} + +/* general purpose mod/reg/rm executioneer helper for LEA. + + this is provided to avoid copy and pasting this source code into the emulation + code for *EVERY* instruction. + + ctx = CPU context + d32 = 386+ 32-bit data size override + mod/reg/rm = mod/reg/rm unpacked byte + + Example of instructions that fit this format: + + LEA AX,[AX+2] (apparently a substitute for add ax,2?) + LEA BX,[SP] (seen sometimes as an alternative to mov bx,sp) + LEA EBX,[ESI+ECX] (surprisingly, often seen in Win32 code) +*/ +void sx86_exec_full_modregrm_lea(softx86_ctx* ctx,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm) +{ + if (mod == 3) { /* register <- register */ + /* TODO: Invalid opcode exception. */ + } + else { /* register <- memory */ + sx86_uword ofs; + +/* don't calculate segment value because LEA does not fetch memory, it only stores + the offset into the destination register */ + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + ctx->state->general_reg[reg].w.lo = ofs; + } +} + +/* general purpose mod/reg/rm executioneer helper for + instructions that modify the destination operand. + + this is provided to avoid copy and pasting this source code into the emulation + code for *EVERY* instruction. + + ctx = CPU context + w16 = 16-bit operand flag + d32 = 386+ 32-bit data size override (ignored if w16 == 0) + mod/reg/rm = mod/reg/rm unpacked byte + op8 = function to call for emulation of instruction, given 8-bit operands "src" and "dst" + op16 = function to call for emulation of instruction, given 16-bit operands "src" and "dst" + op32 = function to call for emulation of instruction, given 32-bit operands "src" and "dst" + + Example of instructions that fit this format: + + MOV AX,CX + MOV WORD PTR [3456h],DX + MOV SI,DI + MOV BX,WORD PTR [1246h] +*/ +void sx86_exec_full_modregrm_rw(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm,sx86_ubyte opswap,sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val),sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val)) +{ + if (mod == 3) { /* register <-> register */ + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword regv,rmv; + + regv = ctx->state->general_reg[reg].w.lo; + rmv = ctx->state->general_reg[rm].w.lo; + + if (opswap) + ctx->state->general_reg[reg].w.lo = + op16(ctx,regv,rmv); + else + ctx->state->general_reg[rm].w.lo = + op16(ctx,rmv,regv); + } + else { + sx86_ubyte regv,rmv; + + regv = *(ctx->__private->ptr_regs_8reg[reg]); + rmv = *(ctx->__private->ptr_regs_8reg[rm]); + + if (opswap) + *(ctx->__private->ptr_regs_8reg[reg]) = + op8(ctx,regv,rmv); + else + *(ctx->__private->ptr_regs_8reg[rm]) = + op8(ctx,rmv,regv); + } + } + else { /* register <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword regv,rmv; + + regv = ctx->state->general_reg[reg].w.lo; + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,2); + SWAP_WORD_FROM_LE(rmv); + + if (opswap) { + ctx->state->general_reg[reg].w.lo = + op16(ctx,regv,rmv); + } + else { + rmv = op16(ctx,rmv,regv); + SWAP_WORD_TO_LE(rmv); + softx86_write(ctx,NULL,lo,&rmv,2); + } + } + else { + sx86_ubyte regv,rmv; + + regv = *(ctx->__private->ptr_regs_8reg[reg]); + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,1); + + if (opswap) { + *(ctx->__private->ptr_regs_8reg[reg]) = + op8(ctx,regv,rmv); + } + else { + rmv = op8(ctx,rmv,regv); + softx86_write(ctx,NULL,lo,&rmv,1); + } + } + } +} + +/* general purpose mod/reg/rm executioneer helper for + instructions that do not modify the destination operand. + + this is provided to avoid copy and pasting this source code into the emulation + code for *EVERY* instruction. + + ctx = CPU context + w16 = 16-bit operand flag + d32 = 386+ 32-bit data size override (ignored if w16 == 0) + mod/reg/rm = mod/reg/rm unpacked byte + op8 = function to call for emulation of instruction, given 8-bit operands "src" and "dst" + op16 = function to call for emulation of instruction, given 16-bit operands "src" and "dst" + op32 = function to call for emulation of instruction, given 32-bit operands "src" and "dst" + + Example of instructions that fit this format: + + TEST AX,CX + TEST WORD PTR [3456h],DX + TEST SI,DI + TEST BX,WORD PTR [1246h] +*/ +void sx86_exec_full_modregrm_ro(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm,sx86_ubyte opswap,sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val),sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val)) +{ + if (mod == 3) { /* register <-> register */ + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword regv,rmv; + + regv = ctx->state->general_reg[reg].w.lo; + rmv = ctx->state->general_reg[rm].w.lo; + + if (opswap) + op16(ctx,regv,rmv); + else + op16(ctx,rmv,regv); + } + else { + sx86_ubyte regv,rmv; + + regv = *(ctx->__private->ptr_regs_8reg[reg]); + rmv = *(ctx->__private->ptr_regs_8reg[rm]); + + if (opswap) + op8(ctx,regv,rmv); + else + op8(ctx,rmv,regv); + } + } + else { /* register <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword regv,rmv; + + regv = ctx->state->general_reg[reg].w.lo; + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,2); + SWAP_WORD_FROM_LE(rmv); + + if (opswap) { + op16(ctx,regv,rmv); + } + else { + op16(ctx,rmv,regv); + } + } + else { + sx86_ubyte regv,rmv; + + regv = *(ctx->__private->ptr_regs_8reg[reg]); + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,1); + + if (opswap) { + op8(ctx,regv,rmv); + } + else { + op8(ctx,rmv,regv); + } + } + } +} + +/* general purpose mod/reg/rm executioneer helper for + instructions that do modify the destination operand + and need a FAR pointer + + this is provided to avoid copy and pasting this source code into the emulation + code for *EVERY* instruction. + + ctx = CPU context + d32 = 386+ 32-bit data size override (ignored if w16 == 0) + mod/reg/rm = mod/reg/rm unpacked byte + op16 = function to call for emulation of instruction, given 16-bit operands "src" and "dst" + op32 = function to call for emulation of instruction, given 32-bit operands "src" and "dst" + + Example of instructions that fit this format: + + LES BX,WORD PTR [5256h] +*/ +void sx86_exec_full_modregrm_far(softx86_ctx* ctx,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm,sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs)) +{ + if (mod == 3) { /* register <-> register */ + /* illegal */ + } + else { /* register <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + { + sx86_uword rmv,rmv2; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,2); + lo += 2; + softx86_fetch(ctx,NULL,lo,&rmv2,2); + SWAP_WORD_FROM_LE(rmv); + SWAP_WORD_FROM_LE(rmv2); + ctx->state->general_reg[reg].w.lo = op16(ctx,rmv2,rmv); + } + } +} + +/* general purpose mod/reg/rm executioneer helper for + instructions that do not modify the destination operand + but need a FAR pointer and the register operand + + this is provided to avoid copy and pasting this source code into the emulation + code for *EVERY* instruction. + + ctx = CPU context + d32 = 386+ 32-bit data size override (ignored if w16 == 0) + mod/reg/rm = mod/reg/rm unpacked byte + op16 = function to call for emulation of instruction, given 16-bit operands "src" and "dst" + op32 = function to call for emulation of instruction, given 32-bit operands "src" and "dst" + + Example of instructions that fit this format: + + BOUND BX,WORD PTR [9874h] +*/ +void sx86_exec_full_modregrm_far_ro3(softx86_ctx* ctx,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm,sx86_sword (*op16)(softx86_ctx* ctx,sx86_sword idx,sx86_sword upper,sx86_sword lower),sx86_sdword (*op32)(softx86_ctx* ctx,sx86_sdword idx,sx86_sdword upper,sx86_sdword lower)) +{ + if (mod == 3) { /* register <-> register */ + /* illegal */ + } + else { /* register <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + { + sx86_sword rmv,rmv2; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,2); + lo += 2; + softx86_fetch(ctx,NULL,lo,&rmv2,2); + SWAP_WORD_FROM_LE(rmv); + SWAP_WORD_FROM_LE(rmv2); + op16(ctx,ctx->state->general_reg[reg].w.lo,rmv2,rmv); + } + } +} + +/* general purpose mod/rm executioneer helper for + instructions that modify the destination operand + and have an immediate operand of specified size. + + this is provided to avoid copy and pasting this source code into the emulation + code for *EVERY* instruction. + + ctx = CPU context + w16 = 16-bit operand flag + d32 = 386+ 32-bit data size override (ignored if w16 == 0) + mod/rm = mod/reg/rm unpacked byte + op8 = function to call for emulation of instruction, given 8-bit operands "src" and "dst" + op16 = function to call for emulation of instruction, given 16-bit operands "src" and "dst" + op32 = function to call for emulation of instruction, given 32-bit operands "src" and "dst" + + Example of instructions that fit this format: + + MOV AH,2456h + MOV WORD PTR [1334h],2222h +*/ +void sx86_exec_full_modrmonly_rw_imm(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte rm,sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val),sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val),int sx) +{ + sx86_uword imm; + + if (mod == 3) { /* immediate <-> register */ + imm = softx86_fetch_exec_byte(ctx); + if (w16) + { + if (sx) imm |= (imm&0x80) ? 0xFF80 : 0; + else imm |= softx86_fetch_exec_byte(ctx)<<8; + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword rmv; + + rmv = ctx->state->general_reg[rm].w.lo; + + ctx->state->general_reg[rm].w.lo = + op16(ctx,rmv,(sx86_uword)imm); + } + else { + sx86_ubyte rmv; + + rmv = *(ctx->__private->ptr_regs_8reg[rm]); + + *(ctx->__private->ptr_regs_8reg[rm]) = + op8(ctx,rmv,(sx86_ubyte)imm); + } + } + else { /* immediate <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + imm = softx86_fetch_exec_byte(ctx); + if (w16) + { + if (sx) imm |= (imm&0x80) ? 0xFF80 : 0; + else imm |= softx86_fetch_exec_byte(ctx)<<8; + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword rmv; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,2); + SWAP_WORD_FROM_LE(rmv); + + rmv = op16(ctx,rmv,(sx86_uword)imm); + SWAP_WORD_TO_LE(rmv); + softx86_write(ctx,NULL,lo,&rmv,2); + } + else { + sx86_ubyte rmv; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,1); + + rmv = op8(ctx,rmv,(sx86_ubyte)imm); + softx86_write(ctx,NULL,lo,&rmv,1); + } + } +} + +/* general purpose mod/rm executioneer helper for + instructions that modify the destination operand + and have an immediate operand of specified size. + + this is provided to avoid copy and pasting this source code into the emulation + code for *EVERY* instruction. + + ctx = CPU context + w16 = 16-bit operand flag + d32 = 386+ 32-bit data size override (ignored if w16 == 0) + mod/rm = mod/reg/rm unpacked byte + op8 = function to call for emulation of instruction, given 8-bit operands "src" and "dst" + op16 = function to call for emulation of instruction, given 16-bit operands "src" and "dst" + op32 = function to call for emulation of instruction, given 32-bit operands "src" and "dst" + + Example of instructions that fit this format: + + MOV AH,2456h + MOV WORD PTR [1334h],2222h +*/ +void sx86_exec_full_modrmonly_rw_imm8(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte rm,sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val),sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val)) +{ + sx86_uword imm; + + if (mod == 3) { /* immediate <-> register */ + imm = softx86_fetch_exec_byte(ctx); + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword rmv; + + rmv = ctx->state->general_reg[rm].w.lo; + + ctx->state->general_reg[rm].w.lo = + op16(ctx,rmv,(sx86_uword)imm); + } + else { + sx86_ubyte rmv; + + rmv = *(ctx->__private->ptr_regs_8reg[rm]); + + *(ctx->__private->ptr_regs_8reg[rm]) = + op8(ctx,rmv,(sx86_ubyte)imm); + } + } + else { /* immediate <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + imm = softx86_fetch_exec_byte(ctx); + if (w16) imm |= softx86_fetch_exec_byte(ctx)<<8; + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword rmv; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,2); + SWAP_WORD_FROM_LE(rmv); + + rmv = op16(ctx,rmv,(sx86_uword)imm); + SWAP_WORD_TO_LE(rmv); + softx86_write(ctx,NULL,lo,&rmv,2); + } + else { + sx86_ubyte rmv; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,1); + + rmv = op8(ctx,rmv,(sx86_ubyte)imm); + softx86_write(ctx,NULL,lo,&rmv,1); + } + } +} + +/* general purpose mod/rm executioneer helper for + instructions that DO NOT modify the destination operand + and have an immediate operand of specified size. + + this is provided to avoid copy and pasting this source code into the emulation + code for *EVERY* instruction. + + ctx = CPU context + w16 = 16-bit operand flag + d32 = 386+ 32-bit data size override (ignored if w16 == 0) + mod/rm = mod/reg/rm unpacked byte + op8 = function to call for emulation of instruction, given 8-bit operands "src" and "dst" + op16 = function to call for emulation of instruction, given 16-bit operands "src" and "dst" + op32 = function to call for emulation of instruction, given 32-bit operands "src" and "dst" + + Example of instructions that fit this format: + + MOV AH,2456h + MOV WORD PTR [1334h],2222h +*/ +void sx86_exec_full_modrmonly_ro_imm(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte rm,sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src,sx86_ubyte val),sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src,sx86_udword val),int sx) +{ + sx86_uword imm; + + if (mod == 3) { /* immediate <-> register */ + imm = softx86_fetch_exec_byte(ctx); + if (w16) + { + if (sx) imm |= (imm&0x80) ? 0xFF80 : 0; + else imm |= softx86_fetch_exec_byte(ctx)<<8; + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword rmv; + + rmv = ctx->state->general_reg[rm].w.lo; + op16(ctx,rmv,(sx86_uword)imm); + } + else { + sx86_ubyte rmv; + + rmv = *(ctx->__private->ptr_regs_8reg[rm]); + op8(ctx,rmv,(sx86_ubyte)imm); + } + } + else { /* immediate <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + imm = softx86_fetch_exec_byte(ctx); + if (w16) + { + if (sx) imm |= (imm&0x80) ? 0xFF80 : 0; + else imm |= softx86_fetch_exec_byte(ctx)<<8; + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword rmv; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,2); + SWAP_WORD_FROM_LE(rmv); + + op16(ctx,rmv,(sx86_uword)imm); + } + else { + sx86_ubyte rmv; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,1); + + op8(ctx,rmv,(sx86_ubyte)imm); + } + } +} + +/* general purpose mod/rm executioneer helper for + instructions that modify the destination operand + and do not have an immediate operand of specified size. + + this is provided to avoid copy and pasting this source code into the emulation + code for *EVERY* instruction. + + ctx = CPU context + w16 = 16-bit operand flag + d32 = 386+ 32-bit data size override (ignored if w16 == 0) + mod/rm = mod/reg/rm unpacked byte + op8 = function to call for emulation of instruction, given 8-bit operand "src" + op16 = function to call for emulation of instruction, given 16-bit operand "src" + op32 = function to call for emulation of instruction, given 32-bit operand "src" + + INC BX + INC WORD PTR [2045h] +*/ +void sx86_exec_full_modrmonly_rw(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte rm,sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src),sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src)) +{ + if (mod == 3) { /* immediate <-> register */ + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword rmv; + + rmv = ctx->state->general_reg[rm].w.lo; + + ctx->state->general_reg[rm].w.lo = + op16(ctx,rmv); + } + else { + sx86_ubyte rmv; + + rmv = *(ctx->__private->ptr_regs_8reg[rm]); + + *(ctx->__private->ptr_regs_8reg[rm]) = + op8(ctx,rmv); + } + } + else { /* immediate <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword rmv; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,2); + SWAP_WORD_FROM_LE(rmv); + + rmv = op16(ctx,rmv); + SWAP_WORD_TO_LE(rmv); + softx86_write(ctx,NULL,lo,&rmv,2); + } + else { + sx86_ubyte rmv; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,1); + + rmv = op8(ctx,rmv); + softx86_write(ctx,NULL,lo,&rmv,1); + } + } +} + +/* general purpose mod/rm executioneer helper for + instructions that do not modify the destination operand + and do not have an immediate operand of specified size. + + this is provided to avoid copy and pasting this source code into the emulation + code for *EVERY* instruction. + + ctx = CPU context + w16 = 16-bit operand flag + d32 = 386+ 32-bit data size override (ignored if w16 == 0) + mod/rm = mod/reg/rm unpacked byte + op8 = function to call for emulation of instruction, given 8-bit operand "src" + op16 = function to call for emulation of instruction, given 16-bit operand "src" + op32 = function to call for emulation of instruction, given 32-bit operand "src" + + CALL WORD PTR [2045h] +*/ +void sx86_exec_full_modrmonly_ro(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte rm,sx86_ubyte (*op8)(softx86_ctx* ctx,sx86_ubyte src),sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src),sx86_udword (*op32)(softx86_ctx* ctx,sx86_udword src)) +{ + if (mod == 3) { /* immediate <-> register */ + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + op16(ctx,ctx->state->general_reg[rm].w.lo); + } + else { + op8(ctx,*(ctx->__private->ptr_regs_8reg[rm])); + } + } + else { /* immediate <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword rmv; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,2); + SWAP_WORD_FROM_LE(rmv); + op16(ctx,rmv); + } + else { + sx86_ubyte rmv; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,1); + op8(ctx,rmv); + } + } +} + +/* general purpose mod/rm executioneer helper for + instructions that modify the destination operand + and do not have an immediate operand of specified size. + these functions do not consider the previous value. + + this is provided to avoid copy and pasting this source code into the emulation + code for *EVERY* instruction. + + ctx = CPU context + w16 = 16-bit operand flag + d32 = 386+ 32-bit data size override (ignored if w16 == 0) + mod/rm = mod/reg/rm unpacked byte + op8 = function to call for emulation of instruction, given 8-bit operand "src" + op16 = function to call for emulation of instruction, given 16-bit operand "src" + op32 = function to call for emulation of instruction, given 32-bit operand "src" + + POP WORD PTR [2045h] +*/ +void sx86_exec_full_modrmonly_wo(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte rm,sx86_ubyte (*op8)(softx86_ctx* ctx),sx86_uword (*op16)(softx86_ctx* ctx),sx86_udword (*op32)(softx86_ctx* ctx)) +{ + if (mod == 3) { /* immediate <-> register */ + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + ctx->state->general_reg[rm].w.lo = op16(ctx); + } + else { + *(ctx->__private->ptr_regs_8reg[rm]) = op8(ctx); + } + } + else { /* immediate <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword rmv; + + lo = sx86_far_to_linear(ctx,seg,ofs); + rmv = op16(ctx); + SWAP_WORD_TO_LE(rmv); + softx86_write(ctx,NULL,lo,&rmv,2); + } + else { + sx86_ubyte rmv; + + lo = sx86_far_to_linear(ctx,seg,ofs); + rmv = op8(ctx); + softx86_write(ctx,NULL,lo,&rmv,1); + } + } +} + +/* general purpose mod/rm executioneer helper for + instructions that need a segment:offset pair + and do not have an immediate operand of specified size. + + this is provided to avoid copy and pasting this source code into the emulation + code for *EVERY* instruction. + + ctx = CPU context + d32 = 386+ 32-bit data size override (ignored if w16 == 0) + mod/rm = mod/reg/rm unpacked byte + op8 = function to call for emulation of instruction, given 8-bit operand "src" + op16 = function to call for emulation of instruction, given 16-bit operand "src" + op32 = function to call for emulation of instruction, given 32-bit operand "src" + + CALL FAR WORD PTR [2045h] +*/ +void sx86_exec_full_modrmonly_callfar(softx86_ctx* ctx,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte rm,void (*op16)(softx86_ctx* ctx,sx86_uword seg,sx86_uword ofs),void (*op32)(softx86_ctx* ctx,sx86_udword seg,sx86_udword ofs)) +{ + if (mod == 3) { /* immediate <-> register */ + // invalid, since a seg:off pair does not fit in a register + } + else { /* immediate <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + { + sx86_uword rmv,rmv2; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,2); lo += 2; + softx86_fetch(ctx,NULL,lo,&rmv2,2); + SWAP_WORD_FROM_LE(rmv); + SWAP_WORD_FROM_LE(rmv2); + op16(ctx,rmv2,rmv); + } + } +} + +/* general purpose mod/reg/rm executioneer helper for + the XCHG instruction. + + this is provided to avoid copy and pasting this source code into the emulation + code for *EVERY* instruction. + + ctx = CPU context + w16 = 16-bit operand flag + d32 = 386+ 32-bit data size override (ignored if w16 == 0) + mod/reg/rm = mod/reg/rm unpacked byte +*/ +void sx86_exec_full_modregrm_xchg(softx86_ctx* ctx,sx86_ubyte w16,sx86_ubyte d32,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm) +{ + if (mod == 3) { /* register <-> register */ + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword tmp; + + tmp = ctx->state->general_reg[reg].w.lo; + ctx->state->general_reg[reg].w.lo = ctx->state->general_reg[rm].w.lo; + ctx->state->general_reg[rm].w.lo = tmp; + } + else { + sx86_ubyte tmp; + + tmp = *(ctx->__private->ptr_regs_8reg[reg]); + *(ctx->__private->ptr_regs_8reg[reg]) = *(ctx->__private->ptr_regs_8reg[rm]); + *(ctx->__private->ptr_regs_8reg[rm]) = tmp; + } + } + else { /* register <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + if (w16) { + sx86_uword tmp,mem; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&mem,2); + SWAP_WORD_FROM_LE(mem); + tmp = ctx->state->general_reg[reg].w.lo; + SWAP_WORD_TO_LE(tmp); + softx86_write(ctx,NULL,lo,&tmp,2); + ctx->state->general_reg[reg].w.lo = mem; + } + else { + sx86_ubyte tmp,mem; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&mem,1); + tmp = *(ctx->__private->ptr_regs_8reg[reg]); + softx86_write(ctx,NULL,lo,&tmp,1); + *(ctx->__private->ptr_regs_8reg[reg]) = mem; + } + } +} + +int softx86_parity8(sx86_ubyte ret) +{ + int b,p; + + p=1; + for (b=0;b < 8;b++) { + p ^= (ret&1); + ret >>= 1; + } + + return p; +} + +int softx86_parity16(sx86_uword ret) +{ + int b,p; + + p=1; + for (b=0;b < 16;b++) { + p ^= (ret&1); + ret >>= 1; + } + + return p; +} + +int softx86_parity32(sx86_udword ret) +{ + int b,p; + + p=1; + for (b=0;b < 32;b++) { + p ^= (ret&1); + ret >>= 1; + } + + return p; +} + +int softx86_parity64(sx86_uldword ret) +{ + int b,p; + + p=1; + for (b=0;b < 64;b++) { + p ^= (ret&1); + ret >>= 1; + } + + return p; +} + +void sx86_exec_full_modrmonly_memx(softx86_ctx* ctx,sx86_ubyte mod,sx86_ubyte rm,int sz,void (*op64)(softx86_ctx* ctx,char *datz,int sz)) +{ + if (sz > 16) + return; + + if (mod == 3) { /* immediate <-> register */ + // invalid + } + else { /* immediate <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + { + sx86_ubyte tmp[16]; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,tmp,sz); + op64(ctx,(char*)tmp,sz); + } + } +} + +void sx86_exec_full_modrw_memx(softx86_ctx* ctx,sx86_ubyte mod,sx86_ubyte rm,int sz,void (*op64)(softx86_ctx* ctx,char *datz,int sz)) +{ + if (sz > 16) + return; + + if (mod == 3) { /* immediate <-> register */ + // invalid + } + else { /* immediate <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + // TODO: For 386+ 32-bit instructions... if (d32) {...} + { + sx86_ubyte tmp[16]; + + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,tmp,sz); + op64(ctx,(char*)tmp,sz); + softx86_write(ctx,NULL,lo,tmp,sz); + } + } +} + +/* general purpose mod/segreg/rm executioneer helper for + instructions that modify the destination operand. + + this is provided to avoid copy and pasting this source code into the emulation + of *EVERY* instruction. + + ctx = CPU context + mod/reg/rm = mod/reg/rm unpacked byte + op16 = function to call for emulation of instruction, given 16-bit operands "src" and "dst" + + MOV AX,ES + MOV CS,BX + MOV ES,WORD PTR [3939h] + MOV WORD PTR [9393h],DS +*/ +void sx86_exec_full_modsregrm_rw(softx86_ctx* ctx,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm,sx86_ubyte opswap,sx86_uword (*op16)(softx86_ctx* ctx,sx86_uword src,sx86_uword val)) +{ + sx86_uword regv,rmv; + +/* because not all segreg values are valid, check validity now! */ + if (reg >= 4) { /* the 8086 does not have FS and GS */ +/* TODO: Invalid opcode exception */ + return; + } + + if (mod == 3) { /* segment register <-> register */ + regv = ctx->state->segment_reg[reg].val; + rmv = ctx->state->general_reg[rm].w.lo; + + if (opswap) { +/* REMEMBER: WE NEVER DIRECTLY MODIFY THE SEGMENT REGISTER VALUES! */ +/* *(ctx->ptr_segregs[reg]) = + op16(ctx,rmv,regv); */ + softx86_setsegval(ctx,reg,rmv); + } + else { + ctx->state->general_reg[rm].w.lo = + op16(ctx,rmv,regv); + } + } + else { /* segment register <-> memory */ + sx86_uword seg,ofs; + sx86_udword lo; + + if (!ctx->state->is_segment_override) +/* apparently if BP is used (i.e. [BP+BX]) the stack segment is assumed. */ + if ((rm == 2 || rm == 3) || (rm == 6 && (mod == 1 || mod == 2))) + seg = ctx->state->segment_reg[SX86_SREG_SS].val; + else + seg = ctx->state->segment_reg[SX86_SREG_DS].val; + else + seg = ctx->state->segment_override; + +/* figure out the memory address */ + if (mod == 0) { + if (rm == 6) { + ofs = softx86_fetch_exec_byte(ctx); + ofs |= softx86_fetch_exec_byte(ctx)<<8; + } + else if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + } + else { + sx86_uword xx; + + if (rm == 0) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 1) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 2) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 3) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo + + ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 4) + ofs = ctx->state->general_reg[SX86_REG_SI].w.lo; + else if (rm == 5) + ofs = ctx->state->general_reg[SX86_REG_DI].w.lo; + else if (rm == 6) + ofs = ctx->state->general_reg[SX86_REG_BP].w.lo; + else if (rm == 7) + ofs = ctx->state->general_reg[SX86_REG_BX].w.lo; + + if (mod == 1) { + xx = softx86_fetch_exec_byte(ctx); + if (xx & 0x80) xx |= 0xFF00; + } + else { + xx = softx86_fetch_exec_byte(ctx); + xx |= softx86_fetch_exec_byte(ctx)<<8; + } + + ofs = FORCE_WORD_SIZE(ofs + xx); + } + + regv = ctx->state->segment_reg[reg].val; + lo = sx86_far_to_linear(ctx,seg,ofs); + softx86_fetch(ctx,NULL,lo,&rmv,2); + SWAP_WORD_FROM_LE(rmv); + + if (opswap) { +/* REMEMBER: WE NEVER DIRECTLY MODIFY THE SEGMENT REGISTER VALUES! */ +/* *(ctx->ptr_segregs[reg]) = + op16(ctx,rmv,regv); */ + softx86_setsegval(ctx,reg,rmv); + } + else { + rmv = op16(ctx,rmv,regv); + SWAP_WORD_TO_LE(rmv); + softx86_write(ctx,NULL,lo,&rmv,2); + } + } +} + +/* basic mod/reg/rm full-use decompiling. + ctx = CPU context struct + is_word = word value + dat32 = 32-bit 386+ data override + mod/reg/rm + op1 = buffer for r/m + op2 = buffer for reg */ +void sx86_dec_full_modregrm(softx86_ctx* ctx,sx86_ubyte is_word,sx86_ubyte dat32,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm,char* op1,char* op2) +{ + sx86_uword o; + + if (is_word) + if (dat32) + sprintf(op2,"%s",sx86_regs32[reg]); + else + sprintf(op2,"%s",sx86_regs16[reg]); + else + sprintf(op2,"%s",sx86_regs8[reg]); + + if (mod == 3) { /* destination: register */ + if (is_word) + if (dat32) + sprintf(op1,"%s",sx86_regs32[rm]); + else + sprintf(op1,"%s",sx86_regs16[rm]); + else + sprintf(op1,"%s",sx86_regs8[rm]); + } + else if (mod == 0) { /* destination: memory address */ + if (rm == 6) { + o = softx86_fetch_dec_byte(ctx); + o |= softx86_fetch_dec_byte(ctx)<<8; + sprintf(op1,"[%04Xh]",o); + } + else { + sprintf(op1,"[%s]",sx86_regsaddr16_16[rm]); + } + } + else { /* destination: memory address + offset */ + if (mod == 1) { + o = softx86_fetch_dec_byte(ctx); + if (o & 0x80) o |= 0xFF00; + } + else if (mod == 2) { + o = softx86_fetch_dec_byte(ctx); + o |= softx86_fetch_dec_byte(ctx)<<8; + } + + sprintf(op1,"[%s+%04Xh]",sx86_regsaddr16_16[rm],o); + } +} + +/* basic mod/rm full-use decompiling (reg used for another purpose) + ctx = CPU context struct + is_word = word value + dat32 = 32-bit 386+ data override + mod/rm + op1 = buffer for r/m */ +void sx86_dec_full_modrmonly(softx86_ctx* ctx,sx86_ubyte is_word,sx86_ubyte dat32,sx86_ubyte mod,sx86_ubyte rm,char* op1) +{ + sx86_uword o; + + if (mod == 3) { /* destination: register */ + if (is_word) + if (dat32) + sprintf(op1,"%s",sx86_regs32[rm]); + else + sprintf(op1,"%s",sx86_regs16[rm]); + else + sprintf(op1,"%s",sx86_regs8[rm]); + } + else if (mod == 0) { /* destination: memory address */ + if (rm == 6) { + o = softx86_fetch_dec_byte(ctx); + o |= softx86_fetch_dec_byte(ctx)<<8; + sprintf(op1,"[%04Xh]",o); + } + else { + sprintf(op1,"[%s]",sx86_regsaddr16_16[rm]); + } + } + else { /* destination: memory address + offset */ + if (mod == 1) { + o = softx86_fetch_dec_byte(ctx); + if (o & 0x80) o |= 0xFF00; + } + else if (mod == 2) { + o = softx86_fetch_dec_byte(ctx); + o |= softx86_fetch_dec_byte(ctx)<<8; + } + + sprintf(op1,"[%s+%04Xh]",sx86_regsaddr16_16[rm],o); + } +} + +/* basic mod/segreg/rm full-use decompiling. + ctx = CPU context struct + is_word = word value + dat32 = 32-bit 386+ data override + mod/reg/rm where "reg" refers to a segment register + op1 = buffer for r/m + op2 = buffer for reg */ +void sx86_dec_full_modsregrm(softx86_ctx* ctx,sx86_ubyte mod,sx86_ubyte reg,sx86_ubyte rm,char* op1,char* op2) +{ + sx86_uword o; + + sprintf(op2,"%s",sx86_segregs[reg]); + + if (mod == 3) { /* destination: register */ + sprintf(op1,"%s",sx86_regs16[rm]); + } + else if (mod == 0) { /* destination: memory address */ + if (rm == 6) { + o = softx86_fetch_dec_byte(ctx); + o |= softx86_fetch_dec_byte(ctx)<<8; + sprintf(op1,"[%04Xh]",o); + } + else { + sprintf(op1,"[%s]",sx86_regsaddr16_16[rm]); + } + } + else { /* destination: memory address + offset */ + if (mod == 1) { + o = softx86_fetch_dec_byte(ctx); + if (o & 0x80) o |= 0xFF00; + } + else if (mod == 2) { + o = softx86_fetch_dec_byte(ctx); + o |= softx86_fetch_dec_byte(ctx)<<8; + } + + sprintf(op1,"[%s+%04Xh]",sx86_regsaddr16_16[rm],o); + } +} + Index: lib/3rdparty/softx86/softx86/softx86.c =================================================================== --- lib/3rdparty/softx86/softx86/softx86.c (révision 59666) +++ lib/3rdparty/softx86/softx86/softx86.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/softx86.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/softx86_dll.def =================================================================== --- lib/3rdparty/softx86/softx86/softx86_dll.def (révision 0) +++ lib/3rdparty/softx86/softx86/softx86_dll.def (copie de travail) @@ -0,0 +1,52 @@ + +LIBRARY SOFTX86 +EXPORTS softx86_bswap2 + softx86_bswap4 + softx86_init + softx86_free + softx86_step + softx86_decompile + softx86_decompile_exec_cs_ip + softx86_stack_popw + softx86_stack_discard_n + softx86_stack_add_n + softx86_stack_pushw + softx86_fetch + softx86_write + softx86_fetch_exec_byte + softx86_fetch_dec_byte + softx86_setsegval + softx86_set_instruction_ptr + softx86_set_instruction_dec_ptr + softx86_set_stack_ptr + softx86_set_near_instruction_ptr + softx86_reset + softx86_getversion + softx86_parity8 + softx86_parity16 + softx86_parity32 + softx86_parity64 + softx86_ext_hw_signal + softx86_ext_hw_ack + softx86_int_sw_signal + softx86_ext_hw_nmi_signal + softx86_ext_hw_nmi_ack + sx86_exec_full_modregrm_rw + sx86_exec_full_modregrm_ro + sx86_exec_full_modsregrm_rw + sx86_exec_full_modrmonly_rw + sx86_exec_full_modrmonly_rw_imm + sx86_exec_full_modrmonly_rw_imm8 + sx86_exec_full_modrmonly_ro_imm + sx86_exec_full_modregrm_xchg + sx86_exec_full_modregrm_lea + sx86_exec_full_modrmonly_callfar + sx86_exec_full_modrmonly_ro + sx86_exec_full_modrmonly_wo + sx86_exec_full_modregrm_far + sx86_exec_full_modregrm_far_ro3 + sx86_exec_full_modrmonly_memx + sx86_exec_full_modrw_memx + sx86_dec_full_modrmonly + sx86_dec_full_modregrm + sx86_dec_full_modsregrm Index: lib/3rdparty/softx86/softx86/softx86_dll.def =================================================================== --- lib/3rdparty/softx86/softx86/softx86_dll.def (révision 59666) +++ lib/3rdparty/softx86/softx86/softx86_dll.def (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/softx86_dll.def ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/softx86_dll.dsp =================================================================== --- lib/3rdparty/softx86/softx86/softx86_dll.dsp (révision 0) +++ lib/3rdparty/softx86/softx86/softx86_dll.dsp (copie de travail) @@ -0,0 +1,109 @@ +# Microsoft Developer Studio Project File - Name="softx86_dll" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=softx86_dll - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "softx86_dll.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "softx86_dll.mak" CFG="softx86_dll - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "softx86_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "softx86_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "softx86_dll - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOFTX86_DLL_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /I ".\\" /I "..\include\\" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOFTX86_DLL_EXPORTS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"..\bin\softx86.dll" /implib:"../lib/softx86_dll.lib" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "softx86_dll - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOFTX86_DLL_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I ".\\" /I "..\include\\" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOFTX86_DLL_EXPORTS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\lib\softx86_static.lib /nologo /dll /debug /machine:I386 /out:"..\bin\softx86.dll" /implib:"../lib/softx86_dll.lib" /pdbtype:sept +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "softx86_dll - Win32 Release" +# Name "softx86_dll - Win32 Debug" +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\softx86_dll.rc +# End Source File +# End Group +# Begin Group "DLL export definitions" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\softx86_dll.def +# End Source File +# End Group +# End Target +# End Project Index: lib/3rdparty/softx86/softx86/softx86_dll.dsp =================================================================== --- lib/3rdparty/softx86/softx86/softx86_dll.dsp (révision 59666) +++ lib/3rdparty/softx86/softx86/softx86_dll.dsp (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/softx86_dll.dsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/softx86_dll.rc =================================================================== --- lib/3rdparty/softx86/softx86/softx86_dll.rc (révision 0) +++ lib/3rdparty/softx86/softx86/softx86_dll.rc (copie de travail) @@ -0,0 +1,109 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,0,0,33 + PRODUCTVERSION 0,0,0,33 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "\0" + VALUE "FileDescription", "Softx86 library v0.00.0033\0" + VALUE "FileVersion", "0, 0, 0, 33\0" + VALUE "InternalName", "softx86.dll\0" + VALUE "LegalCopyright", "Copyright © 2003, 2004 Jonathan Campbell\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "softx86.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "Softx86\0" + VALUE "ProductVersion", "0, 0, 0, 33\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + Index: lib/3rdparty/softx86/softx86/softx86_dll.rc =================================================================== --- lib/3rdparty/softx86/softx86/softx86_dll.rc (révision 59666) +++ lib/3rdparty/softx86/softx86/softx86_dll.rc (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/softx86_dll.rc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86/softx86_static.dsp =================================================================== --- lib/3rdparty/softx86/softx86/softx86_static.dsp (révision 0) +++ lib/3rdparty/softx86/softx86/softx86_static.dsp (copie de travail) @@ -0,0 +1,252 @@ +# Microsoft Developer Studio Project File - Name="softx86_static" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=softx86_static - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "softx86_static.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "softx86_static.mak" CFG="softx86_static - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "softx86_static - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "softx86_static - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "softx86_static - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I ".\\" /I "..\include\\" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\lib\softx86_static.lib" + +!ELSEIF "$(CFG)" == "softx86_static - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I ".\\" /I "..\include\\" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\lib\softx86_static.lib" + +!ENDIF + +# Begin Target + +# Name "softx86_static - Win32 Release" +# Name "softx86_static - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\aaa.c +# End Source File +# Begin Source File + +SOURCE=.\add.c +# End Source File +# Begin Source File + +SOURCE=.\binops.c +# End Source File +# Begin Source File + +SOURCE=.\cbw.c +# End Source File +# Begin Source File + +SOURCE=.\clc.c +# End Source File +# Begin Source File + +SOURCE=.\drooling_duh.c +# End Source File +# Begin Source File + +SOURCE=.\fpu.c +# End Source File +# Begin Source File + +SOURCE=.\groupies.c +# End Source File +# Begin Source File + +SOURCE=.\inc.c +# End Source File +# Begin Source File + +SOURCE=.\interrupts.c +# End Source File +# Begin Source File + +SOURCE=.\ioport.c +# End Source File +# Begin Source File + +SOURCE=.\jumpy.c +# End Source File +# Begin Source File + +SOURCE=.\mov.c +# End Source File +# Begin Source File + +SOURCE=.\optable.c +# End Source File +# Begin Source File + +SOURCE=.\prefixes.c +# End Source File +# Begin Source File + +SOURCE=.\procframe.c +# End Source File +# Begin Source File + +SOURCE=.\pushpop.c +# End Source File +# Begin Source File + +SOURCE=.\shovel.c +# End Source File +# Begin Source File + +SOURCE=.\softx86.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\aaa.h +# End Source File +# Begin Source File + +SOURCE=.\add.h +# End Source File +# Begin Source File + +SOURCE=.\binops.h +# End Source File +# Begin Source File + +SOURCE=.\cbw.h +# End Source File +# Begin Source File + +SOURCE=.\clc.h +# End Source File +# Begin Source File + +SOURCE=.\drooling_duh.h +# End Source File +# Begin Source File + +SOURCE=.\fpu.h +# End Source File +# Begin Source File + +SOURCE=.\groupies.h +# End Source File +# Begin Source File + +SOURCE=.\inc.h +# End Source File +# Begin Source File + +SOURCE=.\interrupts.h +# End Source File +# Begin Source File + +SOURCE=.\ioport.h +# End Source File +# Begin Source File + +SOURCE=.\jumpy.h +# End Source File +# Begin Source File + +SOURCE=.\mov.h +# End Source File +# Begin Source File + +SOURCE=.\optable.h +# End Source File +# Begin Source File + +SOURCE=.\prefixes.h +# End Source File +# Begin Source File + +SOURCE=.\procframe.h +# End Source File +# Begin Source File + +SOURCE=.\pushpop.h +# End Source File +# Begin Source File + +SOURCE=.\shovel.h +# End Source File +# Begin Source File + +SOURCE=..\include\softx86.h +# End Source File +# Begin Source File + +SOURCE=..\include\softx86cfg.h +# End Source File +# End Group +# Begin Source File + +SOURCE=..\readme.txt +# End Source File +# End Target +# End Project Index: lib/3rdparty/softx86/softx86/softx86_static.dsp =================================================================== --- lib/3rdparty/softx86/softx86/softx86_static.dsp (révision 59666) +++ lib/3rdparty/softx86/softx86/softx86_static.dsp (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx86/softx86_static.dsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx86_ros.diff =================================================================== --- lib/3rdparty/softx86/softx86_ros.diff (révision 0) +++ lib/3rdparty/softx86/softx86_ros.diff (copie de travail) @@ -0,0 +1,64 @@ +Index: softx86/optable.c +=================================================================== +--- softx86/optable.c (révision 59247) ++++ softx86/optable.c (copie de travail) +@@ -217,9 +217,9 @@ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x66 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x67 */ + +- {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x68 */ ++ {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x68 */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x69 */ +- {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x6A */ ++ {Sfx86OpcodeExec_push, Sfx86OpcodeDec_push}, /* 0x6A */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x6B */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x6C */ + {Sfx86OpcodeExec_default, Sfx86OpcodeDec_default}, /* 0x6D */ +Index: softx86/pushpop.c +=================================================================== +--- softx86/pushpop.c (révision 59247) ++++ softx86/pushpop.c (copie de travail) +@@ -167,6 +167,21 @@ + return 1; + } + ++ if (opcode == 0x6A) // PUSH imm8 ++ { ++ sx86_ubyte b = softx86_fetch_exec_byte(ctx); ++ softx86_stack_pushw(ctx, (sx86_uword)b); ++ return 1; ++ } ++ ++ if (opcode == 0x68) // PUSH imm16 ++ { ++ sx86_uword w = softx86_fetch_exec_byte(ctx); ++ w |= softx86_fetch_exec_byte(ctx) << 8; ++ softx86_stack_pushw(ctx, w); ++ return 1; ++ } ++ + return 0; + } + +@@ -202,6 +217,21 @@ + return 1; + } + ++ if (opcode == 0x6A && ctx->__private->level >= SX86_CPULEVEL_80186) // PUSH imm8 ++ { ++ sx86_ubyte b = softx86_fetch_exec_byte(ctx); ++ sprintf(buf, "PUSH %02Xh", b); ++ return 1; ++ } ++ ++ if (opcode == 0x68 && ctx->__private->level >= SX86_CPULEVEL_80186) // PUSH imm16 ++ { ++ sx86_uword w = softx86_fetch_exec_byte(ctx); ++ w |= softx86_fetch_exec_byte(ctx) << 8; ++ sprintf(buf, "PUSH %04Xh", w); ++ return 1; ++ } ++ + return 0; + } + Index: lib/3rdparty/softx86/softx87 =================================================================== --- lib/3rdparty/softx86/softx87 (révision 59666) +++ lib/3rdparty/softx86/softx87 (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx87 ___________________________________________________________________ Added: bugtraq:url ## -0,0 +1 ## +http://www.reactos.org/bugzilla/show_bug.cgi?id=%BUGID% \ No newline at end of property Added: bugtraq:message ## -0,0 +1 ## +See issue #%BUGID% for more details. \ No newline at end of property Added: tsvn:logminsize ## -0,0 +1 ## +10 \ No newline at end of property Added: bugtraq:logregex ## -0,0 +1,2 ## +([Ii]ssue|[Bb]ug)s? #?(\d+)(,? ?#?(\d+))*(,? ?(and |or )?#?(\d+))? +(\d+) \ No newline at end of property Index: lib/3rdparty/softx86/softx87/CMakeLists.txt =================================================================== --- lib/3rdparty/softx86/softx87/CMakeLists.txt (révision 0) +++ lib/3rdparty/softx86/softx87/CMakeLists.txt (copie de travail) @@ -0,0 +1,13 @@ + +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/softx86) + +list(APPEND SOURCE + optable.c + softx87.c +### Uncomment the following files for dll compilation: +# windll.c +# softx87_dll.def +# softx87_dll.rc +) + +add_library(softx87 ${SOURCE}) Index: lib/3rdparty/softx86/softx87/CMakeLists.txt =================================================================== --- lib/3rdparty/softx86/softx87/CMakeLists.txt (révision 59666) +++ lib/3rdparty/softx86/softx87/CMakeLists.txt (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx87/CMakeLists.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx87/Makefile =================================================================== --- lib/3rdparty/softx86/softx87/Makefile (révision 0) +++ lib/3rdparty/softx86/softx87/Makefile (copie de travail) @@ -0,0 +1,41 @@ +# SOFTX87 Makefile for Linux/GCC 3.xx +# (C) 2003 Jonathan Campbell +# +# NOTE: Assumes subdirectory ./obj/ and places all object files there +# rather than mix them up with the source code. It's less messy +# that way. The only exception is the final output, softx86.o. + +all:: __obj ../lib/libsoftx87.a ../lib/libsoftx87.so + +ALL_OBJS = obj/optable.o obj/softx87.o + +INCLUDZ = -I../include + +clean:: + rm -f $(ALL_OBJS) + +distclean:: clean + rm -f ../lib/libsoftx87.a + rm -f ../lib/libsoftx87.so + if [[ -d obj ]]; then rmdir obj; fi + if [[ -d Release ]]; then rm -R Release; fi + if [[ -d Debug ]]; then rm -R Debug; fi + rm -f *.plg + rm -f *.aps + +# make sure there is an "obj" subdirectory +__obj: + if [[ !(-d obj) ]]; then mkdir obj; fi + +../lib/libsoftx87.a: $(ALL_OBJS) + ld -aarchive -r -o ../lib/libsoftx87.a $(ALL_OBJS) + +../lib/libsoftx87.so: $(ALL_OBJS) + ld -shared -o ../lib/libsoftx87.so $(ALL_OBJS) + +obj/optable.o: optable.c + gcc $(INCLUDZ) -c -o obj/optable.o optable.c + +obj/softx87.o: softx87.c + gcc $(INCLUDZ) -c -o obj/softx87.o softx87.c + Index: lib/3rdparty/softx86/softx87/Makefile =================================================================== --- lib/3rdparty/softx86/softx87/Makefile (révision 59666) +++ lib/3rdparty/softx86/softx87/Makefile (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx87/Makefile ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx87/optab87.h =================================================================== --- lib/3rdparty/softx86/softx87/optab87.h (révision 0) +++ lib/3rdparty/softx86/softx87/optab87.h (copie de travail) @@ -0,0 +1,26 @@ + +// return value: +// 0 = opcode not recognized +// 1 = opcode recognized, parsing complete +// 2 = opcode recognized, more parsing needed (i.e., prefix) +typedef int (*Sfx87OpcodeExec)(sx86_ubyte opcode,softx87_ctx* ctx); +typedef int (*Sfx87OpcodeDec)(sx86_ubyte opcode,softx87_ctx* ctx,char buf[128]); + +typedef struct { + Sfx87OpcodeExec exec; + Sfx87OpcodeDec dec; +} Sfx87Opcode; + +/* for sanity's sake we only look at the + upper 3 bits of the 11-bit opcode. + the opcode arrangement of FPU opcodes + makes a lot less sense than the CPU + opcode arrangement. */ +typedef struct { + Sfx87Opcode table[8]; +} Sfx87OpcodeTable; + +extern Sfx87OpcodeTable optab8087; + +extern char s87op1_tmp[32]; +extern char s87op2_tmp[32]; Index: lib/3rdparty/softx86/softx87/optab87.h =================================================================== --- lib/3rdparty/softx86/softx87/optab87.h (révision 59666) +++ lib/3rdparty/softx86/softx87/optab87.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx87/optab87.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx87/optable.c =================================================================== --- lib/3rdparty/softx86/softx87/optable.c (révision 0) +++ lib/3rdparty/softx86/softx87/optable.c (copie de travail) @@ -0,0 +1,1994 @@ +/* + * optable.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Opcode jumptable. + * + * Allows the recognition of many opcodes without having to write approximately + * 500+ if...then...else statements which is a) inefficient and b) apparently can + * cause some compilers such as Microsoft C++ to crash during the compile stage with + * an error. Since it's a table, it can be referred to via a pointer that can be easily + * redirected to other opcode tables (i.e., one for the 8086, one for the 80286, etc.) + * without much hassle. + * + * The table contains two pointers: one for an "execute" function, and one for a + * "decompile" function. The execute function is given the context and the initial opcode. + * If more opcodes are needed the function calls softx86_fetch_exec_byte(). The decode + * function is also given the opcode but also a char[] array where it is expected to + * sprintf() or strcpy() the disassembled output. If that function needs more opcodes + * it calls softx86_fetch_dec_byte(). + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include +#include "optab87.h" + +void op_fcom(softx87_ctx* ctx,softx87_reg80 *dst,softx87_reg80 *src); +void op_fadd(softx87_ctx* ctx,softx87_reg80 *dst,softx87_reg80 *src); +void op_fsub(softx87_ctx* ctx,softx87_reg80 *dst,softx87_reg80 *src); +void op_fdiv(softx87_ctx* ctx,softx87_reg80 *dst,softx87_reg80 *src); +void op_fdivr(softx87_ctx* ctx,softx87_reg80 *dst,softx87_reg80 *src); + +char s87op1_tmp[32]; +char s87op2_tmp[32]; + +/* pops value from FPU stack */ +void softx86_popstack(softx87_ctx* ctx87) +{ + int TOP; + + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + SX87_FPUTAGW_TAG_SET(ctx87->state.tag_word,TOP,SX87_FPUTAGVAL_EMPTY); + TOP = (TOP+1)&7; + SX87_FPUSTAT_TOP_SET(ctx87->state.status_word,TOP); +} + +/* given an FPU register, convert to an integer */ +sx86_uldword sx87_getint(softx87_reg80 *r) +{ + sx86_uldword m; + sx86_uword e; + +// TODO: take into consideration the rounding mode + e = 63 - (r->exponent - 16383); + if (e > 63) { + m = 0; + } + else if (e > 0) { + // TODO: rounding mode? + m = r->mantissa >> ((sx86_uldword)(e)); + } + else if (e < 0) { + sx86_uldword n; + +/* first figure out if bits will be shifted out (too large). + if that's the case compensate by setting the mantissa to + the largest possible __uint64 value. */ + n = ((sx86_uldword)-1) << ((sx86_uldword)(63 + e)); + if (((sx86_uldword)(r->mantissa & n)) != ((sx86_uldword)0)) + m = (sx86_uldword)-1; + else + m = r->mantissa << ((sx86_uldword)(-e)); + } + else { + m = r->mantissa; + } + + return m; +} + +/* FBSTP 80 */ +void op_fbstp80(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + int i; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 10 || !ctx87) return; + + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + +/* TODO: check and perform cases as documented: + +-infinity = #IA exception +-infinity = #IA exception + + TODO: what do we do really if the entry is empty? +*/ + tmp.sign_bit = ctx87->state.st[TOP].sign_bit; + tmp.mantissa = ctx87->state.st[TOP].mantissa; + tmp.exponent = ctx87->state.st[TOP].exponent; + +/* shift data around to produce integer version. */ +/* if it's too large, clip it */ + tmp.mantissa = sx87_getint(&tmp); + +/* if too large for BCD coding, clip it. */ + if (tmp.mantissa > 999999999999999999) /* 18 digits usable, so... */ + tmp.mantissa = 999999999999999999; /* clip if >= 10^19 */ + +/* put it out there */ + for (i=0;i < 9;i++) { + datz[i] = (char)(tmp.mantissa % ((sx86_uldword)10)); + tmp.mantissa /= (sx86_uldword)10; + datz[i] |= ((char)(tmp.mantissa % ((sx86_uldword)10)))<<4; + tmp.mantissa /= (sx86_uldword)10; + } + + datz[9] = tmp.sign_bit ? ((char)0x80) : 0x00; + +/* pop */ + softx86_popstack(ctx->ref_softx87_ctx); +} + +/* the hard work behind FLD [mem32] is here */ +void op_fld32(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 4 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_fp32(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); +/* set C1 if stack overflow */ + if (SX87_FPUTAGW_TAG(ctx87->state.tag_word,TOP) != SX87_FPUTAGVAL_EMPTY) + ctx87->state.status_word |= SX87_FPUSTAT_C1; + else + ctx87->state.status_word &= ~SX87_FPUSTAT_C1; +/* decrement TOP, tag as valid */ + TOP = (TOP-1)&7; + SX87_FPUSTAT_TOP_SET(ctx87->state.status_word,TOP); + SX87_FPUTAGW_TAG_SET(ctx87->state.tag_word,TOP,SX87_FPUTAGVAL_VALID); +/* store */ + ctx87->state.st[TOP].exponent = tmp.exponent; + ctx87->state.st[TOP].mantissa = tmp.mantissa; + ctx87->state.st[TOP].sign_bit = tmp.sign_bit; +} + +/* the hard work behind FLD [mem64] is here */ +void op_fld64(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 8 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_fp64(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); +/* set C1 if stack overflow */ + if (SX87_FPUTAGW_TAG(ctx87->state.tag_word,TOP) != SX87_FPUTAGVAL_EMPTY) + ctx87->state.status_word |= SX87_FPUSTAT_C1; + else + ctx87->state.status_word &= ~SX87_FPUSTAT_C1; +/* decrement TOP, tag as valid */ + TOP = (TOP-1)&7; + SX87_FPUSTAT_TOP_SET(ctx87->state.status_word,TOP); + SX87_FPUTAGW_TAG_SET(ctx87->state.tag_word,TOP,SX87_FPUTAGVAL_VALID); +/* store */ + ctx87->state.st[TOP].exponent = tmp.exponent; + ctx87->state.st[TOP].mantissa = tmp.mantissa; + ctx87->state.st[TOP].sign_bit = tmp.sign_bit; +} + +/* FIADD [mem16] */ +void op_fiadd16(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 2 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_int16(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fadd(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FICOM [mem16] */ +void op_ficom16(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 2 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_int16(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fcom(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FICOMP [mem16] */ +void op_ficomp16(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 2 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_int16(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fcom(ctx87,&ctx87->state.st[TOP],&tmp); + softx86_popstack(ctx87); +} + +/* FICOM [mem32] */ +void op_ficom32(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 4 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_int32(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fcom(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FICOMP [mem32] */ +void op_ficomp32(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 4 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_int32(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fcom(ctx87,&ctx87->state.st[TOP],&tmp); + softx86_popstack(ctx87); +} + +/* FISUB [mem16] */ +void op_fisub16(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 2 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_int16(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fsub(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FIADD [mem32] */ +void op_fiadd32(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 4 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_int32(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fadd(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FISUB [mem32] */ +void op_fisub32(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 4 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_int32(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fsub(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FIDIV [mem32] */ +void op_fidiv32(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 4 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_int32(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fdiv(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FIDIVR [mem32] */ +void op_fidivr32(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 4 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_int32(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fdivr(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FIDIV [mem16] */ +void op_fidiv16(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 2 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_int16(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fdiv(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FIDIVR [mem16] */ +void op_fidivr16(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 2 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_int16(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fdivr(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FADD [mem32] */ +void op_fadd32(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 4 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_fp32(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fadd(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FDIV [mem32] */ +void op_fdiv32(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 4 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_fp32(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fdiv(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FDIVR [mem32] */ +void op_fdivr32(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 4 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_fp32(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fdivr(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FDIVR [mem64] */ +void op_fdivr64(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 8 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_fp64(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fdivr(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FDIV [mem64] */ +void op_fdiv64(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 8 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_fp64(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fdiv(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FSUB [mem32] */ +void op_fsub32(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 4 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_fp32(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fsub(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FADD [mem64] */ +void op_fadd64(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 8 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_fp64(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fadd(ctx87,&ctx87->state.st[TOP],&tmp); +} + +/* FSUB [mem64] */ +void op_fsub64(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 8 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_fp64(ctx87,datz,&tmp); +/* normalize */ + softx87_normalize(ctx87,&tmp); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + op_fsub(ctx87,&ctx87->state.st[TOP],&tmp); +} + +static void op_fcom_compflags(softx87_ctx* ctx,softx87_reg80 *diff) +{ + if (diff->mantissa == 0) { // equal (basically zero no matter what the exponent) + ctx->state.status_word |= SX87_FPUSTAT_C3; + ctx->state.status_word &= ~(SX87_FPUSTAT_C2 | SX87_FPUSTAT_C0); + } + else if (diff->sign_bit == 1) { // st0 < src + ctx->state.status_word |= SX87_FPUSTAT_C0; + ctx->state.status_word &= ~(SX87_FPUSTAT_C3 | SX87_FPUSTAT_C2); + } + else if (diff->sign_bit == 0) { // st0 > src + ctx->state.status_word &= ~(SX87_FPUSTAT_C3 | SX87_FPUSTAT_C2 | SX87_FPUSTAT_C0); + } + else { + // TODO + } +} + +/* FCOM [mem64] */ +void op_fcom64(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 src; + softx87_reg80 st0; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 8 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_fp64(ctx87,datz,&src); +/* normalize */ + softx87_normalize(ctx87,&src); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + memcpy(&st0,&ctx87->state.st[TOP],sizeof(softx87_reg80)); + softx87_normalize(ctx87,&st0); + op_fsub(ctx87,&st0,&src); // st0 -= src + +/* what is the result? */ + op_fcom_compflags(ctx87,&st0); +} + +/* FCOMP [mem64] */ +void op_fcomp64(softx86_ctx* ctx,char *datz,int sz) +{ + op_fcom64(ctx,datz,sz); + softx86_popstack(ctx->ref_softx87_ctx); +} + +/* FCOM [mem32] */ +void op_fcom32(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 src; + softx87_reg80 st0; + softx87_ctx* ctx87; + int TOP; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 4 || !ctx87) return; + +/* convert to 80-bit floating point */ + softx87_unpack_raw_fp32(ctx87,datz,&src); +/* normalize */ + softx87_normalize(ctx87,&src); + +/* do it */ + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); + memcpy(&st0,&ctx87->state.st[TOP],sizeof(softx87_reg80)); + softx87_normalize(ctx87,&st0); + op_fsub(ctx87,&st0,&src); // st0 -= src + +/* what is the result? */ + op_fcom_compflags(ctx87,&st0); +} + +/* FCOMP [mem32] */ +void op_fcomp32(softx86_ctx* ctx,char *datz,int sz) +{ + op_fcom32(ctx,datz,sz); + softx86_popstack(ctx->ref_softx87_ctx); +} + +/* FBLD [mem80] */ +void op_fbld80(softx86_ctx* ctx,char *datz,int sz) +{ + softx87_reg80 tmp; + softx87_ctx* ctx87; + int TOP,i; + +/* sanity check */ + ctx87 = (softx87_ctx*)ctx->ref_softx87_ctx; + if (sz != 10 || !ctx87) return; + +/* think of it as a string where each character is stored in one nibble + representing one digit. UNFORTUNATELY it's also stored backwards... */ + if (datz[9] & 0x80) tmp.sign_bit = 1; + else tmp.sign_bit = 0; + + tmp.exponent = 16383 + 63; + tmp.mantissa = (sx86_uldword)0; + for (i=17;i >= 0;i--) { + tmp.mantissa *= (sx86_uldword)10; + tmp.mantissa += (sx86_uldword)((datz[i>>1] >> ((i&1)*4))&0xF); + } + +/* normalize */ + softx87_normalize(ctx87,&tmp); + + TOP = SX87_FPUSTAT_TOP(ctx87->state.status_word); +/* set C1 if stack overflow */ + if (SX87_FPUTAGW_TAG(ctx87->state.tag_word,TOP) != SX87_FPUTAGVAL_EMPTY) + ctx87->state.status_word |= SX87_FPUSTAT_C1; + else + ctx87->state.status_word &= ~SX87_FPUSTAT_C1; +/* decrement TOP, tag as valid */ + TOP = (TOP-1)&7; + SX87_FPUSTAT_TOP_SET(ctx87->state.status_word,TOP); + SX87_FPUTAGW_TAG_SET(ctx87->state.tag_word,TOP,SX87_FPUTAGVAL_VALID); +/* store */ + ctx87->state.st[TOP].exponent = tmp.exponent; + ctx87->state.st[TOP].mantissa = tmp.mantissa; + ctx87->state.st[TOP].sign_bit = tmp.sign_bit; +} + +/* general purpose FADD */ +void op_fadd(softx87_ctx* ctx,softx87_reg80 *dst,softx87_reg80 *src) +{ + softx87_reg80 major; + softx87_reg80 minor; + sx87_uldword waste,threshhold; + int exb; +/* TODO: check and perform cases as documented: + +-infinity + (anything) = -infinity +-infinity + +infinity = #IA exception +NaN + (anything) = NaN +*/ + +/* in doing this... how many extra bits will we need? */ + exb = (int)(src->mantissa>>((sx87_uldword)63)); + exb |= (int)(dst->mantissa>>((sx87_uldword)63)); + if (src->sign_bit != dst->sign_bit) exb++; +/* avoid addition if it wouldn't make any difference */ + if (dst->exponent >= (src->exponent+(64-exb))) + return; +/* copy src => dst if the destination value is dwarfed by the source value */ + else if (dst->exponent <= (src->exponent-(64-exb))) { + memcpy(dst,src,sizeof(softx87_reg80)); + return; + } + +/* scale them up so their exponents match */ + if (dst->exponent > src->exponent) { + memcpy(&major,dst,sizeof(softx87_reg80)); + memcpy(&minor,src,sizeof(softx87_reg80)); + } + else if (dst->exponent < src->exponent) { + memcpy(&major,src,sizeof(softx87_reg80)); + memcpy(&minor,dst,sizeof(softx87_reg80)); + } + else { + memcpy(&major,dst,sizeof(softx87_reg80)); + memcpy(&minor,src,sizeof(softx87_reg80)); + } + +/* "major" should have the highest exponent */ + if ((major.exponent+exb) > minor.exponent) { + int b; + + b = (major.exponent - minor.exponent)+exb; + threshhold = (sx87_uldword)-1; + threshhold >>= (sx87_uldword)(64-b); + waste = minor.mantissa & threshhold; + threshhold = (threshhold+1)>>1; + +/* scale up the minor value */ + minor.exponent += b; + minor.mantissa >>= (sx87_uldword)b; +/* round it */ + switch (SX87_FPUCTRLW_RNDCTL(ctx->state.control_word)) + { + case SX87_FPUCTRLW_RNDCTL_NEAREST: + if (waste >= threshhold) minor.mantissa++; + break; + + case SX87_FPUCTRLW_RNDCTL_DOWNINF: + if (waste != 0L && minor.sign_bit) minor.mantissa++; + break; + + case SX87_FPUCTRLW_RNDCTL_UPINF: + if (waste != 0L && !minor.sign_bit) minor.mantissa++; + break; + + case SX87_FPUCTRLW_RNDCTL_ZERO: + /* nothing */ + break; + } + } + + if (exb > 0) { +/* scale up the major value */ + threshhold = (sx87_uldword)-1; + threshhold >>= (sx87_uldword)(64-exb); + waste = major.mantissa & threshhold; + threshhold = (threshhold+1)>>1; + + major.exponent += exb; + major.mantissa >>= (sx87_uldword)exb; +/* round it */ + switch (SX87_FPUCTRLW_RNDCTL(ctx->state.control_word)) + { + case SX87_FPUCTRLW_RNDCTL_NEAREST: + if (waste >= threshhold) major.mantissa++; + break; + + case SX87_FPUCTRLW_RNDCTL_DOWNINF: + if (waste != 0L && major.sign_bit) major.mantissa++; + break; + + case SX87_FPUCTRLW_RNDCTL_UPINF: + if (waste != 0L && !major.sign_bit) major.mantissa++; + break; + + case SX87_FPUCTRLW_RNDCTL_ZERO: + /* nothing */ + break; + } + } + + if (src->sign_bit == dst->sign_bit) { + /* simply add */ + dst->exponent = major.exponent; + dst->sign_bit = major.sign_bit; + dst->mantissa = minor.mantissa + major.mantissa; + } + else { + /* negate mantissa based on sign */ + if (minor.sign_bit) minor.mantissa = -minor.mantissa; + if (major.sign_bit) major.mantissa = -major.mantissa; + /* now add, treating 63rd bit as sign */ + dst->exponent = major.exponent; + dst->mantissa = minor.mantissa + major.mantissa; + dst->sign_bit = dst->mantissa>>((sx87_uldword)63); + if (dst->sign_bit) dst->mantissa = -dst->mantissa; + } + + softx87_normalize(ctx,dst); +} + +/* FCOM */ +void op_fcom(softx87_ctx* ctx,softx87_reg80 *dst,softx87_reg80 *src) +{ + softx87_reg80 st0; + + memcpy(&st0,dst,sizeof(softx87_reg80)); + softx87_normalize(ctx,&st0); + op_fsub(ctx,&st0,src); // st0 -= src + +/* what is the result? */ + op_fcom_compflags(ctx,&st0); +} + +/* FCOM */ +void op_fcomp(softx87_ctx* ctx,softx87_reg80 *dst,softx87_reg80 *src) +{ + softx87_reg80 st0; + + memcpy(&st0,dst,sizeof(softx87_reg80)); + softx87_normalize(ctx,&st0); + op_fsub(ctx,&st0,src); // st0 -= src + +/* what is the result? */ + op_fcom_compflags(ctx,&st0); + softx86_popstack(ctx); +} + +/* general purpose FSUB */ +void op_fsub(softx87_ctx* ctx,softx87_reg80 *dst,softx87_reg80 *src) +{ + softx87_reg80 stm; + +/* cheap trick for now ;) */ + memcpy(&stm,src,sizeof(softx87_reg80)); + stm.sign_bit=!stm.sign_bit; + op_fadd(ctx,dst,&stm); +} + +/* general purpose FDIV */ +void op_fdiv(softx87_ctx* ctx,softx87_reg80 *dst,softx87_reg80 *src) +{ + double x,y; + +// TODO: consideration for NaN, etc. +// TODO: make own dividing implementation, this is a cheap hack. + x = softx87_get_fpu_double(ctx,dst,NULL); + y = softx87_get_fpu_double(ctx,src,NULL); + x /= y; + softx87_set_fpu_double(ctx,dst,x); +} + +/* general purpose FDIVR */ +void op_fdivr(softx87_ctx* ctx,softx87_reg80 *dst,softx87_reg80 *src) +{ + double x,y; + +// TODO: consideration for NaN, etc. +// TODO: make own dividing implementation, this is a cheap hack. + x = softx87_get_fpu_double(ctx,dst,NULL); + y = softx87_get_fpu_double(ctx,src,NULL); + x = y / x; + softx87_set_fpu_double(ctx,dst,x); +} + +static int Sfx87OpcodeExec_group_D8(sx87_ubyte opcode,softx87_ctx* ctx) +{ +/* FADD ST(0),ST(i) */ + if (opcode >= 0xC0 && opcode < 0xC8) { + int st0,i; + + i = (int)(opcode-0xC0); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fadd(ctx,&ctx->state.st[st0],&ctx->state.st[i]); +/* done */ + return 1; + } +/* FCOM ST(0),ST(i) */ + else if (opcode >= 0xD0 && opcode < 0xD8) { + int st0,i; + + i = (int)(opcode-0xD0); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fcom(ctx,&ctx->state.st[st0],&ctx->state.st[i]); +/* done */ + return 1; + } +/* FCOMP ST(0),ST(i) */ + else if (opcode >= 0xD8 && opcode < 0xE0) { + int st0,i; + + i = (int)(opcode-0xD8); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fcomp(ctx,&ctx->state.st[st0],&ctx->state.st[i]); +/* done */ + return 1; + } +/* FSUB ST(0),ST(i) */ + else if (opcode >= 0xE0 && opcode < 0xE8) { + int st0,i; + + i = (int)(opcode-0xE0); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fsub(ctx,&ctx->state.st[st0],&ctx->state.st[i]); +/* done */ + return 1; + } +/* FDIV ST(0),ST(i) */ + else if (opcode >= 0xF0 && opcode < 0xF8) { + int st0,i; + + i = (int)(opcode-0xF0); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fdiv(ctx,&ctx->state.st[st0],&ctx->state.st[i]); +/* done */ + return 1; + } +/* FDIVR ST(0),ST(i) */ + else if (opcode >= 0xF8) { + int st0,i; + + i = (int)(opcode-0xF8); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fdivr(ctx,&ctx->state.st[st0],&ctx->state.st[i]); +/* done */ + return 1; + } +/* combo */ + else if (opcode < 0xC0) { + sx86_ubyte mod,reg,rm; + + sx86_modregrm_unpack(opcode,mod,reg,rm); + + if (reg == 0) /* FADD mem32 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,4,op_fadd32); + else if (reg == 2) /* FCOM mem32 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,4,op_fcom32); + else if (reg == 3) /* FCOMP mem32 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,4,op_fcomp32); + else if (reg == 4) /* FSUB mem32 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,4,op_fsub32); + else if (reg == 6) /* FDIV mem32 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,4,op_fdiv32); + else if (reg == 7) /* FDIVR mem32 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,4,op_fdivr32); + else + return 0; + + return 1; + } + + return 0; +} + +static int Sfx87OpcodeDec_group_D8(sx87_ubyte opcode,softx87_ctx* ctx,char buf[128]) +{ +/* FADD ST(0),ST(i) */ + if (opcode >= 0xC0 && opcode < 0xC8) { + sprintf(buf,"FADD ST(0),ST(%d)",opcode-0xC0); + return 1; + } +/* FCOM ST(0),ST(i) */ + else if (opcode >= 0xD0 && opcode < 0xD8) { + sprintf(buf,"FCOM ST(0),ST(%d)",opcode-0xD0); + return 1; + } +/* FCOMP ST(0),ST(i) */ + else if (opcode >= 0xD8 && opcode < 0xE0) { + sprintf(buf,"FCOMP ST(0),ST(%d)",opcode-0xD8); + return 1; + } +/* FSUB ST(0),ST(i) */ + else if (opcode >= 0xE0 && opcode < 0xE8) { + sprintf(buf,"FSUB ST(0),ST(%d)",opcode-0xE0); + return 1; + } +/* FDIV ST(0),ST(i) */ + else if (opcode >= 0xF0 && opcode < 0xF8) { + sprintf(buf,"FDIV ST(0),ST(%d)",opcode-0xF0); + return 1; + } +/* FDIVR ST(0),ST(i) */ + else if (opcode >= 0xF8) { + sprintf(buf,"FDIVR ST(0),ST(%d)",opcode-0xF8); + return 1; + } +/* combo */ + else if (opcode < 0xC0) { + sx86_ubyte mod,reg,rm; + + sx86_modregrm_unpack(opcode,mod,reg,rm); + ctx->callbacks.on_sx86_dec_full_modrmonly(ctx->ref_softx86,1,0,mod,rm,s87op1_tmp); + + if (reg == 0) + sprintf(buf,"FADD %s (mem32)",s87op1_tmp); + else if (reg == 2) + sprintf(buf,"FCOM %s (mem32)",s87op1_tmp); + else if (reg == 3) + sprintf(buf,"FCOMP %s (mem32)",s87op1_tmp); + else if (reg == 4) + sprintf(buf,"FSUB %s (mem32)",s87op1_tmp); + else if (reg == 6) + sprintf(buf,"FDIV %s (mem32)",s87op1_tmp); + else if (reg == 7) + sprintf(buf,"FDIVR %s (mem32)",s87op1_tmp); + else + return 0; + + return 1; + } + + buf[0]=0; + return 0; +} + +void sx87_rnd(softx87_reg80 *val) +{ +/* TODO: rounding modes */ + if (1) { + /* round to nearest */ + if (val->exponent < 16382) { + /* value is too small that val must be < 0.5 */ + val->mantissa = 0; + val->exponent = 16383; + val->sign_bit = 0; + } + else if (val->exponent > (16383+63)) { + /* value is too large to round */ + } + else { + sx87_uldword t,s,m,i; + + s = (sx87_uldword)(val->exponent-16382); + m = ((sx87_uldword)-1) >> s; + t = val->mantissa & m; + i = val->mantissa & (~m); +/* special case: when s == 0, m = 0xFFFFFFFFFFFFFFFF which can + overflow to 0 if incremented and shifted */ + if (s == 0) s = (sx87_uldword)0x8000000000000000L; + else s = (m + ((sx87_uldword)1)) >> ((sx87_uldword)1); +/* m = mask to obtain fractional part + t = fractional part + i = whole part + s = fractional part / 2 */ + if (t >= s) i++; + val->mantissa = i; + } + } +} + +static int Sfx87OpcodeExec_group_D9(sx87_ubyte opcode,softx87_ctx* ctx) +{ +/* FSCALE */ + if (opcode == 0xFD) { + sx86_uldword e; + int ST0,ST1; + + ST0 = SX87_FPUSTAT_TOP(ctx->state.status_word); + ST1 = (ST0 + 1) & 7; + + // TODO: cases with infinity, NaN, etc + e = sx87_getint(&ctx->state.st[ST1]); + e = ctx->state.st[ST0].exponent + e; + if (e < 0) { + ctx->state.st[ST0].exponent = 16383; + ctx->state.st[ST0].mantissa = 0; + } + else if (e > 0x7FFF) { + ctx->state.st[ST0].exponent = 0x7FFF; + ctx->state.st[ST0].mantissa = (sx86_uldword)(-1); + } + else { + ctx->state.st[ST0].exponent = (sx86_uword)(e); + } + + return 1; + } +/* FRNDINT */ + else if (opcode == 0xFC) { + int TOP; + + TOP = SX87_FPUSTAT_TOP(ctx->state.status_word); + sx87_rnd(&ctx->state.st[TOP]); + return 1; + } +/* FINCSTP */ + else if (opcode == 0xF7) { + int TOP; + + TOP = SX87_FPUSTAT_TOP(ctx->state.status_word); + ctx->state.status_word &= ~SX87_FPUSTAT_C1; +/* decrement Top Of Stack. nothing is tagged empty. */ + TOP = (TOP+1)&7; + SX87_FPUSTAT_TOP_SET(ctx->state.status_word,TOP); +/* done */ + return 1; + } +/* FDECSTP */ + else if (opcode == 0xF6) { + int TOP; + + TOP = SX87_FPUSTAT_TOP(ctx->state.status_word); + ctx->state.status_word &= ~SX87_FPUSTAT_C1; +/* decrement Top Of Stack. nothing is tagged empty. */ + TOP = (TOP-1)&7; + SX87_FPUSTAT_TOP_SET(ctx->state.status_word,TOP); +/* done */ + return 1; + } +/* F2XM1 */ + else if (opcode == 0xF0) { + int TOP; + double v; + + TOP = SX87_FPUSTAT_TOP(ctx->state.status_word); + v = softx87_get_fpu_register_double(ctx,TOP,NULL); + /* NOTE: Intel says that this instruction is limited to domain -1.0 <= x <= 1.0 + and anything outside that is undefined..... so what? */ + // TODO: Make own implementation of exponential function + v = pow(2.0,v); + softx87_set_fpu_register_double(ctx,TOP,v); + return 1; + } +/* FLD1 */ + else if (opcode == 0xE8) { + int TOP; + + TOP = SX87_FPUSTAT_TOP(ctx->state.status_word); +/* set C1 if stack overflow */ + if (SX87_FPUTAGW_TAG(ctx->state.tag_word,TOP) != SX87_FPUTAGVAL_EMPTY) + ctx->state.status_word |= SX87_FPUSTAT_C1; + else + ctx->state.status_word &= ~SX87_FPUSTAT_C1; +/* decrement TOP, tag as valid */ + TOP = (TOP-1)&7; + SX87_FPUSTAT_TOP_SET(ctx->state.status_word,TOP); + SX87_FPUTAGW_TAG_SET(ctx->state.tag_word,TOP,SX87_FPUTAGVAL_VALID); +/* store */ + ctx->state.st[TOP].exponent = 16383 + 63; + ctx->state.st[TOP].mantissa = 1; + ctx->state.st[TOP].sign_bit = 0; + return 1; + } +/* FLDL2T */ + else if (opcode == 0xE9) { + int TOP; + + TOP = SX87_FPUSTAT_TOP(ctx->state.status_word); +/* set C1 if stack overflow */ + if (SX87_FPUTAGW_TAG(ctx->state.tag_word,TOP) != SX87_FPUTAGVAL_EMPTY) + ctx->state.status_word |= SX87_FPUSTAT_C1; + else + ctx->state.status_word &= ~SX87_FPUSTAT_C1; +/* decrement TOP, tag as valid */ + TOP = (TOP-1)&7; + SX87_FPUSTAT_TOP_SET(ctx->state.status_word,TOP); + SX87_FPUTAGW_TAG_SET(ctx->state.tag_word,TOP,SX87_FPUTAGVAL_VALID); +/* store log2(10) = 3.3219280948873623478703194294894 */ + softx87_set_fpu_register_double(ctx,TOP,(double)(3.3219280948873623478703194294894)); + return 1; + } +/* FLDL2E */ + else if (opcode == 0xEA) { + int TOP; + + TOP = SX87_FPUSTAT_TOP(ctx->state.status_word); +/* set C1 if stack overflow */ + if (SX87_FPUTAGW_TAG(ctx->state.tag_word,TOP) != SX87_FPUTAGVAL_EMPTY) + ctx->state.status_word |= SX87_FPUSTAT_C1; + else + ctx->state.status_word &= ~SX87_FPUSTAT_C1; +/* decrement TOP, tag as valid */ + TOP = (TOP-1)&7; + SX87_FPUSTAT_TOP_SET(ctx->state.status_word,TOP); + SX87_FPUTAGW_TAG_SET(ctx->state.tag_word,TOP,SX87_FPUTAGVAL_VALID); +/* store log2(e) = 1.4426950408889634073599246810019 */ + softx87_set_fpu_register_double(ctx,TOP,(double)(1.4426950408889634073599246810019)); + return 1; + } +/* FLDPI */ + else if (opcode == 0xEB) { + int TOP; + + TOP = SX87_FPUSTAT_TOP(ctx->state.status_word); +/* set C1 if stack overflow */ + if (SX87_FPUTAGW_TAG(ctx->state.tag_word,TOP) != SX87_FPUTAGVAL_EMPTY) + ctx->state.status_word |= SX87_FPUSTAT_C1; + else + ctx->state.status_word &= ~SX87_FPUSTAT_C1; +/* decrement TOP, tag as valid */ + TOP = (TOP-1)&7; + SX87_FPUSTAT_TOP_SET(ctx->state.status_word,TOP); + SX87_FPUTAGW_TAG_SET(ctx->state.tag_word,TOP,SX87_FPUTAGVAL_VALID); +/* store PI the way Intel documents it (IA-32 Intel Architecture SW dev vol 1, ch 8.3.8) */ + ctx->state.st[TOP].exponent = 16383 + 1; + ctx->state.st[TOP].mantissa = (sx86_uldword)(0xC90FDAA22168C234); // C90F DAA2 2168 C234 C + ctx->state.st[TOP].sign_bit = 0; + return 1; + } +/* FLDLG2 */ + else if (opcode == 0xEC) { + int TOP; + + TOP = SX87_FPUSTAT_TOP(ctx->state.status_word); +/* set C1 if stack overflow */ + if (SX87_FPUTAGW_TAG(ctx->state.tag_word,TOP) != SX87_FPUTAGVAL_EMPTY) + ctx->state.status_word |= SX87_FPUSTAT_C1; + else + ctx->state.status_word &= ~SX87_FPUSTAT_C1; +/* decrement TOP, tag as valid */ + TOP = (TOP-1)&7; + SX87_FPUSTAT_TOP_SET(ctx->state.status_word,TOP); + SX87_FPUTAGW_TAG_SET(ctx->state.tag_word,TOP,SX87_FPUTAGVAL_VALID); +/* store log10(2) = 0.30102999566398119521373889472449 */ + softx87_set_fpu_register_double(ctx,TOP,(double)(0.30102999566398119521373889472449)); + return 1; + } +/* FLDLN2 */ + else if (opcode == 0xED) { + int TOP; + + TOP = SX87_FPUSTAT_TOP(ctx->state.status_word); +/* set C1 if stack overflow */ + if (SX87_FPUTAGW_TAG(ctx->state.tag_word,TOP) != SX87_FPUTAGVAL_EMPTY) + ctx->state.status_word |= SX87_FPUSTAT_C1; + else + ctx->state.status_word &= ~SX87_FPUSTAT_C1; +/* decrement TOP, tag as valid */ + TOP = (TOP-1)&7; + SX87_FPUSTAT_TOP_SET(ctx->state.status_word,TOP); + SX87_FPUTAGW_TAG_SET(ctx->state.tag_word,TOP,SX87_FPUTAGVAL_VALID); +/* store ln(2) = 0.69314718055994530941723212145818 */ + softx87_set_fpu_register_double(ctx,TOP,(double)(0.69314718055994530941723212145818)); + return 1; + } +/* FLDZ */ + else if (opcode == 0xEE) { + int TOP; + + TOP = SX87_FPUSTAT_TOP(ctx->state.status_word); +/* set C1 if stack overflow */ + if (SX87_FPUTAGW_TAG(ctx->state.tag_word,TOP) != SX87_FPUTAGVAL_EMPTY) + ctx->state.status_word |= SX87_FPUSTAT_C1; + else + ctx->state.status_word &= ~SX87_FPUSTAT_C1; +/* decrement TOP, tag as valid */ + TOP = (TOP-1)&7; + SX87_FPUSTAT_TOP_SET(ctx->state.status_word,TOP); + SX87_FPUTAGW_TAG_SET(ctx->state.tag_word,TOP,SX87_FPUTAGVAL_VALID); +/* store */ + ctx->state.st[TOP].exponent = 16383 + 63; + ctx->state.st[TOP].mantissa = 0; + ctx->state.st[TOP].sign_bit = 0; + return 1; + } +/* FABS */ + else if (opcode == 0xE1) { + int TOP; + + TOP = SX87_FPUSTAT_TOP(ctx->state.status_word); + ctx->state.st[TOP].sign_bit = 0; + return 1; + } +/* FCHS */ + else if (opcode == 0xE0) { + int TOP; + + TOP = SX87_FPUSTAT_TOP(ctx->state.status_word); + ctx->state.st[TOP].sign_bit = !ctx->state.st[TOP].sign_bit; + return 1; + } +/* FNOP */ + else if (opcode == 0xD0) { + /* no-op */ + return 1; + } +/* FLD ST(i) */ + else if (opcode >= 0xC0 && opcode < 0xC8) { + int TOP,i; + + i = (int)(opcode-0xC0); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + TOP = SX87_FPUSTAT_TOP(ctx->state.status_word); +/* set C1 if stack overflow */ + if (SX87_FPUTAGW_TAG(ctx->state.tag_word,TOP) != SX87_FPUTAGVAL_EMPTY) + ctx->state.status_word |= SX87_FPUSTAT_C1; + else + ctx->state.status_word &= ~SX87_FPUSTAT_C1; +/* decrement Top Of Stack, Tag as valid, and store */ + TOP = (TOP-1)&7; + SX87_FPUSTAT_TOP_SET(ctx->state.status_word,TOP); + SX87_FPUTAGW_TAG_SET(ctx->state.tag_word,TOP,SX87_FPUTAGVAL_VALID); +/* copy */ + ctx->state.st[TOP].exponent = ctx->state.st[i].exponent; + ctx->state.st[TOP].mantissa = ctx->state.st[i].mantissa; + ctx->state.st[TOP].sign_bit = ctx->state.st[i].sign_bit; +/* done */ + return 1; + } +/* combo */ + else if (opcode < 0xC0) { + sx86_ubyte mod,reg,rm; + + sx86_modregrm_unpack(opcode,mod,reg,rm); + + if (reg == 0) /* FLD mem32 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,4,op_fld32); + else + return 0; + + return 1; + } + + return 0; +} + +static int Sfx87OpcodeDec_group_D9(sx87_ubyte opcode,softx87_ctx* ctx,char buf[128]) +{ +/* FSCALE */ + if (opcode == 0xFD) { + strcpy(buf,"FSCALE"); + return 1; + } +/* FRNDINT */ + else if (opcode == 0xFC) { + strcpy(buf,"FRNDINT"); + return 1; + } +/* FINCSTP */ + else if (opcode == 0xF7) { + strcpy(buf,"FINCSTP"); + return 1; + } +/* FDECSTP */ + else if (opcode == 0xF6) { + strcpy(buf,"FDECSTP"); + return 1; + } +/* F2XM1 */ + else if (opcode == 0xF0) { + strcpy(buf,"F2XM1"); + return 1; + } +/* FLD1 */ + else if (opcode == 0xE8) { + strcpy(buf,"FLD1"); + return 1; + } +/* FLDL2T */ + else if (opcode == 0xE9) { + strcpy(buf,"FLDL2T"); + return 1; + } +/* FLDL2E */ + else if (opcode == 0xEA) { + strcpy(buf,"FLDL2E"); + return 1; + } +/* FLDPI */ + else if (opcode == 0xEB) { + strcpy(buf,"FLDPI"); + return 1; + } +/* FLDLG2 */ + else if (opcode == 0xEC) { + strcpy(buf,"FLDLG2"); + return 1; + } +/* FLDLN2 */ + else if (opcode == 0xED) { + strcpy(buf,"FLDLN2"); + return 1; + } +/* FLDZ */ + else if (opcode == 0xEE) { + strcpy(buf,"FLDZ"); + return 1; + } +/* FABS */ + else if (opcode == 0xE1) { + strcpy(buf,"FABS"); + return 1; + } +/* FCHS */ + else if (opcode == 0xE0) { + strcpy(buf,"FABS"); + return 1; + } +/* FNOP */ + else if (opcode == 0xD0) { + strcpy(buf,"FNOP"); + return 1; + } +/* FLD ST(i) */ + else if (opcode >= 0xC0 && opcode < 0xC8) { + sprintf(buf,"FLD ST(%d)",opcode-0xC0); + return 1; + } +/* combo */ + else if (opcode < 0xC0) { + sx86_ubyte mod,reg,rm; + + sx86_modregrm_unpack(opcode,mod,reg,rm); + ctx->callbacks.on_sx86_dec_full_modrmonly(ctx->ref_softx86,1,0,mod,rm,s87op1_tmp); + + if (reg == 0) + sprintf(buf,"FLD %s (mem32)",s87op1_tmp); + else + return 0; + + return 1; + } + + buf[0]=0; + return 0; +} + +static int Sfx87OpcodeExec_group_DA(sx87_ubyte opcode,softx87_ctx* ctx) +{ +/* combo */ + if (opcode < 0xC0) { + sx86_ubyte mod,reg,rm; + + sx86_modregrm_unpack(opcode,mod,reg,rm); + + if (reg == 0) /* FIADD mem32 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,4,op_fiadd32); + else if (reg == 2) /* FICOM mem32 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,4,op_ficom32); + else if (reg == 3) /* FICOMP mem32 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,4,op_ficomp32); + else if (reg == 4) /* FISUB mem32 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,4,op_fisub32); + else if (reg == 6) /* FIDIV mem32 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,4,op_fidiv32); + else if (reg == 7) /* FIDIVR mem32 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,4,op_fidivr32); + else + return 0; + + return 1; + } + + return 0; +} + +static int Sfx87OpcodeDec_group_DA(sx87_ubyte opcode,softx87_ctx* ctx,char buf[128]) +{ +/* combo */ + if (opcode < 0xC0) { + sx86_ubyte mod,reg,rm; + + sx86_modregrm_unpack(opcode,mod,reg,rm); + ctx->callbacks.on_sx86_dec_full_modrmonly(ctx->ref_softx86,1,0,mod,rm,s87op1_tmp); + + if (reg == 0) + sprintf(buf,"FIADD %s (mem32)",s87op1_tmp); + else if (reg == 2) + sprintf(buf,"FICOM %s (mem32)",s87op1_tmp); + else if (reg == 3) + sprintf(buf,"FICOMP %s (mem32)",s87op1_tmp); + else if (reg == 4) + sprintf(buf,"FISUB %s (mem32)",s87op1_tmp); + else if (reg == 6) + sprintf(buf,"FIDIV %s (mem32)",s87op1_tmp); + else if (reg == 7) + sprintf(buf,"FIDIVR %s (mem32)",s87op1_tmp); + else + return 0; + + return 1; + } + + buf[0]=0; + return 0; +} + +static int Sfx87OpcodeExec_group_DB(sx87_ubyte opcode,softx87_ctx* ctx) +{ +/* FINIT a.k.a. FNINIT */ + if (opcode == 0xE3) { + softx87_finit_setup(ctx); + return 1; + } +/* FCLEX a.k.a. FNCLEX */ + else if (opcode == 0xE2) { + ctx->state.status_word = 0; + return 1; + } + + return 0; +} + +static int Sfx87OpcodeDec_group_DB(sx87_ubyte opcode,softx87_ctx* ctx,char buf[128]) +{ +/* FINIT a.k.a. FNINIT */ + if (opcode == 0xE3) { + strcpy(buf,"FINIT"); + return 1; + } +/* FCLEX a.k.a. FNCLEX */ + else if (opcode == 0xE2) { + strcpy(buf,"FCLEX"); + return 1; + } + + buf[0]=0; + return 0; +} + +static int Sfx87OpcodeExec_group_DC(sx87_ubyte opcode,softx87_ctx* ctx) +{ +/* FADD ST(i),ST(0) */ + if (opcode >= 0xC0 && opcode < 0xC8) { + int st0,i; + + i = (int)(opcode-0xC0); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fadd(ctx,&ctx->state.st[i],&ctx->state.st[st0]); +/* done */ + return 1; + } +/* FSUB ST(i),ST(0) */ + else if (opcode >= 0xE8 && opcode < 0xF0) { + int st0,i; + + i = (int)(opcode-0xE8); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fsub(ctx,&ctx->state.st[i],&ctx->state.st[st0]); +/* done */ + return 1; + } +/* FDIVR ST(i),ST(0) */ + else if (opcode >= 0xF0 && opcode < 0xF8) { + int st0,i; + + i = (int)(opcode-0xF0); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fdivr(ctx,&ctx->state.st[i],&ctx->state.st[st0]); +/* done */ + return 1; + } +/* FDIV ST(i),ST(0) */ + else if (opcode >= 0xF8) { + int st0,i; + + i = (int)(opcode-0xF8); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fdiv(ctx,&ctx->state.st[i],&ctx->state.st[st0]); +/* done */ + return 1; + } +/* combo */ + else if (opcode < 0xC0) { + sx86_ubyte mod,reg,rm; + + sx86_modregrm_unpack(opcode,mod,reg,rm); + + if (reg == 0) /* FADD mem64 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,8,op_fadd64); + else if (reg == 2) /* FCOM mem64 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,8,op_fcom64); + else if (reg == 3) /* FCOMP mem64 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,8,op_fcomp64); + else if (reg == 4) /* FSUB mem64 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,8,op_fsub64); + else if (reg == 6) /* FDIV mem64 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,8,op_fdiv64); + else if (reg == 7) /* FDIVR mem64 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,8,op_fdivr64); + else + return 0; + + return 1; + } + + return 0; +} + +static int Sfx87OpcodeDec_group_DC(sx87_ubyte opcode,softx87_ctx* ctx,char buf[128]) +{ +/* FADD ST(i),ST(0) */ + if (opcode >= 0xC0 && opcode < 0xC8) { + sprintf(buf,"FADD ST(%d),ST(0)",opcode-0xC0); + return 1; + } +/* FSUB ST(i),ST(0) */ + else if (opcode >= 0xE8 && opcode < 0xF0) { + sprintf(buf,"FSUB ST(%d),ST(0)",opcode-0xE8); + return 1; + } +/* FDIVR ST(i),ST(0) */ + else if (opcode >= 0xF0 && opcode < 0xF8) { + sprintf(buf,"FDIVR ST(%d),ST(0)",opcode-0xF0); + return 1; + } +/* FDIV ST(i),ST(0) */ + else if (opcode >= 0xF8) { + sprintf(buf,"FDIV ST(%d),ST(0)",opcode-0xF8); + return 1; + } +/* combo */ + else if (opcode < 0xC0) { + sx86_ubyte mod,reg,rm; + + sx86_modregrm_unpack(opcode,mod,reg,rm); + ctx->callbacks.on_sx86_dec_full_modrmonly(ctx->ref_softx86,1,0,mod,rm,s87op1_tmp); + + if (reg == 0) + sprintf(buf,"FADD %s (mem64)",s87op1_tmp); + else if (reg == 2) + sprintf(buf,"FCOM %s (mem64)",s87op1_tmp); + else if (reg == 3) + sprintf(buf,"FCOMP %s (mem64)",s87op1_tmp); + else if (reg == 4) + sprintf(buf,"FSUB %s (mem64)",s87op1_tmp); + else if (reg == 6) + sprintf(buf,"FDIV %s (mem64)",s87op1_tmp); + else if (reg == 7) + sprintf(buf,"FDIVR %s (mem64)",s87op1_tmp); + else + return 0; + + return 1; + } + + buf[0]=0; + return 0; +} + +static int Sfx87OpcodeExec_group_DD(sx87_ubyte opcode,softx87_ctx* ctx) +{ +/* combo */ + if (opcode < 0xC0) { + sx86_ubyte mod,reg,rm; + + sx86_modregrm_unpack(opcode,mod,reg,rm); + + if (reg == 0) /* FLD mem64 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,8,op_fld64); + else + return 0; + + return 1; + } +/* FFREE ST(i) */ + else if (opcode >= 0xC0 && opcode < 0xC8) { + int i; + + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),(int)(opcode-0xC0)); + SX87_FPUTAGW_TAG_SET(ctx->state.tag_word,i,SX87_FPUTAGVAL_EMPTY); + + return 1; + } + + return 0; +} + +static int Sfx87OpcodeDec_group_DD(sx87_ubyte opcode,softx87_ctx* ctx,char buf[128]) +{ +/* combo */ + if (opcode < 0xC0) { + sx86_ubyte mod,reg,rm; + + sx86_modregrm_unpack(opcode,mod,reg,rm); + ctx->callbacks.on_sx86_dec_full_modrmonly(ctx->ref_softx86,1,0,mod,rm,s87op1_tmp); + + if (reg == 0) + sprintf(buf,"FLD %s (mem64)",s87op1_tmp); + else + return 0; + + return 1; + } +/* FFREE ST(i) */ + else if (opcode >= 0xC0 && opcode < 0xC8) { + sprintf(buf,"FFREE ST(%d)",opcode-0xC0); + return 1; + } + + buf[0]=0; + return 0; +} + +static int Sfx87OpcodeExec_group_DE(sx87_ubyte opcode,softx87_ctx* ctx) +{ +/* FADDP ST(i),ST(0) */ + if (opcode >= 0xC0 && opcode < 0xC8) { + int st0,i; + + i = (int)(opcode-0xC0); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fadd(ctx,&ctx->state.st[i],&ctx->state.st[st0]); +/* pop */ + softx86_popstack(ctx); +/* done */ + return 1; + } +/* FCOMPP ST(0),ST(1) */ + else if (opcode == 0xD9) { + int st0,i; + + i = (int)(opcode-0xD9); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fcom(ctx,&ctx->state.st[i],&ctx->state.st[st0]); +/* pop */ + softx86_popstack(ctx); + softx86_popstack(ctx); +/* done */ + return 1; + } +/* FSUBP ST(i),ST(0) */ + else if (opcode >= 0xE8 && opcode < 0xEF) { + int st0,i; + + i = (int)(opcode-0xE8); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fsub(ctx,&ctx->state.st[i],&ctx->state.st[st0]); +/* pop */ + softx86_popstack(ctx); +/* done */ + return 1; + } +/* FDIVRP ST(i),ST(0) */ + else if (opcode >= 0xF0 && opcode < 0xF8) { + int st0,i; + + i = (int)(opcode-0xF0); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fdivr(ctx,&ctx->state.st[i],&ctx->state.st[st0]); +/* pop */ + softx86_popstack(ctx); +/* done */ + return 1; + } +/* FDIVP ST(i),ST(0) */ + else if (opcode >= 0xF8) { + int st0,i; + + i = (int)(opcode-0xF8); + i = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),i); + st0 = SX87_FPU_ST(SX87_FPUSTAT_TOP(ctx->state.status_word),0); +/* add */ + op_fdiv(ctx,&ctx->state.st[i],&ctx->state.st[st0]); +/* pop */ + softx86_popstack(ctx); +/* done */ + return 1; + } +/* combo */ + else if (opcode < 0xC0) { + sx86_ubyte mod,reg,rm; + + sx86_modregrm_unpack(opcode,mod,reg,rm); + + if (reg == 0) /* FIADD mem16 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,2,op_fiadd16); + else if (reg == 2) /* FICOM mem16 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,2,op_ficom16); + else if (reg == 3) /* FICOMP mem16 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,2,op_ficomp16); + else if (reg == 4) /* FISUB mem16 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,2,op_fisub16); + else if (reg == 6) /* FIDIV mem16 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,2,op_fidiv16); + else if (reg == 7) /* FIDIVR mem16 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,2,op_fidivr16); + else + return 0; + + return 1; + } + + return 0; +} + +static int Sfx87OpcodeDec_group_DE(sx87_ubyte opcode,softx87_ctx* ctx,char buf[128]) +{ +/* FADDP ST(i),ST(0) */ + if (opcode >= 0xC0 && opcode < 0xC8) { + sprintf(buf,"FADDP ST(%d),ST(0)",opcode-0xC0); + return 1; + } +/* FCOMPP ST(0),ST(1) */ + else if (opcode == 0xD9) { + strcpy(buf,"FCOMPP"); + return 1; + } +/* FSUBP ST(i),ST(0) */ + else if (opcode >= 0xE8 && opcode < 0xEF) { + sprintf(buf,"FSUBP ST(%d),ST(0)",opcode-0xE8); + return 1; + } +/* FDIVP ST(i),ST(0) */ + else if (opcode >= 0xF8) { + sprintf(buf,"FDIVP ST(%d),ST(0)",opcode-0xF8); + return 1; + } +/* combo */ + else if (opcode < 0xC0) { + sx86_ubyte mod,reg,rm; + + sx86_modregrm_unpack(opcode,mod,reg,rm); + ctx->callbacks.on_sx86_dec_full_modrmonly(ctx->ref_softx86,1,0,mod,rm,s87op1_tmp); + + if (reg == 0) + sprintf(buf,"FIADD %s (mem16)",s87op1_tmp); + else if (reg == 2) + sprintf(buf,"FICOM %s (mem16)",s87op1_tmp); + else if (reg == 3) + sprintf(buf,"FICOMP %s (mem16)",s87op1_tmp); + else if (reg == 4) + sprintf(buf,"FISUB %s (mem16)",s87op1_tmp); + else if (reg == 6) + sprintf(buf,"FIDIV %s (mem16)",s87op1_tmp); + else if (reg == 7) + sprintf(buf,"FIDIVR %s (mem16)",s87op1_tmp); + else + return 0; + + return 1; + } + + buf[0]=0; + return 0; +} + +static int Sfx87OpcodeExec_group_DF(sx87_ubyte opcode,softx87_ctx* ctx) +{ +/* combo */ + if (opcode < 0xC0) { + sx86_ubyte mod,reg,rm; + + sx86_modregrm_unpack(opcode,mod,reg,rm); + + if (reg == 4) /* FBLD mem80 */ + ctx->callbacks.on_sx86_exec_full_modrmonly_memx(ctx->ref_softx86,mod,rm,10,op_fbld80); + else if (reg == 6) /* FBSTP mem80 */ + ctx->callbacks.on_sx86_exec_full_modrw_memx(ctx->ref_softx86,mod,rm,10,op_fbstp80); + else + return 0; + + return 1; + } + + return 0; +} + +static int Sfx87OpcodeDec_group_DF(sx87_ubyte opcode,softx87_ctx* ctx,char buf[128]) +{ +/* combo */ + if (opcode < 0xC0) { + sx86_ubyte mod,reg,rm; + + sx86_modregrm_unpack(opcode,mod,reg,rm); + ctx->callbacks.on_sx86_dec_full_modrmonly(ctx->ref_softx86,1,0,mod,rm,s87op1_tmp); + + if (reg == 4) + sprintf(buf,"FBLD %s (mem80)",s87op1_tmp); + else if (reg == 6) + sprintf(buf,"FBSTP %s (mem80)",s87op1_tmp); + else + return 0; + + return 1; + } + + buf[0]=0; + return 0; +} + +Sfx87OpcodeTable optab8087 = { +{ + {Sfx87OpcodeExec_group_D8, Sfx87OpcodeDec_group_D8}, /* 0xD8xx */ + {Sfx87OpcodeExec_group_D9, Sfx87OpcodeDec_group_D9}, /* 0xD9xx */ + {Sfx87OpcodeExec_group_DA, Sfx87OpcodeDec_group_DA}, /* 0xDAxx */ + {Sfx87OpcodeExec_group_DB, Sfx87OpcodeDec_group_DB}, /* 0xDBxx */ + {Sfx87OpcodeExec_group_DC, Sfx87OpcodeDec_group_DC}, /* 0xDCxx */ + {Sfx87OpcodeExec_group_DD, Sfx87OpcodeDec_group_DD}, /* 0xDDxx */ + {Sfx87OpcodeExec_group_DE, Sfx87OpcodeDec_group_DE}, /* 0xDExx */ + {Sfx87OpcodeExec_group_DF, Sfx87OpcodeDec_group_DF}, /* 0xDFxx */ +}, +}; Index: lib/3rdparty/softx86/softx87/optable.c =================================================================== --- lib/3rdparty/softx86/softx87/optable.c (révision 59666) +++ lib/3rdparty/softx86/softx87/optable.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx87/optable.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx87/resource.h =================================================================== --- lib/3rdparty/softx86/softx87/resource.h (révision 0) +++ lib/3rdparty/softx86/softx87/resource.h (copie de travail) @@ -0,0 +1,15 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Developer Studio generated include file. +// Used by softx87_dll.rc +// + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1000 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif Index: lib/3rdparty/softx86/softx87/resource.h =================================================================== --- lib/3rdparty/softx86/softx87/resource.h (révision 59666) +++ lib/3rdparty/softx86/softx87/resource.h (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx87/resource.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx87/softx87.c =================================================================== --- lib/3rdparty/softx86/softx87/softx87.c (révision 0) +++ lib/3rdparty/softx86/softx87/softx87.c (copie de travail) @@ -0,0 +1,446 @@ +/* + * softx87.c + * + * Copyright (C) 2003, 2004 Jonathan Campbell + * + * Softx87 library API. + * + * Initialization, de-initialization, register modification, and default + * routines for callbacks (in case they weren't set by the host app). + * + * Internal to this library, there are also functions to take care of + * fetching the current opcode (as referred to by CS:IP), fetching + * the current opcode for the decompiler (as referred to by a separate + * pair CS:IP), and pushing/popping data to/from the stack (SS:SP). + * + *********************************************************************************** + * 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. + ************************************************************************************/ + +#include +#include +#include +#include +#include +#include "optab87.h" + +/* utility function to normalize a floating point value */ +void softx87_normalize(softx87_ctx* ctx,softx87_reg80 *val) +{ + int lead0; + sx87_uldword sh; + + if (!val->mantissa) + return; + +/* how many leading 0 bits in the mantissa */ + lead0=0; + sh=0; + while (!((val->mantissa>>(63-sh))&1)) { + lead0++; + sh++; + } + +/* if none, don't do anything */ + if (!sh) + return; + +/* normalize */ + val->exponent -= sh; + val->mantissa <<= sh; +} + + +/* API for converting an FPU register to a type "double" value. + Yes, it is an approximation. Don't take it as the exact value. */ +double softx87_get_fpu_double(softx87_ctx* ctx,softx87_reg80 *reg,int *numtype) +{ + double val; + int exp; + +/* all special cases seem to revolve around exp == 0x7FFF */ + if (reg->exponent == 0x7FFF) { + if (reg->mantissa == 0) { + if (reg->sign_bit) { + if (numtype) + *numtype = SX87_FPU_NUMTYPE_NEGINF; + + return 0.00; + } + else { + if (numtype) + *numtype = SX87_FPU_NUMTYPE_POSINF; + + return 0.00; + } + } + else { + if (numtype) + *numtype = SX87_FPU_NUMTYPE_NAN; + + return 0.00; + } + } + +/* 16383 is the IEEE-754 bias for double extended precision numbers */ + exp = reg->exponent - (16383+63); +#ifdef MSVC_CANT_CONVERT_UI64_TO_DOUBLE + if ((reg->mantissa >> ((sx87_uldword)63))&1) + /* +2^64 to encourage positive value */ + val = ((double)((sx87_sldword)reg->mantissa)) + 18446744073709551616.00; + else + val = (double)((sx87_sldword)reg->mantissa); +#else + val = (double)(reg->mantissa); +#endif + val *= pow(2,(double)exp); + + if (numtype) + *numtype = SX87_FPU_NUMTYPE_NUMBER; + + if (reg->sign_bit) + val = -val; + + return val; +} + +double softx87_get_fpu_register_double(softx87_ctx* ctx,int i,int *numtype) +{ + if (i < 0 || i > 7) { + if (numtype) + *numtype = SX87_FPU_NUMTYPE_NAN; + + return 0.00; + } + + return softx87_get_fpu_double(ctx,&ctx->state.st[i],numtype); +} + +/* API for converting a type "double" value to an FPU register. + Yes, it is an approximation. Don't take it as the exact value. */ +void softx87_set_fpu_double(softx87_ctx* ctx,softx87_reg80 *reg,double val) +{ +/* log2 x = ln x / ln 2 */ + double sal; + int l2b; + int sgn; + + if (val < 0) { + sgn = 1; + val = -val; + } + else { + sgn = 0; + } + + if (val == 0) { + reg->sign_bit = sgn; + reg->exponent = 0; + reg->mantissa = 0; + return; + } + + l2b = (int)ceil(log(val)/log(2.0)); +/* calculate just so to produce a normalized value */ + sal = val * pow(2,(double)(63-l2b)); + l2b = 16383 + l2b; +/* store */ + reg->sign_bit = sgn; + reg->exponent = l2b; + reg->mantissa = (sx87_uldword)sal; +} + +void softx87_set_fpu_register_double(softx87_ctx* ctx,int i,double val) +{ + if (i < 0 || i > 7) + return; + + softx87_set_fpu_double(ctx,&ctx->state.st[i],val); +} + +/* callbacks intended to be called by softx86 */ +int softx87_on_fpu_opcode_exec(/* softx86_ctx */ void* _ctx86,/* softx87_ctx */ void* _ctx87,sx86_ubyte opcode) +{ + Sfx87OpcodeTable *sop; + softx86_ctx *ctx86; + softx87_ctx *ctx87; + sx87_ubyte op2; + +/* sanity check */ + ctx86 = (softx86_ctx*)_ctx86; + ctx87 = (softx87_ctx*)_ctx87; + if (!_ctx86 || !_ctx87) return 0; + if (opcode < 0xD8 || opcode > 0xDF) return 0; + sop = (Sfx87OpcodeTable*)ctx87->opcode_table; + + op2 = ctx87->callbacks.on_softx86_fetch_exec_byte(ctx86); + return sop->table[opcode-0xD8].exec(op2,ctx87); +} + +int softx87_on_fpu_opcode_dec(/* softx86_ctx */ void* _ctx86,/* softx87_ctx */ void* _ctx87,sx86_ubyte opcode,char buf[128]) +{ + Sfx87OpcodeTable *sop; + softx86_ctx *ctx86; + softx87_ctx *ctx87; + sx87_ubyte op2; + +/* sanity check */ + ctx86 = (softx86_ctx*)_ctx86; + ctx87 = (softx87_ctx*)_ctx87; + if (!_ctx86 || !_ctx87) return 0; + if (opcode < 0xD8 || opcode > 0xDF) return 0; + sop = (Sfx87OpcodeTable*)ctx87->opcode_table; + + op2 = ctx87->callbacks.on_softx86_fetch_dec_byte(ctx86); + return sop->table[opcode-0xD8].dec(op2,ctx87,buf); +} + +void softx87_finit_setup(softx87_ctx* ctx) +{ + softx87_set_fpu_register_double(ctx,0,0.00); + softx87_set_fpu_register_double(ctx,1,0.00); + softx87_set_fpu_register_double(ctx,2,0.00); + softx87_set_fpu_register_double(ctx,3,0.00); + softx87_set_fpu_register_double(ctx,4,0.00); + softx87_set_fpu_register_double(ctx,5,0.00); + softx87_set_fpu_register_double(ctx,6,0.00); + softx87_set_fpu_register_double(ctx,7,0.00); + ctx->state.control_word = 0x037F; + ctx->state.status_word = 0x0000; + ctx->state.tag_word = 0xFFFF; // all empty + ctx->state.last_instruction_memptr.offset = 0; + ctx->state.last_instruction_memptr.segment = 0; + ctx->state.data_pointer.offset = 0; + ctx->state.data_pointer.segment = 0; + ctx->state.last_opcode = 0; +} + +/* softx87_reset(context) + Resets a FPU + + return value: + 0 = failed + 1 = success */ +int softx87_reset(softx87_ctx* ctx) +{ + if (!ctx) return 0; + +/* switch on/off bugs */ + ctx->bugs.ip_ignores_prefix = + (ctx->level <= SX87_FPULEVEL_8087)?1:0; + +/* opcode table */ + ctx->opcode_table = (void*)(&optab8087); + +/* set up as if FINIT */ + softx87_finit_setup(ctx); + + return 1; /* success */ +} + +int softx87_getversion(int *major,int *minor,int *subminor) +{ + if (!minor || !major || !subminor) return 0; + + *major = SOFTX87_VERSION_HI; + *minor = SOFTX87_VERSION_LO; + *subminor = SOFTX87_VERSION_SUBLO; + return 1; +} + +/* softx87_init(context) + Initialize a FPU context structure. + + return value: + 0 = failed + 1 = success + 2 = beta development advisory (FPU level emulation not quite stable) */ +int softx87_init(softx87_ctx* ctx,int level) +{ + int ret; + + ret=1; + if (!ctx) return 0; + if (level > SX87_FPULEVEL_8087) return 0; /* we currently support up to the 8087 */ + if (level < 0) return 0; /* apparently the host wants an 80(-1)87? :) */ +// if (level > SX87_FPULEVEL_8087) ret=2; /* 80287 or higher emulation is not stable yet */ + ctx->level = level; + + if (!softx87_reset(ctx)) return 0; + +/* store version in the structure */ + ctx->version_hi = SOFTX87_VERSION_HI; + ctx->version_lo = SOFTX87_VERSION_LO; + ctx->version_sublo = SOFTX87_VERSION_SUBLO; + +/* default callbacks */ + ctx->callbacks.on_read_memory = softx87_step_def_on_read_memory; + ctx->callbacks.on_write_memory = softx87_step_def_on_write_memory; + ctx->callbacks.on_softx86_fetch_exec_byte = softx87_def_on_softx86_fetch_exec_byte; + ctx->callbacks.on_softx86_fetch_dec_byte = softx87_def_on_softx86_fetch_dec_byte; + ctx->callbacks.on_sx86_exec_full_modrmonly_memx = softx87_on_sx86_exec_full_modrmonly_memx; + ctx->callbacks.on_sx86_dec_full_modrmonly = softx87_on_sx86_dec_full_modrmonly; + + return ret; /* success */ +} + +/* softx86_free(context) + Free a FPU context structure */ +int softx87_free(softx87_ctx* ctx) +{ + if (!ctx) return 0; + + return 1; /* success */ +} + +/* enable/disable emulation of specific bugs. */ +int softx87_setbug(softx87_ctx* ctx,sx86_udword bug_id,sx86_ubyte on_off) +{ + if (bug_id == SX87_BUG_IP_IGNORES_PREFIX) { + ctx->bugs.ip_ignores_prefix = on_off; + return 1; + } + + return 0; +} + +/*-------------------------------------------------------------------------------- + default callbacks + --------------------------------------------------------------------------------*/ + +void softx87_on_sx86_exec_full_modrmonly_memx(softx86_ctx *ctx,sx86_ubyte mod,sx86_ubyte rm,int sz,void (*op64)(softx86_ctx* ctx,char *datz,int sz)) +{ +} + +void softx87_on_sx86_dec_full_modrmonly(softx86_ctx* ctx,sx86_ubyte is_word,sx86_ubyte dat32,sx86_ubyte mod,sx86_ubyte rm,char* op1) +{ +} + +sx86_ubyte softx87_def_on_softx86_fetch_exec_byte(softx86_ctx* ctx) +{ + return 0xFF; +} + +sx86_ubyte softx87_def_on_softx86_fetch_dec_byte(softx86_ctx* ctx) +{ + return 0xFF; +} + +void softx87_step_def_on_read_memory(void* _ctx,sx86_udword address,sx86_ubyte *buf,int size) +{ + softx87_ctx *ctx = ((softx87_ctx*)_ctx); + if (!ctx || !buf || size < 1) return; + memset(buf,0xFF,size); +} + +void softx87_step_def_on_write_memory(void* _ctx,sx86_udword address,sx86_ubyte *buf,int size) +{ + softx87_ctx *ctx = ((softx87_ctx*)_ctx); + if (!ctx || !buf || size < 1) return; +} + +/* loading/storing and conversion code */ + +/* loads 16-bit integer from data[] */ +void softx87_unpack_raw_int16(softx87_ctx* ctx,char *data,softx87_reg80 *v) +{ +#if SX86_BYTE_ORDER == LE + v->mantissa = (sx87_uldword)(*((sx87_uword*)data)); +#else + v->mantissa = (sx87_uldword)data[0]; + v->mantissa |= ((sx87_uldword)data[1])<<((sx87_uldword)8); +#endif + +/* there. we have all 16 bits. spread them around. */ + v->sign_bit = (v->mantissa >> ((sx87_uldword)15)); + v->exponent = 14; + if (v->sign_bit) v->mantissa = ((v->mantissa ^ 0xFFFF)+1); + v->mantissa <<= (sx87_uldword)49; + +/* convert the exponent */ + v->exponent = v->exponent + 16383; +} + +/* loads 32-bit integer from data[] */ +void softx87_unpack_raw_int32(softx87_ctx* ctx,char *data,softx87_reg80 *v) +{ +#if SX86_BYTE_ORDER == LE + v->mantissa = (sx87_uldword)(*((sx87_udword*)data)); +#else + v->mantissa = (sx87_uldword)data[3]; + v->mantissa |= ((sx87_uldword)data[2])<<((sx87_uldword)8); + v->mantissa |= ((sx87_uldword)data[1])<<((sx87_uldword)16); + v->mantissa |= ((sx87_uldword)data[0])<<((sx87_uldword)24); +#endif + +/* there. we have all 32 bits. spread them around. */ + v->sign_bit = (v->mantissa >> ((sx87_uldword)31)); + v->exponent = 30; + if (v->sign_bit) v->mantissa = ((v->mantissa ^ 0xFFFFFFFF)+1); + v->mantissa <<= (sx87_uldword)33; + +/* convert the exponent */ + v->exponent = v->exponent + 16383; +} + +/* loads 32-bit double precision floating point from data[] */ +void softx87_unpack_raw_fp32(softx87_ctx* ctx,char *data,softx87_reg80 *v) +{ +#if SX86_BYTE_ORDER == LE + v->mantissa = (sx87_uldword)(*((sx87_udword*)data)); +#else + v->mantissa = (sx87_uldword)data[3]; + v->mantissa |= ((sx87_uldword)data[2])<<((sx87_uldword)8); + v->mantissa |= ((sx87_uldword)data[1])<<((sx87_uldword)16); + v->mantissa |= ((sx87_uldword)data[0])<<((sx87_uldword)24); +#endif + +/* there. we have all 32 bits. spread them around. */ + v->sign_bit = (v->mantissa >> ((sx87_uldword)31)); + v->exponent = (v->mantissa >> ((sx87_uldword)23))&0xFF; + v->mantissa &= (sx87_uldword)(0x7FFFFF); + v->mantissa |= (sx87_uldword)(0x800000); /* implied "1"? */ + v->mantissa <<= (sx87_uldword)40; + +/* convert the exponent */ + v->exponent = (v->exponent - 127) + 16383; +} + +/* loads 64-bit double precision floating point from data[] */ +void softx87_unpack_raw_fp64(softx87_ctx* ctx,char *data,softx87_reg80 *v) +{ +#if SX86_BYTE_ORDER == LE + v->mantissa = *((sx87_uldword*)data); +#else + v->mantissa = (sx87_uldword)data[7]; + v->mantissa |= ((sx87_uldword)data[6])<<((sx87_uldword)8); + v->mantissa |= ((sx87_uldword)data[5])<<((sx87_uldword)16); + v->mantissa |= ((sx87_uldword)data[4])<<((sx87_uldword)24); + v->mantissa |= ((sx87_uldword)data[3])<<((sx87_uldword)32); + v->mantissa |= ((sx87_uldword)data[2])<<((sx87_uldword)40); + v->mantissa |= ((sx87_uldword)data[1])<<((sx87_uldword)48); + v->mantissa |= ((sx87_uldword)data[0])<<((sx87_uldword)56); +#endif + +/* there. we have all 64 bits. spread them around. */ + v->sign_bit = (v->mantissa >> ((sx87_uldword)63)); + v->exponent = (v->mantissa >> ((sx87_uldword)52))&0x7FF; + v->mantissa &= (sx87_uldword)(0x0FFFFFFFFFFFFF); + v->mantissa |= (sx87_uldword)(0x10000000000000); /* implied "1"? */ + v->mantissa <<= (sx87_uldword)11; + +/* convert the exponent */ + v->exponent = (v->exponent - 1023) + 16383; +} Index: lib/3rdparty/softx86/softx87/softx87.c =================================================================== --- lib/3rdparty/softx86/softx87/softx87.c (révision 59666) +++ lib/3rdparty/softx86/softx87/softx87.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx87/softx87.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx87/softx87_dll.def =================================================================== --- lib/3rdparty/softx86/softx87/softx87_dll.def (révision 0) +++ lib/3rdparty/softx86/softx87/softx87_dll.def (copie de travail) @@ -0,0 +1,14 @@ + +LIBRARY SOFTX87 +EXPORTS softx87_getversion + softx87_init + softx87_reset + softx87_free + softx87_get_fpu_register_double + softx87_set_fpu_register_double + softx87_finit_setup + softx87_on_fpu_opcode_exec + softx87_on_fpu_opcode_dec + softx87_setbug + softx87_unpack_raw_fp32 + softx87_unpack_raw_fp64 Index: lib/3rdparty/softx86/softx87/softx87_dll.def =================================================================== --- lib/3rdparty/softx86/softx87/softx87_dll.def (révision 59666) +++ lib/3rdparty/softx86/softx87/softx87_dll.def (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx87/softx87_dll.def ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx87/softx87_dll.dsp =================================================================== --- lib/3rdparty/softx86/softx87/softx87_dll.dsp (révision 0) +++ lib/3rdparty/softx86/softx87/softx87_dll.dsp (copie de travail) @@ -0,0 +1,117 @@ +# Microsoft Developer Studio Project File - Name="softx87_dll" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102 + +CFG=softx87_dll - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "softx87_dll.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "softx87_dll.mak" CFG="softx87_dll - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "softx87_dll - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE "softx87_dll - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +MTL=midl.exe +RSC=rc.exe + +!IF "$(CFG)" == "softx87_dll - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOFTX87_DLL_EXPORTS" /YX /FD /c +# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOFTX87_DLL_EXPORTS" /YX /FD /c +# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386 /out:"../bin/softx87.dll" /implib:"../lib/softx87_dll.lib" +# SUBTRACT LINK32 /pdb:none + +!ELSEIF "$(CFG)" == "softx87_dll - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Ignore_Export_Lib 0 +# PROP Target_Dir "" +# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOFTX87_DLL_EXPORTS" /YX /FD /GZ /c +# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "SOFTX87_DLL_EXPORTS" /YX /FD /GZ /c +# ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32 +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LINK32=link.exe +# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept +# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib ..\lib\softx87_static.lib /nologo /dll /debug /machine:I386 /out:"../bin/softx87.dll" /implib:"../lib/softx87_dll.lib" /pdbtype:sept +# SUBTRACT LINK32 /pdb:none + +!ENDIF + +# Begin Target + +# Name "softx87_dll - Win32 Release" +# Name "softx87_dll - Win32 Debug" +# Begin Group "Resource Files" + +# PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe" +# Begin Source File + +SOURCE=.\softx87_dll.rc +# End Source File +# End Group +# Begin Group "DLL export definitions" + +# PROP Default_Filter "*.def" +# Begin Source File + +SOURCE=.\softx87_dll.def +# End Source File +# End Group +# Begin Group "Win32 DLL shell" + +# PROP Default_Filter "" +# Begin Source File + +SOURCE=.\windll.c +# End Source File +# End Group +# End Target +# End Project Index: lib/3rdparty/softx86/softx87/softx87_dll.dsp =================================================================== --- lib/3rdparty/softx86/softx87/softx87_dll.dsp (révision 59666) +++ lib/3rdparty/softx86/softx87/softx87_dll.dsp (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx87/softx87_dll.dsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx87/softx87_dll.rc =================================================================== --- lib/3rdparty/softx86/softx87/softx87_dll.rc (révision 0) +++ lib/3rdparty/softx86/softx87/softx87_dll.rc (copie de travail) @@ -0,0 +1,109 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// English (U.S.) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_ENU) +#ifdef _WIN32 +LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US +#pragma code_page(1252) +#endif //_WIN32 + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 0,0,0,33 + PRODUCTVERSION 0,0,0,33 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x4L + FILETYPE 0x2L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "040904b0" + BEGIN + VALUE "Comments", "\0" + VALUE "CompanyName", "\0" + VALUE "FileDescription", "Softx87 FPU library v0.00.0033\0" + VALUE "FileVersion", "0, 0, 0, 33\0" + VALUE "InternalName", "softx87.dll\0" + VALUE "LegalCopyright", "Copyright © 2003, 2004 Jonathan Campbell\0" + VALUE "LegalTrademarks", "\0" + VALUE "OriginalFilename", "softx87.dll\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "Softx87\0" + VALUE "ProductVersion", "0, 0, 0, 33\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x409, 1200 + END +END + +#endif // !_MAC + + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + +#endif // English (U.S.) resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + Index: lib/3rdparty/softx86/softx87/softx87_dll.rc =================================================================== --- lib/3rdparty/softx86/softx87/softx87_dll.rc (révision 59666) +++ lib/3rdparty/softx86/softx87/softx87_dll.rc (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx87/softx87_dll.rc ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx87/softx87_static.dsp =================================================================== --- lib/3rdparty/softx86/softx87/softx87_static.dsp (révision 0) +++ lib/3rdparty/softx86/softx87/softx87_static.dsp (copie de travail) @@ -0,0 +1,108 @@ +# Microsoft Developer Studio Project File - Name="softx87_static" - Package Owner=<4> +# Microsoft Developer Studio Generated Build File, Format Version 6.00 +# ** DO NOT EDIT ** + +# TARGTYPE "Win32 (x86) Static Library" 0x0104 + +CFG=softx87_static - Win32 Debug +!MESSAGE This is not a valid makefile. To build this project using NMAKE, +!MESSAGE use the Export Makefile command and run +!MESSAGE +!MESSAGE NMAKE /f "softx87_static.mak". +!MESSAGE +!MESSAGE You can specify a configuration when running NMAKE +!MESSAGE by defining the macro CFG on the command line. For example: +!MESSAGE +!MESSAGE NMAKE /f "softx87_static.mak" CFG="softx87_static - Win32 Debug" +!MESSAGE +!MESSAGE Possible choices for configuration are: +!MESSAGE +!MESSAGE "softx87_static - Win32 Release" (based on "Win32 (x86) Static Library") +!MESSAGE "softx87_static - Win32 Debug" (based on "Win32 (x86) Static Library") +!MESSAGE + +# Begin Project +# PROP AllowPerConfigDependencies 0 +# PROP Scc_ProjName "" +# PROP Scc_LocalPath "" +CPP=cl.exe +RSC=rc.exe + +!IF "$(CFG)" == "softx87_static - Win32 Release" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 0 +# PROP BASE Output_Dir "Release" +# PROP BASE Intermediate_Dir "Release" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 0 +# PROP Output_Dir "Release" +# PROP Intermediate_Dir "Release" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD CPP /nologo /W3 /GX /O2 /I "./" /I "../include" /D "WIN32" /D "NDEBUG" /D "_MBCS" /D "_LIB" /YX /FD /c +# ADD BASE RSC /l 0x409 /d "NDEBUG" +# ADD RSC /l 0x409 /d "NDEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\lib\softx87_static.lib" + +!ELSEIF "$(CFG)" == "softx87_static - Win32 Debug" + +# PROP BASE Use_MFC 0 +# PROP BASE Use_Debug_Libraries 1 +# PROP BASE Output_Dir "Debug" +# PROP BASE Intermediate_Dir "Debug" +# PROP BASE Target_Dir "" +# PROP Use_MFC 0 +# PROP Use_Debug_Libraries 1 +# PROP Output_Dir "Debug" +# PROP Intermediate_Dir "Debug" +# PROP Target_Dir "" +# ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "./" /I "../include" /D "WIN32" /D "_DEBUG" /D "_MBCS" /D "_LIB" /YX /FD /GZ /c +# ADD BASE RSC /l 0x409 /d "_DEBUG" +# ADD RSC /l 0x409 /d "_DEBUG" +BSC32=bscmake.exe +# ADD BASE BSC32 /nologo +# ADD BSC32 /nologo +LIB32=link.exe -lib +# ADD BASE LIB32 /nologo +# ADD LIB32 /nologo /out:"..\lib\softx87_static.lib" + +!ENDIF + +# Begin Target + +# Name "softx87_static - Win32 Release" +# Name "softx87_static - Win32 Debug" +# Begin Group "Source Files" + +# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat" +# Begin Source File + +SOURCE=.\optable.c +# End Source File +# Begin Source File + +SOURCE=.\softx87.c +# End Source File +# End Group +# Begin Group "Header Files" + +# PROP Default_Filter "h;hpp;hxx;hm;inl" +# Begin Source File + +SOURCE=.\optab87.h +# End Source File +# Begin Source File + +SOURCE=..\include\softx87.h +# End Source File +# End Group +# End Target +# End Project Index: lib/3rdparty/softx86/softx87/softx87_static.dsp =================================================================== --- lib/3rdparty/softx86/softx87/softx87_static.dsp (révision 59666) +++ lib/3rdparty/softx86/softx87/softx87_static.dsp (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx87/softx87_static.dsp ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/softx87/windll.c =================================================================== --- lib/3rdparty/softx86/softx87/windll.c (révision 0) +++ lib/3rdparty/softx86/softx87/windll.c (copie de travail) @@ -0,0 +1,7 @@ + +#include + +BOOL WINAPI DllMain(HINSTANCE hInstance,DWORD dwReason,LPVOID lpWhatever) +{ + return TRUE; +} \ Pas de retour chariot à la fin du fichier Index: lib/3rdparty/softx86/softx87/windll.c =================================================================== --- lib/3rdparty/softx86/softx87/windll.c (révision 59666) +++ lib/3rdparty/softx86/softx87/windll.c (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/softx87/windll.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: lib/3rdparty/softx86/todo.txt =================================================================== --- lib/3rdparty/softx86/todo.txt (révision 0) +++ lib/3rdparty/softx86/todo.txt (copie de travail) @@ -0,0 +1,11 @@ + + - Most (if not the entire) x86 instruction set :) + + - Correct me if I'm wrong about when certain instructions + (like BOUND) appeared in the 8086 instruction set. Nobody + seems to have clear-cut documentation on precisely what + revision added what instructions. + + - Find everything wrong with 8086/8088 emulation NOW + so that in the future, development of 286/386/486 + emulation goes a lot smoother. \ Pas de retour chariot à la fin du fichier Index: lib/3rdparty/softx86/todo.txt =================================================================== --- lib/3rdparty/softx86/todo.txt (révision 59666) +++ lib/3rdparty/softx86/todo.txt (copie de travail) Modification de propriétés sur lib/3rdparty/softx86/todo.txt ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: ntoskrnl/ke/clock.c =================================================================== --- ntoskrnl/ke/clock.c (révision 59666) +++ ntoskrnl/ke/clock.c (copie de travail) @@ -242,8 +242,40 @@ OUT PULONG MaximumResolution, OUT PULONG ActualResolution) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + + /* Check if the call came from user mode */ + if (PreviousMode != KernelMode) + { + _SEH2_TRY + { + /* Probe the parameters */ + ProbeForWriteUlong(MinimumResolution); + ProbeForWriteUlong(MaximumResolution); + ProbeForWriteUlong(ActualResolution); + + /* Try to set the parameters to the actual values */ + *MinimumResolution = KeMinimumIncrement; + *MaximumResolution = KeMaximumIncrement; + *ActualResolution = KeTimeIncrement; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Return the exception code */ + _SEH2_YIELD(return _SEH2_GetExceptionCode()); + } + _SEH2_END; + } + else + { + /* The call came from kernel mode. Use the pointers directly */ + *MinimumResolution = KeMinimumIncrement; + *MaximumResolution = KeMaximumIncrement; + *ActualResolution = KeTimeIncrement; + } + + /* Return success */ + return STATUS_SUCCESS; } NTSTATUS @@ -252,8 +284,37 @@ IN BOOLEAN SetResolution, OUT PULONG CurrentResolution) { - UNIMPLEMENTED; - return STATUS_NOT_IMPLEMENTED; + ULONG NewResolution; + KPROCESSOR_MODE PreviousMode = ExGetPreviousMode(); + + /* Call the internal API */ + NewResolution = ExSetTimerResolution(DesiredResolution, SetResolution); + + /* Check if the call came from user mode */ + if (PreviousMode != KernelMode) + { + /* Try to write the value */ + _SEH2_TRY + { + ProbeForWriteUlong(CurrentResolution); + *CurrentResolution = NewResolution; + } + _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) + { + /* Return the exception code */ + _SEH2_YIELD(return _SEH2_GetExceptionCode()); + } + _SEH2_END; + } + else + { + /* The call came from kernel mode. Use the pointer directly */ + *CurrentResolution = NewResolution; + } + + /* Return success if we set the resolution */ + if (SetResolution) return STATUS_SUCCESS; + else return STATUS_TIMER_RESOLUTION_NOT_SET; } /* EOF */ Index: ntoskrnl/mm/section.c =================================================================== --- ntoskrnl/mm/section.c (révision 59666) +++ ntoskrnl/mm/section.c (copie de travail) @@ -237,6 +237,10 @@ if(pidhDosHeader->e_magic != IMAGE_DOS_SIGNATURE) DIE(("No MZ signature found, e_magic is %hX\n", pidhDosHeader->e_magic)); + /* check if this is an old MZ executable */ + if(pidhDosHeader->e_lfarlc < 0x40) + DIE(("Old-style MZ executable found, e_lfarlc is %d\n", pidhDosHeader->e_lfarlc)); + /* not a Windows executable */ if(pidhDosHeader->e_lfanew <= 0) DIE(("Not a Windows executable, e_lfanew is %d\n", pidhDosHeader->e_lfanew)); Index: subsystems/ntvdm/bios.c =================================================================== --- subsystems/ntvdm/bios.c (révision 0) +++ subsystems/ntvdm/bios.c (copie de travail) @@ -0,0 +1,951 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: bios.c + * PURPOSE: VDM BIOS + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "bios.h" +#include "emulator.h" +#include "vga.h" +#include "pic.h" +#include "ps2.h" +#include "timer.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static PBIOS_DATA_AREA Bda; +static BYTE BiosKeyboardMap[256]; +static HANDLE BiosConsoleInput = INVALID_HANDLE_VALUE; +static HANDLE BiosConsoleOutput = INVALID_HANDLE_VALUE; +static CONSOLE_SCREEN_BUFFER_INFO BiosSavedBufferInfo; + +static BYTE VideoMode_40x25_text[] = +{ + /* Miscellaneous Register */ + 0x67, + + /* Sequencer Registers */ + 0x03, 0x08, 0x03, 0x00, 0x02, + + /* GC Registers */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF, + + /* CRTC Registers */ + 0x2D, 0x27, 0x28, 0x90, 0x2B, 0xA0, 0xBF, 0x1F, 0x00, 0x4F, 0x0E, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x1F, 0x96, 0xB9, 0xA3, + 0xFF, + + /* AC Registers */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x01, 0x0F, 0x13, 0x00 +}; + +static BYTE VideoMode_80x25_text[] = +{ + /* Miscellaneous Register */ + 0x67, + + /* Sequencer Registers */ + 0x03, 0x00, 0x03, 0x00, 0x02, + + /* GC Registers */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x0E, 0x0F, 0xFF, + + /* CRTC Registers */ + 0x5F, 0x4F, 0x50, 0x82, 0x55, 0x81, 0xBF, 0x1F, 0x00, 0x4F, 0x0E, 0x0F, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x28, 0x1F, 0x96, 0xB9, 0xA3, + 0xFF, + + /* AC Registers */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x0C, 0x01, 0x0F, 0x13, 0x00 +}; + +static BYTE VideoMode_320x200_4color[] = +{ + /* Miscellaneous Register */ + 0x63, + + /* Sequencer Registers */ + 0x03, 0x09, 0x03, 0x00, 0x02, + + /* GC Registers */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x0F, 0x0F, 0xFF, + + /* CRTC Registers */ + 0x2D, 0x27, 0x28, 0x90, 0x2B, 0x80, 0xBF, 0x1F, 0x00, 0xC1, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x8E, 0x8F, 0x14, 0x00, 0x96, 0xB9, 0xA2, + 0xFF, + + /* AC Registers */ + 0x00, 0x13, 0x15, 0x17, 0x02, 0x04, 0x06, 0x07, 0x10, 0x11, 0x12, 0x13, + 0x14, 0x15, 0x16, 0x17, 0x01, 0x00, 0x03, 0x00, 0x00 +}; + +static BYTE VideoMode_640x480_16color[] = +{ + /* Miscellaneous Register */ + 0xE3, + + /* Sequencer Registers */ + 0x03, 0x01, 0x08, 0x00, 0x06, + + /* GC Registers */ + 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x05, 0x0F, 0xFF, + + /* CRTC Registers */ + 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0x0B, 0x3E, 0x00, 0x40, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0xEA, 0x0C, 0xDF, 0x28, 0x00, 0xE7, 0x04, 0xE3, + 0xFF, + + /* AC Registers */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x14, 0x07, 0x38, 0x39, 0x3A, 0x3B, + 0x3C, 0x3D, 0x3E, 0x3F, 0x01, 0x00, 0x0F, 0x00, 0x00 +}; + +static BYTE VideoMode_320x200_256color[] = +{ + /* Miscellaneous Register */ + 0x63, + + /* Sequencer Registers */ + 0x03, 0x01, 0x0F, 0x00, 0x0E, + + /* GC Registers */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x05, 0x0F, 0xFF, + + /* CRTC Registers */ + 0x5F, 0x4F, 0x50, 0x82, 0x54, 0x80, 0xBF, 0x1F, 0x00, 0x41, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x9C, 0x0E, 0x8F, 0x28, 0x40, 0x96, 0xB9, 0xA3, + 0xFF, + + /* AC Registers */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, + 0x0C, 0x0D, 0x0E, 0x0F, 0x41, 0x00, 0x0F, 0x00, 0x00 +}; + +static LPBYTE VideoModes[] = +{ + VideoMode_40x25_text, /* Mode 00h */ + VideoMode_40x25_text, /* Mode 01h */ + VideoMode_80x25_text, /* Mode 02h */ + VideoMode_80x25_text, /* Mode 03h */ + VideoMode_320x200_4color, /* Mode 04h */ + VideoMode_320x200_4color, /* Mode 05h */ + NULL, /* Mode 06h */ + NULL, /* Mode 07h */ + NULL, /* Mode 08h */ + NULL, /* Mode 09h */ + NULL, /* Mode 0Ah */ + NULL, /* Mode 0Bh */ + NULL, /* Mode 0Ch */ + NULL, /* Mode 0Dh */ + NULL, /* Mode 0Eh */ + NULL, /* Mode 0Fh */ + NULL, /* Mode 10h */ + NULL, /* Mode 11h */ + VideoMode_640x480_16color, /* Mode 12h */ + VideoMode_320x200_256color, /* Mode 13h */ +}; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static BOOLEAN BiosKbdBufferPush(WORD Data) +{ + /* Get the location of the element after the head */ + WORD NextElement = Bda->KeybdBufferHead + 2; + + /* Wrap it around if it's at or beyond the end */ + if (NextElement >= Bda->KeybdBufferEnd) NextElement = Bda->KeybdBufferStart; + + /* If it's full, fail */ + if (NextElement == Bda->KeybdBufferTail) return FALSE; + + /* Put the value in the queue */ + *((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferTail)) = Data; + Bda->KeybdBufferTail += sizeof(WORD); + + /* Check if we are at, or have passed, the end of the buffer */ + if (Bda->KeybdBufferTail >= Bda->KeybdBufferEnd) + { + /* Return it to the beginning */ + Bda->KeybdBufferTail = Bda->KeybdBufferStart; + } + + /* Return success */ + return TRUE; +} + +static BOOLEAN BiosKbdBufferTop(LPWORD Data) +{ + /* If it's empty, fail */ + if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE; + + /* Otherwise, get the value and return success */ + *Data = *((LPWORD)((ULONG_PTR)Bda + Bda->KeybdBufferHead)); + + return TRUE; +} + +static BOOLEAN BiosKbdBufferPop(VOID) +{ + /* If it's empty, fail */ + if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return FALSE; + + /* Remove the value from the queue */ + Bda->KeybdBufferHead += sizeof(WORD); + + /* Check if we are at, or have passed, the end of the buffer */ + if (Bda->KeybdBufferHead >= Bda->KeybdBufferEnd) + { + /* Return it to the beginning */ + Bda->KeybdBufferHead = Bda->KeybdBufferStart; + } + + /* Return success */ + return TRUE; +} + +static VOID BiosReadWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page) +{ + INT i, j; + INT Counter = 0; + WORD Character; + DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize); + + for (i = Rectangle.Top; i <= Rectangle.Bottom; i++) + { + for (j = Rectangle.Left; j <= Rectangle.Right; j++) + { + /* Read from video memory */ + VgaReadMemory(VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD), + (LPVOID)&Character, + sizeof(WORD)); + + /* Write the data to the buffer in row order */ + Buffer[Counter++] = Character; + } + } +} + +static VOID BiosWriteWindow(LPWORD Buffer, SMALL_RECT Rectangle, BYTE Page) +{ + INT i, j; + INT Counter = 0; + WORD Character; + DWORD VideoAddress = TO_LINEAR(TEXT_VIDEO_SEG, Page * Bda->VideoPageSize); + + for (i = Rectangle.Top; i <= Rectangle.Bottom; i++) + { + for (j = Rectangle.Left; j <= Rectangle.Right; j++) + { + Character = Buffer[Counter++]; + + /* Read from video memory */ + VgaWriteMemory(VideoAddress + (i * Bda->ScreenColumns + j) * sizeof(WORD), + (LPVOID)&Character, + sizeof(WORD)); + } + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +BYTE BiosGetVideoMode(VOID) +{ + return Bda->VideoMode; +} + +BOOLEAN BiosSetVideoMode(BYTE ModeNumber) +{ + INT i; + COORD Resolution; + LPBYTE Values = VideoModes[ModeNumber]; + + if (Values == NULL) return FALSE; + + /* Write the misc register */ + VgaWritePort(VGA_MISC_WRITE, *(Values++)); + + /* Write the sequencer registers */ + for (i = 0; i < VGA_SEQ_MAX_REG; i++) + { + VgaWritePort(VGA_SEQ_INDEX, i); + VgaWritePort(VGA_SEQ_DATA, *(Values++)); + } + + /* Write the GC registers */ + for (i = 0; i < VGA_GC_MAX_REG; i++) + { + VgaWritePort(VGA_GC_INDEX, i); + VgaWritePort(VGA_GC_DATA, *(Values++)); + } + + /* Write the CRTC registers */ + for (i = 0; i < VGA_CRTC_MAX_REG; i++) + { + VgaWritePort(VGA_CRTC_INDEX, i); + VgaWritePort(VGA_CRTC_DATA, *(Values++)); + } + + /* Write the AC registers */ + for (i = 0; i < VGA_AC_MAX_REG; i++) + { + VgaWritePort(VGA_AC_INDEX, i); + VgaWritePort(VGA_AC_WRITE, *(Values++)); + } + + /* Update the values in the BDA */ + Bda->VideoMode = ModeNumber; + Bda->VideoPage = 0; + Bda->VideoPageSize = BIOS_PAGE_SIZE; + Bda->VideoPageOffset = 0; + Bda->CharacterHeight = 16; + + Resolution = VgaGetDisplayResolution(); + Bda->ScreenColumns = Resolution.X; + Bda->ScreenRows = Resolution.Y - 1; + + return TRUE; +} + +BOOLEAN BiosSetVideoPage(BYTE PageNumber) +{ + if (PageNumber >= BIOS_MAX_PAGES) return FALSE; + + /* Set the values in the BDA */ + Bda->VideoPage = PageNumber; + Bda->VideoPageSize = BIOS_PAGE_SIZE; + Bda->VideoPageOffset = PageNumber * BIOS_PAGE_SIZE; + + /* Set the start address in the CRTC */ + VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG); + VgaWritePort(VGA_CRTC_DATA , LOBYTE(Bda->VideoPageOffset)); + VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG); + VgaWritePort(VGA_CRTC_DATA , HIBYTE(Bda->VideoPageOffset)); + + return TRUE; +} + +BOOLEAN BiosInitialize(VOID) +{ + INT i; + WORD Offset = 0; + LPWORD IntVecTable = (LPWORD)((ULONG_PTR)BaseAddress); + LPBYTE BiosCode = (LPBYTE)((ULONG_PTR)BaseAddress + TO_LINEAR(BIOS_SEGMENT, 0)); + + /* Initialize the BDA */ + Bda = (PBIOS_DATA_AREA)((ULONG_PTR)BaseAddress + TO_LINEAR(BDA_SEGMENT, 0)); + Bda->EquipmentList = BIOS_EQUIPMENT_LIST; + Bda->KeybdBufferStart = FIELD_OFFSET(BIOS_DATA_AREA, KeybdBuffer); + Bda->KeybdBufferEnd = Bda->KeybdBufferStart + BIOS_KBD_BUFFER_SIZE * sizeof(WORD); + + /* Generate ISR stubs and fill the IVT */ + for (i = 0; i < 256; i++) + { + IntVecTable[i * 2] = Offset; + IntVecTable[i * 2 + 1] = BIOS_SEGMENT; + + BiosCode[Offset++] = 0xFA; // cli + + BiosCode[Offset++] = 0x6A; // push i + BiosCode[Offset++] = (BYTE)i; + + BiosCode[Offset++] = LOBYTE(EMULATOR_BOP); // BOP sequence + BiosCode[Offset++] = HIBYTE(EMULATOR_BOP); + BiosCode[Offset++] = LOBYTE(EMULATOR_INT_BOP); + BiosCode[Offset++] = HIBYTE(EMULATOR_INT_BOP); + + BiosCode[Offset++] = 0x83; // add sp, 2 + BiosCode[Offset++] = 0xC4; + BiosCode[Offset++] = 0x02; + + BiosCode[Offset++] = 0xCF; // iret + } + + /* Get the input handle to the real console, and check for success */ + BiosConsoleInput = CreateFileW(L"CONIN$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + if (BiosConsoleInput == INVALID_HANDLE_VALUE) + { + return FALSE; + } + + /* Get the output handle to the real console, and check for success */ + BiosConsoleOutput = CreateFileW(L"CONOUT$", + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + OPEN_EXISTING, + 0, + NULL); + if (BiosConsoleOutput == INVALID_HANDLE_VALUE) + { + CloseHandle(BiosConsoleInput); + return FALSE; + } + + /* Save the console screen buffer information */ + if (!GetConsoleScreenBufferInfo(BiosConsoleOutput, &BiosSavedBufferInfo)) + { + CloseHandle(BiosConsoleOutput); + CloseHandle(BiosConsoleInput); + return FALSE; + } + + /* Store the cursor position */ + Bda->CursorPosition[0] = MAKEWORD(BiosSavedBufferInfo.dwCursorPosition.X, + BiosSavedBufferInfo.dwCursorPosition.Y); + + VgaInitialize(BiosConsoleOutput); + + /* Set the console input mode */ + SetConsoleMode(BiosConsoleInput, ENABLE_MOUSE_INPUT | ENABLE_PROCESSED_INPUT); + + /* Initialize the PIC */ + PicWriteCommand(PIC_MASTER_CMD, PIC_ICW1 | PIC_ICW1_ICW4); + PicWriteCommand(PIC_SLAVE_CMD , PIC_ICW1 | PIC_ICW1_ICW4); + + /* Set the interrupt offsets */ + PicWriteData(PIC_MASTER_DATA, BIOS_PIC_MASTER_INT); + PicWriteData(PIC_SLAVE_DATA , BIOS_PIC_SLAVE_INT); + + /* Tell the master PIC there is a slave at IRQ 2 */ + PicWriteData(PIC_MASTER_DATA, 1 << 2); + PicWriteData(PIC_SLAVE_DATA , 2); + + /* Make sure the PIC is in 8086 mode */ + PicWriteData(PIC_MASTER_DATA, PIC_ICW4_8086); + PicWriteData(PIC_SLAVE_DATA , PIC_ICW4_8086); + + /* Clear the masks for both PICs */ + PicWriteData(PIC_MASTER_DATA, 0x00); + PicWriteData(PIC_SLAVE_DATA , 0x00); + + PitWriteCommand(0x34); + PitWriteData(0, 0x00); + PitWriteData(0, 0x00); + + return TRUE; +} + +VOID BiosCleanup(VOID) +{ + /* Restore the old screen buffer */ + SetConsoleActiveScreenBuffer(BiosConsoleOutput); + + /* Restore the screen buffer size */ + SetConsoleScreenBufferSize(BiosConsoleOutput, BiosSavedBufferInfo.dwSize); + + /* Close the console handles */ + if (BiosConsoleOutput != INVALID_HANDLE_VALUE) CloseHandle(BiosConsoleOutput); + if (BiosConsoleInput != INVALID_HANDLE_VALUE) CloseHandle(BiosConsoleInput); +} + +WORD BiosPeekCharacter(VOID) +{ + WORD CharacterData; + + /* Check if there is a key available */ + if (Bda->KeybdBufferHead == Bda->KeybdBufferTail) return 0xFFFF; + + /* Get the key from the queue, but don't remove it */ + BiosKbdBufferTop(&CharacterData); + + return CharacterData; +} + +WORD BiosGetCharacter(VOID) +{ + WORD CharacterData; + INPUT_RECORD InputRecord; + DWORD Count; + + /* Check if there is a key available */ + if (Bda->KeybdBufferHead != Bda->KeybdBufferTail) + { + /* Get the key from the queue, and remove it */ + BiosKbdBufferTop(&CharacterData); + BiosKbdBufferPop(); + } + else + { + while (TRUE) + { + /* Wait for a console event */ + WaitForSingleObject(BiosConsoleInput, INFINITE); + + /* Read the event, and make sure it's a keypress */ + if (!ReadConsoleInput(BiosConsoleInput, &InputRecord, 1, &Count)) continue; + if (InputRecord.EventType != KEY_EVENT) continue; + if (!InputRecord.Event.KeyEvent.bKeyDown) continue; + + /* Save the scan code and end the loop */ + CharacterData = (InputRecord.Event.KeyEvent.wVirtualScanCode << 8) + | InputRecord.Event.KeyEvent.uChar.AsciiChar; + + break; + } + } + + return CharacterData; +} + +VOID BiosSetCursorPosition(BYTE Row, BYTE Column, BYTE Page) +{ + /* Make sure the selected video page is valid */ + if (Page >= BIOS_MAX_PAGES) return; + + /* Update the position in the BDA */ + Bda->CursorPosition[Page] = (Row << 8) | Column; + + /* Check if this is the current video page */ + if (Page == Bda->VideoPage) + { + WORD Offset = Row * Bda->ScreenColumns + Column; + + /* Modify the CRTC registers */ + VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_LOW_REG); + VgaWritePort(VGA_CRTC_DATA , LOBYTE(Offset)); + VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_LOC_HIGH_REG); + VgaWritePort(VGA_CRTC_DATA , HIBYTE(Offset)); + } +} + +BOOLEAN BiosScrollWindow(INT Direction, + DWORD Amount, + SMALL_RECT Rectangle, + BYTE Page, + BYTE FillAttribute) +{ + DWORD i; + LPWORD WindowData; + DWORD WindowSize = (Rectangle.Bottom - Rectangle.Top + 1) + * (Rectangle.Right - Rectangle.Left + 1); + + /* Allocate a buffer for the window */ + WindowData = (LPWORD)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + WindowSize * sizeof(WORD)); + if (WindowData == NULL) return FALSE; + + /* Read the window data */ + BiosReadWindow(WindowData, Rectangle, Page); + + if (Amount == 0) + { + /* Fill the window */ + for (i = 0; i < WindowSize; i++) + { + WindowData[i] = ' ' | (FillAttribute << 8); + } + + goto Done; + } + + // TODO: Scroll the window! + +Done: + /* Write back the window data */ + BiosWriteWindow(WindowData, Rectangle, Page); + + /* Free the window buffer */ + HeapFree(GetProcessHeap(), 0, WindowData); + + return TRUE; +} + +VOID BiosPrintCharacter(CHAR Character, BYTE Attribute, BYTE Page) +{ + WORD CharData = (Attribute << 8) | Character; + BYTE Row, Column; + + /* Make sure the page exists */ + if (Page >= BIOS_MAX_PAGES) return; + + /* Get the cursor location */ + Row = HIBYTE(Bda->CursorPosition[Page]); + Column = LOBYTE(Bda->CursorPosition[Page]); + + /* Write the character */ + VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG, + (Row * Bda->ScreenColumns + Column) * sizeof(WORD)), + (LPVOID)&CharData, + sizeof(WORD)); + + /* Advance the cursor */ + Column++; + + /* Check if it passed the end of the row */ + if (Column == Bda->ScreenColumns) + { + /* Return to the first column */ + Column = 0; + + if (Row == Bda->ScreenRows) + { + /* The screen must be scrolled */ + SMALL_RECT Rectangle = { 0, 0, Bda->ScreenColumns - 1, Bda->ScreenRows }; + + BiosScrollWindow(SCROLL_DIRECTION_UP, + 1, + Rectangle, + Page, + DEFAULT_ATTRIBUTE); + } + else Row++; + } + + /* Set the cursor position */ + BiosSetCursorPosition(Row, Column, Page); +} + +VOID BiosVideoService(LPWORD Stack) +{ + DWORD Eax = EmulatorGetRegister(EMULATOR_REG_AX); + DWORD Ecx = EmulatorGetRegister(EMULATOR_REG_CX); + DWORD Edx = EmulatorGetRegister(EMULATOR_REG_DX); + DWORD Ebx = EmulatorGetRegister(EMULATOR_REG_BX); + + switch (HIBYTE(Eax)) + { + /* Set Video Mode */ + case 0x00: + { + BiosSetVideoMode(LOBYTE(Eax)); + break; + } + + /* Set Text-Mode Cursor Shape */ + case 0x01: + { + /* Update the BDA */ + Bda->CursorStartLine = HIBYTE(Ecx); + Bda->CursorEndLine = LOBYTE(Ecx); + + /* Modify the CRTC registers */ + VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_START_REG); + VgaWritePort(VGA_CRTC_DATA , Bda->CursorStartLine); + VgaWritePort(VGA_CRTC_INDEX, VGA_CRTC_CURSOR_END_REG); + VgaWritePort(VGA_CRTC_DATA , Bda->CursorEndLine); + + break; + } + + /* Set Cursor Position */ + case 0x02: + { + BiosSetCursorPosition(HIBYTE(Edx), LOBYTE(Edx), HIBYTE(Ebx)); + break; + } + + /* Get Cursor Position */ + case 0x03: + { + /* Make sure the selected video page exists */ + if (HIBYTE(Ebx) >= BIOS_MAX_PAGES) break; + + /* Return the result */ + EmulatorSetRegister(EMULATOR_REG_AX, 0); + EmulatorSetRegister(EMULATOR_REG_CX, + (Bda->CursorStartLine << 8) | Bda->CursorEndLine); + EmulatorSetRegister(EMULATOR_REG_DX, Bda->CursorPosition[HIBYTE(Ebx)]); + + break; + } + + /* Select Active Display Page */ + case 0x05: + { + /* Check if the page exists */ + if (LOBYTE(Eax) >= BIOS_MAX_PAGES) break; + + /* Check if this is the same page */ + if (LOBYTE(Eax) == Bda->VideoPage) break; + + /* Change the video page */ + BiosSetVideoPage(LOBYTE(Eax)); + + break; + } + + /* Scroll Window Up/Down */ + case 0x06: + case 0x07: + { + SMALL_RECT Rectangle = + { + LOBYTE(Ecx), + HIBYTE(Ecx), + LOBYTE(Edx), + HIBYTE(Edx) + }; + + /* Call the internal function */ + BiosScrollWindow((HIBYTE(Eax)== 0x06) + ? SCROLL_DIRECTION_UP : SCROLL_DIRECTION_DOWN, + LOBYTE(Eax), + Rectangle, + Bda->VideoPage, + HIBYTE(Ebx)); + + break; + } + + /* Read/Write Character From Cursor Position */ + case 0x08: + case 0x09: + case 0x0A: + { + WORD CharacterData = MAKEWORD(LOBYTE(Eax), LOBYTE(Ebx)); + BYTE Page = HIBYTE(Ebx); + DWORD Offset; + + /* Check if the page exists */ + if (Page >= BIOS_MAX_PAGES) break; + + /* Find the offset of the character */ + Offset = Page * Bda->VideoPageSize + + (HIBYTE(Bda->CursorPosition[Page]) * Bda->ScreenColumns + + LOBYTE(Bda->CursorPosition[Page])) * 2; + + if (HIBYTE(Eax) == 0x08) + { + /* Read from the video memory */ + VgaReadMemory(TO_LINEAR(TEXT_VIDEO_SEG, Offset), + (LPVOID)&CharacterData, + sizeof(WORD)); + + /* Return the character in AX */ + EmulatorSetRegister(EMULATOR_REG_AX, CharacterData); + } + else + { + /* Write to video memory */ + VgaWriteMemory(TO_LINEAR(TEXT_VIDEO_SEG, Offset), + (LPVOID)&CharacterData, + (HIBYTE(Ebx) == 0x09) ? sizeof(WORD) : sizeof(BYTE)); + } + + break; + } + + /* Teletype Output */ + case 0x0E: + { + BiosPrintCharacter(LOBYTE(Eax), LOBYTE(Ebx), HIBYTE(Ebx)); + break; + } + + /* Get Current Video Mode */ + case 0x0F: + { + EmulatorSetRegister(EMULATOR_REG_AX, + MAKEWORD(Bda->VideoMode, Bda->ScreenColumns)); + EmulatorSetRegister(EMULATOR_REG_BX, + MAKEWORD(LOBYTE(Ebx), Bda->VideoPage)); + + break; + } + + /* Scroll Window */ + case 0x12: + { + SMALL_RECT Rectangle = + { + LOBYTE(Ecx), + HIBYTE(Ecx), + LOBYTE(Edx), + HIBYTE(Edx) + }; + + /* Call the internal function */ + BiosScrollWindow(LOBYTE(Ebx), + LOBYTE(Eax), + Rectangle, + Bda->VideoPage, + DEFAULT_ATTRIBUTE); + + break; + } + + default: + { + DPRINT1("BIOS Function INT 10h, AH = 0x%02X NOT IMPLEMENTED\n", + HIBYTE(Eax)); + } + } +} + +VOID BiosKeyboardService(LPWORD Stack) +{ + DWORD Eax = EmulatorGetRegister(EMULATOR_REG_AX); + + switch (HIBYTE(Eax)) + { + case 0x00: + { + /* Read the character (and wait if necessary) */ + EmulatorSetRegister(EMULATOR_REG_AX, BiosGetCharacter()); + + break; + } + + case 0x01: + { + WORD Data = BiosPeekCharacter(); + + if (Data != 0xFFFF) + { + /* There is a character, clear ZF and return it */ + EmulatorSetRegister(EMULATOR_REG_AX, Data); + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_ZF; + } + else + { + /* No character, set ZF */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_ZF; + } + + break; + } + + default: + { + DPRINT1("BIOS Function INT 16h, AH = 0x%02X NOT IMPLEMENTED\n", + HIBYTE(Eax)); + } + } +} + +VOID BiosTimeService(LPWORD Stack) +{ + DWORD Eax = EmulatorGetRegister(EMULATOR_REG_AX); + DWORD Ecx = EmulatorGetRegister(EMULATOR_REG_CX); + DWORD Edx = EmulatorGetRegister(EMULATOR_REG_DX); + + switch (HIBYTE(Eax)) + { + case 0x00: + { + /* Set AL to 1 if midnight had passed, 0 otherwise */ + Eax &= 0xFFFFFF00; + if (Bda->MidnightPassed) Eax |= 1; + + /* Return the tick count in CX:DX */ + EmulatorSetRegister(EMULATOR_REG_AX, Eax); + EmulatorSetRegister(EMULATOR_REG_CX, HIWORD(Bda->TickCounter)); + EmulatorSetRegister(EMULATOR_REG_DX, LOWORD(Bda->TickCounter)); + + /* Reset the midnight flag */ + Bda->MidnightPassed = FALSE; + + break; + } + + case 0x01: + { + /* Set the tick count to CX:DX */ + Bda->TickCounter = MAKELONG(LOWORD(Edx), LOWORD(Ecx)); + + /* Reset the midnight flag */ + Bda->MidnightPassed = FALSE; + + break; + } + + default: + { + DPRINT1("BIOS Function INT 1Ah, AH = 0x%02X NOT IMPLEMENTED\n", + HIBYTE(Eax)); + } + } +} + +VOID BiosSystemTimerInterrupt(LPWORD Stack) +{ + /* Increase the system tick count */ + Bda->TickCounter++; +} + +VOID BiosEquipmentService(LPWORD Stack) +{ + /* Return the equipment list */ + EmulatorSetRegister(EMULATOR_REG_AX, Bda->EquipmentList); +} + +VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack) +{ + switch (IrqNumber) + { + /* PIT IRQ */ + case 0: + { + /* Perform the system timer interrupt */ + EmulatorInterrupt(BIOS_SYS_TIMER_INTERRUPT); + + break; + } + + /* Keyboard IRQ */ + case 1: + { + BYTE ScanCode, VirtualKey; + WORD Character; + + /* Check if there is a scancode available */ + if (!(KeyboardReadStatus() & 1)) break; + + /* Get the scan code and virtual key code */ + ScanCode = KeyboardReadData(); + VirtualKey = MapVirtualKey(ScanCode & 0x7F, MAPVK_VSC_TO_VK); + + /* Check if this is a key press or release */ + if (!(ScanCode & (1 << 7))) + { + /* Key press */ + if (VirtualKey == VK_NUMLOCK + || VirtualKey == VK_CAPITAL + || VirtualKey == VK_SCROLL) + { + /* For toggle keys, toggle the lowest bit in the keyboard map */ + BiosKeyboardMap[VirtualKey] ^= ~(1 << 0); + } + + /* Set the highest bit */ + BiosKeyboardMap[VirtualKey] |= (1 << 7); + + /* Find out which character this is */ + if (ToAscii(VirtualKey, ScanCode, BiosKeyboardMap, &Character, 0) > 0) + { + /* Push it onto the BIOS keyboard queue */ + BiosKbdBufferPush((ScanCode << 8) | (Character & 0xFF)); + } + } + else + { + /* Key release, unset the highest bit */ + BiosKeyboardMap[VirtualKey] &= ~(1 << 7); + } + + break; + } + } + + /* Send End-of-Interrupt to the PIC */ + if (IrqNumber > 8) PicWriteCommand(PIC_SLAVE_CMD, PIC_OCW2_EOI); + PicWriteCommand(PIC_MASTER_CMD, PIC_OCW2_EOI); +} + +/* EOF */ Index: subsystems/ntvdm/bios.c =================================================================== --- subsystems/ntvdm/bios.c (révision 59666) +++ subsystems/ntvdm/bios.c (copie de travail) Modification de propriétés sur subsystems/ntvdm/bios.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: subsystems/ntvdm/bios.h =================================================================== --- subsystems/ntvdm/bios.h (révision 0) +++ subsystems/ntvdm/bios.h (copie de travail) @@ -0,0 +1,122 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: bios.h + * PURPOSE: VDM BIOS (header file) + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _BIOS_H_ +#define _BIOS_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +#define ROM_AREA_START 0xE0000 +#define ROM_AREA_END 0xFFFFF +#define BDA_SEGMENT 0x40 +#define BIOS_PIC_MASTER_INT 0x08 +#define BIOS_PIC_SLAVE_INT 0x70 +#define BIOS_SEGMENT 0xF000 +#define BIOS_VIDEO_INTERRUPT 0x10 +#define BIOS_EQUIPMENT_INTERRUPT 0x11 +#define BIOS_KBD_INTERRUPT 0x16 +#define BIOS_TIME_INTERRUPT 0x1A +#define BIOS_SYS_TIMER_INTERRUPT 0x1C +#define CONSOLE_FONT_HEIGHT 8 +#define BIOS_KBD_BUFFER_SIZE 16 +#define BIOS_EQUIPMENT_LIST 0x2C // HACK: Disable FPU for now +#define BIOS_DEFAULT_VIDEO_MODE 0x03 +#define BIOS_MAX_PAGES 8 +#define BIOS_PAGE_SIZE 0x1000 +#define BIOS_MAX_VIDEO_MODE 0x13 +#define DEFAULT_ATTRIBUTE 0x07 +#define GRAPHICS_VIDEO_SEG 0xA000 +#define TEXT_VIDEO_SEG 0xB800 + +enum +{ + SCROLL_DIRECTION_UP, + SCROLL_DIRECTION_DOWN, + SCROLL_DIRECTION_LEFT, + SCROLL_DIRECTION_RIGHT +}; + +#pragma pack(push, 1) + +typedef struct +{ + WORD SerialPorts[4]; + WORD ParallelPorts[3]; + WORD EbdaSegment; + WORD EquipmentList; + BYTE Reserved0; + WORD MemorySize; + WORD Reserved1; + WORD KeyboardFlags; + BYTE AlternateKeypad; + WORD KeybdBufferHead; + WORD KeybdBufferTail; + WORD KeybdBuffer[BIOS_KBD_BUFFER_SIZE]; + BYTE DriveRecalibrate; + BYTE DriveMotorStatus; + BYTE MotorShutdownCounter; + BYTE LastDisketteOperation; + BYTE Reserved2[7]; + BYTE VideoMode; + WORD ScreenColumns; + WORD VideoPageSize; + WORD VideoPageOffset; + WORD CursorPosition[BIOS_MAX_PAGES]; + BYTE CursorEndLine; + BYTE CursorStartLine; + BYTE VideoPage; + WORD CrtBasePort; + BYTE CrtModeControl; + BYTE CrtColorPaletteMask; + DWORD Uptime; + BYTE Reserved3; + DWORD TickCounter; + BYTE MidnightPassed; + BYTE BreakFlag; + WORD SoftReset; + BYTE LastDiskOperation; + BYTE NumDisks; + BYTE DriveControlByte; + BYTE DiskPortOffset; + BYTE LptTimeOut[4]; + BYTE ComTimeOut[4]; + WORD KeybdBufferStart; + WORD KeybdBufferEnd; + BYTE ScreenRows; + WORD CharacterHeight; +} BIOS_DATA_AREA, *PBIOS_DATA_AREA; + +#pragma pack(pop) + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN BiosInitialize(VOID); +VOID BiosCleanup(VOID); +BYTE BiosGetVideoMode(VOID); +BOOLEAN BiosSetVideoMode(BYTE ModeNumber); +WORD BiosPeekCharacter(VOID); +WORD BiosGetCharacter(VOID); +VOID BiosVideoService(LPWORD Stack); +VOID BiosEquipmentService(LPWORD Stack); +VOID BiosKeyboardService(LPWORD Stack); +VOID BiosTimeService(LPWORD Stack); +VOID BiosHandleIrq(BYTE IrqNumber, LPWORD Stack); +VOID BiosSystemTimerInterrupt(LPWORD Stack); +BOOLEAN BiosScrollWindow( + INT Direction, + DWORD Amount, + SMALL_RECT Rectangle, + BYTE Page, + BYTE FillAttribute +); + +#endif Index: subsystems/ntvdm/bios.h =================================================================== --- subsystems/ntvdm/bios.h (révision 59666) +++ subsystems/ntvdm/bios.h (copie de travail) Modification de propriétés sur subsystems/ntvdm/bios.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: subsystems/ntvdm/CMakeLists.txt =================================================================== --- subsystems/ntvdm/CMakeLists.txt (révision 59666) +++ subsystems/ntvdm/CMakeLists.txt (copie de travail) @@ -1,11 +1,20 @@ -include_directories(.) +include_directories(${REACTOS_SOURCE_DIR}/include/reactos/libs/softx86) -add_executable(ntvdm +list(APPEND SOURCE + bios.c + dos.c + emulator.c + pic.c + timer.c + ps2.c + vga.c ntvdm.c ntvdm.rc) -set_module_type(ntvdm win32cui) -add_importlibs(ntvdm ntdll user32 gdi32 advapi32 msvcrt kernel32) -add_dependencies(ntvdm ndk bugcodes) +add_executable(ntvdm ${SOURCE}) +set_module_type(ntvdm win32cui UNICODE) +target_link_libraries(ntvdm softx86 softx87) +add_importlibs(ntvdm msvcrt user32 kernel32 ntdll) +add_dependencies(ntvdm softx86 softx87) add_cd_file(TARGET ntvdm DESTINATION reactos/system32 FOR all) Index: subsystems/ntvdm/dos.c =================================================================== --- subsystems/ntvdm/dos.c (révision 0) +++ subsystems/ntvdm/dos.c (copie de travail) @@ -0,0 +1,2047 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: dos.c + * PURPOSE: VDM DOS Kernel + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "dos.h" +#include "bios.h" +#include "emulator.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static WORD CurrentPsp = SYSTEM_PSP; +static WORD DosLastError = 0; +static DWORD DiskTransferArea; +static HANDLE DosSystemFileTable[DOS_SFT_SIZE]; +static WORD DosSftRefCount[DOS_SFT_SIZE]; +static BYTE DosAllocStrategy = DOS_ALLOC_BEST_FIT; +static BOOLEAN DosUmbLinked = FALSE; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static VOID DosCombineFreeBlocks(WORD StartBlock) +{ + PDOS_MCB CurrentMcb = SEGMENT_TO_MCB(StartBlock), NextMcb; + + /* If this is the last block or it's not free, quit */ + if (CurrentMcb->BlockType == 'Z' || CurrentMcb->OwnerPsp != 0) return; + + while (TRUE) + { + /* Get a pointer to the next MCB */ + NextMcb = SEGMENT_TO_MCB(StartBlock + CurrentMcb->Size + 1); + + /* Check if the next MCB is free */ + if (NextMcb->OwnerPsp == 0) + { + /* Combine them */ + CurrentMcb->Size += NextMcb->Size + 1; + CurrentMcb->BlockType = NextMcb->BlockType; + NextMcb->BlockType = 'I'; + } + else + { + /* No more adjoining free blocks */ + break; + } + } +} + +static WORD DosCopyEnvironmentBlock(WORD SourceSegment, LPCSTR ProgramName) +{ + PCHAR Ptr, SourceBuffer, DestBuffer = NULL; + ULONG TotalSize = 0; + WORD DestSegment; + + Ptr = SourceBuffer = (PCHAR)((ULONG_PTR)BaseAddress + TO_LINEAR(SourceSegment, 0)); + + /* Calculate the size of the environment block */ + while (*Ptr) + { + TotalSize += strlen(Ptr) + 1; + Ptr += strlen(Ptr) + 1; + } + TotalSize++; + + /* Add the string buffer size */ + TotalSize += strlen(ProgramName) + 1; + + /* Allocate the memory for the environment block */ + DestSegment = DosAllocateMemory((WORD)((TotalSize + 0x0F) >> 4), NULL); + if (!DestSegment) return 0; + + Ptr = SourceBuffer; + + DestBuffer = (PCHAR)((ULONG_PTR)BaseAddress + TO_LINEAR(DestSegment, 0)); + while (*Ptr) + { + /* Copy the string */ + strcpy(DestBuffer, Ptr); + + /* Advance to the next string */ + DestBuffer += strlen(Ptr); + Ptr += strlen(Ptr) + 1; + + /* Put a zero after the string */ + *(DestBuffer++) = 0; + } + + /* Set the final zero */ + *(DestBuffer++) = 0; + + /* Copy the program name after the environment block */ + strcpy(DestBuffer, ProgramName); + + return DestSegment; +} + +static VOID DosChangeMemoryOwner(WORD Segment, WORD NewOwner) +{ + PDOS_MCB Mcb = SEGMENT_TO_MCB(Segment - 1); + + /* Just set the owner */ + Mcb->OwnerPsp = NewOwner; +} + +static WORD DosOpenHandle(HANDLE Handle) +{ + BYTE i; + WORD DosHandle; + PDOS_PSP PspBlock; + LPBYTE HandleTable; + + /* The system PSP has no handle table */ + if (CurrentPsp == SYSTEM_PSP) return INVALID_DOS_HANDLE; + + /* Get a pointer to the handle table */ + PspBlock = SEGMENT_TO_PSP(CurrentPsp); + HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr); + + /* Find a free entry in the JFT */ + for (DosHandle = 0; DosHandle < PspBlock->HandleTableSize; DosHandle++) + { + if (HandleTable[DosHandle] == 0xFF) break; + } + + /* If there are no free entries, fail */ + if (DosHandle == PspBlock->HandleTableSize) return INVALID_DOS_HANDLE; + + /* Check if the handle is already in the SFT */ + for (i = 0; i < DOS_SFT_SIZE; i++) + { + /* Check if this is the same handle */ + if (DosSystemFileTable[i] != Handle) continue; + + /* Already in the table, reference it */ + DosSftRefCount[i]++; + + /* Set the JFT entry to that SFT index */ + HandleTable[DosHandle] = i; + + /* Return the new handle */ + return DosHandle; + } + + /* Add the handle to the SFT */ + for (i = 0; i < DOS_SFT_SIZE; i++) + { + /* Make sure this is an empty table entry */ + if (DosSystemFileTable[i] != INVALID_HANDLE_VALUE) continue; + + /* Initialize the empty table entry */ + DosSystemFileTable[i] = Handle; + DosSftRefCount[i] = 1; + + /* Set the JFT entry to that SFT index */ + HandleTable[DosHandle] = i; + + /* Return the new handle */ + return DosHandle; + } + + /* The SFT is full */ + return INVALID_DOS_HANDLE; +} + +static HANDLE DosGetRealHandle(WORD DosHandle) +{ + PDOS_PSP PspBlock; + LPBYTE HandleTable; + + /* The system PSP has no handle table */ + if (CurrentPsp == SYSTEM_PSP) return INVALID_HANDLE_VALUE; + + /* Get a pointer to the handle table */ + PspBlock = SEGMENT_TO_PSP(CurrentPsp); + HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr); + + /* Make sure the handle is open */ + if (HandleTable[DosHandle] == 0xFF) return INVALID_HANDLE_VALUE; + + /* Return the Win32 handle */ + return DosSystemFileTable[HandleTable[DosHandle]]; +} + +static VOID DosCopyHandleTable(LPBYTE DestinationTable) +{ + INT i; + PDOS_PSP PspBlock; + LPBYTE SourceTable; + + /* Clear the table first */ + for (i = 0; i < 20; i++) DestinationTable[i] = 0xFF; + + /* Check if this is the initial process */ + if (CurrentPsp == SYSTEM_PSP) + { + /* Set up the standard I/O devices */ + for (i = 0; i <= 2; i++) + { + /* Set the index in the SFT */ + DestinationTable[i] = i; + + /* Increase the reference count */ + DosSftRefCount[i]++; + } + + /* Done */ + return; + } + + /* Get the parent PSP block and handle table */ + PspBlock = SEGMENT_TO_PSP(CurrentPsp); + SourceTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr); + + /* Copy the first 20 handles into the new table */ + for (i = 0; i < 20; i++) + { + DestinationTable[i] = SourceTable[i]; + + /* Increase the reference count */ + DosSftRefCount[SourceTable[i]]++; + } +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable) +{ + WORD Result = 0, Segment = FIRST_MCB_SEGMENT, MaxSize = 0; + PDOS_MCB CurrentMcb, NextMcb; + BOOLEAN SearchUmb = FALSE; + + DPRINT("DosAllocateMemory: Size 0x%04X\n", Size); + + if (DosUmbLinked && (DosAllocStrategy & (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW))) + { + /* Search UMB first */ + Segment = UMB_START_SEGMENT; + SearchUmb = TRUE; + } + + while (TRUE) + { + /* Get a pointer to the MCB */ + CurrentMcb = SEGMENT_TO_MCB(Segment); + + /* Make sure it's valid */ + if (CurrentMcb->BlockType != 'M' && CurrentMcb->BlockType != 'Z') + { + DPRINT("The DOS memory arena is corrupted!\n"); + DosLastError = ERROR_ARENA_TRASHED; + return 0; + } + + /* Only check free blocks */ + if (CurrentMcb->OwnerPsp != 0) goto Next; + + /* Combine this free block with adjoining free blocks */ + DosCombineFreeBlocks(Segment); + + /* Update the maximum block size */ + if (CurrentMcb->Size > MaxSize) MaxSize = CurrentMcb->Size; + + /* Check if this block is big enough */ + if (CurrentMcb->Size < Size) goto Next; + + switch (DosAllocStrategy & 0x3F) + { + case DOS_ALLOC_FIRST_FIT: + { + /* For first fit, stop immediately */ + Result = Segment; + goto Done; + } + + case DOS_ALLOC_BEST_FIT: + { + /* For best fit, update the smallest block found so far */ + if ((Result == 0) || (CurrentMcb->Size < SEGMENT_TO_MCB(Result)->Size)) + { + Result = Segment; + } + + break; + } + + case DOS_ALLOC_LAST_FIT: + { + /* For last fit, make the current block the result, but keep searching */ + Result = Segment; + break; + } + } + +Next: + /* If this was the last MCB in the chain, quit */ + if (CurrentMcb->BlockType == 'Z') + { + /* Check if nothing was found while searching through UMBs */ + if ((Result == 0) && SearchUmb && (DosAllocStrategy & DOS_ALLOC_HIGH_LOW)) + { + /* Search low memory */ + Segment = FIRST_MCB_SEGMENT; + continue; + } + + break; + } + + /* Otherwise, update the segment and continue */ + Segment += CurrentMcb->Size + 1; + } + +Done: + + /* If we didn't find a free block, return 0 */ + if (Result == 0) + { + DosLastError = ERROR_NOT_ENOUGH_MEMORY; + if (MaxAvailable) *MaxAvailable = MaxSize; + return 0; + } + + /* Get a pointer to the MCB */ + CurrentMcb = SEGMENT_TO_MCB(Result); + + /* Check if the block is larger than requested */ + if (CurrentMcb->Size > Size) + { + /* It is, split it into two blocks */ + NextMcb = SEGMENT_TO_MCB(Result + Size + 1); + + /* Initialize the new MCB structure */ + NextMcb->BlockType = CurrentMcb->BlockType; + NextMcb->Size = CurrentMcb->Size - Size - 1; + NextMcb->OwnerPsp = 0; + + /* Update the current block */ + CurrentMcb->BlockType = 'M'; + CurrentMcb->Size = Size; + } + + /* Take ownership of the block */ + CurrentMcb->OwnerPsp = CurrentPsp; + + /* Return the segment of the data portion of the block */ + return Result + 1; +} + +BOOLEAN DosResizeMemory(WORD BlockData, WORD NewSize, WORD *MaxAvailable) +{ + BOOLEAN Success = TRUE; + WORD Segment = BlockData - 1, ReturnSize = 0, NextSegment; + PDOS_MCB Mcb = SEGMENT_TO_MCB(Segment), NextMcb; + + DPRINT("DosResizeMemory: BlockData 0x%04X, NewSize 0x%04X\n", + BlockData, + NewSize); + + /* Make sure this is a valid, allocated block */ + if ((Mcb->BlockType != 'M' && Mcb->BlockType != 'Z') || Mcb->OwnerPsp == 0) + { + Success = FALSE; + DosLastError = ERROR_INVALID_HANDLE; + goto Done; + } + + ReturnSize = Mcb->Size; + + /* Check if we need to expand or contract the block */ + if (NewSize > Mcb->Size) + { + /* We can't expand the last block */ + if (Mcb->BlockType != 'M') + { + Success = FALSE; + goto Done; + } + + /* Get the pointer and segment of the next MCB */ + NextSegment = Segment + Mcb->Size + 1; + NextMcb = SEGMENT_TO_MCB(NextSegment); + + /* Make sure the next segment is free */ + if (NextMcb->OwnerPsp != 0) + { + DPRINT("Cannot expand memory block: next segment is not free!\n"); + DosLastError = ERROR_NOT_ENOUGH_MEMORY; + Success = FALSE; + goto Done; + } + + /* Combine this free block with adjoining free blocks */ + DosCombineFreeBlocks(NextSegment); + + /* Set the maximum possible size of the block */ + ReturnSize += NextMcb->Size + 1; + + /* Maximize the current block */ + Mcb->Size = ReturnSize; + Mcb->BlockType = NextMcb->BlockType; + + /* Invalidate the next block */ + NextMcb->BlockType = 'I'; + + /* Check if the block is larger than requested */ + if (Mcb->Size > NewSize) + { + DPRINT("Block too large, reducing size from 0x%04X to 0x%04X\n", + Mcb->Size, + NewSize); + + /* It is, split it into two blocks */ + NextMcb = SEGMENT_TO_MCB(Segment + NewSize + 1); + + /* Initialize the new MCB structure */ + NextMcb->BlockType = Mcb->BlockType; + NextMcb->Size = Mcb->Size - NewSize - 1; + NextMcb->OwnerPsp = 0; + + /* Update the current block */ + Mcb->BlockType = 'M'; + Mcb->Size = NewSize; + } + } + else if (NewSize < Mcb->Size) + { + DPRINT("Shrinking block from 0x%04X to 0x%04X\n", + Mcb->Size, + NewSize); + + /* Just split the block */ + NextMcb = SEGMENT_TO_MCB(Segment + NewSize + 1); + NextMcb->BlockType = Mcb->BlockType; + NextMcb->Size = Mcb->Size - NewSize - 1; + NextMcb->OwnerPsp = 0; + + /* Update the MCB */ + Mcb->BlockType = 'M'; + Mcb->Size = NewSize; + } + +Done: + /* Check if the operation failed */ + if (!Success) + { + DPRINT("DosResizeMemory FAILED. Maximum available: 0x%04X\n", + ReturnSize); + + /* Return the maximum possible size */ + if (MaxAvailable) *MaxAvailable = ReturnSize; + } + + return Success; +} + +BOOLEAN DosFreeMemory(WORD BlockData) +{ + PDOS_MCB Mcb = SEGMENT_TO_MCB(BlockData - 1); + + DPRINT("DosFreeMemory: BlockData 0x%04X\n", BlockData); + + /* Make sure the MCB is valid */ + if (Mcb->BlockType != 'M' && Mcb->BlockType != 'Z') + { + DPRINT("MCB block type '%c' not valid!\n", Mcb->BlockType); + return FALSE; + } + + /* Mark the block as free */ + Mcb->OwnerPsp = 0; + + return TRUE; +} + +BOOLEAN DosLinkUmb(VOID) +{ + DWORD Segment = FIRST_MCB_SEGMENT; + PDOS_MCB Mcb = SEGMENT_TO_MCB(Segment); + + DPRINT("Linking UMB\n"); + + /* Check if UMBs are already linked */ + if (DosUmbLinked) return FALSE; + + /* Find the last block */ + while ((Mcb->BlockType == 'M') && (Segment <= 0xFFFF)) + { + Segment += Mcb->Size + 1; + Mcb = SEGMENT_TO_MCB(Segment); + } + + /* Make sure it's valid */ + if (Mcb->BlockType != 'Z') return FALSE; + + /* Connect the MCB with the UMB chain */ + Mcb->BlockType = 'M'; + + DosUmbLinked = TRUE; + return TRUE; +} + +BOOLEAN DosUnlinkUmb(VOID) +{ + DWORD Segment = FIRST_MCB_SEGMENT; + PDOS_MCB Mcb = SEGMENT_TO_MCB(Segment); + + DPRINT("Unlinking UMB\n"); + + /* Check if UMBs are already unlinked */ + if (!DosUmbLinked) return FALSE; + + /* Find the block preceding the MCB that links it with the UMB chain */ + while (Segment <= 0xFFFF) + { + if ((Segment + Mcb->Size) == (FIRST_MCB_SEGMENT + USER_MEMORY_SIZE)) + { + /* This is the last non-UMB segment */ + break; + } + + /* Advance to the next MCB */ + Segment += Mcb->Size + 1; + Mcb = SEGMENT_TO_MCB(Segment); + } + + /* Mark the MCB as the last MCB */ + Mcb->BlockType = 'Z'; + + DosUmbLinked = FALSE; + return TRUE; +} + +WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes) +{ + HANDLE FileHandle; + WORD DosHandle; + + DPRINT("DosCreateFile: FilePath \"%s\", Attributes 0x%04X\n", + FilePath, + Attributes); + + /* Create the file */ + FileHandle = CreateFileA(FilePath, + GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + CREATE_ALWAYS, + Attributes, + NULL); + + if (FileHandle == INVALID_HANDLE_VALUE) + { + /* Return the error code */ + return (WORD)GetLastError(); + } + + /* Open the DOS handle */ + DosHandle = DosOpenHandle(FileHandle); + + if (DosHandle == INVALID_DOS_HANDLE) + { + /* Close the handle */ + CloseHandle(FileHandle); + + /* Return the error code */ + return ERROR_TOO_MANY_OPEN_FILES; + } + + /* It was successful */ + *Handle = DosHandle; + return ERROR_SUCCESS; +} + +WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessMode) +{ + HANDLE FileHandle; + ACCESS_MASK Access = 0; + WORD DosHandle; + + DPRINT("DosOpenFile: FilePath \"%s\", AccessMode 0x%04X\n", + FilePath, + AccessMode); + + /* Parse the access mode */ + switch (AccessMode & 3) + { + case 0: + { + /* Read-only */ + Access = GENERIC_READ; + break; + } + + case 1: + { + /* Write only */ + Access = GENERIC_WRITE; + break; + } + + case 2: + { + /* Read and write */ + Access = GENERIC_READ | GENERIC_WRITE; + break; + } + + default: + { + /* Invalid */ + return ERROR_INVALID_PARAMETER; + } + } + + /* Open the file */ + FileHandle = CreateFileA(FilePath, + Access, + FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + + if (FileHandle == INVALID_HANDLE_VALUE) + { + /* Return the error code */ + return (WORD)GetLastError(); + } + + /* Open the DOS handle */ + DosHandle = DosOpenHandle(FileHandle); + + if (DosHandle == INVALID_DOS_HANDLE) + { + /* Close the handle */ + CloseHandle(FileHandle); + + /* Return the error code */ + return ERROR_TOO_MANY_OPEN_FILES; + } + + /* It was successful */ + *Handle = DosHandle; + return ERROR_SUCCESS; +} + +WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead) +{ + WORD Result = ERROR_SUCCESS; + DWORD BytesRead32 = 0; + HANDLE Handle = DosGetRealHandle(FileHandle); + + DPRINT("DosReadFile: FileHandle 0x%04X, Count 0x%04X\n", FileHandle, Count); + + /* Make sure the handle is valid */ + if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE; + + /* Read the file */ + if (!ReadFile(Handle, Buffer, Count, &BytesRead32, NULL)) + { + /* Store the error code */ + Result = (WORD)GetLastError(); + } + + /* The number of bytes read is always 16-bit */ + *BytesRead = LOWORD(BytesRead32); + + /* Return the error code */ + return Result; +} + +WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten) +{ + WORD Result = ERROR_SUCCESS; + DWORD BytesWritten32 = 0; + HANDLE Handle = DosGetRealHandle(FileHandle); + + DPRINT("DosWriteFile: FileHandle 0x%04X, Count 0x%04X\n", + FileHandle, + Count); + + /* Make sure the handle is valid */ + if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE; + + /* Write the file */ + if (!WriteFile(Handle, Buffer, Count, &BytesWritten32, NULL)) + { + /* Store the error code */ + Result = (WORD)GetLastError(); + } + + /* The number of bytes written is always 16-bit */ + *BytesWritten = LOWORD(BytesWritten32); + + /* Return the error code */ + return Result; +} + +WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset) +{ + WORD Result = ERROR_SUCCESS; + DWORD FilePointer; + HANDLE Handle = DosGetRealHandle(FileHandle); + + DPRINT("DosSeekFile: FileHandle 0x%04X, Offset 0x%08X, Origin 0x%02X\n", + FileHandle, + Offset, + Origin); + + /* Make sure the handle is valid */ + if (Handle == INVALID_HANDLE_VALUE) return ERROR_INVALID_HANDLE; + + /* Check if the origin is valid */ + if (Origin != FILE_BEGIN && Origin != FILE_CURRENT && Origin != FILE_END) + { + return ERROR_INVALID_FUNCTION; + } + + /* Move the file pointer */ + FilePointer = SetFilePointer(Handle, Offset, NULL, Origin); + + /* Check if there's a possibility the operation failed */ + if (FilePointer == INVALID_SET_FILE_POINTER) + { + /* Get the real error code */ + Result = (WORD)GetLastError(); + } + + if (Result != ERROR_SUCCESS) + { + /* The operation did fail */ + return Result; + } + + /* Return the file pointer, if requested */ + if (NewOffset) *NewOffset = FilePointer; + + /* Return success */ + return ERROR_SUCCESS; +} + +BOOLEAN DosDuplicateHandle(WORD OldHandle, WORD NewHandle) +{ + BYTE SftIndex; + PDOS_PSP PspBlock; + LPBYTE HandleTable; + + DPRINT("DosDuplicateHandle: OldHandle 0x%04X, NewHandle 0x%04X\n", + OldHandle, + NewHandle); + + /* The system PSP has no handle table */ + if (CurrentPsp == SYSTEM_PSP) return FALSE; + + /* Get a pointer to the handle table */ + PspBlock = SEGMENT_TO_PSP(CurrentPsp); + HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr); + + /* Make sure the old handle is open */ + if (HandleTable[OldHandle] == 0xFF) return FALSE; + + /* Check if the new handle is open */ + if (HandleTable[NewHandle] != 0xFF) + { + /* Close it */ + DosCloseHandle(NewHandle); + } + + /* Increment the reference count of the SFT entry */ + SftIndex = HandleTable[OldHandle]; + DosSftRefCount[SftIndex]++; + + /* Make the new handle point to that SFT entry */ + HandleTable[NewHandle] = SftIndex; + + /* Return success */ + return TRUE; +} + +BOOLEAN DosCloseHandle(WORD DosHandle) +{ + BYTE SftIndex; + PDOS_PSP PspBlock; + LPBYTE HandleTable; + + DPRINT("DosCloseHandle: DosHandle 0x%04X\n", DosHandle); + + /* The system PSP has no handle table */ + if (CurrentPsp == SYSTEM_PSP) return FALSE; + + /* Get a pointer to the handle table */ + PspBlock = SEGMENT_TO_PSP(CurrentPsp); + HandleTable = (LPBYTE)FAR_POINTER(PspBlock->HandleTablePtr); + + /* Make sure the handle is open */ + if (HandleTable[DosHandle] == 0xFF) return FALSE; + + /* Decrement the reference count of the SFT entry */ + SftIndex = HandleTable[DosHandle]; + DosSftRefCount[SftIndex]--; + + /* Check if the reference count fell to zero */ + if (!DosSftRefCount[SftIndex]) + { + /* Close the file, it's no longer needed */ + CloseHandle(DosSystemFileTable[SftIndex]); + + /* Clear the handle */ + DosSystemFileTable[SftIndex] = INVALID_HANDLE_VALUE; + } + + /* Clear the entry in the JFT */ + HandleTable[DosHandle] = 0xFF; + + return TRUE; +} + +VOID DosInitializePsp(WORD PspSegment, LPCSTR CommandLine, WORD ProgramSize, WORD Environment) +{ + PDOS_PSP PspBlock = SEGMENT_TO_PSP(PspSegment); + LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress); + + ZeroMemory(PspBlock, sizeof(DOS_PSP)); + + /* Set the exit interrupt */ + PspBlock->Exit[0] = 0xCD; // int 0x20 + PspBlock->Exit[1] = 0x20; + + /* Set the number of the last paragraph */ + PspBlock->LastParagraph = PspSegment + ProgramSize - 1; + + /* Save the interrupt vectors */ + PspBlock->TerminateAddress = IntVecTable[0x22]; + PspBlock->BreakAddress = IntVecTable[0x23]; + PspBlock->CriticalAddress = IntVecTable[0x24]; + + /* Set the parent PSP */ + PspBlock->ParentPsp = CurrentPsp; + + /* Copy the parent handle table */ + DosCopyHandleTable(PspBlock->HandleTable); + + /* Set the environment block */ + PspBlock->EnvBlock = Environment; + + /* Set the handle table pointers to the internal handle table */ + PspBlock->HandleTableSize = 20; + PspBlock->HandleTablePtr = MAKELONG(0x18, PspSegment); + + /* Set the DOS version */ + PspBlock->DosVersion = DOS_VERSION; + + /* Set the far call opcodes */ + PspBlock->FarCall[0] = 0xCD; // int 0x21 + PspBlock->FarCall[1] = 0x21; + PspBlock->FarCall[2] = 0xCB; // retf + + /* Set the command line */ + PspBlock->CommandLineSize = strlen(CommandLine); + RtlCopyMemory(PspBlock->CommandLine, CommandLine, PspBlock->CommandLineSize); + PspBlock->CommandLine[PspBlock->CommandLineSize] = '\r'; +} + +BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock) +{ + BOOLEAN Success = FALSE, AllocatedEnvBlock = FALSE; + HANDLE FileHandle = INVALID_HANDLE_VALUE, FileMapping = NULL; + LPBYTE Address = NULL; + LPSTR ProgramFilePath, Parameters[128]; + CHAR CommandLineCopy[128]; + INT ParamCount = 0; + WORD Segment = 0; + WORD MaxAllocSize; + DWORD i, FileSize, ExeSize; + PIMAGE_DOS_HEADER Header; + PDWORD RelocationTable; + PWORD RelocWord; + + DPRINT("DosCreateProcess: CommandLine \"%s\", EnvBlock 0x%04X\n", + CommandLine, + EnvBlock); + + /* Save a copy of the command line */ + strcpy(CommandLineCopy, CommandLine); + + /* Get the file name of the executable */ + ProgramFilePath = strtok(CommandLineCopy, " \t"); + + /* Load the parameters in the local array */ + while ((ParamCount < 256) + && ((Parameters[ParamCount] = strtok(NULL, " \t")) != NULL)) + { + ParamCount++; + } + + /* Open a handle to the executable */ + FileHandle = CreateFileA(ProgramFilePath, + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, + NULL); + if (FileHandle == INVALID_HANDLE_VALUE) goto Cleanup; + + /* Get the file size */ + FileSize = GetFileSize(FileHandle, NULL); + + /* Create a mapping object for the file */ + FileMapping = CreateFileMapping(FileHandle, + NULL, + PAGE_READONLY, + 0, + 0, + NULL); + if (FileMapping == NULL) goto Cleanup; + + /* Map the file into memory */ + Address = (LPBYTE)MapViewOfFile(FileMapping, FILE_MAP_READ, 0, 0, 0); + if (Address == NULL) goto Cleanup; + + /* Did we get an environment segment? */ + if (!EnvBlock) + { + /* Set a flag to know if the environment block was allocated here */ + AllocatedEnvBlock = TRUE; + + /* No, copy the one from the parent */ + EnvBlock = DosCopyEnvironmentBlock((CurrentPsp != SYSTEM_PSP) + ? SEGMENT_TO_PSP(CurrentPsp)->EnvBlock + : SYSTEM_ENV_BLOCK, + ProgramFilePath); + } + + /* Check if this is an EXE file or a COM file */ + if (Address[0] == 'M' && Address[1] == 'Z') + { + /* EXE file */ + + /* Get the MZ header */ + Header = (PIMAGE_DOS_HEADER)Address; + + /* Get the base size of the file, in paragraphs (rounded up) */ + ExeSize = (((Header->e_cp - 1) * 512) + Header->e_cblp + 0x0F) >> 4; + + /* Add the PSP size, in paragraphs */ + ExeSize += sizeof(DOS_PSP) >> 4; + + /* Add the maximum size that should be allocated */ + ExeSize += Header->e_maxalloc; + + /* Make sure it does not pass 0xFFFF */ + if (ExeSize > 0xFFFF) ExeSize = 0xFFFF; + + /* Reduce the size one by one until the allocation is successful */ + for (i = Header->e_maxalloc; i >= Header->e_minalloc; i--, ExeSize--) + { + /* Try to allocate that much memory */ + Segment = DosAllocateMemory(ExeSize, NULL); + if (Segment != 0) break; + } + + /* Check if at least the lowest allocation was successful */ + if (Segment == 0) goto Cleanup; + + /* Initialize the PSP */ + DosInitializePsp(Segment, + CommandLine, + ExeSize, + EnvBlock); + + /* The process owns its own memory */ + DosChangeMemoryOwner(Segment, Segment); + DosChangeMemoryOwner(EnvBlock, Segment); + + /* Copy the program to Segment:0100 */ + RtlCopyMemory((PVOID)((ULONG_PTR)BaseAddress + + TO_LINEAR(Segment, 0x100)), + Address + (Header->e_cparhdr << 4), + min(FileSize - (Header->e_cparhdr << 4), + (ExeSize << 4) - sizeof(DOS_PSP))); + + /* Get the relocation table */ + RelocationTable = (PDWORD)(Address + Header->e_lfarlc); + + /* Perform relocations */ + for (i = 0; i < Header->e_crlc; i++) + { + /* Get a pointer to the word that needs to be patched */ + RelocWord = (PWORD)((ULONG_PTR)BaseAddress + + TO_LINEAR(Segment + HIWORD(RelocationTable[i]), + 0x100 + LOWORD(RelocationTable[i]))); + + /* Add the number of the EXE segment to it */ + *RelocWord += Segment + (sizeof(DOS_PSP) >> 4); + } + + /* Set the initial segment registers */ + EmulatorSetRegister(EMULATOR_REG_DS, Segment); + EmulatorSetRegister(EMULATOR_REG_ES, Segment); + + /* Set the stack to the location from the header */ + EmulatorSetStack(Segment + (sizeof(DOS_PSP) >> 4) + Header->e_ss, + Header->e_sp); + + /* Execute */ + CurrentPsp = Segment; + DiskTransferArea = MAKELONG(0x80, Segment); + EmulatorExecute(Segment + Header->e_cs + (sizeof(DOS_PSP) >> 4), + Header->e_ip); + + Success = TRUE; + } + else + { + /* COM file */ + + /* Find the maximum amount of memory that can be allocated */ + DosAllocateMemory(0xFFFF, &MaxAllocSize); + + /* Make sure it's enough for the whole program and the PSP */ + if (((DWORD)MaxAllocSize << 4) < (FileSize + sizeof(DOS_PSP))) goto Cleanup; + + /* Allocate all of it */ + Segment = DosAllocateMemory(MaxAllocSize, NULL); + if (Segment == 0) goto Cleanup; + + /* The process owns its own memory */ + DosChangeMemoryOwner(Segment, Segment); + DosChangeMemoryOwner(EnvBlock, Segment); + + /* Copy the program to Segment:0100 */ + RtlCopyMemory((PVOID)((ULONG_PTR)BaseAddress + + TO_LINEAR(Segment, 0x100)), + Address, + FileSize); + + /* Initialize the PSP */ + DosInitializePsp(Segment, + CommandLine, + (FileSize + sizeof(DOS_PSP)) >> 4, + EnvBlock); + + /* Set the initial segment registers */ + EmulatorSetRegister(EMULATOR_REG_DS, Segment); + EmulatorSetRegister(EMULATOR_REG_ES, Segment); + + /* Set the stack to the last word of the segment */ + EmulatorSetStack(Segment, 0xFFFE); + + /* Execute */ + CurrentPsp = Segment; + DiskTransferArea = MAKELONG(0x80, Segment); + EmulatorExecute(Segment, 0x100); + + Success = TRUE; + } + +Cleanup: + if (!Success) + { + /* It was not successful, cleanup the DOS memory */ + if (AllocatedEnvBlock) DosFreeMemory(EnvBlock); + if (Segment) DosFreeMemory(Segment); + } + + /* Unmap the file*/ + if (Address != NULL) UnmapViewOfFile(Address); + + /* Close the file mapping object */ + if (FileMapping != NULL) CloseHandle(FileMapping); + + /* Close the file handle */ + if (FileHandle != INVALID_HANDLE_VALUE) CloseHandle(FileHandle); + + return Success; +} + +VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode) +{ + WORD i; + WORD McbSegment = FIRST_MCB_SEGMENT; + PDOS_MCB CurrentMcb; + LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress); + PDOS_PSP PspBlock = SEGMENT_TO_PSP(Psp); + + DPRINT("DosTerminateProcess: Psp 0x%04X, ReturnCode 0x%02X\n", + Psp, + ReturnCode); + + /* Check if this PSP is it's own parent */ + if (PspBlock->ParentPsp == Psp) goto Done; + + for (i = 0; i < PspBlock->HandleTableSize; i++) + { + /* Close the handle */ + DosCloseHandle(i); + } + + /* Free the memory used by the process */ + while (TRUE) + { + /* Get a pointer to the MCB */ + CurrentMcb = SEGMENT_TO_MCB(McbSegment); + + /* Make sure the MCB is valid */ + if (CurrentMcb->BlockType != 'M' && CurrentMcb->BlockType !='Z') break; + + /* If this block was allocated by the process, free it */ + if (CurrentMcb->OwnerPsp == Psp) DosFreeMemory(McbSegment); + + /* If this was the last block, quit */ + if (CurrentMcb->BlockType == 'Z') break; + + /* Update the segment and continue */ + McbSegment += CurrentMcb->Size + 1; + } + +Done: + /* Restore the interrupt vectors */ + IntVecTable[0x22] = PspBlock->TerminateAddress; + IntVecTable[0x23] = PspBlock->BreakAddress; + IntVecTable[0x24] = PspBlock->CriticalAddress; + + /* Update the current PSP */ + if (Psp == CurrentPsp) + { + CurrentPsp = PspBlock->ParentPsp; + if (CurrentPsp == SYSTEM_PSP) VdmRunning = FALSE; + } + + /* Return control to the parent process */ + EmulatorExecute(HIWORD(PspBlock->TerminateAddress), + LOWORD(PspBlock->TerminateAddress)); +} + +CHAR DosReadCharacter(VOID) +{ + CHAR Character = '\0'; + WORD BytesRead; + + /* Use the file reading function */ + DosReadFile(DOS_INPUT_HANDLE, &Character, sizeof(CHAR), &BytesRead); + + return Character; +} + +VOID DosPrintCharacter(CHAR Character) +{ + WORD BytesWritten; + + /* Use the file writing function */ + DosWriteFile(DOS_OUTPUT_HANDLE, &Character, sizeof(CHAR), &BytesWritten); +} + +BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle) +{ + HANDLE Handle = DosGetRealHandle(FileHandle); + + if (Handle == INVALID_HANDLE_VALUE) + { + /* Doesn't exist */ + DosLastError = ERROR_FILE_NOT_FOUND; + return FALSE; + } + + switch (ControlCode) + { + /* Get Device Information */ + case 0x00: + { + WORD InfoWord = 0; + + if (Handle == DosSystemFileTable[0]) + { + /* Console input */ + InfoWord |= 1 << 0; + } + else if (Handle == DosSystemFileTable[1]) + { + /* Console output */ + InfoWord |= 1 << 1; + } + + /* It is a character device */ + InfoWord |= 1 << 7; + + /* Return the device information word */ + EmulatorSetRegister(EMULATOR_REG_DX, InfoWord); + + return TRUE; + } + + /* Unsupported control code */ + default: + { + DPRINT1("Unsupported IOCTL: 0x%02X\n", ControlCode); + + DosLastError = ERROR_INVALID_PARAMETER; + return FALSE; + } + } +} + +VOID DosInt20h(LPWORD Stack) +{ + /* This is the exit interrupt */ + DosTerminateProcess(Stack[STACK_CS], 0); +} + +VOID DosInt21h(LPWORD Stack) +{ + INT i; + CHAR Character; + SYSTEMTIME SystemTime; + PCHAR String; + PDOS_INPUT_BUFFER InputBuffer; + DWORD Eax = EmulatorGetRegister(EMULATOR_REG_AX); + DWORD Ecx = EmulatorGetRegister(EMULATOR_REG_CX); + DWORD Edx = EmulatorGetRegister(EMULATOR_REG_DX); + DWORD Ebx = EmulatorGetRegister(EMULATOR_REG_BX); + WORD DataSegment = EmulatorGetRegister(EMULATOR_REG_DS); + WORD ExtSegment = EmulatorGetRegister(EMULATOR_REG_ES); + + /* Check the value in the AH register */ + switch (HIBYTE(Eax)) + { + /* Terminate Program */ + case 0x00: + { + DosTerminateProcess(Stack[STACK_CS], 0); + break; + } + + /* Read Character And Echo */ + case 0x01: + { + Character = DosReadCharacter(); + DosPrintCharacter(Character); + EmulatorSetRegister(EMULATOR_REG_AX, (Eax & 0xFFFFFF00) | Character); + break; + } + + /* Print Character */ + case 0x02: + { + DosPrintCharacter(LOBYTE(Edx)); + break; + } + + /* Read Character Without Echo */ + case 0x07: + case 0x08: + { + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFFFF00) | DosReadCharacter()); + break; + } + + /* Print String */ + case 0x09: + { + String = (PCHAR)((ULONG_PTR)BaseAddress + + TO_LINEAR(DataSegment, LOWORD(Edx))); + + while ((*String) != '$') + { + DosPrintCharacter(*String); + String++; + } + + break; + } + + /* Read Buffered Input */ + case 0x0A: + { + InputBuffer = (PDOS_INPUT_BUFFER)((ULONG_PTR)BaseAddress + + TO_LINEAR(DataSegment, + LOWORD(Edx))); + + InputBuffer->Length = 0; + for (i = 0; i < InputBuffer->MaxLength; i ++) + { + Character = DosReadCharacter(); + DosPrintCharacter(Character); + InputBuffer->Buffer[InputBuffer->Length] = Character; + if (Character == '\r') break; + InputBuffer->Length++; + } + + break; + } + + /* Set Disk Transfer Area */ + case 0x1A: + { + DiskTransferArea = MAKELONG(LOWORD(Edx), DataSegment); + break; + } + + /* Set Interrupt Vector */ + case 0x25: + { + DWORD FarPointer = MAKELONG(LOWORD(Edx), DataSegment); + + /* Write the new far pointer to the IDT */ + ((PDWORD)BaseAddress)[LOBYTE(Eax)] = FarPointer; + + break; + } + + /* Get system date */ + case 0x2A: + { + GetLocalTime(&SystemTime); + EmulatorSetRegister(EMULATOR_REG_CX, + (Ecx & 0xFFFF0000) | SystemTime.wYear); + EmulatorSetRegister(EMULATOR_REG_DX, + (Edx & 0xFFFF0000) + | (SystemTime.wMonth << 8) + | SystemTime.wDay); + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFFFF00) | SystemTime.wDayOfWeek); + break; + } + + /* Set system date */ + case 0x2B: + { + GetLocalTime(&SystemTime); + SystemTime.wYear = LOWORD(Ecx); + SystemTime.wMonth = HIBYTE(Edx); + SystemTime.wDay = LOBYTE(Edx); + + if (SetLocalTime(&SystemTime)) + { + /* Return success */ + EmulatorSetRegister(EMULATOR_REG_AX, Eax & 0xFFFFFF00); + } + else + { + /* Return failure */ + EmulatorSetRegister(EMULATOR_REG_AX, Eax | 0xFF); + } + + break; + } + + /* Get system time */ + case 0x2C: + { + GetLocalTime(&SystemTime); + EmulatorSetRegister(EMULATOR_REG_CX, + (Ecx & 0xFFFF0000) + | (SystemTime.wHour << 8) + | SystemTime.wMinute); + EmulatorSetRegister(EMULATOR_REG_DX, + (Edx & 0xFFFF0000) + | (SystemTime.wSecond << 8) + | (SystemTime.wMilliseconds / 10)); + break; + } + + /* Set system time */ + case 0x2D: + { + GetLocalTime(&SystemTime); + SystemTime.wHour = HIBYTE(Ecx); + SystemTime.wMinute = LOBYTE(Ecx); + SystemTime.wSecond = HIBYTE(Edx); + SystemTime.wMilliseconds = LOBYTE(Edx) * 10; + + if (SetLocalTime(&SystemTime)) + { + /* Return success */ + EmulatorSetRegister(EMULATOR_REG_AX, Eax & 0xFFFFFF00); + } + else + { + /* Return failure */ + EmulatorSetRegister(EMULATOR_REG_AX, Eax | 0xFF); + } + + break; + } + + /* Get Disk Transfer Area */ + case 0x2F: + { + EmulatorSetRegister(EMULATOR_REG_ES, HIWORD(DiskTransferArea)); + EmulatorSetRegister(EMULATOR_REG_BX, LOWORD(DiskTransferArea)); + + break; + } + + /* Get DOS Version */ + case 0x30: + { + PDOS_PSP PspBlock = SEGMENT_TO_PSP(CurrentPsp); + + EmulatorSetRegister(EMULATOR_REG_AX, PspBlock->DosVersion); + break; + } + + /* Get Interrupt Vector */ + case 0x35: + { + DWORD FarPointer = ((PDWORD)BaseAddress)[LOBYTE(Eax)]; + + /* Read the address from the IDT into ES:BX */ + EmulatorSetRegister(EMULATOR_REG_ES, HIWORD(FarPointer)); + EmulatorSetRegister(EMULATOR_REG_BX, LOWORD(FarPointer)); + + break; + } + + /* Create Directory */ + case 0x39: + { + String = (PCHAR)((ULONG_PTR)BaseAddress + + TO_LINEAR(DataSegment, LOWORD(Edx))); + + if (CreateDirectoryA(String, NULL)) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFF0000) | LOWORD(GetLastError())); + } + + break; + } + + /* Remove Directory */ + case 0x3A: + { + String = (PCHAR)((ULONG_PTR)BaseAddress + + TO_LINEAR(DataSegment, LOWORD(Edx))); + + if (RemoveDirectoryA(String)) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFF0000) | LOWORD(GetLastError())); + } + + + break; + } + + /* Set Current Directory */ + case 0x3B: + { + String = (PCHAR)((ULONG_PTR)BaseAddress + + TO_LINEAR(DataSegment, LOWORD(Edx))); + + if (SetCurrentDirectoryA(String)) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFF0000) | LOWORD(GetLastError())); + } + + break; + } + + /* Create File */ + case 0x3C: + { + WORD FileHandle; + WORD ErrorCode = DosCreateFile(&FileHandle, + (LPCSTR)(ULONG_PTR)BaseAddress + + TO_LINEAR(DataSegment, LOWORD(Edx)), + LOWORD(Ecx)); + + if (ErrorCode == 0) + { + /* Clear CF */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + + /* Return the handle in AX */ + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFF0000) | FileHandle); + } + else + { + /* Set CF */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + + /* Return the error code in AX */ + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFF0000) | ErrorCode); + } + + break; + } + + /* Open File */ + case 0x3D: + { + WORD FileHandle; + WORD ErrorCode = DosCreateFile(&FileHandle, + (LPCSTR)(ULONG_PTR)BaseAddress + + TO_LINEAR(DataSegment, LOWORD(Edx)), + LOBYTE(Eax)); + + if (ErrorCode == 0) + { + /* Clear CF */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + + /* Return the handle in AX */ + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFF0000) | FileHandle); + } + else + { + /* Set CF */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + + /* Return the error code in AX */ + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFF0000) | ErrorCode); + } + + break; + } + + /* Close File */ + case 0x3E: + { + if (DosCloseHandle(LOWORD(Ebx))) + { + /* Clear CF */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + /* Set CF */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + + /* Return the error code in AX */ + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFF0000) | ERROR_INVALID_HANDLE); + } + + break; + } + + /* Read File */ + case 0x3F: + { + WORD BytesRead = 0; + WORD ErrorCode = DosReadFile(LOWORD(Ebx), + (LPVOID)((ULONG_PTR)BaseAddress + + TO_LINEAR(DataSegment, LOWORD(Edx))), + LOWORD(Ecx), + &BytesRead); + + if (ErrorCode == 0) + { + /* Clear CF */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + + /* Return the number of bytes read in AX */ + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFF0000) | BytesRead); + } + else + { + /* Set CF */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + + /* Return the error code in AX */ + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFF0000) | ErrorCode); + } + break; + } + + /* Write File */ + case 0x40: + { + WORD BytesWritten = 0; + WORD ErrorCode = DosWriteFile(LOWORD(Ebx), + (LPVOID)((ULONG_PTR)BaseAddress + + TO_LINEAR(DataSegment, LOWORD(Edx))), + LOWORD(Ecx), + &BytesWritten); + + if (ErrorCode == 0) + { + /* Clear CF */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + + /* Return the number of bytes written in AX */ + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFF0000) | BytesWritten); + } + else + { + /* Set CF */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + + /* Return the error code in AX */ + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFF0000) | ErrorCode); + } + + break; + } + + /* Delete File */ + case 0x41: + { + LPSTR FileName = (LPSTR)((ULONG_PTR)BaseAddress + TO_LINEAR(DataSegment, Edx)); + + /* Call the API function */ + if (DeleteFileA(FileName)) Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_AX, GetLastError()); + } + + break; + } + + /* Seek File */ + case 0x42: + { + DWORD NewLocation; + WORD ErrorCode = DosSeekFile(LOWORD(Ebx), + MAKELONG(LOWORD(Edx), LOWORD(Ecx)), + LOBYTE(Eax), + &NewLocation); + + if (ErrorCode == 0) + { + /* Clear CF */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + + /* Return the new offset in DX:AX */ + EmulatorSetRegister(EMULATOR_REG_DX, + (Edx & 0xFFFF0000) | HIWORD(NewLocation)); + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFF0000) | LOWORD(NewLocation)); + } + else + { + /* Set CF */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + + /* Return the error code in AX */ + EmulatorSetRegister(EMULATOR_REG_AX, + (Eax & 0xFFFF0000) | ErrorCode); + } + + break; + } + + /* Get/Set File Attributes */ + case 0x43: + { + DWORD Attributes; + LPSTR FileName = (LPSTR)((ULONG_PTR)BaseAddress + TO_LINEAR(DataSegment, Edx)); + + if (LOBYTE(Eax) == 0x00) + { + /* Get the attributes */ + Attributes = GetFileAttributesA(FileName); + + /* Check if it failed */ + if (Attributes == INVALID_FILE_ATTRIBUTES) + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_AX, GetLastError()); + + break; + } + + /* Return the attributes that DOS can understand */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_CX, + (Ecx & 0xFFFFFF00) | LOBYTE(Attributes)); + } + else if (LOBYTE(Eax) == 0x01) + { + /* Try to set the attributes */ + if (SetFileAttributesA(FileName, LOBYTE(Ecx))) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_AX, GetLastError()); + } + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_FUNCTION); + } + + break; + } + + /* IOCTL */ + case 0x44: + { + if (DosHandleIoctl(LOBYTE(Eax), LOWORD(Ebx))) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_AX, DosLastError); + } + + break; + } + + /* Duplicate Handle */ + case 0x45: + { + WORD NewHandle; + HANDLE Handle = DosGetRealHandle(LOWORD(Ebx)); + + if (Handle != INVALID_HANDLE_VALUE) + { + /* The handle is invalid */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_HANDLE); + + break; + } + + /* Open a new handle to the same entry */ + NewHandle = DosOpenHandle(Handle); + + if (NewHandle == INVALID_DOS_HANDLE) + { + /* Too many files open */ + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_AX, ERROR_TOO_MANY_OPEN_FILES); + + break; + } + + /* Return the result */ + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_AX, NewHandle); + + break; + } + + /* Force Duplicate Handle */ + case 0x46: + { + if (DosDuplicateHandle(LOWORD(Ebx), LOWORD(Ecx))) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_HANDLE); + } + + break; + } + + /* Allocate Memory */ + case 0x48: + { + WORD MaxAvailable = 0; + WORD Segment = DosAllocateMemory(LOWORD(Ebx), &MaxAvailable); + + if (Segment != 0) + { + EmulatorSetRegister(EMULATOR_REG_AX, Segment); + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + EmulatorSetRegister(EMULATOR_REG_AX, DosLastError); + EmulatorSetRegister(EMULATOR_REG_BX, MaxAvailable); + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + } + + break; + } + + /* Free Memory */ + case 0x49: + { + if (DosFreeMemory(ExtSegment)) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + EmulatorSetRegister(EMULATOR_REG_AX, ERROR_ARENA_TRASHED); + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + } + + break; + } + + /* Resize Memory Block */ + case 0x4A: + { + WORD Size; + + if (DosResizeMemory(ExtSegment, LOWORD(Ebx), &Size)) + { + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + EmulatorSetRegister(EMULATOR_REG_AX, DosLastError); + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_BX, Size); + } + + break; + } + + /* Terminate With Return Code */ + case 0x4C: + { + DosTerminateProcess(CurrentPsp, LOBYTE(Eax)); + break; + } + + /* Get Current Process */ + case 0x51: + { + EmulatorSetRegister(EMULATOR_REG_BX, CurrentPsp); + + break; + } + + /* Get/Set Memory Management Options */ + case 0x58: + { + if (LOBYTE(Eax) == 0x00) + { + /* Get allocation strategy */ + + EmulatorSetRegister(EMULATOR_REG_AX, DosAllocStrategy); + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else if (LOBYTE(Eax) == 0x01) + { + /* Set allocation strategy */ + + if ((LOBYTE(Ebx) & (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW)) + == (DOS_ALLOC_HIGH | DOS_ALLOC_HIGH_LOW)) + { + /* Can't set both */ + EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_PARAMETER); + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + break; + } + + if ((LOBYTE(Ebx) & 0x3F) > DOS_ALLOC_LAST_FIT) + { + /* Invalid allocation strategy */ + EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_PARAMETER); + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + break; + } + + DosAllocStrategy = LOBYTE(Ebx); + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else if (LOBYTE(Eax) == 0x02) + { + /* Get UMB link state */ + + Eax &= 0xFFFFFF00; + if (DosUmbLinked) Eax |= 1; + EmulatorSetRegister(EMULATOR_REG_AX, Eax); + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else if (LOBYTE(Eax) == 0x03) + { + /* Set UMB link state */ + + if (Ebx) DosLinkUmb(); + else DosUnlinkUmb(); + Stack[STACK_FLAGS] &= ~EMULATOR_FLAG_CF; + } + else + { + /* Invalid or unsupported function */ + + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + EmulatorSetRegister(EMULATOR_REG_AX, ERROR_INVALID_FUNCTION); + } + + break; + } + + /* Unsupported */ + default: + { + DPRINT1("DOS Function INT 0x21, AH = 0x%02X NOT IMPLEMENTED!\n", HIBYTE(Eax)); + Stack[STACK_FLAGS] |= EMULATOR_FLAG_CF; + } + } +} + +VOID DosBreakInterrupt(LPWORD Stack) +{ + VdmRunning = FALSE; +} + +BOOLEAN DosInitialize(VOID) +{ + BYTE i; + PDOS_MCB Mcb = SEGMENT_TO_MCB(FIRST_MCB_SEGMENT); + FILE *Stream; + WCHAR Buffer[256]; + LPWSTR SourcePtr, Environment; + LPSTR AsciiString; + LPSTR DestPtr = (LPSTR)((ULONG_PTR)BaseAddress + TO_LINEAR(SYSTEM_ENV_BLOCK, 0)); + DWORD AsciiSize; + + /* Initialize the MCB */ + Mcb->BlockType = 'Z'; + Mcb->Size = USER_MEMORY_SIZE; + Mcb->OwnerPsp = 0; + + /* Initialize the link MCB to the UMB area */ + Mcb = SEGMENT_TO_MCB(FIRST_MCB_SEGMENT + USER_MEMORY_SIZE + 1); + Mcb->BlockType = 'M'; + Mcb->Size = UMB_START_SEGMENT - FIRST_MCB_SEGMENT - USER_MEMORY_SIZE - 2; + Mcb->OwnerPsp = SYSTEM_PSP; + + /* Initialize the UMB area */ + Mcb = SEGMENT_TO_MCB(UMB_START_SEGMENT); + Mcb->BlockType = 'Z'; + Mcb->Size = UMB_END_SEGMENT - UMB_START_SEGMENT; + Mcb->OwnerPsp = 0; + + /* Get the environment strings */ + SourcePtr = Environment = GetEnvironmentStringsW(); + if (Environment == NULL) return FALSE; + + /* Fill the DOS system environment block */ + while (*SourcePtr) + { + /* Get the size of the ASCII string */ + AsciiSize = WideCharToMultiByte(CP_ACP, + 0, + SourcePtr, + -1, + NULL, + 0, + NULL, + NULL); + + /* Allocate memory for the ASCII string */ + AsciiString = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, AsciiSize); + if (AsciiString == NULL) + { + FreeEnvironmentStringsW(Environment); + return FALSE; + } + + /* Convert to ASCII */ + WideCharToMultiByte(CP_ACP, + 0, + SourcePtr, + -1, + AsciiString, + AsciiSize, + NULL, + NULL); + + /* Copy the string into DOS memory */ + strcpy(DestPtr, AsciiString); + + /* Move to the next string */ + SourcePtr += wcslen(SourcePtr) + 1; + DestPtr += strlen(AsciiString); + *(DestPtr++) = 0; + + /* Free the memory */ + HeapFree(GetProcessHeap(), 0, AsciiString); + } + *DestPtr = 0; + + /* Free the memory allocated for environment strings */ + FreeEnvironmentStringsW(Environment); + + /* Read CONFIG.SYS */ + Stream = _wfopen(DOS_CONFIG_PATH, L"r"); + if (Stream != NULL) + { + while (fgetws(Buffer, 256, Stream)) + { + // TODO: Parse the line + } + fclose(Stream); + } + + /* Initialize the SFT */ + for (i = 0; i < DOS_SFT_SIZE; i++) + { + DosSystemFileTable[i] = INVALID_HANDLE_VALUE; + DosSftRefCount[i] = 0; + } + + /* Get handles to standard I/O devices */ + DosSystemFileTable[0] = GetStdHandle(STD_INPUT_HANDLE); + DosSystemFileTable[1] = GetStdHandle(STD_OUTPUT_HANDLE); + DosSystemFileTable[2] = GetStdHandle(STD_ERROR_HANDLE); + + return TRUE; +} + +/* EOF */ Index: subsystems/ntvdm/dos.c =================================================================== --- subsystems/ntvdm/dos.c (révision 59666) +++ subsystems/ntvdm/dos.c (copie de travail) Modification de propriétés sur subsystems/ntvdm/dos.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: subsystems/ntvdm/dos.h =================================================================== --- subsystems/ntvdm/dos.h (révision 0) +++ subsystems/ntvdm/dos.h (copie de travail) @@ -0,0 +1,138 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: dos.h + * PURPOSE: VDM DOS Kernel (header file) + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _DOS_H_ +#define _DOS_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +#define DOS_VERSION MAKEWORD(6, 0) +#define DOS_CONFIG_PATH L"%SystemRoot%\\system32\\CONFIG.NT" +#define DOS_COMMAND_INTERPRETER L"%SystemRoot%\\system32\\COMMAND.COM /k %SystemRoot%\\system32\\AUTOEXEC.NT" +#define FIRST_MCB_SEGMENT 0x1000 +#define USER_MEMORY_SIZE 0x8FFE +#define SYSTEM_PSP 0x08 +#define SYSTEM_ENV_BLOCK 0x800 +#define INVALID_DOS_HANDLE 0xFFFF +#define DOS_INPUT_HANDLE 0 +#define DOS_OUTPUT_HANDLE 1 +#define DOS_ERROR_HANDLE 2 +#define DOS_SFT_SIZE 255 +#define SEGMENT_TO_MCB(seg) ((PDOS_MCB)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0))) +#define SEGMENT_TO_PSP(seg) ((PDOS_PSP)((ULONG_PTR)BaseAddress + TO_LINEAR((seg), 0))) +#define UMB_START_SEGMENT 0xC000 +#define UMB_END_SEGMENT 0xDFFF +#define DOS_ALLOC_HIGH 0x40 +#define DOS_ALLOC_HIGH_LOW 0x80 + +enum DOS_ALLOC_STRATEGY +{ + DOS_ALLOC_FIRST_FIT, + DOS_ALLOC_BEST_FIT, + DOS_ALLOC_LAST_FIT +}; + +#pragma pack(push, 1) + +typedef struct _DOS_MCB +{ + CHAR BlockType; + WORD OwnerPsp; + WORD Size; + BYTE Unused[3]; + CHAR Name[8]; +} DOS_MCB, *PDOS_MCB; + +typedef struct _DOS_FCB +{ + BYTE DriveNumber; + CHAR FileName[8]; + CHAR FileExt[3]; + WORD BlockNumber; + WORD RecordSize; + DWORD FileSize; + WORD LastWriteDate; + WORD LastWriteTime; + BYTE Reserved[8]; + BYTE BlockRecord; + BYTE RecordNumber[3]; +} DOS_FCB, *PDOS_FCB; + +typedef struct _DOS_PSP +{ + BYTE Exit[2]; + WORD LastParagraph; + BYTE Reserved0[6]; + DWORD TerminateAddress; + DWORD BreakAddress; + DWORD CriticalAddress; + WORD ParentPsp; + BYTE HandleTable[20]; + WORD EnvBlock; + DWORD LastStack; + WORD HandleTableSize; + DWORD HandleTablePtr; + DWORD PreviousPsp; + DWORD Reserved1; + WORD DosVersion; + BYTE Reserved2[14]; + BYTE FarCall[3]; + BYTE Reserved3[9]; + DOS_FCB Fcb; + BYTE CommandLineSize; + CHAR CommandLine[127]; +} DOS_PSP, *PDOS_PSP; + +typedef struct _DOS_INPUT_BUFFER +{ + BYTE MaxLength, Length; + CHAR Buffer[ANYSIZE_ARRAY]; +} DOS_INPUT_BUFFER, *PDOS_INPUT_BUFFER; + +typedef struct _DOS_DRIVER_HEADER +{ + DWORD NextDriver; + WORD Attributes; + WORD StrategyEntry; + WORD InterruptEntry; + CHAR DeviceName[8]; +} DOS_DRIVER_HEADER, *PDOS_DRIVER_HEADER; + +#pragma pack(pop) + +/* FUNCTIONS ******************************************************************/ + +WORD DosAllocateMemory(WORD Size, WORD *MaxAvailable); +BOOLEAN DosResizeMemory(WORD BlockData, WORD NewSize, WORD *MaxAvailable); +BOOLEAN DosFreeMemory(WORD BlockData); +WORD DosCreateFile(LPWORD Handle, LPCSTR FilePath, WORD Attributes); +WORD DosOpenFile(LPWORD Handle, LPCSTR FilePath, BYTE AccessMode); +WORD DosReadFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesRead); +WORD DosWriteFile(WORD FileHandle, LPVOID Buffer, WORD Count, LPWORD BytesWritten); +WORD DosSeekFile(WORD FileHandle, LONG Offset, BYTE Origin, LPDWORD NewOffset); +BOOLEAN DosDuplicateHandle(WORD OldHandle, WORD NewHandle); +BOOLEAN DosCloseHandle(WORD DosHandle); +VOID DosInitializePsp(WORD PspSegment, LPCSTR CommandLine, WORD ProgramSize, WORD Environment); +BOOLEAN DosCreateProcess(LPCSTR CommandLine, WORD EnvBlock); +VOID DosTerminateProcess(WORD Psp, BYTE ReturnCode); +CHAR DosReadCharacter(VOID); +VOID DosPrintCharacter(CHAR Character); +BOOLEAN DosHandleIoctl(BYTE ControlCode, WORD FileHandle); +VOID DosInt20h(LPWORD Stack); +VOID DosInt21h(LPWORD Stack); +VOID DosBreakInterrupt(LPWORD Stack); +BOOLEAN DosInitialize(VOID); + +#endif + +/* EOF */ + Index: subsystems/ntvdm/dos.h =================================================================== --- subsystems/ntvdm/dos.h (révision 59666) +++ subsystems/ntvdm/dos.h (copie de travail) Modification de propriétés sur subsystems/ntvdm/dos.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: subsystems/ntvdm/emulator.c =================================================================== --- subsystems/ntvdm/emulator.c (révision 0) +++ subsystems/ntvdm/emulator.c (copie de travail) @@ -0,0 +1,561 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: emulator.c + * PURPOSE: Minimal x86 machine emulator for the VDM + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "emulator.h" +#include "bios.h" +#include "dos.h" +#include "vga.h" +#include "pic.h" +#include "ps2.h" +#include "timer.h" + +/* PRIVATE VARIABLES **********************************************************/ + +#ifndef NEW_EMULATOR +softx86_ctx EmulatorContext; +softx87_ctx FpuEmulatorContext; +#else +EMULATOR_CONTEXT EmulatorContext; +#endif + +static BOOLEAN A20Line = FALSE; + +/* PRIVATE FUNCTIONS **********************************************************/ + +#ifndef NEW_EMULATOR + +static VOID EmulatorReadMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size) +{ + /* If the A20 line is disabled, mask bit 20 */ + if (!A20Line) Address &= ~(1 << 20); + + /* Make sure the requested address is valid */ + if ((Address + Size) >= MAX_ADDRESS) return; + + /* Read the data from the virtual address space and store it in the buffer */ + RtlCopyMemory(Buffer, (LPVOID)((ULONG_PTR)BaseAddress + Address), Size); + + /* Check if we modified the console video memory */ + if (((Address + Size) >= VgaGetVideoBaseAddress()) + && (Address < VgaGetVideoLimitAddress())) + { + DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress()); + LPBYTE VgaBuffer = &Buffer[VgaAddress - Address]; + + /* Read from the VGA memory */ + VgaReadMemory(VgaAddress, VgaBuffer, Size); + } +} + +static VOID EmulatorWriteMemory(PVOID Context, UINT Address, LPBYTE Buffer, INT Size) +{ + /* If the A20 line is disabled, mask bit 20 */ + if (!A20Line) Address &= ~(1 << 20); + + /* Make sure the requested address is valid */ + if ((Address + Size) >= MAX_ADDRESS) return; + + /* Make sure we don't write to the ROM area */ + if ((Address + Size) >= ROM_AREA_START && (Address < ROM_AREA_END)) return; + + /* Read the data from the buffer and store it in the virtual address space */ + RtlCopyMemory((LPVOID)((ULONG_PTR)BaseAddress + Address), Buffer, Size); + + /* Check if we modified the console video memory */ + if (((Address + Size) >= VgaGetVideoBaseAddress()) + && (Address < VgaGetVideoLimitAddress())) + { + DWORD VgaAddress = max(Address, VgaGetVideoBaseAddress()); + LPBYTE VgaBuffer = &Buffer[VgaAddress - Address]; + + /* Write to the VGA memory */ + VgaWriteMemory(VgaAddress, VgaBuffer, Size); + } +} + +static VOID EmulatorReadIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size) +{ + switch (Address) + { + case PIC_MASTER_CMD: + case PIC_SLAVE_CMD: + { + *Buffer = PicReadCommand(Address); + break; + } + + case PIC_MASTER_DATA: + case PIC_SLAVE_DATA: + { + *Buffer = PicReadData(Address); + break; + } + + case PIT_DATA_PORT(0): + case PIT_DATA_PORT(1): + case PIT_DATA_PORT(2): + { + *Buffer = PitReadData(Address - PIT_DATA_PORT(0)); + break; + } + + case PS2_CONTROL_PORT: + { + *Buffer = KeyboardReadStatus(); + break; + } + + case PS2_DATA_PORT: + { + *Buffer = KeyboardReadData(); + break; + } + + case VGA_AC_WRITE: + case VGA_AC_READ: + case VGA_SEQ_INDEX: + case VGA_SEQ_DATA: + case VGA_DAC_READ_INDEX: + case VGA_DAC_WRITE_INDEX: + case VGA_DAC_DATA: + case VGA_MISC_READ: + case VGA_MISC_WRITE: + case VGA_CRTC_INDEX: + case VGA_CRTC_DATA: + case VGA_GC_INDEX: + case VGA_GC_DATA: + case VGA_STAT_MONO: + case VGA_STAT_COLOR: + { + *Buffer = VgaReadPort(Address); + break; + } + + default: + { + DPRINT1("Read from unknown port: 0x%X\n", Address); + } + } +} + +static VOID EmulatorWriteIo(PVOID Context, UINT Address, LPBYTE Buffer, INT Size) +{ + BYTE Byte = *Buffer; + + switch (Address) + { + case PIT_COMMAND_PORT: + { + PitWriteCommand(Byte); + break; + } + + case PIT_DATA_PORT(0): + case PIT_DATA_PORT(1): + case PIT_DATA_PORT(2): + { + PitWriteData(Address - PIT_DATA_PORT(0), Byte); + break; + } + + case PIC_MASTER_CMD: + case PIC_SLAVE_CMD: + { + PicWriteCommand(Address, Byte); + break; + } + + case PIC_MASTER_DATA: + case PIC_SLAVE_DATA: + { + PicWriteData(Address, Byte); + break; + } + + case PS2_CONTROL_PORT: + { + KeyboardWriteCommand(Byte); + break; + } + + case PS2_DATA_PORT: + { + KeyboardWriteData(Byte); + break; + } + + case VGA_AC_WRITE: + case VGA_AC_READ: + case VGA_SEQ_INDEX: + case VGA_SEQ_DATA: + case VGA_DAC_READ_INDEX: + case VGA_DAC_WRITE_INDEX: + case VGA_DAC_DATA: + case VGA_MISC_READ: + case VGA_MISC_WRITE: + case VGA_CRTC_INDEX: + case VGA_CRTC_DATA: + case VGA_GC_INDEX: + case VGA_GC_DATA: + case VGA_STAT_MONO: + case VGA_STAT_COLOR: + { + VgaWritePort(Address, Byte); + break; + } + + default: + { + DPRINT1("Write to unknown port: 0x%X\n", Address); + } + } +} + +static VOID EmulatorBop(WORD Code) +{ + WORD StackSegment, StackPointer, CodeSegment, InstructionPointer; + BYTE IntNum; + LPWORD Stack; + + /* Get the SS:SP */ +#ifndef NEW_EMULATOR + StackSegment = EmulatorContext.state->segment_reg[SX86_SREG_SS].val; + StackPointer = EmulatorContext.state->general_reg[SX86_REG_SP].val; +#else + StackSegment = EmulatorContext.Registers[EMULATOR_REG_SS].LowWord; + StackPointer = EmulatorContext.Registers[EMULATOR_REG_SP].LowWord; +#endif + + /* Get the stack */ + Stack = (LPWORD)((ULONG_PTR)BaseAddress + TO_LINEAR(StackSegment, StackPointer)); + + if (Code == EMULATOR_INT_BOP) + { + /* Get the interrupt number */ + IntNum = LOBYTE(Stack[STACK_INT_NUM]); + + /* Get the CS:IP */ + InstructionPointer = Stack[STACK_IP]; + CodeSegment = Stack[STACK_CS]; + + /* Check if this was an exception */ + if (IntNum < 8) + { + /* Display a message to the user */ + DisplayMessage(L"Exception: %s occured at %04X:%04X", + ExceptionName[IntNum], + CodeSegment, + InstructionPointer); + + /* Stop the VDM */ + VdmRunning = FALSE; + return; + } + + /* Check if this was an PIC IRQ */ + if (IntNum >= BIOS_PIC_MASTER_INT && IntNum < BIOS_PIC_MASTER_INT + 8) + { + /* It was an IRQ from the master PIC */ + BiosHandleIrq(IntNum - BIOS_PIC_MASTER_INT, Stack); + return; + } + else if (IntNum >= BIOS_PIC_SLAVE_INT && IntNum < BIOS_PIC_SLAVE_INT + 8) + { + /* It was an IRQ from the slave PIC */ + BiosHandleIrq(IntNum - BIOS_PIC_SLAVE_INT + 8, Stack); + return; + } + + switch (IntNum) + { + case BIOS_VIDEO_INTERRUPT: + { + /* This is the video BIOS interrupt, call the BIOS */ + BiosVideoService(Stack); + break; + } + case BIOS_EQUIPMENT_INTERRUPT: + { + /* This is the BIOS "get equipment" command, call the BIOS */ + BiosEquipmentService(Stack); + break; + } + case BIOS_KBD_INTERRUPT: + { + /* This is the keyboard BIOS interrupt, call the BIOS */ + BiosKeyboardService(Stack); + break; + } + case BIOS_TIME_INTERRUPT: + { + /* This is the time BIOS interrupt, call the BIOS */ + BiosTimeService(Stack); + break; + } + case BIOS_SYS_TIMER_INTERRUPT: + { + /* BIOS timer update */ + BiosSystemTimerInterrupt(Stack); + break; + } + case 0x20: + { + DosInt20h(Stack); + break; + } + case 0x21: + { + DosInt21h(Stack); + break; + } + case 0x23: + { + DosBreakInterrupt(Stack); + break; + } + default: + { + DPRINT1("Unhandled interrupt: 0x%02X\n", IntNum); + break; + } + } + } +} + +static VOID EmulatorSoftwareInt(PVOID Context, BYTE Number) +{ + /* Do nothing */ +} + +static VOID EmulatorHardwareInt(PVOID Context, BYTE Number) +{ + /* Do nothing */ +} + +static VOID EmulatorHardwareIntAck(PVOID Context, BYTE Number) +{ + /* Do nothing */ +} + +#endif + +/* PUBLIC FUNCTIONS ***********************************************************/ + +BOOLEAN EmulatorInitialize() +{ + /* Allocate memory for the 16-bit address space */ + BaseAddress = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, MAX_ADDRESS); + if (BaseAddress == NULL) return FALSE; + +#ifndef NEW_EMULATOR + /* Initialize the softx86 CPU emulator */ + if (!softx86_init(&EmulatorContext, SX86_CPULEVEL_80286)) + { + HeapFree(GetProcessHeap(), 0, BaseAddress); + return FALSE; + } + + /* Initialize the softx87 FPU emulator*/ + if(!softx87_init(&FpuEmulatorContext, SX87_FPULEVEL_8087)) + { + softx86_free(&EmulatorContext); + HeapFree(GetProcessHeap(), 0, BaseAddress); + return FALSE; + } + + /* Set memory read/write callbacks */ + EmulatorContext.callbacks->on_read_memory = EmulatorReadMemory; + EmulatorContext.callbacks->on_write_memory = EmulatorWriteMemory; + + /* Set MMIO read/write callbacks */ + EmulatorContext.callbacks->on_read_io = EmulatorReadIo; + EmulatorContext.callbacks->on_write_io = EmulatorWriteIo; + + /* Set interrupt callbacks */ + EmulatorContext.callbacks->on_sw_int = EmulatorSoftwareInt; + EmulatorContext.callbacks->on_hw_int = EmulatorHardwareInt; + EmulatorContext.callbacks->on_hw_int_ack = EmulatorHardwareIntAck; + + /* Connect the emulated FPU to the emulated CPU */ + softx87_connect_to_CPU(&EmulatorContext, &FpuEmulatorContext); +#else + // TODO: NOT IMPLEMENTED +#endif + + /* Enable interrupts */ + EmulatorSetFlag(EMULATOR_FLAG_IF); + + return TRUE; +} + +VOID EmulatorSetStack(WORD Segment, WORD Offset) +{ +#ifndef NEW_EMULATOR + /* Call the softx86 API */ + softx86_set_stack_ptr(&EmulatorContext, Segment, Offset); +#else + // TODO: NOT IMPLEMENTED +#endif +} + +VOID EmulatorExecute(WORD Segment, WORD Offset) +{ +#ifndef NEW_EMULATOR + /* Call the softx86 API */ + softx86_set_instruction_ptr(&EmulatorContext, Segment, Offset); +#else + // TODO: NOT IMPLEMENTED +#endif +} + +VOID EmulatorInterrupt(BYTE Number) +{ + LPDWORD IntVecTable = (LPDWORD)((ULONG_PTR)BaseAddress); + UINT Segment, Offset; + + /* Get the segment and offset */ + Segment = HIWORD(IntVecTable[Number]); + Offset = LOWORD(IntVecTable[Number]); + +#ifndef NEW_EMULATOR + /* Call the softx86 API */ + softx86_make_simple_interrupt_call(&EmulatorContext, &Segment, &Offset); +#else + UNREFERENCED_PARAMETER(Segment); + UNREFERENCED_PARAMETER(Offset); + // TODO: NOT IMPLEMENTED +#endif +} + +VOID EmulatorExternalInterrupt(BYTE Number) +{ +#ifndef NEW_EMULATOR + /* Call the softx86 API */ + softx86_ext_hw_signal(&EmulatorContext, Number); +#endif +} + +ULONG EmulatorGetRegister(ULONG Register) +{ +#ifndef NEW_EMULATOR + if (Register < EMULATOR_REG_ES) + { + return EmulatorContext.state->general_reg[Register].val; + } + else + { + return EmulatorContext.state->segment_reg[Register - EMULATOR_REG_ES].val; + } +#else + return EmulatorContext.Registers[Register].Long; +#endif +} + +VOID EmulatorSetRegister(ULONG Register, ULONG Value) +{ +#ifndef NEW_EMULATOR + if (Register < EMULATOR_REG_CS) + { + EmulatorContext.state->general_reg[Register].val = Value; + } + else + { + EmulatorContext.state->segment_reg[Register - EMULATOR_REG_ES].val = (WORD)Value; + } +#else + // TODO: NOT IMPLEMENTED +#endif +} + +BOOLEAN EmulatorGetFlag(ULONG Flag) +{ +#ifndef NEW_EMULATOR + return (EmulatorContext.state->reg_flags.val & Flag) ? TRUE : FALSE; +#else + return (EmulatorContext.Flags.Long & Flag) ? TRUE : FALSE; +#endif +} + +VOID EmulatorSetFlag(ULONG Flag) +{ +#ifndef NEW_EMULATOR + EmulatorContext.state->reg_flags.val |= Flag; +#else + EmulatorContext.Flags.Long |= Flag; +#endif +} + +VOID EmulatorClearFlag(ULONG Flag) +{ +#ifndef NEW_EMULATOR + EmulatorContext.state->reg_flags.val &= ~Flag; +#else + EmulatorContext.Flags.Long &= ~Flag; +#endif +} + +VOID EmulatorStep(VOID) +{ + LPWORD Instruction; + +#ifndef NEW_EMULATOR + /* Print the current position - useful for debugging */ + DPRINT("Executing at CS:IP = %04X:%04X\n", + EmulatorGetRegister(EMULATOR_REG_CS), + EmulatorContext.state->reg_ip); + + Instruction = (LPWORD)((ULONG_PTR)BaseAddress + + TO_LINEAR(EmulatorGetRegister(EMULATOR_REG_CS), + EmulatorContext.state->reg_ip)); + + /* Check for the BIOS operation (BOP) sequence */ + if (Instruction[0] == EMULATOR_BOP) + { + /* Skip the opcodes */ + EmulatorContext.state->reg_ip += 4; + + // HACK: Refresh the display because the called function may wait. + VgaRefreshDisplay(); + + /* Call the BOP handler */ + EmulatorBop(Instruction[1]); + } + + /* Call the softx86 API */ + if (!softx86_step(&EmulatorContext)) + { + /* Invalid opcode */ + EmulatorInterrupt(EMULATOR_EXCEPTION_INVALID_OPCODE); + } +#else + // TODO: NOT IMPLEMENTED +#endif +} + +VOID EmulatorCleanup(VOID) +{ +#ifndef NEW_EMULATOR + /* Free the softx86 CPU and FPU emulator */ + softx87_free(&FpuEmulatorContext); + softx86_free(&EmulatorContext); +#endif + + /* Free the memory allocated for the 16-bit address space */ + if (BaseAddress != NULL) HeapFree(GetProcessHeap(), 0, BaseAddress); +} + +VOID EmulatorSetA20(BOOLEAN Enabled) +{ + A20Line = Enabled; +} + +/* EOF */ Index: subsystems/ntvdm/emulator.c =================================================================== --- subsystems/ntvdm/emulator.c (révision 59666) +++ subsystems/ntvdm/emulator.c (copie de travail) Modification de propriétés sur subsystems/ntvdm/emulator.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: subsystems/ntvdm/emulator.h =================================================================== --- subsystems/ntvdm/emulator.h (révision 0) +++ subsystems/ntvdm/emulator.h (copie de travail) @@ -0,0 +1,190 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: emulator.h + * PURPOSE: Minimal x86 machine emulator for the VDM (header file) + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _EMULATOR_H_ +#define _EMULATOR_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +#ifndef NEW_EMULATOR +#include +#include +#endif + +/* DEFINES ********************************************************************/ + +/* FLAGS */ +#define EMULATOR_FLAG_CF (1 << 0) +#define EMULATOR_FLAG_PF (1 << 2) +#define EMULATOR_FLAG_AF (1 << 4) +#define EMULATOR_FLAG_ZF (1 << 6) +#define EMULATOR_FLAG_SF (1 << 7) +#define EMULATOR_FLAG_TF (1 << 8) +#define EMULATOR_FLAG_IF (1 << 9) +#define EMULATOR_FLAG_DF (1 << 10) +#define EMULATOR_FLAG_OF (1 << 11) +#define EMULATOR_FLAG_NT (1 << 14) +#define EMULATOR_FLAG_RF (1 << 16) +#define EMULATOR_FLAG_VM (1 << 17) +#define EMULATOR_FLAG_AC (1 << 18) +#define EMULATOR_FLAG_VIF (1 << 19) +#define EMULATOR_FLAG_VIP (1 << 20) +#define EMULATOR_FLAG_ID (1 << 21) + +/* CR0 */ +#define EMULATOR_CR0_PE (1 << 0) +#define EMULATOR_CR0_MP (1 << 1) +#define EMULATOR_CR0_EM (1 << 2) +#define EMULATOR_CR0_TS (1 << 3) +#define EMULATOR_CR0_ET (1 << 4) +#define EMULATOR_CR0_NE (1 << 5) +#define EMULATOR_CR0_WP (1 << 16) +#define EMULATOR_CR0_AM (1 << 18) +#define EMULATOR_CR0_NW (1 << 29) +#define EMULATOR_CR0_CD (1 << 30) +#define EMULATOR_CR0_PG (1 << 31) + +/* GDT Access byte */ +#define GDT_SEG_ACCESSED (1 << 0) +#define GDT_DATA_WRITEABLE (1 << 1) +#define GDT_CODE_READABLE (1 << 1) +#define GDT_CONFORMING (1 << 2) +#define GDT_DIRECTION (1 << 2) +#define GDT_CODE_SEGMENT (1 << 3) +#define GDT_PRESENT (1 << 7) + +/* GDT flags */ +#define GDT_32BIT_SEGMENT (1 << 2) +#define GDT_PAGE_GRANULARITY (1 << 3) + +/* Common definitions */ +#define EMULATOR_NUM_GENERAL_REGS 8 +#define EMULATOR_NUM_SEGMENT_REGS 6 +#define EMULATOR_NUM_CONTROL_REGS 8 +#define EMULATOR_NUM_DEBUG_REGS 8 +#define MAX_GDT_ENTRIES 8192 +#define EMULATOR_BOP 0xC4C4 +#define EMULATOR_INT_BOP 0xBEEF +#define STACK_INT_NUM 0 +#define STACK_IP 1 +#define STACK_CS 2 +#define STACK_FLAGS 3 + +enum +{ + EMULATOR_EXCEPTION_DIVISION_BY_ZERO, + EMULATOR_EXCEPTION_DEBUG, + EMULATOR_EXCEPTION_NMI, + EMULATOR_EXCEPTION_BREAKPOINT, + EMULATOR_EXCEPTION_OVERFLOW, + EMULATOR_EXCEPTION_BOUND, + EMULATOR_EXCEPTION_INVALID_OPCODE, + EMULATOR_EXCEPTION_NO_FPU, + EMULATOR_EXCEPTION_DOUBLE_FAULT, + EMULATOR_EXCEPTION_FPU_SEGMENT, + EMULATOR_EXCEPTION_INVALID_TSS, + EMULATOR_EXCEPTION_NO_SEGMENT, + EMULATOR_EXCEPTION_STACK_SEGMENT, + EMULATOR_EXCEPTION_GPF, + EMULATOR_EXCEPTION_PAGE_FAULT +}; + +enum +{ + EMULATOR_REG_AX, + EMULATOR_REG_CX, + EMULATOR_REG_DX, + EMULATOR_REG_BX, + EMULATOR_REG_SP, + EMULATOR_REG_BP, + EMULATOR_REG_SI, + EMULATOR_REG_DI, + EMULATOR_REG_ES, + EMULATOR_REG_CS, + EMULATOR_REG_SS, + EMULATOR_REG_DS, + EMULATOR_REG_FS, + EMULATOR_REG_GS +}; + +typedef union +{ + struct + { + BYTE LowByte; + BYTE HighByte; + }; + WORD LowWord; + DWORD Long; +} EMULATOR_REGISTER, *PEMULATOR_REGISTER; + +typedef struct +{ + ULONG Limit : 16; + ULONG Base : 24; + ULONG AccessByte : 8; + ULONG LimitHigh : 4; + ULONG Flags : 4; + ULONG BaseHigh : 8; +} EMULATOR_GDT_ENTRY; + +typedef struct +{ + ULONG Offset : 16; + ULONG Selector : 16; + ULONG Zero : 8; + ULONG TypeAndAttributes : 8; + ULONG OffsetHigh : 16; +} EMULATOR_IDT_ENTRY; + +typedef struct +{ + WORD Size; + DWORD Address; +} EMULATOR_TABLE_REGISTER; + +typedef struct +{ + EMULATOR_REGISTER Registers[EMULATOR_NUM_GENERAL_REGS + + EMULATOR_NUM_SEGMENT_REGS]; + EMULATOR_REGISTER Flags; + EMULATOR_REGISTER InstructionPointer; + EMULATOR_REGISTER ControlRegisters[EMULATOR_NUM_CONTROL_REGS]; + EMULATOR_REGISTER DebugRegisters[EMULATOR_NUM_DEBUG_REGS]; + ULONGLONG TimeStampCounter; + BOOLEAN OperandSizeOverload; + BOOLEAN AddressSizeOverload; + EMULATOR_TABLE_REGISTER Gdtr, Idtr; + EMULATOR_GDT_ENTRY CachedDescriptors[EMULATOR_NUM_SEGMENT_REGS]; + UINT ExceptionCount; +} EMULATOR_CONTEXT, *PEMULATOR_CONTEXT; + +typedef VOID (*EMULATOR_OPCODE_HANDLER)(PEMULATOR_CONTEXT Context, BYTE Opcode); + +/* FUNCTIONS ******************************************************************/ + +BOOLEAN EmulatorInitialize(); +VOID EmulatorSetStack(WORD Segment, WORD Offset); +VOID EmulatorExecute(WORD Segment, WORD Offset); +VOID EmulatorInterrupt(BYTE Number); +VOID EmulatorExternalInterrupt(BYTE Number); +ULONG EmulatorGetRegister(ULONG Register); +VOID EmulatorSetRegister(ULONG Register, ULONG Value); +BOOLEAN EmulatorGetFlag(ULONG Flag); +VOID EmulatorSetFlag(ULONG Flag); +VOID EmulatorClearFlag(ULONG Flag); +VOID EmulatorStep(); +VOID EmulatorCleanup(); +VOID EmulatorSetA20(BOOLEAN Enabled); + +#endif + +/* EOF */ + Index: subsystems/ntvdm/emulator.h =================================================================== --- subsystems/ntvdm/emulator.h (révision 59666) +++ subsystems/ntvdm/emulator.h (copie de travail) Modification de propriétés sur subsystems/ntvdm/emulator.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: subsystems/ntvdm/lang/bg-BG.rc =================================================================== --- subsystems/ntvdm/lang/bg-BG.rc (révision 59666) +++ subsystems/ntvdm/lang/bg-BG.rc (copie de travail) @@ -1,12 +0,0 @@ -/* - * Moved all hardcoded strings to En.rc. - * By Magnus Olsen 2005 - */ - -LANGUAGE LANG_BULGARIAN, SUBLANG_DEFAULT -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "Ïîääðúæêà íà ÐåàêòÎÑ çà ïðèâèäíà ÄÎÑ ìàøèíà.\n" -STRING_PromptMsg, "Íàïèøåòå r çà ïóñêàíå, s çà ñïèðàíå èëè q çà èçõîä." -END Index: subsystems/ntvdm/lang/cs-CZ.rc =================================================================== --- subsystems/ntvdm/lang/cs-CZ.rc (révision 59666) +++ subsystems/ntvdm/lang/cs-CZ.rc (copie de travail) @@ -1,12 +0,0 @@ -/* FILE: subsystems/ntvdm/lang/cs-CZ.rc - * TRANSLATOR: Radek Liska aka Black_Fox (radekliska at gmail dot com) - * UPDATED: 2008-06-24 - */ - -LANGUAGE LANG_CZECH, SUBLANG_DEFAULT -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "ReactOS podpora virtuálního DOS stroje.\n" -STRING_PromptMsg, "Napište r pro spuštìní, s pro vypnutí nebo q pro ukonèení." -END Index: subsystems/ntvdm/lang/de-DE.rc =================================================================== --- subsystems/ntvdm/lang/de-DE.rc (révision 59666) +++ subsystems/ntvdm/lang/de-DE.rc (copie de travail) @@ -1,13 +0,0 @@ -/* - * Translate into German. - * By Rouven Wessling 2005 pentiumforever@gmail.com - * 2008 dark_shadow@gmx.at - */ - -LANGUAGE LANG_GERMAN, SUBLANG_NEUTRAL -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "ReactOS virtuelle DOS-Unterstützung.\n" -STRING_PromptMsg, "Drücken Sie r zum Starten, s zum Herunterfahren oder q zum Beenden." -END Index: subsystems/ntvdm/lang/en-US.rc =================================================================== --- subsystems/ntvdm/lang/en-US.rc (révision 59666) +++ subsystems/ntvdm/lang/en-US.rc (copie de travail) @@ -1,12 +0,0 @@ -/* - * Moved all hardcoded strings to En.rc. - * By Magnus Olsen 2005 - */ - -LANGUAGE LANG_ENGLISH, SUBLANG_ENGLISH_US -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "ReactOS Virtual DOS Machine support.\n" -STRING_PromptMsg, "Type r to run, s to shutdown or q to quit now." -END Index: subsystems/ntvdm/lang/es-ES.rc =================================================================== --- subsystems/ntvdm/lang/es-ES.rc (révision 59666) +++ subsystems/ntvdm/lang/es-ES.rc (copie de travail) @@ -1,12 +0,0 @@ -/* - * Spanish Resource File - * Reactos(c)2006 Samuel Serapion - */ - -LANGUAGE LANG_SPANISH, SUBLANG_NEUTRAL -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "Maquina virtual de DOS en ReactOS.\n" -STRING_PromptMsg, "Escriba r para correr, s para desactivar or q para salir ahora." -END Index: subsystems/ntvdm/lang/fr-FR.rc =================================================================== --- subsystems/ntvdm/lang/fr-FR.rc (révision 59666) +++ subsystems/ntvdm/lang/fr-FR.rc (copie de travail) @@ -1,12 +0,0 @@ -/* - * Moved all hardcoded strings to En.rc. - * By Magnus Olsen 2005 - */ - -LANGUAGE LANG_FRENCH, SUBLANG_NEUTRAL -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "Aide de la Machine DOS Virtuel de ReactOS.\n" -STRING_PromptMsg, "Taper r pour démarrer, s pour éteindre ou q pour quitter maintenant." -END Index: subsystems/ntvdm/lang/hu-HU.rc =================================================================== --- subsystems/ntvdm/lang/hu-HU.rc (révision 59666) +++ subsystems/ntvdm/lang/hu-HU.rc (copie de travail) @@ -1,14 +0,0 @@ -/* - * Hungarian resource file for ntvdm - * Moved all hardcoded strings to En.rc. - * By Magnus Olsen 2005 - * Translation by Robert Horvath 2005 - talley at cubeclub.hu - */ - -LANGUAGE LANG_HUNGARIAN, SUBLANG_DEFAULT -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "ReactOS Virtuális DOS Gép támogatás.\n" -STRING_PromptMsg, "Futtatáshoz nyomd meg a r, leállításhoz a s vagy kilépéshez a q gombot." -END Index: subsystems/ntvdm/lang/id-ID.rc =================================================================== --- subsystems/ntvdm/lang/id-ID.rc (révision 59666) +++ subsystems/ntvdm/lang/id-ID.rc (copie de travail) @@ -1,8 +0,0 @@ - -LANGUAGE LANG_INDONESIAN, SUBLANG_DEFAULT -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "Dukungan ReactOS Virtual DOS Machine.\n" -STRING_PromptMsg, "Ketik r untuk menjalankan, s untuk mematikan atau q untuk keluar sekarang." -END Index: subsystems/ntvdm/lang/it-IT.rc =================================================================== --- subsystems/ntvdm/lang/it-IT.rc (révision 59666) +++ subsystems/ntvdm/lang/it-IT.rc (copie de travail) @@ -1,16 +0,0 @@ -/* -* PROJECT: ReactOS Virtual DOS Machine -* LICENSE: GPL - See COPYING in the top level directory -* FILE: subsystems/ntvdm/it-IT.rc -* PURPOSE: Italian Translation of subsystems/ntvdm/en-US.rc -* PROGRAMMERS: Copyright (C) 2005 Magnus Olsen -* Copyright (C) 2007 Daniele Forsi (dforsi at gmail.com) Italian Translation -*/ - -LANGUAGE LANG_ITALIAN, SUBLANG_NEUTRAL -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "Supporto di ReactOS per la macchina virtuale DOS.\n" -STRING_PromptMsg, "Digitare r per avviare, s per arrestare o q per abbandonare ora." -END Index: subsystems/ntvdm/lang/ja-JP.rc =================================================================== --- subsystems/ntvdm/lang/ja-JP.rc (révision 59666) +++ subsystems/ntvdm/lang/ja-JP.rc (copie de travail) @@ -1,12 +0,0 @@ -/* - * Moved all hardcoded strings to En.rc. - * By Magnus Olsen 2005 - */ - -LANGUAGE LANG_JAPANESE, SUBLANG_DEFAULT -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "ReactOS Virtual DOS Machine support.\n" -STRING_PromptMsg, "‹N“®‚·‚é‚É‚Í r ‚ðAƒVƒƒƒbƒgƒ_ƒEƒ“‚·‚é‚É‚Í s ‚ðA¡‚·‚®I—¹‚³‚¹‚é‚É‚Í q ‚ð“ü—Í‚µ‚Ä‚­‚¾‚³‚¢B" -END Index: subsystems/ntvdm/lang/no-NO.rc =================================================================== --- subsystems/ntvdm/lang/no-NO.rc (révision 59666) +++ subsystems/ntvdm/lang/no-NO.rc (copie de travail) @@ -1,12 +0,0 @@ -/* - * Moved all hardcoded strings to En.rc. - * By Magnus Olsen 2005 - */ - -LANGUAGE LANG_NORWEGIAN, SUBLANG_NEUTRAL -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "ReactOS Vituell DOS Maskin støtte.\n" -STRING_PromptMsg, "Skriv r for å kjøre, s å avslutte eller q for å slutte nå." -END Index: subsystems/ntvdm/lang/pl-PL.rc =================================================================== --- subsystems/ntvdm/lang/pl-PL.rc (révision 59666) +++ subsystems/ntvdm/lang/pl-PL.rc (copie de travail) @@ -1,14 +0,0 @@ -/* - * translated by xrogers - * xxrogers@users.sourceforge.net - * https://sourceforge.net/projects/reactospl - * UTF-8 conversion by Caemyr (May, 2011) - */ - -LANGUAGE LANG_POLISH, SUBLANG_DEFAULT -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "Wirtualna maszyna DOS dla ReactOS.\n" -STRING_PromptMsg, "WciÅ›nij r aby uruchomić, s aby wyÅ‚Ä…czyć lub q, aby zakoÅ„czyć." -END Index: subsystems/ntvdm/lang/pt-BR.rc =================================================================== --- subsystems/ntvdm/lang/pt-BR.rc (révision 59666) +++ subsystems/ntvdm/lang/pt-BR.rc (copie de travail) @@ -1,12 +0,0 @@ -/* - * Moved all hardcoded strings to En.rc. - * By Magnus Olsen 2005 - */ - -LANGUAGE LANG_PORTUGUESE, SUBLANG_NEUTRAL -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "ReactOS subsistema para suporte DOS de 16 bits.\n" -STRING_PromptMsg, "Digite r para executar, s para desligar ou q para sair." -END Index: subsystems/ntvdm/lang/ro-RO.rc =================================================================== --- subsystems/ntvdm/lang/ro-RO.rc (révision 59666) +++ subsystems/ntvdm/lang/ro-RO.rc (copie de travail) @@ -1,14 +0,0 @@ -/* - * FILE: subsystems/ntvdm/lang/ro-RO.rc - * ReactOS Project (http://www.reactos.org) - * TRANSLATOR: Fulea Ștefan (PM on ReactOS Forum at fulea.stefan) - * CHANGE LOG: 2011-10-16 initial translation - */ - -LANGUAGE LANG_ROMANIAN, SUBLANG_NEUTRAL -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "Asistență pentru maÈ™ina virtuală DOS.\n" -STRING_PromptMsg, "TastaÈ›i r pentru a executa, s pentru a închide sau q pentru a ieÈ™i imediat." -END Index: subsystems/ntvdm/lang/ru-RU.rc =================================================================== --- subsystems/ntvdm/lang/ru-RU.rc (révision 59666) +++ subsystems/ntvdm/lang/ru-RU.rc (copie de travail) @@ -1,12 +0,0 @@ -/* - * Moved all hardcoded strings to En.rc. - * By Magnus Olsen 2005 - */ - -LANGUAGE LANG_RUSSIAN, SUBLANG_DEFAULT -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "Ð’Ð¸Ñ€Ñ‚ÑƒÐ°Ð»ÑŒÐ½Ð°Ñ Ð¼Ð°ÑˆÐ¸Ð½Ð° поддержки DOS Ð´Ð»Ñ ReactOS.\n" -STRING_PromptMsg, "Введите r Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑка, s Ð´Ð»Ñ Ð²Ñ‹ÐºÐ»ÑŽÑ‡ÐµÐ½Ð¸Ñ Ð¸Ð»Ð¸ q выхода." -END Index: subsystems/ntvdm/lang/sk-SK.rc =================================================================== --- subsystems/ntvdm/lang/sk-SK.rc (révision 59666) +++ subsystems/ntvdm/lang/sk-SK.rc (copie de travail) @@ -1,11 +0,0 @@ -/* TRANSLATOR: Mário Kaèmár /Mario Kacmar/ aka Kario (kario@szm.sk) - * DATE OF TR: 12-02-2008 - */ - -LANGUAGE LANG_SLOVAK, SUBLANG_DEFAULT -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "Podpora virtuálneho DOSového stroja v systéme ReactOS.\n" -STRING_PromptMsg, "Napíšte r pre spustenie, s pre vypnutie alebo q pre okamžité skonèenie." -END Index: subsystems/ntvdm/lang/th-TH.rc =================================================================== --- subsystems/ntvdm/lang/th-TH.rc (révision 59666) +++ subsystems/ntvdm/lang/th-TH.rc (copie de travail) @@ -1,8 +0,0 @@ - -LANGUAGE LANG_THAI, SUBLANG_DEFAULT -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "ÃͧÃѺ¡Ò÷ӧҹÃкº´ÍÊàÊÁ×͹¢Í§ ReactOS\n" -STRING_PromptMsg, "Ẻ r à¾×èÍ·Ó§Ò¹, s à¾×èͻԴÃкºËÃ×Í q à¾×èÍÍÍ¡·Ñ¹·Õ" -END Index: subsystems/ntvdm/lang/uk-UA.rc =================================================================== --- subsystems/ntvdm/lang/uk-UA.rc (révision 59666) +++ subsystems/ntvdm/lang/uk-UA.rc (copie de travail) @@ -1,16 +0,0 @@ -/* - * PROJECT: Virtual DOS Machine - * LICENSE: GPL - See COPYING in the top level directory - * FILE: subsystems/ntvdm/Uk.rc - * PURPOSE: Ukraianian Language File for Virtual DOS Machine - * TRANSLATOR: Artem Reznikov - */ - -LANGUAGE LANG_UKRAINIAN, SUBLANG_DEFAULT - -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "Підтримка віртуальної машини DOS у ReactOS.\n" -STRING_PromptMsg, "Введіть r Ð´Ð»Ñ Ð·Ð°Ð¿ÑƒÑку, s Ð´Ð»Ñ Ð·Ð°ÐºÑ€Ð¸Ñ‚Ñ‚Ñ Ð°Ð±Ð¾ q, щоб вийти зараз." -END Index: subsystems/ntvdm/lang/zh-CN.rc =================================================================== --- subsystems/ntvdm/lang/zh-CN.rc (révision 59666) +++ subsystems/ntvdm/lang/zh-CN.rc (copie de travail) @@ -1,8 +0,0 @@ - -LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "ReactOS ÐéÄâ DOS »úÖ§³Ö¡£\n" -STRING_PromptMsg, "ÊäÈë r ÒÔ±ãÔËÐУ¬s ÒÔ±ã¹Ø±Õ»òÕß q ÒÔ±ãÁ¢¼´Í˳ö¡£" -END Index: subsystems/ntvdm/lang/zh-TW.rc =================================================================== --- subsystems/ntvdm/lang/zh-TW.rc (révision 59666) +++ subsystems/ntvdm/lang/zh-TW.rc (copie de travail) @@ -1,8 +0,0 @@ - -LANGUAGE LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL -STRINGTABLE DISCARDABLE -BEGIN - -STRING_WelcomeMsg, "ReactOS µêÀÀ DOS ¾÷¤ä´©¡C\n" -STRING_PromptMsg, "Áä¤J r ¥H«K¹B¦æ¡A s ¥H«KÃö³¬©ÎªÌ q ¥H«K¥ß§Y°h¥X¡C" -END Index: subsystems/ntvdm/ntvdm.c =================================================================== --- subsystems/ntvdm/ntvdm.c (révision 59666) +++ subsystems/ntvdm/ntvdm.c (copie de travail) @@ -1,375 +1,204 @@ /* - * COPYRIGHT: See COPYING in the top level directory - * PROJECT: ReactOS kernel - * FILE: subsys/ntvdm/ntvdm->c + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: ntvdm.c * PURPOSE: Virtual DOS Machine - * PROGRAMMER: Robert Dickenson (robd@mok.lvcm.com) - * UPDATE HISTORY: - * Created 23/10/2002 + * PROGRAMMERS: Aleksandar Andrejevic */ -/* INCLUDES *****************************************************************/ +/* INCLUDES *******************************************************************/ -#include -#define WIN32_NO_STATUS -#include -#include -#include -#include -#include - -#include "resource.h" - #define NDEBUG -#include -/* GLOBALS ******************************************************************/ +#include "ntvdm.h" +#include "emulator.h" +#include "bios.h" +#include "vga.h" +#include "dos.h" +#include "timer.h" +#include "pic.h" +#include "ps2.h" - -/* FUNCTIONS *****************************************************************/ - -void PrintString(char* fmt,...) -{ - char buffer[512]; - va_list ap; - - va_start(ap, fmt); - vsprintf(buffer, fmt, ap); - va_end(ap); - - OutputDebugStringA(buffer); -} - /* -GetVersion -GetVolumeInformationW -GetWindowsDirectoryA -GlobalMemoryStatus -HeapAlloc -HeapCreate -HeapDestroy -HeapFree -HeapReAlloc - -GetNextVDMCommand -ExitVDM -RegisterConsoleVDM -SetVDMCurrentDirectories -VDMConsoleOperation -WriteConsoleInputVDMW - -NtSetLdtEntries -NtTerminateProcess - -NtMapViewOfSection -NtUnmapViewOfSection - -NtVdmControl + * Activate this line if you want to be able to test NTVDM with: + * ntvdm.exe */ -typedef struct tag_VDM_CONFIG { - int dos_options; - int files; - int buffers; - WCHAR** device_list; -//dos=high, umb -//device=%SystemRoot%\system32\himem.sys -//files=40 -} VDM_CONFIG, *PVDM_CONFIG; +// #define TESTING -typedef struct tag_VDM_AUTOEXEC { - WCHAR** load_list; -//lh %SystemRoot%\system32\mscdexnt.exe -//lh %SystemRoot%\system32\redir -//lh %SystemRoot%\system32\dosx -} VDM_AUTOEXEC, *PVDM_AUTOEXEC; +/* PUBLIC VARIABLES ***********************************************************/ -typedef struct tag_VDM_CONTROL_BLOCK { - HANDLE hHeap; - PVOID ImageMem; - VDM_CONFIG vdmConfig; - VDM_AUTOEXEC vdmAutoexec; - PROCESS_INFORMATION ProcessInformation; - CHAR CommandLine[MAX_PATH]; - CHAR CurrentDirectory[MAX_PATH]; - -} VDM_CONTROL_BLOCK, *PVDM_CONTROL_BLOCK; - - -BOOL -StartVDM(PVDM_CONTROL_BLOCK vdm) +BOOLEAN VdmRunning = TRUE; +LPVOID BaseAddress = NULL; +LPCWSTR ExceptionName[] = { - BOOL Result; - STARTUPINFOA StartupInfo; + L"Division By Zero", + L"Debug", + L"Unexpected Error", + L"Breakpoint", + L"Integer Overflow", + L"Bound Range Exceeded", + L"Invalid Opcode", + L"FPU Not Available" +}; - StartupInfo.cb = sizeof(StartupInfo); - StartupInfo.lpReserved = NULL; - StartupInfo.lpDesktop = NULL; - StartupInfo.lpTitle = NULL; - StartupInfo.dwFlags = 0; - StartupInfo.cbReserved2 = 0; - StartupInfo.lpReserved2 = 0; +/* PUBLIC FUNCTIONS ***********************************************************/ - Result = CreateProcessA(vdm->CommandLine, - NULL, - NULL, - NULL, - FALSE, - DETACHED_PROCESS, - NULL, - NULL, - &StartupInfo, - &vdm->ProcessInformation); - if (!Result) { - PrintString("VDM: Failed to execute target process\n"); - return FALSE; - } - WaitForSingleObject(vdm->ProcessInformation.hProcess, INFINITE); - CloseHandle(vdm->ProcessInformation.hProcess); - CloseHandle(vdm->ProcessInformation.hThread); - return TRUE; -} - -BOOL -ShutdownVDM(PVDM_CONTROL_BLOCK vdm) +VOID DisplayMessage(LPCWSTR Format, ...) { - BOOL result = TRUE; + WCHAR Buffer[256]; + va_list Parameters; - return result; + va_start(Parameters, Format); + _vsnwprintf(Buffer, 256, Format, Parameters); + MessageBoxW(NULL, Buffer, L"NTVDM Subsystem", MB_OK); + va_end(Parameters); } -BOOL ReadConfigForVDM(PVDM_CONTROL_BLOCK vdm) +BOOL WINAPI ConsoleCtrlHandler(DWORD ControlType) { - BOOL result = TRUE; - DWORD dwError; - HANDLE hFile; - - hFile = CreateFileW(L"\\system32\\config.nt", - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_ALWAYS /*OPEN_EXISTING*/, - FILE_ATTRIBUTE_NORMAL, - 0); - dwError = GetLastError(); - if (hFile == INVALID_HANDLE_VALUE) { - // error with file path or system problem? - } else { - if (dwError == 0L) { - // we just created a new file, perhaps we should set/write some defaults? + switch (ControlType) + { + case CTRL_C_EVENT: + case CTRL_BREAK_EVENT: + { + /* Perform interrupt 0x23 */ + EmulatorInterrupt(0x23); + break; } - if (dwError == ERROR_ALREADY_EXISTS) { - // read the line entries and cache in some struct... + default: + { + /* Stop the VDM if the user logs out or closes the console */ + VdmRunning = FALSE; } - CloseHandle(hFile); } - - hFile = CreateFileW(L"\\system32\\autoexec.nt", - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_ALWAYS, - FILE_ATTRIBUTE_NORMAL, - 0); - dwError = GetLastError(); - if (hFile == INVALID_HANDLE_VALUE) { - // error with file path or system problem? - } else { - if (dwError == 0L) { - // we just created a new file, perhaps we should set/write some defaults? - } - if (dwError == ERROR_ALREADY_EXISTS) { - // read the line entries and cache in some struct... - } - CloseHandle(hFile); - } - - return result; + return TRUE; } -BOOL -LoadConfigDriversForVDM(PVDM_CONFIG vdmConfig) +INT wmain(INT argc, WCHAR *argv[]) { - BOOL result = TRUE; + INT i; + CHAR CommandLine[128]; + DWORD CurrentTickCount; + DWORD LastTickCount = GetTickCount(); + DWORD Cycles = 0; + DWORD LastCyclePrintout = GetTickCount(); + DWORD LastVerticalRefresh = GetTickCount(); + LARGE_INTEGER Frequency, LastTimerTick, Counter; + LONGLONG TimerTicks; - return result; -} + /* Set the handler routine */ + SetConsoleCtrlHandler(ConsoleCtrlHandler, TRUE); -BOOL -SetConfigOptionsForVDM(PVDM_AUTOEXEC vdmAutoexec) -{ - BOOL result = TRUE; - - return result; -} - -BOOL -CreateVDM(PVDM_CONTROL_BLOCK vdm) -{ -// BOOL result = TRUE; - SYSTEM_INFO inf; - MEMORYSTATUS stat; - - - GlobalMemoryStatus(&stat); - if (stat.dwLength != sizeof(MEMORYSTATUS)) { - printf("WARNING: GlobalMemoryStatus() returned unknown structure version, size %ld, expected %d.\n", stat.dwLength, sizeof(stat)); - } else { - printf("Memory Load: %ld percent in use.\n", stat.dwMemoryLoad); - printf("\t%ld total bytes physical memory.\n", stat.dwTotalPhys); - printf("\t%ld available physical memory.\n", stat.dwAvailPhys); - printf("\t%ld total bytes paging file.\n", stat.dwTotalPageFile); - printf("\t%ld available paging file.\n", stat.dwAvailPageFile); - printf("\t%lx total bytes virtual memory.\n", stat.dwTotalVirtual); - printf("\t%lx available bytes virtual memory.\n", stat.dwAvailVirtual); - -#define OUT_OF_HEADROOM 90 - if (stat.dwMemoryLoad > OUT_OF_HEADROOM) { - DPRINT("VDM: system resources deemed to low to start VDM.\n"); - //SetLastError(); - return FALSE; - } - +#ifndef TESTING + /* The DOS command line must be ASCII */ + WideCharToMultiByte(CP_ACP, 0, GetCommandLine(), -1, CommandLine, 128, NULL, NULL); +#else + if (argc == 2 && argv[1] != NULL) + { + WideCharToMultiByte(CP_ACP, 0, argv[1], -1, CommandLine, 128, NULL, NULL); } + else + { + wprintf(L"\nReactOS Virtual DOS Machine\n\n" + L"Usage: NTVDM \n"); + return 0; + } +#endif - GetSystemInfo(&inf); - vdm->hHeap = HeapCreate(0, inf.dwAllocationGranularity, 0); - if (vdm->hHeap == NULL) { - DPRINT("VDM: failed to create heap.\n"); - return FALSE; + if (!EmulatorInitialize()) + { + wprintf(L"FATAL: Failed to initialize the CPU emulator\n"); + goto Cleanup; } + + /* Initialize the performance counter (needed for hardware timers) */ + if (!QueryPerformanceFrequency(&Frequency)) + { + wprintf(L"FATAL: Performance counter not available\n"); + goto Cleanup; + } -#define DEFAULT_VDM_IMAGE_SIZE 2000000 - vdm->ImageMem = HeapAlloc(vdm->hHeap, 0, DEFAULT_VDM_IMAGE_SIZE); - if (vdm->ImageMem == NULL) { - DPRINT("VDM: failed to allocate image memory from heap %x.\n", vdm->hHeap); - HeapDestroy(vdm->hHeap); - vdm->hHeap = NULL; - return FALSE; + /* Initialize the system BIOS */ + if (!BiosInitialize()) + { + wprintf(L"FATAL: Failed to initialize the VDM BIOS.\n"); + goto Cleanup; } - return TRUE; -} -BOOL -DestroyVDM(PVDM_CONTROL_BLOCK vdm) -{ - BOOL result = TRUE; - - if (vdm->ImageMem != NULL) { - if (HeapFree(vdm->hHeap, 0, vdm->ImageMem) != FALSE) { - DPRINT("VDM: failed to free memory from heap %x.\n", vdm->hHeap); - result = FALSE; - } - vdm->ImageMem = NULL; + /* Initialize the VDM DOS kernel */ + if (!DosInitialize()) + { + wprintf(L"FATAL: Failed to initialize the VDM DOS kernel.\n"); + goto Cleanup; } - if (vdm->hHeap != NULL) { - if (!HeapDestroy(vdm->hHeap)) { - DPRINT("VDM: failed to destroy heap %x.\n", vdm->hHeap); - result = FALSE; - } - vdm->hHeap = NULL; - } - return result; -} -int WINAPI -WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) -{ - VDM_CONTROL_BLOCK VdmCB; - DWORD Result; - ULONG i; - BOOL vdmStarted = FALSE; - - WCHAR WelcomeMsg[RC_STRING_MAX_SIZE]; - WCHAR PromptMsg[RC_STRING_MAX_SIZE]; - CHAR InputBuffer[255]; - - LoadStringW( GetModuleHandle(NULL), STRING_WelcomeMsg, WelcomeMsg,sizeof(WelcomeMsg) / sizeof(WelcomeMsg[0])); - LoadStringW( GetModuleHandle(NULL), STRING_PromptMsg, PromptMsg ,sizeof(PromptMsg) / sizeof(PromptMsg[0])); - - AllocConsole(); - SetConsoleTitleW(L"ntvdm"); - - WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), - WelcomeMsg, lstrlenW(WelcomeMsg), // wcslen(WelcomeMsg), - &Result, NULL); - - if (!CreateVDM(&VdmCB)) { - DPRINT("VDM: failed to create VDM.\n"); - //SetLastError(); - return 2; + /* Start the process from the command line */ + if (!DosCreateProcess(CommandLine, 0)) + { + DisplayMessage(L"Could not start program: %S", CommandLine); + return -1; } + + /* Set the last timer tick to the current time */ + QueryPerformanceCounter(&LastTimerTick); - ReadConfigForVDM(&VdmCB); + /* Main loop */ + while (VdmRunning) + { + /* Get the current number of ticks */ + CurrentTickCount = GetTickCount(); + + /* Get the current performance counter value */ + QueryPerformanceCounter(&Counter); + + /* Get the number of PIT ticks that have passed */ + TimerTicks = ((Counter.QuadPart - LastTimerTick.QuadPart) + * PIT_BASE_FREQUENCY) / Frequency.QuadPart; + + /* Update the PIT */ + for (i = 0; i < TimerTicks; i++) PitDecrementCount(); + LastTimerTick = Counter; - if (!LoadConfigDriversForVDM(&(VdmCB.vdmConfig))) { - DPRINT("VDM: failed to load configuration drivers.\n"); - //SetLastError(); - return 2; - } - if (!SetConfigOptionsForVDM(&(VdmCB.vdmAutoexec))) { - DPRINT("VDM: failed to set configuration options.\n"); - //SetLastError(); - return 3; - } + /* Check for console input events every millisecond */ + if (CurrentTickCount != LastTickCount) + { + CheckForInputEvents(); + LastTickCount = CurrentTickCount; + } - GetSystemDirectoryA(VdmCB.CommandLine, MAX_PATH); - strcat(VdmCB.CommandLine, "\\hello.exe"); - GetWindowsDirectoryA(VdmCB.CurrentDirectory, MAX_PATH); + /* Check for vertical retrace */ + if ((CurrentTickCount - LastVerticalRefresh) >= 16) + { + VgaRefreshDisplay(); + LastVerticalRefresh = CurrentTickCount; + } - for (;;) { - WriteConsoleW(GetStdHandle(STD_OUTPUT_HANDLE), - PromptMsg, lstrlenW(PromptMsg), // wcslen(PromptMsg), - &Result, NULL); - i = 0; - do { - ReadConsoleA(GetStdHandle(STD_INPUT_HANDLE), - &InputBuffer[i], 1, - &Result, NULL); - if (++i >= (sizeof(InputBuffer) - 1)) { - break; - } - } while (InputBuffer[i - 1] != '\n'); - InputBuffer[i - 1] = '\0'; + /* Horizontal retrace occurs as fast as possible */ + VgaHorizontalRetrace(); - if (InputBuffer[0] == 'r' || InputBuffer[0] == 'R') { - if (!vdmStarted) { - if (StartVDM(&VdmCB)) { - vdmStarted = TRUE; - } else { - DPRINT("VDM: failed to start.\n"); - } - } else { - DPRINT("VDM: already started.\n"); - } + /* Continue CPU emulation */ + for (i = 0; (i < STEPS_PER_CYCLE) && VdmRunning; i++) + { + EmulatorStep(); + Cycles++; } - if (InputBuffer[0] == 's' || InputBuffer[0] == 'S') { - if (vdmStarted) { - if (ShutdownVDM(&VdmCB)) { - vdmStarted = FALSE; - } else { - DPRINT("VDM: failed to shutdown.\n"); - } - } else { - DPRINT("VDM: not started.\n"); - } + + if ((CurrentTickCount - LastCyclePrintout) >= 1000) + { + DPRINT1("NTVDM: %d Instructions Per Second\n", Cycles); + LastCyclePrintout = CurrentTickCount; + Cycles = 0; } - if (InputBuffer[0] == 'q' || InputBuffer[0] == 'Q') { - break; - } } - if (!ShutdownVDM(&VdmCB)) { - DPRINT("VDM: failed to cleanly shutdown VDM.\n"); - //SetLastError(); - return 5; - } + /* Perform another screen refresh */ + VgaRefreshDisplay(); - if (!DestroyVDM(&VdmCB)) { - DPRINT("VDM: failed to cleanly destroy VDM.\n"); - //SetLastError(); - return 6; - } +Cleanup: + BiosCleanup(); + EmulatorCleanup(); - ExitProcess(0); return 0; } + +/* EOF */ Index: subsystems/ntvdm/ntvdm.h =================================================================== --- subsystems/ntvdm/ntvdm.h (révision 0) +++ subsystems/ntvdm/ntvdm.h (copie de travail) @@ -0,0 +1,39 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: ntvdm.h + * PURPOSE: Header file to define commonly used stuff + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _NTVDM_H_ +#define _NTVDM_H_ + +/* INCLUDES *******************************************************************/ + +#include +#include +#include +#include +#include + +/* DEFINES ********************************************************************/ + +#define TO_LINEAR(seg, off) (((seg) << 4) + (off)) +#define MAX_SEGMENT 0xFFFF +#define MAX_OFFSET 0xFFFF +#define MAX_ADDRESS TO_LINEAR(MAX_SEGMENT, MAX_OFFSET) +#define FAR_POINTER(x) ((ULONG_PTR)BaseAddress + TO_LINEAR(HIWORD(x), LOWORD(x))) +#define STEPS_PER_CYCLE 256 + +/* FUNCTIONS ******************************************************************/ + +extern LPVOID BaseAddress; +extern BOOLEAN VdmRunning; +extern LPCWSTR ExceptionName[]; + +VOID DisplayMessage(LPCWSTR Format, ...); + +#endif + +/* EOF */ Index: subsystems/ntvdm/ntvdm.h =================================================================== --- subsystems/ntvdm/ntvdm.h (révision 59666) +++ subsystems/ntvdm/ntvdm.h (copie de travail) Modification de propriétés sur subsystems/ntvdm/ntvdm.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: subsystems/ntvdm/ntvdm.rc =================================================================== --- subsystems/ntvdm/ntvdm.rc (révision 59666) +++ subsystems/ntvdm/ntvdm.rc (copie de travail) @@ -1,8 +1,12 @@ +#include +#include +#include "resource.h" -#include -#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Virtual DOS Machine\0" -#define REACTOS_STR_INTERNAL_NAME "ntvdm\0" -#define REACTOS_STR_ORIGINAL_FILENAME "ntvdm.exe\0" +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL + +#define REACTOS_STR_FILE_DESCRIPTION "ReactOS Virtual DOS Machine" +#define REACTOS_STR_INTERNAL_NAME "ntvdm" +#define REACTOS_STR_ORIGINAL_FILENAME "ntvdm.exe" #include #include "rsrc.rc" Index: subsystems/ntvdm/pic.c =================================================================== --- subsystems/ntvdm/pic.c (révision 0) +++ subsystems/ntvdm/pic.c (copie de travail) @@ -0,0 +1,207 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: pic.c + * PURPOSE: Programmable Interrupt Controller emulation + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "pic.h" +#include "emulator.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static PIC MasterPic, SlavePic; + +/* PUBLIC FUNCTIONS ***********************************************************/ + +BYTE PicReadCommand(BYTE Port) +{ + PPIC Pic; + + /* Which PIC are we accessing? */ + if (Port == PIC_MASTER_CMD) Pic = &MasterPic; + else Pic = &SlavePic; + + if (Pic->ReadIsr) + { + /* Read the in-service register */ + Pic->ReadIsr = FALSE; + return Pic->InServiceRegister; + } + else + { + /* The IRR is always 0, as the emulated CPU receives the interrupt instantly */ + return 0; + } +} + +VOID PicWriteCommand(BYTE Port, BYTE Value) +{ + PPIC Pic; + + /* Which PIC are we accessing? */ + if (Port == PIC_MASTER_CMD) Pic = &MasterPic; + else Pic = &SlavePic; + + if (Value & PIC_ICW1) + { + /* Start initialization */ + Pic->Initialization = TRUE; + Pic->IntOffset = 0xFF; + Pic->CascadeRegisterSet = FALSE; + Pic->ConfigRegister = Value; + return; + } + + if (Value & PIC_OCW3) + { + /* This is an OCR3 */ + if (Value == PIC_OCW3_READ_ISR) + { + /* Return the ISR on next read from command port */ + Pic->ReadIsr = TRUE; + } + + return; + } + + /* This is an OCW2 */ + if (Value & PIC_OCW2_EOI) + { + if (Value & PIC_OCW2_SL) + { + /* If the SL bit is set, clear a specific IRQ */ + Pic->InServiceRegister &= ~(1 << (Value & PIC_OCW2_NUM_MASK)); + } + else + { + /* Otherwise, clear all of them */ + Pic->InServiceRegister = 0; + } + } +} + +BYTE PicReadData(BYTE Port) +{ + /* Read the mask register */ + if (Port == PIC_MASTER_DATA) return MasterPic.MaskRegister; + else return SlavePic.MaskRegister; +} + +VOID PicWriteData(BYTE Port, BYTE Value) +{ + PPIC Pic; + + /* Which PIC are we accessing? */ + if (Port == PIC_MASTER_DATA) Pic = &MasterPic; + else Pic = &SlavePic; + + /* Is the PIC ready? */ + if (!Pic->Initialization) + { + /* Yes, this is an OCW1 */ + Pic->MaskRegister = Value; + return; + } + + /* Has the interrupt offset been set? */ + if (Pic->IntOffset == 0xFF) + { + /* This is an ICW2, set the offset (last three bits always zero) */ + Pic->IntOffset = Value & 0xF8; + + /* Check if we are in single mode and don't need an ICW4 */ + if ((Pic->ConfigRegister & PIC_ICW1_SINGLE) + && !(Pic->ConfigRegister & PIC_ICW1_ICW4)) + { + /* Yes, done initializing */ + Pic->Initialization = FALSE; + } + return; + } + + /* Check if we are in cascade mode and the cascade register was not set */ + if (!(Pic->ConfigRegister & PIC_ICW1_SINGLE) && !Pic->CascadeRegisterSet) + { + /* This is an ICW3 */ + Pic->CascadeRegister = Value; + Pic->CascadeRegisterSet = TRUE; + + /* Check if we need an ICW4 */ + if (!(Pic->ConfigRegister & PIC_ICW1_ICW4)) + { + /* No, done initializing */ + Pic->Initialization = FALSE; + } + return; + } + + /* This must be an ICW4, we will ignore the 8086 bit (assume always set) */ + if (Value & PIC_ICW4_AEOI) + { + /* Use automatic end-of-interrupt */ + Pic->AutoEoi = TRUE; + } + + /* Done initializing */ + Pic->Initialization = FALSE; +} + +VOID PicInterruptRequest(BYTE Number) +{ + BYTE i; + + if (Number >= 0 && Number < 8) + { + /* Check if any of the higher-priorirty interrupts are busy */ + for (i = 0; i <= Number ; i++) + { + if (MasterPic.InServiceRegister & (1 << Number)) return; + } + + /* Check if the interrupt is masked */ + if (MasterPic.MaskRegister & (1 << Number)) return; + + /* Set the appropriate bit in the ISR and interrupt the CPU */ + if (!MasterPic.AutoEoi) MasterPic.InServiceRegister |= 1 << Number; + EmulatorExternalInterrupt(MasterPic.IntOffset + Number); + } + else if (Number >= 8 && Number < 16) + { + Number -= 8; + + /* + * The slave PIC is connected to IRQ 2, always! If the master PIC + * was misconfigured, don't do anything. + */ + if (!(MasterPic.CascadeRegister & (1 << 2)) + || SlavePic.CascadeRegister != 2) + { + return; + } + + /* Check if any of the higher-priorirty interrupts are busy */ + if (MasterPic.InServiceRegister != 0) return; + for (i = 0; i <= Number ; i++) + { + if (SlavePic.InServiceRegister & (1 << Number)) return; + } + + /* Check if the interrupt is masked */ + if (SlavePic.MaskRegister & (1 << Number)) return; + + /* Set the IRQ 2 bit in the master ISR */ + if (!MasterPic.AutoEoi) MasterPic.InServiceRegister |= 1 << 2; + + /* Set the appropriate bit in the ISR and interrupt the CPU */ + if (!SlavePic.AutoEoi) SlavePic.InServiceRegister |= 1 << Number; + EmulatorExternalInterrupt(SlavePic.IntOffset + Number); + } +} + +/* EOF */ Index: subsystems/ntvdm/pic.c =================================================================== --- subsystems/ntvdm/pic.c (révision 59666) +++ subsystems/ntvdm/pic.c (copie de travail) Modification de propriétés sur subsystems/ntvdm/pic.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: subsystems/ntvdm/pic.h =================================================================== --- subsystems/ntvdm/pic.h (révision 0) +++ subsystems/ntvdm/pic.h (copie de travail) @@ -0,0 +1,57 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: pic.h + * PURPOSE: Programmable Interrupt Controller emulation (header file) + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _PIC_H_ +#define _PIC_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +#define PIC_MASTER_CMD 0x20 +#define PIC_MASTER_DATA 0x21 +#define PIC_SLAVE_CMD 0xA0 +#define PIC_SLAVE_DATA 0xA1 +#define PIC_ICW1 0x10 +#define PIC_ICW1_ICW4 (1 << 0) +#define PIC_ICW1_SINGLE (1 << 1) +#define PIC_ICW4_8086 (1 << 0) +#define PIC_ICW4_AEOI (1 << 1) +#define PIC_OCW2_NUM_MASK 0x07 +#define PIC_OCW2_EOI (1 << 5) +#define PIC_OCW2_SL (1 << 6) +#define PIC_OCW3 (1 << 3) +#define PIC_OCW3_READ_ISR 0x0B + +typedef struct _PIC +{ + BOOLEAN Initialization; + BYTE MaskRegister; + BYTE InServiceRegister; + BYTE IntOffset; + BYTE ConfigRegister; + BYTE CascadeRegister; + BOOLEAN CascadeRegisterSet; + BOOLEAN AutoEoi; + BOOLEAN Slave; + BOOLEAN ReadIsr; +} PIC, *PPIC; + +/* FUNCTIONS ******************************************************************/ + +BYTE PicReadCommand(BYTE Port); +VOID PicWriteCommand(BYTE Port, BYTE Value); +BYTE PicReadData(BYTE Port); +VOID PicWriteData(BYTE Port, BYTE Value); +VOID PicInterruptRequest(BYTE Number); + +#endif + +/* EOF */ Index: subsystems/ntvdm/pic.h =================================================================== --- subsystems/ntvdm/pic.h (révision 59666) +++ subsystems/ntvdm/pic.h (copie de travail) Modification de propriétés sur subsystems/ntvdm/pic.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: subsystems/ntvdm/ps2.c =================================================================== --- subsystems/ntvdm/ps2.c (révision 0) +++ subsystems/ntvdm/ps2.c (copie de travail) @@ -0,0 +1,314 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: ps2.c + * PURPOSE: PS/2 controller emulation + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "ps2.h" +#include "emulator.h" +#include "pic.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static BYTE KeyboardQueue[KEYBOARD_BUFFER_SIZE]; +static BOOLEAN KeyboardQueueEmpty = TRUE; +static UINT KeyboardQueueStart = 0; +static UINT KeyboardQueueEnd = 0; +static BYTE KeyboardResponse = 0; +static BOOLEAN KeyboardReadResponse = FALSE, KeyboardWriteResponse = FALSE; +static BYTE KeyboardConfig = PS2_DEFAULT_CONFIG; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static BOOLEAN KeyboardQueuePush(BYTE ScanCode) +{ + /* Check if the keyboard queue is full */ + if (!KeyboardQueueEmpty && (KeyboardQueueStart == KeyboardQueueEnd)) + { + return FALSE; + } + + /* Insert the value in the queue */ + KeyboardQueue[KeyboardQueueEnd] = ScanCode; + KeyboardQueueEnd++; + KeyboardQueueEnd %= KEYBOARD_BUFFER_SIZE; + + /* Since we inserted a value, it's not empty anymore */ + KeyboardQueueEmpty = FALSE; + + return TRUE; +} + +static BOOLEAN KeyboardQueuePop(BYTE *ScanCode) +{ + /* Make sure the keyboard queue is not empty */ + if (KeyboardQueueEmpty) return FALSE; + + /* Get the scan code */ + *ScanCode = KeyboardQueue[KeyboardQueueStart]; + + /* Remove the value from the queue */ + KeyboardQueueStart++; + KeyboardQueueStart %= KEYBOARD_BUFFER_SIZE; + + /* Check if the queue is now empty */ + if (KeyboardQueueStart == KeyboardQueueEnd) + { + KeyboardQueueEmpty = TRUE; + } + + return TRUE; +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +BYTE KeyboardReadStatus() +{ + BYTE Status = 0; + + /* Set the first bit if the data can be read */ + if (KeyboardReadResponse || !KeyboardQueueEmpty) Status |= 1 << 0; + + /* Always set bit 2 */ + Status |= 1 << 2; + + /* Set bit 3 if the next byte goes to the controller */ + if (KeyboardWriteResponse) Status |= 1 << 3; + + return Status; +} + +VOID KeyboardWriteCommand(BYTE Command) +{ + switch (Command) + { + /* Read configuration byte */ + case 0x20: + { + KeyboardResponse = KeyboardConfig; + KeyboardReadResponse = TRUE; + + break; + } + + /* Write configuration byte */ + case 0x60: + /* Write controller output port */ + case 0xD1: + /* Write keyboard output buffer */ + case 0xD2: + /* Write mouse output buffer */ + case 0xD3: + /* Write mouse input buffer */ + case 0xD4: + { + /* These commands require a response */ + KeyboardResponse = Command; + KeyboardWriteResponse = TRUE; + + break; + } + + /* Disable mouse */ + case 0xA7: + { + // TODO: Mouse support + + break; + } + + /* Enable mouse */ + case 0xA8: + { + // TODO: Mouse support + + break; + } + + /* Test mouse port */ + case 0xA9: + { + KeyboardResponse = 0; + KeyboardReadResponse = TRUE; + + break; + } + + /* Test PS/2 controller */ + case 0xAA: + { + KeyboardResponse = 0x55; + KeyboardReadResponse = TRUE; + + break; + } + + /* Disable keyboard */ + case 0xAD: + { + // TODO: Not implemented + break; + } + + /* Enable keyboard */ + case 0xAE: + { + // TODO: Not implemented + break; + } + + /* Read controller output port */ + case 0xD0: + { + // TODO: Not implemented + break; + } + + /* CPU Reset */ + case 0xF0: + case 0xF2: + case 0xF4: + case 0xF6: + case 0xF8: + case 0xFA: + case 0xFC: + case 0xFE: + { + /* Stop the simulation */ + VdmRunning = FALSE; + + break; + } + } +} + +BYTE KeyboardReadData() +{ + BYTE Value = 0; + + /* If there was a response byte from the controller, return it */ + if (KeyboardReadResponse) + { + KeyboardReadResponse = FALSE; + return KeyboardResponse; + } + + /* Otherwise, read the data from the queue */ + KeyboardQueuePop(&Value); + + return Value; +} + +VOID KeyboardWriteData(BYTE Data) +{ + /* Check if the controller is waiting for a response */ + if (KeyboardWriteResponse) + { + KeyboardWriteResponse = FALSE; + + /* Check which command it was */ + switch (KeyboardResponse) + { + /* Write configuration byte */ + case 0x60: + { + KeyboardConfig = Data; + break; + } + + /* Write controller output */ + case 0xD1: + { + /* Check if bit 0 is unset */ + if (!(Data & (1 << 0))) + { + /* CPU disabled - end simulation */ + VdmRunning = FALSE; + } + + /* Update the A20 line setting */ + EmulatorSetA20(Data & (1 << 1)); + + break; + } + + case 0xD2: + { + /* Push the data byte to the keyboard queue */ + KeyboardQueuePush(Data); + + break; + } + + case 0xD3: + { + // TODO: Mouse support + break; + } + + case 0xD4: + { + // TODO: Mouse support + break; + } + } + + return; + } + + // TODO: Implement PS/2 device commands +} + +VOID CheckForInputEvents() +{ + PINPUT_RECORD Buffer; + HANDLE ConsoleInput = GetStdHandle(STD_INPUT_HANDLE); + DWORD i, j, Count, TotalEvents; + BYTE ScanCode; + + /* Get the number of input events */ + if (!GetNumberOfConsoleInputEvents(ConsoleInput, &Count)) return; + if (Count == 0) return; + + /* Allocate the buffer */ + Buffer = (PINPUT_RECORD)HeapAlloc(GetProcessHeap(), 0, Count * sizeof(INPUT_RECORD)); + if (Buffer == NULL) return; + + /* Peek the input events */ + if (!ReadConsoleInput(ConsoleInput, Buffer, Count, &TotalEvents)) goto Cleanup; + + for (i = 0; i < TotalEvents; i++) + { + /* Check if this is a key event */ + if (Buffer[i].EventType != KEY_EVENT) continue; + + /* Get the scan code */ + ScanCode = (BYTE)Buffer[i].Event.KeyEvent.wVirtualScanCode; + + /* If this is a key release, set the highest bit in the scan code */ + if (!Buffer[i].Event.KeyEvent.bKeyDown) ScanCode |= 0x80; + + /* Push the scan code onto the keyboard queue */ + for (j = 0; j < Buffer[i].Event.KeyEvent.wRepeatCount; j++) + { + KeyboardQueuePush(ScanCode); + } + + /* Yes, IRQ 1 */ + PicInterruptRequest(1); + + /* Stop the loop */ + break; + } + +Cleanup: + HeapFree(GetProcessHeap(), 0, Buffer); +} + +/* EOF */ Index: subsystems/ntvdm/ps2.c =================================================================== --- subsystems/ntvdm/ps2.c (révision 59666) +++ subsystems/ntvdm/ps2.c (copie de travail) Modification de propriétés sur subsystems/ntvdm/ps2.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: subsystems/ntvdm/ps2.h =================================================================== --- subsystems/ntvdm/ps2.h (révision 0) +++ subsystems/ntvdm/ps2.h (copie de travail) @@ -0,0 +1,33 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: ps2.h + * PURPOSE: PS/2 controller emulation (header file) + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _PS2_H_ +#define _PS2_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +#define KEYBOARD_BUFFER_SIZE 32 +#define PS2_DATA_PORT 0x60 +#define PS2_CONTROL_PORT 0x64 +#define PS2_DEFAULT_CONFIG 0x05 +#define KEYBOARD_ACK 0xFA +#define KEYBOARD_RESEND 0xFE + +/* FUNCTIONS ******************************************************************/ + +BYTE KeyboardReadStatus(); +VOID KeyboardWriteCommand(BYTE Command); +BYTE KeyboardReadData(); +VOID KeyboardWriteData(BYTE Data); +VOID CheckForInputEvents(); + +#endif Index: subsystems/ntvdm/ps2.h =================================================================== --- subsystems/ntvdm/ps2.h (révision 59666) +++ subsystems/ntvdm/ps2.h (copie de travail) Modification de propriétés sur subsystems/ntvdm/ps2.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: subsystems/ntvdm/resource.h =================================================================== --- subsystems/ntvdm/resource.h (révision 59666) +++ subsystems/ntvdm/resource.h (copie de travail) @@ -1,6 +1,2 @@ -#define RC_STRING_MAX_SIZE 2048 -#define STRING_WelcomeMsg 100 -#define STRING_PromptMsg 101 - /* EOF */ Index: subsystems/ntvdm/rsrc.rc =================================================================== --- subsystems/ntvdm/rsrc.rc (révision 59666) +++ subsystems/ntvdm/rsrc.rc (copie de travail) @@ -1,27 +1,4 @@ -#include -#include "resource.h" +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL -/* Language-specific resources */ -#include "lang/bg-BG.rc" -#include "lang/cs-CZ.rc" -#include "lang/de-DE.rc" -#include "lang/en-US.rc" -#include "lang/es-ES.rc" -#include "lang/fr-FR.rc" -#include "lang/hu-HU.rc" -#include "lang/id-ID.rc" -#include "lang/it-IT.rc" -#include "lang/ja-JP.rc" -#include "lang/no-NO.rc" -#include "lang/th-TH.rc" -#include "lang/pt-BR.rc" -#include "lang/sk-SK.rc" -#include "lang/zh-CN.rc" -#include "lang/zh-TW.rc" - // UTF-8 #pragma code_page(65001) -#include "lang/pl-PL.rc" -#include "lang/ro-RO.rc" -#include "lang/ru-RU.rc" -#include "lang/uk-UA.rc" Index: subsystems/ntvdm/timer.c =================================================================== --- subsystems/ntvdm/timer.c (révision 0) +++ subsystems/ntvdm/timer.c (copie de travail) @@ -0,0 +1,236 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: timer.c + * PURPOSE: Programmable Interval Timer emulation + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "timer.h" +#include "pic.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static PIT_CHANNEL PitChannels[PIT_CHANNELS]; + +/* PUBLIC FUNCTIONS ***********************************************************/ + +VOID PitWriteCommand(BYTE Value) +{ + BYTE Channel = Value >> 6; + BYTE Mode = (Value >> 1) & 0x07; + + /* Check if this is a counter latch command */ + if (((Value >> 4) & 3) == 0) + { + PitChannels[Channel].LatchSet = TRUE; + PitChannels[Channel].LatchedValue = PitChannels[Channel].CurrentValue; + return; + } + + /* Set the access mode and reset flip-flops */ + PitChannels[Channel].AccessMode = (Value >> 4) & 3; + PitChannels[Channel].Pulsed = FALSE; + PitChannels[Channel].LatchSet = FALSE; + PitChannels[Channel].InputFlipFlop = FALSE; + PitChannels[Channel].OutputFlipFlop = FALSE; + + switch (Mode) + { + case 0: + case 1: + case 2: + case 3: + case 4: + case 5: + { + PitChannels[Channel].Mode = Mode; + break; + } + + case 6: + { + PitChannels[Channel].Mode = PIT_MODE_RATE_GENERATOR; + break; + } + + case 7: + { + PitChannels[Channel].Mode = PIT_MODE_SQUARE_WAVE; + break; + } + } +} + +BYTE PitReadData(BYTE Channel) +{ + WORD CurrentValue = PitChannels[Channel].CurrentValue; + BYTE AccessMode = PitChannels[Channel].AccessMode; + + /* Check if the value was latched */ + if (PitChannels[Channel].LatchSet) + { + CurrentValue = PitChannels[Channel].LatchedValue; + + if (AccessMode == 1 || AccessMode == 2) + { + /* The latched value was read as one byte */ + PitChannels[Channel].LatchSet = FALSE; + } + } + + /* Use the flip-flop for access mode 3 */ + if (AccessMode == 3) + { + AccessMode = PitChannels[Channel].InputFlipFlop ? 1 : 2; + PitChannels[Channel].InputFlipFlop = !PitChannels[Channel].InputFlipFlop; + + /* Check if this was the last read for the latched value */ + if (!PitChannels[Channel].InputFlipFlop) + { + /* Yes, the latch value was read as two bytes */ + PitChannels[Channel].LatchSet = FALSE; + } + } + + switch (AccessMode) + { + case 1: + { + /* Low byte */ + return CurrentValue & 0x00FF; + } + + case 2: + { + /* High byte */ + return CurrentValue >> 8; + } + } + + /* Shouldn't get here */ + return 0; +} + +VOID PitWriteData(BYTE Channel, BYTE Value) +{ + BYTE AccessMode = PitChannels[Channel].AccessMode; + + /* Use the flip-flop for access mode 3 */ + if (PitChannels[Channel].AccessMode == 3) + { + AccessMode = PitChannels[Channel].InputFlipFlop ? 1 : 2; + PitChannels[Channel].InputFlipFlop = !PitChannels[Channel].InputFlipFlop; + } + + switch (AccessMode) + { + case 1: + { + /* Low byte */ + PitChannels[Channel].ReloadValue &= 0xFF00; + PitChannels[Channel].ReloadValue |= Value; + break; + } + + case 2: + { + /* High byte */ + PitChannels[Channel].ReloadValue &= 0x00FF; + PitChannels[Channel].ReloadValue |= Value << 8; + } + } +} + +VOID PitDecrementCount() +{ + INT i; + + for (i = 0; i < PIT_CHANNELS; i++) + { + switch (PitChannels[i].Mode) + { + case PIT_MODE_INT_ON_TERMINAL_COUNT: + { + /* Decrement the value */ + PitChannels[i].CurrentValue--; + + /* Did it fall to the terminal count? */ + if (PitChannels[i].CurrentValue == 0 && !PitChannels[i].Pulsed) + { + /* Yes, raise the output line */ + if (i == 0) PicInterruptRequest(0); + PitChannels[i].Pulsed = TRUE; + } + break; + } + + case PIT_MODE_RATE_GENERATOR: + { + /* Decrement the value */ + PitChannels[i].CurrentValue--; + + /* Did it fall to zero? */ + if (PitChannels[i].CurrentValue != 0) break; + + /* Yes, raise the output line and reload */ + if (i == 0) PicInterruptRequest(0); + PitChannels[i].CurrentValue = PitChannels[i].ReloadValue; + + break; + } + + case PIT_MODE_SQUARE_WAVE: + { + /* Decrement the value by 2 */ + PitChannels[i].CurrentValue -= 2; + + /* Did it fall to zero? */ + if (PitChannels[i].CurrentValue != 0) break; + + /* Yes, toggle the flip-flop */ + PitChannels[i].OutputFlipFlop = !PitChannels[i].OutputFlipFlop; + + /* Did this create a rising edge in the signal? */ + if (PitChannels[i].OutputFlipFlop) + { + /* Yes, IRQ 0 if this is channel 0 */ + if (i == 0) PicInterruptRequest(0); + } + + /* Reload the value, but make sure it's even */ + if (PitChannels[i].ReloadValue % 2) + { + /* It's odd, reduce it by 1 */ + PitChannels[i].CurrentValue = PitChannels[i].ReloadValue - 1; + } + else + { + /* It was even */ + PitChannels[i].CurrentValue = PitChannels[i].ReloadValue; + } + + break; + } + + case PIT_MODE_SOFTWARE_STROBE: + { + // TODO: NOT IMPLEMENTED + break; + } + + case PIT_MODE_HARDWARE_ONE_SHOT: + case PIT_MODE_HARDWARE_STROBE: + { + /* These modes do not work on x86 PCs */ + break; + } + } + } +} + +/* EOF */ Index: subsystems/ntvdm/timer.c =================================================================== --- subsystems/ntvdm/timer.c (révision 59666) +++ subsystems/ntvdm/timer.c (copie de travail) Modification de propriétés sur subsystems/ntvdm/timer.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: subsystems/ntvdm/timer.h =================================================================== --- subsystems/ntvdm/timer.h (révision 0) +++ subsystems/ntvdm/timer.h (copie de travail) @@ -0,0 +1,56 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: timer.h + * PURPOSE: Programmable Interval Timer emulation (header file) + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _TIMER_H_ +#define _TIMER_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +#define PIT_CHANNELS 3 +#define PIT_BASE_FREQUENCY 1193182LL +#define PIT_DATA_PORT(x) (0x40 + (x)) +#define PIT_COMMAND_PORT 0x43 + +enum +{ + PIT_MODE_INT_ON_TERMINAL_COUNT, + PIT_MODE_HARDWARE_ONE_SHOT, + PIT_MODE_RATE_GENERATOR, + PIT_MODE_SQUARE_WAVE, + PIT_MODE_SOFTWARE_STROBE, + PIT_MODE_HARDWARE_STROBE +}; + +typedef struct _PIT_CHANNEL +{ + WORD ReloadValue; + WORD CurrentValue; + WORD LatchedValue; + INT Mode; + BOOLEAN Pulsed; + BOOLEAN LatchSet; + BOOLEAN InputFlipFlop; + BOOLEAN OutputFlipFlop; + BYTE AccessMode; +} PIT_CHANNEL, *PPIT_CHANNEL; + +/* FUNCTIONS ******************************************************************/ + +VOID PitWriteCommand(BYTE Value); +BYTE PitReadData(BYTE Channel); +VOID PitWriteData(BYTE Channel, BYTE Value); +VOID PitDecrementCount(); + +#endif + +/* EOF */ + Index: subsystems/ntvdm/timer.h =================================================================== --- subsystems/ntvdm/timer.h (révision 59666) +++ subsystems/ntvdm/timer.h (copie de travail) Modification de propriétés sur subsystems/ntvdm/timer.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: subsystems/ntvdm/vga.c =================================================================== --- subsystems/ntvdm/vga.c (révision 0) +++ subsystems/ntvdm/vga.c (copie de travail) @@ -0,0 +1,973 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: vga.c + * PURPOSE: VGA hardware emulation + * PROGRAMMERS: Aleksandar Andrejevic + */ + +/* INCLUDES *******************************************************************/ + +#define NDEBUG + +#include "vga.h" +#include "bios.h" + +/* PRIVATE VARIABLES **********************************************************/ + +static CONST DWORD MemoryBase[] = { 0xA0000, 0xA0000, 0xB0000, 0xB8000 }; +static CONST DWORD MemoryLimit[] = { 0xA7FFF, 0xA7FFF, 0xB7FFF, 0xBFFFF }; + +static BYTE VgaMemory[VGA_NUM_BANKS * VGA_BANK_SIZE]; +static BYTE VgaMiscRegister; +static BYTE VgaSeqIndex = VGA_SEQ_RESET_REG; +static BYTE VgaSeqRegisters[VGA_SEQ_MAX_REG]; +static BYTE VgaGcIndex = VGA_GC_RESET_REG; +static BYTE VgaGcRegisters[VGA_GC_MAX_REG]; +static BYTE VgaCrtcIndex = VGA_CRTC_HORZ_TOTAL_REG; +static BYTE VgaCrtcRegisters[VGA_CRTC_MAX_REG]; +static BYTE VgaAcIndex = VGA_AC_PAL_0_REG; +static BOOLEAN VgaAcLatch = FALSE; +static BYTE VgaAcRegisters[VGA_AC_MAX_REG]; +static BYTE VgaDacIndex = 0; +static BOOLEAN VgaDacReadWrite = FALSE; +static BYTE VgaDacRegisters[VGA_PALETTE_SIZE]; +static BOOLEAN InVerticalRetrace = FALSE; +static BOOLEAN InHorizontalRetrace = FALSE; +static HANDLE TextConsoleBuffer = NULL; +static HANDLE GraphicsConsoleBuffer = NULL; +static LPVOID ConsoleFramebuffer = NULL; +static HANDLE ConsoleMutex = NULL; +static BOOLEAN NeedsUpdate = FALSE; +static BOOLEAN ModeChanged = TRUE; +static BOOLEAN CursorMoved = FALSE; +static BOOLEAN TextMode = TRUE; +static SMALL_RECT UpdateRectangle = { 0, 0, 0, 0 }; + +/* PRIVATE FUNCTIONS **********************************************************/ + +static inline INT VgaGetAddressSize(VOID) +{ + if (VgaCrtcRegisters[VGA_CRTC_UNDERLINE_REG] & VGA_CRTC_UNDERLINE_DWORD) + { + /* Double-word addressing */ + return 4; + } + + if (VgaCrtcRegisters[VGA_CRTC_MODE_CONTROL_REG] & VGA_CRTC_MODE_CONTROL_BYTE) + { + /* Byte addressing */ + return 1; + } + + /* Word addressing */ + return 2; +} + +static inline DWORD VgaTranslateReadAddress(DWORD Address) +{ + DWORD Offset = Address - VgaGetVideoBaseAddress(); + BYTE Plane; + + /* Check for chain-4 and odd-even mode */ + if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4) + { + /* The lowest two bits are the plane number */ + Plane = Offset & 3; + Offset >>= 2; + } + else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE) + { + /* The LSB is the plane number */ + Plane = Offset & 1; + Offset >>= 1; + } + else + { + /* Use the read mode */ + Plane = VgaGcRegisters[VGA_GC_READ_MAP_SEL_REG] & 0x03; + } + + /* Multiply the offset by the address size */ + Offset *= VgaGetAddressSize(); + + return Offset + Plane * VGA_BANK_SIZE; +} + +static inline DWORD VgaTranslateWriteAddress(DWORD Address) +{ + DWORD Offset = Address - VgaGetVideoBaseAddress(); + + /* Check for chain-4 and odd-even mode */ + if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4) + { + /* Shift the offset to the right by 2 */ + Offset >>= 2; + } + else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE) + { + /* Shift the offset to the right by 1 */ + Offset >>= 1; + } + + /* Multiply the offset by the address size */ + Offset *= VgaGetAddressSize(); + + /* Return the offset on plane 0 */ + return Offset; +} + +static inline VOID VgaMarkForUpdate(SHORT Row, SHORT Column) +{ + DPRINT("VgaMarkForUpdate: Row %d, Column %d\n", Row, Column); + + /* Check if this is the first time the rectangle is updated */ + if (!NeedsUpdate) + { + UpdateRectangle.Left = UpdateRectangle.Top = (SHORT)0x7FFF; + UpdateRectangle.Right = UpdateRectangle.Bottom = (SHORT)0x8000; + } + + /* Expand the rectangle to include the point */ + UpdateRectangle.Left = min(UpdateRectangle.Left, Column); + UpdateRectangle.Right = max(UpdateRectangle.Right, Column); + UpdateRectangle.Top = min(UpdateRectangle.Top, Row); + UpdateRectangle.Bottom = max(UpdateRectangle.Bottom, Row); + + /* Set the update request flag */ + NeedsUpdate = TRUE; +} + +static VOID VgaWriteSequencer(BYTE Data) +{ + ASSERT(VgaSeqIndex < VGA_SEQ_MAX_REG); + + /* Save the value */ + VgaSeqRegisters[VgaSeqIndex] = Data; +} + +static VOID VgaWriteGc(BYTE Data) +{ + ASSERT(VgaGcIndex < VGA_GC_MAX_REG); + + /* Save the value */ + VgaGcRegisters[VgaGcIndex] = Data; + + /* Check the index */ + switch (VgaGcIndex) + { + case VGA_GC_MISC_REG: + { + /* The GC misc register decides if it's text or graphics mode */ + ModeChanged = TRUE; + + break; + } + } +} + +static VOID VgaWriteCrtc(BYTE Data) +{ + ASSERT(VgaGcIndex < VGA_CRTC_MAX_REG); + + /* Save the value */ + VgaCrtcRegisters[VgaCrtcIndex] = Data; + + /* Check the index */ + switch (VgaCrtcIndex) + { + case VGA_CRTC_END_HORZ_DISP_REG: + case VGA_CRTC_VERT_DISP_END_REG: + case VGA_CRTC_OVERFLOW_REG: + { + /* The video mode has changed */ + ModeChanged = TRUE; + + break; + } + + case VGA_CRTC_CURSOR_LOC_LOW_REG: + case VGA_CRTC_CURSOR_LOC_HIGH_REG: + case VGA_CRTC_CURSOR_START_REG: + case VGA_CRTC_CURSOR_END_REG: + { + /* Set the cursor moved flag */ + CursorMoved = TRUE; + + break; + } + } +} + +static VOID VgaWriteDac(BYTE Data) +{ + /* Set the value */ + VgaDacRegisters[VgaDacIndex++] = Data; + VgaDacIndex %= VGA_PALETTE_SIZE; + + // TODO: Change the palette! +} + +static VOID VgaWriteAc(BYTE Data) +{ + ASSERT(VgaAcIndex < VGA_AC_MAX_REG); + + /* Save the value */ + VgaAcRegisters[VgaAcIndex] = Data; +} + +static VOID VgaEnterGraphicsMode(UINT Width, UINT Height, UINT BitDepth) +{ + DWORD i; + CONSOLE_GRAPHICS_BUFFER_INFO GraphicsBufferInfo; + BYTE BitmapInfoBuffer[VGA_BITMAP_INFO_SIZE]; + LPBITMAPINFO BitmapInfo = (LPBITMAPINFO)BitmapInfoBuffer; + LPWORD PaletteIndex = (LPWORD)(BitmapInfoBuffer + sizeof(BITMAPINFOHEADER)); + + /* Fill the bitmap info header */ + ZeroMemory(&BitmapInfo->bmiHeader, sizeof(BITMAPINFOHEADER)); + BitmapInfo->bmiHeader.biSize = sizeof(BITMAPINFOHEADER); + BitmapInfo->bmiHeader.biWidth = Width; + BitmapInfo->bmiHeader.biHeight = Height; + BitmapInfo->bmiHeader.biBitCount = 8; + BitmapInfo->bmiHeader.biPlanes = 1; + BitmapInfo->bmiHeader.biCompression = BI_RGB; + BitmapInfo->bmiHeader.biSizeImage = Width * Height * (BitDepth / 8); + + /* Fill the palette data */ + for (i = 0; i < BitDepth; i++) PaletteIndex[i] = i; + + /* Fill the console graphics buffer info */ + GraphicsBufferInfo.dwBitMapInfoLength = VGA_BITMAP_INFO_SIZE; + GraphicsBufferInfo.lpBitMapInfo = BitmapInfo; + GraphicsBufferInfo.dwUsage = DIB_PAL_COLORS; + + /* Create the buffer */ + GraphicsConsoleBuffer = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, + FILE_SHARE_READ | FILE_SHARE_WRITE, + NULL, + CONSOLE_GRAPHICS_BUFFER, + &GraphicsBufferInfo); + + /* Save the framebuffer address and mutex */ + ConsoleFramebuffer = GraphicsBufferInfo.lpBitMap; + ConsoleMutex = GraphicsBufferInfo.hMutex; + + /* Set the active buffer */ + SetConsoleActiveScreenBuffer(GraphicsConsoleBuffer); +} + +static VOID VgaLeaveGraphicsMode() +{ + /* Switch back to the text buffer */ + SetConsoleActiveScreenBuffer(TextConsoleBuffer); + + /* Cleanup the video data */ + CloseHandle(ConsoleMutex); + CloseHandle(GraphicsConsoleBuffer); + GraphicsConsoleBuffer = NULL; +} + +static VOID VgaUpdateMode(VOID) +{ + COORD Resolution = VgaGetDisplayResolution(); + + if (!TextMode) + { + /* Switching from graphics mode to text mode */ + VgaLeaveGraphicsMode(); + } + else + { + /* Free the old framebuffer */ + HeapFree(GetProcessHeap(), 0, ConsoleFramebuffer); + ConsoleFramebuffer = NULL; + } + + /* Check if the new mode is alphanumeric */ + if (!(VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA)) + { + /* Resize the console */ + SetConsoleScreenBufferSize(TextConsoleBuffer, Resolution); + + /* Allocate a framebuffer */ + ConsoleFramebuffer = HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY, + sizeof(CHAR_INFO) + * Resolution.X + * Resolution.Y); + if (ConsoleFramebuffer == NULL) + { + DisplayMessage(L"An unexpected error occurred!\n"); + VdmRunning = FALSE; + return; + } + + /* Set the text mode flag */ + TextMode = TRUE; + } + else + { + /* Enter 8-bit graphics mode */ + VgaEnterGraphicsMode(Resolution.X, Resolution.Y, 8); + + /* Clear the text mode flag */ + TextMode = FALSE; + } + + /* Perform a full update */ + NeedsUpdate = TRUE; + UpdateRectangle.Left = 0; + UpdateRectangle.Top = 0; + UpdateRectangle.Right = Resolution.X; + UpdateRectangle.Bottom = Resolution.Y; +} + +static VOID VgaUpdateFramebuffer(VOID) +{ + INT i, j, k; + COORD Resolution = VgaGetDisplayResolution(); + INT AddressSize = VgaGetAddressSize(); + DWORD Address = (VgaCrtcRegisters[VGA_CRTC_START_ADDR_HIGH_REG] << 8) + + VgaCrtcRegisters[VGA_CRTC_START_ADDR_LOW_REG]; + DWORD ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2; + PCHAR_INFO CharBuffer = (PCHAR_INFO)ConsoleFramebuffer; + PBYTE GraphicsBuffer = (PBYTE)ConsoleFramebuffer; + + /* Loop through the scanlines */ + for (i = 0; i < Resolution.Y; i++) + { + /* Check if this is text mode or graphics mode */ + if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) + { + /* Graphics mode */ + + /* Loop through the pixels */ + for (j = 0; j < Resolution.X; j++) + { + BYTE PixelData = 0; + + /* Check the shifting mode */ + if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_SHIFT256) + { + /* 4 bits shifted from each plane */ + + /* Check if this is 16 or 256 color mode */ + if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT) + { + /* One byte per pixel */ + PixelData = VgaMemory[(j % VGA_NUM_BANKS) * VGA_BANK_SIZE + + (Address + (j / VGA_NUM_BANKS)) + * AddressSize]; + } + else + { + /* 4-bits per pixel */ + + PixelData = VgaMemory[(j % VGA_NUM_BANKS) * VGA_BANK_SIZE + + (Address + (j / (VGA_NUM_BANKS * 2))) + * AddressSize]; + + /* Check if we should use the highest 4 bits or lowest 4 */ + if (((j / VGA_NUM_BANKS) % 2) == 0) + { + /* Highest 4 */ + PixelData >>= 4; + } + else + { + /* Lowest 4 */ + PixelData &= 0x0F; + } + } + } + else if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_SHIFTREG) + { + /* + * 2 bits shifted from plane 0 and 2 for the first 4 pixels, + * then 2 bits shifted from plane 1 and 3 for the next 4 + */ + + // TODO: NOT IMPLEMENTED! + DPRINT1("Interleaved shift mode is not implemented!\n"); + } + else + { + /* 1 bit shifted from each plane */ + + /* Check if this is 16 or 256 color mode */ + if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT) + { + /* 8 bits per pixel, 2 on each plane */ + + for (k = 0; k < VGA_NUM_BANKS; k++) + { + /* The data is on plane k, 4 pixels per byte */ + BYTE PlaneData = VgaMemory[k * VGA_BANK_SIZE + + (Address + (j / 4)) * AddressSize]; + + /* The mask of the first bit in the pair */ + BYTE BitMask = 1 << (((3 - (j % 4)) * 2) + 1); + + /* Bits 0, 1, 2 and 3 come from the first bit of the pair */ + if (PlaneData & BitMask) PixelData |= 1 << k; + + /* Bits 4, 5, 6 and 7 come from the second bit of the pair */ + if (PlaneData & (BitMask >> 1)) PixelData |= 1 << (k + 4); + } + } + else + { + /* 4 bits per pixel, 1 on each plane */ + + for (k = 0; k < VGA_NUM_BANKS; k++) + { + BYTE PlaneData = VgaMemory[k * VGA_BANK_SIZE + + (Address + (j / 8)) * AddressSize]; + + /* If the bit on that plane is set, set it */ + if (PlaneData & (1 << (7 - (j % 8)))) PixelData |= 1 << k; + } + } + } + + /* Now check if the resulting pixel data has changed */ + if (GraphicsBuffer[i * Resolution.X + j] != PixelData) + { + /* Yes, write the new value */ + GraphicsBuffer[i * Resolution.X + j] = PixelData; + + /* Mark the specified pixel as changed */ + VgaMarkForUpdate(i, j); + } + } + } + else + { + /* Text mode */ + + /* Loop through the characters */ + for (j = 0; j < Resolution.X; j++) + { + DWORD CurrentAddr = LOWORD((Address + j) * AddressSize); + CHAR_INFO CharInfo; + + /* Plane 0 holds the character itself */ + CharInfo.Char.AsciiChar = VgaMemory[CurrentAddr]; + + /* Plane 1 holds the attribute */ + CharInfo.Attributes = VgaMemory[CurrentAddr + VGA_BANK_SIZE]; + + /* Now check if the resulting character data has changed */ + if ((CharBuffer[i * Resolution.X + j].Char.AsciiChar != CharInfo.Char.AsciiChar) + || (CharBuffer[i * Resolution.X + j].Attributes != CharInfo.Attributes)) + { + /* Yes, write the new value */ + CharBuffer[i * Resolution.X + j] = CharInfo; + + /* Mark the specified pixel as changed */ + VgaMarkForUpdate(i, j); + } + } + } + + /* Move to the next scanline */ + Address += ScanlineSize; + } +} + +static VOID VgaUpdateTextCursor(VOID) +{ + COORD Position; + CONSOLE_CURSOR_INFO CursorInfo; + BYTE CursorStart = VgaCrtcRegisters[VGA_CRTC_CURSOR_START_REG] & 0x3F; + BYTE CursorEnd = VgaCrtcRegisters[VGA_CRTC_CURSOR_END_REG] & 0x1F; + DWORD ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2; + WORD Location = MAKEWORD(VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_LOW_REG], + VgaCrtcRegisters[VGA_CRTC_CURSOR_LOC_HIGH_REG]); + + if (CursorStart < CursorEnd) + { + /* Visible cursor */ + CursorInfo.bVisible = TRUE; + CursorInfo.dwSize = (100 * (CursorEnd - CursorStart)) >> 5; + } + else + { + /* No cursor */ + CursorInfo.bVisible = FALSE; + CursorInfo.dwSize = 0; + } + + /* Add the cursor skew to the location */ + Location += (VgaCrtcRegisters[VGA_CRTC_CURSOR_END_REG] >> 5) & 3; + + /* Find the coordinates of the new position */ + Position.X = Location % ScanlineSize; + Position.Y = Location / ScanlineSize; + + /* Update the physical cursor */ + SetConsoleCursorInfo(TextConsoleBuffer, &CursorInfo); + SetConsoleCursorPosition(TextConsoleBuffer, Position); +} + +/* PUBLIC FUNCTIONS ***********************************************************/ + +DWORD VgaGetVideoBaseAddress(VOID) +{ + return MemoryBase[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03]; +} + +DWORD VgaGetVideoLimitAddress(VOID) +{ + return MemoryLimit[(VgaGcRegisters[VGA_GC_MISC_REG] >> 2) & 0x03]; +} + +COORD VgaGetDisplayResolution(VOID) +{ + COORD Resolution; + + /* The low 8 bits are in the display registers */ + Resolution.X = VgaCrtcRegisters[VGA_CRTC_END_HORZ_DISP_REG]; + Resolution.Y = VgaCrtcRegisters[VGA_CRTC_VERT_DISP_END_REG]; + + /* Set the top bits from the overflow register */ + if (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VDE8) + { + Resolution.Y |= 1 << 8; + } + if (VgaCrtcRegisters[VGA_CRTC_OVERFLOW_REG] & VGA_CRTC_OVERFLOW_VDE9) + { + Resolution.Y |= 1 << 9; + } + + /* Increase the values by 1 */ + Resolution.X++; + Resolution.Y++; + + if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) + { + /* Multiply the horizontal resolution by the 9/8 dot mode */ + Resolution.X *= (VgaSeqRegisters[VGA_SEQ_CLOCK_REG] & VGA_SEQ_CLOCK_98DM) + ? 8 : 9; + + /* The horizontal resolution is halved in 8-bit mode */ + if (VgaAcRegisters[VGA_AC_CONTROL_REG] & VGA_AC_CONTROL_8BIT) Resolution.X /= 2; + + /* Divide the vertical resolution by the maximum scan line */ + Resolution.Y /= ((DWORD)VgaCrtcRegisters[VGA_CRTC_MAX_SCAN_LINE_REG] & 0x1F) + 1; + } + else + { + /* Divide the number of scanlines by the font size */ + Resolution.Y /= 16; + } + + /* Return the resolution */ + return Resolution; +} + +VOID VgaRefreshDisplay(VOID) +{ + COORD Resolution = VgaGetDisplayResolution(); + + DPRINT("VgaRefreshDisplay\n"); + + if (ModeChanged) + { + /* Change the display mode */ + VgaUpdateMode(); + + /* Reset the mode change flag */ + ModeChanged = FALSE; + } + + if (CursorMoved) + { + /* Change the text cursor location */ + VgaUpdateTextCursor(); + + /* Reset the cursor move flag */ + CursorMoved = FALSE; + } + + /* Update the contents of the framebuffer */ + VgaUpdateFramebuffer(); + + /* Set the vertical retrace flag */ + InVerticalRetrace = TRUE; + + /* Ignore if there's nothing to update */ + if (!NeedsUpdate) return; + + DPRINT("Updating screen rectangle (%d, %d, %d, %d)\n", + UpdateRectangle.Left, + UpdateRectangle.Top, + UpdateRectangle.Right, + UpdateRectangle.Bottom); + + /* Check if this is text mode or graphics mode */ + if (VgaGcRegisters[VGA_GC_MISC_REG] & VGA_GC_MISC_NOALPHA) + { + /* Graphics mode */ + + /* Redraw the screen */ + InvalidateConsoleDIBits(GraphicsConsoleBuffer, &UpdateRectangle); + } + else + { + /* Text mode */ + COORD Origin = { UpdateRectangle.Left, UpdateRectangle.Top }; + + /* Write the data to the console */ + WriteConsoleOutputA(TextConsoleBuffer, + (PCHAR_INFO)ConsoleFramebuffer, + Resolution, + Origin, + &UpdateRectangle); + + } + + /* Clear the update flag */ + NeedsUpdate = FALSE; +} + +VOID VgaHorizontalRetrace(VOID) +{ + /* Set the flag */ + InHorizontalRetrace = TRUE; +} + +VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size) +{ + DWORD i; + + DPRINT("VgaReadMemory: Address 0x%08X, Size %lu\n", + Address, + Size); + + /* Ignore if video RAM access is disabled */ + if (!(VgaMiscRegister & VGA_MISC_RAM_ENABLED)) return; + + /* Loop through each byte */ + for (i = 0; i < Size; i++) + { + DWORD VideoAddress = VgaTranslateReadAddress(Address + i); + + /* Copy the value to the buffer */ + Buffer[i] = VgaMemory[VideoAddress]; + } +} + +VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size) +{ + DWORD i, j; + + DPRINT("VgaWriteMemory: Address 0x%08X, Size %lu\n", + Address, + Size); + + /* Ignore if video RAM access is disabled */ + if (!(VgaMiscRegister & VGA_MISC_RAM_ENABLED)) return; + + /* Also ignore if write access to all planes is disabled */ + if ((VgaSeqRegisters[VGA_SEQ_MASK_REG] & 0x0F) == 0x00) return; + + /* Loop through each byte */ + for (i = 0; i < Size; i++) + { + DWORD VideoAddress = VgaTranslateWriteAddress(Address + i); + + for (j = 0; j < VGA_NUM_BANKS; j++) + { + /* Make sure the page is writeable */ + if (!(VgaSeqRegisters[VGA_SEQ_MASK_REG] & (1 << j))) continue; + + /* Check if this is chain-4 mode */ + if (VgaSeqRegisters[VGA_SEQ_MEM_REG] & VGA_SEQ_MEM_C4) + { + if (((Address + i) & 3) != j) + { + /* This plane will not be accessed */ + continue; + } + } + + /* Check if this is odd-even mode */ + if (VgaGcRegisters[VGA_GC_MODE_REG] & VGA_GC_MODE_OE) + { + if (((Address + i) & 1) != (j & 1)) + { + /* This plane will not be accessed */ + continue; + } + } + + /* Copy the value to the VGA memory */ + VgaMemory[VideoAddress + j * VGA_BANK_SIZE] = Buffer[i]; + } + } +} + +BYTE VgaReadPort(WORD Port) +{ + DPRINT("VgaReadPort: Port 0x%04X\n", Port); + + switch (Port) + { + case VGA_AC_INDEX: + { + return VgaAcIndex; + } + + case VGA_AC_READ: + { + return VgaAcRegisters[VgaAcIndex]; + } + + case VGA_SEQ_INDEX: + { + return VgaSeqIndex; + } + + case VGA_SEQ_DATA: + { + return VgaSeqRegisters[VgaSeqIndex]; + } + + case VGA_DAC_READ_INDEX: + { + /* This returns the read/write state */ + return VgaDacReadWrite ? 0 : 3; + } + + case VGA_DAC_WRITE_INDEX: + { + return VgaDacIndex; + } + + case VGA_DAC_DATA: + { + /* Ignore reads in write mode */ + if (!VgaDacReadWrite) + { + BYTE Data = VgaDacRegisters[VgaDacIndex++]; + VgaDacIndex %= VGA_PALETTE_SIZE; + return Data; + } + + break; + } + + case VGA_MISC_READ: + { + return VgaMiscRegister; + } + + case VGA_CRTC_INDEX: + { + return VgaCrtcIndex; + } + + case VGA_CRTC_DATA: + { + return VgaCrtcRegisters[VgaCrtcIndex]; + } + + case VGA_GC_INDEX: + { + return VgaGcIndex; + } + + case VGA_GC_DATA: + { + return VgaGcRegisters[VgaGcIndex]; + } + + case VGA_STAT_MONO: + case VGA_STAT_COLOR: + { + BYTE Result = 0; + + /* Reset the AC latch */ + VgaAcLatch = FALSE; + + /* Set a flag if there is a vertical or horizontal retrace */ + if (InVerticalRetrace || InHorizontalRetrace) Result |= VGA_STAT_DD; + + /* Set an additional flag if there was a vertical retrace */ + if (InVerticalRetrace) Result |= VGA_STAT_VRETRACE; + + /* Clear the flags */ + InHorizontalRetrace = InVerticalRetrace = FALSE; + + return Result; + } + } + + return 0; +} + +VOID VgaWritePort(WORD Port, BYTE Data) +{ + DPRINT("VgaWritePort: Port 0x%04X, Data 0x%02X\n", Port, Data); + + switch (Port) + { + case VGA_AC_INDEX: + { + if (!VgaAcLatch) + { + /* Change the index */ + if (Data < VGA_AC_MAX_REG) VgaAcIndex = Data; + } + else + { + /* Write the data */ + VgaWriteAc(Data); + } + + /* Toggle the latch */ + VgaAcLatch = !VgaAcLatch; + + break; + } + + case VGA_SEQ_INDEX: + { + /* Set the sequencer index register */ + if (Data < VGA_SEQ_MAX_REG) VgaSeqIndex = Data; + + break; + } + + case VGA_SEQ_DATA: + { + /* Call the sequencer function */ + VgaWriteSequencer(Data); + + break; + } + + case VGA_DAC_READ_INDEX: + { + VgaDacReadWrite = FALSE; + VgaDacIndex = Data % VGA_PALETTE_SIZE; + + break; + } + + case VGA_DAC_WRITE_INDEX: + { + VgaDacReadWrite = TRUE; + VgaDacIndex = Data % VGA_PALETTE_SIZE; + + break; + } + + case VGA_DAC_DATA: + { + /* Ignore writes in read mode */ + if (VgaDacReadWrite) VgaWriteDac(Data & 0x3F); + + break; + } + + case VGA_MISC_WRITE: + { + VgaMiscRegister = Data; + + break; + } + + case VGA_CRTC_INDEX: + { + /* Set the CRTC index register */ + if (Data < VGA_CRTC_MAX_REG) VgaCrtcIndex = Data; + + break; + } + + case VGA_CRTC_DATA: + { + /* Call the CRTC function */ + VgaWriteCrtc(Data); + + break; + } + + case VGA_GC_INDEX: + { + /* Set the GC index register */ + if (Data < VGA_GC_MAX_REG) VgaGcIndex = Data; + break; + } + + case VGA_GC_DATA: + { + /* Call the GC function */ + VgaWriteGc(Data); + + break; + } + } +} + +VOID VgaInitialize(HANDLE TextHandle) +{ + INT i, j; + COORD Resolution; + INT AddressSize; + DWORD ScanlineSize; + COORD Origin = { 0, 0 }; + SMALL_RECT ScreenRect; + PCHAR_INFO CharBuffer; + DWORD Address = 0; + + /* Set the global handle */ + TextConsoleBuffer = TextHandle; + + /* Set the default video mode */ + BiosSetVideoMode(BIOS_DEFAULT_VIDEO_MODE); + VgaUpdateMode(); + ModeChanged = FALSE; + + /* Get the data */ + Resolution = VgaGetDisplayResolution(); + CharBuffer = (PCHAR_INFO)ConsoleFramebuffer; + AddressSize = VgaGetAddressSize(); + ScreenRect.Left = ScreenRect.Top = 0; + ScreenRect.Right = Resolution.X; + ScreenRect.Bottom = Resolution.Y; + ScanlineSize = (DWORD)VgaCrtcRegisters[VGA_CRTC_OFFSET_REG] * 2; + + /* Read the data from the console into the framebuffer */ + ReadConsoleOutputA(TextConsoleBuffer, + ConsoleFramebuffer, + Resolution, + Origin, + &ScreenRect); + + + /* Loop through the scanlines */ + for (i = 0; i < Resolution.Y; i++) + { + /* Loop through the characters */ + for (j = 0; j < Resolution.X; j++) + { + DWORD CurrentAddr = LOWORD((Address + j) * AddressSize); + + /* Store the character in plane 0 */ + VgaMemory[CurrentAddr] = CharBuffer[i * Resolution.X + j].Char.AsciiChar; + + /* Store the attribute in plane 1 */ + VgaMemory[CurrentAddr + VGA_BANK_SIZE] = (BYTE)CharBuffer[i * Resolution.X + j].Attributes; + } + + /* Move to the next scanline */ + Address += ScanlineSize; + } +} + +/* EOF */ + Index: subsystems/ntvdm/vga.c =================================================================== --- subsystems/ntvdm/vga.c (révision 59666) +++ subsystems/ntvdm/vga.c (copie de travail) Modification de propriétés sur subsystems/ntvdm/vga.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Index: subsystems/ntvdm/vga.h =================================================================== --- subsystems/ntvdm/vga.h (révision 0) +++ subsystems/ntvdm/vga.h (copie de travail) @@ -0,0 +1,200 @@ +/* + * COPYRIGHT: GPL - See COPYING in the top level directory + * PROJECT: ReactOS Virtual DOS Machine + * FILE: vga.h + * PURPOSE: VGA hardware emulation (header file) + * PROGRAMMERS: Aleksandar Andrejevic + */ + +#ifndef _VGA_H_ +#define _VGA_H_ + +/* INCLUDES *******************************************************************/ + +#include "ntvdm.h" + +/* DEFINES ********************************************************************/ + +/* Register I/O ports */ +#define VGA_AC_INDEX 0x3C0 +#define VGA_AC_WRITE 0x3C0 +#define VGA_AC_READ 0x3C1 +#define VGA_SEQ_INDEX 0x3C4 +#define VGA_SEQ_DATA 0x3C5 +#define VGA_DAC_READ_INDEX 0x3C7 +#define VGA_DAC_WRITE_INDEX 0x3C8 +#define VGA_DAC_DATA 0x3C9 +#define VGA_MISC_READ 0x3CC +#define VGA_MISC_WRITE 0x3C2 +#define VGA_CRTC_INDEX 0x3D4 +#define VGA_CRTC_DATA 0x3D5 +#define VGA_GC_INDEX 0x3CE +#define VGA_GC_DATA 0x3CF +#define VGA_STAT_MONO 0x3BA +#define VGA_STAT_COLOR 0x3DA + +#define VGA_NUM_BANKS 4 +#define VGA_BANK_SIZE 0x10000 +#define VGA_PALETTE_SIZE 768 +#define VGA_BITMAP_INFO_SIZE (sizeof(BITMAPINFOHEADER) + 2 * (VGA_PALETTE_SIZE / 3)) + +/* Sequencer reset register bits */ +#define VGA_SEQ_RESET_AR (1 << 0) +#define VGA_SEQ_RESET_SR (1 << 1) + +/* Sequencer clock register bits */ +#define VGA_SEQ_CLOCK_98DM (1 << 0) +#define VGA_SEQ_CLOCK_SLR (1 << 2) +#define VGA_SEQ_CLOCK_DCR (1 << 3) +#define VGA_SEQ_CLOCK_S4 (1 << 4) +#define VGA_SEQ_CLOCK_SD (1 << 5) + +/* Sequencer memory register bits */ +#define VGA_SEQ_MEM_EXT (1 << 1) +#define VGA_SEQ_MEM_OE (1 << 2) +#define VGA_SEQ_MEM_C4 (1 << 3) + +/* Graphics controller mode register bits */ +#define VGA_GC_MODE_READ (1 << 3) +#define VGA_GC_MODE_OE (1 << 4) +#define VGA_GC_MODE_SHIFTREG (1 << 5) +#define VGA_GC_MODE_SHIFT256 (1 << 6) + +/* Graphics controller miscellaneous register bits */ +#define VGA_GC_MISC_NOALPHA (1 << 0) +#define VGA_GC_MISC_OE (1 << 1) + +/* CRTC overflow register bits */ +#define VGA_CRTC_OVERFLOW_VT8 (1 << 0) +#define VGA_CRTC_OVERFLOW_VDE8 (1 << 1) +#define VGA_CRTC_OVERFLOW_VRS8 (1 << 2) +#define VGA_CRTC_OVERFLOW_SVB8 (1 << 3) +#define VGA_CRTC_OVERFLOW_LC8 (1 << 4) +#define VGA_CRTC_OVERFLOW_VT9 (1 << 5) +#define VGA_CRTC_OVERFLOW_VDE9 (1 << 6) +#define VGA_CRTC_OVERFLOW_VRS9 (1 << 7) + +/* CRTC underline register bits */ +#define VGA_CRTC_UNDERLINE_DWORD (1 << 6) + +/* CRTC mode control register bits */ +#define VGA_CRTC_MODE_CONTROL_WRAP (1 << 5) +#define VGA_CRTC_MODE_CONTROL_BYTE (1 << 6) +#define VGA_CRTC_MODE_CONTROL_SYNC (1 << 7) + +/* AC control register bits */ +#define VGA_AC_CONTROL_ATGE (1 << 0) +#define VGA_AC_CONTROL_MONO (1 << 1) +#define VGA_AC_CONTROL_LGE (1 << 2) +#define VGA_AC_CONTROL_BLINK (1 << 3) +#define VGA_AC_CONTROL_PPM (1 << 5) +#define VGA_AC_CONTROL_8BIT (1 << 6) +#define VGA_AC_CONTROL_P54S (1 << 7) + +/* Miscellaneous register bits */ +#define VGA_MISC_COLOR (1 << 0) +#define VGA_MISC_RAM_ENABLED (1 << 1) +#define VGA_MISC_OE_INVERT (1 << 5) +#define VGA_MISC_HSYNCP (1 << 6) +#define VGA_MISC_VSYNCP (1 << 7) + +/* Status register flags */ +#define VGA_STAT_DD (1 << 0) +#define VGA_STAT_VRETRACE (1 << 3) + +enum +{ + VGA_SEQ_RESET_REG, + VGA_SEQ_CLOCK_REG, + VGA_SEQ_MASK_REG, + VGA_SEQ_CHAR_REG, + VGA_SEQ_MEM_REG, + VGA_SEQ_MAX_REG +}; + +enum +{ + VGA_GC_RESET_REG, + VGA_GC_ENABLE_RESET_REG, + VGA_GC_COLOR_COMPARE_REG, + VGA_GC_ROTATE_REG, + VGA_GC_READ_MAP_SEL_REG, + VGA_GC_MODE_REG, + VGA_GC_MISC_REG, + VGA_GC_COLOR_IGNORE_REG, + VGA_GC_BITMASK_REG, + VGA_GC_MAX_REG +}; + +enum +{ + VGA_CRTC_HORZ_TOTAL_REG, + VGA_CRTC_END_HORZ_DISP_REG, + VGA_CRTC_START_HORZ_BLANKING_REG, + VGA_CRTC_END_HORZ_BLANKING_REG, + VGA_CRTC_START_HORZ_RETRACE_REG, + VGA_CRTC_END_HORZ_RETRACE_REG, + VGA_CRTC_VERT_TOTAL_REG, + VGA_CRTC_OVERFLOW_REG, + VGA_CRTC_PRESET_ROW_SCAN_REG, + VGA_CRTC_MAX_SCAN_LINE_REG, + VGA_CRTC_CURSOR_START_REG, + VGA_CRTC_CURSOR_END_REG, + VGA_CRTC_START_ADDR_HIGH_REG, + VGA_CRTC_START_ADDR_LOW_REG, + VGA_CRTC_CURSOR_LOC_HIGH_REG, + VGA_CRTC_CURSOR_LOC_LOW_REG, + VGA_CRTC_VERT_RETRACE_START_REG, + VGA_CRTC_VERT_RETRACE_END_REG, + VGA_CRTC_VERT_DISP_END_REG, + VGA_CRTC_OFFSET_REG, + VGA_CRTC_UNDERLINE_REG, + VGA_CRTC_START_VERT_BLANKING_REG, + VGA_CRTC_END_VERT_BLANKING, + VGA_CRTC_MODE_CONTROL_REG, + VGA_CRTC_LINE_COMPARE_REG, + VGA_CRTC_MAX_REG +}; + +enum +{ + VGA_AC_PAL_0_REG, + VGA_AC_PAL_1_REG, + VGA_AC_PAL_2_REG, + VGA_AC_PAL_3_REG, + VGA_AC_PAL_4_REG, + VGA_AC_PAL_5_REG, + VGA_AC_PAL_6_REG, + VGA_AC_PAL_7_REG, + VGA_AC_PAL_8_REG, + VGA_AC_PAL_9_REG, + VGA_AC_PAL_A_REG, + VGA_AC_PAL_B_REG, + VGA_AC_PAL_C_REG, + VGA_AC_PAL_D_REG, + VGA_AC_PAL_E_REG, + VGA_AC_PAL_F_REG, + VGA_AC_CONTROL_REG, + VGA_AC_OVERSCAN_REG, + VGA_AC_COLOR_PLANE_REG, + VGA_AC_HORZ_PANNING_REG, + VGA_AC_COLOR_SEL_REG, + VGA_AC_MAX_REG +}; + +/* FUNCTIONS ******************************************************************/ + +DWORD VgaGetVideoBaseAddress(VOID); +DWORD VgaGetVideoLimitAddress(VOID); +COORD VgaGetDisplayResolution(VOID); +VOID VgaRefreshDisplay(VOID); +VOID VgaHorizontalRetrace(VOID); +VOID VgaReadMemory(DWORD Address, LPBYTE Buffer, DWORD Size); +VOID VgaWriteMemory(DWORD Address, LPBYTE Buffer, DWORD Size); +BYTE VgaReadPort(WORD Port); +VOID VgaWritePort(WORD Port, BYTE Data); +VOID VgaInitialize(HANDLE TextHandle); + +#endif + +/* EOF */ Index: subsystems/ntvdm/vga.h =================================================================== --- subsystems/ntvdm/vga.h (révision 59666) +++ subsystems/ntvdm/vga.h (copie de travail) Modification de propriétés sur subsystems/ntvdm/vga.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property