Repository: WindowsNT/asm Branch: master Commit: dea912bccbda Files: 162 Total size: 1.1 MB Directory structure: gitextract_9e9nie88/ ├── .gitattributes ├── .gitignore ├── .gitmodules ├── Readme.md ├── a.img ├── a20.asm ├── acpi16.asm ├── acpi32.asm ├── acpi64.asm ├── asm.sln ├── asm.vcxproj ├── asm.vcxproj.filters ├── asmtest.vbox ├── asmtest.vbox-prev ├── bochsrc.bxrc ├── build.bat ├── bx_enh_dbg.ini ├── code16.asm ├── code32.asm ├── code64.asm ├── config.asm ├── data16.asm ├── data32.asm ├── data64.asm ├── debuggee.asm ├── directlong.asm ├── dis/ │ ├── Makefile.am │ ├── Makefile.in │ ├── d.lb1 │ ├── d.lib │ ├── d.mk │ ├── d.mk1 │ ├── d.tgt │ ├── d.wpj │ ├── decode.c │ ├── decode.h │ ├── dism.lk1 │ ├── dism.mk │ ├── dism.mk1 │ ├── dism.sym │ ├── dism.tgt │ ├── dism.txt │ ├── dism.wpj │ ├── extern.h │ ├── itab.c │ ├── itab.h │ ├── main.c │ ├── stderr.txt │ ├── stdout.txt │ ├── syn-att.c │ ├── syn-intel.c │ ├── syn.c │ ├── syn.h │ ├── types.h │ ├── udint.h │ ├── udis86.c │ └── udis86.err ├── dmmic.asm ├── dos32.asm ├── dpmi/ │ ├── DPMI.LOD │ ├── DPMI.PRO │ ├── DPMIONE.PRO │ ├── LICENSE.TXT │ ├── README.TXT │ ├── UNCOMMIT.TXT │ └── VERSION.TXT ├── dpmic.asm ├── entry.asm ├── gdt.asm ├── guest16.asm ├── guest32.asm ├── guest64.asm ├── himem16.asm ├── idt.asm ├── int16.asm ├── int32.asm ├── int64.asm ├── iso.ps1 ├── leheader.asm ├── lemain.asm ├── mdebug.asm ├── mdebugcore.asm ├── mutex16.asm ├── mutex32.asm ├── mutex64.asm ├── opcodes.asm ├── page16.asm ├── page32.asm ├── qlink/ │ ├── QLINK.CFG │ ├── QLINK.HTM │ ├── QLINK.TXT │ ├── W95DPMI.386 │ └── WINDPMI.386 ├── reqdmmi.asm ├── runx.bat ├── stack16.asm ├── stack32.asm ├── stack64.asm ├── startbochs.bat ├── startvbox.bat ├── startvmware.bat ├── struct.asm ├── swat/ │ ├── 386SWAT │ ├── 386SWAT.DOC │ ├── 386SWAT.GRM │ ├── 386SWAT.LOD │ ├── FILELIST.TXT │ ├── KEYBIN.COM │ ├── KEYBIN.HTM │ ├── KEYBIN.TXT │ ├── SWAT.HTM │ ├── SWATAFLT.HTM │ ├── SWATBMRK.HTM │ ├── SWATCMD.HTM │ ├── SWATCMR.HTM │ ├── SWATDEF.HTM │ ├── SWATDISP.HTM │ ├── SWATDOC.HTM │ ├── SWATGRM.HTM │ ├── SWATINST.HTM │ ├── SWATINV.HTM │ ├── SWATMAX.HTM │ ├── SWATMON.HTM │ ├── SWATNDP.HTM │ ├── SWATPRO.HTM │ ├── SWATREM.HTM │ ├── SWATRMV.HTM │ ├── SWATRUN.COM │ ├── SWATSCR.HTM │ ├── SWATSYM.DOC │ ├── SWATSYM.HTM │ ├── SWATVER.HTM │ ├── SWATVXD.DOC │ ├── SWATVXD.HTM │ ├── SWATWDBG.HTM │ ├── SWATWISH.HTM │ ├── SWATWKD.HTM │ ├── VCPIDBG.DOC │ ├── VCPIDBG.HTM │ ├── WHATSNEW │ ├── WINKDBG.DOC │ └── WINKDBG.HTM ├── switcher/ │ ├── main.cpp │ ├── switcher.lk1 │ ├── switcher.mk │ ├── switcher.mk1 │ ├── switcher.sym │ ├── switcher.tgt │ └── switcher.wpj ├── thread16.asm ├── thread32.asm ├── thread64.asm ├── unreal.asm ├── vbox.vbox-prev ├── vdebug.asm ├── vdebug64.asm ├── vdisplay.asm ├── vm.nvram ├── vm.vmsd ├── vm.vmx ├── vm.vmxf └── vmxhost64.asm ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitattributes ================================================ ############################################################################### # Set default behavior to automatically normalize line endings. ############################################################################### * text=auto ############################################################################### # Set default behavior for command prompt diff. # # This is need for earlier builds of msysgit that does not have it on by # default for csharp files. # Note: This is only used by command line ############################################################################### #*.cs diff=csharp ############################################################################### # Set the merge driver for project and solution files # # Merging from the command prompt will add diff markers to the files if there # are conflicts (Merging from VS is not affected by the settings below, in VS # the diff markers are never inserted). Diff markers may cause the following # file extensions to fail to load in VS. An alternative would be to treat # these files as binary and thus will always conflict and require user # intervention with every merge. To do so, just uncomment the entries below ############################################################################### #*.sln merge=binary #*.csproj merge=binary #*.vbproj merge=binary #*.vcxproj merge=binary #*.vcproj merge=binary #*.dbproj merge=binary #*.fsproj merge=binary #*.lsproj merge=binary #*.wixproj merge=binary #*.modelproj merge=binary #*.sqlproj merge=binary #*.wwaproj merge=binary ############################################################################### # behavior for image files # # image files are treated as binary by default. ############################################################################### #*.jpg binary #*.png binary #*.gif binary ############################################################################### # diff behavior for common document formats # # Convert binary document formats to text before diffing them. This feature # is only available from the command line. Turn it on by uncommenting the # entries below. ############################################################################### #*.doc diff=astextplain #*.DOC diff=astextplain #*.docx diff=astextplain #*.DOCX diff=astextplain #*.dot diff=astextplain #*.DOT diff=astextplain #*.pdf diff=astextplain #*.PDF diff=astextplain #*.rtf diff=astextplain #*.RTF diff=astextplain ================================================ FILE: .gitignore ================================================ ## Ignore Visual Studio temporary files, build results, and ## files generated by popular Visual Studio add-ons. # User-specific files *.suo *.user *.userosscache *.sln.docstates *.iso # User-specific files (MonoDevelop/Xamarin Studio) *.userprefs # Build results [Dd]ebug/ [Dd]ebugPublic/ [Rr]elease/ [Rr]eleases/ x64/ x86/ bld/ [Bb]in/ [Oo]bj/ [Ll]og/ # Visual Studio 2015 cache/options directory .vs/ # Uncomment if you have tasks that create the project's static files in wwwroot #wwwroot/ # MSTest test Results [Tt]est[Rr]esult*/ [Bb]uild[Ll]og.* # NUNIT *.VisualState.xml TestResult.xml # Build Results of an ATL Project [Dd]ebugPS/ [Rr]eleasePS/ dlldata.c # DNX project.lock.json project.fragment.lock.json artifacts/ *_i.c *_p.c *_i.h *.ilk *.meta *.obj *.pch *.pdb *.pgc *.pgd *.rsp *.sbr *.tlb *.tli *.tlh *.tmp *.tmp_proj *.log *.vspscc *.vssscc .builds *.pidb *.svclog *.scc # Chutzpah Test files _Chutzpah* # Visual C++ cache files ipch/ *.aps *.ncb *.opendb *.opensdf *.sdf *.cachefile *.VC.db *.VC.VC.opendb # Visual Studio profiler *.psess *.vsp *.vspx *.sap # TFS 2012 Local Workspace $tf/ # Guidance Automation Toolkit *.gpState # ReSharper is a .NET coding add-in _ReSharper*/ *.[Rr]e[Ss]harper *.DotSettings.user # JustCode is a .NET coding add-in .JustCode # TeamCity is a build add-in _TeamCity* # DotCover is a Code Coverage Tool *.dotCover # NCrunch _NCrunch_* .*crunch*.local.xml nCrunchTemp_* # MightyMoose *.mm.* AutoTest.Net/ # Web workbench (sass) .sass-cache/ # Installshield output folder [Ee]xpress/ # DocProject is a documentation generator add-in DocProject/buildhelp/ DocProject/Help/*.HxT DocProject/Help/*.HxC DocProject/Help/*.hhc DocProject/Help/*.hhk DocProject/Help/*.hhp DocProject/Help/Html2 DocProject/Help/html # Click-Once directory publish/ # Publish Web Output *.[Pp]ublish.xml *.azurePubxml # TODO: Comment the next line if you want to checkin your web deploy settings # but database connection strings (with potential passwords) will be unencrypted #*.pubxml *.publishproj # Microsoft Azure Web App publish settings. Comment the next line if you want to # checkin your Azure Web App publish settings, but sensitive information contained # in these scripts will be unencrypted PublishScripts/ # NuGet Packages *.nupkg # The packages folder can be ignored because of Package Restore **/packages/* # except build/, which is used as an MSBuild target. !**/packages/build/ # Uncomment if necessary however generally it will be regenerated when needed #!**/packages/repositories.config # NuGet v3's project.json files produces more ignoreable files *.nuget.props *.nuget.targets # Microsoft Azure Build Output csx/ *.build.csdef # Microsoft Azure Emulator ecf/ rcf/ # Windows Store app package directories and files AppPackages/ BundleArtifacts/ Package.StoreAssociation.xml _pkginfo.txt # Visual Studio cache files # files ending in .cache can be ignored *.[Cc]ache # but keep track of directories ending in .cache !*.[Cc]ache/ # Others ClientBin/ ~$* *~ *.dbmdl *.dbproj.schemaview *.jfm *.pfx *.publishsettings node_modules/ orleans.codegen.cs # Since there are multiple workflows, uncomment next line to ignore bower_components # (https://github.com/github/gitignore/pull/1529#issuecomment-104372622) #bower_components/ # RIA/Silverlight projects Generated_Code/ # Backup & report files from converting an old project file # to a newer Visual Studio version. Backup files are not needed, # because we have git ;-) _UpgradeReport_Files/ Backup*/ UpgradeLog*.XML UpgradeLog*.htm # SQL Server files *.mdf *.ldf # Business Intelligence projects *.rdl.data *.bim.layout *.bim_*.settings # Microsoft Fakes FakesAssemblies/ # GhostDoc plugin setting file *.GhostDoc.xml # Node.js Tools for Visual Studio .ntvs_analysis.dat # Visual Studio 6 build log *.plg # Visual Studio 6 workspace options file *.opt # Visual Studio LightSwitch build output **/*.HTMLClient/GeneratedArtifacts **/*.DesktopClient/GeneratedArtifacts **/*.DesktopClient/ModelManifest.xml **/*.Server/GeneratedArtifacts **/*.Server/ModelManifest.xml _Pvt_Extensions # Paket dependency manager .paket/paket.exe paket-files/ # FAKE - F# Make .fake/ # JetBrains Rider .idea/ *.sln.iml # CodeRush .cr/ # Python Tools for Visual Studio (PTVS) __pycache__/ *.pyc /Dos622.img /Logs /CD /vm.vmx.lck/M43884.lck ================================================ FILE: .gitmodules ================================================ [submodule "Int50"] path = Int50 url = https://github.com/WindowsNT/Int50 ================================================ FILE: Readme.md ================================================ # Assembly Manual Welcome to my assembly tutorials. # Update Cleaner DMMI interface for you: https://github.com/WindowsNT/Int50 Articles: * Full article (all in one): https://www.codeproject.com/Articles/1273844/The-Intel-Assembly-Manual Older Articles: * Real/Protected/Long mode : https://www.codeproject.com/Articles/45788/The-Real-Protected-Long-mode-assembly-tutorial-for * Virtualization: https://www.codeproject.com/Articles/215458/Virtualization-for-System-Programmers * Multicore DOS: https://www.codeproject.com/Articles/889245/Deep-inside-CPU-Raw-multicore-programming * DMMI: https://www.codeproject.com/Articles/894522/Teh-Low-Level-M-ss-DOS-Multicore-Mode-Interface At the moment, the first part is implemented (Real/Protected/Long mode), the Protected Mode Virtualization (working in Bochs), the third part (test SIPI multicore, working on Bochs and VMWare) and the fourth part finished (DMMI). More to follow soon. ## Instructions 1. Edit build.bat to specify flat assembler (FASM) path. 2. Edit startbochs.bat, startvmware.bat and startvbox.bat to locate the executables of these applications. Bochs is included in the repository. Build and run, it will automatically start bochs/vmware/virtualbox with the included FreeDOS image. It will create a CD-ROM as D: and you can run it from d:\entry.exe, by default it is automatically run (autoexec.bat) ## 3rd Party Apps included 1. DOS32A - http://dos32a.narechk.net/index_en.html 2. 386SWAT - http://www.sudleyplace.com/swat/ 3. UDIS86 - http://udis86.sourceforge.net/ , including an open watcom C project that is used by VDEBUG and MDEBUG 4. DPMIONE - http://www.sudleyplace.com/dpmione/ 5. QLINK - http://www.sudleyplace.com/qlink/ ## Tests performed 1. Real mode test 2. Protected mode test with or without paging 3. Long mode test with paging and PAE 4. Real mode thread calling 5. Real mode thread called from protected mode 6. Real mode thread called from long mode 7. Protected mode thread called from real mode 8. Long mode thread called from real mode 9. VMX is there 10. Spawn a Virtual Machine in Unrestricted guest mode. Paged Protected Mode guest also there. 11. Entry /r which installs as TSR the DMMI services 12. DPMI startup example taken from https://board.flatassembler.net/topic.php?t=7122 13. DMMIC app runs which demonstrates DMMI, launching real mode, protected mode, long mode and virtualized protected mode threads 14. DOS32A loads a linear executable created with FASM 15. VDEBUG Virtualized Debugger (Not fully implemented yet) 15. MDEBUG Multicore Debugger (Not fully implemented yet) 16. SWITCHER multitasker (Not fully implemented yet) ## DMMI I've called it DOS Multicore Mode Interface. It is a driver which helps you develop 32 and 64 bit multicore applications for DOS, using int 0xF0. This interrupt is accessible from both real, protected and long mode. Put the function number to AH. To check for existence, check the vector for INT 0xF0. It should not be pointing to 0 or to an IRET, ES:BX+2 should point to a dword 'dmmi'. Int 0xF0 provides the following functions to all modes (real, protected, long) 1. AH = 0, verify existence. Return values, AX = 0xFACE if the driver exists, DL = total CPUs, DH = virtualization support (0 none, 1 PM only, 2 Unrestricted guest). This function is accessible from real, protected and long mode. 2. AH = 1, begin thread. BL is the CPU index (1 to max-1). The function creates a thread, depending on AL: * 0, begin (un)real mode thread. ES:DX = new thread seg:ofs. The thread is run with FS capable of unreal mode addressing, must use RETF to return. * 1, begin 32 bit protected mode thread. EDX is the linear address of the thread. The thread must return with RETF. * 2, begin 64 bit long mode thread. EDX holds the linear address of the code to start in 64-bit long mode. The thread must terminate with RET. * 3, begin virtualized thread. BH contains the virtualization mode (1 for unrestricted guest real mode thread, and 2 for protected mode), and EDX the virtualized linear stack (or in seg:ofs format if unrestricted guest). The thread must return with RETF or VMCALL. 3. AH = 5, mutex functions. This function is accessible from all modes. * AL = 0 => initialize mutex to ES:DI (real) , EDI linear (protected), RDI linear (long). * AL = 1 => Lock mutex * AL = 2 => Unlock mutex * AL = 3 => Wait for mutex 4. AH = 4, execute real mode interrupt. This function is accessible from all modes. AL is the interrupt number, BP holds the AX value and BX,CX,DX,SI,DI are passed to the interrupt. DS and ES are loaded from the high 16 bits of ESI and EDI. 4. AH = 9, Switch To Mode. * From real mode: AL = 0 (enter unreal), AL = 2 (enter long, ECX = linear address to start. Code must set IDT found at [rax] on entry) * From long mode: AL = 0, go back to real, ECX = linear. Now, if you have more than one CPU, your DOS applications/games can now directly access all 2^64 of memory and all your CPUs, while still being able to call DOS directly. In order to avoid calling int 0xF0 directly from assembly and to make the driver compatible with higher level languages, an INT 0x21 redirection handler is installed. If you call INT 0x21 from the main thread, INT 0x21 is executed directly. If you call INT 0x21 from protected or long mode thread, then INT 0xF0 function AX = 0x0421 is executed automatically. ## Virtualization Debugger Debugging protected or long mode under DOS is next to impossible. I am now trying to create a simple DEBUG enhancement, called VDEBUG, which should be able to debug any DOS app in virtualization. Compile it with config.asm VDEBUG = 1. This app does the following: * Load the debugee (int 0x21, function 0x4B01) * Enter long mode (int 0xf0, function 0x0902) * Prepare virtualization structures (int 0xf0, function 0x0801) * Launch an unrestricted guest VM * In the VM, set the trap flag so each opcode causes a VMEXIT. * Jump to the entry point of the debugee * When target process calls int 0x21 function 0x4C to terminate, control returns to the command next to the int 0x21 function 0x4B01 call. Check there if under virtual machine. If so, do VMCALL to exit. * Go back to real mode and exit. * At the moment, the implemented functions are: * r - (registers) - shows Control, General, Segment regs, Dissassembly and bytes using UDIS86 * g - (go) - runs program * t - (trace) - traces commands * h - (help) - shows help * q - (quit) - quits ## Multicore Debugger Debugging protected or long mode under DOS is next to impossible (again). I am now trying to create a simple DEBUG enhancement, called MDEBUG, which should be able to debug any DOS app from another CPU core. Compile it with config.asm MDEBUG = 1. This app should perform the following: * Jump to another core * Load the debugee (int 0x21, function 0x4B01) * Set the trap flag * On exception, HLT the first processor then go to the MDEBUG processor * On resume, send resume IPI to the first processor This project is not yet created, but I hope that it will be here soon! ## Switcher Switcher is a DMMI client that is able to do multitasking in DOS using multiple cores and virtualization. More to follow soon! ================================================ FILE: a20.asm ================================================ ; --------------------------------------- A20 line routines --------------------------------------- USE16 WaitKBC: mov cx,0ffffh A20L: in al,64h test al,2 loopnz A20L ret EnableA20: call WaitKBC mov al,0d1h out 64h,al call WaitKBC mov al,0dfh out 60h,al ret EnableA20f: call WaitKBC mov al,0d1h out 64h,al call WaitKBC mov al,0dfh out 60h,al retf DisableA20: call WaitKBC mov al,0d1h out 64h,al call WaitKBC mov al,0ddh out 60h,al ret CheckA20: PUSH ax PUSH ds PUSH es XOR ax,ax MOV ds,ax NOT ax MOV es,ax MOV ah,[ds:0] CMP ah,[es:10h] JNZ A20_ON CLI INC ah MOV [ds:0],ah CMP [es:10h],ah PUSHF DEC ah MOV [ds:0],ah STI POPF JNZ A20_ON CLC POP es POP ds POP ax RET A20_ON: STC POP es POP ds POP ax RET ================================================ FILE: acpi16.asm ================================================ ; --------------------------------------- 16 bit APIC functions --------------------------------------- USE16 include 'mutex16.asm' ; Returns APIC in EBX ; implemented as FAR to allow calling from elsewhere GetMyApic16f: push eax push ecx push edx mov eax,1 cpuid and ebx,0xff000000 shr ebx,24 pop edx pop ecx pop eax retf ;------------------------------------------------------------------------------------------- ; Function ChecksumValid : Check the sum. EDI physical addr, ECX count ;------------------------------------------------------------------------------------------- ChecksumValid: PUSH ECX PUSH EDI XOR EAX,EAX .St: ADD EAX,[FS:EDI] INC EDI DEC ECX JECXZ .End JMP .St .End: TEST EAX,0xFF JNZ .F MOV EAX,1 .F: POP EDI POP ECX RETF ;------------------------------------------------------------------------------------------- ; Function FillACPI : Finds RDSP, and then RDST or XDST ;------------------------------------------------------------------------------------------- FillACPI: pushadxeax push es mov es,[fs:040eh] xor edi,edi mov di,[es:0] pop es mov edi, 0x000E0000 .s: cmp edi, 0x000FFFFF ; jge .noACPI ; Fail. mov eax,[fs:edi] add edi,4 mov edx,[fs:edi] add edi,4 cmp eax,0x20445352 jnz .s cmp edx,0x20525450 jnz .s jmp .found .noACPI: popadxeax mov EAX,0xFFFFFFFF RETF .found: ; Found at EDI sub edi,8 mov esi,edi ; 36 bytes for ACPI 2 mov ecx,36 push cs call ChecksumValid cmp eax,1 jnz .noACPI2 mov eax,[fs:edi + 24] mov dword [ds:XsdtAddress],eax mov eax,[fs:edi + 28] mov dword [ds:XsdtAddress + 4],eax mov edi,dword [ds:XsdtAddress] mov eax,[fs:edi] cmp eax, 'XSDT' ; Valid? jnz .noACPI2 popadxeax RETF .noACPI2: mov edi,esi mov ecx,20 push cs call ChecksumValid cmp eax,1 jnz .noACPI mov eax,[fs:edi + 16] mov dword [ds:XsdtAddress],eax mov edi,dword [ds:XsdtAddress] mov eax,[fs:edi] cmp eax, 'RSDT' ; Valid? jnz .noACPI mov edi,dword [ds:XsdtAddress] mov dword [ds:XsdtAddress],0 mov dword [ds:RsdtAddress],edi popadxeax RETF ;------------------------------------------------------------------------------------------- ; Function FindACPITableX : Finds EAX Table, edi is rsdt/xsdt address and ecx is 4 or 8 ;------------------------------------------------------------------------------------------- FindACPITableX: cmp edi,0 jz .f ; len, must be more than 36 mov ebx,[fs:edi + 4] cmp ebx,36 jle .f sub ebx,36 xor edx,edx .loop: cmp edx,ebx jz .f mov esi,[fs:edi + 36 + edx] cmp eax,[fs:esi] jnz .c mov eax,esi RETF .c: add edx,ecx jmp .loop .f: mov eax,0ffffffffh RETF ;------------------------------------------------------------------------------------------- ; Function DumpMadt : Fills from EAX MADT ;------------------------------------------------------------------------------------------- DumpMadt: ; EAX pushad mov edi,eax mov [ds:numcpus],0 mov ecx,[fs:edi + 4] ; length mov eax,[fs:edi + 0x24] ; Local APIC mov [ds:LocalApic],eax add edi,0x2C sub ecx,0x2C .l1: xor ebx,ebx mov bl,[fs:edi + 1] ; length cmp bl,0 jz .end ; duh sub ecx,ebx mov al,[fs:edi] ; type cmp al,0 jnz .no0 ; This is a CPU! xor eax,eax mov al,[ds:numcpus] inc [ds:numcpus] mov edx,cpusstructize mul edx xor esi,esi mov si,cpus add esi,eax mov al,[fs:edi + 2]; ACPI id mov byte [ds:si],al mov al,[fs:edi + 3]; APIC id mov byte [ds:si + 4],al .no0: add edi,ebx jecxz .end jmp .l1 .end: popad RETF ;------------------------------------------------------------------------------------------- ; Function DumpAll ; edi = xsdt or rsdt ;------------------------------------------------------------------------------------------- DumpAll: mov ebp, 32 ; max count cmp edi,0 jz .f ; len, must be more than 36 mov ebx,[fs:edi + 4] cmp ebx,36 jle .f sub ebx,36 xor edx,edx .loop: cmp edx,ebx jz .f mov esi,[fs:edi + 36 + edx] mov eax,[fs:esi] ; eax to show push edx mov edx,eax mov ah,2 int 21h shr edx,8 mov ah,2 int 21h shr edx,8 mov ah,2 int 21h shr edx,8 mov ah,2 int 21h mov dl,' '; mov ah,2 int 21h pop edx add edx,ecx dec ebp cmp ebp, 0 jz .f jmp .loop .f: RETF ;------------------------------------------------------------------------------------------- ; Function SendSIPIf : Sends SIPI. EBX = CPU Index, EAX = linear ;------------------------------------------------------------------------------------------- SendSIPIf: PUSHAD PUSH DS mov cx,DATA16 mov ds,cx XOR ECX,ECX ; Spurious MOV EDI,[DS:LocalApic] ADD EDI,0x0F0 MOV EDX,[FS:EDI] OR EDX,0x1FF MOV [FS:EDI],EDX ; Vector .L1: MOV ECX,EAX TEST EAX,0xFFF JZ .L2 INC EAX JMP .L1 .L2: MOV ESI,EAX SHR ESI,12 ; Init MOV ECX,0x04500 OR ECX,ESI push cs call SendIPI16 ; Delay 10 ms = 0,01 s = (100 Hz) ; 1193182/100 ; sleep16 11931 MOV AH,86H MOV CX,0 MOV DX,10*1000 ;10 ms INT 15H ; SIPI 1 MOV ECX,0x05600 OR ECX,ESI push cs call SendIPI16 ; Delay 200 us = 0,2 ms = 0,0002 s = (5000 Hz) ; 1193182/5000 ; sleep16 238 MOV AH,86H MOV CX,0 MOV DX,200 ; 200us INT 15H ; SIPI 2 MOV ECX,0x05600 OR ECX,ESI push cs call SendIPI16 POP DS POPAD RETF ;------------------------------------------------------------------------------------------- ; Function SendIPI16 : Sends IPI. EBX = CPU Index, ECX = IPI ;------------------------------------------------------------------------------------------- SendIPI16: ; EBX = CPU INDEX, ECX = IPI PUSHAD ; Lock Mutex mov ax,mut_ipi push cs call qwaitlock16 ; Write it to 0x310 ; EBX is CPU INDEX ; MAKE IT APIC ID xor eax,eax mov ax,cpusstructize mul bx add ax,cpus mov di,ax add di,4 mov bl,[ds:di] MOV EDI,[DS:LocalApic] ADD EDI,0x310 MOV EDX,[FS:EDI] AND EDX,0xFFFFFF XOR EAX,EAX MOV AL,BL SHL EAX,24 OR EDX,EAX MOV [FS:EDI],EDX ; Write it to 0x300 MOV EDI,[DS:LocalApic] ADD EDI,0x300 MOV [FS:EDI],ECX ; Verify it got delivered .Verify: PAUSE MOV EAX,[FS:EDI]; SHR EAX,12 TEST EAX,1 JNZ .Verify ; Write it to 0xB0 (EOI) ; MOV EDI,[DS:LocalApic] ; ADD EDI,0xB0 ; MOV dword [FS:EDI],0 ; Release Mutex qunlock16 mut_ipi POPAD RETF ================================================ FILE: acpi32.asm ================================================ ; --------------------------------------- 32 bit APIC functions --------------------------------------- USE32 include 'mutex32.asm' ;------------------------------------------------------------------------------------------- ; Function SendSIPI32f : Sends SIPI. EBX = CPU Index, EAX = linear ;------------------------------------------------------------------------------------------- SendSIPI32f: PUSHAD PUSH DS PUSH ES mov cx,page32_idx ; This is a base-0 segment, so "linear" for EDI positioning mov es,cx mov cx,data16_idx mov ds,cx XOR ECX,ECX ; Spurious MOV EDI,[DS:LocalApic] ADD EDI,0x0F0 MOV EDX,[ES:EDI] OR EDX,0x1FF MOV [ES:EDI],EDX ; Vector .L1: MOV ECX,EAX TEST EAX,0xFFF JZ .L2 INC EAX JMP .L1 .L2: MOV ESI,EAX SHR ESI,12 ; Init MOV ECX,0x04500 OR ECX,ESI push cs call SendIPI32 ; SIPI 1 MOV ECX,0x05600 OR ECX,ESI push cs call SendIPI32 ; SIPI 2 MOV ECX,0x05600 OR ECX,ESI push cs call SendIPI32 POP ES POP DS POPAD RETF ;------------------------------------------------------------------------------------------- ; Function SendIPI32 : Sends IPI. EBX = CPU Index, ECX = IPI ;------------------------------------------------------------------------------------------- SendIPI32: ; EBX = CPU INDEX, ECX = IPI PUSHAD ; Lock Mutex mov ax,mut_ipi push cs call qwaitlock32 ; Write it to 0x310 ; EBX is CPU INDEX ; MAKE IT APIC ID xor eax,eax mov ax,cpusstructize mul bx add ax,cpus mov di,ax add di,4 mov bl,[ds:di] MOV EDI,[DS:LocalApic] ADD EDI,0x310 MOV EDX,[ES:EDI] AND EDX,0xFFFFFF XOR EAX,EAX MOV AL,BL SHL EAX,24 OR EDX,EAX MOV [ES:EDI],EDX ; Write it to 0x300 MOV EDI,[DS:LocalApic] ADD EDI,0x300 MOV [ES:EDI],ECX ; Verify it got delivered .Verify: PAUSE MOV EAX,[ES:EDI]; SHR EAX,12 TEST EAX,1 JNZ .Verify ; Write it to 0xB0 (EOI) MOV EDI,[DS:LocalApic] ADD EDI,0xB0 MOV dword [ES:EDI],0 ; Release Mutex qunlock32 mut_ipi POPAD RETF ================================================ FILE: acpi64.asm ================================================ ; --------------------------------------- 64 bit APIC functions --------------------------------------- USE64 include 'mutex64.asm' ;------------------------------------------------------------------------------------------- ; Function SendSIPI64 : Sends SIPI. RBX = CPU Index, EAX = linear ;------------------------------------------------------------------------------------------- SendSIPI64: PUSH RAX PUSH RBX PUSH RCX PUSH RDX PUSH RSI PUSH RDI linear edi,LocalApic mov ecx,[edi] ; Spurious MOV EDI,[RCX] ADD EDI,0x0F0 MOV EDX,[EDI] OR EDX,0x1FF MOV [EDI],EDX ; Vector .L1: MOV ECX,EAX TEST EAX,0xFFF JZ .L2 INC EAX JMP .L1 .L2: MOV ESI,EAX SHR ESI,12 ; Init MOV ECX,0x04500 OR ECX,ESI call SendIPI64 ; SIPI 1 MOV ECX,0x05600 OR ECX,ESI call SendIPI64 ; SIPI 2 MOV ECX,0x05600 OR ECX,ESI call SendIPI64 POP RDI POP RSI POP RDX POP RCX POP RBX POP RAX RET ;------------------------------------------------------------------------------------------- ; Function SendIPI64 : Sends IPI. EBX = CPU Index, ECX = IPI ;------------------------------------------------------------------------------------------- SendIPI64: ; EBX = CPU INDEX, ECX = IPI PUSH RAX PUSH RBX PUSH RCX PUSH RDX PUSH RSI PUSH RDI ; Lock Mutex xor rax,rax mov ax,mut_ipi call qwaitlock64 ; Write it to 0x310 ; EBX is CPU INDEX ; MAKE IT APIC ID xor eax,eax mov ax,cpusstructize mul bx add ax,cpus xor rdi,rdi mov di,ax add di,4 linear esi,edi mov bl,[esi] linear edi,LocalApic mov edi,[edi] ADD EDI,0x310 MOV EDX,[EDI] AND EDX,0xFFFFFF XOR EAX,EAX MOV AL,BL SHL EAX,24 OR EDX,EAX MOV [EDI],EDX ; Write it to 0x300 linear edi,LocalApic mov edi,[edi] ADD EDI,0x300 MOV [EDI],ECX ; Verify it got delivered .Verify: PAUSE MOV EAX,[EDI]; SHR EAX,12 TEST EAX,1 JNZ .Verify ; Write it to 0xB0 (EOI) ; MOV EDI,[ecx] ; ADD EDI,0xB0 ; MOV dword [EDI],0 ; Release Mutex qunlock64 mut_ipi POP RDI POP RSI POP RDX POP RCX POP RBX POP RAX RET ================================================ FILE: asm.sln ================================================  Microsoft Visual Studio Solution File, Format Version 12.00 # Visual Studio 15 VisualStudioVersion = 15.0.28307.168 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "asm", "asm.vcxproj", "{68FEA001-C33A-4EBC-A70F-9788736975B5}" EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Bochs|DOS = Bochs|DOS VirtualBox|DOS = VirtualBox|DOS VMWare|DOS = VMWare|DOS EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {68FEA001-C33A-4EBC-A70F-9788736975B5}.Bochs|DOS.ActiveCfg = DOS|x64 {68FEA001-C33A-4EBC-A70F-9788736975B5}.Bochs|DOS.Build.0 = DOS|x64 {68FEA001-C33A-4EBC-A70F-9788736975B5}.VirtualBox|DOS.ActiveCfg = VirtualBox|x64 {68FEA001-C33A-4EBC-A70F-9788736975B5}.VirtualBox|DOS.Build.0 = VirtualBox|x64 {68FEA001-C33A-4EBC-A70F-9788736975B5}.VMWare|DOS.ActiveCfg = VMWare|x64 {68FEA001-C33A-4EBC-A70F-9788736975B5}.VMWare|DOS.Build.0 = VMWare|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution SolutionGuid = {FA27BBE5-85B1-418A-9938-437642B9D60B} EndGlobalSection EndGlobal ================================================ FILE: asm.vcxproj ================================================ BochsNoDebug x64 DOS x64 VirtualBox x64 VMWare x64 15.0 {68FEA001-C33A-4EBC-A70F-9788736975B5} asm 10.0 Application false v143 true MultiByte Application false v143 true MultiByte Application false v143 true MultiByte Application false v143 true MultiByte Level3 MaxSpeed true true true true true true Level3 MaxSpeed true true true true true true Level3 MaxSpeed true true true true true true Level3 MaxSpeed true true true true true true Document build.bat build.bat build.bat build.bat entry.exe;dmmic.exe;le.exe;debuggee.exe;vdebug.exe;mdebug.exe entry.exe;dmmic.exe;le.exe;debuggee.exe;vdebug.exe;mdebug.exe entry.exe;dmmic.exe;le.exe;debuggee.exe;vdebug.exe;mdebug.exe entry.exe;dmmic.exe;le.exe;debuggee.exe;vdebug.exe;mdebug.exe false false false false true true true true *.asm *.asm *.asm *.asm Document Document false false false false CppCode ================================================ FILE: asm.vcxproj.filters ================================================  {f5fc6a1f-afcd-4e0e-999a-4740cb3500c2} {f2ee1441-75fc-48c0-baec-44f7ad5f153f} {05819406-8f59-4c3a-a88d-6638e01bd070} {4FC737F1-C7A5-4376-A066-2A32D752A2FF} cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx {1f5ef5e6-1cd9-452e-b6d1-e803a1a2e812} {3d1fb20d-d4c2-4578-9778-ec0c4531a433} {19c81409-b80e-4267-80bc-95d0f74ac19d} {0d5a1d9a-c2fb-4445-a6d7-4676170147c1} {7f2ca36e-0cd5-4db7-ae28-3f94f4eb6f98} {189d96b4-2842-4505-805a-815b3b66bbd4} {3d37bfd1-8ba1-4f5b-b5f5-5a30a1334465} 16 bit code 16 bit code 16 bit code 16 bit code 16 bit code Configuration Configuration Data Data Data Data Configuration Configuration Configuration 32 bit code 64 bit code Data Data Data 32 bit code Configuration Configuration Configuration Configuration 16 bit code 16 bit code 16 bit code 16 bit code Configuration 32 bit code 32 bit code 64 bit code 64 bit code 16 bit code 32 bit code 64 bit code 16 bit code 16 bit code 32 bit code 64 bit code 16 bit code DMMI Client 32 bit code 16 bit code 64 bit code 16 bit code 64 bit code DPMI Client DPMI Client 16 bit code VDebug VDebug Debuggee MDebug DMMI Client MDebug VDebug Configuration DPMI Client Switcher Switcher Switcher 16 bit code ================================================ FILE: asmtest.vbox ================================================ ================================================ FILE: asmtest.vbox-prev ================================================ ================================================ FILE: bochsrc.bxrc ================================================ # configuration file generated by Bochs plugin_ctrl: unmapped=1, biosdev=1, speaker=1, extfpuirq=1, parallel=1, serial=1, gameport=1 config_interface: win32config display_library: win32, options="gui_debug" memory: host=32, guest=32 romimage: file="g:\bochs2/BIOS-bochs-latest", address=0x0, options=none vgaromimage: file="g:\bochs2/VGABIOS-lgpl-latest" boot: floppy floppy_bootsig_check: disabled=0 floppya: type=1_44, 1_44="F:\TOOLS\ASM\full2\a.img", status=inserted, write_protected=0 # no floppyb ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14 ata0-master: type=none ata0-slave: type=cdrom, path="F:\TOOLS\ASM\full2\d.iso", status=inserted, model="Generic 1234", biosdetect=auto ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15 ata1-master: type=none ata1-slave: type=none ata2: enabled=0 ata3: enabled=0 optromimage1: file=none optromimage2: file=none optromimage3: file=none optromimage4: file=none optramimage1: file=none optramimage2: file=none optramimage3: file=none optramimage4: file=none pci: enabled=1, chipset=i440fx vga: extension=vbe, update_freq=5, realtime=1 cpu: count=2:2:2, ips=4000000, quantum=16, model=bx_generic, reset_on_triple_fault=1, cpuid_limit_winnt=0, ignore_bad_msrs=1, mwait_is_nop=0 cpuid: level=6, stepping=3, model=3, family=6, vendor_string="GenuineIntel", brand_string=" Intel(R) Pentium(R) 4 CPU " cpuid: mmx=1, apic=x2apic, simd=ssse3, sse4a=0, misaligned_sse=0, sep=1, movbe=0, adx=0 cpuid: aes=1, sha=0, xsave=0, xsaveopt=0, x86_64=1, 1g_pages=1, pcid=0, fsgsbase=0 cpuid: smep=0, smap=0, mwait=1, vmx=2 print_timestamps: enabled=0 debugger_log: - magic_break: enabled=1 port_e9_hack: enabled=0 private_colormap: enabled=0 clock: sync=none, time0=local, rtc_sync=0 # no cmosimage # no loader log: - logprefix: %t%e%d debug: action=ignore info: action=report error: action=report panic: action=ask keyboard: type=mf, serial_delay=250, paste_delay=100000, user_shortcut=none mouse: type=ps2, enabled=0, toggle=ctrl+mbutton sound: waveoutdrv=win, waveout=none, waveindrv=win, wavein=none, midioutdrv=win, midiout=none speaker: enabled=1, mode=sound parport1: enabled=1, file=none parport2: enabled=0 com1: enabled=1, mode=null com2: enabled=0 com3: enabled=0 com4: enabled=0 ================================================ FILE: build.bat ================================================ del d.iso fasm entry.asm fasm dpmic.asm fasm dmmic.asm fasm vdebug.asm fasm mdebug.asm fasm debuggee.asm fasm leheader.asm le.exe REM Wmake REM Replace G:\WATCOM with your OpenWatcom Path cd switcher g:\watcom\binnt\wpp main.cpp -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml g:\WATCOM\binnt\wlink libpath g:\watcom\lib286 libpath g:\watcom\lib286\dos name switcher d all op m op maxe=25 op q op symf file main.obj format dos cd .. REM upx --best entry.exe mkdir CD copy /y vdebug.exe .\CD\ copy /y mdebug.exe .\CD\mdebug.exe copy /y debuggee.exe .\CD\debuggee.exe copy /y entry.exe .\CD\entry.exe copy /y dmmic.exe .\CD\dmmic.exe copy /y dpmic.exe .\CD\dpmic.exe copy /y .\switcher\switcher.exe .\CD\switcher.exe copy /y le.exe .\CD\le.exe copy /y runx.bat .\CD\runx.bat powershell -ExecutionPolicy RemoteSigned -File "iso.ps1" del .\CD\386swat.lod copy swat\386swat.lod .\CD\386swat.lod copy /y dos32a\* .\CD\ xcopy /y /s /e /i swat\* .\CD\swat xcopy /y /s /e /i qlink\* .\CD\qlink xcopy /y /s /e /i dpmi\* .\CD\dpmi copy /y dis\dism.exe .\CD\ ================================================ FILE: bx_enh_dbg.ini ================================================ # bx_enh_dbg_ini SeeReg[0] = TRUE SeeReg[1] = TRUE SeeReg[2] = TRUE SeeReg[3] = TRUE SeeReg[4] = FALSE SeeReg[5] = FALSE SeeReg[6] = FALSE SeeReg[7] = FALSE SingleCPU = FALSE ShowIOWindows = TRUE ShowButtons = TRUE SeeRegColors = TRUE ignoreNxtT = TRUE ignSSDisasm = TRUE UprCase = 1 DumpInAsciiMode = 2 isLittleEndian = TRUE DefaultAsmLines = 512 DumpWSIndex = 0 DockOrder = 0x123 ListWidthPix[0] = 561 ListWidthPix[1] = 446 ListWidthPix[2] = 382 FontName = System FontSize = -16 MainWindow = 307, 106, 1712, 956 ================================================ FILE: code16.asm ================================================ SEGMENT CODE16 USE16 ORG 0h macro break16 { xchg bx,bx } INCLUDE 'himem16.asm' INCLUDE 'unreal.asm' INCLUDE 'page16.asm' INCLUDE 'acpi16.asm' INCLUDE 'thread16.asm' INCLUDE 'opcodes.asm' macro EnterProtected ofs32 = Start32,codeseg = code32_idx,noinits = 0 { mov ax,noinits cmp ax,1 jz .noinitg mov ax,DATA16 mov ds,ax call far CODE16:GDTInit call far CODE16:IDTInit call far CODE16:IDTInit64 .noinitg: cli mov bx,gdt_start lgdt [bx] mov bx,idt_PM_start ; = NO DEBUG HERE = lidt [bx] mov eax,cr0 or al,1 mov cr0,eax ; gs load with linear data so DMMI knows mov ax,page32_idx mov gs,ax db 066h db 0eah dd ofs32 dw codeseg NOP ; never executed } INCLUDE 'int16.asm' ; --------------------------------------- This is where the application starts --------------------------------------- start16: ; --------------------------------------- Initialization of our segments --------------------------------------- cli ; Overriden by HEAP 0 in entry.asm ;mov ax,0x4A00 ;mov bx,ENDS ;int 0x21 mov ax,DATA16 mov ds,ax mov es,ax mov ax,STACK16 mov sp,stack16_end mov ss,ax sti mov bx,idt_RM_start sidt [bx] ; --------------------------------------- HIMEM.SYS test --------------------------------------- call himemthere mov edx,1024 call allochigh mov dx,cx call freehigh ; --------------------------------------- A20 line --------------------------------------- mov [ds:a20enabled],0 call CheckA20 jc A20AlreadyOn call EnableA20 mov [ds:a20enabled],1 A20AlreadyOn: ; --------------------------------------- Opcode tests --------------------------------------- call OpcodeTest ; --------------------------------------- Prepare Long Mode --------------------------------------- if TEST_LONG > 0 ; Supported? mov [LongModeSupported],0 mov eax, 0x80000000 cpuid cmp eax, 0x80000001 jb .NoLongMode mov [LongModeSupported],1 mov dx,supportlm mov ax,0x0900 int 0x21 xor eax,eax mov ax,CODE64 shl eax,4 add eax,Start64 push fs mov bx,CODE32 mov fs,bx mov dword [fs:PutLinearStart64],eax pop fs ; And Page 1GB Support mov [Support1GBPaging],0 mov eax,80000001h cpuid bt edx,26 jnc .no1gbpg mov [Support1GBPaging],1 mov dx,support1gb mov ax,0x0900 int 0x21 .no1gbpg: .NoLongMode: end if ; --------------------------------------- Protected Mode Find Page Entry --------------------------------------- xor ecx,ecx ; Alloc 32 Pages high, preserve low ram mov edx,1024*100 call allochigh mov [Paging32InXMSH],cx mov [Paging32InXMS],edi LoopPMR: xor eax,eax mov eax,[Paging32InXMS] add eax,ecx mov ebx,eax shr eax,12 shl eax,12 cmp eax,ebx jz LoopPRMFound inc ecx jmp LoopPMR LoopPRMFound: mov [PhysicalPagingOffset32],eax ; --------------------------------------- Long Mode Find Page Entry --------------------------------------- if TEST_LONG > 0 ; Alloc 64 Pages high, preserve low ram mov edx,1024*100 call allochigh mov [Paging64InXMSH],cx mov [Paging64InXMS],edi xor ecx,ecx LoopPMR2: xor eax,eax mov eax,[Paging64InXMS] add eax,ecx mov ebx,eax shr eax,12 shl eax,12 cmp eax,ebx jz LoopPRMFound2 inc ecx jmp LoopPMR2 LoopPRMFound2: mov [PhysicalPagingOffset64],eax end if ; --------------------------------------- VMX EPT Find Page Entry --------------------------------------- if TEST_VMX > 0 mov [VMXSupported],0 mov [VMXUnrestrictedSupported],0 mov eax,1 cpuid bt ecx,5 jnc VMX_NotSupported mov [VMXSupported],1 mov dx,supportvm mov ax,0x0900 int 0x21 ; Unrestricted guest also xor eax,eax xor edx,edx mov ecx,0x48B ; IA32_VMX_PROCBASED_CTLS2 rdmsr bt edx,7 jnc VMX_NoUR mov [VMXUnrestrictedSupported],1 VMX_NoUR: VMX_NotSupported: ; Alloc VMX Pages high, preserve low ram mov edx,1024*100 call allochigh mov [PagingVMInXMSH],cx mov [PagingVMInXMS],edi xor ecx,ecx LoopPMR5: xor eax,eax mov eax,[PagingVMInXMS] add eax,ecx mov ebx,eax shr eax,12 shl eax,12 cmp eax,ebx jz LoopPRMFound5 inc ecx jmp LoopPMR5 LoopPRMFound5: mov dword [PhysicalEptOffset64],eax end if ; --------------------------------------- Quick Unreal --------------------------------------- push cs cli call EnterUnreal sti push cs call InitPageTableFor64 mov ax,CODE16 mov ds,ax linear eax,Thread64P,CODE16 mov [Thread64Ptr1],eax mov ax,CODE64 mov ds,ax linear eax,Thread64_1a,CODE64 mov [Thread64Ptr2],eax mov ax,CODE16 mov ds,ax linear eax,BackFromExecutingInterruptLM,CODE64 mov [Thread64Ptr3],eax mov ax,CODE16 mov ds,ax linear eax,Thread64PV,CODE16 mov [Thread64Ptr4],eax mov ax,CODE16 mov ds,ax linear eax,UR_Mode_2,CODE16 mov [Thread64Ptr1V],eax mov ax,CODE16 mov ds,ax linear eax,VMX_Init_Structures,CODE64 mov [cv64_vmxinitstructures],eax linear eax,VMX_Enable,CODE64 mov [cv64_vmxenable],eax linear eax,VMX_Disable,CODE64 mov [cv64_vmxdisable],eax linear eax,VMX_Initialize_Host,CODE64 mov [cv64_vmxinithost],eax linear eax,VMX_Initialize_Guest2,CODE64 mov [cv64_vmxinitguest2],eax linear eax,VMX_Initialize_UnrestrictedGuest,CODE64 mov [cv64_vmxinitguest1],eax linear eax,VMX_InitializeEPT,CODE64 mov [cv64_vmxinitept],eax linear eax,VMX_Initialize_VMX_Controls,CODE64 mov [cv64_vmxinitcontrols1],eax mov [cv64_vmxinitcontrols2],eax ; --------------------------------------- Find ACPI --------------------------------------- if TEST_MULTI > 0 mov ax,DATA16 mov ds,ax push cs call GetMyApic16f mov [ds:MainCPUAPIC],bl push cs call FillACPI cmp eax,0xFFFFFFFF jnz .coo jmp .noacpi .coo: cmp eax, 'XSDT' jz .ac2 mov eax,'APIC' push cs mov ecx,4 mov edi,[RsdtAddress] call FindACPITableX jmp .eac .ac2: mov eax,'APIC' push cs mov ecx,8 mov edi,dword [XsdtAddress] call FindACPITableX .eac: cmp eax,0xFFFFFFFF jnz .coo2 jmp .noacpi .coo2: push cs call DumpMadt .noacpi: end if ; Resident test /r cmdline mov ax,0x6200 int 0x21 push ds mov ds,bx mov al,[0x80] cmp al,3 jnz .nores mov al,[0x82] cmp al,'/' jnz .nores mov al,[0x83] cmp al,'r' jnz .nores ; Resident pop ds if RESIDENT = 0 mov ax,0x4c00 int 0x21 end if ; Check if there first mov ax,0x35F0 int 0x21 cmp dword [es:bx + 2],'dmmi' jz .yres jmp .fres .yres: mov ax,0 int 0xF0 cmp ax,0xFACE jnz .fres mov ax,DATA16 mov ds,ax mov ax,0x0900 mov dx,resm2 int 0x21 mov ax,0x4C00 int 0x21 .fres: mov ax,0x35F0 int 0x21 mov ax,DATA16 mov ds,ax mov [of0s],es mov [of0o],bx mov ax,CODE16 mov ds,ax mov ax,0x25F0 mov dx,int16 int 0x21 mov ax,DATA16 mov ds,ax mov ax,0x0900 mov dx,resm int 0x21 mov dx,ENDS mov ax,0x3100 int 0x21 .nores: pop ds ; --------------------------------------- Protected Mode Test --------------------------------------- EnterProtected ; --------------------------------------- Exit --------------------------------------- exit16: mov eax,cr0 and al,not 1 mov cr0,eax db 0eah dw flush_ipq,CODE16 flush_ipq: mov ax,STACK16 mov ss,ax mov sp,stack16_end mov ax, DATA16 mov ds,ax mov es,ax mov di,idt_RM_start lidt [di] sti ; = END NO DEBUG HERE = ; Free Paging 32 bit reserved in XMS mov dx,[Paging32InXMSH] call freehigh ; Free Paging 64 bit reserved in XMS mov dx,[Paging64InXMSH] call freehigh ; Free Paging VM bit reserved in XMS mov dx,[PagingVMInXMSH] call freehigh ; --------------------------------------- Quick Unreal --------------------------------------- push cs cli call EnterUnreal sti if TEST_LONG > 0 ; Restore screen (long mode bug) -- Fixed :) ;mov ax,3 ;int 10h end if ; --------------------------------------- ACPI tests --------------------------------------- if TEST_MULTI > 0 if TEST_RM_SIPI > 0 qlock16 mut_1 qlock16 mut_1 qlock16 mut_1 qlock16 mut_1 xor eax,eax mov ax,DATA16 mov ds,ax linear eax,Thread16_1,CODE16 mov ebx,1 call far CODE16:SendSIPIf xor eax,eax mov ax,DATA16 mov ds,ax linear eax,Thread16_2,CODE16 mov ebx,2 call far CODE16:SendSIPIf xor eax,eax mov ax,DATA16 mov ds,ax linear eax,Thread32_1,CODE32 mov ebx,3 call far CODE16:SendSIPIf xor eax,eax mov ax,DATA16 mov ds,ax linear eax,Thread64_1,CODE64 mov ebx,1 ; Back to 1 core call far CODE16:SendSIPIf mov ax,mut_1 push cs call qwait16 mov ax,mut_1 push cs call qwait16 mov ax,mut_1 push cs call qwait16 mov ax,mut_1 push cs call qwait16 end if end if ; --------------------------------------- Tests --------------------------------------- if TEST_MULTI > 0 ; NumCpus xor cx,cx mov cl,[ds:numcpus] .cpul: cmp cx,0 je .endr dec cx mov ax,0900h mov dx,cpuf int 21h jmp .cpul .endr: mov ax,0900h mov dx,crlf int 21h end if push cs call EnterUnreal if TEST_MULTI > 0 ; Apic test cmp dword [ds:RsdtAddress],0 jz .noa1 mov ax,0900h mov dx,ap1 int 21h mov edi, [ds:RsdtAddress] push cs mov ecx,4 call DumpAll mov ax,0900h mov dx,crlf int 21h .noa1: cmp dword [ds:XsdtAddress],0 jz .noa2 mov ax,0900h mov dx,ap2 int 21h mov edi, dword [ds:XsdtAddress] mov ecx,8 push cs call DumpAll mov ax,0900h mov dx,crlf int 21h .noa2: macro thrtest too,msg { local .fx mov ax,DATA16 mov gs,ax cmp [gs:too],1 jnz .fx mov dx,msg mov ax,0900h int 21h .fx: } thrtest FromThread1,thr1 thrtest FromThread2,thr2 thrtest FromThread3,thr3 thrtest FromThread4,thr4 thrtest FromThread5,thr5 thrtest FromThread6,thr6 mov ax,0x900 mov dx,crlf int 0x21 end if ; Real mode test mov ax,0900h mov dx,rm1 int 21h ; PM mode test mov ax,DATA32 mov gs,ax cmp [gs:d32],1 jnz fail_1 mov dx,pm1 mov ax,0900h int 21h fail_1: if TEST_LONG > 0 ; Long mode test mov ax,DATA64 mov gs,ax cmp [gs:d64],1 jnz fail_2 mov dx,lm1 mov ax,0900h int 21h fail_2: end if ; VMX test macro vmxshow vmt,vmm { local .ffx cmp [vmt],1 jnz .ffx mov dx,vmm mov ax,0900h int 21h .ffx: } vmxshow vmt1,vmm1 vmxshow vmt2,vmm2 vmxshow vmt3,vmm2 mov ax,0900h mov dx,crlf int 21h ; A20 off if enabled cmp [ds:a20enabled],1 jnz SkipA20Disable mov ax,0900h mov dx,a20off int 21h call DisableA20 SkipA20Disable: ; --------------------------------------- Bye! --------------------------------------- mov ax,4c00h int 21h ================================================ FILE: code32.asm ================================================ ; --------------------------------------- 32 bit Code --------------------------------------- SEGMENT CODE32 USE32 ORG 0h macro break32 { xchg bx,bx } ; --------------------------------------- One interrupt definition --------------------------------------- intr00: IRETD INCLUDE 'acpi32.asm' INCLUDE 'page32.asm' include 'thread32.asm' INCLUDE 'int32.asm' ; --------------------------------------- Entry Point --------------------------------------- Start32: mov ax,stack32_idx mov ss,ax mov esp,stack32_end mov ax,data32_idx mov ds,ax mov es,ax mov ax,data16_idx mov gs,ax mov fs,ax ;jmp ToBack16 ; --------------------------------------- Data stuff --------------------------------------- mov eax,1 mov [ds:d32],eax mov ebx,[ds:d32] ; --------------------------------------- Interrupt Test --------------------------------------- int 0x0; ; --------------------------------------- SIPI to real mode test --------------------------------------- if TEST_PM_SIPI > 0 qlock32 mut_1 xor eax,eax mov ax,data16_idx mov ds,ax linear eax,Thread16_3,CODE16 mov ebx,1 push cs call SendSIPI32f mov ax,mut_1 push cs call qwait32 end if ; --------------------------------------- LLDT --------------------------------------- mov ax,ldt_idx lldt ax mov ax,data32_ldt_idx mov gs,ax push ds pop gs ; --------------------------------------- Page Tests--------------------------------------- call InitPageTable32a mov ax,data16_idx push gs mov gs,ax mov edx,[gs:PhysicalPagingOffset32] pop gs mov CR3,edx mov eax,cr4 bts eax,4 mov cr4,eax mov eax, cr0 or eax,80000000h mov cr0, eax ; Paging is now enabled nop nop nop ; Disable Paging mov eax, cr0 ; Read CR0. and eax,7FFFFFFFh; Set PE=0 mov cr0, eax ; Write CR0. ; jmp ToBack16 ; --------------------------------------- Prepare Long Mode --------------------------------------- if TEST_LONG > 0 if TEST_LM_SIPI > 0 mov ax,data16_idx push gs mov gs,ax mov dl,[gs:Support1GBPaging] mov dh,[gs:LongModeSupported] pop gs cmp dh,1 jnz ToBack16 cmp dl,1 jnz .no1GB call InitPageTable643 ; 1gb pages, map entire 4gb jmp .okPaging .no1GB: call InitPageTable642 ; Small pages else call InitPageTable642 end if .okPaging: ; Enable PAE mov eax, cr4 bts eax, 5 mov cr4, eax ; Load new page table mov ax,data16_idx push gs mov gs,ax mov edx,[gs:PhysicalPagingOffset64] pop gs mov cr3,edx ; Enable Long Mode mov ecx, 0c0000080h ; EFER MSR number. rdmsr ; Read EFER. bts eax, 8 ; Set LME=1. wrmsr ; Write EFER. ; Enable Paging to activate Long Mode mov eax, cr0 ; Read CR0. or eax,80000000h ; Set PE=1. mov cr0, eax ; Write CR0. nop nop nop ; We are now in Long Mode / Compatibility mode ; Jump to an 64-bit segment to enable 64-bit mode db 0eah PutLinearStart64 dd 0 dw code64_idx else jmp ToBack16 end if ; --------------------------------------- Back from Long Mode --------------------------------------- Back32: ; We are now in Compatibility mode again mov ax,stack32_idx mov ss,ax mov esp,stack32_end mov ax,data32_idx mov ds,ax mov es,ax mov ax,data16_idx mov gs,ax mov fs,ax ; Disable Paging to get out of Long Mode mov eax, cr0 and eax,7fffffffh mov cr0, eax ; Deactivate Long Mode mov ecx, 0c0000080h rdmsr btc eax, 8 wrmsr ; Disable PAE mov eax, cr4 btc eax, 5 mov cr4, eax ; --------------------------------------- Back to Real mode --------------------------------------- ToBack16: ; = Give FS the abs32 segment ; To test unreal mode mov ax,absd32_idx mov fs,ax ; Go back db 066h ; because we are in a 32bit segment db 0eah dw exit16 dw code16_idx ================================================ FILE: code64.asm ================================================ ; --------------------------------------- 64 bit Code --------------------------------------- SEGMENT CODE64 USE64 ORG 0h macro break64 { xchg bx,bx } include 'guest64.asm' include 'acpi64.asm' include 'thread64.asm' INCLUDE 'int64.asm' include 'vmxhost64.asm' ; --------------------------------------- One interrupt definition --------------------------------------- intr6400: nop nop IRETQ Start64: xor r8d,r8d linear rsp,stack64_end push rax mov rax,0 pop rax ; access d64 using linear, ds not used xor rax,rax mov ax,DATA64 shl rax,4 add rax,d64 mov byte [rax],1 ; --------------------------------------- Interrupt Test --------------------------------------- linear rax,idt_LM_start lidt [rax] int 0x1; ; --------------------------------------- SIPI to real mode test --------------------------------------- if TEST_LM_SIPI > 0 qlock64 mut_1 linear rax,Thread16_4,CODE16 mov rbx,1 call SendSIPI64 mov rax,mut_1 call qwait64 end if if TEST_VMX > 0 ; VMX operations call VMX_Host end if ; Back to Compatibility Mode push code32_idx xor rcx,rcx mov ecx,Back32 push rcx retf ================================================ FILE: config.asm ================================================ TEST_LONG = 1 TEST_MULTI = 1 TEST_RM_SIPI = 1 TEST_PM_SIPI = 1 TEST_LM_SIPI = 1 TEST_VMX = 1 RESIDENT = 1 VDEBUG = 0 MDEBUG = 0 ================================================ FILE: data16.asm ================================================ SEGMENT DATA16 USE16 ; --------------------------------------- 16 bit data --------------------------------------- a20enabled db 0 numcpus db 0 somecpu A_CPU 0,0,0,0 cpusstructize = $-(somecpu) CpusOfs: cpus db cpusstructize*64 dup(0) MainCPUAPIC db 0 LocalApic dd 0xFEE00000 RsdtAddress dd 0 XsdtAddress dq 0 ProcedureStart dd 0 FromThread1 db 0 FromThread2 db 0 FromThread3 db 0 FromThread4 db 0 FromThread5 db 0 FromThread6 db 0 of0s dw 0 of0o dw 0 LongModeSupported db 0 Support1GBPaging db 0 VMXSupported db 0 VMXUnrestrictedSupported db 0 Paging32InXMS dd 0 Paging32InXMSH dw 0 Paging64InXMS dd 0 Paging64InXMSH dw 0 PagingVMInXMS dd 0 PagingVMInXMSH dw 0 ; --------------------------------------- VMX tests--------------------------------------- vmt1 db 0 ; existence vmt2 db 0 ; protected mode guest vmt3 db 0 ; unrestricted guest vmm1 db "[VMX] ","$" vmm2 db "[VMX Launch] ","$" ; --------------------------------------- 16 bit mutexes --------------------------------------- mut_ipi db 0xFF mut_1 db 0xFF mut_i21 db 0xFF ; --------------------------------------- Messages --------------------------------------- rm1 db "[Real mode] ","$" pm1 db "[Protected mode] ","$" lm1 db "[Long mode] ","$" ap1 db "Apic 1 found ","$" ap2 db "Apic 2 found ","$" cpuf db "CPU $" thrm1 db "Message from real mode thread",0dh,0ah,"$" thrm2 db "Message from real mode thread called from protected mode",0dh,0ah,"$" thrm3 db "Message from real mode thread called from long mode",0dh,0ah,"$" thr1 db "[T1 RM] $" thr2 db "[T2 RM] $" thr3 db "[T3 PM->RM] $" thr4 db "[T4 LM->RM] $" thr5 db "[T5 RM->PM] $" thr6 db "[T6 RM->LM] $" resm db "DMMI Server Active",0dh,0ah,"$" resm2 db "DMMI Server Already installed",0dh,0ah,"$" a20off db "Restoring A20",0dh,0ah,"$" crlf db 0dh,0ah,"$" ; --------------------------------------- GDT --------------------------------------- gdt_start dw gdt_size gdt_ptr dd 0 dummy_descriptor GDT_STR 0,0,0,0,0,0 code32_descriptor GDT_STR 0ffffh,0,0,9ah,0cfh,0 ; 4GB 32-bit code , 9ah = 10011010b = Present, DPL 00,No System, Code Exec/Read. 0cfh access = 11001111b = Big,32bit,,1111 more size data32_descriptor GDT_STR 0ffffh,0,0,92h,0cfh,0 ; 4GB 32-bit data, 92h = 10010010b = Presetn , DPL 00, No System, Data Read/Write stack32_descriptor GDT_STR 0ffffh,0,0,92h,0cfh,0 ; 4GB 32-bit stack code16_descriptor GDT_STR 0ffffh,0,0,9ah,0,0 ; 64k 16-bit code data16_descriptor GDT_STR 0ffffh,0,0,92h,0,0 ; 64k 16-bit data stack16_descriptor GDT_STR 0ffffh,0,0,92h,0,0 ; 64k 16-bit data ldt_descriptor GDT_STR ldt_size,0,0,82h,0,0 ; pointer to LDT, 82h = 10000010b = Present, DPL 00, System , Type "0010b" = LDT entry code64_descriptor GDT_STR 0ffffh,0,0,9ah,0afh,0 ; 16TB 64-bit code, 08cfh access = 01001111b = Big,64bit (0), 1111 more size page32_descriptor GDT_STR 0ffffh,0,0,92h,0cfh,0 ; 4GB 32-bit data, 92h = 10010010b = Presetn , DPL 00, No System, Data Read/Write page64_descriptor GDT_STR 0ffffh,0,0,92h,0cfh,0 ; 4GB 32-bit data, 92h = 10010010b = Presetn , DPL 00, No System, Data Read/Write absd32_descriptor GDT_STR 0ffffh,0,0,92h,0cfh,0 ; 4GB 32-bit data, 92h = 10010010b = Presetn , DPL 00, No System, Data Read/Write data64_descriptor GDT_STR 0ffffh,0,0,92h,0afh,0 ; 16TB 64-bit data, 08cfh access = 10001111b = Big,64bit (0), 1111 more size absd64_descriptor GDT_STR 0ffffh,0,0,92h,0afh,0 ; 16TB 64-bit data, 08cfh access = 10001111b = Big,64bit (0), 1111 more size tssd32_descriptor GDT_STR 0h,0,0,89h,040h,0 ; TSS segment in GDT vmx32_descriptor GDT_STR 0ffffh,0,0,9ah,0cfh,0 ; 4GB 32-bit code , 9ah = 10011010b = Present, DPL 00,No System, Code Exec/Read. 0cfh access = 11001111b = Big,32bit,,1111 more size raw32_descriptor GDT_STR 0ffffh,0,0,9ah,0cfh,0 ; 4GB 32-bit code , 9ah = 10011010b = Present, DPL 00,No System, Code Exec/Read. 0cfh access = 11001111b = Big,32bit,,1111 more size tssd64_descriptor GDT_STR 0h,0,0,89h,040h,0 ; TSS segment in GDT gdt_size = $-(dummy_descriptor) dummy_idx = 0h ; dummy selector code32_idx = 08h ; offset of 32-bit code segment in GDT data32_idx = 10h ; offset of 32-bit data segment in GDT stack32_idx = 18h ; offset of 32-bit stack segment in GDT code16_idx = 20h ; offset of 16-bit code segment in GDT data16_idx = 28h ; offset of 16-bit data segment in GDT stack16_idx = 30h ; offset of 16-bit stack segment in GDT ldt_idx = 38h ; offset of LDT in GDT code64_idx = 40h ; offset of 64-bit code segment in GDT page32_idx = 48h ; offset of 32-bit data segment in GDT page64_idx = 50h ; offset of 64-bit data segment in GDT absd32_idx = 58h ; offset of 32-bit data segment in GDT data64_idx = 60h ; offset of 64-bit data segment in GDT absd64_idx = 68h ; offset of 64-bit data segment in GDT tssd32_idx = 70h ; TSS descriptor vmx32_idx = 78h ; offset of 32-bit code segment in GDT raw32_idx = 80h ; offset of 32-bit code segment in GDT tssd64_idx = 88h ; TSS descriptor data32_ldt_idx = 04h ; offset of 32-bit data segment in LDT ; And For Quick Unreal gdt_startUNR dw gdt_sizeUNR gdt_ptrUNR dd 0 dummy_descriptorUNR GDT_STR 0,0,0,0,0,0 code16_descriptorUNR GDT_STR 0ffffh,0,0,9ah,0,0 data32_descriptorUNR GDT_STR 0ffffh,0,0,92h,0cfh,0 gdt_sizeUNR = $-(dummy_descriptorUNR) ; --------------------------------------- IDT --------------------------------------- idt_RM_start dw 0 idt_RM_ptr dd 0 idt_PM_start dw idt_size idt_PM_ptr dd 0 interruptsall rb 256*8 ;interruptsall IDT_STR 0,0,0,0,0 ; rb 256 * 8 idt_size=$-(interruptsall) idt_LM_start dw idtl_size idt_LM_ptr db 0 dup(8) interruptsall64 rb 256*16 idtl_size=$-(interruptsall64) ; --------------------------------------- PAGE --------------------------------------- PhysicalPagingOffset32 dd 0 PhysicalPagingOffset64 dd 0 PhysicalEptOffset64 dq 0 ; --------------------------------------- Supported --------------------------------------- supportlm db "[Long Mode] ","$" support1gb db "[1GB Paging] ","$" supportvm db "[VM] ",0x0d,0x0a,"$" ;supportvmu db "VM Unrestricted Supported",0x0d,0x0a,"$" ; --- DISM dismdata db 1000 dup (0) ; 1 type byte, 2 length, 3+data dismdatac dd 0 dismdata2 db 2000 dup (0) ; Result ================================================ FILE: data32.asm ================================================ ; --------------------------------------- 32 bit Data --------------------------------------- SEGMENT DATA32 USE32 ldt_start: ldt_1_descriptor GDT_STR 0ffffh,0,0,92h,0cfh,0 ; 4GB 32-bit data ldt_size=$-(ldt_1_descriptor) ; unlike the GDT , LDT does not have a 6-byte header to indicate its absolute address and limit ; these are specified into its GDT entry. tssdata db 2048 dup (0) ; for some empty TSS d32 dd 0 ; --------------------------------------- MOVEMENTS FOR INT0xF0 --------------------------------------- From32To16Regs db 64 dup (0) ================================================ FILE: data64.asm ================================================ ; --------------------------------------- 64 bit Data --------------------------------------- SEGMENT DATA64 USE64 ORG 0 d64 db 0 SEGMENT VMXDATA64 USE64 ; --------------------------------------- VMX Data --------------------------------------- ALIGN 4096 VMXStructureData db 20000 dup (0) VMXStructureData1 dq 0 ; Used for VMXON VMXStructureData2 dq 0 ; First VMCS ;VMXStructureData3 dq 0 ; Second VMCS VMXRevision dd 0 ; Save Revision here VMXStructureSize dd 0 ; Save structure size here ; Temp Data TempData db 128 dup(0) ; --------------------------------------- MOVEMENTS FOR INT0xF0 --------------------------------------- From64To16Regs db 64 dup (0) ; --------------------------------------- 64 bit Data another segment--------------------------------------- SEGMENT ABSD64 USE64 ================================================ FILE: debuggee.asm ================================================ FORMAT MZ HEAP 0 macro linear reg,trg,seg = DATA16 { mov reg,seg shl reg,4 add reg,trg } struc GDT_STR s0_15,b0_15,b16_23,flags,access,b24_31 { .s0_15 dw s0_15 .b0_15 dw b0_15 .b16_23 db b16_23 .flags db flags .access db access .b24_31 db b24_31 } segment DATA16 USE16 ; And For Quick Unreal gdt_startUNR dw gdt_sizeUNR gdt_ptrUNR dd 0 dummy_descriptorUNR GDT_STR 0,0,0,0,0,0 code16_descriptorUNR GDT_STR 0ffffh,0,0,9ah,0,0 data32_descriptorUNR GDT_STR 0ffffh,0,0,92h,0cfh,0 gdt_sizeUNR = $-(dummy_descriptorUNR) ; main segment CODE16 USE16 m1 db "Hello",0xD,0xA,"$" include 'unreal.asm' start16: mov ax,CODE16 mov ds,ax mov ax,0x0900 mov dx,m1 int 0x21 nop nop ; Enter Unreal ;call EnterUnreal mov ax,0x4C00 int 0x21 SEGMENT ENDS entry CODE16:start16 ================================================ FILE: directlong.asm ================================================ macro thread64header brk=0 { local nobrk USE16 ; Remember CPU starts in real mode db 4096 dup (144) ; // fill NOPs cli ; Stack mov ax,STACK16T5 mov ss,ax mov sp,stack16t5_end ; A20 call FAR CODE16:EnableA20f ; Unreal call FAR CODE16:EnterUnreal ; GDT and IDT mov ax,DATA16 mov ds,ax call far CODE16:GDTInit call far CODE16:IDTInit call far CODE16:IDTInit64 mov bx,gdt_start lgdt [bx] ; Prepare Paging nop nop call FAR CODE16:InitPageTableFor64 ; Spurious, APIC MOV EDI,[DS:LocalApic] ADD EDI,0x0F0 MOV EDX,[FS:EDI] OR EDX,0x1FF push dword 0 pop fs MOV [FS:EDI],EDX MOV EDI,[DS:LocalApic] ADD EDI,0x0B0 MOV dword [FS:EDI],0 ; Breakpoint mov ax,brk cmp ax,1 jnz nobrk xchg bx,bx nobrk: ; Enter Long Mode mov eax, cr4 bts eax, 5 mov cr4, eax ; Load new page table mov ax,DATA16 push gs mov gs,ax mov edx,[gs:PhysicalPagingOffset64] pop gs mov cr3,edx ; Enable Long Mode mov ecx, 0c0000080h ; EFER MSR number. rdmsr ; Read EFER. bts eax, 8 ; Set LME=1. wrmsr ; Write EFER. ; Enable both PM and Paging to activate Long Mode from Real Mode mov eax, cr0 ; Read CR0. or eax,80000000h ; Set PE=1. or eax,1 ; Also PM=1 mov cr0, eax ; Write CR0. nop nop nop ; We are now in Long Mode / Compatibility mode ; Jump to an 64-bit segment to enable 64-bit mode } ================================================ FILE: dis/Makefile.am ================================================ # # -- udis86/libudis86 # PYTHON = @PYTHON@ OPTABLE = @top_srcdir@/docs/x86/optable.xml MAINTAINERCLEANFILES = Makefile.in lib_LTLIBRARIES = libudis86.la libudis86_la_SOURCES = \ itab.c \ decode.c \ syn.c \ syn-intel.c \ syn-att.c \ udis86.c \ udint.h \ syn.h \ decode.h include_ladir = ${includedir}/libudis86 include_la_HEADERS = \ types.h \ extern.h \ itab.h BUILT_SOURCES = \ itab.c \ itab.h # # DLLs may not contain undefined symbol references. # We have the linker check this explicitly. # if TARGET_WINDOWS libudis86_la_LDFLAGS = -no-undefined -version-info 0:0:0 endif itab.c itab.h: $(OPTABLE) \ $(top_srcdir)/scripts/ud_itab.py \ $(top_srcdir)/scripts/ud_opcode.py \ $(top_srcdir)/scripts/ud_optable.py $(PYTHON) $(top_srcdir)/scripts/ud_itab.py $(OPTABLE) $(srcdir) clean-local: rm -rf $(BUILT_SOURCES) maintainer-clean-local: ================================================ FILE: dis/Makefile.in ================================================ # Makefile.in generated by automake 1.13.1 from Makefile.am. # @configure_input@ # Copyright (C) 1994-2012 Free Software Foundation, Inc. # This Makefile.in is free software; the Free Software Foundation # gives unlimited permission to copy and/or distribute it, # with or without modifications, as long as this notice is preserved. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY, to the extent permitted by law; without # even the implied warranty of MERCHANTABILITY or FITNESS FOR A # PARTICULAR PURPOSE. @SET_MAKE@ # # -- udis86/libudis86 # VPATH = @srcdir@ am__make_dryrun = \ { \ am__dry=no; \ case $$MAKEFLAGS in \ *\\[\ \ ]*) \ echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \ | grep '^AM OK$$' >/dev/null || am__dry=yes;; \ *) \ for am__flg in $$MAKEFLAGS; do \ case $$am__flg in \ *=*|--*) ;; \ *n*) am__dry=yes; break;; \ esac; \ done;; \ esac; \ test $$am__dry = yes; \ } pkgdatadir = $(datadir)/@PACKAGE@ pkgincludedir = $(includedir)/@PACKAGE@ pkglibdir = $(libdir)/@PACKAGE@ pkglibexecdir = $(libexecdir)/@PACKAGE@ am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd install_sh_DATA = $(install_sh) -c -m 644 install_sh_PROGRAM = $(install_sh) -c install_sh_SCRIPT = $(install_sh) -c INSTALL_HEADER = $(INSTALL_DATA) transform = $(program_transform_name) NORMAL_INSTALL = : PRE_INSTALL = : POST_INSTALL = : NORMAL_UNINSTALL = : PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ subdir = libudis86 DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/Makefile.am \ $(top_srcdir)/build/depcomp $(include_la_HEADERS) ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 am__aclocal_m4_deps = $(top_srcdir)/build/m4/libtool.m4 \ $(top_srcdir)/build/m4/ltoptions.m4 \ $(top_srcdir)/build/m4/ltsugar.m4 \ $(top_srcdir)/build/m4/ltversion.m4 \ $(top_srcdir)/build/m4/lt~obsolete.m4 \ $(top_srcdir)/m4/ax_compare_version.m4 \ $(top_srcdir)/m4/ax_prog_sphinx_version.m4 \ $(top_srcdir)/m4/ax_prog_yasm_version.m4 \ $(top_srcdir)/m4/ax_with_prog.m4 \ $(top_srcdir)/m4/ax_with_python.m4 $(top_srcdir)/configure.ac am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ $(ACLOCAL_M4) mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = CONFIG_CLEAN_VPATH_FILES = am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; am__vpath_adj = case $$p in \ $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ *) f=$$p;; \ esac; am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; am__install_max = 40 am__nobase_strip_setup = \ srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` am__nobase_strip = \ for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" am__nobase_list = $(am__nobase_strip_setup); \ for p in $$list; do echo "$$p $$p"; done | \ sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ if (++n[$$2] == $(am__install_max)) \ { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ END { for (dir in files) print dir, files[dir] }' am__base_list = \ sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' am__uninstall_files_from_dir = { \ test -z "$$files" \ || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \ || { echo " ( cd '$$dir' && rm -f" $$files ")"; \ $(am__cd) "$$dir" && rm -f $$files; }; \ } am__installdirs = "$(DESTDIR)$(libdir)" "$(DESTDIR)$(include_ladir)" LTLIBRARIES = $(lib_LTLIBRARIES) libudis86_la_LIBADD = am_libudis86_la_OBJECTS = itab.lo decode.lo syn.lo syn-intel.lo \ syn-att.lo udis86.lo libudis86_la_OBJECTS = $(am_libudis86_la_OBJECTS) AM_V_lt = $(am__v_lt_@AM_V@) am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@) am__v_lt_0 = --silent am__v_lt_1 = libudis86_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(libudis86_la_LDFLAGS) $(LDFLAGS) -o $@ AM_V_P = $(am__v_P_@AM_V@) am__v_P_ = $(am__v_P_@AM_DEFAULT_V@) am__v_P_0 = false am__v_P_1 = : AM_V_GEN = $(am__v_GEN_@AM_V@) am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@) am__v_GEN_0 = @echo " GEN " $@; am__v_GEN_1 = AM_V_at = $(am__v_at_@AM_V@) am__v_at_ = $(am__v_at_@AM_DEFAULT_V@) am__v_at_0 = @ am__v_at_1 = DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/build/depcomp am__depfiles_maybe = depfiles am__mv = mv -f COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ $(AM_CFLAGS) $(CFLAGS) AM_V_CC = $(am__v_CC_@AM_V@) am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@) am__v_CC_0 = @echo " CC " $@; am__v_CC_1 = CCLD = $(CC) LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ AM_V_CCLD = $(am__v_CCLD_@AM_V@) am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@) am__v_CCLD_0 = @echo " CCLD " $@; am__v_CCLD_1 = SOURCES = $(libudis86_la_SOURCES) DIST_SOURCES = $(libudis86_la_SOURCES) am__can_run_installinfo = \ case $$AM_UPDATE_INFO_DIR in \ n|no|NO) false;; \ *) (install-info --version) >/dev/null 2>&1;; \ esac HEADERS = $(include_la_HEADERS) am__tagged_files = $(HEADERS) $(SOURCES) $(TAGS_FILES) $(LISP) # Read a list of newline-separated strings from the standard input, # and print each of them once, without duplicates. Input order is # *not* preserved. am__uniquify_input = $(AWK) '\ BEGIN { nonempty = 0; } \ { items[$$0] = 1; nonempty = 1; } \ END { if (nonempty) { for (i in items) print i; }; } \ ' # Make sure the list of sources is unique. This is necessary because, # e.g., the same source file might be shared among _SOURCES variables # for different programs/libraries. am__define_uniq_tagged_files = \ list='$(am__tagged_files)'; \ unique=`for i in $$list; do \ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \ done | $(am__uniquify_input)` ETAGS = etags CTAGS = ctags DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) ACLOCAL = @ACLOCAL@ ACLOCAL_AMFLAGS = @ACLOCAL_AMFLAGS@ AMTAR = @AMTAR@ AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ AR = @AR@ AS = @AS@ AUTOCONF = @AUTOCONF@ AUTOHEADER = @AUTOHEADER@ AUTOMAKE = @AUTOMAKE@ AWK = @AWK@ CC = @CC@ CCDEPMODE = @CCDEPMODE@ CFLAGS = @CFLAGS@ CPP = @CPP@ CPPFLAGS = @CPPFLAGS@ CYGPATH_W = @CYGPATH_W@ DEFS = @DEFS@ DEPDIR = @DEPDIR@ DLLTOOL = @DLLTOOL@ DSYMUTIL = @DSYMUTIL@ DUMPBIN = @DUMPBIN@ ECHO_C = @ECHO_C@ ECHO_N = @ECHO_N@ ECHO_T = @ECHO_T@ EGREP = @EGREP@ EXEEXT = @EXEEXT@ FGREP = @FGREP@ GREP = @GREP@ INSTALL = @INSTALL@ INSTALL_DATA = @INSTALL_DATA@ INSTALL_PROGRAM = @INSTALL_PROGRAM@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ LD = @LD@ LDFLAGS = @LDFLAGS@ LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ LIPO = @LIPO@ LN_S = @LN_S@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ MKDIR_P = @MKDIR_P@ NM = @NM@ NMEDIT = @NMEDIT@ OBJDUMP = @OBJDUMP@ OBJEXT = @OBJEXT@ OTOOL = @OTOOL@ OTOOL64 = @OTOOL64@ PACKAGE = @PACKAGE@ PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@ PACKAGE_NAME = @PACKAGE_NAME@ PACKAGE_STRING = @PACKAGE_STRING@ PACKAGE_TARNAME = @PACKAGE_TARNAME@ PACKAGE_URL = @PACKAGE_URL@ PACKAGE_VERSION = @PACKAGE_VERSION@ PATH_SEPARATOR = @PATH_SEPARATOR@ PYTHON = @PYTHON@ RANLIB = @RANLIB@ SED = @SED@ SET_MAKE = @SET_MAKE@ SHELL = @SHELL@ SPHINX_BUILD = @SPHINX_BUILD@ SPHINX_VERSION = @SPHINX_VERSION@ STRIP = @STRIP@ VERSION = @VERSION@ YASM = @YASM@ YASM_VERSION = @YASM_VERSION@ abs_builddir = @abs_builddir@ abs_srcdir = @abs_srcdir@ abs_top_builddir = @abs_top_builddir@ abs_top_srcdir = @abs_top_srcdir@ ac_ct_AR = @ac_ct_AR@ ac_ct_CC = @ac_ct_CC@ ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ am__include = @am__include@ am__leading_dot = @am__leading_dot@ am__quote = @am__quote@ am__tar = @am__tar@ am__untar = @am__untar@ bindir = @bindir@ build = @build@ build_alias = @build_alias@ build_cpu = @build_cpu@ build_os = @build_os@ build_vendor = @build_vendor@ builddir = @builddir@ datadir = @datadir@ datarootdir = @datarootdir@ docdir = @docdir@ dvidir = @dvidir@ exec_prefix = @exec_prefix@ host = @host@ host_alias = @host_alias@ host_cpu = @host_cpu@ host_os = @host_os@ host_vendor = @host_vendor@ htmldir = @htmldir@ includedir = @includedir@ infodir = @infodir@ install_sh = @install_sh@ libdir = @libdir@ libexecdir = @libexecdir@ localedir = @localedir@ localstatedir = @localstatedir@ mandir = @mandir@ mkdir_p = @mkdir_p@ oldincludedir = @oldincludedir@ pdfdir = @pdfdir@ prefix = @prefix@ program_transform_name = @program_transform_name@ psdir = @psdir@ sbindir = @sbindir@ sharedstatedir = @sharedstatedir@ srcdir = @srcdir@ sysconfdir = @sysconfdir@ target_alias = @target_alias@ top_build_prefix = @top_build_prefix@ top_builddir = @top_builddir@ top_srcdir = @top_srcdir@ OPTABLE = @top_srcdir@/docs/x86/optable.xml MAINTAINERCLEANFILES = Makefile.in lib_LTLIBRARIES = libudis86.la libudis86_la_SOURCES = \ itab.c \ decode.c \ syn.c \ syn-intel.c \ syn-att.c \ udis86.c \ udint.h \ syn.h \ decode.h include_ladir = ${includedir}/libudis86 include_la_HEADERS = \ types.h \ extern.h \ itab.h BUILT_SOURCES = \ itab.c \ itab.h # # DLLs may not contain undefined symbol references. # We have the linker check this explicitly. # @TARGET_WINDOWS_TRUE@libudis86_la_LDFLAGS = -no-undefined -version-info 0:0:0 all: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) all-am .SUFFIXES: .SUFFIXES: .c .lo .o .obj $(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps) @for dep in $?; do \ case '$(am__configure_deps)' in \ *$$dep*) \ ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \ && { if test -f $@; then exit 0; else break; fi; }; \ exit 1;; \ esac; \ done; \ echo ' cd $(top_srcdir) && $(AUTOMAKE) --foreign libudis86/Makefile'; \ $(am__cd) $(top_srcdir) && \ $(AUTOMAKE) --foreign libudis86/Makefile .PRECIOUS: Makefile Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status @case '$?' in \ *config.status*) \ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \ *) \ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \ esac; $(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(top_srcdir)/configure: $(am__configure_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(ACLOCAL_M4): $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh $(am__aclocal_m4_deps): install-libLTLIBRARIES: $(lib_LTLIBRARIES) @$(NORMAL_INSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ list2=; for p in $$list; do \ if test -f $$p; then \ list2="$$list2 $$p"; \ else :; fi; \ done; \ test -z "$$list2" || { \ echo " $(MKDIR_P) '$(DESTDIR)$(libdir)'"; \ $(MKDIR_P) "$(DESTDIR)$(libdir)" || exit 1; \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(libdir)'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(libdir)"; \ } uninstall-libLTLIBRARIES: @$(NORMAL_UNINSTALL) @list='$(lib_LTLIBRARIES)'; test -n "$(libdir)" || list=; \ for p in $$list; do \ $(am__strip_dir) \ echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(libdir)/$$f'"; \ $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(libdir)/$$f"; \ done clean-libLTLIBRARIES: -test -z "$(lib_LTLIBRARIES)" || rm -f $(lib_LTLIBRARIES) @list='$(lib_LTLIBRARIES)'; \ locs=`for p in $$list; do echo $$p; done | \ sed 's|^[^/]*$$|.|; s|/[^/]*$$||; s|$$|/so_locations|' | \ sort -u`; \ test -z "$$locs" || { \ echo rm -f $${locs}; \ rm -f $${locs}; \ } libudis86.la: $(libudis86_la_OBJECTS) $(libudis86_la_DEPENDENCIES) $(EXTRA_libudis86_la_DEPENDENCIES) $(AM_V_CCLD)$(libudis86_la_LINK) -rpath $(libdir) $(libudis86_la_OBJECTS) $(libudis86_la_LIBADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) distclean-compile: -rm -f *.tab.c @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/decode.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/itab.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syn-att.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syn-intel.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/syn.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/udis86.Plo@am__quote@ .c.o: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $< .c.obj: @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'` .c.lo: @am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo @AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $< mostlyclean-libtool: -rm -f *.lo clean-libtool: -rm -rf .libs _libs install-include_laHEADERS: $(include_la_HEADERS) @$(NORMAL_INSTALL) @list='$(include_la_HEADERS)'; test -n "$(include_ladir)" || list=; \ if test -n "$$list"; then \ echo " $(MKDIR_P) '$(DESTDIR)$(include_ladir)'"; \ $(MKDIR_P) "$(DESTDIR)$(include_ladir)" || exit 1; \ fi; \ for p in $$list; do \ if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ echo "$$d$$p"; \ done | $(am__base_list) | \ while read files; do \ echo " $(INSTALL_HEADER) $$files '$(DESTDIR)$(include_ladir)'"; \ $(INSTALL_HEADER) $$files "$(DESTDIR)$(include_ladir)" || exit $$?; \ done uninstall-include_laHEADERS: @$(NORMAL_UNINSTALL) @list='$(include_la_HEADERS)'; test -n "$(include_ladir)" || list=; \ files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ dir='$(DESTDIR)$(include_ladir)'; $(am__uninstall_files_from_dir) ID: $(am__tagged_files) $(am__define_uniq_tagged_files); mkid -fID $$unique tags: tags-am TAGS: tags tags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) set x; \ here=`pwd`; \ $(am__define_uniq_tagged_files); \ shift; \ if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ test -n "$$unique" || unique=$$empty_fix; \ if test $$# -gt 0; then \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ "$$@" $$unique; \ else \ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ $$unique; \ fi; \ fi ctags: ctags-am CTAGS: ctags ctags-am: $(TAGS_DEPENDENCIES) $(am__tagged_files) $(am__define_uniq_tagged_files); \ test -z "$(CTAGS_ARGS)$$unique" \ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ $$unique GTAGS: here=`$(am__cd) $(top_builddir) && pwd` \ && $(am__cd) $(top_srcdir) \ && gtags -i $(GTAGS_ARGS) "$$here" cscopelist: cscopelist-am cscopelist-am: $(am__tagged_files) list='$(am__tagged_files)'; \ case "$(srcdir)" in \ [\\/]* | ?:[\\/]*) sdir="$(srcdir)" ;; \ *) sdir=$(subdir)/$(srcdir) ;; \ esac; \ for i in $$list; do \ if test -f "$$i"; then \ echo "$(subdir)/$$i"; \ else \ echo "$$sdir/$$i"; \ fi; \ done >> $(top_builddir)/cscope.files distclean-tags: -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags distdir: $(DISTFILES) @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ list='$(DISTFILES)'; \ dist_files=`for file in $$list; do echo $$file; done | \ sed -e "s|^$$srcdirstrip/||;t" \ -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ case $$dist_files in \ */*) $(MKDIR_P) `echo "$$dist_files" | \ sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ sort -u` ;; \ esac; \ for file in $$dist_files; do \ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ if test -d $$d/$$file; then \ dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ if test -d "$(distdir)/$$file"; then \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ fi; \ cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ else \ test -f "$(distdir)/$$file" \ || cp -p $$d/$$file "$(distdir)/$$file" \ || exit 1; \ fi; \ done check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-am all-am: Makefile $(LTLIBRARIES) $(HEADERS) installdirs: for dir in "$(DESTDIR)$(libdir)" "$(DESTDIR)$(include_ladir)"; do \ test -z "$$dir" || $(MKDIR_P) "$$dir"; \ done install: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) install-am install-exec: install-exec-am install-data: install-data-am uninstall: uninstall-am install-am: all-am @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am installcheck: installcheck-am install-strip: if test -z '$(STRIP)'; then \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ install; \ else \ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \ "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \ fi mostlyclean-generic: clean-generic: distclean-generic: -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES) -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) maintainer-clean-generic: @echo "This command is intended for maintainers to use" @echo "it deletes files that may require special tools to rebuild." -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES) -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-am clean-am: clean-generic clean-libLTLIBRARIES clean-libtool clean-local \ mostlyclean-am distclean: distclean-am -rm -rf ./$(DEPDIR) -rm -f Makefile distclean-am: clean-am distclean-compile distclean-generic \ distclean-tags dvi: dvi-am dvi-am: html: html-am html-am: info: info-am info-am: install-data-am: install-include_laHEADERS install-dvi: install-dvi-am install-dvi-am: install-exec-am: install-libLTLIBRARIES install-html: install-html-am install-html-am: install-info: install-info-am install-info-am: install-man: install-pdf: install-pdf-am install-pdf-am: install-ps: install-ps-am install-ps-am: installcheck-am: maintainer-clean: maintainer-clean-am -rm -rf ./$(DEPDIR) -rm -f Makefile maintainer-clean-am: distclean-am maintainer-clean-generic \ maintainer-clean-local mostlyclean: mostlyclean-am mostlyclean-am: mostlyclean-compile mostlyclean-generic \ mostlyclean-libtool pdf: pdf-am pdf-am: ps: ps-am ps-am: uninstall-am: uninstall-include_laHEADERS uninstall-libLTLIBRARIES .MAKE: all check install install-am install-strip .PHONY: CTAGS GTAGS TAGS all all-am check check-am clean clean-generic \ clean-libLTLIBRARIES clean-libtool clean-local cscopelist-am \ ctags ctags-am distclean distclean-compile distclean-generic \ distclean-libtool distclean-tags distdir dvi dvi-am html \ html-am info info-am install install-am install-data \ install-data-am install-dvi install-dvi-am install-exec \ install-exec-am install-html install-html-am \ install-include_laHEADERS install-info install-info-am \ install-libLTLIBRARIES install-man install-pdf install-pdf-am \ install-ps install-ps-am install-strip installcheck \ installcheck-am installdirs maintainer-clean \ maintainer-clean-generic maintainer-clean-local mostlyclean \ mostlyclean-compile mostlyclean-generic mostlyclean-libtool \ pdf pdf-am ps ps-am tags tags-am uninstall uninstall-am \ uninstall-include_laHEADERS uninstall-libLTLIBRARIES itab.c itab.h: $(OPTABLE) \ $(top_srcdir)/scripts/ud_itab.py \ $(top_srcdir)/scripts/ud_opcode.py \ $(top_srcdir)/scripts/ud_optable.py $(PYTHON) $(top_srcdir)/scripts/ud_itab.py $(OPTABLE) $(srcdir) clean-local: rm -rf $(BUILT_SOURCES) maintainer-clean-local: # Tell versions [3.59,3.63) of GNU make to not export all variables. # Otherwise a system limit (for SysV at least) may be exceeded. .NOEXPORT: ================================================ FILE: dis/d.lb1 ================================================ +'decode.obj' +'itab.obj' +'syn-att.obj' +'syn-intel.obj' +'syn.obj' +'udis86.obj' ================================================ FILE: dis/d.mk ================================================ project : F:\TOOLS\ASM\full2\dis\d.lib .SYMBOLIC !include F:\TOOLS\ASM\full2\dis\d.mk1 ================================================ FILE: dis/d.mk1 ================================================ !define BLANK "" F:\TOOLS\ASM\full2\dis\decode.obj : F:\TOOLS\ASM\full2\dis\decode.c .AUTODEP& END @F: cd F:\TOOLS\ASM\full2\dis *wcc decode.c -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml F:\TOOLS\ASM\full2\dis\itab.obj : F:\TOOLS\ASM\full2\dis\itab.c .AUTODEPEND @F: cd F:\TOOLS\ASM\full2\dis *wcc itab.c -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml F:\TOOLS\ASM\full2\dis\syn-att.obj : F:\TOOLS\ASM\full2\dis\syn-att.c .AUTOD& EPEND @F: cd F:\TOOLS\ASM\full2\dis *wcc syn-att.c -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml F:\TOOLS\ASM\full2\dis\syn-intel.obj : F:\TOOLS\ASM\full2\dis\syn-intel.c .A& UTODEPEND @F: cd F:\TOOLS\ASM\full2\dis *wcc syn-intel.c -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml F:\TOOLS\ASM\full2\dis\syn.obj : F:\TOOLS\ASM\full2\dis\syn.c .AUTODEPEND @F: cd F:\TOOLS\ASM\full2\dis *wcc syn.c -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml F:\TOOLS\ASM\full2\dis\udis86.obj : F:\TOOLS\ASM\full2\dis\udis86.c .AUTODEP& END @F: cd F:\TOOLS\ASM\full2\dis *wcc udis86.c -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml F:\TOOLS\ASM\full2\dis\d.lib : F:\TOOLS\ASM\full2\dis\decode.obj F:\TOOLS\AS& M\full2\dis\itab.obj F:\TOOLS\ASM\full2\dis\syn-att.obj F:\TOOLS\ASM\full2\d& is\syn-intel.obj F:\TOOLS\ASM\full2\dis\syn.obj F:\TOOLS\ASM\full2\dis\udis8& 6.obj .AUTODEPEND @F: cd F:\TOOLS\ASM\full2\dis %create d.lb1 !ifneq BLANK "decode.obj itab.obj syn-att.obj syn-intel.obj syn.obj udis86.o& bj" @for %i in (decode.obj itab.obj syn-att.obj syn-intel.obj syn.obj udis86.ob& j) do @%append d.lb1 +'%i' !endif !ifneq BLANK "" @for %i in () do @%append d.lb1 +'%i' !endif *wlib -b -c -n -q -p=512 d.lib @d.lb1 ================================================ FILE: dis/d.tgt ================================================ 40 targetIdent 0 MProject 1 MComponent 0 2 WString 3 LIB 3 WString 5 d_6sn 1 0 1 4 MCommand 0 5 MCommand 0 6 MItem 5 d.lib 7 WString 3 LIB 8 WVList 0 9 WVList 0 -1 1 1 0 10 WPickList 7 11 MItem 3 *.c 12 WString 4 COBJ 13 WVList 0 14 WVList 0 -1 1 1 0 15 MItem 8 decode.c 16 WString 4 COBJ 17 WVList 0 18 WVList 0 11 1 1 0 19 MItem 6 itab.c 20 WString 4 COBJ 21 WVList 0 22 WVList 0 11 1 1 0 23 MItem 9 syn-att.c 24 WString 4 COBJ 25 WVList 0 26 WVList 0 11 1 1 0 27 MItem 11 syn-intel.c 28 WString 4 COBJ 29 WVList 0 30 WVList 0 11 1 1 0 31 MItem 5 syn.c 32 WString 4 COBJ 33 WVList 0 34 WVList 0 11 1 1 0 35 MItem 8 udis86.c 36 WString 4 COBJ 37 WVList 0 38 WVList 0 11 1 1 0 ================================================ FILE: dis/d.wpj ================================================ 40 projectIdent 0 VpeMain 1 WRect 0 0 7680 9210 2 MProject 3 MCommand 0 4 MCommand 0 1 5 WFileName 5 d.tgt 6 WVList 1 7 VComponent 8 WRect 0 0 5666 4280 0 0 9 WFileName 5 d.tgt 0 0 7 ================================================ FILE: dis/decode.c ================================================ /* udis86 - libudis86/decode.c * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "udint.h" #include "types.h" #include "decode.h" #ifndef __UD_STANDALONE__ # include #endif /* __UD_STANDALONE__ */ /* The max number of prefixes to an instruction */ #define MAX_PREFIXES 15 /* rex prefix bits */ #define REX_W(r) ( ( 0xF & ( r ) ) >> 3 ) #define REX_R(r) ( ( 0x7 & ( r ) ) >> 2 ) #define REX_X(r) ( ( 0x3 & ( r ) ) >> 1 ) #define REX_B(r) ( ( 0x1 & ( r ) ) >> 0 ) #define REX_PFX_MASK(n) ( ( P_REXW(n) << 3 ) | \ ( P_REXR(n) << 2 ) | \ ( P_REXX(n) << 1 ) | \ ( P_REXB(n) << 0 ) ) /* scable-index-base bits */ #define SIB_S(b) ( ( b ) >> 6 ) #define SIB_I(b) ( ( ( b ) >> 3 ) & 7 ) #define SIB_B(b) ( ( b ) & 7 ) /* modrm bits */ #define MODRM_REG(b) ( ( ( b ) >> 3 ) & 7 ) #define MODRM_NNN(b) ( ( ( b ) >> 3 ) & 7 ) #define MODRM_MOD(b) ( ( ( b ) >> 6 ) & 3 ) #define MODRM_RM(b) ( ( b ) & 7 ) static int decode_ext(struct ud *u, uint16_t ptr); enum reg_class { /* register classes */ REGCLASS_GPR, REGCLASS_MMX, REGCLASS_CR, REGCLASS_DB, REGCLASS_SEG, REGCLASS_XMM }; /* * inp_start * Should be called before each de-code operation. */ static void inp_start(struct ud *u) { u->inp_ctr = 0; } static uint8_t inp_next(struct ud *u) { if (u->inp_end == 0) { if (u->inp_buf != NULL) { if (u->inp_buf_index < u->inp_buf_size) { u->inp_ctr++; return (u->inp_curr = u->inp_buf[u->inp_buf_index++]); } } else { int c; if ((c = u->inp_hook(u)) != UD_EOI) { u->inp_curr = c; u->inp_sess[u->inp_ctr++] = u->inp_curr; return u->inp_curr; } } } u->inp_end = 1; UDERR(u, "byte expected, eoi received\n"); return 0; } static uint8_t inp_curr(struct ud *u) { return u->inp_curr; } /* * inp_uint8 * int_uint16 * int_uint32 * int_uint64 * Load little-endian values from input */ static uint8_t inp_uint8(struct ud* u) { return inp_next(u); } static uint16_t inp_uint16(struct ud* u) { uint16_t r, ret; ret = inp_next(u); r = inp_next(u); return ret | (r << 8); } static uint32_t inp_uint32(struct ud* u) { uint32_t r, ret; ret = inp_next(u); r = inp_next(u); ret = ret | (r << 8); r = inp_next(u); ret = ret | (r << 16); r = inp_next(u); return ret | (r << 24); } static uint64_t inp_uint64(struct ud* u) { uint64_t r, ret; ret = inp_next(u); r = inp_next(u); ret = ret | (r << 8); r = inp_next(u); ret = ret | (r << 16); r = inp_next(u); ret = ret | (r << 24); r = inp_next(u); ret = ret | (r << 32); r = inp_next(u); ret = ret | (r << 40); r = inp_next(u); ret = ret | (r << 48); r = inp_next(u); return ret | (r << 56); } static inline int eff_opr_mode(int dis_mode, int rex_w, int pfx_opr) { if (dis_mode == 64) { return rex_w ? 64 : (pfx_opr ? 16 : 32); } else if (dis_mode == 32) { return pfx_opr ? 16 : 32; } else { UD_ASSERT(dis_mode == 16); return pfx_opr ? 32 : 16; } } static inline int eff_adr_mode(int dis_mode, int pfx_adr) { if (dis_mode == 64) { return pfx_adr ? 32 : 64; } else if (dis_mode == 32) { return pfx_adr ? 16 : 32; } else { UD_ASSERT(dis_mode == 16); return pfx_adr ? 32 : 16; } } /* * decode_prefixes * * Extracts instruction prefixes. */ static int decode_prefixes(struct ud *u) { int done = 0; uint8_t curr, last = 0; UD_RETURN_ON_ERROR(u); do { last = curr; curr = inp_next(u); UD_RETURN_ON_ERROR(u); if (u->inp_ctr == MAX_INSN_LENGTH) { UD_RETURN_WITH_ERROR(u, "max instruction length"); } switch (curr) { case 0x2E: u->pfx_seg = UD_R_CS; break; case 0x36: u->pfx_seg = UD_R_SS; break; case 0x3E: u->pfx_seg = UD_R_DS; break; case 0x26: u->pfx_seg = UD_R_ES; break; case 0x64: u->pfx_seg = UD_R_FS; break; case 0x65: u->pfx_seg = UD_R_GS; break; case 0x67: /* adress-size override prefix */ u->pfx_adr = 0x67; break; case 0xF0: u->pfx_lock = 0xF0; break; case 0x66: u->pfx_opr = 0x66; break; case 0xF2: u->pfx_str = 0xf2; break; case 0xF3: u->pfx_str = 0xf3; break; default: /* consume if rex */ done = (u->dis_mode == 64 && (curr & 0xF0) == 0x40) ? 0 : 1; break; } } while (!done); /* rex prefixes in 64bit mode, must be the last prefix */ if (u->dis_mode == 64 && (last & 0xF0) == 0x40) { u->pfx_rex = last; } return 0; } static inline unsigned int modrm( struct ud * u ) { if ( !u->have_modrm ) { u->modrm = inp_next( u ); u->have_modrm = 1; } return u->modrm; } static unsigned int resolve_operand_size( const struct ud * u, unsigned int s ) { switch ( s ) { case SZ_V: return ( u->opr_mode ); case SZ_Z: return ( u->opr_mode == 16 ) ? 16 : 32; case SZ_Y: return ( u->opr_mode == 16 ) ? 32 : u->opr_mode; case SZ_RDQ: return ( u->dis_mode == 64 ) ? 64 : 32; default: return s; } } static int resolve_mnemonic( struct ud* u ) { /* resolve 3dnow weirdness. */ if ( u->mnemonic == UD_I3dnow ) { u->mnemonic = ud_itab[ u->le->table[ inp_curr( u ) ] ].mnemonic; } /* SWAPGS is only valid in 64bits mode */ if ( u->mnemonic == UD_Iswapgs && u->dis_mode != 64 ) { UDERR(u, "swapgs invalid in 64bits mode\n"); return -1; } if (u->mnemonic == UD_Ixchg) { if ((u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_AX && u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_AX) || (u->operand[0].type == UD_OP_REG && u->operand[0].base == UD_R_EAX && u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_EAX)) { u->operand[0].type = UD_NONE; u->operand[1].type = UD_NONE; u->mnemonic = UD_Inop; } } if (u->mnemonic == UD_Inop && u->pfx_repe) { u->pfx_repe = 0; u->mnemonic = UD_Ipause; } return 0; } /* ----------------------------------------------------------------------------- * decode_a()- Decodes operands of the type seg:offset * ----------------------------------------------------------------------------- */ static void decode_a(struct ud* u, struct ud_operand *op) { if (u->opr_mode == 16) { /* seg16:off16 */ op->type = UD_OP_PTR; op->size = 32; op->lval.ptr.off = inp_uint16(u); op->lval.ptr.seg = inp_uint16(u); } else { /* seg16:off32 */ op->type = UD_OP_PTR; op->size = 48; op->lval.ptr.off = inp_uint32(u); op->lval.ptr.seg = inp_uint16(u); } } /* ----------------------------------------------------------------------------- * decode_gpr() - Returns decoded General Purpose Register * ----------------------------------------------------------------------------- */ static enum ud_type decode_gpr(register struct ud* u, unsigned int s, unsigned char rm) { switch (s) { case 64: return UD_R_RAX + rm; case 32: return UD_R_EAX + rm; case 16: return UD_R_AX + rm; case 8: if (u->dis_mode == 64 && u->pfx_rex) { if (rm >= 4) return UD_R_SPL + (rm-4); return UD_R_AL + rm; } else return UD_R_AL + rm; case 0: /* invalid size in case of a decode error */ UD_ASSERT(u->error); return UD_NONE; default: UD_ASSERT(!"invalid operand size"); return UD_NONE; } } static void decode_reg(struct ud *u, struct ud_operand *opr, int type, int num, int size) { int reg; size = resolve_operand_size(u, size); switch (type) { case REGCLASS_GPR : reg = decode_gpr(u, size, num); break; case REGCLASS_MMX : reg = UD_R_MM0 + (num & 7); break; case REGCLASS_XMM : reg = UD_R_XMM0 + num; break; case REGCLASS_CR : reg = UD_R_CR0 + num; break; case REGCLASS_DB : reg = UD_R_DR0 + num; break; case REGCLASS_SEG : { /* * Only 6 segment registers, anything else is an error. */ if ((num & 7) > 5) { UDERR(u, "invalid segment register value\n"); return; } else { reg = UD_R_ES + (num & 7); } break; } default: UD_ASSERT(!"invalid register type"); return; } opr->type = UD_OP_REG; opr->base = reg; opr->size = size; } /* * decode_imm * * Decode Immediate values. */ static void decode_imm(struct ud* u, unsigned int size, struct ud_operand *op) { op->size = resolve_operand_size(u, size); op->type = UD_OP_IMM; switch (op->size) { case 8: op->lval.sbyte = inp_uint8(u); break; case 16: op->lval.uword = inp_uint16(u); break; case 32: op->lval.udword = inp_uint32(u); break; case 64: op->lval.uqword = inp_uint64(u); break; default: return; } } /* * decode_mem_disp * * Decode mem address displacement. */ static void decode_mem_disp(struct ud* u, unsigned int size, struct ud_operand *op) { switch (size) { case 8: op->offset = 8; op->lval.ubyte = inp_uint8(u); break; case 16: op->offset = 16; op->lval.uword = inp_uint16(u); break; case 32: op->offset = 32; op->lval.udword = inp_uint32(u); break; case 64: op->offset = 64; op->lval.uqword = inp_uint64(u); break; default: return; } } /* * decode_modrm_reg * * Decodes reg field of mod/rm byte * */ static inline void decode_modrm_reg(struct ud *u, struct ud_operand *operand, unsigned int type, unsigned int size) { uint8_t reg = (REX_R(u->pfx_rex) << 3) | MODRM_REG(modrm(u)); decode_reg(u, operand, type, reg, size); } /* * decode_modrm_rm * * Decodes rm field of mod/rm byte * */ static void decode_modrm_rm(struct ud *u, struct ud_operand *op, unsigned char type, /* register type */ unsigned int size) /* operand size */ { size_t offset = 0; unsigned char mod, rm; /* get mod, r/m and reg fields */ mod = MODRM_MOD(modrm(u)); rm = (REX_B(u->pfx_rex) << 3) | MODRM_RM(modrm(u)); /* * If mod is 11b, then the modrm.rm specifies a register. * */ if (mod == 3) { decode_reg(u, op, type, rm, size); return; } /* * !11b => Memory Address */ op->type = UD_OP_MEM; op->size = resolve_operand_size(u, size); if (u->adr_mode == 64) { op->base = UD_R_RAX + rm; if (mod == 1) { offset = 8; } else if (mod == 2) { offset = 32; } else if (mod == 0 && (rm & 7) == 5) { op->base = UD_R_RIP; offset = 32; } else { offset = 0; } /* * Scale-Index-Base (SIB) */ if ((rm & 7) == 4) { inp_next(u); op->scale = (1 << SIB_S(inp_curr(u))) & ~1; op->index = UD_R_RAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); op->base = UD_R_RAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); /* special conditions for base reference */ if (op->index == UD_R_RSP) { op->index = UD_NONE; op->scale = UD_NONE; } if (op->base == UD_R_RBP || op->base == UD_R_R13) { if (mod == 0) { op->base = UD_NONE; } if (mod == 1) { offset = 8; } else { offset = 32; } } } } else if (u->adr_mode == 32) { op->base = UD_R_EAX + rm; if (mod == 1) { offset = 8; } else if (mod == 2) { offset = 32; } else if (mod == 0 && rm == 5) { op->base = UD_NONE; offset = 32; } else { offset = 0; } /* Scale-Index-Base (SIB) */ if ((rm & 7) == 4) { inp_next(u); op->scale = (1 << SIB_S(inp_curr(u))) & ~1; op->index = UD_R_EAX + (SIB_I(inp_curr(u)) | (REX_X(u->pfx_rex) << 3)); op->base = UD_R_EAX + (SIB_B(inp_curr(u)) | (REX_B(u->pfx_rex) << 3)); if (op->index == UD_R_ESP) { op->index = UD_NONE; op->scale = UD_NONE; } /* special condition for base reference */ if (op->base == UD_R_EBP) { if (mod == 0) { op->base = UD_NONE; } if (mod == 1) { offset = 8; } else { offset = 32; } } } } else { const unsigned int bases[] = { UD_R_BX, UD_R_BX, UD_R_BP, UD_R_BP, UD_R_SI, UD_R_DI, UD_R_BP, UD_R_BX }; const unsigned int indices[] = { UD_R_SI, UD_R_DI, UD_R_SI, UD_R_DI, UD_NONE, UD_NONE, UD_NONE, UD_NONE }; op->base = bases[rm & 7]; op->index = indices[rm & 7]; if (mod == 0 && rm == 6) { offset = 16; op->base = UD_NONE; } else if (mod == 1) { offset = 8; } else if (mod == 2) { offset = 16; } } if (offset) { decode_mem_disp(u, offset, op); } } /* * decode_moffset * Decode offset-only memory operand */ static void decode_moffset(struct ud *u, unsigned int size, struct ud_operand *opr) { opr->type = UD_OP_MEM; opr->size = resolve_operand_size(u, size); decode_mem_disp(u, u->adr_mode, opr); } /* ----------------------------------------------------------------------------- * decode_operands() - Disassembles Operands. * ----------------------------------------------------------------------------- */ static int decode_operand(struct ud *u, struct ud_operand *operand, enum ud_operand_code type, unsigned int size) { operand->_oprcode = type; switch (type) { case OP_A : decode_a(u, operand); break; case OP_MR: decode_modrm_rm(u, operand, REGCLASS_GPR, MODRM_MOD(modrm(u)) == 3 ? Mx_reg_size(size) : Mx_mem_size(size)); break; case OP_F: u->br_far = 1; /* intended fall through */ case OP_M: if (MODRM_MOD(modrm(u)) == 3) { UDERR(u, "expected modrm.mod != 3\n"); } /* intended fall through */ case OP_E: decode_modrm_rm(u, operand, REGCLASS_GPR, size); break; case OP_G: decode_modrm_reg(u, operand, REGCLASS_GPR, size); break; case OP_sI: case OP_I: decode_imm(u, size, operand); break; case OP_I1: operand->type = UD_OP_CONST; operand->lval.udword = 1; break; case OP_N: if (MODRM_MOD(modrm(u)) != 3) { UDERR(u, "expected modrm.mod == 3\n"); } /* intended fall through */ case OP_Q: decode_modrm_rm(u, operand, REGCLASS_MMX, size); break; case OP_P: decode_modrm_reg(u, operand, REGCLASS_MMX, size); break; case OP_U: if (MODRM_MOD(modrm(u)) != 3) { UDERR(u, "expected modrm.mod == 3\n"); } /* intended fall through */ case OP_W: decode_modrm_rm(u, operand, REGCLASS_XMM, size); break; case OP_V: decode_modrm_reg(u, operand, REGCLASS_XMM, size); break; case OP_MU: decode_modrm_rm(u, operand, REGCLASS_XMM, MODRM_MOD(modrm(u)) == 3 ? Mx_reg_size(size) : Mx_mem_size(size)); break; case OP_S: decode_modrm_reg(u, operand, REGCLASS_SEG, size); break; case OP_O: decode_moffset(u, size, operand); break; case OP_R0: case OP_R1: case OP_R2: case OP_R3: case OP_R4: case OP_R5: case OP_R6: case OP_R7: decode_reg(u, operand, REGCLASS_GPR, (REX_B(u->pfx_rex) << 3) | (type - OP_R0), size); break; case OP_AL: case OP_AX: case OP_eAX: case OP_rAX: decode_reg(u, operand, REGCLASS_GPR, 0, size); break; case OP_CL: case OP_CX: case OP_eCX: decode_reg(u, operand, REGCLASS_GPR, 1, size); break; case OP_DL: case OP_DX: case OP_eDX: decode_reg(u, operand, REGCLASS_GPR, 2, size); break; case OP_ES: case OP_CS: case OP_DS: case OP_SS: case OP_FS: case OP_GS: /* in 64bits mode, only fs and gs are allowed */ if (u->dis_mode == 64) { if (type != OP_FS && type != OP_GS) { UDERR(u, "invalid segment register in 64bits\n"); } } operand->type = UD_OP_REG; operand->base = (type - OP_ES) + UD_R_ES; operand->size = 16; break; case OP_J : decode_imm(u, size, operand); operand->type = UD_OP_JIMM; break ; case OP_R : if (MODRM_MOD(modrm(u)) != 3) { UDERR(u, "expected modrm.mod == 3\n"); } decode_modrm_rm(u, operand, REGCLASS_GPR, size); break; case OP_C: decode_modrm_reg(u, operand, REGCLASS_CR, size); break; case OP_D: decode_modrm_reg(u, operand, REGCLASS_DB, size); break; case OP_I3 : operand->type = UD_OP_CONST; operand->lval.sbyte = 3; break; case OP_ST0: case OP_ST1: case OP_ST2: case OP_ST3: case OP_ST4: case OP_ST5: case OP_ST6: case OP_ST7: operand->type = UD_OP_REG; operand->base = (type - OP_ST0) + UD_R_ST0; operand->size = 80; break; default : break; } return 0; } /* * decode_operands * * Disassemble upto 3 operands of the current instruction being * disassembled. By the end of the function, the operand fields * of the ud structure will have been filled. */ static int decode_operands(struct ud* u) { decode_operand(u, &u->operand[0], u->itab_entry->operand1.type, u->itab_entry->operand1.size); decode_operand(u, &u->operand[1], u->itab_entry->operand2.type, u->itab_entry->operand2.size); decode_operand(u, &u->operand[2], u->itab_entry->operand3.type, u->itab_entry->operand3.size); return 0; } /* ----------------------------------------------------------------------------- * clear_insn() - clear instruction structure * ----------------------------------------------------------------------------- */ static void clear_insn(register struct ud* u) { u->error = 0; u->pfx_seg = 0; u->pfx_opr = 0; u->pfx_adr = 0; u->pfx_lock = 0; u->pfx_repne = 0; u->pfx_rep = 0; u->pfx_repe = 0; u->pfx_rex = 0; u->pfx_str = 0; u->mnemonic = UD_Inone; u->itab_entry = NULL; u->have_modrm = 0; u->br_far = 0; memset( &u->operand[ 0 ], 0, sizeof( struct ud_operand ) ); memset( &u->operand[ 1 ], 0, sizeof( struct ud_operand ) ); memset( &u->operand[ 2 ], 0, sizeof( struct ud_operand ) ); } static inline int resolve_pfx_str(struct ud* u) { if (u->pfx_str == 0xf3) { if (P_STR(u->itab_entry->prefix)) { u->pfx_rep = 0xf3; } else { u->pfx_repe = 0xf3; } } else if (u->pfx_str == 0xf2) { u->pfx_repne = 0xf3; } return 0; } static int resolve_mode( struct ud* u ) { int default64; /* if in error state, bail out */ if ( u->error ) return -1; /* propagate prefix effects */ if ( u->dis_mode == 64 ) { /* set 64bit-mode flags */ /* Check validity of instruction m64 */ if ( P_INV64( u->itab_entry->prefix ) ) { UDERR(u, "instruction invalid in 64bits\n"); return -1; } /* effective rex prefix is the effective mask for the * instruction hard-coded in the opcode map. */ u->pfx_rex = ( u->pfx_rex & 0x40 ) | ( u->pfx_rex & REX_PFX_MASK( u->itab_entry->prefix ) ); /* whether this instruction has a default operand size of * 64bit, also hardcoded into the opcode map. */ default64 = P_DEF64( u->itab_entry->prefix ); /* calculate effective operand size */ if ( REX_W( u->pfx_rex ) ) { u->opr_mode = 64; } else if ( u->pfx_opr ) { u->opr_mode = 16; } else { /* unless the default opr size of instruction is 64, * the effective operand size in the absence of rex.w * prefix is 32. */ u->opr_mode = default64 ? 64 : 32; } /* calculate effective address size */ u->adr_mode = (u->pfx_adr) ? 32 : 64; } else if ( u->dis_mode == 32 ) { /* set 32bit-mode flags */ u->opr_mode = ( u->pfx_opr ) ? 16 : 32; u->adr_mode = ( u->pfx_adr ) ? 16 : 32; } else if ( u->dis_mode == 16 ) { /* set 16bit-mode flags */ u->opr_mode = ( u->pfx_opr ) ? 32 : 16; u->adr_mode = ( u->pfx_adr ) ? 32 : 16; } return 0; } static inline int decode_insn(struct ud *u, uint16_t ptr) { UD_ASSERT((ptr & 0x8000) == 0); u->itab_entry = &ud_itab[ ptr ]; u->mnemonic = u->itab_entry->mnemonic; return (resolve_pfx_str(u) == 0 && resolve_mode(u) == 0 && decode_operands(u) == 0 && resolve_mnemonic(u) == 0) ? 0 : -1; } /* * decode_3dnow() * * Decoding 3dnow is a little tricky because of its strange opcode * structure. The final opcode disambiguation depends on the last * byte that comes after the operands have been decoded. Fortunately, * all 3dnow instructions have the same set of operand types. So we * go ahead and decode the instruction by picking an arbitrarily chosen * valid entry in the table, decode the operands, and read the final * byte to resolve the menmonic. */ static inline int decode_3dnow(struct ud* u) { uint16_t ptr; UD_ASSERT(u->le->type == UD_TAB__OPC_3DNOW); UD_ASSERT(u->le->table[0xc] != 0); decode_insn(u, u->le->table[0xc]); inp_next(u); if (u->error) { return -1; } ptr = u->le->table[inp_curr(u)]; UD_ASSERT((ptr & 0x8000) == 0); u->mnemonic = ud_itab[ptr].mnemonic; return 0; } static int decode_ssepfx(struct ud *u) { uint8_t idx; uint8_t pfx; /* * String prefixes (f2, f3) take precedence over operand * size prefix (66). */ pfx = u->pfx_str; if (pfx == 0) { pfx = u->pfx_opr; } idx = ((pfx & 0xf) + 1) / 2; if (u->le->table[idx] == 0) { idx = 0; } if (idx && u->le->table[idx] != 0) { /* * "Consume" the prefix as a part of the opcode, so it is no * longer exported as an instruction prefix. */ u->pfx_str = 0; if (pfx == 0x66) { /* * consume "66" only if it was used for decoding, leaving * it to be used as an operands size override for some * simd instructions. */ u->pfx_opr = 0; } } return decode_ext(u, u->le->table[idx]); } /* * decode_ext() * * Decode opcode extensions (if any) */ static int decode_ext(struct ud *u, uint16_t ptr) { uint8_t idx = 0; if ((ptr & 0x8000) == 0) { return decode_insn(u, ptr); } u->le = &ud_lookup_table_list[(~0x8000 & ptr)]; if (u->le->type == UD_TAB__OPC_3DNOW) { return decode_3dnow(u); } switch (u->le->type) { case UD_TAB__OPC_MOD: /* !11 = 0, 11 = 1 */ idx = (MODRM_MOD(modrm(u)) + 1) / 4; break; /* disassembly mode/operand size/address size based tables. * 16 = 0,, 32 = 1, 64 = 2 */ case UD_TAB__OPC_MODE: idx = u->dis_mode != 64 ? 0 : 1; break; case UD_TAB__OPC_OSIZE: idx = eff_opr_mode(u->dis_mode, REX_W(u->pfx_rex), u->pfx_opr) / 32; break; case UD_TAB__OPC_ASIZE: idx = eff_adr_mode(u->dis_mode, u->pfx_adr) / 32; break; case UD_TAB__OPC_X87: idx = modrm(u) - 0xC0; break; case UD_TAB__OPC_VENDOR: if (u->vendor == UD_VENDOR_ANY) { /* choose a valid entry */ idx = (u->le->table[idx] != 0) ? 0 : 1; } else if (u->vendor == UD_VENDOR_AMD) { idx = 0; } else { idx = 1; } break; case UD_TAB__OPC_RM: idx = MODRM_RM(modrm(u)); break; case UD_TAB__OPC_REG: idx = MODRM_REG(modrm(u)); break; case UD_TAB__OPC_SSE: return decode_ssepfx(u); default: UD_ASSERT(!"not reached"); break; } return decode_ext(u, u->le->table[idx]); } static int decode_opcode(struct ud *u) { uint16_t ptr; UD_ASSERT(u->le->type == UD_TAB__OPC_TABLE); UD_RETURN_ON_ERROR(u); u->primary_opcode = inp_curr(u); ptr = u->le->table[inp_curr(u)]; if (ptr & 0x8000) { u->le = &ud_lookup_table_list[ptr & ~0x8000]; if (u->le->type == UD_TAB__OPC_TABLE) { inp_next(u); return decode_opcode(u); } } return decode_ext(u, ptr); } /* ============================================================================= * ud_decode() - Instruction decoder. Returns the number of bytes decoded. * ============================================================================= */ unsigned int ud_decode(struct ud *u) { inp_start(u); clear_insn(u); u->le = &ud_lookup_table_list[0]; u->error = decode_prefixes(u) == -1 || decode_opcode(u) == -1 || u->error; /* Handle decode error. */ if (u->error) { /* clear out the decode data. */ clear_insn(u); /* mark the sequence of bytes as invalid. */ u->itab_entry = &ud_itab[0]; /* entry 0 is invalid */ u->mnemonic = u->itab_entry->mnemonic; } /* maybe this stray segment override byte * should be spewed out? */ if ( !P_SEG( u->itab_entry->prefix ) && u->operand[0].type != UD_OP_MEM && u->operand[1].type != UD_OP_MEM ) u->pfx_seg = 0; u->insn_offset = u->pc; /* set offset of instruction */ u->asm_buf_fill = 0; /* set translation buffer index to 0 */ u->pc += u->inp_ctr; /* move program counter by bytes decoded */ /* return number of bytes disassembled. */ return u->inp_ctr; } /* vim: set ts=2 sw=2 expandtab */ ================================================ FILE: dis/decode.h ================================================ /* udis86 - libudis86/decode.h * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef UD_DECODE_H #define UD_DECODE_H #include "types.h" #include "itab.h" #define MAX_INSN_LENGTH 15 /* itab prefix bits */ #define P_none ( 0 ) #define P_cast ( 1 << 0 ) #define P_CAST(n) ( ( n >> 0 ) & 1 ) #define P_rexb ( 1 << 1 ) #define P_REXB(n) ( ( n >> 1 ) & 1 ) #define P_inv64 ( 1 << 4 ) #define P_INV64(n) ( ( n >> 4 ) & 1 ) #define P_rexw ( 1 << 5 ) #define P_REXW(n) ( ( n >> 5 ) & 1 ) #define P_def64 ( 1 << 7 ) #define P_DEF64(n) ( ( n >> 7 ) & 1 ) #define P_rexr ( 1 << 8 ) #define P_REXR(n) ( ( n >> 8 ) & 1 ) #define P_oso ( 1 << 9 ) #define P_OSO(n) ( ( n >> 9 ) & 1 ) #define P_aso ( 1 << 10 ) #define P_ASO(n) ( ( n >> 10 ) & 1 ) #define P_rexx ( 1 << 11 ) #define P_REXX(n) ( ( n >> 11 ) & 1 ) #define P_ImpAddr ( 1 << 12 ) #define P_IMPADDR(n) ( ( n >> 12 ) & 1 ) #define P_seg ( 1 << 13 ) #define P_SEG(n) ( ( n >> 13 ) & 1 ) #define P_str ( 1 << 14 ) #define P_STR(n) ( ( n >> 14 ) & 1 ) #define P_strz ( 1 << 15 ) #define P_STR_ZF(n) ( ( n >> 15 ) & 1 ) /* operand type constants -- order is important! */ enum ud_operand_code { OP_NONE, OP_A, OP_E, OP_M, OP_G, OP_I, OP_F, OP_R0, OP_R1, OP_R2, OP_R3, OP_R4, OP_R5, OP_R6, OP_R7, OP_AL, OP_CL, OP_DL, OP_AX, OP_CX, OP_DX, OP_eAX, OP_eCX, OP_eDX, OP_rAX, OP_rCX, OP_rDX, OP_ES, OP_CS, OP_SS, OP_DS, OP_FS, OP_GS, OP_ST0, OP_ST1, OP_ST2, OP_ST3, OP_ST4, OP_ST5, OP_ST6, OP_ST7, OP_J, OP_S, OP_O, OP_I1, OP_I3, OP_sI, OP_V, OP_W, OP_Q, OP_P, OP_U, OP_N, OP_MU, OP_R, OP_C, OP_D, OP_MR } UD_ATTR_PACKED; /* operand size constants */ enum ud_operand_size { SZ_NA = 0, SZ_Z = 1, SZ_V = 2, SZ_RDQ = 7, /* the following values are used as is, * and thus hard-coded. changing them * will break internals */ SZ_B = 8, SZ_W = 16, SZ_D = 32, SZ_Q = 64, SZ_T = 80, SZ_O = 128, SZ_Y = 17, /* * complex size types, that encode sizes for operands * of type MR (memory or register), for internal use * only. Id space 256 and above. */ SZ_BD = (SZ_B << 8) | SZ_D, SZ_BV = (SZ_B << 8) | SZ_V, SZ_WD = (SZ_W << 8) | SZ_D, SZ_WV = (SZ_W << 8) | SZ_V, SZ_WY = (SZ_W << 8) | SZ_Y, SZ_DY = (SZ_D << 8) | SZ_Y, SZ_WO = (SZ_W << 8) | SZ_O, SZ_DO = (SZ_D << 8) | SZ_O, SZ_QO = (SZ_Q << 8) | SZ_O, } UD_ATTR_PACKED; /* resolve complex size type. */ static inline enum ud_operand_size Mx_mem_size(enum ud_operand_size size) { return (size >> 8) & 0xff; } static inline enum ud_operand_size Mx_reg_size(enum ud_operand_size size) { return size & 0xff; } /* A single operand of an entry in the instruction table. * (internal use only) */ struct ud_itab_entry_operand { enum ud_operand_code type; enum ud_operand_size size; }; /* A single entry in an instruction table. *(internal use only) */ struct ud_itab_entry { enum ud_mnemonic_code mnemonic; struct ud_itab_entry_operand operand1; struct ud_itab_entry_operand operand2; struct ud_itab_entry_operand operand3; uint32_t prefix; }; struct ud_lookup_table_list_entry { const uint16_t *table; enum ud_table_type type; const char *meta; }; static inline int ud_opcode_field_sext(uint8_t primary_opcode) { return (primary_opcode & 0x02) != 0; } extern struct ud_itab_entry ud_itab[]; extern struct ud_lookup_table_list_entry ud_lookup_table_list[]; #endif /* UD_DECODE_H */ /* vim:cindent * vim:expandtab * vim:ts=4 * vim:sw=4 */ ================================================ FILE: dis/dism.lk1 ================================================ FIL decode.obj,itab.obj,main.obj,syn-att.obj,syn-intel.obj,syn.obj,udis86.obj ================================================ FILE: dis/dism.mk ================================================ project : F:\TOOLS\ASM\full2\dis\dism.exe .SYMBOLIC !include F:\TOOLS\ASM\full2\dis\dism.mk1 ================================================ FILE: dis/dism.mk1 ================================================ !define BLANK "" F:\TOOLS\ASM\full2\dis\decode.obj : F:\TOOLS\ASM\full2\dis\decode.c .AUTODEP& END @F: cd F:\TOOLS\ASM\full2\dis *wcc decode.c -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml F:\TOOLS\ASM\full2\dis\itab.obj : F:\TOOLS\ASM\full2\dis\itab.c .AUTODEPEND @F: cd F:\TOOLS\ASM\full2\dis *wcc itab.c -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml F:\TOOLS\ASM\full2\dis\main.obj : F:\TOOLS\ASM\full2\dis\main.c .AUTODEPEND @F: cd F:\TOOLS\ASM\full2\dis *wcc main.c -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml F:\TOOLS\ASM\full2\dis\syn-att.obj : F:\TOOLS\ASM\full2\dis\syn-att.c .AUTOD& EPEND @F: cd F:\TOOLS\ASM\full2\dis *wcc syn-att.c -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml F:\TOOLS\ASM\full2\dis\syn-intel.obj : F:\TOOLS\ASM\full2\dis\syn-intel.c .A& UTODEPEND @F: cd F:\TOOLS\ASM\full2\dis *wcc syn-intel.c -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml F:\TOOLS\ASM\full2\dis\syn.obj : F:\TOOLS\ASM\full2\dis\syn.c .AUTODEPEND @F: cd F:\TOOLS\ASM\full2\dis *wcc syn.c -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml F:\TOOLS\ASM\full2\dis\udis86.obj : F:\TOOLS\ASM\full2\dis\udis86.c .AUTODEP& END @F: cd F:\TOOLS\ASM\full2\dis *wcc udis86.c -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml F:\TOOLS\ASM\full2\dis\dism.exe : F:\TOOLS\ASM\full2\dis\decode.obj F:\TOOLS& \ASM\full2\dis\itab.obj F:\TOOLS\ASM\full2\dis\main.obj F:\TOOLS\ASM\full2\d& is\syn-att.obj F:\TOOLS\ASM\full2\dis\syn-intel.obj F:\TOOLS\ASM\full2\dis\s& yn.obj F:\TOOLS\ASM\full2\dis\udis86.obj F:\TOOLS\ASM\full2\dis\decode.h F:\& TOOLS\ASM\full2\dis\extern.h F:\TOOLS\ASM\full2\dis\itab.h F:\TOOLS\ASM\full& 2\dis\syn.h F:\TOOLS\ASM\full2\dis\types.h F:\TOOLS\ASM\full2\dis\udint.h .A& UTODEPEND @F: cd F:\TOOLS\ASM\full2\dis @%write dism.lk1 FIL decode.obj,itab.obj,main.obj,syn-att.obj,syn-intel.obj& ,syn.obj,udis86.obj @%append dism.lk1 *wlink name dism d all sys dos op m op maxe=25 op q op symf @dism.lk1 ================================================ FILE: dis/dism.tgt ================================================ 40 targetIdent 0 MProject 1 MComponent 0 2 WString 3 EXE 3 WString 5 de6en 1 0 1 4 MCommand 0 5 MCommand 0 6 MItem 8 dism.exe 7 WString 3 EXE 8 WVList 0 9 WVList 0 -1 1 1 0 10 WPickList 15 11 MItem 3 *.c 12 WString 4 COBJ 13 WVList 0 14 WVList 0 -1 1 1 0 15 MItem 8 decode.c 16 WString 4 COBJ 17 WVList 0 18 WVList 0 11 1 1 0 19 MItem 6 itab.c 20 WString 4 COBJ 21 WVList 0 22 WVList 0 11 1 1 0 23 MItem 6 main.c 24 WString 4 COBJ 25 WVList 0 26 WVList 0 11 1 1 0 27 MItem 9 syn-att.c 28 WString 4 COBJ 29 WVList 0 30 WVList 0 11 1 1 0 31 MItem 11 syn-intel.c 32 WString 4 COBJ 33 WVList 0 34 WVList 0 11 1 1 0 35 MItem 5 syn.c 36 WString 4 COBJ 37 WVList 0 38 WVList 0 11 1 1 0 39 MItem 8 udis86.c 40 WString 4 COBJ 41 WVList 0 42 WVList 0 11 1 1 0 43 MItem 3 *.h 44 WString 3 NIL 45 WVList 0 46 WVList 0 -1 1 1 0 47 MItem 8 decode.h 48 WString 3 NIL 49 WVList 0 50 WVList 0 43 1 1 0 51 MItem 8 extern.h 52 WString 3 NIL 53 WVList 0 54 WVList 0 43 1 1 0 55 MItem 6 itab.h 56 WString 3 NIL 57 WVList 0 58 WVList 0 43 1 1 0 59 MItem 5 syn.h 60 WString 3 NIL 61 WVList 0 62 WVList 0 43 1 1 0 63 MItem 7 types.h 64 WString 3 NIL 65 WVList 0 66 WVList 0 43 1 1 0 67 MItem 7 udint.h 68 WString 3 NIL 69 WVList 0 70 WVList 0 43 1 1 0 ================================================ FILE: dis/dism.txt ================================================ cd F:\TOOLS\ASM\full2\dis wmake -f F:\TOOLS\ASM\full2\dis\dism.mk -h -e wcc main.c -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml wlink name dism d all sys dos op m op maxe=25 op q op symf @dism.lk1 Execution complete ================================================ FILE: dis/dism.wpj ================================================ 40 projectIdent 0 VpeMain 1 WRect 0 0 7680 9210 2 MProject 3 MCommand 0 4 MCommand 0 1 5 WFileName 8 dism.tgt 6 WVList 1 7 VComponent 8 WRect 0 0 5666 4280 0 0 9 WFileName 8 dism.tgt 0 3 7 ================================================ FILE: dis/extern.h ================================================ /* udis86 - libudis86/extern.h * * Copyright (c) 2002-2009, 2013 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef UD_EXTERN_H #define UD_EXTERN_H #ifdef __cplusplus extern "C" { #endif #include "types.h" /* ============================= PUBLIC API ================================= */ extern void ud_init(struct ud*); extern void ud_set_mode(struct ud*, uint8_t); extern void ud_set_pc(struct ud*, uint64_t); extern void ud_set_input_hook(struct ud*, int (*)(struct ud*)); extern void ud_set_input_buffer(struct ud*, const uint8_t*, size_t); #ifndef __UD_STANDALONE__ extern void ud_set_input_file(struct ud*, FILE*); #endif /* __UD_STANDALONE__ */ extern void ud_set_vendor(struct ud*, unsigned); extern void ud_set_syntax(struct ud*, void (*)(struct ud*)); extern void ud_input_skip(struct ud*, size_t); extern int ud_input_end(const struct ud*); extern unsigned int ud_decode(struct ud*); extern unsigned int ud_disassemble(struct ud*); extern void ud_translate_intel(struct ud*); extern void ud_translate_att(struct ud*); extern const char* ud_insn_asm(const struct ud* u); extern const uint8_t* ud_insn_ptr(const struct ud* u); extern uint64_t ud_insn_off(const struct ud*); extern const char* ud_insn_hex(struct ud*); extern unsigned int ud_insn_len(const struct ud* u); extern const struct ud_operand* ud_insn_opr(const struct ud *u, unsigned int n); extern int ud_opr_is_sreg(const struct ud_operand *opr); extern int ud_opr_is_gpr(const struct ud_operand *opr); extern enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u); extern const char* ud_lookup_mnemonic(enum ud_mnemonic_code c); extern void ud_set_user_opaque_data(struct ud*, void*); extern void* ud_get_user_opaque_data(const struct ud*); extern uint64_t ud_insn_sext_imm(const struct ud*, const struct ud_operand*); extern void ud_set_asm_buffer(struct ud *u, char *buf, size_t size); extern void ud_set_sym_resolver(struct ud *u, const char* (*resolver)(struct ud*, uint64_t addr, int64_t *offset)); /* ========================================================================== */ #ifdef __cplusplus } #endif #endif /* UD_EXTERN_H */ ================================================ FILE: dis/itab.c ================================================ /* itab.c -- generated by udis86:scripts/ud_itab.py, do no edit */ #include "decode.h" #define GROUP(n) (0x8000 | (n)) static const uint16_t ud_itab__1[] = { /* 0 */ 7, 0, }; static const uint16_t ud_itab__2[] = { /* 0 */ 8, 0, }; static const uint16_t ud_itab__3[] = { /* 0 */ 15, 0, }; static const uint16_t ud_itab__6[] = { /* 0 */ 16, 0, 0, 0, }; static const uint16_t ud_itab__7[] = { /* 0 */ 17, 0, 0, 0, }; static const uint16_t ud_itab__8[] = { /* 0 */ 18, 0, 0, 0, }; static const uint16_t ud_itab__9[] = { /* 0 */ 19, 0, 0, 0, }; static const uint16_t ud_itab__10[] = { /* 0 */ 20, 0, 0, 0, }; static const uint16_t ud_itab__11[] = { /* 0 */ 21, 0, 0, 0, }; static const uint16_t ud_itab__5[] = { /* 0 */ GROUP(6), GROUP(7), GROUP(8), GROUP(9), /* 4 */ GROUP(10), GROUP(11), 0, 0, }; static const uint16_t ud_itab__15[] = { /* 0 */ 22, 0, }; static const uint16_t ud_itab__14[] = { /* 0 */ GROUP(15), 0, 0, 0, }; static const uint16_t ud_itab__17[] = { /* 0 */ 23, 0, }; static const uint16_t ud_itab__16[] = { /* 0 */ GROUP(17), 0, 0, 0, }; static const uint16_t ud_itab__19[] = { /* 0 */ 24, 0, }; static const uint16_t ud_itab__18[] = { /* 0 */ GROUP(19), 0, 0, 0, }; static const uint16_t ud_itab__21[] = { /* 0 */ 25, 0, }; static const uint16_t ud_itab__20[] = { /* 0 */ GROUP(21), 0, 0, 0, }; static const uint16_t ud_itab__23[] = { /* 0 */ 26, 0, }; static const uint16_t ud_itab__22[] = { /* 0 */ GROUP(23), 0, 0, 0, }; static const uint16_t ud_itab__25[] = { /* 0 */ 27, 0, }; static const uint16_t ud_itab__24[] = { /* 0 */ GROUP(25), 0, 0, 0, }; static const uint16_t ud_itab__27[] = { /* 0 */ 28, 0, }; static const uint16_t ud_itab__26[] = { /* 0 */ GROUP(27), 0, 0, 0, }; static const uint16_t ud_itab__13[] = { /* 0 */ GROUP(14), GROUP(16), GROUP(18), GROUP(20), /* 4 */ GROUP(22), 0, GROUP(24), GROUP(26), }; static const uint16_t ud_itab__32[] = { /* 0 */ 0, 29, 0, }; static const uint16_t ud_itab__31[] = { /* 0 */ 0, GROUP(32), }; static const uint16_t ud_itab__30[] = { /* 0 */ GROUP(31), 0, 0, 0, }; static const uint16_t ud_itab__35[] = { /* 0 */ 0, 30, 0, }; static const uint16_t ud_itab__34[] = { /* 0 */ 0, GROUP(35), }; static const uint16_t ud_itab__33[] = { /* 0 */ GROUP(34), 0, 0, 0, }; static const uint16_t ud_itab__38[] = { /* 0 */ 0, 31, 0, }; static const uint16_t ud_itab__37[] = { /* 0 */ 0, GROUP(38), }; static const uint16_t ud_itab__36[] = { /* 0 */ GROUP(37), 0, 0, 0, }; static const uint16_t ud_itab__41[] = { /* 0 */ 0, 32, 0, }; static const uint16_t ud_itab__40[] = { /* 0 */ 0, GROUP(41), }; static const uint16_t ud_itab__39[] = { /* 0 */ GROUP(40), 0, 0, 0, }; static const uint16_t ud_itab__29[] = { /* 0 */ 0, GROUP(30), GROUP(33), GROUP(36), /* 4 */ GROUP(39), 0, 0, 0, }; static const uint16_t ud_itab__44[] = { /* 0 */ 0, 33, }; static const uint16_t ud_itab__43[] = { /* 0 */ GROUP(44), 0, 0, 0, }; static const uint16_t ud_itab__46[] = { /* 0 */ 0, 34, }; static const uint16_t ud_itab__45[] = { /* 0 */ GROUP(46), 0, 0, 0, }; static const uint16_t ud_itab__42[] = { /* 0 */ GROUP(43), GROUP(45), 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__49[] = { /* 0 */ 0, 35, }; static const uint16_t ud_itab__48[] = { /* 0 */ GROUP(49), 0, 0, 0, }; static const uint16_t ud_itab__51[] = { /* 0 */ 0, 36, }; static const uint16_t ud_itab__50[] = { /* 0 */ GROUP(51), 0, 0, 0, }; static const uint16_t ud_itab__47[] = { /* 0 */ GROUP(48), GROUP(50), 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__55[] = { /* 0 */ 37, 0, 0, }; static const uint16_t ud_itab__54[] = { /* 0 */ 0, GROUP(55), }; static const uint16_t ud_itab__53[] = { /* 0 */ GROUP(54), 0, 0, 0, }; static const uint16_t ud_itab__58[] = { /* 0 */ 38, 0, 0, }; static const uint16_t ud_itab__57[] = { /* 0 */ 0, GROUP(58), }; static const uint16_t ud_itab__56[] = { /* 0 */ GROUP(57), 0, 0, 0, }; static const uint16_t ud_itab__61[] = { /* 0 */ 39, 0, 0, }; static const uint16_t ud_itab__60[] = { /* 0 */ 0, GROUP(61), }; static const uint16_t ud_itab__59[] = { /* 0 */ GROUP(60), 0, 0, 0, }; static const uint16_t ud_itab__64[] = { /* 0 */ 40, 0, 0, }; static const uint16_t ud_itab__63[] = { /* 0 */ 0, GROUP(64), }; static const uint16_t ud_itab__62[] = { /* 0 */ GROUP(63), 0, 0, 0, }; static const uint16_t ud_itab__67[] = { /* 0 */ 41, 0, 0, }; static const uint16_t ud_itab__66[] = { /* 0 */ 0, GROUP(67), }; static const uint16_t ud_itab__65[] = { /* 0 */ GROUP(66), 0, 0, 0, }; static const uint16_t ud_itab__70[] = { /* 0 */ 42, 0, 0, }; static const uint16_t ud_itab__69[] = { /* 0 */ 0, GROUP(70), }; static const uint16_t ud_itab__68[] = { /* 0 */ GROUP(69), 0, 0, 0, }; static const uint16_t ud_itab__73[] = { /* 0 */ 43, 0, 0, }; static const uint16_t ud_itab__72[] = { /* 0 */ 0, GROUP(73), }; static const uint16_t ud_itab__71[] = { /* 0 */ GROUP(72), 0, 0, 0, }; static const uint16_t ud_itab__76[] = { /* 0 */ 44, 0, 0, }; static const uint16_t ud_itab__75[] = { /* 0 */ 0, GROUP(76), }; static const uint16_t ud_itab__74[] = { /* 0 */ GROUP(75), 0, 0, 0, }; static const uint16_t ud_itab__52[] = { /* 0 */ GROUP(53), GROUP(56), GROUP(59), GROUP(62), /* 4 */ GROUP(65), GROUP(68), GROUP(71), GROUP(74), }; static const uint16_t ud_itab__78[] = { /* 0 */ 0, 45, }; static const uint16_t ud_itab__77[] = { /* 0 */ GROUP(78), 0, 0, 0, }; static const uint16_t ud_itab__80[] = { /* 0 */ 0, 46, }; static const uint16_t ud_itab__79[] = { /* 0 */ GROUP(80), 0, 0, 0, }; static const uint16_t ud_itab__83[] = { /* 0 */ 0, 47, }; static const uint16_t ud_itab__82[] = { /* 0 */ GROUP(83), 0, 0, 0, }; static const uint16_t ud_itab__86[] = { /* 0 */ 48, 0, 0, }; static const uint16_t ud_itab__85[] = { /* 0 */ 0, GROUP(86), }; static const uint16_t ud_itab__84[] = { /* 0 */ GROUP(85), 0, 0, 0, }; static const uint16_t ud_itab__81[] = { /* 0 */ GROUP(82), GROUP(84), 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__28[] = { /* 0 */ GROUP(29), GROUP(42), GROUP(47), GROUP(52), /* 4 */ GROUP(77), 0, GROUP(79), GROUP(81), }; static const uint16_t ud_itab__12[] = { /* 0 */ GROUP(13), GROUP(28), }; static const uint16_t ud_itab__87[] = { /* 0 */ 49, 0, 0, 0, }; static const uint16_t ud_itab__88[] = { /* 0 */ 50, 0, 0, 0, }; static const uint16_t ud_itab__89[] = { /* 0 */ 51, 0, 0, 0, }; static const uint16_t ud_itab__90[] = { /* 0 */ 52, 0, 0, 0, }; static const uint16_t ud_itab__91[] = { /* 0 */ 53, 0, 0, 0, }; static const uint16_t ud_itab__92[] = { /* 0 */ 54, 0, 0, 0, }; static const uint16_t ud_itab__93[] = { /* 0 */ 55, 0, 0, 0, }; static const uint16_t ud_itab__94[] = { /* 0 */ 56, 0, 0, 0, }; static const uint16_t ud_itab__96[] = { /* 0 */ 57, 0, 0, 0, }; static const uint16_t ud_itab__97[] = { /* 0 */ 58, 0, 0, 0, }; static const uint16_t ud_itab__98[] = { /* 0 */ 59, 0, 0, 0, }; static const uint16_t ud_itab__99[] = { /* 0 */ 60, 0, 0, 0, }; static const uint16_t ud_itab__100[] = { /* 0 */ 61, 0, 0, 0, }; static const uint16_t ud_itab__101[] = { /* 0 */ 62, 0, 0, 0, }; static const uint16_t ud_itab__102[] = { /* 0 */ 63, 0, 0, 0, }; static const uint16_t ud_itab__103[] = { /* 0 */ 64, 0, 0, 0, }; static const uint16_t ud_itab__95[] = { /* 0 */ GROUP(96), GROUP(97), GROUP(98), GROUP(99), /* 4 */ GROUP(100), GROUP(101), GROUP(102), GROUP(103), }; static const uint16_t ud_itab__104[] = { /* 0 */ 65, 0, 0, 0, }; static const uint16_t ud_itab__105[] = { /* 0 */ 0, 0, 0, 0, /* 4 */ 0, 0, 0, 0, /* 8 */ 0, 0, 0, 0, /* c */ 66, 67, 0, 0, /* 10 */ 0, 0, 0, 0, /* 14 */ 0, 0, 0, 0, /* 18 */ 0, 0, 0, 0, /* 1c */ 68, 69, 0, 0, /* 20 */ 0, 0, 0, 0, /* 24 */ 0, 0, 0, 0, /* 28 */ 0, 0, 0, 0, /* 2c */ 0, 0, 0, 0, /* 30 */ 0, 0, 0, 0, /* 34 */ 0, 0, 0, 0, /* 38 */ 0, 0, 0, 0, /* 3c */ 0, 0, 0, 0, /* 40 */ 0, 0, 0, 0, /* 44 */ 0, 0, 0, 0, /* 48 */ 0, 0, 0, 0, /* 4c */ 0, 0, 0, 0, /* 50 */ 0, 0, 0, 0, /* 54 */ 0, 0, 0, 0, /* 58 */ 0, 0, 0, 0, /* 5c */ 0, 0, 0, 0, /* 60 */ 0, 0, 0, 0, /* 64 */ 0, 0, 0, 0, /* 68 */ 0, 0, 0, 0, /* 6c */ 0, 0, 0, 0, /* 70 */ 0, 0, 0, 0, /* 74 */ 0, 0, 0, 0, /* 78 */ 0, 0, 0, 0, /* 7c */ 0, 0, 0, 0, /* 80 */ 0, 0, 0, 0, /* 84 */ 0, 0, 0, 0, /* 88 */ 0, 0, 70, 0, /* 8c */ 0, 0, 71, 0, /* 90 */ 72, 0, 0, 0, /* 94 */ 73, 0, 74, 75, /* 98 */ 0, 0, 76, 0, /* 9c */ 0, 0, 77, 0, /* a0 */ 78, 0, 0, 0, /* a4 */ 79, 0, 80, 81, /* a8 */ 0, 0, 82, 0, /* ac */ 0, 0, 83, 0, /* b0 */ 84, 0, 0, 0, /* b4 */ 85, 0, 86, 87, /* b8 */ 0, 0, 0, 88, /* bc */ 0, 0, 0, 89, /* c0 */ 0, 0, 0, 0, /* c4 */ 0, 0, 0, 0, /* c8 */ 0, 0, 0, 0, /* cc */ 0, 0, 0, 0, /* d0 */ 0, 0, 0, 0, /* d4 */ 0, 0, 0, 0, /* d8 */ 0, 0, 0, 0, /* dc */ 0, 0, 0, 0, /* e0 */ 0, 0, 0, 0, /* e4 */ 0, 0, 0, 0, /* e8 */ 0, 0, 0, 0, /* ec */ 0, 0, 0, 0, /* f0 */ 0, 0, 0, 0, /* f4 */ 0, 0, 0, 0, /* f8 */ 0, 0, 0, 0, /* fc */ 0, 0, 0, 0, }; static const uint16_t ud_itab__106[] = { /* 0 */ 90, 91, 92, 93, }; static const uint16_t ud_itab__107[] = { /* 0 */ 94, 95, 96, 97, }; static const uint16_t ud_itab__110[] = { /* 0 */ 98, 0, }; static const uint16_t ud_itab__111[] = { /* 0 */ 99, 0, }; static const uint16_t ud_itab__112[] = { /* 0 */ 100, 0, }; static const uint16_t ud_itab__113[] = { /* 0 */ 101, 0, }; static const uint16_t ud_itab__109[] = { /* 0 */ GROUP(110), GROUP(111), GROUP(112), GROUP(113), }; static const uint16_t ud_itab__115[] = { /* 0 */ 0, 102, }; static const uint16_t ud_itab__116[] = { /* 0 */ 0, 103, }; static const uint16_t ud_itab__117[] = { /* 0 */ 0, 104, }; static const uint16_t ud_itab__114[] = { /* 0 */ GROUP(115), GROUP(116), GROUP(117), 0, }; static const uint16_t ud_itab__108[] = { /* 0 */ GROUP(109), GROUP(114), }; static const uint16_t ud_itab__118[] = { /* 0 */ 105, 0, 0, 106, }; static const uint16_t ud_itab__119[] = { /* 0 */ 107, 0, 0, 108, }; static const uint16_t ud_itab__120[] = { /* 0 */ 109, 0, 0, 110, }; static const uint16_t ud_itab__123[] = { /* 0 */ 111, 0, }; static const uint16_t ud_itab__124[] = { /* 0 */ 112, 0, }; static const uint16_t ud_itab__125[] = { /* 0 */ 113, 0, }; static const uint16_t ud_itab__122[] = { /* 0 */ GROUP(123), 0, GROUP(124), GROUP(125), }; static const uint16_t ud_itab__127[] = { /* 0 */ 0, 114, }; static const uint16_t ud_itab__128[] = { /* 0 */ 0, 115, }; static const uint16_t ud_itab__126[] = { /* 0 */ GROUP(127), 0, GROUP(128), 0, }; static const uint16_t ud_itab__121[] = { /* 0 */ GROUP(122), GROUP(126), }; static const uint16_t ud_itab__129[] = { /* 0 */ 116, 0, 0, 117, }; static const uint16_t ud_itab__131[] = { /* 0 */ 118, 0, 0, 0, }; static const uint16_t ud_itab__132[] = { /* 0 */ 119, 0, 0, 0, }; static const uint16_t ud_itab__133[] = { /* 0 */ 120, 0, 0, 0, }; static const uint16_t ud_itab__134[] = { /* 0 */ 121, 0, 0, 0, }; static const uint16_t ud_itab__130[] = { /* 0 */ GROUP(131), GROUP(132), GROUP(133), GROUP(134), /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__135[] = { /* 0 */ 122, 0, 0, 0, }; static const uint16_t ud_itab__136[] = { /* 0 */ 123, 0, 0, 0, }; static const uint16_t ud_itab__137[] = { /* 0 */ 124, 0, 0, 0, }; static const uint16_t ud_itab__138[] = { /* 0 */ 125, 0, 0, 0, }; static const uint16_t ud_itab__139[] = { /* 0 */ 126, 0, 0, 0, }; static const uint16_t ud_itab__140[] = { /* 0 */ 127, 0, 0, 0, }; static const uint16_t ud_itab__141[] = { /* 0 */ 128, 0, 0, 0, }; static const uint16_t ud_itab__142[] = { /* 0 */ 129, 0, 0, 0, }; static const uint16_t ud_itab__143[] = { /* 0 */ 130, 0, 0, 0, }; static const uint16_t ud_itab__144[] = { /* 0 */ 131, 0, 0, 0, }; static const uint16_t ud_itab__145[] = { /* 0 */ 132, 0, 0, 0, }; static const uint16_t ud_itab__146[] = { /* 0 */ 133, 0, 0, 134, }; static const uint16_t ud_itab__147[] = { /* 0 */ 135, 0, 0, 136, }; static const uint16_t ud_itab__148[] = { /* 0 */ 137, 138, 139, 140, }; static const uint16_t ud_itab__149[] = { /* 0 */ 141, 0, 0, 142, }; static const uint16_t ud_itab__150[] = { /* 0 */ 143, 144, 145, 146, }; static const uint16_t ud_itab__151[] = { /* 0 */ 147, 148, 149, 150, }; static const uint16_t ud_itab__152[] = { /* 0 */ 151, 0, 0, 152, }; static const uint16_t ud_itab__153[] = { /* 0 */ 153, 0, 0, 154, }; static const uint16_t ud_itab__154[] = { /* 0 */ 155, 0, 0, 0, }; static const uint16_t ud_itab__155[] = { /* 0 */ 156, 0, 0, 0, }; static const uint16_t ud_itab__156[] = { /* 0 */ 157, 0, 0, 0, }; static const uint16_t ud_itab__157[] = { /* 0 */ 158, 0, 0, 0, }; static const uint16_t ud_itab__160[] = { /* 0 */ 0, 160, 0, }; static const uint16_t ud_itab__159[] = { /* 0 */ 159, GROUP(160), }; static const uint16_t ud_itab__158[] = { /* 0 */ GROUP(159), 0, 0, 0, }; static const uint16_t ud_itab__163[] = { /* 0 */ 0, 162, 0, }; static const uint16_t ud_itab__162[] = { /* 0 */ 161, GROUP(163), }; static const uint16_t ud_itab__161[] = { /* 0 */ GROUP(162), 0, 0, 0, }; static const uint16_t ud_itab__164[] = { /* 0 */ 163, 0, 0, 0, }; static const uint16_t ud_itab__166[] = { /* 0 */ 164, 0, 0, 165, }; static const uint16_t ud_itab__167[] = { /* 0 */ 166, 0, 0, 167, }; static const uint16_t ud_itab__168[] = { /* 0 */ 168, 0, 0, 169, }; static const uint16_t ud_itab__169[] = { /* 0 */ 170, 0, 0, 171, }; static const uint16_t ud_itab__170[] = { /* 0 */ 172, 0, 0, 173, }; static const uint16_t ud_itab__171[] = { /* 0 */ 174, 0, 0, 175, }; static const uint16_t ud_itab__172[] = { /* 0 */ 176, 0, 0, 177, }; static const uint16_t ud_itab__173[] = { /* 0 */ 178, 0, 0, 179, }; static const uint16_t ud_itab__174[] = { /* 0 */ 180, 0, 0, 181, }; static const uint16_t ud_itab__175[] = { /* 0 */ 182, 0, 0, 183, }; static const uint16_t ud_itab__176[] = { /* 0 */ 184, 0, 0, 185, }; static const uint16_t ud_itab__177[] = { /* 0 */ 186, 0, 0, 187, }; static const uint16_t ud_itab__178[] = { /* 0 */ 0, 0, 0, 188, }; static const uint16_t ud_itab__179[] = { /* 0 */ 0, 0, 0, 189, }; static const uint16_t ud_itab__180[] = { /* 0 */ 0, 0, 0, 190, }; static const uint16_t ud_itab__181[] = { /* 0 */ 0, 0, 0, 191, }; static const uint16_t ud_itab__182[] = { /* 0 */ 192, 0, 0, 193, }; static const uint16_t ud_itab__183[] = { /* 0 */ 194, 0, 0, 195, }; static const uint16_t ud_itab__184[] = { /* 0 */ 196, 0, 0, 197, }; static const uint16_t ud_itab__185[] = { /* 0 */ 0, 0, 0, 198, }; static const uint16_t ud_itab__186[] = { /* 0 */ 0, 0, 0, 199, }; static const uint16_t ud_itab__187[] = { /* 0 */ 0, 0, 0, 200, }; static const uint16_t ud_itab__188[] = { /* 0 */ 0, 0, 0, 201, }; static const uint16_t ud_itab__189[] = { /* 0 */ 0, 0, 0, 202, }; static const uint16_t ud_itab__190[] = { /* 0 */ 0, 0, 0, 203, }; static const uint16_t ud_itab__191[] = { /* 0 */ 0, 0, 0, 204, }; static const uint16_t ud_itab__192[] = { /* 0 */ 0, 0, 0, 205, }; static const uint16_t ud_itab__193[] = { /* 0 */ 0, 0, 0, 206, }; static const uint16_t ud_itab__194[] = { /* 0 */ 0, 0, 0, 207, }; static const uint16_t ud_itab__195[] = { /* 0 */ 0, 0, 0, 208, }; static const uint16_t ud_itab__196[] = { /* 0 */ 0, 0, 0, 209, }; static const uint16_t ud_itab__197[] = { /* 0 */ 0, 0, 0, 210, }; static const uint16_t ud_itab__198[] = { /* 0 */ 0, 0, 0, 211, }; static const uint16_t ud_itab__199[] = { /* 0 */ 0, 0, 0, 212, }; static const uint16_t ud_itab__200[] = { /* 0 */ 0, 0, 0, 213, }; static const uint16_t ud_itab__201[] = { /* 0 */ 0, 0, 0, 214, }; static const uint16_t ud_itab__202[] = { /* 0 */ 0, 0, 0, 215, }; static const uint16_t ud_itab__203[] = { /* 0 */ 0, 0, 0, 216, }; static const uint16_t ud_itab__204[] = { /* 0 */ 0, 0, 0, 217, }; static const uint16_t ud_itab__205[] = { /* 0 */ 0, 0, 0, 218, }; static const uint16_t ud_itab__206[] = { /* 0 */ 0, 0, 0, 219, }; static const uint16_t ud_itab__207[] = { /* 0 */ 0, 0, 0, 220, }; static const uint16_t ud_itab__208[] = { /* 0 */ 0, 0, 0, 221, }; static const uint16_t ud_itab__209[] = { /* 0 */ 0, 0, 0, 222, }; static const uint16_t ud_itab__210[] = { /* 0 */ 0, 0, 0, 223, }; static const uint16_t ud_itab__211[] = { /* 0 */ 0, 0, 0, 224, }; static const uint16_t ud_itab__214[] = { /* 0 */ 0, 225, 0, }; static const uint16_t ud_itab__213[] = { /* 0 */ 0, GROUP(214), }; static const uint16_t ud_itab__212[] = { /* 0 */ 0, 0, 0, GROUP(213), }; static const uint16_t ud_itab__217[] = { /* 0 */ 0, 226, 0, }; static const uint16_t ud_itab__216[] = { /* 0 */ 0, GROUP(217), }; static const uint16_t ud_itab__215[] = { /* 0 */ 0, 0, 0, GROUP(216), }; static const uint16_t ud_itab__218[] = { /* 0 */ 0, 0, 0, 227, }; static const uint16_t ud_itab__219[] = { /* 0 */ 0, 0, 0, 228, }; static const uint16_t ud_itab__220[] = { /* 0 */ 0, 0, 0, 229, }; static const uint16_t ud_itab__221[] = { /* 0 */ 0, 0, 0, 230, }; static const uint16_t ud_itab__222[] = { /* 0 */ 0, 0, 0, 231, }; static const uint16_t ud_itab__223[] = { /* 0 */ 232, 233, 0, 0, }; static const uint16_t ud_itab__224[] = { /* 0 */ 234, 235, 0, 0, }; static const uint16_t ud_itab__165[] = { /* 0 */ GROUP(166), GROUP(167), GROUP(168), GROUP(169), /* 4 */ GROUP(170), GROUP(171), GROUP(172), GROUP(173), /* 8 */ GROUP(174), GROUP(175), GROUP(176), GROUP(177), /* c */ 0, 0, 0, 0, /* 10 */ GROUP(178), 0, 0, 0, /* 14 */ GROUP(179), GROUP(180), 0, GROUP(181), /* 18 */ 0, 0, 0, 0, /* 1c */ GROUP(182), GROUP(183), GROUP(184), 0, /* 20 */ GROUP(185), GROUP(186), GROUP(187), GROUP(188), /* 24 */ GROUP(189), GROUP(190), 0, 0, /* 28 */ GROUP(191), GROUP(192), GROUP(193), GROUP(194), /* 2c */ 0, 0, 0, 0, /* 30 */ GROUP(195), GROUP(196), GROUP(197), GROUP(198), /* 34 */ GROUP(199), GROUP(200), 0, GROUP(201), /* 38 */ GROUP(202), GROUP(203), GROUP(204), GROUP(205), /* 3c */ GROUP(206), GROUP(207), GROUP(208), GROUP(209), /* 40 */ GROUP(210), GROUP(211), 0, 0, /* 44 */ 0, 0, 0, 0, /* 48 */ 0, 0, 0, 0, /* 4c */ 0, 0, 0, 0, /* 50 */ 0, 0, 0, 0, /* 54 */ 0, 0, 0, 0, /* 58 */ 0, 0, 0, 0, /* 5c */ 0, 0, 0, 0, /* 60 */ 0, 0, 0, 0, /* 64 */ 0, 0, 0, 0, /* 68 */ 0, 0, 0, 0, /* 6c */ 0, 0, 0, 0, /* 70 */ 0, 0, 0, 0, /* 74 */ 0, 0, 0, 0, /* 78 */ 0, 0, 0, 0, /* 7c */ 0, 0, 0, 0, /* 80 */ GROUP(212), GROUP(215), 0, 0, /* 84 */ 0, 0, 0, 0, /* 88 */ 0, 0, 0, 0, /* 8c */ 0, 0, 0, 0, /* 90 */ 0, 0, 0, 0, /* 94 */ 0, 0, 0, 0, /* 98 */ 0, 0, 0, 0, /* 9c */ 0, 0, 0, 0, /* a0 */ 0, 0, 0, 0, /* a4 */ 0, 0, 0, 0, /* a8 */ 0, 0, 0, 0, /* ac */ 0, 0, 0, 0, /* b0 */ 0, 0, 0, 0, /* b4 */ 0, 0, 0, 0, /* b8 */ 0, 0, 0, 0, /* bc */ 0, 0, 0, 0, /* c0 */ 0, 0, 0, 0, /* c4 */ 0, 0, 0, 0, /* c8 */ 0, 0, 0, 0, /* cc */ 0, 0, 0, 0, /* d0 */ 0, 0, 0, 0, /* d4 */ 0, 0, 0, 0, /* d8 */ 0, 0, 0, GROUP(218), /* dc */ GROUP(219), GROUP(220), GROUP(221), GROUP(222), /* e0 */ 0, 0, 0, 0, /* e4 */ 0, 0, 0, 0, /* e8 */ 0, 0, 0, 0, /* ec */ 0, 0, 0, 0, /* f0 */ GROUP(223), GROUP(224), 0, 0, /* f4 */ 0, 0, 0, 0, /* f8 */ 0, 0, 0, 0, /* fc */ 0, 0, 0, 0, }; static const uint16_t ud_itab__226[] = { /* 0 */ 0, 0, 0, 236, }; static const uint16_t ud_itab__227[] = { /* 0 */ 0, 0, 0, 237, }; static const uint16_t ud_itab__228[] = { /* 0 */ 0, 0, 0, 238, }; static const uint16_t ud_itab__229[] = { /* 0 */ 0, 0, 0, 239, }; static const uint16_t ud_itab__230[] = { /* 0 */ 0, 0, 0, 240, }; static const uint16_t ud_itab__231[] = { /* 0 */ 0, 0, 0, 241, }; static const uint16_t ud_itab__232[] = { /* 0 */ 0, 0, 0, 242, }; static const uint16_t ud_itab__233[] = { /* 0 */ 243, 0, 0, 244, }; static const uint16_t ud_itab__234[] = { /* 0 */ 0, 0, 0, 245, }; static const uint16_t ud_itab__235[] = { /* 0 */ 0, 0, 0, 246, }; static const uint16_t ud_itab__237[] = { /* 0 */ 247, 248, 249, }; static const uint16_t ud_itab__236[] = { /* 0 */ 0, 0, 0, GROUP(237), }; static const uint16_t ud_itab__238[] = { /* 0 */ 0, 0, 0, 250, }; static const uint16_t ud_itab__239[] = { /* 0 */ 0, 0, 0, 251, }; static const uint16_t ud_itab__240[] = { /* 0 */ 0, 0, 0, 252, }; static const uint16_t ud_itab__242[] = { /* 0 */ 253, 254, 255, }; static const uint16_t ud_itab__241[] = { /* 0 */ 0, 0, 0, GROUP(242), }; static const uint16_t ud_itab__243[] = { /* 0 */ 0, 0, 0, 256, }; static const uint16_t ud_itab__244[] = { /* 0 */ 0, 0, 0, 257, }; static const uint16_t ud_itab__245[] = { /* 0 */ 0, 0, 0, 258, }; static const uint16_t ud_itab__246[] = { /* 0 */ 0, 0, 0, 259, }; static const uint16_t ud_itab__247[] = { /* 0 */ 0, 0, 0, 260, }; static const uint16_t ud_itab__248[] = { /* 0 */ 0, 0, 0, 261, }; static const uint16_t ud_itab__249[] = { /* 0 */ 0, 0, 0, 262, }; static const uint16_t ud_itab__250[] = { /* 0 */ 0, 0, 0, 263, }; static const uint16_t ud_itab__251[] = { /* 0 */ 0, 0, 0, 264, }; static const uint16_t ud_itab__225[] = { /* 0 */ 0, 0, 0, 0, /* 4 */ 0, 0, 0, 0, /* 8 */ GROUP(226), GROUP(227), GROUP(228), GROUP(229), /* c */ GROUP(230), GROUP(231), GROUP(232), GROUP(233), /* 10 */ 0, 0, 0, 0, /* 14 */ GROUP(234), GROUP(235), GROUP(236), GROUP(238), /* 18 */ 0, 0, 0, 0, /* 1c */ 0, 0, 0, 0, /* 20 */ GROUP(239), GROUP(240), GROUP(241), 0, /* 24 */ 0, 0, 0, 0, /* 28 */ 0, 0, 0, 0, /* 2c */ 0, 0, 0, 0, /* 30 */ 0, 0, 0, 0, /* 34 */ 0, 0, 0, 0, /* 38 */ 0, 0, 0, 0, /* 3c */ 0, 0, 0, 0, /* 40 */ GROUP(243), GROUP(244), GROUP(245), 0, /* 44 */ GROUP(246), 0, 0, 0, /* 48 */ 0, 0, 0, 0, /* 4c */ 0, 0, 0, 0, /* 50 */ 0, 0, 0, 0, /* 54 */ 0, 0, 0, 0, /* 58 */ 0, 0, 0, 0, /* 5c */ 0, 0, 0, 0, /* 60 */ GROUP(247), GROUP(248), GROUP(249), GROUP(250), /* 64 */ 0, 0, 0, 0, /* 68 */ 0, 0, 0, 0, /* 6c */ 0, 0, 0, 0, /* 70 */ 0, 0, 0, 0, /* 74 */ 0, 0, 0, 0, /* 78 */ 0, 0, 0, 0, /* 7c */ 0, 0, 0, 0, /* 80 */ 0, 0, 0, 0, /* 84 */ 0, 0, 0, 0, /* 88 */ 0, 0, 0, 0, /* 8c */ 0, 0, 0, 0, /* 90 */ 0, 0, 0, 0, /* 94 */ 0, 0, 0, 0, /* 98 */ 0, 0, 0, 0, /* 9c */ 0, 0, 0, 0, /* a0 */ 0, 0, 0, 0, /* a4 */ 0, 0, 0, 0, /* a8 */ 0, 0, 0, 0, /* ac */ 0, 0, 0, 0, /* b0 */ 0, 0, 0, 0, /* b4 */ 0, 0, 0, 0, /* b8 */ 0, 0, 0, 0, /* bc */ 0, 0, 0, 0, /* c0 */ 0, 0, 0, 0, /* c4 */ 0, 0, 0, 0, /* c8 */ 0, 0, 0, 0, /* cc */ 0, 0, 0, 0, /* d0 */ 0, 0, 0, 0, /* d4 */ 0, 0, 0, 0, /* d8 */ 0, 0, 0, 0, /* dc */ 0, 0, 0, GROUP(251), /* e0 */ 0, 0, 0, 0, /* e4 */ 0, 0, 0, 0, /* e8 */ 0, 0, 0, 0, /* ec */ 0, 0, 0, 0, /* f0 */ 0, 0, 0, 0, /* f4 */ 0, 0, 0, 0, /* f8 */ 0, 0, 0, 0, /* fc */ 0, 0, 0, 0, }; static const uint16_t ud_itab__252[] = { /* 0 */ 265, 0, 0, 0, }; static const uint16_t ud_itab__253[] = { /* 0 */ 266, 0, 0, 0, }; static const uint16_t ud_itab__254[] = { /* 0 */ 267, 0, 0, 0, }; static const uint16_t ud_itab__255[] = { /* 0 */ 268, 0, 0, 0, }; static const uint16_t ud_itab__256[] = { /* 0 */ 269, 0, 0, 0, }; static const uint16_t ud_itab__257[] = { /* 0 */ 270, 0, 0, 0, }; static const uint16_t ud_itab__258[] = { /* 0 */ 271, 0, 0, 0, }; static const uint16_t ud_itab__259[] = { /* 0 */ 272, 0, 0, 0, }; static const uint16_t ud_itab__260[] = { /* 0 */ 273, 0, 0, 0, }; static const uint16_t ud_itab__261[] = { /* 0 */ 274, 0, 0, 0, }; static const uint16_t ud_itab__262[] = { /* 0 */ 275, 0, 0, 0, }; static const uint16_t ud_itab__263[] = { /* 0 */ 276, 0, 0, 0, }; static const uint16_t ud_itab__264[] = { /* 0 */ 277, 0, 0, 0, }; static const uint16_t ud_itab__265[] = { /* 0 */ 278, 0, 0, 0, }; static const uint16_t ud_itab__266[] = { /* 0 */ 279, 0, 0, 0, }; static const uint16_t ud_itab__267[] = { /* 0 */ 280, 0, 0, 0, }; static const uint16_t ud_itab__268[] = { /* 0 */ 281, 0, 0, 282, }; static const uint16_t ud_itab__269[] = { /* 0 */ 283, 284, 285, 286, }; static const uint16_t ud_itab__270[] = { /* 0 */ 287, 0, 288, 0, }; static const uint16_t ud_itab__271[] = { /* 0 */ 289, 0, 290, 0, }; static const uint16_t ud_itab__272[] = { /* 0 */ 291, 0, 0, 292, }; static const uint16_t ud_itab__273[] = { /* 0 */ 293, 0, 0, 294, }; static const uint16_t ud_itab__274[] = { /* 0 */ 295, 0, 0, 296, }; static const uint16_t ud_itab__275[] = { /* 0 */ 297, 0, 0, 298, }; static const uint16_t ud_itab__276[] = { /* 0 */ 299, 300, 301, 302, }; static const uint16_t ud_itab__277[] = { /* 0 */ 303, 304, 305, 306, }; static const uint16_t ud_itab__278[] = { /* 0 */ 307, 308, 309, 310, }; static const uint16_t ud_itab__279[] = { /* 0 */ 311, 0, 312, 313, }; static const uint16_t ud_itab__280[] = { /* 0 */ 314, 315, 316, 317, }; static const uint16_t ud_itab__281[] = { /* 0 */ 318, 319, 320, 321, }; static const uint16_t ud_itab__282[] = { /* 0 */ 322, 323, 324, 325, }; static const uint16_t ud_itab__283[] = { /* 0 */ 326, 327, 328, 329, }; static const uint16_t ud_itab__284[] = { /* 0 */ 330, 0, 0, 331, }; static const uint16_t ud_itab__285[] = { /* 0 */ 332, 0, 0, 333, }; static const uint16_t ud_itab__286[] = { /* 0 */ 334, 0, 0, 335, }; static const uint16_t ud_itab__287[] = { /* 0 */ 336, 0, 0, 337, }; static const uint16_t ud_itab__288[] = { /* 0 */ 338, 0, 0, 339, }; static const uint16_t ud_itab__289[] = { /* 0 */ 340, 0, 0, 341, }; static const uint16_t ud_itab__290[] = { /* 0 */ 342, 0, 0, 343, }; static const uint16_t ud_itab__291[] = { /* 0 */ 344, 0, 0, 345, }; static const uint16_t ud_itab__292[] = { /* 0 */ 346, 0, 0, 347, }; static const uint16_t ud_itab__293[] = { /* 0 */ 348, 0, 0, 349, }; static const uint16_t ud_itab__294[] = { /* 0 */ 350, 0, 0, 351, }; static const uint16_t ud_itab__295[] = { /* 0 */ 352, 0, 0, 353, }; static const uint16_t ud_itab__296[] = { /* 0 */ 0, 0, 0, 354, }; static const uint16_t ud_itab__297[] = { /* 0 */ 0, 0, 0, 355, }; static const uint16_t ud_itab__298[] = { /* 0 */ 356, 0, 0, 357, }; static const uint16_t ud_itab__299[] = { /* 0 */ 358, 0, 359, 360, }; static const uint16_t ud_itab__300[] = { /* 0 */ 361, 362, 363, 364, }; static const uint16_t ud_itab__302[] = { /* 0 */ 365, 0, 0, 366, }; static const uint16_t ud_itab__303[] = { /* 0 */ 367, 0, 0, 368, }; static const uint16_t ud_itab__304[] = { /* 0 */ 369, 0, 0, 370, }; static const uint16_t ud_itab__301[] = { /* 0 */ 0, 0, GROUP(302), 0, /* 4 */ GROUP(303), 0, GROUP(304), 0, }; static const uint16_t ud_itab__306[] = { /* 0 */ 371, 0, 0, 372, }; static const uint16_t ud_itab__307[] = { /* 0 */ 373, 0, 0, 374, }; static const uint16_t ud_itab__308[] = { /* 0 */ 375, 0, 0, 376, }; static const uint16_t ud_itab__305[] = { /* 0 */ 0, 0, GROUP(306), 0, /* 4 */ GROUP(307), 0, GROUP(308), 0, }; static const uint16_t ud_itab__310[] = { /* 0 */ 377, 0, 0, 378, }; static const uint16_t ud_itab__311[] = { /* 0 */ 0, 0, 0, 379, }; static const uint16_t ud_itab__312[] = { /* 0 */ 380, 0, 0, 381, }; static const uint16_t ud_itab__313[] = { /* 0 */ 0, 0, 0, 382, }; static const uint16_t ud_itab__309[] = { /* 0 */ 0, 0, GROUP(310), GROUP(311), /* 4 */ 0, 0, GROUP(312), GROUP(313), }; static const uint16_t ud_itab__314[] = { /* 0 */ 383, 0, 0, 384, }; static const uint16_t ud_itab__315[] = { /* 0 */ 385, 0, 0, 386, }; static const uint16_t ud_itab__316[] = { /* 0 */ 387, 0, 0, 388, }; static const uint16_t ud_itab__317[] = { /* 0 */ 389, 0, 0, 0, }; static const uint16_t ud_itab__319[] = { /* 0 */ 0, 390, 0, }; static const uint16_t ud_itab__318[] = { /* 0 */ GROUP(319), 0, 0, 0, }; static const uint16_t ud_itab__321[] = { /* 0 */ 0, 391, 0, }; static const uint16_t ud_itab__320[] = { /* 0 */ GROUP(321), 0, 0, 0, }; static const uint16_t ud_itab__322[] = { /* 0 */ 0, 392, 0, 393, }; static const uint16_t ud_itab__323[] = { /* 0 */ 0, 394, 0, 395, }; static const uint16_t ud_itab__324[] = { /* 0 */ 396, 0, 397, 398, }; static const uint16_t ud_itab__325[] = { /* 0 */ 399, 0, 400, 401, }; static const uint16_t ud_itab__326[] = { /* 0 */ 402, 0, 0, 0, }; static const uint16_t ud_itab__327[] = { /* 0 */ 403, 0, 0, 0, }; static const uint16_t ud_itab__328[] = { /* 0 */ 404, 0, 0, 0, }; static const uint16_t ud_itab__329[] = { /* 0 */ 405, 0, 0, 0, }; static const uint16_t ud_itab__330[] = { /* 0 */ 406, 0, 0, 0, }; static const uint16_t ud_itab__331[] = { /* 0 */ 407, 0, 0, 0, }; static const uint16_t ud_itab__332[] = { /* 0 */ 408, 0, 0, 0, }; static const uint16_t ud_itab__333[] = { /* 0 */ 409, 0, 0, 0, }; static const uint16_t ud_itab__334[] = { /* 0 */ 410, 0, 0, 0, }; static const uint16_t ud_itab__335[] = { /* 0 */ 411, 0, 0, 0, }; static const uint16_t ud_itab__336[] = { /* 0 */ 412, 0, 0, 0, }; static const uint16_t ud_itab__337[] = { /* 0 */ 413, 0, 0, 0, }; static const uint16_t ud_itab__338[] = { /* 0 */ 414, 0, 0, 0, }; static const uint16_t ud_itab__339[] = { /* 0 */ 415, 0, 0, 0, }; static const uint16_t ud_itab__340[] = { /* 0 */ 416, 0, 0, 0, }; static const uint16_t ud_itab__341[] = { /* 0 */ 417, 0, 0, 0, }; static const uint16_t ud_itab__342[] = { /* 0 */ 418, 0, 0, 0, }; static const uint16_t ud_itab__343[] = { /* 0 */ 419, 0, 0, 0, }; static const uint16_t ud_itab__344[] = { /* 0 */ 420, 0, 0, 0, }; static const uint16_t ud_itab__345[] = { /* 0 */ 421, 0, 0, 0, }; static const uint16_t ud_itab__346[] = { /* 0 */ 422, 0, 0, 0, }; static const uint16_t ud_itab__347[] = { /* 0 */ 423, 0, 0, 0, }; static const uint16_t ud_itab__348[] = { /* 0 */ 424, 0, 0, 0, }; static const uint16_t ud_itab__349[] = { /* 0 */ 425, 0, 0, 0, }; static const uint16_t ud_itab__350[] = { /* 0 */ 426, 0, 0, 0, }; static const uint16_t ud_itab__351[] = { /* 0 */ 427, 0, 0, 0, }; static const uint16_t ud_itab__352[] = { /* 0 */ 428, 0, 0, 0, }; static const uint16_t ud_itab__353[] = { /* 0 */ 429, 0, 0, 0, }; static const uint16_t ud_itab__354[] = { /* 0 */ 430, 0, 0, 0, }; static const uint16_t ud_itab__355[] = { /* 0 */ 431, 0, 0, 0, }; static const uint16_t ud_itab__356[] = { /* 0 */ 432, 0, 0, 0, }; static const uint16_t ud_itab__357[] = { /* 0 */ 433, 0, 0, 0, }; static const uint16_t ud_itab__358[] = { /* 0 */ 434, 0, 0, 0, }; static const uint16_t ud_itab__359[] = { /* 0 */ 435, 0, 0, 0, }; static const uint16_t ud_itab__360[] = { /* 0 */ 436, 0, 0, 0, }; static const uint16_t ud_itab__361[] = { /* 0 */ 437, 0, 0, 0, }; static const uint16_t ud_itab__362[] = { /* 0 */ 438, 0, 0, 0, }; static const uint16_t ud_itab__363[] = { /* 0 */ 439, 0, 0, 0, }; static const uint16_t ud_itab__368[] = { /* 0 */ 0, 440, }; static const uint16_t ud_itab__367[] = { /* 0 */ GROUP(368), 0, 0, 0, }; static const uint16_t ud_itab__366[] = { /* 0 */ GROUP(367), 0, 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__371[] = { /* 0 */ 0, 441, }; static const uint16_t ud_itab__370[] = { /* 0 */ GROUP(371), 0, 0, 0, }; static const uint16_t ud_itab__369[] = { /* 0 */ GROUP(370), 0, 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__374[] = { /* 0 */ 0, 442, }; static const uint16_t ud_itab__373[] = { /* 0 */ GROUP(374), 0, 0, 0, }; static const uint16_t ud_itab__372[] = { /* 0 */ GROUP(373), 0, 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__365[] = { /* 0 */ GROUP(366), GROUP(369), GROUP(372), 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__364[] = { /* 0 */ 0, GROUP(365), }; static const uint16_t ud_itab__379[] = { /* 0 */ 0, 443, }; static const uint16_t ud_itab__378[] = { /* 0 */ GROUP(379), 0, 0, 0, }; static const uint16_t ud_itab__377[] = { /* 0 */ GROUP(378), 0, 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__382[] = { /* 0 */ 0, 444, }; static const uint16_t ud_itab__381[] = { /* 0 */ GROUP(382), 0, 0, 0, }; static const uint16_t ud_itab__380[] = { /* 0 */ GROUP(381), 0, 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__385[] = { /* 0 */ 0, 445, }; static const uint16_t ud_itab__384[] = { /* 0 */ GROUP(385), 0, 0, 0, }; static const uint16_t ud_itab__383[] = { /* 0 */ GROUP(384), 0, 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__388[] = { /* 0 */ 0, 446, }; static const uint16_t ud_itab__387[] = { /* 0 */ GROUP(388), 0, 0, 0, }; static const uint16_t ud_itab__386[] = { /* 0 */ GROUP(387), 0, 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__391[] = { /* 0 */ 0, 447, }; static const uint16_t ud_itab__390[] = { /* 0 */ GROUP(391), 0, 0, 0, }; static const uint16_t ud_itab__389[] = { /* 0 */ GROUP(390), 0, 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__394[] = { /* 0 */ 0, 448, }; static const uint16_t ud_itab__393[] = { /* 0 */ GROUP(394), 0, 0, 0, }; static const uint16_t ud_itab__392[] = { /* 0 */ GROUP(393), 0, 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__376[] = { /* 0 */ GROUP(377), GROUP(380), GROUP(383), GROUP(386), /* 4 */ GROUP(389), GROUP(392), 0, 0, }; static const uint16_t ud_itab__375[] = { /* 0 */ 0, GROUP(376), }; static const uint16_t ud_itab__395[] = { /* 0 */ 449, 0, 0, 0, }; static const uint16_t ud_itab__396[] = { /* 0 */ 450, 0, 0, 0, }; static const uint16_t ud_itab__397[] = { /* 0 */ 451, 0, 0, 0, }; static const uint16_t ud_itab__398[] = { /* 0 */ 452, 0, 0, 0, }; static const uint16_t ud_itab__399[] = { /* 0 */ 453, 0, 0, 0, }; static const uint16_t ud_itab__400[] = { /* 0 */ 454, 0, 0, 0, }; static const uint16_t ud_itab__404[] = { /* 0 */ 455, 0, }; static const uint16_t ud_itab__403[] = { /* 0 */ GROUP(404), 0, 0, 0, }; static const uint16_t ud_itab__406[] = { /* 0 */ 456, 0, }; static const uint16_t ud_itab__405[] = { /* 0 */ GROUP(406), 0, 0, 0, }; static const uint16_t ud_itab__408[] = { /* 0 */ 457, 0, }; static const uint16_t ud_itab__407[] = { /* 0 */ GROUP(408), 0, 0, 0, }; static const uint16_t ud_itab__410[] = { /* 0 */ 458, 0, }; static const uint16_t ud_itab__409[] = { /* 0 */ GROUP(410), 0, 0, 0, }; static const uint16_t ud_itab__412[] = { /* 0 */ 459, 0, }; static const uint16_t ud_itab__411[] = { /* 0 */ GROUP(412), 0, 0, 0, }; static const uint16_t ud_itab__414[] = { /* 0 */ 460, 0, }; static const uint16_t ud_itab__413[] = { /* 0 */ GROUP(414), 0, 0, 0, }; static const uint16_t ud_itab__416[] = { /* 0 */ 461, 0, }; static const uint16_t ud_itab__415[] = { /* 0 */ GROUP(416), 0, 0, 0, }; static const uint16_t ud_itab__402[] = { /* 0 */ GROUP(403), GROUP(405), GROUP(407), GROUP(409), /* 4 */ GROUP(411), GROUP(413), 0, GROUP(415), }; static const uint16_t ud_itab__420[] = { /* 0 */ 0, 462, }; static const uint16_t ud_itab__419[] = { /* 0 */ GROUP(420), 0, 0, 0, }; static const uint16_t ud_itab__422[] = { /* 0 */ 0, 463, }; static const uint16_t ud_itab__421[] = { /* 0 */ GROUP(422), 0, 0, 0, }; static const uint16_t ud_itab__424[] = { /* 0 */ 0, 464, }; static const uint16_t ud_itab__423[] = { /* 0 */ GROUP(424), 0, 0, 0, }; static const uint16_t ud_itab__426[] = { /* 0 */ 0, 465, }; static const uint16_t ud_itab__425[] = { /* 0 */ GROUP(426), 0, 0, 0, }; static const uint16_t ud_itab__428[] = { /* 0 */ 0, 466, }; static const uint16_t ud_itab__427[] = { /* 0 */ GROUP(428), 0, 0, 0, }; static const uint16_t ud_itab__430[] = { /* 0 */ 0, 467, }; static const uint16_t ud_itab__429[] = { /* 0 */ GROUP(430), 0, 0, 0, }; static const uint16_t ud_itab__432[] = { /* 0 */ 0, 468, }; static const uint16_t ud_itab__431[] = { /* 0 */ GROUP(432), 0, 0, 0, }; static const uint16_t ud_itab__434[] = { /* 0 */ 0, 469, }; static const uint16_t ud_itab__433[] = { /* 0 */ GROUP(434), 0, 0, 0, }; static const uint16_t ud_itab__418[] = { /* 0 */ GROUP(419), GROUP(421), GROUP(423), GROUP(425), /* 4 */ GROUP(427), GROUP(429), GROUP(431), GROUP(433), }; static const uint16_t ud_itab__437[] = { /* 0 */ 0, 470, }; static const uint16_t ud_itab__436[] = { /* 0 */ GROUP(437), 0, 0, 0, }; static const uint16_t ud_itab__439[] = { /* 0 */ 0, 471, }; static const uint16_t ud_itab__438[] = { /* 0 */ GROUP(439), 0, 0, 0, }; static const uint16_t ud_itab__441[] = { /* 0 */ 0, 472, }; static const uint16_t ud_itab__440[] = { /* 0 */ GROUP(441), 0, 0, 0, }; static const uint16_t ud_itab__443[] = { /* 0 */ 0, 473, }; static const uint16_t ud_itab__442[] = { /* 0 */ GROUP(443), 0, 0, 0, }; static const uint16_t ud_itab__445[] = { /* 0 */ 0, 474, }; static const uint16_t ud_itab__444[] = { /* 0 */ GROUP(445), 0, 0, 0, }; static const uint16_t ud_itab__447[] = { /* 0 */ 0, 475, }; static const uint16_t ud_itab__446[] = { /* 0 */ GROUP(447), 0, 0, 0, }; static const uint16_t ud_itab__449[] = { /* 0 */ 0, 476, }; static const uint16_t ud_itab__448[] = { /* 0 */ GROUP(449), 0, 0, 0, }; static const uint16_t ud_itab__451[] = { /* 0 */ 0, 477, }; static const uint16_t ud_itab__450[] = { /* 0 */ GROUP(451), 0, 0, 0, }; static const uint16_t ud_itab__435[] = { /* 0 */ GROUP(436), GROUP(438), GROUP(440), GROUP(442), /* 4 */ GROUP(444), GROUP(446), GROUP(448), GROUP(450), }; static const uint16_t ud_itab__454[] = { /* 0 */ 0, 478, }; static const uint16_t ud_itab__453[] = { /* 0 */ GROUP(454), 0, 0, 0, }; static const uint16_t ud_itab__456[] = { /* 0 */ 0, 479, }; static const uint16_t ud_itab__455[] = { /* 0 */ GROUP(456), 0, 0, 0, }; static const uint16_t ud_itab__458[] = { /* 0 */ 0, 480, }; static const uint16_t ud_itab__457[] = { /* 0 */ GROUP(458), 0, 0, 0, }; static const uint16_t ud_itab__460[] = { /* 0 */ 0, 481, }; static const uint16_t ud_itab__459[] = { /* 0 */ GROUP(460), 0, 0, 0, }; static const uint16_t ud_itab__462[] = { /* 0 */ 0, 482, }; static const uint16_t ud_itab__461[] = { /* 0 */ GROUP(462), 0, 0, 0, }; static const uint16_t ud_itab__464[] = { /* 0 */ 0, 483, }; static const uint16_t ud_itab__463[] = { /* 0 */ GROUP(464), 0, 0, 0, }; static const uint16_t ud_itab__466[] = { /* 0 */ 0, 484, }; static const uint16_t ud_itab__465[] = { /* 0 */ GROUP(466), 0, 0, 0, }; static const uint16_t ud_itab__468[] = { /* 0 */ 0, 485, }; static const uint16_t ud_itab__467[] = { /* 0 */ GROUP(468), 0, 0, 0, }; static const uint16_t ud_itab__452[] = { /* 0 */ GROUP(453), GROUP(455), GROUP(457), GROUP(459), /* 4 */ GROUP(461), GROUP(463), GROUP(465), GROUP(467), }; static const uint16_t ud_itab__417[] = { /* 0 */ 0, 0, 0, 0, /* 4 */ 0, GROUP(418), GROUP(435), GROUP(452), }; static const uint16_t ud_itab__401[] = { /* 0 */ GROUP(402), GROUP(417), }; static const uint16_t ud_itab__469[] = { /* 0 */ 486, 0, 0, 0, }; static const uint16_t ud_itab__470[] = { /* 0 */ 487, 0, 0, 0, }; static const uint16_t ud_itab__471[] = { /* 0 */ 488, 0, 0, 0, }; static const uint16_t ud_itab__472[] = { /* 0 */ 489, 0, 0, 0, }; static const uint16_t ud_itab__473[] = { /* 0 */ 490, 0, 0, 0, }; static const uint16_t ud_itab__474[] = { /* 0 */ 491, 0, 0, 0, }; static const uint16_t ud_itab__475[] = { /* 0 */ 492, 0, 0, 0, }; static const uint16_t ud_itab__476[] = { /* 0 */ 493, 0, 0, 0, }; static const uint16_t ud_itab__477[] = { /* 0 */ 494, 0, 0, 0, }; static const uint16_t ud_itab__478[] = { /* 0 */ 0, 0, 495, 0, }; static const uint16_t ud_itab__480[] = { /* 0 */ 496, 0, 0, 0, }; static const uint16_t ud_itab__481[] = { /* 0 */ 497, 0, 0, 0, }; static const uint16_t ud_itab__482[] = { /* 0 */ 498, 0, 0, 0, }; static const uint16_t ud_itab__483[] = { /* 0 */ 499, 0, 0, 0, }; static const uint16_t ud_itab__479[] = { /* 0 */ 0, 0, 0, 0, /* 4 */ GROUP(480), GROUP(481), GROUP(482), GROUP(483), }; static const uint16_t ud_itab__484[] = { /* 0 */ 500, 0, 0, 0, }; static const uint16_t ud_itab__485[] = { /* 0 */ 501, 0, 0, 0, }; static const uint16_t ud_itab__486[] = { /* 0 */ 502, 0, 0, 0, }; static const uint16_t ud_itab__487[] = { /* 0 */ 503, 0, 0, 0, }; static const uint16_t ud_itab__488[] = { /* 0 */ 504, 0, 0, 0, }; static const uint16_t ud_itab__489[] = { /* 0 */ 505, 0, 0, 0, }; static const uint16_t ud_itab__490[] = { /* 0 */ 506, 0, 0, 0, }; static const uint16_t ud_itab__491[] = { /* 0 */ 507, 508, 509, 510, }; static const uint16_t ud_itab__492[] = { /* 0 */ 511, 0, 0, 0, }; static const uint16_t ud_itab__493[] = { /* 0 */ 512, 0, 0, 513, }; static const uint16_t ud_itab__494[] = { /* 0 */ 514, 0, 0, 515, }; static const uint16_t ud_itab__495[] = { /* 0 */ 516, 0, 0, 517, }; static const uint16_t ud_itab__498[] = { /* 0 */ 518, 519, 520, }; static const uint16_t ud_itab__497[] = { /* 0 */ GROUP(498), 0, 0, 0, }; static const uint16_t ud_itab__500[] = { /* 0 */ 0, 521, 0, }; static const uint16_t ud_itab__501[] = { /* 0 */ 0, 522, 0, }; static const uint16_t ud_itab__502[] = { /* 0 */ 0, 523, 0, }; static const uint16_t ud_itab__499[] = { /* 0 */ GROUP(500), 0, GROUP(501), GROUP(502), }; static const uint16_t ud_itab__504[] = { /* 0 */ 0, 524, 0, }; static const uint16_t ud_itab__503[] = { /* 0 */ GROUP(504), 0, 0, 0, }; static const uint16_t ud_itab__496[] = { /* 0 */ 0, GROUP(497), 0, 0, /* 4 */ 0, 0, GROUP(499), GROUP(503), }; static const uint16_t ud_itab__505[] = { /* 0 */ 525, 0, 0, 0, }; static const uint16_t ud_itab__506[] = { /* 0 */ 526, 0, 0, 0, }; static const uint16_t ud_itab__507[] = { /* 0 */ 527, 0, 0, 0, }; static const uint16_t ud_itab__508[] = { /* 0 */ 528, 0, 0, 0, }; static const uint16_t ud_itab__509[] = { /* 0 */ 529, 0, 0, 0, }; static const uint16_t ud_itab__510[] = { /* 0 */ 530, 0, 0, 0, }; static const uint16_t ud_itab__511[] = { /* 0 */ 531, 0, 0, 0, }; static const uint16_t ud_itab__512[] = { /* 0 */ 532, 0, 0, 0, }; static const uint16_t ud_itab__513[] = { /* 0 */ 0, 533, 0, 534, }; static const uint16_t ud_itab__514[] = { /* 0 */ 535, 0, 0, 536, }; static const uint16_t ud_itab__515[] = { /* 0 */ 537, 0, 0, 538, }; static const uint16_t ud_itab__516[] = { /* 0 */ 539, 0, 0, 540, }; static const uint16_t ud_itab__517[] = { /* 0 */ 541, 0, 0, 542, }; static const uint16_t ud_itab__518[] = { /* 0 */ 543, 0, 0, 544, }; static const uint16_t ud_itab__519[] = { /* 0 */ 0, 545, 546, 547, }; static const uint16_t ud_itab__520[] = { /* 0 */ 548, 0, 0, 549, }; static const uint16_t ud_itab__521[] = { /* 0 */ 550, 0, 0, 551, }; static const uint16_t ud_itab__522[] = { /* 0 */ 552, 0, 0, 553, }; static const uint16_t ud_itab__523[] = { /* 0 */ 554, 0, 0, 555, }; static const uint16_t ud_itab__524[] = { /* 0 */ 556, 0, 0, 557, }; static const uint16_t ud_itab__525[] = { /* 0 */ 558, 0, 0, 559, }; static const uint16_t ud_itab__526[] = { /* 0 */ 560, 0, 0, 561, }; static const uint16_t ud_itab__527[] = { /* 0 */ 562, 0, 0, 563, }; static const uint16_t ud_itab__528[] = { /* 0 */ 564, 0, 0, 565, }; static const uint16_t ud_itab__529[] = { /* 0 */ 566, 0, 0, 567, }; static const uint16_t ud_itab__530[] = { /* 0 */ 568, 0, 0, 569, }; static const uint16_t ud_itab__531[] = { /* 0 */ 570, 0, 0, 571, }; static const uint16_t ud_itab__532[] = { /* 0 */ 572, 0, 0, 573, }; static const uint16_t ud_itab__533[] = { /* 0 */ 574, 0, 0, 575, }; static const uint16_t ud_itab__534[] = { /* 0 */ 576, 0, 0, 577, }; static const uint16_t ud_itab__535[] = { /* 0 */ 0, 578, 579, 580, }; static const uint16_t ud_itab__536[] = { /* 0 */ 581, 0, 0, 582, }; static const uint16_t ud_itab__537[] = { /* 0 */ 583, 0, 0, 584, }; static const uint16_t ud_itab__538[] = { /* 0 */ 585, 0, 0, 586, }; static const uint16_t ud_itab__539[] = { /* 0 */ 587, 0, 0, 588, }; static const uint16_t ud_itab__540[] = { /* 0 */ 589, 0, 0, 590, }; static const uint16_t ud_itab__541[] = { /* 0 */ 591, 0, 0, 592, }; static const uint16_t ud_itab__542[] = { /* 0 */ 593, 0, 0, 594, }; static const uint16_t ud_itab__543[] = { /* 0 */ 595, 0, 0, 596, }; static const uint16_t ud_itab__544[] = { /* 0 */ 597, 0, 0, 598, }; static const uint16_t ud_itab__545[] = { /* 0 */ 0, 599, 0, 0, }; static const uint16_t ud_itab__546[] = { /* 0 */ 600, 0, 0, 601, }; static const uint16_t ud_itab__547[] = { /* 0 */ 602, 0, 0, 603, }; static const uint16_t ud_itab__548[] = { /* 0 */ 604, 0, 0, 605, }; static const uint16_t ud_itab__549[] = { /* 0 */ 606, 0, 0, 607, }; static const uint16_t ud_itab__550[] = { /* 0 */ 608, 0, 0, 609, }; static const uint16_t ud_itab__551[] = { /* 0 */ 610, 0, 0, 611, }; static const uint16_t ud_itab__554[] = { /* 0 */ 0, 612, }; static const uint16_t ud_itab__555[] = { /* 0 */ 0, 613, }; static const uint16_t ud_itab__553[] = { /* 0 */ GROUP(554), 0, 0, GROUP(555), }; static const uint16_t ud_itab__552[] = { /* 0 */ 0, GROUP(553), }; static const uint16_t ud_itab__556[] = { /* 0 */ 614, 0, 0, 615, }; static const uint16_t ud_itab__557[] = { /* 0 */ 616, 0, 0, 617, }; static const uint16_t ud_itab__558[] = { /* 0 */ 618, 0, 0, 619, }; static const uint16_t ud_itab__559[] = { /* 0 */ 620, 0, 0, 621, }; static const uint16_t ud_itab__560[] = { /* 0 */ 622, 0, 0, 623, }; static const uint16_t ud_itab__561[] = { /* 0 */ 624, 0, 0, 625, }; static const uint16_t ud_itab__562[] = { /* 0 */ 626, 0, 0, 627, }; static const uint16_t ud_itab__4[] = { /* 0 */ GROUP(5), GROUP(12), GROUP(87), GROUP(88), /* 4 */ 0, GROUP(89), GROUP(90), GROUP(91), /* 8 */ GROUP(92), GROUP(93), 0, GROUP(94), /* c */ 0, GROUP(95), GROUP(104), GROUP(105), /* 10 */ GROUP(106), GROUP(107), GROUP(108), GROUP(118), /* 14 */ GROUP(119), GROUP(120), GROUP(121), GROUP(129), /* 18 */ GROUP(130), GROUP(135), GROUP(136), GROUP(137), /* 1c */ GROUP(138), GROUP(139), GROUP(140), GROUP(141), /* 20 */ GROUP(142), GROUP(143), GROUP(144), GROUP(145), /* 24 */ 0, 0, 0, 0, /* 28 */ GROUP(146), GROUP(147), GROUP(148), GROUP(149), /* 2c */ GROUP(150), GROUP(151), GROUP(152), GROUP(153), /* 30 */ GROUP(154), GROUP(155), GROUP(156), GROUP(157), /* 34 */ GROUP(158), GROUP(161), 0, GROUP(164), /* 38 */ GROUP(165), 0, GROUP(225), 0, /* 3c */ 0, 0, 0, 0, /* 40 */ GROUP(252), GROUP(253), GROUP(254), GROUP(255), /* 44 */ GROUP(256), GROUP(257), GROUP(258), GROUP(259), /* 48 */ GROUP(260), GROUP(261), GROUP(262), GROUP(263), /* 4c */ GROUP(264), GROUP(265), GROUP(266), GROUP(267), /* 50 */ GROUP(268), GROUP(269), GROUP(270), GROUP(271), /* 54 */ GROUP(272), GROUP(273), GROUP(274), GROUP(275), /* 58 */ GROUP(276), GROUP(277), GROUP(278), GROUP(279), /* 5c */ GROUP(280), GROUP(281), GROUP(282), GROUP(283), /* 60 */ GROUP(284), GROUP(285), GROUP(286), GROUP(287), /* 64 */ GROUP(288), GROUP(289), GROUP(290), GROUP(291), /* 68 */ GROUP(292), GROUP(293), GROUP(294), GROUP(295), /* 6c */ GROUP(296), GROUP(297), GROUP(298), GROUP(299), /* 70 */ GROUP(300), GROUP(301), GROUP(305), GROUP(309), /* 74 */ GROUP(314), GROUP(315), GROUP(316), GROUP(317), /* 78 */ GROUP(318), GROUP(320), 0, 0, /* 7c */ GROUP(322), GROUP(323), GROUP(324), GROUP(325), /* 80 */ GROUP(326), GROUP(327), GROUP(328), GROUP(329), /* 84 */ GROUP(330), GROUP(331), GROUP(332), GROUP(333), /* 88 */ GROUP(334), GROUP(335), GROUP(336), GROUP(337), /* 8c */ GROUP(338), GROUP(339), GROUP(340), GROUP(341), /* 90 */ GROUP(342), GROUP(343), GROUP(344), GROUP(345), /* 94 */ GROUP(346), GROUP(347), GROUP(348), GROUP(349), /* 98 */ GROUP(350), GROUP(351), GROUP(352), GROUP(353), /* 9c */ GROUP(354), GROUP(355), GROUP(356), GROUP(357), /* a0 */ GROUP(358), GROUP(359), GROUP(360), GROUP(361), /* a4 */ GROUP(362), GROUP(363), GROUP(364), GROUP(375), /* a8 */ GROUP(395), GROUP(396), GROUP(397), GROUP(398), /* ac */ GROUP(399), GROUP(400), GROUP(401), GROUP(469), /* b0 */ GROUP(470), GROUP(471), GROUP(472), GROUP(473), /* b4 */ GROUP(474), GROUP(475), GROUP(476), GROUP(477), /* b8 */ GROUP(478), 0, GROUP(479), GROUP(484), /* bc */ GROUP(485), GROUP(486), GROUP(487), GROUP(488), /* c0 */ GROUP(489), GROUP(490), GROUP(491), GROUP(492), /* c4 */ GROUP(493), GROUP(494), GROUP(495), GROUP(496), /* c8 */ GROUP(505), GROUP(506), GROUP(507), GROUP(508), /* cc */ GROUP(509), GROUP(510), GROUP(511), GROUP(512), /* d0 */ GROUP(513), GROUP(514), GROUP(515), GROUP(516), /* d4 */ GROUP(517), GROUP(518), GROUP(519), GROUP(520), /* d8 */ GROUP(521), GROUP(522), GROUP(523), GROUP(524), /* dc */ GROUP(525), GROUP(526), GROUP(527), GROUP(528), /* e0 */ GROUP(529), GROUP(530), GROUP(531), GROUP(532), /* e4 */ GROUP(533), GROUP(534), GROUP(535), GROUP(536), /* e8 */ GROUP(537), GROUP(538), GROUP(539), GROUP(540), /* ec */ GROUP(541), GROUP(542), GROUP(543), GROUP(544), /* f0 */ GROUP(545), GROUP(546), GROUP(547), GROUP(548), /* f4 */ GROUP(549), GROUP(550), GROUP(551), GROUP(552), /* f8 */ GROUP(556), GROUP(557), GROUP(558), GROUP(559), /* fc */ GROUP(560), GROUP(561), GROUP(562), 0, }; static const uint16_t ud_itab__563[] = { /* 0 */ 634, 0, }; static const uint16_t ud_itab__564[] = { /* 0 */ 635, 0, }; static const uint16_t ud_itab__565[] = { /* 0 */ 642, 0, }; static const uint16_t ud_itab__566[] = { /* 0 */ 643, 0, }; static const uint16_t ud_itab__567[] = { /* 0 */ 650, 0, }; static const uint16_t ud_itab__568[] = { /* 0 */ 657, 0, }; static const uint16_t ud_itab__569[] = { /* 0 */ 664, 0, }; static const uint16_t ud_itab__570[] = { /* 0 */ 671, 0, }; static const uint16_t ud_itab__572[] = { /* 0 */ 704, 0, }; static const uint16_t ud_itab__573[] = { /* 0 */ 705, 0, }; static const uint16_t ud_itab__571[] = { /* 0 */ GROUP(572), GROUP(573), 0, }; static const uint16_t ud_itab__575[] = { /* 0 */ 706, 0, }; static const uint16_t ud_itab__576[] = { /* 0 */ 707, 0, }; static const uint16_t ud_itab__574[] = { /* 0 */ GROUP(575), GROUP(576), 0, }; static const uint16_t ud_itab__577[] = { /* 0 */ 708, 0, }; static const uint16_t ud_itab__578[] = { /* 0 */ 709, 710, }; static const uint16_t ud_itab__579[] = { /* 0 */ 716, 717, 0, }; static const uint16_t ud_itab__580[] = { /* 0 */ 719, 720, 0, }; static const uint16_t ud_itab__581[] = { /* 0 */ 737, 738, 739, 740, /* 4 */ 741, 742, 743, 744, }; static const uint16_t ud_itab__582[] = { /* 0 */ 745, 746, 747, 748, /* 4 */ 749, 750, 751, 752, }; static const uint16_t ud_itab__584[] = { /* 0 */ 753, 0, }; static const uint16_t ud_itab__585[] = { /* 0 */ 754, 0, }; static const uint16_t ud_itab__586[] = { /* 0 */ 755, 0, }; static const uint16_t ud_itab__587[] = { /* 0 */ 756, 0, }; static const uint16_t ud_itab__588[] = { /* 0 */ 757, 0, }; static const uint16_t ud_itab__589[] = { /* 0 */ 758, 0, }; static const uint16_t ud_itab__590[] = { /* 0 */ 759, 0, }; static const uint16_t ud_itab__591[] = { /* 0 */ 760, 0, }; static const uint16_t ud_itab__583[] = { /* 0 */ GROUP(584), GROUP(585), GROUP(586), GROUP(587), /* 4 */ GROUP(588), GROUP(589), GROUP(590), GROUP(591), }; static const uint16_t ud_itab__592[] = { /* 0 */ 761, 762, 763, 764, /* 4 */ 765, 766, 767, 768, }; static const uint16_t ud_itab__593[] = { /* 0 */ 780, 0, 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__594[] = { /* 0 */ 789, 790, 791, }; static const uint16_t ud_itab__595[] = { /* 0 */ 792, 793, 794, }; static const uint16_t ud_itab__596[] = { /* 0 */ 795, 0, }; static const uint16_t ud_itab__598[] = { /* 0 */ 797, 798, }; static const uint16_t ud_itab__599[] = { /* 0 */ 799, 800, }; static const uint16_t ud_itab__600[] = { /* 0 */ 0, 801, }; static const uint16_t ud_itab__597[] = { /* 0 */ GROUP(598), GROUP(599), GROUP(600), }; static const uint16_t ud_itab__602[] = { /* 0 */ 802, 0, }; static const uint16_t ud_itab__603[] = { /* 0 */ 803, 804, }; static const uint16_t ud_itab__604[] = { /* 0 */ 0, 805, }; static const uint16_t ud_itab__601[] = { /* 0 */ GROUP(602), GROUP(603), GROUP(604), }; static const uint16_t ud_itab__605[] = { /* 0 */ 813, 814, 815, }; static const uint16_t ud_itab__606[] = { /* 0 */ 817, 818, 819, }; static const uint16_t ud_itab__607[] = { /* 0 */ 823, 824, 825, }; static const uint16_t ud_itab__608[] = { /* 0 */ 827, 828, 829, }; static const uint16_t ud_itab__609[] = { /* 0 */ 831, 832, 833, }; static const uint16_t ud_itab__610[] = { /* 0 */ 850, 851, 852, 853, /* 4 */ 854, 855, 856, 857, }; static const uint16_t ud_itab__611[] = { /* 0 */ 858, 859, 860, 861, /* 4 */ 862, 863, 864, 865, }; static const uint16_t ud_itab__612[] = { /* 0 */ 868, 0, }; static const uint16_t ud_itab__613[] = { /* 0 */ 869, 0, }; static const uint16_t ud_itab__614[] = { /* 0 */ 870, 0, 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__615[] = { /* 0 */ 871, 0, 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__616[] = { /* 0 */ 878, 0, }; static const uint16_t ud_itab__617[] = { /* 0 */ 879, 880, 881, }; static const uint16_t ud_itab__618[] = { /* 0 */ 882, 883, 884, 885, /* 4 */ 886, 887, 888, 889, }; static const uint16_t ud_itab__619[] = { /* 0 */ 890, 891, 892, 893, /* 4 */ 894, 895, 896, 897, }; static const uint16_t ud_itab__620[] = { /* 0 */ 898, 899, 900, 901, /* 4 */ 902, 903, 904, 905, }; static const uint16_t ud_itab__621[] = { /* 0 */ 906, 907, 908, 909, /* 4 */ 910, 911, 912, 913, }; static const uint16_t ud_itab__622[] = { /* 0 */ 914, 0, }; static const uint16_t ud_itab__623[] = { /* 0 */ 915, 0, }; static const uint16_t ud_itab__624[] = { /* 0 */ 916, 0, }; static const uint16_t ud_itab__627[] = { /* 0 */ 918, 0, }; static const uint16_t ud_itab__628[] = { /* 0 */ 919, 0, }; static const uint16_t ud_itab__629[] = { /* 0 */ 920, 0, }; static const uint16_t ud_itab__630[] = { /* 0 */ 921, 0, }; static const uint16_t ud_itab__631[] = { /* 0 */ 922, 0, }; static const uint16_t ud_itab__632[] = { /* 0 */ 923, 0, }; static const uint16_t ud_itab__633[] = { /* 0 */ 924, 0, }; static const uint16_t ud_itab__634[] = { /* 0 */ 925, 0, }; static const uint16_t ud_itab__626[] = { /* 0 */ GROUP(627), GROUP(628), GROUP(629), GROUP(630), /* 4 */ GROUP(631), GROUP(632), GROUP(633), GROUP(634), }; static const uint16_t ud_itab__636[] = { /* 0 */ 0, 926, }; static const uint16_t ud_itab__637[] = { /* 0 */ 0, 927, }; static const uint16_t ud_itab__638[] = { /* 0 */ 0, 928, }; static const uint16_t ud_itab__639[] = { /* 0 */ 0, 929, }; static const uint16_t ud_itab__640[] = { /* 0 */ 0, 930, }; static const uint16_t ud_itab__641[] = { /* 0 */ 0, 931, }; static const uint16_t ud_itab__642[] = { /* 0 */ 0, 932, }; static const uint16_t ud_itab__643[] = { /* 0 */ 0, 933, }; static const uint16_t ud_itab__644[] = { /* 0 */ 0, 934, }; static const uint16_t ud_itab__645[] = { /* 0 */ 0, 935, }; static const uint16_t ud_itab__646[] = { /* 0 */ 0, 936, }; static const uint16_t ud_itab__647[] = { /* 0 */ 0, 937, }; static const uint16_t ud_itab__648[] = { /* 0 */ 0, 938, }; static const uint16_t ud_itab__649[] = { /* 0 */ 0, 939, }; static const uint16_t ud_itab__650[] = { /* 0 */ 0, 940, }; static const uint16_t ud_itab__651[] = { /* 0 */ 0, 941, }; static const uint16_t ud_itab__652[] = { /* 0 */ 0, 942, }; static const uint16_t ud_itab__653[] = { /* 0 */ 0, 943, }; static const uint16_t ud_itab__654[] = { /* 0 */ 0, 944, }; static const uint16_t ud_itab__655[] = { /* 0 */ 0, 945, }; static const uint16_t ud_itab__656[] = { /* 0 */ 0, 946, }; static const uint16_t ud_itab__657[] = { /* 0 */ 0, 947, }; static const uint16_t ud_itab__658[] = { /* 0 */ 0, 948, }; static const uint16_t ud_itab__659[] = { /* 0 */ 0, 949, }; static const uint16_t ud_itab__660[] = { /* 0 */ 0, 950, }; static const uint16_t ud_itab__661[] = { /* 0 */ 0, 951, }; static const uint16_t ud_itab__662[] = { /* 0 */ 0, 952, }; static const uint16_t ud_itab__663[] = { /* 0 */ 0, 953, }; static const uint16_t ud_itab__664[] = { /* 0 */ 0, 954, }; static const uint16_t ud_itab__665[] = { /* 0 */ 0, 955, }; static const uint16_t ud_itab__666[] = { /* 0 */ 0, 956, }; static const uint16_t ud_itab__667[] = { /* 0 */ 0, 957, }; static const uint16_t ud_itab__668[] = { /* 0 */ 0, 958, }; static const uint16_t ud_itab__669[] = { /* 0 */ 0, 959, }; static const uint16_t ud_itab__670[] = { /* 0 */ 0, 960, }; static const uint16_t ud_itab__671[] = { /* 0 */ 0, 961, }; static const uint16_t ud_itab__672[] = { /* 0 */ 0, 962, }; static const uint16_t ud_itab__673[] = { /* 0 */ 0, 963, }; static const uint16_t ud_itab__674[] = { /* 0 */ 0, 964, }; static const uint16_t ud_itab__675[] = { /* 0 */ 0, 965, }; static const uint16_t ud_itab__676[] = { /* 0 */ 0, 966, }; static const uint16_t ud_itab__677[] = { /* 0 */ 0, 967, }; static const uint16_t ud_itab__678[] = { /* 0 */ 0, 968, }; static const uint16_t ud_itab__679[] = { /* 0 */ 0, 969, }; static const uint16_t ud_itab__680[] = { /* 0 */ 0, 970, }; static const uint16_t ud_itab__681[] = { /* 0 */ 0, 971, }; static const uint16_t ud_itab__682[] = { /* 0 */ 0, 972, }; static const uint16_t ud_itab__683[] = { /* 0 */ 0, 973, }; static const uint16_t ud_itab__684[] = { /* 0 */ 0, 974, }; static const uint16_t ud_itab__685[] = { /* 0 */ 0, 975, }; static const uint16_t ud_itab__686[] = { /* 0 */ 0, 976, }; static const uint16_t ud_itab__687[] = { /* 0 */ 0, 977, }; static const uint16_t ud_itab__688[] = { /* 0 */ 0, 978, }; static const uint16_t ud_itab__689[] = { /* 0 */ 0, 979, }; static const uint16_t ud_itab__690[] = { /* 0 */ 0, 980, }; static const uint16_t ud_itab__691[] = { /* 0 */ 0, 981, }; static const uint16_t ud_itab__692[] = { /* 0 */ 0, 982, }; static const uint16_t ud_itab__693[] = { /* 0 */ 0, 983, }; static const uint16_t ud_itab__694[] = { /* 0 */ 0, 984, }; static const uint16_t ud_itab__695[] = { /* 0 */ 0, 985, }; static const uint16_t ud_itab__696[] = { /* 0 */ 0, 986, }; static const uint16_t ud_itab__697[] = { /* 0 */ 0, 987, }; static const uint16_t ud_itab__698[] = { /* 0 */ 0, 988, }; static const uint16_t ud_itab__699[] = { /* 0 */ 0, 989, }; static const uint16_t ud_itab__635[] = { /* 0 */ GROUP(636), GROUP(637), GROUP(638), GROUP(639), /* 4 */ GROUP(640), GROUP(641), GROUP(642), GROUP(643), /* 8 */ GROUP(644), GROUP(645), GROUP(646), GROUP(647), /* c */ GROUP(648), GROUP(649), GROUP(650), GROUP(651), /* 10 */ GROUP(652), GROUP(653), GROUP(654), GROUP(655), /* 14 */ GROUP(656), GROUP(657), GROUP(658), GROUP(659), /* 18 */ GROUP(660), GROUP(661), GROUP(662), GROUP(663), /* 1c */ GROUP(664), GROUP(665), GROUP(666), GROUP(667), /* 20 */ GROUP(668), GROUP(669), GROUP(670), GROUP(671), /* 24 */ GROUP(672), GROUP(673), GROUP(674), GROUP(675), /* 28 */ GROUP(676), GROUP(677), GROUP(678), GROUP(679), /* 2c */ GROUP(680), GROUP(681), GROUP(682), GROUP(683), /* 30 */ GROUP(684), GROUP(685), GROUP(686), GROUP(687), /* 34 */ GROUP(688), GROUP(689), GROUP(690), GROUP(691), /* 38 */ GROUP(692), GROUP(693), GROUP(694), GROUP(695), /* 3c */ GROUP(696), GROUP(697), GROUP(698), GROUP(699), }; static const uint16_t ud_itab__625[] = { /* 0 */ GROUP(626), GROUP(635), }; static const uint16_t ud_itab__702[] = { /* 0 */ 990, 0, }; static const uint16_t ud_itab__703[] = { /* 0 */ 991, 0, }; static const uint16_t ud_itab__704[] = { /* 0 */ 992, 0, }; static const uint16_t ud_itab__705[] = { /* 0 */ 993, 0, }; static const uint16_t ud_itab__706[] = { /* 0 */ 994, 0, }; static const uint16_t ud_itab__707[] = { /* 0 */ 995, 0, }; static const uint16_t ud_itab__708[] = { /* 0 */ 996, 0, }; static const uint16_t ud_itab__701[] = { /* 0 */ GROUP(702), 0, GROUP(703), GROUP(704), /* 4 */ GROUP(705), GROUP(706), GROUP(707), GROUP(708), }; static const uint16_t ud_itab__710[] = { /* 0 */ 0, 997, }; static const uint16_t ud_itab__711[] = { /* 0 */ 0, 998, }; static const uint16_t ud_itab__712[] = { /* 0 */ 0, 999, }; static const uint16_t ud_itab__713[] = { /* 0 */ 0, 1000, }; static const uint16_t ud_itab__714[] = { /* 0 */ 0, 1001, }; static const uint16_t ud_itab__715[] = { /* 0 */ 0, 1002, }; static const uint16_t ud_itab__716[] = { /* 0 */ 0, 1003, }; static const uint16_t ud_itab__717[] = { /* 0 */ 0, 1004, }; static const uint16_t ud_itab__718[] = { /* 0 */ 0, 1005, }; static const uint16_t ud_itab__719[] = { /* 0 */ 0, 1006, }; static const uint16_t ud_itab__720[] = { /* 0 */ 0, 1007, }; static const uint16_t ud_itab__721[] = { /* 0 */ 0, 1008, }; static const uint16_t ud_itab__722[] = { /* 0 */ 0, 1009, }; static const uint16_t ud_itab__723[] = { /* 0 */ 0, 1010, }; static const uint16_t ud_itab__724[] = { /* 0 */ 0, 1011, }; static const uint16_t ud_itab__725[] = { /* 0 */ 0, 1012, }; static const uint16_t ud_itab__726[] = { /* 0 */ 0, 1013, }; static const uint16_t ud_itab__727[] = { /* 0 */ 0, 1014, }; static const uint16_t ud_itab__728[] = { /* 0 */ 0, 1015, }; static const uint16_t ud_itab__729[] = { /* 0 */ 0, 1016, }; static const uint16_t ud_itab__730[] = { /* 0 */ 0, 1017, }; static const uint16_t ud_itab__731[] = { /* 0 */ 0, 1018, }; static const uint16_t ud_itab__732[] = { /* 0 */ 0, 1019, }; static const uint16_t ud_itab__733[] = { /* 0 */ 0, 1020, }; static const uint16_t ud_itab__734[] = { /* 0 */ 0, 1021, }; static const uint16_t ud_itab__735[] = { /* 0 */ 0, 1022, }; static const uint16_t ud_itab__736[] = { /* 0 */ 0, 1023, }; static const uint16_t ud_itab__737[] = { /* 0 */ 0, 1024, }; static const uint16_t ud_itab__738[] = { /* 0 */ 0, 1025, }; static const uint16_t ud_itab__739[] = { /* 0 */ 0, 1026, }; static const uint16_t ud_itab__740[] = { /* 0 */ 0, 1027, }; static const uint16_t ud_itab__741[] = { /* 0 */ 0, 1028, }; static const uint16_t ud_itab__742[] = { /* 0 */ 0, 1029, }; static const uint16_t ud_itab__743[] = { /* 0 */ 0, 1030, }; static const uint16_t ud_itab__744[] = { /* 0 */ 0, 1031, }; static const uint16_t ud_itab__745[] = { /* 0 */ 0, 1032, }; static const uint16_t ud_itab__746[] = { /* 0 */ 0, 1033, }; static const uint16_t ud_itab__747[] = { /* 0 */ 0, 1034, }; static const uint16_t ud_itab__748[] = { /* 0 */ 0, 1035, }; static const uint16_t ud_itab__749[] = { /* 0 */ 0, 1036, }; static const uint16_t ud_itab__750[] = { /* 0 */ 0, 1037, }; static const uint16_t ud_itab__751[] = { /* 0 */ 0, 1038, }; static const uint16_t ud_itab__752[] = { /* 0 */ 0, 1039, }; static const uint16_t ud_itab__753[] = { /* 0 */ 0, 1040, }; static const uint16_t ud_itab__754[] = { /* 0 */ 0, 1041, }; static const uint16_t ud_itab__755[] = { /* 0 */ 0, 1042, }; static const uint16_t ud_itab__756[] = { /* 0 */ 0, 1043, }; static const uint16_t ud_itab__757[] = { /* 0 */ 0, 1044, }; static const uint16_t ud_itab__758[] = { /* 0 */ 0, 1045, }; static const uint16_t ud_itab__759[] = { /* 0 */ 0, 1046, }; static const uint16_t ud_itab__760[] = { /* 0 */ 0, 1047, }; static const uint16_t ud_itab__761[] = { /* 0 */ 0, 1048, }; static const uint16_t ud_itab__709[] = { /* 0 */ GROUP(710), GROUP(711), GROUP(712), GROUP(713), /* 4 */ GROUP(714), GROUP(715), GROUP(716), GROUP(717), /* 8 */ GROUP(718), GROUP(719), GROUP(720), GROUP(721), /* c */ GROUP(722), GROUP(723), GROUP(724), GROUP(725), /* 10 */ GROUP(726), 0, 0, 0, /* 14 */ 0, 0, 0, 0, /* 18 */ GROUP(727), GROUP(728), GROUP(729), GROUP(730), /* 1c */ GROUP(731), GROUP(732), GROUP(733), GROUP(734), /* 20 */ GROUP(735), GROUP(736), 0, 0, /* 24 */ GROUP(737), GROUP(738), 0, 0, /* 28 */ GROUP(739), GROUP(740), GROUP(741), GROUP(742), /* 2c */ GROUP(743), GROUP(744), GROUP(745), 0, /* 30 */ GROUP(746), GROUP(747), GROUP(748), GROUP(749), /* 34 */ GROUP(750), GROUP(751), GROUP(752), GROUP(753), /* 38 */ GROUP(754), GROUP(755), GROUP(756), GROUP(757), /* 3c */ GROUP(758), GROUP(759), GROUP(760), GROUP(761), }; static const uint16_t ud_itab__700[] = { /* 0 */ GROUP(701), GROUP(709), }; static const uint16_t ud_itab__764[] = { /* 0 */ 1049, 0, }; static const uint16_t ud_itab__765[] = { /* 0 */ 1050, 0, }; static const uint16_t ud_itab__766[] = { /* 0 */ 1051, 0, }; static const uint16_t ud_itab__767[] = { /* 0 */ 1052, 0, }; static const uint16_t ud_itab__768[] = { /* 0 */ 1053, 0, }; static const uint16_t ud_itab__769[] = { /* 0 */ 1054, 0, }; static const uint16_t ud_itab__770[] = { /* 0 */ 1055, 0, }; static const uint16_t ud_itab__771[] = { /* 0 */ 1056, 0, }; static const uint16_t ud_itab__763[] = { /* 0 */ GROUP(764), GROUP(765), GROUP(766), GROUP(767), /* 4 */ GROUP(768), GROUP(769), GROUP(770), GROUP(771), }; static const uint16_t ud_itab__773[] = { /* 0 */ 0, 1057, }; static const uint16_t ud_itab__774[] = { /* 0 */ 0, 1058, }; static const uint16_t ud_itab__775[] = { /* 0 */ 0, 1059, }; static const uint16_t ud_itab__776[] = { /* 0 */ 0, 1060, }; static const uint16_t ud_itab__777[] = { /* 0 */ 0, 1061, }; static const uint16_t ud_itab__778[] = { /* 0 */ 0, 1062, }; static const uint16_t ud_itab__779[] = { /* 0 */ 0, 1063, }; static const uint16_t ud_itab__780[] = { /* 0 */ 0, 1064, }; static const uint16_t ud_itab__781[] = { /* 0 */ 0, 1065, }; static const uint16_t ud_itab__782[] = { /* 0 */ 0, 1066, }; static const uint16_t ud_itab__783[] = { /* 0 */ 0, 1067, }; static const uint16_t ud_itab__784[] = { /* 0 */ 0, 1068, }; static const uint16_t ud_itab__785[] = { /* 0 */ 0, 1069, }; static const uint16_t ud_itab__786[] = { /* 0 */ 0, 1070, }; static const uint16_t ud_itab__787[] = { /* 0 */ 0, 1071, }; static const uint16_t ud_itab__788[] = { /* 0 */ 0, 1072, }; static const uint16_t ud_itab__789[] = { /* 0 */ 0, 1073, }; static const uint16_t ud_itab__790[] = { /* 0 */ 0, 1074, }; static const uint16_t ud_itab__791[] = { /* 0 */ 0, 1075, }; static const uint16_t ud_itab__792[] = { /* 0 */ 0, 1076, }; static const uint16_t ud_itab__793[] = { /* 0 */ 0, 1077, }; static const uint16_t ud_itab__794[] = { /* 0 */ 0, 1078, }; static const uint16_t ud_itab__795[] = { /* 0 */ 0, 1079, }; static const uint16_t ud_itab__796[] = { /* 0 */ 0, 1080, }; static const uint16_t ud_itab__797[] = { /* 0 */ 0, 1081, }; static const uint16_t ud_itab__798[] = { /* 0 */ 0, 1082, }; static const uint16_t ud_itab__799[] = { /* 0 */ 0, 1083, }; static const uint16_t ud_itab__800[] = { /* 0 */ 0, 1084, }; static const uint16_t ud_itab__801[] = { /* 0 */ 0, 1085, }; static const uint16_t ud_itab__802[] = { /* 0 */ 0, 1086, }; static const uint16_t ud_itab__803[] = { /* 0 */ 0, 1087, }; static const uint16_t ud_itab__804[] = { /* 0 */ 0, 1088, }; static const uint16_t ud_itab__805[] = { /* 0 */ 0, 1089, }; static const uint16_t ud_itab__772[] = { /* 0 */ GROUP(773), GROUP(774), GROUP(775), GROUP(776), /* 4 */ GROUP(777), GROUP(778), GROUP(779), GROUP(780), /* 8 */ GROUP(781), GROUP(782), GROUP(783), GROUP(784), /* c */ GROUP(785), GROUP(786), GROUP(787), GROUP(788), /* 10 */ GROUP(789), GROUP(790), GROUP(791), GROUP(792), /* 14 */ GROUP(793), GROUP(794), GROUP(795), GROUP(796), /* 18 */ GROUP(797), GROUP(798), GROUP(799), GROUP(800), /* 1c */ GROUP(801), GROUP(802), GROUP(803), GROUP(804), /* 20 */ 0, 0, 0, 0, /* 24 */ 0, 0, 0, 0, /* 28 */ 0, GROUP(805), 0, 0, /* 2c */ 0, 0, 0, 0, /* 30 */ 0, 0, 0, 0, /* 34 */ 0, 0, 0, 0, /* 38 */ 0, 0, 0, 0, /* 3c */ 0, 0, 0, 0, }; static const uint16_t ud_itab__762[] = { /* 0 */ GROUP(763), GROUP(772), }; static const uint16_t ud_itab__808[] = { /* 0 */ 1090, 0, }; static const uint16_t ud_itab__809[] = { /* 0 */ 1091, 0, }; static const uint16_t ud_itab__810[] = { /* 0 */ 1092, 0, }; static const uint16_t ud_itab__811[] = { /* 0 */ 1093, 0, }; static const uint16_t ud_itab__812[] = { /* 0 */ 1094, 0, }; static const uint16_t ud_itab__813[] = { /* 0 */ 1095, 0, }; static const uint16_t ud_itab__807[] = { /* 0 */ GROUP(808), GROUP(809), GROUP(810), GROUP(811), /* 4 */ 0, GROUP(812), 0, GROUP(813), }; static const uint16_t ud_itab__815[] = { /* 0 */ 0, 1096, }; static const uint16_t ud_itab__816[] = { /* 0 */ 0, 1097, }; static const uint16_t ud_itab__817[] = { /* 0 */ 0, 1098, }; static const uint16_t ud_itab__818[] = { /* 0 */ 0, 1099, }; static const uint16_t ud_itab__819[] = { /* 0 */ 0, 1100, }; static const uint16_t ud_itab__820[] = { /* 0 */ 0, 1101, }; static const uint16_t ud_itab__821[] = { /* 0 */ 0, 1102, }; static const uint16_t ud_itab__822[] = { /* 0 */ 0, 1103, }; static const uint16_t ud_itab__823[] = { /* 0 */ 0, 1104, }; static const uint16_t ud_itab__824[] = { /* 0 */ 0, 1105, }; static const uint16_t ud_itab__825[] = { /* 0 */ 0, 1106, }; static const uint16_t ud_itab__826[] = { /* 0 */ 0, 1107, }; static const uint16_t ud_itab__827[] = { /* 0 */ 0, 1108, }; static const uint16_t ud_itab__828[] = { /* 0 */ 0, 1109, }; static const uint16_t ud_itab__829[] = { /* 0 */ 0, 1110, }; static const uint16_t ud_itab__830[] = { /* 0 */ 0, 1111, }; static const uint16_t ud_itab__831[] = { /* 0 */ 0, 1112, }; static const uint16_t ud_itab__832[] = { /* 0 */ 0, 1113, }; static const uint16_t ud_itab__833[] = { /* 0 */ 0, 1114, }; static const uint16_t ud_itab__834[] = { /* 0 */ 0, 1115, }; static const uint16_t ud_itab__835[] = { /* 0 */ 0, 1116, }; static const uint16_t ud_itab__836[] = { /* 0 */ 0, 1117, }; static const uint16_t ud_itab__837[] = { /* 0 */ 0, 1118, }; static const uint16_t ud_itab__838[] = { /* 0 */ 0, 1119, }; static const uint16_t ud_itab__839[] = { /* 0 */ 0, 1120, }; static const uint16_t ud_itab__840[] = { /* 0 */ 0, 1121, }; static const uint16_t ud_itab__841[] = { /* 0 */ 0, 1122, }; static const uint16_t ud_itab__842[] = { /* 0 */ 0, 1123, }; static const uint16_t ud_itab__843[] = { /* 0 */ 0, 1124, }; static const uint16_t ud_itab__844[] = { /* 0 */ 0, 1125, }; static const uint16_t ud_itab__845[] = { /* 0 */ 0, 1126, }; static const uint16_t ud_itab__846[] = { /* 0 */ 0, 1127, }; static const uint16_t ud_itab__847[] = { /* 0 */ 0, 1128, }; static const uint16_t ud_itab__848[] = { /* 0 */ 0, 1129, }; static const uint16_t ud_itab__849[] = { /* 0 */ 0, 1130, }; static const uint16_t ud_itab__850[] = { /* 0 */ 0, 1131, }; static const uint16_t ud_itab__851[] = { /* 0 */ 0, 1132, }; static const uint16_t ud_itab__852[] = { /* 0 */ 0, 1133, }; static const uint16_t ud_itab__853[] = { /* 0 */ 0, 1134, }; static const uint16_t ud_itab__854[] = { /* 0 */ 0, 1135, }; static const uint16_t ud_itab__855[] = { /* 0 */ 0, 1136, }; static const uint16_t ud_itab__856[] = { /* 0 */ 0, 1137, }; static const uint16_t ud_itab__857[] = { /* 0 */ 0, 1138, }; static const uint16_t ud_itab__858[] = { /* 0 */ 0, 1139, }; static const uint16_t ud_itab__859[] = { /* 0 */ 0, 1140, }; static const uint16_t ud_itab__860[] = { /* 0 */ 0, 1141, }; static const uint16_t ud_itab__861[] = { /* 0 */ 0, 1142, }; static const uint16_t ud_itab__862[] = { /* 0 */ 0, 1143, }; static const uint16_t ud_itab__863[] = { /* 0 */ 0, 1144, }; static const uint16_t ud_itab__864[] = { /* 0 */ 0, 1145, }; static const uint16_t ud_itab__814[] = { /* 0 */ GROUP(815), GROUP(816), GROUP(817), GROUP(818), /* 4 */ GROUP(819), GROUP(820), GROUP(821), GROUP(822), /* 8 */ GROUP(823), GROUP(824), GROUP(825), GROUP(826), /* c */ GROUP(827), GROUP(828), GROUP(829), GROUP(830), /* 10 */ GROUP(831), GROUP(832), GROUP(833), GROUP(834), /* 14 */ GROUP(835), GROUP(836), GROUP(837), GROUP(838), /* 18 */ GROUP(839), GROUP(840), GROUP(841), GROUP(842), /* 1c */ GROUP(843), GROUP(844), GROUP(845), GROUP(846), /* 20 */ 0, 0, GROUP(847), GROUP(848), /* 24 */ 0, 0, 0, 0, /* 28 */ GROUP(849), GROUP(850), GROUP(851), GROUP(852), /* 2c */ GROUP(853), GROUP(854), GROUP(855), GROUP(856), /* 30 */ GROUP(857), GROUP(858), GROUP(859), GROUP(860), /* 34 */ GROUP(861), GROUP(862), GROUP(863), GROUP(864), /* 38 */ 0, 0, 0, 0, /* 3c */ 0, 0, 0, 0, }; static const uint16_t ud_itab__806[] = { /* 0 */ GROUP(807), GROUP(814), }; static const uint16_t ud_itab__867[] = { /* 0 */ 1146, 0, }; static const uint16_t ud_itab__868[] = { /* 0 */ 1147, 0, }; static const uint16_t ud_itab__869[] = { /* 0 */ 1148, 0, }; static const uint16_t ud_itab__870[] = { /* 0 */ 1149, 0, }; static const uint16_t ud_itab__871[] = { /* 0 */ 1150, 0, }; static const uint16_t ud_itab__872[] = { /* 0 */ 1151, 0, }; static const uint16_t ud_itab__873[] = { /* 0 */ 1152, 0, }; static const uint16_t ud_itab__874[] = { /* 0 */ 1153, 0, }; static const uint16_t ud_itab__866[] = { /* 0 */ GROUP(867), GROUP(868), GROUP(869), GROUP(870), /* 4 */ GROUP(871), GROUP(872), GROUP(873), GROUP(874), }; static const uint16_t ud_itab__876[] = { /* 0 */ 0, 1154, }; static const uint16_t ud_itab__877[] = { /* 0 */ 0, 1155, }; static const uint16_t ud_itab__878[] = { /* 0 */ 0, 1156, }; static const uint16_t ud_itab__879[] = { /* 0 */ 0, 1157, }; static const uint16_t ud_itab__880[] = { /* 0 */ 0, 1158, }; static const uint16_t ud_itab__881[] = { /* 0 */ 0, 1159, }; static const uint16_t ud_itab__882[] = { /* 0 */ 0, 1160, }; static const uint16_t ud_itab__883[] = { /* 0 */ 0, 1161, }; static const uint16_t ud_itab__884[] = { /* 0 */ 0, 1162, }; static const uint16_t ud_itab__885[] = { /* 0 */ 0, 1163, }; static const uint16_t ud_itab__886[] = { /* 0 */ 0, 1164, }; static const uint16_t ud_itab__887[] = { /* 0 */ 0, 1165, }; static const uint16_t ud_itab__888[] = { /* 0 */ 0, 1166, }; static const uint16_t ud_itab__889[] = { /* 0 */ 0, 1167, }; static const uint16_t ud_itab__890[] = { /* 0 */ 0, 1168, }; static const uint16_t ud_itab__891[] = { /* 0 */ 0, 1169, }; static const uint16_t ud_itab__892[] = { /* 0 */ 0, 1170, }; static const uint16_t ud_itab__893[] = { /* 0 */ 0, 1171, }; static const uint16_t ud_itab__894[] = { /* 0 */ 0, 1172, }; static const uint16_t ud_itab__895[] = { /* 0 */ 0, 1173, }; static const uint16_t ud_itab__896[] = { /* 0 */ 0, 1174, }; static const uint16_t ud_itab__897[] = { /* 0 */ 0, 1175, }; static const uint16_t ud_itab__898[] = { /* 0 */ 0, 1176, }; static const uint16_t ud_itab__899[] = { /* 0 */ 0, 1177, }; static const uint16_t ud_itab__900[] = { /* 0 */ 0, 1178, }; static const uint16_t ud_itab__901[] = { /* 0 */ 0, 1179, }; static const uint16_t ud_itab__902[] = { /* 0 */ 0, 1180, }; static const uint16_t ud_itab__903[] = { /* 0 */ 0, 1181, }; static const uint16_t ud_itab__904[] = { /* 0 */ 0, 1182, }; static const uint16_t ud_itab__905[] = { /* 0 */ 0, 1183, }; static const uint16_t ud_itab__906[] = { /* 0 */ 0, 1184, }; static const uint16_t ud_itab__907[] = { /* 0 */ 0, 1185, }; static const uint16_t ud_itab__908[] = { /* 0 */ 0, 1186, }; static const uint16_t ud_itab__909[] = { /* 0 */ 0, 1187, }; static const uint16_t ud_itab__910[] = { /* 0 */ 0, 1188, }; static const uint16_t ud_itab__911[] = { /* 0 */ 0, 1189, }; static const uint16_t ud_itab__912[] = { /* 0 */ 0, 1190, }; static const uint16_t ud_itab__913[] = { /* 0 */ 0, 1191, }; static const uint16_t ud_itab__914[] = { /* 0 */ 0, 1192, }; static const uint16_t ud_itab__915[] = { /* 0 */ 0, 1193, }; static const uint16_t ud_itab__916[] = { /* 0 */ 0, 1194, }; static const uint16_t ud_itab__917[] = { /* 0 */ 0, 1195, }; static const uint16_t ud_itab__918[] = { /* 0 */ 0, 1196, }; static const uint16_t ud_itab__919[] = { /* 0 */ 0, 1197, }; static const uint16_t ud_itab__920[] = { /* 0 */ 0, 1198, }; static const uint16_t ud_itab__921[] = { /* 0 */ 0, 1199, }; static const uint16_t ud_itab__922[] = { /* 0 */ 0, 1200, }; static const uint16_t ud_itab__923[] = { /* 0 */ 0, 1201, }; static const uint16_t ud_itab__924[] = { /* 0 */ 0, 1202, }; static const uint16_t ud_itab__925[] = { /* 0 */ 0, 1203, }; static const uint16_t ud_itab__926[] = { /* 0 */ 0, 1204, }; static const uint16_t ud_itab__927[] = { /* 0 */ 0, 1205, }; static const uint16_t ud_itab__928[] = { /* 0 */ 0, 1206, }; static const uint16_t ud_itab__929[] = { /* 0 */ 0, 1207, }; static const uint16_t ud_itab__930[] = { /* 0 */ 0, 1208, }; static const uint16_t ud_itab__931[] = { /* 0 */ 0, 1209, }; static const uint16_t ud_itab__932[] = { /* 0 */ 0, 1210, }; static const uint16_t ud_itab__933[] = { /* 0 */ 0, 1211, }; static const uint16_t ud_itab__934[] = { /* 0 */ 0, 1212, }; static const uint16_t ud_itab__935[] = { /* 0 */ 0, 1213, }; static const uint16_t ud_itab__936[] = { /* 0 */ 0, 1214, }; static const uint16_t ud_itab__937[] = { /* 0 */ 0, 1215, }; static const uint16_t ud_itab__938[] = { /* 0 */ 0, 1216, }; static const uint16_t ud_itab__939[] = { /* 0 */ 0, 1217, }; static const uint16_t ud_itab__875[] = { /* 0 */ GROUP(876), GROUP(877), GROUP(878), GROUP(879), /* 4 */ GROUP(880), GROUP(881), GROUP(882), GROUP(883), /* 8 */ GROUP(884), GROUP(885), GROUP(886), GROUP(887), /* c */ GROUP(888), GROUP(889), GROUP(890), GROUP(891), /* 10 */ GROUP(892), GROUP(893), GROUP(894), GROUP(895), /* 14 */ GROUP(896), GROUP(897), GROUP(898), GROUP(899), /* 18 */ GROUP(900), GROUP(901), GROUP(902), GROUP(903), /* 1c */ GROUP(904), GROUP(905), GROUP(906), GROUP(907), /* 20 */ GROUP(908), GROUP(909), GROUP(910), GROUP(911), /* 24 */ GROUP(912), GROUP(913), GROUP(914), GROUP(915), /* 28 */ GROUP(916), GROUP(917), GROUP(918), GROUP(919), /* 2c */ GROUP(920), GROUP(921), GROUP(922), GROUP(923), /* 30 */ GROUP(924), GROUP(925), GROUP(926), GROUP(927), /* 34 */ GROUP(928), GROUP(929), GROUP(930), GROUP(931), /* 38 */ GROUP(932), GROUP(933), GROUP(934), GROUP(935), /* 3c */ GROUP(936), GROUP(937), GROUP(938), GROUP(939), }; static const uint16_t ud_itab__865[] = { /* 0 */ GROUP(866), GROUP(875), }; static const uint16_t ud_itab__942[] = { /* 0 */ 1218, 0, }; static const uint16_t ud_itab__943[] = { /* 0 */ 1219, 0, }; static const uint16_t ud_itab__944[] = { /* 0 */ 1220, 0, }; static const uint16_t ud_itab__945[] = { /* 0 */ 1221, 0, }; static const uint16_t ud_itab__946[] = { /* 0 */ 1222, 0, }; static const uint16_t ud_itab__947[] = { /* 0 */ 1223, 0, }; static const uint16_t ud_itab__948[] = { /* 0 */ 1224, 0, }; static const uint16_t ud_itab__941[] = { /* 0 */ GROUP(942), GROUP(943), GROUP(944), GROUP(945), /* 4 */ GROUP(946), 0, GROUP(947), GROUP(948), }; static const uint16_t ud_itab__950[] = { /* 0 */ 0, 1225, }; static const uint16_t ud_itab__951[] = { /* 0 */ 0, 1226, }; static const uint16_t ud_itab__952[] = { /* 0 */ 0, 1227, }; static const uint16_t ud_itab__953[] = { /* 0 */ 0, 1228, }; static const uint16_t ud_itab__954[] = { /* 0 */ 0, 1229, }; static const uint16_t ud_itab__955[] = { /* 0 */ 0, 1230, }; static const uint16_t ud_itab__956[] = { /* 0 */ 0, 1231, }; static const uint16_t ud_itab__957[] = { /* 0 */ 0, 1232, }; static const uint16_t ud_itab__958[] = { /* 0 */ 0, 1233, }; static const uint16_t ud_itab__959[] = { /* 0 */ 0, 1234, }; static const uint16_t ud_itab__960[] = { /* 0 */ 0, 1235, }; static const uint16_t ud_itab__961[] = { /* 0 */ 0, 1236, }; static const uint16_t ud_itab__962[] = { /* 0 */ 0, 1237, }; static const uint16_t ud_itab__963[] = { /* 0 */ 0, 1238, }; static const uint16_t ud_itab__964[] = { /* 0 */ 0, 1239, }; static const uint16_t ud_itab__965[] = { /* 0 */ 0, 1240, }; static const uint16_t ud_itab__966[] = { /* 0 */ 0, 1241, }; static const uint16_t ud_itab__967[] = { /* 0 */ 0, 1242, }; static const uint16_t ud_itab__968[] = { /* 0 */ 0, 1243, }; static const uint16_t ud_itab__969[] = { /* 0 */ 0, 1244, }; static const uint16_t ud_itab__970[] = { /* 0 */ 0, 1245, }; static const uint16_t ud_itab__971[] = { /* 0 */ 0, 1246, }; static const uint16_t ud_itab__972[] = { /* 0 */ 0, 1247, }; static const uint16_t ud_itab__973[] = { /* 0 */ 0, 1248, }; static const uint16_t ud_itab__974[] = { /* 0 */ 0, 1249, }; static const uint16_t ud_itab__975[] = { /* 0 */ 0, 1250, }; static const uint16_t ud_itab__976[] = { /* 0 */ 0, 1251, }; static const uint16_t ud_itab__977[] = { /* 0 */ 0, 1252, }; static const uint16_t ud_itab__978[] = { /* 0 */ 0, 1253, }; static const uint16_t ud_itab__979[] = { /* 0 */ 0, 1254, }; static const uint16_t ud_itab__980[] = { /* 0 */ 0, 1255, }; static const uint16_t ud_itab__981[] = { /* 0 */ 0, 1256, }; static const uint16_t ud_itab__982[] = { /* 0 */ 0, 1257, }; static const uint16_t ud_itab__983[] = { /* 0 */ 0, 1258, }; static const uint16_t ud_itab__984[] = { /* 0 */ 0, 1259, }; static const uint16_t ud_itab__985[] = { /* 0 */ 0, 1260, }; static const uint16_t ud_itab__986[] = { /* 0 */ 0, 1261, }; static const uint16_t ud_itab__987[] = { /* 0 */ 0, 1262, }; static const uint16_t ud_itab__988[] = { /* 0 */ 0, 1263, }; static const uint16_t ud_itab__989[] = { /* 0 */ 0, 1264, }; static const uint16_t ud_itab__990[] = { /* 0 */ 0, 1265, }; static const uint16_t ud_itab__991[] = { /* 0 */ 0, 1266, }; static const uint16_t ud_itab__992[] = { /* 0 */ 0, 1267, }; static const uint16_t ud_itab__993[] = { /* 0 */ 0, 1268, }; static const uint16_t ud_itab__994[] = { /* 0 */ 0, 1269, }; static const uint16_t ud_itab__995[] = { /* 0 */ 0, 1270, }; static const uint16_t ud_itab__996[] = { /* 0 */ 0, 1271, }; static const uint16_t ud_itab__997[] = { /* 0 */ 0, 1272, }; static const uint16_t ud_itab__949[] = { /* 0 */ GROUP(950), GROUP(951), GROUP(952), GROUP(953), /* 4 */ GROUP(954), GROUP(955), GROUP(956), GROUP(957), /* 8 */ GROUP(958), GROUP(959), GROUP(960), GROUP(961), /* c */ GROUP(962), GROUP(963), GROUP(964), GROUP(965), /* 10 */ GROUP(966), GROUP(967), GROUP(968), GROUP(969), /* 14 */ GROUP(970), GROUP(971), GROUP(972), GROUP(973), /* 18 */ GROUP(974), GROUP(975), GROUP(976), GROUP(977), /* 1c */ GROUP(978), GROUP(979), GROUP(980), GROUP(981), /* 20 */ GROUP(982), GROUP(983), GROUP(984), GROUP(985), /* 24 */ GROUP(986), GROUP(987), GROUP(988), GROUP(989), /* 28 */ GROUP(990), GROUP(991), GROUP(992), GROUP(993), /* 2c */ GROUP(994), GROUP(995), GROUP(996), GROUP(997), /* 30 */ 0, 0, 0, 0, /* 34 */ 0, 0, 0, 0, /* 38 */ 0, 0, 0, 0, /* 3c */ 0, 0, 0, 0, }; static const uint16_t ud_itab__940[] = { /* 0 */ GROUP(941), GROUP(949), }; static const uint16_t ud_itab__1000[] = { /* 0 */ 1273, 0, }; static const uint16_t ud_itab__1001[] = { /* 0 */ 1274, 0, }; static const uint16_t ud_itab__1002[] = { /* 0 */ 1275, 0, }; static const uint16_t ud_itab__1003[] = { /* 0 */ 1276, 0, }; static const uint16_t ud_itab__1004[] = { /* 0 */ 1277, 0, }; static const uint16_t ud_itab__1005[] = { /* 0 */ 1278, 0, }; static const uint16_t ud_itab__1006[] = { /* 0 */ 1279, 0, }; static const uint16_t ud_itab__1007[] = { /* 0 */ 1280, 0, }; static const uint16_t ud_itab__999[] = { /* 0 */ GROUP(1000), GROUP(1001), GROUP(1002), GROUP(1003), /* 4 */ GROUP(1004), GROUP(1005), GROUP(1006), GROUP(1007), }; static const uint16_t ud_itab__1009[] = { /* 0 */ 0, 1281, }; static const uint16_t ud_itab__1010[] = { /* 0 */ 0, 1282, }; static const uint16_t ud_itab__1011[] = { /* 0 */ 0, 1283, }; static const uint16_t ud_itab__1012[] = { /* 0 */ 0, 1284, }; static const uint16_t ud_itab__1013[] = { /* 0 */ 0, 1285, }; static const uint16_t ud_itab__1014[] = { /* 0 */ 0, 1286, }; static const uint16_t ud_itab__1015[] = { /* 0 */ 0, 1287, }; static const uint16_t ud_itab__1016[] = { /* 0 */ 0, 1288, }; static const uint16_t ud_itab__1017[] = { /* 0 */ 0, 1289, }; static const uint16_t ud_itab__1018[] = { /* 0 */ 0, 1290, }; static const uint16_t ud_itab__1019[] = { /* 0 */ 0, 1291, }; static const uint16_t ud_itab__1020[] = { /* 0 */ 0, 1292, }; static const uint16_t ud_itab__1021[] = { /* 0 */ 0, 1293, }; static const uint16_t ud_itab__1022[] = { /* 0 */ 0, 1294, }; static const uint16_t ud_itab__1023[] = { /* 0 */ 0, 1295, }; static const uint16_t ud_itab__1024[] = { /* 0 */ 0, 1296, }; static const uint16_t ud_itab__1025[] = { /* 0 */ 0, 1297, }; static const uint16_t ud_itab__1026[] = { /* 0 */ 0, 1298, }; static const uint16_t ud_itab__1027[] = { /* 0 */ 0, 1299, }; static const uint16_t ud_itab__1028[] = { /* 0 */ 0, 1300, }; static const uint16_t ud_itab__1029[] = { /* 0 */ 0, 1301, }; static const uint16_t ud_itab__1030[] = { /* 0 */ 0, 1302, }; static const uint16_t ud_itab__1031[] = { /* 0 */ 0, 1303, }; static const uint16_t ud_itab__1032[] = { /* 0 */ 0, 1304, }; static const uint16_t ud_itab__1033[] = { /* 0 */ 0, 1305, }; static const uint16_t ud_itab__1034[] = { /* 0 */ 0, 1306, }; static const uint16_t ud_itab__1035[] = { /* 0 */ 0, 1307, }; static const uint16_t ud_itab__1036[] = { /* 0 */ 0, 1308, }; static const uint16_t ud_itab__1037[] = { /* 0 */ 0, 1309, }; static const uint16_t ud_itab__1038[] = { /* 0 */ 0, 1310, }; static const uint16_t ud_itab__1039[] = { /* 0 */ 0, 1311, }; static const uint16_t ud_itab__1040[] = { /* 0 */ 0, 1312, }; static const uint16_t ud_itab__1041[] = { /* 0 */ 0, 1313, }; static const uint16_t ud_itab__1042[] = { /* 0 */ 0, 1314, }; static const uint16_t ud_itab__1043[] = { /* 0 */ 0, 1315, }; static const uint16_t ud_itab__1044[] = { /* 0 */ 0, 1316, }; static const uint16_t ud_itab__1045[] = { /* 0 */ 0, 1317, }; static const uint16_t ud_itab__1046[] = { /* 0 */ 0, 1318, }; static const uint16_t ud_itab__1047[] = { /* 0 */ 0, 1319, }; static const uint16_t ud_itab__1048[] = { /* 0 */ 0, 1320, }; static const uint16_t ud_itab__1049[] = { /* 0 */ 0, 1321, }; static const uint16_t ud_itab__1050[] = { /* 0 */ 0, 1322, }; static const uint16_t ud_itab__1051[] = { /* 0 */ 0, 1323, }; static const uint16_t ud_itab__1052[] = { /* 0 */ 0, 1324, }; static const uint16_t ud_itab__1053[] = { /* 0 */ 0, 1325, }; static const uint16_t ud_itab__1054[] = { /* 0 */ 0, 1326, }; static const uint16_t ud_itab__1055[] = { /* 0 */ 0, 1327, }; static const uint16_t ud_itab__1056[] = { /* 0 */ 0, 1328, }; static const uint16_t ud_itab__1057[] = { /* 0 */ 0, 1329, }; static const uint16_t ud_itab__1058[] = { /* 0 */ 0, 1330, }; static const uint16_t ud_itab__1059[] = { /* 0 */ 0, 1331, }; static const uint16_t ud_itab__1060[] = { /* 0 */ 0, 1332, }; static const uint16_t ud_itab__1061[] = { /* 0 */ 0, 1333, }; static const uint16_t ud_itab__1062[] = { /* 0 */ 0, 1334, }; static const uint16_t ud_itab__1063[] = { /* 0 */ 0, 1335, }; static const uint16_t ud_itab__1064[] = { /* 0 */ 0, 1336, }; static const uint16_t ud_itab__1065[] = { /* 0 */ 0, 1337, }; static const uint16_t ud_itab__1008[] = { /* 0 */ GROUP(1009), GROUP(1010), GROUP(1011), GROUP(1012), /* 4 */ GROUP(1013), GROUP(1014), GROUP(1015), GROUP(1016), /* 8 */ GROUP(1017), GROUP(1018), GROUP(1019), GROUP(1020), /* c */ GROUP(1021), GROUP(1022), GROUP(1023), GROUP(1024), /* 10 */ GROUP(1025), GROUP(1026), GROUP(1027), GROUP(1028), /* 14 */ GROUP(1029), GROUP(1030), GROUP(1031), GROUP(1032), /* 18 */ 0, GROUP(1033), 0, 0, /* 1c */ 0, 0, 0, 0, /* 20 */ GROUP(1034), GROUP(1035), GROUP(1036), GROUP(1037), /* 24 */ GROUP(1038), GROUP(1039), GROUP(1040), GROUP(1041), /* 28 */ GROUP(1042), GROUP(1043), GROUP(1044), GROUP(1045), /* 2c */ GROUP(1046), GROUP(1047), GROUP(1048), GROUP(1049), /* 30 */ GROUP(1050), GROUP(1051), GROUP(1052), GROUP(1053), /* 34 */ GROUP(1054), GROUP(1055), GROUP(1056), GROUP(1057), /* 38 */ GROUP(1058), GROUP(1059), GROUP(1060), GROUP(1061), /* 3c */ GROUP(1062), GROUP(1063), GROUP(1064), GROUP(1065), }; static const uint16_t ud_itab__998[] = { /* 0 */ GROUP(999), GROUP(1008), }; static const uint16_t ud_itab__1068[] = { /* 0 */ 1338, 0, }; static const uint16_t ud_itab__1069[] = { /* 0 */ 1339, 0, }; static const uint16_t ud_itab__1070[] = { /* 0 */ 1340, 0, }; static const uint16_t ud_itab__1071[] = { /* 0 */ 1341, 0, }; static const uint16_t ud_itab__1072[] = { /* 0 */ 1342, 0, }; static const uint16_t ud_itab__1073[] = { /* 0 */ 1343, 0, }; static const uint16_t ud_itab__1074[] = { /* 0 */ 1344, 0, }; static const uint16_t ud_itab__1075[] = { /* 0 */ 1345, 0, }; static const uint16_t ud_itab__1067[] = { /* 0 */ GROUP(1068), GROUP(1069), GROUP(1070), GROUP(1071), /* 4 */ GROUP(1072), GROUP(1073), GROUP(1074), GROUP(1075), }; static const uint16_t ud_itab__1077[] = { /* 0 */ 0, 1346, }; static const uint16_t ud_itab__1078[] = { /* 0 */ 0, 1347, }; static const uint16_t ud_itab__1079[] = { /* 0 */ 0, 1348, }; static const uint16_t ud_itab__1080[] = { /* 0 */ 0, 1349, }; static const uint16_t ud_itab__1081[] = { /* 0 */ 0, 1350, }; static const uint16_t ud_itab__1082[] = { /* 0 */ 0, 1351, }; static const uint16_t ud_itab__1083[] = { /* 0 */ 0, 1352, }; static const uint16_t ud_itab__1084[] = { /* 0 */ 0, 1353, }; static const uint16_t ud_itab__1085[] = { /* 0 */ 0, 1354, }; static const uint16_t ud_itab__1086[] = { /* 0 */ 0, 1355, }; static const uint16_t ud_itab__1087[] = { /* 0 */ 0, 1356, }; static const uint16_t ud_itab__1088[] = { /* 0 */ 0, 1357, }; static const uint16_t ud_itab__1089[] = { /* 0 */ 0, 1358, }; static const uint16_t ud_itab__1090[] = { /* 0 */ 0, 1359, }; static const uint16_t ud_itab__1091[] = { /* 0 */ 0, 1360, }; static const uint16_t ud_itab__1092[] = { /* 0 */ 0, 1361, }; static const uint16_t ud_itab__1093[] = { /* 0 */ 0, 1362, }; static const uint16_t ud_itab__1094[] = { /* 0 */ 0, 1363, }; static const uint16_t ud_itab__1095[] = { /* 0 */ 0, 1364, }; static const uint16_t ud_itab__1096[] = { /* 0 */ 0, 1365, }; static const uint16_t ud_itab__1097[] = { /* 0 */ 0, 1366, }; static const uint16_t ud_itab__1098[] = { /* 0 */ 0, 1367, }; static const uint16_t ud_itab__1099[] = { /* 0 */ 0, 1368, }; static const uint16_t ud_itab__1100[] = { /* 0 */ 0, 1369, }; static const uint16_t ud_itab__1101[] = { /* 0 */ 0, 1370, }; static const uint16_t ud_itab__1102[] = { /* 0 */ 0, 1371, }; static const uint16_t ud_itab__1103[] = { /* 0 */ 0, 1372, }; static const uint16_t ud_itab__1104[] = { /* 0 */ 0, 1373, }; static const uint16_t ud_itab__1105[] = { /* 0 */ 0, 1374, }; static const uint16_t ud_itab__1106[] = { /* 0 */ 0, 1375, }; static const uint16_t ud_itab__1107[] = { /* 0 */ 0, 1376, }; static const uint16_t ud_itab__1108[] = { /* 0 */ 0, 1377, }; static const uint16_t ud_itab__1109[] = { /* 0 */ 0, 1378, }; static const uint16_t ud_itab__1110[] = { /* 0 */ 0, 1379, }; static const uint16_t ud_itab__1111[] = { /* 0 */ 0, 1380, }; static const uint16_t ud_itab__1112[] = { /* 0 */ 0, 1381, }; static const uint16_t ud_itab__1113[] = { /* 0 */ 0, 1382, }; static const uint16_t ud_itab__1114[] = { /* 0 */ 0, 1383, }; static const uint16_t ud_itab__1115[] = { /* 0 */ 0, 1384, }; static const uint16_t ud_itab__1116[] = { /* 0 */ 0, 1385, }; static const uint16_t ud_itab__1117[] = { /* 0 */ 0, 1386, }; static const uint16_t ud_itab__1118[] = { /* 0 */ 0, 1387, }; static const uint16_t ud_itab__1119[] = { /* 0 */ 0, 1388, }; static const uint16_t ud_itab__1120[] = { /* 0 */ 0, 1389, }; static const uint16_t ud_itab__1121[] = { /* 0 */ 0, 1390, }; static const uint16_t ud_itab__1122[] = { /* 0 */ 0, 1391, }; static const uint16_t ud_itab__1123[] = { /* 0 */ 0, 1392, }; static const uint16_t ud_itab__1124[] = { /* 0 */ 0, 1393, }; static const uint16_t ud_itab__1125[] = { /* 0 */ 0, 1394, }; static const uint16_t ud_itab__1076[] = { /* 0 */ GROUP(1077), GROUP(1078), GROUP(1079), GROUP(1080), /* 4 */ GROUP(1081), GROUP(1082), GROUP(1083), GROUP(1084), /* 8 */ GROUP(1085), GROUP(1086), GROUP(1087), GROUP(1088), /* c */ GROUP(1089), GROUP(1090), GROUP(1091), GROUP(1092), /* 10 */ GROUP(1093), GROUP(1094), GROUP(1095), GROUP(1096), /* 14 */ GROUP(1097), GROUP(1098), GROUP(1099), GROUP(1100), /* 18 */ GROUP(1101), GROUP(1102), GROUP(1103), GROUP(1104), /* 1c */ GROUP(1105), GROUP(1106), GROUP(1107), GROUP(1108), /* 20 */ GROUP(1109), 0, 0, 0, /* 24 */ 0, 0, 0, 0, /* 28 */ GROUP(1110), GROUP(1111), GROUP(1112), GROUP(1113), /* 2c */ GROUP(1114), GROUP(1115), GROUP(1116), GROUP(1117), /* 30 */ GROUP(1118), GROUP(1119), GROUP(1120), GROUP(1121), /* 34 */ GROUP(1122), GROUP(1123), GROUP(1124), GROUP(1125), /* 38 */ 0, 0, 0, 0, /* 3c */ 0, 0, 0, 0, }; static const uint16_t ud_itab__1066[] = { /* 0 */ GROUP(1067), GROUP(1076), }; static const uint16_t ud_itab__1126[] = { /* 0 */ 1398, 1399, 1400, }; static const uint16_t ud_itab__1127[] = { /* 0 */ 1407, 0, }; static const uint16_t ud_itab__1128[] = { /* 0 */ 1419, 1420, 1421, 1422, /* 4 */ 1423, 1424, 1425, 1426, }; static const uint16_t ud_itab__1129[] = { /* 0 */ 1427, 1428, 1429, 1430, /* 4 */ 1431, 1432, 1433, 1434, }; static const uint16_t ud_itab__1130[] = { /* 0 */ 1441, 1442, 0, 0, /* 4 */ 0, 0, 0, 0, }; static const uint16_t ud_itab__1132[] = { /* 0 */ 1445, 1446, }; static const uint16_t ud_itab__1131[] = { /* 0 */ 1443, 1444, GROUP(1132), 1447, /* 4 */ 1448, 1449, 1450, 0, }; const uint16_t ud_itab__0[] = { /* 0 */ 1, 2, 3, 4, /* 4 */ 5, 6, GROUP(1), GROUP(2), /* 8 */ 9, 10, 11, 12, /* c */ 13, 14, GROUP(3), GROUP(4), /* 10 */ 628, 629, 630, 631, /* 14 */ 632, 633, GROUP(563), GROUP(564), /* 18 */ 636, 637, 638, 639, /* 1c */ 640, 641, GROUP(565), GROUP(566), /* 20 */ 644, 645, 646, 647, /* 24 */ 648, 649, 0, GROUP(567), /* 28 */ 651, 652, 653, 654, /* 2c */ 655, 656, 0, GROUP(568), /* 30 */ 658, 659, 660, 661, /* 34 */ 662, 663, 0, GROUP(569), /* 38 */ 665, 666, 667, 668, /* 3c */ 669, 670, 0, GROUP(570), /* 40 */ 672, 673, 674, 675, /* 44 */ 676, 677, 678, 679, /* 48 */ 680, 681, 682, 683, /* 4c */ 684, 685, 686, 687, /* 50 */ 688, 689, 690, 691, /* 54 */ 692, 693, 694, 695, /* 58 */ 696, 697, 698, 699, /* 5c */ 700, 701, 702, 703, /* 60 */ GROUP(571), GROUP(574), GROUP(577), GROUP(578), /* 64 */ 0, 0, 0, 0, /* 68 */ 711, 712, 713, 714, /* 6c */ 715, GROUP(579), 718, GROUP(580), /* 70 */ 721, 722, 723, 724, /* 74 */ 725, 726, 727, 728, /* 78 */ 729, 730, 731, 732, /* 7c */ 733, 734, 735, 736, /* 80 */ GROUP(581), GROUP(582), GROUP(583), GROUP(592), /* 84 */ 769, 770, 771, 772, /* 88 */ 773, 774, 775, 776, /* 8c */ 777, 778, 779, GROUP(593), /* 90 */ 781, 782, 783, 784, /* 94 */ 785, 786, 787, 788, /* 98 */ GROUP(594), GROUP(595), GROUP(596), 796, /* 9c */ GROUP(597), GROUP(601), 806, 807, /* a0 */ 808, 809, 810, 811, /* a4 */ 812, GROUP(605), 816, GROUP(606), /* a8 */ 820, 821, 822, GROUP(607), /* ac */ 826, GROUP(608), 830, GROUP(609), /* b0 */ 834, 835, 836, 837, /* b4 */ 838, 839, 840, 841, /* b8 */ 842, 843, 844, 845, /* bc */ 846, 847, 848, 849, /* c0 */ GROUP(610), GROUP(611), 866, 867, /* c4 */ GROUP(612), GROUP(613), GROUP(614), GROUP(615), /* c8 */ 872, 873, 874, 875, /* cc */ 876, 877, GROUP(616), GROUP(617), /* d0 */ GROUP(618), GROUP(619), GROUP(620), GROUP(621), /* d4 */ GROUP(622), GROUP(623), GROUP(624), 917, /* d8 */ GROUP(625), GROUP(700), GROUP(762), GROUP(806), /* dc */ GROUP(865), GROUP(940), GROUP(998), GROUP(1066), /* e0 */ 1395, 1396, 1397, GROUP(1126), /* e4 */ 1401, 1402, 1403, 1404, /* e8 */ 1405, 1406, GROUP(1127), 1408, /* ec */ 1409, 1410, 1411, 1412, /* f0 */ 1413, 1414, 1415, 1416, /* f4 */ 1417, 1418, GROUP(1128), GROUP(1129), /* f8 */ 1435, 1436, 1437, 1438, /* fc */ 1439, 1440, GROUP(1130), GROUP(1131), }; struct ud_lookup_table_list_entry ud_lookup_table_list[] = { /* 000 */ { ud_itab__0, UD_TAB__OPC_TABLE, "table0" }, /* 001 */ { ud_itab__1, UD_TAB__OPC_MODE, "/m" }, /* 002 */ { ud_itab__2, UD_TAB__OPC_MODE, "/m" }, /* 003 */ { ud_itab__3, UD_TAB__OPC_MODE, "/m" }, /* 004 */ { ud_itab__4, UD_TAB__OPC_TABLE, "0f" }, /* 005 */ { ud_itab__5, UD_TAB__OPC_REG, "/reg" }, /* 006 */ { ud_itab__6, UD_TAB__OPC_SSE, "/sse" }, /* 007 */ { ud_itab__7, UD_TAB__OPC_SSE, "/sse" }, /* 008 */ { ud_itab__8, UD_TAB__OPC_SSE, "/sse" }, /* 009 */ { ud_itab__9, UD_TAB__OPC_SSE, "/sse" }, /* 010 */ { ud_itab__10, UD_TAB__OPC_SSE, "/sse" }, /* 011 */ { ud_itab__11, UD_TAB__OPC_SSE, "/sse" }, /* 012 */ { ud_itab__12, UD_TAB__OPC_MOD, "/mod" }, /* 013 */ { ud_itab__13, UD_TAB__OPC_REG, "/reg" }, /* 014 */ { ud_itab__14, UD_TAB__OPC_SSE, "/sse" }, /* 015 */ { ud_itab__15, UD_TAB__OPC_MOD, "/mod" }, /* 016 */ { ud_itab__16, UD_TAB__OPC_SSE, "/sse" }, /* 017 */ { ud_itab__17, UD_TAB__OPC_MOD, "/mod" }, /* 018 */ { ud_itab__18, UD_TAB__OPC_SSE, "/sse" }, /* 019 */ { ud_itab__19, UD_TAB__OPC_MOD, "/mod" }, /* 020 */ { ud_itab__20, UD_TAB__OPC_SSE, "/sse" }, /* 021 */ { ud_itab__21, UD_TAB__OPC_MOD, "/mod" }, /* 022 */ { ud_itab__22, UD_TAB__OPC_SSE, "/sse" }, /* 023 */ { ud_itab__23, UD_TAB__OPC_MOD, "/mod" }, /* 024 */ { ud_itab__24, UD_TAB__OPC_SSE, "/sse" }, /* 025 */ { ud_itab__25, UD_TAB__OPC_MOD, "/mod" }, /* 026 */ { ud_itab__26, UD_TAB__OPC_SSE, "/sse" }, /* 027 */ { ud_itab__27, UD_TAB__OPC_MOD, "/mod" }, /* 028 */ { ud_itab__28, UD_TAB__OPC_REG, "/reg" }, /* 029 */ { ud_itab__29, UD_TAB__OPC_RM, "/rm" }, /* 030 */ { ud_itab__30, UD_TAB__OPC_SSE, "/sse" }, /* 031 */ { ud_itab__31, UD_TAB__OPC_MOD, "/mod" }, /* 032 */ { ud_itab__32, UD_TAB__OPC_VENDOR, "intel" }, /* 033 */ { ud_itab__33, UD_TAB__OPC_SSE, "/sse" }, /* 034 */ { ud_itab__34, UD_TAB__OPC_MOD, "/mod" }, /* 035 */ { ud_itab__35, UD_TAB__OPC_VENDOR, "intel" }, /* 036 */ { ud_itab__36, UD_TAB__OPC_SSE, "/sse" }, /* 037 */ { ud_itab__37, UD_TAB__OPC_MOD, "/mod" }, /* 038 */ { ud_itab__38, UD_TAB__OPC_VENDOR, "intel" }, /* 039 */ { ud_itab__39, UD_TAB__OPC_SSE, "/sse" }, /* 040 */ { ud_itab__40, UD_TAB__OPC_MOD, "/mod" }, /* 041 */ { ud_itab__41, UD_TAB__OPC_VENDOR, "intel" }, /* 042 */ { ud_itab__42, UD_TAB__OPC_RM, "/rm" }, /* 043 */ { ud_itab__43, UD_TAB__OPC_SSE, "/sse" }, /* 044 */ { ud_itab__44, UD_TAB__OPC_MOD, "/mod" }, /* 045 */ { ud_itab__45, UD_TAB__OPC_SSE, "/sse" }, /* 046 */ { ud_itab__46, UD_TAB__OPC_MOD, "/mod" }, /* 047 */ { ud_itab__47, UD_TAB__OPC_RM, "/rm" }, /* 048 */ { ud_itab__48, UD_TAB__OPC_SSE, "/sse" }, /* 049 */ { ud_itab__49, UD_TAB__OPC_MOD, "/mod" }, /* 050 */ { ud_itab__50, UD_TAB__OPC_SSE, "/sse" }, /* 051 */ { ud_itab__51, UD_TAB__OPC_MOD, "/mod" }, /* 052 */ { ud_itab__52, UD_TAB__OPC_RM, "/rm" }, /* 053 */ { ud_itab__53, UD_TAB__OPC_SSE, "/sse" }, /* 054 */ { ud_itab__54, UD_TAB__OPC_MOD, "/mod" }, /* 055 */ { ud_itab__55, UD_TAB__OPC_VENDOR, "amd" }, /* 056 */ { ud_itab__56, UD_TAB__OPC_SSE, "/sse" }, /* 057 */ { ud_itab__57, UD_TAB__OPC_MOD, "/mod" }, /* 058 */ { ud_itab__58, UD_TAB__OPC_VENDOR, "amd" }, /* 059 */ { ud_itab__59, UD_TAB__OPC_SSE, "/sse" }, /* 060 */ { ud_itab__60, UD_TAB__OPC_MOD, "/mod" }, /* 061 */ { ud_itab__61, UD_TAB__OPC_VENDOR, "amd" }, /* 062 */ { ud_itab__62, UD_TAB__OPC_SSE, "/sse" }, /* 063 */ { ud_itab__63, UD_TAB__OPC_MOD, "/mod" }, /* 064 */ { ud_itab__64, UD_TAB__OPC_VENDOR, "amd" }, /* 065 */ { ud_itab__65, UD_TAB__OPC_SSE, "/sse" }, /* 066 */ { ud_itab__66, UD_TAB__OPC_MOD, "/mod" }, /* 067 */ { ud_itab__67, UD_TAB__OPC_VENDOR, "amd" }, /* 068 */ { ud_itab__68, UD_TAB__OPC_SSE, "/sse" }, /* 069 */ { ud_itab__69, UD_TAB__OPC_MOD, "/mod" }, /* 070 */ { ud_itab__70, UD_TAB__OPC_VENDOR, "amd" }, /* 071 */ { ud_itab__71, UD_TAB__OPC_SSE, "/sse" }, /* 072 */ { ud_itab__72, UD_TAB__OPC_MOD, "/mod" }, /* 073 */ { ud_itab__73, UD_TAB__OPC_VENDOR, "amd" }, /* 074 */ { ud_itab__74, UD_TAB__OPC_SSE, "/sse" }, /* 075 */ { ud_itab__75, UD_TAB__OPC_MOD, "/mod" }, /* 076 */ { ud_itab__76, UD_TAB__OPC_VENDOR, "amd" }, /* 077 */ { ud_itab__77, UD_TAB__OPC_SSE, "/sse" }, /* 078 */ { ud_itab__78, UD_TAB__OPC_MOD, "/mod" }, /* 079 */ { ud_itab__79, UD_TAB__OPC_SSE, "/sse" }, /* 080 */ { ud_itab__80, UD_TAB__OPC_MOD, "/mod" }, /* 081 */ { ud_itab__81, UD_TAB__OPC_RM, "/rm" }, /* 082 */ { ud_itab__82, UD_TAB__OPC_SSE, "/sse" }, /* 083 */ { ud_itab__83, UD_TAB__OPC_MOD, "/mod" }, /* 084 */ { ud_itab__84, UD_TAB__OPC_SSE, "/sse" }, /* 085 */ { ud_itab__85, UD_TAB__OPC_MOD, "/mod" }, /* 086 */ { ud_itab__86, UD_TAB__OPC_VENDOR, "amd" }, /* 087 */ { ud_itab__87, UD_TAB__OPC_SSE, "/sse" }, /* 088 */ { ud_itab__88, UD_TAB__OPC_SSE, "/sse" }, /* 089 */ { ud_itab__89, UD_TAB__OPC_SSE, "/sse" }, /* 090 */ { ud_itab__90, UD_TAB__OPC_SSE, "/sse" }, /* 091 */ { ud_itab__91, UD_TAB__OPC_SSE, "/sse" }, /* 092 */ { ud_itab__92, UD_TAB__OPC_SSE, "/sse" }, /* 093 */ { ud_itab__93, UD_TAB__OPC_SSE, "/sse" }, /* 094 */ { ud_itab__94, UD_TAB__OPC_SSE, "/sse" }, /* 095 */ { ud_itab__95, UD_TAB__OPC_REG, "/reg" }, /* 096 */ { ud_itab__96, UD_TAB__OPC_SSE, "/sse" }, /* 097 */ { ud_itab__97, UD_TAB__OPC_SSE, "/sse" }, /* 098 */ { ud_itab__98, UD_TAB__OPC_SSE, "/sse" }, /* 099 */ { ud_itab__99, UD_TAB__OPC_SSE, "/sse" }, /* 100 */ { ud_itab__100, UD_TAB__OPC_SSE, "/sse" }, /* 101 */ { ud_itab__101, UD_TAB__OPC_SSE, "/sse" }, /* 102 */ { ud_itab__102, UD_TAB__OPC_SSE, "/sse" }, /* 103 */ { ud_itab__103, UD_TAB__OPC_SSE, "/sse" }, /* 104 */ { ud_itab__104, UD_TAB__OPC_SSE, "/sse" }, /* 105 */ { ud_itab__105, UD_TAB__OPC_3DNOW, "/3dnow" }, /* 106 */ { ud_itab__106, UD_TAB__OPC_SSE, "/sse" }, /* 107 */ { ud_itab__107, UD_TAB__OPC_SSE, "/sse" }, /* 108 */ { ud_itab__108, UD_TAB__OPC_MOD, "/mod" }, /* 109 */ { ud_itab__109, UD_TAB__OPC_SSE, "/sse" }, /* 110 */ { ud_itab__110, UD_TAB__OPC_MOD, "/mod" }, /* 111 */ { ud_itab__111, UD_TAB__OPC_MOD, "/mod" }, /* 112 */ { ud_itab__112, UD_TAB__OPC_MOD, "/mod" }, /* 113 */ { ud_itab__113, UD_TAB__OPC_MOD, "/mod" }, /* 114 */ { ud_itab__114, UD_TAB__OPC_SSE, "/sse" }, /* 115 */ { ud_itab__115, UD_TAB__OPC_MOD, "/mod" }, /* 116 */ { ud_itab__116, UD_TAB__OPC_MOD, "/mod" }, /* 117 */ { ud_itab__117, UD_TAB__OPC_MOD, "/mod" }, /* 118 */ { ud_itab__118, UD_TAB__OPC_SSE, "/sse" }, /* 119 */ { ud_itab__119, UD_TAB__OPC_SSE, "/sse" }, /* 120 */ { ud_itab__120, UD_TAB__OPC_SSE, "/sse" }, /* 121 */ { ud_itab__121, UD_TAB__OPC_MOD, "/mod" }, /* 122 */ { ud_itab__122, UD_TAB__OPC_SSE, "/sse" }, /* 123 */ { ud_itab__123, UD_TAB__OPC_MOD, "/mod" }, /* 124 */ { ud_itab__124, UD_TAB__OPC_MOD, "/mod" }, /* 125 */ { ud_itab__125, UD_TAB__OPC_MOD, "/mod" }, /* 126 */ { ud_itab__126, UD_TAB__OPC_SSE, "/sse" }, /* 127 */ { ud_itab__127, UD_TAB__OPC_MOD, "/mod" }, /* 128 */ { ud_itab__128, UD_TAB__OPC_MOD, "/mod" }, /* 129 */ { ud_itab__129, UD_TAB__OPC_SSE, "/sse" }, /* 130 */ { ud_itab__130, UD_TAB__OPC_REG, "/reg" }, /* 131 */ { ud_itab__131, UD_TAB__OPC_SSE, "/sse" }, /* 132 */ { ud_itab__132, UD_TAB__OPC_SSE, "/sse" }, /* 133 */ { ud_itab__133, UD_TAB__OPC_SSE, "/sse" }, /* 134 */ { ud_itab__134, UD_TAB__OPC_SSE, "/sse" }, /* 135 */ { ud_itab__135, UD_TAB__OPC_SSE, "/sse" }, /* 136 */ { ud_itab__136, UD_TAB__OPC_SSE, "/sse" }, /* 137 */ { ud_itab__137, UD_TAB__OPC_SSE, "/sse" }, /* 138 */ { ud_itab__138, UD_TAB__OPC_SSE, "/sse" }, /* 139 */ { ud_itab__139, UD_TAB__OPC_SSE, "/sse" }, /* 140 */ { ud_itab__140, UD_TAB__OPC_SSE, "/sse" }, /* 141 */ { ud_itab__141, UD_TAB__OPC_SSE, "/sse" }, /* 142 */ { ud_itab__142, UD_TAB__OPC_SSE, "/sse" }, /* 143 */ { ud_itab__143, UD_TAB__OPC_SSE, "/sse" }, /* 144 */ { ud_itab__144, UD_TAB__OPC_SSE, "/sse" }, /* 145 */ { ud_itab__145, UD_TAB__OPC_SSE, "/sse" }, /* 146 */ { ud_itab__146, UD_TAB__OPC_SSE, "/sse" }, /* 147 */ { ud_itab__147, UD_TAB__OPC_SSE, "/sse" }, /* 148 */ { ud_itab__148, UD_TAB__OPC_SSE, "/sse" }, /* 149 */ { ud_itab__149, UD_TAB__OPC_SSE, "/sse" }, /* 150 */ { ud_itab__150, UD_TAB__OPC_SSE, "/sse" }, /* 151 */ { ud_itab__151, UD_TAB__OPC_SSE, "/sse" }, /* 152 */ { ud_itab__152, UD_TAB__OPC_SSE, "/sse" }, /* 153 */ { ud_itab__153, UD_TAB__OPC_SSE, "/sse" }, /* 154 */ { ud_itab__154, UD_TAB__OPC_SSE, "/sse" }, /* 155 */ { ud_itab__155, UD_TAB__OPC_SSE, "/sse" }, /* 156 */ { ud_itab__156, UD_TAB__OPC_SSE, "/sse" }, /* 157 */ { ud_itab__157, UD_TAB__OPC_SSE, "/sse" }, /* 158 */ { ud_itab__158, UD_TAB__OPC_SSE, "/sse" }, /* 159 */ { ud_itab__159, UD_TAB__OPC_MODE, "/m" }, /* 160 */ { ud_itab__160, UD_TAB__OPC_VENDOR, "intel" }, /* 161 */ { ud_itab__161, UD_TAB__OPC_SSE, "/sse" }, /* 162 */ { ud_itab__162, UD_TAB__OPC_MODE, "/m" }, /* 163 */ { ud_itab__163, UD_TAB__OPC_VENDOR, "intel" }, /* 164 */ { ud_itab__164, UD_TAB__OPC_SSE, "/sse" }, /* 165 */ { ud_itab__165, UD_TAB__OPC_TABLE, "38" }, /* 166 */ { ud_itab__166, UD_TAB__OPC_SSE, "/sse" }, /* 167 */ { ud_itab__167, UD_TAB__OPC_SSE, "/sse" }, /* 168 */ { ud_itab__168, UD_TAB__OPC_SSE, "/sse" }, /* 169 */ { ud_itab__169, UD_TAB__OPC_SSE, "/sse" }, /* 170 */ { ud_itab__170, UD_TAB__OPC_SSE, "/sse" }, /* 171 */ { ud_itab__171, UD_TAB__OPC_SSE, "/sse" }, /* 172 */ { ud_itab__172, UD_TAB__OPC_SSE, "/sse" }, /* 173 */ { ud_itab__173, UD_TAB__OPC_SSE, "/sse" }, /* 174 */ { ud_itab__174, UD_TAB__OPC_SSE, "/sse" }, /* 175 */ { ud_itab__175, UD_TAB__OPC_SSE, "/sse" }, /* 176 */ { ud_itab__176, UD_TAB__OPC_SSE, "/sse" }, /* 177 */ { ud_itab__177, UD_TAB__OPC_SSE, "/sse" }, /* 178 */ { ud_itab__178, UD_TAB__OPC_SSE, "/sse" }, /* 179 */ { ud_itab__179, UD_TAB__OPC_SSE, "/sse" }, /* 180 */ { ud_itab__180, UD_TAB__OPC_SSE, "/sse" }, /* 181 */ { ud_itab__181, UD_TAB__OPC_SSE, "/sse" }, /* 182 */ { ud_itab__182, UD_TAB__OPC_SSE, "/sse" }, /* 183 */ { ud_itab__183, UD_TAB__OPC_SSE, "/sse" }, /* 184 */ { ud_itab__184, UD_TAB__OPC_SSE, "/sse" }, /* 185 */ { ud_itab__185, UD_TAB__OPC_SSE, "/sse" }, /* 186 */ { ud_itab__186, UD_TAB__OPC_SSE, "/sse" }, /* 187 */ { ud_itab__187, UD_TAB__OPC_SSE, "/sse" }, /* 188 */ { ud_itab__188, UD_TAB__OPC_SSE, "/sse" }, /* 189 */ { ud_itab__189, UD_TAB__OPC_SSE, "/sse" }, /* 190 */ { ud_itab__190, UD_TAB__OPC_SSE, "/sse" }, /* 191 */ { ud_itab__191, UD_TAB__OPC_SSE, "/sse" }, /* 192 */ { ud_itab__192, UD_TAB__OPC_SSE, "/sse" }, /* 193 */ { ud_itab__193, UD_TAB__OPC_SSE, "/sse" }, /* 194 */ { ud_itab__194, UD_TAB__OPC_SSE, "/sse" }, /* 195 */ { ud_itab__195, UD_TAB__OPC_SSE, "/sse" }, /* 196 */ { ud_itab__196, UD_TAB__OPC_SSE, "/sse" }, /* 197 */ { ud_itab__197, UD_TAB__OPC_SSE, "/sse" }, /* 198 */ { ud_itab__198, UD_TAB__OPC_SSE, "/sse" }, /* 199 */ { ud_itab__199, UD_TAB__OPC_SSE, "/sse" }, /* 200 */ { ud_itab__200, UD_TAB__OPC_SSE, "/sse" }, /* 201 */ { ud_itab__201, UD_TAB__OPC_SSE, "/sse" }, /* 202 */ { ud_itab__202, UD_TAB__OPC_SSE, "/sse" }, /* 203 */ { ud_itab__203, UD_TAB__OPC_SSE, "/sse" }, /* 204 */ { ud_itab__204, UD_TAB__OPC_SSE, "/sse" }, /* 205 */ { ud_itab__205, UD_TAB__OPC_SSE, "/sse" }, /* 206 */ { ud_itab__206, UD_TAB__OPC_SSE, "/sse" }, /* 207 */ { ud_itab__207, UD_TAB__OPC_SSE, "/sse" }, /* 208 */ { ud_itab__208, UD_TAB__OPC_SSE, "/sse" }, /* 209 */ { ud_itab__209, UD_TAB__OPC_SSE, "/sse" }, /* 210 */ { ud_itab__210, UD_TAB__OPC_SSE, "/sse" }, /* 211 */ { ud_itab__211, UD_TAB__OPC_SSE, "/sse" }, /* 212 */ { ud_itab__212, UD_TAB__OPC_SSE, "/sse" }, /* 213 */ { ud_itab__213, UD_TAB__OPC_MODE, "/m" }, /* 214 */ { ud_itab__214, UD_TAB__OPC_VENDOR, "intel" }, /* 215 */ { ud_itab__215, UD_TAB__OPC_SSE, "/sse" }, /* 216 */ { ud_itab__216, UD_TAB__OPC_MODE, "/m" }, /* 217 */ { ud_itab__217, UD_TAB__OPC_VENDOR, "intel" }, /* 218 */ { ud_itab__218, UD_TAB__OPC_SSE, "/sse" }, /* 219 */ { ud_itab__219, UD_TAB__OPC_SSE, "/sse" }, /* 220 */ { ud_itab__220, UD_TAB__OPC_SSE, "/sse" }, /* 221 */ { ud_itab__221, UD_TAB__OPC_SSE, "/sse" }, /* 222 */ { ud_itab__222, UD_TAB__OPC_SSE, "/sse" }, /* 223 */ { ud_itab__223, UD_TAB__OPC_SSE, "/sse" }, /* 224 */ { ud_itab__224, UD_TAB__OPC_SSE, "/sse" }, /* 225 */ { ud_itab__225, UD_TAB__OPC_TABLE, "3a" }, /* 226 */ { ud_itab__226, UD_TAB__OPC_SSE, "/sse" }, /* 227 */ { ud_itab__227, UD_TAB__OPC_SSE, "/sse" }, /* 228 */ { ud_itab__228, UD_TAB__OPC_SSE, "/sse" }, /* 229 */ { ud_itab__229, UD_TAB__OPC_SSE, "/sse" }, /* 230 */ { ud_itab__230, UD_TAB__OPC_SSE, "/sse" }, /* 231 */ { ud_itab__231, UD_TAB__OPC_SSE, "/sse" }, /* 232 */ { ud_itab__232, UD_TAB__OPC_SSE, "/sse" }, /* 233 */ { ud_itab__233, UD_TAB__OPC_SSE, "/sse" }, /* 234 */ { ud_itab__234, UD_TAB__OPC_SSE, "/sse" }, /* 235 */ { ud_itab__235, UD_TAB__OPC_SSE, "/sse" }, /* 236 */ { ud_itab__236, UD_TAB__OPC_SSE, "/sse" }, /* 237 */ { ud_itab__237, UD_TAB__OPC_OSIZE, "/o" }, /* 238 */ { ud_itab__238, UD_TAB__OPC_SSE, "/sse" }, /* 239 */ { ud_itab__239, UD_TAB__OPC_SSE, "/sse" }, /* 240 */ { ud_itab__240, UD_TAB__OPC_SSE, "/sse" }, /* 241 */ { ud_itab__241, UD_TAB__OPC_SSE, "/sse" }, /* 242 */ { ud_itab__242, UD_TAB__OPC_OSIZE, "/o" }, /* 243 */ { ud_itab__243, UD_TAB__OPC_SSE, "/sse" }, /* 244 */ { ud_itab__244, UD_TAB__OPC_SSE, "/sse" }, /* 245 */ { ud_itab__245, UD_TAB__OPC_SSE, "/sse" }, /* 246 */ { ud_itab__246, UD_TAB__OPC_SSE, "/sse" }, /* 247 */ { ud_itab__247, UD_TAB__OPC_SSE, "/sse" }, /* 248 */ { ud_itab__248, UD_TAB__OPC_SSE, "/sse" }, /* 249 */ { ud_itab__249, UD_TAB__OPC_SSE, "/sse" }, /* 250 */ { ud_itab__250, UD_TAB__OPC_SSE, "/sse" }, /* 251 */ { ud_itab__251, UD_TAB__OPC_SSE, "/sse" }, /* 252 */ { ud_itab__252, UD_TAB__OPC_SSE, "/sse" }, /* 253 */ { ud_itab__253, UD_TAB__OPC_SSE, "/sse" }, /* 254 */ { ud_itab__254, UD_TAB__OPC_SSE, "/sse" }, /* 255 */ { ud_itab__255, UD_TAB__OPC_SSE, "/sse" }, /* 256 */ { ud_itab__256, UD_TAB__OPC_SSE, "/sse" }, /* 257 */ { ud_itab__257, UD_TAB__OPC_SSE, "/sse" }, /* 258 */ { ud_itab__258, UD_TAB__OPC_SSE, "/sse" }, /* 259 */ { ud_itab__259, UD_TAB__OPC_SSE, "/sse" }, /* 260 */ { ud_itab__260, UD_TAB__OPC_SSE, "/sse" }, /* 261 */ { ud_itab__261, UD_TAB__OPC_SSE, "/sse" }, /* 262 */ { ud_itab__262, UD_TAB__OPC_SSE, "/sse" }, /* 263 */ { ud_itab__263, UD_TAB__OPC_SSE, "/sse" }, /* 264 */ { ud_itab__264, UD_TAB__OPC_SSE, "/sse" }, /* 265 */ { ud_itab__265, UD_TAB__OPC_SSE, "/sse" }, /* 266 */ { ud_itab__266, UD_TAB__OPC_SSE, "/sse" }, /* 267 */ { ud_itab__267, UD_TAB__OPC_SSE, "/sse" }, /* 268 */ { ud_itab__268, UD_TAB__OPC_SSE, "/sse" }, /* 269 */ { ud_itab__269, UD_TAB__OPC_SSE, "/sse" }, /* 270 */ { ud_itab__270, UD_TAB__OPC_SSE, "/sse" }, /* 271 */ { ud_itab__271, UD_TAB__OPC_SSE, "/sse" }, /* 272 */ { ud_itab__272, UD_TAB__OPC_SSE, "/sse" }, /* 273 */ { ud_itab__273, UD_TAB__OPC_SSE, "/sse" }, /* 274 */ { ud_itab__274, UD_TAB__OPC_SSE, "/sse" }, /* 275 */ { ud_itab__275, UD_TAB__OPC_SSE, "/sse" }, /* 276 */ { ud_itab__276, UD_TAB__OPC_SSE, "/sse" }, /* 277 */ { ud_itab__277, UD_TAB__OPC_SSE, "/sse" }, /* 278 */ { ud_itab__278, UD_TAB__OPC_SSE, "/sse" }, /* 279 */ { ud_itab__279, UD_TAB__OPC_SSE, "/sse" }, /* 280 */ { ud_itab__280, UD_TAB__OPC_SSE, "/sse" }, /* 281 */ { ud_itab__281, UD_TAB__OPC_SSE, "/sse" }, /* 282 */ { ud_itab__282, UD_TAB__OPC_SSE, "/sse" }, /* 283 */ { ud_itab__283, UD_TAB__OPC_SSE, "/sse" }, /* 284 */ { ud_itab__284, UD_TAB__OPC_SSE, "/sse" }, /* 285 */ { ud_itab__285, UD_TAB__OPC_SSE, "/sse" }, /* 286 */ { ud_itab__286, UD_TAB__OPC_SSE, "/sse" }, /* 287 */ { ud_itab__287, UD_TAB__OPC_SSE, "/sse" }, /* 288 */ { ud_itab__288, UD_TAB__OPC_SSE, "/sse" }, /* 289 */ { ud_itab__289, UD_TAB__OPC_SSE, "/sse" }, /* 290 */ { ud_itab__290, UD_TAB__OPC_SSE, "/sse" }, /* 291 */ { ud_itab__291, UD_TAB__OPC_SSE, "/sse" }, /* 292 */ { ud_itab__292, UD_TAB__OPC_SSE, "/sse" }, /* 293 */ { ud_itab__293, UD_TAB__OPC_SSE, "/sse" }, /* 294 */ { ud_itab__294, UD_TAB__OPC_SSE, "/sse" }, /* 295 */ { ud_itab__295, UD_TAB__OPC_SSE, "/sse" }, /* 296 */ { ud_itab__296, UD_TAB__OPC_SSE, "/sse" }, /* 297 */ { ud_itab__297, UD_TAB__OPC_SSE, "/sse" }, /* 298 */ { ud_itab__298, UD_TAB__OPC_SSE, "/sse" }, /* 299 */ { ud_itab__299, UD_TAB__OPC_SSE, "/sse" }, /* 300 */ { ud_itab__300, UD_TAB__OPC_SSE, "/sse" }, /* 301 */ { ud_itab__301, UD_TAB__OPC_REG, "/reg" }, /* 302 */ { ud_itab__302, UD_TAB__OPC_SSE, "/sse" }, /* 303 */ { ud_itab__303, UD_TAB__OPC_SSE, "/sse" }, /* 304 */ { ud_itab__304, UD_TAB__OPC_SSE, "/sse" }, /* 305 */ { ud_itab__305, UD_TAB__OPC_REG, "/reg" }, /* 306 */ { ud_itab__306, UD_TAB__OPC_SSE, "/sse" }, /* 307 */ { ud_itab__307, UD_TAB__OPC_SSE, "/sse" }, /* 308 */ { ud_itab__308, UD_TAB__OPC_SSE, "/sse" }, /* 309 */ { ud_itab__309, UD_TAB__OPC_REG, "/reg" }, /* 310 */ { ud_itab__310, UD_TAB__OPC_SSE, "/sse" }, /* 311 */ { ud_itab__311, UD_TAB__OPC_SSE, "/sse" }, /* 312 */ { ud_itab__312, UD_TAB__OPC_SSE, "/sse" }, /* 313 */ { ud_itab__313, UD_TAB__OPC_SSE, "/sse" }, /* 314 */ { ud_itab__314, UD_TAB__OPC_SSE, "/sse" }, /* 315 */ { ud_itab__315, UD_TAB__OPC_SSE, "/sse" }, /* 316 */ { ud_itab__316, UD_TAB__OPC_SSE, "/sse" }, /* 317 */ { ud_itab__317, UD_TAB__OPC_SSE, "/sse" }, /* 318 */ { ud_itab__318, UD_TAB__OPC_SSE, "/sse" }, /* 319 */ { ud_itab__319, UD_TAB__OPC_VENDOR, "intel" }, /* 320 */ { ud_itab__320, UD_TAB__OPC_SSE, "/sse" }, /* 321 */ { ud_itab__321, UD_TAB__OPC_VENDOR, "intel" }, /* 322 */ { ud_itab__322, UD_TAB__OPC_SSE, "/sse" }, /* 323 */ { ud_itab__323, UD_TAB__OPC_SSE, "/sse" }, /* 324 */ { ud_itab__324, UD_TAB__OPC_SSE, "/sse" }, /* 325 */ { ud_itab__325, UD_TAB__OPC_SSE, "/sse" }, /* 326 */ { ud_itab__326, UD_TAB__OPC_SSE, "/sse" }, /* 327 */ { ud_itab__327, UD_TAB__OPC_SSE, "/sse" }, /* 328 */ { ud_itab__328, UD_TAB__OPC_SSE, "/sse" }, /* 329 */ { ud_itab__329, UD_TAB__OPC_SSE, "/sse" }, /* 330 */ { ud_itab__330, UD_TAB__OPC_SSE, "/sse" }, /* 331 */ { ud_itab__331, UD_TAB__OPC_SSE, "/sse" }, /* 332 */ { ud_itab__332, UD_TAB__OPC_SSE, "/sse" }, /* 333 */ { ud_itab__333, UD_TAB__OPC_SSE, "/sse" }, /* 334 */ { ud_itab__334, UD_TAB__OPC_SSE, "/sse" }, /* 335 */ { ud_itab__335, UD_TAB__OPC_SSE, "/sse" }, /* 336 */ { ud_itab__336, UD_TAB__OPC_SSE, "/sse" }, /* 337 */ { ud_itab__337, UD_TAB__OPC_SSE, "/sse" }, /* 338 */ { ud_itab__338, UD_TAB__OPC_SSE, "/sse" }, /* 339 */ { ud_itab__339, UD_TAB__OPC_SSE, "/sse" }, /* 340 */ { ud_itab__340, UD_TAB__OPC_SSE, "/sse" }, /* 341 */ { ud_itab__341, UD_TAB__OPC_SSE, "/sse" }, /* 342 */ { ud_itab__342, UD_TAB__OPC_SSE, "/sse" }, /* 343 */ { ud_itab__343, UD_TAB__OPC_SSE, "/sse" }, /* 344 */ { ud_itab__344, UD_TAB__OPC_SSE, "/sse" }, /* 345 */ { ud_itab__345, UD_TAB__OPC_SSE, "/sse" }, /* 346 */ { ud_itab__346, UD_TAB__OPC_SSE, "/sse" }, /* 347 */ { ud_itab__347, UD_TAB__OPC_SSE, "/sse" }, /* 348 */ { ud_itab__348, UD_TAB__OPC_SSE, "/sse" }, /* 349 */ { ud_itab__349, UD_TAB__OPC_SSE, "/sse" }, /* 350 */ { ud_itab__350, UD_TAB__OPC_SSE, "/sse" }, /* 351 */ { ud_itab__351, UD_TAB__OPC_SSE, "/sse" }, /* 352 */ { ud_itab__352, UD_TAB__OPC_SSE, "/sse" }, /* 353 */ { ud_itab__353, UD_TAB__OPC_SSE, "/sse" }, /* 354 */ { ud_itab__354, UD_TAB__OPC_SSE, "/sse" }, /* 355 */ { ud_itab__355, UD_TAB__OPC_SSE, "/sse" }, /* 356 */ { ud_itab__356, UD_TAB__OPC_SSE, "/sse" }, /* 357 */ { ud_itab__357, UD_TAB__OPC_SSE, "/sse" }, /* 358 */ { ud_itab__358, UD_TAB__OPC_SSE, "/sse" }, /* 359 */ { ud_itab__359, UD_TAB__OPC_SSE, "/sse" }, /* 360 */ { ud_itab__360, UD_TAB__OPC_SSE, "/sse" }, /* 361 */ { ud_itab__361, UD_TAB__OPC_SSE, "/sse" }, /* 362 */ { ud_itab__362, UD_TAB__OPC_SSE, "/sse" }, /* 363 */ { ud_itab__363, UD_TAB__OPC_SSE, "/sse" }, /* 364 */ { ud_itab__364, UD_TAB__OPC_MOD, "/mod" }, /* 365 */ { ud_itab__365, UD_TAB__OPC_REG, "/reg" }, /* 366 */ { ud_itab__366, UD_TAB__OPC_RM, "/rm" }, /* 367 */ { ud_itab__367, UD_TAB__OPC_SSE, "/sse" }, /* 368 */ { ud_itab__368, UD_TAB__OPC_MOD, "/mod" }, /* 369 */ { ud_itab__369, UD_TAB__OPC_RM, "/rm" }, /* 370 */ { ud_itab__370, UD_TAB__OPC_SSE, "/sse" }, /* 371 */ { ud_itab__371, UD_TAB__OPC_MOD, "/mod" }, /* 372 */ { ud_itab__372, UD_TAB__OPC_RM, "/rm" }, /* 373 */ { ud_itab__373, UD_TAB__OPC_SSE, "/sse" }, /* 374 */ { ud_itab__374, UD_TAB__OPC_MOD, "/mod" }, /* 375 */ { ud_itab__375, UD_TAB__OPC_MOD, "/mod" }, /* 376 */ { ud_itab__376, UD_TAB__OPC_REG, "/reg" }, /* 377 */ { ud_itab__377, UD_TAB__OPC_RM, "/rm" }, /* 378 */ { ud_itab__378, UD_TAB__OPC_SSE, "/sse" }, /* 379 */ { ud_itab__379, UD_TAB__OPC_MOD, "/mod" }, /* 380 */ { ud_itab__380, UD_TAB__OPC_RM, "/rm" }, /* 381 */ { ud_itab__381, UD_TAB__OPC_SSE, "/sse" }, /* 382 */ { ud_itab__382, UD_TAB__OPC_MOD, "/mod" }, /* 383 */ { ud_itab__383, UD_TAB__OPC_RM, "/rm" }, /* 384 */ { ud_itab__384, UD_TAB__OPC_SSE, "/sse" }, /* 385 */ { ud_itab__385, UD_TAB__OPC_MOD, "/mod" }, /* 386 */ { ud_itab__386, UD_TAB__OPC_RM, "/rm" }, /* 387 */ { ud_itab__387, UD_TAB__OPC_SSE, "/sse" }, /* 388 */ { ud_itab__388, UD_TAB__OPC_MOD, "/mod" }, /* 389 */ { ud_itab__389, UD_TAB__OPC_RM, "/rm" }, /* 390 */ { ud_itab__390, UD_TAB__OPC_SSE, "/sse" }, /* 391 */ { ud_itab__391, UD_TAB__OPC_MOD, "/mod" }, /* 392 */ { ud_itab__392, UD_TAB__OPC_RM, "/rm" }, /* 393 */ { ud_itab__393, UD_TAB__OPC_SSE, "/sse" }, /* 394 */ { ud_itab__394, UD_TAB__OPC_MOD, "/mod" }, /* 395 */ { ud_itab__395, UD_TAB__OPC_SSE, "/sse" }, /* 396 */ { ud_itab__396, UD_TAB__OPC_SSE, "/sse" }, /* 397 */ { ud_itab__397, UD_TAB__OPC_SSE, "/sse" }, /* 398 */ { ud_itab__398, UD_TAB__OPC_SSE, "/sse" }, /* 399 */ { ud_itab__399, UD_TAB__OPC_SSE, "/sse" }, /* 400 */ { ud_itab__400, UD_TAB__OPC_SSE, "/sse" }, /* 401 */ { ud_itab__401, UD_TAB__OPC_MOD, "/mod" }, /* 402 */ { ud_itab__402, UD_TAB__OPC_REG, "/reg" }, /* 403 */ { ud_itab__403, UD_TAB__OPC_SSE, "/sse" }, /* 404 */ { ud_itab__404, UD_TAB__OPC_MOD, "/mod" }, /* 405 */ { ud_itab__405, UD_TAB__OPC_SSE, "/sse" }, /* 406 */ { ud_itab__406, UD_TAB__OPC_MOD, "/mod" }, /* 407 */ { ud_itab__407, UD_TAB__OPC_SSE, "/sse" }, /* 408 */ { ud_itab__408, UD_TAB__OPC_MOD, "/mod" }, /* 409 */ { ud_itab__409, UD_TAB__OPC_SSE, "/sse" }, /* 410 */ { ud_itab__410, UD_TAB__OPC_MOD, "/mod" }, /* 411 */ { ud_itab__411, UD_TAB__OPC_SSE, "/sse" }, /* 412 */ { ud_itab__412, UD_TAB__OPC_MOD, "/mod" }, /* 413 */ { ud_itab__413, UD_TAB__OPC_SSE, "/sse" }, /* 414 */ { ud_itab__414, UD_TAB__OPC_MOD, "/mod" }, /* 415 */ { ud_itab__415, UD_TAB__OPC_SSE, "/sse" }, /* 416 */ { ud_itab__416, UD_TAB__OPC_MOD, "/mod" }, /* 417 */ { ud_itab__417, UD_TAB__OPC_REG, "/reg" }, /* 418 */ { ud_itab__418, UD_TAB__OPC_RM, "/rm" }, /* 419 */ { ud_itab__419, UD_TAB__OPC_SSE, "/sse" }, /* 420 */ { ud_itab__420, UD_TAB__OPC_MOD, "/mod" }, /* 421 */ { ud_itab__421, UD_TAB__OPC_SSE, "/sse" }, /* 422 */ { ud_itab__422, UD_TAB__OPC_MOD, "/mod" }, /* 423 */ { ud_itab__423, UD_TAB__OPC_SSE, "/sse" }, /* 424 */ { ud_itab__424, UD_TAB__OPC_MOD, "/mod" }, /* 425 */ { ud_itab__425, UD_TAB__OPC_SSE, "/sse" }, /* 426 */ { ud_itab__426, UD_TAB__OPC_MOD, "/mod" }, /* 427 */ { ud_itab__427, UD_TAB__OPC_SSE, "/sse" }, /* 428 */ { ud_itab__428, UD_TAB__OPC_MOD, "/mod" }, /* 429 */ { ud_itab__429, UD_TAB__OPC_SSE, "/sse" }, /* 430 */ { ud_itab__430, UD_TAB__OPC_MOD, "/mod" }, /* 431 */ { ud_itab__431, UD_TAB__OPC_SSE, "/sse" }, /* 432 */ { ud_itab__432, UD_TAB__OPC_MOD, "/mod" }, /* 433 */ { ud_itab__433, UD_TAB__OPC_SSE, "/sse" }, /* 434 */ { ud_itab__434, UD_TAB__OPC_MOD, "/mod" }, /* 435 */ { ud_itab__435, UD_TAB__OPC_RM, "/rm" }, /* 436 */ { ud_itab__436, UD_TAB__OPC_SSE, "/sse" }, /* 437 */ { ud_itab__437, UD_TAB__OPC_MOD, "/mod" }, /* 438 */ { ud_itab__438, UD_TAB__OPC_SSE, "/sse" }, /* 439 */ { ud_itab__439, UD_TAB__OPC_MOD, "/mod" }, /* 440 */ { ud_itab__440, UD_TAB__OPC_SSE, "/sse" }, /* 441 */ { ud_itab__441, UD_TAB__OPC_MOD, "/mod" }, /* 442 */ { ud_itab__442, UD_TAB__OPC_SSE, "/sse" }, /* 443 */ { ud_itab__443, UD_TAB__OPC_MOD, "/mod" }, /* 444 */ { ud_itab__444, UD_TAB__OPC_SSE, "/sse" }, /* 445 */ { ud_itab__445, UD_TAB__OPC_MOD, "/mod" }, /* 446 */ { ud_itab__446, UD_TAB__OPC_SSE, "/sse" }, /* 447 */ { ud_itab__447, UD_TAB__OPC_MOD, "/mod" }, /* 448 */ { ud_itab__448, UD_TAB__OPC_SSE, "/sse" }, /* 449 */ { ud_itab__449, UD_TAB__OPC_MOD, "/mod" }, /* 450 */ { ud_itab__450, UD_TAB__OPC_SSE, "/sse" }, /* 451 */ { ud_itab__451, UD_TAB__OPC_MOD, "/mod" }, /* 452 */ { ud_itab__452, UD_TAB__OPC_RM, "/rm" }, /* 453 */ { ud_itab__453, UD_TAB__OPC_SSE, "/sse" }, /* 454 */ { ud_itab__454, UD_TAB__OPC_MOD, "/mod" }, /* 455 */ { ud_itab__455, UD_TAB__OPC_SSE, "/sse" }, /* 456 */ { ud_itab__456, UD_TAB__OPC_MOD, "/mod" }, /* 457 */ { ud_itab__457, UD_TAB__OPC_SSE, "/sse" }, /* 458 */ { ud_itab__458, UD_TAB__OPC_MOD, "/mod" }, /* 459 */ { ud_itab__459, UD_TAB__OPC_SSE, "/sse" }, /* 460 */ { ud_itab__460, UD_TAB__OPC_MOD, "/mod" }, /* 461 */ { ud_itab__461, UD_TAB__OPC_SSE, "/sse" }, /* 462 */ { ud_itab__462, UD_TAB__OPC_MOD, "/mod" }, /* 463 */ { ud_itab__463, UD_TAB__OPC_SSE, "/sse" }, /* 464 */ { ud_itab__464, UD_TAB__OPC_MOD, "/mod" }, /* 465 */ { ud_itab__465, UD_TAB__OPC_SSE, "/sse" }, /* 466 */ { ud_itab__466, UD_TAB__OPC_MOD, "/mod" }, /* 467 */ { ud_itab__467, UD_TAB__OPC_SSE, "/sse" }, /* 468 */ { ud_itab__468, UD_TAB__OPC_MOD, "/mod" }, /* 469 */ { ud_itab__469, UD_TAB__OPC_SSE, "/sse" }, /* 470 */ { ud_itab__470, UD_TAB__OPC_SSE, "/sse" }, /* 471 */ { ud_itab__471, UD_TAB__OPC_SSE, "/sse" }, /* 472 */ { ud_itab__472, UD_TAB__OPC_SSE, "/sse" }, /* 473 */ { ud_itab__473, UD_TAB__OPC_SSE, "/sse" }, /* 474 */ { ud_itab__474, UD_TAB__OPC_SSE, "/sse" }, /* 475 */ { ud_itab__475, UD_TAB__OPC_SSE, "/sse" }, /* 476 */ { ud_itab__476, UD_TAB__OPC_SSE, "/sse" }, /* 477 */ { ud_itab__477, UD_TAB__OPC_SSE, "/sse" }, /* 478 */ { ud_itab__478, UD_TAB__OPC_SSE, "/sse" }, /* 479 */ { ud_itab__479, UD_TAB__OPC_REG, "/reg" }, /* 480 */ { ud_itab__480, UD_TAB__OPC_SSE, "/sse" }, /* 481 */ { ud_itab__481, UD_TAB__OPC_SSE, "/sse" }, /* 482 */ { ud_itab__482, UD_TAB__OPC_SSE, "/sse" }, /* 483 */ { ud_itab__483, UD_TAB__OPC_SSE, "/sse" }, /* 484 */ { ud_itab__484, UD_TAB__OPC_SSE, "/sse" }, /* 485 */ { ud_itab__485, UD_TAB__OPC_SSE, "/sse" }, /* 486 */ { ud_itab__486, UD_TAB__OPC_SSE, "/sse" }, /* 487 */ { ud_itab__487, UD_TAB__OPC_SSE, "/sse" }, /* 488 */ { ud_itab__488, UD_TAB__OPC_SSE, "/sse" }, /* 489 */ { ud_itab__489, UD_TAB__OPC_SSE, "/sse" }, /* 490 */ { ud_itab__490, UD_TAB__OPC_SSE, "/sse" }, /* 491 */ { ud_itab__491, UD_TAB__OPC_SSE, "/sse" }, /* 492 */ { ud_itab__492, UD_TAB__OPC_SSE, "/sse" }, /* 493 */ { ud_itab__493, UD_TAB__OPC_SSE, "/sse" }, /* 494 */ { ud_itab__494, UD_TAB__OPC_SSE, "/sse" }, /* 495 */ { ud_itab__495, UD_TAB__OPC_SSE, "/sse" }, /* 496 */ { ud_itab__496, UD_TAB__OPC_REG, "/reg" }, /* 497 */ { ud_itab__497, UD_TAB__OPC_SSE, "/sse" }, /* 498 */ { ud_itab__498, UD_TAB__OPC_OSIZE, "/o" }, /* 499 */ { ud_itab__499, UD_TAB__OPC_SSE, "/sse" }, /* 500 */ { ud_itab__500, UD_TAB__OPC_VENDOR, "intel" }, /* 501 */ { ud_itab__501, UD_TAB__OPC_VENDOR, "intel" }, /* 502 */ { ud_itab__502, UD_TAB__OPC_VENDOR, "intel" }, /* 503 */ { ud_itab__503, UD_TAB__OPC_SSE, "/sse" }, /* 504 */ { ud_itab__504, UD_TAB__OPC_VENDOR, "intel" }, /* 505 */ { ud_itab__505, UD_TAB__OPC_SSE, "/sse" }, /* 506 */ { ud_itab__506, UD_TAB__OPC_SSE, "/sse" }, /* 507 */ { ud_itab__507, UD_TAB__OPC_SSE, "/sse" }, /* 508 */ { ud_itab__508, UD_TAB__OPC_SSE, "/sse" }, /* 509 */ { ud_itab__509, UD_TAB__OPC_SSE, "/sse" }, /* 510 */ { ud_itab__510, UD_TAB__OPC_SSE, "/sse" }, /* 511 */ { ud_itab__511, UD_TAB__OPC_SSE, "/sse" }, /* 512 */ { ud_itab__512, UD_TAB__OPC_SSE, "/sse" }, /* 513 */ { ud_itab__513, UD_TAB__OPC_SSE, "/sse" }, /* 514 */ { ud_itab__514, UD_TAB__OPC_SSE, "/sse" }, /* 515 */ { ud_itab__515, UD_TAB__OPC_SSE, "/sse" }, /* 516 */ { ud_itab__516, UD_TAB__OPC_SSE, "/sse" }, /* 517 */ { ud_itab__517, UD_TAB__OPC_SSE, "/sse" }, /* 518 */ { ud_itab__518, UD_TAB__OPC_SSE, "/sse" }, /* 519 */ { ud_itab__519, UD_TAB__OPC_SSE, "/sse" }, /* 520 */ { ud_itab__520, UD_TAB__OPC_SSE, "/sse" }, /* 521 */ { ud_itab__521, UD_TAB__OPC_SSE, "/sse" }, /* 522 */ { ud_itab__522, UD_TAB__OPC_SSE, "/sse" }, /* 523 */ { ud_itab__523, UD_TAB__OPC_SSE, "/sse" }, /* 524 */ { ud_itab__524, UD_TAB__OPC_SSE, "/sse" }, /* 525 */ { ud_itab__525, UD_TAB__OPC_SSE, "/sse" }, /* 526 */ { ud_itab__526, UD_TAB__OPC_SSE, "/sse" }, /* 527 */ { ud_itab__527, UD_TAB__OPC_SSE, "/sse" }, /* 528 */ { ud_itab__528, UD_TAB__OPC_SSE, "/sse" }, /* 529 */ { ud_itab__529, UD_TAB__OPC_SSE, "/sse" }, /* 530 */ { ud_itab__530, UD_TAB__OPC_SSE, "/sse" }, /* 531 */ { ud_itab__531, UD_TAB__OPC_SSE, "/sse" }, /* 532 */ { ud_itab__532, UD_TAB__OPC_SSE, "/sse" }, /* 533 */ { ud_itab__533, UD_TAB__OPC_SSE, "/sse" }, /* 534 */ { ud_itab__534, UD_TAB__OPC_SSE, "/sse" }, /* 535 */ { ud_itab__535, UD_TAB__OPC_SSE, "/sse" }, /* 536 */ { ud_itab__536, UD_TAB__OPC_SSE, "/sse" }, /* 537 */ { ud_itab__537, UD_TAB__OPC_SSE, "/sse" }, /* 538 */ { ud_itab__538, UD_TAB__OPC_SSE, "/sse" }, /* 539 */ { ud_itab__539, UD_TAB__OPC_SSE, "/sse" }, /* 540 */ { ud_itab__540, UD_TAB__OPC_SSE, "/sse" }, /* 541 */ { ud_itab__541, UD_TAB__OPC_SSE, "/sse" }, /* 542 */ { ud_itab__542, UD_TAB__OPC_SSE, "/sse" }, /* 543 */ { ud_itab__543, UD_TAB__OPC_SSE, "/sse" }, /* 544 */ { ud_itab__544, UD_TAB__OPC_SSE, "/sse" }, /* 545 */ { ud_itab__545, UD_TAB__OPC_SSE, "/sse" }, /* 546 */ { ud_itab__546, UD_TAB__OPC_SSE, "/sse" }, /* 547 */ { ud_itab__547, UD_TAB__OPC_SSE, "/sse" }, /* 548 */ { ud_itab__548, UD_TAB__OPC_SSE, "/sse" }, /* 549 */ { ud_itab__549, UD_TAB__OPC_SSE, "/sse" }, /* 550 */ { ud_itab__550, UD_TAB__OPC_SSE, "/sse" }, /* 551 */ { ud_itab__551, UD_TAB__OPC_SSE, "/sse" }, /* 552 */ { ud_itab__552, UD_TAB__OPC_MOD, "/mod" }, /* 553 */ { ud_itab__553, UD_TAB__OPC_SSE, "/sse" }, /* 554 */ { ud_itab__554, UD_TAB__OPC_MOD, "/mod" }, /* 555 */ { ud_itab__555, UD_TAB__OPC_MOD, "/mod" }, /* 556 */ { ud_itab__556, UD_TAB__OPC_SSE, "/sse" }, /* 557 */ { ud_itab__557, UD_TAB__OPC_SSE, "/sse" }, /* 558 */ { ud_itab__558, UD_TAB__OPC_SSE, "/sse" }, /* 559 */ { ud_itab__559, UD_TAB__OPC_SSE, "/sse" }, /* 560 */ { ud_itab__560, UD_TAB__OPC_SSE, "/sse" }, /* 561 */ { ud_itab__561, UD_TAB__OPC_SSE, "/sse" }, /* 562 */ { ud_itab__562, UD_TAB__OPC_SSE, "/sse" }, /* 563 */ { ud_itab__563, UD_TAB__OPC_MODE, "/m" }, /* 564 */ { ud_itab__564, UD_TAB__OPC_MODE, "/m" }, /* 565 */ { ud_itab__565, UD_TAB__OPC_MODE, "/m" }, /* 566 */ { ud_itab__566, UD_TAB__OPC_MODE, "/m" }, /* 567 */ { ud_itab__567, UD_TAB__OPC_MODE, "/m" }, /* 568 */ { ud_itab__568, UD_TAB__OPC_MODE, "/m" }, /* 569 */ { ud_itab__569, UD_TAB__OPC_MODE, "/m" }, /* 570 */ { ud_itab__570, UD_TAB__OPC_MODE, "/m" }, /* 571 */ { ud_itab__571, UD_TAB__OPC_OSIZE, "/o" }, /* 572 */ { ud_itab__572, UD_TAB__OPC_MODE, "/m" }, /* 573 */ { ud_itab__573, UD_TAB__OPC_MODE, "/m" }, /* 574 */ { ud_itab__574, UD_TAB__OPC_OSIZE, "/o" }, /* 575 */ { ud_itab__575, UD_TAB__OPC_MODE, "/m" }, /* 576 */ { ud_itab__576, UD_TAB__OPC_MODE, "/m" }, /* 577 */ { ud_itab__577, UD_TAB__OPC_MODE, "/m" }, /* 578 */ { ud_itab__578, UD_TAB__OPC_MODE, "/m" }, /* 579 */ { ud_itab__579, UD_TAB__OPC_OSIZE, "/o" }, /* 580 */ { ud_itab__580, UD_TAB__OPC_OSIZE, "/o" }, /* 581 */ { ud_itab__581, UD_TAB__OPC_REG, "/reg" }, /* 582 */ { ud_itab__582, UD_TAB__OPC_REG, "/reg" }, /* 583 */ { ud_itab__583, UD_TAB__OPC_REG, "/reg" }, /* 584 */ { ud_itab__584, UD_TAB__OPC_MODE, "/m" }, /* 585 */ { ud_itab__585, UD_TAB__OPC_MODE, "/m" }, /* 586 */ { ud_itab__586, UD_TAB__OPC_MODE, "/m" }, /* 587 */ { ud_itab__587, UD_TAB__OPC_MODE, "/m" }, /* 588 */ { ud_itab__588, UD_TAB__OPC_MODE, "/m" }, /* 589 */ { ud_itab__589, UD_TAB__OPC_MODE, "/m" }, /* 590 */ { ud_itab__590, UD_TAB__OPC_MODE, "/m" }, /* 591 */ { ud_itab__591, UD_TAB__OPC_MODE, "/m" }, /* 592 */ { ud_itab__592, UD_TAB__OPC_REG, "/reg" }, /* 593 */ { ud_itab__593, UD_TAB__OPC_REG, "/reg" }, /* 594 */ { ud_itab__594, UD_TAB__OPC_OSIZE, "/o" }, /* 595 */ { ud_itab__595, UD_TAB__OPC_OSIZE, "/o" }, /* 596 */ { ud_itab__596, UD_TAB__OPC_MODE, "/m" }, /* 597 */ { ud_itab__597, UD_TAB__OPC_OSIZE, "/o" }, /* 598 */ { ud_itab__598, UD_TAB__OPC_MODE, "/m" }, /* 599 */ { ud_itab__599, UD_TAB__OPC_MODE, "/m" }, /* 600 */ { ud_itab__600, UD_TAB__OPC_MODE, "/m" }, /* 601 */ { ud_itab__601, UD_TAB__OPC_OSIZE, "/o" }, /* 602 */ { ud_itab__602, UD_TAB__OPC_MODE, "/m" }, /* 603 */ { ud_itab__603, UD_TAB__OPC_MODE, "/m" }, /* 604 */ { ud_itab__604, UD_TAB__OPC_MODE, "/m" }, /* 605 */ { ud_itab__605, UD_TAB__OPC_OSIZE, "/o" }, /* 606 */ { ud_itab__606, UD_TAB__OPC_OSIZE, "/o" }, /* 607 */ { ud_itab__607, UD_TAB__OPC_OSIZE, "/o" }, /* 608 */ { ud_itab__608, UD_TAB__OPC_OSIZE, "/o" }, /* 609 */ { ud_itab__609, UD_TAB__OPC_OSIZE, "/o" }, /* 610 */ { ud_itab__610, UD_TAB__OPC_REG, "/reg" }, /* 611 */ { ud_itab__611, UD_TAB__OPC_REG, "/reg" }, /* 612 */ { ud_itab__612, UD_TAB__OPC_MODE, "/m" }, /* 613 */ { ud_itab__613, UD_TAB__OPC_MODE, "/m" }, /* 614 */ { ud_itab__614, UD_TAB__OPC_REG, "/reg" }, /* 615 */ { ud_itab__615, UD_TAB__OPC_REG, "/reg" }, /* 616 */ { ud_itab__616, UD_TAB__OPC_MODE, "/m" }, /* 617 */ { ud_itab__617, UD_TAB__OPC_OSIZE, "/o" }, /* 618 */ { ud_itab__618, UD_TAB__OPC_REG, "/reg" }, /* 619 */ { ud_itab__619, UD_TAB__OPC_REG, "/reg" }, /* 620 */ { ud_itab__620, UD_TAB__OPC_REG, "/reg" }, /* 621 */ { ud_itab__621, UD_TAB__OPC_REG, "/reg" }, /* 622 */ { ud_itab__622, UD_TAB__OPC_MODE, "/m" }, /* 623 */ { ud_itab__623, UD_TAB__OPC_MODE, "/m" }, /* 624 */ { ud_itab__624, UD_TAB__OPC_MODE, "/m" }, /* 625 */ { ud_itab__625, UD_TAB__OPC_MOD, "/mod" }, /* 626 */ { ud_itab__626, UD_TAB__OPC_REG, "/reg" }, /* 627 */ { ud_itab__627, UD_TAB__OPC_MOD, "/mod" }, /* 628 */ { ud_itab__628, UD_TAB__OPC_MOD, "/mod" }, /* 629 */ { ud_itab__629, UD_TAB__OPC_MOD, "/mod" }, /* 630 */ { ud_itab__630, UD_TAB__OPC_MOD, "/mod" }, /* 631 */ { ud_itab__631, UD_TAB__OPC_MOD, "/mod" }, /* 632 */ { ud_itab__632, UD_TAB__OPC_MOD, "/mod" }, /* 633 */ { ud_itab__633, UD_TAB__OPC_MOD, "/mod" }, /* 634 */ { ud_itab__634, UD_TAB__OPC_MOD, "/mod" }, /* 635 */ { ud_itab__635, UD_TAB__OPC_X87, "/x87" }, /* 636 */ { ud_itab__636, UD_TAB__OPC_MOD, "/mod" }, /* 637 */ { ud_itab__637, UD_TAB__OPC_MOD, "/mod" }, /* 638 */ { ud_itab__638, UD_TAB__OPC_MOD, "/mod" }, /* 639 */ { ud_itab__639, UD_TAB__OPC_MOD, "/mod" }, /* 640 */ { ud_itab__640, UD_TAB__OPC_MOD, "/mod" }, /* 641 */ { ud_itab__641, UD_TAB__OPC_MOD, "/mod" }, /* 642 */ { ud_itab__642, UD_TAB__OPC_MOD, "/mod" }, /* 643 */ { ud_itab__643, UD_TAB__OPC_MOD, "/mod" }, /* 644 */ { ud_itab__644, UD_TAB__OPC_MOD, "/mod" }, /* 645 */ { ud_itab__645, UD_TAB__OPC_MOD, "/mod" }, /* 646 */ { ud_itab__646, UD_TAB__OPC_MOD, "/mod" }, /* 647 */ { ud_itab__647, UD_TAB__OPC_MOD, "/mod" }, /* 648 */ { ud_itab__648, UD_TAB__OPC_MOD, "/mod" }, /* 649 */ { ud_itab__649, UD_TAB__OPC_MOD, "/mod" }, /* 650 */ { ud_itab__650, UD_TAB__OPC_MOD, "/mod" }, /* 651 */ { ud_itab__651, UD_TAB__OPC_MOD, "/mod" }, /* 652 */ { ud_itab__652, UD_TAB__OPC_MOD, "/mod" }, /* 653 */ { ud_itab__653, UD_TAB__OPC_MOD, "/mod" }, /* 654 */ { ud_itab__654, UD_TAB__OPC_MOD, "/mod" }, /* 655 */ { ud_itab__655, UD_TAB__OPC_MOD, "/mod" }, /* 656 */ { ud_itab__656, UD_TAB__OPC_MOD, "/mod" }, /* 657 */ { ud_itab__657, UD_TAB__OPC_MOD, "/mod" }, /* 658 */ { ud_itab__658, UD_TAB__OPC_MOD, "/mod" }, /* 659 */ { ud_itab__659, UD_TAB__OPC_MOD, "/mod" }, /* 660 */ { ud_itab__660, UD_TAB__OPC_MOD, "/mod" }, /* 661 */ { ud_itab__661, UD_TAB__OPC_MOD, "/mod" }, /* 662 */ { ud_itab__662, UD_TAB__OPC_MOD, "/mod" }, /* 663 */ { ud_itab__663, UD_TAB__OPC_MOD, "/mod" }, /* 664 */ { ud_itab__664, UD_TAB__OPC_MOD, "/mod" }, /* 665 */ { ud_itab__665, UD_TAB__OPC_MOD, "/mod" }, /* 666 */ { ud_itab__666, UD_TAB__OPC_MOD, "/mod" }, /* 667 */ { ud_itab__667, UD_TAB__OPC_MOD, "/mod" }, /* 668 */ { ud_itab__668, UD_TAB__OPC_MOD, "/mod" }, /* 669 */ { ud_itab__669, UD_TAB__OPC_MOD, "/mod" }, /* 670 */ { ud_itab__670, UD_TAB__OPC_MOD, "/mod" }, /* 671 */ { ud_itab__671, UD_TAB__OPC_MOD, "/mod" }, /* 672 */ { ud_itab__672, UD_TAB__OPC_MOD, "/mod" }, /* 673 */ { ud_itab__673, UD_TAB__OPC_MOD, "/mod" }, /* 674 */ { ud_itab__674, UD_TAB__OPC_MOD, "/mod" }, /* 675 */ { ud_itab__675, UD_TAB__OPC_MOD, "/mod" }, /* 676 */ { ud_itab__676, UD_TAB__OPC_MOD, "/mod" }, /* 677 */ { ud_itab__677, UD_TAB__OPC_MOD, "/mod" }, /* 678 */ { ud_itab__678, UD_TAB__OPC_MOD, "/mod" }, /* 679 */ { ud_itab__679, UD_TAB__OPC_MOD, "/mod" }, /* 680 */ { ud_itab__680, UD_TAB__OPC_MOD, "/mod" }, /* 681 */ { ud_itab__681, UD_TAB__OPC_MOD, "/mod" }, /* 682 */ { ud_itab__682, UD_TAB__OPC_MOD, "/mod" }, /* 683 */ { ud_itab__683, UD_TAB__OPC_MOD, "/mod" }, /* 684 */ { ud_itab__684, UD_TAB__OPC_MOD, "/mod" }, /* 685 */ { ud_itab__685, UD_TAB__OPC_MOD, "/mod" }, /* 686 */ { ud_itab__686, UD_TAB__OPC_MOD, "/mod" }, /* 687 */ { ud_itab__687, UD_TAB__OPC_MOD, "/mod" }, /* 688 */ { ud_itab__688, UD_TAB__OPC_MOD, "/mod" }, /* 689 */ { ud_itab__689, UD_TAB__OPC_MOD, "/mod" }, /* 690 */ { ud_itab__690, UD_TAB__OPC_MOD, "/mod" }, /* 691 */ { ud_itab__691, UD_TAB__OPC_MOD, "/mod" }, /* 692 */ { ud_itab__692, UD_TAB__OPC_MOD, "/mod" }, /* 693 */ { ud_itab__693, UD_TAB__OPC_MOD, "/mod" }, /* 694 */ { ud_itab__694, UD_TAB__OPC_MOD, "/mod" }, /* 695 */ { ud_itab__695, UD_TAB__OPC_MOD, "/mod" }, /* 696 */ { ud_itab__696, UD_TAB__OPC_MOD, "/mod" }, /* 697 */ { ud_itab__697, UD_TAB__OPC_MOD, "/mod" }, /* 698 */ { ud_itab__698, UD_TAB__OPC_MOD, "/mod" }, /* 699 */ { ud_itab__699, UD_TAB__OPC_MOD, "/mod" }, /* 700 */ { ud_itab__700, UD_TAB__OPC_MOD, "/mod" }, /* 701 */ { ud_itab__701, UD_TAB__OPC_REG, "/reg" }, /* 702 */ { ud_itab__702, UD_TAB__OPC_MOD, "/mod" }, /* 703 */ { ud_itab__703, UD_TAB__OPC_MOD, "/mod" }, /* 704 */ { ud_itab__704, UD_TAB__OPC_MOD, "/mod" }, /* 705 */ { ud_itab__705, UD_TAB__OPC_MOD, "/mod" }, /* 706 */ { ud_itab__706, UD_TAB__OPC_MOD, "/mod" }, /* 707 */ { ud_itab__707, UD_TAB__OPC_MOD, "/mod" }, /* 708 */ { ud_itab__708, UD_TAB__OPC_MOD, "/mod" }, /* 709 */ { ud_itab__709, UD_TAB__OPC_X87, "/x87" }, /* 710 */ { ud_itab__710, UD_TAB__OPC_MOD, "/mod" }, /* 711 */ { ud_itab__711, UD_TAB__OPC_MOD, "/mod" }, /* 712 */ { ud_itab__712, UD_TAB__OPC_MOD, "/mod" }, /* 713 */ { ud_itab__713, UD_TAB__OPC_MOD, "/mod" }, /* 714 */ { ud_itab__714, UD_TAB__OPC_MOD, "/mod" }, /* 715 */ { ud_itab__715, UD_TAB__OPC_MOD, "/mod" }, /* 716 */ { ud_itab__716, UD_TAB__OPC_MOD, "/mod" }, /* 717 */ { ud_itab__717, UD_TAB__OPC_MOD, "/mod" }, /* 718 */ { ud_itab__718, UD_TAB__OPC_MOD, "/mod" }, /* 719 */ { ud_itab__719, UD_TAB__OPC_MOD, "/mod" }, /* 720 */ { ud_itab__720, UD_TAB__OPC_MOD, "/mod" }, /* 721 */ { ud_itab__721, UD_TAB__OPC_MOD, "/mod" }, /* 722 */ { ud_itab__722, UD_TAB__OPC_MOD, "/mod" }, /* 723 */ { ud_itab__723, UD_TAB__OPC_MOD, "/mod" }, /* 724 */ { ud_itab__724, UD_TAB__OPC_MOD, "/mod" }, /* 725 */ { ud_itab__725, UD_TAB__OPC_MOD, "/mod" }, /* 726 */ { ud_itab__726, UD_TAB__OPC_MOD, "/mod" }, /* 727 */ { ud_itab__727, UD_TAB__OPC_MOD, "/mod" }, /* 728 */ { ud_itab__728, UD_TAB__OPC_MOD, "/mod" }, /* 729 */ { ud_itab__729, UD_TAB__OPC_MOD, "/mod" }, /* 730 */ { ud_itab__730, UD_TAB__OPC_MOD, "/mod" }, /* 731 */ { ud_itab__731, UD_TAB__OPC_MOD, "/mod" }, /* 732 */ { ud_itab__732, UD_TAB__OPC_MOD, "/mod" }, /* 733 */ { ud_itab__733, UD_TAB__OPC_MOD, "/mod" }, /* 734 */ { ud_itab__734, UD_TAB__OPC_MOD, "/mod" }, /* 735 */ { ud_itab__735, UD_TAB__OPC_MOD, "/mod" }, /* 736 */ { ud_itab__736, UD_TAB__OPC_MOD, "/mod" }, /* 737 */ { ud_itab__737, UD_TAB__OPC_MOD, "/mod" }, /* 738 */ { ud_itab__738, UD_TAB__OPC_MOD, "/mod" }, /* 739 */ { ud_itab__739, UD_TAB__OPC_MOD, "/mod" }, /* 740 */ { ud_itab__740, UD_TAB__OPC_MOD, "/mod" }, /* 741 */ { ud_itab__741, UD_TAB__OPC_MOD, "/mod" }, /* 742 */ { ud_itab__742, UD_TAB__OPC_MOD, "/mod" }, /* 743 */ { ud_itab__743, UD_TAB__OPC_MOD, "/mod" }, /* 744 */ { ud_itab__744, UD_TAB__OPC_MOD, "/mod" }, /* 745 */ { ud_itab__745, UD_TAB__OPC_MOD, "/mod" }, /* 746 */ { ud_itab__746, UD_TAB__OPC_MOD, "/mod" }, /* 747 */ { ud_itab__747, UD_TAB__OPC_MOD, "/mod" }, /* 748 */ { ud_itab__748, UD_TAB__OPC_MOD, "/mod" }, /* 749 */ { ud_itab__749, UD_TAB__OPC_MOD, "/mod" }, /* 750 */ { ud_itab__750, UD_TAB__OPC_MOD, "/mod" }, /* 751 */ { ud_itab__751, UD_TAB__OPC_MOD, "/mod" }, /* 752 */ { ud_itab__752, UD_TAB__OPC_MOD, "/mod" }, /* 753 */ { ud_itab__753, UD_TAB__OPC_MOD, "/mod" }, /* 754 */ { ud_itab__754, UD_TAB__OPC_MOD, "/mod" }, /* 755 */ { ud_itab__755, UD_TAB__OPC_MOD, "/mod" }, /* 756 */ { ud_itab__756, UD_TAB__OPC_MOD, "/mod" }, /* 757 */ { ud_itab__757, UD_TAB__OPC_MOD, "/mod" }, /* 758 */ { ud_itab__758, UD_TAB__OPC_MOD, "/mod" }, /* 759 */ { ud_itab__759, UD_TAB__OPC_MOD, "/mod" }, /* 760 */ { ud_itab__760, UD_TAB__OPC_MOD, "/mod" }, /* 761 */ { ud_itab__761, UD_TAB__OPC_MOD, "/mod" }, /* 762 */ { ud_itab__762, UD_TAB__OPC_MOD, "/mod" }, /* 763 */ { ud_itab__763, UD_TAB__OPC_REG, "/reg" }, /* 764 */ { ud_itab__764, UD_TAB__OPC_MOD, "/mod" }, /* 765 */ { ud_itab__765, UD_TAB__OPC_MOD, "/mod" }, /* 766 */ { ud_itab__766, UD_TAB__OPC_MOD, "/mod" }, /* 767 */ { ud_itab__767, UD_TAB__OPC_MOD, "/mod" }, /* 768 */ { ud_itab__768, UD_TAB__OPC_MOD, "/mod" }, /* 769 */ { ud_itab__769, UD_TAB__OPC_MOD, "/mod" }, /* 770 */ { ud_itab__770, UD_TAB__OPC_MOD, "/mod" }, /* 771 */ { ud_itab__771, UD_TAB__OPC_MOD, "/mod" }, /* 772 */ { ud_itab__772, UD_TAB__OPC_X87, "/x87" }, /* 773 */ { ud_itab__773, UD_TAB__OPC_MOD, "/mod" }, /* 774 */ { ud_itab__774, UD_TAB__OPC_MOD, "/mod" }, /* 775 */ { ud_itab__775, UD_TAB__OPC_MOD, "/mod" }, /* 776 */ { ud_itab__776, UD_TAB__OPC_MOD, "/mod" }, /* 777 */ { ud_itab__777, UD_TAB__OPC_MOD, "/mod" }, /* 778 */ { ud_itab__778, UD_TAB__OPC_MOD, "/mod" }, /* 779 */ { ud_itab__779, UD_TAB__OPC_MOD, "/mod" }, /* 780 */ { ud_itab__780, UD_TAB__OPC_MOD, "/mod" }, /* 781 */ { ud_itab__781, UD_TAB__OPC_MOD, "/mod" }, /* 782 */ { ud_itab__782, UD_TAB__OPC_MOD, "/mod" }, /* 783 */ { ud_itab__783, UD_TAB__OPC_MOD, "/mod" }, /* 784 */ { ud_itab__784, UD_TAB__OPC_MOD, "/mod" }, /* 785 */ { ud_itab__785, UD_TAB__OPC_MOD, "/mod" }, /* 786 */ { ud_itab__786, UD_TAB__OPC_MOD, "/mod" }, /* 787 */ { ud_itab__787, UD_TAB__OPC_MOD, "/mod" }, /* 788 */ { ud_itab__788, UD_TAB__OPC_MOD, "/mod" }, /* 789 */ { ud_itab__789, UD_TAB__OPC_MOD, "/mod" }, /* 790 */ { ud_itab__790, UD_TAB__OPC_MOD, "/mod" }, /* 791 */ { ud_itab__791, UD_TAB__OPC_MOD, "/mod" }, /* 792 */ { ud_itab__792, UD_TAB__OPC_MOD, "/mod" }, /* 793 */ { ud_itab__793, UD_TAB__OPC_MOD, "/mod" }, /* 794 */ { ud_itab__794, UD_TAB__OPC_MOD, "/mod" }, /* 795 */ { ud_itab__795, UD_TAB__OPC_MOD, "/mod" }, /* 796 */ { ud_itab__796, UD_TAB__OPC_MOD, "/mod" }, /* 797 */ { ud_itab__797, UD_TAB__OPC_MOD, "/mod" }, /* 798 */ { ud_itab__798, UD_TAB__OPC_MOD, "/mod" }, /* 799 */ { ud_itab__799, UD_TAB__OPC_MOD, "/mod" }, /* 800 */ { ud_itab__800, UD_TAB__OPC_MOD, "/mod" }, /* 801 */ { ud_itab__801, UD_TAB__OPC_MOD, "/mod" }, /* 802 */ { ud_itab__802, UD_TAB__OPC_MOD, "/mod" }, /* 803 */ { ud_itab__803, UD_TAB__OPC_MOD, "/mod" }, /* 804 */ { ud_itab__804, UD_TAB__OPC_MOD, "/mod" }, /* 805 */ { ud_itab__805, UD_TAB__OPC_MOD, "/mod" }, /* 806 */ { ud_itab__806, UD_TAB__OPC_MOD, "/mod" }, /* 807 */ { ud_itab__807, UD_TAB__OPC_REG, "/reg" }, /* 808 */ { ud_itab__808, UD_TAB__OPC_MOD, "/mod" }, /* 809 */ { ud_itab__809, UD_TAB__OPC_MOD, "/mod" }, /* 810 */ { ud_itab__810, UD_TAB__OPC_MOD, "/mod" }, /* 811 */ { ud_itab__811, UD_TAB__OPC_MOD, "/mod" }, /* 812 */ { ud_itab__812, UD_TAB__OPC_MOD, "/mod" }, /* 813 */ { ud_itab__813, UD_TAB__OPC_MOD, "/mod" }, /* 814 */ { ud_itab__814, UD_TAB__OPC_X87, "/x87" }, /* 815 */ { ud_itab__815, UD_TAB__OPC_MOD, "/mod" }, /* 816 */ { ud_itab__816, UD_TAB__OPC_MOD, "/mod" }, /* 817 */ { ud_itab__817, UD_TAB__OPC_MOD, "/mod" }, /* 818 */ { ud_itab__818, UD_TAB__OPC_MOD, "/mod" }, /* 819 */ { ud_itab__819, UD_TAB__OPC_MOD, "/mod" }, /* 820 */ { ud_itab__820, UD_TAB__OPC_MOD, "/mod" }, /* 821 */ { ud_itab__821, UD_TAB__OPC_MOD, "/mod" }, /* 822 */ { ud_itab__822, UD_TAB__OPC_MOD, "/mod" }, /* 823 */ { ud_itab__823, UD_TAB__OPC_MOD, "/mod" }, /* 824 */ { ud_itab__824, UD_TAB__OPC_MOD, "/mod" }, /* 825 */ { ud_itab__825, UD_TAB__OPC_MOD, "/mod" }, /* 826 */ { ud_itab__826, UD_TAB__OPC_MOD, "/mod" }, /* 827 */ { ud_itab__827, UD_TAB__OPC_MOD, "/mod" }, /* 828 */ { ud_itab__828, UD_TAB__OPC_MOD, "/mod" }, /* 829 */ { ud_itab__829, UD_TAB__OPC_MOD, "/mod" }, /* 830 */ { ud_itab__830, UD_TAB__OPC_MOD, "/mod" }, /* 831 */ { ud_itab__831, UD_TAB__OPC_MOD, "/mod" }, /* 832 */ { ud_itab__832, UD_TAB__OPC_MOD, "/mod" }, /* 833 */ { ud_itab__833, UD_TAB__OPC_MOD, "/mod" }, /* 834 */ { ud_itab__834, UD_TAB__OPC_MOD, "/mod" }, /* 835 */ { ud_itab__835, UD_TAB__OPC_MOD, "/mod" }, /* 836 */ { ud_itab__836, UD_TAB__OPC_MOD, "/mod" }, /* 837 */ { ud_itab__837, UD_TAB__OPC_MOD, "/mod" }, /* 838 */ { ud_itab__838, UD_TAB__OPC_MOD, "/mod" }, /* 839 */ { ud_itab__839, UD_TAB__OPC_MOD, "/mod" }, /* 840 */ { ud_itab__840, UD_TAB__OPC_MOD, "/mod" }, /* 841 */ { ud_itab__841, UD_TAB__OPC_MOD, "/mod" }, /* 842 */ { ud_itab__842, UD_TAB__OPC_MOD, "/mod" }, /* 843 */ { ud_itab__843, UD_TAB__OPC_MOD, "/mod" }, /* 844 */ { ud_itab__844, UD_TAB__OPC_MOD, "/mod" }, /* 845 */ { ud_itab__845, UD_TAB__OPC_MOD, "/mod" }, /* 846 */ { ud_itab__846, UD_TAB__OPC_MOD, "/mod" }, /* 847 */ { ud_itab__847, UD_TAB__OPC_MOD, "/mod" }, /* 848 */ { ud_itab__848, UD_TAB__OPC_MOD, "/mod" }, /* 849 */ { ud_itab__849, UD_TAB__OPC_MOD, "/mod" }, /* 850 */ { ud_itab__850, UD_TAB__OPC_MOD, "/mod" }, /* 851 */ { ud_itab__851, UD_TAB__OPC_MOD, "/mod" }, /* 852 */ { ud_itab__852, UD_TAB__OPC_MOD, "/mod" }, /* 853 */ { ud_itab__853, UD_TAB__OPC_MOD, "/mod" }, /* 854 */ { ud_itab__854, UD_TAB__OPC_MOD, "/mod" }, /* 855 */ { ud_itab__855, UD_TAB__OPC_MOD, "/mod" }, /* 856 */ { ud_itab__856, UD_TAB__OPC_MOD, "/mod" }, /* 857 */ { ud_itab__857, UD_TAB__OPC_MOD, "/mod" }, /* 858 */ { ud_itab__858, UD_TAB__OPC_MOD, "/mod" }, /* 859 */ { ud_itab__859, UD_TAB__OPC_MOD, "/mod" }, /* 860 */ { ud_itab__860, UD_TAB__OPC_MOD, "/mod" }, /* 861 */ { ud_itab__861, UD_TAB__OPC_MOD, "/mod" }, /* 862 */ { ud_itab__862, UD_TAB__OPC_MOD, "/mod" }, /* 863 */ { ud_itab__863, UD_TAB__OPC_MOD, "/mod" }, /* 864 */ { ud_itab__864, UD_TAB__OPC_MOD, "/mod" }, /* 865 */ { ud_itab__865, UD_TAB__OPC_MOD, "/mod" }, /* 866 */ { ud_itab__866, UD_TAB__OPC_REG, "/reg" }, /* 867 */ { ud_itab__867, UD_TAB__OPC_MOD, "/mod" }, /* 868 */ { ud_itab__868, UD_TAB__OPC_MOD, "/mod" }, /* 869 */ { ud_itab__869, UD_TAB__OPC_MOD, "/mod" }, /* 870 */ { ud_itab__870, UD_TAB__OPC_MOD, "/mod" }, /* 871 */ { ud_itab__871, UD_TAB__OPC_MOD, "/mod" }, /* 872 */ { ud_itab__872, UD_TAB__OPC_MOD, "/mod" }, /* 873 */ { ud_itab__873, UD_TAB__OPC_MOD, "/mod" }, /* 874 */ { ud_itab__874, UD_TAB__OPC_MOD, "/mod" }, /* 875 */ { ud_itab__875, UD_TAB__OPC_X87, "/x87" }, /* 876 */ { ud_itab__876, UD_TAB__OPC_MOD, "/mod" }, /* 877 */ { ud_itab__877, UD_TAB__OPC_MOD, "/mod" }, /* 878 */ { ud_itab__878, UD_TAB__OPC_MOD, "/mod" }, /* 879 */ { ud_itab__879, UD_TAB__OPC_MOD, "/mod" }, /* 880 */ { ud_itab__880, UD_TAB__OPC_MOD, "/mod" }, /* 881 */ { ud_itab__881, UD_TAB__OPC_MOD, "/mod" }, /* 882 */ { ud_itab__882, UD_TAB__OPC_MOD, "/mod" }, /* 883 */ { ud_itab__883, UD_TAB__OPC_MOD, "/mod" }, /* 884 */ { ud_itab__884, UD_TAB__OPC_MOD, "/mod" }, /* 885 */ { ud_itab__885, UD_TAB__OPC_MOD, "/mod" }, /* 886 */ { ud_itab__886, UD_TAB__OPC_MOD, "/mod" }, /* 887 */ { ud_itab__887, UD_TAB__OPC_MOD, "/mod" }, /* 888 */ { ud_itab__888, UD_TAB__OPC_MOD, "/mod" }, /* 889 */ { ud_itab__889, UD_TAB__OPC_MOD, "/mod" }, /* 890 */ { ud_itab__890, UD_TAB__OPC_MOD, "/mod" }, /* 891 */ { ud_itab__891, UD_TAB__OPC_MOD, "/mod" }, /* 892 */ { ud_itab__892, UD_TAB__OPC_MOD, "/mod" }, /* 893 */ { ud_itab__893, UD_TAB__OPC_MOD, "/mod" }, /* 894 */ { ud_itab__894, UD_TAB__OPC_MOD, "/mod" }, /* 895 */ { ud_itab__895, UD_TAB__OPC_MOD, "/mod" }, /* 896 */ { ud_itab__896, UD_TAB__OPC_MOD, "/mod" }, /* 897 */ { ud_itab__897, UD_TAB__OPC_MOD, "/mod" }, /* 898 */ { ud_itab__898, UD_TAB__OPC_MOD, "/mod" }, /* 899 */ { ud_itab__899, UD_TAB__OPC_MOD, "/mod" }, /* 900 */ { ud_itab__900, UD_TAB__OPC_MOD, "/mod" }, /* 901 */ { ud_itab__901, UD_TAB__OPC_MOD, "/mod" }, /* 902 */ { ud_itab__902, UD_TAB__OPC_MOD, "/mod" }, /* 903 */ { ud_itab__903, UD_TAB__OPC_MOD, "/mod" }, /* 904 */ { ud_itab__904, UD_TAB__OPC_MOD, "/mod" }, /* 905 */ { ud_itab__905, UD_TAB__OPC_MOD, "/mod" }, /* 906 */ { ud_itab__906, UD_TAB__OPC_MOD, "/mod" }, /* 907 */ { ud_itab__907, UD_TAB__OPC_MOD, "/mod" }, /* 908 */ { ud_itab__908, UD_TAB__OPC_MOD, "/mod" }, /* 909 */ { ud_itab__909, UD_TAB__OPC_MOD, "/mod" }, /* 910 */ { ud_itab__910, UD_TAB__OPC_MOD, "/mod" }, /* 911 */ { ud_itab__911, UD_TAB__OPC_MOD, "/mod" }, /* 912 */ { ud_itab__912, UD_TAB__OPC_MOD, "/mod" }, /* 913 */ { ud_itab__913, UD_TAB__OPC_MOD, "/mod" }, /* 914 */ { ud_itab__914, UD_TAB__OPC_MOD, "/mod" }, /* 915 */ { ud_itab__915, UD_TAB__OPC_MOD, "/mod" }, /* 916 */ { ud_itab__916, UD_TAB__OPC_MOD, "/mod" }, /* 917 */ { ud_itab__917, UD_TAB__OPC_MOD, "/mod" }, /* 918 */ { ud_itab__918, UD_TAB__OPC_MOD, "/mod" }, /* 919 */ { ud_itab__919, UD_TAB__OPC_MOD, "/mod" }, /* 920 */ { ud_itab__920, UD_TAB__OPC_MOD, "/mod" }, /* 921 */ { ud_itab__921, UD_TAB__OPC_MOD, "/mod" }, /* 922 */ { ud_itab__922, UD_TAB__OPC_MOD, "/mod" }, /* 923 */ { ud_itab__923, UD_TAB__OPC_MOD, "/mod" }, /* 924 */ { ud_itab__924, UD_TAB__OPC_MOD, "/mod" }, /* 925 */ { ud_itab__925, UD_TAB__OPC_MOD, "/mod" }, /* 926 */ { ud_itab__926, UD_TAB__OPC_MOD, "/mod" }, /* 927 */ { ud_itab__927, UD_TAB__OPC_MOD, "/mod" }, /* 928 */ { ud_itab__928, UD_TAB__OPC_MOD, "/mod" }, /* 929 */ { ud_itab__929, UD_TAB__OPC_MOD, "/mod" }, /* 930 */ { ud_itab__930, UD_TAB__OPC_MOD, "/mod" }, /* 931 */ { ud_itab__931, UD_TAB__OPC_MOD, "/mod" }, /* 932 */ { ud_itab__932, UD_TAB__OPC_MOD, "/mod" }, /* 933 */ { ud_itab__933, UD_TAB__OPC_MOD, "/mod" }, /* 934 */ { ud_itab__934, UD_TAB__OPC_MOD, "/mod" }, /* 935 */ { ud_itab__935, UD_TAB__OPC_MOD, "/mod" }, /* 936 */ { ud_itab__936, UD_TAB__OPC_MOD, "/mod" }, /* 937 */ { ud_itab__937, UD_TAB__OPC_MOD, "/mod" }, /* 938 */ { ud_itab__938, UD_TAB__OPC_MOD, "/mod" }, /* 939 */ { ud_itab__939, UD_TAB__OPC_MOD, "/mod" }, /* 940 */ { ud_itab__940, UD_TAB__OPC_MOD, "/mod" }, /* 941 */ { ud_itab__941, UD_TAB__OPC_REG, "/reg" }, /* 942 */ { ud_itab__942, UD_TAB__OPC_MOD, "/mod" }, /* 943 */ { ud_itab__943, UD_TAB__OPC_MOD, "/mod" }, /* 944 */ { ud_itab__944, UD_TAB__OPC_MOD, "/mod" }, /* 945 */ { ud_itab__945, UD_TAB__OPC_MOD, "/mod" }, /* 946 */ { ud_itab__946, UD_TAB__OPC_MOD, "/mod" }, /* 947 */ { ud_itab__947, UD_TAB__OPC_MOD, "/mod" }, /* 948 */ { ud_itab__948, UD_TAB__OPC_MOD, "/mod" }, /* 949 */ { ud_itab__949, UD_TAB__OPC_X87, "/x87" }, /* 950 */ { ud_itab__950, UD_TAB__OPC_MOD, "/mod" }, /* 951 */ { ud_itab__951, UD_TAB__OPC_MOD, "/mod" }, /* 952 */ { ud_itab__952, UD_TAB__OPC_MOD, "/mod" }, /* 953 */ { ud_itab__953, UD_TAB__OPC_MOD, "/mod" }, /* 954 */ { ud_itab__954, UD_TAB__OPC_MOD, "/mod" }, /* 955 */ { ud_itab__955, UD_TAB__OPC_MOD, "/mod" }, /* 956 */ { ud_itab__956, UD_TAB__OPC_MOD, "/mod" }, /* 957 */ { ud_itab__957, UD_TAB__OPC_MOD, "/mod" }, /* 958 */ { ud_itab__958, UD_TAB__OPC_MOD, "/mod" }, /* 959 */ { ud_itab__959, UD_TAB__OPC_MOD, "/mod" }, /* 960 */ { ud_itab__960, UD_TAB__OPC_MOD, "/mod" }, /* 961 */ { ud_itab__961, UD_TAB__OPC_MOD, "/mod" }, /* 962 */ { ud_itab__962, UD_TAB__OPC_MOD, "/mod" }, /* 963 */ { ud_itab__963, UD_TAB__OPC_MOD, "/mod" }, /* 964 */ { ud_itab__964, UD_TAB__OPC_MOD, "/mod" }, /* 965 */ { ud_itab__965, UD_TAB__OPC_MOD, "/mod" }, /* 966 */ { ud_itab__966, UD_TAB__OPC_MOD, "/mod" }, /* 967 */ { ud_itab__967, UD_TAB__OPC_MOD, "/mod" }, /* 968 */ { ud_itab__968, UD_TAB__OPC_MOD, "/mod" }, /* 969 */ { ud_itab__969, UD_TAB__OPC_MOD, "/mod" }, /* 970 */ { ud_itab__970, UD_TAB__OPC_MOD, "/mod" }, /* 971 */ { ud_itab__971, UD_TAB__OPC_MOD, "/mod" }, /* 972 */ { ud_itab__972, UD_TAB__OPC_MOD, "/mod" }, /* 973 */ { ud_itab__973, UD_TAB__OPC_MOD, "/mod" }, /* 974 */ { ud_itab__974, UD_TAB__OPC_MOD, "/mod" }, /* 975 */ { ud_itab__975, UD_TAB__OPC_MOD, "/mod" }, /* 976 */ { ud_itab__976, UD_TAB__OPC_MOD, "/mod" }, /* 977 */ { ud_itab__977, UD_TAB__OPC_MOD, "/mod" }, /* 978 */ { ud_itab__978, UD_TAB__OPC_MOD, "/mod" }, /* 979 */ { ud_itab__979, UD_TAB__OPC_MOD, "/mod" }, /* 980 */ { ud_itab__980, UD_TAB__OPC_MOD, "/mod" }, /* 981 */ { ud_itab__981, UD_TAB__OPC_MOD, "/mod" }, /* 982 */ { ud_itab__982, UD_TAB__OPC_MOD, "/mod" }, /* 983 */ { ud_itab__983, UD_TAB__OPC_MOD, "/mod" }, /* 984 */ { ud_itab__984, UD_TAB__OPC_MOD, "/mod" }, /* 985 */ { ud_itab__985, UD_TAB__OPC_MOD, "/mod" }, /* 986 */ { ud_itab__986, UD_TAB__OPC_MOD, "/mod" }, /* 987 */ { ud_itab__987, UD_TAB__OPC_MOD, "/mod" }, /* 988 */ { ud_itab__988, UD_TAB__OPC_MOD, "/mod" }, /* 989 */ { ud_itab__989, UD_TAB__OPC_MOD, "/mod" }, /* 990 */ { ud_itab__990, UD_TAB__OPC_MOD, "/mod" }, /* 991 */ { ud_itab__991, UD_TAB__OPC_MOD, "/mod" }, /* 992 */ { ud_itab__992, UD_TAB__OPC_MOD, "/mod" }, /* 993 */ { ud_itab__993, UD_TAB__OPC_MOD, "/mod" }, /* 994 */ { ud_itab__994, UD_TAB__OPC_MOD, "/mod" }, /* 995 */ { ud_itab__995, UD_TAB__OPC_MOD, "/mod" }, /* 996 */ { ud_itab__996, UD_TAB__OPC_MOD, "/mod" }, /* 997 */ { ud_itab__997, UD_TAB__OPC_MOD, "/mod" }, /* 998 */ { ud_itab__998, UD_TAB__OPC_MOD, "/mod" }, /* 999 */ { ud_itab__999, UD_TAB__OPC_REG, "/reg" }, /* 1000 */ { ud_itab__1000, UD_TAB__OPC_MOD, "/mod" }, /* 1001 */ { ud_itab__1001, UD_TAB__OPC_MOD, "/mod" }, /* 1002 */ { ud_itab__1002, UD_TAB__OPC_MOD, "/mod" }, /* 1003 */ { ud_itab__1003, UD_TAB__OPC_MOD, "/mod" }, /* 1004 */ { ud_itab__1004, UD_TAB__OPC_MOD, "/mod" }, /* 1005 */ { ud_itab__1005, UD_TAB__OPC_MOD, "/mod" }, /* 1006 */ { ud_itab__1006, UD_TAB__OPC_MOD, "/mod" }, /* 1007 */ { ud_itab__1007, UD_TAB__OPC_MOD, "/mod" }, /* 1008 */ { ud_itab__1008, UD_TAB__OPC_X87, "/x87" }, /* 1009 */ { ud_itab__1009, UD_TAB__OPC_MOD, "/mod" }, /* 1010 */ { ud_itab__1010, UD_TAB__OPC_MOD, "/mod" }, /* 1011 */ { ud_itab__1011, UD_TAB__OPC_MOD, "/mod" }, /* 1012 */ { ud_itab__1012, UD_TAB__OPC_MOD, "/mod" }, /* 1013 */ { ud_itab__1013, UD_TAB__OPC_MOD, "/mod" }, /* 1014 */ { ud_itab__1014, UD_TAB__OPC_MOD, "/mod" }, /* 1015 */ { ud_itab__1015, UD_TAB__OPC_MOD, "/mod" }, /* 1016 */ { ud_itab__1016, UD_TAB__OPC_MOD, "/mod" }, /* 1017 */ { ud_itab__1017, UD_TAB__OPC_MOD, "/mod" }, /* 1018 */ { ud_itab__1018, UD_TAB__OPC_MOD, "/mod" }, /* 1019 */ { ud_itab__1019, UD_TAB__OPC_MOD, "/mod" }, /* 1020 */ { ud_itab__1020, UD_TAB__OPC_MOD, "/mod" }, /* 1021 */ { ud_itab__1021, UD_TAB__OPC_MOD, "/mod" }, /* 1022 */ { ud_itab__1022, UD_TAB__OPC_MOD, "/mod" }, /* 1023 */ { ud_itab__1023, UD_TAB__OPC_MOD, "/mod" }, /* 1024 */ { ud_itab__1024, UD_TAB__OPC_MOD, "/mod" }, /* 1025 */ { ud_itab__1025, UD_TAB__OPC_MOD, "/mod" }, /* 1026 */ { ud_itab__1026, UD_TAB__OPC_MOD, "/mod" }, /* 1027 */ { ud_itab__1027, UD_TAB__OPC_MOD, "/mod" }, /* 1028 */ { ud_itab__1028, UD_TAB__OPC_MOD, "/mod" }, /* 1029 */ { ud_itab__1029, UD_TAB__OPC_MOD, "/mod" }, /* 1030 */ { ud_itab__1030, UD_TAB__OPC_MOD, "/mod" }, /* 1031 */ { ud_itab__1031, UD_TAB__OPC_MOD, "/mod" }, /* 1032 */ { ud_itab__1032, UD_TAB__OPC_MOD, "/mod" }, /* 1033 */ { ud_itab__1033, UD_TAB__OPC_MOD, "/mod" }, /* 1034 */ { ud_itab__1034, UD_TAB__OPC_MOD, "/mod" }, /* 1035 */ { ud_itab__1035, UD_TAB__OPC_MOD, "/mod" }, /* 1036 */ { ud_itab__1036, UD_TAB__OPC_MOD, "/mod" }, /* 1037 */ { ud_itab__1037, UD_TAB__OPC_MOD, "/mod" }, /* 1038 */ { ud_itab__1038, UD_TAB__OPC_MOD, "/mod" }, /* 1039 */ { ud_itab__1039, UD_TAB__OPC_MOD, "/mod" }, /* 1040 */ { ud_itab__1040, UD_TAB__OPC_MOD, "/mod" }, /* 1041 */ { ud_itab__1041, UD_TAB__OPC_MOD, "/mod" }, /* 1042 */ { ud_itab__1042, UD_TAB__OPC_MOD, "/mod" }, /* 1043 */ { ud_itab__1043, UD_TAB__OPC_MOD, "/mod" }, /* 1044 */ { ud_itab__1044, UD_TAB__OPC_MOD, "/mod" }, /* 1045 */ { ud_itab__1045, UD_TAB__OPC_MOD, "/mod" }, /* 1046 */ { ud_itab__1046, UD_TAB__OPC_MOD, "/mod" }, /* 1047 */ { ud_itab__1047, UD_TAB__OPC_MOD, "/mod" }, /* 1048 */ { ud_itab__1048, UD_TAB__OPC_MOD, "/mod" }, /* 1049 */ { ud_itab__1049, UD_TAB__OPC_MOD, "/mod" }, /* 1050 */ { ud_itab__1050, UD_TAB__OPC_MOD, "/mod" }, /* 1051 */ { ud_itab__1051, UD_TAB__OPC_MOD, "/mod" }, /* 1052 */ { ud_itab__1052, UD_TAB__OPC_MOD, "/mod" }, /* 1053 */ { ud_itab__1053, UD_TAB__OPC_MOD, "/mod" }, /* 1054 */ { ud_itab__1054, UD_TAB__OPC_MOD, "/mod" }, /* 1055 */ { ud_itab__1055, UD_TAB__OPC_MOD, "/mod" }, /* 1056 */ { ud_itab__1056, UD_TAB__OPC_MOD, "/mod" }, /* 1057 */ { ud_itab__1057, UD_TAB__OPC_MOD, "/mod" }, /* 1058 */ { ud_itab__1058, UD_TAB__OPC_MOD, "/mod" }, /* 1059 */ { ud_itab__1059, UD_TAB__OPC_MOD, "/mod" }, /* 1060 */ { ud_itab__1060, UD_TAB__OPC_MOD, "/mod" }, /* 1061 */ { ud_itab__1061, UD_TAB__OPC_MOD, "/mod" }, /* 1062 */ { ud_itab__1062, UD_TAB__OPC_MOD, "/mod" }, /* 1063 */ { ud_itab__1063, UD_TAB__OPC_MOD, "/mod" }, /* 1064 */ { ud_itab__1064, UD_TAB__OPC_MOD, "/mod" }, /* 1065 */ { ud_itab__1065, UD_TAB__OPC_MOD, "/mod" }, /* 1066 */ { ud_itab__1066, UD_TAB__OPC_MOD, "/mod" }, /* 1067 */ { ud_itab__1067, UD_TAB__OPC_REG, "/reg" }, /* 1068 */ { ud_itab__1068, UD_TAB__OPC_MOD, "/mod" }, /* 1069 */ { ud_itab__1069, UD_TAB__OPC_MOD, "/mod" }, /* 1070 */ { ud_itab__1070, UD_TAB__OPC_MOD, "/mod" }, /* 1071 */ { ud_itab__1071, UD_TAB__OPC_MOD, "/mod" }, /* 1072 */ { ud_itab__1072, UD_TAB__OPC_MOD, "/mod" }, /* 1073 */ { ud_itab__1073, UD_TAB__OPC_MOD, "/mod" }, /* 1074 */ { ud_itab__1074, UD_TAB__OPC_MOD, "/mod" }, /* 1075 */ { ud_itab__1075, UD_TAB__OPC_MOD, "/mod" }, /* 1076 */ { ud_itab__1076, UD_TAB__OPC_X87, "/x87" }, /* 1077 */ { ud_itab__1077, UD_TAB__OPC_MOD, "/mod" }, /* 1078 */ { ud_itab__1078, UD_TAB__OPC_MOD, "/mod" }, /* 1079 */ { ud_itab__1079, UD_TAB__OPC_MOD, "/mod" }, /* 1080 */ { ud_itab__1080, UD_TAB__OPC_MOD, "/mod" }, /* 1081 */ { ud_itab__1081, UD_TAB__OPC_MOD, "/mod" }, /* 1082 */ { ud_itab__1082, UD_TAB__OPC_MOD, "/mod" }, /* 1083 */ { ud_itab__1083, UD_TAB__OPC_MOD, "/mod" }, /* 1084 */ { ud_itab__1084, UD_TAB__OPC_MOD, "/mod" }, /* 1085 */ { ud_itab__1085, UD_TAB__OPC_MOD, "/mod" }, /* 1086 */ { ud_itab__1086, UD_TAB__OPC_MOD, "/mod" }, /* 1087 */ { ud_itab__1087, UD_TAB__OPC_MOD, "/mod" }, /* 1088 */ { ud_itab__1088, UD_TAB__OPC_MOD, "/mod" }, /* 1089 */ { ud_itab__1089, UD_TAB__OPC_MOD, "/mod" }, /* 1090 */ { ud_itab__1090, UD_TAB__OPC_MOD, "/mod" }, /* 1091 */ { ud_itab__1091, UD_TAB__OPC_MOD, "/mod" }, /* 1092 */ { ud_itab__1092, UD_TAB__OPC_MOD, "/mod" }, /* 1093 */ { ud_itab__1093, UD_TAB__OPC_MOD, "/mod" }, /* 1094 */ { ud_itab__1094, UD_TAB__OPC_MOD, "/mod" }, /* 1095 */ { ud_itab__1095, UD_TAB__OPC_MOD, "/mod" }, /* 1096 */ { ud_itab__1096, UD_TAB__OPC_MOD, "/mod" }, /* 1097 */ { ud_itab__1097, UD_TAB__OPC_MOD, "/mod" }, /* 1098 */ { ud_itab__1098, UD_TAB__OPC_MOD, "/mod" }, /* 1099 */ { ud_itab__1099, UD_TAB__OPC_MOD, "/mod" }, /* 1100 */ { ud_itab__1100, UD_TAB__OPC_MOD, "/mod" }, /* 1101 */ { ud_itab__1101, UD_TAB__OPC_MOD, "/mod" }, /* 1102 */ { ud_itab__1102, UD_TAB__OPC_MOD, "/mod" }, /* 1103 */ { ud_itab__1103, UD_TAB__OPC_MOD, "/mod" }, /* 1104 */ { ud_itab__1104, UD_TAB__OPC_MOD, "/mod" }, /* 1105 */ { ud_itab__1105, UD_TAB__OPC_MOD, "/mod" }, /* 1106 */ { ud_itab__1106, UD_TAB__OPC_MOD, "/mod" }, /* 1107 */ { ud_itab__1107, UD_TAB__OPC_MOD, "/mod" }, /* 1108 */ { ud_itab__1108, UD_TAB__OPC_MOD, "/mod" }, /* 1109 */ { ud_itab__1109, UD_TAB__OPC_MOD, "/mod" }, /* 1110 */ { ud_itab__1110, UD_TAB__OPC_MOD, "/mod" }, /* 1111 */ { ud_itab__1111, UD_TAB__OPC_MOD, "/mod" }, /* 1112 */ { ud_itab__1112, UD_TAB__OPC_MOD, "/mod" }, /* 1113 */ { ud_itab__1113, UD_TAB__OPC_MOD, "/mod" }, /* 1114 */ { ud_itab__1114, UD_TAB__OPC_MOD, "/mod" }, /* 1115 */ { ud_itab__1115, UD_TAB__OPC_MOD, "/mod" }, /* 1116 */ { ud_itab__1116, UD_TAB__OPC_MOD, "/mod" }, /* 1117 */ { ud_itab__1117, UD_TAB__OPC_MOD, "/mod" }, /* 1118 */ { ud_itab__1118, UD_TAB__OPC_MOD, "/mod" }, /* 1119 */ { ud_itab__1119, UD_TAB__OPC_MOD, "/mod" }, /* 1120 */ { ud_itab__1120, UD_TAB__OPC_MOD, "/mod" }, /* 1121 */ { ud_itab__1121, UD_TAB__OPC_MOD, "/mod" }, /* 1122 */ { ud_itab__1122, UD_TAB__OPC_MOD, "/mod" }, /* 1123 */ { ud_itab__1123, UD_TAB__OPC_MOD, "/mod" }, /* 1124 */ { ud_itab__1124, UD_TAB__OPC_MOD, "/mod" }, /* 1125 */ { ud_itab__1125, UD_TAB__OPC_MOD, "/mod" }, /* 1126 */ { ud_itab__1126, UD_TAB__OPC_ASIZE, "/a" }, /* 1127 */ { ud_itab__1127, UD_TAB__OPC_MODE, "/m" }, /* 1128 */ { ud_itab__1128, UD_TAB__OPC_REG, "/reg" }, /* 1129 */ { ud_itab__1129, UD_TAB__OPC_REG, "/reg" }, /* 1130 */ { ud_itab__1130, UD_TAB__OPC_REG, "/reg" }, /* 1131 */ { ud_itab__1131, UD_TAB__OPC_REG, "/reg" }, /* 1132 */ { ud_itab__1132, UD_TAB__OPC_MODE, "/m" }, }; /* itab entry operand definitions (for readability) */ #define O_AL { OP_AL, SZ_B } #define O_AX { OP_AX, SZ_W } #define O_Av { OP_A, SZ_V } #define O_C { OP_C, SZ_NA } #define O_CL { OP_CL, SZ_B } #define O_CS { OP_CS, SZ_NA } #define O_CX { OP_CX, SZ_W } #define O_D { OP_D, SZ_NA } #define O_DL { OP_DL, SZ_B } #define O_DS { OP_DS, SZ_NA } #define O_DX { OP_DX, SZ_W } #define O_E { OP_E, SZ_NA } #define O_ES { OP_ES, SZ_NA } #define O_Eb { OP_E, SZ_B } #define O_Ed { OP_E, SZ_D } #define O_Eq { OP_E, SZ_Q } #define O_Ev { OP_E, SZ_V } #define O_Ew { OP_E, SZ_W } #define O_Ey { OP_E, SZ_Y } #define O_Ez { OP_E, SZ_Z } #define O_FS { OP_FS, SZ_NA } #define O_Fv { OP_F, SZ_V } #define O_G { OP_G, SZ_NA } #define O_GS { OP_GS, SZ_NA } #define O_Gb { OP_G, SZ_B } #define O_Gd { OP_G, SZ_D } #define O_Gq { OP_G, SZ_Q } #define O_Gv { OP_G, SZ_V } #define O_Gw { OP_G, SZ_W } #define O_Gy { OP_G, SZ_Y } #define O_Gz { OP_G, SZ_Z } #define O_I1 { OP_I1, SZ_NA } #define O_I3 { OP_I3, SZ_NA } #define O_Ib { OP_I, SZ_B } #define O_Iv { OP_I, SZ_V } #define O_Iw { OP_I, SZ_W } #define O_Iz { OP_I, SZ_Z } #define O_Jb { OP_J, SZ_B } #define O_Jv { OP_J, SZ_V } #define O_Jz { OP_J, SZ_Z } #define O_M { OP_M, SZ_NA } #define O_Mb { OP_M, SZ_B } #define O_MbRd { OP_MR, SZ_BD } #define O_MbRv { OP_MR, SZ_BV } #define O_Md { OP_M, SZ_D } #define O_MdRy { OP_MR, SZ_DY } #define O_MdU { OP_MU, SZ_DO } #define O_Mo { OP_M, SZ_O } #define O_Mq { OP_M, SZ_Q } #define O_MqU { OP_MU, SZ_QO } #define O_Ms { OP_M, SZ_W } #define O_Mt { OP_M, SZ_T } #define O_Mv { OP_M, SZ_V } #define O_Mw { OP_M, SZ_W } #define O_MwRd { OP_MR, SZ_WD } #define O_MwRv { OP_MR, SZ_WV } #define O_MwRy { OP_MR, SZ_WY } #define O_MwU { OP_MU, SZ_WO } #define O_N { OP_N, SZ_Q } #define O_NONE { OP_NONE, SZ_NA } #define O_Ob { OP_O, SZ_B } #define O_Ov { OP_O, SZ_V } #define O_Ow { OP_O, SZ_W } #define O_P { OP_P, SZ_Q } #define O_Q { OP_Q, SZ_Q } #define O_R { OP_R, SZ_RDQ } #define O_R0b { OP_R0, SZ_B } #define O_R0v { OP_R0, SZ_V } #define O_R0w { OP_R0, SZ_W } #define O_R0y { OP_R0, SZ_Y } #define O_R0z { OP_R0, SZ_Z } #define O_R1b { OP_R1, SZ_B } #define O_R1v { OP_R1, SZ_V } #define O_R1w { OP_R1, SZ_W } #define O_R1y { OP_R1, SZ_Y } #define O_R1z { OP_R1, SZ_Z } #define O_R2b { OP_R2, SZ_B } #define O_R2v { OP_R2, SZ_V } #define O_R2w { OP_R2, SZ_W } #define O_R2y { OP_R2, SZ_Y } #define O_R2z { OP_R2, SZ_Z } #define O_R3b { OP_R3, SZ_B } #define O_R3v { OP_R3, SZ_V } #define O_R3w { OP_R3, SZ_W } #define O_R3y { OP_R3, SZ_Y } #define O_R3z { OP_R3, SZ_Z } #define O_R4b { OP_R4, SZ_B } #define O_R4v { OP_R4, SZ_V } #define O_R4w { OP_R4, SZ_W } #define O_R4y { OP_R4, SZ_Y } #define O_R4z { OP_R4, SZ_Z } #define O_R5b { OP_R5, SZ_B } #define O_R5v { OP_R5, SZ_V } #define O_R5w { OP_R5, SZ_W } #define O_R5y { OP_R5, SZ_Y } #define O_R5z { OP_R5, SZ_Z } #define O_R6b { OP_R6, SZ_B } #define O_R6v { OP_R6, SZ_V } #define O_R6w { OP_R6, SZ_W } #define O_R6y { OP_R6, SZ_Y } #define O_R6z { OP_R6, SZ_Z } #define O_R7b { OP_R7, SZ_B } #define O_R7v { OP_R7, SZ_V } #define O_R7w { OP_R7, SZ_W } #define O_R7y { OP_R7, SZ_Y } #define O_R7z { OP_R7, SZ_Z } #define O_S { OP_S, SZ_NA } #define O_SS { OP_SS, SZ_NA } #define O_ST0 { OP_ST0, SZ_NA } #define O_ST1 { OP_ST1, SZ_NA } #define O_ST2 { OP_ST2, SZ_NA } #define O_ST3 { OP_ST3, SZ_NA } #define O_ST4 { OP_ST4, SZ_NA } #define O_ST5 { OP_ST5, SZ_NA } #define O_ST6 { OP_ST6, SZ_NA } #define O_ST7 { OP_ST7, SZ_NA } #define O_U { OP_U, SZ_O } #define O_V { OP_V, SZ_O } #define O_W { OP_W, SZ_O } #define O_eAX { OP_eAX, SZ_Z } #define O_eCX { OP_eCX, SZ_Z } #define O_eDX { OP_eDX, SZ_Z } #define O_rAX { OP_rAX, SZ_V } #define O_rCX { OP_rCX, SZ_V } #define O_rDX { OP_rDX, SZ_V } #define O_sIb { OP_sI, SZ_B } #define O_sIv { OP_sI, SZ_V } #define O_sIz { OP_sI, SZ_Z } struct ud_itab_entry ud_itab[] = { /* 0000 */ { UD_Iinvalid, O_NONE, O_NONE, O_NONE, P_none }, /* 0001 */ { UD_Iadd, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0002 */ { UD_Iadd, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0003 */ { UD_Iadd, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0004 */ { UD_Iadd, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0005 */ { UD_Iadd, O_AL, O_Ib, O_NONE, P_none }, /* 0006 */ { UD_Iadd, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, /* 0007 */ { UD_Ipush, O_ES, O_NONE, O_NONE, P_inv64 }, /* 0008 */ { UD_Ipop, O_ES, O_NONE, O_NONE, P_inv64 }, /* 0009 */ { UD_Ior, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0010 */ { UD_Ior, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0011 */ { UD_Ior, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0012 */ { UD_Ior, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0013 */ { UD_Ior, O_AL, O_Ib, O_NONE, P_none }, /* 0014 */ { UD_Ior, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, /* 0015 */ { UD_Ipush, O_CS, O_NONE, O_NONE, P_inv64 }, /* 0016 */ { UD_Isldt, O_MwRv, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0017 */ { UD_Istr, O_MwRv, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0018 */ { UD_Illdt, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0019 */ { UD_Iltr, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0020 */ { UD_Iverr, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0021 */ { UD_Iverw, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0022 */ { UD_Isgdt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0023 */ { UD_Isidt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0024 */ { UD_Ilgdt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0025 */ { UD_Ilidt, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0026 */ { UD_Ismsw, O_MwRv, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0027 */ { UD_Ilmsw, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0028 */ { UD_Iinvlpg, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0029 */ { UD_Ivmcall, O_NONE, O_NONE, O_NONE, P_none }, /* 0030 */ { UD_Ivmlaunch, O_NONE, O_NONE, O_NONE, P_none }, /* 0031 */ { UD_Ivmresume, O_NONE, O_NONE, O_NONE, P_none }, /* 0032 */ { UD_Ivmxoff, O_NONE, O_NONE, O_NONE, P_none }, /* 0033 */ { UD_Imonitor, O_NONE, O_NONE, O_NONE, P_none }, /* 0034 */ { UD_Imwait, O_NONE, O_NONE, O_NONE, P_none }, /* 0035 */ { UD_Ixgetbv, O_NONE, O_NONE, O_NONE, P_none }, /* 0036 */ { UD_Ixsetbv, O_NONE, O_NONE, O_NONE, P_none }, /* 0037 */ { UD_Ivmrun, O_NONE, O_NONE, O_NONE, P_none }, /* 0038 */ { UD_Ivmmcall, O_NONE, O_NONE, O_NONE, P_none }, /* 0039 */ { UD_Ivmload, O_NONE, O_NONE, O_NONE, P_none }, /* 0040 */ { UD_Ivmsave, O_NONE, O_NONE, O_NONE, P_none }, /* 0041 */ { UD_Istgi, O_NONE, O_NONE, O_NONE, P_none }, /* 0042 */ { UD_Iclgi, O_NONE, O_NONE, O_NONE, P_none }, /* 0043 */ { UD_Iskinit, O_NONE, O_NONE, O_NONE, P_none }, /* 0044 */ { UD_Iinvlpga, O_NONE, O_NONE, O_NONE, P_none }, /* 0045 */ { UD_Ismsw, O_MwRv, O_NONE, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0046 */ { UD_Ilmsw, O_Ew, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0047 */ { UD_Iswapgs, O_NONE, O_NONE, O_NONE, P_none }, /* 0048 */ { UD_Irdtscp, O_NONE, O_NONE, O_NONE, P_none }, /* 0049 */ { UD_Ilar, O_Gv, O_Ew, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0050 */ { UD_Ilsl, O_Gv, O_Ew, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0051 */ { UD_Isyscall, O_NONE, O_NONE, O_NONE, P_none }, /* 0052 */ { UD_Iclts, O_NONE, O_NONE, O_NONE, P_none }, /* 0053 */ { UD_Isysret, O_NONE, O_NONE, O_NONE, P_none }, /* 0054 */ { UD_Iinvd, O_NONE, O_NONE, O_NONE, P_none }, /* 0055 */ { UD_Iwbinvd, O_NONE, O_NONE, O_NONE, P_none }, /* 0056 */ { UD_Iud2, O_NONE, O_NONE, O_NONE, P_none }, /* 0057 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0058 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0059 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0060 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0061 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0062 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0063 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0064 */ { UD_Iprefetch, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0065 */ { UD_Ifemms, O_NONE, O_NONE, O_NONE, P_none }, /* 0066 */ { UD_Ipi2fw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0067 */ { UD_Ipi2fd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0068 */ { UD_Ipf2iw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0069 */ { UD_Ipf2id, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0070 */ { UD_Ipfnacc, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0071 */ { UD_Ipfpnacc, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0072 */ { UD_Ipfcmpge, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0073 */ { UD_Ipfmin, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0074 */ { UD_Ipfrcp, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0075 */ { UD_Ipfrsqrt, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0076 */ { UD_Ipfsub, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0077 */ { UD_Ipfadd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0078 */ { UD_Ipfcmpgt, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0079 */ { UD_Ipfmax, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0080 */ { UD_Ipfrcpit1, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0081 */ { UD_Ipfrsqit1, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0082 */ { UD_Ipfsubr, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0083 */ { UD_Ipfacc, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0084 */ { UD_Ipfcmpeq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0085 */ { UD_Ipfmul, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0086 */ { UD_Ipfrcpit2, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0087 */ { UD_Ipmulhrw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0088 */ { UD_Ipswapd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0089 */ { UD_Ipavgusb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0090 */ { UD_Imovups, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0091 */ { UD_Imovsd, O_V, O_W, O_NONE, P_str|P_aso|P_rexr|P_rexx|P_rexb }, /* 0092 */ { UD_Imovss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0093 */ { UD_Imovupd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0094 */ { UD_Imovups, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0095 */ { UD_Imovsd, O_W, O_V, O_NONE, P_str|P_aso|P_rexr|P_rexx|P_rexb }, /* 0096 */ { UD_Imovss, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0097 */ { UD_Imovupd, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0098 */ { UD_Imovlps, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0099 */ { UD_Imovddup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0100 */ { UD_Imovsldup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0101 */ { UD_Imovlpd, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0102 */ { UD_Imovhlps, O_V, O_U, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0103 */ { UD_Imovddup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0104 */ { UD_Imovsldup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0105 */ { UD_Imovlps, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0106 */ { UD_Imovlpd, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0107 */ { UD_Iunpcklps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0108 */ { UD_Iunpcklpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0109 */ { UD_Iunpckhps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0110 */ { UD_Iunpckhpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0111 */ { UD_Imovhps, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0112 */ { UD_Imovshdup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0113 */ { UD_Imovhpd, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0114 */ { UD_Imovlhps, O_V, O_U, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0115 */ { UD_Imovshdup, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0116 */ { UD_Imovhps, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0117 */ { UD_Imovhpd, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0118 */ { UD_Iprefetchnta, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0119 */ { UD_Iprefetcht0, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0120 */ { UD_Iprefetcht1, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0121 */ { UD_Iprefetcht2, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0122 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0123 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0124 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0125 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0126 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0127 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0128 */ { UD_Inop, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0129 */ { UD_Imov, O_R, O_C, O_NONE, P_rexr|P_rexw|P_rexb }, /* 0130 */ { UD_Imov, O_R, O_D, O_NONE, P_rexr|P_rexw|P_rexb }, /* 0131 */ { UD_Imov, O_C, O_R, O_NONE, P_rexr|P_rexw|P_rexb }, /* 0132 */ { UD_Imov, O_D, O_R, O_NONE, P_rexr|P_rexw|P_rexb }, /* 0133 */ { UD_Imovaps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0134 */ { UD_Imovapd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0135 */ { UD_Imovaps, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0136 */ { UD_Imovapd, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0137 */ { UD_Icvtpi2ps, O_V, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0138 */ { UD_Icvtsi2sd, O_V, O_Ey, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0139 */ { UD_Icvtsi2ss, O_V, O_Ey, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0140 */ { UD_Icvtpi2pd, O_V, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0141 */ { UD_Imovntps, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0142 */ { UD_Imovntpd, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0143 */ { UD_Icvttps2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0144 */ { UD_Icvttsd2si, O_Gy, O_W, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0145 */ { UD_Icvttss2si, O_Gy, O_W, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0146 */ { UD_Icvttpd2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0147 */ { UD_Icvtps2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0148 */ { UD_Icvtsd2si, O_Gy, O_W, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0149 */ { UD_Icvtss2si, O_Gy, O_W, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0150 */ { UD_Icvtpd2pi, O_P, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0151 */ { UD_Iucomiss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0152 */ { UD_Iucomisd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0153 */ { UD_Icomiss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0154 */ { UD_Icomisd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0155 */ { UD_Iwrmsr, O_NONE, O_NONE, O_NONE, P_none }, /* 0156 */ { UD_Irdtsc, O_NONE, O_NONE, O_NONE, P_none }, /* 0157 */ { UD_Irdmsr, O_NONE, O_NONE, O_NONE, P_none }, /* 0158 */ { UD_Irdpmc, O_NONE, O_NONE, O_NONE, P_none }, /* 0159 */ { UD_Isysenter, O_NONE, O_NONE, O_NONE, P_none }, /* 0160 */ { UD_Isysenter, O_NONE, O_NONE, O_NONE, P_none }, /* 0161 */ { UD_Isysexit, O_NONE, O_NONE, O_NONE, P_none }, /* 0162 */ { UD_Isysexit, O_NONE, O_NONE, O_NONE, P_none }, /* 0163 */ { UD_Igetsec, O_NONE, O_NONE, O_NONE, P_none }, /* 0164 */ { UD_Ipshufb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0165 */ { UD_Ipshufb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0166 */ { UD_Iphaddw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0167 */ { UD_Iphaddw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0168 */ { UD_Iphaddd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0169 */ { UD_Iphaddd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0170 */ { UD_Iphaddsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0171 */ { UD_Iphaddsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0172 */ { UD_Ipmaddubsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0173 */ { UD_Ipmaddubsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0174 */ { UD_Iphsubw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0175 */ { UD_Iphsubw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0176 */ { UD_Iphsubd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0177 */ { UD_Iphsubd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0178 */ { UD_Iphsubsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0179 */ { UD_Iphsubsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0180 */ { UD_Ipsignb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0181 */ { UD_Ipsignb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0182 */ { UD_Ipsignw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0183 */ { UD_Ipsignw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0184 */ { UD_Ipsignd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0185 */ { UD_Ipsignd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0186 */ { UD_Ipmulhrsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0187 */ { UD_Ipmulhrsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0188 */ { UD_Ipblendvb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0189 */ { UD_Iblendvps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0190 */ { UD_Iblendvpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0191 */ { UD_Iptest, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0192 */ { UD_Ipabsb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0193 */ { UD_Ipabsb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0194 */ { UD_Ipabsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0195 */ { UD_Ipabsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0196 */ { UD_Ipabsd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0197 */ { UD_Ipabsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0198 */ { UD_Ipmovsxbw, O_V, O_MqU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0199 */ { UD_Ipmovsxbd, O_V, O_MdU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0200 */ { UD_Ipmovsxbq, O_V, O_MwU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0201 */ { UD_Ipmovsxwd, O_V, O_MqU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0202 */ { UD_Ipmovsxwq, O_V, O_MdU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0203 */ { UD_Ipmovsxdq, O_V, O_MqU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0204 */ { UD_Ipmuldq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0205 */ { UD_Ipcmpeqq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0206 */ { UD_Imovntdqa, O_V, O_Mo, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0207 */ { UD_Ipackusdw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0208 */ { UD_Ipmovzxbw, O_V, O_MqU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0209 */ { UD_Ipmovzxbd, O_V, O_MdU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0210 */ { UD_Ipmovzxbq, O_V, O_MwU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0211 */ { UD_Ipmovzxwd, O_V, O_MqU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0212 */ { UD_Ipmovzxwq, O_V, O_MdU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0213 */ { UD_Ipmovzxdq, O_V, O_MqU, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0214 */ { UD_Ipcmpgtq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0215 */ { UD_Ipminsb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0216 */ { UD_Ipminsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0217 */ { UD_Ipminuw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0218 */ { UD_Ipminud, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0219 */ { UD_Ipmaxsb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0220 */ { UD_Ipmaxsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0221 */ { UD_Ipmaxuw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0222 */ { UD_Ipmaxud, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0223 */ { UD_Ipmulld, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0224 */ { UD_Iphminposuw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0225 */ { UD_Iinvept, O_Gq, O_Mo, O_NONE, P_none }, /* 0226 */ { UD_Iinvvpid, O_Gq, O_Mo, O_NONE, P_none }, /* 0227 */ { UD_Iaesimc, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0228 */ { UD_Iaesenc, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0229 */ { UD_Iaesenclast, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0230 */ { UD_Iaesdec, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0231 */ { UD_Iaesdeclast, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0232 */ { UD_Imovbe, O_Gv, O_Mv, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0233 */ { UD_Icrc32, O_Gy, O_Eb, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0234 */ { UD_Imovbe, O_Mv, O_Gv, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0235 */ { UD_Icrc32, O_Gy, O_Ev, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0236 */ { UD_Iroundps, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0237 */ { UD_Iroundpd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0238 */ { UD_Iroundss, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0239 */ { UD_Iroundsd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0240 */ { UD_Iblendps, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0241 */ { UD_Iblendpd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0242 */ { UD_Ipblendw, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0243 */ { UD_Ipalignr, O_P, O_Q, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0244 */ { UD_Ipalignr, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0245 */ { UD_Ipextrb, O_MbRv, O_V, O_Ib, P_aso|P_rexx|P_rexr|P_rexb|P_def64 }, /* 0246 */ { UD_Ipextrw, O_MwRd, O_V, O_Ib, P_aso|P_rexx|P_rexr|P_rexb }, /* 0247 */ { UD_Ipextrd, O_Ed, O_V, O_Ib, P_aso|P_rexr|P_rexx|P_rexw|P_rexb }, /* 0248 */ { UD_Ipextrd, O_Ed, O_V, O_Ib, P_aso|P_rexr|P_rexx|P_rexw|P_rexb }, /* 0249 */ { UD_Ipextrq, O_Eq, O_V, O_Ib, P_aso|P_rexr|P_rexw|P_rexb|P_def64 }, /* 0250 */ { UD_Iextractps, O_MdRy, O_V, O_Ib, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0251 */ { UD_Ipinsrb, O_V, O_MbRd, O_Ib, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0252 */ { UD_Iinsertps, O_V, O_Md, O_Ib, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0253 */ { UD_Ipinsrd, O_V, O_Ed, O_Ib, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0254 */ { UD_Ipinsrd, O_V, O_Ed, O_Ib, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0255 */ { UD_Ipinsrq, O_V, O_Eq, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0256 */ { UD_Idpps, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0257 */ { UD_Idppd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0258 */ { UD_Impsadbw, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0259 */ { UD_Ipclmulqdq, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0260 */ { UD_Ipcmpestrm, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0261 */ { UD_Ipcmpestri, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0262 */ { UD_Ipcmpistrm, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0263 */ { UD_Ipcmpistri, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0264 */ { UD_Iaeskeygenassist, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0265 */ { UD_Icmovo, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0266 */ { UD_Icmovno, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0267 */ { UD_Icmovb, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0268 */ { UD_Icmovae, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0269 */ { UD_Icmovz, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0270 */ { UD_Icmovnz, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0271 */ { UD_Icmovbe, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0272 */ { UD_Icmova, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0273 */ { UD_Icmovs, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0274 */ { UD_Icmovns, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0275 */ { UD_Icmovp, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0276 */ { UD_Icmovnp, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0277 */ { UD_Icmovl, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0278 */ { UD_Icmovge, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0279 */ { UD_Icmovle, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0280 */ { UD_Icmovg, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0281 */ { UD_Imovmskps, O_Gd, O_U, O_NONE, P_oso|P_rexr|P_rexb }, /* 0282 */ { UD_Imovmskpd, O_Gd, O_U, O_NONE, P_oso|P_rexr|P_rexb }, /* 0283 */ { UD_Isqrtps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0284 */ { UD_Isqrtsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0285 */ { UD_Isqrtss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0286 */ { UD_Isqrtpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0287 */ { UD_Irsqrtps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0288 */ { UD_Irsqrtss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0289 */ { UD_Ircpps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0290 */ { UD_Ircpss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0291 */ { UD_Iandps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0292 */ { UD_Iandpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0293 */ { UD_Iandnps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0294 */ { UD_Iandnpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0295 */ { UD_Iorps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0296 */ { UD_Iorpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0297 */ { UD_Ixorps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0298 */ { UD_Ixorpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0299 */ { UD_Iaddps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0300 */ { UD_Iaddsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0301 */ { UD_Iaddss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0302 */ { UD_Iaddpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0303 */ { UD_Imulps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0304 */ { UD_Imulsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0305 */ { UD_Imulss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0306 */ { UD_Imulpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0307 */ { UD_Icvtps2pd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0308 */ { UD_Icvtsd2ss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0309 */ { UD_Icvtss2sd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0310 */ { UD_Icvtpd2ps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0311 */ { UD_Icvtdq2ps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0312 */ { UD_Icvttps2dq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0313 */ { UD_Icvtps2dq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0314 */ { UD_Isubps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0315 */ { UD_Isubsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0316 */ { UD_Isubss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0317 */ { UD_Isubpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0318 */ { UD_Iminps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0319 */ { UD_Iminsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0320 */ { UD_Iminss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0321 */ { UD_Iminpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0322 */ { UD_Idivps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0323 */ { UD_Idivsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0324 */ { UD_Idivss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0325 */ { UD_Idivpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0326 */ { UD_Imaxps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0327 */ { UD_Imaxsd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0328 */ { UD_Imaxss, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0329 */ { UD_Imaxpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0330 */ { UD_Ipunpcklbw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0331 */ { UD_Ipunpcklbw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0332 */ { UD_Ipunpcklwd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0333 */ { UD_Ipunpcklwd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0334 */ { UD_Ipunpckldq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0335 */ { UD_Ipunpckldq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0336 */ { UD_Ipacksswb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0337 */ { UD_Ipacksswb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0338 */ { UD_Ipcmpgtb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0339 */ { UD_Ipcmpgtb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0340 */ { UD_Ipcmpgtw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0341 */ { UD_Ipcmpgtw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0342 */ { UD_Ipcmpgtd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0343 */ { UD_Ipcmpgtd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0344 */ { UD_Ipackuswb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0345 */ { UD_Ipackuswb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0346 */ { UD_Ipunpckhbw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0347 */ { UD_Ipunpckhbw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0348 */ { UD_Ipunpckhwd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0349 */ { UD_Ipunpckhwd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0350 */ { UD_Ipunpckhdq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0351 */ { UD_Ipunpckhdq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0352 */ { UD_Ipackssdw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0353 */ { UD_Ipackssdw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0354 */ { UD_Ipunpcklqdq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0355 */ { UD_Ipunpckhqdq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0356 */ { UD_Imovd, O_P, O_Ey, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0357 */ { UD_Imovd, O_V, O_Ey, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0358 */ { UD_Imovq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0359 */ { UD_Imovdqu, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0360 */ { UD_Imovdqa, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0361 */ { UD_Ipshufw, O_P, O_Q, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0362 */ { UD_Ipshuflw, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0363 */ { UD_Ipshufhw, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0364 */ { UD_Ipshufd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0365 */ { UD_Ipsrlw, O_N, O_Ib, O_NONE, P_none }, /* 0366 */ { UD_Ipsrlw, O_U, O_Ib, O_NONE, P_rexb }, /* 0367 */ { UD_Ipsraw, O_N, O_Ib, O_NONE, P_none }, /* 0368 */ { UD_Ipsraw, O_U, O_Ib, O_NONE, P_rexb }, /* 0369 */ { UD_Ipsllw, O_N, O_Ib, O_NONE, P_none }, /* 0370 */ { UD_Ipsllw, O_U, O_Ib, O_NONE, P_rexb }, /* 0371 */ { UD_Ipsrld, O_N, O_Ib, O_NONE, P_none }, /* 0372 */ { UD_Ipsrld, O_U, O_Ib, O_NONE, P_rexb }, /* 0373 */ { UD_Ipsrad, O_N, O_Ib, O_NONE, P_none }, /* 0374 */ { UD_Ipsrad, O_U, O_Ib, O_NONE, P_rexb }, /* 0375 */ { UD_Ipslld, O_N, O_Ib, O_NONE, P_none }, /* 0376 */ { UD_Ipslld, O_U, O_Ib, O_NONE, P_rexb }, /* 0377 */ { UD_Ipsrlq, O_N, O_Ib, O_NONE, P_none }, /* 0378 */ { UD_Ipsrlq, O_U, O_Ib, O_NONE, P_rexb }, /* 0379 */ { UD_Ipsrldq, O_U, O_Ib, O_NONE, P_rexb }, /* 0380 */ { UD_Ipsllq, O_N, O_Ib, O_NONE, P_none }, /* 0381 */ { UD_Ipsllq, O_U, O_Ib, O_NONE, P_rexb }, /* 0382 */ { UD_Ipslldq, O_U, O_Ib, O_NONE, P_rexb }, /* 0383 */ { UD_Ipcmpeqb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0384 */ { UD_Ipcmpeqb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0385 */ { UD_Ipcmpeqw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0386 */ { UD_Ipcmpeqw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0387 */ { UD_Ipcmpeqd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0388 */ { UD_Ipcmpeqd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0389 */ { UD_Iemms, O_NONE, O_NONE, O_NONE, P_none }, /* 0390 */ { UD_Ivmread, O_Ey, O_Gy, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_def64 }, /* 0391 */ { UD_Ivmwrite, O_Gy, O_Ey, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_def64 }, /* 0392 */ { UD_Ihaddps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0393 */ { UD_Ihaddpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0394 */ { UD_Ihsubps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0395 */ { UD_Ihsubpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0396 */ { UD_Imovd, O_Ey, O_P, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0397 */ { UD_Imovq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0398 */ { UD_Imovd, O_Ey, O_V, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0399 */ { UD_Imovq, O_Q, O_P, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0400 */ { UD_Imovdqu, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0401 */ { UD_Imovdqa, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0402 */ { UD_Ijo, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0403 */ { UD_Ijno, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0404 */ { UD_Ijb, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0405 */ { UD_Ijae, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0406 */ { UD_Ijz, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0407 */ { UD_Ijnz, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0408 */ { UD_Ijbe, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0409 */ { UD_Ija, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0410 */ { UD_Ijs, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0411 */ { UD_Ijns, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0412 */ { UD_Ijp, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0413 */ { UD_Ijnp, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0414 */ { UD_Ijl, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0415 */ { UD_Ijge, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0416 */ { UD_Ijle, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0417 */ { UD_Ijg, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0418 */ { UD_Iseto, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0419 */ { UD_Isetno, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0420 */ { UD_Isetb, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0421 */ { UD_Isetae, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0422 */ { UD_Isetz, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0423 */ { UD_Isetnz, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0424 */ { UD_Isetbe, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0425 */ { UD_Iseta, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0426 */ { UD_Isets, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0427 */ { UD_Isetns, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0428 */ { UD_Isetp, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0429 */ { UD_Isetnp, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0430 */ { UD_Isetl, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0431 */ { UD_Isetge, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0432 */ { UD_Isetle, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0433 */ { UD_Isetg, O_Eb, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0434 */ { UD_Ipush, O_FS, O_NONE, O_NONE, P_none }, /* 0435 */ { UD_Ipop, O_FS, O_NONE, O_NONE, P_none }, /* 0436 */ { UD_Icpuid, O_NONE, O_NONE, O_NONE, P_none }, /* 0437 */ { UD_Ibt, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0438 */ { UD_Ishld, O_Ev, O_Gv, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0439 */ { UD_Ishld, O_Ev, O_Gv, O_CL, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0440 */ { UD_Imontmul, O_NONE, O_NONE, O_NONE, P_none }, /* 0441 */ { UD_Ixsha1, O_NONE, O_NONE, O_NONE, P_none }, /* 0442 */ { UD_Ixsha256, O_NONE, O_NONE, O_NONE, P_none }, /* 0443 */ { UD_Ixstore, O_NONE, O_NONE, O_NONE, P_none }, /* 0444 */ { UD_Ixcryptecb, O_NONE, O_NONE, O_NONE, P_none }, /* 0445 */ { UD_Ixcryptcbc, O_NONE, O_NONE, O_NONE, P_none }, /* 0446 */ { UD_Ixcryptctr, O_NONE, O_NONE, O_NONE, P_none }, /* 0447 */ { UD_Ixcryptcfb, O_NONE, O_NONE, O_NONE, P_none }, /* 0448 */ { UD_Ixcryptofb, O_NONE, O_NONE, O_NONE, P_none }, /* 0449 */ { UD_Ipush, O_GS, O_NONE, O_NONE, P_none }, /* 0450 */ { UD_Ipop, O_GS, O_NONE, O_NONE, P_none }, /* 0451 */ { UD_Irsm, O_NONE, O_NONE, O_NONE, P_none }, /* 0452 */ { UD_Ibts, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0453 */ { UD_Ishrd, O_Ev, O_Gv, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0454 */ { UD_Ishrd, O_Ev, O_Gv, O_CL, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0455 */ { UD_Ifxsave, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0456 */ { UD_Ifxrstor, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0457 */ { UD_Ildmxcsr, O_Md, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0458 */ { UD_Istmxcsr, O_Md, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0459 */ { UD_Ixsave, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0460 */ { UD_Ixrstor, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0461 */ { UD_Iclflush, O_M, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0462 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0463 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0464 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0465 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0466 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0467 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0468 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0469 */ { UD_Ilfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0470 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0471 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0472 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0473 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0474 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0475 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0476 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0477 */ { UD_Imfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0478 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0479 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0480 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0481 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0482 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0483 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0484 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0485 */ { UD_Isfence, O_NONE, O_NONE, O_NONE, P_none }, /* 0486 */ { UD_Iimul, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0487 */ { UD_Icmpxchg, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0488 */ { UD_Icmpxchg, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0489 */ { UD_Ilss, O_Gv, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0490 */ { UD_Ibtr, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0491 */ { UD_Ilfs, O_Gz, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0492 */ { UD_Ilgs, O_Gz, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0493 */ { UD_Imovzx, O_Gv, O_Eb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0494 */ { UD_Imovzx, O_Gy, O_Ew, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0495 */ { UD_Ipopcnt, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexr|P_rexw|P_rexx|P_rexb }, /* 0496 */ { UD_Ibt, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0497 */ { UD_Ibts, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0498 */ { UD_Ibtr, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0499 */ { UD_Ibtc, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0500 */ { UD_Ibtc, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0501 */ { UD_Ibsf, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0502 */ { UD_Ibsr, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0503 */ { UD_Imovsx, O_Gv, O_Eb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0504 */ { UD_Imovsx, O_Gy, O_Ew, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0505 */ { UD_Ixadd, O_Eb, O_Gb, O_NONE, P_aso|P_oso|P_rexr|P_rexx|P_rexb }, /* 0506 */ { UD_Ixadd, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0507 */ { UD_Icmpps, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0508 */ { UD_Icmpsd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0509 */ { UD_Icmpss, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0510 */ { UD_Icmppd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0511 */ { UD_Imovnti, O_M, O_Gy, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0512 */ { UD_Ipinsrw, O_P, O_MwRy, O_Ib, P_aso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, /* 0513 */ { UD_Ipinsrw, O_V, O_MwRy, O_Ib, P_aso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, /* 0514 */ { UD_Ipextrw, O_Gd, O_N, O_Ib, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0515 */ { UD_Ipextrw, O_Gd, O_U, O_Ib, P_aso|P_rexr|P_rexb }, /* 0516 */ { UD_Ishufps, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0517 */ { UD_Ishufpd, O_V, O_W, O_Ib, P_aso|P_rexr|P_rexx|P_rexb }, /* 0518 */ { UD_Icmpxchg8b, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0519 */ { UD_Icmpxchg8b, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0520 */ { UD_Icmpxchg16b, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0521 */ { UD_Ivmptrld, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0522 */ { UD_Ivmxon, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0523 */ { UD_Ivmclear, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0524 */ { UD_Ivmptrst, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0525 */ { UD_Ibswap, O_R0y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* 0526 */ { UD_Ibswap, O_R1y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* 0527 */ { UD_Ibswap, O_R2y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* 0528 */ { UD_Ibswap, O_R3y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* 0529 */ { UD_Ibswap, O_R4y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* 0530 */ { UD_Ibswap, O_R5y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* 0531 */ { UD_Ibswap, O_R6y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* 0532 */ { UD_Ibswap, O_R7y, O_NONE, O_NONE, P_oso|P_rexw|P_rexb }, /* 0533 */ { UD_Iaddsubps, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0534 */ { UD_Iaddsubpd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0535 */ { UD_Ipsrlw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0536 */ { UD_Ipsrlw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0537 */ { UD_Ipsrld, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0538 */ { UD_Ipsrld, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0539 */ { UD_Ipsrlq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0540 */ { UD_Ipsrlq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0541 */ { UD_Ipaddq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0542 */ { UD_Ipaddq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0543 */ { UD_Ipmullw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0544 */ { UD_Ipmullw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0545 */ { UD_Imovdq2q, O_P, O_U, O_NONE, P_aso|P_rexb }, /* 0546 */ { UD_Imovq2dq, O_V, O_N, O_NONE, P_aso|P_rexr }, /* 0547 */ { UD_Imovq, O_W, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0548 */ { UD_Ipmovmskb, O_Gd, O_N, O_NONE, P_oso|P_rexr|P_rexb }, /* 0549 */ { UD_Ipmovmskb, O_Gd, O_U, O_NONE, P_rexr|P_rexb }, /* 0550 */ { UD_Ipsubusb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0551 */ { UD_Ipsubusb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0552 */ { UD_Ipsubusw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0553 */ { UD_Ipsubusw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0554 */ { UD_Ipminub, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0555 */ { UD_Ipminub, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0556 */ { UD_Ipand, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0557 */ { UD_Ipand, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0558 */ { UD_Ipaddusb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0559 */ { UD_Ipaddusb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0560 */ { UD_Ipaddusw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0561 */ { UD_Ipaddusw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0562 */ { UD_Ipmaxub, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0563 */ { UD_Ipmaxub, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0564 */ { UD_Ipandn, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0565 */ { UD_Ipandn, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0566 */ { UD_Ipavgb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0567 */ { UD_Ipavgb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0568 */ { UD_Ipsraw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0569 */ { UD_Ipsraw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0570 */ { UD_Ipsrad, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0571 */ { UD_Ipsrad, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0572 */ { UD_Ipavgw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0573 */ { UD_Ipavgw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0574 */ { UD_Ipmulhuw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0575 */ { UD_Ipmulhuw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0576 */ { UD_Ipmulhw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0577 */ { UD_Ipmulhw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0578 */ { UD_Icvtpd2dq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0579 */ { UD_Icvtdq2pd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0580 */ { UD_Icvttpd2dq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0581 */ { UD_Imovntq, O_M, O_P, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0582 */ { UD_Imovntdq, O_M, O_V, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0583 */ { UD_Ipsubsb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0584 */ { UD_Ipsubsb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0585 */ { UD_Ipsubsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0586 */ { UD_Ipsubsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0587 */ { UD_Ipminsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0588 */ { UD_Ipminsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0589 */ { UD_Ipor, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0590 */ { UD_Ipor, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0591 */ { UD_Ipaddsb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0592 */ { UD_Ipaddsb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0593 */ { UD_Ipaddsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0594 */ { UD_Ipaddsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0595 */ { UD_Ipmaxsw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0596 */ { UD_Ipmaxsw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0597 */ { UD_Ipxor, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0598 */ { UD_Ipxor, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0599 */ { UD_Ilddqu, O_V, O_M, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0600 */ { UD_Ipsllw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0601 */ { UD_Ipsllw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0602 */ { UD_Ipslld, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0603 */ { UD_Ipslld, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0604 */ { UD_Ipsllq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0605 */ { UD_Ipsllq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0606 */ { UD_Ipmuludq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0607 */ { UD_Ipmuludq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0608 */ { UD_Ipmaddwd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0609 */ { UD_Ipmaddwd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0610 */ { UD_Ipsadbw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0611 */ { UD_Ipsadbw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0612 */ { UD_Imaskmovq, O_P, O_N, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0613 */ { UD_Imaskmovdqu, O_V, O_U, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0614 */ { UD_Ipsubb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0615 */ { UD_Ipsubb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0616 */ { UD_Ipsubw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0617 */ { UD_Ipsubw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0618 */ { UD_Ipsubd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0619 */ { UD_Ipsubd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0620 */ { UD_Ipsubq, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0621 */ { UD_Ipsubq, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0622 */ { UD_Ipaddb, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0623 */ { UD_Ipaddb, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0624 */ { UD_Ipaddw, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0625 */ { UD_Ipaddw, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0626 */ { UD_Ipaddd, O_P, O_Q, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0627 */ { UD_Ipaddd, O_V, O_W, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0628 */ { UD_Iadc, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0629 */ { UD_Iadc, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0630 */ { UD_Iadc, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0631 */ { UD_Iadc, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0632 */ { UD_Iadc, O_AL, O_Ib, O_NONE, P_none }, /* 0633 */ { UD_Iadc, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, /* 0634 */ { UD_Ipush, O_SS, O_NONE, O_NONE, P_inv64 }, /* 0635 */ { UD_Ipop, O_SS, O_NONE, O_NONE, P_inv64 }, /* 0636 */ { UD_Isbb, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0637 */ { UD_Isbb, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0638 */ { UD_Isbb, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0639 */ { UD_Isbb, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0640 */ { UD_Isbb, O_AL, O_Ib, O_NONE, P_none }, /* 0641 */ { UD_Isbb, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, /* 0642 */ { UD_Ipush, O_DS, O_NONE, O_NONE, P_inv64 }, /* 0643 */ { UD_Ipop, O_DS, O_NONE, O_NONE, P_inv64 }, /* 0644 */ { UD_Iand, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0645 */ { UD_Iand, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0646 */ { UD_Iand, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0647 */ { UD_Iand, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0648 */ { UD_Iand, O_AL, O_Ib, O_NONE, P_none }, /* 0649 */ { UD_Iand, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, /* 0650 */ { UD_Idaa, O_NONE, O_NONE, O_NONE, P_inv64 }, /* 0651 */ { UD_Isub, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0652 */ { UD_Isub, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0653 */ { UD_Isub, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0654 */ { UD_Isub, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0655 */ { UD_Isub, O_AL, O_Ib, O_NONE, P_none }, /* 0656 */ { UD_Isub, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, /* 0657 */ { UD_Idas, O_NONE, O_NONE, O_NONE, P_inv64 }, /* 0658 */ { UD_Ixor, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0659 */ { UD_Ixor, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0660 */ { UD_Ixor, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0661 */ { UD_Ixor, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0662 */ { UD_Ixor, O_AL, O_Ib, O_NONE, P_none }, /* 0663 */ { UD_Ixor, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, /* 0664 */ { UD_Iaaa, O_NONE, O_NONE, O_NONE, P_none }, /* 0665 */ { UD_Icmp, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0666 */ { UD_Icmp, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0667 */ { UD_Icmp, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0668 */ { UD_Icmp, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0669 */ { UD_Icmp, O_AL, O_Ib, O_NONE, P_none }, /* 0670 */ { UD_Icmp, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, /* 0671 */ { UD_Iaas, O_NONE, O_NONE, O_NONE, P_none }, /* 0672 */ { UD_Iinc, O_R0z, O_NONE, O_NONE, P_oso }, /* 0673 */ { UD_Iinc, O_R1z, O_NONE, O_NONE, P_oso }, /* 0674 */ { UD_Iinc, O_R2z, O_NONE, O_NONE, P_oso }, /* 0675 */ { UD_Iinc, O_R3z, O_NONE, O_NONE, P_oso }, /* 0676 */ { UD_Iinc, O_R4z, O_NONE, O_NONE, P_oso }, /* 0677 */ { UD_Iinc, O_R5z, O_NONE, O_NONE, P_oso }, /* 0678 */ { UD_Iinc, O_R6z, O_NONE, O_NONE, P_oso }, /* 0679 */ { UD_Iinc, O_R7z, O_NONE, O_NONE, P_oso }, /* 0680 */ { UD_Idec, O_R0z, O_NONE, O_NONE, P_oso }, /* 0681 */ { UD_Idec, O_R1z, O_NONE, O_NONE, P_oso }, /* 0682 */ { UD_Idec, O_R2z, O_NONE, O_NONE, P_oso }, /* 0683 */ { UD_Idec, O_R3z, O_NONE, O_NONE, P_oso }, /* 0684 */ { UD_Idec, O_R4z, O_NONE, O_NONE, P_oso }, /* 0685 */ { UD_Idec, O_R5z, O_NONE, O_NONE, P_oso }, /* 0686 */ { UD_Idec, O_R6z, O_NONE, O_NONE, P_oso }, /* 0687 */ { UD_Idec, O_R7z, O_NONE, O_NONE, P_oso }, /* 0688 */ { UD_Ipush, O_R0v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0689 */ { UD_Ipush, O_R1v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0690 */ { UD_Ipush, O_R2v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0691 */ { UD_Ipush, O_R3v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0692 */ { UD_Ipush, O_R4v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0693 */ { UD_Ipush, O_R5v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0694 */ { UD_Ipush, O_R6v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0695 */ { UD_Ipush, O_R7v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0696 */ { UD_Ipop, O_R0v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0697 */ { UD_Ipop, O_R1v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0698 */ { UD_Ipop, O_R2v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0699 */ { UD_Ipop, O_R3v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0700 */ { UD_Ipop, O_R4v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0701 */ { UD_Ipop, O_R5v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0702 */ { UD_Ipop, O_R6v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0703 */ { UD_Ipop, O_R7v, O_NONE, O_NONE, P_oso|P_rexb|P_def64 }, /* 0704 */ { UD_Ipusha, O_NONE, O_NONE, O_NONE, P_oso|P_inv64 }, /* 0705 */ { UD_Ipushad, O_NONE, O_NONE, O_NONE, P_oso|P_inv64 }, /* 0706 */ { UD_Ipopa, O_NONE, O_NONE, O_NONE, P_oso|P_inv64 }, /* 0707 */ { UD_Ipopad, O_NONE, O_NONE, O_NONE, P_oso|P_inv64 }, /* 0708 */ { UD_Ibound, O_Gv, O_M, O_NONE, P_aso|P_oso }, /* 0709 */ { UD_Iarpl, O_Ew, O_Gw, O_NONE, P_aso }, /* 0710 */ { UD_Imovsxd, O_Gq, O_Ed, O_NONE, P_aso|P_oso|P_rexw|P_rexx|P_rexr|P_rexb }, /* 0711 */ { UD_Ipush, O_sIz, O_NONE, O_NONE, P_oso|P_def64 }, /* 0712 */ { UD_Iimul, O_Gv, O_Ev, O_Iz, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0713 */ { UD_Ipush, O_sIb, O_NONE, O_NONE, P_oso|P_def64 }, /* 0714 */ { UD_Iimul, O_Gv, O_Ev, O_sIb, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0715 */ { UD_Iinsb, O_NONE, O_NONE, O_NONE, P_str|P_seg }, /* 0716 */ { UD_Iinsw, O_NONE, O_NONE, O_NONE, P_str|P_oso|P_seg }, /* 0717 */ { UD_Iinsd, O_NONE, O_NONE, O_NONE, P_str|P_oso|P_seg }, /* 0718 */ { UD_Ioutsb, O_NONE, O_NONE, O_NONE, P_str|P_seg }, /* 0719 */ { UD_Ioutsw, O_NONE, O_NONE, O_NONE, P_str|P_oso|P_seg }, /* 0720 */ { UD_Ioutsd, O_NONE, O_NONE, O_NONE, P_str|P_oso|P_seg }, /* 0721 */ { UD_Ijo, O_Jb, O_NONE, O_NONE, P_none }, /* 0722 */ { UD_Ijno, O_Jb, O_NONE, O_NONE, P_none }, /* 0723 */ { UD_Ijb, O_Jb, O_NONE, O_NONE, P_none }, /* 0724 */ { UD_Ijae, O_Jb, O_NONE, O_NONE, P_none }, /* 0725 */ { UD_Ijz, O_Jb, O_NONE, O_NONE, P_none }, /* 0726 */ { UD_Ijnz, O_Jb, O_NONE, O_NONE, P_none }, /* 0727 */ { UD_Ijbe, O_Jb, O_NONE, O_NONE, P_none }, /* 0728 */ { UD_Ija, O_Jb, O_NONE, O_NONE, P_none }, /* 0729 */ { UD_Ijs, O_Jb, O_NONE, O_NONE, P_none }, /* 0730 */ { UD_Ijns, O_Jb, O_NONE, O_NONE, P_none }, /* 0731 */ { UD_Ijp, O_Jb, O_NONE, O_NONE, P_none }, /* 0732 */ { UD_Ijnp, O_Jb, O_NONE, O_NONE, P_none }, /* 0733 */ { UD_Ijl, O_Jb, O_NONE, O_NONE, P_none }, /* 0734 */ { UD_Ijge, O_Jb, O_NONE, O_NONE, P_none }, /* 0735 */ { UD_Ijle, O_Jb, O_NONE, O_NONE, P_none }, /* 0736 */ { UD_Ijg, O_Jb, O_NONE, O_NONE, P_none }, /* 0737 */ { UD_Iadd, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0738 */ { UD_Ior, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0739 */ { UD_Iadc, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0740 */ { UD_Isbb, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0741 */ { UD_Iand, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0742 */ { UD_Isub, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0743 */ { UD_Ixor, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0744 */ { UD_Icmp, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0745 */ { UD_Iadd, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0746 */ { UD_Ior, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0747 */ { UD_Iadc, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0748 */ { UD_Isbb, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0749 */ { UD_Iand, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0750 */ { UD_Isub, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0751 */ { UD_Ixor, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0752 */ { UD_Icmp, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0753 */ { UD_Iadd, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, /* 0754 */ { UD_Ior, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0755 */ { UD_Iadc, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, /* 0756 */ { UD_Isbb, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, /* 0757 */ { UD_Iand, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, /* 0758 */ { UD_Isub, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, /* 0759 */ { UD_Ixor, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, /* 0760 */ { UD_Icmp, O_Eb, O_Ib, O_NONE, P_aso|P_rexr|P_rexx|P_rexb|P_inv64 }, /* 0761 */ { UD_Iadd, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0762 */ { UD_Ior, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0763 */ { UD_Iadc, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0764 */ { UD_Isbb, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0765 */ { UD_Iand, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0766 */ { UD_Isub, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0767 */ { UD_Ixor, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0768 */ { UD_Icmp, O_Ev, O_sIb, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0769 */ { UD_Itest, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0770 */ { UD_Itest, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0771 */ { UD_Ixchg, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0772 */ { UD_Ixchg, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0773 */ { UD_Imov, O_Eb, O_Gb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0774 */ { UD_Imov, O_Ev, O_Gv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0775 */ { UD_Imov, O_Gb, O_Eb, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0776 */ { UD_Imov, O_Gv, O_Ev, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0777 */ { UD_Imov, O_MwRv, O_S, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0778 */ { UD_Ilea, O_Gv, O_M, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0779 */ { UD_Imov, O_S, O_MwRv, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0780 */ { UD_Ipop, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, /* 0781 */ { UD_Ixchg, O_R0v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 0782 */ { UD_Ixchg, O_R1v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 0783 */ { UD_Ixchg, O_R2v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 0784 */ { UD_Ixchg, O_R3v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 0785 */ { UD_Ixchg, O_R4v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 0786 */ { UD_Ixchg, O_R5v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 0787 */ { UD_Ixchg, O_R6v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 0788 */ { UD_Ixchg, O_R7v, O_rAX, O_NONE, P_oso|P_rexw|P_rexb }, /* 0789 */ { UD_Icbw, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 0790 */ { UD_Icwde, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 0791 */ { UD_Icdqe, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 0792 */ { UD_Icwd, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 0793 */ { UD_Icdq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 0794 */ { UD_Icqo, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 0795 */ { UD_Icall, O_Av, O_NONE, O_NONE, P_oso }, /* 0796 */ { UD_Iwait, O_NONE, O_NONE, O_NONE, P_none }, /* 0797 */ { UD_Ipushfw, O_NONE, O_NONE, O_NONE, P_oso }, /* 0798 */ { UD_Ipushfw, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_def64 }, /* 0799 */ { UD_Ipushfd, O_NONE, O_NONE, O_NONE, P_oso }, /* 0800 */ { UD_Ipushfq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_def64 }, /* 0801 */ { UD_Ipushfq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw|P_def64 }, /* 0802 */ { UD_Ipopfw, O_NONE, O_NONE, O_NONE, P_oso }, /* 0803 */ { UD_Ipopfd, O_NONE, O_NONE, O_NONE, P_oso }, /* 0804 */ { UD_Ipopfq, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, /* 0805 */ { UD_Ipopfq, O_NONE, O_NONE, O_NONE, P_oso|P_def64 }, /* 0806 */ { UD_Isahf, O_NONE, O_NONE, O_NONE, P_none }, /* 0807 */ { UD_Ilahf, O_NONE, O_NONE, O_NONE, P_none }, /* 0808 */ { UD_Imov, O_AL, O_Ob, O_NONE, P_none }, /* 0809 */ { UD_Imov, O_rAX, O_Ov, O_NONE, P_aso|P_oso|P_rexw }, /* 0810 */ { UD_Imov, O_Ob, O_AL, O_NONE, P_none }, /* 0811 */ { UD_Imov, O_Ov, O_rAX, O_NONE, P_aso|P_oso|P_rexw }, /* 0812 */ { UD_Imovsb, O_NONE, O_NONE, O_NONE, P_str|P_seg }, /* 0813 */ { UD_Imovsw, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, /* 0814 */ { UD_Imovsd, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, /* 0815 */ { UD_Imovsq, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, /* 0816 */ { UD_Icmpsb, O_NONE, O_NONE, O_NONE, P_strz|P_seg }, /* 0817 */ { UD_Icmpsw, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw|P_seg }, /* 0818 */ { UD_Icmpsd, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw|P_seg }, /* 0819 */ { UD_Icmpsq, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw|P_seg }, /* 0820 */ { UD_Itest, O_AL, O_Ib, O_NONE, P_none }, /* 0821 */ { UD_Itest, O_rAX, O_sIz, O_NONE, P_oso|P_rexw }, /* 0822 */ { UD_Istosb, O_NONE, O_NONE, O_NONE, P_str|P_seg }, /* 0823 */ { UD_Istosw, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, /* 0824 */ { UD_Istosd, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, /* 0825 */ { UD_Istosq, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, /* 0826 */ { UD_Ilodsb, O_NONE, O_NONE, O_NONE, P_str|P_seg }, /* 0827 */ { UD_Ilodsw, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, /* 0828 */ { UD_Ilodsd, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, /* 0829 */ { UD_Ilodsq, O_NONE, O_NONE, O_NONE, P_str|P_seg|P_oso|P_rexw }, /* 0830 */ { UD_Iscasb, O_NONE, O_NONE, O_NONE, P_strz }, /* 0831 */ { UD_Iscasw, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw }, /* 0832 */ { UD_Iscasd, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw }, /* 0833 */ { UD_Iscasq, O_NONE, O_NONE, O_NONE, P_strz|P_oso|P_rexw }, /* 0834 */ { UD_Imov, O_R0b, O_Ib, O_NONE, P_rexb }, /* 0835 */ { UD_Imov, O_R1b, O_Ib, O_NONE, P_rexb }, /* 0836 */ { UD_Imov, O_R2b, O_Ib, O_NONE, P_rexb }, /* 0837 */ { UD_Imov, O_R3b, O_Ib, O_NONE, P_rexb }, /* 0838 */ { UD_Imov, O_R4b, O_Ib, O_NONE, P_rexb }, /* 0839 */ { UD_Imov, O_R5b, O_Ib, O_NONE, P_rexb }, /* 0840 */ { UD_Imov, O_R6b, O_Ib, O_NONE, P_rexb }, /* 0841 */ { UD_Imov, O_R7b, O_Ib, O_NONE, P_rexb }, /* 0842 */ { UD_Imov, O_R0v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* 0843 */ { UD_Imov, O_R1v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* 0844 */ { UD_Imov, O_R2v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* 0845 */ { UD_Imov, O_R3v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* 0846 */ { UD_Imov, O_R4v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* 0847 */ { UD_Imov, O_R5v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* 0848 */ { UD_Imov, O_R6v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* 0849 */ { UD_Imov, O_R7v, O_Iv, O_NONE, P_oso|P_rexw|P_rexb }, /* 0850 */ { UD_Irol, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0851 */ { UD_Iror, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0852 */ { UD_Ircl, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0853 */ { UD_Ircr, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0854 */ { UD_Ishl, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0855 */ { UD_Ishr, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0856 */ { UD_Ishl, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0857 */ { UD_Isar, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0858 */ { UD_Irol, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0859 */ { UD_Iror, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0860 */ { UD_Ircl, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0861 */ { UD_Ircr, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0862 */ { UD_Ishl, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0863 */ { UD_Ishr, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0864 */ { UD_Ishl, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0865 */ { UD_Isar, O_Ev, O_Ib, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0866 */ { UD_Iret, O_Iw, O_NONE, O_NONE, P_none }, /* 0867 */ { UD_Iret, O_NONE, O_NONE, O_NONE, P_none }, /* 0868 */ { UD_Iles, O_Gv, O_M, O_NONE, P_aso|P_oso }, /* 0869 */ { UD_Ilds, O_Gv, O_M, O_NONE, P_aso|P_oso }, /* 0870 */ { UD_Imov, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0871 */ { UD_Imov, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0872 */ { UD_Ienter, O_Iw, O_Ib, O_NONE, P_def64 }, /* 0873 */ { UD_Ileave, O_NONE, O_NONE, O_NONE, P_none }, /* 0874 */ { UD_Iretf, O_Iw, O_NONE, O_NONE, P_none }, /* 0875 */ { UD_Iretf, O_NONE, O_NONE, O_NONE, P_none }, /* 0876 */ { UD_Iint3, O_NONE, O_NONE, O_NONE, P_none }, /* 0877 */ { UD_Iint, O_Ib, O_NONE, O_NONE, P_none }, /* 0878 */ { UD_Iinto, O_NONE, O_NONE, O_NONE, P_inv64 }, /* 0879 */ { UD_Iiretw, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 0880 */ { UD_Iiretd, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 0881 */ { UD_Iiretq, O_NONE, O_NONE, O_NONE, P_oso|P_rexw }, /* 0882 */ { UD_Irol, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0883 */ { UD_Iror, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0884 */ { UD_Ircl, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0885 */ { UD_Ircr, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0886 */ { UD_Ishl, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0887 */ { UD_Ishr, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0888 */ { UD_Ishl, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0889 */ { UD_Isar, O_Eb, O_I1, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0890 */ { UD_Irol, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0891 */ { UD_Iror, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0892 */ { UD_Ircl, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0893 */ { UD_Ircr, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0894 */ { UD_Ishl, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0895 */ { UD_Ishr, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0896 */ { UD_Ishl, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0897 */ { UD_Isar, O_Ev, O_I1, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0898 */ { UD_Irol, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0899 */ { UD_Iror, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0900 */ { UD_Ircl, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0901 */ { UD_Ircr, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0902 */ { UD_Ishl, O_Eb, O_CL, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0903 */ { UD_Ishr, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0904 */ { UD_Ishl, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0905 */ { UD_Isar, O_Eb, O_CL, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0906 */ { UD_Irol, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0907 */ { UD_Iror, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0908 */ { UD_Ircl, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0909 */ { UD_Ircr, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0910 */ { UD_Ishl, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0911 */ { UD_Ishr, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0912 */ { UD_Ishl, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0913 */ { UD_Isar, O_Ev, O_CL, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 0914 */ { UD_Iaam, O_Ib, O_NONE, O_NONE, P_none }, /* 0915 */ { UD_Iaad, O_Ib, O_NONE, O_NONE, P_none }, /* 0916 */ { UD_Isalc, O_NONE, O_NONE, O_NONE, P_inv64 }, /* 0917 */ { UD_Ixlatb, O_NONE, O_NONE, O_NONE, P_rexw|P_seg }, /* 0918 */ { UD_Ifadd, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0919 */ { UD_Ifmul, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0920 */ { UD_Ifcom, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0921 */ { UD_Ifcomp, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0922 */ { UD_Ifsub, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0923 */ { UD_Ifsubr, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0924 */ { UD_Ifdiv, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0925 */ { UD_Ifdivr, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0926 */ { UD_Ifadd, O_ST0, O_ST0, O_NONE, P_none }, /* 0927 */ { UD_Ifadd, O_ST0, O_ST1, O_NONE, P_none }, /* 0928 */ { UD_Ifadd, O_ST0, O_ST2, O_NONE, P_none }, /* 0929 */ { UD_Ifadd, O_ST0, O_ST3, O_NONE, P_none }, /* 0930 */ { UD_Ifadd, O_ST0, O_ST4, O_NONE, P_none }, /* 0931 */ { UD_Ifadd, O_ST0, O_ST5, O_NONE, P_none }, /* 0932 */ { UD_Ifadd, O_ST0, O_ST6, O_NONE, P_none }, /* 0933 */ { UD_Ifadd, O_ST0, O_ST7, O_NONE, P_none }, /* 0934 */ { UD_Ifmul, O_ST0, O_ST0, O_NONE, P_none }, /* 0935 */ { UD_Ifmul, O_ST0, O_ST1, O_NONE, P_none }, /* 0936 */ { UD_Ifmul, O_ST0, O_ST2, O_NONE, P_none }, /* 0937 */ { UD_Ifmul, O_ST0, O_ST3, O_NONE, P_none }, /* 0938 */ { UD_Ifmul, O_ST0, O_ST4, O_NONE, P_none }, /* 0939 */ { UD_Ifmul, O_ST0, O_ST5, O_NONE, P_none }, /* 0940 */ { UD_Ifmul, O_ST0, O_ST6, O_NONE, P_none }, /* 0941 */ { UD_Ifmul, O_ST0, O_ST7, O_NONE, P_none }, /* 0942 */ { UD_Ifcom, O_ST0, O_ST0, O_NONE, P_none }, /* 0943 */ { UD_Ifcom, O_ST0, O_ST1, O_NONE, P_none }, /* 0944 */ { UD_Ifcom, O_ST0, O_ST2, O_NONE, P_none }, /* 0945 */ { UD_Ifcom, O_ST0, O_ST3, O_NONE, P_none }, /* 0946 */ { UD_Ifcom, O_ST0, O_ST4, O_NONE, P_none }, /* 0947 */ { UD_Ifcom, O_ST0, O_ST5, O_NONE, P_none }, /* 0948 */ { UD_Ifcom, O_ST0, O_ST6, O_NONE, P_none }, /* 0949 */ { UD_Ifcom, O_ST0, O_ST7, O_NONE, P_none }, /* 0950 */ { UD_Ifcomp, O_ST0, O_ST0, O_NONE, P_none }, /* 0951 */ { UD_Ifcomp, O_ST0, O_ST1, O_NONE, P_none }, /* 0952 */ { UD_Ifcomp, O_ST0, O_ST2, O_NONE, P_none }, /* 0953 */ { UD_Ifcomp, O_ST0, O_ST3, O_NONE, P_none }, /* 0954 */ { UD_Ifcomp, O_ST0, O_ST4, O_NONE, P_none }, /* 0955 */ { UD_Ifcomp, O_ST0, O_ST5, O_NONE, P_none }, /* 0956 */ { UD_Ifcomp, O_ST0, O_ST6, O_NONE, P_none }, /* 0957 */ { UD_Ifcomp, O_ST0, O_ST7, O_NONE, P_none }, /* 0958 */ { UD_Ifsub, O_ST0, O_ST0, O_NONE, P_none }, /* 0959 */ { UD_Ifsub, O_ST0, O_ST1, O_NONE, P_none }, /* 0960 */ { UD_Ifsub, O_ST0, O_ST2, O_NONE, P_none }, /* 0961 */ { UD_Ifsub, O_ST0, O_ST3, O_NONE, P_none }, /* 0962 */ { UD_Ifsub, O_ST0, O_ST4, O_NONE, P_none }, /* 0963 */ { UD_Ifsub, O_ST0, O_ST5, O_NONE, P_none }, /* 0964 */ { UD_Ifsub, O_ST0, O_ST6, O_NONE, P_none }, /* 0965 */ { UD_Ifsub, O_ST0, O_ST7, O_NONE, P_none }, /* 0966 */ { UD_Ifsubr, O_ST0, O_ST0, O_NONE, P_none }, /* 0967 */ { UD_Ifsubr, O_ST0, O_ST1, O_NONE, P_none }, /* 0968 */ { UD_Ifsubr, O_ST0, O_ST2, O_NONE, P_none }, /* 0969 */ { UD_Ifsubr, O_ST0, O_ST3, O_NONE, P_none }, /* 0970 */ { UD_Ifsubr, O_ST0, O_ST4, O_NONE, P_none }, /* 0971 */ { UD_Ifsubr, O_ST0, O_ST5, O_NONE, P_none }, /* 0972 */ { UD_Ifsubr, O_ST0, O_ST6, O_NONE, P_none }, /* 0973 */ { UD_Ifsubr, O_ST0, O_ST7, O_NONE, P_none }, /* 0974 */ { UD_Ifdiv, O_ST0, O_ST0, O_NONE, P_none }, /* 0975 */ { UD_Ifdiv, O_ST0, O_ST1, O_NONE, P_none }, /* 0976 */ { UD_Ifdiv, O_ST0, O_ST2, O_NONE, P_none }, /* 0977 */ { UD_Ifdiv, O_ST0, O_ST3, O_NONE, P_none }, /* 0978 */ { UD_Ifdiv, O_ST0, O_ST4, O_NONE, P_none }, /* 0979 */ { UD_Ifdiv, O_ST0, O_ST5, O_NONE, P_none }, /* 0980 */ { UD_Ifdiv, O_ST0, O_ST6, O_NONE, P_none }, /* 0981 */ { UD_Ifdiv, O_ST0, O_ST7, O_NONE, P_none }, /* 0982 */ { UD_Ifdivr, O_ST0, O_ST0, O_NONE, P_none }, /* 0983 */ { UD_Ifdivr, O_ST0, O_ST1, O_NONE, P_none }, /* 0984 */ { UD_Ifdivr, O_ST0, O_ST2, O_NONE, P_none }, /* 0985 */ { UD_Ifdivr, O_ST0, O_ST3, O_NONE, P_none }, /* 0986 */ { UD_Ifdivr, O_ST0, O_ST4, O_NONE, P_none }, /* 0987 */ { UD_Ifdivr, O_ST0, O_ST5, O_NONE, P_none }, /* 0988 */ { UD_Ifdivr, O_ST0, O_ST6, O_NONE, P_none }, /* 0989 */ { UD_Ifdivr, O_ST0, O_ST7, O_NONE, P_none }, /* 0990 */ { UD_Ifld, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0991 */ { UD_Ifst, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0992 */ { UD_Ifstp, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0993 */ { UD_Ifldenv, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0994 */ { UD_Ifldcw, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0995 */ { UD_Ifnstenv, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0996 */ { UD_Ifnstcw, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 0997 */ { UD_Ifld, O_ST0, O_NONE, O_NONE, P_none }, /* 0998 */ { UD_Ifld, O_ST1, O_NONE, O_NONE, P_none }, /* 0999 */ { UD_Ifld, O_ST2, O_NONE, O_NONE, P_none }, /* 1000 */ { UD_Ifld, O_ST3, O_NONE, O_NONE, P_none }, /* 1001 */ { UD_Ifld, O_ST4, O_NONE, O_NONE, P_none }, /* 1002 */ { UD_Ifld, O_ST5, O_NONE, O_NONE, P_none }, /* 1003 */ { UD_Ifld, O_ST6, O_NONE, O_NONE, P_none }, /* 1004 */ { UD_Ifld, O_ST7, O_NONE, O_NONE, P_none }, /* 1005 */ { UD_Ifxch, O_ST0, O_ST0, O_NONE, P_none }, /* 1006 */ { UD_Ifxch, O_ST0, O_ST1, O_NONE, P_none }, /* 1007 */ { UD_Ifxch, O_ST0, O_ST2, O_NONE, P_none }, /* 1008 */ { UD_Ifxch, O_ST0, O_ST3, O_NONE, P_none }, /* 1009 */ { UD_Ifxch, O_ST0, O_ST4, O_NONE, P_none }, /* 1010 */ { UD_Ifxch, O_ST0, O_ST5, O_NONE, P_none }, /* 1011 */ { UD_Ifxch, O_ST0, O_ST6, O_NONE, P_none }, /* 1012 */ { UD_Ifxch, O_ST0, O_ST7, O_NONE, P_none }, /* 1013 */ { UD_Ifnop, O_NONE, O_NONE, O_NONE, P_none }, /* 1014 */ { UD_Ifstp1, O_ST0, O_NONE, O_NONE, P_none }, /* 1015 */ { UD_Ifstp1, O_ST1, O_NONE, O_NONE, P_none }, /* 1016 */ { UD_Ifstp1, O_ST2, O_NONE, O_NONE, P_none }, /* 1017 */ { UD_Ifstp1, O_ST3, O_NONE, O_NONE, P_none }, /* 1018 */ { UD_Ifstp1, O_ST4, O_NONE, O_NONE, P_none }, /* 1019 */ { UD_Ifstp1, O_ST5, O_NONE, O_NONE, P_none }, /* 1020 */ { UD_Ifstp1, O_ST6, O_NONE, O_NONE, P_none }, /* 1021 */ { UD_Ifstp1, O_ST7, O_NONE, O_NONE, P_none }, /* 1022 */ { UD_Ifchs, O_NONE, O_NONE, O_NONE, P_none }, /* 1023 */ { UD_Ifabs, O_NONE, O_NONE, O_NONE, P_none }, /* 1024 */ { UD_Iftst, O_NONE, O_NONE, O_NONE, P_none }, /* 1025 */ { UD_Ifxam, O_NONE, O_NONE, O_NONE, P_none }, /* 1026 */ { UD_Ifld1, O_NONE, O_NONE, O_NONE, P_none }, /* 1027 */ { UD_Ifldl2t, O_NONE, O_NONE, O_NONE, P_none }, /* 1028 */ { UD_Ifldl2e, O_NONE, O_NONE, O_NONE, P_none }, /* 1029 */ { UD_Ifldpi, O_NONE, O_NONE, O_NONE, P_none }, /* 1030 */ { UD_Ifldlg2, O_NONE, O_NONE, O_NONE, P_none }, /* 1031 */ { UD_Ifldln2, O_NONE, O_NONE, O_NONE, P_none }, /* 1032 */ { UD_Ifldz, O_NONE, O_NONE, O_NONE, P_none }, /* 1033 */ { UD_If2xm1, O_NONE, O_NONE, O_NONE, P_none }, /* 1034 */ { UD_Ifyl2x, O_NONE, O_NONE, O_NONE, P_none }, /* 1035 */ { UD_Ifptan, O_NONE, O_NONE, O_NONE, P_none }, /* 1036 */ { UD_Ifpatan, O_NONE, O_NONE, O_NONE, P_none }, /* 1037 */ { UD_Ifxtract, O_NONE, O_NONE, O_NONE, P_none }, /* 1038 */ { UD_Ifprem1, O_NONE, O_NONE, O_NONE, P_none }, /* 1039 */ { UD_Ifdecstp, O_NONE, O_NONE, O_NONE, P_none }, /* 1040 */ { UD_Ifincstp, O_NONE, O_NONE, O_NONE, P_none }, /* 1041 */ { UD_Ifprem, O_NONE, O_NONE, O_NONE, P_none }, /* 1042 */ { UD_Ifyl2xp1, O_NONE, O_NONE, O_NONE, P_none }, /* 1043 */ { UD_Ifsqrt, O_NONE, O_NONE, O_NONE, P_none }, /* 1044 */ { UD_Ifsincos, O_NONE, O_NONE, O_NONE, P_none }, /* 1045 */ { UD_Ifrndint, O_NONE, O_NONE, O_NONE, P_none }, /* 1046 */ { UD_Ifscale, O_NONE, O_NONE, O_NONE, P_none }, /* 1047 */ { UD_Ifsin, O_NONE, O_NONE, O_NONE, P_none }, /* 1048 */ { UD_Ifcos, O_NONE, O_NONE, O_NONE, P_none }, /* 1049 */ { UD_Ifiadd, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1050 */ { UD_Ifimul, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1051 */ { UD_Ificom, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1052 */ { UD_Ificomp, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1053 */ { UD_Ifisub, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1054 */ { UD_Ifisubr, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1055 */ { UD_Ifidiv, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1056 */ { UD_Ifidivr, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1057 */ { UD_Ifcmovb, O_ST0, O_ST0, O_NONE, P_none }, /* 1058 */ { UD_Ifcmovb, O_ST0, O_ST1, O_NONE, P_none }, /* 1059 */ { UD_Ifcmovb, O_ST0, O_ST2, O_NONE, P_none }, /* 1060 */ { UD_Ifcmovb, O_ST0, O_ST3, O_NONE, P_none }, /* 1061 */ { UD_Ifcmovb, O_ST0, O_ST4, O_NONE, P_none }, /* 1062 */ { UD_Ifcmovb, O_ST0, O_ST5, O_NONE, P_none }, /* 1063 */ { UD_Ifcmovb, O_ST0, O_ST6, O_NONE, P_none }, /* 1064 */ { UD_Ifcmovb, O_ST0, O_ST7, O_NONE, P_none }, /* 1065 */ { UD_Ifcmove, O_ST0, O_ST0, O_NONE, P_none }, /* 1066 */ { UD_Ifcmove, O_ST0, O_ST1, O_NONE, P_none }, /* 1067 */ { UD_Ifcmove, O_ST0, O_ST2, O_NONE, P_none }, /* 1068 */ { UD_Ifcmove, O_ST0, O_ST3, O_NONE, P_none }, /* 1069 */ { UD_Ifcmove, O_ST0, O_ST4, O_NONE, P_none }, /* 1070 */ { UD_Ifcmove, O_ST0, O_ST5, O_NONE, P_none }, /* 1071 */ { UD_Ifcmove, O_ST0, O_ST6, O_NONE, P_none }, /* 1072 */ { UD_Ifcmove, O_ST0, O_ST7, O_NONE, P_none }, /* 1073 */ { UD_Ifcmovbe, O_ST0, O_ST0, O_NONE, P_none }, /* 1074 */ { UD_Ifcmovbe, O_ST0, O_ST1, O_NONE, P_none }, /* 1075 */ { UD_Ifcmovbe, O_ST0, O_ST2, O_NONE, P_none }, /* 1076 */ { UD_Ifcmovbe, O_ST0, O_ST3, O_NONE, P_none }, /* 1077 */ { UD_Ifcmovbe, O_ST0, O_ST4, O_NONE, P_none }, /* 1078 */ { UD_Ifcmovbe, O_ST0, O_ST5, O_NONE, P_none }, /* 1079 */ { UD_Ifcmovbe, O_ST0, O_ST6, O_NONE, P_none }, /* 1080 */ { UD_Ifcmovbe, O_ST0, O_ST7, O_NONE, P_none }, /* 1081 */ { UD_Ifcmovu, O_ST0, O_ST0, O_NONE, P_none }, /* 1082 */ { UD_Ifcmovu, O_ST0, O_ST1, O_NONE, P_none }, /* 1083 */ { UD_Ifcmovu, O_ST0, O_ST2, O_NONE, P_none }, /* 1084 */ { UD_Ifcmovu, O_ST0, O_ST3, O_NONE, P_none }, /* 1085 */ { UD_Ifcmovu, O_ST0, O_ST4, O_NONE, P_none }, /* 1086 */ { UD_Ifcmovu, O_ST0, O_ST5, O_NONE, P_none }, /* 1087 */ { UD_Ifcmovu, O_ST0, O_ST6, O_NONE, P_none }, /* 1088 */ { UD_Ifcmovu, O_ST0, O_ST7, O_NONE, P_none }, /* 1089 */ { UD_Ifucompp, O_NONE, O_NONE, O_NONE, P_none }, /* 1090 */ { UD_Ifild, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1091 */ { UD_Ifisttp, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1092 */ { UD_Ifist, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1093 */ { UD_Ifistp, O_Md, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1094 */ { UD_Ifld, O_Mt, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1095 */ { UD_Ifstp, O_Mt, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1096 */ { UD_Ifcmovnb, O_ST0, O_ST0, O_NONE, P_none }, /* 1097 */ { UD_Ifcmovnb, O_ST0, O_ST1, O_NONE, P_none }, /* 1098 */ { UD_Ifcmovnb, O_ST0, O_ST2, O_NONE, P_none }, /* 1099 */ { UD_Ifcmovnb, O_ST0, O_ST3, O_NONE, P_none }, /* 1100 */ { UD_Ifcmovnb, O_ST0, O_ST4, O_NONE, P_none }, /* 1101 */ { UD_Ifcmovnb, O_ST0, O_ST5, O_NONE, P_none }, /* 1102 */ { UD_Ifcmovnb, O_ST0, O_ST6, O_NONE, P_none }, /* 1103 */ { UD_Ifcmovnb, O_ST0, O_ST7, O_NONE, P_none }, /* 1104 */ { UD_Ifcmovne, O_ST0, O_ST0, O_NONE, P_none }, /* 1105 */ { UD_Ifcmovne, O_ST0, O_ST1, O_NONE, P_none }, /* 1106 */ { UD_Ifcmovne, O_ST0, O_ST2, O_NONE, P_none }, /* 1107 */ { UD_Ifcmovne, O_ST0, O_ST3, O_NONE, P_none }, /* 1108 */ { UD_Ifcmovne, O_ST0, O_ST4, O_NONE, P_none }, /* 1109 */ { UD_Ifcmovne, O_ST0, O_ST5, O_NONE, P_none }, /* 1110 */ { UD_Ifcmovne, O_ST0, O_ST6, O_NONE, P_none }, /* 1111 */ { UD_Ifcmovne, O_ST0, O_ST7, O_NONE, P_none }, /* 1112 */ { UD_Ifcmovnbe, O_ST0, O_ST0, O_NONE, P_none }, /* 1113 */ { UD_Ifcmovnbe, O_ST0, O_ST1, O_NONE, P_none }, /* 1114 */ { UD_Ifcmovnbe, O_ST0, O_ST2, O_NONE, P_none }, /* 1115 */ { UD_Ifcmovnbe, O_ST0, O_ST3, O_NONE, P_none }, /* 1116 */ { UD_Ifcmovnbe, O_ST0, O_ST4, O_NONE, P_none }, /* 1117 */ { UD_Ifcmovnbe, O_ST0, O_ST5, O_NONE, P_none }, /* 1118 */ { UD_Ifcmovnbe, O_ST0, O_ST6, O_NONE, P_none }, /* 1119 */ { UD_Ifcmovnbe, O_ST0, O_ST7, O_NONE, P_none }, /* 1120 */ { UD_Ifcmovnu, O_ST0, O_ST0, O_NONE, P_none }, /* 1121 */ { UD_Ifcmovnu, O_ST0, O_ST1, O_NONE, P_none }, /* 1122 */ { UD_Ifcmovnu, O_ST0, O_ST2, O_NONE, P_none }, /* 1123 */ { UD_Ifcmovnu, O_ST0, O_ST3, O_NONE, P_none }, /* 1124 */ { UD_Ifcmovnu, O_ST0, O_ST4, O_NONE, P_none }, /* 1125 */ { UD_Ifcmovnu, O_ST0, O_ST5, O_NONE, P_none }, /* 1126 */ { UD_Ifcmovnu, O_ST0, O_ST6, O_NONE, P_none }, /* 1127 */ { UD_Ifcmovnu, O_ST0, O_ST7, O_NONE, P_none }, /* 1128 */ { UD_Ifclex, O_NONE, O_NONE, O_NONE, P_none }, /* 1129 */ { UD_Ifninit, O_NONE, O_NONE, O_NONE, P_none }, /* 1130 */ { UD_Ifucomi, O_ST0, O_ST0, O_NONE, P_none }, /* 1131 */ { UD_Ifucomi, O_ST0, O_ST1, O_NONE, P_none }, /* 1132 */ { UD_Ifucomi, O_ST0, O_ST2, O_NONE, P_none }, /* 1133 */ { UD_Ifucomi, O_ST0, O_ST3, O_NONE, P_none }, /* 1134 */ { UD_Ifucomi, O_ST0, O_ST4, O_NONE, P_none }, /* 1135 */ { UD_Ifucomi, O_ST0, O_ST5, O_NONE, P_none }, /* 1136 */ { UD_Ifucomi, O_ST0, O_ST6, O_NONE, P_none }, /* 1137 */ { UD_Ifucomi, O_ST0, O_ST7, O_NONE, P_none }, /* 1138 */ { UD_Ifcomi, O_ST0, O_ST0, O_NONE, P_none }, /* 1139 */ { UD_Ifcomi, O_ST0, O_ST1, O_NONE, P_none }, /* 1140 */ { UD_Ifcomi, O_ST0, O_ST2, O_NONE, P_none }, /* 1141 */ { UD_Ifcomi, O_ST0, O_ST3, O_NONE, P_none }, /* 1142 */ { UD_Ifcomi, O_ST0, O_ST4, O_NONE, P_none }, /* 1143 */ { UD_Ifcomi, O_ST0, O_ST5, O_NONE, P_none }, /* 1144 */ { UD_Ifcomi, O_ST0, O_ST6, O_NONE, P_none }, /* 1145 */ { UD_Ifcomi, O_ST0, O_ST7, O_NONE, P_none }, /* 1146 */ { UD_Ifadd, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1147 */ { UD_Ifmul, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1148 */ { UD_Ifcom, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1149 */ { UD_Ifcomp, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1150 */ { UD_Ifsub, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1151 */ { UD_Ifsubr, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1152 */ { UD_Ifdiv, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1153 */ { UD_Ifdivr, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1154 */ { UD_Ifadd, O_ST0, O_ST0, O_NONE, P_none }, /* 1155 */ { UD_Ifadd, O_ST1, O_ST0, O_NONE, P_none }, /* 1156 */ { UD_Ifadd, O_ST2, O_ST0, O_NONE, P_none }, /* 1157 */ { UD_Ifadd, O_ST3, O_ST0, O_NONE, P_none }, /* 1158 */ { UD_Ifadd, O_ST4, O_ST0, O_NONE, P_none }, /* 1159 */ { UD_Ifadd, O_ST5, O_ST0, O_NONE, P_none }, /* 1160 */ { UD_Ifadd, O_ST6, O_ST0, O_NONE, P_none }, /* 1161 */ { UD_Ifadd, O_ST7, O_ST0, O_NONE, P_none }, /* 1162 */ { UD_Ifmul, O_ST0, O_ST0, O_NONE, P_none }, /* 1163 */ { UD_Ifmul, O_ST1, O_ST0, O_NONE, P_none }, /* 1164 */ { UD_Ifmul, O_ST2, O_ST0, O_NONE, P_none }, /* 1165 */ { UD_Ifmul, O_ST3, O_ST0, O_NONE, P_none }, /* 1166 */ { UD_Ifmul, O_ST4, O_ST0, O_NONE, P_none }, /* 1167 */ { UD_Ifmul, O_ST5, O_ST0, O_NONE, P_none }, /* 1168 */ { UD_Ifmul, O_ST6, O_ST0, O_NONE, P_none }, /* 1169 */ { UD_Ifmul, O_ST7, O_ST0, O_NONE, P_none }, /* 1170 */ { UD_Ifcom2, O_ST0, O_NONE, O_NONE, P_none }, /* 1171 */ { UD_Ifcom2, O_ST1, O_NONE, O_NONE, P_none }, /* 1172 */ { UD_Ifcom2, O_ST2, O_NONE, O_NONE, P_none }, /* 1173 */ { UD_Ifcom2, O_ST3, O_NONE, O_NONE, P_none }, /* 1174 */ { UD_Ifcom2, O_ST4, O_NONE, O_NONE, P_none }, /* 1175 */ { UD_Ifcom2, O_ST5, O_NONE, O_NONE, P_none }, /* 1176 */ { UD_Ifcom2, O_ST6, O_NONE, O_NONE, P_none }, /* 1177 */ { UD_Ifcom2, O_ST7, O_NONE, O_NONE, P_none }, /* 1178 */ { UD_Ifcomp3, O_ST0, O_NONE, O_NONE, P_none }, /* 1179 */ { UD_Ifcomp3, O_ST1, O_NONE, O_NONE, P_none }, /* 1180 */ { UD_Ifcomp3, O_ST2, O_NONE, O_NONE, P_none }, /* 1181 */ { UD_Ifcomp3, O_ST3, O_NONE, O_NONE, P_none }, /* 1182 */ { UD_Ifcomp3, O_ST4, O_NONE, O_NONE, P_none }, /* 1183 */ { UD_Ifcomp3, O_ST5, O_NONE, O_NONE, P_none }, /* 1184 */ { UD_Ifcomp3, O_ST6, O_NONE, O_NONE, P_none }, /* 1185 */ { UD_Ifcomp3, O_ST7, O_NONE, O_NONE, P_none }, /* 1186 */ { UD_Ifsubr, O_ST0, O_ST0, O_NONE, P_none }, /* 1187 */ { UD_Ifsubr, O_ST1, O_ST0, O_NONE, P_none }, /* 1188 */ { UD_Ifsubr, O_ST2, O_ST0, O_NONE, P_none }, /* 1189 */ { UD_Ifsubr, O_ST3, O_ST0, O_NONE, P_none }, /* 1190 */ { UD_Ifsubr, O_ST4, O_ST0, O_NONE, P_none }, /* 1191 */ { UD_Ifsubr, O_ST5, O_ST0, O_NONE, P_none }, /* 1192 */ { UD_Ifsubr, O_ST6, O_ST0, O_NONE, P_none }, /* 1193 */ { UD_Ifsubr, O_ST7, O_ST0, O_NONE, P_none }, /* 1194 */ { UD_Ifsub, O_ST0, O_ST0, O_NONE, P_none }, /* 1195 */ { UD_Ifsub, O_ST1, O_ST0, O_NONE, P_none }, /* 1196 */ { UD_Ifsub, O_ST2, O_ST0, O_NONE, P_none }, /* 1197 */ { UD_Ifsub, O_ST3, O_ST0, O_NONE, P_none }, /* 1198 */ { UD_Ifsub, O_ST4, O_ST0, O_NONE, P_none }, /* 1199 */ { UD_Ifsub, O_ST5, O_ST0, O_NONE, P_none }, /* 1200 */ { UD_Ifsub, O_ST6, O_ST0, O_NONE, P_none }, /* 1201 */ { UD_Ifsub, O_ST7, O_ST0, O_NONE, P_none }, /* 1202 */ { UD_Ifdivr, O_ST0, O_ST0, O_NONE, P_none }, /* 1203 */ { UD_Ifdivr, O_ST1, O_ST0, O_NONE, P_none }, /* 1204 */ { UD_Ifdivr, O_ST2, O_ST0, O_NONE, P_none }, /* 1205 */ { UD_Ifdivr, O_ST3, O_ST0, O_NONE, P_none }, /* 1206 */ { UD_Ifdivr, O_ST4, O_ST0, O_NONE, P_none }, /* 1207 */ { UD_Ifdivr, O_ST5, O_ST0, O_NONE, P_none }, /* 1208 */ { UD_Ifdivr, O_ST6, O_ST0, O_NONE, P_none }, /* 1209 */ { UD_Ifdivr, O_ST7, O_ST0, O_NONE, P_none }, /* 1210 */ { UD_Ifdiv, O_ST0, O_ST0, O_NONE, P_none }, /* 1211 */ { UD_Ifdiv, O_ST1, O_ST0, O_NONE, P_none }, /* 1212 */ { UD_Ifdiv, O_ST2, O_ST0, O_NONE, P_none }, /* 1213 */ { UD_Ifdiv, O_ST3, O_ST0, O_NONE, P_none }, /* 1214 */ { UD_Ifdiv, O_ST4, O_ST0, O_NONE, P_none }, /* 1215 */ { UD_Ifdiv, O_ST5, O_ST0, O_NONE, P_none }, /* 1216 */ { UD_Ifdiv, O_ST6, O_ST0, O_NONE, P_none }, /* 1217 */ { UD_Ifdiv, O_ST7, O_ST0, O_NONE, P_none }, /* 1218 */ { UD_Ifld, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1219 */ { UD_Ifisttp, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1220 */ { UD_Ifst, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1221 */ { UD_Ifstp, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1222 */ { UD_Ifrstor, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1223 */ { UD_Ifnsave, O_M, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1224 */ { UD_Ifnstsw, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1225 */ { UD_Iffree, O_ST0, O_NONE, O_NONE, P_none }, /* 1226 */ { UD_Iffree, O_ST1, O_NONE, O_NONE, P_none }, /* 1227 */ { UD_Iffree, O_ST2, O_NONE, O_NONE, P_none }, /* 1228 */ { UD_Iffree, O_ST3, O_NONE, O_NONE, P_none }, /* 1229 */ { UD_Iffree, O_ST4, O_NONE, O_NONE, P_none }, /* 1230 */ { UD_Iffree, O_ST5, O_NONE, O_NONE, P_none }, /* 1231 */ { UD_Iffree, O_ST6, O_NONE, O_NONE, P_none }, /* 1232 */ { UD_Iffree, O_ST7, O_NONE, O_NONE, P_none }, /* 1233 */ { UD_Ifxch4, O_ST0, O_NONE, O_NONE, P_none }, /* 1234 */ { UD_Ifxch4, O_ST1, O_NONE, O_NONE, P_none }, /* 1235 */ { UD_Ifxch4, O_ST2, O_NONE, O_NONE, P_none }, /* 1236 */ { UD_Ifxch4, O_ST3, O_NONE, O_NONE, P_none }, /* 1237 */ { UD_Ifxch4, O_ST4, O_NONE, O_NONE, P_none }, /* 1238 */ { UD_Ifxch4, O_ST5, O_NONE, O_NONE, P_none }, /* 1239 */ { UD_Ifxch4, O_ST6, O_NONE, O_NONE, P_none }, /* 1240 */ { UD_Ifxch4, O_ST7, O_NONE, O_NONE, P_none }, /* 1241 */ { UD_Ifst, O_ST0, O_NONE, O_NONE, P_none }, /* 1242 */ { UD_Ifst, O_ST1, O_NONE, O_NONE, P_none }, /* 1243 */ { UD_Ifst, O_ST2, O_NONE, O_NONE, P_none }, /* 1244 */ { UD_Ifst, O_ST3, O_NONE, O_NONE, P_none }, /* 1245 */ { UD_Ifst, O_ST4, O_NONE, O_NONE, P_none }, /* 1246 */ { UD_Ifst, O_ST5, O_NONE, O_NONE, P_none }, /* 1247 */ { UD_Ifst, O_ST6, O_NONE, O_NONE, P_none }, /* 1248 */ { UD_Ifst, O_ST7, O_NONE, O_NONE, P_none }, /* 1249 */ { UD_Ifstp, O_ST0, O_NONE, O_NONE, P_none }, /* 1250 */ { UD_Ifstp, O_ST1, O_NONE, O_NONE, P_none }, /* 1251 */ { UD_Ifstp, O_ST2, O_NONE, O_NONE, P_none }, /* 1252 */ { UD_Ifstp, O_ST3, O_NONE, O_NONE, P_none }, /* 1253 */ { UD_Ifstp, O_ST4, O_NONE, O_NONE, P_none }, /* 1254 */ { UD_Ifstp, O_ST5, O_NONE, O_NONE, P_none }, /* 1255 */ { UD_Ifstp, O_ST6, O_NONE, O_NONE, P_none }, /* 1256 */ { UD_Ifstp, O_ST7, O_NONE, O_NONE, P_none }, /* 1257 */ { UD_Ifucom, O_ST0, O_NONE, O_NONE, P_none }, /* 1258 */ { UD_Ifucom, O_ST1, O_NONE, O_NONE, P_none }, /* 1259 */ { UD_Ifucom, O_ST2, O_NONE, O_NONE, P_none }, /* 1260 */ { UD_Ifucom, O_ST3, O_NONE, O_NONE, P_none }, /* 1261 */ { UD_Ifucom, O_ST4, O_NONE, O_NONE, P_none }, /* 1262 */ { UD_Ifucom, O_ST5, O_NONE, O_NONE, P_none }, /* 1263 */ { UD_Ifucom, O_ST6, O_NONE, O_NONE, P_none }, /* 1264 */ { UD_Ifucom, O_ST7, O_NONE, O_NONE, P_none }, /* 1265 */ { UD_Ifucomp, O_ST0, O_NONE, O_NONE, P_none }, /* 1266 */ { UD_Ifucomp, O_ST1, O_NONE, O_NONE, P_none }, /* 1267 */ { UD_Ifucomp, O_ST2, O_NONE, O_NONE, P_none }, /* 1268 */ { UD_Ifucomp, O_ST3, O_NONE, O_NONE, P_none }, /* 1269 */ { UD_Ifucomp, O_ST4, O_NONE, O_NONE, P_none }, /* 1270 */ { UD_Ifucomp, O_ST5, O_NONE, O_NONE, P_none }, /* 1271 */ { UD_Ifucomp, O_ST6, O_NONE, O_NONE, P_none }, /* 1272 */ { UD_Ifucomp, O_ST7, O_NONE, O_NONE, P_none }, /* 1273 */ { UD_Ifiadd, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1274 */ { UD_Ifimul, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1275 */ { UD_Ificom, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1276 */ { UD_Ificomp, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1277 */ { UD_Ifisub, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1278 */ { UD_Ifisubr, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1279 */ { UD_Ifidiv, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1280 */ { UD_Ifidivr, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1281 */ { UD_Ifaddp, O_ST0, O_ST0, O_NONE, P_none }, /* 1282 */ { UD_Ifaddp, O_ST1, O_ST0, O_NONE, P_none }, /* 1283 */ { UD_Ifaddp, O_ST2, O_ST0, O_NONE, P_none }, /* 1284 */ { UD_Ifaddp, O_ST3, O_ST0, O_NONE, P_none }, /* 1285 */ { UD_Ifaddp, O_ST4, O_ST0, O_NONE, P_none }, /* 1286 */ { UD_Ifaddp, O_ST5, O_ST0, O_NONE, P_none }, /* 1287 */ { UD_Ifaddp, O_ST6, O_ST0, O_NONE, P_none }, /* 1288 */ { UD_Ifaddp, O_ST7, O_ST0, O_NONE, P_none }, /* 1289 */ { UD_Ifmulp, O_ST0, O_ST0, O_NONE, P_none }, /* 1290 */ { UD_Ifmulp, O_ST1, O_ST0, O_NONE, P_none }, /* 1291 */ { UD_Ifmulp, O_ST2, O_ST0, O_NONE, P_none }, /* 1292 */ { UD_Ifmulp, O_ST3, O_ST0, O_NONE, P_none }, /* 1293 */ { UD_Ifmulp, O_ST4, O_ST0, O_NONE, P_none }, /* 1294 */ { UD_Ifmulp, O_ST5, O_ST0, O_NONE, P_none }, /* 1295 */ { UD_Ifmulp, O_ST6, O_ST0, O_NONE, P_none }, /* 1296 */ { UD_Ifmulp, O_ST7, O_ST0, O_NONE, P_none }, /* 1297 */ { UD_Ifcomp5, O_ST0, O_NONE, O_NONE, P_none }, /* 1298 */ { UD_Ifcomp5, O_ST1, O_NONE, O_NONE, P_none }, /* 1299 */ { UD_Ifcomp5, O_ST2, O_NONE, O_NONE, P_none }, /* 1300 */ { UD_Ifcomp5, O_ST3, O_NONE, O_NONE, P_none }, /* 1301 */ { UD_Ifcomp5, O_ST4, O_NONE, O_NONE, P_none }, /* 1302 */ { UD_Ifcomp5, O_ST5, O_NONE, O_NONE, P_none }, /* 1303 */ { UD_Ifcomp5, O_ST6, O_NONE, O_NONE, P_none }, /* 1304 */ { UD_Ifcomp5, O_ST7, O_NONE, O_NONE, P_none }, /* 1305 */ { UD_Ifcompp, O_NONE, O_NONE, O_NONE, P_none }, /* 1306 */ { UD_Ifsubrp, O_ST0, O_ST0, O_NONE, P_none }, /* 1307 */ { UD_Ifsubrp, O_ST1, O_ST0, O_NONE, P_none }, /* 1308 */ { UD_Ifsubrp, O_ST2, O_ST0, O_NONE, P_none }, /* 1309 */ { UD_Ifsubrp, O_ST3, O_ST0, O_NONE, P_none }, /* 1310 */ { UD_Ifsubrp, O_ST4, O_ST0, O_NONE, P_none }, /* 1311 */ { UD_Ifsubrp, O_ST5, O_ST0, O_NONE, P_none }, /* 1312 */ { UD_Ifsubrp, O_ST6, O_ST0, O_NONE, P_none }, /* 1313 */ { UD_Ifsubrp, O_ST7, O_ST0, O_NONE, P_none }, /* 1314 */ { UD_Ifsubp, O_ST0, O_ST0, O_NONE, P_none }, /* 1315 */ { UD_Ifsubp, O_ST1, O_ST0, O_NONE, P_none }, /* 1316 */ { UD_Ifsubp, O_ST2, O_ST0, O_NONE, P_none }, /* 1317 */ { UD_Ifsubp, O_ST3, O_ST0, O_NONE, P_none }, /* 1318 */ { UD_Ifsubp, O_ST4, O_ST0, O_NONE, P_none }, /* 1319 */ { UD_Ifsubp, O_ST5, O_ST0, O_NONE, P_none }, /* 1320 */ { UD_Ifsubp, O_ST6, O_ST0, O_NONE, P_none }, /* 1321 */ { UD_Ifsubp, O_ST7, O_ST0, O_NONE, P_none }, /* 1322 */ { UD_Ifdivrp, O_ST0, O_ST0, O_NONE, P_none }, /* 1323 */ { UD_Ifdivrp, O_ST1, O_ST0, O_NONE, P_none }, /* 1324 */ { UD_Ifdivrp, O_ST2, O_ST0, O_NONE, P_none }, /* 1325 */ { UD_Ifdivrp, O_ST3, O_ST0, O_NONE, P_none }, /* 1326 */ { UD_Ifdivrp, O_ST4, O_ST0, O_NONE, P_none }, /* 1327 */ { UD_Ifdivrp, O_ST5, O_ST0, O_NONE, P_none }, /* 1328 */ { UD_Ifdivrp, O_ST6, O_ST0, O_NONE, P_none }, /* 1329 */ { UD_Ifdivrp, O_ST7, O_ST0, O_NONE, P_none }, /* 1330 */ { UD_Ifdivp, O_ST0, O_ST0, O_NONE, P_none }, /* 1331 */ { UD_Ifdivp, O_ST1, O_ST0, O_NONE, P_none }, /* 1332 */ { UD_Ifdivp, O_ST2, O_ST0, O_NONE, P_none }, /* 1333 */ { UD_Ifdivp, O_ST3, O_ST0, O_NONE, P_none }, /* 1334 */ { UD_Ifdivp, O_ST4, O_ST0, O_NONE, P_none }, /* 1335 */ { UD_Ifdivp, O_ST5, O_ST0, O_NONE, P_none }, /* 1336 */ { UD_Ifdivp, O_ST6, O_ST0, O_NONE, P_none }, /* 1337 */ { UD_Ifdivp, O_ST7, O_ST0, O_NONE, P_none }, /* 1338 */ { UD_Ifild, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1339 */ { UD_Ifisttp, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1340 */ { UD_Ifist, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1341 */ { UD_Ifistp, O_Mw, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1342 */ { UD_Ifbld, O_Mt, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1343 */ { UD_Ifild, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1344 */ { UD_Ifbstp, O_Mt, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1345 */ { UD_Ifistp, O_Mq, O_NONE, O_NONE, P_aso|P_rexr|P_rexx|P_rexb }, /* 1346 */ { UD_Iffreep, O_ST0, O_NONE, O_NONE, P_none }, /* 1347 */ { UD_Iffreep, O_ST1, O_NONE, O_NONE, P_none }, /* 1348 */ { UD_Iffreep, O_ST2, O_NONE, O_NONE, P_none }, /* 1349 */ { UD_Iffreep, O_ST3, O_NONE, O_NONE, P_none }, /* 1350 */ { UD_Iffreep, O_ST4, O_NONE, O_NONE, P_none }, /* 1351 */ { UD_Iffreep, O_ST5, O_NONE, O_NONE, P_none }, /* 1352 */ { UD_Iffreep, O_ST6, O_NONE, O_NONE, P_none }, /* 1353 */ { UD_Iffreep, O_ST7, O_NONE, O_NONE, P_none }, /* 1354 */ { UD_Ifxch7, O_ST0, O_NONE, O_NONE, P_none }, /* 1355 */ { UD_Ifxch7, O_ST1, O_NONE, O_NONE, P_none }, /* 1356 */ { UD_Ifxch7, O_ST2, O_NONE, O_NONE, P_none }, /* 1357 */ { UD_Ifxch7, O_ST3, O_NONE, O_NONE, P_none }, /* 1358 */ { UD_Ifxch7, O_ST4, O_NONE, O_NONE, P_none }, /* 1359 */ { UD_Ifxch7, O_ST5, O_NONE, O_NONE, P_none }, /* 1360 */ { UD_Ifxch7, O_ST6, O_NONE, O_NONE, P_none }, /* 1361 */ { UD_Ifxch7, O_ST7, O_NONE, O_NONE, P_none }, /* 1362 */ { UD_Ifstp8, O_ST0, O_NONE, O_NONE, P_none }, /* 1363 */ { UD_Ifstp8, O_ST1, O_NONE, O_NONE, P_none }, /* 1364 */ { UD_Ifstp8, O_ST2, O_NONE, O_NONE, P_none }, /* 1365 */ { UD_Ifstp8, O_ST3, O_NONE, O_NONE, P_none }, /* 1366 */ { UD_Ifstp8, O_ST4, O_NONE, O_NONE, P_none }, /* 1367 */ { UD_Ifstp8, O_ST5, O_NONE, O_NONE, P_none }, /* 1368 */ { UD_Ifstp8, O_ST6, O_NONE, O_NONE, P_none }, /* 1369 */ { UD_Ifstp8, O_ST7, O_NONE, O_NONE, P_none }, /* 1370 */ { UD_Ifstp9, O_ST0, O_NONE, O_NONE, P_none }, /* 1371 */ { UD_Ifstp9, O_ST1, O_NONE, O_NONE, P_none }, /* 1372 */ { UD_Ifstp9, O_ST2, O_NONE, O_NONE, P_none }, /* 1373 */ { UD_Ifstp9, O_ST3, O_NONE, O_NONE, P_none }, /* 1374 */ { UD_Ifstp9, O_ST4, O_NONE, O_NONE, P_none }, /* 1375 */ { UD_Ifstp9, O_ST5, O_NONE, O_NONE, P_none }, /* 1376 */ { UD_Ifstp9, O_ST6, O_NONE, O_NONE, P_none }, /* 1377 */ { UD_Ifstp9, O_ST7, O_NONE, O_NONE, P_none }, /* 1378 */ { UD_Ifnstsw, O_AX, O_NONE, O_NONE, P_none }, /* 1379 */ { UD_Ifucomip, O_ST0, O_ST0, O_NONE, P_none }, /* 1380 */ { UD_Ifucomip, O_ST0, O_ST1, O_NONE, P_none }, /* 1381 */ { UD_Ifucomip, O_ST0, O_ST2, O_NONE, P_none }, /* 1382 */ { UD_Ifucomip, O_ST0, O_ST3, O_NONE, P_none }, /* 1383 */ { UD_Ifucomip, O_ST0, O_ST4, O_NONE, P_none }, /* 1384 */ { UD_Ifucomip, O_ST0, O_ST5, O_NONE, P_none }, /* 1385 */ { UD_Ifucomip, O_ST0, O_ST6, O_NONE, P_none }, /* 1386 */ { UD_Ifucomip, O_ST0, O_ST7, O_NONE, P_none }, /* 1387 */ { UD_Ifcomip, O_ST0, O_ST0, O_NONE, P_none }, /* 1388 */ { UD_Ifcomip, O_ST0, O_ST1, O_NONE, P_none }, /* 1389 */ { UD_Ifcomip, O_ST0, O_ST2, O_NONE, P_none }, /* 1390 */ { UD_Ifcomip, O_ST0, O_ST3, O_NONE, P_none }, /* 1391 */ { UD_Ifcomip, O_ST0, O_ST4, O_NONE, P_none }, /* 1392 */ { UD_Ifcomip, O_ST0, O_ST5, O_NONE, P_none }, /* 1393 */ { UD_Ifcomip, O_ST0, O_ST6, O_NONE, P_none }, /* 1394 */ { UD_Ifcomip, O_ST0, O_ST7, O_NONE, P_none }, /* 1395 */ { UD_Iloopne, O_Jb, O_NONE, O_NONE, P_none }, /* 1396 */ { UD_Iloope, O_Jb, O_NONE, O_NONE, P_none }, /* 1397 */ { UD_Iloop, O_Jb, O_NONE, O_NONE, P_none }, /* 1398 */ { UD_Ijcxz, O_Jb, O_NONE, O_NONE, P_aso }, /* 1399 */ { UD_Ijecxz, O_Jb, O_NONE, O_NONE, P_aso }, /* 1400 */ { UD_Ijrcxz, O_Jb, O_NONE, O_NONE, P_aso }, /* 1401 */ { UD_Iin, O_AL, O_Ib, O_NONE, P_none }, /* 1402 */ { UD_Iin, O_eAX, O_Ib, O_NONE, P_oso }, /* 1403 */ { UD_Iout, O_Ib, O_AL, O_NONE, P_none }, /* 1404 */ { UD_Iout, O_Ib, O_eAX, O_NONE, P_oso }, /* 1405 */ { UD_Icall, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 1406 */ { UD_Ijmp, O_Jz, O_NONE, O_NONE, P_oso|P_def64 }, /* 1407 */ { UD_Ijmp, O_Av, O_NONE, O_NONE, P_oso }, /* 1408 */ { UD_Ijmp, O_Jb, O_NONE, O_NONE, P_def64 }, /* 1409 */ { UD_Iin, O_AL, O_DX, O_NONE, P_none }, /* 1410 */ { UD_Iin, O_eAX, O_DX, O_NONE, P_oso }, /* 1411 */ { UD_Iout, O_DX, O_AL, O_NONE, P_none }, /* 1412 */ { UD_Iout, O_DX, O_eAX, O_NONE, P_oso }, /* 1413 */ { UD_Ilock, O_NONE, O_NONE, O_NONE, P_none }, /* 1414 */ { UD_Iint1, O_NONE, O_NONE, O_NONE, P_none }, /* 1415 */ { UD_Irepne, O_NONE, O_NONE, O_NONE, P_none }, /* 1416 */ { UD_Irep, O_NONE, O_NONE, O_NONE, P_none }, /* 1417 */ { UD_Ihlt, O_NONE, O_NONE, O_NONE, P_none }, /* 1418 */ { UD_Icmc, O_NONE, O_NONE, O_NONE, P_none }, /* 1419 */ { UD_Itest, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1420 */ { UD_Itest, O_Eb, O_Ib, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1421 */ { UD_Inot, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1422 */ { UD_Ineg, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1423 */ { UD_Imul, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1424 */ { UD_Iimul, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1425 */ { UD_Idiv, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1426 */ { UD_Iidiv, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1427 */ { UD_Itest, O_Ev, O_sIz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1428 */ { UD_Itest, O_Ev, O_Iz, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1429 */ { UD_Inot, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1430 */ { UD_Ineg, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1431 */ { UD_Imul, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1432 */ { UD_Iimul, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1433 */ { UD_Idiv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1434 */ { UD_Iidiv, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1435 */ { UD_Iclc, O_NONE, O_NONE, O_NONE, P_none }, /* 1436 */ { UD_Istc, O_NONE, O_NONE, O_NONE, P_none }, /* 1437 */ { UD_Icli, O_NONE, O_NONE, O_NONE, P_none }, /* 1438 */ { UD_Isti, O_NONE, O_NONE, O_NONE, P_none }, /* 1439 */ { UD_Icld, O_NONE, O_NONE, O_NONE, P_none }, /* 1440 */ { UD_Istd, O_NONE, O_NONE, O_NONE, P_none }, /* 1441 */ { UD_Iinc, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1442 */ { UD_Idec, O_Eb, O_NONE, O_NONE, P_aso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1443 */ { UD_Iinc, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1444 */ { UD_Idec, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1445 */ { UD_Icall, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1446 */ { UD_Icall, O_Eq, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, /* 1447 */ { UD_Icall, O_Fv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1448 */ { UD_Ijmp, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, /* 1449 */ { UD_Ijmp, O_Fv, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb }, /* 1450 */ { UD_Ipush, O_Ev, O_NONE, O_NONE, P_aso|P_oso|P_rexw|P_rexr|P_rexx|P_rexb|P_def64 }, }; const char * ud_mnemonics_str[] = { "invalid", "3dnow", "none", "db", "pause", "aaa", "aad", "aam", "aas", "adc", "add", "addpd", "addps", "addsd", "addss", "and", "andpd", "andps", "andnpd", "andnps", "arpl", "movsxd", "bound", "bsf", "bsr", "bswap", "bt", "btc", "btr", "bts", "call", "cbw", "cwde", "cdqe", "clc", "cld", "clflush", "clgi", "cli", "clts", "cmc", "cmovo", "cmovno", "cmovb", "cmovae", "cmovz", "cmovnz", "cmovbe", "cmova", "cmovs", "cmovns", "cmovp", "cmovnp", "cmovl", "cmovge", "cmovle", "cmovg", "cmp", "cmppd", "cmpps", "cmpsb", "cmpsw", "cmpsd", "cmpsq", "cmpss", "cmpxchg", "cmpxchg8b", "cmpxchg16b", "comisd", "comiss", "cpuid", "cvtdq2pd", "cvtdq2ps", "cvtpd2dq", "cvtpd2pi", "cvtpd2ps", "cvtpi2ps", "cvtpi2pd", "cvtps2dq", "cvtps2pi", "cvtps2pd", "cvtsd2si", "cvtsd2ss", "cvtsi2ss", "cvtss2si", "cvtss2sd", "cvttpd2pi", "cvttpd2dq", "cvttps2dq", "cvttps2pi", "cvttsd2si", "cvtsi2sd", "cvttss2si", "cwd", "cdq", "cqo", "daa", "das", "dec", "div", "divpd", "divps", "divsd", "divss", "emms", "enter", "f2xm1", "fabs", "fadd", "faddp", "fbld", "fbstp", "fchs", "fclex", "fcmovb", "fcmove", "fcmovbe", "fcmovu", "fcmovnb", "fcmovne", "fcmovnbe", "fcmovnu", "fucomi", "fcom", "fcom2", "fcomp3", "fcomi", "fucomip", "fcomip", "fcomp", "fcomp5", "fcompp", "fcos", "fdecstp", "fdiv", "fdivp", "fdivr", "fdivrp", "femms", "ffree", "ffreep", "ficom", "ficomp", "fild", "fincstp", "fninit", "fiadd", "fidivr", "fidiv", "fisub", "fisubr", "fist", "fistp", "fisttp", "fld", "fld1", "fldl2t", "fldl2e", "fldpi", "fldlg2", "fldln2", "fldz", "fldcw", "fldenv", "fmul", "fmulp", "fimul", "fnop", "fpatan", "fprem", "fprem1", "fptan", "frndint", "frstor", "fnsave", "fscale", "fsin", "fsincos", "fsqrt", "fstp", "fstp1", "fstp8", "fstp9", "fst", "fnstcw", "fnstenv", "fnstsw", "fsub", "fsubp", "fsubr", "fsubrp", "ftst", "fucom", "fucomp", "fucompp", "fxam", "fxch", "fxch4", "fxch7", "fxrstor", "fxsave", "fxtract", "fyl2x", "fyl2xp1", "hlt", "idiv", "in", "imul", "inc", "insb", "insw", "insd", "int1", "int3", "int", "into", "invd", "invept", "invlpg", "invlpga", "invvpid", "iretw", "iretd", "iretq", "jo", "jno", "jb", "jae", "jz", "jnz", "jbe", "ja", "js", "jns", "jp", "jnp", "jl", "jge", "jle", "jg", "jcxz", "jecxz", "jrcxz", "jmp", "lahf", "lar", "lddqu", "ldmxcsr", "lds", "lea", "les", "lfs", "lgs", "lidt", "lss", "leave", "lfence", "lgdt", "lldt", "lmsw", "lock", "lodsb", "lodsw", "lodsd", "lodsq", "loopne", "loope", "loop", "lsl", "ltr", "maskmovq", "maxpd", "maxps", "maxsd", "maxss", "mfence", "minpd", "minps", "minsd", "minss", "monitor", "montmul", "mov", "movapd", "movaps", "movd", "movhpd", "movhps", "movlhps", "movlpd", "movlps", "movhlps", "movmskpd", "movmskps", "movntdq", "movnti", "movntpd", "movntps", "movntq", "movq", "movsb", "movsw", "movsd", "movsq", "movss", "movsx", "movupd", "movups", "movzx", "mul", "mulpd", "mulps", "mulsd", "mulss", "mwait", "neg", "nop", "not", "or", "orpd", "orps", "out", "outsb", "outsw", "outsd", "packsswb", "packssdw", "packuswb", "paddb", "paddw", "paddd", "paddsb", "paddsw", "paddusb", "paddusw", "pand", "pandn", "pavgb", "pavgw", "pcmpeqb", "pcmpeqw", "pcmpeqd", "pcmpgtb", "pcmpgtw", "pcmpgtd", "pextrb", "pextrd", "pextrq", "pextrw", "pinsrb", "pinsrw", "pinsrd", "pinsrq", "pmaddwd", "pmaxsw", "pmaxub", "pminsw", "pminub", "pmovmskb", "pmulhuw", "pmulhw", "pmullw", "pop", "popa", "popad", "popfw", "popfd", "popfq", "por", "prefetch", "prefetchnta", "prefetcht0", "prefetcht1", "prefetcht2", "psadbw", "pshufw", "psllw", "pslld", "psllq", "psraw", "psrad", "psrlw", "psrld", "psrlq", "psubb", "psubw", "psubd", "psubsb", "psubsw", "psubusb", "psubusw", "punpckhbw", "punpckhwd", "punpckhdq", "punpcklbw", "punpcklwd", "punpckldq", "pi2fw", "pi2fd", "pf2iw", "pf2id", "pfnacc", "pfpnacc", "pfcmpge", "pfmin", "pfrcp", "pfrsqrt", "pfsub", "pfadd", "pfcmpgt", "pfmax", "pfrcpit1", "pfrsqit1", "pfsubr", "pfacc", "pfcmpeq", "pfmul", "pfrcpit2", "pmulhrw", "pswapd", "pavgusb", "push", "pusha", "pushad", "pushfw", "pushfd", "pushfq", "pxor", "rcl", "rcr", "rol", "ror", "rcpps", "rcpss", "rdmsr", "rdpmc", "rdtsc", "rdtscp", "repne", "rep", "ret", "retf", "rsm", "rsqrtps", "rsqrtss", "sahf", "salc", "sar", "shl", "shr", "sbb", "scasb", "scasw", "scasd", "scasq", "seto", "setno", "setb", "setae", "setz", "setnz", "setbe", "seta", "sets", "setns", "setp", "setnp", "setl", "setge", "setle", "setg", "sfence", "sgdt", "shld", "shrd", "shufpd", "shufps", "sidt", "sldt", "smsw", "sqrtps", "sqrtpd", "sqrtsd", "sqrtss", "stc", "std", "stgi", "sti", "skinit", "stmxcsr", "stosb", "stosw", "stosd", "stosq", "str", "sub", "subpd", "subps", "subsd", "subss", "swapgs", "syscall", "sysenter", "sysexit", "sysret", "test", "ucomisd", "ucomiss", "ud2", "unpckhpd", "unpckhps", "unpcklps", "unpcklpd", "verr", "verw", "vmcall", "vmclear", "vmxon", "vmptrld", "vmptrst", "vmlaunch", "vmresume", "vmxoff", "vmread", "vmwrite", "vmrun", "vmmcall", "vmload", "vmsave", "wait", "wbinvd", "wrmsr", "xadd", "xchg", "xgetbv", "xlatb", "xor", "xorpd", "xorps", "xcryptecb", "xcryptcbc", "xcryptctr", "xcryptcfb", "xcryptofb", "xrstor", "xsave", "xsetbv", "xsha1", "xsha256", "xstore", "aesdec", "aesdeclast", "aesenc", "aesenclast", "aesimc", "aeskeygenassist", "pclmulqdq", "getsec", "movdqa", "maskmovdqu", "movdq2q", "movdqu", "movq2dq", "paddq", "psubq", "pmuludq", "pshufhw", "pshuflw", "pshufd", "pslldq", "psrldq", "punpckhqdq", "punpcklqdq", "addsubpd", "addsubps", "haddpd", "haddps", "hsubpd", "hsubps", "movddup", "movshdup", "movsldup", "pabsb", "pabsw", "pabsd", "pshufb", "phaddw", "phaddd", "phaddsw", "pmaddubsw", "phsubw", "phsubd", "phsubsw", "psignb", "psignd", "psignw", "pmulhrsw", "palignr", "pblendvb", "pmuldq", "pminsb", "pminsd", "pminuw", "pminud", "pmaxsb", "pmaxsd", "pmaxud", "pmaxuw", "pmulld", "phminposuw", "roundps", "roundpd", "roundss", "roundsd", "blendpd", "pblendw", "blendps", "blendvpd", "blendvps", "dpps", "dppd", "mpsadbw", "extractps", "insertps", "movntdqa", "packusdw", "pmovsxbw", "pmovsxbd", "pmovsxbq", "pmovsxwd", "pmovsxwq", "pmovsxdq", "pmovzxbw", "pmovzxbd", "pmovzxbq", "pmovzxwd", "pmovzxwq", "pmovzxdq", "pcmpeqq", "popcnt", "ptest", "pcmpestri", "pcmpestrm", "pcmpgtq", "pcmpistri", "pcmpistrm", "movbe", "crc32" }; ================================================ FILE: dis/itab.h ================================================ #ifndef UD_ITAB_H #define UD_ITAB_H /* itab.h -- generated by udis86:scripts/ud_itab.py, do no edit */ /* ud_table_type -- lookup table types (see decode.c) */ enum ud_table_type { UD_TAB__OPC_TABLE, UD_TAB__OPC_X87, UD_TAB__OPC_MOD, UD_TAB__OPC_VEX_M, UD_TAB__OPC_VEX_P, UD_TAB__OPC_RM, UD_TAB__OPC_VENDOR, UD_TAB__OPC_OSIZE, UD_TAB__OPC_MODE, UD_TAB__OPC_3DNOW, UD_TAB__OPC_REG, UD_TAB__OPC_ASIZE, UD_TAB__OPC_SSE }; /* ud_mnemonic -- mnemonic constants */ enum ud_mnemonic_code { UD_Iinvalid, UD_I3dnow, UD_Inone, UD_Idb, UD_Ipause, UD_Iaaa, UD_Iaad, UD_Iaam, UD_Iaas, UD_Iadc, UD_Iadd, UD_Iaddpd, UD_Iaddps, UD_Iaddsd, UD_Iaddss, UD_Iand, UD_Iandpd, UD_Iandps, UD_Iandnpd, UD_Iandnps, UD_Iarpl, UD_Imovsxd, UD_Ibound, UD_Ibsf, UD_Ibsr, UD_Ibswap, UD_Ibt, UD_Ibtc, UD_Ibtr, UD_Ibts, UD_Icall, UD_Icbw, UD_Icwde, UD_Icdqe, UD_Iclc, UD_Icld, UD_Iclflush, UD_Iclgi, UD_Icli, UD_Iclts, UD_Icmc, UD_Icmovo, UD_Icmovno, UD_Icmovb, UD_Icmovae, UD_Icmovz, UD_Icmovnz, UD_Icmovbe, UD_Icmova, UD_Icmovs, UD_Icmovns, UD_Icmovp, UD_Icmovnp, UD_Icmovl, UD_Icmovge, UD_Icmovle, UD_Icmovg, UD_Icmp, UD_Icmppd, UD_Icmpps, UD_Icmpsb, UD_Icmpsw, UD_Icmpsd, UD_Icmpsq, UD_Icmpss, UD_Icmpxchg, UD_Icmpxchg8b, UD_Icmpxchg16b, UD_Icomisd, UD_Icomiss, UD_Icpuid, UD_Icvtdq2pd, UD_Icvtdq2ps, UD_Icvtpd2dq, UD_Icvtpd2pi, UD_Icvtpd2ps, UD_Icvtpi2ps, UD_Icvtpi2pd, UD_Icvtps2dq, UD_Icvtps2pi, UD_Icvtps2pd, UD_Icvtsd2si, UD_Icvtsd2ss, UD_Icvtsi2ss, UD_Icvtss2si, UD_Icvtss2sd, UD_Icvttpd2pi, UD_Icvttpd2dq, UD_Icvttps2dq, UD_Icvttps2pi, UD_Icvttsd2si, UD_Icvtsi2sd, UD_Icvttss2si, UD_Icwd, UD_Icdq, UD_Icqo, UD_Idaa, UD_Idas, UD_Idec, UD_Idiv, UD_Idivpd, UD_Idivps, UD_Idivsd, UD_Idivss, UD_Iemms, UD_Ienter, UD_If2xm1, UD_Ifabs, UD_Ifadd, UD_Ifaddp, UD_Ifbld, UD_Ifbstp, UD_Ifchs, UD_Ifclex, UD_Ifcmovb, UD_Ifcmove, UD_Ifcmovbe, UD_Ifcmovu, UD_Ifcmovnb, UD_Ifcmovne, UD_Ifcmovnbe, UD_Ifcmovnu, UD_Ifucomi, UD_Ifcom, UD_Ifcom2, UD_Ifcomp3, UD_Ifcomi, UD_Ifucomip, UD_Ifcomip, UD_Ifcomp, UD_Ifcomp5, UD_Ifcompp, UD_Ifcos, UD_Ifdecstp, UD_Ifdiv, UD_Ifdivp, UD_Ifdivr, UD_Ifdivrp, UD_Ifemms, UD_Iffree, UD_Iffreep, UD_Ificom, UD_Ificomp, UD_Ifild, UD_Ifincstp, UD_Ifninit, UD_Ifiadd, UD_Ifidivr, UD_Ifidiv, UD_Ifisub, UD_Ifisubr, UD_Ifist, UD_Ifistp, UD_Ifisttp, UD_Ifld, UD_Ifld1, UD_Ifldl2t, UD_Ifldl2e, UD_Ifldpi, UD_Ifldlg2, UD_Ifldln2, UD_Ifldz, UD_Ifldcw, UD_Ifldenv, UD_Ifmul, UD_Ifmulp, UD_Ifimul, UD_Ifnop, UD_Ifpatan, UD_Ifprem, UD_Ifprem1, UD_Ifptan, UD_Ifrndint, UD_Ifrstor, UD_Ifnsave, UD_Ifscale, UD_Ifsin, UD_Ifsincos, UD_Ifsqrt, UD_Ifstp, UD_Ifstp1, UD_Ifstp8, UD_Ifstp9, UD_Ifst, UD_Ifnstcw, UD_Ifnstenv, UD_Ifnstsw, UD_Ifsub, UD_Ifsubp, UD_Ifsubr, UD_Ifsubrp, UD_Iftst, UD_Ifucom, UD_Ifucomp, UD_Ifucompp, UD_Ifxam, UD_Ifxch, UD_Ifxch4, UD_Ifxch7, UD_Ifxrstor, UD_Ifxsave, UD_Ifxtract, UD_Ifyl2x, UD_Ifyl2xp1, UD_Ihlt, UD_Iidiv, UD_Iin, UD_Iimul, UD_Iinc, UD_Iinsb, UD_Iinsw, UD_Iinsd, UD_Iint1, UD_Iint3, UD_Iint, UD_Iinto, UD_Iinvd, UD_Iinvept, UD_Iinvlpg, UD_Iinvlpga, UD_Iinvvpid, UD_Iiretw, UD_Iiretd, UD_Iiretq, UD_Ijo, UD_Ijno, UD_Ijb, UD_Ijae, UD_Ijz, UD_Ijnz, UD_Ijbe, UD_Ija, UD_Ijs, UD_Ijns, UD_Ijp, UD_Ijnp, UD_Ijl, UD_Ijge, UD_Ijle, UD_Ijg, UD_Ijcxz, UD_Ijecxz, UD_Ijrcxz, UD_Ijmp, UD_Ilahf, UD_Ilar, UD_Ilddqu, UD_Ildmxcsr, UD_Ilds, UD_Ilea, UD_Iles, UD_Ilfs, UD_Ilgs, UD_Ilidt, UD_Ilss, UD_Ileave, UD_Ilfence, UD_Ilgdt, UD_Illdt, UD_Ilmsw, UD_Ilock, UD_Ilodsb, UD_Ilodsw, UD_Ilodsd, UD_Ilodsq, UD_Iloopne, UD_Iloope, UD_Iloop, UD_Ilsl, UD_Iltr, UD_Imaskmovq, UD_Imaxpd, UD_Imaxps, UD_Imaxsd, UD_Imaxss, UD_Imfence, UD_Iminpd, UD_Iminps, UD_Iminsd, UD_Iminss, UD_Imonitor, UD_Imontmul, UD_Imov, UD_Imovapd, UD_Imovaps, UD_Imovd, UD_Imovhpd, UD_Imovhps, UD_Imovlhps, UD_Imovlpd, UD_Imovlps, UD_Imovhlps, UD_Imovmskpd, UD_Imovmskps, UD_Imovntdq, UD_Imovnti, UD_Imovntpd, UD_Imovntps, UD_Imovntq, UD_Imovq, UD_Imovsb, UD_Imovsw, UD_Imovsd, UD_Imovsq, UD_Imovss, UD_Imovsx, UD_Imovupd, UD_Imovups, UD_Imovzx, UD_Imul, UD_Imulpd, UD_Imulps, UD_Imulsd, UD_Imulss, UD_Imwait, UD_Ineg, UD_Inop, UD_Inot, UD_Ior, UD_Iorpd, UD_Iorps, UD_Iout, UD_Ioutsb, UD_Ioutsw, UD_Ioutsd, UD_Ipacksswb, UD_Ipackssdw, UD_Ipackuswb, UD_Ipaddb, UD_Ipaddw, UD_Ipaddd, UD_Ipaddsb, UD_Ipaddsw, UD_Ipaddusb, UD_Ipaddusw, UD_Ipand, UD_Ipandn, UD_Ipavgb, UD_Ipavgw, UD_Ipcmpeqb, UD_Ipcmpeqw, UD_Ipcmpeqd, UD_Ipcmpgtb, UD_Ipcmpgtw, UD_Ipcmpgtd, UD_Ipextrb, UD_Ipextrd, UD_Ipextrq, UD_Ipextrw, UD_Ipinsrb, UD_Ipinsrw, UD_Ipinsrd, UD_Ipinsrq, UD_Ipmaddwd, UD_Ipmaxsw, UD_Ipmaxub, UD_Ipminsw, UD_Ipminub, UD_Ipmovmskb, UD_Ipmulhuw, UD_Ipmulhw, UD_Ipmullw, UD_Ipop, UD_Ipopa, UD_Ipopad, UD_Ipopfw, UD_Ipopfd, UD_Ipopfq, UD_Ipor, UD_Iprefetch, UD_Iprefetchnta, UD_Iprefetcht0, UD_Iprefetcht1, UD_Iprefetcht2, UD_Ipsadbw, UD_Ipshufw, UD_Ipsllw, UD_Ipslld, UD_Ipsllq, UD_Ipsraw, UD_Ipsrad, UD_Ipsrlw, UD_Ipsrld, UD_Ipsrlq, UD_Ipsubb, UD_Ipsubw, UD_Ipsubd, UD_Ipsubsb, UD_Ipsubsw, UD_Ipsubusb, UD_Ipsubusw, UD_Ipunpckhbw, UD_Ipunpckhwd, UD_Ipunpckhdq, UD_Ipunpcklbw, UD_Ipunpcklwd, UD_Ipunpckldq, UD_Ipi2fw, UD_Ipi2fd, UD_Ipf2iw, UD_Ipf2id, UD_Ipfnacc, UD_Ipfpnacc, UD_Ipfcmpge, UD_Ipfmin, UD_Ipfrcp, UD_Ipfrsqrt, UD_Ipfsub, UD_Ipfadd, UD_Ipfcmpgt, UD_Ipfmax, UD_Ipfrcpit1, UD_Ipfrsqit1, UD_Ipfsubr, UD_Ipfacc, UD_Ipfcmpeq, UD_Ipfmul, UD_Ipfrcpit2, UD_Ipmulhrw, UD_Ipswapd, UD_Ipavgusb, UD_Ipush, UD_Ipusha, UD_Ipushad, UD_Ipushfw, UD_Ipushfd, UD_Ipushfq, UD_Ipxor, UD_Ircl, UD_Ircr, UD_Irol, UD_Iror, UD_Ircpps, UD_Ircpss, UD_Irdmsr, UD_Irdpmc, UD_Irdtsc, UD_Irdtscp, UD_Irepne, UD_Irep, UD_Iret, UD_Iretf, UD_Irsm, UD_Irsqrtps, UD_Irsqrtss, UD_Isahf, UD_Isalc, UD_Isar, UD_Ishl, UD_Ishr, UD_Isbb, UD_Iscasb, UD_Iscasw, UD_Iscasd, UD_Iscasq, UD_Iseto, UD_Isetno, UD_Isetb, UD_Isetae, UD_Isetz, UD_Isetnz, UD_Isetbe, UD_Iseta, UD_Isets, UD_Isetns, UD_Isetp, UD_Isetnp, UD_Isetl, UD_Isetge, UD_Isetle, UD_Isetg, UD_Isfence, UD_Isgdt, UD_Ishld, UD_Ishrd, UD_Ishufpd, UD_Ishufps, UD_Isidt, UD_Isldt, UD_Ismsw, UD_Isqrtps, UD_Isqrtpd, UD_Isqrtsd, UD_Isqrtss, UD_Istc, UD_Istd, UD_Istgi, UD_Isti, UD_Iskinit, UD_Istmxcsr, UD_Istosb, UD_Istosw, UD_Istosd, UD_Istosq, UD_Istr, UD_Isub, UD_Isubpd, UD_Isubps, UD_Isubsd, UD_Isubss, UD_Iswapgs, UD_Isyscall, UD_Isysenter, UD_Isysexit, UD_Isysret, UD_Itest, UD_Iucomisd, UD_Iucomiss, UD_Iud2, UD_Iunpckhpd, UD_Iunpckhps, UD_Iunpcklps, UD_Iunpcklpd, UD_Iverr, UD_Iverw, UD_Ivmcall, UD_Ivmclear, UD_Ivmxon, UD_Ivmptrld, UD_Ivmptrst, UD_Ivmlaunch, UD_Ivmresume, UD_Ivmxoff, UD_Ivmread, UD_Ivmwrite, UD_Ivmrun, UD_Ivmmcall, UD_Ivmload, UD_Ivmsave, UD_Iwait, UD_Iwbinvd, UD_Iwrmsr, UD_Ixadd, UD_Ixchg, UD_Ixgetbv, UD_Ixlatb, UD_Ixor, UD_Ixorpd, UD_Ixorps, UD_Ixcryptecb, UD_Ixcryptcbc, UD_Ixcryptctr, UD_Ixcryptcfb, UD_Ixcryptofb, UD_Ixrstor, UD_Ixsave, UD_Ixsetbv, UD_Ixsha1, UD_Ixsha256, UD_Ixstore, UD_Iaesdec, UD_Iaesdeclast, UD_Iaesenc, UD_Iaesenclast, UD_Iaesimc, UD_Iaeskeygenassist, UD_Ipclmulqdq, UD_Igetsec, UD_Imovdqa, UD_Imaskmovdqu, UD_Imovdq2q, UD_Imovdqu, UD_Imovq2dq, UD_Ipaddq, UD_Ipsubq, UD_Ipmuludq, UD_Ipshufhw, UD_Ipshuflw, UD_Ipshufd, UD_Ipslldq, UD_Ipsrldq, UD_Ipunpckhqdq, UD_Ipunpcklqdq, UD_Iaddsubpd, UD_Iaddsubps, UD_Ihaddpd, UD_Ihaddps, UD_Ihsubpd, UD_Ihsubps, UD_Imovddup, UD_Imovshdup, UD_Imovsldup, UD_Ipabsb, UD_Ipabsw, UD_Ipabsd, UD_Ipshufb, UD_Iphaddw, UD_Iphaddd, UD_Iphaddsw, UD_Ipmaddubsw, UD_Iphsubw, UD_Iphsubd, UD_Iphsubsw, UD_Ipsignb, UD_Ipsignd, UD_Ipsignw, UD_Ipmulhrsw, UD_Ipalignr, UD_Ipblendvb, UD_Ipmuldq, UD_Ipminsb, UD_Ipminsd, UD_Ipminuw, UD_Ipminud, UD_Ipmaxsb, UD_Ipmaxsd, UD_Ipmaxud, UD_Ipmaxuw, UD_Ipmulld, UD_Iphminposuw, UD_Iroundps, UD_Iroundpd, UD_Iroundss, UD_Iroundsd, UD_Iblendpd, UD_Ipblendw, UD_Iblendps, UD_Iblendvpd, UD_Iblendvps, UD_Idpps, UD_Idppd, UD_Impsadbw, UD_Iextractps, UD_Iinsertps, UD_Imovntdqa, UD_Ipackusdw, UD_Ipmovsxbw, UD_Ipmovsxbd, UD_Ipmovsxbq, UD_Ipmovsxwd, UD_Ipmovsxwq, UD_Ipmovsxdq, UD_Ipmovzxbw, UD_Ipmovzxbd, UD_Ipmovzxbq, UD_Ipmovzxwd, UD_Ipmovzxwq, UD_Ipmovzxdq, UD_Ipcmpeqq, UD_Ipopcnt, UD_Iptest, UD_Ipcmpestri, UD_Ipcmpestrm, UD_Ipcmpgtq, UD_Ipcmpistri, UD_Ipcmpistrm, UD_Imovbe, UD_Icrc32, UD_MAX_MNEMONIC_CODE } UD_ATTR_PACKED; extern const char * ud_mnemonics_str[]; #endif /* UD_ITAB_H */ ================================================ FILE: dis/main.c ================================================ #include #include #include "types.h" #include "extern.h" extern char far *get_ptr_1(char far* x,int b); #pragma aux get_ptr_1 = \ "mov ax,1401h" \ "int 0f0h" \ parm [cx dx] [bx] \ value [ds si] \ modify [ax]; char dsr[100]; char far * fpp = 0; char sz = 0; int im = 0; int ty = 0; int hook(struct ud_t *ud_obj) { char a1 = UD_EOI; if (!fpp) return UD_EOI; if (im >= sz) return UD_EOI; im++; a1 = fpp[im]; return a1; } int main(int argc,char** argv) { ud_t ud_obj; char rb = 0; if (!fpp) { fpp = get_ptr_1(0,0); if (!fpp) return UD_EOI; ty = fpp[0]; ud_set_mode(&ud_obj, ty); sz = fpp[1]; im = 1; } ud_init(&ud_obj); ud_set_input_hook(&ud_obj, hook); ud_set_syntax(&ud_obj, UD_SYN_INTEL); for (;;) { rb = ud_disassemble(&ud_obj); if (!rb) break; sprintf(dsr, "%s", ud_insn_asm(&ud_obj)); get_ptr_1(dsr, rb); break; } //printf("kkk"); // return 0; // ud_set_input_buffer(&ud_obj, "\x90\x90\x90\x90", 4); //ud_set_input_file(&ud_obj, stdin); // ud_set_mode(&ud_obj, 64); return 0; } ================================================ FILE: dis/stderr.txt ================================================ ================================================ FILE: dis/stdout.txt ================================================ DOSBox version 0.74-2 Copyright 2002-2018 DOSBox Team, published under GNU GPL. --- SDL_Init: Starting up with SDL windib video driver. Try to update your video card and directx drivers! CONFIG:Loading primary settings from config file G:\progs\dosbox\woa86FA.tmp "vga" is not a valid value for variable: machine. It might now be reset it to default value: svga_s3 Memory sizes above 31 MB are NOT recommended. Stick with the default values unless you are absolutely certain. MIDI:win32 selected Microsoft GS Wavetable Synth MIDI:Opened device:win32 ================================================ FILE: dis/syn-att.c ================================================ /* udis86 - libudis86/syn-att.c * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "types.h" #include "extern.h" #include "decode.h" #include "itab.h" #include "syn.h" #include "udint.h" /* ----------------------------------------------------------------------------- * opr_cast() - Prints an operand cast. * ----------------------------------------------------------------------------- */ static void opr_cast(struct ud* u, struct ud_operand* op) { switch(op->size) { case 16 : case 32 : ud_asmprintf(u, "*"); break; default: break; } } /* ----------------------------------------------------------------------------- * gen_operand() - Generates assembly output for each operand. * ----------------------------------------------------------------------------- */ static void gen_operand(struct ud* u, struct ud_operand* op) { switch(op->type) { case UD_OP_CONST: ud_asmprintf(u, "$0x%x", op->lval.udword); break; case UD_OP_REG: ud_asmprintf(u, "%%%s", ud_reg_tab[op->base - UD_R_AL]); break; case UD_OP_MEM: if (u->br_far) { opr_cast(u, op); } if (u->pfx_seg) { ud_asmprintf(u, "%%%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); } if (op->offset != 0) { ud_syn_print_mem_disp(u, op, 0); } if (op->base) { ud_asmprintf(u, "(%%%s", ud_reg_tab[op->base - UD_R_AL]); } if (op->index) { if (op->base) { ud_asmprintf(u, ","); } else { ud_asmprintf(u, "("); } ud_asmprintf(u, "%%%s", ud_reg_tab[op->index - UD_R_AL]); } if (op->scale) { ud_asmprintf(u, ",%d", op->scale); } if (op->base || op->index) { ud_asmprintf(u, ")"); } break; case UD_OP_IMM: ud_asmprintf(u, "$"); ud_syn_print_imm(u, op); break; case UD_OP_JIMM: ud_syn_print_addr(u, ud_syn_rel_target(u, op)); break; case UD_OP_PTR: switch (op->size) { case 32: ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg, op->lval.ptr.off & 0xFFFF); break; case 48: ud_asmprintf(u, "$0x%x, $0x%x", op->lval.ptr.seg, op->lval.ptr.off); break; } break; default: return; } } /* ============================================================================= * translates to AT&T syntax * ============================================================================= */ extern void ud_translate_att(struct ud *u) { int size = 0; int star = 0; /* check if P_OSO prefix is used */ if (! P_OSO(u->itab_entry->prefix) && u->pfx_opr) { switch (u->dis_mode) { case 16: ud_asmprintf(u, "o32 "); break; case 32: case 64: ud_asmprintf(u, "o16 "); break; } } /* check if P_ASO prefix was used */ if (! P_ASO(u->itab_entry->prefix) && u->pfx_adr) { switch (u->dis_mode) { case 16: ud_asmprintf(u, "a32 "); break; case 32: ud_asmprintf(u, "a16 "); break; case 64: ud_asmprintf(u, "a32 "); break; } } if (u->pfx_lock) ud_asmprintf(u, "lock "); if (u->pfx_rep) { ud_asmprintf(u, "rep "); } else if (u->pfx_rep) { ud_asmprintf(u, "repe "); } else if (u->pfx_repne) { ud_asmprintf(u, "repne "); } /* special instructions */ switch (u->mnemonic) { case UD_Iretf: ud_asmprintf(u, "lret "); break; case UD_Idb: ud_asmprintf(u, ".byte 0x%x", u->operand[0].lval.ubyte); return; case UD_Ijmp: case UD_Icall: if (u->br_far) ud_asmprintf(u, "l"); if (u->operand[0].type == UD_OP_REG) { star = 1; } ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); break; case UD_Ibound: case UD_Ienter: if (u->operand[0].type != UD_NONE) gen_operand(u, &u->operand[0]); if (u->operand[1].type != UD_NONE) { ud_asmprintf(u, ","); gen_operand(u, &u->operand[1]); } return; default: ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); } if (size == 8) ud_asmprintf(u, "b"); else if (size == 16) ud_asmprintf(u, "w"); else if (size == 64) ud_asmprintf(u, "q"); if (star) { ud_asmprintf(u, " *"); } else { ud_asmprintf(u, " "); } if (u->operand[2].type != UD_NONE) { gen_operand(u, &u->operand[2]); ud_asmprintf(u, ", "); } if (u->operand[1].type != UD_NONE) { gen_operand(u, &u->operand[1]); ud_asmprintf(u, ", "); } if (u->operand[0].type != UD_NONE) gen_operand(u, &u->operand[0]); } /* vim: set ts=2 sw=2 expandtab */ ================================================ FILE: dis/syn-intel.c ================================================ /* udis86 - libudis86/syn-intel.c * * Copyright (c) 2002-2013 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "types.h" #include "extern.h" #include "decode.h" #include "itab.h" #include "syn.h" #include "udint.h" /* ----------------------------------------------------------------------------- * opr_cast() - Prints an operand cast. * ----------------------------------------------------------------------------- */ static void opr_cast(struct ud* u, struct ud_operand* op) { if (u->br_far) { ud_asmprintf(u, "far "); } switch(op->size) { case 8: ud_asmprintf(u, "byte " ); break; case 16: ud_asmprintf(u, "word " ); break; case 32: ud_asmprintf(u, "dword "); break; case 64: ud_asmprintf(u, "qword "); break; case 80: ud_asmprintf(u, "tword "); break; default: break; } } /* ----------------------------------------------------------------------------- * gen_operand() - Generates assembly output for each operand. * ----------------------------------------------------------------------------- */ static void gen_operand(struct ud* u, struct ud_operand* op, int syn_cast) { switch(op->type) { case UD_OP_REG: ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]); break; case UD_OP_MEM: if (syn_cast) { opr_cast(u, op); } ud_asmprintf(u, "["); if (u->pfx_seg) { ud_asmprintf(u, "%s:", ud_reg_tab[u->pfx_seg - UD_R_AL]); } if (op->base) { ud_asmprintf(u, "%s", ud_reg_tab[op->base - UD_R_AL]); } if (op->index) { ud_asmprintf(u, "%s%s", op->base != UD_NONE? "+" : "", ud_reg_tab[op->index - UD_R_AL]); if (op->scale) { ud_asmprintf(u, "*%d", op->scale); } } if (op->offset != 0) { ud_syn_print_mem_disp(u, op, (op->base != UD_NONE || op->index != UD_NONE) ? 1 : 0); } ud_asmprintf(u, "]"); break; case UD_OP_IMM: ud_syn_print_imm(u, op); break; case UD_OP_JIMM: ud_syn_print_addr(u, ud_syn_rel_target(u, op)); break; case UD_OP_PTR: switch (op->size) { case 32: ud_asmprintf(u, "word 0x%x:0x%x", op->lval.ptr.seg, op->lval.ptr.off & 0xFFFF); break; case 48: ud_asmprintf(u, "dword 0x%x:0x%x", op->lval.ptr.seg, op->lval.ptr.off); break; } break; case UD_OP_CONST: if (syn_cast) opr_cast(u, op); ud_asmprintf(u, "%d", op->lval.udword); break; default: return; } } /* ============================================================================= * translates to intel syntax * ============================================================================= */ extern void ud_translate_intel(struct ud* u) { /* check if P_OSO prefix is used */ if (!P_OSO(u->itab_entry->prefix) && u->pfx_opr) { switch (u->dis_mode) { case 16: ud_asmprintf(u, "o32 "); break; case 32: case 64: ud_asmprintf(u, "o16 "); break; } } /* check if P_ASO prefix was used */ if (!P_ASO(u->itab_entry->prefix) && u->pfx_adr) { switch (u->dis_mode) { case 16: ud_asmprintf(u, "a32 "); break; case 32: ud_asmprintf(u, "a16 "); break; case 64: ud_asmprintf(u, "a32 "); break; } } if (u->pfx_seg && u->operand[0].type != UD_OP_MEM && u->operand[1].type != UD_OP_MEM ) { ud_asmprintf(u, "%s ", ud_reg_tab[u->pfx_seg - UD_R_AL]); } if (u->pfx_lock) { ud_asmprintf(u, "lock "); } if (u->pfx_rep) { ud_asmprintf(u, "rep "); } else if (u->pfx_repe) { ud_asmprintf(u, "repe "); } else if (u->pfx_repne) { ud_asmprintf(u, "repne "); } /* print the instruction mnemonic */ ud_asmprintf(u, "%s", ud_lookup_mnemonic(u->mnemonic)); if (u->operand[0].type != UD_NONE) { int cast = 0; ud_asmprintf(u, " "); if (u->operand[0].type == UD_OP_MEM) { if (u->operand[1].type == UD_OP_IMM || u->operand[1].type == UD_OP_CONST || u->operand[1].type == UD_NONE || (u->operand[0].size != u->operand[1].size && u->operand[1].type != UD_OP_REG)) { cast = 1; } else if (u->operand[1].type == UD_OP_REG && u->operand[1].base == UD_R_CL) { switch (u->mnemonic) { case UD_Ircl: case UD_Irol: case UD_Iror: case UD_Ircr: case UD_Ishl: case UD_Ishr: case UD_Isar: cast = 1; break; default: break; } } } gen_operand(u, &u->operand[0], cast); } if (u->operand[1].type != UD_NONE) { int cast = 0; ud_asmprintf(u, ", "); if (u->operand[1].type == UD_OP_MEM && u->operand[0].size != u->operand[1].size && !ud_opr_is_sreg(&u->operand[0])) { cast = 1; } gen_operand(u, &u->operand[1], cast); } if (u->operand[2].type != UD_NONE) { ud_asmprintf(u, ", "); gen_operand(u, &u->operand[2], 0); } } /* vim: set ts=2 sw=2 expandtab */ ================================================ FILE: dis/syn.c ================================================ /* udis86 - libudis86/syn.c * * Copyright (c) 2002-2013 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "types.h" #include "decode.h" #include "syn.h" #include "udint.h" /* ----------------------------------------------------------------------------- * Intel Register Table - Order Matters (types.h)! * ----------------------------------------------------------------------------- */ const char* ud_reg_tab[] = { "al", "cl", "dl", "bl", "ah", "ch", "dh", "bh", "spl", "bpl", "sil", "dil", "r8b", "r9b", "r10b", "r11b", "r12b", "r13b", "r14b", "r15b", "ax", "cx", "dx", "bx", "sp", "bp", "si", "di", "r8w", "r9w", "r10w", "r11w", "r12w", "r13w" , "r14w", "r15w", "eax", "ecx", "edx", "ebx", "esp", "ebp", "esi", "edi", "r8d", "r9d", "r10d", "r11d", "r12d", "r13d", "r14d", "r15d", "rax", "rcx", "rdx", "rbx", "rsp", "rbp", "rsi", "rdi", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "es", "cs", "ss", "ds", "fs", "gs", "cr0", "cr1", "cr2", "cr3", "cr4", "cr5", "cr6", "cr7", "cr8", "cr9", "cr10", "cr11", "cr12", "cr13", "cr14", "cr15", "dr0", "dr1", "dr2", "dr3", "dr4", "dr5", "dr6", "dr7", "dr8", "dr9", "dr10", "dr11", "dr12", "dr13", "dr14", "dr15", "mm0", "mm1", "mm2", "mm3", "mm4", "mm5", "mm6", "mm7", "st0", "st1", "st2", "st3", "st4", "st5", "st6", "st7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", "xmm8", "xmm9", "xmm10", "xmm11", "xmm12", "xmm13", "xmm14", "xmm15", "rip" }; uint64_t ud_syn_rel_target(struct ud *u, struct ud_operand *opr) { const uint64_t trunc_mask = 0xffffffffffffffffull >> (64 - u->opr_mode); switch (opr->size) { case 8 : return (u->pc + opr->lval.sbyte) & trunc_mask; case 16: return (u->pc + opr->lval.sword) & trunc_mask; case 32: return (u->pc + opr->lval.sdword) & trunc_mask; default: UD_ASSERT(!"invalid relative offset size."); return 0ull; } } /* * asmprintf * Printf style function for printing translated assembly * output. Returns the number of characters written and * moves the buffer pointer forward. On an overflow, * returns a negative number and truncates the output. */ int ud_asmprintf(struct ud *u, const char *fmt, ...) { int ret; int avail; va_list ap; va_start(ap, fmt); avail = u->asm_buf_size - u->asm_buf_fill - 1 /* nullchar */; ret = vsnprintf((char*) u->asm_buf + u->asm_buf_fill, avail, fmt, ap); if (ret < 0 || ret > avail) { u->asm_buf_fill = u->asm_buf_size - 1; } else { u->asm_buf_fill += ret; } va_end(ap); return ret; } void ud_syn_print_addr(struct ud *u, uint64_t addr) { const char *name = NULL; if (u->sym_resolver) { int64_t offset = 0; name = u->sym_resolver(u, addr, &offset); if (name) { if (offset) { ud_asmprintf(u, "%s%+" FMT64 "d", name, offset); } else { ud_asmprintf(u, "%s", name); } return; } } ud_asmprintf(u, "0x%" FMT64 "x", addr); } void ud_syn_print_imm(struct ud* u, const struct ud_operand *op) { uint64_t v; if (op->_oprcode == OP_sI && op->size != u->opr_mode) { if (op->size == 8) { v = (int64_t)op->lval.sbyte; } else { UD_ASSERT(op->size == 32); v = (int64_t)op->lval.sdword; } if (u->opr_mode < 64) { v = v & ((1ull << u->opr_mode) - 1ull); } } else { switch (op->size) { case 8 : v = op->lval.ubyte; break; case 16: v = op->lval.uword; break; case 32: v = op->lval.udword; break; case 64: v = op->lval.uqword; break; default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ } } ud_asmprintf(u, "0x%" FMT64 "x", v); } void ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *op, int sign) { UD_ASSERT(op->offset != 0); if (op->base == UD_NONE && op->index == UD_NONE) { uint64_t v; UD_ASSERT(op->scale == UD_NONE && op->offset != 8); /* unsigned mem-offset */ switch (op->offset) { case 16: v = op->lval.uword; break; case 32: v = op->lval.udword; break; case 64: v = op->lval.uqword; break; default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ } ud_asmprintf(u, "0x%" FMT64 "x", v); } else { int64_t v; UD_ASSERT(op->offset != 64); switch (op->offset) { case 8 : v = op->lval.sbyte; break; case 16: v = op->lval.sword; break; case 32: v = op->lval.sdword; break; default: UD_ASSERT(!"invalid offset"); v = 0; /* keep cc happy */ } if (v < 0) { ud_asmprintf(u, "-0x%" FMT64 "x", -v); } else if (v > 0) { ud_asmprintf(u, "%s0x%" FMT64 "x", sign? "+" : "", v); } } } /* vim: set ts=2 sw=2 expandtab */ ================================================ FILE: dis/syn.h ================================================ /* udis86 - libudis86/syn.h * * Copyright (c) 2002-2009 * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef UD_SYN_H #define UD_SYN_H #include "types.h" #ifndef __UD_STANDALONE__ # include #endif /* __UD_STANDALONE__ */ extern const char* ud_reg_tab[]; uint64_t ud_syn_rel_target(struct ud*, struct ud_operand*); #ifdef __GNUC__ int ud_asmprintf(struct ud *u, const char *fmt, ...) __attribute__ ((format (printf, 2, 3))); #else int ud_asmprintf(struct ud *u, const char *fmt, ...); #endif void ud_syn_print_addr(struct ud *u, uint64_t addr); void ud_syn_print_imm(struct ud* u, const struct ud_operand *op); void ud_syn_print_mem_disp(struct ud* u, const struct ud_operand *, int sign); #endif /* UD_SYN_H */ /* vim: set ts=2 sw=2 expandtab */ ================================================ FILE: dis/types.h ================================================ /* udis86 - libudis86/types.h * * Copyright (c) 2002-2013 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef UD_TYPES_H #define UD_TYPES_H #ifdef __KERNEL__ /* -D__KERNEL__ is automatically passed on the command line when building something as part of the Linux kernel */ # include # include # ifndef __UD_STANDALONE__ # define __UD_STANDALONE__ 1 #endif #endif /* __KERNEL__ */ #if defined(_MSC_VER) || defined(__BORLANDC__) # include # include # define inline __inline /* MS Visual Studio requires __inline instead of inline for C code */ #elif !defined(__UD_STANDALONE__) # include # include #endif /* !__UD_STANDALONE__ */ /* gcc specific extensions */ #ifdef __GNUC__ # define UD_ATTR_PACKED __attribute__((packed)) #else # define UD_ATTR_PACKED #endif /* UD_ATTR_PACKED */ /* ----------------------------------------------------------------------------- * All possible "types" of objects in udis86. Order is Important! * ----------------------------------------------------------------------------- */ enum ud_type { UD_NONE, /* 8 bit GPRs */ UD_R_AL, UD_R_CL, UD_R_DL, UD_R_BL, UD_R_AH, UD_R_CH, UD_R_DH, UD_R_BH, UD_R_SPL, UD_R_BPL, UD_R_SIL, UD_R_DIL, UD_R_R8B, UD_R_R9B, UD_R_R10B, UD_R_R11B, UD_R_R12B, UD_R_R13B, UD_R_R14B, UD_R_R15B, /* 16 bit GPRs */ UD_R_AX, UD_R_CX, UD_R_DX, UD_R_BX, UD_R_SP, UD_R_BP, UD_R_SI, UD_R_DI, UD_R_R8W, UD_R_R9W, UD_R_R10W, UD_R_R11W, UD_R_R12W, UD_R_R13W, UD_R_R14W, UD_R_R15W, /* 32 bit GPRs */ UD_R_EAX, UD_R_ECX, UD_R_EDX, UD_R_EBX, UD_R_ESP, UD_R_EBP, UD_R_ESI, UD_R_EDI, UD_R_R8D, UD_R_R9D, UD_R_R10D, UD_R_R11D, UD_R_R12D, UD_R_R13D, UD_R_R14D, UD_R_R15D, /* 64 bit GPRs */ UD_R_RAX, UD_R_RCX, UD_R_RDX, UD_R_RBX, UD_R_RSP, UD_R_RBP, UD_R_RSI, UD_R_RDI, UD_R_R8, UD_R_R9, UD_R_R10, UD_R_R11, UD_R_R12, UD_R_R13, UD_R_R14, UD_R_R15, /* segment registers */ UD_R_ES, UD_R_CS, UD_R_SS, UD_R_DS, UD_R_FS, UD_R_GS, /* control registers*/ UD_R_CR0, UD_R_CR1, UD_R_CR2, UD_R_CR3, UD_R_CR4, UD_R_CR5, UD_R_CR6, UD_R_CR7, UD_R_CR8, UD_R_CR9, UD_R_CR10, UD_R_CR11, UD_R_CR12, UD_R_CR13, UD_R_CR14, UD_R_CR15, /* debug registers */ UD_R_DR0, UD_R_DR1, UD_R_DR2, UD_R_DR3, UD_R_DR4, UD_R_DR5, UD_R_DR6, UD_R_DR7, UD_R_DR8, UD_R_DR9, UD_R_DR10, UD_R_DR11, UD_R_DR12, UD_R_DR13, UD_R_DR14, UD_R_DR15, /* mmx registers */ UD_R_MM0, UD_R_MM1, UD_R_MM2, UD_R_MM3, UD_R_MM4, UD_R_MM5, UD_R_MM6, UD_R_MM7, /* x87 registers */ UD_R_ST0, UD_R_ST1, UD_R_ST2, UD_R_ST3, UD_R_ST4, UD_R_ST5, UD_R_ST6, UD_R_ST7, /* extended multimedia registers */ UD_R_XMM0, UD_R_XMM1, UD_R_XMM2, UD_R_XMM3, UD_R_XMM4, UD_R_XMM5, UD_R_XMM6, UD_R_XMM7, UD_R_XMM8, UD_R_XMM9, UD_R_XMM10, UD_R_XMM11, UD_R_XMM12, UD_R_XMM13, UD_R_XMM14, UD_R_XMM15, UD_R_RIP, /* Operand Types */ UD_OP_REG, UD_OP_MEM, UD_OP_PTR, UD_OP_IMM, UD_OP_JIMM, UD_OP_CONST }; #include "itab.h" union ud_lval { int8_t sbyte; uint8_t ubyte; int16_t sword; uint16_t uword; int32_t sdword; uint32_t udword; int64_t sqword; uint64_t uqword; struct { uint16_t seg; uint32_t off; } ptr; }; /* ----------------------------------------------------------------------------- * struct ud_operand - Disassembled instruction Operand. * ----------------------------------------------------------------------------- */ struct ud_operand { enum ud_type type; uint8_t size; enum ud_type base; enum ud_type index; uint8_t scale; uint8_t offset; union ud_lval lval; /* * internal use only */ uint64_t _legacy; /* this will be removed in 1.8 */ uint8_t _oprcode; }; /* ----------------------------------------------------------------------------- * struct ud - The udis86 object. * ----------------------------------------------------------------------------- */ struct ud { /* * input buffering */ int (*inp_hook) (struct ud*); #ifndef __UD_STANDALONE__ FILE* inp_file; #endif const uint8_t* inp_buf; size_t inp_buf_size; size_t inp_buf_index; uint8_t inp_curr; size_t inp_ctr; uint8_t inp_sess[64]; int inp_end; void (*translator)(struct ud*); uint64_t insn_offset; char insn_hexcode[64]; /* * Assembly output buffer */ char *asm_buf; size_t asm_buf_size; size_t asm_buf_fill; char asm_buf_int[128]; /* * Symbol resolver for use in the translation phase. */ const char* (*sym_resolver)(struct ud*, uint64_t addr, int64_t *offset); uint8_t dis_mode; uint64_t pc; uint8_t vendor; enum ud_mnemonic_code mnemonic; struct ud_operand operand[3]; uint8_t error; uint8_t pfx_rex; uint8_t pfx_seg; uint8_t pfx_opr; uint8_t pfx_adr; uint8_t pfx_lock; uint8_t pfx_str; uint8_t pfx_rep; uint8_t pfx_repe; uint8_t pfx_repne; uint8_t opr_mode; uint8_t adr_mode; uint8_t br_far; uint8_t br_near; uint8_t have_modrm; uint8_t modrm; uint8_t primary_opcode; void * user_opaque_data; struct ud_itab_entry * itab_entry; struct ud_lookup_table_list_entry *le; }; /* ----------------------------------------------------------------------------- * Type-definitions * ----------------------------------------------------------------------------- */ typedef enum ud_type ud_type_t; typedef enum ud_mnemonic_code ud_mnemonic_code_t; typedef struct ud ud_t; typedef struct ud_operand ud_operand_t; #define UD_SYN_INTEL ud_translate_intel #define UD_SYN_ATT ud_translate_att #define UD_EOI (-1) #define UD_INP_CACHE_SZ 32 #define UD_VENDOR_AMD 0 #define UD_VENDOR_INTEL 1 #define UD_VENDOR_ANY 2 #endif /* vim: set ts=2 sw=2 expandtab */ ================================================ FILE: dis/udint.h ================================================ /* udis86 - libudis86/udint.h -- definitions for internal use only * * Copyright (c) 2002-2009 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #ifndef _UDINT_H_ #define _UDINT_H_ #ifdef HAVE_CONFIG_H # include #endif /* HAVE_CONFIG_H */ #if defined(UD_DEBUG) && HAVE_ASSERT_H # include # define UD_ASSERT(_x) assert(_x) #else # define UD_ASSERT(_x) #endif /* !HAVE_ASSERT_H */ #if defined(UD_DEBUG) #define UDERR(u, msg) \ do { \ (u)->error = 1; \ fprintf(stderr, "decode-error: %s:%d: %s", \ __FILE__, __LINE__, (msg)); \ } while (0) #else #define UDERR(u, m) \ do { \ (u)->error = 1; \ } while (0) #endif /* !LOGERR */ #define UD_RETURN_ON_ERROR(u) \ do { \ if ((u)->error != 0) { \ return (u)->error; \ } \ } while (0) #define UD_RETURN_WITH_ERROR(u, m) \ do { \ UDERR(u, m); \ return (u)->error; \ } while (0) #ifndef __UD_STANDALONE__ # define UD_NON_STANDALONE(x) x #else # define UD_NON_STANDALONE(x) #endif /* printf formatting int64 specifier */ #ifdef FMT64 # undef FMT64 #endif #if defined(_MSC_VER) || defined(__BORLANDC__) # define FMT64 "I64" #else # if defined(__APPLE__) # define FMT64 "ll" # elif defined(__amd64__) || defined(__x86_64__) # define FMT64 "l" # else # define FMT64 "ll" # endif /* !x64 */ #endif #endif /* _UDINT_H_ */ ================================================ FILE: dis/udis86.c ================================================ /* udis86 - libudis86/udis86.c * * Copyright (c) 2002-2013 Vivek Thampi * All rights reserved. * * Redistribution and use in source and binary forms, with or without modification, * are permitted provided that the following conditions are met: * * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ #include "udint.h" #include "extern.h" #include "decode.h" #if !defined(__UD_STANDALONE__) # if HAVE_STRING_H # include # endif #endif /* !__UD_STANDALONE__ */ static void ud_inp_init(struct ud *u); /* ============================================================================= * ud_init * Initializes ud_t object. * ============================================================================= */ extern void ud_init(struct ud* u) { memset((void*)u, 0, sizeof(struct ud)); ud_set_mode(u, 16); u->mnemonic = UD_Iinvalid; ud_set_pc(u, 0); #ifndef __UD_STANDALONE__ ud_set_input_file(u, stdin); #endif /* __UD_STANDALONE__ */ ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); } /* ============================================================================= * ud_disassemble * Disassembles one instruction and returns the number of * bytes disassembled. A zero means end of disassembly. * ============================================================================= */ extern unsigned int ud_disassemble(struct ud* u) { int len; if (u->inp_end) { return 0; } if ((len = ud_decode(u)) > 0) { if (u->translator != NULL) { u->asm_buf[0] = '\0'; u->translator(u); } } return len; } /* ============================================================================= * ud_set_mode() - Set Disassemly Mode. * ============================================================================= */ extern void ud_set_mode(struct ud* u, uint8_t m) { switch(m) { case 16: case 32: case 64: u->dis_mode = m ; return; default: u->dis_mode = 16; return; } } /* ============================================================================= * ud_set_vendor() - Set vendor. * ============================================================================= */ extern void ud_set_vendor(struct ud* u, unsigned v) { switch(v) { case UD_VENDOR_INTEL: u->vendor = v; break; case UD_VENDOR_ANY: u->vendor = v; break; default: u->vendor = UD_VENDOR_AMD; } } /* ============================================================================= * ud_set_pc() - Sets code origin. * ============================================================================= */ extern void ud_set_pc(struct ud* u, uint64_t o) { u->pc = o; } /* ============================================================================= * ud_set_syntax() - Sets the output syntax. * ============================================================================= */ extern void ud_set_syntax(struct ud* u, void (*t)(struct ud*)) { u->translator = t; } /* ============================================================================= * ud_insn() - returns the disassembled instruction * ============================================================================= */ const char* ud_insn_asm(const struct ud* u) { return u->asm_buf; } /* ============================================================================= * ud_insn_offset() - Returns the offset. * ============================================================================= */ uint64_t ud_insn_off(const struct ud* u) { return u->insn_offset; } /* ============================================================================= * ud_insn_hex() - Returns hex form of disassembled instruction. * ============================================================================= */ const char* ud_insn_hex(struct ud* u) { u->insn_hexcode[0] = 0; if (!u->error) { unsigned int i; const unsigned char *src_ptr = ud_insn_ptr(u); char* src_hex; src_hex = (char*) u->insn_hexcode; /* for each byte used to decode instruction */ for (i = 0; i < ud_insn_len(u) && i < sizeof(u->insn_hexcode) / 2; ++i, ++src_ptr) { sprintf(src_hex, "%02x", *src_ptr & 0xFF); src_hex += 2; } } return u->insn_hexcode; } /* ============================================================================= * ud_insn_ptr * Returns a pointer to buffer containing the bytes that were * disassembled. * ============================================================================= */ extern const uint8_t* ud_insn_ptr(const struct ud* u) { return (u->inp_buf == NULL) ? u->inp_sess : u->inp_buf + (u->inp_buf_index - u->inp_ctr); } /* ============================================================================= * ud_insn_len * Returns the count of bytes disassembled. * ============================================================================= */ extern unsigned int ud_insn_len(const struct ud* u) { return u->inp_ctr; } /* ============================================================================= * ud_insn_get_opr * Return the operand struct representing the nth operand of * the currently disassembled instruction. Returns NULL if * there's no such operand. * ============================================================================= */ const struct ud_operand* ud_insn_opr(const struct ud *u, unsigned int n) { if (n > 2 || u->operand[n].type == UD_NONE) { return NULL; } else { return &u->operand[n]; } } /* ============================================================================= * ud_opr_is_sreg * Returns non-zero if the given operand is of a segment register type. * ============================================================================= */ int ud_opr_is_sreg(const struct ud_operand *opr) { return opr->type == UD_OP_REG && opr->base >= UD_R_ES && opr->base <= UD_R_GS; } /* ============================================================================= * ud_opr_is_sreg * Returns non-zero if the given operand is of a general purpose * register type. * ============================================================================= */ int ud_opr_is_gpr(const struct ud_operand *opr) { return opr->type == UD_OP_REG && opr->base >= UD_R_AL && opr->base <= UD_R_R15; } /* ============================================================================= * ud_set_user_opaque_data * ud_get_user_opaque_data * Get/set user opaqute data pointer * ============================================================================= */ void ud_set_user_opaque_data(struct ud * u, void* opaque) { u->user_opaque_data = opaque; } void* ud_get_user_opaque_data(const struct ud *u) { return u->user_opaque_data; } /* ============================================================================= * ud_set_asm_buffer * Allow the user to set an assembler output buffer. If `buf` is NULL, * we switch back to the internal buffer. * ============================================================================= */ void ud_set_asm_buffer(struct ud *u, char *buf, size_t size) { if (buf == NULL) { ud_set_asm_buffer(u, u->asm_buf_int, sizeof(u->asm_buf_int)); } else { u->asm_buf = buf; u->asm_buf_size = size; } } /* ============================================================================= * ud_set_sym_resolver * Set symbol resolver for relative targets used in the translation * phase. * * The resolver is a function that takes a uint64_t address and returns a * symbolic name for the that address. The function also takes a second * argument pointing to an integer that the client can optionally set to a * non-zero value for offsetted targets. (symbol+offset) The function may * also return NULL, in which case the translator only prints the target * address. * * The function pointer maybe NULL which resets symbol resolution. * ============================================================================= */ void ud_set_sym_resolver(struct ud *u, const char* (*resolver)(struct ud*, uint64_t addr, int64_t *offset)) { u->sym_resolver = resolver; } /* ============================================================================= * ud_insn_mnemonic * Return the current instruction mnemonic. * ============================================================================= */ enum ud_mnemonic_code ud_insn_mnemonic(const struct ud *u) { return u->mnemonic; } /* ============================================================================= * ud_lookup_mnemonic * Looks up mnemonic code in the mnemonic string table. * Returns NULL if the mnemonic code is invalid. * ============================================================================= */ const char* ud_lookup_mnemonic(enum ud_mnemonic_code c) { if (c < UD_MAX_MNEMONIC_CODE) { return ud_mnemonics_str[c]; } else { return NULL; } } /* * ud_inp_init * Initializes the input system. */ static void ud_inp_init(struct ud *u) { u->inp_hook = NULL; u->inp_buf = NULL; u->inp_buf_size = 0; u->inp_buf_index = 0; u->inp_curr = 0; u->inp_ctr = 0; u->inp_end = 0; UD_NON_STANDALONE(u->inp_file = NULL); } /* ============================================================================= * ud_inp_set_hook * Sets input hook. * ============================================================================= */ void ud_set_input_hook(register struct ud* u, int (*hook)(struct ud*)) { ud_inp_init(u); u->inp_hook = hook; } /* ============================================================================= * ud_inp_set_buffer * Set buffer as input. * ============================================================================= */ void ud_set_input_buffer(register struct ud* u, const uint8_t* buf, size_t len) { ud_inp_init(u); u->inp_buf = buf; u->inp_buf_size = len; u->inp_buf_index = 0; } #ifndef __UD_STANDALONE__ /* ============================================================================= * ud_input_set_file * Set FILE as input. * ============================================================================= */ static int inp_file_hook(struct ud* u) { return fgetc(u->inp_file); } void ud_set_input_file(register struct ud* u, FILE* f) { ud_inp_init(u); u->inp_hook = inp_file_hook; u->inp_file = f; } #endif /* __UD_STANDALONE__ */ /* ============================================================================= * ud_input_skip * Skip n input bytes. * ============================================================================ */ void ud_input_skip(struct ud* u, size_t n) { if (u->inp_end) { return; } if (u->inp_buf == NULL) { while (n--) { int c = u->inp_hook(u); if (c == UD_EOI) { goto eoi; } } return; } else { if (n > u->inp_buf_size || u->inp_buf_index > u->inp_buf_size - n) { u->inp_buf_index = u->inp_buf_size; goto eoi; } u->inp_buf_index += n; return; } eoi: u->inp_end = 1; UDERR(u, "cannot skip, eoi received\b"); return; } /* ============================================================================= * ud_input_end * Returns non-zero on end-of-input. * ============================================================================= */ int ud_input_end(const struct ud *u) { return u->inp_end; } /* vim:set ts=2 sw=2 expandtab */ ================================================ FILE: dis/udis86.err ================================================ udis86.c(47): Warning! W131: No prototype found for function 'memset' ================================================ FILE: dmmic.asm ================================================ FORMAT MZ include 'config.asm' macro linear reg,trg,seg { xor reg,reg mov reg,seg shl reg,4 add reg,trg } macro rinear reg,trg,seg { xor reg,reg mov reg,seg shl reg,16 add reg,trg } ; --- Thread Stacks SEGMENT STACKS stx1 dw 100 dup (?) stx1e: stx2 dw 100 dup(0) stx2e: stx3 dw 1000 dup(0) stx3e: stx4 dw 1000 dup(0) stx4e: stx5 dw 1000 dup(0) stx5e: stx6 dw 1000 dup(0) stx6e: stx7 dw 1000 dup(0) stx7e: stx8 dw 1000 dup(0) stx8e: stx9 dw 1000 dup(0) stx9e: nop ; ---- Unrestricted vm Mode Thread SEGMENT T16 USE16 v0: sti mov ax,0x0900 int 0xF0 mov si,MAIN16 shl esi,16 mov dx,m4 mov bp,0x0900 mov ax,0x0421 int 0xF0 ; Unlock mutex mov ax,MAIN16 mov es,ax mov di,mut1 mov ax,0x0503 int 0xF0 vmcall ; ---- Protected Mode Thread SEGMENT T32 USE32 rt2: ; Int 0xF0 works also in protected mode mov ax,0 int 0xF0 ; DOS call mov bp,0x0900 xor esi,esi mov si,MAIN16 shl esi,16 mov dx,m2 mov ax,0x421 int 0xF0 ; Unlock mutex mov ax,0x0503 linear edi,mut1,MAIN16 int 0xF0 retf ; Virtualized PM Thread (from Virtualized Paged Mode or Unrestricted Mode ) v1: ; Int 0xF0 works also in protected mode (but CPUID not in virtualization) xchg bx,bx ; DOS call mov bp,0x0900 xor esi,esi mov si,MAIN16 shl esi,16 mov dx,m1 mov ax,0x421 ;int 0xF0 ;Not Yet ; Unlock mutex mov ax,0x0503 linear edi,mut1,MAIN16 int 0xF0 retf ; ---- Long Mode Thread SEGMENT T64 USE64 ; Virtualized LM Thread (from Unrestricted Mode ) v3: xchg bx,bx nop nop vmcall rt3: nop nop nop nop nop ; Int 0xF0 works also in long mode mov ax,0 int 0xF0 ; DOS call xor rsi,rsi mov si,MAIN16 shl rsi,16 mov rdx,m3 mov rax,0x0900 int 0x21 ; Unlock mutex mov ax,0x0503 linear rdi,mut1,MAIN16 int 0xF0 ret ; Virtualized LM Thread v2: vmcall SEGMENT MAIN16 USE16 ORG 0h m1 db "[real] ","$"; m2 db "[protected] ","$"; m3 db "[long] ","$"; m4 db "[virtualized real]","$"; crlf db 0dh,0ah,"$" mut1 db 0 dhvalue db 0 include "reqdmmi.asm" ; Real mode thread rt1: sti push cs pop si shl esi,16 mov dx,m1 mov bp,0x0900 mov ax,0x0421 int 0xF0 ; unlock mut push cs pop es mov di,mut1 mov ax,0x0503 int 0xF0 retf main: if RESIDENT = 0 mov ax,0x4c00 int 0x21 end if RequireDMMI ; dl = num of cpus ; dh = virtualization mode mov [cs:dhvalue],dh ; enter unreal mov ax,0x0900 int 0xF0 ; init mut push cs pop es mov di,mut1 mov ax,0x0500 int 0xF0 repeat 4 ; lock mut push cs pop es mov di,mut1 mov ax,0x0502 int 0xF0 end repeat ; run a real mode thread push cs pop es mov dx,rt1 mov cx,STACKS mov gs,cx mov cx,stx1e mov ax,0x0100 mov ebx,1 int 0xF0 ; run a protected thread push cs pop es mov ax,0x0101 mov ebx,3 linear ecx,stx3e,STACKS linear edx,rt2,T32 int 0xF0 ; run a long thread push cs pop es mov ax,0x0102 mov ebx,4 linear ecx,stx4e,STACKS linear edx,rt3,T64 int 0xF0 ; run a virtualized paged protected mode thread cmp [cs:dhvalue],2 je .useUnr cmp [cs:dhvalue],1 je .usePmV ; No virtualization supported ; Release one mutex push cs pop es mov di,mut1 mov ax,0x0503 int 0xF0 jmp .AfterV .usePmV: push cs pop es mov ax,0x0103 mov ebx,0x107 linear edi,stx6e,STACKS linear ecx,stx7e,STACKS linear edx,v1,T32 int 0xF0 jmp .AfterV ; run a virtualized unrestricted guest -> real mode thread .useUnr: push cs pop es mov ax,0x0103 mov ebx,0x007 rinear edi,stx8e,STACKS linear ecx,stx9e,STACKS rinear edx,v0,T16 mov esi,0 ; Mode 0 -> Real mode int 0xF0 ; Virtualized Unrestricted Guest -> protected mode thread push cs pop es mov ax,0x0103 mov ebx,0x007 linear ecx,stx3e,STACKS linear edx,v1,T32 mov esi,1 ; Mode 1 -> Protected mode ;int 0xF0 ; Virtualized Unrestricted Guest -> long mode thread push cs pop es mov ax,0x0103 mov ebx,0x007 linear ecx,stx3e,STACKS linear edx,v3,T64 mov esi,2 ; Mode 2 -> Long mode ;int 0xF0 ; Not working yet because MSR writing causes VMEXIT, (we haven't yet defined MSR bitmaps in VMX) .AfterV: ; wait mut push cs pop es mov di,mut1 mov ax,0x0504 int 0xF0 push cs pop ds mov ax,0x0900 mov dx,crlf int 0x21 mov ax,0x4c00 int 0x21 entry MAIN16:main ================================================ FILE: dos32.asm ================================================ USE32 calldos32: retf ================================================ FILE: dpmi/DPMI.PRO ================================================ ; Profile for DPMI.LOD ; ; Options currently in effect are ; ; Default options are ; dpmimem=616,1024,4096,32,32,1,2048 ; Set DPMI memory options ; sharedmem=16 ; Set the Shared Memory size to nnnn MB ; ; All possible options recognized by DPMI.LOD are ; debug=cli ; Don't disable interrupts on CLI in PM ; debug=dpmierr ; Signal INT 01h on each DPMI error ; debug=dpmilock ; Check for InDOS when paging ; debug=dpminewsel ; Force new selector on all allocates ; debug=dpmiphys ; Disable checks in DPMI_GETP2L ; debug=dpmisel ; Signal INT 01h on each LAST_DPMI_xS error ; debug=dpmispurnt ; Signal INT 01h on spurious NT task switches ; debug=dpmistart ; Signal INT 01h on DPMI client startup ; debug=dpmistd ; Force KRNL386 to come up in standard mode ; debug=dpmiterm ; Signal INT 01h if we free resources upon termination ; debug=dpmiv100 ; Force DPMI version 1.00 even if Rational Systems-based app ; debug=nodebug ; Disable hooks for INTs 01h and 03h for debugging purposes ; debug=nokeyb ; Disable hook for INT 09h for debugging purposes ; debug=nonmi ; Disable hook for INT 02h for debugging purposes ; debug=nowrap ; Trap even boundary stack wraps at 0000 ; dpmimem=lll,sss,bbb,ccc,hhh,ppp,ddd ; Set DPMI memory options: Min Def ; lll = # LDT entries 32 616 ; sss = byte size of the HPDA stack 512 1024 ; bbb = byte size of the HPDA buffer 512 4096 ; ccc = # VM callbacks 16 32 ; hhh = # DPMI memory handles 1 32 ; ppp = # page directories 1 1 ; ddd = byte size of the dynamic save area 1024 2048 ; forcelpm16 ; Force the LPM stack to be 16-bit (overcome bug in MS linker) ; noumb ; Don't allocate memory in UMBs ; novcpi ; Disable VCPI presence detection ; pro=d:\path\filename.ext ; Load a profile (cannot be used from within a profile) ; sharedmem=nnnn ; Set the Shared Memory size to nnnn MB ; ; (default = 16 MB, must be multiple of 4 MB) ; swapfile [=d:\path\filename.ext] [/s=nnnn] [/t] [/p] ; Use a swapfile for DPMI VMM ; optional args ; d:\path\filename.ext Use this as permanent swapfile ; /p Make it permanent ; /t On second thought, it's temporary ; /s=nnnn Make it nnnn KB in size (default = 8192) ; If no filename is specified, the SWAPFILE is temporary ; unless /P is specified. Otherwise, it's permanent ; unless /T is specified.  ================================================ FILE: dpmi/DPMIONE.PRO ================================================ ; Profile for DPMIONE.EXE LOAD=dpmi.lod pro=dpmi.pro ; ; The default options are ; ; DEBUG=QSWAT Don't signal INT 01h if preceding 386SWAT present. ; ; All possible options recognized by DPMIONE.EXE are ; ; LOAD=d:\path\filename.ext Load a PM program such as DPMI.LOD ; PRO=d:\path\filename.ext Parse a profile. ; UNLOAD Uninstall DPMIONE. ; UNINST ... ; UNINSTALL ... ; DEBUG=NSWAT Don't pass on SWAT presence to load modules. ; DEBUG=QSWAT Don't signal INT 01h if preceding 386SWAT present.  ================================================ FILE: dpmi/LICENSE.TXT ================================================ DPMIONE -- A DPMI 1.0 Host -- Version 0.91 (C) Copyright 1990-2004 Qualitas, Inc. All Rights Reserved. Author & Copyright ------------------ This program was written by Bob Smith (bsmith@sudleyplace.com) and is (C) Copyright 1990-2004 Qualitas, Inc. The most recent version may be found at http://www.sudleyplace.com/dpmione/. License ------- This program may be used free for non-commercial use; commercial use requires a Volume Purchase Agreement from the author. It may be freely distributed as long as no part of the program or its documentation is altered and the program and its documentation are kept together.  ================================================ FILE: dpmi/README.TXT ================================================ DPMIONE -- A DPMI 1.0 Host -- Version 0.91 (C) Copyright 1990-2004 Qualitas, Inc. All Rights Reserved. Overview -------- The DOS Protected Mode Interface (DPMI) Specification version 0.9 was created by the DPMI Committee in 1990, and extended to version 1.0 in 1991. From the introduction to the DPMI 1.0 spec, "The DOS Protected Mode Interface (DPMI) allows DOS programmers to access the advanced features of 80286, 80386, and 80486-based PCs in a well-behaved, hardware-independent fashion that does not compromise system protection". With this spec, it becomes especially easy to write a program which enters Protected Mode (PM), and has access to all of the system's extended memory. DPMI 0.9 hosts are readily available, standalone or otherwise. Some DPMI 0.9 hosts implemented a handful of DPMI 1.0 features, but other than 386MAX, none of them did the whole spec. DPMIONE is, to my knowledge, the first publicly available standalone DPMI 1.0 host. This program is an outgrowth of the DPMI 1.0 host which first appeared in 386MAX from Qualitas, Inc. in 1992. As such, it has undergone extensive testing in that commercial product before being ported to this standalone program. Features -------- * Supports DPMI 1.0 (superset of DPMI 0.9) * Starts from either Real Mode or Virtual Mode (using VCPI) * Low DOS memory resident size is about 15KB * Extended memory resident size is about 300KB plus Page Tables (4KB per 4MB of physical memory) * Loads from command line or as device driver so subsequently loaded device drivers can use DPMI * Supports both 16-bit and 32-bit DPMI clients * Supports nested DPMI clients * Supports uncommitted memory (a very handy DPMI 1.0 feature) (See the file UNCOMMIT.TXT for details.) * Full DOS (INT 21h) & Mouse (INT 33h) translation services * Swapfile support * Compatible with 386SWAT for debugging DPMI clients System Requirements ------------------- * 80386 CPU or later * XMS driver (HIMEM.SYS or Memory Manager EMM386/QEMM/etc. -- 386MAX 7 and later versions already support DPMI 1.0) Limitations ----------- * VM/RM exceptions 06h (Invalid Opcode) and 0Dh (GP Fault) only are reflected to PM. * The TSR facility of DPMI 1.0 is not supported. Installation ------------ 1. Unzip the files into a separate directory (say, C:\DPMIONE). 2. Edit the file DPMIONE.PRO to include a line which loads the DPMI.LOD file, e.g. load=c:\dpmione\dpmi.lod pro=c:\dpmione\dpmi.pro 3. Edit the DPMI.PRO file as necessary (no changes are needed from the defaults). 4. Decide whether you want to load DPMIONE.EXE in your CONFIG.SYS or AUTOEXEC.BAT file (or neither). Then, do either step 4a or 4b (but *NOT BOTH*): a. Edit your CONFIG.SYS file to include a line such as Device=c:\dpmione\dpmione.exe pro=c:\dpmione\dpmione.pro b. Edit your AUTOEXEC.BAT file to include a line such as c:\dpmione\dpmione pro=c:\dpmione\dpmione.pro c. If you chose not to load DPMIONE automatically, you can run it from the command line at a later time, with a line similar to the one in 4b. 5. If necessary, reboot your system to load DPMIONE. Compatibility ------------- As a test of this program's compatibility as a DPMI host, you can actually use it as a substitute for the Windows 3.1x DPMI host. That is, install a fresh copy of Windows 3.1x. Then, with DPMIONE resident, go to the WINDOWS directory and type system\krnl386 and Windows is up and running. This instance of Windows does not support DOS sessions or anything related to that, but most other Windows functions are there including File Manager. This has proven to be an exceptionally rigorous test of a DPMI host. No other unrelated DPMI host can make this claim. Expand Down Stacks ------------------ The Locked Protected Mode stack used by DPMIONE for hardware interrupts and faults is marked as Expand Down so it expands automatically. In the process of making this work, I learned a lot. For more details on Expand Down segments, see http://www.sudleyplace.com/dpmione/expanddown.htm. Author & Copyright ------------------ This program was written by Bob Smith (bsmith@sudleyplace.com) and is (C) Copyright 1990-2004 Qualitas, Inc. The most recent version may be found at http://www.sudleyplace.com/dpmione/. License ------- This program may be used free for non-commercial use; commercial use requires a volume purchase agreement from the author. It may be freely distributed as long as no part of the program or its documentation is altered and the program and its documentation are kept together. Download -------- The program files may be downloaded from our FTP site at ftp://ftp.sudleyplace.com/sudleyplace/dpmione.zip. Specification ------------- To view the DPMI 1.0 specification, try one of the following links: http://www.delorie.com/djgpp/doc/dpmi/ (HTML) http://clio.rice.edu/cwsdpmi/dpmispec1.pdf (PDF) Version History --------------- Please see the file VERSION.TXT.  ================================================ FILE: dpmi/UNCOMMIT.TXT ================================================ How to Use Uncommitted Memory Overview -------- One of the really nice features of DPMI 1.0 is its support of uncommitted memory, that is the ability to allocate address space without allocating memory to back it up at the same time. For example, say you need space for an object whose size you can't compute at the start, but has a reasonable upper limit of, say, 100 megabytes. Using uncommitted memory, you can allocate 100 MB of address space and then just start using it. When you first write to anywhere in the address space, the DPMI 1.0 host signals a Visible Page Fault (VPF) which your program has hooked and is now given the opportunity to handle. Your program's response to the VPF is to mark the 4KB block's page attributes as Read/Write and Committed, and then simply re-execute the instruction which triggered the VPF. The DPMI host takes over from there, maps in a 4KB block of memory, and your program continues on as if nothing had happened. Subsequent accesses to different 4KB blocks of the uncommitted memory trigger additional VPFs to which your program responds in the same way. This provides a very efficient mechanism with a small amount of overhead once per 4KB block of the address space and commits only the amount of memory actually needed. I used this technique in my linker, QLINK. At the start of the program, it doesn't know how big each segment might be, but it can make a reasonable guess that none will be bigger than a few megabytes. When data is written to each segment, QLINK's VPF handler marks the faulting address as committed, and continues on. This feature allows QLINK to pass through each object file only once instead of the usual two passes needed by other linkers. Details ------- To use uncommitted memory, follow these steps: 1. Allocate address space via DPMI function 504h (Allocate Linear Memory Block) with EDX = 0 to create Uncommitted Pages. 2. Hook the Page Fault handler via DPMI function 210h (Get Extended Processor Exception Handler -- PM), interrupt 0Eh. 3. When the Page Fault handler hooked above is called, find the matching handle from step 1, and change the corresponding 4KB block's Page Attributes (via DPMI function 507h -- Set Page Attributes) to Read/Write and Committed. 4. Return to the caller to re-execute the instruction which triggered the VPF. ================================================ FILE: dpmi/VERSION.TXT ================================================ Version History for DPMIONE --------------------------- 0.91 -- 22 April 2004 * Fix bugs when loading as device driver. * Provide partial DOS translation services for Virtual DMA Services (VDS -- INT 4Bh). 0.90 -- 9 February 2004 * Overcome bug in MS 16-bit linker (5.31) where their GP Fault handler mistakenly assumes that the incoming LPM stack is 16-bit even though they are a 32-bit client. * Implement FORCELPM16 in DPMI.PRO in case there are other apps with the same bug. 0.89 -- 8 July 2003 * Fix bug where if in VM, but no VCPI host name match, program mistakenly tries to enter PM as if in RM. 0.88 -- 4 June 2003 * Workaround bug in WinME where it has effectively disabled INT 15h/AH=87h (Move Extended Memory BIOS function). * Fix obscure bug related to marking a PDE as uncommitted. * Implement SHAREDMEM=nnn in DPMI.PRO. 0.87--26 May 2003 * Remove debugging code which, were it encountered, would cause the system to reboot. 0.86 -- 17 May 2003 * Fix bug in DPMI function 505h (Resize Linear Memory Block) when used on Expand Down segments. * Increase size of TSR space to accommodate larger resident size of DPMI.LOD. * Fix bug in stack alignment when LPM stack selector pushed. 0.85 -- 14 May 2003 * Initial release to public as beta.  ================================================ FILE: dpmic.asm ================================================ FORMAT MZ HEAP 0 segment DATA16 USE16 ; main segment CODE16 USE16 error: mov ax,0x4C00 int 0x21 modesw dd 0 start16: ; A raw (not DOS32A) DPMI client mov ax,1687h ; get address of DPMI host's int 2fh or ax,ax ; exit if no DPMI host jnz error mov word [modesw],di mov word [modesw+2],es or si,si ; check private data area size jz .l1 ; jump if no private data area mov bx,si ; allocate DPMI private area mov ah,48h ; allocate memory int 21h ; transfer to DOS jc error ; jump, allocation failed mov es,ax ; let ES=segment of data area .l1: xchg bx,bx mov ax,0 ; bit 0=0 indicates 16-bit app call [modesw] ; switch to protected mode xchg bx,bx jc error ; jump if mode switch failed ; else we're in prot. mode now nop mov ax,0x4C00 int 0x21 SEGMENT ENDS entry CODE16:start16 ================================================ FILE: entry.asm ================================================ FORMAT MZ HEAP 0 INCLUDE 'config.asm' INCLUDE 'struct.asm' INCLUDE 'data16.asm' INCLUDE 'guest32.asm' INCLUDE 'data32.asm' INCLUDE 'data64.asm' INCLUDE 'stack16.asm' INCLUDE 'stack32.asm' INCLUDE 'stack64.asm' INCLUDE 'guest16.asm' INCLUDE 'code16.asm' INCLUDE 'a20.asm' INCLUDE 'idt.asm' INCLUDE 'gdt.asm' INCLUDE 'code32.asm' INCLUDE 'code64.asm' SEGMENT ENDS entry CODE16:start16 ================================================ FILE: gdt.asm ================================================ ; --------------------------------------- GDT routines --------------------------------------- USE16 macro gdt_initialize a_seg,a_desc { xor eax,eax mov ax,a_seg shl eax,4 mov [a_desc + 2],ax shr eax,8 mov [a_desc + 4],ah } macro gdt_initialize64 a_seg,a_desc { xor eax,eax mov [a_desc + 2],ax mov [a_desc + 4],ah } GDTInit: ; 16-32 segments gdt_initialize CODE32,code32_descriptor gdt_initialize DATA32,data32_descriptor gdt_initialize STACK32,stack32_descriptor gdt_initialize CODE16,code16_descriptor gdt_initialize DATA16,data16_descriptor gdt_initialize STACK16,stack16_descriptor gdt_initialize 0,raw32_descriptor ; Paging segment, we 've found it already xor eax,eax mov [ds:page32_descriptor.b0_15],ax mov [ds:page32_descriptor.b16_23],ah xor eax,eax mov [ds:page64_descriptor.b0_15],ax mov [ds:page64_descriptor.b16_23],ah ; 64 segments gdt_initialize64 CODE64,code64_descriptor gdt_initialize64 DATA64,data64_descriptor ; and the LDT xor eax,eax mov ax,DATA32 shl eax,4 add eax,ldt_start mov [ds:ldt_descriptor.b0_15],ax shr eax,8 mov [ds:ldt_descriptor.b16_23],ah ; Set gdt ptr xor eax,eax mov ax,DATA16 shl eax,4 add ax,dummy_descriptor mov [gdt_ptr],eax RETF ================================================ FILE: guest16.asm ================================================ SEGMENT VMX16 USE16 ; VMX Entry for our Virtual Machine ; This is a Real Mode segment ; Note that since the memory is see through, BIOS and DOS interrupts work here! StartVM: ; Remember we used a protected mode selector to get here? ; Jump to a real mode segment now so CS gets a proper value nop nop db 0eah dw PM_VM_Entry,VMX16 PM_VM_Entry: mov ax,DATA16 mov ds,ax mov [vmt3],1 vmcall ; Forces exit ================================================ FILE: guest32.asm ================================================ SEGMENT VMX32 USE32 ; VMX Entry for our Virtual Machine ; This is a Protected Mode segment StartVM2: ; This is a protected mode start - 32 bit so registers are already loaded mov ax,data16_idx mov ds,ax mov byte [ds:vmt2],0x1 vmcall ; Forces exit ================================================ FILE: guest64.asm ================================================ ; VMX Entry for our Virtual Machine ; This is a Protected Mode segment StartVM3: ; This is a protected mode start - 32 bit so registers are already loaded xchg bx,bx vmcall ; Forces exit ================================================ FILE: himem16.asm ================================================ himaddrx: himaddr dd 0 himemthere: mov ax,0x4300 int 0x2F cmp al,0x80 jz .hi ret .hi: mov ax,0x4310 int 0x2F mov word [cs:himaddrx + 2],es mov word [cs:himaddrx],bx mov al,0x80 ret allochigh: ; EDX = bytes, return ECX = handle, EDI = linear xor ecx,ecx cmp [cs:himaddr],0 jnz .useh .noh: mov ecx,0 mov edi,0 ret .useh: mov ax,0x0900 shr edx,10 call far [cs:himaddr] cmp dx,0 jz .noh mov ax,0x0C00 mov cx,dx xor edx,edx xor ebx,ebx mov dx,cx call far [cs:himaddr] cmp ax,1 jz .okh mov ax,0x0A00 mov dx,cx call far [cs:himaddr] jmp .noh .okh: xor edi,edi mov di,dx shl edi,16 add edi,ebx ret freehigh: ; DX = handle cmp dx,0 jz .noh cmp [cs:himaddr],0 jnz .useh .noh: ret .useh: mov ax,0x0D00 call far [cs:himaddr] mov ax,0x0A00 call far [cs:himaddr] ret ================================================ FILE: idt.asm ================================================ ; --------------------------------------- IDT routines --------------------------------------- USE16 IDTInit2: ; Base for intr00 -> All vectors point to this, except f0 xor edx,edx mov dx,CODE32 shl edx,4 add edx,intr00 ; EDX now contains physical address for handler mov cx,255 xor esi,esi mov si,interruptsall Loop1a: ; push edx cmp cx, 15 jnz .nof0 linear edx,int32,CODE32 .nof0: mov edi,esi mov eax,edx mov word [edi],ax ; lower add edi,2 mov word [edi],code32_idx ; sel add edi,2 mov byte [edi],0 add edi,1 mov byte [edi],08Eh; add edi,1 mov eax,edx shr eax,16 mov word [edi],ax ; upper pop edx jcxz EndLoop1a dec cx add esi,8 jmp Loop1a EndLoop1a: ; Set idt ptr xor eax,eax mov ax,DATA16 shl eax,4 add ax,interruptsall mov [idt_PM_ptr],eax retf IDTInit: push es mov ax,DATA16 mov es,ax ; 00h mov ecx,255 xor edi,edi mov di,interruptsall .Loop1: mov bp,8 mov ax,cx mul bp mov bp,ax xor eax,eax cmp cx, 0x0F jz .yf0 cmp cx, 0xDE jz .y21 add eax,intr00 jmp .ef .y21: add eax,int32_21 jmp .ef .yf0: add eax,int32 jmp .ef .ef: mov [di],ax shr eax,16 mov [di + 6],ax mov ax,code32_idx mov [di + 2],ax xor ah,ah mov [di + 4],ah mov ah,08eh mov [di + 5],ah; 10001110 selector add di,8 jcxz .EndLoop1 dec cx jmp .Loop1 .EndLoop1: ; Set idt ptr xor eax,eax mov ax,DATA16 shl eax,4 add ax,interruptsall mov [idt_PM_ptr],eax pop es RETF IDTInit64: push es mov ax,DATA16 mov es,ax ; 00h mov ecx,0 xor edi,edi mov di,interruptsall64 .Loop1: cmp ecx,0x100 jz .End linear eax,intr6400,CODE64 cmp ecx,0xF0 jz .yf0 cmp ecx,0x21 jz .y21 jmp .ef0 .yf0: linear eax,int64,CODE64 jmp .ef0 .y21: linear eax,int64_21,CODE64 jmp .ef0 .ef0: ; 0(2) - Low bits offset mov word [di],ax ; 2(2) - Selector mov word [di + 2],code64_idx ; 4(1) - zero mov byte [di + 4],0 ; 5(1) - Type + Attributes mov byte [di + 5],0x8E ; 6(2) - Middle offset mov edx,eax shr edx,16 mov word [di + 6],dx ; 8(4) High bits mov dword [di + 8],0 ; 12(4) zero mov dword [di + 12],0 add di,16 inc ecx jmp .Loop1 .End: ; Set idt ptr linear eax,interruptsall64 mov dword [idt_LM_ptr],eax mov dword [idt_LM_ptr + 4],0 pop es RETF ================================================ FILE: int16.asm ================================================ ; --------------------------------------- int 0xF0 real --------------------------------------- c16o dw 0 c16s dw 0 c16sts dw 0 c16sto dw 0 include 'directlong.asm' Thread16C: thread16header STACK16T1,stack16t1_end mov ax,CODE16 mov ds,ax mov ax,[c16sts] mov ss,ax mov ax,[c16sto] mov sp,ax mov ax,0x25F0 mov dx,int16 int 0x21 mov ax,CODE16 mov ds,ax call far dword [c16o] cli hlt hlt Thread32P: mov ax,page32_idx mov ss,ax ; mov esp,xxxxxxxx db 0x66 db 0xBC c32st dd 0 mov ax,code16_idx mov ds,ax db 066h db 09ah c32 dd 0 dw vmx32_idx cli hlt hlt USE64 Thread64P: ; mov rsp,xxxxxxxx ;mov rsp,0x0000000012345678 db 0x48 db 0xC7 db 0xC4 c64st dd 0 linear rax,idt_LM_start lidt [rax] mov ax,page64_idx mov ss,ax linear rax,retx,CODE16 push rax; for returning db 0x68; push c64 dd 0 ret retx: cli hlt hlt cv64vmode db 0 cv64vmode2 dw 0 Thread64PV: ; mov rsp,xxxxxxxx ;mov rsp,0x0000000012345678 db 0x48 db 0xC7 db 0xC4 cv64st dd 0 linear rax,idt_LM_start lidt [rax] mov ax,page64_idx mov ss,ax mov ds,ax mov es,ax ; ---- VMX ; Existence test linear rbx,vmt1,DATA16 mov byte [rbx],0 ; VMX Preparation linear rbx,vmt1,DATA16 mov byte [rbx],1 ; VMX_Init linear rax,vvr1,CODE16 push rax; for returning db 0x68; push cv64_vmxinitstructures dd 0 ret vvr1: ; VMX_Enable linear rax,vvr2,CODE16 push rax; for returning db 0x68; push cv64_vmxenable dd 0 ret vvr2: ; Load the revision linear rdi,VMXRevision,VMXDATA64 mov ebx,[rdi]; ; Initialize the region linear rdi,VMXStructureData2,VMXDATA64 mov rcx,[rdi]; Get address of data1 mov rsi,rdi mov rdi,rcx mov [rdi],ebx ; // Put the revision VMCLEAR [rsi] mov [rdi],ebx ; // Put the revision VMPTRLD [rsi] mov [rdi],ebx ; // Put the revision ; EPT init linear rax,vvr7,CODE16 push rax; for returning db 0x68; push cv64_vmxinitept dd 0 ret vvr7: linear rax,cv64vmode,CODE16 mov al,[rax] cmp al,1 jz cPM ; Controls init ur xor rdx,rdx bts rdx,1 bts rdx,7 linear rax,vvr6,CODE16 push rax; for returning db 0x68; push cv64_vmxinitcontrols1 dd 0 ret cPM: ; pm init controls mov rdx,0x49 linear rax,vvr6,CODE16 push rax; for returning db 0x68; push cv64_vmxinitcontrols2 dd 0 ret vvr6: ; Host Init push gs push fs linear rcx,vretxx,CODE16 linear rax,vvr4,CODE16 push rax; for returning db 0x68; push cv64_vmxinithost dd 0 ret vvr4: pop fs pop gs ; Guest Init mov r8,raw32_idx mov r9,0 linear rax,cv64vmode,CODE16 mov al,[rax] cmp al,1 jz uPM ; UR mov r10,vmentryx mov r9,CODE16 linear rax,vvr5,CODE16 push rax; for returning db 0x68; push cv64_vmxinitguest1 dd 0 ret uPM: ; PM linear r10,vmentry,CODE16 linear rax,vvr5,CODE16 push rax; for returning db 0x68; push cv64_vmxinitguest2 dd 0 ret vvr5: ; The EPT initialization for the guest linear rax,PhysicalEptOffset64,DATA16 mov rax,[rax] or rax,0 ; Memory Type 0 or rax,0x18 ; Page Walk Length 3 mov rbx,0x201A ; EPTP vmwrite rbx,rax ; The Link Pointer -1 initialization mov rax,0xFFFFFFFFFFFFFFFF mov rbx,0x2800 ; LP vmwrite rbx,rax ; One more RSP initialization of the host xor rax,rax mov rbx,0x6c14 ; RSP mov rax,rsp vmwrite rbx,rax VMLAUNCH jmp vretxx ; Virtual Machine Here, Protected mode USE32 vmentry: ; set the stack mov ax,page32_idx mov ss,ax ; set the IDT linear ebx,idt_PM_start,DATA16 lidt [ebx] ; mov esp,xxxxxxxx db 0xBC cv64vst1 dd 0 ; call the address db 09ah cv64 dd 0 dw vmx32_idx VMCALL ; Virtual Machine Here, Unrestricted mode USE16 cv64vst0 dd 0 vmentryx: mov ax,DATA16 mov ds,ax ; set the IDT mov ebx,idt_RM_start lidt [ebx] ; set the stack mov eax,[cs:cv64vst0] mov ss,ax shr eax,16 mov sp,ax ; Check submode mov ax,[cs:cv64vmode2] cmp ax,0 je UR_Mode_0 cmp ax,1 je UR_Mode_1_P cmp ax,2 je UR_Mode_2_P VMCALL; Nothing else supported atm ; ------------ Long Submode UR_Mode_2: USE64 xchg bx,bx vmcall USE16 UR_Mode_2_P: ; Restore CS (remember it is loaded with a protected mode selector) db 0eah dw PM_VM_Entry4,CODE16 PM_VM_Entry4: thread64header 1 db 066h db 0eah Thread64Ptr1V dd 0 dw code64_idx ; ------------ ; ------------ Protected Submode UR_Mode_1: USE16 mov ax,page32_idx mov ss,ax ; mov esp,xxxxxxxx db 0x66 db 0xBC c32stV dd 0 mov ax,code16_idx mov ds,ax db 066h db 09ah c32V dd 0 dw vmx32_idx vmcall USE16 UR_Mode_1_P: ; Protected Mode from Unrestricted guest ; Restore CS (remember it is loaded with a protected mode selector) db 0eah dw PM_VM_Entry3,CODE16 PM_VM_Entry3: EnterProtected UR_Mode_1,code16_idx ; ------------ ; ------------ Real Submode Mode UR_Mode_0: ; call the address db 09ah cv64u dd 0 VMCALL ; ------------ USE64 vretxx: ; VMX_Disable linear rax,vvr3,CODE16 push rax; for returning db 0x68; push cv64_vmxdisable dd 0 ret vvr3: cli hlt hlt USE16 Thread32C: thread16header STACK16T1,stack16t1_end EnterProtected Thread32P,code16_idx Thread64C: thread64header db 066h db 0eah Thread64Ptr1 dd 0 dw code64_idx Thread64CV: thread64header db 066h db 0eah Thread64Ptr4 dd 0 dw code64_idx int16: jmp .ibegin db 'dmmi' db 10 dup(0x90) .ibegin: ; AX 0, find interface cmp ax,0 jnz .n0 dh_virtualization; push ds mov ax,DATA16 mov ds,ax mov dl,[numcpus] pop ds mov ax,0xFACE IRET .n0: ; AH 1, begin thead cmp ah,1 jnz .n1 cmp al,0 jnz .n10 ; BL = CPU ; AL = 0 = Unreal mode thread ; ES:DX = Run address ; GS:CX = Stack and ebx,0xFF mov ax,CODE16 mov ds,ax mov [c16s],es mov [c16o],dx mov [c16sts],gs mov [c16sto],cx linear eax,Thread16C,CODE16 call far CODE16:SendSIPIf IRET .n10: cmp al,1 jnz .n11 ; BL = CPU ; AL = 1 = Protected mode thread ; EDX = Linear Address ; ECX = Linear Stack and ebx,0xFF mov ax,CODE16 mov ds,ax mov [c32],edx mov [c32st],ecx linear eax,Thread32C,CODE16 call far CODE16:SendSIPIf IRET .n11: cmp al,2 jnz .n12 ; BL = CPU ; AL = 2 = Long mode thread ; EDX = Linear Address ; ECX = Linear Stack and ebx,0xFF mov ax,CODE16 mov ds,ax mov [c64],edx mov [c64st],ecx linear eax,Thread64C,CODE16 call far CODE16:SendSIPIf IRET .n12: cmp al,3 jnz .n13 ; BL = CPU ; AL = 3 = Virtualized Thread ; BH = mode (1 PM mode,0 UG mode) ; SI = submode (0 Unreal mode) ; EDX = Linear Address (or seg:ofs if submode 0) ; ECX = Linear Stack ; EDI = Virtualized Linear Stack (or seg:ofs if submode 0) ; Test existence push eax push ebx push ecx push edx mov eax,1 cpuid bt ecx,5 pop edx pop ecx pop ebx pop eax JC .okvm iret; duh .okvm: mov ax,CODE16 mov ds,ax mov [cv64u],edx mov [cv64],edx mov [cv64st],ecx mov [c32V],edx mov [c32stV],ecx mov [cv64vst0],edi mov [cv64vst1],edi mov [cv64vmode],bh mov [cv64vmode2],si and ebx,0xFF linear eax,Thread64CV,CODE16 call far CODE16:SendSIPIf IRET .n13: IRET .n1: ; AH 5, mutex functions cmp ah,5 jnz .n5 ; Initialize mutex cmp al,0 jnz .n50 mov byte [es:di],0xFF iret .n50: ; lock mutex cmp al,2 jnz .n52 dec byte [es:di] iret .n52: ; unlock mutex cmp al,3 jnz .n53 cmp byte [es:di],0xFF jz .okl inc byte [es:di] .okl: iret .n53: ; wait mutex cmp al,4 jnz .n54 .Loop1: CMP byte [es:di],0xff JZ .OutLoop1 pause JMP .Loop1 .OutLoop1: iret .n54: IRET .n5: ; AH 4, call real mode interrupt ; AL = INT NUM ; BP = AX VALUE ; CX,DX,SI,DI = Normal values ; Upper ESI,EDI => DS and ES cmp ah,4 jnz nr4 push ds push es push ax ; Mutex Lock mov ax,mut_i21 call far CODE16:qwaitlock16 push esi shr esi,16 mov ds,si pop esi push edi shr edi,16 mov es,di pop edi ; Interrupt put pop ax mov [cs:inttr],al push ax cmp al,0 jz skip1 mov ax,bp db 0xCD inttr db 0 skip1: pop ax pop es pop ds ; Unlock qunlock16 mut_i21 iret nr4: ; AX 9, switch to mode cmp ah,9 jnz n9 ; AL 0, unreal cmp al,0 jnz .n90 push cs cli call EnterUnreal sti IRET .n90: ; AL 1, protected cmp al,1 jnz n91 mov [cs:n91aa],ecx mov ax,DATA16 mov ds,ax mov bx,gdt_start lgdt [bx] mov bx,idt_PM_start lidt [bx] mov eax,cr0 or al,1 mov cr0,eax mov ax,page32_idx mov gs,ax db 066h db 0eah n91aa dd 0 dw vmx32_idx n91: ; AL 2, long ; ECX = linear address cmp al,2 jnz n92 mov [cs:Thread64F9],ecx thread64header mov ax,page64_idx mov ss,ax mov es,ax mov ds,ax linear eax,idt_LM_start db 066h db 0eah Thread64F9 dd 0 dw code64_idx IRET n92: IRET n9: ; AX 0x1401 Helper for DISM to take dissassembly cmp ax,0x1401 jnz n1401 ; Input CX:DX output of what we had ; BX # of bytes dissassembled ;break cmp cx,0 jz .nxx cmp dx,0 jz .nxx push ds push es push si push di mov ax,cx mov ds,ax mov si,dx mov ax,DATA16 mov es,ax mov di,dismdata2 mov [es:dismdatac],ebx .rlp: mov al,[ds:si] mov [es:di],al cmp al,0 jz .ee inc si inc di jmp .rlp .ee: pop di pop si pop es pop ds IRET .nxx: ; Return DS:SI the 100 byte buffer mov si,DATA16 mov ds,si xor esi,esi mov si,dismdatac shl esi,16 MOV si,dismdata2 ; mov byte [ds:si],16 ; mov byte [ds:si + 1],2 ; mov byte [ds:si + 2],0x90 ; mov byte [ds:si + 3],0x90 IRET n1401: IRET TempBackRM: mov eax,cr0 and al,not 1 and eax,7FFFFFFFh; Set PE=0 mov cr0,eax db 0eah dw .flush_ipq,CODE16 .flush_ipq: mov ax,STACK16 mov ss,ax xor esp,esp mov sp,stack16dmmi2_end mov ax, DATA16 mov ds,ax mov es,ax mov di,idt_RM_start lidt [di] sti ; execute the interrupt mov ax,DATA32 mov ds,ax mov bp,word [From32To16Regs] mov bx,word [From32To16Regs + 2] mov cx,word [From32To16Regs + 4] mov dx,word [From32To16Regs + 6] mov si,word [From32To16Regs + 8] mov di,word [From32To16Regs + 10] mov ax, word [From32To16Regs + 12] mov gs,ax ; later DS mov ax, word [From32To16Regs + 14] mov fs,ax ; later ES mov al, byte [From32To16Regs + 16] mov [cs:inttt],al cmp al,0 jz skip2 push bp pop ax push gs pop ds push fs pop es db 0xCD inttt db 0 skip2: ; And again protected ; macro EnterProtected ofs32 = Start32,codeseg = code32_idx,noinits = 0 EnterProtected i4BackFromRM,code32_idx TempBackLM: mov eax,cr0 and al,not 1 and eax,7FFFFFFFh; Set PE=0 mov cr0,eax db 0eah dw .flush_ipq,CODE16 .flush_ipq: mov ax,STACK16 mov ss,ax mov sp,stack16dmmi2_end mov ax, DATA16 mov ds,ax mov es,ax mov di,idt_RM_start lidt [di] push cs call EnterUnreal ; execute the interrupt mov ax,STACK16S mov ss,ax xor esp,esp mov esp,stack16dmmi2_end mov ax,DATA64 mov ds,ax mov bp,word [From64To16Regs] mov bx,word [From64To16Regs + 2] mov cx,word [From64To16Regs + 4] mov dx,word [From64To16Regs + 6] mov si,word [From64To16Regs + 8] mov di,word [From64To16Regs + 10] mov ax, word [From64To16Regs + 12] mov gs,ax ; later DS mov ax, word [From64To16Regs + 14] mov fs,ax ; later ES mov al, byte [From64To16Regs + 16] mov [cs:inttt2],al cmp al,0 jz skip3 push bp pop ax push gs pop ds push fs pop es db 0xCD inttt2 db 0 skip3: ; and again long mode thread64header db 066h db 0eah Thread64Ptr3 dd 0 dw code64_idx TempBackLMnnn0: mov eax,cr0 and al,not 1 and eax,7FFFFFFFh; Set PE=0 mov cr0,eax db 0eah dw .flush_ipq,CODE16 .flush_ipq: mov ax, DATA16 mov ds,ax mov es,ax mov di,idt_RM_start lidt [di] ; jmp 0x1234:0x5678 db 0xEA segnnn0 dw 0 ofsnnn0 dw 0 ================================================ FILE: int32.asm ================================================ ; --------------------------------------- int 0xF0 protected --------------------------------------- int32_21: mov bp,ax mov ax,0x0421 int32: jmp .ibegin db 'dmmi' .ibegin: ; AX 0, find interface cmp ax,0 jnz .n0 dh_virtualization; push ds mov ax,data16_idx mov ds,ax mov dl,[numcpus] pop ds mov ax,0xFACE IRETD .n0: ; AH 4, call real mode interrupt ; AL = INT NUM ; BP = AX VALUE ; CX,DX,SI,DI = Normal values ; Upper ESI,EDI => DS and ES cmp ah,4 jnz nn4 push ds push eax mov ax,data32_idx mov ds,ax ; Mutex Lock mov ax,mut_i21 call far code32_idx:qwaitlock32 ; Save: AX,BX,CD,DX,SI,DI,DS,ES mov word [From32To16Regs],bp mov word [From32To16Regs + 2],bx mov word [From32To16Regs + 4],cx mov word [From32To16Regs + 6],dx mov word [From32To16Regs + 8],si mov word [From32To16Regs + 10],di mov eax,esi shr eax,16 mov word [From32To16Regs + 12],ax mov eax,edi shr eax,16 mov word [From32To16Regs + 14],ax pop eax mov byte [From32To16Regs + 16],al ; #intr mov word [From32To16Regs + 18],ss ; save for later mov dword [From32To16Regs + 20],esp ; save for later ; back to real mode db 066h db 0eah dw TempBackRM dw code16_idx i4BackFromRM: mov ax,stack32_idx mov ss,ax mov ax,data32_idx mov ds,ax mov ax,word [From32To16Regs + 18] mov ss,ax mov esp,dword [From32To16Regs + 20] pop ds qunlock32 mut_i21 iretd nn4: ; AH 5, mutex functions cmp ah,5 jnz .n5 ; Initialize mutex cmp al,0 jnz .n50 push fs mov bx,page32_idx mov fs,bx mov byte [fs:edi],0xFF pop fs iretd .n50: ; lock mutex cmp al,2 jnz .n52 push fs mov bx,page32_idx mov fs,bx dec byte [fs:edi] pop fs iretd .n52: ; unlock mutex cmp al,3 jnz .n53 push fs mov bx,page32_idx mov fs,bx cmp byte [fs:edi],0xFF jz .okl inc byte [fs:edi] .okl: pop fs iretd .n53: ; wait mutex cmp al,4 jnz .n54 push fs mov bx,page32_idx mov fs,bx .Loop1: CMP byte [fs:edi],0xff JZ .OutLoop1 pause JMP .Loop1 .OutLoop1: pop fs iretd .n54: IRETd .n5: ; AX 9, switch to mode cmp ah,9 jnz nn9 ; AL 0, unreal cmp al,0 jnz .nn90 ; Back to real mode, ecx = seg:ofs mov ax,page32_idx mov ds,ax linear eax,ofsnnn0,CODE16 mov word [eax],cx shr ecx,16 linear eax,ofsnnn0,CODE16 mov word [eax],cx push code32_idx mov ecx,nnn90Back push ecx retf IRETD .nn90: IRETD nn9: nop iretd CompatFromLongIntF0: ; Disable Paging to get out of Long Mode mov eax, cr0 and eax,7fffffffh mov cr0, eax ; Deactivate Long Mode mov ecx, 0c0000080h rdmsr btc eax, 8 wrmsr ; Disable PAE mov eax, cr4 btc eax, 5 mov cr4, eax ; Go Real db 066h db 0eah dw TempBackLM dw code16_idx nnn90Back: ; Disable Paging to get out of Long Mode mov eax, cr0 and eax,7fffffffh mov cr0, eax ; Deactivate Long Mode mov ecx, 0c0000080h rdmsr btc eax, 8 wrmsr ; Disable PAE mov eax, cr4 btc eax, 5 mov cr4, eax ; Go Real db 066h db 0eah dw TempBackLMnnn0 dw code16_idx ================================================ FILE: int64.asm ================================================ ; --------------------------------------- int 0xF0 long --------------------------------------- int64_21: mov bp,ax mov ax,0x0421 int64: jmp .ibegin db 'dmmi' db 10 dup(0x90) .ibegin: ; AX 0, find interface cmp ax,0 jnz .n0 dh_virtualization; linear rax,numcpus,DATA16 mov dl,[rax] mov rax,0xFACE IRETQ .n0: ; AH 4, call real mode interrupt ; AL = INT NUM ; BP = AX VALUE ; CX,DX,SI,DI = Normal values ; Upper ESI,EDI => DS and ES cmp ah,4 jnz nx4 push rax linear r8,From64To16Regs,DATA64 ; Mutex Lock mov rax,mut_i21 call qwaitlock64 ; Save: AX,BX,CD,DX,SI,DI,DS,ES mov word [r8],bp mov word [r8 + 2],bx mov word [r8 + 4],cx mov word [r8 + 6],dx mov word [r8 + 8],si mov word [r8 + 10],di mov eax,esi shr eax,16 mov word [r8 + 12],ax mov eax,edi shr eax,16 mov word [r8 + 14],ax pop rax mov byte [r8 + 16],al ; #intr mov word [r8 + 18],ss ; save for later mov dword [r8 + 20],esp ; save for later ; go to compatibility mode push code32_idx xor rcx,rcx mov ecx,CompatFromLongIntF0 push rcx retf USE64 BackFromExecutingInterruptLM: linear rax,idt_LM_start lidt [rax] mov ax,page64_idx mov ss,ax linear r8,From64To16Regs,DATA64 xor rsp,rsp mov esp,dword [r8 + 20] qunlock64 mut_i21 iretq nx4: ; AH 5, mutex functions cmp ah,5 jnz .n5 ; Initialize mutex cmp al,0 jnz .n50 mov byte [rdi],0xFF iretq .n50: ; lock mutex cmp al,2 jnz .n52 dec byte [rdi] iretq .n52: ; unlock mutex cmp al,3 jnz .n53 cmp byte [rdi],0xFF jz .okl inc byte [rdi] .okl: iretq .n53: ; wait mutex cmp al,4 jnz .n54 .Loop1: CMP byte [rdi],0xff JZ .OutLoop1 pause JMP .Loop1 .OutLoop1: iretq .n54: IRETQ .n5: ; AX 0x800, disable VMX cmp ax,0x800 jnz nnn800 call VMX_Disable IRETQ nnn800: ; AX 0x801, prepare vmx structures cmp ax,0x801 jnz nnn801 ; r8 host return ; r9 seg vm ; r10 ofs vm call VMX_Init_Structures call VMX_Enable call VMXInit call VMX_InitializeEPT xor rdx,rdx bts rdx,1 bts rdx,7 call VMX_Initialize_VMX_Controls mov rcx,r8 call VMX_Initialize_Host call VMX_Initialize_UnrestrictedGuest call VMXInit2 IRETQ nnn801: ; AX 9, switch to mode cmp ah,9 jnz nnn9 ; AL 0, unreal cmp al,0 jnz .nnn90 linear eax,segnnn0,CODE16 mov word [eax],cx shr ecx,16 linear eax,ofsnnn0,CODE16 mov word [eax],cx ; Back to Compatibility Mode push code32_idx xor rcx,rcx mov ecx,nnn90Back push rcx retf IRETQ .nnn90: IRETQ nnn9: IRETQ ================================================ FILE: iso.ps1 ================================================ function New-IsoFile { <# .Synopsis Creates a new .iso file .Description The New-IsoFile cmdlet creates a new .iso file containing content from chosen folders .Example New-IsoFile "c:\tools","c:Downloads\utils" This command creates a .iso file in $env:temp folder (default location) that contains c:\tools and c:\downloads\utils folders. The folders themselves are included at the root of the .iso image. .Example New-IsoFile -FromClipboard -Verbose Before running this command, select and copy (Ctrl-C) files/folders in Explorer first. .Example dir c:\WinPE | New-IsoFile -Path c:\temp\WinPE.iso -BootFile "${env:ProgramFiles(x86)}\Windows Kits\10\Assessment and Deployment Kit\Deployment Tools\amd64\Oscdimg\efisys.bin" -Media DVDPLUSR -Title "WinPE" This command creates a bootable .iso file containing the content from c:\WinPE folder, but the folder itself isn't included. Boot file etfsboot.com can be found in Windows ADK. Refer to IMAPI_MEDIA_PHYSICAL_TYPE enumeration for possible media types: http://msdn.microsoft.com/en-us/library/windows/desktop/aa366217(v=vs.85).aspx .Notes NAME: New-IsoFile AUTHOR: Chris Wu LASTEDIT: 03/23/2016 14:46:50 #> [CmdletBinding(DefaultParameterSetName='Source')]Param( [parameter(Position=1,Mandatory=$true,ValueFromPipeline=$true, ParameterSetName='Source')]$Source, [parameter(Position=2)][string]$Path = "$env:temp\$((Get-Date).ToString('yyyyMMdd-HHmmss.ffff')).iso", [ValidateScript({Test-Path -LiteralPath $_ -PathType Leaf})][string]$BootFile = $null, [ValidateSet('CDR','CDRW','DVDRAM','DVDPLUSR','DVDPLUSRW','DVDPLUSR_DUALLAYER','DVDDASHR','DVDDASHRW','DVDDASHR_DUALLAYER','DISK','DVDPLUSRW_DUALLAYER','BDR','BDRE')][string] $Media = 'CDR', [string]$Title = (Get-Date).ToString("yyyyMMdd-HHmmss.ffff"), [switch]$Force, [parameter(ParameterSetName='Clipboard')][switch]$FromClipboard ) Begin { ($cp = new-object System.CodeDom.Compiler.CompilerParameters).CompilerOptions = '/unsafe' if (!('ISOFile' -as [type])) { Add-Type -CompilerParameters $cp -TypeDefinition @' public class ISOFile { public unsafe static void Create(string Path, object Stream, int BlockSize, int TotalBlocks) { int bytes = 0; byte[] buf = new byte[BlockSize]; var ptr = (System.IntPtr)(&bytes); var o = System.IO.File.OpenWrite(Path); var i = Stream as System.Runtime.InteropServices.ComTypes.IStream; if (o != null) { while (TotalBlocks-- > 0) { i.Read(buf, BlockSize, ptr); o.Write(buf, 0, bytes); } o.Flush(); o.Close(); } } } '@ } if ($BootFile) { if('BDR','BDRE' -contains $Media) { Write-Warning "Bootable image doesn't seem to work with media type $Media" } ($Stream = New-Object -ComObject ADODB.Stream -Property @{Type=1}).Open() # adFileTypeBinary $Stream.LoadFromFile((Get-Item -LiteralPath $BootFile).Fullname) ($Boot = New-Object -ComObject IMAPI2FS.BootOptions).AssignBootImage($Stream) } $MediaType = @('UNKNOWN','CDROM','CDR','CDRW','DVDROM','DVDRAM','DVDPLUSR','DVDPLUSRW','DVDPLUSR_DUALLAYER','DVDDASHR','DVDDASHRW','DVDDASHR_DUALLAYER','DISK','DVDPLUSRW_DUALLAYER','HDDVDROM','HDDVDR','HDDVDRAM','BDROM','BDR','BDRE') Write "Selected media type is $Media with value $($MediaType.IndexOf($Media))" ($Image = New-Object -com IMAPI2FS.MsftFileSystemImage -Property @{VolumeName=$Title}).ChooseImageDefaultsForMediaType($MediaType.IndexOf($Media)) if (!($Target = New-Item -Path $Path -ItemType File -Force:$Force -ErrorAction SilentlyContinue)) { Write "Cannot create file $Path. Use -Force parameter to overwrite if the target file already exists."; break } } Process { if($FromClipboard) { if($PSVersionTable.PSVersion.Major -lt 5) { Write 'The -FromClipboard parameter is only supported on PowerShell v5 or higher'; break } $Source = Get-Clipboard -Format FileDropList } foreach($item in $Source) { if($item -isnot [System.IO.FileInfo] -and $item -isnot [System.IO.DirectoryInfo]) { $item = Get-Item -LiteralPath $item } if($item) { Write "Adding item to the target image: $($item.FullName)" try { $Image.Root.AddTree($item.FullName, $true) } catch { Write ($_.Exception.Message.Trim() + ' Try a different media type.') } } } } End { if ($Boot) { $Image.BootImageOptions=$Boot } $Result = $Image.CreateResultImage() [ISOFile]::Create($Target.FullName,$Result.ImageStream,$Result.BlockSize,$Result.TotalBlocks) Write "Target image ($($Target.FullName)) has been created" $Target } } get-childitem ".\cd" | New-ISOFile -force -path d.iso ================================================ FILE: leheader.asm ================================================ ; ; FASM example of creation of a linear ( exponential soon Very Happy ) ; executable ("LE") for running on DOS/32A extender. ; ; Compiles directly from .ASM into .LE , no linker Very Happy ; ; Use "SB" tool to bind it with the extender. ; ; http://board.flatassembler.net/topic.php?t=7122 ; ; Limitations: ; - No relocs (crappy anyway) ; - Only one "object" ( no problem, flat rules Very Happy ) ; ; Size should be no problem, tested with 2 MiB, should ; support up to 2 Gib Wink ; format binary as "LE" use32 org 0 ; *** Constants *** ccstackp = 2 ; Stack size in pages ( 1 page = 4 KiB ) ; *** Calculations *** vvstackb = ccstackp shl 12 ; Pages -> Bytes vvcodesize = llcodeend - llcode vvcodep = ( vvcodesize + $0FFF ) shr 12 ; Bytes -> Pages vvpagestotal = vvcodep + ccstackp vvpagestotalali = ( vvpagestotal + 3 ) and $000FFFFC ; Align to integer multi of 4 vvcodepad = 2 ; Allign code size to integer multi of $10, and add 2 to make loader / DOS happy vvtemp1 = vvcodesize and $0F ; Temp, find out used bytes on last 16-Bytes block if vvtemp1 > 0 vvcodepad = 18 - vvtemp1 end if ; *** LE / [LX] "Module Header" (0,$AC) *** ;org 0 db "LE" db 0,0 ; Little endian, surprisingly Very Happy db 0,0,0,0 ; "level" ... of zeroizm db 2,0 ; 80386 db 1,0 ; "OS/2" Osama's System Very Happy db 0,0,0,0 ; "module version" ; org $10 dd 0 ; "module type", crap dd vvpagestotal ; Number of pages total dd 1,0 ; CS:EIP object number (4 bytes) & offset (4 bytes) ; org $20 dd 2, vvstackb ; SS:ESP object number (4 bytes) & offset (4 bytes) dd $1000 ; Page size in bytes dd 0 ; LX: "shift" alignement (4 -> $10 bytes) | LE: bytes on last page | crap Sad ; org $30 dd vvpagestotalali shl 2 , 0 ; "fixup" size, chk | "size" may NEVER be 0 !!! Can be skipped in LE, but not empty dd $30,0 ; "loader" size, chk ; org $40 dd $B0 ; Offset of the "Object table" (relative to "LE") dd 2 ; Number of entries dd $E0 ; LX: Offset of the "Object Page Table" | LE: Offset of object "Map" !!! dd 0 ; Offset of ??? , "iterate" crap ; org $50 dd 0 ; Offset ressource table dd 0 ; Number of entries dd 0 ; Offset "resident" crap dd 0 ; Offset of "entry" crap table Sad ; org $60 dd 0,0 ; "MD" offset & entries, useless junk Very Happy dd $E0 ; Fixup offset 1, important in LX only !!! dd $E0 ; Fixup offset 2, useless junk both LE and LX Wink ; org $70 dd 0,0 ; Import offset, count, both junk dd 0,0 ; 2 more offsets, crap ; org $80 dd llcode ; "Data pages offset" - where the code begins, relative to MZ, not "LE" !!! ; "SB" will care when binding ... just v. 7.1 won't - it has a BUG !!! Sad dd 0,0,0 ; Some more crap ; org $90 dd 0,0,0,0 ; Useless "chk", "auto", 2 x deBUG ; org $A0 dd 0,0,0 ; Crap / "heap" ; *** Reserved / crap ($AC,4) *** dd 0 ; *** Object table entry #1 ($B0,$18 ) (main) *** ; Flags can be $2045 (R) or $2047 (R&W) dd vvcodep shl 12 ; Size in bytes (we always align to 4 KiB) dd 0 ; Base address won't work, let's set it to most funny value of 0 dd $2047 ; Flags: "huge 32-bit" | "preloaded" | "executable" | "writable" | "readable" dd 1,vvcodep ; "map" index (count from 1 ???) / entries dd 0 ; Reserved / crap ; *** Object table entry #2 ($C8,$18 ) (stack) *** ; !!! Stack may *** NEVER *** be executable !!! dd ccstackp shl 12 ; Size in bytes dd 0 ; Base address won't work dd $2043 ; Flags: "huge 32-bit" | "preloaded" | "writable" | "readable" dd 1+vvcodep,ccstackp ; "map" index / entries dd 0 ; Reserved / crap ; *** Object Page Map ($E0,n*$10 ) | Fixup 1st Table | Fixup 2nd Table *** dd vvpagestotalali dup (0) ; Crap, one "dd" zero needed per page macro laddr reg,ofs { local thiscall call thiscall thiscall: pop reg add reg,ofs-thiscall } ; *** Code, forget about "org", never loads correctly Wink *** ; "org" $F0 minimum, always $10 bytes aligned llcode: include 'lemain.asm' llcodeend: db vvcodepad dup (0) ; Crap, to prevent unexpected EOF ;end. ================================================ FILE: lemain.asm ================================================ ; le-main, 32-bit flat, everything is inside here jmp main tx1b db 'Hello from protected mode, using DOS/32A, coded with FASM !!!',0x0D,0x0A,0x24 main: laddr edx,tx1b mov ah,9 int 0x21 mov ax,0x4C00 int 0x21 ================================================ FILE: mdebug.asm ================================================ FORMAT MZ HEAP 0 include 'struct.asm' ; stack segment STACK16 USE16 dw 128 dup(0) stre: dw 128 dup(0) stx1e: ; data segment DATA16 USE16 run db 0 psp dw 0 m1 db "Multicore Debugger, (C) Chourdakis Michael",0x0D,0x0A,"$" prg db "d:\debuggee.exe",0x0 struc LoadX a,b,c,d,e,f,g { .f1 dw a .f2 dd b .f3 dd c .f4 dd d .sp dw g .ss dw f .cs dw e .ip dw e } bbb LoadX 0,0,0,0,0,0,0 mut0 db 0 ; main segment CODE16 USE16 include "mdebugcore.asm" include "reqdmmi.asm" start16: mov ax,STACK16 mov ss,ax mov eax,stre mov esp,eax mov ax,DATA16 mov ds,ax mov es,ax mov ax,0x0900 mov dx,m1 int 0x21 RequireDMMI ; enter unreal mov ax,0x0900 int 0xF0 ; Load executable mov bx,bbb mov dx,prg mov ax,0x4B01 int 0x21 jc endx BackExecutable: mov ax,DATA16 mov ds,ax cmp [run],1 je endx2 mov [run],1 mov ah,0x62 int 0x21 mov [psp],bx ; mutexes mov ax,DATA16 mov es,ax mov ax,0x0500 mov di,mut0 int 0xF0 mov ax,DATA16 mov es,ax mov ax,0x0502 mov di,mut0 int 0xF0 ; start thread mov ax,CODE16 mov es,ax mov dx,Thr mov ax,0x0100 mov bl,1 mov cx,STACK16 mov gs,cx mov cx,stx1e int 0xF0 ; run mov ax,DATA16 mov ds,ax mov ax,[bbb.sp] mov sp,ax mov ax,[bbb.ss] mov ss,ax mov ax,[bbb.ip] push ax mov ax,[bbb.cs] push ax retf endx2: ; wait mutex mov ax,DATA16 mov es,ax mov ax,0x0504 mov di,mut0 int 0xF0 endx: ; End mov ax,0x4C00 int 0x21 SEGMENT ENDS entry CODE16:start16 ================================================ FILE: mdebugcore.asm ================================================ Thr: ; mutex release mov ax,DATA16 mov es,ax mov ax,0x0503 mov di,mut0 int 0xF0 retf ================================================ FILE: mutex16.asm ================================================ USE16 macro qlock16 trg,del = -1 { push ds push di push ecx MOV DI,DATA16 MOV DS,DI MOV DI,trg dec byte [ds:di] pop ecx pop di pop ds } macro qunlock16 trg { push ds push di MOV DI,DATA16 MOV DS,DI MOV DI,trg cmp byte [ds:di],0xFF jz .unlk inc byte [ds:di] .unlk: pop di pop ds } qwait16: ; ax = target mutex in data16 push ds push di MOV DI,DATA16 MOV DS,DI MOV DI,ax .Loop1: CMP byte [ds:di],0xff JZ .OutLoop1 pause JMP .Loop1 .OutLoop1: pop di pop ds retf qwaitlock16: ; ax = target mutex in data16 push bx push ds push di MOV DI,DATA16 MOV DS,DI MOV DI,ax .Loop1: CMP byte [ds:di],0xff JZ .OutLoop1 pause JMP .Loop1 .OutLoop1: ; Lock is free, can we grab it? mov bl,0xfe MOV AL,0xFF LOCK CMPXCHG [DS:DI],bl JNZ .Loop1 ; Write failed .OutLoop2: ; Lock Acquired pop di pop ds pop bx retf ================================================ FILE: mutex32.asm ================================================ USE32 macro qlock32 trg { push ds push di push ecx MOV DI,data16_idx MOV DS,DI MOV DI,trg dec byte [ds:di] pop ecx pop di pop ds } macro qunlock32 trg { push ds push di MOV DI,data16_idx MOV DS,DI MOV DI,trg cmp byte [ds:di],0xFF jz .unlk inc byte [ds:di] .unlk: pop di pop ds } qwait32: ; ax = target mutex in data16 push ds push di MOV DI,data16_idx MOV DS,DI MOV DI,ax .Loop1: CMP byte [ds:di],0xff JZ .OutLoop1 pause JMP .Loop1 .OutLoop1: pop di pop ds retf qwaitlock32: ; ax = target mutex in data16 push bx push ds push di MOV DI,data16_idx MOV DS,DI MOV DI,ax .Loop1: CMP byte [ds:di],0xff JZ .OutLoop1 pause JMP .Loop1 .OutLoop1: ; Lock is free, can we grab it? mov bl,0xfe MOV AL,0xFF LOCK CMPXCHG [DS:DI],bl JNZ .Loop1 ; Write failed .OutLoop2: ; Lock Acquired pop di pop ds pop bx retf ================================================ FILE: mutex64.asm ================================================ USE64 macro qlock64 trg { push rcx linear rcx,trg dec byte [rcx] pop rcx } macro qunlock64 trg { push rcx linear rcx,trg cmp byte [rcx],0xFF jz .unlk inc byte [rcx] .unlk: pop rcx } qwait64: ; ax = target mutex in data16 push rcx linear rcx,rax .Loop1: CMP byte [rcx],0xff JZ .OutLoop1 pause JMP .Loop1 .OutLoop1: pop rcx ret qwaitlock64: ; rax = target mutex in data16 push rbx push rcx linear rcx,rax .Loop1: mov al,[rcx] CMP al,0xff JZ .OutLoop1 pause JMP .Loop1 .OutLoop1: ; Lock is free, can we grab it? mov bl,0xfe MOV AL,0xFF LOCK CMPXCHG [rcx],bl JNZ .Loop1 ; Write failed .OutLoop2: ; Lock Acquired pop rcx pop rbx ret ================================================ FILE: opcodes.asm ================================================ op1: rdtscp ret OpcodeTest: call op1 ret ================================================ FILE: page16.asm ================================================ ; --------------------------------------- 16 bit Paging routines to map 1GB --------------------------------------- USE16 ; We will call this from real mode to enter long mode directly when needed InitPageTableFor64: ; a function to use 1GB pages pushad push es push gs mov ax,DATA16 mov gs,ax mov esi,[gs:PhysicalPagingOffset64] ; Put the PML4T to 0x0000, these are 512 entries, so it takes 0x1000 bytes ; We only want the first PML4T mov eax,esi add eax,0x1000 ; point it to the first PDPT or eax,3 ; Present, Readable/Writable mov [fs:esi + 0x0000],eax mov ecx,4 ; Map 4GB (512*1GB). mov eax,0x83 ; Also bit 7 mov edi,esi add edi,0x1000 .lxf1: mov [fs:edi],eax add eax,1024*1024*1024 add edi,8 loop .lxf1 pop gs pop es popad retf ================================================ FILE: page32.asm ================================================ ; --------------------------------------- Paging routines --------------------------------------- USE32 InitPageTable32a: ; A more clean version of what we are doing. ; We map the entire 4GB address space (1024*1024*4096) See Through pushad push ds push es mov ax,data16_idx push gs mov gs,ax mov ebp,[gs:PhysicalPagingOffset32] pop gs mov ax,page32_idx mov ds,ax mov es,ax ; Tables Clear mov edi,ebp mov ecx,2048 xor eax,eax rep stosd ; PageDir32 points to PageTables32 ; Create 1024 entries mov edi,ebp xor ecx,ecx LoopPageDir1: xor eax,eax mov eax,ebp add eax,4096 shr eax,12 ; Get rid of lower 12 bits (4096 alignment) mov ebx,ecx add eax,ebx shl eax,12 or al,7 ; Present, Writable, Everyone, stosd inc ecx cmp ecx,1024 jnz LoopPageDir1 ; PageTables32 create 1024 entries mov edi,ebp add edi,4096 xor ecx,ecx LoopPageTables1: xor eax,eax mov eax,0 ; See-Through, so we start at 0 add eax,ecx shl eax,12 or al,7 ; Present, Writable, Everyone, stosd inc ecx cmp ecx,1024 jnz LoopPageTables1 pop es pop ds popad ret InitPageTable642: pushad push ds push es mov ax,data16_idx push gs mov gs,ax mov esi,[gs:PhysicalPagingOffset64] pop gs mov ax,page64_idx mov ds,ax mov es,ax xor eax, eax mov edi,esi mov ecx,03000h rep stosb ;top level page table mov eax, esi add eax,0x1000 or eax,3 mov [esi],eax mov eax, esi add eax,0x2000 or eax,3 mov [esi + 0x1000],eax ;2MB pages to identity map the first 16MB ram mov eax,1 shl eax,7 or eax,3 mov [esi + 0x2000],eax add eax,0x200000 mov [esi + 0x2008],eax add eax,0x200000 mov [esi + 0x2010],eax add eax,0x200000 mov [esi + 0x2018],eax add eax,0x200000 mov [esi + 0x2020],eax add eax,0x200000 mov [esi + 0x2028],eax add eax,0x200000 mov [esi + 0x2030],eax add eax,0x200000 mov [esi + 0x2038],eax pop es pop ds popad ret InitPageTable643: ; a function to use 1GB pages pushad push es push gs mov ax,data16_idx mov gs,ax mov ax,page32_idx mov es,ax mov esi,[gs:PhysicalPagingOffset64] ; clear mov edi,esi xor eax,eax mov ecx,03000h rep stosb ; Put the PML4T to 0x0000, these are 512 entries, so it takes 0x1000 bytes ; We only want the first PML4T mov eax,esi add eax,0x1000 ; point it to the first PDPT or eax,3 ; Present, Readable/Writable mov [es:esi + 0x0000],eax mov ecx,4 ; Map 4GB (512*1GB). mov eax,0x83 ; Also bit 7 mov edi,esi add edi,0x1000 .lxf1: mov [es:edi],eax add eax,1024*1024*1024 add edi,8 loop .lxf1 pop gs pop es popad ret ================================================ FILE: qlink/QLINK.CFG ================================================ # QLINK Configuration File # Put additional switches here rather than the command line # to avoid cluttering up that resource. # Switch list ################## # /F:switch to fail on event named 'switch' # /W:switch to warn on event named 'switch' and take default action # /I:switch to ignore event named 'switch' and take default action # Where 'switch' is one of the following: # ALL = Set all of the switches below to the specified state. # OMFIGN = An OMF record is encountered which is ignorable (typically # this record is obsolete). The ignore/warn action is to # ignore the record. # OMFUNK = An unknown OMF record is encountered. Either QLINK # doesn't implement that record (please call us), or the # .OBJ file is corrupted (but not so corrupted as to fail # the checksum test). The ignore/warn action is to ignore # the record. # CSUMINV = An OMF record' checksum is invalid. Some language # translators don't compute a proper checksum, but they # should put in a zero for the checksum field which QLINK # allows. Something else is going on. The ignore/warn # action is to ignore the invalid checksum and process the # record. # CTYPINV = A SEGDEF record has an invalid combine type. The # ignore/warn action is to use a combine type of private (do # not combine). # ALININV = A SEGDEF record has an invalid alignment type. The # ignore/warn action is to use an alignment of byte. # ALINDIF = Two SEGDEF records describing the same segment/class have # different alignment types. The ignore/warn action is to # use the actual alignment type for each segment. # USEDIF = Two SEGDEF records desribing the same segment/class have # different USE16/USE32 attributes. The ignore/warn action # is to use USE32 as the segment attribute. # GRPINV = A GRPDEF record has an invalid group component descriptor # (it should be FF, but isn't). The ignore/warn action is # to ignore the value. # GRPDIF = A segment is contained in two different groups. The # ignore/warn action is to ignore the second and subsequent # grouping of the segment. # SEGBIG = A USE16 segment exceeds 64KB in size. The ignore/warn # action is to ignore the problem. You fix it. # GRPBIG = A USE16 segment in a group ends above 64KB. The # ignore/warn action is to ignore the problem. # GRPMIX = A group has mixed absolute and relocatable segments. The # ignore/warn action is to ignore the problem. # FIXOVF = The value of an external reference is wider than the # target field. The ignore/warn action is to shorten the # value to fit the field and then ignore the problem, # although you shouldn't. # FIXOVF$ = The value of an external reference is wider than the # target field in a segment named '$$SYMBOLS'. The # ignore/warn action is to shorten the value to fit the # field and then ignore the problem. # ABSOVF = The value of an absolute constant is wider than the # target field. The ignore/warn action is to fixup the # location with the wider value. This can happen due to a # bug in MASM 5.10b where it generates an incorrect .OBJ # record when referencing an external absolute constant in a # DD of DF field (it marks is as a word width rather than a # dword width). # ABSDIF = A group has absolute segments with differing starting # addresses. The ignore/warn action is to ignore the # problem. # TYPDIF = Tyep indices differ between two occurrences of the same # symbol. The ignore/warn action is to ignore the problem. # SEGEXT = A FIXUPP record has an external target in a different # segment than the frame segment. The ignore/warn action is # to calculate the fixup using the difference between the # two segments. # SEGEXT0 = A FIXUPP record has an external target not in a segment # whereas the frame is a segment. The ignore/warn action is # to ignore the frame segment. # GRPEXT = The group which contains an external Target in a FIXUPP # record is different from the Frame group. This can occur # due to incorrect assume statements. For example, if you # put data variables in a code segment (with, say, ASSUME # CS:PGROUP), be sure to use a corresponding ASSUME # DS:PGROUP as the assume for DS is the segment/group # reference used as the frame for data variables. The # ignore/warn action is to ignore the problem, but you # shouldn't. # GRPEXT0 = The group which contains an ungrouped external Target in a # FIXUPP record is different from the Frame group. This can # occur due to incorrect assume statements. For example, if # you put data variables in a code segment (with, say, # ASSUME CS:PGROUP), be sure to use a corresponding ASSUME # DS:PGROUP as the assume for DS is the segment/group # reference used as the frame for data variables. The # ignore/warn action is to ignore the problem, but you # shouldn't. # RELGRP = A self-relative FIXUPP record has a frame group which does # not contain the fixup segment. The ignore/warn action is # to calculate the fixup using the difference between the # fixup segment and the frame group. # RELSEG = A self-relative FIXUPP record has a frame segment which is # not the same as the fixup segment. The ignore/warn action # is the calculate the fixup using the difference between # the fixup segment and the frame segment. # RELTGT = A self-relative FIXUPP record has a frame segment which is # not the same as the target segment. The ignore/warn action # is the calculate the fixup using the difference between # the target segment and the frame segment. # RELGRPX = A self-relative FIXUPP record has an external frame group # which does not contain the fixup segment. The ignore/warn # action is to calculate the fixup using the difference # between the fixup segment and the frame group. # RELSEGX = A self-relative FIXUPP record has an external frame # segment which is not the same as the fixup segment. The # ignore/warn action is the calculate the fixup using the # difference between the fixup segment and the frame # segment. # PUBDIF = In a PUBDEF record, the referenced segment is not # contained in the referenced group. The ignore/warn action # is to ignore the problem. # LINDIF = In a LINNUM record, the referenced segment is not # contained in the referenced group. The ignore/warn action # is to ignore the problem. # FIXDIF = In a FIXUPP record, the Frame or Target group does not # contain the Target or Frame segment. The ignore/warn # action is to ignore the problem. # FIXDIFX = In a FIXUPP record, the Frame or Target segment is not # contained in any group, but there's a Target or Frame # group. The ignore/warn action is to ignore the problem. # FRMSEG = The Frame base of a FIXUPP record is a segment, but # perhaps should be the group which contains the segment. # The ignore/warn action is to ignore the problem. # FRMSEG0 = The Frame base of a FIXUPP record is a segment, but # perhaps should be the group which contains the segment, # although the segment is the first one in the group. The # default action is to ignore this problem. The ignore/warn # action is to ignore the problem. # FRMSEG$ = A FRMSEG error has occurred for a fixup in a segment # named '$$SYMBOLS'. The default action is to ignore this # problem. The ignore/warn action is to ignore the problem. # THRINV = The Target Method field of a thread FIXUPP record is > 3. # The The ignore/warn action is to reduce the method number # modulo 4. # BAKPAT = A BAKPAT record has an invalid location type (> 2). The # default action is to fail. The ignore/warn action is to use a # byte-wide location. # NBKPAT = A NBKPAT record has an invalid location type (> 2). The # default action is to fail. The ignore/warn action is to use a # byte-wide location. # EXTMAT = Ensure that all EXTDEFs have a matching reference to them. # If not, then presumably the corresponding extrn can be # deleted. The ignore/warn action is to ignore the problem. # MTOBJ = Ensure that all .OBJ files are nonempty. If not, then likely # the assembler/compiler didn't complete its job. The # The ignore/warn action is to ignore the empty file. # BLKDEF = Normally, you should ignore a Block Definition Record as # it is ignored by QLINK. The only reason this switch is # present is so the default action can be /I as opposed to # having to ignore all OMFIGN records some of which might be # of interest. The ignore/warn action is to ignore the # problem. # BLKEND = Normally, you should ignore a Block End Record as it is # ignored by QLINK. The only reason this switch is present # is so the default action can be /I as opposed to having to # ignore all OMFIGN records some of which might be of # interest. The ignore/warn action is to ignore the # problem. # TYPDEF = Normally, you should ignore a Type Definition Record as # it is ignored by QLINK. The only reason this switch is # present is so the default action can be /I as opposed to # having to ignore all OMFIGN records some of which might be # of interest. The ignore/warn action is to ignore the # problem. ###################################################################### # Default settings # # The default setting for all error messages is /F:switch for all # switches (i.e., /F:ALL), except for EXTMAT, THRINV, BLKDEF, BLKEND, # TYPDEF, FRMSEG0, FRMSEG$, and FIXOVF$ for which the default setting # is to ignore. ================================================ FILE: qlink/QLINK.HTM ================================================ Qualitas Linker

QLINK Documentation File
Version 5.08
23 March 2006

Overview

QLINK is a DOS linker and analysis tool designed to link together MS-DOS compatible .OBJ files.  It can replace the MS-DOS LINK.EXE program when producing MS-DOS compatible .EXE and .COM files.

Installation

Make a directory (e.g., C:\QLINK), copy the zip file to that directory, and unzip the files:

MD C:\QLINK
CD C:\QLINK
COPY A:\QLINK.ZIP
PKUNZIP QLINK.ZIP

If you'll be running QLINK under Windows 3.1x (see below for Win95 instructions), copy the file WINDPMI.386 to your Windows system directory.  For example, if you installed Windows into the directory C:\WINDOWS, copy WINDPMI.386 to C:\WINDOWS\SYSTEM.  Then edit your Windows SYSTEM.INI file to insert a line such as the following in the [386ENH] section:

    device=windpmi.386

You should first ensure that no other similar line already appears in your SYSTEM.INI file.  For example, you might already have a line such as

    device=c:\bc4\bin\windpmi.386

If this is the case, do not insert another call to the same driver; you need only one. This VxD does not work with Win9x.

If you'll be running QLINK under Win9x, follow the above procedure using the file W95DPMI.386 instead of WINDPMI.386.

Benefits

  • One pass linker (using uncommitted memory in DPMI 1.0)
  • Better performance (typically twice as fast as MS LINK, sometimes ten times faster)
  • Handles USE32 segments > 64KB
  • Detailed error checking to the point that it becomes a highly valuable analysis tool
  • Detailed error information (e.g., source code line number info (if in .OBJ file) for fixup overflows)
  • Type checking between .OBJ files (if in .OBJ files).

System Requirements

  • MS-DOS 3.x or later
  • DPMI host which supports DPMI 1.0 calls -- use either 386MAX version 7.0 or later, or Windows 3.1 with a (supplied) VxD from Borland (WINDPMI.386), or Win95 with a different VxD (W95DPMI.386), or DPMIONE.

How To Use

For the most part, just call QLINK instead of LINK or TLINK as appropriate.  Borland users should note that a number of Borland specific Object Module Formats (OMFs) are not implemented as yet (I'm waiting for the documentation from Borland).  Several MS link switches are not supported as yet (e.g., /PACKC).  If there are switches you particularly need which are not supported, let me know.  For an explanation of the old linker switches, see your linker manual.

Tips

To take advantage of the detailed error processing in QLINK, use the assembler switches which generate types and line numbers.  For MASM and TASM these switches are /Zd and /Zi.

Segment Ordering

The order in which segments appear in the executable file depends on several factors.  The first is whether or not the /DOSSEG switch appears explicitly on the command line or implicitly in a OMF record in one of the .OBJ files.

If /DOSSEG is specified, the segment order is as follows:

  • All segments with a class name ending in 'CODE'
  • All other segments not in DGROUP, grouping together segments with the same class name
  • DGROUP segments in the following order:
    • Any segments of class 'BEGDATA'
    • Any segment not of class 'BEGDATA', 'BSS', or 'STACK'
    • Segments of class 'BSS'
    • Segments of class 'STACK'

Otherwise, the segment order is as follows:

  • All unclassed segments
  • All classed segments by class (that is, segments in the same class appear adjacent to each other).

Error Messages

There are a number of switches specific to QLINK which are documented in the file QLINK.CFG.  These switches control the processing of error messages from QLINK.   All error messages begin with either

==> WARN:

or

==> FAIL:

Messages which begin with WARN are warnings and do not halt the linker.  Messages which being with FAIL cause the linker to stop immediately and not continue processing the input files.

If an error message is followed by a name such as FIXOVF or GRPEXT0 in parentheses, then that error can be controlled by the switches /I:switch, /W:switch, and /F:switch, where switch is the name in parentheses in the error message.

If you wish to ignore this error (meaning the linker takes a default action and continues processing), use /I:switch.  To warn about an error (meaning an error message is displayed, the linker takes a default action, and continues processing), use /W:switch.  The default settings for all error messages are described in the file QLINK.CFG.

This same file (QLINK.CFG) is consulted when QLINK begins execution.  Any switches found there (including switches such as /MAP, /LINE, etc.) are processed before the command line is parsed.  Switches only may be contained in QLINK.CFG, not names of .OBJ files, etc.  Even earlier in the process, the environment variable QLINK= is consulted, and it too may contain only switches.

Thus the order of processing of switches is first, those contained in the environment variable QLINK=, then those in the file QLINK.CFG (first in the current directory, and if not found there in the directory from which QLINK is loaded), and finally those found on the command line to QLINK.  Switches processed later in the sequence override ones processed earlier.

Name Substitutions

Occasionally, you want to link together .OBJ modules from different projects which use different naming conventions.  For example, in one project code segments are in class CODE and in others they are in class PROG.  Previously, you would have to edit the source code, make the changes, and re-compile.  With the Name Substitution feature of QLINK, it's a snap.

To substitute names on the fly within the .OBJ file, place the switch /NS before the reference to each .OBJ file whose names are to be substituted.  For example, use /NS:PROG-CODE to tell QLINK that the name PROG is to be changed to CODE.

Each substitution is effective for all .OBJ files which appear after it until that substitution (or all substitutions) are halted.  Use the form /NS:name to halt substitutions on name; use /NS with no arguments to halt all substitutions.

Note that this means that the occurrences of /NS are sensitive to the position and order in which they appear.  Be sure to place occurrences of /NS before the reference to the .OBJ file to which they apply.

To swap two symbols in the same file, use (say) /NS:A-B:B-A.

The substitution is made on all references to the name regardless of context.  Thus if you have a file with a segment named PROG and a class named PROG, substituting CODE for PROG changes both references.

The full syntax is

Nameset:   (empty)                 ; Halt substitution on all names
          | name                   ; Halt substitution on this name
          | name '-' name          ; Substitute the second name for the first name

Namedef:    Nameset
          | Namedef ':' Nameset

Switch:     '/NS:' Namedef

The keyword /NS may appear in the QLINK environment variable, the QLINK.CFG configuration file, the automatic response file, and the QLINK command line.

Frequently Asked Questions

Q:  When I link modules with the MS linker and QLINK, sometimes the executable files are of very different sizes?
A:  This can occur if a .LIB is used to resolve external references.  Because there is no rule as to the order in which external refs are processed, different ordering of these references mean that there can be different segment boundary alignments which can change the final executable file size.

Future Work

In no particular order of importance (nor of expectation of getting done), the following topics are on my list:

  • Support Borland-specific OMFs
  • Support MS-specific OMFs (for which I don't have any examples)
  • External procedure for symbol processing (instead of reading .MAP file)
  • Allow segment attribute changes per .OBJ file
  • Generate Windows compatible .EXEs
  • Generate Code view information
  • Generate Turbo Debugger information
  • Compress .EXE using LZH or some such technique (for Windows executables as well)
  • Finish type checking of structures

Please feel free to add to this list.

Technical Support

Please contact the author via Internet e-mail at

    (Bob Smith)

QLINK is © Copyright 1994-2006 Qualitas, Inc.  All rights reserved.

Change History

5.08    23 March 2006

  • Fix bug in .LIB symbol compares for case-insensitive libraries whose symbols contain uppercase letters (thanks Bob Snuggs).

5.07    2 January 2004

  • Fix bug which prevents multiple .LIB files from being recognized (thanks Japheth).

5.06    24 December 2003

  • Catch invalid OMF record where an LIDATA record has a zero repeat count.

5.05    19 June 2003

  • Mark COMM variables as USE32 if the segment in which they are defined (c_common or FAR_BSS) is USE32.
  • Load .OBJ files into extended memory instead of low DOS in case there's not enough room.
  • Implement undocumented /KNOWEAS for compatibility with MS linker.

5.04    22 May 2003

  • Added more information to USEDIF error message to point to .OBJ file in which the segment was first defined.
  • Added references to DPMIONE as a DPMI 1.0 host under which QLINK runs.

5.03    21 July 2002

  • Modified the change in version 5.00 for fixup overflows to treat the Target Displacement as a signed number and then ignore overflows if the upper 24- (for byte fixups) or 16-bits (for word fixups) are all ones.

5.02    1 July 2002

  • Fix bug where a MODEND fixup generating any kind of error causes the routine which displays the .OBJ file name to fail (thanks to Vladomir Rodriquez for pointing this out).

5.01    26 June 2002

  • Fix bug where .MAP file occasionally not written out.
  • Display segment combine type in /MAP:FULL.
  • Fix bug in display of line #s for grouped segments which are not first in the group.
  • Append IGNOREd errors to .ERR file if /DEBUG:ERR in effect.
  • Added FIXOVF$ switch to ignore fixup overflows in '$$SYMBOLS' segments.
  • Fix bug when parsing command line and/or .ARF file if leading '+' in multiple entry (.OBJ or .LIB) fields.

5.00    26 June 2002

  • Change version # to 5 to workaround bug in EXEHDR.
  • Fix bug in display of FRMSEG$ message.
  • Display error message if not enough memory to enter PM through the DPMI host.
  • Fix bug when checking for fixup overflows where the displacement wasn't added in before the overflow check, thus missing some overflows (thanks to Vladomir Rodriquez for pointing this out).

1.30    22 June 2002

  • Added MTOBJ switch to fail on empty .OBJ files which can occur when a language translator creates an object file but halts for some reason before writing anything to it.

1.29    18 April 2002

  • Fix bug to change ignore/warn action on OMFUNK to ignore the record.

1.28    25 April 2000

  • Fix bug handling weak externs if the symbol is already public.

1.27    18 April 2000

  • Implement support for COMDAT records.
  • Avoid searching through duplicate library names.
  • Handle blank line in ARF file as field marker.
  • Allow library directories in libfiles part of the command line.

1.26    10 April 2000

  • Extend checking for FRMSEG, FRMSEG0, and FRMSEG$ to the FT01 case.
  • Define RELTGT switch to catch the case where a self-relative fixup's Frame and Target segments are different in the FT00 case.

1.25    7 April 2000

  • Extend checking for RELGRP errors in self-relative fixups to the FT10 and FT11 cases.
  • Extend checking for RELGRPX and RELSEGX errors in self-relative fixups to the FT20 and FT21 cases.
  • Extend checking for RELSEG errors in self-relative fixups to the FT01 case.

1.24    4 April 2000

  • Extend Name Substitutions to PUBDEF and EXTDEF records (it previously applied to LNAMES & LLNAMES records only).
  • Extend Name Substitutions to .LIB files.

1.23    30 March 2000

  • Define FRMSEG$ switch to catch the case where a FRMSEG error occurs in a fixup segment named '$$SYMBOLS'.  This reduces some of the noise when linking with debugging info.  The default action is to ignore the error.
  • Fix bug when an external mixed-case symbol precedes the matching public declaration of the same symbol in a different case.

1.22    30 March 2000

  • Implement /NS keyword to handle name substitutions.
  • Implement additional debugging display for fixups via /DEBUG:FIXUP.

1.21    28 March 2000

  •  Force /NOE as I can't figure out how it works.  I thought I understood it, but now I'm convinced I do not.

1.20    24 March 2000

  • Implement /FARCALL.
  • Fix bugs when recognizing special class, segment, and group  names (wasn't case-insensitive and was off by one in length when comparing names).

1.19    22 March 2000

  • Define FRMSEG0 switch to reduce the number of spurious FRMSEG  messages in the case where the segment is the first one in the group.  In this case, the fixup value is the same independent of whether the fixup is segment- or group-relative.  The default action is to ignore FRMSEG0 errors.

1.18    15 March 2000

  •  Fix bug in self-relative fixups for several Frame vs. Target cases I never thought could occur until NASM came along.

1.17    2 October 1999

  • Change default behavior of ALINDIF to align segments of the same type according to the actual alignment (which may differ from segment to segment) instead of enforcing a single alignment across all segments of the same type.  This change mimics the MS-LINK behavior.  Using segments of the same type with different alignment is still a mistake.

1.16    8 September 1999

  • Fix bug when encountering multiple different segments with stack combine type (use the first one only).

1.15    6 September 1999

  • Fix bug which didn't display an error if a .LIB file was not found.
  • Implement switches for BLKDEF, BLKEND, and TYPDEF records instead of lumping them into OMFIGN.  As the default action is to ignore these records, you don't have to ignore all OMFIGN records just to ignore these.

1.14    3 September 1999

  • Fix bug where default EXE and MAP filenames were not displayed when using an Automatic Response File.

1.13    25 May 1999

  • Fix bug with not generating .MAP file when /MAP specified without an end-of-field marker.

1.12    16 May 1999

  • Fix bug with /DOSSEG segment ordering.

1.11    25 June 1998

  • Compare segment and class names case insensitively so as to mimic MS LINK behavior.
  • Fix bug in FIXUPP of Frame Segment, Target External where the wrong variable was used when checking for FRMSEG errors.
  • Round down Frame Base to para boundary before calculating fixups.

1.10    27 April 1998

  • Mark THRINV as ignored.  Apparently, MSVC 8 (and possibly earlier versions) set bit 2 in the method field of a THREAD subrecord in a FIXUPP record.
  • Fix bugs with aliased symbols.
  • Fix spurious error report with BAKPAT records.

1.09    12 March 1998

  • Fix bug in parsing of .LIB file on the command line so that QLINK no longer asks for more .LIB files if one is specified.
  • Implement /OPTHEADER (/OP) to optimize the .EXE file header by rounding the header up to a paragraph boundary instead of a 512-byte boundary.

1.08    12 November 1997

  • Wrote the VxD W95DPMI.386 which provides the appropriate DPMI 1.0 functions for QLINK to run under Win95.  In particular, this VxD supplies the needed calls to allocate uncommitted pages.

1.07    8 July 1997

  • Add EXTMAT config option to display message if an external in a module is not referenced by that module.  Presumably (but not always), these references can be deleted from the source file.

1.06    25 June 1995

  • If /MAP but no explicit entry in map file field, create one anyway.
  • Fix bug in fixup of far call to extern in a later segment which doesn't start on a para boundary.
  • Fix bug where /NOE didn't work.
  • Fix bug where null para at start of _TEXT not handled.

1.05    8 May 1995

  • Implement /ONERROR:NOEXE.
  • Parse and ignore /NOLOGO.
  • Parse and warn /PACKCODE:nnn.
  • Use FSA to parse .ARF files.
  • Change THRINV from always Fail to Ignore, Warn, Fail.
  • Support BAKPAT records.
  • Support CEXTDEF records.
  • Support LLNAMES records.
  • Treat extra fields in ARF file as EOF.
  • Implement /NOIGNORECASE.

1.04    25 March 1995

  • Allow addition with seg directive, e.g., DW (seg PGROUP)+10h.  Note that MS-LINK doesn't handle this correctly.
  • Fix bug in handling of OMF FIXUPP records for Frame & Target external for self-relative fixups.  This format is used by MASM 6.10, but neither MASM 5.10b nor 6.11a.

1.03    14 February 1995

  • Allow options occasionally enabled by some Integrated Development Environments which turn off unsupported features such as
    • /NOPACKCODE
    • /NOPACKDATA
    • /NOPACKFUNCTIONS
  • Also allow (and signal warning) for unsupported features
    • /FARCALLTRANSLATION
    • /PACKCODE
    • /PACKDATA
    • /PACKFUNCTIONS

1.02    18 November 1994

  • Fix bug if QLINK is run w/o DPMI host present.
  • Fix misspelling of /NOEXTDICTIONARY.

1.01    26 October 1994

  • Fix bug if searching for library file.
  • Write out minimal sized .EXE file.

1.00    2 October 1994

  • Initial release
================================================ FILE: qlink/QLINK.TXT ================================================ QLINK Documentation File Overview -------- QLINK is a DOS linker and analysis tool designed to link together MS-DOS compatible .OBJ files. It can replace the MS-DOS LINK.EXE program when producing MS-DOS compatible .EXE and .COM files. Installation ------------ Make a directory (e.g., C:\QLINK), copy the zip file to that directory, and unzip the files: MD C:\QLINK CD C:\QLINK COPY A:\QLINK.ZIP PKUNZIP QLINK.ZIP If you'll be running QLINK under Windows 3.1x (see below for Win95 instructions), copy the file WINDPMI.386 to your Windows system directory. For example, if you installed Windows into the directory C:\WINDOWS, copy WINDPMI.386 to C:\WINDOWS\SYSTEM. Then edit your Windows SYSTEM.INI file to insert a line such as the following in the [386ENH] section: device=windpmi.386 You should first ensure that no other similar line already appears in your SYSTEM.INI file. For example, you might already have a line such as device=c:\bc4\bin\windpmi.386 If this is the case, do not insert another call to the same driver; you need only one. This VxD does not work with Win9x. If you'll be running QLINK under Win9x, follow the above procedure using the file W95DPMI.386 instead of WINDPMI.386. Benefits -------- * One pass linker (using uncommitted memory in DPMI 1.0) * Better performance (typically twice as fast as MS LINK, sometimes ten times faster) * Handles USE32 segments > 64KB * Detailed error checking to the point that it becomes a highly valuable analysis tool * Detailed error information (e.g., source code line number info (if in .OBJ file) for fixup overflows) * Type checking between .OBJ files (if in .OBJ files) System Requirements ------------------- * MS-DOS 3.x or later * DPMI host which supports DPMI 1.0 calls -- use either 386MAX version 7.0 or later, or Windows 3.1x with a (supplied) VxD from Borland (WINDPMI.386), or DPMIONE (see http://www.sudleyplace.com/dpmione/). How To Use ---------- For the most part, just call QLINK instead of LINK or TLINK as appropriate. Borland users should note that a number of Borland-specific Object Module Formats (OMFs) are not implemented as yet (I'm waiting for the documentation from Borland). Several MS link switches are not supported as yet (e.g., /PACKC). If there are switches you particularly need which are not supported, let me know. For an explanation of the old linker switches, see your linker manual. Tips ---- To take advantage of the detailed error processing in QLINK, use the assembler switches which generate types and line numbers. For MASM and TASM these switches are /Zd and /Zi. Segment Ordering ---------------- The order in which segments appear in the executable file depends on several factors. The first is whether or not the /DOSSEG switch appears explicitly on the command line or implicitly in a OMF record in one of the .OBJ files. If /DOSSEG is specified, the segment order is as follows: * All segments with a class name ending in 'CODE' * All other segments not in DGROUP * DGROUP segments in the following order: * Any segments of class 'BEGDATA' * Any segment not of class 'BEGDATA', 'BSS', or 'STACK' * Segments of class 'BSS' * Segments of class 'STACK' Otherwise, the segment order is as follows: * All unclassed segments * All classed segments by class (that is, segments in the same class appear adjacent to each other). Error Messages -------------- There are a number of switches specific to QLINK which are documented in the file QLINK.CFG. These switches control the processing of error messages from QLINK. All error messages begin with either > WARN: or > FAIL: Messages which begin with WARN are warnings and do not halt the linker. Messages which being with FAIL cause the linker to stop immediately and not continue processsing the input files. If an error message is followed by a name such as FIXOVF or GRPEXT0 in parentheses, then that error can be controlled by the switches /I:switch, /W:switch, and /F:switch, where 'switch' is the name in parentheses in the error message. If you wish to ignore this error (meaning the linker takes a default action and continues processing), use /I:switch. To warn about an error (meaning an error message is displayed, the linker takes a default action, and continues processing), use /W:switch. The default settings for all error messages are described in the file QLINK.CFG. This same file (QLINK.CFG) is consulted when QLINK begins execution. Any switches found there (including switches such as /MAP, /LINE, etc.) are processed before the command line is parsed. Switches only may be contained in QLINK.CFG, not names of .OBJ files, etc. Even earlier in the process, the environment variable QLINK= is consulted, and it too may contain only switches. Thus the order of processing of switches is first, those contained in the environment variable QLINK=, then those in the file QLINK.CFG (first in the current directory, and if not found there in the directory from which QLINK is loaded), and finally those found on the command line to QLINK. Switches processed later in the sequence override ones processed ealier. Name Substitutions ------------------ Occasionally, you want to link together .OBJ modules from different projects which use different naming conventions. For example, in one project code segments are in class 'CODE' and in others they are in class 'PROG'. Previously, you would have to edit the source code, make the changes, and re-compile. With the Name Substitution feature of QLINK, it's a snap. To substitute names on the fly within the .OBJ file, place the switch /NS before the reference to each .OBJ file whose names are to be substituted. For example, use /NS:PROG-CODE to tell QLINK that the name 'PROG' is to be changed to 'CODE'. Each substitution is effective for all .OBJ files which appear after it until that substitution (or all substitutions) are halted. Use the form /NS:name to halt substitutions on 'name'; use /NS with no arguments to halt all substitutions. Note that this means that the occurrences of /NS are sensitive to the position and order in which they appear. Be sure to place occurrences of /NS before the reference to the .OBJ file to which they apply. To swap two symbols in the same file, use (say) /NS:A-B:B-A. The substitution is made on all references to the name regardless of context. Thus if you have a file with a segment named PROG and a class named PROG, substituting CODE for PROG changes both references. The full syntax is Nameset: (empty) ; Halt substitution on all names | name ; Halt substitution on this name | name '-' name ; Substitute the second name for the ; first name Namedef: Nameset | Namedef ':' Nameset Switch: '/NS:' Namedef The keyword /NS may appear in the QLINK environment variable, the QLINK.CFG configuration file, the automatic response file, and the QLINK command line. Frequently Asked Questions -------------------------- Q: When I link modules with the MS linker and QLINK, sometimes the executable files are of very different sizes? A: This can occur if a .LIB is used to resolve external references. Because there is no rule as to the order in which external refs are processed, different ordering of these references mean that there can be different segment boundary alignments which can change the final executable file size. Future Work ----------- In no particular order of importance (nor of expectation of getting done), the following topics are on my list: * Support Borland-specific OMFs * Support MS-specific OMFs (for which I don't have any examples) * External procedure for symbol processing (instead of reading .MAP file) * Allow segment attribute changes per .OBJ file * Generate Windows-compatible .EXEs * Generate Codeview information * Generate Turbo Debugger information * Compress .EXE using LZH or some such technique (for Windows executables as well) * Finish type checking of structures Please feel free to add to this list. Technical Support ----------------- Please contact the author via Internet e-mail at bsmith@sudleyplace.com (Bob Smith) QLINK is (C) Copyright 1994-2006 Qualitas, Inc. All rights reserved. Change History -------------- 5.08 23 March 2006 * Fix bug in .LIB symbol compares for case-insensitive libraries whose symbols contain uppercase letters (thanks Bob Snuggs). 5.07 2 January 2004 * Fix bug which prevents multiple .LIB files from being recognized (thanks Japheth). 5.06 24 December 2003 * Catch invalid OMF record where an LIDATA record has a zero repeat count. 5.05 19 June 2003 * Mark COMM variables as USE32 if the segment in which they are defined (c_common or FAR_BSS) is USE32. * Load .OBJ files into extended memory instead of low DOS in case there's not enough room. * Implement undocumented /KNOWEAS for compatibility with MS linker. 5.04 22 May 2003 * Added more information to USEDIF error message to point to .OBJ file in which the segment was first defined. * Added references to DPMIONE as a DPMI 1.0 host under which QLINK runs. 5.03 21 July 2002 * Modified the change in version 5.00 for fixup overflows to treat the Target Displacement as a signed number and then ignore overflows if the upper 24- (for byte fixups) or 16-bits (for word fixups) are all ones. 5.02 1 July 2002 * Fix bug where a MODEND fixup generating any kind of error causes the routine which displays the .OBJ file name to fail (thanks to Vladomir Rodriquez for pointing this out). 5.01 26 June 2002 * Fix bug where .MAP file occasionally not written out. * Display segment combine type in /MAP:FULL. * Fix bug in display of line #s for grouped segments which are not first in the group. * Append IGNOREd errors to .ERR file if /DEBUG:ERR in effect. * Added FIXOVF$ switch to ignore fixup overflows in '$$SYMBOLS' segments. * Fix bug when parsing command line and/or .ARF file if leading '+' in multiple entry (.OBJ or .LIB) fields. 5.00 26 June 2002 * Change version # to 5 to workaround bug in EXEHDR. * Fix bug in display of FRMSEG$ message. * Display error message if not enough memory to enter PM through the DPMI host. * Fix bug when checking for fixup overflows where the displacement wasn't added in before the overflow check, thus missing some overflows (thanks to Vladomir Rodriquez for pointing this out). 1.30 22 June 2002 * Added MTOBJ switch to fail on empty .OBJ files which can occur when a language translator creates an object file but halts for some reason before writing anything to it. 1.29 18 April 2002 * Fix bug to change ignore/warn action on OMFUNK to ignore the record. 1.28 25 April 2000 * Fix bug handling weak externs if the symbol is already public. 1.27 18 April 2000 * Implement support for COMDAT records. * Avoid searching through duplicate library names. * Handle blank line in ARF file as field marker. * Allow library directories in libfiles part of the command line. 1.26 10 April 2000 * Extend checking for FRMSEG, FRMSEG0, and FRMSEG$ to the FT01 case. * Define RELTGT switch to catch the case where a self-relative fixup's Frame and Target segments are different in the FT00 case. 1.25 7 April 2000 * Extend checking for RELGRP errors in self-relative fixups to the FT10 and FT11 cases. * Extend checking for RELGRPX and RELSEGX errors in self-relative fixups to the FT20 and FT21 cases. * Extend checking for RELSEG errors in self-relative fixups to the FT01 case. 1.24 4 April 2000 * Extend Name Substitutions to PUBDEF and EXTDEF records (it previously applied to LNAMES & LLNAMES records only). * Extend Name Substitutions to .LIB files. 1.23 30 March 2000 * Define FRMSEG$ switch to catch the case where a FRMSEG error occurs in a fixup segment named '$$SYMBOLS'. This reduces some of the noise when linking with debugging info. The default action is to ignore the error. * Fix bug when an external mixed-case symbol precedes the matching public declaration of the same symbol in a different case. 1.22 30 March 2000 * Implement /NS keyword to handle name substitutions. * Implement additional debugging display for fixups via /DEBUG:FIXUP. 1.21 28 March 2000 * Force /NOE as I can't figure out how it works. I thought I understood it, but now I'm convinced I do not. 1.20 24 March 2000 * Implement /FARCALL. * Fix bugs when recognizing special class, segment, and group names (wasn't case-insensitive and was off by one in length when comparing names). 1.19 22 March 2000 * Define FRMSEG0 switch to reduce the number of spurious FRMSEG messages in the case where the segment is the first one in the group. In this case, the fixup value is the same independent of whether the fixup is segment- or group-relative. The default action is to ignore FRMSEG0 errors. 1.18 15 March 2000 * Fix bug in self-relative fixups for several Frame vs. Target cases I never thought could occur until NASM came along. 1.17 2 October 1999 * Change default behavior of ALINDIF to align segments of the same type according to the actual alignment (which may differ from segment to segment) instead of enforcing a single alignment across all segments of the same type. This change mimics the MS-LINK behavior. Using segments of the same type with different alignment is still a mistake. 1.16 8 September 1999 * Fix bug when encountering multiple different segments with stack combine type (use the first one only). 1.15 6 September 1999 * Fix bug which didn't display an error if a .LIB file was not found. * Implement switches for BLKDEF, BLKEND, and TYPDEF records instead of lumping them into OMFIGN. As the default action is to ignore these records, you don't have to ignore all OMFIGN records just to ignore these. 1.14 3 September 1999 * Fix bug where default EXE and MAP filenames were not displayed when using an Automatic Response File. 1.13 25 May 1999 * Fix bug with not generating .MAP file when /MAP specified without an end-of-field marker. 1.12 16 May 1999 * Fix bug with DOSSEG segmnent ordering. 1.11 25 June 1998 * Compare segment and class names case insensitively so as to mimic MS LINK behavior. * Fix bug in FIXUPP of Frame Segment, Target External where the wrong variable was used when checking for FRMSEG errors. * Round down Frame Base to para boundary before calculating fixups. 1.10 27 April 1998 * Mark THRINV as ignored. Apparently, MSVC 8 (and possibly earlier versions) set bit 2 in the method field of a THREAD subrecord in a FIXUPP record. * Fix bugs with aliased symbols. * Fix spurious error report with BAKPAT records. 1.09 12 March 1998 * Fix bug in parsing of .LIB file on the command line so that QLINK no longer asks for more .LIB files if one is specified. * Implement /OPTHEADER (/OP) to optimize the .EXE file header by rounding the header up to a paragraph boundary instead of a 512-byte boundary. 1.08 12 November 1997 * Wrote the VxD W95DPMI.386 which provides the appropriate DPMI 1.0 functions needed for QLINK to run under Win95. 1.07 8 July 1997 * Add EXTMAT config option to display message if an external in a module is not referenced by that module. Presumably (but not always), these references can be deleted from the source file. 1.06 25 June 1995 * If /MAP but no explicit entry in mapfile field, create one anyway. * Fix bug in fixup of far call to extern in a later segment which doesn't start on a para boundary. * Fix bug where /NOE didn't work. * Fix bug where null para at start of _TEXT not handled. 1.05 8 May 1995 * Implement /ONERROR:NOEXE. * Parse and ignore /NOLOGO. * Parse and warn /PACKCODE:nnn. * Use FSA to parse .ARF files. * Change THRINV from always Fail to Ignore, Warn, Fail. * Support BAKPAT records. * Support CEXTDEF records. * Support LLNAMES records. * Treat extra fields in ARF file as EOF. * Implement /NOIGNORECASE. 1.04 25 March 1995 * Allow addition with seg directive, e.g., DW (seg PGROUP)+10h. Note that MS-LINK doesn't handle this correctly. * Fix bug in handling of OMF FIXUPP records for Frame & Target external for self-relative fixups. This format is used by MASM 6.10, but neither MASM 5.10b nor 6.11a. 1.03 14 February 1995 * Allow options occasionally enabled by some Integrated Development Environments which turn off unsupported features such as /NOPACKCODE /NOPACKDATA /NOPACKFUNCTIONS * Also allow (and signal warning) for unsupported features /FARCALLTRANSLATION /PACKCODE /PACKDATA /PACKFUNCTIONS 1.02 18 November 1994 * Fix bug if QLINK is run w/o DPMI host present. * Fix misspelling of /NOEXTDICTIONARY. 1.01 26 October 1994 * Fix bug if searching for library file. * Write out minimal sized .EXE file. 1.00 2 October 1994 * Initial release.  ================================================ FILE: reqdmmi.asm ================================================ macro RequireDMMI { local FailX local SuccX local FailErr pushad push es push ds mov ax,0x35F0 int 0x21 cmp dword [es:bx + 2],'dmmi' jnz FailX mov ax,0 int 0xF0 cmp ax,0xFACE jnz FailX pop ds pop es popad jmp SuccX FailErr db "This app requires a DMMI Server",0xD,0xA,"$" FailX: push cs pop ds mov ax,0x0900 mov dx,FailErr int 0x21 pop ds pop es popad mov ax,0x4c00 int 0x21 SuccX: } ================================================ FILE: runx.bat ================================================ @echo off D: entry.exe entry.exe /r dmmic.exe dos32a.exe le.exe rem cd dpmi rem dpmione pro=dpmione.pro rem cd .. vdebug debuggee.exe mdebug debuggee.exe switcher a: ================================================ FILE: stack16.asm ================================================ ; --------------------------------------- 16 bit stack --------------------------------------- SEGMENT STACK16 USE16 sseg16 dw 1024 dup (?) stack16_end: ;------------------------------------------------------------------------------------------- ; 16 bit stack segment for sipi ;------------------------------------------------------------------------------------------- SEGMENT STACK16S USE16 ORG 0 sseg16s dw 200 dup (?) stack16s_end: sseg16dmmi2 dw 100 dup (?) stack16dmmi2_end: sseg16dmmi3 dw 100 dup (?) stack16dmmi3_end: ;------------------------------------------------------------------------------------------- ; 16 bit stack segments for threads ;------------------------------------------------------------------------------------------- SEGMENT STACK16T1 USE16 ORG 0 sseg16t1 dw 200 dup (?) stack16t1_end: SEGMENT STACK16T2 USE16 ORG 0 sseg16t2 dw 200 dup (?) stack16t2_end: SEGMENT STACK16T3 USE16 ORG 0 sseg16t3 dw 200 dup (?) stack16t3_end: SEGMENT STACK16T4 USE16 ORG 0 sseg16t4 dw 200 dup (?) stack16t4_end: SEGMENT STACK16T5 USE16 ORG 0 sseg16t5 dw 200 dup (?) stack16t5_end: ================================================ FILE: stack32.asm ================================================ ; --------------------------------------- 32 bit stack --------------------------------------- SEGMENT STACK32 USE32 stack32 db 100 dup (?) stack32_end: ================================================ FILE: stack64.asm ================================================ ; --------------------------------------- 64 bit stack --------------------------------------- SEGMENT STACK64 USE64 ORG 0 stack64 db 1000 dup (?) stack64_end: nop stack64dmmi db 1000 dup (?) stack64dmmi_end: nop ================================================ FILE: startbochs.bat ================================================ bochs.exe -q -f "%1" ================================================ FILE: startvbox.bat ================================================ g:\virtualbox\VBoxManage.exe unregistervm asmtest g:\virtualbox\VBoxManage.exe registervm "%1" set VBOX_GUI_DBG_AUTO_SHOW=true set VBOX_GUI_DBG_ENABLED=true g:\virtualbox\VBoxManage.exe startvm asmtest -E VBOX_GUI_DBG_AUTO_SHOW=true -E VBOX_GUI_DBG_ENABLED=true ================================================ FILE: startvmware.bat ================================================ "C:\Program Files (x86)\VMware\VMware Workstation\vmware.exe" -q -x "%1" ================================================ FILE: struct.asm ================================================ ; --------------------------------------- Macro and Structure Definitions --------------------------------------- macro linear reg,trg,seg = DATA16 { ; xor reg,reg mov reg,seg shl reg,4 add reg,trg } macro atlinear reg,trg,seg { mov reg,seg shl reg,4 add reg,trg mov reg,[reg] } macro dh_virtualization { local .nuvmx local .nvmx ; dh -> 0 no virtualization ; dh -> 1 virtualization plain ; dh -> 2 virtualization unrestricted guest mov eax,1 cpuid xor dx,dx bt ecx,5 jnc .nvmx mov dh,1 xor eax,eax xor edx,edx mov ecx,0x48B ; IA32_VMX_PROCBASED_CTLS2 rdmsr bt edx,7 jnc .nuvmx mov dh,2 jmp .nvmx .nuvmx: mov dh,1 .nvmx: } macro pushadxeax { push ebx push ecx push edx push esi push edi push ebp } macro popadxeax { pop ebp pop edi pop esi pop edx pop ecx pop ebx } macro push64 { push rax push rbx push rcx push rdx push rsi push rdi push rbp push r8 push r9 push r10 push r11 push r12 push r13 push r14 push r15 } macro pop64 { pop r15 pop r14 pop r13 pop r12 pop r11 pop r10 pop r9 pop r8 pop rbp pop rdi pop rsi pop rdx pop rcx pop rbx pop rax } struc A_CPU a,b,c,d { .acpi dd a .apic dd b .flags dd c .handle dd d } struc GDT_STR s0_15,b0_15,b16_23,flags,access,b24_31 { .s0_15 dw s0_15 .b0_15 dw b0_15 .b16_23 db b16_23 .flags db flags .access db access .b24_31 db b24_31 } struc IDT_STR o0_15,se0_15,zb,flags,o16_31 { .o0_15 dw o0_15 .se0_15 dw se0_15 .zb db zb .flags db flags .o16_31 dw o16_31 } struc IDT_STR64 o0_15,se0_15,zb,flags,o16_31,o32_63,zr { .o0_15 dw o0_15 .se0_15 dw se0_15 .zb db zb .flags db flags .o16_31 dw o16_31 .o32_63 dd o32_63 .zr dd zr } macro vmw16 code,value { mov ebx,code xor eax,eax mov ax,value vmwrite ebx,eax } macro vmw32 code,value { mov ebx,code mov eax,value vmwrite ebx,eax } macro vmw64 code,value { mov rbx,code mov rax,value vmwrite rbx,rax } macro vmr r,code { mov rbx,code vmread r,rbx } macro break { xchg bx,bx } struc LoadX a,b,c,d,e,f,g { .f1 dw a .f2 dd b .f3 dd c .f4 dd d .sp dw g .ss dw f .cs dw e .ip dw e } ================================================ FILE: swat/386SWAT ================================================ ; ; Recommended options are trapdiv ; Direct INT 00h to 386SWAT (Divide Overflow Fault) trapnmi ; Direct INT 02h to 386SWAT (Non-maskable interrupt) trapbound ; Direct INT 05h to 386SWAT (BOUND Fault) trapinv ; Direct INT 06h to 386SWAT (Invalid Opcode Fault) trapstack ; Direct INT 0Ch to 386SWAT (Stack Fault) x15 ; Pass through all INT 15h memory calls ; ; The default options are ; ; addrhbits=12 ; Specify bits in addresses to hash (8-12) ; btbsize=0 ; Specify size of Branch Trace Buffer in kilobytes ; cmdhist=1024 ; Specify the size of the command history buffer ; intrude ; Attempt to intrude into another memory manager's PL0 context ; logsize=4096 ; Specify size of error log buffer in bytes ; normlidt ; Disable Real Mode LIDT redirection ; proxsrch=4,1 ; Search symbols for matches within range 4 of units with ; ; granularity 1 (default granularity is 1 for byte). ; savescreen=16 ; Specify # last screens to save ; symfilter=__imp__ _ ; Specify leading text to strip from symbols ; symsize=4096 ; Specify # bytes to reserve for the symbol table ; trapskip ; Direct INT 03h to 386SWAT (Single-skip) ; trapstep ; Direct INT 01h to 386SWAT (Single-step) ; wkdls=0 ; No Windows Kernel Debugger Load Segment symbols ; ; ; The default services are ; ; Windows Kernel Debugger services enabled (disable via nowink) ; ; ; All possible options are ; ; [section name] ; Limit profile processing to the matching MultiConfig ; ; section in CONFIG.SYS ; addrhbits=nn ; Specify bits in addresses to hash (8-12, default=12) ; altscr ; Use alternate screen for debugging ; /a ; Alias for ALTSCR ; btbsize=nnnnn ; Specify size of Branch Trace Buffer in kilobytes (default=0) ; buckets=nnn ; Specify # 1K hash bucket blocks (1-255) ; cmdhist=nnn ; Specify the size of the command history buffer ; coldboot ; Do not try to warm boot on Ctrl-Alt-Del ; dvga ; Use Dual VGA screen ; fsonly ; SWAT available in Fullscreen mode in Windows only ; gpskip=key[,key] ; GP Skip instructions: ALL, INT, HLT, OUTD, OUTI, OUTS, ; ; IND, INI, INS, CLI, STI, IRET, PPF, and CRn so far ; intrude ; Obsolete option which is now the default ; keyb=cclay ; Use international keyboard whose country code/layout is cclay. ; ; Possible values are ; ; cclay Country ; ; ---------------------- ; ; GR129 Germany ; ; SP172 Spain ; lcd ; LCD screen present ; loadhigh ; Obsolete option which is now the default ; loadlow ; Tell 386MAX it's not OK to load us into extended memory ; ; after INIT_REAL and to relocate our INIT_VIRT code. ; loadsym ; Enable command line loading of symbols ; loadsym=d:\path\filename.ext [optional args] ; Load SSF file at PM init time ; ; [/b=xxxxxxxx] Optional physical base address in hex ; ; [/h] Optional HPDA flag (enable DPMI services) ; ; [/li-] Optional disable of line numbers ; ; [/xl] Disable larger comparison w/SYMSIZE ; logsize=nnnnn ; Specify size of error log buffer in bytes (default=4096) ; mono ; Use monochrome adapter if present ; nogd ; Don't automatically set the GD bit in DR7 ; normlidt ; Disable Real Mode LIDT redirection ; noswap ; Don't swap screens over single-step/skip ; novxd ; Don't load the VxD ; nowindpci ; Disable Windows Dual PCI switching ; nowink ; Disable Windows Kernel Debugger services ; passthrough=nn,nn,... ; Specify one or more hardware interrupt handlers ; ; (numbers in hex) to pass through while SWAT is active. ; ; The only ones currently supported are B, C, 76, and 77. ; path=dir[,dir2[...]] ; Specify source code search path for symbolic debugging ; ; (current directory is NOT included by default) ; portinit=string ; Specify a modem initialization string (setcom must be ; ; specified as well). Valid escape sequences are: ; ; \\ Send a backslash ; ; \r Send a carriage return ; ; \b Send a break signal ; ; \p Pause about 250 ms. ; ; \1 - \0 Wait 1 - 10 seconds. ; ; On the first invocation of SWAT, the system will ; ; automatically attempt to establish connection with a remote ; ; SWAT system. ; proxsrch=r[,g] ; Search symbols for matches within range r of units with ; ; granularity g (default granularity is 1 for byte). ; ps4=xxxx ; Periscope 4 hardware debugger board is at I/O port xxxx ; rmlidt ; Enable Real Mode LIDT redirection ; savescreen=nnn ; Specify # last screens to save (default = 16) ; setcom=port,bps[,{IRQ|p}[,base]] ; Initialize specified serial port (1-4) for ; ; remote debugging at specified bps. Optional IRQ number (3,4) ; ; overrides default association of ports with IRQs, or p may ; ; be specified for polled operation. Optional port base ; ; may be specified to override BIOS value at 40:0. ; symfilter=text1 [text2 [...]] ; Specify leading text to strip from symbols ; symsize=nnnnn ; Specify # bytes to reserve for the symbol table (default=4096) ; trapbound ; Direct INT 05h to 386SWAT (BOUND Fault) ; trapdebug ; Direct INT 01h/03h to 386SWAT (Same as TRAPSTEP with TRAPSKIP) ; trapdiv ; Direct INT 00h to 386SWAT (Divide Overflow Fault) ; trapgenp ; Direct INT 0Dh to 386SWAT (General Protection Fault) ; trapinv ; Direct INT 06h to 386SWAT (Invalid Opcode Fault) ; trapnmi ; Direct INT 02h to 386SWAT (Non-maskable interrupt) ; trappage ; Direct INT 0Eh to 386SWAT (Page Fault) ; trapsegnp ; Direct INT 0Bh to 386SWAT (Segment Not Present Fault) ; trapskip ; Direct INT 03h to 386SWAT (Single-skip) ; trapstack ; Direct INT 0Ch to 386SWAT (Stack Fault) ; trapstep ; Direct INT 01h to 386SWAT (Single-step) ; traptss ; Direct INT 0Ah to 386SWAT (TSS Fault) ; unreal [+|-][cs|ds|es|fs|gs|ss|all] ; Enable (+) or disable (-) Unreal ; ; (Flat Real) mode on selected (all) segment registers ; vcpiswat ; Don't attempt to intrude into a memory manager's PL0 context ; video=d:\path\filename.ext ; Load/create video tables ; vmscount=n ; Number of times to intrude on GDT/IDT for VCPI debugging ; vmsint ; Launder Windows and VCPI mode switches and hook interrupts ; ; 00, 01, 02, 03, 05, 06, 08, 0A, 0B, 0C, 0D, and 0E. ; vmsint=nn,nn,... ; Limit VMSINT debugging to these interrupt #s ; watchdog=nn ; Set watchdog timer to nn timer ticks (0-255) ; wkdls=nnn ; Define # WKD Load Segment entries ; x15 ; Pass through all INT 15h memory calls ; xirqcode ; Skip IRQ code ; debug=caps ; Signal NMI if CapsLock pressed at startup ; debug=ibv ; Use Interrupt mask base Vector for Ctrl-Alt-PAD5 ; debug=int ; Signal INT 03h if CapsLock present at startup ; debug=pmi ; Signal INT 03h near end of INIT_PROT ; debug=trip ; Use triple fault method to reboot ; debug=vmi ; Signal INT 01h on entry to INIT_VIRT ; debug=wcb ; Signal INT 01h on entry to Windows Callback Disable ; debug=xpushf ; Don't skip over (INT 03h) PUSHF/PUSHFD  ================================================ FILE: swat/386SWAT.DOC ================================================ 386SWAT -- A Debugger for All Modes (C) Copyright 1988-2001 Qualitas, Inc. All rights reserved. This protected mode debugger when used in conjunction with 386MAX or any other memory manager provides debugging services to protected mode, virtual 8086 mode programs, and DPMI and VCPI clients while occupying zero bytes of memory in the first megabyte. It supports disassembly of the full 386, 387, 486, and Pentium CPU instruction set through the Pentium 4 MMX & SSE instructions. Installing 386SWAT ------------------ Create a directory on your hard disk (say, C:\386SWAT), copy the ZIP file to that directory, and unzip it there. To unzip 386SWAT, use PKUNZIP 386SWAT This debugger can be used in conjunction with any memory manager which supports VCPI, or with just HIMEM.SYS. * To install 386SWAT, place the following line into your CONFIG.SYS file: DEVICE=d:\path\386SWAT.LOD options Place the DEVICE= statement for 386SWAT immediately following the DEVICE= for the memory manager (if any), or HIMEM.SYS if no memory manager is being used. "d:\path\" represents the drive and path location of 386SWAT and "options" represents zero or more profile options. As there are several options you may wish to use with 386SWAT, we recommend that you put all 386SWAT keywords in a profile one keyword per line, and point to the profile with the PRO= option on the 386SWAT.LOD line. For example, DEVICE=d:\path\386SWAT.LOD PRO=d:\path\386SWAT.PRO 386SWAT Profile Options ----------------------- The following profile options are recognized by 386SWAT. Options may be entered in upper and/or lower case. See the file 386SWAT for a list you can use already in profile format. [section name] For versions of DOS which support MultiConfig, this option limits profile processing to the matching MultiConfig section in CONFIG.SYS. ADDRHBITS=n Bits to use for address hashing (8-12; default 12). ALTSCR Display debugging information on the screen other than the current one being used. That is, in a two monitor system, if the current screen uses the color adapter, display debugging data on the monochrome screen and vice versa. This option is valid only if we detect that there are both a color and monochrome adapter in the system. Otherwise, it is ignored. Note that the screens can be swapped via Alt-F7. An alias for this option is /A. BUCKETS=n Specify the number of name hashing blocks to allocate (about 1K each). CMDHIST=nnn Specify the size of the command history buffer. Default is 1024. COLDBOOT Don't write 1234h to warm boot flag location when rebooting system from within 386SWAT. DEBUG=TRIP Use triple fault method of rebooting. Sometimes a system doesn't reboot when using the 8042 method (the default), so here's another way to skin the cat. DEBUG=WCB1 Signal an INT 01h at Windows Callback time when entering Windows (VM->RM) so breakpoints can be set. This keyword is particvularly useful in conjunction with the INSERT command. To change this state later on, use the command WKD WCB1 [ON|OFF]. DVGA Use a Dual VGA screen as the secondary monitor. GPSKIP=key[,key] If a GP Fault occurs on any of the instructions named in the list, do not signal this to 386SWAT. This option allows you to trap GP Faults but filter out ones which may commonly occur but not be of interest. The key values (GP Skip instructions) supported are Keyword Instruction(s) CLI CLI CRn MOV r32,CRn/MOV CRn,r32 HLT HLT IND IN AL/AX/EAX,DX INI IN AL/AX/EAX,immed INT INT xx IRET IRET/IRETD OUTD OUT DX,AL/AX/EAX OUTI OUT immed,AL/AX/EAX PPF PUSHF/POPF/PUSHFD/POPFD STI STI The keyword ALL covers all of the above options. INTRUDE Attempt to intrude into another memory manager's PL0 context. If this is successful, 386SWAT appears as a PL0 debugger in the context of the memory manager. This option is now the default. To disable this option, see VCPISWAT. KEYB=ccidn Use international keyboard whose country code/layout is cclay. Possible values are cclay Country ------------------------- GR129 Germany SP172 Spain If your keyboard is not in this list, read the file KEYBIN.TXT to see how you can help. LCD An LCD screen is present (and 386SWAT uses the monochrome screen attributes). Does anyone know how to detect this case under program control? I would prefer not to require the user to tell us what the screen is like. LOADLOW Tell 386MAX it's not OK to load us into extended memory after INIT_REAL and to relocate our INIT_VIRT code. It's highly unlikely you'll need this option. LOADSYM=filename [optional] Load specified symbol file with optional arguments: /b=xxxxxxxx Optional physical base address in hex /h Optional HPDA flag (enable DPMI services) /li- Optional disable of line numbers /xl Disable larger comparison w/SYMSIZE LOGSIZE=nnnnn Define size of error log in bytes. Default is 4096. MONO Use monochrome adapter if present. NOGD Because some programs may reset the debug registers which you've carefully setup, 386SWAT automatically sets the Global Debug (GD) bit in DR7 on startup so that we can stop such programs before they can do any harm. In case you don't want 386SWAT to do this, use this keyword. NORMLIDT Disable Real Mode LIDT redirection. Device 386SWAT uses a separate IDT to handle nasty bugs which write into the Real Mode IDT at 0:0 such as DOS 6.x does during its transient CONFIG.SYS processing. This is the default state. NOSWAP Don't restore the previous underlying screen when single-stepping. This option is useful in conjunction with the ALTSCR option. This option specifies the initial state only. It can be toggled via Alt-F6. NOWINK Disable Windows Kernel Debugging. PASSTHROUGH=xx,xx,xx,... Allow one or more hardware interrupts to be passed through to the previous protected mode handler while 386SWAT is active. Currently, these are limited to 76, 77, 0B, and 0C. THIS OPTION SHOULD NOT BE USED UNLESS NECESSARY. For example, when the IBM PS/2 SCSI adapter (8EFE or 8EFF) is used, staying in 386SWAT for more than 1 or 2 minutes will cause the hard disk to lock on the next disk access. PASSTHROUGH=76 will allow one to stay in 386SWAT indefinitely. PATH=d:\dir1[,d:\dir2[,...]] Specify source file search path. PORTINIT=string Initialize serial port. String may contain any character except semicolon, including the following escape sequences: \\ Send backslash \r Send CR \b Send a break signal (this is a hardware signal, not a character) \p Pause for about 250ms. \1 - \0 Delay for 1 - 10 seconds. SETCOM must be specified to set the parameters for the serial port. On the first entry to 386SWAT (which may be remotely triggered) 386SWAT will automatically try to connect for remote debugging. PRO=d:\path\filename.ext Read subsequent command line options from a profile. Just as with 386MAX, as you append more and more options to the 386SWAT command line, you may prefer to collect them all in a 386SWAT profile, one per line. These options may be followed by a semicolon and a comment. This profile is handled exactly the same way as is the corresponding profile for 386MAX. PROXSRCH=r[,g] Set range and granularity for proximity searching on symbol addresses. PS4=xxxx Periscope 4 hardware debugger board is installed at I/O port xxxx (for reference, the factory setting is 300h). This feature allows 386SWAT to manage the traceback buffer and other features of the Periscope Company's 386 hardware debugger. *NOTE* this feature isn't finished. RMLIDT Enable Real Mode LIDT redirection. Device 386SWAT uses a separate IDT to handle nasty bugs which write into the Real Mode IDT at 0:0 such as DOS 6.x does during its transient CONFIG.SYS processing. SAVESCREEN=nnn Specify the number of last screens to save. This keyword allows you to control how many screens back Alt-F10 can display. The default is sixteen. Each screen consumes 4000 bytes of storage in extended memory. SETCOM=port,bps[,itype[,portbase]] Specify port to use for remote debugging. port From 1-4 for COM1 through COM4. bps Transfer rate, from 1 to 115200. itype Interrupt mode. May be 3 or 4 to specify IRQ (default is IRQ3 for COM2/COM4, IRQ4 for COM1/COM3), * for default, or p for polled operation. Currently, an IRQ line is required for remote debugging. portbase UART port base if different from defaults: COM1=3F8, COM2=2F8, COM3=3E8, COM4=2E8. SYMFILTER=text1 [text2 [...]] Some symbols, especially from Windows programs written in C, are prefaced with text such as "__imp__", "_", and the like which adds to the symbol's length but not understanding. This feature allows you to specify in the 386SWAT profile leading text which is to be stripped from each symbol. The default settings are SYMFILTER=__imp__ _ Up to 128 characters can be specified in this way. SYMSIZE=nnnnn Specify the number of bytes to reserve for the symbol table. The default size is 4096. TRAPBOUND Trap BOUND instruction interrupts, ignoring INT 05h. TRAPDEBUG Intercept INT 01h/03h at installation time. Normally, 386MAX directs protected mode occurrences of INT 01h/03h to 386SWAT and real mode occurrences to the real IDT handler. This options causes all such interrupts to be handled by 386SWAT. This feature may be toggled via Alt-F1. TRAPDIV Trap divide overflow interrupts. TRAPGENP Trap General Protection Faults (toggle via Alt-F3). TRAPINV Trap Invalid Opcode interrupts (toggle via Ctl-F3). TRAPNMI Trap Non-Maskable Interrupts. This option is useful in conjunction with a hardware breakout switch which can be used to invoke the debugger even if all interrupts are disabled (toggle via Alt-F2). TRAPPAGE Trap Page Faults (toggle via Alt-F4). TRAPSEGNP Trap Segment Not Present Faults. TRAPSKIP Trap INT 03h instructions (toggle via Ctl-F2). TRAPSTACK Trap Stack Faults (toggle via Ctl-F4). TRAPSTEP Trap INT 01h breakpoints (toggle via Ctl-F1). TRAPTSS Trap TSS Faults. VCPISWAT Do not attempt to intrude into another memory manager's PL0 context. This option disables the default INTRUDE option. VIDEO=d:\path\filename.ext Read in/write to video tables. If the specified file exists, it is read in and used as video table information. If the file doesn't exist, it is created. The information in the video table specifies how to switch to particular video modes as well as how to set certain cursor types. Use this option if you wish to bring up 386SWAT on top of graphic applications on single-monitor systems. *NOTE* this option doesn't fully work as yet, so I suggest that you don't use it. VMSCOUNT=n Used with VMSINT (see below). Limit number of times 386SWAT inserts itself into VCPI client's GDT/IDT. This may be useful when debugging VCPI applications that call Enter Protected Mode (AX=DE0C) repeatedly, such as a real-mode int 8 handler that enters protected mode on every clock tick. The correct value may have to be determined by trial and error. VMSINT[=xx,xx,..] Trap VCPI Enter Protected Mode switches (AX=DE0C) and blast in sufficient GDT and IDT entries to debug the client application. This option is useful when debugging a VCPI application which does not follow the preliminary VCPI debugger specification. Use this option with care. The argument (if present) limits the intercepted interrupts to the values. When VMSINT is in effect, it may be important to limit the interrupts. For example, some DOS16M apps (such as Lotus 1-2-3 Version 3.0) intercept interrupts but don't set the access rights byte in the IDT (they assume that it's still set for a 286 interrupt gate, as DOS16M setup originally). Thus when 386SWAT blasts its task gate entries into the IDT, subsequent DOS16M intercepts leave those entries marked as a task gate. This debug option limits us to intercepting those faults necessary to catch catastrophic errors, but not everything. Interrupts which may be intercepted are 00, 01, 02, 03, 05, 06, 0A, 0B, 0C, 0D, and 0E. WKDLS=nnn Allow up to nnn Windows Kernel Debugger Load Segment values. These are the segments of VxDs loaded at Windows startup. They are identified by the VxD name followed by either "_Code" or "_Data" followed by the segment number. For example, VWIN32_Code0001. The default count is zero. Invoking The Debugger --------------------- Generally, the debugger lies in the background waiting for some catastrophic event to occur. To bring up the debugger from the keyboard, press Ctl-Alt-Pad5. That is, with the Ctl- and Alt-keys held down, pressing the 5 key on the numeric pad invokes the debugger. This mechanism is useful when your program is stuck somewhere. Remember, the keyboard and the keyboard interrupt must be enabled for this to work. On systems for which the Pad5 key is inconvenient to use (such as some laptops), the sequence Ctl-Alt-SysReq also brings up the debugger. To run a particular program through the debugger, use the SWATRUN utility. If remote debugging is active (see SETCOM profile option and SETCOM command) the debugger may also be activated by sending 'SWT!' followed by a break signal. This is done by pressing Ctl-6 in the CHAT screen. The utility SWATCMD.EXE (loaded via Device= or from the DOS command line) may be used to pass commands to 386SWAT. Invoking SWATCMD with no options brings up 386SWAT at an INT 03h (assuming TRAPSKIP or TRAPDEBUG is active). Debugging Aids in 386MAX ------------------------ The following options are recognized by 386MAX and may be useful in conjunction with 386SWAT. These options should be placed in your 386MAX profile. To catch even-value stack wraps, use DEBUG=NOWRAP. This situation occurs when an interrupt is encountered with SP = 2 or 4. In this case, the 386 will push the three words onto the stack and wrap to the end of the stack segment leaving SP = FFFC or FFFE. Quite likely, this is an error as most stack segments aren't meant to be 64 KB in length. Technically, this event is not an error as far as the 386 is concerned, but logically it almost always is an error. The default behavior of 386MAX is not to signal an error; the DEBUG=NOWRAP keyword tells 386MAX to trap this case. To catch writes into unmapped EMS pages, use DEBUG=EMSWRIT. This option traps with a Page Fault attempts to write into unmapped EMS pages as well as after a Save Page Map call. The latter is presumed to have been done by a memory-resident program prior to mapping in its own pages. To catch reads and/or writes in unmapped EMS pages, use DEBUG=EMSRDWR. To catch an EMS bug in MS-DOS 4.0x, try this latter option with BUFFERS in EMS memory. To catch unemulated Invalid Opcodes, use DEBUG=I06. To signal an INT 01h on each DPMI error, use DEBUG=DPMIERR. To force a new selector on all selector allocates, use DEBUG=DPMINEWSEL. This option is useful if your code has a stale selector, that is, you allocate a selector and tuck it away for later use, but then, before its last reference, you free it and allocate another selector. Without this option you might get the old selector number (the one you just freed). When the stale selector is used, it might not generate an error, but surely it won't do what you expected. Debugging Screen ---------------- The top of the initial debugging screen consists of a row of the 32-bit general purpose registers, two rows of the segment registers, and one row of CR0, CR2, and extended flags. The rest of the initial debugging screen displays the instructions to be executed with the stack appearing on the right in one or two columns. If the current instruction references memory, the segment register, offset, and memory value of the reference are displayed on the line separating the registers from the instructions. The last line is the command line. There are several keystrokes available at this point: ESC Continue processing. Equivalent to Go command in other debuggers. F1 Display a help screen with submenus. F2 Display GDT entries. F3 Display LDT entries. F4 Display IDT entries. F5 Display PTE entries. F6 Display search screen. F7 Display memory. While this display is active, Ctl-B displays in byte format, Ctl-W, in word format, Ctl-D in dword format, Ctl-V in vector format, Ctl-G in GDT format, Ctl-I in IDT format, and Ctl-T in TSS format. F8 Display TSS entries. F9 Display the instruction disassembly screen. F10 Display screen on entry to debugger (this feature has no effect on two-monitor systems). F11 Single-step the current instruction (see Padplus). This key as well as F12 are useful on systems without a Padplus/Padminus key, or ones for which this key is difficult to type such as some laptops. F12 Single-skip the current instruction (see Padminus). s-F1 Goto the immediate CALL or JMP address of the instruction at the top of the screen and save the address of the current instruction (see Disassembly Bookmarks below). s-F2 Return from the previous s-F1 goto. s-F3 Goto the instruction on the top line (see Padstar). s-F4 Display the last AutoFault message. s-F5 Display the Real Mode Interrupt Vector Table. s-F10 Save the current screen in the last screen buffers. a-F1 Toggle intercept of INTs 01h/03h. The current state appears below the segment/selector register display as 01 or blank, 03 or blank. The default state is controlled by the presence or absence of the TRAPDEBUG keyword. a-F2 Toggle intercept of INT 02h. The current state appears below the segment/selector register display as 02 or blank. The default state is controlled by the presence or absence of the TRAPNMI keyword. a-F3 Toggle intercept of INT 0Dh. The current state appears below the segment/selector register display as 0D or blank. The default state is controlled by the presence or absence of the TRAPGENP keyword. a-F4 Toggle intercept of INT 0Eh. The current state appears below the segment/selector register display as 0E or blank. The default state is controlled by the presence or absence of the TRAPPAGE keyword. a-F5 Toggle stack display state between two columns of words and one column of dwords. The tick marks appear every 16 bytes. a-F6 Toggle screen save state (eliminates screen flicker when single-stepping over instructions which don't write to the screen). The current state appears below the segment/selector register display as SS=ON or SS=OFF. a-F7 Toggle video base (switch debugging screens in a two-monitor system). a-F8 Display NDP register screen. Use the same keystroke to remove the NDP screen. a-F9 Display debug register screen. This screen remains active until it is replaced by another screen. That is, you may type on the command line, etc. while the debug register screen is displayed. a-F10 Display previous debugging screens. This option can be used to compare changes over a single-step or single-skip. Up to sixteen previous screens can be displayed in this manner using the Up and Down arrows. To change from the default value of sixteen, use the keyword SAVESCREEN (see above). a-F11 Display MMX and SSE2 register screen. a-F Goto the far return address at SS:SP or SS|eSP (depending upon the current mode). If the current code segment is USE16, the far return address is assumed to be word:word (or word|word); if it's USE32, the format is assumed to be word:dword (or word|dword). This shortcut is equivalent to typing G .RETF at the command line. a-N Goto the near return address at SS:SP or SS|eSP (depending upon the current mode). If the current code segment is USE16, the near return address is assumed to be word; if it's USE32, the format is assumed to be dword. This shortcut is equivalent to typing G .RETN at the command line. c-F1 Toggle intercept of INT 01h only. The current state appears below the segment/selector register display as 01 or blank. The default state is controlled by the presence or absence of the TRAPSTEP keyword. c-F2 Toggle intercept of INT 03h only. The current state appears below the segment/selector register display as 03 or blank. The default state is controlled by the presence or absence of the TRAPSKIP keyword. c-F3 Toggle intercept of INT 06h. The current state appears below the segment/selector register display as 06 or blank. The default state is controlled by the presence or absence of the TRAPINV keyword. c-F4 Toggle intercept of INT 0Ch. The current state appears below the segment/selector register display as 0C or blank. The default state is controlled by the presence or absence of the TRAPSTACK keyword. c-F5 Display PDE entries. c-F6 Display symbols. c-F7 Display file browser. c-F8 Enter CHAT mode. This allows two connected machines to test the serial port connection. What you type is displayed on the lower screen and sent to the other system; whatever is received is displayed on the top screen. If only garbage characters appear the two machines may not have the same data transfer rate set. c-F9 Attempt to connect for remote debugging. See the section at the end of this document on remote debugging. c-F10 Display error log. c-F11 Single-step INT-like instruction in VM to PM, otherwise just single-step (same as c-Padplus). c-Up Decrement the location pointer to the previous entry. This change has a different effect depending upon the type of information being displayed. If used in a data display, it moves back one data item (byte, word, dword, etc.). If used in a TSS display, the I/O ports in the I/O bit permission map scroll up. c-Down Increment the location pointer to the next entry. This change has a different effect depending upon the type of information being displayed. If used in a data display, it moves forward one data item (byte, word, dword, etc.). If used in a TSS display, the I/O ports in the I/O bit permission map scroll down. c-Home Place the current instruction at the top of the screen. c-B Display memory in byte (xx) format. c-D Display memory in dword (xxxxxxxx) format. c-G Display memory in GDT format. c-I Display memory in IDT format. c-K Display Windows Kernel Debugger Structures menu. This menu may be displayed only when running under Windows as a kernel debugger. c-M Display memory allocation chain entries based at the value assigned to MACBASE. By default, this value is the initial value of .DMAC. c-T Display memory in TSS format. c-V Display memory in vector (xxxx:xxxx) format. c-W Display memory in word (xxxx) format. c-Z Zap (convert to NOPs) the instruction at the top of the instruction disassembly window. c-ESC Same as ESC, but if you're on an INT 03h, it skips over it first and then continues. If the current instruction is not an INT 03h, this keystroke behaves identically to ESC. Padplus Single-step the current instruction (same as F11). c-Padplus Single-step INT-like instruction in VM to PM, otherwise just single-step (same as c-F11). Padminus Single-skip the current instruction (same as F12). That is, execute the current instruction and put a breakpoint on the instruction following. This is used to execute but not single-step through a CALL or LOOP instruction. Padstar Goto the instruction on the top line. Up Scroll the screen up one line. This key has the same effect in almost all screen displays. Down Scroll the screen down one line. This key has the same effect in almost all screen displays. PgUp Scroll the screen up one page. This key has the same effect in almost all screen displays. PgDown Scroll the screen down one page. This key has the same effect in almost all screen displays. s-PrtSc Print the screen. Note that if either the previous application screen (F10) or one of the previous debugging screens (a-F10) is currently displayed, that screen is sent to the printer. The I/O port in the BIOS data area which corresponds to LPT1 is used. c-s-PrtSc Print the instruction portion of the screen. If the current screen displayed is the instruction disassembly window, print only the instruction portion of that screen. The I/O port in the BIOS data area which corresponds to LPT1 is used. Ctl-Alt-Del Reboot the system. Disassembly Bookmarks --------------------- At times you need to browse through some code (sometimes it's even your own code) following subroutine calls, conditional jumps, etc. wherever they might go. To make this task easier, use the s-F1 and s-F2 keys. To disassemble at the target of some instruction which transfers control, place the instruction at the top of the disassembly window and press s-F1. For example, say at offset 1234 in the code segment there is a CALL 5678. Place the CALL at the top of the disassembly window and press s-F1. The disassembly window now displays the code at 5678 with an invisible bookmark left at the return address 1234. Each time s-F1 is used, it leaves a bookmark at the instruction at the top of the disassembly window and disassembles at that instruction's target. To return to the previous bookmark, press s-F2. 386SWAT supports up to 128 nested levels of such disassembly. As another example, you should be able to disassemble almost any interrupt (say, U .VMI21 which disassembles at VM interrupt 21h), and using the bookmark feature exclusively, go down to the bottom of the chain. This feature is clever, but not that clever. It can figure out where (say) JMP Dword Ptr CS:[1234] is going and disassemble at that target, but it can't figure out the same instruction with a DS override. Nor can it handle effective addresses other than ones with an immediate displacement only (i.e., no registers such as [BX+SI]). Autofault --------- Have you ever been puzzled by some CPU fault as to why it occurred, that is, why did the CPU think there was a problem? If so, this feature is for you. Whenever 386SWAT is called on the difficult to figure out CPU faults (TSS Fault, Stack fault, GP Fault, or Page Fault), the Autofault feature attempts to determine why and to present a short prose description of the cause. The description is displayed in the lower lefthand corner of the screen. Pressing a key causes the message to disappear. To display it again (up to the time another fault occurs), press s-F4. This feature is implemented for GP, TSS, and Page Faults. Windows Debugging ----------------- 386SWAT runs as a debugger under Windows when accompanied by its VxD. This file (SWATVXD.EXE) should be in the same directory as the debugger file (386SWAT.LOD) and is loaded automatically when Windows starts. To take advantage of the information provided by the VxD, you should have a monochrome monitor and screen attached to your system. For more details about the VxD including how to configure it, see the file SWATVXD.DOC. Windows Kernel Deubugging ------------------------- If you program under Windows 3.1x or Win95 (but not WinNT), 386SWAT presents itself to Windows as a very low-level debugger. Essentially, 386SWAT is provided the same level of access as the remote debugger WDEB386 shipped with Windows. WDEB386 requires that you run it from a separate system with a COM cable running between the two systems. In contrast, 386SWAT runs on the same system being debugged, however it does require that you have a monochrome adapter and monitor installed in the system. For more details on this topic, see the file WINKDBG.DOC. Unreal Mode ----------- This mode is a variant of Real Mode in which any segment register can access all of the 4GB address space. That is, instead of the normal 64KB length of a segment, the length is 4GB. This command can enable all or just some of the segment registers for Unreal Mode. To enable this mode, use the command UNREAL as follows: UNREAL s reg [s reg ...] where s is a sign (+ or -) indicating whether to enable or disable, and reg is a segment register CS, DS, ES, FS, GS, SS, or the keyword ALL. For example, UNREAL +ALL enables UM for all segment registers UNREAL -ALL disables ... UNREAL +DS enables UM for DS only UNREAL +DS +ES enables UM for DS and ES To see if a segment register is enabled for UM, look for the plus sign next to the segment number in the instruction disassembly window. Command Line ------------ The line at the bottom of the screen is used to enter various commands. The following table summarizes the possibilities. The usual editing keys are available such as Left, Right, Home, End, Insert, Backspace, and Delete. Note that a colon (:) is used to separate a segment from an offset (Virtual 8086 Mode) and that a broken stile (|) is used to separate a selector from an offset (Protected Mode). The command line is parsed according to the grammar found in the file 386SWAT.GRM. Command Line Recall ------------------- Commands entered on the command line are saved in a ring buffer whose length can be changed from the default of 1024 via the profile keyword CMDHIST=nnn. Previous commands can be retrieved via the keystrokes Alt-< (previous command) and Alt-> (next command). Pressing either of these keys repeatedly scrolls through the buffer in the chosen direction. The keystroke Alt-? displays a history of (up to 25) commands from which a command can be chosen by scrolling up or down through the list, or by typing the letter next to the command. A command may be deleted from this list via the Del key. Monitor mode ------------ The GM (go monitor) command takes an expression which will be evaluated as the CPU single-steps (equivalent to Pad-plus or F11). No display will occur until 1) the monitor expression evaluates TRUE or 2) 386SWAT is invoked by some other means (GP fault, NMI, Ctrl- Alt-Pad5, etc.) Boolean expressions may be constructed using the dyadic operators &&, ||, <, <=, ==, >=, and >. Operator precedence is the same as the C language. See _Operators_. For example: gm ah will execute until AH is non-zero. gm [.csip == 21cd && ah!=9 will execute until the current instruction is INT 21 and AH is any value other than 9 (DOS display string). gm cx == 0 will execute until CX is 0. gm will execute until the last expression specified with gm is TRUE. Functions --------- A number of arithmetic, bitwise, and logical functions are available. The precedence of evaluation is similar to that of the C programming language. Here they are, listed in order of precedence: Functions Type --------------------------------------------------------------- - ~ Monadic * / Dyadic + - Dyadic symbols, .code, .data, etc. Address expression : | Dyadic (address construction) ] [ { Monadic (extraction) >> << Dyadic (bit shift) < <= >= > Dyadic (relational) == != Equality & Dyadic (bitwise AND) ^ Dyadic (bitwise XOR) && Dyadic (logical AND) || Dyadic (logical OR) For example, this expression 2a + 3 * {[.data+2|2c / 4 & ffff == 5af && 3 << bl || 21 ^ 2 is evaluated as (((2a + (3 * ({([.data+2)|(2c / 4)))) & (ffff == 5af)) && (3 << bl)) || (21 ^ 2) Code Breakpoints BC Display all code breakpoints. BC addr Set code breakpoint at ADDR. BC* Clear all code breakpoints. BC* addr Clear code breakpoint at ADDR. BC+ Enable all code breakpoints. BC+ addr Enable code breakpoint at ADDR. BC- Disable all code breakpoints. BC- addr Disable code breakpoint at ADDR. Debug Registers DR0 to DR3 BD Display debug registers (also Alt-F9). BD addr Set DR breakpoint on instruction fetches at address addr. BD addr Ln R Set DR breakpoint on read/writes of length n (n=1, 2, 4) at address addr. BD addr Ln W Set DR breakpoint on writes of length n (n=1, 2, 4) at address addr. BDn* Clear DRn. BDn+ Enable DRn. BDn- Disable DRn. Data Display D Display next screen of data D addr Data display D- Data display back one page Dx addr Data type (B = Byte, W = Word, D = Dword, V = Vector, G = GDT, I = IDT, T = TSS, T2 = 286 TSS, T3 = 386 TSS) Dx addr P Data display as physical data (say in ROM which has been mapped over by 386MAX) Dx addr P exp Data display using exp as CR3 - this is useful when debugging VCPI clients because they use a separate CR3 All data display commands may be followed by an optional width switch (e.g., DW/5 which displays the data at five words per line instead of the usual eight). The data width switch must be placed between the data command and its arguments (if any) as in DW/5 DS:0. Descriptor Table Entry DTE expr Display on the command line a Descriptor Table Entry. Data Entry E addr [xx ...] Enter data starting at ADDR using optional hex bytes xx. Exit To DOS EXIT Exit to DOS. This command is equivalent to the ' following command sequence: R AH=4C SIGINT 21 G Data Fill F addr L len xx Fill data starting at ADDR of length LEN with byte value xx. F addr L len xx P Fill physical data starting at ADDR of length LEN with byte value xx. F addr L len xx P exp Fill data starting at ADDR of length LEN with byte value xx where ADDR is translated using exp as CR3 - this is useful when debugging VCPI clients because they use a separate CR3. Data Move M addr L len addr Move data starting at first ADDR of length LEN to second ADDR Hex Arithmetic H exp Display hex arithmetic result Instruction Goto G Go without stopping (same as ESC) G addr Goto to instruction at address ADDR GM bool_exp Go monitor (single-step until bool_exp is TRUE) GM Go monitor using last boolean expression specified with gm MAC Display MACBASE addr Set the base address of the MAC chain in case it's different from .DMAC. This is handy when displaying the DOS subsegment chain. Insertion Into PM Context',CR INSERT gdtr idtr [cr3 [lapde]] Insert into PM context. INSERT * idtr Insert into IDT. where gdtr = linear address of fword describing the GDT idtr = ... IDT cr3 = incoming CR3 (optional) lapde= linear address of 4MB block where 386SWAT's PDE(s) should be copied Insert 386SWAT into a PM context while still in RM. This feature is useful when attempting to debug across the boundary from RM to PM. In particular, it can be used to gain control shortly after Windows enters PM. Instruction Disassembly U Display the next screen of instructions U addr Unassemble instructions starting at ADDR U- Unassemble instructions back one page U16 addr Unassemble instructions starting at ADDR as a 16-bit code segment U32 addr Unassemble instructions starting at ADDR as a 32-bit code segment Ux addr P Unassemble instructions as physical data (say in ROM which has been mapped over by 386MAX) Ux addr P exp Unassemble instructions starting at ADDR using exp as CR3 - this is useful when debugging VCPI clients because they use a separate CR3 Page Table Display PTE addr Display the Page Directory and Page Table entries PTE val which correspond to the address addr or linear address val. SPTE addr/val Same as PTE command, but also displays the matching PTE in the PTE display screen (F5). Signal Interrupt SIGINT xx Signal interrupt xx (00 to FF, of course). This keyword is useful (particularly for hardware interrupts) when you are debugging a time-critical piece of code and need to see what would happen if (say) a timer tick happened at this particular point. Toggle Interrupt Interception TOGINT xx [xx ...] Toggle interception of interrupt xx (00 to FF, of course). Valid interrupts are 00, 01, 02, 03, 05, 06, 0C, 0D, 0E. For example, if TRAPINV does not appear in the 386SWAT profile and you wish to enable it, use TOGINT 6. Register Operations R reg=exp Set register REG to EXP. Valid registers include all GP and EGP as well as FL, EFL, CRn, DRn, TRn, TR, and LDTR. There are two ways to crash the system via this command: setting CR3 to a bad value, or setting EFL with a bad value for the VM or IOPL flags. The code which sets CR0 forces the Page Enable and Protect Enable bits on (as evidenced by typing R CR0=0), so experiment without fear. Use the pseudo-register names CSIP or CSEIP to set both registers to an address. R reg.str=exp This command also supports bit mask qualifiers on registers. For example, to set the AM bit in CR0, type R CR0.AM=1. See below for a complete list of mask values supported. RC Clear saved register state so another RS may execute. RR Restore saved registers. RS Save registers to restore later via RR. Only one RS may be executed at a time without either restoring the state via RR or clearing the state via RC. Search Operations S addr1 addr2 tgt Search from addr1 to addr2 or from ea for len S addr L len tgt bytes for target tgt. The search results are displayed on a separate screen which may be made active at other times by pressing F6. Only the first 23 matches are displayed. In a future release the Up, Down, Page Up, and Page Down keys will allow scrolling through successive matches. The target may take one of several forms: * Use a target of the form xx, xxxx, xxxxxxxx where x represents a hex digit to search for bytes, words, or dwords of a specified value. For example, the form S 0:0 L FFFF 10CD searches for all occurrences of the hex bytes CD followed by 10 in the first 64KB of conventional memory. Word and dword searches do not require word or dword alignment of the matching data. The number of digits entered determines the width of the value. Thus you should use leading zeros to pad out a small value to a wider width. For example, 0 and 00 both search for a single byte of zeros, 000 and 0000 both search for a word of zeros, and 00000, 000000, 0000000, and 00000000 all search for a dword of zeros. * Use a target of the form "search_string" to search for a case sensitive string. For example, S 0:0 L FFFF "386MAX" searches for all occurrences of the string 386MAX in the first 64KB of conventional memory. The ability to search for a case insensitive string will be added in the future. * Use a target of the form !instr to search for a specific assembler instruction. For example, S 0:0 L FFFF !INT 10 searches for all occurrences of video interrupts in the first 64KB of conventional memory. This target is found by disassembling the code between the start and stop addresses instruction by instruction, thus the alignment of the matching instructions and the starting address is critical. If data appears within that range, some matches may be missed. The command S1 (instead of S) can be used to disassemble the code byte by byte. That is, with the S command, having disassembled an instruction which does not match the specified pattern, the next instruction is searched; with the S1 command, the next byte is searched. The code search text may include one or more question marks as wildcards which match any character in the disassembled instructions. For example, use S 50|0 FFFF !mov e??,cr? to find all moves from a control register to a 32-bit register. Try the forms S 3BC7:100 FFFF !mov [1234] and S 3BC7:100 FFFF !mov ?s:[1234] to find all moves into location [1234] with or without a segment override. To find jumps to a specific location, use the code targets !j? 1234, !j?? 1234, and !j??? 1234. Note that floating point instructions may be disassembled beginning with either 'F' or 'FN' depending upon the presence of a preceding WAIT opcode (9Bh). To be safe, search for both. * Use a target of the form #PTE to search for a PTE in the Page Tables. For example, S 0 C0000000 # CF4000 searches for the PTE CF4000 from linear 0 through linear C0000000. The linear addresses are both rounded down to a 4KB boundary. A match at a particular linear address means that the PTE was found and it covers the 4KB block at the linear address displayed. When comparing PTEs, the flag bits are ignored, thus a match might be found when the PTE in the Page Tables is not present. I/O Port Read/Write Ix port Input Byte, Word, or Dword from PORT IMR Display current Interrupt Mask Register values for master and slave PICs IRR Display current Interrupt Request Register values ISR Display current In-Service Register values Ox port val Output Byte, Word, Dword VAL to PORT Symbolic Debugging (see SWATSYM.DOC for details) CD [d:][path] Change the current directory to path. If no CHDIR [d:][path] argument, display the current drive/directory. FS Flush symbol table. LF filename Load file into browser. LI + Enable line number display in disassembly screen. LI - Disable line number display. LI dddd Go to line dddd (decimal) in file browser. LI dddd+ Go to line dddd forward from current line. LI dddd- Go to line dddd back from current line. LS filename Load symbol file. LS filename exp Load symbol file and add 16-bit value to all VM segments. PATH d:\dir1[,d:\dir2[,...]] Set source file search path. PATH+ d:\dira[,d:\dirb[,...]] Add to source file search path. PS r Set range of symbol proximity searches to r. PS r g Set range and granularity (1=bytes, 2=words, 4=dwords) of symbol proximity searches. QS addr Display the symbol nearest to (and below) thegiven address. SB+ Enable source browser mode. SB- Disable source browser mode. SB*+ Enable source browser mode but disregard module names. TS Force all symbols to be retranslated according to current GDT and LDT. TS sel Retranslates only for selector/segment sel. TS * ID Retranslates for all selectors/segments with ID specified. TS sel ID Retranslates only for selector/segment sel with ID specified. TS *|sel *|ID v|p Change to specified mode for selector and/or ID specified. TS *|sel *|ID *|v|p nsel Replace segment/selector and mode for specified selectors and IDs. If * is specified for mode, the mode is left alone. TS *|sel *|ID *|v|p nsel+ nsel is added to all specified segments. Remote debugging APPKEY Edit application keystroke buffer. This is primarily useful for remote debugging. If an application is waiting for a keystroke, this feature allows you to send one to the application, as well as to view any that may already be available. CHAT Enter CHAT mode (also via Ctl-F8) SETCOM port bps Initialize specified serial port for communications. See SETCOM= profile option for full syntax. SETCOM Reinitialize the serial port with values last specified by SETCOM or SETCOM=. This is useful when an application has reprogrammed the UART. SETCOM - Ignore all activity on serial port. Use this if you are done with remote debugging and wish an application to have access to the serial port. When 386SWAT is using the serial port, no serial port interrupts will be visible to virtual mode programs. SETCOM RTS+ Pull RTS (Request To Send) line high. SETCOM RTS- Drop RTS (Request To Send) line low. SETCOM DTR+ Pull DTR (Data Terminal Ready) line high. SETCOM DTR- Drop DTR (Data Terminal Ready) line low. This is one way to hang up a modem that won't respond to (wait)+++ (wait)ATH(ENTER). REMDBG Attempt to establish remote debugging session (also via Ctl-F9). See the section below on remote debugging. Unreal Mode UNREAL s reg [s reg ...] Turn on or off Unreal Mode. This mode is a variant of Real Mode in which data registers (DS, ES, FS, GS, or SS) can access all of the 4GB address space. That is, instead of the normal 64KB length of a data segment, the length is 4GB. This command can enable all or just some of the data registers for Unreal Mode. Legend: s is either + or - and reg is one of ALL DS ES FS GS or SS For example: To enable all registers, use +ALL To disable all registers, use -ALL To enable or disable selected registers, use +xS or -xS, where x is D E F G or S, as in +DS or -ES. You may specify multiple registers on the same line as in +DS +ES. Virtual Mode Switches VMSCOUNT=val Don't intrude into the GDT/IDT for VCPI debugging until the value in this counter has decremented to zero. This keyword is useful for occasions where the VCPI client shuffles its GDT and IDT around for a while before deciding just where it's going to be. VMSINT=ON Enable (ON) or disable (OFF) VCPI debugging. Use VMSINT=OFF this feature in cases where some VCPI programs misbehave when VCPI debugging is enabled. In this case, enable VCPI debugging only as necessary. VMSINT=xx,xx,... Change the default interrupts intercepted by 386SWAT when debugging VCPI clients. Pentium-Pro CPU Specific Commands BTF Display Branch Trace Facility state (ON or OFF). BTF ON|OFF Turn Branch Trace Facility state ON or OFF. LBR Display Last Branch/Exception values on the command line. LBR ON|OFF Turn Last Branch/Exception window display ON or OFF. The four-line window displays the Last Branch From EIP, Last Branch To EIP, Last Exception From EIP, and Last Exception To EIP. Also, the keywords .LBRFR, .LBRTO, .LEXFR, .LEXTO contain the value of the Last Branch/Exception From/To EIP in case these need to be used in command line expressions (e.g., U .LBRFR). Windows Debugging Commands IPF [/d] [/s] [/r] expr If Invalid Page Faults are being trapped by 386SWAT's VxD (see SWATVXD.DOC for more details), use the IPF command to control how these events are to be handled. The optional switch /d tells 386SWAT not to display a message on the mono screen describing this event, /s tells 386SWAT not to stop when this event occurs, /r tells 386SWAT to remove this entry from its local tables, and expr is an expression which evaulates to a linear address corresponding to the Invalid Page Fault. MDB expr Display the memory pointed to by the selector expr as a Windows Module Database. SGH [/b|/s|/h|/o] [/c] expr Search through the Windows Global Heap for values. The expression (expr) entered is interpreted as a base address if /b is specified, size if /s, handle if /h, and owner if /h. If /c is specified, the search continues from the currently displayed entry; otherwise, the search starts at the top of the heap. TDB expr Display the memory pointed to by the selector expr as a Windows Task Database. WKD [ON|OFF] Turn ON or OFF Kernel Debugging. This command cannot be used from within Windows. WKD [QUIET|NOISY] Disable (QUIET) or Enable (NOISY) reports on Parameter Errors. WKD LOGERROR [ON|OFF] Turn ON or OFF the INT 01h trap of LogErrors. WKD FAULT [ON|OFF|SKIP] Turn ON, OFF, or SKIP once traps for Faults. WKD WCB1 [ON|OFF] Turn ON or OFF signalling of signalling an INT 01h at Windows Callback time when entering Windows (VM->RM) so breakpoints can be set. This command is particularly useful in conjunction with the INSERT command. Common Memory References ------------------------ There are a number of points in memory to which it is common to refer, e.g., the address of the instruction at the top of the disassembly window. These references are made easier by using one of the following shortcuts (all of which can be used anywhere on the command line where an address is expected such as BD .CODE, or BD .DATA L4 W): .EA Effective Address of the first (or only) operand to the instruction at the top of the disassembly window .EA2 Effective Address of the second operand to the instruction at the top of the disassembly window .GDT GDT base address (using selector zero) .IDT IDT ... .LDT LDT ... .TSS TSS ... .CMAC Seg:Off of next C MAC entry -- equivalent to .DATA + 2 + FFFE & [.DATA .CODE current code display address .CSIP current cs:[e]ip .DATA current data display address .DMAC Seg:0 of first DOS MAC entry .NMAC Seg:0 of next DOS MAC entry -- equivalent to ((S..DATA)+1+[.DATA+3):0 .LBRFR EIP of Last Branch From .LBRTO ... To .LEXFR ... Exception From .LEXTO ... To .MDB Sel|0 of current Windows Module Database .TDB ... Task ... .PMIxx Sel|Off of PM Interrupt xxh .RMIxx Seg:Off of RM interrupt # xx .VM Sel|Off of current Windows VM structure .VMCRS Sel|Off of Client Register Struc in .VM .VMIxx Seg:Off of VM interrupt # xx .VMRET Return CS|EIP saved in .VMCRS .XBDA Seg:Off of XBDA; same as ([40:0E):0 .XBDA2 Seg:Off of 2ndary XBDA; same as ((S..XBDA)+[.XBDA+B4):0 A common address to jump to is the (near or far) return address of a subroutine. This is made easier by using shortened forms of the commands one might use to extract these addresses. The various flavors of return addresses are (where LaSTK is the address of the current stack pointer -- SS:SP if VM, SS|SP if PM and the B-bit in SS is clear, and SS|ESP if PM and the B-bit in SS is set): Keyword Grammar Equivalent Meaning --------------------------------------------------------------------- .RETND {LaSTK Near dword .RETNS [LaSTK Near word .RETFD :{LaSTK or |{LaSTK Far word:dword or word|dword (depending upon the VM bit in the current EFL) .RETFS :[LaSTK or |[LaSTK Far word:word or word|word (depending upon the VM bit in the current EFL) .RETN .RETND or .RETNS Depending upon the D-bit in CS .RETF .RETFD or .RETFS ... .IRET .RETF in VM Also allows mode switch from .RETFD in PM PM to VM by checking VM bit in EFL above return address As a common shortcut, .RETN and .RETF refer to one of the above forms depending upon the setting of the D-bit in the current CS (that is, whether we're running in a USE16 or USE32 segment). Moreover, .IRET can be used as a shorthand for .RETF with the added check on the VM bit in the EFL above the return address. If this bit is set, the return address is interpreted as a VM address even though the current mode is PM. No magic is invoked to extract the return address if data has been pushed onto the stack below the return address, so be sure that LaSTK points to the actual return address. Also note that the keystrokes A-F and A-N are defined as shortcuts for the commands G .RETF and G .RETN, respectively. Register Mask Values -------------------- The following pseudo-records describe the bit masks supported by the register command where "*" represents reserved bits with no corresponding name: EFL record *:13, AC:1, VM:1, RF:1, *:1, NT:1, IOPL:2, OF:1, DF:1,\ IF:1, TF:1, SF:1, ZF:1, *:1, AF:1, *:1, PF:1, *:1, CF:1 CR0 record PG:1, CD:1, NW:1, *:10, AM:1, *:1, WP:1,\ *:10, NE:1, ET:1, TS:1, EM:1, MP:1, PE:1 PTE record FRM:20, PTE_AVL:3, *:2, PTE_D:1, PTE_A:1,\ PTE_CE:1, PTE_WT:1, PTE_US:1, PTE_RW:1, PTE_P:1 SEL record SEL:13, TI:1, PL:2 DR6 record *:16, BT:1, BS:1, BD:1, *:9, B3:1, B2:1, B1:1, B0:1 DR7 record LEN3:2, RW3:2, LEN2:2, RW2:2, LEN1:2, RW1:2, LEN0:2, RW0:2,\ *:2, GD:1, *:3, GE:1, LE:1, G3:1, L3:1, G2:1, L2:1, G1:1, L1:1,\ G0:1, L0:1 TR4 record TR4_TAG:21, TR4_WVAL:1, TR4_LRU:3, TR4_RVAL:4, *:3 TR5 record *:21, TR5_SSEL:7, TR5_ESEL:2, TR5_CTL:2 TR6 record FRM:20, TR6_V:1, TR6_D:1, TR6_DP:1, TR6_U:1, TR6_UP:1,\ TR6_W:1, TR6_WP:1, *:4, TR6_C:1 TR7 record FRM:20,*:7, TR7_HT:1, TR7_REP:2, *:2 NDP Register Screen ------------------- This feature is preliminary, but it does allow you to move through the NDP registers and settings and change them at will. Lacking is an exact binary to decimal conversion algorithm as well as a decimal to binary conversion algorithm. It can be displayed and cleared via Alt-F8. MMX & SSE Register Screen ------------------------- This feature is preliminary, but it does display all of the registers. To see the register display, press Alt-F11. If there are things you like to see on this screen, just ask. Not being an MMX or SSE programmer, I'm not sure what such programmers need. Remote debugging ---------------- Two machines may be connected for remote debugging. The connection may be made via a null modem cable connecting the serial ports on both machines, or via modem. The connection is initiated by using the SETCOM command to initialize the serial port, then pressing Ctl-F9 on each system to attempt to connect. When a connection is established, the "Press M to become master" prompt appears. Only one of the two systems may become master; the other one then becomes the slave. Processing on the slave system then proceeds normally; the master system is now running a special terminal program. Keystrokes typed in the master terminal program are sent to the remote system (with some exceptions - see below), and screen output from the remote 386SWAT system appears on the master terminal screen. Special keys Ctl-Alt-Del will NOT be sent to the remote system while in the master terminal screen - it will reboot the master system. Ctl-F9 invokes a menu of special options for the master system: T Terminate connection with slave immediately. G Terminate connection, but have slave go instead of returning to the 386SWAT command prompt. R Terminate connection, have slave go, but have slave automatically attempt to re-establish connection on next invocation of 386SWAT. B Terminate connection and reboot slave system. S Suspend session temporarily. This temporarily exits the terminal program. You may exit 386SWAT. Ctl-F9 again resumes the connection. U Upload program to remote. D Download program from remote. Esc Continue with terminal program Other keys are Ctl-6 (interrupt remote) and Alt-F7 (send remote screen only to master). Alt-F7 is useful for debugging when the remote system is in graphics mode or otherwise unable to access the CRT controller. VCPI Program Debugging ---------------------- An API for use by VCPI programs is described in the file VCPIDBG.DOC. Real Mode Debugging ------------------- If you find that an error (such as GP Fault) is signalled at an address other than the expected address, you might have DOS Stacks switched on. In this case, DOS intercepts all IRQ interrupts inserts a new stack into the picture and then passes the interrupt onto the next handler. To avoid this problem (and others which DOS Stacks attempts to solve but doesn't), put Stacks=0,0 into your CONIFG.SYS file and reboot. If you have ever installed Windows 3.x or later (including Win 9x/ME) on your system, likely there is a residual Stacks=9,256 in your CONFIG.SYS. That statement has the effect of wasting 2500 bytes of low DOS memory for nothing. Limitations ----------- This program is very preliminary. It lacks many of the features of a full-blown debugger. On the other hand, it has a few features they don't have. Technical Support ----------------- Please send your problems, praises, and comments to bsmith@sudleyplace.com  ================================================ FILE: swat/386SWAT.GRM ================================================ '$Header: P:/PVCS/386SWAT/386SWAT.GRV 1.32 10 Aug 1998 11:00:44 BOB $ GRAMMAR FOR 386SWAT COMMAND LINE // Command lines APPKEY BCnx opt_addr n {, 0..7} x {, *, +, -} BD opt_addr BD addr Ln I n {, 1, 2, 4} BD addr Ln R n {, 1, 2, 4} BD addr Ln W n {, 1, 2, 4} BD addr L1 X BDnx x {*, +, -} n {, 0, 1, 2, 3} BPnx opt_addr n {, 0..7} x {, *, +, -} BTF BTF {ON|OFF} CHAT Dxy- x {, b, d, g, i, t, t2, t3, v, w}, y {, /n} where n is the data width Dxy opt_addr x {, b, d, g, i, t, t2, t3, v, w}, y {, /n} where n is the data width Dxy addr P x {, b, d, g, i, t, t2, t3, v, w}, y {, /n} where n is the data width Dxy addr P exp x {, b, d, g, i, t, t2, t3, v, w}, y {, /n} where n is the data width DLGx addr x {16, A, 32, W} DTE exp E addr E addr lvallist EXIT F addr L lval lval F addr L lval lval P F addr L lval lval P exp FS G opt_addr GM opt_boolexp H addr Ix lval x {, b, d, w} IMR INSERT gdtr idtr [cr3 [lapde]] INSERT * idtr IPF [/d] [/s] [/r] expr IRR ISR LBR LBR {ON|OFF} LF filename LI x x {+, -} LI dcon x x {, +, -} LS filename x x {, lval} M addr L lval addr MACBASE addr MDB exp Ox lval lval x {, b, d, w} PATHx dirlist x {, +} PS lval x x {, lval (<256)} PTE addr PTE exp PTE addr P exp PTE exp P exp QS addr R reg = exp R reg.str = exp REBOOT x x {0, 1, 2} REMDBG RC RR RS Sx addr L expr atom x {, 1} Sx addr addr atom x {, 1} S addr addr ! instr S addr L expr ! instr S addr addr # PTE S addr L expr # PTE SBx x {+, -} SB*x x {+, -} SETCOM x x {, -} SETCOM port bps port {1, 2, 3, 4} SETCOM xn x {RTS, DTR} n {+, -} SGH [/b|/s|/h|/o|/n] [/c] expr SIGINT lval SPTE addr SPTE exp SPTE addr P exp SPTE exp P exp TDB exp TOGINT lvallist TS TS opt_sel opt_group x opt_seln opt_addr x {, *, P, V} n {, +, -} Ux- x {, 16, 32} Ux opt_addr x {, 16, 32} Ux addr P x {, 16, 32} Ux addr P exp x {, 16, 32} VMSCOUNT xx VMSINT {ON|OFF} VMSINT=xx,xx,... WKD FAULT [ON|OFF|SKIP] WKD LOGERROR [ON|OFF] WKD [ON|OFF] WKD [QUIET|NOISY] // Lval list lvallist lval lval lvallist // Optional addresses opt_addr addr // Addresses addr exp using default segment/selector as per specific command ea // Optional boolean expression opt_boolexp exp // Expressions on values exp ( exp ) mfn monadic functions dfn dyadic functions // Monadic functions mfn atom [ ea extract word at effective address { ea extract dword ... O.ea extract offset from effective address S.ea extract segment/selector ... L.ea extract linear address ... P.ea extract physical address ... + exp - exp ~ exp // Lefthand values lval atom ( exp ) // Effective address with segment/selector ea seg : exp sel | exp .EA Effective Address #1 (or the only one) .EA2 ... #2 .GDT GDT base address (using selector zero) .IDT IDT ... .LDT LDT ... .TSS TSS ... .CMAC address of next C MAC entry .CODE current code display address .CSIP address of current cs:[e]ip .DATA current data display address .DMAC segment of first DOS MAC entry .NMAC segment of next DOS MAC entry .PMIxx Sel|Off of PM Interrupt xxh .RMIxx Seg:Off of RM interrupt # xx .VM Sel|Off of current Windows VM structure .VMIxx .. VM ... .VMRET return cs|eip from Windows VM (|{.vmstk+50 or |{.vmstk+150) .VMSTK current ss|esp saved in Windows VM structure (same as |{.vm+40) .IRET far word:dword return address on stack allowing a mode switch from PM to VM .RETN near word or dword return address on stack .RETND near dword return address on stack .RETNS near word return address on stack .RETF far word:word or word:dword return address on stack .RETFD far word:dword return address on stack .RETFS far word:word return address on stack .XBDA Seg:Off of XBDA; same as ([40:0E):0 .XBDA2 Seg:Off of 2ndary XBDA; same as ((S..XBDA)+[.XBDA+B4):0 dotcmd ? exp dyadic functions on dot commands (.GDT, .IDT, etc.) where ? is a dyadic function :[ ea extract word:word at effective address :{ ea ... word:dword ... |[ ea ... word|word ... |{ ea ... word|dword ... |G ea ... ... in GDT-format (using selector zero) |I ea ... ... in IDT-format (using IDT selector) |L ea ... ... in LDT-format (same as GDT-format) |T ea ... ... in TSS-format (using CS|EIP) symbol effective address of this symbol // Dyadic functions on dot commands dotcmd ? exp S.dotcmd : O.dotcmd ? exp for VM addresses S.dotcmd | O.dotcmd ? exp ... PM ... where ? is a dyadic function // Dyadic functions dfn atom lval + exp addition lval - exp subtraction lval * exp multiplication lval / exp division (with truncation towards zero) lval & exp bitwise AND lval ^ exp bitwise XOR lval == exp is equal (eq) lval != exp is not equal (ne) lval < exp is less than (lt) lval <= exp lt or eq lval > exp is greater than (gt) lval >= exp gt or eq lval && exp logical AND lval || exp logical OR Because we have usurped the | symbol as the selector separator, it is not available for bitwise OR. To do bitwise OR between A and B, use (A & ~B) ^ B // Precedence Operators Type - ~ Monadic * / Dyadic + - Dyadic symbols, .code, .data, etc. Address expression : | Dyadic (address construction) ] [ { Monadic (extraction) >> << Dyadic (bit shift) < <= >= > Dyadic (relational) == != Equality & Dyadic (bitwise AND) ^ Dyadic (bitwise XOR) && Dyadic (logical AND) || Dyadic (logical OR) // Segment or selector seg lval sel lval // Optional segment or selector opt_sel * seg sel // Optional group ID opt_group * con // Atoms atom con reg .LBRFR .LBRTO .LEXFR .LEXTO // Registers reg GP AX, AL, AH, BX, ... EGP EAX, EBX, ECX, ... CRn Control registers DRn Debug registers TRn Test registers Misc IP, EIP, FL, EFL, TR, LDTR // Constants con <32-bit hex values> dcon <16-bit unsigned decimal values> filename dirlist // Bits per second (BPS) values bps 55 110 300 600 1200 2400 4800 9600 19200 38400 76800 115200 Note that this grammar is mostly precedence-free. Multiplication and division have a higher precedence than addition and subtraction, but everything else is at the same level. Moreover, other than the above exception, all expressions execute right to left. When in doubt, use parentheses. Examples -------- * To display the successive entries in the DOS memory allocation chain, display one such entry via a DB command. Then type /D ((S..DATA)+1+[.DATA+3):0 Continuing to press Enter displays the successive MAC entries. * To display the successive entries in the C memory allocation chain, display one such entry (at the count word) via a DB command. Then type /D .DATA + 2 + FFFE & [.DATA  ================================================ FILE: swat/FILELIST.TXT ================================================ This file contains a list of all files included in 386SWAT.ZIP along with a brief description of each file's contents. FILELIST.TXT This file. 386SWAT.DOC A preliminary documentation file. SWATSYM.DOC A documentation file for 386SWAT symbolic debugging. VCPIDBG.DOC A documentation file describing the API implemented in 386SWAT for debugging VCPI clients. 386SWAT.LOD The debugger itself. See 386SWAT.DOC for details. 386SWAT A sample profile file listing all profile options. You may wish to copy this file to *.PRO and use it as the basis for your customized profile. 386SWAT.GRM A listing of the LALR grammar used by 386SWAT's command line. MAPSSF.EXE A program to convert a .MAP file to a .SSF (SWAT Symbol File) as well as pass symbols to 386SWAT. See the file SWATSYM.DOC for details. SWATCMD.EXE A program used to send commands to 386SWAT. This program also runs as a device driver to aid in debugging those programs. SWATRUN.COM A program used to run another program under 386SWAT's control. See the file SWATSYM.DOC for details. SWATVXD.EXE A VxD for debugging Windows applications (as well as other VxDs). See SWATVXD.DOC for details. DPMITSR.ZIP This program is an example of a simple DPMI TSR. It hooks Int 21 function 4B. EPM.ZIP This program is an example of Entering PM from any of RM, VM-VCPI, or VM-DPMI. When debugging VCPI clients, make sure you have enabled the VMSINT flag (use VMSINT ON from the SWAT command line). HELLO_PM.ZIP This program is an example of a DPMI application that enters protected mode via DPMI services, prints "Hello, world," then returns to DOS (and V86 mode). SWATDPMI.ZIP This program is an example of a DPMI application that copies code into extended memory, then executes it. KEYBIN.COM Use this program on an International keyboard to help the author of 386SWAT support your keyboard. KEYBIN.TXT Consult this text file to see how to use KEYBIN.  ================================================ FILE: swat/KEYBIN.HTM ================================================ Documentation For KEYBIN.COM
Documentation for KEYBIN.COM

Use this program on an international keyboard to help the author of 386SWAT support your keyboard.

First try out the program to see how it works (note Space bar to Exit).  Next redirect the program's output to a file and type all keys (blindly).

Type every key on your keyboard except for function, arrow, and keypad keys.  Type every key in unshifted state as well as with the Shift-, Control-, and Alt-keys.  If your keyboard distinguishes between the left and right Shift-, Control-, and/or Alt-keys be sure to test all states for all keys.

After exiting the program, annotate the output file with any comments you consider appropriate.  Finally, e-mail the file to the author (bsmith@sudleyplace.com).

For reference, supported international keyboard layouts include
GR129 Germany
SP172 Spain
The keyboard layouts to which I have access and don't currently support are as follows:
BE120 Belgium
CF058 Canada (French)
DK159 Denmark
SU153 Finland
FR120 France
FR189 France
IS197 Iceland
IT142 Italy
LA171 Latin America
NL143 Netherlands
NO155 Norway
PO163 Portugal
SF150 Switzerland (French)
SG150 Switzerland (German)
TR179 Turkey
UK166 United Kingdom
YU234 Yugoslavia (Latin)
================================================ FILE: swat/KEYBIN.TXT ================================================ Documentation for KEYBIN.COM Use this program on an international keyboard to help the author of 386SWAT support your keyboard. First try out the program to see how it works (note Space bar to Exit). Next redirect the program's output to a file and type all keys (blindly). Type every key on your keyboard except for function, arrow, and keypad keys. Type every key in unshifted state as well as with the Shift-, Control-, and Alt-keys. If your keyboard distinguishes between the left and right Shift-, Control-, and/or Alt-keys be sure to test all states for all keys. After exiting the program, annotate the output file with any comments you consider appropriate. Finally, e-mail the file to the author (see the address at the bottom of the 386SWAT.DOC file). For reference, supported keyboard layouts include GR129 Germany SP172 Spain The keyboard layouts to which I have access and don't currently support are as follows: BE120 Belgium CF058 Canada (French) DK159 Denmark SU153 Finland FR120 France FR189 France IS197 Iceland IT142 Italy LA171 Latin America NL143 Netherlands NO155 Norway PO163 Portugal SF150 Switzerland (French) SG150 Switzerland (German) TR179 Turkey UK166 United Kingdom YU234 Yugoslavia (Latin)  ================================================ FILE: swat/SWAT.HTM ================================================ 386SWAT Overview

386SWAT -- A Protected Mode Debugger
(C) Copyright 1988-2003 Qualitas, Inc. All rights reserved.

This protected mode debugger provides debugging services to real mode, protected mode, virtual 8086 mode programs, DPMI and VCPI clients, and Win 3.1x and Win95/98 programs under any memory manager while occupying only a few kilobytes of low DOS memory.

It supports disassembly of the full 386, 387, 486, Pentium, and Pentium Pro CPU instruction sets through the Pentium MMX & SSE instructions.

This debugger is also a Windows Kernel Debugger providing low-level Windows debugging services a la WDEB386, but residing in the same machine, so no COM port hookup is needed. To take advantage of this feature, you must have a separate video adapter (PCI or ISA monochrome) and matching monitor attached to your system.

This program started out in early 1988 as an internal tool in Qualitas to help write and debug 386MAX, but has matured into a significant program in itself (the executable is over 400 KB generated from over 3MB of 386 assembly language source code). As it stands now, 386SWAT can debug almost any

  • Real Mode (RM)
  • Virtual Mode (VM)
  • VCPI- or DPMI-based Protected Mode (PM), and
  • Windows 3.1x and Win95/98 program.

Although 386SWAT was written to debug 386MAX, it can also intrude into the PL0 context of other memory managers as well so as to function as a PL0 debugger there. It also can debug programs remotely (over a modem) and can display source code instead of just disassembly instructions, along with many other features.

I'd be interested in getting some feedback from you as to how useful 386SWAT is as well as how I can improve it.

Questions or comments, please e-mail the author at bsmith@sudleyplace.com, or perhaps you'd like more detailed documentation, or just jump right in and download it.

================================================ FILE: swat/SWATAFLT.HTM ================================================ Autofault

Autofault

Have you ever been puzzled by some CPU fault as to why it occurred, that is, why did the CPU think there was a problem?  If so, this feature is for you.  Whenever 386SWAT is called on the difficult to figure out CPU faults (TSS Fault, Stack Fault, GP Fault, or Page Fault), the Autofault feature attempts to determine why and to present a short prose description of the cause.  The description is displayed in the lower lefthand corner of the screen. Pressing a key causes the message to disappear.  To display it again (up to the time another fault occurs), press s-F4.

This feature is implemented for GP, TSS, and Page Faults, although they all could use more tweaking.  ================================================ FILE: swat/SWATBMRK.HTM ================================================ Disassembly Bookmarks

Disassembly Bookmarks

At times you need to browse through some code (sometimes it's even your own code) following subroutine calls, conditional jumps, etc. wherever they might go. To make this task easier, use the s-F1 and s-F2 keys. To disassemble at the target of some instruction which transfers control, place the instruction at the top of the disassembly window and press s-F1. For example, say at offset 1234 in the code segment there is a CALL 5678. Place the CALL at the top of the disassembly window and press s-F1. The disassembly window now displays the code at 5678 with an invisible bookmark left at the calling address 1234. Each time s-F1 is used, it leaves a bookmark at the instruction at the top of the disassembly window and disassembles at that instruction's target. To return to the previous bookmark, press s-F2.  386SWAT supports up to 128 nested levels of such disassembly.

As another example, you should be able to disassemble almost any interrupt (say, U .VMI21 which disassembles at VM interrupt 21h), and using the bookmark feature exclusively, go down to the bottom of the chain.

This feature is clever, but not that clever. It can figure out where (say)

    JMP Dword Ptr CS:[1234]

is going and disassemble at that target, but it can't figure out the same instruction with a DS override. Nor can it handle effective addresses other than ones with an immediate displacement only (i.e., no registers such as [BX+SI]).  ================================================ FILE: swat/SWATCMD.HTM ================================================ Command Line Actions

Command Line Actions

A number of arithmetic, bitwise, and logical functions are available. The precedence of evaluation is similar to that of the C programming language.  Here they are, listed in order of precedence:
 
Functions Type
- ~ Monadic
* / Dyadic
+ - Dyadic
symbols, .code, .data, etc. Address expression
: | Dyadic (address construction)
] [ { Monadic (extraction)
>> << Dyadic (bit shift)
< <= >= > Dyadic (relational)
== != Equality
& Dyadic (bitwise AND)
^ Dyadic (bitwise XOR)
&& Dyadic (logical AND)
|| Dyadic (logical OR)
For example, this expression

2a + 3 * {[.data+2|2c / 4 & ffff == 5af && 3 << bl || 21 ^ 2

is evaluated as

(((2a + (3 * ({([.data+2)|(2c / 4)))) & (ffff == 5af)) && (3 << bl)) || (21 ^ 2)
 
 
Code Breakpoints
BC Display all code breakpoints.
BC addr Set code breakpoint at addr.
BC* Clear all code breakpoints.
BC* addr Clear code breakpoint at addr.
BC+ Enable all code breakpoints.
BC+ addr Enable code breakpoint at addr.
BC- Disable all code breakpoints.
BC- addr Disable code breakpoint at addr.

 
Debug Registers DR0 to DR3
BD Display debug registers (also Alt-F9).
BD addr Set DR breakpoint on instruction fetches at address addr.
BD addr LnI Set DR breakpoint on I/O of length n (n=1 (byte), 2 (word), 4 (dword)) at I/O port addr.
BD addr LnR Set DR breakpoint on read/writes of length n (n=1, 2, 4) at address addr.
BD addr LnW Set DR breakpoint on writes of length n (n=1, 2, 4) at address addr.
BDn* Clear DRn.
BDn+ Enable DRn.
BDn- Disable DRn.

 
Data Display
D Display next screen of data.
D addr Data display.
D- Data display back one page.
Dx addr Data type (B = Byte, W = Word, D = Dword, V = Vector, G = GDT, I = IDT, T = TSS, T2 = 286 TSS, T3 = 386 TSS).
Dx addr P Data display as physical data (say in ROM which has been mapped over by 386MAX).
Dx addr Pexp Data display using exp as CR3 - this is useful when debugging VCPI clients because they use a separate CR3.
All data display commands may be followed by an optional width switch (e.g., DW/5 which displays the data at five words per line instead of the usual eight). The data width switch must be placed between the data command and its arguments (if any) as in DW/5 DS:0

 
Data Entry
E addr [xx ...] Enter data starting at addr using optional hex bytes xx.

 
Descriptor Table Entry
DTE expr Display the Descriptor Table Entry corresponding to the selector in expr.

 
Exit To DOS
EXIT Exit to DOS. This command is equivalent to the following command sequence: 

R AH=4C
SIGINT 21
G


 
Data Fill
F addrL len xx Fill data starting at addr of length len with byte value xx.
F addr Llen xx P Fill physical data starting at addr of length len with byte value xx.
F addr Llen xx Pexp Fill data starting at addr of length len with byte value xx where addr is translated using exp as CR3 - this is useful when debugging VCPI clients because they use a separate CR3.

 
Data Move
M addr Llen addr Move data starting at first addr of length len to second addr

 
Hex Arithmetic
H exp Display hex arithmetic result

 
Instruction Goto
G Go without stopping (same as ESC)
G addr Goto to instruction at address addr
GM bool_exp Go monitor (single-step until bool_exp is TRUE) -- see Monitor Mode
GM Go monitor using last boolean expression specified with GM

 
MAC Display
MACBASE addr Set the base address of the MAC chain in case it's different from .DMAC. This is handy when displaying the DOS subsegment chain.

 
Insertion Into PM Context
INSERT gdtridtr [cr3 [lapde]] Insert into PM context.
INSERT * idtr Insert into IDT.
where 
gdtr = linear address of fword describing the GDT 
idtr = ... IDT 
cr3 = incoming CR3 (optional) 
lapde= linear address of 4MB block where 386SWAT's PDE(s) should be copied 
Insert 386SWAT into a PM context while still in RM. This feature is useful when attempting to debug across the boundary from RM to PM. In particular, it can be used to gain control shortly after Windows enters PM. 

 
Instruction Disassembly
U Display the next screen of instructions.
U addr Unassemble instructions starting at addr.
U- Unassemble instructions back one page.
U16 addr Unassemble instructions starting at addr as a 16-bit code segment.
U32 addr Unassemble instructions starting at addr as a 32-bit code segment.
Ux addr P Unassemble instructions as physical data (say in ROM which has been mapped over by 386MAX).
Ux addr Pexp Unassemble instructions starting at addr using exp as CR3 - this is useful when debugging VCPI clients because they use a separate CR3.

 
Page Table Display
PTE addr
PTE val
Display the Page Directory and Page Table entries which correspond to the address addr or linear address val.
SPTE addr/val Same as PTE command, but also displays the matching PTE in the PTE display screen (F5).

 
Signal Interrupt
SIGINT xx Signal interrupt xx (00 to FF, of course).
This keyword is useful (particularly for hardware interrupts) when you are debugging a time-critical piece of code and need to see what would happen if (say) a timer tick happened at this particular point.

 
Toggle Interrupt Interception
TOGINT xx [xx ...] Toggle interception of interrupt xx (00 to FF, of course). Valid interrupts are 00, 01, 02, 03, 05, 06, 0C, 0D, 0E. For example, if TRAPINV does not appear in the 386SWAT profile and you wish to enable it, use TOGINT 6.

 
Register Operations
R reg[=]exp Set register reg to exp. Valid registers include all GP and EGP as well as FL, EFL, CRn, DRn, TRn, TR, and LDTR. There are two ways to crash the system via this command: setting CR3 to a bad value, or setting EFL with a bad value for the VM or IOPL flags. The code which sets CR0 forces the Page Enable and Protect Enable bits on (as evidenced by typing R CR0=0), so experiment without fear. Use the pseudo-register names CSIP or CSEIP to set both registers to an address.
R reg.str[=]exp This command also supports bit mask qualifiers on registers. For example, to set the AM bit in CR0, type R CR0.AM=1. See Register Mask Values for a complete list of mask values supported.
RC Clear saved register state so another RS may execute.
RR Restore saved registers.
RS Save registers to restore later via RR. Only one RS may be executed at a time without either restoring the state via RR or clearing the state via RC.

 
Search Operations
S addr1 addr2 tgt
S addr L len tgt
Search from addr1 to addr2 or from ea for len bytes for target tgt.
The search results are displayed on a separate screen which may be made active at other times by pressing F6. Only the first 23 matches are displayed. In a future release the Up, Down, Page Up, and Page Down keys will allow scrolling through successive matches.

The target may take one of several forms:

* Use a target of the form xx, xxxx, xxxxxxxx where x represents a hex digit to search for bytes, words, or dwords of a specified value. For example, the form S 0:0 L FFFF 10CD searches for all occurrences of the hex bytes CD followed by 10 in the first 64KB of conventional memory. Word and dword searches do not require word or dword alignment of the matching data. The number of digits entered determines the width of the value.  Thus you should use leading zeros to pad out a small value to a wider width.  For example, 0 and 00 both search for a single byte of zeros, 000 and 0000 both search for a word of zeros, and 00000, 000000, 0000000, and 00000000 all search for a dword of zeros.

* Use a target of the form "search_string" to search for a case sensitive string. For example, S 0:0 L FFFF "386MAX" searches for all occurrences of the string 386MAX in the first 64KB of conventional memory. The ability to search for a case insensitive string will be added in the future.

* Use a target of the form !instr to search for a specific assembler instruction. For example, S 0:0 L FFFF !INT 10 searches for all occurrences of video interrupts in the first 64KB of conventional memory. This target is found by disassembling the code between the start and stop addresses instruction by instruction, thus the alignment of the matching instructions and the starting address is critical. If data appears within that range, some matches may be missed. The command S1 (instead of S) can be used to disassemble the code byte by byte. That is, with the S command, having disassembled an instruction which does not match the specified pattern, the next instruction is searched; with the S1 command, the next byte is searched. The code search text may include one or more question marks as wildcards which match any character in the disassembled instructions. For example, use S 50|0 FFFF !mov e??,cr? to find all moves from a control register to a 32-bit register. Try the forms S 3BC7:100 FFFF !mov [1234] and S 3BC7:100 FFFF !mov ?s:[1234] to find all moves into location [1234] with or without a segment override. To find jumps to a specific location, use the code targets !j? 1234, !j?? 1234, and !j??? 1234. Note that floating point instructions may be disassembled beginning with either F or FN depending upon the presence of a preceding WAIT opcode (9Bh). To be safe, search for both.

* Use a target of the form #pte to search for a PTE in the Page Tables. For example, S 0 C0000000 # CF4000 searches for the PTE CF4000 from linear 0 through linear C0000000. The linear addresses are both rounded down to a 4KB boundary. A match at a particular linear address means that the PTE was found and it covers the 4KB block at the linear address displayed. When comparing PTEs, the flag bits are ignored, thus a match might be found when the PTE in the Page Tables is not present.
 
 
I/O Port Read/Write
Ix port Input Byte, Word, or Dword from port.
IMR Display current Interrupt Mask Register values for master and slave PICs.
IRR Display current Interrupt Request Register values.
ISR Display current In-Service Register values.
Ox port val Output Byte, Word, Dword val to port.

 
Symbolic Debugging (see SWATSYM.DOC for details)
CD [d:][path]
CHDIR [d:][path]
Change the current directory to path. If no argument, display the current drive/directory.
FS Flush symbol table.
LF filename Load file into browser.
LI + Enable line number display in disassembly screen.
LI - Disable line number display.
LI dddd Go to line dddd (decimal) in file browser.
LI dddd+ Go to line dddd forward from current line.
LI dddd- Go to line dddd back from current line.
LS filename Load symbol file.
LS filename exp Load symbol file and add 16-bit value to all VM segments.
PATH d:\dir1[,d:\dir2[,...]] Set source file search path.
PATH+ d:\dira[,d:\dirb[,...]] Add to source file search path.
PS r Set range of symbol proximity searches to r.
PS r g Set range r and granularity g (1=bytes, 2=words, 4=dwords) of symbol proximity searches.
QS addr Display the symbol which is nearest to (and below) the given address.
SB+ Enable source browser mode.
SB- Disable source browser mode.
SB*+ Enable source browser mode but disregard module names.
TS Force all symbols to be retranslated according to current GDT and LDT.
TS sel Retranslates only for selector/segment sel.
TS * ID Retranslates for all selectors/segments with ID specified.
TS sel ID Retranslates only for selector/segment sel with ID specified.
TS *|sel *|IDv|p Change to specified mode for selector and/or ID specified.
TS *|sel *|ID *|v|p nsel Replace segment/selector and mode for specified selectors and IDs. If * is specified for mode, the mode is left alone.
TS *|sel *|ID *|v|p nsel+ nsel is added to all specified segments.

 
Remote debugging (see SWATREM.DOC)
APPKEY Edit application keystroke buffer. This is primarily useful for remote debugging. If an application is waiting for a keystroke, this feature allows you to send one to the application, as well as to view any that may already be available. 
CHAT Enter CHAT mode (also via Ctl-F8).
SETCOM port bps Initialize specified serial port for communications. See SETCOM= profile option for full syntax.
SETCOM Reinitialize the serial port with values last specified by SETCOM or SETCOM=. This is useful when an application has reprogrammed the UART.
SETCOM - Ignore all activity on serial port. Use this if you are done with remote debugging and wish an application to have access to the serial port. When 386SWAT is using the serial port, no serial port interrupts will be visible to virtual mode programs.
SETCOM RTS+ Pull RTS (Request To Send) line high.
SETCOM RTS- Drop RTS (Request To Send) line low.
SETCOM DTR+ Pull DTR (Data Terminal Ready) line high.
SETCOM DTR- Drop DTR (Data Terminal Ready) line low. This is one way to hang up a modem that won't respond to (wait)+++ (wait)ATH(ENTER).
REMDBG Attempt to establish remote debugging session (also via Ctl-F9). See the section below on remote debugging.

 
Unreal Mode
UNREAL s reg [s reg...]

where s is a sign (+ or -) indicating whether to enable or disable, and reg is a segment register CS, DS
ES, FS, GS, SS, or the keyword ALL.

Turn on and off Unreal Mode for all or selected segment registers.  This mode is a variant of Real Mode in which any segment register can access all of the 4GB address space.  That is, instead of the normal 64KB length of a segment, the length is 4GB.  This command can enable all or just some of the segment registers for Unreal Mode.  For example, 
UNREAL +ALL enables UM for all segment registers
UNREAL -ALL disables ...
UNREAL +DS enables UM for DS only
UNREAL +DS +ES enables UM for DS and ES
To see if a segment register is enabled for UM, look for the plus sign next to the segment number in the instruction disassembly window.
Virtual Mode Switches
VMSCOUNT=val Don't intrude into the GDT/IDT for VCPI debugging until the value in this counter has decremented to zero. This keyword is useful for occasions where the VCPI client shuffles its GDT and IDT around for a while before deciding just where it's going to be.
VMSINT=ON|OFF Enable (ON) or disable (OFF) VCPI debugging. Use this feature in cases where some VCPI programs misbehave when VCPI debugging is enabled. In this case, enable VCPI debugging only as necessary.
VMSINT=xx,xx,... Change the default interrupts intercepted by 386SWAT when debugging VCPI clients.

 
Pentium-Pro CPU Specific Commands
BTF Display Branch Trace Facility state (ON or OFF).
BTF ON|OFF Turn Branch Trace Facility state ON or OFF.
LBR Display Last Branch/Exception values on the command line.
LBR ON|OFF Turn Last Branch/Exception window display ON or OFF. The four-line window displays the Last Branch From EIP, Last Branch To EIP, Last Exception From EIP, and Last Exception To EIP. Also, the keywords .LBRFR, .LBRTO, .LEXFR, .LEXTO contain the value of the Last Branch/Exception From/To EIP in case these need to be used in command line expressions (e.g., U .LBRFR).

 
Windows Debugging Commands (see WINKDBG.DOC)
IPF [/d] [/s] [/r] expr If Invalid Page Faults are being trapped by 386SWAT's VxD (see SWATVXD.DOC for more details), use the IPF command to control how these events are to be handled. The optional switch /d tells 386SWAT not to display a message on the mono screen describing this event, /s tells 386SWAT not to stop when this event occurs, /r tells 386SWAT to remove this entry from its local tables, and expr is an expression which evaulates to a linear address corresponding to the Invalid Page Fault.
MDB expr Display the memory which corresponds to the selector expr as a Module Database.
SGH [/b|/s|/h|/o] [/c] expr Search through the Windows Global Heap for values. The expression (expr) entered is interpreted as a base address if /b is specified, size if /s, handle if /h, and owner if /h. If /c is specified, the search continues from the currently displayed entry; otherwise, the search starts at the top of the heap.
TDB expr Display the memory which corresponds to the selector expr as a Task Database.
WKD [ON|OFF] Turn ON or OFF Kernel Debugging. This command cannot be used from within Windows.
WKD [QUIET|NOISY] Disable (QUIET) or Enable (NOISY) reports on Parameter Errors.
WKD LOGERROR [ON|OFF] Turn ON or OFF the INT 01h trap of calls to LogError ().
WKD FAULT [ON|OFF|SKIP] Turn ON, OFF, or SKIP once traps for Faults.
================================================ FILE: swat/SWATCMR.HTM ================================================ Common Memory References

Common Memory References

There are a number of points in memory to which it is common to refer, e.g., the address of the instruction at the top of the disassembly window. These references are made easier by using one of the following shortcuts (all of which can be used anywhere on the command line where an address is expected such as BD .CODE, or BD .DATA L4 W):
.EA  Effective Address of the first (or only) operand to the instruction at the top of the disassembly window
.EA2 Effective Address of the second operand to the instruction at the top of the disassembly window
.GDT GDT base address (using selector zero)
.IDT IDT base address (using selector zero)
.LDT LDT base address (using selector zero)
.TSS TSS base address (using selector zero)
.CMAC Seg:Off of next C MAC entry -- equivalent to .DATA + 2 + FFFE & [.DATA
.CODE current code display address
.CSIP current cs:[e]ip
.DATA current data display address
.DMAC Seg:0 of first DOS MAC entry
.NMAC Seg:0 of next DOS MAC entry -- equivalent to ((S..DATA)+1+[.DATA+3):0
.LBRFR EIP of Last Branch From
.LBRTO EIP of Last Branch To
.LEXFR EIP of Exception From
.LEXTO EIP of Exception To
.MDB Base address of the current Module Database (Windows only)
.PMIxx Sel|Off of PM Interrupt xxh
.RMIxx Seg:Off of RM interrupt # xx
.TDB Base address of the current Task Database (Windows only)
.VM Sel|Off of current Windows VM structure
.VMIxx Seg:Off of VM interrupt # xx
.VMRET Return CS|EIP saved in .VMSTK at .VMSTK+50 (DPMI fn 0300) or .VMSTK+150 (emulated INT)
.VMSTK Sel|Off of stack saved in .VM
.XBDA Seg:Off of XBDA; same as ([40:0E):0
.XBDA2 Seg:Off of 2ndary XBDA; same as ((S..XBDA)+[.XBDA+B4):0
A common address to jump to is the (near or far) return address of a subroutine. This is made easier by using shortened forms of the commands one might use to extract these addresses. The various flavors of return addresses are (where LaSTK is the address of the current stack pointer -- SS:SP if VM, SS|SP if PM and the B-bit in SS is clear, and SS|ESP if PM and the B-bit in SS is set):
 
Keyword  Grammar Equivalent Meaning
.RETND {LaSTK Near dword
.RETNS [LaSTK  Near word
.RETFD :{LaSTK or |{LaSTK Far word:dword or word|dword (depending upon the VM bit in the current EFL)
.RETFS :[LaSTK or |[LaSTK Far word:word or word|word (depending upon the VM bit in the current EFL)
.RETN .RETND or .RETNS Depending upon the D-bit in CS
.RETF .RETFD or .RETFS Depending upon the D-bit in CS
.IRET .RETF in VM 
.RETFD in PM
Also allows mode switch from PM to VM by checking VM bit in EFL above return address
As a common shortcut, .RETN and .RETF refer to one of the above forms depending upon the setting of the D-bit in the current CS (that is, whether we're running in a USE16 or USE32 segment). Moreover, .IRET can be used as a shorthand for .RETF with the added check on the VM bit in the EFL above the return address. If this bit is set, the return address is interpreted as a VM address even though the current mode is PM.

No magic is invoked to extract the return address if data has been pushed onto the stack below the return address, so be sure that LaSTK points to the actual return address.

Also note that the keystrokes A-F and A-N are defined as shortcuts for the commands G .RETF and G .RETN, respectively.  ================================================ FILE: swat/SWATDEF.HTM ================================================ 386SWAT Default Options

386SWAT Default Options


; Recommended options are

  trapdiv    ; Direct INT 00h to 386SWAT (Divide Overflow Fault)
  trapnmi    ; Direct INT 02h to 386SWAT (Non-maskable interrupt)
  trapbound  ; Direct INT 05h to 386SWAT (BOUND Fault)
  trapinv    ; Direct INT 06h to 386SWAT (Invalid Opcode Fault)
  trapstack  ; Direct INT 0Ch to 386SWAT (Stack Fault)


; The default options are
;
; addrhbits=12 ; Specify bits in addresses to hash (8-12)
; cmdhist=1024 ; Specify the size of the command history buffer
; intrude    ; Attempt to intrude into another memory manager's PL0 context
; logsize=4096 ; Specify size of error log buffer in bytes
; normlidt   ; Disable Real Mode LIDT redirection
; proxsrch=2,1 ; Search symbols for matches within range 2 of units with
;            ; granularity 1 (default granularity is 1 for byte).
; savescreen=16 ; Specify # last screens to save
; symfilter=__imp__ _ ; Specify leading text to strip from symbols
; symsize=4096 ; Specify # bytes to reserve for the symbol table
; trapskip   ; Direct INT 03h to 386SWAT (Single-skip)
; trapstep   ; Direct INT 01h to 386SWAT (Single-step)
; wkdls=0    ; No Windows Kernel Debugger Load Segment symbols
;

; The default services are
;
; Windows Kernel Debugger services enabled (disable via nowink)
;


; All possible options are
;
; [section name] ; Limit profile processing to the matching MultiConfig
;            ; section in CONFIG.SYS
; addrhbits=nn ; Specify bits in addresses to hash (8-12, default=12)
; altscr     ; Use alternate screen for debugging
; /a         ; Alias for ALTSCR
; buckets=nnn ; Specify # 1K hash bucket blocks (1-255)
; cmdhist=nnn ; Specify the size of the command history buffer
; coldboot   ; Do not try to warm boot on Ctrl-Alt-Del
; dvga       ; Use Dual VGA screen
; gpskip=key[,key] ; GP Skip instructions:  ALL, INT, HLT, OUTD, OUTI, IND,
;            ; INI, CLI, STI, IRET, PPF, and CRn so far
; intrude    ; Obsolete option which is now the default
; keyb=cclay ; Use international keyboard whose country code/layout is cclay.
;            ; Possible values are
;            ;   cclay  Country
;            ; ----------------------
;            ;   GR129  Germany
;            ;   SP172  Spain
; lcd        ; LCD screen present
; loadhigh   ; Obsolete option which is now the default
; loadlow    ; Tell 386MAX it's not OK to load us into extended memory
;            ; after INIT_REAL and to relocate our INIT_VIRT code.
; loadsym    ; Enable command line loading of symbols
; loadsym=d:\path\filename.ext [optional args] ; Load SSF file at PM init time
;            ; [/b=xxxxxxxx]    Optional physical base address in hex
;            ; [/h]         Optional HPDA flag (enable DPMI services)
;            ; [/li-]       Optional disable of line numbers
;            ; [/xl]        Disable larger comparison w/SYMSIZE
; logsize=nnnnn ; Specify size of error log buffer in bytes (default=4096)
; mono       ; Use monochrome adapter if present
; nogd       ; Don't automatically set the GD bit in DR7
; normlidt   ; Disable Real Mode LIDT redirection
; noswap     ; Don't swap screens over single-step/skip
; nowink     ; Disable Windows Kernel Debugger services
; passthrough=nn,nn,... ; Specify one or more hardware interrupt handlers
;            ; (numbers in hex) to pass through while SWAT is active.
;            ; The only ones currently supported are B, C, 76, and 77.
; path=dir[,dir2[...]] ; Specify source code search path for symbolic debugging
;            ; (current directory is NOT included by default)
; portinit=string ; Specify a modem initialization string (setcom must be
;            ; specified as well).  Valid escape sequences are:
;            ; \\ Send a backslash
;            ; \r Send a carriage return
;            ; \b Send a break signal
;            ; \p Pause about 250 ms.
;            ; \1 - \0 Wait 1 - 10 seconds.
;            ; On the first invocation of SWAT, the system will
;            ; automatically attempt to establish connection with a remote
;            ; SWAT system.
; proxsrch=r[,g] ; Search symbols for matches within range r of units with
;            ; granularity g (default granularity is 1 for byte).
; ps4=xxxx   ; Periscope 4 hardware debugger board is at I/O port xxxx
; rmlidt     ; Enable Real Mode LIDT redirection
; savescreen=nnn ; Specify # last screens to save (default = 16)
; setcom=port,bps[,{IRQ|p}[,base]] ; Initialize specified serial port (1-4) for
;            ; remote debugging at specified bps.  Optional IRQ number (3,4)
;            ; overrides default association of ports with IRQs, or p may
;            ; be specified for polled operation.  Optional port base
;            ; may be specified to override BIOS value at 40:0.
; symfilter=text1 [text2 [...]] ; Specify leading text to strip from symbols
; symsize=nnnnn ; Specify # bytes to reserve for the symbol table (default=4096)
; trapbound  ; Direct INT 05h to 386SWAT (BOUND Fault)
; trapdebug  ; Direct INT 01h/03h to 386SWAT (Same as TRAPSTEP with TRAPSKIP)
; trapdiv    ; Direct INT 00h to 386SWAT (Divide Overflow Fault)
; trapgenp   ; Direct INT 0Dh to 386SWAT (General Protection Fault)
; trapinv    ; Direct INT 06h to 386SWAT (Invalid Opcode Fault)
; trapnmi    ; Direct INT 02h to 386SWAT (Non-maskable interrupt)
; trappage   ; Direct INT 0Eh to 386SWAT (Page Fault)
; trapsegnp  ; Direct INT 0Bh to 386SWAT (Segment Not Present Fault)
; trapskip   ; Direct INT 03h to 386SWAT (Single-skip)
; trapstack  ; Direct INT 0Ch to 386SWAT (Stack Fault)
; trapstep   ; Direct INT 01h to 386SWAT (Single-step)
; traptss    ; Direct INT 0Ah to 386SWAT (TSS Fault)
; vcpiswat   ; Don't attempt to intrude into a memory manager's PL0 context
; video=d:\path\filename.ext ; Load/create video tables
; vmscount=n ; Number of times to intrude on GDT/IDT for VCPI debugging
; vmsint     ; Launder Windows and VCPI mode switches and hook interrupts
;            ; 00, 01, 02, 03, 05, 06, 08, 0A, 0B, 0C, 0D, and 0E.
; vmsint=nn,nn,... ; Limit VMSINT debugging to these interrupt #s
; watchdog=nn ; Set watchdog timer to nn timer ticks (0-255)
; wkdls=nnn  ; Define # WKD Load Segment entries

; debug=caps ; Signal NMI if CapsLock pressed at startup
; debug=ibv  ; Use Interrupt mask base Vector for Ctrl-Alt-PAD5
; debug=int  ; Signal INT 03h if CapsLock present at startup
; debug=pmi  ; Signal INT 03h near end of INIT_PROT
; debug=trip ; Use triple fault method to reboot
; debug=vmi  ; Signal INT 03h on entry to INIT_VIRT
; debug=wcb1 ; Signal INT 01h on WCB VM->RM ================================================ FILE: swat/SWATDISP.HTM ================================================ 386SWAT Display Options

386SWAT Display Options

The debugger presents its output on various display devices in various contexts.  Typically, it uses the primary display, but other options are possible.  If you have a secondary display, such as a monochrome adapter/monitor or if you are running on a PCI system with a second PCI VGA adapter, 386SWAT can use those also.

If you have a monochrome adapter in your system, place the keyword MONO in your 386SWAT profile.  The debugger determines whether or not your monochrome adapter is always visible or is hidden by a PCI VGA card, even an AGP controller.  In either case, 386SWAT ferrets out the adapter and displays its output there.  Pressing Alt-F7 switches between the monochrome and color adapters.

If you have a secondary PCI VGA adapter in your system, place the keyword DVGA in your 386SWAT profile.  The debugger displays its output on this screen, even if it's hidden by an AGP controller.  Pressing Alt-F7 switches between the two PCI VGA adapters.

I learned a bit about PCI programming getting the above to work, so I've gathered together assembler code to demonstrate the techniques used for you to browse.  Thanks go to Dominik Behr, Federico Bianchi, Ralf Brown, and others for their helpful suggestions and/or source code. ================================================ FILE: swat/SWATDOC.HTM ================================================ 386SWAT Documentation

386SWAT Documentation

This protected mode debugger when used in conjunction with 386MAX or any other memory manager provides debugging services to protected mode, virtual 8086 mode programs, Windows 3.1x and Win95/98 programs, and DPMI and VCPI clients while occupying only a few kilobytes of conventional memory. It supports disassembly of the full 386, 387, 486, Pentium, Pentium Pro through the Pentium 4 MMX & SSE instruction set.  Note that all of this documentation is included in the download file in HTML format.

Installing 386SWAT -- getting it into your system

386SWAT Profile Options -- configuring it

Invoking The Debugger -- bringing it up

Monochrome and Dual PCI VGA Support -- displaying it

Debugging Aids in 386MAX -- in case you're running my favorite memory manager

Debugging Screen and Keystrokes -- what it looks like and what you can type

Disassembly Bookmarks -- a feature for browsing through assembly code

Autofault -- a feature for understanding faults

Windows Debugging -- how it works under Windows

Windows Kernel Debugging -- very low-level debugging

Monitor mode -- conditional tracing

Command Line Actions -- built-in commands

Common Memory References -- dot commands

Register Mask Values -- bit mask modifiers for registers

NDP Register Screen -- Numeric Data Processor display

Remote debugging -- over a COM line

VCPI Program Debugging -- going where no debugger had gone before

Wish List -- it'll never be finished

Version History -- what's been done
 

Limitations

This program is very preliminary. It lacks many of the features of a full-blown debugger. On the other hand, it has a few features they don't have.
 

Technical Support

Please send your problems, praises, and comments to bsmith@sudleyplace.com ================================================ FILE: swat/SWATGRM.HTM ================================================ 386SWAT Grammar

Grammar For 386SWAT Command Line

// Command lines
APPKEY
BCx opt_addr        x = {<empty>, *, +, -}
BD opt_addr
BD addr Ln       n = {<empty>, 1, 2, 4}
BD addr Ln W    n = {<empty>, 1, 2, 4}
BDnx                    x = {*, +, -}   n = {<empty>, 0, 1, 2, 3}
BTF
BTF {ON|OFF}
CHAT
Dxy-                     x = {<empty>, b, d, g, i, t, t2, t3, v, w},
                            y = {<empty>, /n} where n is the data width
Dxy opt_addr         x = {<empty>, b, d, g, i, t, t2, t3, v, w},
                            y = {<empty>, /n} where n is the data width
Dxy addr P            x = {<empty>, b, d, g, i, t, t2, t3, v, w},
                            y = {<empty>, /n} where n is the data width
Dxy addr P exp      x = {<empty>, b, d, g, i, t, t2, t3, v, w},
                            y = {<empty>, /n} where n is the data width
DTE exp
E  addr
E  addr lvallist
EXIT
F  addr L lval lval
F  addr L lval lval P
F  addr L lval lval P exp
FS
G  opt_addr
GM opt_boolexp
H  addr
Ix lval         x = {<empty>, b, d, w}
IMR
INSERT gdtr idtr [cr3 [lapde]]
INSERT * idtr
IPF [/d] [/s] [/r] exp
IRR
ISR
LBR
LBR {ON|OFF}
LF filename
LI x                    x = {+, -}
LI dcon           x = {<empty>, +, -}
LS filename x      x = {<empty>, lval}
M  addr L lval addr
MACBASE addr
MDB exp
Ox lval lval           x = {<empty>, b, d, w}
PATHx dirlist        x = {<empty>, +}
PS lval             x = {<empty>, lval (<256)}
PTE addr
PTE exp
PTE addr P exp
PTE exp  P exp
QS addr
R  reg [=] exp
R  reg.str [=] exp
REMDBG
RC
RR
RS
Sx addr L exp atom x = {<empty>, 1}
Sx addr addr   atom x = {<empty>, 1}
S  addr addr ! instr
S  addr L exp ! instr
S  addr addr   # exp
S  addr L exp # exp
SBx         x = {+, -}
SB*x            x = {+, -}
SETCOM x        x = {<empty>, -}
SETCOM port bps     port = {1, 2, 3, 4}
SETCOM xn       x = {RTS, DTR}      n = {+, -}
SGH [/b|/s|/h|/o|/n]  [/c] exp
SIGINT lval
SPTE addr
SPTE exp
SPTE addr P exp
SPTE exp  P exp
TDB exp
TOGINT lvallist
TS
TS opt_sel opt_group x opt_seln opt_addr
                x = {<empty>, *, P, Vn = {<empty>, +, -}
Ux-          x = {<empty>, 16, 32}
Ux opt_addr        x = {<empty>, 16, 32}
Ux addr P           x = {<empty>, 16, 32}
Ux addr P exp     x = {<empty>, 16, 32}

VMSCOUNT xx
VMSINT {ON|OFF}
VMSINT=xx,xx,...

WKD FAULT [ON|OFF|SKIP]
WKD LOGERROR [ON|OFF]
WKD [ON|OFF]
WKD [QUIET|NOISY]
 
 
Lval list
lvallist lval
lval lvallist
 
 
Optional addresses
opt_addr <empty>
addr
 
Addresses
addr exp using default segment/selector as per specific command
ea
 
Optional boolean expression
opt_boolexp <empty>
exp
 
Expressions on values
exp ( exp )
mfn monadic functions
dfn dyadic functions
 
Monadic functions
mfn atom
[ ea extract word at effective address
{ ea extract dword ...
O.ea extract offset from effective address
S.ea extract segment/selector ...
L.ea extract linear address ...
P.ea extract physical address ...
+exp
-exp
~exp
 
Lefthand values
lval atom
( exp )
 
Effective address with segment/selector
ea seg : exp
sel | exp
.EA Effective Address #1 (or the only one)
.EA2 ...                        #2 
.GDT  GDT base address (using selector zero)
.IDT IDT ...
.LDT LDT ...
.TSS TSS ...
.CMAC address of next C MAC entry
.CODE current code display address
.CSIP address of current cs:[e]ip
.DATA current data display address
.DMAC segment of first DOS MAC entry
.NMAC segment of next  DOS MAC entry
.PMIxx Sel|Off of PM Interrupt xx
.RMIxx Seg:Off of RM interrupt xxh
.VM Sel|Off of current Windows VM structure
.VMIxx ...     VM ... 
.VMRET return cs|eip from Windows VM (|{.vmstk+50 or |{.vmstk+150
.VMSTK current ss|esp saved in Windows VM structure (same as |{.vm+40)
.IRET far word:dword return address on stack allowing a mode switch from PM to VM
.RETN near word or dword return address on stack
.RETND near dword return address on stack
.RETNS near word return address on stack 
.RETF far word:word or word:dword return address on stack 
.RETFD far word:dword return address on stack
.RETFS far word:word return address on stack
.XBDA Seg:Off of XBDA; same as ([40:0E):0
.XBDA2 Seg:Off of 2ndary XBDA; same as ((S..XBDA)+[.XBDA+B4):0
dotcmd ? exp dyadic functions on dot commands (.GDT, .IDT, etc.) where ? is a dyadic function
:[ ea extract word:word at effective address
:{ ea extract word:dword at effective address
|[ ea ... word|word ... 
|{ ea ... word|dword ...
|G ea ... ...    in GDT-format (using selector zero)
|I ea ... ...    in IDT-format (using IDT selector)
|L ea ... ...    in LDT-format (same as GDT-format)
|T ea ... ...    in TSS-format (using CS|EIP
symbol effective address of this symbol
 
Dyadic functions on dot commands
dotcmd ? exp 
 
S.dotcmd : O.dotcmd ? exp for VM addresses
S.dotcmd | O.dotcmd ? exp for PM addresses 
where ? is a dyadic function
 
Dyadic Functions
dfn atom
lval + exp addition
lval - exp subtraction
lval * exp multiplication
lval / exp division (with truncation towards zero)
lval & exp bitwise AND
lval ^ exp bitwise XOR
lval == exp is equal (eq)
lval != exp is not equal (ne) 
lval exp is less than (lt)
lval <= exp lt or eq
lval exp is greater than (gt)
lval >= exp gt or eq
lval && exp logical AND
lval || exp logical OR
Because we have usurped the | symbol as the selector separator, it is
not available for bitwise OR.  To do bitwise OR between A and B, use
      (A & ~B) ^ B
 
Precedence
Operators Type
- ~ Monadic
* / Dyadic
+ - Dyadic
symbols, .code, .data, etc. Address expression
: | Dyadic (address construction)
] [ { Monadic (extraction)
>> << Dyadic (bit shift)
< <= >= > Dyadic (relational)
== != Equality
& Dyadic (bitwise AND)
^ Dyadic (bitwise XOR)
&& Dyadic (logical AND)
|| Dyadic (logical OR)
 
Segment or Selector
seg lval
sel lval
 
Optional segment or selector
opt_sel <empty>
*
seg
sel
 
Optional Group ID
opt_group <empty>
*
con
 
Atoms
atom con
reg
.LBRFR
.LBRTO
.LEXFR
.LEXTO
 
Registers
reg GP AX, AL, AH, BX, ... 
EGP EAX, EBX, ECX, ...
CRn Control registers
DRn Debug registers
TRn Test registers
Misc IP, EIP, FL, EFL, TR, LDTR
 
Constants
con <32-bit hex values>
dcon <16-bit unsigned decimal values>
filename <DOS pathname>
dirlist <List of directory names separated by commas (,)>
 
Bits per second (BPS) values
bps 55
110
300
600
1200
2400
4800
9600
19200
38400
76800
115200
 

Examples

* To display the successive entries in the DOS memory allocation chain, display one such entry via a DB command.  Then type

    /D ((S..DATA)+1+[.DATA+3):0

  Continuing to press Enter displays the successive MAC entries.

* To display the successive entries in the C memory allocation chain, display one such entry (at the count word) via a DB command.  Then type

    /D .DATA + 2 + FFFE & [.DATA  ================================================ FILE: swat/SWATINST.HTM ================================================ Installing 386SWAT

Installing 386SWAT

Create a directory on your hard disk (say, C:\386SWAT), copy the ZIP file to that directory, and unzip it there. To unzip 386SWAT, use

    PKUNZIP 386SWAT

This debugger can be used in conjunction with any memory manager which supports VCPI, or with just HIMEM.SYS.

To install 386SWAT, place the following line into your CONFIG.SYS file:

    Device=d:\path\386SWAT.LOD options

Place the Device= statement for 386SWAT immediately following the Device= for the memory manager (if any), or HIMEM.SYS if no memory manager is being used. d:\path\ represents the drive and path location of 386SWAT and options represents zero or more profile options.

As there are several options you may wish to use with 386SWAT, we recommend that you put all 386SWAT keywords in a profile one keyword per line, and point to the profile with the PRO= option on the 386SWAT.LOD line. For example,

    Device=d:\path\386SWAT.LOD PRO=d:\path\386SWAT.PRO
================================================ FILE: swat/SWATINV.HTM ================================================ Invoking 386SWAT

Invoking 386SWAT

Generally, the debugger lies in the background waiting for some catastrophic event to occur.

To bring up the debugger from the keyboard, press Ctl-Alt-Pad5. That is, with the Ctl- and Alt-keys held down, pressing the 5 key on the numeric pad invokes the debugger. This mechanism is useful when your program is stuck somewhere. Remember, the keyboard and the keyboard interrupt must be enabled for this to work. On systems for which the Pad5 key is inconvenient to use (such as some laptops), the sequence Ctl-Alt-SysReq also brings up the debugger.

It is also handy to install an NMI switch for when the system really gets locked up.  Be sure to put the keyword TRAPNMI in the 386SWAT profile.

To run a particular program through the debugger, use the SWATRUN utility.

If remote debugging is active (see SETCOM profile option and SETCOM command) the debugger may also be activated by sending SWT! followed by a break signal. This is done by pressing Ctl-6 in the CHAT screen.

The utility SWATCMD (loaded via Device= or from the DOS command line) may be used to pass commands to 386SWAT.  Invoking SWATCMD with no options brings up 386SWAT at an INT 03h (assuming TRAPSKIP or TRAPDEBUG is active). ================================================ FILE: swat/SWATMAX.HTM ================================================ Debugging Aids in 386MAX

Debugging Aids in 386MAX

The following options are recognized by 386MAX and may be useful in conjunction with 386SWAT. These options should be placed in your 386MAX profile.

To catch even-value stack wraps, use DEBUG=NOWRAP. This situation occurs when an interrupt is encountered with SP = 2 or 4. In this case, the 386 will push the three words onto the stack and wrap to the end of the stack segment leaving SP = FFFC or FFFE. Quite likely, this is an error as most stack segments aren't meant to be 64 KB in length. Technically, this event is not an error as far as the 386 is concerned, but logically it almost always is an error. The default behavior of 386MAX is to emulate the behavior of the CPU and not signal an error; the DEBUG=NOWRAP keyword tells 386MAX to trap this case.

To catch writes into unmapped EMS pages, use DEBUG=EMSWRIT. This option traps with a Page Fault attempts to write into unmapped EMS pages as well as after a Save Page Map call. The latter is presumed to have been done by a memory-resident program prior to mapping in its own pages. To catch reads and/or writes in unmapped EMS pages, use DEBUG=EMSRDWR. To catch an EMS bug in MS-DOS 4.0x, try this latter option with BUFFERS in EMS memory.

To catch unemulated Invalid Opcodes, use DEBUG=I06.

To signal an INT 01h on each DPMI error, use DEBUG=DPMIERR.

To force a new selector on all selector allocates, use DEBUG=DPMINEWSEL. This option is useful if your code has a stale selector, that is, you allocate a selector and tuck it away for later use, but then, before its last reference, you free it and allocate another selector. Without this option you might get the old selector number (the one you just freed). When the stale selector is used, it might not generate an error, but surely it won't do what you expected. ================================================ FILE: swat/SWATMON.HTM ================================================ Monitor Mode

Monitor Mode

The GM (go monitor) command takes an expression which will be evaluated as the CPU single-steps (equivalent to Padplus or F11). No display will occur until

1) the monitor expression evaluates TRUE, or
2) 386SWAT is invoked by some other means (GP fault, NMI, Ctrl-Alt-Pad5, etc.)

Boolean expressions may be constructed using the dyadic functions &&, ||, <, <=, ==, >=, and >. Function precedence is the same as the C language. See Command Line Actions.

For example:

gm ah
will execute until AH is non-zero.

gm [.csip == 21cd && ah!=9
will execute until the current instruction is INT 21 and AH is any value other than 9 (DOS display string).

gm cx == 0
will execute until CX is 0.

gm
will execute until the last expression specified with gm is TRUE. ================================================ FILE: swat/SWATNDP.HTM ================================================ NDP Register Screen

NDP Register Screen

This feature is preliminary, but it does allow you to move through the Numeric Data Processor (NDP) registers and settings and change them at will.  Lacking is an exact binary to decimal conversion algorithm as well as a decimal to binary conversion algorithm.  This screen can be displayed and cleared via Alt-F8. ================================================ FILE: swat/SWATPRO.HTM ================================================ 386SWAT Profile Options

386SWAT Profile Options

The following profile options are recognized by 386SWAT.  Options may be entered in upper and/or lower case.  See the file 386SWAT for a list you can use already in profile format.
 
[section name] For versions of DOS which support MultiConfig, this option limits profile processing to the matching MultiConfig section in CONFIG.SYS.
ADDRHBITS=n Bits to use for address hashing (8-12; default 12).  See SWATSYM.DOC.
ALTSCR Display debugging information on the screen other than the current one being used. That is, in a two monitor system, if the current screen uses the color adapter, display debugging data on the monochrome screen and vice versa. This option is valid only if we detect that there are both a color and monochrome adapter in the system. Otherwise, it is ignored. Note that the screens can be swapped via Alt-F7. An alias for this option is /A.
BUCKETS=n Specify the number of name hashing blocks to allocate (about 1K each).  See SWATSYM.DOC.
CMDHIST=nnn Specify the size of the command history buffer used by command lie recall. Default is 1024.
COLDBOOT Don't write 1234h to warm boot flag location when rebooting system from within 386SWAT.
DEBUG=TRIP Use triple fault method of rebooting. Sometimes a system doesn't reboot when using the 8042 method (the default), so here's another way to skin the cat.
DVGA Use a Dual VGA screen as the secondary monitor.
GPSKIP=key[,key] If a GP Fault occurs on any of the instructions named in the list, do not signal this to 386SWAT. This option allows you to trap GP Faults but filter out ones which may commonly occur but not be of interest. The key values (GP Skip instructions) supported are 
Keyword Instruction(s)
CLI CLI
CRn MOV r32,CRn  
MOV CRn,r32
HLT HLT
IND IN AL,DX 
IN AX,DX 
IN EAX,DX
INI IN AL,immed 
IN AX,immed 
IN EAX,immed
INT INT xx
IRET IRET  
IRETD
OUTD OUT DX,AL 
OUT DX,AX 
OUT DX,EAX
OUTI OUT immed,AL 
OUT immed,AX 
OUT immed,EAX
PPF PUSHF  
POPF  
PUSHFD  
POPFD
STI STI
The keyword ALL covers all of the above options.
INTRUDE Attempt to intrude into another memory manager's PL0 context. If this is successful, 386SWAT appears as a PL0 debugger in the context of the memory manager. This option is now the default. To disable this option, use VCPISWAT.
KEYB=cclay Use international keyboard whose country code/layout is cclay. Possible values are 
cclay Country
GR129 Germany
SP172 Spain
If your international keyboard is not in this list, read the file KEYBIN.TXT to see how you can help.
LCD Specify that an LCD screen is present (and 386SWAT uses the LCD screen attributes). Does anyone know how to detect this case under program control? I would prefer not to require the user to tell us what the screen is like.
LOADLOW Tell 386MAX it's not OK to load us into extended memory after INIT_REAL and to relocate our INIT_VIRT code. It's highly unlikely you'll need this option.
LOADSYM=filename [optional] Load specified symbol file with optional arguments: 
/b=xxxxxxxx  Optional physical base address in hex
/h  Optional HPDA flag (enable DPMI services)
/li- Optional disable of line numbers
/xl Disable larger comparison w/SYMSIZE
 
LOGSIZE=nnnnn Define size of error log in bytes. Default is 4096.
MONO Use monochrome adapter if present.
NOGD Because some programs may reset the debug registers which you've carefully setup, 386SWAT automatically sets the Global Debug (GD) bit in DR7 on startup so that we can stop such programs before they can do any harm. In case you don't want 386SWAT to do this, use this keyword.
NORMLIDT Disable Real Mode LIDT redirection. Device 386SWAT uses a separate IDT to handle nasty bugs which write into the Real Mode IDT at 0:0 such as DOS 6.x does during its transient CONFIG.SYS processing. This is the default state.  Use RMLIDT to find this kind of bug.
NOSWAP Don't restore the previous underlying screen when single-stepping. This option is useful in conjunction with the ALTSCR option. This option specifies the initial state only. It can be toggled via Alt-F6.
NOWINK Disable Windows Kernel Debugging.
PASSTHROUGH=xx,xx,xx,... Allow one or more hardware interrupts to be passed through to the previous protected mode handler while 386SWAT is active. Currently, these are limited to 76, 77, 0B, and 0C. THIS OPTION SHOULD NOT BE USED UNLESS NECESSARY. For example, when the IBM PS/2 SCSI adapter (8EFE or 8EFF) is used, staying in 386SWAT for more than 1 or 2 minutes will cause the hard disk to lock on the next disk access. PASSTHROUGH=76 will allow one to stay in 386SWAT indefinitely.
PATH=d:\dir1[,d:\dir2[,...]] Specify source file search path (see SWATSYM.DOC).
PORTINIT=string Initialize serial port. String may contain any character except semicolon, including the following escape sequences: 
\\  Send backslash.
\r Send CR.
\b Send a break signal (this is a hardware signal, not a character).
\p Pause for about 250ms.
\1 - \0 Delay for 1 - 10 seconds.
SETCOM must be specified to set the parameters for the serial port. On the first entry to 386SWAT (which may be remotely triggered) 386SWAT will automatically try to connect for remote debugging. 
PRO=d:\path\filename.ext Read subsequent command line options from a profile. Just as with 386MAX, as you append more and more options to the 386SWAT command line, you may prefer to collect them all in a 386SWAT profile, one per line. These options may be followed by a semicolon and a comment. This profile is handled exactly the same way as is the corresponding profile for 386MAX.
PROXSRCH=r[,g] Set range and granularity for proximity searching on symbol addresses.  See SWATSYM.DOC.
PS4=xxxx Periscope 4 hardware debugger board is installed at I/O port xxxx (for reference, the factory setting is 300h). This feature allows 386SWAT to manage the traceback buffer and other features of the Periscope Company's 386 hardware debugger. *NOTE* this feature isn't finished.
RMLIDT Enable Real Mode LIDT redirection. Device 386SWAT uses a separate IDT to handle nasty bugs which write into the Real Mode IDT at 0:0 such as DOS 6.x does during its transient CONFIG.SYS processing.
SAVESCREEN=nnn Specify the number of last screens to save. This keyword allows you to control how many screens back Alt-F10 can display. The default is sixteen. Each screen consumes 4000 bytes of storage in extended memory.
SETCOM=port,bps[,itype[,portbase]] Specify port to use for remote debugging. 
port From 1-4 for COM1 through COM4.
bps Transfer rate, from 1 to 115200.
itype Interrupt mode. May be 3 or 4 to specify IRQ (default is IRQ3 for COM2/COM4, IRQ4 for COM1/COM3), * for default, or p for polled operation. Currently, an IRQ line is required for remote debugging.
portbase UART port base if different from defaults: COM1=3F8, COM2=2F8, COM3=3E8, COM4=2E8.
 
SYMFILTER=text1 [text2 [...]] Some symbols, especially from Windows programs written in C, are prefaced with text such as "__imp__", "_", and the like which adds to the symbol's length but not understanding. This feature allows you to specify in the 386SWAT profile leading text which is to be stripped from each symbol. 

The default settings are 

SYMFILTER=__imp__ _  

Up to 128 characters can be specified in this way.

SYMSIZE=nnnnn Specify the number of bytes to reserve for the symbol table. The default size is 4096.  See SWATSYM.DOC.
TRAPBOUND Trap BOUND instruction interrupts, ignoring INT 05h.
TRAPDEBUG Intercept INT 01h/03h at installation time. Normally, 386MAX directs protected mode occurrences of INT 01h/03h to 386SWAT and real mode occurrences to the real IDT handler. This options causes all such interrupts to be handled by 386SWAT. This feature may be toggled via Alt-F1.
TRAPDIV Trap divide overflow interrupts.
TRAPGENP Trap General Protection Faults (toggle via Alt-F3).
TRAPINV Trap Invalid Opcode interrupts (toggle via Ctl-F3).
TRAPNMI Trap Non-Maskable Interrupts. This option is useful in conjunction with a hardware breakout switch which can be used to invoke the debugger even if all interrupts are disabled (toggle via Alt-F2).
TRAPPAGE Trap Page Faults (toggle via Alt-F4).
TRAPSEGNP Trap Segment Not Present Faults.
TRAPSKIP Trap INT 03h instructions (toggle via Ctl-F2).
TRAPSTACK Trap Stack Faults (toggle via Ctl-F4).
TRAPSTEP Trap INT 01h breakpoints (toggle via Ctl-F1).
TRAPTSS Trap TSS Faults.
VCPISWAT Do not attempt to intrude into another memory manager's PL0 context. This option disables the default INTRUDE option.
VIDEO=d:\path\filename.ext Read in/write to video tables. If the specified file exists, it is read in and used as video table information. If the file doesn't exist, it is created. The information in the video table specifies how to switch to particular video modes as well as how to set certain cursor types. Use this option if you wish to bring up 386SWAT on top of graphic applications on single-monitor systems. *NOTE* this option doesn't fully work as yet, so I suggest that you don't use it.
VMSCOUNT=n Used with VMSINT.  Limit number of times 386SWAT inserts itself into a VCPI client's GDT/IDT. This may be useful when debugging VCPI applications that call Enter Protected Mode (AX=DE0C) repeatedly, such as a real-mode int 08h handler that enters protected mode on every clock tick. The correct value may have to be determined by trial and error.
VMSINT[=xx,xx,...] Trap VCPI Enter Protected Mode switches (AX=DE0C) and blast in sufficient GDT and IDT entries to debug the client application. This option is useful when debugging a VCPI application which does not follow the preliminary VCPI debugger specification. Use this option with care. The argument (if present) limits the intercepted interrupts to the values. When VMSINT is in effect, it may be important to limit the interrupts. For example, some DOS16M apps (such as Lotus 1-2-3 Version 3.0) intercept interrupts but don't set the access rights byte in the IDT (they assume that it's still set for a 286 interrupt gate, as DOS16M setup originally). Thus when 386SWAT blasts its task gate entries into the IDT, subsequent DOS16M intercepts leave those entries marked as a task gate. This debug option limits us to intercepting those faults necessary to catch catastrophic errors, but not everything. Interrupts which may be intercepted are 00, 01, 02, 03, 05, 06, 0A, 0B, 0C, 0D, and 0E.
WKDLS=nnn Reserve space for nnn WKD load segment entries.
================================================ FILE: swat/SWATREM.HTM ================================================ Remote Debugging

Remote Debugging

Two machines may be connected for remote debugging. The connection may be made via a null modem cable connecting the serial ports on both machines, or via modem.

The connection is initiated by using the SETCOM command to initialize the serial port, then pressing Ctl-F9 on each system to attempt to connect. When a connection is established, the "Press M to become master" prompt appears. Only one of the two systems may become master; the other one then becomes the slave. Processing on the slave system then proceeds normally; the master system is now running a special terminal program.

Keystrokes typed in the master terminal program are sent to the remote system (with some exceptions - see below), and screen output from the remote 386SWAT system appears on the master terminal screen.
 

Special keys

Ctl-Alt-Del will NOT be sent to the remote system while in the master terminal screen - it will reboot the master system.  Ctl-F9 invokes a menu of special options for the master system:
 
T Terminate connection with slave immediately.
G Terminate connection, but have slave go instead of returning to the 386SWAT command prompt.
R Terminate connection, have slave go, but have slave automatically attempt to re-establish connection on next invocation of 386SWAT.
B Terminate connection and reboot slave system.
S Suspend session temporarily. This temporarily exits the terminal program. You may exit 386SWAT. Ctl-F9 again resumes the connection.
U Upload program to remote.
D Download program from remote.
Esc Continue with terminal program
Other keys are Ctl-6 (interrupt remote) and Alt-F7 (send remote screen only to master). Alt-F7 is useful for debugging when the remote system is in graphics mode or otherwise unable to access the CRT controller. ================================================ FILE: swat/SWATRMV.HTM ================================================ Register Mask Values

Register Mask Values

The following pseudo-records describe the bit masks supported by the register command where "*" represents reserved bits with no corresponding name:
 
EFL record *:13, AC:1, VM:1, RF:1, *:1, NT:1, IOPL:2, OF:1, DF:1, IF:1, TF:1, SF:1, ZF:1, *:1, AF:1, *:1, PF:1, *:1, CF:1
CR0 record PG:1, CD:1, NW:1, *:10, AM:1, *:1, WP:1, *:10, NE:1, ET:1, TS:1, EM:1, MP:1, PE:1
PTE record  FRM:20, PTE_AVL:3, *:2, PTE_D:1, PTE_A:1, PTE_CE:1, PTE_WT:1, PTE_US:1, PTE_RW:1, PTE_P:1
SEL record SEL:13, TI:1, PL:2
DR6 record *:16, BT:1, BS:1, BD:1, *:9, B3:1, B2:1, B1:1, B0:1
DR7 record LEN3:2, RW3:2, LEN2:2, RW2:2, LEN1:2, RW1:2, LEN0:2, RW0:2, *:2, GD:1, *:3, GE:1, LE:1, G3:1, L3:1, G2:1, L2:1, G1:1, L1:1, G0:1, L0:1
TR4 record TR4_TAG:21, TR4_WVAL:1, TR4_LRU:3, TR4_RVAL:4, *:3
TR5 record *:21, TR5_SSEL:7, TR5_ESEL:2, TR5_CTL:2
TR6 record FRM:20, TR6_V:1, TR6_D:1, TR6_DP:1, TR6_U:1, TR6_UP:1, TR6_W:1, TR6_WP:1, *:4, TR6_C:1
TR7 record FRM:20,*:7, TR7_HT:1, TR7_REP:2, *:2
================================================ FILE: swat/SWATSCR.HTM ================================================ Debugging Screen and Keystrokes

Debugging Screen and Keystrokes

Debugging Screen

The top of the initial debugging screen consists of a row of the 32-bit general purpose registers, two rows of the segment registers, and one row of CR0, CR2, and extended flags.

The rest of the initial debugging screen displays the instructions to be executed with the stack appearing on the right in one or two columns. If the current instruction references memory, the segment register, offset, and memory value of the reference are displayed on the line separating the registers from the instructions.

The line at the bottom of the screen is used to enter various commands.  The following table summarizes the possibilities. The usual editing keys are available such as Left, Right, Home, End, Insert, Backspace, and Delete.  Note that a colon (:) is used to separate a segment from an offset (Virtual 8086 Mode) and that a stile (|) is used to separate a selector from an offset (Protected Mode).  The command line is parsed according to the grammar found in the file 386SWAT.GRM.
 

Command Line Recall

Commands entered on the command line are saved in a ring buffer whose length can be changed from the default of 1024 via the profile keyword CMDHIST=nnn.

Previous commands can be retrieved via the keystrokes Alt-< (previous command) and Alt-> (next command). Pressing either of these keys repeatedly scrolls through the buffer in the chosen direction. The keystroke Alt-? displays a history of (up to 24) commands from which a command can be chosen by scrolling up or down through the list, or by typing the letter next to the command. A command may be deleted from this list via the Del key.
 

Special Keystrokes

Special keystrokes available from the command line include:
 
ESC Continue processing. Equivalent to the Go command.
F1 Display a help screen with submenus.
F3 Display LDT entries.
F4 Display IDT entries.
F5 Display PTE entries.
F6 Display search screen.
F7 Display memory. While this display is active, Ctl-B displays in byte format, Ctl-W, in word format, Ctl-D in dword format, Ctl-V in vector format, Ctl-G in GDT format, Ctl-I in IDT format, and Ctl-T in TSS format.
F8 Display TSS entries.
F9 Display the instruction disassembly screen.
F10 Display screen on entry to debugger.
F11 Single-step the current instruction (see Padplus). This key as well as F12 are useful on systems without a Padplus/Padminus key, or ones for which those keys are difficult to type such as some laptops.
F12 Single-skip the current instruction (see Padminus).
s-F1 Goto the immediate CALL or JMP address of the instruction at the top of the screen and save the address of the current instruction (see Disassembly Bookmarks).
s-F2 Return from the previous s-F1 goto (see Disassembly Bookmarks).
s-F3 Goto the instruction on the top line (see Padstar).
s-F4 Display the last AutoFault message.
s-F5 Display the Real Mode Interrupt Vector Table.
s-F10 Save the current screen into the last screen buffers.
a-F1 Toggle intercept of INTs 01h/03h. The current state appears below the segment/selector register display as 01 or blank, 03 or blank. The default state is controlled by the presence or absence of the TRAPDEBUGkeyword.
a-F2 Toggle intercept of INT 02h. The current state appears below the segment/selector register display as 02 or blank. The default state is controlled by the presence or absence of the TRAPNMIkeyword.
a-F3 Toggle intercept of INT 0Dh. The current state appears below the segment/selector register display as 0D or blank. The default state is controlled by the presence or absence of the TRAPGENPkeyword.
a-F4 Toggle intercept of INT 0Eh. The current state appears below the segment/selector register display as 0E or blank. The default state is controlled by the presence or absence of the TRAPPAGEkeyword.
a-F5 Toggle stack display state between two columns of words and one column of dwords. The tick marks appear every 16 bytes.
a-F6 Toggle screen save state (eliminates screen flicker when single-stepping over instructions which don't write to the screen). The current state appears below the segment/selector register display as SS=ON or SS=OFF.
a-F7 Toggle video base (switch debugging screens in a two-monitor system).
a-F8 Display NDP (floating point) register screen. Use the same keystroke to remove the NDP screen.
a-F9 Display debug register screen. This screen remains active until it is replaced by another screen. That is, you may type on the command line, etc. while the debug register screen is displayed.
a-F10 Display previous debugging screens. This option can be used to compare changes over a single-step or single-skip. Up to sixteen previous screens can be displayed in this manner using the Up and Down arrows. To change from the default value of sixteen, use the keyword SAVESCREEN(see above).
a-F11 Display MMX and SSE2 register screen.
a-F Goto the far return address at SS:SP or SS|eSP (depending upon the current mode). If the current code segment is USE16, the far return address is assumed to be word:word (or word|word); if it's USE32, the format is assumed to be word:dword (or word|dword). This shortcut is equivalent to typing G .RETF at the command line.
a-N Goto the near return address at SS:SP or SS|eSP (depending upon the current mode). If the current code segment is USE16, the near return address is assumed to be word; if it's USE32, the format is assumed to be dword. This shortcut is equivalent to typing G .RETN at the command line.
a-< Retrieve the previous command from the command history buffer.
a-> Retrieve the next command from the command history buffer.
a-? Display the command history buffer.
c-F1 Toggle intercept of INT 01h only. The current state appears below the segment/selector register display as 01 or blank. The default state is controlled by the presence or absence of the TRAPSTEPkeyword.
c-F2 Toggle intercept of INT 03h only. The current state appears below the segment/selector register display as 03 or blank. The default state is controlled by the presence or absence of the TRAPSKIPkeyword.
c-F3 Toggle intercept of INT 06h. The current state appears below the segment/selector register display as 06 or blank. The default state is controlled by the presence or absence of the TRAPINVkeyword.
c-F4 Toggle intercept of INT 0Ch. The current state appears below the segment/selector register display as 0C or blank. The default state is controlled by the presence or absence of the TRAPSTACKkeyword.
c-F5 Display PDE entries.
c-F6 Display symbols.
c-F7 Display file browser.
c-F8 Enter CHAT mode. This allows two connected machines to test the serial port connection. What you type is displayed on the lower screen and sent to the other system; whatever is received is displayed on the top screen. If only garbage characters appear the two machines may not have the same data transfer rate set.
c-F9 Attempt to connect for remote debugging. See the section at the end of this document on remote debugging.
c-F10 Display error log.
c-F11 Single-step INT-like instruction in VM to PM, otherwise just single-step (same as c-Padplus).
c-Up Decrement the location pointer to the previous entry. This change has a different effect depending upon the type of information being displayed. If used in a data display, it moves back one data item (byte, word, dword, etc.). If used in a TSS display, the I/O ports in the I/O bit permission map scroll up.
c-Down Increment the location pointer to the next entry. This change has a different effect depending upon the type of information being displayed. If used in a data display, it moves forward one data item (byte, word, dword, etc.). If used in a TSS display, the I/O ports in the I/O bit permission map scroll down.
c-Home Place the current instruction at the top of the screen.
c-B Display memory in byte (xx) format.
c-D Display memory in dword (xxxxxxxx) format.
c-G Display memory in GDT format.
c-I Display memory in IDT format.
c-K Display Windows Kernel Debugger Structures menu. This menu may be displayed only when running under Windows as a kernel debugger.  See WINKDBG.DOC.
c-M Display memory allocation chain entries based at the value assigned to MACBASE. By default, this value is the initial value of .DMAC.
c-T Display memory in TSS format.
c-V Display memory in vector (xxxx:xxxx) format.
c-W Display memory in word (xxxx) format.
c-Z Zap (convert to NOPs) the instruction at the top of the instruction disassembly window.
c-ESC Same as ESC, but if you're on an INT 03h, it skips over it first and then continues. If the current instruction is not an INT 03h, this keystroke behaves identically to ESC.
Padplus Single-step the current instruction (same as F11).
c-Padplus Single-step INT-like instruction in VM to PM, otherwise just single-step (same as c-F11).
Padminus Single-skip the current instruction (same as F12). That is, execute the current instruction and put a breakpoint on the instruction following. This is used to execute but not single-step through a CALL or LOOP instruction.
Padstar Goto the instruction on the top line (same as s-F3).
Up Scroll the screen up one line. This key has the same effect in almost all screen displays.
Down Scroll the screen down one line. This key has the same effect in almost all screen displays.
PgUp Scroll the screen up one page. This key has the same effect in almost all screen displays.
PgDown Scroll the screen down one page. This key has the same effect in almost all screen displays.
s-PrtSc Print the screen. Note that if either the previous application screen (F10) or one of the previous debugging screens (a-F10) is currently displayed, that screen is sent to the printer. The I/O port in the BIOS data area which corresponds to LPT1 is used.
Ctl-Alt-Del Reboot the system.
================================================ FILE: swat/SWATSYM.DOC ================================================ 386SWAT symbolic debugging This document covers the basics of symbolic debugging support for 386SWAT. The 386SWAT API specifics are documented in SYMBOLS.TXT; here we will describe actual usage of SWAT for symbolic debugging, and the tools needed to load symbols. There are three sections: 386SWAT - new profile options and commands SWATRUN - program loader for debugging .COM and .EXE files MAPSSF - symbol loader/translator 386SWAT Three profile options are new to SWAT: SYMSIZE=n This option sets the number of bytes to be used for the SWAT symbol table. The internal format of SWAT's symbol table is 12 bytes larger than the symbol table used for the SWAT API calls. Each public or line number occupies 23 bytes plus the length of the symbol name. SYMSIZE is used to calculate a default value for BUCKETS (described below). If BUCKETS is not explicitly defined in the profile, it will be set to min (255, max (1, SYMSIZE / 4096)). If SYMSIZE is not specified, it will default to 4096 bytes. The default BUCKETS value (if also not specified) will then be 1. See below for BUCKETS storage requirements. Use SYMSIZE=0 to minimize symbol storage requirements. This will save 4K over the default. BUCKETS=n Specify number of 1K blocks to be used for symbol name hashing. Values less than 1 and over 255 are ignored. To speed symbol name searches, all names are hashed using the following algorithm: extern unsigned int HASHPRIME; int hashpjw(char *s) { char *p; unsigned long h=0, g; for (p=s; *p; p++) { h = (h << 4) + (unsigned) tolower (*p); if (g = (h & 0xf0000000)) { h = h ^ (g >> 24); h = h ^ g; } } return ((int) (h % HASHPRIME)); } HASHPRIME is derived from a table of prime numbers closest to multiples of 256. Here are some examples: BUCKETS HASHPRIME 1 257 2 509 3 769 254 65027 255 65287 The storage occupied by the name hashing table is HASHPRIMES[BUCKETS-1] * 4, or approximately BUCKETS * 1K. When a hash value is calculated from a name, that value is shifted left 2 bits and used as an index into the table of dword bucket pointers based at the address contained in SYMNHASH. A bucket pointer may contain -1 (FFFFFFFF) or an offset from the address contained in SYMBASE. In this case, a "bucket" actually points to a symbol record. Next name pointers in each symbol record form a linked list which may be traversed to find an exact name match. The smaller the BUCKETS value, the longer these bucket chains will be, thus increasing name search time. This is only likely to be a performance hit when loading symbols, since SWAT checks for existing symbols by name. Searches for symbols entered at the command line would not be visibly impacted by longer searches. ADDRHBITS=n Specify number of address bits to use for address hash table. Values less than 8 and over 12 are ignored. Address hash table storage in bytes is 2 ^ (ADDRHBITS + 2). The minimum is therefore 1K and the maximum, 16K. ADDRHBITS defaults to 12. When symbols are present, all possible addresses in the disassembly screen are searched against the address hash table. Possible hits require traversal of the address hash buckets chain, similar to name hash bucket traversal. A "next address bucket" pointer is part of the symbol record. Thus the set of symbol records forms two interleaved linked lists: the address bucket chain and the name bucket chain. The number of bits specified by ADDRHBITS are taken from a resolved linear address, shifted left 2 bits, and used as an index into the table of dword pointers based at the address contained in SYMNHASH. The address pointed to is an offset from the address in SYMBASE, and points to the beginning symbol record in that address bucket chain. If the value is -1 (FFFFFFFF), there is no such address. Smaller address hash tables may significantly impact unassembly. Using symbols Any symbol may be used as an effective address. For example, dd 180|{SYMHASH will display the symbol address hash table. Symbol display will occur automatically if the symbols are loaded properly. See sections below on SWATRUN and MAPSSF. Symbols are displayed in the Unassemble (F9) screen. Code addresses may be displayed as public names or line numbers (if line numbers were specified with the linker's /LI option). Addresses within the unassembly are handled as intelligently as possible. For example, mov ax,[bx+7c39] may be displayed as mov ax,[bx+FOOBAR] if FOOBAR's offset is 7c39 and the default segment/selector (DS in this case) matches the segment/selector specified for the symbol FOOBAR. SWAT can now resolve addresses CLOSE TO symbols; a construction commonly seen in C code might be: mov [FOOBAR],bx mov [7c3b],es SWAT will disassemble this as mov [FOOBAR],bx mov [FOOBAR+02],es The PROXSRCH variable determines how far SWAT continues proximity searches and with what granularity. The default is 1 word. Currently, the only way to change this is by editing the memory location where PROXSRCH is stored. The high order byte of PROXSRCH contains the granularity in bytes, and the low order byte contains the number of units to search. The default is 0201h. 0108h would do byte granular searches from x+1 to x+8. Proximity searches should not visibly impact disassembly performance. A separate check for an empty symbol table ensures that no time is wasted in unnecessary calls to the symbol search routine (which has its own check for empty tables). No proximity searches are done for label display and data display; this only affects values within the disassembly. A future enhancement would be to implement a profile option to set PROXSRCH. It should also be settable from the command line. Another useful feature would be to turn off case sensitivity when searching for symbol matches. This is more of an issue when debugging C code. Again, it could be settable in the profile as well as from the command line. New commands within SWAT The Translate Symbols (TS) command may be used to adjust segment/selector values, as well as to add a constant to symbol offsets, after the symbols are loaded. This is needed for debugging the VXD. The VXD symbols would be loaded with MAPSSF, using a .wsg file to assign selector values and group ID's to the different linker groups. Once SWATVXD has located the offsets of the different VXD groups, they may be translated one at a time. For example, the VXD's DGROUP is assigned selector 28, group ID 2001, and IGROUP is assigned selector 30, group ID 2002. The .WSG file entries are: 2001 P 28 DGROUP ; Comments 2002 P 30 IGROUP ; More comments We load the .MAP file before entering Windows: MAPSSF -wVXD.WSG VXD.MAP We find that the offsets within the Windows flat model segment are DGROUP 8001BE24 IGROUP 8020397C The TS command is used to translate both groups: ts 28 2001 P 28 8001BE24 ts 30 2002 P 30 8020397C The complete syntax of the TS command is: TS osel ogrp nflag nsel nbase osel Old selector value ogrp Target group value (unless specified in .WSG file, 0) nflag P for PM symbols V for VM symbols nsel New selector value (in above example, unchanged) nbase Base value to be added to all symbol offsets SWATRUN Syntax: SWATRUN [options] progname [arguments] SWATRUN is a program loader for debugging V86 mode programs. It creates a breakpoint before the first instruction of the target program, and will also attempt to load symbols into SWAT via the VCPI debugger API with the appropriate segment fixup. If no file extension is specified, SWATRUN looks first for a .COM file then an .EXE file. The filename specified is converted into a fully qualified pathname including drive letter, directory, and extension. SWATRUN will load this file using the undocumented DOS function 4B01 to determine the segment fixup. SWATRUN will then look for a matching .SSF file, and if found, will load it directly into SWAT. If an .SSF file is not found, SWATRUN will look for a matching .MAP file. If a .MAP file is found, SWATRUN will invoke MAPSSF with the proper parameters to fixup and load the parsed .MAP file. See the section on MAPSSF for further information on .MAP file formats supported and on creation of .SSF files. .SSF file loading is faster, but does not currently report symbol allocation table shortages. If your symbols do not appear to be loaded from an .SSF file, delete the .SSF file. SWATRUN will try to load symbols from the .MAP file with MAPSSF. MAPSSF will report any changes required to the 386SWAT.PRO file. Valid SWATRUN options are: /b Generate Int 1 at beginning of SWATRUN This is useful only for debugging the loading process /mMAPFILE Load MAPFILE instead of progname.map If no .SSF file is present, SWATRUN constructs a map file name by taking the path and basename of the .EXE or .COM file and adding .MAP. This filename is passed to MAPSSF if it exists. This option may be used to specify a map file on another drive:directory. /n Do not load symbols If SWATRUN has already run once, the target program did not go resident, and symbols were loaded, run SWATRUN with this option on subsequent invocations. /o Overwrite existing SWAT symbols This option is passed to MAPSSF. Any existing symbols will be destroyed. /sSYMFILE Load SYMFILE instead of progname.ssf SWATRUN normally constructs a .ssf file name by taking the path and basename of the .EXE or .COM file and adding .SSF. If this file exists and is in the proper format created by MAPSSF, it will be loaded into 386SWAT. /? Display this message MAPSSF This program is called by SWATRUN to load .MAP files on the fly. It may also be used to produce .SSF files for loading at CONFIG.SYS time (not currently supported by SWAT). .SSF files may also be loaded directly by SWATRUN. This is faster than calling MAPSSF every time symbols are loaded. Besides reading .MAP files, MAPSSF will also process Windows SYM32 files. MAPSSF has been tested with the following .MAP file formats: - Microsoft LINK - Microsoft LINK386 flat model - Borland TLINK Syntax: MapSSF [options] fspec1 [fspec2 [...]] All options are preceded with - or /: -g#,# restrict symbol group types to specified #'s (SYM32 files only) Only symbols with group types matching one of these values will be loaded. The group type in SYM32 files is NOT the same as the group ID defined in a .WSG file. -l ignore line number information in .MAP file This option may be used to suppress loading of line number symbols when space is at a premium. Typically, line numbers take about 80% of symbol space. -o overwrite existing symbol table (default is append) Normally, new symbols are added to SWAT. Existing symbols will be updated. This option forces the symbol table to be flushed at the beginning of MAPSSF. -sxxxxm set selector to xxxx hex, where m is v for V86/real mode v+ for V86/real mode, add value to segment, p for protected mode The -sxxxxv+ form is used by SWATRUN to add a fixup to all segment values. -tfname echo SWAT tables to file fname This option may be used to create a file in SWAT symbol format (.ssf file). -wfname[.wsg] read Windows Symbol Group file fname.wsg This feature may be used for .MAP files or for .SYM files. As an example, the QMAX.WSG file contains: ; group mode sel group[!segment] 3000 P 50 PGROUP ; 386MAX code 3001 P 18 PGROUP!EDATA ; 386MAX data 3001 P 18 PGROUP!VALSEG ; 386MAX data 0 D 0 PGROUP!NCODE ; 386MAX non-resident code 0 D 0 PGROUP!NDATA ; 386MAX non-resident data 3002 P 118 IGROUP!ICODE ; 386MAX extra code 3003 P 120 IGROUP!IDATA ; 386MAX extra data 0 D 0 XGROUP ; 386MAX non-resident code/data 0 D 0 PSPGRP ; PSP group (non-resident) 3004 P 70 PDTGRP ; OFFPDT group (uninitialized) Note that all groups listed with unique segment values in the Group section of the MAP file are listed. The real mode groups XGROUP and PSPGRP will not be loaded. Association of public symbols with groups is sometimes not sufficient. Both code and data are in PGROUP, but different selectors are used. We therefore specify the individual data segments within PGROUP that will be assigned selector 18 (EDATA and VALSEG). Since segments are more completely specified in the MAP file than groups, MAPSSF will check for segment matches before checking for group matches. We also use this mechanism to avoid loading the NCODE and NDATA segments within PGROUP. Group matches are made by checking group origin values, which are sorted by value in descending order, against addresses. ALL groups which COULD include an address, from highest to lowest, are checked for inclusion in the .WSG file. The first match determines what changes are made to the matching symbol address. -v sort symbols by value (default is by name) This option controls which section of the .MAP file is read. If included on the command line, the "By Value" section is read. By default, the "By Name" section is read. By controlling the order in which symbols are passed to SWAT, the display in SWAT's Ctrl-F6 screen may be sorted by name or by value. -x# set debugging level to # (default is 0 -- no messages) This is useful for debugging only. -y default to recognizing files as SYM32 format Normally, MAPSSF recognizes files as .MAP or .SYM by their extension. If neither extension is used, this option forces recognition as SYM32.  ================================================ FILE: swat/SWATSYM.HTM ================================================ 386SWAT Symbols Documentation

386SWAT Symbolic Debugging

This document covers the basics of symbolic debugging support for 386SWAT.  The 386SWAT API specifics are documented in VCPIDBG.DOC; here we will describe actual usage of SWAT for symbolic debugging, and the tools needed to load symbols.

386SWAT Profile Options

Using symbols

New Commands Within 386SWAT

Utility Programs

386SWAT Profile Options

Several profile options are new to 386SWAT:

ADDRHBITS=n

Specify number of address bits to use for address hash table.  Values less than 8 and over 12 are ignored.

Address hash table storage in bytes is 2 ^ (ADDRHBITS + 2).  The minimum is therefore 1K and the maximum, 16K.

ADDRHBITS defaults to 12.  When symbols are present, all possible addresses in the disassembly screen are searched against the address hash table.  Possible hits require traversal of the address hash buckets chain, similar to name hash bucket traversal.  A "next address bucket" pointer is part of the symbol record.  Thus the set of  symbol records forms two interleaved linked lists: the address bucket chain and the name bucket chain.

The number of bits specified by ADDRHBITS are taken from a resolved linear address, shifted left 2 bits, and used as an index into the table of dword pointers based at the address contained in SYMNHASH.  The address pointed to is an offset from the address in SYMBASE, and points to the beginning symbol record in that address bucket chain.  If the value is -1 (FFFFFFFF), there is no such address.

Smaller address hash tables may significantly impact unassembly.
 

BUCKETS=n

Specify number of 1K blocks to be used for symbol name hashing.  Values less than 1 and over 255 are ignored.

To speed symbol name searches, all names are hashed using the following algorithm:

extern unsigned int HASHPRIME;

int hashpjw(char *s)
{
  char *p;
  unsigned long h=0, g;

  for (p=s; *p; p++) {
       h = (h << 4) + (unsigned) tolower (*p);
       if (g = (h & 0xf0000000)) {
           h = h ^ (g >> 24);
           h = h ^ g;
       }
  }

  return ((int) (h % HASHPRIME));
}

HASHPRIME is derived from a table of prime numbers closest to multiples of 256.  Here are some examples:

BUCKETS    HASHPRIME
    1         257
    2         509
    3         769
  254       65027
  255       65287

The storage occupied by the name hashing table is HASHPRIMES[BUCKETS-1] * 4, or approximately BUCKETS * 1K.

When a hash value is calculated from a name, that value is shifted left 2 bits and used as an index into the table of dword bucket pointers based at the address contained in SYMNHASH.  A bucket pointer may contain -1 (FFFFFFFF) or an offset from the address contained in SYMBASE.  In this case, a "bucket" actually points to a symbol record.  Next name pointers in each symbol record form a linked list which may be traversed to find an exact name match.

The smaller the BUCKETS value, the longer these bucket chains will be, thus increasing name search time.  This is only likely to be a performance hit when loading symbols, since 386SWAT checks for existing symbols by name.  Searches for symbols entered at the command line would not be visibly impacted by longer searches.
 

LOADSYM     Enable file I/O functions within 386SWAT.  This is needed for using the file browser, and for source level debugging.

LOADSYM=filename.ssf

Enables file I/O (same as LOADSYM).  Also loads symbols from the specified .SSF file (created by MAPSSF) at initialization time.
 

PATH=d:\dir1[,d:\dir2[,...]]

Specify search path for source browser.  If not specified, only the current directory is searched.  If a path is specified, the current directory (.) must be included explicitly.  For example, PATH=c:\qui\quilib,c:\qui\inst will not search the current directory for source files.
 

PROXSRCH=r[,g]

Specify how far 386SWAT continues proximity searches and with what granularity.  The default is 1 word.  The high order byte of PROXSRCH contains the granularity in bytes, and the low order byte contains the number of units to search.  The default is 0201h0108h would do byte granular searches from x+1 to x+8.

Proximity searches should not visibly impact disassembly performance.  A separate check for an empty symbol table ensures that no time is wasted in unnecessary calls to the symbol search routine (which has its own check for empty tables).  No proximity searches are done for label display and data display; this only affects values within the disassembly.

The command line option PS allows these settings to be changed on the fly.
 

SYMSIZE=n

This option sets the number of bytes to be used for the 386SWAT symbol table.  The internal format of 386SWAT's symbol table is 12 bytes larger than the symbol table used for the 386SWAT API calls.  Each public or line number occupies 23 bytes plus the length of the symbol name.

SYMSIZE is used to calculate a default value for BUCKETS (described below).  If BUCKETS is not explicitly defined in the profile, it will be set to min (255, max (1, SYMSIZE / 4096)).

If SYMSIZE is not specified, it will default to 4096 bytes.  The default BUCKETS value (if also not specified) will then be 1.  See below for BUCKETS storage requirements.

Use SYMSIZE=0 to minimize symbol storage requirements.  This will save 4K over the default.
 

Using symbols

Any symbol may be used as an effective address.  For example,

dd 180|{SYMHASH

will display the symbol address hash table.  Symbol display occurs automatically if the symbols are loaded properly.  See sections below on SWATRUN and MAPSSF.

Symbols are displayed in the Unassemble (F9) screen.  Code addresses may be displayed as public names or line numbers (if line numbers were specified with the linker's /LI option).  Addresses within the unassembly are handled as intelligently as possible.  For example,

mov ax,[bx+7c39]

may be displayed as

mov ax,[bx+FOOBAR]

if FOOBAR's offset is 7C39 and the default segment/selector (DS in this case) matches the segment/selector specified for the symbol FOOBAR.

386SWAT can now resolve addresses CLOSE TO symbols; a construction commonly seen in C code might be:

mov [FOOBAR],bx
mov [7c3b],es

386SWAT will disassemble this as

mov [FOOBAR],bx
mov [FOOBAR+02],es

Another useful feature would be to turn off case sensitivity when searching for symbol matches.  This is more of an issue when debugging C code. Again, it could be settable in the profile as well as from the command line.
 

New Commands Within 386SWAT

The Translate Symbols (TS) command may be used to adjust segment/selector values, as well as to add a constant to symbol offsets, after the symbols are loaded.  This is needed for debugging the VxD.  The VxD symbols would be loaded with MAPSSF, using a .wsg file to assign selector values and group ID's to the different linker groups.  Once SWATVXD has located the offsets of the different VxD groups, they may be translated one at a time.

For example, the VxD's DGROUP is assigned selector 28, group ID 2001, and IGROUP is assigned selector 30, group ID 2002.  The .WSG file entries are

  2001  P       28      DGROUP          ; Comments
  2002  P       30      IGROUP          ; More comments

We load the .MAP file before entering Windows:

MAPSSF -wVXD.WSG VXD.MAP

We find that the offsets within the Windows flat model segment are

DGROUP  8001BE24
IGROUP  8020397C

The TS command is used to translate both groups:

ts 28 2001 P 28 8001BE24
ts 30 2002 P 30 8020397C

The complete syntax of the TS command is

TS osel ogrp nflag nsel nbase
 
osel Old selector value
ogrp Target group value (unless specified in .WSG file, 0)
nflag P for PM symbols 
V for VM symbols
nsel New selector value (in above example, unchanged)
nbase Base value to be added to all symbol offsets
 

The Query Symbol (QS) command may be used to display on the command line the name and distance from a given address.  For example,

QS .code

might display as

QS .code = VWIN32_Code0001+00005678
 

Utility Programs

MAPSSF

This program is called by SWATRUN to load .MAP files on the fly.  It may also be used to produce .SSF files for loading at CONFIG.SYS time (not currently supported by SWAT).  .SSF files may also be loaded directly by SWATRUN.  This is faster than calling MAPSSF every time symbols are loaded.

Besides reading .MAP files, MAPSSF will also process Windows SYM32 files.  MAPSSF has been tested with the following .MAP file formats:

- Microsoft LINK
- Microsoft LINK386 flat model
- Borland TLINK

Syntax:

MapSSF [options] fspec1 [fspec2 [...]]

All options are preceded with - or /
 
-g#,# restrict symbol group types to specified #'s (SYM32 files only).  Only symbols with group types matching one of these values will be loaded.  The group type in SYM32 files is NOT the same as the group ID defined in a .WSG file.
-l ignore line number information in .MAP file.  This option may be used to suppress loading of line number symbols when space is at a premium.  Typically, line numbers take about 80% of symbol space.
-o overwrite existing symbol table (default is append).  Normally, new symbols are added to SWAT.  Existing 
symbols will be updated.  This option forces the symbol table to be flushed at the beginning of MAPSSF.
-sxxxxm set selector to xxxx hex, where m is 
v for V86/real mode
v+ for V86/real mode, add value to segment,
p for protected mode
The -sxxxxv+ form is used by SWATRUN to add a fixup to all segment values.
-tfname echo 386SWAT tables to file fname.  This option may be used to create a file in 386SWAT symbol format (.SSF file).
-wfname[.wsg] read Windows Symbol Group file fname.wsg.  This feature may be used for .MAP files or for .SYM files.  As an example, the QMAX.WSG file contains: 
group mode sel group[!segment] ; comment
3000 P 50 PGROUP ; 386MAX code
3001 P 18 PGROUP!EDATA ; 386MAX data
3001 P 18 PGROUP!VALSEG ; 386MAX data
0 D 0 PGROUP!NCODE ; 386MAX non-resident code
0 D 0 PGROUP!NDATA ; 386MAX non-resident data
3002 P 118 IGROUP!ICODE ; 386MAX extra code
3003 P 120 IGROUP!IDATA ; 386MAX extra data
0 D 0 XGROUP ; 386MAX non-resident code/data
0 D 0 PSPGRP ; PSP group (non-resident)
3004 P 70 PDTGRP ; OFFPDT group (uninitialized)
Note that all groups listed with unique segment values in the Group section of the MAP file are listed.  The real mode groups a XGROUP and PSPGRP will not be loaded. 

Association of public symbols with groups is sometimes not sufficient.  Both code and data are in PGROUP, but different selectors are used.  We therefore specify the individual data segments within PGROUP that will be assigned selector 18h (EDATA and VALSEG).  Since segments are more completely specified in the MAP file than groups, MAPSSF will check for segment matches before checking for group matches.  We also use this mechanism to avoid loading the NCODE and NDATA segments within PGROUP

Group matches are made by checking group origin values, which are sorted by value in descending order, against addresses.  ALL groups which COULD include an address, from highest to lowest, are checked for inclusion in the .WSG file.  The first match determines what changes are made to the matching symbol address.

-v sort symbols by value (default is by name).  This option controls which section of the .MAP file is read.  If included on the command line, the "By Value" section is read.  By default, the "By Name" section is read.  By controlling the order in which symbols are passed to SWAT, the display in SWAT's Ctrl-F6 screen may be sorted by name or by value. 
-x# set debugging level to # (default is 0 -- no messages).  This is useful for debugging only.
-y default to recognizing files as SYM32 format.  Normally, MAPSSF recognizes files as .MAP or .SYM by their extension.  If neither extension is used, this option forces recognition as SYM32. 
 

SWATCMD

Syntax:  Device=d:\path\swatcmd.exe command
  or        swatcmd command

SWATCMD can be loaded via Device= or from the DOS command line.  It may be used to pass commands to 386SWAT under program control.  Invoking SWATCMD with no options brings up 386SWAT at an INT 03h (assuming TRAPSKIP or TRAPDEBUG is active).
 

SWATRUN

Syntax: SWATRUN [options] progname [arguments]

SWATRUN is a program loader for debugging V86 mode programs.  It creates a breakpoint before the first instruction of the target program, and will also attempt to load symbols into 386SWAT via the VCPI debugger API (VCPIDBG.DOC) with the appropriate segment fixup.

If no file extension is specified, SWATRUN looks first for a .COM file then an .EXE file.  The filename specified is converted into a fully qualified pathname including drive letter, directory, and extension.  SWATRUN will load this file using  DOS function 4B01 to determine the segment fixup.

SWATRUN will then look for a matching .SSF file, and if found, will load it directly into 386SWAT.  If an .SSF file is not found, SWATRUN will look for a matching .MAP file.  If a .MAP file is found, SWATRUN will invoke MAPSSF with the proper parameters to fixup and load the parsed .MAP file.  See the section on MAPSSF for further information on .MAP file formats supported and on creation of .SSF files.  .SSF file loading is faster, but does not currently report symbol allocation table shortages.  If your symbols do not appear to be loaded from an .SSF file, delete the .SSF file.  SWATRUN will try to load symbols from the .MAP file with MAPSSF.  MAPSSF will report any changes required to the 386SWAT.PRO file.
 
Valid SWATRUN options are
 
/b Generate Int 1 at beginning of SWATRUN.  This is useful only for debugging the loading process
/mMAPFILE Load MAPFILE instead of progname.map.  If no .SSF file is present, SWATRUN constructs a map file name by taking the path and basename of the .EXE or .COM file and adding .MAP.  This filename is passed to MAPSSF if it exists.  This option may be used to specify a map file on another drive:directory.
/n Do not load symbols.  If SWATRUN has already run once, the target program did not go resident, and symbols were loaded, run SWATRUN with this option on subsequent invocations.
/o Overwrite existing SWAT symbols.  This option is passed to MAPSSF.  Any existing symbols will be destroyed.
/sSYMFILE Load SYMFILE instead of progname.ssf.  SWATRUN normally constructs a .ssf file name by taking the path and basename of the .EXE or .COM file and adding .SSF.  If this file exists and is in the proper format created by MAPSSF, it will be loaded into 386SWAT.
/? Display a help message.
================================================ FILE: swat/SWATVER.HTM ================================================ 386SWAT Version History

386SWAT Version History

Version 6.03

  • Support for display of MMX & SSE instructions
  • Display MMX and SSE registers via Alt-F11.
  • Support for display of FCMOVcc, FCOMI, FUCOMI, FCOMIP, FUCOMIP  instructions
  • Implement FSONLY keyword to allow SWAT to install in Windows w/o DVGA or MDA because you promise to bring up SWAT in a Full Screen DOS window only.
  • Implement X15 keyword to tell SWAT to pass through INT 15h memory size calls (thus not protecting its own allocated memory).  This is a debugging keyword only, not for general use.
  • Fix bug where all Family 6 CPUs were thought to support the Last Branch/Exception feature, whereas, in fact, only Intel CPUs do.  This would cause SWAT to reboot during initialization on certain Cyrix CPUs.
  • Display + or - sign after jcc instruction if a Branch Hint prefix (2Eh or 3Eh) is present.
Version 6.02
  • Support MDA hidden by PCI VGA or PCI AGP controller, and secondary PCI VGA adapter.  See SWATDISP.HTM for more details.
  • Support 4MB pages in PTE display as well as the PTE and SPTE commands.
  • Fix bug when using BC on current instruction and G to another instruction.
  • Fix bug in display of MOV r32,[EBP*n+disp32].
  • Display appropriate comments on PCI calls (INT 1Ah).
  • Emulate references to the debug registers (DRn) if the GD bit is set in DR7.\
  • Implement search for not a value, e.g., Saddr addr ~val.
  • Implement DLG16 & DLG32 commands to display dialogs when in Windows.
Version 6.01
  • Implement UNREAL command to allow debugging of Unreal Mode
This mode is a variant of Real Mode in which any segment register can access all of the 4GB address space.  That is, instead of the normal 64KB length of a segment, the length is 4GB.  This command can enable all or just some of the segment registers for Unreal Mode.  See SWATCMD.HTM for more details.
Version 6.00.002
  • Implement s-F10 to save the current screen into the last screen buffers.
  • Fix various bugs in 386SWAT's RM Windows support.
  • Implement QS command to display nearest symbol at or before a given address.
  • Implement DTE command to display Descriptor Table Entry on the command line.
  • Implement MDB command to display a Windows Module Database.
  • Implement TDB command to display a Windows Task Database.
  • Implement .MDB to return Sel|0 of current MDB.
  • Implement .TDB to return Sel|0 of current TDB.
  • Display PDE and PTE bits with PTE command.
Version 6.00.001
  • Code reorganization to accommodate logged in versions 5.10.071-9
  • Documentation moved over to HTML format.
Version 6.00.000
  • Implement support for Windows kernel debugging
This major upgrade is described (to some degree) in WINKDBG.DOC; also see 386SWAT.DOC and SWATVXD.DOC.
Version 5.10.079
  • Add More Service Routine Text
Add service routine text displays for Win95 VMM routines.  This text is displayed when decoding INT 20h calls.
Version 5.10.078
  • Fix .VMSTK and .VMRET Commands
For some reason, the implementations of the .VMSTK and .VMRET commands didn't work, so now they do.  Moreover, .VMSTK is now called .VMCRS (for Client Register Struc).
Version 5.10.077
  • Implement Time Stamp Counter Display
    On CPUs which support it (TSC bit set in CR4), display the # clocks executed since the last time 386SWAT was entered.  There is a certain amount of overhead in each entry to 386SWAT, so the numbers displayed will never be at the level of single instruction clock counts, but it is a good measure of time over a longer set of instructions.
Version 5.10.076
  • Handle New Windows Keyboard Keys
The Microsoft Natural keyboard contains three new keys:
Left Windows key
Right Windows key
Application key
These keys have new scan codes which our keyboard handler now recognizes, although we don't do much with them as yet.  The left and right Windows keys are meant to be modifiers just as Shift, Ctl-, and Alt-keys are modifiers.  The Application key is meant to be an actual keystroke, so I've assigned arbitrary key codes to it in its Unshifted, Shift-, Ctl-, and Alt-states.
For the moment, until someone can think of something better, the   Application key invokes the Help menu.
Version 5.10.075
  • Miscellaneous internal changes
Version 5.10.074
  • Use Ctrl-Shift-PrtSc To Print Instruction Window Only
When printing multiple instruction screens, repeating the register display and other information on the second and subsequent screens is unnecessary.  To this end, the key combination Ctrl-Shift-PrtSc prints the instruction portion of the display only, assuming the instruction window is displayed (if not, the entire screen is printed as usual).
Version 5.10.073
  • Implement Saved Register Clear Command

  •  

     
     
     
     
     
     
     

    In case you do not need to restore a saved register set, the saved state can be cleared with the RC command.

  • In the operand analysis display for an IRETd with NT=1, the back link TSS selector is omitted as there's no room for it and all of the other information being displayed.
Version 5.10.072
  • Implement Command Recall
Commands entered on the command line are saved in a ring buffer whose length can be changed from the default of 1024 via the profile keyword CMDHIST=nnn.
Previous commands can be retrieved via the keystrokes Alt-< (previous command) and Alt-> (next command).  Pressing either of these keys repeatedly scrolls through the buffer in the chosen direction.  The keystroke Alt-?  displays a history of (up to 25) commands from which a command can be chosen by scrolling up or down through the list, or by typing the letter next to the command.  A command may be deleted from this list via the Del key.
  • A bug was fixed when running under Windows where a jump was taken with the wrong sense (JZ vs.  JNZ) if Win386 services are available.
  • A new help screen to describe the various searching options is defined.
Version 5.10.071
  • Fix Bug When Searching For Bytes
In an earlier TWT, when handling Page Faults, the ZF flag was cleared without realizing that subsequent code depended upon it being set.  The effect was that searches for bytes were never found.  This change fixes that.
Version 5.10.070
To debug Windows at the lowest level, we need to be able to insert ourselves into Windows startup shortly after it enters PM.  To this end, the INSERT command is available.  It is used from the 386SWAT command line at the point just before Windows enters PM.
Version 5.10.069
  • Allow Fill Command On Physical Memory
The Fill (F) command used to change data in memory now allows an optional trailing P also optionally followed by a CR3, just as the Unassemble and other commands allow.
Version 5.10.068
  • Fix Bug In Implicit Stack References
When displaying the data (if any) pointed to by the current instruction, if the instruction used an implicit stack reference (such as the PUSH instruction) we sometimes would use the wrong base register (ESP vs. SP).  This TWT fixes that bug.
Version 5.10.067
  • AutoFault for GP Faults
The Autofault facility has been extended to GP Faults.  This means that an attempt is made to interpret each GP Fault intercepted by 386SWAT in a short sentence.  Type Shift-F4 to see the last Autofault error message.  Because GP Faults are many and varied, some cases will be missed (marked as unknown) or mistaken.  Please notify the author as you encounter such cases with the exact circumstances of the GP Fault so they may be corrected.
Version 5.10.066
  • When Running Under Windows, Map In/Out VM's First Megabyte
Previously, when our local keyboard handler was active, we avoided checking and setting the keyboard values in the BIOS data area if Windows was active because we couldn't be sure that that memory region was mapped in.  Now that I have discovered Win386 (INT 22h) services, we can map in/out that region around references to it.
Version 5.10.065
  • Set the GD Bit In DR7
Because some programs get a kick out of resetting the debug registers which we've carefully setup, this change has 386SWAT automatically set the Global Debug (GD) bit in DR7 on startup so that we can stop such programs before they can do any harm.  Perhaps it doesn't surprise you that Windows is the chief reason for this feature.
Version 5.10.064
  • Display Real Mode Interrupt Vector Table
As it's a very common data structure to view, the keystroke Shift-F5 now displays the RM IVT.
Version 5.10.063
  • Filter Leading Text From Symbols
Some symbols, especially from Windows programs written in C, are prefaced with text such as "__imp__", "_", and the like which adds the symbol's length but not understanding.  This feature allows you to specify in the 386SWAT profile leading text which is to be stripped from each symbol.
     SYMFILTER= text1 [text2 [...]]
The default settings are
     SYMFILTER=__imp__ _
Up to 128 characters can be specified in this way.
Version 5.10.062
  • Fix Bug When Displaying Long Symbol Names
When we display a symbol names of 50 chars or greater at the top of a data screen, we're off by one in our calculations which can cause the name to fold to the next line.
Version 5.10.061
  • Fix Bug In The Stack Width Change Calculation
Previously, the calculation of when to change stack width (words or dwords) occurred only when the code selector changed.  In fact, it should be checked when the stack selector changes (duh!).
Version 5.10.060
  • Fix Bug With Mis-aligned Stack In GP Fault Handler
If the user hooks GP Faults, the handler in LCL_INT0D uses a stack structure which is missing one word in the middle.  It's amazing it has worked at all so far.
Version 5.10.059
  • Implement Support For P6 Features
    Two P6 features are supported by this TWT.

    1.  The Branch Trace Facility (BTF) can be turned on and off via the command line BTF ON/OFF.
    2.  The Last Branch/Exception From/To registers can be displayed at all times in the lower right corner of the screen.  This feature can be turned on and off via the command line LBR ON/OFF.

  • Skip Over Read/Write From/To Debug Registers If GD Bit Is Set
When the GD bit in DR7 is set, any read from or write to a debug
register triggers a Debug Fault (and the CPU clears the GD bit from
DR7 so the Debug Fault handler can use those registers).
Some environments (Microsoft Windows comes to mind) clear the debug registers upon entry (and at other times) thus making it difficult debug in that context.  With this change, setting the GD bit traps reads and writes of those registers and handles them transparently.  A read from a debug register returns the actual value.  A write to a debug register is ignored.  The GD bit can be set from the 386SWAT command line via
    R DR7.GD=1
If you desire this behavior to be the default, use SWATCMD with the above argument.
Version 5.10.058
  • Add .VM addresses for Windows debugging
Especially when debugging calls from a Windows app down to a VM interrupt handler, it is sometimes useful to know where we'll come back to in Windows on the other side of the ARPL wall.  .VMRET will often work if the call was made via DPMI SIMVMI (function 0300h) or an INT instruction emulated by the DPMI host (Windows).
  • Add Go Monitor command and .CSIP to 386SWAT
The GM (go monitor) command takes an expression which will be evaluated as the CPU single-steps (equivalent to Pad-plus or F11).  No display will occur until 1) the monitor expression evaluates TRUE or 2) 386SWAT is invoked by some other means (GP fault, NMI, Ctrl-Alt-Pad5, etc.)
Boolean expressions may be constructed using the dyadic functions &&, ||,<, <=, ==, >=, and >.  Operator precedence is the same as the C language.
For example:
GM ah
   executes until AH is non-zero.
GM [.csip == 21cd && ah!=9
   executes until the current instruction is INT 21 and AH is any value other than 9 (DOS display string).
GM cx == 0
   executes until CX is 0.
GM
  executes until the last expression specified with GM is TRUE.
There are some limitations:
1. Currently, GM does not single-step across mode switches via INT (but will handle any mode switch handled by Pad Plus).
2. It is slow as molasses.
3. With the addition of boolean operators like && and || precedence becomes more of something one would reasonably expect.
4. GM will not work in TSS mode currently (non-critical, failure mode is the expression doesn't trigger).
Version 5.10.057
  • Fix Bug When Testing For Extended Memory
Due to an oversight, when I put in the code to determine the amount of extended memory using the INT 15h/0E801h call, I put it in after the INT 15h/0DA88h, instead of before.  Because of a bug in Phoenix 4.04 BIOSes, which crash on the 0DA88h call, the order is important.
Also, when setting up the IDT entry for VCPI debugging using TSSes, we used to set the offset to -1 (because the IDT selector is a TSS and the offset isn't used).  For convenience, I'm now setting the low-order byte of the offset to the interrupt #.  That way, when looking at the IDT in memory (not via F4) it's easy to tell which interrupt it covers.
Version 5.10.056
  • Workaround Feature In Win95
Because of a quirk in Win95 (what, only one!), when we blast in the PTEs for 386SWAT to address the monochrome and color video buffers from local addresses, we need to preserve the AVL bits and set the accessed bit so this PTE won't be thought of as one available for allocation.
Version 5.10.055
  • Handle Large Size 386SWAT With VCPI Clients
If the resident portion of 386SWAT becomes too large (perhaps a large SYMSIZE or SAVESCREEN), then we might not be able to debug VCPI clients because our footprint exceeds the 4MB limit (one page directory) for VCPI.  If this happens, we should at least warn the user in case s/he intends to debug VCPI clients.
  • Fix Bug With Unused GDT Entry
When 386SWAT loads via the 386MAX profile, it is passed its linear address when it is a VCPI client in the third of the three GDT entries allocated for load modules.  This is done because 386SWAT's PTEs are part of 386MAX's and get relocated by 386MAX when a VCPI client loads.
When 386SWAT intrudes into a Memory Manager, we don't use the third GDT entry in the same way, and in some cases we might not even allocate a third GDT entry if we have found existing GDT entries for an all memory selector and one which maps CR3.  In this case (I encountered it when intruding into QEMM), we can mistakenly reference the third GDT entry.  This TWT fixes that.
  • Check For Additional Autofault Errors For TSS Faults
If a TSS fault occurs, there are some additional reasons for it which we now test for and report on, such as invalid selectors in the back link TSS when a return from a nested TSS occurs.
At the same time, I included some additional fault error messages which occur when we're using TSSs ourselves (typically when we're debugging VCPI clients) which we we're checking for before.  This also involves moving that error message text from the data to the code segment to match where the Autofault code expects it.
Also, I changed references to $PTE_0 to $PTE_G as that's its new definition, and checked for Page Fault problems related to that bit if PTE Global Extensions are enabled in CR4.
Version 5.10.054
  • Handle Multiple GDTs When VCPI Debugging
While tracking down a bug in the CDROM game The 11th Hour, I found that 386SWAT needed to handle intruding into multiple GDTs as this game appear to use up to three different ones, alternating between two quite frequently.  We now support up to eight alternating GDTs.
At the same time, I fixed a bug where 386SWAT was not correctly recognizing whether or not it had already intruded into a GDT.  This had the effect of filling up the GDT with 386SWAT's TSS selectors which crashed the system in quick order.
Finally, while running VCPITEST to see if I had broken anything in the process, I decided to remove the check for VMSINT=ON from the VCPI call DE01 (Get PM Interface) in order to allow Intrude 386SWAT to work with a cooperating VCPI client without having to set that variable.  This means that Intrude 386SWAT will insert its PTEs into every such call, but that should be harmless.  The VMSINT=ON setting still controls whether or not 386SWAT intrudes into the VCPI call DE0C (Switch From VM To PM).
Version 5.10.053
  • Enable Debugging Extensions (If Supported) At Virtual Init Time
The Pentium CPU's debugging extensions are supported in 386SWAT via the BD command on an I/O port at which time the $DE bit is set in CR4.  This change enables them at an earlier time so any other program (such as 386MAX) can modify its behavior depending upon whether or not the $DE bit is set.
Version 5.10.052
  • Make Device Driver 386SWAT Sensitive to Another Extended Memory Function
The recent change to 386MAX to support the 0E801h Extended Memory function call needs to be copied to device-loading 386SWAT not only so it can detect how much extended memory is in the system, but also so it can lie to any subsequent program requesting the extended memory size through that interface.
Version 5.10.051
  • Implement Show PTE Command
Strolling through a large set of Page Tables such as under Windows can be tiresome, hence there's a new command.  The SPTE command works exactly likely the PTE command (displaying the Linear address/PDE/PTE on the command line) as well as displaying the corresponding PTE (as if you had pressed F5 and scrolled down to the appropriate entry).
At the same time, I allowed Ctrl-Up and -Down to scroll through the PDEs/PTEs one entry at a time (Up and Down scroll through one line at a time).
Version 5.10.050
  • Fix Bug When Using TSS For Faults
A previous TWT changed a local routine to be more self-sufficient by setting DS within the routine instead of relying upon the caller to set this register.  Alas, that was a mistake as in some cases we rely upon the Invisible Descriptor Cache, particularly when we're accessing selector values in the caller's LDT.  This TWT fixes that to use two routines, one which assumes the global DS has been set, one which does not.
At the same time, I fixed a problem with device-loading 386SWAT where software INTs 01h, 02h, 03h, and 68h are not being enabled if VME is.
Version 5.10.049
  • Fix Bug With DEBUG=PMI And Device-Loading 386SWAT
If we're loading as Device 386SWAT at startup, INIT_PROT is called at the point where 386SWAT is a temporary VCPI client of the MM.  Thus the active IDT is that of the VCPI client and INIT_PROT is setting up the MM's IDT where the VCPI client has calculated the IDT's linear address in the VCPI client's linear address space.
All this is background to say that we can't signal an INT 01h if DEBUG=PMI is specified because the active IDT (that of the VCPI client) does not have its IDT entries setup for debugging unless there's a preceding 386SWAT in the picture.  This changes enforces that condition.
Version 5.10.048
  • Call REST_PROT/INIT_PROT On Windows Entry/Exit With Device-Loading 386SWAT
When 386SWAT is loaded as a device driver (whether it was intruding into an existing memory manager or loading as VCPI 386SWAT), previously it wasn't handling the transitions into and out of Windows.
When Windows starts up, 386SWAT needs to disable itself (by calling its REST_PROT entry point) so that it is in the proper state when the 386SWAT VxD calls 386SWAT's INIT_PROT entry point after Windows loads.  Correspondingly, when Windows terminates, the VxD calls 386SWAT at its REST_PROT and 386SWAT needs to call its INIT_PROT entry point to re-enable it.
When 386SWAT is loaded from within 386MAX, MAX handles calling the proper REST_PROT/INIT_PROT entry points.  When 386SWAT is loaded as a device driver, these calls were not made.
Now they are.
Version 5.10.047
  • Swap Out Local IDT Entries Around TOGINT Call
When 386SWAT is active, it hooks various interrupts for its own use such as the timer, keyboard, cascade, and mouse (the latter two in case there's a PS/2-style mouse which goes through the keyboard controller).
When we toggle an interrupt via command line (TOGINT xx xx ...), or keystroke (Alt-F1, etc.), we need to swap out our local entries around the toggle so that we save the new entry in the proper (global) location.  In particular, this affects TOGINT 0A which is hooked locally.
Version 5.10.045 & 5.10.046
  • Allow Search Command Of PTEs

  •  
    When tracking down a bug in Win95, I found it useful to extend the search command to search through the PTEs for a specific value.  The new syntax is
       S  addr addr#PTE
       S  addr Lexpr#PTE
     where PTE can be any expression.
    At the same time, I fixed a bug where a Page Fault during the display of the searched for data caused a crash.
  • Miscellaneous Changes
1.  Display appropriate comment on DPMI interrupt lines.  This also involves defining a new segment to hold the DPMI function values (as words).
2.  For display of PTEs, note the PDE which contains the top line of the display as well as the range of linear addresses covered by the top line.
3.  For display of PDEs, note the range of linear addresses covered by the top line.
4.  Display display of PTEs and PDEs, handle not present entries by displaying "????????".
5.  Change the initial mask for memory display to allow 32-bit values.
6.  Change the number of entries displayed in dword format to eight by squeezing the entries together.  Note that the previous width can be obtained via the dd/4 command.
7.  Save the previous d?/?? value for later use separately for each width.
8.  If the selector passed to any routine which calls GETARWBASE is not present, return with CF=1 to indicate an error.  This change is needed by WINSWAT to avoid displaying an incorrect label for not present selectors.  As it turns out, without this change and with the new KRNL386, USER, GDI symbol display in WINSWAT the label displayed for not present selectors is that of the Windows routine BOZOSLIVEHERE.
Version 5.10.044
  • Prepare for Winswat
A feature needed by WINSWAT is the ability to set a temporary breakpoint from a Windows program.  This requires that we fill in the rest of the fields where else this feature is used.
A feature needed by WINSWAT is the ability to refresh debug hooks when a selector's linear address changes.
Version 5.10.043
  • Make Device Driver 386SWAT Sensitive to PCI Extended Memory Function
The recent change to 386MAX to support the PCI Extended Memory function call needs to be copied to device-loading 386SWAT not only so it can detect how much extended memory is in the system, but also so it can lie to any subsequent program requesting the extended memory size through that interface.
Version 5.10.042
  • Implement Data Width Switch
When displaying data via the Dx command, a new switch allows you to specify the number of elements to be displayed per line.  For example, to display five (instead of the usual eight) words per line, use DW/5.
This feature is a stopgap until I implement a more general data record display as in the Periscope debugger.
Version 5.10.041
  • Use Monochrome Adapter If Present
Rather than switch to the mono adapter every time I startup the system, I thought it easier to implement a keyword to do the same.  With this keyword (MONO) present, if a monochrome adapter is present in the system, it becomes the initial display screen for 386SWAT.  The monochrome adapter has always been supported by 386SWAT -- this just makes it the initial display screen as opposed to the color monitor.
Version 5.10.040
  • Allow TSS Debugging In VM
If a program enters PM from RM and asks 386SWAT to enter its GDT and IDT, as usual we setup TSS selectors for the interrupts we manage.  If this program subsequently enters VM, we need to handle the interrupt via a TSS from VM differently as the stack and register interpretation (segments vs. selectors) are different.  Previously, our TSS interrupt code expected to be entered from PM only, so a change is needed.
Also, when debugging such a RM program where the user sets a breakpoint shortly after entering PM (via setting the PE bit in CR0) but before setting TR, I found that 386SWAT failed miserably because it was depending upon there being a valid back link in the local TSS.  Thus, more changes were needed to handle an invalid back link.  In conjunction with this change, the register set command (R) is enhanced to allow TR and LDTR (a.k.a.  LDT) to be read and set, so the user can setup a valid back link should the need arise.
Also, when 386SWAT is installed as a RM debugger, avoid setting TR to our local TSS as that changes it from an invalid value to a valid value.  Unfortunately, this doesn't prevent another program from doing the same, but at least we're not the culprit.  BTW, unlike the LDTR, there seems to be no way to clear (and thus invalidate) the Task Register once it's set.  Setting TR to zero (which is after all its initial state), causes a GP Fault even though the current value of TR may be already be invalid.  Thus, once TR is set to an invalid (and possibly non-zero) value, it stays that way until set to a valid value.
  • Clear NT bit in EPM.ASM
After switching into PM, the code in EPM.ASM should clear the NT bit in case a subsequent IRET/D occurs (as it does) in order to avoid a TSS Fault.  Thanks to John Fine for pointing this out.
Version 5.10.039
  • Support Spain 172 Keyboard Layout
Thanks to Roberto Deza Asensio, 386SWAT now supports this keyboard layout.

 

 
 
 
 
 

Version 5.10.038

  • Include Function-Specific Text in INT 21h Comments
Because they occur so often in code, the display of INT 21h instructions which are the current instruction now includes function-specific text (e.g., "Write File (handle)").
Version 5.10.037
  • Calculate SYMSIZE based upon the size of the loaded symbol table
    Previously, I had attempted to calculate SYMSIZE based upon the size of the incoming .SSF file and it didn't work.  This time it does.  The effect is that you don't need to use SYMSIZE with a LOADSYM, thus reducing wasted space in 386SWAT's symbol table as well as perhaps avoiding a mistake when calculating SYMSIZE and finding it is too small.
  • Fix Bug In MAPSSF
Due to a bug in my linker, certain far calls weren't fixed up properly.
Version 5.10.036
  • Support International Keyboards
One of 386SWAT's design goals is to be as unassuming about the system as possible, intruding into the system at an absolute minimum.  As part of achieving this goal, 386SWAT has its own keyboard handler so it can debug keyboard actions within the BIOS as well as not depend upon the system's keyboard routines or data being intact and functional.
One consequence of this is that 386SWAT needs to be changed in order to support international keyboards which is what this TWT accomplishes.
To this end, the keyword KEYB= is recognized in the 386SWAT profile.  At the start, the only keyboard supported is the German one -- its keyboard layout is 129, so the KEYB= value is GR129.  Others can be supported as the need arises.  See file 386SWAT.DOC under the KEYB= entry for the list of supported keyboards.
Thanks to Armin Kunaschik, 386SWAT now supports this keyboard layout.
Version 5.10.035
  • Include INT 03h and INTO in GPSKIP=INT Processing
When I put in GPSKIP=INT, I checked for the INT xxh opcode (0CDh), but forgot about INT 03h (0CCh) and INTO (0CEh).  These cases are now covered.
Version 5.10.034
  • Implement Return Address and Goto Return Address
A common address to jump to is the (near or far) return address of a subroutine.  This is made easier by using shortened forms of the commands one might use to extract these addresses.  For details, see the "Common Memory References" section in 386SWAT.DOC.
Version 5.10.033
I've encountered enough circumstances debugging RM where RM LIDT redirection has gotten in the way, that I've decided that it's best to make NORMLIDT the default and use the (new) keyword RMLIDT to enable it when necessary.
Version 5.10.032
  • Parse I/O Command line Instructions as LVALs
For greater generality, the command line I/O instructions now allow an LVAL instead of just an atom.  Also, the IMR command line action displays the original values not the ones set by 386SWAT.
Version 5.10.031
  • Validate Back Link In Operand Analysis Display for IRET/D
On occasion, I've had the system go poof on an IRET/D when the NT bit was set (and I didn't notice that) and the back link TSS was invalid for some reason (either bad TSS selector, or something was wrong with the TSS, such as the CR3 value was invalid).  This TWT checks for that condition and reports it as part of the operand analysis display for the IRET/D instructions.
Version 5.10.030
  • Ensure Default Options Set If No Profile
If the user omits a profile on the 386SWAT device line, we skip out before setting default options.  Now we don't.
Version 5.10.029
  • Handle Invalid Symbol Selectors
If we upload symbols with an invalid selector (say, the *.WSG file is for another context -- DPMI vs.  VCPI vs.  RM), the call to GETBASE returns an error along with EAX=-1.  If this value is used for the linear address, the symbol is marked as invalid and the address hash code gets confused.  This change checks for the above eventuality and sets the pseudo-linear address to zero to avoid this problem.  BTW, the symptom is that (say) SWATRUN hangs when uploading symbols if it has two or more symbols with the same (invalid) linear address, e.g.  300|0.
  • At the same time, I upgraded the grammar for LS and PS to accept lvals instead of just atoms, thus allowing a wider variety of ways of specifying the arguments to these commands.  Others in this same vein to follow.
Version 5.10.028
Now that INTRUDE is reasonably well debugged, I'm making it the default option so users don't need to remember to use it (which has happened several times).  This will reduce the number of tech support questions I get from users of 386SWAT on the Internet.  In case the user needs to use the VCPI client version of 386SWAT, the disabling option VCPISWAT is defined.
Version 5.10.027
  • Fix Bug When Running in RM
An earlier TWT introduced a bug (for RM 386SWAT only) which set the B-bit in the stack selector.  The problem is that I forgot to reset that bit when returning to RM.  The solution is to define a new selector which has the same characteristics as DTE_SS, except with the B-bit is clear.  Before returning to RM, we switch to this new selector so as to return to an environment which is compatible with RM.
Version 5.10.026
  • Handle SIGINT 1/3
While debugging an incompatibilty with ViruSafe, I needed a minor enhancement to SIGINT to overcome their attempts to fool a RM debugger.  They used many tricks including self-modifying code, as well as installing their own INT 01h/03h handlers.  At one point their code signals INT 01h which 386SWAT intercepts, of course.  I needed to signal this interrupt to them, but SIGINT 1 invoked it as a PM interrupt, which proceeded to crash the system.  The solution was to signal INT 01h/03h as a VM interrupt, as well as ensure that TF is set in the return flags if it's INT 01h from a single-step (as opposed to a software interrupt INT 01h).
  • At the same time, I needed to save the incoming value of DR6 which triggered another change (and bug fix).  The bug fixed is an incorrect data value width in a struc missed when I changed the code segment from USE16 to USE32.
  • A related change cleaned up (and documented) the tests which handle the case where 386SWAT is entered other than through a debug exception, but with the GD bit set.
Version 5.10.025
  • Display MAC Entries
After many years of wading through MAC entries, I decided to implement a separate display screen for them (actually, Win95 pushed me over the edge -- this is a variant of "The devil made me do it").
The keyboard combination of Ctl-M brings up this screen.
  • There's also a separate command MACBASE which allows you to set the base address of the MAC chain in case it's different from .DMAC.  This is handy when displaying the DOS subsegment chain.
Version 5.10.024
  • Fix Bug In PATH= Profile Routine
When converting over to USE32 data, I missed a place where I should have cleared the high-order word of a 32-bit register.
Also, in the process of debugging this problem, I put in several more Shift debugging messages.
Version 5.10.023
  • Fix Bug With VCPI Get Protected Mode Interface Calls
In order for us to provide debugging services to VCPI clients, we need to insert our PTEs into the VCPI client's address space.  There are several contexts in which this might occur:
1.  386SWAT is loaded via LOAD= with 386MAX:  our PTEs are automatically copied to the VCPI client's address space as part of 386MAX's response to the Get Protected Mode Interface (GPMI -- DE01h) call.
2.  386SWAT is loaded as a VCPI client to a memory manager:  previously we didn't handle this case.  Now we use the newly defined RMDEV_GPMITAIL label in low DOS memory which this TWT defines an return point in order to catch the tail of the GPMI call.  At this point, we switch back to our code in extended memory, and copy our PTEs to the end of the GPMI caller's PTE buffer.
3.  386SWAT intruded into a MM (possibly 386MAX):  previously we placed a PM return address on the stack and passed control on to the MM.  This doesn't work with all MMs as some check the VM bit in the flags when interpreting the segment registers saved on the stack.  Now we use the newly defined DEV_GPMITAIL label which this TWT defines as a return point in order to catch the tail of the GPMI call.  At this point, we switch back to our code in extended memory, and copy our PTEs to the end of the GPMI caller's PTE buffer.
Version 5.10.022
  • Avoid Page Fault on LIN2PPTE Accesses
The LIN2PPTE subroutine translates a linear address to a pointer to the corresponding PTE according to a specific CR3.  Sometimes we need to read more than one PTE from the Page Directory which doesn't always work (because the subroutine doesn't know how many PTEs to map in the case we're not mapping relative to the current CR3).  A solution to this is to tell the subroutine how many PTEs are to be mapped in.
Version 5.10.021
  • Compatibility With PMODE
There is a popular shareware DOS extender available on the Internet called PMODE which is used to create PM programs.  When it is run as a VCPI client, it allocates selectors from the top down in the GDT -- the same as 386SWAT does.  PMODE uses the AVL bit in the DTE to mark a selector as in use, so this change has us set that bit in the selectors we allocate so PMODE doesn't write on top of our selectors.
Version 5.10.020
  • Fix Bug When Swapping INTs
When we swap IDT entries (say when displaying the IDT via F4) so we see or act upon the global IDT entries, we don't swap INTs 74h and 76h.  Now we do.
Version 5.10.019
  • Use Same DPL When Hooking Interrupts
Some memory managers (pssst, it's EMM386) set the DPL of various entries in the IDT to zero expecting the CPU to signal a GP Fault if the corresponding software interrupt occurs.  When we intrude into their PL0 context, previously we were setting the DPL to three because we didn't expect to encounter a MM which had a fetish with GP Faults.  Now we retain the same DPL as the original IDT entry except for INTs 01h and 03h.  They are handled differently so we can issue the corresponding software interrupts and gain control immediately instead of having to hook the GP Fault handler and pick them off there.
Version 5.10.018
  • Fix Disappearing Cursor Bug
For years we've put up with this bug.  Now it's fixed.
The problem occurs in any of three contexts:
* when reviewing last screens (Alt-F10),
* when switching between color and mono adapters (Alt-F7), or
* when swapping screens (say, when exiting 386SWAT).
The problem occurs because not all programs maintain a consistent set of data values in the BIOS data area on which we rely (e.g., the dependence between the cursor type and the cursor emulation bit).
The fix is to read the cursor start and end line values upon entry and restore those values in the above circumstances.  A new routine, GET6845 is defined for the read starting value part.  I seem to recall that the original definition of the 6845 registers was that they were write-only, but apparently they are now readable as well.
At the same time, while testing the different contexts in which 386SWAT changes the cursor type, I noticed that the Enter command handles the INS key, but not the XINS key, so I changed it.
Version 5.10.017
  • Implement Exit Command
A common command line sequence is to set AH to 4C, SIGINT 21, and G.  This is now done via a command called EXIT.
Version 5.10.016
  • Add Debugging Displays To 386SWAT During Initialization
To help me figure out why 386SWAT wasn't installing under Win95, I made several changes:
* Add some debugging displays (press and hold either shift key when 386SWAT is loading ala Shift-MAX).
* If there are no VCPI services (DEBUG=NOVCPI in 386MAX), fail gracefully.
* Ensure interrupts are re-enabled upon returning from VCPI/PM.
* Ensure that the B-bit is set in our stack selector.
* Avoid calling CHECK_I92 if we're in VM as it can reboot the system (learned the hard way).
* Put in a check to avoid calling OLDINT67_VEC if it's zero (who can argue with that?).
* Avoid a bug in MASM 5.10b which generates a word fixup when it should generate a dword fixup.  Any questions on why I want to write my own assembler?
================================================ FILE: swat/SWATVXD.DOC ================================================ SWATVXD -- Version 3.02 -- A Debugger for WIN386 (C) Copyright 1990-8 Qualitas, Inc. All rights reserved. The SWATVXD.EXE file is the accompanying VxD to 386SWAT. As long as it is in the same directory as the debugger file (386SWAT.LOD), it is loaded automatically by 386SWAT. If for some reason you don't wish that to happen, using the command "WIN NOSWAT" prevents the VxD from loading. Switches -------- The VxD provides Windows services for 386SWAT, and is useful for debugging VxDs. The VxD's operation is controlled by various switches all of which appear in the [386SWAT] section of your SYSTEM.INI file. SWATDualDisplay Squirt cool info to the mono display -- you must use this option to get the most useful output to the mono screen. SSF=d:\path\name.SSF Specify the WIN.SSF file -- this file is generated when SWAT VxD is built and contains useful symbol information about Windows VxDs. SWATVxDROM In Sys_Critical_Init, mark the Page Table Entries of all VxD code segments as read-only (normally, they are read-writable!). This feature was implemented in an attempt to figure out why Windows was crashing (I thought that there might be a bad pointer out there). While I didn't find anything in particular, it is handy to rule out this problem. If a VxD code segment is written into, an Invalid Page Fault is generated (see below). Likely, you'll find that a single IPF due to this feature is generated at the start of Windows. The default action (taken by pressing Esc at the command line) is to test for a RO page and set the RW bit. This clears the IPF for this one page only. From that point on, all IPFs should be examined carefully. If this switch is set, the SWATVxDIPF and SWATPL0WP switches are also set automatically. SWATVxDIPF In Sys_Critical_Init, hook the Invalid Page Fault handler. This feature, in conjunction with the IPF command in SWAT can be useful for debugging these beasts. The mono screen contains a formatted message of the incoming data to the IPF hook procedure. This feature is preliminary and provides a way to get control at the point of the IPF -- after that, you're on your own. If you can suggest more things SWAT can do to help debug IPFs, I'm very open to suggestions. SWATPL0WP In Sys_Critical_Init, set the WP bit in CR0 so we can trap writes into Read-Only pages at PL0. HookIRQ Hook IRQ0-7 locally if SWAT hooks them. This switch is necessary for some VxDs (RAM Doubler in particular) as they don't install correctly if they find some IRQs not hooked by selector 28h. Go figure. Debugging VxDs -------------- To debug VxDs at their entry points, use the following switches: HookVxD=DDB_Name[,#s] Trap at a particular VxD by name. Note that is case sensitive, and <#> specifies message numbers (optional). See the VxD Filename and Message # tables below. HookPM=DDB_Name,reg,# Trap at a particular VxD's PM API entry. specifies a 16-bit register used by the VxD for the function code, and <#> specifies the functions to trap. For example, HookPM=SHELL,DX,3 traps at the WINOLDAP hook VxD Filenames ------------- Some VxD filenames, DDB names, Device_ID, and their switches: WINA20.386 'LA20HMA ' xxxxh NOLOW64KPAGING NOLOW64KPAGINGPORT Debug ' ' 0002h *VPICD 'VPICD ' 0003h *VDMAD 'VDMAD ' 0004h *VTD 'VTD ' 0005h *V86MMGR 'V86MMGR ' 0006h *PAGESWAP 'PageSwap' 0007h *VKD 'VKD ' 000Dh INITPS2MOUSEATEXIT=ON/OFF *DOSMGR 'DOSMGR ' 0015h *WSHELL 'SHELL ' 0017h *PAGEFILE 'PageFile' 0021h 386MAX.VXD 'LoadHi ' 001Ch SWATVXD.EXE 'SWATVXD ' 2400h VDDVGA.386 'VDD ' 000Ah VNETWARE.386 'DOSNET ' 001Ah PM_BIOS.386 'PMVDD ' 2250h VxD Message #s -------------- 0000h Sys_Critical_Init 001Bh Sys_Dynamic_Device_Init 0001h Device_Init 001Ch Sys_Dynamic_Device_Exit 0002h Init_Complete 001Dh Create_Thread 0003h Sys_VM_Init 001Eh Thread_Init 0004h Sys_VM_Terminate 001Fh Terminate_Thread 0005h System_Exit 0020h Thread_Not_Executeable 0006h Sys_Critical_Exit 0021h Destroy_Thread 0007h Create_VM 0022h PNP_New_Devnode 0008h VM_Critical_Init 0023h W32_DeviceIOControl 0009h VM_Init 0024h Sys_VM_Terminate2 000Ah VM_Terminate 0025h System_Exit2 000Bh VM_Not_Executeable 0026h Sys_Critical_Exit2 000Ch Destroy_VM 0027h Vm_Terminate2 000Dh VM_Suspend 0028h Vm_Not_Executeable2 000Eh VM_Resume 0029h Destroy_VM2 000Fh Set_Device_Focus 002Ah VM_Suspend2 0010h Begin_Message_Mode 002Bh End_Message_Mode2 0011h End_Message_Mode 002Ch End_PM_App2 0012h Reboot_Processor 002Dh Device_Reboot_Notify2 0013h Query_Destroy 002Eh Crit_Reboot_Notify2 0014h Debug_Query 002Fh Close_VM_Notify2 0015h Begin_PM_App 0030h Get_Contention_Handler 0016h End_PM_App 0031h Kernel32_Initialized 0017h Device_Reboot_Notify 0032h Kernel32_Shutdown 0018h Crit_Reboot_Notify 0019h Close_VM_Notify 001Ah Power_Event Message Number Traps -------------------- To stop inside SWAT at various message numbers, use the following switches: SWATSysCriticalInit SWATDeviceInit SWATInitComplete SWATSysVMInit SWATSysVMTerminate SWATSystemExit SWATSysCriticalExit SWATCreateVM SWATVMCriticalInit SWATVMInit SWATVMTerminate SWATVMNotExecuteable SWATDestroyVM SWATVMSuspend SWATVMResume SWATSetDeviceFocus SWATBeginMessageMode SWATEndMessageMode SWATRebootProcessor SWATQueryDestroy SWATDebugQuery SWATBeginPMApp SWATEndPMApp SWATDeviceRebootNotify SWATCritRebootNotify SWATCloseVMNotify SWATPowerEvent SWATSysDynamicDeviceInit SWATSysDynamicDeviceExit SWATCreateThread SWATThreadInit SWATTerminateThread SWATThreadNotExecuteable SWATDestroyThread SWATPNPNewDevnode SWATW32DeviceIOControl SWATSysVMTerminate2 SWATSystemExit2 SWATSysCriticalExit2 SWATVMTerminate2 SWATVMNotExecuteable2 SWATDestroyVM2 SWATVMSuspend2 SWATEndMessageMode2 SWATEndPMApp2 SWATDeviceRebootNotify2 SWATCritRebootNotify2 SWATCloseVMNotify2 SWATGetContentionHandler SWATKernel32Initialized SWATKernel32Shutdown Internal Use Only ----------------- The following switches are for internal use only. SSFPrefix=name Specify device name and DDB prefix. SWATDebugThruExit Call SWAT's INIT_PROT during Critical_Exit. This allows debugging on the way out of SWAT. Now that SWAT is a Windows kernel debugger, this switch is unnecessary. RealModeBreak=ON/OFF Hit an INT 1 early in RealModeInit. Rehook123=ON/OFF Blast INTs 1, 2, and 3 into the IDT. To avoid trouble with WDEB386. Now that SWAT is a Windows kernel debugger, there should be less need to run WDEB386.  ================================================ FILE: swat/SWATVXD.HTM ================================================ SWAT VxD Documentation
SWATVXD -- A Debugger for WIN386
(C) Copyright 1990-7 Qualitas, Inc.  All rights reserved.

The SWATVXD.EXE file is the accompanying VxD to 386SWAT.  As long as it is in the same directory as the debugger file (386SWAT.LOD), it is loaded automatically by 386SWAT.  If for some reason you don't wish that to happen, using the command WIN NOSWAT prevents the VxD from loading.
 

Switches

The VxD provides Windows services for 386SWAT, and is useful for debugging VxDs.

The VxD's operation is controlled by various switches all of which appear in the [386SWAT] section of your SYSTEM.INI file.

SWATDualDisplay
Squirt cool info to the mono display -- you must use this option to get the most useful output to the mono screen.

SSF=d:\path\name.SSF
Specify the WIN.SSF file -- this file is generated when 386SWAT VxD is built and contains useful symbol information about Windows VxDs.

SWATVxDROM
In Sys_Critical_Init, mark the Page Table Entries of all VxD code segments as read-only (normally, they are read-writable!).  This feature was implemented in an attempt to figure out why Windows was crashing (I thought that there might be a bad pointer out there). While I didn't find anything in particular, it is handy to rule out this problem.  If a VxD code segment is written into, an Invalid Page Fault is generated (see below).  Likely, you'll find that a single IPF due to this feature is generated at the start of Windows.  The default action (taken by pressing Esc at the command line) is to test for a RO page and set the RW bit.  This clears the IPF for this one page only. From that point on, all IPFs should be examined carefully.  If this switch is set, the SWATVxDIPF switch is also set automatically.

SWATVxDIPF
In Sys_Critical_Init, hook the Invalid Page Fault handler.  This feature, in conjunction with the IPF command in 386SWAT can be useful for debugging these beasts.  The mono screen contains a formatted message of the incoming data to the IPF hook procedure.  This feature is preliminary and provides a way to get control at the point of the IPF -- after that, you're on your own.  If you can suggest more things 386SWAT can do to help debug IPFs, I'm very open to suggestions.
 
HookIRQ
Hook IRQ0-7 locally if 386SWAT hooks them.  This switch is necessary for some VxDs (RAM Doubler in particular) as they don't install correctly if they find some IRQs not hooked by selector 28h.  Go figure.
 

Debugging VxDs

To debug VxDs at their entry points, use the following switches:

HookVxD=DDB_Name[,#s]
Trap at a particular VxD by name.  Note that DDB_Name is case sensitive, and # specifies message numbers (optional).  See the VxD Filename and Message # tables below.

HookPM=DDB_Name,reg,#
Trap at a particular VxD's PM API entry.  reg specifies a 16-bit register used by the VxD for the function code, and # specifies the functions to trap.  For example, HookPM=SHELL,DX,3 traps at the WINOLDAP hook
 

VxD Filenames

Some VxD filenames, DDB names, Device_ID, and their switches:

WINA20.386       'LA20HMA ' xxxxh
                            NOLOW64KPAGING
                            NOLOW64KPAGINGPORT
Debug            '        ' 0002h
*VPICD           'VPICD   ' 0003h
*VDMAD           'VDMAD   ' 0004h
*VTD             'VTD     ' 0005h
*V86MMGR         'V86MMGR ' 0006h
*PAGESWAP        'PageSwap' 0007h
*VKD             'VKD     ' 000Dh
                            INITPS2MOUSEATEXIT=ON/OFF
*DOSMGR          'DOSMGR  ' 0015h
*WSHELL          'SHELL   ' 0017h
*PAGEFILE        'PageFile' 0021h
386MAX.VXD       'LoadHi  ' 001Ch
SWATVXD.EXE  'SWATVXD ' 2400h
VDDVGA.386       'VDD     ' 000Ah
VNETWARE.386 'DOSNET  ' 001Ah
PM_BIOS.386  'PMVDD   ' 2250h
 

VxD Message #s

0000h  Sys_Critical_Init     001Bh Sys_Dynamic_Device_Init
0001h  Device_Init           001Ch Sys_Dynamic_Device_Exit
0002h  Init_Complete         001Dh Create_Thread
0003h  Sys_VM_Init           001Eh Thread_Init
0004h  Sys_VM_Terminate      001Fh Terminate_Thread
0005h  System_Exit           0020h Thread_Not_Executeable
0006h  Sys_Critical_Exit     0021h Destroy_Thread
0007h  Create_VM             0022h PNP_New_Devnode
0008h  VM_Critical_Init      0023h W32_DeviceIOControl
0009h  VM_Init               0024h Sys_VM_Terminate2
000Ah  VM_Terminate          0025h System_Exit2
000Bh  VM_Not_Executeable    0026h Sys_Critical_Exit2
000Ch  Destroy_VM            0027h Vm_Terminate2
000Dh  VM_Suspend            0028h Vm_Not_Executeable2
000Eh  VM_Resume             0029h Destroy_VM2
000Fh  Set_Device_Focus      002Ah VM_Suspend2
0010h  Begin_Message_Mode    002Bh End_Message_Mode2
0011h  End_Message_Mode      002Ch End_PM_App2
0012h  Reboot_Processor      002Dh Device_Reboot_Notify2
0013h  Query_Destroy         002Eh Crit_Reboot_Notify2
0014h  Debug_Query           002Fh Close_VM_Notify2
0015h  Begin_PM_App          0030h Get_Contention_Handler
0016h  End_PM_App            0031h Kernel32_Initialized
0017h  Device_Reboot_Notify  0032h Kernel32_Shutdown
0018h  Crit_Reboot_Notify
0019h  Close_VM_Notify
001Ah  Power_Event      
 

Message Number Traps

To stop inside 386SWAT at various message numbers, use the following switches:

SWATSysCriticalInit
SWATDeviceInit
SWATInitComplete
SWATSysVMInit
SWATSysVMTerminate
SWATSystemExit
SWATSysCriticalExit
SWATCreateVM
SWATVMCriticalInit
SWATVMInit
SWATVMTerminate
SWATVMNotExecuteable
SWATDestroyVM
SWATVMSuspend
SWATVMResume
SWATSetDeviceFocus
SWATBeginMessageMode
SWATEndMessageMode
SWATRebootProcessor
SWATQueryDestroy
SWATDebugQuery
SWATBeginPMApp
SWATEndPMApp
SWATDeviceRebootNotify
SWATCritRebootNotify
SWATCloseVMNotify
SWATPowerEvent
SWATSysDynamicDeviceInit
SWATSysDynamicDeviceExit
SWATCreateThread
SWATThreadInit
SWATTerminateThread
SWATThreadNotExecuteable
SWATDestroyThread
SWATPNPNewDevnode
SWATW32DeviceIOControl
SWATSysVMTerminate2
SWATSystemExit2
SWATSysCriticalExit2
SWATVMTerminate2
SWATVMNotExecuteable2
SWATDestroyVM2
SWATVMSuspend2
SWATEndMessageMode2
SWATEndPMApp2
SWATDeviceRebootNotify2
SWATCritRebootNotify2
SWATCloseVMNotify2
SWATGetContentionHandler
SWATKernel32Initialized
SWATKernel32Shutdown
 

Internal Use Only

The following switches are for internal use only.

SSFPrefix=name
Specify device name and DDB prefix.
 
SWATDebugThruExit
Call 386SWAT's INIT_PROT during Sys_Critical_Exit.  This allows debugging on the way out of 386SWAT.  Now that 386SWAT is a Windows kernel debugger, this switch is unnecessary.

RealModeBreak=ON/OFF
Hit an INT 1 early in RealModeInit.
 
Rehook123=ON/OFF
Blast INTs 1, 2, and 3 into the IDT.  To avoid trouble with WDEB386. Now that 386SWAT is a Windows kernel debugger, there should be less need to run WDEB386.  ================================================ FILE: swat/SWATWDBG.HTM ================================================ Windows Debugging

Windows Debugging

386SWAT runs as a debugger under Windows 3.x and 95/98 when accompanied by its VxD. This file (SWATVXD.EXE) should be in the same directory as the debugger file (386SWAT.LOD) and is loaded automatically when Windows starts. To take advantage of the information provided by the VxD, you should have a monochrome monitor attached to your system. For more details about the VxD including how to configure it, see the file SWATVXD.DOC ================================================ FILE: swat/SWATWISH.HTM ================================================ 386SWAT Wish List

386SWAT Wish List

Here's my wish list (in no particular order) of things I would like this debugger to do.  Feel free to contribute yours in our newsgroup:

  • Internal assembler to insert code into memory
  • User defined macro expansion on the command line
  • Write Master Boot Record loader to get in at the very beginning
  • Display remaining Windows internal structures
  • Figure out how to install under Windows NT (where there's no starting DOS session)
  • Allow the user to configure the screen display
  • Allow the user to define and display custom data records (such as three words followed by two bytes, followed by an ASCIIZ text string, etc.)
  • Define PL3 Windows application for displaying 386SWAT screens
  • Get DOS extender library authors to add support for 386SWAT to their programs
  • Better documentation
  • Redo internal symbol table to allow deletion
================================================ FILE: swat/SWATWKD.HTM ================================================ Windows Kernel Debugging
Windows Kernel Debugging

If you program under Windows 3.1x or Win95/98 (but not WinNT), 386SWAT presents itself to Windows as a very low-level debugger. Essentially, 386SWAT is provided the same level of access as the remote debugger WDEB386 shipped with Windows. WDEB386 requires that you run it from a separate system with a COM cable running between the two systems. In contrast, 386SWAT runs on the same system being debugged, however it does require that you have a monochrome adapter and monitor installed in the system.

For more details on this topic, see the file WINKDBG.DOC ================================================ FILE: swat/VCPIDBG.DOC ================================================ Preliminary Proposal For Debugger Extensions to VCPI Specification 30 May 89 Amended 22 Aug 90 Amended 9 Aug 94 Ŀ Rationale The premise is that there is already a resident debugger in the system which the client wishes to use. These calls provide an interface between the client and the debugger to allow that to happen. In order for the debugger to support this interface, it should intercept INT 67h during its initialization and troll for the following calls, ignoring most others. The debugger may wish to troll for the "Set 8259A Interrupt Vector Mappings" call in order to properly determine where the timer and keyboard interrupts start. Ŀ V86 Mode Program Interface OVERVIEW If your program enters PM via DPMI using a memory manager with an integrated DPMI host, skip all this as 386SWAT hooks into the host's GDT and IDT through the INTRUDE option. Note that DPMI hosts which install as a separate device driver appear to the memory manager (and thus to 386SWAT) as a VCPI client, so the above advice to skip this document does not apply. I haven't tried to debug a DPMI client in this context, so I'm not sure how to do it. If your program enters PM via VCPI, use functions DEF0, DE01, DEF4, DEF2, and DEF3 in that order so that 386SWAT is properly initialized in your program's GDT and IDT. If your program enters PM from RM and uses paging, use functions DEF0, DEF4, DEF2, DEF3, and DEF9 in that order although function DEF9 can be executed anytime after function DEF0 executes successfully. If your program enters PM from RM and does not use paging, use functions DEF0, DEF4, DEF2, and DEF3 in that order. When debugging VCPI clients, be sure to enable the VMSINT flag either by putting the keyword VMSINT into your 386SWAT profile, or by typing VMSINT ON from the 386SWAT command line. INT 67h AX = 0DEF0h Determine Debugger Presence INPUTS: None. OUTPUTS: AH = 00h if successful = 84h if VCPI not supported = 8Fh if debugger support not present BH = Debugger specification major version # BL = ... minor ... This call determines whether or not a resident debugger is present in the system. The current specification version number is 5.00; that is, BH = 05, BL = 00. These values are in binary such that if the specification version number were 10.12, this call would return BH = 0Ah, BL = 0Ch. INT 67h AX = 0DEF1h Get Debugger Information INPUTS: None. OUTPUTS: AH = 00h if successful EDX = Physical address of debugger information This call returns the physical address of a certain data structure inside 386SWAT for use in conjunction with the 386SWAT Virutal Device for Windows 3. The contents of the structure is as follows: INFO_LEN dw ? ; Byte count of structure INFO_BASE dd ? ; Physical base address of SWAT code segment SWTINF_VER dw ? ; Version # of structure More fields are defined which are used by SWATVXD. INT 67h AX = 0DEF2h Initialize Debugger Interface, Task Gate INPUTS: ES:DI ==> GDT entries for debugger support If ES = 0, EDI ==> ... BX = initial selector OUTPUTS: AH = 00h if successful = 84h if VCPI not supported = 8Fh if debugger support not present BX:EDX = Address of protected mode entry point This call allows the debugger to setup its own GDT entries as it pleases. The number of entries it may use is limited to thirty (30) so the client can statically allocate space in its GDT. Each GDT entry used by SWAT is a TSS selector, and the IDT entries used (when DEF3 is called) are Task Gates (cf. DEFD). The starting selector number in BX is needed so that the "Initialize Debugger IDT Entry" call knows what selectors to use when initializing an IDT entry. Consequently, this call must precede that call in order to know the proper selector value. If you are writing a PM program which enters PM via VCPI, your call to the VCPI Get PM Interface (DE01) must precede this call as 386SWAT needs to hook into the latter call in order to ensure that its PTEs are visible when the VCPI client is active (and thus know what its new linear address is). The selector and offset returned identify the address of the protected mode entry point in the debugger (see below). This entry point should be called via a USE32 far call as it might be a task gate. INT 67h AX = 0DEF3h Initialize Debugger IDT Entry INPUTS: BX = interrupt # ES:DI ==> IDT entry for interrupt BX If ES = 0, EDI ==> ... OUTPUTS: AH = 00h if successful = 83h if interrupt # not supported by the debugger = 84h if VCPI not supported = 8Fh if debugger support not present This call allows the client to selectively activate the debugger's interrupt handlers. Because some debuggers may support more interrupt handlers than others, it is recommended that the client call this function for all interrupts between 00h and 1Fh. If the debugger doesn't support a particular interrupt number, it will return an error code which the caller can ignore. Some interrupt numbers may be handled wholly by the debugger (not passed on to the previous handler). Some may be chained, with the debugger handling only certain situations (as may be the case if the 8259A's interrupt numbers overlay CPU fault interrupt numbers). For this reason, the client should initialize the IDT entry with a valid handler in case the debugger passes along the interrupt. Because this call may be invoked multiple times on the same interrupt number, the debugger must check the existing entry to see if it is the same as the value to which it would initialize the entry. If that's the case, the debugger should ignore the call and return a successful result code. If you are writing a PM program which enters PM via VCPI, your call to the VCPI Get PM Interface (DE01) must precede this call as 386SWAT needs to hook into the latter call in order to ensure that its PTEs are visible when the VCPI client is active (and thus know what its new linear address is). INT 67h AX = 0DEF4h Set New Debugger CR3 and Linear Address INPUTS: EBX = new CR3 or -1 if unchanged EDX = new linear address or -1 if unchanged. OUTPUTS: AH = 00h if successful This call is used in conjunction with functions DEF2 and DEF3 if your program enters PM without using either VCPI or DPMI. In that case, this case must precede the calls to functions DEF2 and DEF3 and you must also call function DEF9. If EDX == -1 on entry, SWAT will return the current linear address in EDX upon return. INT 67h AX = 0DEF5h (Reserved) INT 67h AX = 0DEF6h Symbol Table Management Functions INPUTS: BL = 00h Append ECX names from DS:ESI ECX = # names to append DS:ESI ==> table of names to append (see SYMC_STR) OUTPUTS: AH = 00h if successful AH = 88h if not ECX = # symbols appended SYMC_STR struc SYMC_FVEC df ? ; Seg:Off or Sel|Off SYMC_FLAG dw ? ; Flags: see SYMFL_REC below SYMC_GRP dw ? ; Group # (arbitray value may be used ; with TS command from the command ; line to group symbols) SYMC_NAMLEN db ? ; Length byte db ? dup (?) ; ASCII name (no terminating zero) SYMC_STR ends SYMFL_REC record $SYMFL_VM:1,$SYMFL_TYP:5,$SYMFL_RSV:10 @SYMFL_VM equ mask $SYMFL_VM ; 1 = symbol is for VM ; 0 = ... PM ; The above flag is meaningful for _DAT and _LN ; types only. @SYMFL_TYP equ mask $SYMFL_TYP ; Data types: see @SYMTYP_xxx below @SYMTYP_DAT equ 0 ; Code or data @SYMTYP_LN equ 1 ; Line number record constructed by MAPSSF @SYMTYP_ABS equ 2 ; ABS record @SYMTYP_SWT equ 3 ; Symbol is for SWAT internal use INPUTS: BL = 01h Search for name DS:ESI DS:ESI ==> name to search for (see SYMC_STR) OUTPUTS: AH = 00h if successful AH = A0h if not found INPUTS: BL = 02h Translate old symbol to new DS:ESI ==> SYMTRAN_STR (see below) OUTPUTS: AH = 00h if successful Use this call to translate a symbol's segment/selector and group to a new segment/selector and base. SYMTRAN_STR struc SYMTRAN_OSEL dw ? ; Old segment/selector SYMTRAN_OGRP dw ? ; Old group # SYMTRAN_NFLAG dw ? ; New flags SYMTRAN_NSEL dw ? ; New segment/selector SYMTRAN_NBASE dd ? ; New base (to be added to all offsets) SYMTRAN_FLAGS dw ? ; Flags for match significance SYMTRAN_STR ends ; Flags used in SYMTRAN_FLAGS to indicate which elements in SYMTRAN_STR ; are to be ignored. ; $SYMFL_ADDVMSEG indicates that the new segment value is to be added ; to all V86 mode segments. SYMTFL_REC record $SYMTFL_IGOSEL:1,$SYMTFL_IGOGRP:1,$SYMTFL_IGNFLAG:1,\ $SYMTFL_IGNSEL:1,$SYMTFL_ADDVMSEG:1,$SYMTFL_RSVD:11 INPUTS: BL = 03h Flush the symbol table OUTPUTS: AH = 00h if successful INPUTS: BL = 04h Append without replacing existing symbols (allow duplicates of existing symbols) (same as BL=00h) OUTPUTS: AH = 00h if successful INPUTS: BL = 05h Execute ASCIIZ command in 386SWAT DS:ESI ==> ASCIIZ string containing a command OUTPUTS: AH = 00h if successful Use this call to execute a command on the 386SWAT command line. This function is used by the SWATCMD.EXE device driver. INPUTS: BL = 06h Copy ASCIIZ string to error log DS:ESI ==> ASCIIZ string OUTPUTS: AH = 00h if successful INT 67h AX = 0DEF7h (Reserved) INT 67h AX = 0DEF8h (Reserved) INT 67h AX = 0DEF9h Fill in 386SWAT's PTEs INPUTS: ECX = maximum # PTEs ES:DI can hold ES:DI ==> save area for PTEs If ES = 0, EDI ==> ... OUTPUTS: AH = 00h if successful AH = 8Bh if 386SWAT needs more PTEs than specified ECX = # additional PTEs 386SWAT needs Use this call in conjunction with function DEF4 if your program enters PM without using VCPI or DPMI so that 386SWAT's PTEs are visible in your program's address space. To determine how many PTEs SWAT needs without filling them in, call this function with ECX = 0, and on return (with AH = 8Bh), ECX has the number of PTEs SWAT needs. INT 67h AX = 0DEFAh (Reserved) INT 67h AX = 0DEFBh (Reserved) INT 67h AX = 0DEFCh (Reserved) INT 67h AX = 0DEFDh Initialize Debugger Interface, Interrupt Gate INPUTS: ES:DI ==> GDT entries for debugger support If ES = 0, EDI ==> ... BX = initial selector OUTPUTS: AH = 00h if successful = 84h if VCPI not supported = 8Fh if debugger support not present BX:EDX = Address of protected mode entry point This call allows the debugger to setup its own GDT entries as it pleases. The number of entries it may use is limited to four (4) so the client can statically allocate space in its GDT. Each GDT entry used by SWAT is a Code, Data, or LDT selector, and the IDT entries used (when DEF3 is called) are Interrupt Gates (cf. DEF2). The starting selector number in BX is needed so that the "Initialize Debugger IDT Entry" call knows what selectors to use when initializing an IDT entry. Consequently, this call must precede that call in order to know the proper selector value. If you are writing a PM program which enters PM via VCPI, your call to the VCPI Get PM Interface (DE01) must precede this call as 386SWAT needs to hook into the latter call in order to ensure that its PTEs are visible when the VCPI client is active (and thus know what its new linear address is). The selector and offset returned identify the address of the protected mode entry point in the debugger (see below). This entry point should be called via a USE32 far call as it might be a task gate. Ŀ Protected Mode Program Interface For the moment, there are no defined functions. However, when there are, we will require that AH = 0DEh and that the subfunction code be in AL. Ŀ Tips On Debugging DPMI Programs If you are using an integrated DPMI host such as 386MAX, no special action is needed on your part to debug a DPMI program. 386SWAT installs itself as a PL0 extension to the memory manager and thus also to the DPMI host. Place breakpoints in your code as needed as well as step right over the far call to the DPMI host which switches from VM to PM. If you using a non-integrated DPMI host such as QDPMI.SYS which is distributed with QEMM, then essentially you are debugging a VCPI client which provides DPMI services to its clients. See the next section for details on debugging VCPI programs. Ŀ Tips On Debugging VCPI Programs Assuming SWAT has successfully intruded into the MM's (memory manager's) PM context, it is on the same level as MM -- that is, you should think of it as a PL0 extension of the VCPI host. This means that you need to tell SWAT to intrude into the VCPI client's context. Some VCPI clients are easy to break into, some are quite hostile (not maliciously, it's just that they don't leave any wiggle room). There's no magic to this. Fundamentally, SWAT needs room in the GDT for its selectors. See the above description on how to get your program to cooperate with SWAT, but if you want to get up and running quickly, you might first try these steps: * Allocate about 30 selectors at the end of the GDT, * Initialize the selectors to all zero, * Plant an INT 01h/03h in the PM portion of your code or whatever you prefer, * Type VMSINT ON on the SWAT command line, * Start your program. The only tricky part is to ensure that any breakpoints you set to which SWAT would respond occur after the stack in the VCPI client has been setup (and preferably also DS, ES, FS, and GS). Typically, this means that you can debug through every single instruction except for the handful which occur during the handoff from the VCPI host's PM context to the VCPI client's PM context. The reason for this is that the VCPI PM handoff depends upon descriptor caching. In particular, the VCPI spec has the client specifying the state of all EGP registers, but only the CS segment registers. Thus the VCPI client starts off execution with its own environment (GDT, LDT, IDT, TR, and CR3) in effect, but on the VCPI host's stack. The value of that stack selector quite likely is invalid in the client's GDT/LDT, so the VCPI client must switch to its own stack ASAP. Of course, if an interrupt/exception occurs before then, when the CPU attempts to use the (presumably) invalid stack it would trigger a Double Fault, quickly followed by a Triple Fault and system shutdown. One other sharp corner I've run into is with VCPI clients which assume that their TSS won't be used by the CPU, so they "save" a few bytes by re-using that data area. SWAT uses TSS selectors for its IDT entries, so when SWAT gains control the CPU saves the preceding context into the caller's TSS. Also, it's a nice touch to save your CR3 into the appropriate place in the TSS, but SWAT will do that for you in case you forget. Other debuggers might not be so thoughtful. Also, if you switch LDTs from the original one, be sure to save the current one in the TSS as that field is read-only. That is, the CPU doesn't save the current LDT there when it performs a task switch, so SWAT can't "see" your LDT otherwise. If your program changes the PIC base(s), use the VCPI call (DE0B) to inform SWAT of the change. As far as symbols are concerned, use MAPSSF with a .WSG file. See the SWATSYM.DOC for more details. After SWAT pops up in PM within your program, type TS on the SWAT command line to tell SWAT to recalculate the base address of all symbols and symbols should appear. The .WSG file tells SWAT the value of various selectors, but of course it can't know at that time the base address. That's why you need to tell SWAT to recalculate. Ŀ Tips On Debugging RM Programs Debugging Real Mode programs is quite similar to debugging VCPI programs, except that you must use the debugging interface to allow SWAT to gain a foothold into your PM context. Because there is no interrupt (such as INT 67h for VCPI) when a RM programs enters PM, your program must cooperate with SWAT in order for it to be of use. Also note that you cannot trace through the instructions which setup the resources the CPU needs to run in PM. In particular, this includes LGDT, LIDT, and MOV CR0,r32 (or LMSW), as well as those instructions which setup the segment registers in PM, especially CS and SS (note that CS is setup by executing a far jump).  ================================================ FILE: swat/VCPIDBG.HTM ================================================ VCPI Debugger Extensions

Preliminary Proposal
For
Debugger Extensions
to
VCPI Specification
30 May 89
Amended 22 Aug 90
Amended  9 Aug 94

Rationale 

The premise is that there is already a resident debugger in the system which the client wishes to use.  These calls provide an interface between the client and the debugger to allow that to happen.  In order for the debugger to support this interface, it should intercept INT 67h during its initialization and troll for the following calls, ignoring most others.  The debugger may wish to troll for the "Set 8259A Interrupt Vector Mappings" call in order to properly determine where the timer and keyboard interrupts start.
 

V86 Mode Program Interface 
OVERVIEW

If your program enters PM via DPMI using a memory manager with an integrated DPMI host, skip all this as 386SWAT hooks into the host's GDT and IDT through the INTRUDE option.  Note that DPMI hosts which install as a separate device driver appear to the memory manager (and thus to 386SWAT) as a VCPI client, so the above advice to skip this document does not apply.  I haven't tried to debug a DPMI client in this context, so I'm not sure how to do it.

If your program enters PM via VCPI, use functions DEF0, DE01, DEF2, and DEF3 in that order so that 386SWAT is properly initialized in your program's GDT and IDT.

If your program enters PM from RM and uses paging, use functions DEF0, DEF4, DEF2, DEF3, and DEF9 in that order although function DEF9 can be executed anytime after function DEF0 executes successfully.

If your program enters PM from RM and does not use paging, use functions DEF0, DEF2, and DEF3 in that order.

When debugging VCPI clients, be sure to enable the VMSINT flag either by putting the keyword VMSINT into your 386SWAT profile, or by typing VMSINT ON from the 386SWAT command line.
 



INT 67h
AX = 0DEF0h      Determine Debugger Presence

INPUTS:        None.

OUTPUTS:    AH = 00h if successful
                          = 84h if VCPI not supported
                          = 8Fh if debugger support not present
                    BH = Debugger specification major version #
                    BL = ...                    minor ...


This call determines whether or not a resident debugger is present in the system.  The current specification version number is 5.00; that is, BH = 05h, BL = 00h.  These values are in binary such that if the specification version number were 10.12, this call would return BH = 0Ah, BL = 0Ch.


INT 67h
AX = 0DEF1h      Get Debugger Information

INPUTS:        None.

OUTPUTS:     AH = 00h if successful
                     EDX = Physical address of debugger information


This call returns the physical address of a certain data structure inside 386SWAT for use in conjunction with the 386SWAT Virutal Device for Windows 3.  The contents of the structure is as follows:

INFO_LEN        dw      ?       ; Byte count of structure
INFO_BASE       dd      ?       ; Physical base address of SWAT code segment
SWTINF_VER      dw      ?       ; Version # of structure
More fields are defined which are used by SWATVXD.


INT 67h
AX = 0DEF2h      Initialize Debugger Interface

INPUTS:        ES:DI ==> GDT entries for debugger support
                     If ES = 0, EDI ==> ...
                     BX = initial selector

OUTPUTS:    AH = 00h if successful
                          = 84h if VCPI not supported
                          = 8Fh if debugger support not present
                     BX:EDX = Address of protected mode entry point


This call allows the debugger to setup its own GDT entries as it pleases.  The number of entries it may use is limited to thirty (30) so the client can statically allocate space in its GDT.  The starting selector number in BX is needed so that the "Initialize Debugger IDT Entry" call knows what selectors to use when initializing an IDT entry.  Consequently, this call must precede that call in order to know the proper selector value.

If you are writing a PM program which enters PM via VCPI, your call to the VCPI Get PM Interface (DE01) must precede this call as 386SWAT needs to hook into the latter call in order to ensure that its PTEs are visible when the VCPI client is active (and thus know what its new linear address is).

The selector and offset returned identify the address of the protected mode entry point in the debugger (see below).  This entry point should be called via a USE32 far call as it might be a task gate.


INT 67h
AX = 0DEF3h      Initialize Debugger IDT Entry

INPUTS:        BX = interrupt #
                     ES:DI ==> IDT entry for interrupt BX
                     If ES = 0, EDI ==> ...

OUTPUTS:    AH = 00h if successful
                          = 83h if interrupt # not supported by the debugger
                          = 84h if VCPI not supported
                          = 8Fh if debugger support not present


This call allows the client to selectively activate the debugger's interrupt handlers.  Because some debuggers may support more interrupt handlers than others, it is recommended that the client call this function for all interrupts between 00h and 1Fh.  If the debugger doesn't support a particular interrupt number, it will return an error code which the caller can ignore.

Some interrupt numbers may be handled wholly by the debugger (not passed on to the previous handler).  Some may be chained, with the debugger handling only certain situations (as may be the case if the 8259A's interrupt numbers overlay CPU fault interrupt numbers).  For this reason, the client should initialize the IDT entry with a valid handler in case the debugger passes along the interrupt.

Because this call may be invoked multiple times on the same interrupt number, the debugger must check the existing entry to see if it is the same as the value to which it would initialize the entry.  If that's the case, the debugger should ignore the call and return a successful result code.

If you are writing a PM program which enters PM via VCPI, your call to the VCPI Get PM Interface (DE01) must precede this call as 386SWAT needs to hook into the latter call in order to ensure that its PTEs are visible when the VCPI client is active (and thus know what its new linear address is).


INT 67h
AX = 0DEF4h      Set New Debugger CR3 and Linear Address

INPUTS:       EBX = new CR3
                    EDX = new linear address or -1 if unchanged.

OUTPUTS:    AH = 00h if successful


This call is used in conjunction with functions DEF2 and DEF3 if your program enters PM without using either VCPI or DPMI.  In that case, this case must precede the calls to functions DEF2 and DEF3 and you must also call function DEF9.


INT 67h
AX = 0DEF5h      (Reserved)

INT 67h
AX = 0DEF6h      Symbol Table Management Functions

INPUTS:       BL = 00h   Append ECX names from DS:ESI
                    ECX = # names to append
                    DS:ESI ==> table of names to append (see SYMC_STR)

OUTPUTS:    AH = 00h if successful
                    AH = 88h if not
                    ECX = # symbols appended


SYMC_STR struc

SYMC_FVEC df     ?              ; Seg:Off or Sel|Off
SYMC_FLAG dw     ?              ; Flags:  see SYMFL_REC below
SYMC_GRP  dw     ?              ; Group # (arbitray value may be used
                                ; with TS command from the command
                                ; line to group symbols)
SYMC_NAMLEN db   ?              ; Length byte
         db      ? dup (?)      ; ASCII name (no terminating zero)

SYMC_STR ends

SYMFL_REC record $SYMFL_VM:1,$SYMFL_TYP:5,$SYMFL_RSV:10

@SYMFL_VM equ    mask $SYMFL_VM ; 1 = symbol is for VM
                                ; 0 = ...           PM
                                ; The above flag is meaningful for _DAT and _LN
                                ; types only.
@SYMFL_TYP equ   mask $SYMFL_TYP ; Data types:  see @SYMTYP_xxx below
@SYMTYP_DAT equ  0              ; Code or data
@SYMTYP_LN  equ  1              ; Line number record constructed by MAPSSF
@SYMTYP_ABS equ  2              ; ABS record
@SYMTYP_SWT equ  3              ; Symbol is for SWAT internal use


INPUTS:       BL = 01h   Search for name DS:ESI
                    DS:ESI ==> name to search for (see SYMC_STR)

OUTPUTS:    AH = 00h if successful
                    AH = A0h if not found

INPUTS:       BL = 02h   Translate old symbol to new
                    DS:ESI ==> SYMTRAN_STR (see below)

OUTPUTS:    AH = 00h if successful


Use this call to translate a symbol's segment/selector and group to a new segment/selector and base.

SYMTRAN_STR struc

SYMTRAN_OSEL dw  ?              ; Old segment/selector
SYMTRAN_OGRP dw  ?              ; Old group #
SYMTRAN_NFLAG dw ?              ; New flags
SYMTRAN_NSEL dw  ?              ; New segment/selector
SYMTRAN_NBASE dd ?              ; New base (to be added to all offsets)
SYMTRAN_FLAGS dw ?              ; Flags for match significance

SYMTRAN_STR ends

; Flags used in SYMTRAN_FLAGS to indicate which elements in SYMTRAN_STR
; are to be ignored.
; $SYMFL_ADDVMSEG indicates that the new segment value is to be added
; to all V86 mode segments.
SYMTFL_REC record $SYMTFL_IGOSEL:1,$SYMTFL_IGOGRP:1,$SYMTFL_IGNFLAG:1,\
        $SYMTFL_IGNSEL:1,$SYMTFL_ADDVMSEG:1,$SYMTFL_RSVD:11


INPUTS:        BL = 03h   Flush the symbol table

OUTPUTS:    AH = 00h if successful

INPUTS:        BL = 04h   Append without replacing existing symbols
                                        (allow duplicates of existing symbols)
                                        (same as BL=00h)

OUTPUTS:    AH = 00h if successful

INPUTS:       BL = 05h   Execute ASCIIZ command in 386SWAT
                    DS:ESI ==> ASCIIZ string containing a command

OUTPUTS:    AH = 00h if successful

Use this call to execute a command on the 386SWAT command line.  This function is used by the SWATCMD.EXE device driver.

INPUTS:       BL = 06h   Copy ASCIIZ string to error log
                    DS:ESI ==> ASCIIZ string

OUTPUTS:    AH = 00h if successful


INT 67h
AX = 0DEF7h      (Reserved)

INT 67h
AX = 0DEF8h      (Reserved)

INT 67h
AX = 0DEF9h      Fill in 386SWAT's PTEs

INPUTS:       ECX = maximum # PTEs ES:DI can hold
                    ES:DI ==> save area for PTEs
                    If ES = 0, EDI ==> ...

OUTPUTS:    AH = 00h if successful
                    AH = 8Bh if 386SWAT needs more PTEs than specified
                    ECX = # additional PTEs 386SWAT needs


Use this call in conjunction with function DEF4 if your program enters PM without using VCPI or DPMI so that 386SWAT's PTEs are visible in your program's address space.

Protected Mode Program Interface

For the moment, there are no defined functions.  However, when there are, we will require that AH = 0DEh and that the subfunction code be in AL.
 


Tips On Debugging DPMI Programs

If you are using an integrated DPMI host such as 386MAX, no special action is needed on your part to debug a DPMI program.  386SWAT installs itself as a PL0 extension to the memory manager and thus also to the DPMI host.  Place breakpoints in your code as needed as well as step right over the far call to the DPMI host which switches from VM to PM.

If you using a non-integrated DPMI host such as QDPMI.SYS which is distributed with QEMM, then essentially you are debugging a VCPI client which provides DPMI services to its clients.  See the next section for details on debugging VCPI programs.
 


Tips On Debugging VCPI Programs

Assuming SWAT has successfully intruded into the MM's (memory manager's) PM context, it is on the same level as MM -- that is, you should think of it as a PL0 extension of the VCPI host.  This means that you need to tell SWAT to intrude into the VCPI client's context.

Some VCPI clients are easy to break into, some are quite hostile (not maliciously, it's just that they don't leave any wiggle room). There's no magic to this.  Fundamentally, SWAT needs room in the GDT for its selectors.  See the above description on how to get your program to cooperate with SWAT, but if you want to get up and running quickly, you might first try these steps:

  • Allocate about 30 selectors at the end of the GDT,
  • Initialize the selectors to all zero,
  • Plant an INT 01h/03h in the PM portion of your code or whatever you prefer,
  • Type VMSINT ON on the SWAT command line,
  • Start your program.
The only tricky part is to ensure that any breakpoints you set to which SWAT would respond occur after the stack in the VCPI client has been setup (and preferably also DS, ES, FS, and GS).  Typically, this means that you can debug through every single instruction except for the handful which occur during the handoff from the VCPI host's PM context to the VCPI client's PM context.  The reason for this is that the VCPI PM handoff depends upon descriptor caching.  In particular, the VCPI spec has the client specifying the state of all EGP registers, but only the CS segment registers.  Thus the VCPI client starts off execution with its own environment (GDT, LDT, IDT, TR, and CR3) in effect, but on the VCPI host's stack.  The value of that stack
selector quite likely is invalid in the client's GDT/LDT, so the VCPI client must switch to its own stack ASAP.  Of course, if an interrupt/exception occurs before then, when the CPU attempts to use the (presumably) invalid stack it would trigger a Double Fault, quickly followed by a Triple Fault and system shutdown.

One other sharp corner I've run into is with VCPI clients which assume that their TSS won't be used by the CPU, so they "save" a few bytes by re-using that data area.  SWAT uses TSS selectors for its IDT entries, so when SWAT gains control the CPU saves the preceding context into the caller's TSS.  Also, it's a nice touch to save your CR3 into the appropriate place in the TSS, but SWAT will do that for you in case you forget.  Other debuggers might not be so thoughtful.

Also, if you switch LDTs from the original one, be sure to save the current one in the TSS as that field is read-only to the CPU.  That is, the CPU doesn't save the current LDT there when it performs a task switch, so SWAT can't "see" your LDT otherwise.

As far as symbols are concerned, use MAPSSF with a .WSG file.  See the SWATSYM.DOC for more details.  After SWAT pops up in PM within your program, type TS on the SWAT command line to tell SWAT to recalculate the base address of all symbols and symbols should appear.  The .WSG file tells SWAT the value of various selectors, but of course it can't know at that time the base address.  That's why you need to tell SWAT to recalculate.


Tips On Debugging RM Programs

Debugging Real Mode programs is quite similar to debugging VCPI programs, except that you must use the debugging interface to allow SWAT to gain a foothold into your PM context.  Because there is no interrupt (such as INT 67h for VCPI) when a RM programs enters PM, your program must cooperate with SWAT in order for it to be of use.

Also note that you cannot trace through the instructions which setup the resources the CPU needs to run in PM.  In particular, this includes LGDT, LIDT, and MOV CR0,r32 (or LMSW), as well as those instructions which setup the segment registers in PM, especially CS and SS (note that CS is setup by executing a far jump).  ================================================ FILE: swat/WHATSNEW ================================================ Version 6.04 * Implement UNREAL as keyword in the 386SWAT.PRO file. Version 6.03 * Support for display of MMX & SSE instructions * Display MMX and SSE registers via Alt-F11. * Support for display of FCMOVcc, FCOMI, FUCOMI, FCOMIP, FUCOMIP instructions * Implement FSONLY keyword to allow SWAT to install in Windows w/o DVGA or MDA because you promise to bring up SWAT in a Full Screen DOS window only. * Implement X15 keyword to tell SWAT to pass through INT 15h memory size calls (thus not protecting its own allocated memory). This is a debugging keyword only, not for general use. * Fix bug where all Family 6 CPUs were thought to support the Last Branch/Exception feature, whereas, in fact, only Intel CPUs do. This would cause SWAT to reboot during initialization on certain Cyrix CPUs. * Display + or - sign after jcc instruction if a Branch Hint prefix (2Eh or 3Eh) is present. Version 6.02 * Support MDA hidden by PCI VGA or PCI AGP controller, and secondary PCI VGA adapter. See SWATIDSP.HTM for more details. * Support 4MB pages in PTE display as well as the PTE and SPTE commands. * Fix bug when using BC on current instruction and G to another instruction. * Fix bug in display of MOV r32,[EBP*n+disp32]. * Display appropriate comments on PCI calls (INT 1Ah). * Emulate references to the debug registers (DRn) if the GD bit is set in DR7. * Implement search for not a value, e.g., S addr addr ~val. * Implement DLG16 & DLG32 commands to display dialogs when in Windows. * Extend monitor expressions to BD and BC commands. * Implement BP command to break on page references. Version 6.01 * Implement UNREAL command to allow debugging of Unreal Mode. This mode is a variant of Real Mode in which any segment register can access all of the 4GB address space. That is, instead of the normal 64KB length of a segment, the length is 4GB. This command can enable all or just some of the segment registers for Unreal Mode. See SWATCMD.HTM for more details. Version 6.00.002 * Implement s-F10 to save the current screen into the last screen buffers. * Fix various bugs in 386SWAT's RM Windows support. * Implement QS command to display nearest symbol at or before a given address. * Implement DTE command to display Descriptor Table Entry on the command line. * Implement MDB command to display a Windows Module Database. * Implement TDB command to display a Windows Task Database. * Implement .MDB to return Sel|0 of current MDB. * Implement .TDB to return Sel|0 of current TDB. * Display PDE and PTE bits with PTE command. Version 6.00.001 * Code reorganization to accommodate logged in versions 5.10.071-9 * Documentation moved over to HTML format. Version 6.00.000 * Implement support for Windows kernel debugging. This major upgrade is described (to some degree) in WINKDBG.DOC; also see 386SWAT.DOC and SWATVXD.DOC. Version 5.10.079 * Add More Service Routine Text Add service routine text displays for Win95 VMM routines. This text is displayed when decoding INT 20h calls. Version 5.10.078 * Fix .VMSTK and .VMRET Commands For some reason, the implementations of the .VMSTK and .VMRET commands didn't work, so now they do. Moreover, .VMSTK is now called .VMCRS (for Client Register Struc). Version 5.10.077 * Implement Time Stamp Counter Display On CPUs which support it (TSC bit set in CR4), display the # clocks executed since the last time 386SWAT was entered. There is a certain amount of overhead in each entry to 386SWAT, so the numbers displayed will never be at the level of single instruction clock counts, but it is a good measure of time over a longer set of instructions. Version 5.10.076 * Handle New Windows Keyboard Keys The Microsoft Natural keyboard contains three new keys: * Left Windows key * Right Windows key * Application key These keys have new scan codes which our keyboard handler now recognizes, although we don't do much with them as yet. The left and right Windows keys are meant to be modifiers just as Shift, Ctl-, and Alt-keys are modifiers. The Application key is meant to be an actual keystroke, so I've assigned arbitrary key codes to it in its Unshifted, Shift-, Ctl-, and Alt-states. For the moment, until someone can think of something better, the Application key invokes the Help menu. Version 5.10.075 * Miscellaneous internal changes Version 5.10.074 * Use Ctrl-Shift-PrtSc To Print Instruction Window Only When printing multiple instruction screens, repeating the register display and other information on the second and subsequent screens is unnecessary. To this end, the key combination Ctrl-Shift-PrtSc prints the instruction portion of the display only, assuming the instruction window is displayed (if not, the entire screen is printed as usual). Version 5.10.073 * Implement Saved Register Clear Command In case you do not need to restore a saved register set, the saved state can be cleared with the RC command. * In the operand analysis display for an IRETd with NT=1, the back link TSS selector is omitted as there's no room for it and all of the other information being displayed. Version 5.10.072 * Implement Command Recall Commands entered on the command line are saved in a ring buffer whose length can be changed from the default of 1024 via the profile keyword CMDHIST=nnn. Previous commands can be retrieved via the keystrokes Alt-< (previous command) and Alt-> (next command). Pressing either of these keys repeatedly scrolls through the buffer in the chosen direction. The keystroke Alt-? displays a history of (up to 25) commands from which a command can be chosen by scrolling up or down through the list, or by typing the letter next to the command. A command may be deleted from this list via the Del key. * A bug was fixed when running under Windows where a jump was taken with the wrong sense (JZ vs. JNZ) if Win386 services are available. * A new help screen to describe the various searching options is defined. Version 5.10.071 * Fix Bug When Searching For Bytes In an earlier TWT, when handling Page Faults, the ZF flag was cleared without realizing that subsequent code depended upon it being set. The effect was that searches for bytes were never found. This change fixes that. Version 5.10.070 * Implement INSERT Command To debug Windows at the lowest level, we need to be able to insert ourselves into Windows startup shortly after it enters PM. To this end, the INSERT command is available. It is used from the 386SWAT command line at the point just before Windows enters PM. Version 5.10.069 * Allow Fill Command On Physical Memory The Fill (F) command used to change data in memory now allows an optional trailing P also optionally followed by a CR3, just as the Unassemble and other commands allow. Version 5.10.068 * Fix Bug In Implicit Stack References When displaying the data (if any) pointed to by the current instruction, if the instruction used an implicit stack reference (such as the PUSH instruction) we sometimes would use the wrong base register (ESP vs. SP). This TWT fixes that bug. Version 5.10.067 * AutoFault for GP Faults The Autofault facility has been extended to GP Faults. This means that an attempt is made to interpret each GP Fault intercepted by 386SWAT in a short sentence. Type Shift-F4 to see the last Autofault error message. Because GP Faults are many and varied, some cases will be missed (marked as unknown) or mistaken. Please notify the author as you encounter such cases with the exact circumstances of the GP Fault so they may be corrected. Version 5.10.066 * When Running Under Windows, Map In/Out VM's First Megabyte Previously, when our local keyboard handler was active, we avoided checking and setting the keyboard values in the BIOS data area if Windows was active because we couldn't be sure that that memory region was mapped in. Now that I have discovered Win386 (INT 22h) services, we can map in/out that region around references to it. Version 5.10.065 * Set the GD Bit In DR7 Because some programs get a kick out of resetting the debug registers which we've carefully setup, this change has 386SWAT automatically set the Global Debug (GD) bit in DR7 on startup so that we can stop such programs before they can do any harm. Perhaps it doesn't surprise you that Windows is the chief reason for this feature. Version 5.10.064 * Display Real Mode Interrupt Vector Table As it's a very common data structure to view, the keystroke Shift-F5 now displays the RM IVT. Version 5.10.063 * Filter Leading Text From Symbols Some symbols, especially from Windows programs written in C, are prefaced with text such as "__imp__", "_", and the like which adds the symbol's length but not understanding. This feature allows you to specify in the 386SWAT profile leading text which is to be stripped from each symbol. SYMFILTER = text1 [text2 [...]] The default settings are SYMFILTER=__imp__ _ Up to 128 characters can be specified in this way. Version 5.10.062 * Fix Bug When Displaying Long Symbol Names When we display a symbol names of 50 chars or greater at the top of a data screen, we're off by one in our calculations which can cause the name to fold to the next line. Version 5.10.061 * Fix Bug In The Stack Width Change Calculation Previously, the calculation of when to change stack width (words or dwords) occurred only when the code selector changed. In fact, it should be checked when the stack selector changes (duh!). Version 5.10.060 * Fix Bug With Mis-aligned Stack In GP Fault Handler If the user hooks GP Faults, the handler in LCL_INT0D uses a stack structure which is missing one word in the middle. It's amazing it has worked at all so far. Version 5.10.059 * Implement Support For P6 Features Two P6 features are supported by this TWT. 1. The Branch Trace Facility (BTF) can be turned on and off via the command line BTF ON/OFF. 2. The Last Branch/Exeception From/To registers can be displayed at all times in the lower right corner of the screen. This feature can be turned on and off via the command line LBR ON/OFF. * Skip Over Read/Write From/To Debug Registers If GD Bit Is Set When the GD bit in DR7 is set, any read from or write to a debug register triggers a Debug Fault (and the CPU clears the GD bit from DR7 so the Debug Fault handler can use those registers). Some environments (Microsoft Windows comes to mind) clear the debug registers upon entry (and at other times) thus making it difficult debug in that context. With this change, setting the GD bit traps reads and writes of those registers and handles them transparently. A read from a debug register returns the actual value. A write to a debug register is ignored. The GD bit can be set from the 386SWAT command line via R DR7.GD=1 If you desire this behavior to be the default, use SWATCMD with the above argument. Version 5.10.058 * Add .VM addresses for Windows debugging Especially when debugging calls from a Windows app down to a VM interrupt handler, it is sometimes useful to know where we'll come back to in Windows on the other side of the ARPL wall. .VMRET will often work if the call was made via DPMI SIMVMI (function 0300h) or an INT instruction emulated by the DPMI host (Windows). * Add Go Monitor command and .CSIP to 386SWAT The GM (go monitor) command takes an expression which will be evaluated as the CPU single-steps (equivalent to Pad-plus or F11). No display will occur until 1) the monitor expression evaluates TRUE or 2) 386SWAT is invoked by some other means (GP fault, NMI, Ctrl- Alt-Pad5, etc.) Boolean expressions may be constructed using the dyadic operators &&, ||, <, <=, ==, >=, and >. Operator precedence is the same as the C language. For example: GM ah executes until AH is non-zero. GM [.csip == 21cd && ah!=9 executes until the current instruction is INT 21 and AH is any value other than 9 (DOS display string). GM cx == 0 executes until CX is 0. GM executes until the last expression specified with GM is TRUE. There are some limitations: 1. Currently, GM does not single-step across mode switches via INT (but will handle any mode switch handled by Pad Plus). 2. It is slow as molasses. 3. With the addition of boolean operators like && and || precedence becomes more of something one would reasonably expect. 4. GM will not work in TSS mode currently (non-critical, failure mode is the expression doesn't trigger). Version 5.10.057 * Fix Bug When Testing For Extended Memory Due to an oversight, when I put in the code to determine the amount of extended memory using the INT 15h/0E801h call, I put it in after the INT 15h/0DA88h, instead of before. Because of a bug in Phoenix 4.04 BIOSes, which crash on the 0DA88h call, the order is important. Also, when setting up the IDT entry for VCPI debugging using TSSes, we used to set the offset to -1 (because the IDT selector is a TSS and the offset isn't used). For convenience, I'm now setting the low-order byte of the offset to the interrupt #. That way, when looking at the IDT in memory (not via F4) it's easy to tell which interrupt it covers. Version 5.10.056 * Workaround Feature In Win95 Because of a quirk in Win95 (what, only one!), when we blast in the PTEs for 386SWAT to address the monochrome and color video buffers from local addresses, we need to preserve the AVL bits and set the accessed bit so this PTE won't be thought of as one available for allocation. Version 5.10.055 * Handle Large Size 386SWAT With VCPI Clients If the resident portion of 386SWAT becomes too large (perhaps a large SYMSIZE or SAVESCREEN), then we might not be able to debug VCPI clients because our footprint exceeds the 4MB limit (one page directory) for VCPI. If this happens, we should at least warn the user in case s/he intends to debug VCPI clients. * Fix Bug With Unused GDT Entry When 386SWAT loads via the 386MAX profile, it is passed its linear address when it is a VCPI client in the third of the three GDT entries allocated for load modules. This is done because 386SWAT's PTEs are part of 386MAX's and get relocated by 386MAX when a VCPI client loads. When 386SWAT intrudes into a Memory Manager, we don't use the third GDT entry in the same way, and in some cases we might not even allocate a third GDT entry if we have found existing GDT entries for an all memory selector and one which maps CR3. In this case (I encountered it when intruding into QEMM), we can mistakenly reference the third GDT entry. This TWT fixes that. * Check For Additional Autofault Errors For TSS Faults If a TSS fault occurs, there are some additional reasons for it which we now test for and report on, such as invalid selectors in the back link TSS when a return from a nested TSS occurs. At the same time, I included some additional fault error messages which occur when we're using TSSs ourselves (typically when we're debugging VCPI clients) which we we're checking for before. This also involves moving that error message text from the data to the code segment to match where the Autofault code expects it. Also, I changed references to $PTE_0 to $PTE_G as that's its new definition, and checked for Page Fault problems related to that bit if PTE Global Extensions are enabled in CR4. Version 5.10.054 * Handle Multiple GDTs When VCPI Debugging While tracking down a bug in the CDROM game The 11th Hour, I found that 386SWAT needed to handle intruding into multiple GDTs as this game appear to use up to three different ones, alternating between two quite frequently. We now support up to eight alternating GDTs. At the same time, I fixed a bug where 386SWAT was not correctly recognizing whether or not it had already intruded into a GDT. This had the effect of filling up the GDT with 386SWAT's TSS selectors which crashed the system in quick order. Finally, while running VCPITEST to see if I had broken anything in the process, I decided to remove the check for VMSINT=ON from the VCPI call DE01 (Get PM Interface) in order to allow Intrude 386SWAT to work with a cooperating VCPI client without having to set that variable. This means that Intrude 386SWAT will insert its PTEs into every such call, but that should be harmless. The VMSINT=ON setting still controls whether or not 386SWAT intrudes into the VCPI call DE0C (Switch From VM To PM). Version 5.10.053 * Enable Debugging Extensions (If Supported) At Virtual Init Time The Pentium CPU's debugging extensions are supported in 386SWAT via the BD command on an I/O port at which time the $DE bit is set in CR4. This change enables them at an earlier time so any other program (such as 386MAX) can modify its behavior depending upon whether or not the $DE bit is set. Version 5.10.052 * Make Device Driver 386SWAT Sensitive to Another Extended Memory Function The recent change to 386MAX to support the 0E801h Extended Memory function call needs to be copied to device-loading 386SWAT not only so it can detect how much extended memory is in the system, but also so it can lie to any subsequent program requesting the extended memory size through that interface. Version 5.10.051 * Implement Show PTE Command Strolling through a large set of Page Tables such as under Windows can be tiresome, hence there's a new command. The SPTE command works exactly likely the PTE command (displaying the Linear address/PDE/PTE on the command line) as well as displaying the corresponding PTE (as if you had pressed F5 and scrolled down to the appropriate entry). At the same time, I allowed Ctrl-Up and -Down to scroll through the PDEs/PTEs one entry at a time (Up and Down scroll through one line at a time). Version 5.10.050 * Fix Bug When Using TSS For Faults A previous TWT changed a local routine to be more self-sufficient by setting DS within the routine instead of relying upon the caller to set this register. Alas, that was a mistake as in some cases we rely upon the Invisible Descriptor Cache, particularly when we're accessing selector values in the caller's LDT. This TWT fixes that to use two routines, one which assumes the global DS has been set, one which does not. At the same time, I fixed a problem with device-loading 386SWAT where software INTs 01h, 02h, 03h, and 68h are not being enabled if VME is. Version 5.10.049 * Fix Bug With DEBUG=PMI And Device-Loading 386SWAT If we're loading as Device 386SWAT at startup, INIT_PROT is called at the point where 386SWAT is a temporary VCPI client of the MM. Thus the active IDT is that of the VCPI client and INIT_PROT is setting up the MM's IDT where the VCPI client has calculated the IDT's linear address in the VCPI client's linear address space. All this is background to say that we can't signal an INT 01h if DEBUG=PMI is specified because the active IDT (that of the VCPI client) does not have its IDT entries setup for debugging unless there's a preceding 386SWAT in the picture. This changes enforces that condition. Version 5.10.048 * Call REST_PROT/INIT_PROT On Windows Entry/Exit With Device-Loading 386SWAT When 386SWAT is loaded as a device driver (whether it was intruding into an existing memory manager or loading as VCPI SWAT), previously it wasn't handling the transitions into and out of Windows. When Windows starts up, 386SWAT needs to disable itself (by calling its REST_PROT entry point) so that it is in the proper state when the 386SWAT VxD calls 386SWAT's INIT_PROT entry point after Windows loads. Correspondingly, when Windows terminates, the VxD calls 386SWAT at its REST_PROT and 386SWAT needs to call its INIT_PROT entry point to re-enable it. When 386SWAT is loaded from within 386MAX, MAX handles calling the proper REST_PROT/INIT_PROT entry points. When 386SWAT is loaded as a device driver, these calls were not made. Now they are. Version 5.10.047 * Swap Out Local IDT Entries Around TOGINT Call When 386SWAT is active, it hooks various interrupts for its own use such as the timer, keyboard, cascade, and mouse (the latter two in case there's a PS/2-style mouse which goes through the keyboard controller). When we toggle an interrupt via command line (TOGINT xx xx ...), or keystroke (Alt-F1, etc.), we need to swap out our local entries around the toggle so that we save the new entry in the proper (global) location. In particular, this affects TOGINT 0A which is hooked locally. Version 5.10.045 & 5.10.046 * Allow Search Command Of PTEs When tracking down a bug in Win95, I found it useful to extend the search command to search through the PTEs for a specific value. The new syntax is S addr addr # PTE S addr L expr # PTE where PTE can be any expression. At the same time, I fixed a bug where a Page Fault during the display of the searched for data caused a crash. * Miscellaneous Changes 1. Display appropriate comment on DPMI interrupt lines. This also involves defining a new segment to hold the DPMI function values (as words). 2. For display of PTEs, note the PDE which contains the top line of the display as well as the range of linear addresses covered by the top line. 3. For display of PDEs, note the range of linear addresses covered by the top line. 4. Display display of PTEs and PDEs, handle not present entries by displaying "????????". 5. Change the initial mask for memory display to allow 32-bit values. 6. Change the number of entries displayed in dword format to eight by squeezing the entries together. Note that the previous width can be obtained via the dd/4 command. 7. Save the previous d?/?? value for later use separately for each width. 8. If the selector passed to any routine which calls GETARWBASE is not present, return with CF=1 to indicate an error. This change is needed by WINSWAT to avoid displaying an incorrect label for not present selectors. As it turns out, without this change and with the new KRNL386, USER, GDI symbol display in WINSWAT the label displayed for not present selectors is that of the Windows routine BOZOSLIVEHERE. Version 5.10.044 * Prepare for Winswat A feature needed by WINSWAT is the ability to set a temporary breakpoint from a Windows program. This requires that we fill in the rest of the fields where else this feature is used. A feature needed by WINSWAT is the ability to refresh debug hooks when a selector's linear address changes. Version 5.10.043 * Make Device Driver 386SWAT Sensitive to PCI Extended Memory Function The recent change to 386MAX to support the PCI Extended Memory function call needs to be copied to device-loading 386SWAT not only so it can detect how much extended memory is in the system, but also so it can lie to any subsequent program requesting the extended memory size through that interface. Version 5.10.042 * Implement Data Width Switch When displaying data via the Dx command, a new switch allows you to specify the number of elements to be displayed per line. For example, to display five (instead of the usual eight) words per line, use DW/5. This feature is a stopgap until I implement a more general data record display as in the Periscope debugger. Version 5.10.041 * Use Monochrome Adapter If Present Rather than switch to the mono adapter every time I startup the system, I thought it easier to implement a keyword to do the same. With this keyword (MONO) present, if a monochrome adapter is present in the system, it becomes the initial display screen for 386SWAT. The monochrome adapter has always been supported by 386SWAT -- this just makes it the initial display screen as opposed to the color monitor. Version 5.10.040 * Allow TSS Debugging In VM If a program enters PM from RM and asks 386SWAT to enter its GDT and IDT, as usual we setup TSS selectors for the interrupts we manage. If this program subsequently enters VM, we need to handle the interrupt via a TSS from VM differently as the stack and register interpretation (segments vs. selectors) are different. Previously, our TSS interrupt code expected to be entered from PM only, so a change is needed. Also, when debugging such a RM program where the user sets a breakpoint shortly after entering PM (via setting the PE bit in CR0) but before setting TR, I found that 386SWAT failed miserably because it was depending upon there being a valid back link in the local TSS. Thus, more changes were needed to handle an invalid back link. In conjunction with this change, the register set command (R) is enhanced to allow TR and LDTR (a.k.a. LDT) to be read and set, so the user can setup a valid back link should the need arise. Also, when 386SWAT is installed as a RM debugger, avoid setting TR to our local TSS as that changes it from an invalid value to a valid value. Unfortunately, this doesn't prevent another program from doing the same, but at least we're not the culprit. BTW, unlike the LDTR, there seems to be no way to clear (and thus invalidate) the Task Register once it's set. Setting TR to zero (which is after all its initial state), causes a GP Fault even though the current value of TR may be already be invalid. Thus, once TR is set to an invalid (and possibly non-zero) value, it stays that way until set to a valid value. * Clear NT bit in EPM.ASM After switching into PM, the code in EPM.ASM should clear the NT bit in case a subsequent IRET/D occurs (as it does) in order to avoid a TSS Fault. Thanks to John Fine for pointing this out. Version 5.10.039 * Support Spain 172 Keyboard Layout Thanks to Roberto Deza Asensio, 386SWAT now supports this keyboard layout. Version 5.10.038 * Include Function-Specific Text in INT 21h Comments Because they occur so often in code, the display of INT 21h instructions which are the current instruction now includes function-specific text (e.g., "Write File (handle)"). Version 5.10.037 * Calculate SYMSIZE based upon the size of the loaded symbol table Previously, I had attempted to calculate SYMSIZE based upon the size of the incoming .SSF file and it didn't work. This time it does. The effect is that you don't need to use SYMSIZE with a LOADSYM, thus reducing wasted space in 386SWAT's symbol table as well as perhaps avoiding a mistake when calculating SYMSIZE and finding it is too small. * Fix Bug In MAPSSF Due to a bug in my linker, certain far calls weren't fixed up properly. Version 5.10.036 * Support International Keyboards One of 386SWAT's design goals is to be as unassuming about the system as possible, intruding into the system at an absolute minimum. As part of achieving this goal, 386SWAT has its own keyboard handler so it can debug keyboard actions within the BIOS as well as not depend upon the system's keyboard routines or data being intact and functional. One consequence of this is that 386SWAT needs to be changed in order to support international keyboards which is what this TWT accomplishes. To this end, the keyword KEYB= is recognized in the 386SWAT profile. At the start, the only keyboard supported is the German one -- its keyboard layout is 129, so the KEYB= value is GR129. Others can be supported as the need arises. See file 386SWAT.DOC under the KEYB= entry for the list of supported keyboards. Thanks to Armin Kunaschik, 386SWAT now supports this keyboard layout. Version 5.10.035 * Include INT 03h and INTO in GPSKIP=INT Processing When I put in GPSKIP=INT, I checked for the INT xxh opcode (0CDh), but forgot about INT 03h (0CCh) and INTO (0CEh). These cases are now covered. Version 5.10.034 * Implement Return Address and Goto Return Address A common address to jump to is the (near or far) return address of a subroutine. This is made easier by using shortened forms of the commands one might use to extract these addresses. For details, see the "Common Memory References" section in 386SWAT.DOC. Version 5.10.033 * Make NORMLIDT The Default I've encountered enough circumstances debugging RM where RM LIDT redirection has gotten in the way, that I've decided that it's best to make NORMLIDT the default and use the (new) keyword RMLIDT to enable it when necessary. Version 5.10.032 * Parse I/O Command line Instructions as LVALs For greater generality, the command line I/O instructions now allow an LVAL instead of just an atom. Also, the IMR command line action displays the original values not the ones set by 386SWAT. Version 5.10.031 * Validate Back Link In Operand Analysis Display for IRET/D On occasion, I've had the system go poof on an IRET/D when the NT bit was set (and I didn't notice that) and the back link TSS was invalid for some reason (either bad TSS selector, or something was wrong with the TSS, such as the CR3 value was invalid). This TWT checks for that condition and reports it as part of the operand analysis display for the IRET/D instructions. Version 5.10.030 * Ensure Default Options Set If No Profile If the user omits a profile on the 386SWAT device line, we skip out before setting default options. Now we don't. Version 5.10.029 * Handle Invalid Symbol Selectors If we upload symbols with an invalid selector (say, the *.WSG file is for another context -- DPMI vs. VCPI vs. RM), the call to GETBASE returns an error along with EAX=-1. If this value is used for the linear address, the symbol is marked as invalid and the address hash code gets confused. This change checks for the above eventuality and sets the pseudo-linear address to zero to avoid this problem. BTW, the symptom is that (say) SWATRUN hangs when uploading symbols if it has two or more symbols with the same (invalid) linear address, e.g. 300|0. * At the same time, I upgraded the grammar for LS and PS to accept lvals instead of just atoms, thus allowing a wider variety of ways of specifying the arguments to these commands. Others in this same vein to follow. Version 5.10.028 * Make INTRUDE The Default Option Now that INTRUDE is reasonably well debugged, I'm making it the default option so users don't need to remember to use it (which has happened several times). This will reduce the number of tech support questions I get from users of 386SWAT on the Internet. In case the user needs to use the VCPI client version of 386SWAT, the disabling option VCPISWAT is defined. Version 5.10.027 * Fix Bug When Running in RM An earlier TWT introduced a bug (for RM SWAT only) which set the B-bit in the stack selector. The problem is that I forgot to reset that bit when returning to RM. The solution is to define a new selector which has the same characteristics as DTE_SS, except with the B-bit is clear. Before returning to RM, we switch to this new selector so as to return to an environment which is compatible with RM. Version 5.10.026 * Handle SIGINT 1/3 While debugging an incompatibilty with ViruSafe, I needed a minor enhancement to SIGINT to overcome their attempts to fool a RM debugger. They used many tricks including self-modifying code, as well as installing their own INT 01h/03h handlers. At one point their code signals INT 01h which 386SWAT intercepts, of course. I needed to signal this interrupt to them, but SIGINT 1 invoked it as a PM interrupt, which proceeded to crash the system. The solution was to signal INT 01h/03h as a VM interrupt, as well as ensure that TF is set in the return flags if it's INT 01h from a single-step (as opposed to a software interrupt INT 01h). * At the same time, I needed to save the incoming value of DR6 which triggered another change (and bug fix). The bug fixed is an incorrect data value width in a struc missed when I changed the code segment from USE16 to USE32. * A related change cleaned up (and documented) the tests which handle the case where 386SWAT is entered other than through a debug exception, but with the GD bit set. Version 5.10.025 * Display MAC Entries After many years of wading through MAC entries, I decided to implement a separate display screen for them (actually, Win95 pushed me over the edge -- this is a variant of "The devil made me do it"). The keyboard combination of Ctl-M brings up this screen. * There's also a separate command MACBASE which allows you to set the base address of the MAC chain in case it's different from .DMAC. This is handy when displaying the DOS subsegment chain. Version 5.10.024 * Fix Bug In PATH= Profile Routine When converting over to USE32 data, I missed a place where I should have cleared the high-order word of a 32-bit register. Also, in the process of debugging this problem, I put in several more Shift debugging messages. Version 5.10.023 * Fix Bug With VCPI Get Protected Mode Interface Calls In order for us to provide debugging services to VCPI clients, we need to insert our PTEs into the VCPI client's address space. There are several contexts in which this might occur: 1. 386SWAT is loaded via LOAD= with 386MAX: our PTEs are automatically copied to the VCPI client's address space as part of 386MAX's response to the Get Protected Mode Interface (GPMI -- DE01h) call. 2. 386SWAT is loaded as a VCPI client to a memory manager: previously we didn't handle this case. Now we use the newly defined RMDEV_GPMITAIL label in low DOS memory which this TWT defines an return point in order to catch the tail of the GPMI call. At this point, we switch back to our code in extended memory, and copy our PTEs to the end of the GPMI caller's PTE buffer. 3. 386SWAT intruded into a MM (possibly 386MAX): previously we placed a PM return address on the stack and passed control on to the MM. This doesn't work with all MMs as some check the VM bit in the flags when interpreting the segment registers saved on the stack. Now we use the newly defined DEV_GPMITAIL label which this TWT defines as a return point in order to catch the tail of the GPMI call. At this point, we switch back to our code in extended memory, and copy our PTEs to the end of the GPMI caller's PTE buffer. Version 5.10.022 * Avoid Page Fault on LIN2PPTE Accesses The LIN2PPTE subroutine translates a linear address to a pointer to the corresponding PTE according to a specific CR3. Sometimes we need to read more than one PTE from the Page Directory which doesn't always work (because the subroutine doesn't know how many PTEs to map in the case we're not mapping relative to the current CR3). A solution to this is to tell the subroutine how many PTEs are to be mapped in. Version 5.10.021 * Compatibility With PMODE There is a popular shareware DOS extender available on the Internet called PMODE which is used to create PM programs. When it is run as a VCPI client, it allocates selectors from the top down in the GDT -- the same as 386SWAT does. PMODE uses the AVL bit in the DTE to mark a selector as in use, so this change has us set that bit in the selectors we allocate so PMODE doesn't write on top of our selectors. Version 5.10.020 * Fix Bug When Swapping INTs When we swap IDT entries (say when displaying the IDT via F4) so we see or act upon the global IDT entries, we don't swap INTs 74h and 76h. Now we do. Version 5.10.019 * Use Same DPL When Hooking Interrupts Some memory managers (pssst, it's EMM386) set the DPL of various entries in the IDT to zero expecting the CPU to signal a GP Fault if the corresponding software interrupt occurs. When we intrude into their PL0 context, previously we were setting the DPL to three because we didn't expect to encounter a MM which had a fetish with GP Faults. Now we retain the same DPL as the original IDT entry except for INTs 01h and 03h. They are handled differently so we can issue the corresponding software interrupts and gain control immediately instead of having to hook the GP Fault handler and pick them off there. Version 5.10.018 * Fix Disappearing Cursor Bug For years we've put up with this bug. Now it's fixed. The problem occurs in any of three contexts: * when reviewing last screens (Alt-F10), * when switching between color and mono adapters (Alt-F7), or * when swapping screens (say, when exiting 386SWAT). The problem occurs because not all programs maintain a consistent set of data values in the BIOS data area on which we rely (e.g., the dependence between the cursor type and the cursor emulation bit). The fix is to read the cursor start and end line values upon entry and restore those values in the above circumstances. A new routine, GET6845 is defined for the read starting value part. I seem to recall that the original definition of the 6845 registers was that they were write-only, but apparently they are now readable as well. At the same time, while testing the different contexts in which 386SWAT changes the cursor type, I noticed that the Enter command handles the INS key, but not the XINS key, so I changed it. Version 5.10.017 * Implement Exit Command A common command line sequence is to set AH to 4C, SIGINT 21, and G. This is now done via a command called EXIT. Version 5.10.016 * Add Debugging Displays To 386SWAT During Initialization To help me figure out why 386SWAT wasn't installing under Win95, I made several changes: * Add some debugging displays (press and hold either shift key when 386SWAT is loading ala Shift-MAX). * If there are no VCPI services (DEBUG=NOVCPI in 386MAX), fail gracefully. * Ensure interrupts are re-enabled upon returning from VCPI/PM. * Ensure that the B-bit is set in our stack selector. * Avoid calling CHECK_I92 if we're in VM as it can reboot the system (learned the hard way). * Put in a check to avoid calling OLDINT67_VEC if it's zero (who can argue with that?). * Avoid a bug in MASM 5.10b which generates a word fixup when it should generate a dword fixup. Any questions on why I want to write my own assembler? ================================================ FILE: swat/WINKDBG.DOC ================================================ Notes on Windows Kernel Debugging --------------------------------- Windows implements a low-level debugging interface called Kernel Debugging (WKD) which obtains control very early in the startup sequence of Windows. The program WDEB386 shipped with the Windows SDK is an example of one such program; 386SWAT is another. When Windows sees that a kernel debugger is present, it informs the debugger about a number of events as they occur, principally parameter errors made by running Windows programs as they call Windows API functions. For example, if a program calls EnableWindow with an invalid window handle (say, zero), this error is passed on to the WKD for processing before returning to the calling program. In this way, a great many errors can be caught before they can cause any harm. By default, 386SWAT is a WKD. If, for some reason, you wish to disable this feature, place the keyword NOWINK into your 386SWAT profile. At the current time, you must have a monochrome adapter and monitor attached to your system in order for WKD services to be allowed by 386SWAT. 386SWAT tests for a mono card and disables WKD if not found. New Command Line Actions ------------------------ * To enable or disable WKD services entirely, use WKD [ON|OFF] This option is available outside Windows only. If you have specified NOWINK in the 386SWAT profile, this option has no effect -- you must remove that profile option and reboot the system to enable WKD services. * To change the response to a parameter error, use WKD [NOISY|QUIET] If NOISY is specified, then each parameter error is followed by the prompt "Break, Ignore, Quiet?" to which you must respond B, I, or Q. A response of Q, is equivalent to setting WKD QUIET after which parameter errors are logged to the screen, but execution does not stop for any more parameter errors until you break into 386SWAT and type WKD NOISY on 386SWAT's command line. This is the default state, so you'll see parameter errors fly past on the mono screen without pause. I recommend that when you are debugging your own code, use WKD NOISY; otherwise, use WKD QUIET. This is because many commercial packages contain so many parameter errors that you'll constantly be interrupted with a BIQ prompt. A response of I, ignores this one error only and continues execution. A response of B, triggers a single step breakpoint at an IRETD inside 386SWAT. Tracing over this instruction returns to the instruction inside Windows immediately following the call to 386SWAT (typically an INT 41h). Tracing from this point on eventually gets you back to a call to LogError which was called by the Windows API function which encountered the invalid parameter, and then back to the application which called the Windows API with an invalid parameter. If the application is Win32, then you'll have to trace back through a thunking layer before you get to the application. This can be quite tricky. At some point, I'll try to put in some stack tracing to aid this process. * Sometimes Windows and/or applications make direct calls to LogError as opposed to indirect calls as part of a parameter error. These calls are uncommon, so there is a separate switch to control 386SWAT's response to such an event. Use WKD LOGERROR [ON|OFF] to change the response of stopping at an IRETD inside 386SWAT or not. The default setting is OFF. * Sometimes an application is bad enough that it triggers an unrecoverable fault (typically a GP or Page Fault) and it must be terminated. Windows gives the WKD a crack at it first to which 386SWAT responds by stopping in the application at the faulting instruction, thus giving you the opportunity to debug the problem. If you wish to tell Windows to handle the fault itself (typically by terminating the application), use WKD FAULT SKIP If you do not want to receive any more fault messages from Windows, use WKD FAULT OFF To restart receiving fault messages, use WKD FAULT ON * The keystroke Ctrl-K brings up a menu from which you can choose to display various internal Windows structures. At the moment, the only one which has been fleshed out is the display of the Windows Global Heap (WGH). The WGH contains one entry for each globally allocated region of memory. For example, the various code and data segments of KRNL386.EXE are global allocations and have entries in this table. To scroll through this table, use the usual up and down arrow keys as well as Page Up and Page Down. To search through the WGH for a specific entry, use the SGH command: SGH [/b|/s|/h|/o] [/c] expr The expression (expr) entered is interpreted as a base address if /b is specified, size if /s, handle if /h, and owner if /o. If /c is specified, the search continues from the currently displayed entry; otherwise, the search starts at the top of the heap. If the value is found in the WGH, the WGH is displayed with the matching entry at the top of the screen. If you wish to repeat the search (perhaps becayse there are multiple entries with the same owner), either retype the command (and specify /c so the search continues with the next entry after the one at the top of the screen), or start the command with a slash so it is not erased after successful execution. If the value is not found in the WGH, an error message is displayed. * If Invalid Page Faults are being trapped by SWAT's VxD (see SWATVXD.DOC for more details), use the IPF command to control how these events are to be handled. IPF [/d] [/s] [/r] expr where /d tells SWAT not to display a message on the mono screen describing this event, /s tells SWAT not to stop when this event occurs, /r tells SWAT to remove this entry from its local tables, and expr is an expression which evaulates to a linear address corresponding to the Invalid Page Fault. * To display the memory pointed to by a selector as a Module Database, use MDB expr * To display the memory pointed to by a selector as a Task Database, use TDB expr * Certain commands usually preceded with a dot are automatically passed to Windows for processing by WIN386, assuming Windows is active and WIN386 services are available. These commands include ? Display a Help screen with the available commands .? Display a list of registered dot commands (e.g., .M) .R [#] Display the registers of the current thread (or thread #) .VM [#] Display the complete VM status of the current VM (or #) .VC [#] Display the current VM's (or #) control block .VH [#] Display a VMM linked list, given list handle .VR [#] Display the registers of the current VM (or #) .VS [#] Display the current VM's (or #) virtual stack .VL Display list of all valid VM handles .DS Display protected mode stack with labels .VMM Display menu of VMM state info . Display device-specific info Profile Options --------------- Because 386SWAT is a WKD, it is given much more information to process. Much of that data is stored in its internal log file (acessible via Ctl-F10) which means that you should increase the log file's default size. You might experiment with different values, but I suggest using something on the order of LOGSIZE=100000. During Windows startup while still in RM/VM, Windows loads the real mode portion of all of the VxDs to be used this Windows session. At this time, Windows tells the WKD about these VxDs and where they will be loaded in memory when in PM, and 386SWAT logs this information in two ways. The first way is to write a line to the mono display with the data about each segment (code or data) of the form Loaded VxD , module at

len The second way is to append a symbol to 386SWAT's symbol table of the form _Code or _Data, where is a decimal sequence number starting at 1 and is used to distinguigh one code/data segment from another. By convention in Windows, code segments are in selector 0028h and data segments are in selector 0030h. These symbols are useful when debugging VxDs. In order to save this information, you need to tell 386SWAT how much space to reserve. The profile option WKDLS (Load Segments) is used for this purpose. The actual value depends upon how many VxD code and data segments are loaded on your system. I use WKDLS=700. If you have no interest in debugging VxDs, omit this profile option as the default value is zero which reserves no space. You might also want to increase the profile value for SYMSIZE. I use SYMSIZE=700000 (you do have 32MB of RAM, don't you?). Debugging DLLs -------------- The Windows SDK (3.1x or 95) contains separate copies of various system DLLs each of which which contain more messages and checks on Windows execution. I haven't played with these much, so you're on your own, but it may be very worthwhile. They also contain symbol files which I haven't put in code to load as yet. SWAT VxD -------- This version of 386SWAT no longer requires that you load SWATVXD.EXE as a resident program (thus saving you a few bytes of DOS memory), but the VxD must be in same directory as 386SWAT.LOD. The VxD is now loaded by 386SWAT when Windows starts up. See the file SWATVXD.DOC for more information on how to configure the VxD. Loading 386SWAT --------------- If you are running 386MAX as your memory manager, you could load 386SWAT from the 386MAX profile with the LOAD= keyword. However, because this mechanism doesn't provide for 386SWAT to have a DOS footprint and such a footprint is needed for WKDing, I do not recommend loading SWAT this way anymore. Instead, load 386SWAT as a device driver on the line which immediately follows the line which loads the memory manager. 386SWAT must load in low DOS memory, so don't try to load it high. The low DOS memory footprint of 386SWAT is about 2KB.  ================================================ FILE: swat/WINKDBG.HTM ================================================ Notes on Windows Kernel Debugging
Notes on Windows Kernel Debugging

Windows implements a low-level debugging interface called Kernel Debugging (WKD) which obtains control very early in the startup sequence of Windows.  The program WDEB386 shipped with the Windows SDK is an example of one such program; 386SWAT is another.

When Windows sees that a kernel debugger is present, it informs the debugger about a number of events as they occur, principally parameter errors made by running Windows programs as they call Windows API functions.  For example, if a program calls EnableWindow with an invalid window handle (say, zero), this error is passed on to the WKD for processing before returning to the calling program.  In this way, a great many errors can be caught before they can cause any harm.

By default, 386SWAT is a WKD.  If, for some reason, you wish to disable this feature, place the keyword NOWINK into your 386SWAT profile.

At the current time, you must have a monochrome adapter and monitor attached to your system in order for WKD services to be allowed by 386SWAT.  386SWAT tests for a mono card and disables WKD if not found.
 

New Command Line Actions

The WKD command takes several options:

  • To enable or disable WKD services entirely, use
        WKD [ON|OFF]
 
This option is available outside Windows only.  If you have specified NOWINK in the 386SWAT profile, this option has no effect -- you must remove that profile option and reboot the system to enable WKD services.
  • To change the response to a parameter error, use
        WKD [NOISY|QUIET]
 
If NOISY is specified, then each parameter error is followed by the prompt Break, Ignore, Quiet? to which you must respond B, I, or Q.
A response of Q, is equivalent to setting WKD QUIET after which parameter errors are logged to the screen, but execution does not stop for any more parameter errors until you break into 386SWAT and  type WKD NOISY on 386SWAT's command line.  This is the default state, so you'll see parameter errors fly past on the mono screen   without pause.  I recommend that when you are debugging your own code, use WKD NOISY; otherwise, use WKD QUIET.  This is because many commercial packages contain so many parameter errors that you'll constantly be interrupted with a BIQ prompt.
A response of I, ignores this one error only and continues execution.
A response of B, triggers a single step breakpoint at an IRETD inside 386SWAT.  Tracing over this instruction returns to the instruction inside Windows immediately following the call to 386SWAT (typically an INT 41h).  Tracing from this point on eventually gets you back to a call to LogError which was called by the Windows API function which encountered the invalid parameter, and then back to the application which called the Windows API with an invalid parameter.  If the application is Win32, then you'll have to trace back through a thunking layer before you get to the application.  This can be quite tricky.  At some point, I'll try to put in some stack tracing to aid this process.
  • Sometimes Windows and/or applications make direct calls to LogError as opposed to indirect calls as part of a parameter error.  These calls are uncommon, so there is a separate switch to control 386SWAT's response to such an event.  Use
        WKD LOGERROR [ON|OFF]
 
to change the response of stopping at an IRETD inside 386SWAT or not.  The default setting is OFF.
  • Sometimes an application is bad enough that it triggers an unrecoverable fault (typically a GP or Page Fault) and it must be terminated.  Windows gives the WKD a crack at it first to which 386SWAT responds by stopping in the application at the faulting instruction, thus giving you the opportunity to debug the problem.  If you wish to tell Windows to handle the fault itself (typically by terminating the application), use
        WKD FAULT SKIP

If you do not want to receive any more fault messages from Windows, use

        WKD FAULT OFF

To restart receiving fault messages, use

    WKD FAULT ON

* The keystroke Ctrl-K brings up a menu of items to display from which you can choose various internal Windows structures.  At the moment, the only one which has been fleshed out is the display of the Windows Global Heap (WGH).  The WGH contains one entry for each globally allocated region of memory.  For example, the various code and data segments of KRNL386.EXE are global allocations and have entries in this table.  To scroll through this table, use the usual up and down arrow keys as well as Page Up and Page Down.

* To search through the WGH for a specific entry, use the SGH command:

          SGH [/b|/s|/h|/o]  [/c] expr

The expression (expr) entered is interpreted as a base address if /b is specified, size if /s, handle if /h, and owner if /o.  If /c is specified, the search continues from the currently displayed entry; otherwise, the search starts at the top of the heap.  If the value is found in the WGH, the WGH is displayed with the matching entry at the top of the screen.  If you wish to repeat the search (perhaps because there are multiple entries with the same owner), either retype the command (and specify /c so the search continues with the next entry after the one at the top of the screen), or start the command with a slash so it is not erased after successful execution. If the value is not found in the WGH, an error message is displayed.

* If Invalid Page Faults are being trapped by SWAT's VxD (see SWATVXD.DOC for more details), use the IPF command to control how these events are to be handled.

          IPF [/d]  [/s]  [/r] expr

where /d tells SWAT not to display a message on the mono screen describing this event, /s tells SWAT not to stop when this event occurs, /r tells SWAT to remove this entry from its local tables, and expr is an expression which evaulates to a linear address corresponding to the Invalid Page Fault.

* To display the memory pointed to by a selector as a Module Database, use

          MDB expr

* To display the memory pointed to by a selector as a Task Database, use

          TDB expr

* Certain commands usually preceded with a dot are automatically passed to Windows for processing by WIN386, assuming Windows is active and WIN386 services are available.  These commands include
? Display a Help screen with the available commands
.? Display a list of registered dot commands (e.g., .M)
.R [#] Display the registers of the current thread (or thread #)
.VM [#] Display the complete VM status of the current VM (or #)
.VC [#] Display the current VM's (or #) control block
.VH [#] Display a VMM linked list, given list handle
.VR [#] Display the registers of the current VM (or #)
.VS [#] Display the current VM's (or #) virtual stack
.VL Display list of all valid VM handles
.DS Display protected mode stack with labels
.VMM Display menu of VMM state info
.dev_name Display device-specific info
 

Profile Options

Because 386SWAT is a WKD, it is given much more information to process.  Much of that data is stored in its internal log file (acessible via Ctl-F10) which means that you should increase the log file's default size.  You might experiment with different values, but I suggest using something on the order of LOGSIZE=100000.

During Windows startup while still in RM/VM, Windows loads the real mode portion of all of the VxDs to be used this Windows session.  At this time, Windows tells the WKD about these VxDs and where they will be loaded in memory when in PM, and 386SWAT logs this information in two ways.

The first way is to write a line to the mono display with the data about each segment (code or data) of the form

Loaded VxD VxDname, module Modname at address len length

The second way is to append a symbol to 386SWAT's symbol table of the form VxDname_Codennnn or VxDname_Datannnn, where nnnn is a decimal sequence number starting at 1 and is used to distinguigh one code/data segment from another.  By convention in Windows, code segments are in selector 0028h and data segments are in selector 0030h.  These symbols are useful when debugging VxDs.

In order to save this information, you need to tell 386SWAT how much space to reserve.  The profile option WKDLS (Load Segments) is used for this purpose.  The actual value depends upon how many VxD code and data segments are loaded on your system.  I use WKDLS=700.  If you have no interest in debugging VxDs, omit this profile option as the default value is zero which reserves no space.  You might also want to increase the profile value for SYMSIZE.  I use SYMSIZE=700000 (you do have 32MB of RAM, don't you?).
 

Debugging DLLs

The Windows SDK (3.1x or 95) contains separate copies of various system DLLs each of which contain more messages and checks on Windows execution.  I haven't played with these much, so you're on your own, but it may be very worthwhile.  They also contain symbol files for which I haven't as yet put in code to load.
 

SWAT VxD

This version of 386SWAT no longer requires that you load SWATVXD.EXE as a resident program (thus saving you a few bytes of DOS memory), but the VxD must be in same directory as 386SWAT.LOD.  The VxD is now loaded by 386SWAT when Windows starts up.  See the file SWATVXD.DOC for more information on how to configure the VxD.
 

Loading 386SWAT

If you are running 386MAX as your memory manager, you could load 386SWAT from the 386MAX profile with the LOAD= keyword.  However, because this mechanism doesn't provide for 386SWAT to have a DOS footprint and such a footprint is needed for WKDing, I do not recommend loading SWAT this way anymore.  Instead, load 386SWAT as a device driver on the line which immediately follows the line which loads the memory manager.  386SWAT must load in low DOS memory, so don't try to load it high.  The low DOS memory footprint of 386SWAT is about 2KB.  ================================================ FILE: switcher/main.cpp ================================================ #include #include #include #include #include using namespace std; extern char far *get_ptr_1(char far* x,int b); #pragma aux get_ptr_1 = \ "mov ax,1401h" \ "int 0f0h" \ parm [cx dx] [bx] \ value [ds si] \ modify [ax]; extern int HasDMMI(); #pragma aux HasDMMI = "mov ax,0" "int 0f0h" value [ax] modify [ax]; int main(int,char**) { exit(0); printf("Switcher DMMI Client, (C) Chourdakis Michael.\r\n"); int i = HasDMMI(); if (i != 0xFACE) { printf("Switcher requires a DMMI Server.\r\n"); exit(1); } char cmd[100] = { 0 }; for (;;) { cout << "* "; cin >> cmd; string c = cmd; if (c == "exit" || c == "quit") { break; } if (c == "help" || c == "?") { cout << "Commands available: help, exit" << endl; continue; } if (c == "run") { // load path size_t pos = 0; std::string token; string delimiter = " "; while ((pos = c.find(delimiter)) != std::string::npos) { token = c.substr(0, pos); c.erase(0, pos + delimiter.length()); } } } printf("Switcher End.\r\n"); return 0; } ================================================ FILE: switcher/switcher.lk1 ================================================ FIL main.obj ================================================ FILE: switcher/switcher.mk ================================================ project : F:\TOOLS\ASM\full2\switcher\switcher.exe .SYMBOLIC !include F:\TOOLS\ASM\full2\switcher\switcher.mk1 ================================================ FILE: switcher/switcher.mk1 ================================================ !define BLANK "" F:\TOOLS\ASM\full2\switcher\main.obj : F:\TOOLS\ASM\full2\switcher\main.cpp & .AUTODEPEND @F: cd F:\TOOLS\ASM\full2\switcher *wpp main.cpp -i="G:\WATCOM/h" -w4 -e25 -zq -od -d2 -bt=dos -fo=.obj -ml -x& s -xr F:\TOOLS\ASM\full2\switcher\switcher.exe : F:\TOOLS\ASM\full2\switcher\main.& obj .AUTODEPEND @F: cd F:\TOOLS\ASM\full2\switcher @%write switcher.lk1 FIL main.obj @%append switcher.lk1 *wlink name switcher d all sys dos op m op maxe=25 op q op symf @switcher.l& k1 ================================================ FILE: switcher/switcher.tgt ================================================ 40 targetIdent 0 MProject 1 MComponent 0 2 WString 3 EXE 3 WString 5 de6en 1 0 1 4 MCommand 0 5 MCommand 0 6 MItem 12 switcher.exe 7 WString 3 EXE 8 WVList 0 9 WVList 0 -1 1 1 0 10 WPickList 2 11 MItem 5 *.cpp 12 WString 6 CPPOBJ 13 WVList 0 14 WVList 0 -1 1 1 0 15 MItem 8 main.cpp 16 WString 6 CPPOBJ 17 WVList 0 18 WVList 0 11 1 1 0 ================================================ FILE: switcher/switcher.wpj ================================================ 40 projectIdent 0 VpeMain 1 WRect 0 0 7680 9178 2 MProject 3 MCommand 0 4 MCommand 0 1 5 WFileName 12 switcher.tgt 6 WVList 1 7 VComponent 8 WRect 0 0 5690 4295 0 0 9 WFileName 12 switcher.tgt 0 0 7 ================================================ FILE: thread16.asm ================================================ USE16 macro thread16header sts,sto { db 4096 dup (144) ; // fill NOPs ; Load IDT CLI mov di,DATA16 mov ds,di lidt fword [ds:idt_RM_start] ; Stack mov ax,sts mov ss,ax mov sp,sto ; A20 call FAR CODE16:EnableA20f ; Quick Enter Unreal call FAR CODE16:EnterUnreal ; Spurious, APIC MOV EDI,[DS:LocalApic] ADD EDI,0x0F0 MOV EDX,[FS:EDI] OR EDX,0x1FF push dword 0 pop fs MOV [FS:EDI],EDX MOV EDI,[DS:LocalApic] ADD EDI,0x0B0 MOV dword [FS:EDI],0 } Thread16_1: thread16header STACK16T1,stack16t1_end ; Start mov [FromThread1],1 qunlock16 mut_1 cli hlt Thread16_2: thread16header STACK16T2,stack16t2_end mov [FromThread2],1 sti mov dx,thrm1 mov ax,0900h int 21h cli qunlock16 mut_1 cli hlt Thread16_3: thread16header STACK16T3,stack16t3_end mov [FromThread3],1 sti mov dx,thrm2 mov ax,0900h int 21h cli qunlock16 mut_1 cli hlt Thread16_4: thread16header STACK16T4,stack16t4_end mov [FromThread4],1 sti mov dx,thrm3 mov ax,0900h int 21h cli qunlock16 mut_1 cli hlt ================================================ FILE: thread32.asm ================================================ USE16 macro thread32header ofs,seg { USE16 ; Remember CPU starts in real mode db 4096 dup (144) ; // fill NOPs ; Stack mov ax,STACK16T5 mov ss,ax mov sp,stack16t5_end ; A20 call FAR CODE16:EnableA20f ; Unreal call FAR CODE16:EnterUnreal ; Spurious, APIC MOV EDI,[DS:LocalApic] ADD EDI,0x0F0 MOV EDX,[FS:EDI] OR EDX,0x1FF push dword 0 pop fs MOV [FS:EDI],EDX MOV EDI,[DS:LocalApic] ADD EDI,0x0B0 MOV dword [FS:EDI],0 ; Protected EnterProtected ofs,seg,0 } Thread32_1: thread32header Thread32_1a,code32_idx cli hlt hlt USE32 Thread32_1a: mov ax,data16_idx mov ds,ax mov [FromThread5],1 qunlock32 mut_1 cli hlt USE32 ================================================ FILE: thread64.asm ================================================ USE16 include 'directlong.asm' Thread64_1: thread64header db 066h db 0eah Thread64Ptr2 dd 0 dw code64_idx USE64 Thread64_1a: linear r8,FromThread6 mov byte [r8],1 qunlock64 mut_1 cli hlt USE64 ================================================ FILE: unreal.asm ================================================ USE16 ; Leaves FS in unreal mode EnterUnreal: cli PUSHAD MOV AX,DATA16 MOV FS,AX linear eax,0,CODE16 mov [fs:code16_descriptorUNR.b0_15],ax ; store it in the dscr shr eax,8 mov [fs:code16_descriptorUNR.b16_23],ah XOR eax,eax mov [fs:data32_descriptorUNR.b0_15],ax ; store it in the dscr mov [fs:data32_descriptorUNR.b16_23],ah ; Set gdt ptr linear eax,dummy_descriptorUNR mov [gdt_ptrUNR],eax mov bx,gdt_startUNR lgdt [fs:bx] mov eax,cr0 or al,1 mov cr0,eax JMP $+2 mov ax,10h mov fs,ax mov eax,cr0 and al,not 1 mov cr0,eax xor ax,ax mov fs,ax POPAD RETF ================================================ FILE: vbox.vbox-prev ================================================ ================================================ FILE: vdebug.asm ================================================ FORMAT MZ HEAP 0 include 'config.asm' include 'struct.asm' ; stack segment STACK16 USE16 dw 128 dup(0) stre: ; data segment DATA16 USE16 run db 0 psp dw 0 mypsp dw 0 if VDEBUG = 0 m1 db "Virtualization Debugger, (C) Chourdakis Michael - Set VDEBUG=1 to config.asm.",0x0D,0x0A,"$" else m1 db "Virtualization Debugger, (C) Chourdakis Michael.",0x0D,0x0A,"$" end if prg db "d:\debuggee.exe",0x0 dismposcount dd 0 dismpos dd 0 bbb LoadX 0,0,0,0,0,0,0 include 'vdebug64.asm' include "reqdmmi.asm" ; main segment CODE16 USE16 back16: ; End cli mov ax,STACK16 mov ss,ax mov eax,stre mov esp,eax sti mov ax,DATA16 mov ds,ax mov es,ax ; Set the PSP mov ah,0x50 mov bx,[mypsp] int 0x21 mov ax,0x4C00 int 0x21 start16: mov ax,STACK16 mov ss,ax mov eax,stre mov esp,eax mov ax,DATA16 mov ds,ax mov es,ax mov ax,0x0900 mov dx,m1 int 0x21 if VDEBUG = 0 mov ax,0x4C00 int 0x21 end if mov ah,0x62 int 0x21 mov [mypsp],bx mov eax,1 cpuid bt ecx,5 jc VMX_Supported mov ax,0x4C00 int 0x21 VMX_Supported: RequireDMMI ; dism pos mov ax,0x1401 xor ecx,ecx xor edx,edx int 0xF0 ;break mov word [es:dismpos],si mov word [es:dismpos + 2],ds shr esi,16 mov word [es:dismposcount],si mov word [es:dismposcount + 2],ds mov ax,DATA16 mov ds,ax ; Load executable mov bx,bbb mov dx,prg mov ax,0x4B01 int 0x21 jc endx BackExecutable: mov ax,DATA16 mov ds,ax cmp [run],1 je endx2 mov [run],1 mov ah,0x62 int 0x21 mov [psp],bx ; Enter Long xor ecx,ecx mov cx,CODE64 shl ecx,4 add ecx,start64 mov ax,0x0902 int 0xF0 endx2: vmcall endx: ; End mov ax,0x4C00 int 0x21 SEGMENT ENDS entry CODE16:start16 ================================================ FILE: vdebug64.asm ================================================ segment V USE16 firstcall db 0 ve: mov ax,DATA16 mov ds,ax mov ax,[bbb.sp] mov sp,ax mov ax,[bbb.ss] mov ss,ax mov ax,[bbb.ip] push ax mov ax,[bbb.cs] push ax vmcall ; first call retf segment STACK64 USE64 stx dq 1024 dup(0) ste: nop rspsave dq 0 exitreason db 0 vregs dq 50 dup (0) segment CODE64 USE64 include 'vdisplay.asm' start64: ; interrupts lidt [eax] linear rsp,ste,STACK64 mov ax,0 int 0xF0 ; Prepare the virtualization structures mov ax,0x801 linear r8,hr,CODE64 mov r9,V mov r10,ve int 0xF0 vmlaunch hr: ; Save all volatile registers push r15 linear r15,vregs,STACK64 mov [r15 + 0x00],rax mov [r15 + 0x08],rbx mov [r15 + 0x10],rcx mov [r15 + 0x18],rdx mov [r15 + 0x20],rsi mov [r15 + 0x28],rdi mov [r15 + 0x30],rbp pop r15 ; check exit reason vmr rax,0x4402 cmp al,18 jnz DebugInterface linear rax,firstcall,V cmp byte [rax],1 je VmFinalCall mov byte [rax],1 ; rip +3 vmr rax,0x681E add rax,3 vmw64 0x681E,rax mov al,18 jmp DebugInterface VmFinalCall: ; Disable VMX mov ax,0x800 int 0xF0 ; Back to real mode cli xor rcx,rcx mov cx,CODE16 shl rcx,16 add ecx,back16 mov ax,0x0900 int 0xF0 DebugInterface: ; al = reason ; Just resume yet, not ready if VDEBUG = 0 jmp DebugResume end if linear rdx,exitreason,STACK64 mov byte [rdx],al call ShowDisplay jmp DebugResume DebugResume: push r15 linear r15,vregs,STACK64 mov rax,[r15 + 0x00] mov rbx,[r15 + 0x08] mov rcx,[r15 + 0x10] mov rdx,[r15 + 0x18] mov rsi,[r15 + 0x20] mov rdi,[r15 + 0x28] mov rbp,[r15 + 0x30] pop r15 vmresume ================================================ FILE: vdisplay.asm ================================================ disp64: push rax shr rax,32 call disp32 pop rax disp32: push rax shr eax,16 call disp16 pop rax disp16: push ax mov al,ah call disp8 pop ax disp8: push ax push cx mov cl,4 shr al,cl call disp4 pop cx pop ax disp4: and al,0fh cmp al,0xA jae .hdisp4 add al,0x30 stosb ret .hdisp4: sub al,0xA add al,0x41 stosb ret mmhelp db 'Commands: ',0xd,0xa,' (? or h) - help',0xd,0xa,' (g) - go',0xd,0xa,' (r) - registers',0xd,0xa,' (t) - trace',0xd,0xa, ' (q) - quit',0xd,0xa, "$" mmj db 40,0 db 50 dup (0) show dq 4096 dup (0) bbb2 LoadX 0,0,0,0,0,0,0 rx db "d:\dism.exe",0 guestmode: vmr rax,0x6800 ; Guest CR0 bt rax,1 jz .noreal mov ax,0 ret .noreal: mov ax,0x0100 ret guestlinear: call guestmode vmr rax,0x681E ; Guest RIP vmr rbx,0x802 ; Guest CS shl rbx,4 add rbx,rax mov rax,rbx ret bytecount dd 0 ShowDism: push rdi ; rdi = where to store info ;mov ax,dismdata2 linear rsi,dismpos,DATA16 xor ecx,ecx xor edx,edx mov dx,[rsi] mov cx,[rsi + 2] xor rdi,rdi mov di,cx shl edi,4 add edi,edx ; EDI = output push rdi call guestlinear ; mode, 16 bit for now ; The following is bad, we must check CS selector ; but test for now push rax call guestmode cmp al,01 jnz .nmx1 mov byte [rdi],32 jmp .ax1 .nmx1: mov byte [rdi],16 .ax1: pop rax ; Check Mode actually ; VMCALL linear rcx,exitreason,STACK64 push rax mov al,[rcx] cmp al,18 pop rax jnz .novmcall pop rdi pop rdi mov rax,'vmcall'; stosq ret; nothing .novmcall: push rax mov rcx,15 mov byte [rdi + 1],15 add rdi,2 .jlpp: mov bl,[rax] mov [rdi],bl inc rax inc rdi dec rcx jrcxz .jlppf jmp .jlpp .jlppf: ; call dism.exe mov bx,bbb2 mov dx,rx mov bp,0x4B00 mov si,CODE64 shl esi,16 mov edi,esi mov ax,0x421 int 0xF0 pop rax pop rdi mov rsi,rdi ; RSI now points to dissm bytes pop rdi ; RDI now to output buffer push rax .jlp: mov al,[rsi] cmp al,0 jz .end stosb inc rsi jmp .jlp .end: pop rax ; also the # of bytes push rdi linear rsi,dismposcount,DATA16 xor ecx,ecx xor edx,edx mov dx,[rsi] mov cx,[rsi + 2] xor rdi,rdi mov di,cx shl edi,4 add edi,edx mov esi,[edi] pop rdi ; ESI = Count of bytes to transfer mov byte [rdi],' ' mov byte [rdi+1],'(' add rdi,2 .jb1: cmp esi,0 jz .jb2 dec esi push rax mov al,[rax] call disp8 pop rax inc rax jmp .jb1 .jb2: mov byte [rdi],')' add rdi,1 ret ShowCRs: ;rax - rdx mov eax,'CR0 '; stosd mov rcx,5 mov al,' ' rep stosb mov eax,'CR3 '; stosd mov rcx,5 mov al,' ' rep stosb mov eax,'CR4 '; stosd mov rcx,5 mov al,' ' rep stosb mov ax,0x0D0A stosw vmr rax,0x6800 call disp32 mov al,' ' stosb vmr rax,0x6802 call disp32 mov al,' ' stosb vmr rax,0x6804 call disp32 mov al,' ' stosb mov ax,0x0D0A stosw ret ShowSegs: ;DS mov eax,'DS '; stosd mov al,' ' stosb mov eax,'ES '; stosd mov al,' ' stosb mov eax,'FS '; stosd mov al,' ' stosb mov eax,'GS '; stosd mov al,' ' stosb mov eax,'SS '; stosd mov al,' ' stosb mov ax,0x0D0A stosw vmr rax,0x806 call disp16 mov al,' ' stosb vmr rax,0x800 call disp16 mov al,' ' stosb vmr rax,0x808 call disp16 mov al,' ' stosb vmr rax,0x80A call disp16 mov al,' ' stosb vmr rax,0x804 call disp16 mov al,' ' stosb mov ax,0x0D0A stosw ret DisplayGuestMode: call guestmode cmp ah,0 jnz .noreal mov eax,'RM '; stosd jmp .afterm .noreal: cmp ah,1 jnz .noprot mov eax,'PM '; stosd jmp .afterm .noprot: .afterm: ret ShowRegs64: push64 linear r15,vregs,STACK64 linear rdi,show,CODE64 cld call ShowCRs call ShowSegs ;rax - rdx mov eax,'RAX '; stosd mov rcx,13 mov al,' ' rep stosb mov eax,'RBX '; stosd mov rcx,13 mov al,' ' rep stosb mov eax,'RCX '; stosd mov rcx,13 mov al,' ' rep stosb mov eax,'RDX '; stosd mov rcx,13 mov al,' ' rep stosb mov ax,0x0D0A stosw mov rax,[r15 + 0x00] call disp64 mov al,' ' stosb mov rax,[r15 + 0x08] call disp64 mov al,' ' stosb mov rax,[r15 + 0x10] call disp64 mov al,' ' stosb mov rax,[r15 + 0x18] call disp64 mov al,' ' stosb mov ax,0x0D0A stosw ; RSI RDI RBP RSP mov eax,'RSI '; stosd mov rcx,13 mov al,' ' rep stosb mov eax,'RDI '; stosd mov rcx,13 mov al,' ' rep stosb mov eax,'RBP '; stosd mov rcx,13 mov al,' ' rep stosb mov eax,'RSP '; stosd mov rcx,13 mov al,' ' rep stosb mov ax,0x0D0A stosw mov rax,[r15 + 0x20] call disp64 mov al,' ' stosb mov rax,[r15 + 0x28] call disp64 mov al,' ' stosb mov rax,[r15 + 0x30] call disp64 mov al,' ' stosb vmr rax,0x681C ; Guest RSP call disp64 mov al,' ' stosb mov ax,0x0D0A stosw ; Mode call DisplayGuestMode ; RIP mov rax,'CS:RIP '; stosq vmr rax,0x802 ; Guest CS call disp16 mov al,':' stosb vmr rax,0x681E ; Guest RIP call disp64 mov al,' ' stosb mov rax,'LINEAR '; stosq call guestlinear call disp64 mov al,' ' stosb mov al,' ' stosb call ShowDism mov ax,0x0D0A stosw mov al,'$' stosb mov dx,show mov si,CODE64 shl esi,16 mov ebp,0x900 mov ax,0x421 int 0xF0 pop64 ret ShowRegs: push64 linear r15,vregs,STACK64 linear rdi,show,CODE64 cld call ShowCRs call ShowSegs ;rax - rdx mov eax,'EAX '; stosd mov rcx,5 mov al,' ' rep stosb mov eax,'EBX '; stosd mov rcx,5 mov al,' ' rep stosb mov eax,'ECX '; stosd mov rcx,5 mov al,' ' rep stosb mov eax,'EDX '; stosd mov rcx,5 mov al,' ' rep stosb mov eax,'ESI '; stosd mov rcx,5 mov al,' ' rep stosb mov eax,'EDI '; stosd mov rcx,5 mov al,' ' rep stosb mov eax,'EBP '; stosd mov rcx,5 mov al,' ' rep stosb mov eax,'ESP '; stosd mov rcx,5 mov al,' ' rep stosb mov ax,0x0D0A stosw mov rax,[r15 + 0x00] call disp32 mov al,' ' stosb mov rax,[r15 + 0x08] call disp32 mov al,' ' stosb mov rax,[r15 + 0x10] call disp32 mov al,' ' stosb mov rax,[r15 + 0x18] call disp32 mov al,' ' stosb mov rax,[r15 + 0x20] call disp32 mov al,' ' stosb mov rax,[r15 + 0x28] call disp32 mov al,' ' stosb mov rax,[r15 + 0x30] call disp32 mov al,' ' stosb vmr rax,0x681C ; Guest RSP call disp32 mov al,' ' stosb mov ax,0x0D0A stosw ; Mode call DisplayGuestMode ; RIP mov rax,'CS:EIP '; stosq vmr rax,0x802 ; Guest CS call disp16 mov al,':' stosb vmr rax,0x681E ; Guest RIP call disp32 mov al,' ' stosb mov rax,'LINEAR '; stosq call guestlinear call disp32 mov al,' ' stosb mov al,' ' stosb call ShowDism mov ax,0x0D0A stosw mov al,'$' stosb mov dx,show mov si,CODE64 shl esi,16 mov ebp,0x900 mov ax,0x421 int 0xF0 pop64 ret ShowPrompt: push64 linear rdi,show,CODE64 cld mov ax,0x0D0A stosw mov al,'*' stosb mov al,' ' stosb mov al,'$' stosb mov dx,show mov si,CODE64 shl esi,16 mov ebp,0x900 mov ax,0x421 int 0xF0 pop64 ret WaitForInput: call ShowPrompt mov dx,mmj mov si,CODE64 shl esi,16 mov ebp,0xa00 mov ax,0x421 int 0xF0 linear rdx,mmj,CODE64 mov al,[rdx + 1] cmp al,0 ; nothing entered? jz WaitForInput ; Single Byte Commands cmp byte [rdx + 2],'?' jz .CmdHelp cmp byte [rdx + 2],'h' jz .CmdHelp cmp byte [rdx + 2],'r' jz .CmdRegs cmp byte [rdx + 2],'g' jz .CmdGo cmp byte [rdx + 2],'t' jz .CmdTrace cmp byte [rdx + 2],'q' jz .CmdQuit jmp WaitForInput .CmdRegs: call ShowRegs jmp WaitForInput .CmdHelp: mov dx,mmhelp mov si,CODE64 shl esi,16 mov ebp,0x900 mov ax,0x421 int 0xF0 jmp WaitForInput .CmdGo: ; Clear Trap vmw32 0x4004,0x0 ; trap exception 0x06 vmr rax,0x6820 btr rax,8 vmw64 0x6820,rax jmp .InputEnd .CmdTrace: ; Set Trap vmw32 0x4004,0x2 ; trap exception 0x06 and 0x01 vmr rax,0x6820 bts rax,8 vmw64 0x6820,rax jmp .InputEnd .CmdQuit: ; Abort all jmp VmFinalCall .InputEnd: ret ShowDisplay: call ShowRegs call WaitForInput ret ================================================ FILE: vm.vmsd ================================================ ================================================ FILE: vm.vmx ================================================ .encoding = "UTF-8" config.version = "8" virtualHW.version = "12" numvcpus = "8" cpuid.coresPerSocket = "1" scsi0.present = "TRUE" scsi0.virtualDev = "lsilogic" memsize = "256" ide1:0.present = "TRUE" ide1:0.fileName = "d.iso" ide1:0.deviceType = "cdrom-image" ethernet0.present = "TRUE" ethernet0.virtualDev = "e1000" ethernet0.wakeOnPcktRcv = "FALSE" ethernet0.addressType = "generated" sound.present = "TRUE" sound.fileName = "-1" sound.autodetect = "TRUE" pciBridge0.present = "TRUE" pciBridge4.present = "TRUE" pciBridge4.virtualDev = "pcieRootPort" pciBridge4.functions = "8" pciBridge5.present = "TRUE" pciBridge5.virtualDev = "pcieRootPort" pciBridge5.functions = "8" pciBridge6.present = "TRUE" pciBridge6.virtualDev = "pcieRootPort" pciBridge6.functions = "8" pciBridge7.present = "TRUE" pciBridge7.virtualDev = "pcieRootPort" pciBridge7.functions = "8" vmci0.present = "TRUE" hpet0.present = "TRUE" displayName = "vm" guestOS = "other-64" nvram = "vm.nvram" virtualHW.productCompatibility = "hosted" powerType.powerOff = "soft" powerType.powerOn = "soft" powerType.suspend = "soft" powerType.reset = "soft" extendedConfigFile = "vm.vmxf" floppy0.present = "TRUE" floppy0.fileType = "file" floppy0.fileName = "a.img" floppy0.clientDevice = "FALSE" ide1:1.present = "FALSE" numa.autosize.vcpu.maxPerVirtualNode = "8" numa.autosize.cookie = "80001" uuid.bios = "56 4d 7d ca 1a f4 3a f5-56 4f dd da 39 38 a1 15" uuid.location = "56 4d 7d ca 1a f4 3a f5-56 4f dd da 39 38 a1 15" migrate.hostlog = ".\vm-e7233550.hlog" pciBridge0.pciSlotNumber = "17" pciBridge4.pciSlotNumber = "21" pciBridge5.pciSlotNumber = "22" pciBridge6.pciSlotNumber = "23" pciBridge7.pciSlotNumber = "24" scsi0.pciSlotNumber = "16" ethernet0.pciSlotNumber = "32" sound.pciSlotNumber = "33" vmci0.pciSlotNumber = "34" ethernet0.generatedAddress = "00:0c:29:38:a1:15" ethernet0.generatedAddressOffset = "0" vmci0.id = "960012565" monitor.phys_bits_used = "42" vmotion.checkpointFBSize = "134217728" vmotion.checkpointSVGAPrimarySize = "134217728" cleanShutdown = "TRUE" softPowerOff = "FALSE" checkpoint.vmState = "" svga.vramSize = "134217728" ================================================ FILE: vm.vmxf ================================================ 52 02 53 21 5d ef 94 b8-dc 4b 85 9c d9 6d f4 1b vm.vmx ================================================ FILE: vmxhost64.asm ================================================ USE64 ; https://www.intel.com/content/www/us/en/architecture-and-technology/64-ia-32-architectures-software-developer-vol-2b-manual.html ; Full 2B manual ; ---------------- Existance test ---------------- VMX_ExistenceTest: ; RAX 1 if VMX is supported MOV RAX,1 CPUID XOR EAX,EAX BTC ECX,5 JNC .f MOV EAX,1 .f: RET ; ---------------- A20 routines in 64 bit ---------------- VMX_EnableA20: push ax in al,92h or al,02 out 92h,al pop ax ret VMX_DisableA20: push ax in al,92h and al,0fdh out 92h,al pop ax ret ; ---------------- Init the structures ---------------- VMX_Init_Structures: ; Read MSR xor eax,eax mov ecx,0480h rdmsr linear ecx,VMXRevision,VMXDATA64 ; EAX holds the revision ; EDX lower 13 bits hold the max size mov [ecx],eax and edx,8191 linear ecx,VMXStructureSize,VMXDATA64 mov [ecx],edx ; Initialize 4096 structure datas for VMX xor eax,eax mov ax,VMXDATA64 shl eax,4 ; physical Loop5X: test eax,01fffh jz Loop5End inc eax jmp Loop5X Loop5End: linear ecx,VMXStructureData1,VMXDATA64 mov dword [ecx],eax add eax,4096 linear ecx,VMXStructureData2,VMXDATA64 mov dword [ecx],eax RET VMX_Initialize_VMX_Controls: ; edx = 0x82 for unrestricted guestm, 0x2 if simple with EPT vmw32 0x4012,0x11FF ; Entry. Ideally, we must read 0x484 MSR to learn what to put here ; bit 9 - Guest is in long mode ; bit 10 - Guest is in SMM ; bit 11 - Deactivate Dual monitor treatment ; We can use also 0x4014 to control MSRs -> if different than the host (mighty) vmw32 0x4000,0x1F ; PIN, Intel 3B Chapter 20.6.1 ; vmw32 0x4002,0x8401e9f2; Proc, Intel 3B Chapter 20.6.2 vmw32 0x4002,0x840069F2; Proc, Intel 3B Chapter 20.6.2, Leave CR3 access so we can enable long mode vmw32 0x401E,edx vmw32 0x400C,0x36FFF RET VMX_Initialize_Host: ; We initialize ; CR0, CR3 , CR4 ; CS:RIP for entry after VMExit ; SS:RSP for entry after VMExit ; DS,ES,TR ; GDTR,IDTR ; RCX = IP ; CRX vmw64 0x6C00,cr0 vmw64 0x6C02,cr3 vmw64 0x6C04,cr4 ; CS:RIP vmw16 0xC02,cs vmw64 0x6C16,rcx ; SS:RSP vmw16 0xC04,ss vmw64 0x6C14,rsp ; DS,ES,FS,GS,TR vmw16 0xC06,ds vmw16 0xC00,es vmw16 0xC08,fs vmw16 0xC0A,gs vmw16 0xC0C,tssd32_idx ; GDTR, IDTR linear rdi,TempData,VMXDATA64 sgdt [rdi] ; 10 bytes : 2 limit and 8 item mov rax,[rdi + 2] mov rbx,0x6C0C vmwrite rbx,rax linear rdi,TempData,VMXDATA64 sidt [rdi] ; 10 bytes : 2 limit and 8 item mov rax,[rdi + 2] mov rbx,0x6C0E vmwrite rbx,rax ; EFER mov ecx, 0c0000080h ; EFER MSR number. rdmsr ; Read EFER. mov rbx,0x2C02 vmwrite rbx,rax RET VMX_InitializeEPT: xor rdi,rdi linear rax,PhysicalEptOffset64,DATA16 mov rdi,[rax] ; Clear everything push rdi xor rax,rax mov ecx,8192 rep stosq pop rdi ; RSI to PDPT mov rsi,rdi add rsi,8*512 ; first pml4t entry xor rax,rax mov rax,rsi ; RAX now points to the RSI (First PDPT entry) shl rax,12 ; So we move it to bit 12 shr rax,12 ; We remove the lower 4096 bits or rax,7 ; Add the RWE bits mov [rdi],rax ; Store the PML4T entry. We only need 1 entry ; First PDPT entry (1st GB) xor rax,rax or rax,7 ; Add the RWE bits bts rax,7 ; Add the 7th "S" bit to tell the CPU that this doesn't refer to a PDT mov [rsi],rax ; Store the PMPT entry for 1st GB ; Second PDPT entry (2nd GB) add rsi,8 xor rax,rax mov rax,1024*1024*1024*1 shr rax,12 shl rax,12 or rax,7 ; Add the RWE bits bts rax,7 ; Add the 7th "S" bit to tell the CPU that this doesn't refer to a PDT mov [rsi],rax ; Store the PMPT entry for 2nd GB ; Third PDPT entry (3rd GB) add rsi,8 xor rax,rax mov rax,1024*1024*1024*2 shr rax,12 shl rax,12 or rax,7 ; Add the RWE bits bts rax,7 ; Add the 7th "S" bit to tell the CPU that this doesn't refer to a PDT mov [rsi],rax ; Store the PMPT entry for 3rd GB ; Fourh PDPT entry (4th GB) add rsi,8 xor rax,rax mov rax,1024*1024*1024*3 shr rax,12 shl rax,12 or rax,7 ; Add the RWE bits bts rax,7 ; Add the 7th "S" bit to tell the CPU that this doesn't refer to a PDT mov [rsi],rax ; Store the PMPT entry for 4th GB RET ; A Protected mode guest VMX_Initialize_Guest2: ; r8 -> selector ; r9 -> base ; r10 -> entry xor rax,rax ; cr0,cr3,cr4 paging protected mode ; cs ss:rip ; flags ; CRx mov ebx,0x6800 ; CR0 mov eax,0x80000031 ; And the NX bit must be set bts eax,31 ; And Paging bit enabled vmwrite rbx,rax mov ebx,0x6802 ; CR3 xor rax,rax linear rax,PhysicalPagingOffset32,DATA16 mov eax,[rax] vmwrite rbx,rax mov ebx,0x6804 ; CR4 mov eax,0 bts eax,13 ; the 13th bit of CR4 must be set in VMX mode ;bts eax,4 ; Page Size 4MB vmwrite rbx,rax ; Flags mov ebx,0x6820 ; RFLAGS mov rax,2 vmwrite rbx,rax ; Startup from r9 : r10 ; cs stuff xor rax,rax mov rax,r8 mov ebx,0x802 ; CS selector vmwrite rbx,rax xor rax,rax mov rax,0xfffff mov ebx,0x4802 ; CS limit vmwrite rbx,rax mov rax,0c09fh mov ebx,0x4816 ; CS access vmwrite rbx,rax xor rax,rax mov rax,r9 shl rax,4 mov ebx,0x6808 ; CS base vmwrite rbx,rax ; xchg bx,bx mov ebx,0x681E ; IP xor rax,rax add rax,r10 vmwrite rbx,rax ; GDTR,IDTR mov ebx,0x6816 ; GDTR Base ;mov rax,gdt_ptr linear rax,gdt_ptr,DATA16 add rax,4 vmwrite rbx,rax mov ebx,0x4810 ; Limit mov rax,gdt_size vmwrite rbx,rax mov ebx,0x6818 ; IDTR Base mov rax,idt_PM_ptr vmwrite rbx,rax mov ebx,0x4812 ; Limit mov rax,idt_size vmwrite rbx,rax ; DR7 mov ebx,0x681A ; DR7 mov rax,0x400 vmwrite rbx,rax ; SEGMENT registers ; es,ss,ds,fs,gs vmw16 0x800,page32_idx vmw16 0x804,page32_idx vmw16 0x806,page32_idx vmw16 0x808,page32_idx vmw16 0x80A,page32_idx ; Limits vmw32 0x4800,0xFFFFF vmw32 0x4804,0xFFFFF vmw32 0x4806,0xFFFFF vmw32 0x4808,0xFFFFF vmw32 0x480A,0xFFFFF ; Access vmw16 0x4814,0x0C093 vmw16 0x4818,0x0C093 vmw16 0x481A,0x0C093 vmw16 0x481C,0x0C093 vmw16 0x481E,0x0C093 ; base vmw32 0x6806,0 vmw32 0x680A,0 vmw32 0x680C,0 vmw32 0x680E,0 vmw32 0x6810,0 ; LDT (Dummy) xor rax,rax mov ax,ldt_idx mov ebx,0x80C ; LDT selector vmwrite rbx,rax mov rax,0xffffffff mov ebx,0x480C ; LDT limit vmwrite rbx,rax mov rax,0x10000 mov ebx,0x4820 ; LDT access vmwrite rbx,rax mov rax,0 mov ebx,0x6812 ; LDT base vmwrite rbx,rax ; TR (Dummy) xor rax,rax mov ax,tssd32_idx mov ebx,0x80E ; TR selector vmwrite rbx,rax mov rax,0xff mov ebx,0x480E ; TR limit vmwrite rbx,rax mov rax,0x8b mov ebx,0x4822 ; TR access vmwrite rbx,rax mov rax,0 mov ebx,0x6814 ; TR base vmwrite rbx,rax RET ; A real mode guest VMX_Initialize_UnrestrictedGuest: ; cr0,cr3,cr4 real mode ; cs ss:rip ; flags xor rax,rax ; CRx mov ebx,0x6800 ; CR0 mov eax,0x60000030 ; And the NX bit must be set vmwrite rbx,rax mov ebx,0x6802 ; CR3 mov eax,0 vmwrite rbx,rax mov ebx,0x6804 ; CR4 mov eax,0 bts eax,13 ; the 13th bit of CR4 must be set in VMX mode vmwrite rbx,rax ; Flags mov ebx,0x6820 ; RFLAGS mov rax,2 vmwrite rbx,rax ; Startup from VMX16 : StartVM ; cs stuff xor rax,rax mov ax,code32_idx mov ebx,0x802 ; CS selector vmwrite rbx,rax xor rax,rax mov rax,0xffff mov ebx,0x4802 ; CS limit vmwrite rbx,rax mov rax,09fh mov ebx,0x4816 ; CS access vmwrite rbx,rax xor rax,rax mov rax,r9 shl rax,4 mov ebx,0x6808 ; CS base vmwrite rbx,rax mov ebx,0x681E ; IP xor rax,rax mov rax,r10 vmwrite rbx,rax ; GDTR,IDTR mov ebx,0x6816 ; GDTR Base mov rax,0 vmwrite rbx,rax mov ebx,0x4810 ; Limit mov rax,0xFFFF vmwrite rbx,rax mov ebx,0x6818 ; IDTR Base mov rax,0 vmwrite rbx,rax mov ebx,0x4812 ; Limit mov rax,0xFFFF vmwrite rbx,rax ; DR7 mov ebx,0x681A ; DR7 mov rax,0x400 vmwrite rbx,rax ; SEGMENT registers ; es,ss,ds,fs,gs vmw16 0x800,data32_idx vmw16 0x804,data32_idx vmw16 0x806,data32_idx vmw16 0x808,data32_idx vmw16 0x80A,data32_idx ; Limits vmw32 0x4800,0xFFFF vmw32 0x4804,0xFFFF vmw32 0x4806,0xFFFF vmw32 0x4808,0xFFFF vmw32 0x480A,0xFFFF ; Access vmw16 0x4814,0x93 vmw16 0x4818,0x93 vmw16 0x481A,0x93 vmw16 0x481C,0x93 vmw16 0x481E,0x93 ; base mov rax,r9 shl rax,4 vmw64 0x6806,rax vmw64 0x680A,rax vmw64 0x680C,rax vmw64 0x680E,rax vmw64 0x6810,rax ; LDT (Dummy) xor rax,rax mov ax,ldt_idx mov ebx,0x80C ; LDT selector vmwrite rbx,rax mov rax,0xffffffff mov ebx,0x480C ; LDT limit vmwrite rbx,rax mov rax,0x10000 mov ebx,0x4820 ; LDT access vmwrite rbx,rax mov rax,0 mov ebx,0x6812 ; LDT base vmwrite rbx,rax ; TR (Dummy) xor rax,rax mov ax,tssd32_idx mov ebx,0x80E ; TR selector vmwrite rbx,rax mov rax,0xff mov ebx,0x480E ; TR limit vmwrite rbx,rax mov rax,0x8b mov ebx,0x4822 ; TR access vmwrite rbx,rax mov rax,0 mov ebx,0x6814 ; TR base vmwrite rbx,rax RET ; ---------------- Enable VMX ---------------- VMX_Enable: ; A20 ; call VMX_DisableA20 ; cr4 mov rax,cr4 bts rax,13 mov cr4,rax ; Load the revision linear rdi,VMXRevision,VMXDATA64 mov ebx,[edi]; ; Initialize the VMXON region linear rdi,VMXStructureData1,VMXDATA64 mov rcx,[rdi]; Get address of data1 mov rsi,rdi mov rdi,rcx ; CR0 bit 5 mov rax,cr0 bts rax,5 mov cr0,rax ; MSR 0x3ah lock bit 0 mov ecx,03ah rdmsr test eax,1 jnz .VMX_LB_Enabled or eax,1 wrmsr .VMX_LB_Enabled: ; Execute the VMXON mov [rdi],ebx ; // Put the revision mov rax,[rsi] VMXON [rsi] RET ; ---------------- Disable VMX ---------------- VMX_Disable: VMXOFF ; A20 ;call VMX_EnableA20 mov rax,cr4 btc rax,13 mov cr4,rax RET ; ---------------- VMX Host Exit ---------------- VMX_VMExit: nop ; Disable call VMX_Disable RET VMXInit: ; Load the revision atlinear rbx,VMXRevision,VMXDATA64 ; Initialize the region linear rdi,VMXStructureData2,VMXDATA64 mov rcx,[rdi]; Get address of data1 mov rsi,rdi mov rdi,rcx mov [rdi],ebx ; // Put the revision VMCLEAR [rsi] mov [rdi],ebx ; // Put the revision VMPTRLD [rsi] mov [rdi],ebx ; // Put the revision RET VMXInit2: ; The EPT initialization for the guest linear rax,PhysicalEptOffset64,DATA16 mov rax,[rax] or rax,0 ; Memory Type 0 or rax,0x18 ; Page Walk Length 3 mov rbx,0x201A ; EPTP vmwrite rbx,rax ; The Link Pointer -1 initialization mov rax,0xFFFFFFFFFFFFFFFF mov rbx,0x2800 ; LP vmwrite rbx,rax ; One more RSP initialization of the host xor rax,rax mov rbx,0x6c14 ; RSP mov rax,rsp add rax,8 ; because we are in a function call vmwrite rbx,rax RET ; ---------------- Host Start ---------------- VMX_Host: linear rbx,vmt1,DATA16 mov byte [rbx],0 call VMX_ExistenceTest cmp rax,1 jz .yvmx RET .yvmx: linear rbx,vmt1,DATA16 mov byte [rbx],1 ; Init structures call VMX_Init_Structures ; Enable call VMX_Enable if TEST_VMX = 1 ; Real mode guest (unrestricted) call VMXInit call VMX_InitializeEPT xor rdx,rdx bts rdx,1 bts rdx,7 call VMX_Initialize_VMX_Controls linear rcx,VMX_VMExit,CODE64 call VMX_Initialize_Host mov r9,VMX16 mov r10,StartVM call VMX_Initialize_UnrestrictedGuest call VMXInit2 ; Launch it!! VMLAUNCH end if if TEST_VMX = 2 ; Protected mode guest call VMXInit ; Initializzation mov rdx,0x49 call VMX_Initialize_VMX_Controls linear rcx,VMX_VMExit,CODE64 call VMX_Initialize_Host mov r8,vmx32_idx mov r9,VMX32 mov r10,StartVM2 call VMX_Initialize_Guest2 call VMXInit2 ; Launch it!! VMLAUNCH end if ; If we get here, VMLAUNCH failed ; Disable call VMX_Disable RET