1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886 |
- /*++
- Copyright (c) 2012 Minoca Corp.
- This file is licensed under the terms of the GNU General Public License
- version 3. Alternative licensing terms are available. Contact
- info@minocacorp.com for details. See the LICENSE file at the root of this
- project for complete licensing information.
- Module Name:
- x86dis.c
- Abstract:
- This module contains routines for disassembling x86 binary code.
- Author:
- Evan Green 21-Jun-2012
- Environment:
- Debugging client
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/lib/types.h>
- #include "disasm.h"
- #include <stdio.h>
- #include <string.h>
- #include <assert.h>
- //
- // --------------------------------------------------------------------- Macros
- //
- //
- // Define macros to get at the pieces of the ModRM byte. This also adds the
- // extra bit extended by the REX byte, which if not present is a no-op, as it
- // will be zero.
- //
- #define X86_MODRM_MOD(_ModRm) (((_ModRm) & X86_MOD_MASK) >> X86_MOD_SHIFT)
- #define X86_MODRM_REG(_Instruction, _ModRm) \
- ((((_ModRm) & X86_REG_MASK) >> X86_REG_SHIFT) | \
- (((_Instruction)->Rex & X64_REX_R) << 1))
- #define X86_MODRM_RM(_Instruction, _ModRm) \
- ((((_ModRm) & X86_RM_MASK) >> X86_RM_SHIFT) | \
- (((_Instruction)->Rex & X64_REX_B) << 3))
- //
- // Define macros to get the fields of the Scale-Index-Base byte, extending
- // index and base with the REX bits.
- //
- #define X86_SIB_BASE(_Instruction) \
- ((((_Instruction)->Sib & X86_BASE_MASK) >> X86_BASE_SHIFT) | \
- (((_Instruction)->Rex & X64_REX_B) << 3))
- #define X86_SIB_INDEX(_Instruction) \
- ((((_Instruction)->Sib & X86_INDEX_MASK) >> X86_INDEX_SHIFT) | \
- (((_Instruction)->Rex & X64_REX_X) << 2))
- #define X86_SIB_SCALE(_Instruction) \
- (1 << (((_Instruction)->Sib & X86_SCALE_MASK) >> X86_SCALE_SHIFT))
- //
- // This macro un-extends a register, just getting the 3-bit value.
- //
- #define X86_BASIC_REG(_Reg) ((_Reg) & 0x7)
- //
- // This macro creates a fake REX prefix from a VEX byte.
- //
- #define X64_VEX_TO_REX(_Vex, _VexMap) \
- (X64_REX_VALUE | ((~(_Vex) >> 5) & 0x7) | (((_VexMap) >> 4) & X64_REX_W))
- //
- // This macro gets the V register out of the VEX byte.
- //
- #define X64_VEX_V(_Vex) ((~(_Vex) >> 3) & 0x0F)
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // Define the meanings of some of size characters used in the encoding table.
- //
- #define X86_WIDTH_BYTE 'b'
- #define X86_WIDTH_WORD 'w'
- #define X86_WIDTH_LONG 'l'
- #define X86_WIDTH_LONGLONG 'q'
- #define X86_WIDTH_OWORD 'o'
- #define X86_WIDTH_YWORD 'y'
- #define X86_WIDTH_ZWORD 'z'
- #define X86_FLOATING_POINT_REGISTER 'f'
- #define X86_CONTROL_REGISTER 'C'
- #define X86_DEBUG_REGISTER 'D'
- #define X86_SEGMENT_REGISTER 'S'
- //
- // Define the internal bitfields of the ModR/M and SIB byte.
- //
- #define X86_MOD_MASK 0xC0
- #define X86_REG_MASK 0x38
- #define X86_RM_MASK 0x07
- #define X86_MOD_SHIFT 6
- #define X86_REG_SHIFT 3
- #define X86_RM_SHIFT 0
- #define X86_SCALE_MASK 0xC0
- #define X86_INDEX_MASK 0x38
- #define X86_BASE_MASK 0x07
- #define X86_SCALE_SHIFT 6
- #define X86_INDEX_SHIFT 3
- #define X86_BASE_SHIFT 0
- //
- // Define the X64 REX bits.
- //
- //
- // This bit indicates a 64-bit operand size.
- //
- #define X64_REX_W 0x08
- //
- // This bit is an extension to the ModRM reg field.
- //
- #define X64_REX_R 0x04
- //
- // This bit is an extension to the SIB index field.
- //
- #define X64_REX_X 0x02
- //
- // This bit is an extension to the ModRM rm field, or SIB base field.
- //
- #define X64_REX_B 0x01
- //
- // This bit is set to indicate 256 bit registers are in use.
- //
- #define X64_VEX_L 0x04
- //
- // This bit is called W/E, and is often the equivalent of the REX W bit.
- //
- #define X64_VEX_W 0x80
- //
- // Define some of the prefixes that can come at the beginning of an instruction.
- //
- #define X86_MAX_PREFIXES 5
- #define X86_OPERAND_OVERRIDE 0x66
- #define X86_ADDRESS_OVERRIDE 0x67
- #define X86_ESCAPE_OPCODE 0x0F
- #define X86_PREFIX_LOCK 0xF0
- #define X86_PREFIX_REPN 0xF2
- #define X86_PREFIX_REP 0xF3
- #define X86_PREFIX_CS 0x2E
- #define X86_PREFIX_DS 0x3E
- #define X86_PREFIX_ES 0x26
- #define X86_PREFIX_FS 0x64
- #define X86_PREFIX_GS 0x65
- #define X86_PREFIX_SS 0x36
- #define X64_REX_MASK 0xF0
- #define X64_REX_VALUE 0x40
- #define X64_XOP 0x8F
- #define X64_VEX3 0xC4
- #define X64_VEX2 0xC5
- #define X64_VEX2_MAP_SELECT 0x61
- #define X86_INVALID_GROUP 99
- //
- // Define the sizes of the register name arrays.
- //
- #define X86_REGISTER_NAME_COUNT 16
- //
- // Define the size of the working buffers.
- //
- #define X86_WORKING_BUFFER_SIZE 100
- //
- // Define some x87 floating point support definitions, constants used in
- // decoding an x87 coprocessor instruction.
- //
- #define X87_ESCAPE_OFFSET 0xD8
- #define X87_FCOM_MASK 0xF8
- #define X87_FCOM_OPCODE 0xD0
- #define X87_D9_E0_OFFSET 0xE0
- #define X87_DA_C0_MASK 0x38
- #define X87_DA_CO_SHIFT 3
- #define X87_FUCOMPP_OPCODE 0xE9
- #define X87_DB_C0_MASK 0x38
- #define X87_DB_C0_SHIFT 3
- #define X87_DB_E0_INDEX 4
- #define X87_DB_E0_MASK 0x7
- #define X87_DF_C0_MASK 0x38
- #define X87_DF_C0_SHIFT 3
- #define X87_DF_E0_INDEX 4
- #define X87_DF_E0_MASK 0x07
- #define X87_DF_E0_COUNT 3
- #define X87_REGISTER_TARGET "Rf"
- #define X87_ST0_TARGET "!est"
- #define X87_FLD_MNEMONIC "fld"
- #define X87_FXCH_MNEMONIC "fxch"
- #define X87_NOP_MNEMONIC "fnop"
- #define X87_FSTP1_MNEMONIC "fstp1"
- #define X87_FUCOMPP_MNEMONIC "fucompp"
- #define X87_DF_E0_TARGET "!eax"
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- /*++
- Structure Description:
- This structure provides basic information about an instruction, including
- its mnemonic name, operand encodings, and additional parsing information.
- Members:
- Mnemonic - Stores a pointer to the string containing the opcode's mnemonic.
- Target - Stores a pointer to a string describing the destination operand's
- encoding.
- Source - Stores a pointer to a string describing the source operand's
- encoding.
- Third - Stores a pointer to a string describing the third operand.
- Group - Stores the opcode group number. Some instructions require furthur
- decoding, the group number indicates that.
- --*/
- typedef struct _X86_INSTRUCTION_DEFINITION {
- PSTR Mnemonic;
- PSTR Target;
- PSTR Source;
- PSTR Third;
- INT Group;
- } X86_INSTRUCTION_DEFINITION, *PX86_INSTRUCTION_DEFINITION;
- /*++
- Structure Description:
- This structure provides the mnemonic switch for an opcode group.
- Members:
- Group - Stores the group number.
- Mnemonics - Stores the mnemonics for each opcode in the group.
- --*/
- typedef struct _X86_OPCODE_GROUP {
- INT Group;
- PSTR Mnemonics[8];
- } X86_OPCODE_GROUP, *PX86_OPCODE_GROUP;
- /*++
- Structure Description:
- This structure stores information about an instructions mnemonics and
- encoding when an array index is wasteful for describing the actual opcode
- number.
- Members:
- Prefix - Stores the specfic prefix value for which this instruction is
- valid.
- Opcode - Stores the opcode this definition defines.
- Instruction - Stores an array describing the mnemonics and encoding of the
- instruction.
- --*/
- typedef struct _X86_SPARSE_INSTRUCTION_DEFINITION {
- BYTE Prefix;
- BYTE Opcode;
- X86_INSTRUCTION_DEFINITION Instruction;
- } X86_SPARSE_INSTRUCTION_DEFINITION, *PX86_SPARSE_INSTRUCTION_DEFINITION;
- /*++
- Structure Description:
- This structure stores all binary information about a decoded instruction.
- Members:
- Language - Stores the machine language type being decoded. Valid values are
- x86 and x64.
- InstructionPointer - Stores the current instruction pointer, used for
- computing the operand address of RIP-relative addresses.
- Prefix - Stores up to 4 prefix bytes, which is the maximum number of
- allowed prefixes in x86 instructions.
- Opcode - Stores the first (and many times only) opcode byte.
- Opcode2 - Stores the second opcode byte, if necessary (as determined by the
- first opcode byte).
- ModRm - Stores the ModR/M byte of the instruction, if one exists. Bits 6-7
- describe the Mod part of the instruction, which can describe what sort
- of addressing/displacement is encoded in the instruction. Bits 5-3 hold
- the Reg data, which stores either a register number or additional
- decoding information for instruction groups. Bits 2-0 store the R/M
- byte, which either stores another register value or describes how the
- memory information is encoded.
- Sib - Stores the Scale/Index/Base byte of the opcode, if one exists.
- Addressing with an sib byte usually looks like (Base + index * 2^Scale),
- where Base and Index are both general registers. Bits 6-7 describe the
- scale, which is raised to the power of two (and can therefore describe a
- scale of 1, 2, 4, or 8). Bits 5-3 describe the index register, and bits
- 2-0 describe the base register, both of which are encoded like the Reg
- field for general registers.
- Rex - Stores the REX byte for 64-bit register extension.
- Vex - Stores the VEX byte (the last byte of the VEX prefix) if there is one.
- VexMap - Stores the second to last byte of the VEX prefix, which includes
- the map select and ~RXB bits. For a two-byte VEX prefix, a specific
- value is inferred, which is set here.
- Displacement - Stores the displacement of the instruction operand.
- Immediate - Stores the immediate value that may or may not be encoded in the
- instruction.
- Length - Stores the total size of this instruction encoding in bytes.
- DisplacementSize - Stores the size in bytes of the displacement value. Once
- the Displacement field is populated, this field is not too useful.
- ImmediateSize - Stores the size in bytes of the immediate value. Once the
- Immediate field is populated, this field is not too useful.
- OperandOverride - Stores a flag indicating whether or not the operand
- override prefix was on this instruction.
- AddressOverrride - Stores a flag indicating whether or not the address
- override prefix was specified on this instruction.
- Definition - Stores a the instruction decoding information,
- including the instruction mnemonic.
- Lock - Stores a lock string or an empty string, depending on whether or not
- the lock prefix was supplied.
- Rep - Stores a rep string or an empty string depending on whether or not
- the rep prefix was supplied.
- SegmentPrefix - Stores the segment prefix string, or an empty string if
- there is no segment prefix.
- --*/
- typedef struct _X86_INSTRUCTION {
- MACHINE_LANGUAGE Language;
- ULONGLONG InstructionPointer;
- BYTE Prefix[X86_MAX_PREFIXES];
- BYTE Opcode;
- BYTE Opcode2;
- BYTE ModRm;
- BYTE Sib;
- BYTE Rex;
- BYTE Vex;
- BYTE VexMap;
- ULONGLONG Displacement;
- ULONGLONG Immediate;
- ULONG Length;
- ULONG DisplacementSize;
- ULONG ImmediateSize;
- BOOL OperandOverride;
- BOOL AddressOverride;
- X86_INSTRUCTION_DEFINITION Definition;
- PCSTR Lock;
- PCSTR Rep;
- PCSTR SegmentPrefix;
- } X86_INSTRUCTION, *PX86_INSTRUCTION;
- typedef enum _X86_REGISTER_VALUE {
- X86RegisterValueAx,
- X86RegisterValueCx,
- X86RegisterValueDx,
- X86RegisterValueBx,
- X86RegisterValueSp,
- X86RegisterValueBp,
- X86RegisterValueSi,
- X86RegisterValueDi,
- X86RegisterValueR8,
- X86RegisterValueR9,
- X86RegisterValueR10,
- X86RegisterValueR11,
- X86RegisterValueR12,
- X86RegisterValueR13,
- X86RegisterValueR14,
- X86RegisterValueR15,
- X86RegisterValueScaleIndexBase,
- X86RegisterValueDisplacement32,
- X86RegisterValueRipRelative
- } X86_REGISTER_VALUE, *PX86_REGISTER_VALUE;
- typedef enum _X86_MOD_VALUE {
- X86ModValueNoDisplacement,
- X86ModValueDisplacement8,
- X86ModValueDisplacement32,
- X86ModValueRegister
- } X86_MOD_VALUE, *PX86_MOD_VALUE;
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // Define the x86 instruction encodings. A 6 after the width character of the
- // opcode format indicates that the default operand size is 64 bits in long
- // mode.
- //
- X86_INSTRUCTION_DEFINITION DbgX86Instructions[256] = {
- {"add", "Eb", "Gb", "", 0}, /* 00 */
- {"add", "Ev", "Gv", "", 0}, /* 01 */
- {"add", "Gb", "Eb", "", 0}, /* 02 */
- {"add", "Gv", "Ev", "", 0}, /* 03 */
- {"add", "!bal", "Ib", "", 0}, /* 04 */
- {"add", "!r0", "Iz", "", 0}, /* 05 */
- {"push", "!wes", "", "", 0}, /* 06 */
- {"pop", "!wes", "", "", 0}, /* 07 */
- {"or", "Eb", "Gb", "", 0}, /* 08 */
- {"or", "Ev", "Gv", "", 0}, /* 09 */
- {"or", "Gb", "Eb", "", 0}, /* 0A */
- {"or", "Gv", "Ev", "", 0}, /* 0B */
- {"or", "!bal", "Ib", "", 0}, /* 0C */
- {"or", "!r0", "Iz", "", 0}, /* 0D */
- {"push", "!wcs", "", "", 0}, /* 0E */
- {"2BYTE", "", "", "", X86_INVALID_GROUP}, /* 0F */ /* Two Byte Opcodes */
- {"adc", "Eb", "Gb", "", 0}, /* 10 */
- {"adc", "Ev", "Gv", "", 0}, /* 11 */
- {"adc", "Gb", "Eb", "", 0}, /* 12 */
- {"adc", "Gv", "Ev", "", 0}, /* 13 */
- {"adc", "!bal", "Ib", "", 0}, /* 14 */
- {"adc", "!r0", "Iz", "", 0}, /* 15 */
- {"push", "!wss", "", "", 0}, /* 16 */
- {"pop", "!wss", "", "", 0}, /* 17 */
- {"sbb", "Eb", "Gb", "", 0}, /* 18 */
- {"sbb", "Ev", "Gv", "", 0}, /* 19 */
- {"sbb", "Gb", "Eb", "", 0}, /* 1A */
- {"sbb", "Gv", "Ev", "", 0}, /* 1B */
- {"sbb", "!bal", "Ib", "", 0}, /* 1C */
- {"sbb", "!r0", "Iz", "", 0}, /* 1D */
- {"push", "!wds", "", "", 0}, /* 1E */
- {"pop", "!wds", "", "", 0}, /* 1F */
- {"and", "Eb", "Gb", "", 0}, /* 20 */
- {"and", "Ev", "Gv", "", 0}, /* 21 */
- {"and", "Gb", "Eb", "", 0}, /* 22 */
- {"and", "Gv", "Ev", "", 0}, /* 23 */
- {"and", "!bal", "Ib", "", 0}, /* 24 */
- {"and", "!r0", "Iz", "", 0}, /* 25 */
- {"ES:", "", "", "", X86_INVALID_GROUP}, /* 26 */ /* ES prefix */
- {"daa", "", "", "", 0}, /* 27 */
- {"sub", "Eb", "Gb", "", 0}, /* 28 */
- {"sub", "Ev", "Gv", "", 0}, /* 29 */
- {"sub", "Gb", "Eb", "", 0}, /* 2A */
- {"sub", "Gv", "Ev", "", 0}, /* 2B */
- {"sub", "!bal", "Ib", "", 0}, /* 2C */
- {"sub", "!r0", "Iz", "", 0}, /* 2D */
- {"CS:", "", "", "", X86_INVALID_GROUP}, /* 2E */ /* CS prefix */
- {"das", "", "", "", 0}, /* 2F */
- {"xor", "Eb", "Gb", "", 0}, /* 30 */
- {"xor", "Ev", "Gv", "", 0}, /* 31 */
- {"xor", "Gb", "Eb", "", 0}, /* 32 */
- {"xor", "Gv", "Ev", "", 0}, /* 33 */
- {"xor", "!bal", "Ib", "", 0}, /* 34 */
- {"xor", "!r0", "Iz", "", 0}, /* 35 */
- {"SS:", "", "", "", X86_INVALID_GROUP}, /* 36 */ /* SS prefix */
- {"aaa", "", "", "", 0}, /* 37 */
- {"cmp", "Eb", "Gb", "", 0}, /* 38 */
- {"cmp", "Ev", "Gv", "", 0}, /* 39 */
- {"cmp", "Gb", "Eb", "", 0}, /* 3A */
- {"cmp", "Gv", "Ev", "", 0}, /* 3B */
- {"cmp", "!bal", "Ib", "", 0}, /* 3C */
- {"cmp", "!r0", "Iz", "", 0}, /* 3D */
- {"DS:", "", "", "", X86_INVALID_GROUP}, /* 3E */ /* DS prefix */
- {"aas", "", "", "", 0}, /* 3F */
- {"inc", "!r0", "", "", 0}, /* 40 */
- {"inc", "!r1", "", "", 0}, /* 41 */
- {"inc", "!r2", "", "", 0}, /* 42 */
- {"inc", "!r3", "", "", 0}, /* 43 */
- {"inc", "!r4", "", "", 0}, /* 44 */
- {"inc", "!r5", "", "", 0}, /* 45 */
- {"inc", "!r6", "", "", 0}, /* 46 */
- {"inc", "!r7", "", "", 0}, /* 47 */
- {"dec", "!r0", "", "", 0}, /* 48 */
- {"dec", "!r1", "", "", 0}, /* 49 */
- {"dec", "!r2", "", "", 0}, /* 4A */
- {"dec", "!r3", "", "", 0}, /* 4B */
- {"dec", "!r4", "", "", 0}, /* 4C */
- {"dec", "!r5", "", "", 0}, /* 4D */
- {"dec", "!r6", "", "", 0}, /* 4E */
- {"dec", "!r7", "", "", 0}, /* 4F */
- {"push", "!r06", "", "", 0}, /* 50 */
- {"push", "!r16", "", "", 0}, /* 51 */
- {"push", "!r26", "", "", 0}, /* 52 */
- {"push", "!r36", "", "", 0}, /* 53 */
- {"push", "!r46", "", "", 0}, /* 54 */
- {"push", "!r56", "", "", 0}, /* 55 */
- {"push", "!r66", "", "", 0}, /* 56 */
- {"push", "!r76", "", "", 0}, /* 57 */
- {"pop", "!r06", "", "", 0}, /* 58 */
- {"pop", "!r16", "", "", 0}, /* 59 */
- {"pop", "!r26", "", "", 0}, /* 5A */
- {"pop", "!r36", "", "", 0}, /* 5B */
- {"pop", "!r46", "", "", 0}, /* 5C */
- {"pop", "!r56", "", "", 0}, /* 5D */
- {"pop", "!r66", "", "", 0}, /* 5E */
- {"pop", "!r76", "", "", 0}, /* 5F */
- {"pushad", "", "", "", 0}, /* 60 */
- {"popad", "", "", "", 0}, /* 61 */
- {"bound", "Gv", "Ma", "", 0}, /* 62 */
- {"movsxd", "Gv", "Ed", "", 0}, /* 63 */ /* Was arpl in 286+ */
- {"FS:", "", "", "", X86_INVALID_GROUP}, /* 64 */ /* FS prefix */
- {"GS:", "", "", "", X86_INVALID_GROUP}, /* 65 */ /* GS prefix */
- {"OPSIZE:", "", "", "", X86_INVALID_GROUP}, /* 66 */ /* Operand override */
- {"ADSIZE:", "", "", "", X86_INVALID_GROUP}, /* 67 */ /* Address override */
- {"push", "Iz", "", "", 0}, /* 68 */
- {"imul", "Gv", "Ev", "Iz", 0}, /* 69 */
- {"push", "Ib", "", "", 0}, /* 6A */
- {"imul", "Gv", "Ev", "Ib", 0}, /* 6B */
- {"ins", "Yb", "!wdx", "", 0}, /* 6C */
- {"ins", "Yz", "!wdx", "", 0}, /* 6D */
- {"outs", "!wdx", "Xb", "", 0}, /* 6E */
- {"outs", "!wdx", "Xz", "", 0}, /* 6F */
- {"jo ", "Jb", "", "", 0}, /* 70 */
- {"jno", "Jb", "", "", 0}, /* 71 */
- {"jb ", "Jb", "", "", 0}, /* 72 */
- {"jnb", "Jb", "", "", 0}, /* 73 */
- {"jz ", "Jb", "", "", 0}, /* 74 */
- {"jnz", "Jb", "", "", 0}, /* 75 */
- {"jbe", "Jb", "", "", 0}, /* 76 */
- {"jnbe", "Jb", "", "", 0}, /* 77 */
- {"js ", "Jb", "", "", 0}, /* 78 */
- {"jns", "Jb", "", "", 0}, /* 79 */
- {"jp ", "Jb", "", "", 0}, /* 7A */
- {"jnp", "Jb", "", "", 0}, /* 7B */
- {"jl ", "Jb", "", "", 0}, /* 7C */
- {"jnl", "Jb", "", "", 0}, /* 7D */
- {"jle", "Jb", "", "", 0}, /* 7E */
- {"jnle", "Jb", "", "", 0}, /* 7F */
- {"GRP1", "Eb", "Ib", "", 1}, /* 80 */ /* Group 1 opcodes. */
- {"GRP1", "Ev", "Iz", "", 1}, /* 81 */ /* Reg of ModR/M */
- {"GRP1", "Eb", "Ib", "", 1}, /* 82 */ /* extends opcode.*/
- {"GRP1", "Ev", "Ib", "", 1}, /* 83 */
- {"test", "Eb", "Gb", "", 0}, /* 84 */
- {"test", "Ev", "Gv", "", 0}, /* 85 */
- {"xchg", "Eb", "Eb", "", 0}, /* 86 */
- {"xchg", "Ev", "Gv", "", 0}, /* 87 */
- {"mov", "Eb", "Gb", "", 0}, /* 88 */
- {"mov", "Ev", "Gv", "", 0}, /* 89 */
- {"mov", "Gb", "Eb", "", 0}, /* 8A */
- {"mov", "Gv", "Ev", "", 0}, /* 8B */
- {"mov", "Ev", "Sw", "", 0}, /* 8C */
- {"lea", "Gv", "M", "", 0}, /* 8D */
- {"mov", "Sw", "Ev", "", 0}, /* 8E */
- {"pop", "Ev6", "", "", 0}, /* 8F */
- {"nop", "", "", "", 0}, /* 90 */
- {"xchg", "!r1", "!r0", "", 0}, /* 91 */
- {"xchg", "!r2", "!r0", "", 0}, /* 92 */
- {"xchg", "!r3", "!r0", "", 0}, /* 93 */
- {"xchg", "!r4", "!r0", "", 0}, /* 94 */
- {"xchg", "!r5", "!r0", "", 0}, /* 95 */
- {"xchg", "!r6", "!r0", "", 0}, /* 96 */
- {"xchg", "!r7", "!r0", "", 0}, /* 97 */
- {"cwde", "", "", "", 0}, /* 98 */
- {"cdq", "", "", "", 0}, /* 99 */
- {"call", "Ap", "", "", 0}, /* 9A */
- {"fwait", "", "", "", 0}, /* 9B */
- {"pushf", "", "", "", 0}, /* 9C */ /* arg1 = Fv */
- {"popf", "", "", "", 0}, /* 9D */ /* arg1 = Fv */
- {"sahf", "", "", "", 0}, /* 9E */
- {"lafh", "", "", "", 0}, /* 9F */
- {"mov", "!bal", "Ob", "", 0}, /* A0 */
- {"mov", "!r0", "Ov", "", 0}, /* A1 */
- {"mov", "Ob", "!bal", "", 0}, /* A2 */
- {"mov", "Ov", "!r0", "", 0}, /* A3 */
- {"movs", "Yb", "Xb", "", 0}, /* A4 */
- {"movs", "Yv", "Xv", "", 0}, /* A5 */
- {"cmps", "Yb", "Xb", "", 0}, /* A6 */
- {"cmps", "Yv", "Xv", "", 0}, /* A7 */
- {"test", "!bal", "Ib", "", 0}, /* A8 */
- {"test", "!r0", "Iz", "", 0}, /* A9 */
- {"stos", "Yb", "!bal", "", 0}, /* AA */
- {"stos", "Yv", "!r0", "", 0}, /* AB */
- {"lods", "!bal", "Xb", "", 0}, /* AC */
- {"lods", "!r0", "Xv", "", 0}, /* AD */
- {"scas", "Yb", "!bal", "", 0}, /* AE */
- {"scas", "Yv", "!r0", "", 0}, /* AF */
- {"mov", "!b0", "Ib", "", 0}, /* B0 */
- {"mov", "!b1", "Ib", "", 0}, /* B1 */
- {"mov", "!b2", "Ib", "", 0}, /* B2 */
- {"mov", "!b3", "Ib", "", 0}, /* B3 */
- {"mov", "!b4", "Ib", "", 0}, /* B4 */
- {"mov", "!b5", "Ib", "", 0}, /* B5 */
- {"mov", "!b6", "Ib", "", 0}, /* B6 */
- {"mov", "!b7", "Ib", "", 0}, /* B7 */
- {"mov", "!r0", "Iv", "", 0}, /* B8 */
- {"mov", "!r1", "Iv", "", 0}, /* B9 */
- {"mov", "!r2", "Iv", "", 0}, /* BA */
- {"mov", "!r3", "Iv", "", 0}, /* BB */
- {"mov", "!r4", "Iv", "", 0}, /* BC */
- {"mov", "!r5", "Iv", "", 0}, /* BD */
- {"mov", "!r6", "Iv", "", 0}, /* BE */
- {"mov", "!r7", "Iv", "", 0}, /* BF */
- {"GRP2", "Eb", "Ib", "", 2}, /* C0 */ /* Group 2 */
- {"GRP2", "Ev", "Ib", "", 2}, /* C1 */ /* Group 2 */
- {"ret", "Iw", "", "", 0}, /* C2 */
- {"ret", "", "", "", 0}, /* C3 */
- {"les", "Gz", "Mp", "", 0}, /* C4 */
- {"lds", "Gz", "Mp", "", 0}, /* C5 */
- {"mov", "Eb", "Ib", "", 11}, /* C6 */ /* Group 11 */
- {"mov", "Ev", "Iz", "", 11}, /* C7 */ /* Group 11 */
- {"enter", "Iw", "Ib", "", 0}, /* C8 */
- {"leave", "", "", "", 0}, /* C9 */
- {"retf", "Iw", "", "", 0}, /* CA */
- {"retf", "", "", "", 0}, /* CB */
- {"int", "!e3", "", "", 0}, /* CC */
- {"int", "Ib", "", "", 0}, /* CD */
- {"into", "", "", "", 0}, /* CE */
- {"iret", "", "", "", 0}, /* CF */
- {"GRP2", "Eb", "!e1", "", 2}, /* D0 */ /* Group 2, arg2 = 1 */
- {"GRP2", "Ev", "!e1", "", 2}, /* D1 */ /* Group 2, arg2 = 1 */
- {"GRP2", "Eb", "!bcl", "", 2}, /* D2 */ /* Group 2 */
- {"GRP2", "Ev", "!bcl", "", 2}, /* D3 */ /* Group 2 */
- {"aam", "Ib", "", "", 0}, /* D4 */
- {"aad", "Ib", "", "", 0}, /* D5 */
- {"setalc", "", "", "", 0}, /* D6 */
- {"xlat", "", "", "", 0}, /* D7 */
- {"ESC0", "Ev", "", "", 0x87}, /* D8 */ /* x87 Floating Pt */
- {"ESC1", "Ev", "", "", 0x87}, /* D9 */
- {"ESC2", "Ev", "", "", 0x87}, /* DA */
- {"ESC3", "Ev", "", "", 0x87}, /* DB */
- {"ESC4", "Ev", "", "", 0x87}, /* DC */
- {"ESC5", "Ev", "", "", 0x87}, /* DD */
- {"ESC6", "Ev", "", "", 0x87}, /* DE */
- {"ESC7", "Ev", "", "", 0x87}, /* DF */
- {"loopnz", "Jb", "", "", 0}, /* E0 */
- {"loopz", "Jb", "", "", 0}, /* E1 */
- {"loop", "Jb", "", "", 0}, /* E2 */
- {"jcxz", "Jb", "", "", 0}, /* E3 */
- {"in ", "!bal", "Ib", "", 0}, /* E4 */
- {"in ", "!eeax", "Iv", "", 0}, /* E5 */
- {"out", "Ib", "!bal", "", 0}, /* E6 */
- {"out", "Ib", "!eeax", "", 0}, /* E7 */
- {"call", "Jz6", "", "", 0}, /* E8 */
- {"jmp", "Jz6", "", "", 0}, /* E9 */
- {"jmp", "Ap", "", "", 0}, /* EA */
- {"jmp", "Jb", "", "", 0}, /* EB */
- {"in ", "!bal", "!wdx", "", 0}, /* EC */
- {"in ", "!eeax", "!wdx", "", 0}, /* ED */
- {"out", "!wdx", "!bal", "", 0}, /* EE */
- {"out", "!wdx", "!eeax", "", 0}, /* EF */
- {"LOCK:", "", "", "", 0}, /* F0 */ /* Lock prefix */
- {"int", "!e1", "", "", 0}, /* F1 */ /* Int 1 */
- {"REPNE:", "", "", "", 0}, /* F2 */ /* Repne prefix */
- {"REP:", "", "", "", 0}, /* F3 */ /* Rep prefix */
- {"hlt", "", "", "", 0}, /* F4 */
- {"cmc", "", "", "", 0}, /* F5 */
- {"GRP3", "Eb", "", "", 3}, /* F6 */ /* Group 3 */
- {"GRP3", "Ev", "", "", 3}, /* F7 */ /* Group 3 */
- {"clc", "", "", "", 0}, /* F8 */
- {"stc", "", "", "", 0}, /* F9 */
- {"cli", "", "", "", 0}, /* FA */
- {"sti", "", "", "", 0}, /* FB */
- {"cld", "", "", "", 0}, /* FC */
- {"std", "", "", "", 0}, /* FD */
- {"GRP4", "Eb", "", "", 4}, /* FE */ /* Group 4 */
- {"GRP5", "Ev", "", "", 5}, /* FF */ /* Group 5 */
- };
- X86_SPARSE_INSTRUCTION_DEFINITION DbgX86TwoByteInstructions[] = {
- {0, 0x0, {"GRP6", "Ev", "", "", 6}}, /* Group 6 */
- {0, 0x1, {"GRP7", "Ev", "", "", 7}}, /* Group 7 */
- {0, 0x2, {"lar", "Gv", "Ew", "", 0}},
- {0, 0x3, {"lsl", "Gv", "Ew", "", 0}},
- {0, 0x5, {"syscall", "", "", "", 0}},
- {0, 0x6, {"clts", "", "", "", 0}},
- {0, 0x7, {"sysret", "", "", "", 0}},
- {0, 0x8, {"invd", "", "", "", 0}},
- {0, 0x9, {"wbinvd", "", "", "", 0}},
- {0, 0xA, {"cl1invmb", "", "", "", 0}},
- {0, 0xB, {"ud1", "", "", "", 0}},
- {0, 0x10, {"movups", "Vx", "Wx", "", 0}},
- {0, 0x11, {"movups", "Wx", "Vx", "", 0}},
- {0, 0x12, {"movlps", "Vo", "Ho", "Mo.q", 0}},
- {0, 0x13, {"movlps", "Mo.q", "Vo", "", 0}},
- {0, 0x14, {"unpcklps", "Vx", "Hx", "Wx", 0}},
- {0, 0x15, {"unpckhps", "Vx", "Hx", "Wx", 0}},
- {0, 0x16, {"movhps", "Vo", "Ho", "Uo", 0}},
- {0, 0x17, {"movhps", "Mo.q", "Vo", "", 0}},
- {0, 0x18, {"GRP16", "M", "", "", 16}}, /* Group 16 */
- {0, 0x19, {"GRP16", "M", "", "", 16}},
- {0, 0x1A, {"GRP16", "M", "", "", 16}},
- {0, 0x1B, {"GRP16", "M", "", "", 16}},
- {0, 0x1C, {"GRP16", "M", "", "", 16}},
- {0, 0x1D, {"GRP16", "M", "", "", 16}},
- {0, 0x1E, {"GRP16", "M", "", "", 16}},
- {0, 0x1F, {"GRP16", "M", "", "", 16}},
- {0x66, 0x10, {"movupd", "Vx", "Wx", "", 0}},
- {0x66, 0x11, {"movupd", "Wx", "Vx", "", 0}},
- {0x66, 0x12, {"movlpd", "Vo", "Ho", "Mo.q", 0}},
- {0x66, 0x13, {"movlpd", "Mo.q", "Vo", "", 0}},
- {0x66, 0x14, {"unpcklpd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x15, {"unpckhpd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x16, {"movhpd", "Vo", "Ho", "Mo.q", 0}},
- {0x66, 0x17, {"movhpd", "Mo.q", "Vo", "", 0}},
- {0x66, 0x18, {"GRP16", "M", "", "", 16}},
- {0x66, 0x19, {"GRP16", "M", "", "", 16}},
- {0x66, 0x1A, {"GRP16", "M", "", "", 16}},
- {0x66, 0x1B, {"GRP16", "M", "", "", 16}},
- {0x66, 0x1C, {"GRP16", "M", "", "", 16}},
- {0x66, 0x1D, {"GRP16", "M", "", "", 16}},
- {0x66, 0x1E, {"GRP16", "M", "", "", 16}},
- {0x66, 0x1F, {"GRP16", "M", "", "", 16}},
- {0xF3, 0x10, {"movss", "Vo", "Mo.d", "", 0}},
- {0xF3, 0x11, {"movss", "Mo.d", "Vo", "", 0}},
- {0xF3, 0x12, {"movsldup", "Vx", "Wx", "", 0}},
- {0xF3, 0x16, {"movshdup", "Vx", "Wx", "", 0}},
- {0xF3, 0x18, {"GRP16", "M", "", "", 16}},
- {0xF3, 0x19, {"GRP16", "M", "", "", 16}},
- {0xF3, 0x1A, {"GRP16", "M", "", "", 16}},
- {0xF3, 0x1B, {"GRP16", "M", "", "", 16}},
- {0xF3, 0x1C, {"GRP16", "M", "", "", 16}},
- {0xF3, 0x1D, {"GRP16", "M", "", "", 16}},
- {0xF3, 0x1E, {"GRP16", "M", "", "", 16}},
- {0xF3, 0x1F, {"GRP16", "M", "", "", 16}},
- {0xF2, 0x10, {"movsd", "Vo", "Mo.d", "", 0}},
- {0xF2, 0x11, {"movsd", "Mo.d", "Vo", "", 0}},
- {0xF2, 0x12, {"movddup", "Vx", "Wx", "", 0}},
- {0xF2, 0x18, {"GRP16", "M", "", "", 16}},
- {0xF2, 0x19, {"GRP16", "M", "", "", 16}},
- {0xF2, 0x1A, {"GRP16", "M", "", "", 16}},
- {0xF2, 0x1B, {"GRP16", "M", "", "", 16}},
- {0xF2, 0x1C, {"GRP16", "M", "", "", 16}},
- {0xF2, 0x1D, {"GRP16", "M", "", "", 16}},
- {0xF2, 0x1E, {"GRP16", "M", "", "", 16}},
- {0xF2, 0x1F, {"GRP16", "M", "", "", 16}},
- {0, 0x20, {"mov", "Ry6", "Cy", "", 0}},
- {0, 0x21, {"mov", "Ry6", "Dy", "", 0}},
- {0, 0x22, {"mov", "Cy", "Ry6", "", 0}},
- {0, 0x23, {"mov", "Dy", "Ry6", "", 0}},
- {0, 0x24, {"mov", "Ry6", "Ty", "", 0}},
- {0, 0x26, {"mov", "Ty", "Ry6", "", 0}},
- {0, 0x28, {"movaps", "Vx", "Wx", "", 0}},
- {0, 0x29, {"movaps", "Wx", "Vx", "", 0}},
- {0, 0x2A, {"cvtpi2ps", "Vo", "Mq", "", 0}},
- {0, 0x2B, {"movntps", "Mx", "Vx", "", 0}},
- {0, 0x2C, {"cvttps2pi", "Pq", "Wo.q", "", 0}},
- {0, 0x2D, {"cvtps2pi", "Pq", "Wo.q", "", 0}},
- {0, 0x2E, {"ucomiss", "Vo", "Wo.d", "", 0}},
- {0, 0x2F, {"comiss", "Vo", "Wo.d", "", 0}},
- {0xF0, 0x20, {"mov", "Rd", "!ecr8", "", 0}},
- {0xF0, 0x22, {"mov", "!ecr8", "Rd", "", 0}},
- {0x66, 0x28, {"movapd", "Vx", "Wx", "", 0}},
- {0x66, 0x29, {"movapd", "Wx", "Vx", "", 0}},
- {0x66, 0x2A, {"cvtpi2pd", "Vo", "Mq", "", 0}},
- {0x66, 0x2B, {"movntpd", "Mx", "Vx", "", 0}},
- {0x66, 0x2C, {"cvttpd2pi", "Pq", "Wo", "", 0}},
- {0x66, 0x2D, {"cvtpd2pi", "Pq", "Wo", "", 0}},
- {0x66, 0x2E, {"ucomisd", "Vo", "Wo.q", "", 0}},
- {0x66, 0x2F, {"comisd", "Vo", "Wo.q", "", 0}},
- {0xF3, 0x2A, {"cvtsi2ss", "Vo", "Ho", "Ey", 0}},
- {0xF3, 0x2B, {"movntss", "Md", "Vo", "", 0}},
- {0xF3, 0x2C, {"cvttss2si", "Gy", "Wo.d", "", 0}},
- {0xF3, 0x2D, {"cvtss2si", "Gy", "Wo.d", "", 0}},
- {0xF2, 0x2A, {"cvtsi2sd", "Vo", "Ho", "Ey", 0}},
- {0xF2, 0x2B, {"movntsd", "Md", "Vo", "", 0}},
- {0xF2, 0x2C, {"cvttsd2si", "Gy", "Wo.q", "", 0}},
- {0xF2, 0x2D, {"cvtsd2si", "Gy", "Wo.q", "", 0}},
- {0, 0x30, {"wrmsr", "", "", "", 0}},
- {0, 0x31, {"rdtsc", "", "", "", 0}},
- {0, 0x32, {"rdmsr", "", "", "", 0}},
- {0, 0x33, {"rdpmc", "", "", "", 0}},
- {0, 0x34, {"sysenter", "", "", "", 0}},
- {0, 0x35, {"sysexit", "", "", "", 0}},
- {0, 0x37, {"getsec", "", "", "", 0}},
- {0, 0x40, {"cmovo", "Gv", "Ev", "", 0}},
- {0, 0x41, {"cmovno", "Gv", "Ev", "", 0}},
- {0, 0x42, {"cmovb", "Gv", "Ev", "", 0}},
- {0, 0x43, {"cmovnb", "Gv", "Ev", "", 0}},
- {0, 0x44, {"cmovz", "Gv", "Ev", "", 0}},
- {0, 0x45, {"cmovnz", "Gv", "Ev", "", 0}},
- {0, 0x46, {"cmovbe", "Gv", "Ev", "", 0}},
- {0, 0x47, {"cmovnbe", "Gv", "Ev", "", 0}},
- {0, 0x48, {"cmovs", "Gv", "Ev", "", 0}},
- {0, 0x49, {"cmovns", "Gv", "Ev", "", 0}},
- {0, 0x4A, {"cmovp", "Gv", "Ev", "", 0}},
- {0, 0x4B, {"cmovnp", "Gv", "Ev", "", 0}},
- {0, 0x4C, {"cmovl", "Gv", "Ev", "", 0}},
- {0, 0x4D, {"cmovnl", "Gv", "Ev", "", 0}},
- {0, 0x4E, {"cmovle", "Gv", "Ev", "", 0}},
- {0, 0x4F, {"cmovnle", "Gv", "Ev", "", 0}},
- {0, 0x50, {"movmskps", "Gy", "Ux", "", 0}},
- {0, 0x51, {"sqrtps", "Vx", "Wx", "", 0}},
- {0, 0x52, {"rsqrtps", "Vx", "Wx", "", 0}},
- {0, 0x53, {"rcpps", "Vx", "Wx", "", 0}},
- {0, 0x54, {"andps", "Vx", "Hx", "Wx", 0}},
- {0, 0x55, {"andnps", "Vx", "Hx", "Wx", 0}},
- {0, 0x56, {"orps", "Vx", "Hx", "Wx", 0}},
- {0, 0x57, {"xorps", "Vx", "Hx", "Wx", 0}},
- {0, 0x58, {"addps", "Vx", "Hx", "Wx", 0}},
- {0, 0x59, {"mulps", "Vx", "Hx", "Wx", 0}},
- {0, 0x5A, {"cvtps2pd", "Vo", "Wo.q", "", 0}},
- {0, 0x5B, {"cvtdq2ps", "Vx", "Wx", "", 0}},
- {0, 0x5C, {"subps", "Vx", "Hx", "Wx", 0}},
- {0, 0x5D, {"minps", "Vx", "Hx", "Wx", 0}},
- {0, 0x5E, {"divps", "Vx", "Hx", "Wx", 0}},
- {0, 0x5F, {"maxps", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x50, {"movmskpd", "Gy", "Ux", "", 0}},
- {0x66, 0x51, {"sqrtpd", "Vx", "Wx", "", 0}},
- {0x66, 0x54, {"andpd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x55, {"andnpd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x56, {"orpd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x57, {"xorpd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x58, {"addpd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x59, {"mulpd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x5A, {"cvtpd2ps", "Vo", "Wo", "", 0}},
- {0x66, 0x5B, {"cvtps2dq", "Vx", "Wx", "", 0}},
- {0x66, 0x5C, {"subpd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x5D, {"minpd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x5E, {"divpd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x5F, {"maxpd", "Vx", "Hx", "Wx", 0}},
- {0xF3, 0x51, {"sqrtss", "Vo", "Ho", "Wo.d", 0}},
- {0xF3, 0x52, {"rsqrtss", "Vo", "Ho", "Wo.d", 0}},
- {0xF3, 0x53, {"rcpss", "Vo", "Ho", "Wo.d", 0}},
- {0xF3, 0x58, {"addss", "Vo", "Ho", "Wo.d", 0}},
- {0xF3, 0x59, {"mulss", "Vo", "Ho", "Wo.d", 0}},
- {0xF3, 0x5A, {"cvtss2sd", "Vo", "Ho", "Wo.d", 0}},
- {0xF3, 0x5B, {"cvttps2dq", "Vx", "Wx", "", 0}},
- {0xF3, 0x5C, {"subss", "Vo", "Ho", "Wo.d", 0}},
- {0xF3, 0x5D, {"minss", "Vo", "Ho", "Wo.d", 0}},
- {0xF3, 0x5E, {"divss", "Vo", "Ho", "Wo.d", 0}},
- {0xF3, 0x5F, {"maxss", "Vo", "Ho", "Wo.d", 0}},
- {0xF2, 0x51, {"sqrtsd", "Vo", "Ho", "Wo.q", 0}},
- {0xF2, 0x58, {"addsd", "Vo", "Ho", "Wo.q", 0}},
- {0xF2, 0x59, {"mulsd", "Vo", "Ho", "Wo.q", 0}},
- {0xF2, 0x5A, {"cvtsd2ss", "Vo", "Ho", "Wo.q", 0}},
- {0xF2, 0x5C, {"subsd", "Vo", "Ho", "Wo.q", 0}},
- {0xF2, 0x5D, {"minsd", "Vo", "Ho", "Wo.q", 0}},
- {0xF2, 0x5E, {"divsd", "Vo", "Ho", "Wo.q", 0}},
- {0xF2, 0x5F, {"maxsd", "Vo", "Ho", "Wo.q", 0}},
- {0, 0x60, {"punpcklbw", "Pq", "Qd", "", 0}},
- {0, 0x61, {"punpcklwd", "Pq", "Qd", "", 0}},
- {0, 0x62, {"punpckldq", "Pq", "Qd", "", 0}},
- {0, 0x63, {"packsswb", "Pq", "Qq", "", 0}},
- {0, 0x64, {"pcmpgtb", "Pq", "Qq", "", 0}},
- {0, 0x65, {"pcmpgtw", "Pq", "Qq", "", 0}},
- {0, 0x66, {"pcmpgtd", "Pq", "Qq", "", 0}},
- {0, 0x67, {"packuswb", "Pq", "Qq", "", 0}},
- {0, 0x68, {"punpckhbw", "Pq", "Qq", "", 0}},
- {0, 0x69, {"punpckhwd", "Pq", "Qq", "", 0}},
- {0, 0x6A, {"punpckhdq", "Pq", "Qq", "", 0}},
- {0, 0x6B, {"packssdw", "Pq", "Qq", "", 0}},
- {0, 0x6E, {"movd", "Pq", "Ey", "", 0}},
- {0, 0x6F, {"movq", "Pq", "Qq", "", 0}},
- {0x66, 0x60, {"unpcklbw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x61, {"punpcklwd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x62, {"punpckldq", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x63, {"packsswb", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x64, {"pcmpgtb", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x65, {"pcmpgtw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x66, {"pcmpgtd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x67, {"packuswb", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x68, {"punpckhbw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x69, {"punpckhwd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x6A, {"punpckhdq", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x6B, {"packssdw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x6C, {"punpckl-qdq", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x6D, {"punpckh-qdq", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x6E, {"movd", "Vo", "Ey", "", 0}},
- {0x66, 0x6F, {"movdqa", "Vx", "Wx", "", 0}},
- {0xF3, 0x6F, {"movdqu", "Vx", "Wx", "", 0}},
- {0, 0x70, {"pshufw", "Pq", "Qq", "Ib", 0}},
- {0, 0x71, {"GRP12", "Nb", "Iq", "", 12}},
- {0, 0x72, {"GRP13", "Nb", "Iq", "", 13}},
- {0, 0x73, {"GRP14", "Nb", "Iq", "", 14}},
- {0, 0x74, {"pcmpeqb", "Pq", "Qq", "", 0}},
- {0, 0x75, {"pcmpeqw", "Pq", "Qq", "", 0}},
- {0, 0x76, {"pcmpeqd", "Pq", "Qq", "", 0}},
- {0, 0x77, {"emms", "", "", "", 0}},
- {0, 0x78, {"vmread", "Ey", "Gy", "", 0}},
- {0, 0x79, {"vmwrite", "Gy", "Ey", "", 0}},
- {0, 0x7E, {"movd", "Ey", "Pq", "", 0}},
- {0, 0x7F, {"movq", "Qq", "Pq", "", 0}},
- {0x66, 0x70, {"pshufd", "Vx", "Wx", "Ib", 0}},
- {0x66, 0x71, {"GRP12", "Nb", "Iq", "", 12}},
- {0x66, 0x72, {"GRP13", "Nb", "Iq", "", 13}},
- {0x66, 0x73, {"GRP14", "Nb", "Iq", "", 14}},
- {0x66, 0x74, {"pcmpeqb", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x75, {"pcmpeqw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x76, {"pcmpeqd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x7C, {"haddpd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x7D, {"hsubpd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0x7E, {"movd", "Ey", "Vo", "", 0}},
- {0x66, 0x7F, {"movdqa", "Wx", "Vx", "", 0}},
- {0xF3, 0x70, {"pshufhw", "Vx", "Wx", "Ib", 0}},
- {0xF3, 0x71, {"GRP12", "Nb", "Iq", "", 12}},
- {0xF3, 0x72, {"GRP13", "Nb", "Iq", "", 13}},
- {0xF3, 0x73, {"GRP14", "Nb", "Iq", "", 14}},
- {0xF3, 0x7E, {"movq", "Vo", "Wo.q", "", 0}},
- {0xF3, 0x7F, {"movdqu", "Wx", "Vx", "", 0}},
- {0xF2, 0x70, {"pshuflw", "Vx", "Wx", "Ib", 0}},
- {0xF2, 0x71, {"GRP12", "Nb", "Iq", "", 12}},
- {0xF2, 0x72, {"GRP13", "Nb", "Iq", "", 13}},
- {0xF2, 0x73, {"GRP14", "Nb", "Iq", "", 14}},
- {0xF2, 0x7C, {"haddps", "Vx", "Hx", "Wx", 0}},
- {0xF2, 0x7D, {"hsubps", "Vx", "Hx", "Wx", 0}},
- {0, 0x80, {"jo ", "Jz", "", "", 0}},
- {0, 0x81, {"jno", "Jz", "", "", 0}},
- {0, 0x82, {"jb ", "Jz", "", "", 0}},
- {0, 0x83, {"jnb", "Jz", "", "", 0}},
- {0, 0x84, {"jz ", "Jz", "", "", 0}},
- {0, 0x85, {"jnz", "Jz", "", "", 0}},
- {0, 0x86, {"jbe", "Jz", "", "", 0}},
- {0, 0x87, {"jnbe", "Jz", "", "", 0}},
- {0, 0x88, {"js ", "Jz", "", "", 0}},
- {0, 0x89, {"jns", "Jz", "", "", 0}},
- {0, 0x8A, {"jp", "Jz", "", "", 0}},
- {0, 0x8B, {"jnp", "Jz", "", "", 0}},
- {0, 0x8C, {"jl ", "Jz", "", "", 0}},
- {0, 0x8D, {"jnl", "Jz", "", "", 0}},
- {0, 0x8E, {"jle", "Jz", "", "", 0}},
- {0, 0x8F, {"jnle", "Jz", "", "", 0}},
- {0, 0x90, {"seto", "Eb", "", "", 0}},
- {0, 0x91, {"setno", "Eb", "", "", 0}},
- {0, 0x92, {"setb", "Eb", "", "", 0}},
- {0, 0x93, {"setnb", "Eb", "", "", 0}},
- {0, 0x94, {"setz", "Eb", "", "", 0}},
- {0, 0x95, {"setnz", "Eb", "", "", 0}},
- {0, 0x96, {"setbe", "Eb", "", "", 0}},
- {0, 0x97, {"setnbe", "Eb", "", "", 0}},
- {0, 0x98, {"sets", "Eb", "", "", 0}},
- {0, 0x99, {"setns", "Eb", "", "", 0}},
- {0, 0x9A, {"setp", "Eb", "", "", 0}},
- {0, 0x9B, {"setnp", "Eb", "", "", 0}},
- {0, 0x9C, {"setl", "Eb", "", "", 0}},
- {0, 0x9D, {"setnl", "Eb", "", "", 0}},
- {0, 0x9E, {"setle", "Eb", "", "", 0}},
- {0, 0x9F, {"setnle", "Eb", "", "", 0}},
- {0, 0xA0, {"push", "!wfs", "", "", 0}},
- {0, 0xA1, {"pop", "!wfs", "", "", 0}},
- {0, 0xA2, {"cpuid", "", "", "", 0}},
- {0, 0xA3, {"bt ", "Ev", "Gv", "", 0}},
- {0, 0xA4, {"shld", "Ev", "Gv", "Ib", 0}},
- {0, 0xA5, {"shld", "Ev", "Gv", "!b1", 0}},
- {0, 0xA6, {"cmpxchg", "", "", "", 0}},
- {0, 0xA7, {"cmpxchg", "", "", "", 0}},
- {0, 0xA8, {"push", "!wgs", "", "", 0}},
- {0, 0xA9, {"pop", "!gs", "", "", 0}},
- {0, 0xAA, {"rsm", "", "", "", 0}},
- {0, 0xAB, {"bts", "Ev", "Gv", "", 0}},
- {0, 0xAC, {"shrd", "Ev", "Gv", "Ib", 0}},
- {0, 0xAD, {"shrd", "Ev", "Gv", "!b1", 0}},
- {0, 0xAE, {"GRP15", "M", "", "", 15}}, /* Group 15 */
- {0, 0xAF, {"imul", "Gv", "Ev", "", 0}},
- {0xF3, 0xAE, {"GRP15A", "Ry", "", "", 0x15A}}, /* Group 15A */
- {0, 0xB0, {"cmpxchg", "Eb", "Gb", "", 0}},
- {0, 0xB1, {"cmpxchg", "Ev", "Gv", "", 0}},
- {0, 0xB2, {"lss", "Gz", "Mp", "", 0}},
- {0, 0xB3, {"btr", "Ev", "Gv", "", 0}},
- {0, 0xB4, {"lfs", "Gz", "Mp", "", 0}},
- {0, 0xB5, {"lgs", "Gz", "Mp", "", 0}},
- {0, 0xB6, {"movzx", "Gv", "Eb", "", 0}},
- {0, 0xB7, {"movxz", "Gv", "Ew", "", 0}},
- {0, 0xB8, {"jmpe", "Jz", "", "", 0}},
- {0, 0xB9, {"ud2", "", "", "", 0}}, /* Group 10 */
- {0, 0xBA, {"GRP8", "Ev", "Ib", "", 8}}, /* Group 8 */
- {0, 0xBB, {"btc", "Ev", "Gv", "", 0}},
- {0, 0xBC, {"bsf", "Gv", "Ev", "", 0}},
- {0, 0xBD, {"bsr", "Gv", "Ev", "", 0}},
- {0, 0xBE, {"movsx", "Gv", "Eb", "", 0}},
- {0, 0xBF, {"movsx", "Gv", "Ew", "", 0}},
- {0xF3, 0xB8, {"popcnt", "Gv", "Ev", "", 0}},
- {0xF3, 0xBD, {"lzcnt", "Gv", "Ev", "", 0}},
- {0, 0xC0, {"xadd", "Eb", "Gb", "", 0}},
- {0, 0xC1, {"xadd", "Ev", "Gv", "", 0}},
- {0, 0xC2, {"cmpccps", "Vx", "Hx", "Wx", 0}},/* Also has Ib */
- {0, 0xC3, {"movnti", "My", "Gy", "", 0}},
- {0, 0xC4, {"pinsrw", "Pq", "Mw", "Ib", 0}},
- {0, 0xC5, {"pextrw", "Gy", "Nq", "Ib", 0}},
- {0, 0xC6, {"shufps", "Vx", "Hx", "Wx", 0}}, /* Also has Ib */
- {0, 0xC7, {"GRP9", "M", "", "", 9}}, /* Group 9 */
- {0, 0xC8, {"bswap", "!r0", "", "", 0}},
- {0, 0xC9, {"bswap", "!r1", "", "", 0}},
- {0, 0xCA, {"bswap", "!r2", "", "", 0}},
- {0, 0xCB, {"bswap", "!r3", "", "", 0}},
- {0, 0xCC, {"bswap", "!r4", "", "", 0}},
- {0, 0xCD, {"bswap", "!r5", "", "", 0}},
- {0, 0xCE, {"bswap", "!r6", "", "", 0}},
- {0, 0xCF, {"bswap", "!r7", "", "", 0}},
- {0x66, 0xC0, {"xadd", "Eb", "Gb", "", 0}},
- {0x66, 0xC1, {"xadd", "Ev", "Gv", "", 0}},
- {0x66, 0xC2, {"cmpccpd", "Vx", "Hx", "Wx", 0}}, /* Also has Ib */
- {0x66, 0xC4, {"pinsrw", "Vo", "Ho", "Mw", 0}}, /* Also has Ib */
- {0x66, 0xC5, {"pextrw", "Gy", "Uo", "Ib", 0}},
- {0x66, 0xC6, {"shufpd", "Vx", "Hx", "Wx", 0}}, /* Also has Ib */
- {0x66, 0xC7, {"GRP9", "M", "", "", 9}}, /* Group 9 */
- {0xF3, 0xC0, {"xadd", "Eb", "Gb", "", 0}},
- {0xF3, 0xC1, {"xadd", "Ev", "Gv", "", 0}},
- {0xF3, 0xC2, {"cmpccss", "Vo", "Ho", "Wo.d", 0}}, /* Also has Ib */
- {0xF3, 0xC7, {"GRP9", "M", "", "", 9}}, /* Group 9 */
- {0xF2, 0xC0, {"xadd", "Eb", "Gb", "", 0}},
- {0xF2, 0xC1, {"xadd", "Ev", "Gv", "", 0}},
- {0xF2, 0xC2, {"cmpccss", "Vo", "Ho", "Wo.d", 0}}, /* Also has Ib */
- {0xF2, 0xC7, {"GRP9", "M", "", "", 9}}, /* Group 9 */
- {0, 0xD1, {"psrlw", "Pq", "Qq", "", 0}},
- {0, 0xD2, {"psrld", "Pq", "Qq", "", 0}},
- {0, 0xD3, {"psrlq", "Pq", "Qq", "", 0}},
- {0, 0xD4, {"paddq", "Pq", "Qq", "", 0}},
- {0, 0xD5, {"pmullw", "Pq", "Qq", "", 0}},
- {0, 0xD7, {"pmovmskb", "Gy", "Nq", "", 0}},
- {0, 0xD8, {"psubusb", "Pq", "Qq", "", 0}},
- {0, 0xD9, {"psubusw", "Pq", "Qq", "", 0}},
- {0, 0xDA, {"pminub", "Pq", "Qq", "", 0}},
- {0, 0xDB, {"pand", "Pq", "Qq", "", 0}},
- {0, 0xDC, {"paddusb", "Pq", "Qq", "", 0}},
- {0, 0xDD, {"paddusw", "Pq", "Qq", "", 0}},
- {0, 0xDE, {"pmaxub", "Pq", "Qq", "", 0}},
- {0, 0xDF, {"pandn", "Pq", "Qq", "", 0}},
- {0x66, 0xD0, {"addsubpd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xD1, {"psrlw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xD2, {"psrld", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xD3, {"psrlq", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xD4, {"paddq", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xD5, {"pmullw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xD6, {"pmovq", "Wo.q", "Vo", "", 0}},
- {0x66, 0xD7, {"pmovmskb", "Gy", "Ux", "", 0}},
- {0x66, 0xD8, {"psubusb", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xD9, {"psubusw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xDA, {"pminub", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xDB, {"pand", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xDC, {"paddusb", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xDD, {"paddusw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xDE, {"pmaxub", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xDF, {"pandn", "Vx", "Hx", "Wx", 0}},
- {0xF3, 0xD6, {"movq2dq", "Vo", "Nq", "", 0}},
- {0xF2, 0xD0, {"addsubps", "Vx", "Hx", "Wx", 0}},
- {0xF2, 0xD6, {"movdq2q", "Pq", "Uq", "", 0}},
- {0, 0xE0, {"pavgb", "Pq", "Qq", "", 0}},
- {0, 0xE1, {"psraw", "Pq", "Qq", "", 0}},
- {0, 0xE2, {"psrad", "Pq", "Qq", "", 0}},
- {0, 0xE3, {"pavgw", "Pq", "Qq", "", 0}},
- {0, 0xE4, {"pmulhuw", "Pq", "Qq", "", 0}},
- {0, 0xE5, {"pmulhw", "Pq", "Qq", "", 0}},
- {0, 0xE7, {"movntq", "Mq", "Pq", "", 0}},
- {0, 0xE8, {"psubsb", "Pq", "Qq", "", 0}},
- {0, 0xE9, {"psubsw", "Pq", "Qq", "", 0}},
- {0, 0xEA, {"pminsw", "Pq", "Qq", "", 0}},
- {0, 0xEB, {"por", "Pq", "Qq", "", 0}},
- {0, 0xEC, {"paddsb", "Pq", "Qq", "", 0}},
- {0, 0xED, {"paddsw", "Pq", "Qq", "", 0}},
- {0, 0xEE, {"pmaxsw", "Mq", "Pq", "", 0}},
- {0, 0xEF, {"pxor", "Mq", "Pq", "", 0}},
- {0x66, 0xE0, {"pavgb", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xE1, {"psraw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xE2, {"psrad", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xE3, {"pavgw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xE4, {"pmulhuw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xE5, {"pmulhw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xE6, {"cvttpd2dq", "Vo", "Wx", "", 0}},
- {0x66, 0xE7, {"movntdq", "Mx", "Vx", "", 0}},
- {0x66, 0xE8, {"psubsb", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xE9, {"psubsw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xEA, {"pminsw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xEB, {"por", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xEC, {"paddsb", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xED, {"paddsw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xEE, {"pmaxsw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xEF, {"pxor", "Vx", "Hx", "Wx", 0}},
- {0xF3, 0xE6, {"cvtdq2pd", "Vo", "Wo.q", "", 0}},
- {0xF2, 0xE6, {"cvtpd2dq", "Vo", "Wx", "", 0}},
- {0, 0xF1, {"psllw", "Pq", "Qq", "", 0}},
- {0, 0xF2, {"pslld", "Pq", "Qq", "", 0}},
- {0, 0xF3, {"psllq", "Pq", "Qq", "", 0}},
- {0, 0xF4, {"pmuludq", "Pq", "Qq", "", 0}},
- {0, 0xF5, {"pmaddwd", "Pq", "Qq", "", 0}},
- {0, 0xF6, {"psadbw", "Pq", "Qq", "", 0}},
- {0, 0xF7, {"maskmovq", "Pq", "Nq", "", 0}},
- {0, 0xF8, {"psubb", "Pq", "Qq", "", 0}},
- {0, 0xF9, {"psubw", "Pq", "Qq", "", 0}},
- {0, 0xFA, {"psubd", "Pq", "Qq", "", 0}},
- {0, 0xFB, {"psubq", "Pq", "Qq", "", 0}},
- {0, 0xFC, {"paddb", "Pq", "Qq", "", 0}},
- {0, 0xFD, {"paddw", "Pq", "Qq", "", 0}},
- {0, 0xFE, {"paddd", "Pq", "Qq", "", 0}},
- {0, 0xFF, {"ud", "", "", "", 0}},
- {0x66, 0xF1, {"psllw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xF2, {"pslld", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xF3, {"psllq", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xF4, {"pmuludq", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xF5, {"pmaddwd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xF6, {"psadbw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xF7, {"maskmovdqq", "Vo", "Uo", "", 0}},
- {0x66, 0xF8, {"psubb", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xF9, {"psubw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xFA, {"psubd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xFB, {"psubq", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xFC, {"paddb", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xFD, {"paddw", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xFE, {"paddd", "Vx", "Hx", "Wx", 0}},
- {0x66, 0xFF, {"ud", "", "", "", 0}},
- {0xF2, 0xF0, {"lddqu", "Vx", "Mx", "", 0}},
- {0, 0x0, {"", "", "", "", 0}},
- };
- //
- // Define the opcode groups, terminated by group zero.
- //
- X86_OPCODE_GROUP DbgX86OpcodeGroups[] = {
- {1, {"add", "or ", "adc", "sbb", "and", "sub", "xor", "cmp"}},
- {2, {"rol", "ror", "rcl", "rcr", "shl", "shr", "sal", "sar"}},
- {3, {"test", "test", "not", "neg", "mul", "imul", "div", "idiv"}},
- {4, {"inc", "dec", "(bad)", "(bad)", "(bad)", "(bad)", "(bad)", "(bad)"}},
- {5, {"inc", "dec", "call", "call", "jmp", "jmp", "push", "(bad)"}},
- {6, {"sldt", "str", "lldt", "ltr", "verr", "verw", "jmpe", "(bad)"}},
- {7, {"sgdt", "sidt", "lgdt", "lidt", "smsw", "rstorssp", "lmsw", "invlpg"}},
- {8, {"(bad)", "(bad)", "(bad)", "(bad)", "bt", "bts", "btr", "btc"}},
- {9, {"(bad)", "cmpxchg8b", "xrstors", "xsavec",
- "xsaves", "(bad)", "vmptrld", "vmptrst"}},
- {10, {"ud2", "ud2", "ud2", "ud2", "ud2", "ud2", "ud2", "ud2"}},
- {11, {"mov", "(bad)", "(bad)", "(bad)",
- "(bad)", "(bad)", "(bad)", "xabort"}},
- {12, {"(bad)", "(bad)", "psrlw", "(bad)",
- "psraw", "(bad)", "psllw", "(bad)"}},
- {13, {"(bad)", "(bad)", "psrld", "(bad)",
- "psrad", "(bad)", "pslld", "(bad)"}},
- {14, {"(bad)", "(bad)", "psrlq", "psrldq",
- "(bad)", "(bad)", "psllq", "pslldq"}},
- {15, {"fxsave", "fxrstor", "ldmxcsr", "stmxcsr",
- "xsave", "xrstor", "xsaveopt", "clflush"}},
- {0x15A, {"rdfsbase", "rdgsbase", "wrfsbase", "wrgsbase",
- "ptwrite", "(bad)", "(bad)", "(bad)"}},
- {16, {"prefetchnta", "prefetcht0", "prefetcht1", "prefetcht2",
- "hint", "hint", "hint", "hint"}},
- {17, {"(bad)", "blsr", "blsmsk", "blsi",
- "(bad)", "(bad)", "(bad)", "(bad)"}},
- {0}
- };
- X86_SPARSE_INSTRUCTION_DEFINITION DbgX860F01Alternates[] = {
- {0, 0xC1, {"vmcall", "", "", "", 0}},
- {0, 0xC2, {"vmlaunch", "", "", "", 0}},
- {0, 0xC3, {"vmresume", "", "", "", 0}},
- {0, 0xC4, {"vmxoff", "", "", "", 0}},
- {0, 0xC8, {"monitor", "", "", "", 0}},
- {0, 0xC9, {"mwait", "", "", "", 0}},
- {0, 0xCA, {"clac", "", "", "", 0}},
- {0, 0xCB, {"stac", "", "", "", 0}},
- {0, 0xCF, {"encls", "", "", "", 0}},
- {0, 0xD0, {"xgetbv", "", "", "", 0}},
- {0, 0xD1, {"xsetbv", "", "", "", 0}},
- {0, 0xD4, {"vmfunc", "", "", "", 0}},
- {0, 0xD5, {"xend", "", "", "", 0}},
- {0, 0xD6, {"xtest", "", "", "", 0}},
- {0, 0xD7, {"enclu", "", "", "", 0}},
- {0, 0xD8, {"vmrun", "", "", "", 0}},
- {0, 0xD9, {"vmmcall", "", "", "", 0}},
- {0, 0xDA, {"vmload", "", "", "", 0}},
- {0, 0xDB, {"vmsave", "", "", "", 0}},
- {0, 0xDC, {"stgi", "", "", "", 0}},
- {0, 0xDD, {"clgi", "", "", "", 0}},
- {0, 0xDE, {"skinit", "", "", "", 0}},
- {0, 0xDF, {"invlpga", "", "", "", 0}},
- {0, 0xEE, {"rdpkru", "", "", "", 0}},
- {0, 0xEF, {"wrpkru", "", "", "", 0}},
- {0, 0xF8, {"swapgs", "", "", "", 0}},
- {0, 0xF9, {"rdtscp", "", "", "", 0}},
- {0, 0xFA, {"monitorx", "", "", "", 0}},
- {0, 0xFB, {"mwaitx", "", "", "", 0}},
- {0, 0xFC, {"clzero", "", "", "", 0}},
- };
- //
- // Define the various x87 floating point mnemonics. The first index is the
- // first opcode (offset from 0xD8), and the second index is the reg2 portion
- // of the ModR/M byte. These are only valid if the mod portion of ModR/M
- // does not specify a register. If it specifies a register, then there are
- // different arrays used for decoding.
- //
- PSTR DbgX87Instructions[8][8] = {
- {
- "fadd",
- "fmul",
- "fcom",
- "fcomp",
- "fsub",
- "fsubr",
- "fdiv",
- "fdivr"
- },
- {
- "fld",
- NULL,
- "fst",
- "fstp",
- "fldenv",
- "fldcw",
- "fstenv",
- "fstcw"
- },
- {
- "fiadd",
- "fimul",
- "ficom",
- "ficomp",
- "fisub",
- "fisubr",
- "fidiv",
- "fidivr"
- },
- {
- "fild",
- "fisttp",
- "fist",
- "fistp",
- NULL,
- "fld",
- NULL,
- "fstp"
- },
- {
- "fadd",
- "fmul",
- "fcom",
- "fcomp",
- "fsub",
- "fsubr",
- "fdiv",
- "fdivr"
- },
- {
- "fld",
- "fisttp",
- "fst",
- "fstp",
- "frstor",
- NULL,
- "fsave",
- "fstsw"
- },
- {
- "fiadd",
- "fimul",
- "ficom",
- "ficomp",
- "fisub",
- "fisubr",
- "fidiv",
- "fidivr"
- },
- {
- "fild",
- "fisttp",
- "fist",
- "fistp",
- "fbld",
- "fild",
- "fbstp",
- "fistp"
- }
- };
- PSTR DbgX87D9E0Instructions[32] = {
- "fchs",
- "fabs",
- NULL,
- NULL,
- "ftst",
- "fxam",
- "ftstp",
- NULL,
- "fld1",
- "fldl2t",
- "fldl2e",
- "fldpi",
- "fldlg2",
- "fldln2",
- "fldz",
- NULL,
- "f2xm1",
- "fyl2x",
- "fptan",
- "fpatan",
- "fxtract",
- "fprem1",
- "fdecstp",
- "fincstp",
- "fprem",
- "fyl2xp1",
- "fsqrt",
- "fsincos",
- "frndint",
- "fscale",
- "fsin",
- "fcos",
- };
- PSTR DbgX87DAC0Instructions[8] = {
- "fcmovb",
- "fcmove",
- "fcmovbe",
- "fcmovu",
- NULL,
- NULL,
- NULL,
- NULL
- };
- PSTR DbgX87DBC0Instructions[8] = {
- "fcmovnb",
- "fcmovne",
- "fcmovnbe",
- "fcmovnu",
- NULL,
- "fucomi",
- "fcomi",
- NULL
- };
- PSTR DbgX87DBE0Instructions[8] = {
- "feni",
- "fdisi",
- "fclex",
- "finit",
- "fsetpm",
- "frstpm",
- NULL,
- NULL
- };
- PSTR DbgX87DCC0Instructions[8] = {
- "fadd",
- "fmul",
- "fcom",
- "fcomp",
- "fsubr",
- "fsub",
- "fdivr",
- "fdiv",
- };
- PSTR DbgX87DDC0Instructions[8] = {
- "ffree",
- "fxch",
- "fst",
- "fstp",
- "fucom",
- "fucomp",
- NULL,
- NULL,
- };
- PSTR DbgX87DEC0Instructions[8] = {
- "faddp",
- "fmulp",
- "fcomp",
- NULL,
- "fsubrp",
- "fsubp",
- "fdivrp",
- "fdivp",
- };
- PSTR DbgX87DFC0Instructions[8] = {
- "freep",
- "fxch",
- "fstp",
- "fstp",
- NULL,
- "fucomip",
- "fcomip",
- NULL,
- };
- PSTR DbgX87DFE0Instructions[X87_DF_E0_COUNT] = {
- "fstsw",
- "fstdw",
- "fstsg",
- };
- //
- // Define the register name constants.
- //
- PSTR DbgX86ControlRegisterNames[X86_REGISTER_NAME_COUNT] = {
- "cr0",
- "cr1",
- "cr2",
- "cr3",
- "cr4",
- "cr5",
- "cr6",
- "cr7",
- "cr8",
- "cr9",
- "cr10",
- "cr11",
- "cr12",
- "cr13",
- "cr14",
- "cr15"
- };
- PSTR DbgX86DebugRegisterNames[X86_REGISTER_NAME_COUNT] = {
- "dr0",
- "dr1",
- "dr2",
- "dr3",
- "dr4",
- "dr5",
- "dr6",
- "dr7",
- "dr8",
- "dr9",
- "dr10",
- "dr11",
- "dr12",
- "dr13",
- "dr14",
- "dr15"
- };
- PSTR DbgX86SegmentRegisterNames[X86_REGISTER_NAME_COUNT] = {
- "es",
- "cs",
- "ss",
- "ds",
- "fs",
- "gs",
- "ERR",
- "ERR",
- "es",
- "cs",
- "ss",
- "ds",
- "fs",
- "gs",
- "ERR",
- "ERR"
- };
- //
- // The 8 bit registers have different names in long mode. The first array here
- // is for 32-bit mode, the second is for long mode.
- //
- PSTR DbgX86RegisterNames8Bit[2][X86_REGISTER_NAME_COUNT] = {
- {
- "al",
- "cl",
- "dl",
- "bl",
- "ah",
- "ch",
- "dh",
- "bh",
- "r8b",
- "r9b",
- "r10b",
- "r11b",
- "r12b",
- "r13b",
- "r14b",
- "r15b"
- },
- {
- "al",
- "cl",
- "dl",
- "bl",
- "spl",
- "bpl",
- "sil",
- "dil",
- "r8b",
- "r9b",
- "r10b",
- "r11b",
- "r12b",
- "r13b",
- "r14b",
- "r15b"
- }
- };
- PSTR DbgX86RegisterNames16Bit[X86_REGISTER_NAME_COUNT] = {
- "ax",
- "cx",
- "dx",
- "bx",
- "sp",
- "bp",
- "si",
- "di",
- "r8w",
- "r9w",
- "r10w",
- "r11w",
- "r12w",
- "r13w",
- "r14w",
- "r15w"
- };
- PSTR DbgX86RegisterNames32Bit[X86_REGISTER_NAME_COUNT] = {
- "eax",
- "ecx",
- "edx",
- "ebx",
- "esp",
- "ebp",
- "esi",
- "edi",
- "r8d",
- "r9d",
- "r10d",
- "r11d",
- "r12d",
- "r13d",
- "r14d",
- "r15d"
- };
- PSTR DbgX86RegisterNames64Bit[X86_REGISTER_NAME_COUNT] = {
- "rax",
- "rcx",
- "rdx",
- "rbx",
- "rsp",
- "rbp",
- "rsi",
- "rdi",
- "r8",
- "r9",
- "r10",
- "r11",
- "r12",
- "r13",
- "r14",
- "r15"
- };
- PSTR DbgX87RegisterNames[X86_REGISTER_NAME_COUNT] = {
- "st(0)",
- "st(1)",
- "st(2)",
- "st(3)",
- "st(4)",
- "st(5)",
- "st(6)",
- "st(7)",
- "ERR",
- "ERR",
- "ERR",
- "ERR",
- "ERR",
- "ERR",
- "ERR",
- "ERR"
- };
- PSTR DbgX86MmxRegisterNames[X86_REGISTER_NAME_COUNT] = {
- "mmx0",
- "mmx1",
- "mmx2",
- "mmx3",
- "mmx4",
- "mmx5",
- "mmx6",
- "mmx7",
- "mmx8",
- "mmx9",
- "mmx10",
- "mmx11",
- "mmx12",
- "mmx13",
- "mmx14",
- "mmx15"
- };
- PSTR DbgX86XmmRegisterNames[X86_REGISTER_NAME_COUNT] = {
- "xmm0",
- "xmm1",
- "xmm2",
- "xmm3",
- "xmm4",
- "xmm5",
- "xmm6",
- "xmm7",
- "xmm8",
- "xmm9",
- "xmm10",
- "xmm11",
- "xmm12",
- "xmm13",
- "xmm14",
- "xmm15"
- };
- PSTR DbgX86YmmRegisterNames[X86_REGISTER_NAME_COUNT] = {
- "ymm0",
- "ymm1",
- "ymm2",
- "ymm3",
- "ymm4",
- "ymm5",
- "ymm6",
- "ymm7",
- "ymm8",
- "ymm9",
- "ymm10",
- "ymm11",
- "ymm12",
- "ymm13",
- "ymm14",
- "ymm15"
- };
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- BOOL
- DbgpX86PrintOperand (
- ULONGLONG InstructionPointer,
- PX86_INSTRUCTION Instruction,
- PSTR OperandFormat,
- PSTR Operand,
- ULONG BufferLength,
- PULONGLONG Address,
- PBOOL AddressValid
- );
- PSTR
- DbgpX86PrintMnemonic (
- PX86_INSTRUCTION Instruction
- );
- BOOL
- DbgpX86GetInstructionComponents (
- PBYTE InstructionStream,
- PX86_INSTRUCTION Instruction
- );
- BOOL
- DbgpX86GetInstructionParameters (
- PBYTE InstructionStream,
- PX86_INSTRUCTION Instruction,
- PBOOL ModRmExists,
- PBOOL SibExists,
- PULONG DisplacementSize,
- PULONG ImmediateSize
- );
- PSTR
- DbgpX86RegisterName (
- PX86_INSTRUCTION Instruction,
- X86_REGISTER_VALUE RegisterNumber,
- CHAR Type
- );
- INT
- DbgpX86GetDisplacement (
- PX86_INSTRUCTION Instruction,
- PSTR Buffer,
- ULONG BufferLength,
- PLONGLONG DisplacementValue
- );
- PX86_INSTRUCTION_DEFINITION
- DbgpX86GetTwoByteInstruction (
- PX86_INSTRUCTION Instruction
- );
- BOOL
- DbgpX86DecodeFloatingPointInstruction (
- PX86_INSTRUCTION Instruction
- );
- //
- // ------------------------------------------------------------------ Functions
- //
- BOOL
- DbgpX86Disassemble (
- ULONGLONG InstructionPointer,
- PBYTE InstructionStream,
- PSTR Buffer,
- ULONG BufferLength,
- PDISASSEMBLED_INSTRUCTION Disassembly,
- MACHINE_LANGUAGE Language
- )
- /*++
- Routine Description:
- This routine decodes one instruction from an IA-32 binary instruction
- stream into a human readable form.
- Arguments:
- InstructionPointer - Supplies the instruction pointer for the start of the
- instruction stream.
- InstructionStream - Supplies a pointer to the binary instruction stream.
- Buffer - Supplies a pointer to the buffer where the human
- readable strings will be printed. This buffer must be allocated by the
- caller.
- BufferLength - Supplies the length of the supplied buffer.
- Disassembly - Supplies a pointer to the structure that will receive
- information about the instruction.
- Language - Supplies the type of machine langage being decoded.
- Return Value:
- TRUE on success.
- FALSE if the instruction was unknown.
- --*/
- {
- ULONGLONG Address;
- BOOL AddressValid;
- X86_INSTRUCTION Instruction;
- INT Length;
- PSTR Mnemonic;
- BOOL Result;
- PSTR ThirdOperandFormat;
- CHAR WorkingBuffer[X86_WORKING_BUFFER_SIZE];
- if ((Disassembly == NULL) || (Buffer == NULL)) {
- return FALSE;
- }
- memset(Buffer, 0, BufferLength);
- memset(Disassembly, 0, sizeof(DISASSEMBLED_INSTRUCTION));
- memset(&Instruction, 0, sizeof(X86_INSTRUCTION));
- Instruction.Language = Language;
- Instruction.InstructionPointer = InstructionPointer;
- //
- // Dissect the instruction into more managable components.
- //
- Result = DbgpX86GetInstructionComponents(InstructionStream, &Instruction);
- if (Result == FALSE) {
- goto DisassembleEnd;
- }
- Disassembly->BinaryLength = Instruction.Length;
- //
- // Print the mnemonic.
- //
- Mnemonic = DbgpX86PrintMnemonic(&Instruction);
- if ((Mnemonic == NULL) || (strlen(Mnemonic) >= BufferLength)) {
- Result = FALSE;
- goto DisassembleEnd;
- }
- //
- // Copy the mnemonic into the buffer, and advance the buffer to the next
- // free spot.
- //
- Length = snprintf(Buffer,
- BufferLength,
- "%s%s%s",
- Instruction.Lock,
- Instruction.Rep,
- Mnemonic);
- if (Length < 0) {
- Result = FALSE;
- goto DisassembleEnd;
- }
- Disassembly->Mnemonic = Buffer;
- Buffer += Length + 1;
- BufferLength -= Length + 1;
- //
- // Get the destination operand.
- //
- WorkingBuffer[0] = '\0';
- Result = DbgpX86PrintOperand(InstructionPointer,
- &Instruction,
- Instruction.Definition.Target,
- WorkingBuffer,
- sizeof(WorkingBuffer),
- &Address,
- &AddressValid);
- if ((Result == FALSE) ||
- (strlen(WorkingBuffer) >= BufferLength)) {
- Result = FALSE;
- goto DisassembleEnd;
- }
- //
- // If an address came out of that, plug it into the result.
- //
- if (AddressValid != FALSE) {
- Disassembly->OperandAddress = Address;
- Disassembly->AddressIsValid = TRUE;
- Disassembly->AddressIsDestination = TRUE;
- }
- //
- // Copy the operand into the buffer, and advance the buffer.
- //
- Disassembly->DestinationOperand = Buffer;
- strncpy(Disassembly->DestinationOperand, WorkingBuffer, BufferLength);
- Buffer += strlen(WorkingBuffer) + 1;
- BufferLength -= strlen(WorkingBuffer) + 1;
- //
- // Get the source operand.
- //
- WorkingBuffer[0] = '\0';
- Result = DbgpX86PrintOperand(InstructionPointer,
- &Instruction,
- Instruction.Definition.Source,
- WorkingBuffer,
- sizeof(WorkingBuffer),
- &Address,
- &AddressValid);
- if ((Result == FALSE) || (strlen(WorkingBuffer) >= BufferLength)) {
- Result = FALSE;
- goto DisassembleEnd;
- }
- //
- // If an address came out of the operand, plug it into the result.
- //
- if (AddressValid != FALSE) {
- Disassembly->OperandAddress = Address;
- Disassembly->AddressIsValid = TRUE;
- Disassembly->AddressIsDestination = FALSE;
- }
- //
- // Copy the operand into the buffer, and advance the buffer.
- //
- if (WorkingBuffer[0] != '\0') {
- Disassembly->SourceOperand = Buffer;
- strncpy(Disassembly->SourceOperand, WorkingBuffer, BufferLength);
- Buffer += strlen(WorkingBuffer) + 1;
- BufferLength -= strlen(WorkingBuffer) + 1;
- }
- //
- // Handle the third operand.
- //
- ThirdOperandFormat = Instruction.Definition.Third;
- if ((ThirdOperandFormat != NULL) && (*ThirdOperandFormat != '\0')) {
- WorkingBuffer[0] = '\0';
- Result = DbgpX86PrintOperand(InstructionPointer,
- &Instruction,
- ThirdOperandFormat,
- WorkingBuffer,
- sizeof(WorkingBuffer),
- &Address,
- &AddressValid);
- if ((Result == FALSE) || (strlen(WorkingBuffer) > BufferLength)) {
- Result = FALSE;
- goto DisassembleEnd;
- }
- //
- // If the second operand is empty, take over its slot.
- //
- if (Disassembly->SourceOperand == NULL) {
- Disassembly->SourceOperand = Buffer;
- } else {
- Disassembly->ThirdOperand = Buffer;
- }
- strncpy(Buffer, WorkingBuffer, BufferLength);
- }
- DisassembleEnd:
- return Result;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- BOOL
- DbgpX86PrintOperand (
- ULONGLONG InstructionPointer,
- PX86_INSTRUCTION Instruction,
- PSTR OperandFormat,
- PSTR Operand,
- ULONG BufferLength,
- PULONGLONG Address,
- PBOOL AddressValid
- )
- /*++
- Routine Description:
- This routine prints an operand in an IA instruction stream depending on the
- supplied format.
- Arguments:
- InstructionPointer - Supplies the instruction pointer for the instruction
- being disassembled.
- Instruction - Supplies a pointer to the instruction structure.
- OperandFormat - Supplies the format of the operand in two or more
- characters. These are largely compatible with the Intel Opcode
- Encodings, except for the ! prefix, which indicates an absolute
- register name.
- Operand - Supplies a pointer to the string that will receive the human
- readable operand.
- BufferLength - Supplies the length of the supplied buffer.
- Address - Supplies a pointer that receives the memory address encoded in the
- operand.
- AddressValid - Supplies a pointer that receives whether or not the value
- store in the Address parameter is valid.
- Return Value:
- TRUE on success.
- FALSE on failure.
- --*/
- {
- PSTR Base;
- BYTE BaseValue;
- PSTR Index;
- BYTE IndexValue;
- INT Length;
- X86_MOD_VALUE Mod;
- PSTR RegisterString;
- UCHAR Rm;
- ULONG Scale;
- CHAR Type;
- CHAR Width;
- Base = NULL;
- Index = NULL;
- IndexValue = 0xFF;
- Scale = 0;
- RegisterString = NULL;
- //
- // Start by doing some parameter checking.
- //
- if ((Operand == NULL) || (BufferLength == 0)) {
- return FALSE;
- }
- Operand[0] = '\0';
- *Address = 0ULL;
- *AddressValid = FALSE;
- if (*OperandFormat == '\0') {
- return TRUE;
- }
- Type = OperandFormat[0];
- Width = OperandFormat[1];
- //
- // 'd' means dword, which gets translated to long here for simplicity.
- //
- switch (Width) {
- case 'd':
- Width = X86_WIDTH_LONG;
- break;
- case '\0':
- case 's':
- case 'p':
- Width = X86_WIDTH_LONG;
- if (Instruction->Language == MachineLanguageX64) {
- Width = X86_WIDTH_LONGLONG;
- }
- break;
- case 'y':
- Width = X86_WIDTH_LONG;
- if ((Instruction->Rex & X64_REX_W) != 0) {
- Width = X86_WIDTH_LONGLONG;
- }
- break;
- //
- // If the width is variable, it is probably a dword unless an override is
- // specified.
- //
- case 'v':
- case 'z':
- //
- // A few instructions default to 64-bits in long mode.
- //
- if ((Instruction->Language == MachineLanguageX64) &&
- (OperandFormat[2] == '6')) {
- Width = X86_WIDTH_LONGLONG;
- if (Instruction->OperandOverride != FALSE) {
- Width = X86_WIDTH_WORD;
- }
- } else if ((Instruction->Rex & X64_REX_W) != 0) {
- if (Width == 'v') {
- Width = X86_WIDTH_LONGLONG;
- } else {
- Width = X86_WIDTH_LONG;
- }
- } else {
- Width = X86_WIDTH_LONG;
- if ((Instruction->OperandOverride == TRUE) ||
- (Instruction->AddressOverride == TRUE)) {
- Width = X86_WIDTH_WORD;
- }
- }
- break;
- case 'u':
- Width = X86_WIDTH_YWORD;
- if (Instruction->OperandOverride != FALSE) {
- Width = X86_WIDTH_ZWORD;
- }
- break;
- case 'x':
- Width = X86_WIDTH_OWORD;
- if ((Instruction->Vex & X64_VEX_L) != 0) {
- Width = X86_WIDTH_YWORD;
- }
- break;
- //
- // An unknown width specifier.
- //
- default:
- break;
- }
- switch (Type) {
- //
- // The ! encoding indicates that a register is hardcoded.
- //
- case '!':
- //
- // If the width is 'e', then it's a hardcoded string.
- //
- if (Width == 'e') {
- strncpy(Operand, OperandFormat + 2, BufferLength);
- //
- // An r indicates a register corresponding to the current mode. These
- // encode a register number as an ASCII number.
- //
- } else if ((OperandFormat[2] >= '0') && (OperandFormat[2] <= '7')) {
- if (Width == 'r') {
- if (Instruction->OperandOverride != FALSE) {
- Width = X86_WIDTH_WORD;
- } else if ((Instruction->Language == MachineLanguageX64) &&
- (OperandFormat[3] == '6')) {
- Width = X86_WIDTH_LONGLONG;
- } else {
- Width = X86_WIDTH_LONG;
- if ((Instruction->Rex & X64_REX_W) != 0) {
- Width = X86_WIDTH_LONGLONG;
- }
- }
- }
- Rm = OperandFormat[2] - '0';
- Rm = X86_MODRM_RM(Instruction, Rm);
- strncpy(Operand,
- DbgpX86RegisterName(Instruction, Rm, Width),
- BufferLength);
- //
- // Otherwise it's something like wcs or bal, with a width and register.
- //
- } else {
- strncpy(Operand, OperandFormat + 2, BufferLength);
- }
- break;
- //
- // A - Direct address, no mod R/M byte; address of operand is encoded in
- // instruction. No base, index, or scaling can be applied.
- //
- case 'A':
- snprintf(Operand,
- BufferLength,
- "%s[0x%llx]",
- Instruction->SegmentPrefix,
- Instruction->Immediate);
- *Address = Instruction->Immediate;
- *AddressValid = TRUE;
- break;
- //
- // C - Reg field of mod R/M byte selects a control register.
- // D - Reg field of mod R/M byte selects a debug register.
- // S - Reg field of ModR/M byte selects a segment register.
- //
- case 'C':
- case 'D':
- case 'S':
- RegisterString = DbgpX86RegisterName(
- Instruction,
- X86_MODRM_REG(Instruction, Instruction->ModRm),
- Type);
- strncpy(Operand, RegisterString, BufferLength);
- break;
- //
- // V - XMM/YMM register specified by ModRM.reg.
- //
- case 'V':
- RegisterString = DbgpX86RegisterName(
- Instruction,
- X86_MODRM_REG(Instruction, Instruction->ModRm),
- Width);
- strncpy(Operand, RegisterString, BufferLength);
- break;
- //
- // H - XMM/YMM register specified by VEX/VOP.vvvv field, if one is present.
- //
- case 'H':
- if (Instruction->VexMap != 0) {
- Rm = X64_VEX_V(Instruction->Vex);
- RegisterString = DbgpX86RegisterName(Instruction, Rm, Width);
- strncpy(Operand, RegisterString, BufferLength);
- }
- break;
- //
- // E - Mod R/M bytes follows opcode and specifies operand. Operand is either
- // a general register or a memory address. If it is a memory address, the
- // address is computed from a segment register and any of the following
- // values: a base register, an index register, a scaling factor, and a
- // displacement.
- // M - Mod R/M byte may only refer to memory.
- // W - XMM/YMM register or memory operand.
- //
- case 'E':
- case 'M':
- case 'W':
- Mod = X86_MODRM_MOD(Instruction->ModRm);
- Rm = X86_MODRM_RM(Instruction, Instruction->ModRm);
- if (Mod == X86ModValueRegister) {
- if (Type == 'M') {
- return FALSE;
- }
- RegisterString = DbgpX86RegisterName(Instruction, Rm, Width);
- } else {
- //
- // Memory accesses only happen via general registers. Convert larger
- // memory references into native ones.
- //
- if ((Width == X86_WIDTH_OWORD) || (Width == X86_WIDTH_YWORD) ||
- (Width == X86_WIDTH_ZWORD)) {
- Width = X86_WIDTH_LONG;
- if (Instruction->Language == MachineLanguageX64) {
- Width = X86_WIDTH_LONGLONG;
- }
- }
- //
- // An R/M value of 4 actually indicates an SIB byte is present, not
- // ESP. The REX extension bit doesn't matter here.
- //
- if (X86_BASIC_REG(Rm) == X86RegisterValueSp) {
- Rm = X86RegisterValueScaleIndexBase;
- BaseValue = X86_SIB_BASE(Instruction);
- IndexValue = X86_SIB_INDEX(Instruction);
- Scale = X86_SIB_SCALE(Instruction);
- Base = DbgpX86RegisterName(Instruction, BaseValue, Width);
- Index = DbgpX86RegisterName(Instruction, IndexValue, Width);
- //
- // A base value of 5 (ebp) indicates that the base field is not
- // used, and a displacement is present. The Mod field then
- // specifies the size of the displacement.
- //
- if (X86_BASIC_REG(BaseValue) == X86RegisterValueBp) {
- Base = "";
- Length = snprintf(Operand,
- BufferLength,
- "0x%llx",
- Instruction->Displacement);
- if (Length <= 0) {
- return FALSE;
- }
- Operand += Length;
- BufferLength -= Length;
- }
- } else if ((Mod == X86ModValueNoDisplacement) &&
- (X86_BASIC_REG(Rm) == X86RegisterValueBp)) {
- Rm = X86RegisterValueDisplacement32;
- if (Instruction->Language == MachineLanguageX64) {
- Rm = X86RegisterValueRipRelative;
- }
- } else {
- RegisterString = DbgpX86RegisterName(Instruction, Rm, Width);
- }
- }
- //
- // The operand is simply a register.
- //
- if (Mod == X86ModValueRegister) {
- strncpy(Operand, RegisterString, BufferLength);
- //
- // The operand is an address with a scale/index/base.
- //
- } else if (Rm == X86RegisterValueScaleIndexBase) {
- Length = snprintf(Operand,
- BufferLength,
- "%s[%s",
- Instruction->SegmentPrefix,
- Base);
- if ((Length <= 0) || (BufferLength - Length <= 3)) {
- return FALSE;
- }
- Operand += Length;
- BufferLength -= Length;
- //
- // An index of 4 indicates that the index and scale fields are not
- // used.
- //
- if (IndexValue != 4) {
- if (*Base != '\0') {
- *Operand = '+';
- Operand += 1;
- BufferLength -= 1;
- }
- Length = snprintf(Operand, BufferLength, "%s*%d", Index, Scale);
- if (Length <= 0) {
- return FALSE;
- }
- Operand += Length;
- BufferLength -= Length;
- }
- Length = DbgpX86GetDisplacement(Instruction,
- Operand,
- BufferLength,
- NULL);
- if ((Length < 0) || (BufferLength - Length <= 2)) {
- return FALSE;
- }
- Operand[Length] = ']';
- Operand += Length + 1;
- BufferLength -= Length + 1;
- *Operand = '\0';
- //
- // The operand is a 32-bit address.
- //
- } else if (Rm == X86RegisterValueDisplacement32) {
- Length = snprintf(Operand,
- BufferLength,
- "%s[0x%llx]",
- Instruction->SegmentPrefix,
- Instruction->Displacement);
- if (Length <= 0) {
- return FALSE;
- }
- *Address = Instruction->Displacement;
- *AddressValid = TRUE;
- //
- // The operand is an address in a register, possibly with some
- // additional displacement.
- //
- } else {
- //
- // The register could be RIP in the long-mode-only RIP-relative
- // addressing.
- //
- if (Rm == X86RegisterValueRipRelative) {
- RegisterString = "rip";
- if (Instruction->AddressOverride != FALSE) {
- RegisterString = "eip";
- }
- *Address = Instruction->InstructionPointer +
- Instruction->Length +
- (LONG)(Instruction->Displacement);
- *AddressValid = TRUE;
- }
- Length = snprintf(Operand,
- BufferLength,
- "%s[%s",
- Instruction->SegmentPrefix,
- RegisterString);
- if (Length <= 0) {
- return FALSE;
- }
- Operand += Length;
- BufferLength -= Length;
- Length = DbgpX86GetDisplacement(Instruction,
- Operand,
- BufferLength,
- NULL);
- if ((Length < 0) || (BufferLength - Length <= 2)) {
- return FALSE;
- }
- Operand[Length] = ']';
- Operand += Length + 1;
- BufferLength -= Length + 1;
- *Operand = '\0';
- }
- break;
- //
- // G - Reg field of Mod R/M byte selects a general register.
- //
- case 'G':
- Rm = X86_MODRM_REG(Instruction, Instruction->ModRm);
- strncpy(Operand,
- DbgpX86RegisterName(Instruction, Rm, Width),
- BufferLength);
- break;
- //
- // I - Immediate data: value of operand is encoded in Immediate field.
- // O - Direct offset: no ModR/M byte. Offset of operand is encoded in
- // instruction. No Base/Index/Scale can be applied.
- //
- case 'I':
- case 'O':
- snprintf(Operand, BufferLength, "0x%llx", Instruction->Immediate);
- break;
- //
- // J - Instruction contains a relative offset to be added to the instruction
- // pointer.
- //
- case 'J':
- DbgpX86GetDisplacement(Instruction,
- Operand,
- BufferLength,
- (PLONGLONG)Address);
- *Address += (InstructionPointer + Instruction->Length);
- snprintf(Operand,
- BufferLength,
- "%s[0x%llx]",
- Instruction->SegmentPrefix,
- *Address);
- *AddressValid = TRUE;
- break;
- //
- // R - R/M field of modR/M byte selects a general register. Mod field should
- // be set to 11.
- // U - XMM/YMM register specified by ModRM.rm with mod set to 11.
- //
- case 'R':
- case 'U':
- Mod = X86_MODRM_MOD(Instruction->ModRm);
- Rm = X86_MODRM_RM(Instruction, Instruction->ModRm);
- if (Mod != X86ModValueRegister) {
- return FALSE;
- }
- strncpy(Operand,
- DbgpX86RegisterName(Instruction, Rm, Width),
- BufferLength);
- break;
- //
- // X - Memory addressed by DS:SI register pair (eg. MOVS CMPS, OUTS, LODS).
- //
- case 'X':
- RegisterString = DbgpX86RegisterName(Instruction,
- X86RegisterValueSi,
- X86_WIDTH_LONG);
- snprintf(Operand, BufferLength, "ds:[%s]", RegisterString);
- break;
- //
- // Y - Memory addressed by ES:DI register pair (eg. MOVS INS, STOS, SCAS).
- //
- case 'Y':
- RegisterString = DbgpX86RegisterName(Instruction,
- X86RegisterValueDi,
- X86_WIDTH_LONG);
- snprintf(Operand, BufferLength, "ds:[%s]", RegisterString);
- break;
- default:
- return FALSE;
- }
- return TRUE;
- }
- PSTR
- DbgpX86PrintMnemonic (
- PX86_INSTRUCTION Instruction
- )
- /*++
- Routine Description:
- This routine prints an instruction mnemonic.
- Arguments:
- Instruction - Supplies a pointer to the instruction structure.
- Return Value:
- A pointer to the mnemonic on success.
- NULL on failure.
- --*/
- {
- PX86_OPCODE_GROUP OpcodeGroup;
- BYTE RegByte;
- if (Instruction == NULL) {
- return NULL;
- }
- if (Instruction->Definition.Group == 0) {
- return Instruction->Definition.Mnemonic;
- }
- assert(Instruction->Definition.Group != X86_INVALID_GROUP);
- RegByte = (Instruction->ModRm & X86_REG_MASK) >> X86_REG_SHIFT;
- OpcodeGroup = &(DbgX86OpcodeGroups[0]);
- while (OpcodeGroup->Group != 0) {
- if (OpcodeGroup->Group == Instruction->Definition.Group) {
- return OpcodeGroup->Mnemonics[RegByte];
- }
- OpcodeGroup += 1;
- }
- assert(FALSE);
- return NULL;
- }
- BOOL
- DbgpX86GetInstructionComponents (
- PBYTE InstructionStream,
- PX86_INSTRUCTION Instruction
- )
- /*++
- Routine Description:
- This routine reads an instruction stream and decomposes it into its
- respective components.
- Arguments:
- InstructionStream - Supplies a pointer to the raw binary instruction stream.
- Instruction - Supplies a pointer to the structure that will accept the
- instruction decomposition.
- Return Value:
- TRUE on success.
- FALSE otherwise.
- --*/
- {
- ULONG AlternateCount;
- ULONG AlternateIndex;
- ULONG Base;
- PBYTE Beginning;
- ULONG DisplacementSize;
- ULONG Group;
- ULONG ImmediateSize;
- ULONG Mod;
- BOOL ModRmExists;
- UCHAR Opcode3;
- INT PrefixIndex;
- BYTE RegByte;
- BOOL Result;
- BOOL SibExists;
- PX86_INSTRUCTION_DEFINITION TopLevelDefinition;
- PX86_INSTRUCTION_DEFINITION TwoByteInstruction;
- if (Instruction == NULL) {
- return FALSE;
- }
- Beginning = InstructionStream;
- Result = TRUE;
- //
- // Begin by handling any prefixes. The prefixes are: F0 (LOCK), F2 (REP),
- // F3 (REP), 2E (CS), 36 (SS), 3E (DS), 26 (ES), 64 (FS), 65 (GS),
- // 66 (Operand-size override), 67 (Address-size override)).
- //
- Instruction->Lock = "";
- Instruction->Rep = "";
- Instruction->SegmentPrefix = "";
- for (PrefixIndex = 0; PrefixIndex < X86_MAX_PREFIXES; PrefixIndex += 1) {
- switch (*InstructionStream) {
- case X86_PREFIX_LOCK:
- Instruction->Lock = "lock ";
- break;
- case X86_PREFIX_REPN:
- Instruction->Rep = "repne ";
- break;
- case X86_PREFIX_REP:
- Instruction->Rep = "rep ";
- break;
- case X86_PREFIX_CS:
- if (Instruction->Language != MachineLanguageX64) {
- Instruction->SegmentPrefix = "cs:";
- }
- break;
- case X86_PREFIX_DS:
- if (Instruction->Language != MachineLanguageX64) {
- Instruction->SegmentPrefix = "ds:";
- }
- break;
- case X86_PREFIX_ES:
- Instruction->SegmentPrefix = "es:";
- break;
- case X86_PREFIX_FS:
- Instruction->SegmentPrefix = "fs:";
- break;
- case X86_PREFIX_GS:
- Instruction->SegmentPrefix = "gs:";
- break;
- case X86_PREFIX_SS:
- Instruction->SegmentPrefix = "ss:";
- break;
- case X86_OPERAND_OVERRIDE:
- Instruction->OperandOverride = TRUE;
- break;
- case X86_ADDRESS_OVERRIDE:
- Instruction->AddressOverride = TRUE;
- break;
- default:
- PrefixIndex = X86_MAX_PREFIXES;
- break;
- }
- if (PrefixIndex == X86_MAX_PREFIXES) {
- break;
- }
- Instruction->Prefix[PrefixIndex] = *InstructionStream;
- InstructionStream += 1;
- Instruction->Length += 1;
- }
- //
- // Grab the REX prefix for x64, which has to go right before the
- // instruction opcode.
- //
- if (Instruction->Language == MachineLanguageX64) {
- if ((*InstructionStream & X64_REX_MASK) == X64_REX_VALUE) {
- Instruction->Rex = *InstructionStream;
- InstructionStream += 1;
- Instruction->Length += 1;
- //
- // Look for the 2-byte VEX prefix. Convert it to a 3 byte prefix.
- //
- } else if (*InstructionStream == X64_VEX2) {
- InstructionStream += 1;
- Instruction->Length += 1;
- Instruction->Vex = *InstructionStream;
- Instruction->VexMap = X64_VEX2_MAP_SELECT |
- (Instruction->Vex & 0x80);
- Instruction->Vex &= 0x7F;
- InstructionStream += 1;
- Instruction->Length += 1;
- Instruction->Rex = X64_VEX_TO_REX(Instruction->Vex,
- Instruction->VexMap);
- //
- // Look for the 3 byte VEX/XOP prefix.
- //
- } else if ((*InstructionStream == X64_VEX3) ||
- (*InstructionStream == X64_XOP)) {
- InstructionStream += 1;
- Instruction->Length += 1;
- Instruction->VexMap = *InstructionStream;
- InstructionStream += 1;
- Instruction->Length += 1;
- Instruction->Vex = *InstructionStream;
- InstructionStream += 1;
- Instruction->Length += 1;
- Instruction->Rex = X64_VEX_TO_REX(Instruction->Vex,
- Instruction->VexMap);
- }
- }
- Instruction->Opcode = *InstructionStream;
- Instruction->Length += 1;
- InstructionStream += 1;
- //
- // Check for a two byte opcode.
- //
- if (Instruction->Opcode == X86_ESCAPE_OPCODE) {
- Instruction->Opcode2 = *InstructionStream;
- Instruction->Length += 1;
- InstructionStream += 1;
- TwoByteInstruction = DbgpX86GetTwoByteInstruction(Instruction);
- if (TwoByteInstruction == NULL) {
- Result = FALSE;
- goto GetInstructionComponentsEnd;
- }
- TopLevelDefinition = TwoByteInstruction;
- } else {
- TopLevelDefinition = &(DbgX86Instructions[Instruction->Opcode]);
- }
- //
- // Modify the instruction definition for groups. If the opcode is in a
- // group, then it must have a modR/M byte, so cheat a little and get it.
- //
- Instruction->Definition = *TopLevelDefinition;
- Group = Instruction->Definition.Group;
- if ((Group != 0) && (Group != X86_INVALID_GROUP)) {
- RegByte = (*InstructionStream & X86_REG_MASK) >> X86_REG_SHIFT;
- switch (Group) {
- case 3:
- if (RegByte <= 1) {
- if (Instruction->Opcode == 0xF6) {
- Instruction->Definition.Source = "Ib";
- } else {
- assert(Instruction->Opcode == 0xF7);
- Instruction->Definition.Source = "Iz";
- }
- }
- break;
- case 7:
- //
- // There are a bunch of alternate encoding instructions hidden
- // behind 0F 01, go look for them.
- //
- if (RegByte == 1) {
- Opcode3 = *InstructionStream;
- AlternateCount = sizeof(DbgX860F01Alternates) /
- sizeof(DbgX860F01Alternates[0]);
- for (AlternateIndex = 0;
- AlternateIndex < AlternateCount;
- AlternateIndex += 1) {
- if (DbgX860F01Alternates[AlternateIndex].Opcode ==
- Opcode3) {
- Instruction->Definition =
- DbgX860F01Alternates[AlternateIndex].Instruction;
- break;
- }
- }
- }
- break;
- default:
- break;
- }
- }
- //
- // Get the structure of the instruction.
- //
- Result = DbgpX86GetInstructionParameters(InstructionStream,
- Instruction,
- &ModRmExists,
- &SibExists,
- &DisplacementSize,
- &ImmediateSize);
- if (Result == FALSE) {
- goto GetInstructionComponentsEnd;
- }
- if (Group != 0) {
- ModRmExists = TRUE;
- }
- //
- // Populate the various pieces of the instruction.
- //
- Instruction->DisplacementSize = DisplacementSize;
- Instruction->ImmediateSize = ImmediateSize;
- if (ModRmExists == TRUE) {
- Instruction->ModRm = *InstructionStream;
- InstructionStream += 1;
- }
- if (SibExists == TRUE) {
- Instruction->Sib = *InstructionStream;
- InstructionStream += 1;
- //
- // Check to see if the SIB byte requires a displacement. EBP is not a
- // valid base, since that can be specified in the Mod bits.
- //
- Base = (Instruction->Sib & X86_BASE_MASK) >> X86_BASE_SHIFT;
- Mod = X86_MODRM_MOD(Instruction->ModRm);
- if (Base == X86RegisterValueBp) {
- if (Mod == X86ModValueDisplacement8) {
- DisplacementSize = 1;
- } else {
- DisplacementSize = 4;
- }
- }
- }
- //
- // Grab the displacement and immediates from the instruction stream if
- // they're there.
- //
- if (DisplacementSize != 0) {
- memcpy(&(Instruction->Displacement),
- InstructionStream,
- DisplacementSize);
- InstructionStream += DisplacementSize;
- }
- if (ImmediateSize != 0) {
- memcpy(&(Instruction->Immediate), InstructionStream, ImmediateSize);
- InstructionStream += ImmediateSize;
- }
- Instruction->Length = InstructionStream - Beginning;
- //
- // If it's an x87 floating point instruction, decode it now that the
- // ModR/M byte was grabbed.
- //
- if (Group == 0x87) {
- Result = DbgpX86DecodeFloatingPointInstruction(Instruction);
- if (Result == FALSE) {
- goto GetInstructionComponentsEnd;
- }
- }
- GetInstructionComponentsEnd:
- return Result;
- }
- BOOL
- DbgpX86GetInstructionParameters (
- PBYTE InstructionStream,
- PX86_INSTRUCTION Instruction,
- PBOOL ModRmExists,
- PBOOL SibExists,
- PULONG DisplacementSize,
- PULONG ImmediateSize
- )
- /*++
- Routine Description:
- This routine determines the format of the rest of the instruction based on
- the opcode, any prefixes, and possibly the ModRM byte.
- Arguments:
- InstructionStream - Supplies a pointer to the binary instruction stream,
- after the prefixes and opcode.
- Instruction - Supplies a pointer to an instruction. The Prefixes, Opcode,
- and Definition must be filled out.
- ModRmExists - Supplies a pointer where a boolean will be returned
- indicating whether or not a ModRM byte is present.
- SibExists - Supplies a pointer where a boolean will be returned indicating
- whether or not a Scale/Index/Base byte is present in the instruction
- stream.
- DisplacementSize - Supplies a pointer where the size of the Displacement
- value will be returned. 0 indicates there is no displacement in the
- instruction.
- ImmediateSize - Supplies a pointer where the size of the Immediate field
- in the instruction will be returned. 0 indicates there is no Immediate
- field in the instruction.
- Return Value:
- TRUE on success.
- FALSE otherwise.
- --*/
- {
- X86_MOD_VALUE Mod;
- BYTE ModRm;
- ULONG ParseCount;
- BYTE RmValue;
- CHAR Type;
- CHAR Width;
- *ModRmExists = FALSE;
- *SibExists = FALSE;
- *DisplacementSize = 0;
- *ImmediateSize = 0;
- if (Instruction->Definition.Target[0] == '\0') {
- return TRUE;
- }
- Type = Instruction->Definition.Target[0];
- Width = Instruction->Definition.Target[1];
- ParseCount = 0;
- do {
- switch (Type) {
- //
- // A - Direct address. No Mod/RM, Immediate specifies address. No SIB.
- //
- case 'A':
- *ImmediateSize = 4;
- break;
- //
- // C - Control register in ModR/M.
- // D - Debug register in ModR/M.
- // S - Segment register in Reg field of ModR/M.
- // T - Test register in ModR/M.
- // V - SIMD floating point register in ModR/M.
- //
- case 'C':
- case 'D':
- case 'S':
- case 'T':
- case 'V':
- *ModRmExists = TRUE;
- break;
- //
- // E - Mod R/M bytes follows opcode and specifies operand. Operand is
- // either a general register or a memory address. If it is a memory
- // address, the address is computed from a segment register and any of
- // the following values: a base register, an index register, a scaling
- // factor, and a displacement.
- // M - Mod R/M byte may only refer to memory.
- // R - Mod R/M byte may only refer to a general register.
- // W - XMM/YMM register or memory operand.
- // U - XMM/YMM register specified by ModRM.rm with mod set to 11.
- //
- case 'E':
- case 'M':
- case 'R':
- case 'U':
- case 'W':
- *ModRmExists = TRUE;
- ModRm = *InstructionStream;
- Mod = X86_MODRM_MOD(ModRm);
- RmValue = (ModRm & X86_RM_MASK) >> X86_RM_SHIFT;
- if (Mod != X86ModValueRegister) {
- //
- // An R/M value of 4 actually indicates an SIB byte is present,
- // not ESP.
- //
- if (RmValue == X86RegisterValueSp) {
- RmValue = X86RegisterValueScaleIndexBase;
- *SibExists = TRUE;
- }
- //
- // An R/M value of 5 when Mod is 0 means that the address is
- // actually just a 32bit displacment.
- //
- if ((Mod == X86ModValueNoDisplacement) &&
- (RmValue == X86RegisterValueBp)) {
- RmValue = X86RegisterValueDisplacement32;
- *DisplacementSize = 4;
- }
- }
- //
- // Get any displacements as specified by the MOD bits.
- //
- if (Mod == X86ModValueDisplacement8) {
- *DisplacementSize = 1;
- } else if (Mod == X86ModValueDisplacement32) {
- *DisplacementSize = 4;
- }
- break;
- //
- // F - Flags register. No additional bytes.
- // H - XMM or YMM register encoded in VEX/VOP.vvvv.
- // X - Memory addressed by DS:SI pair.
- // Y - Memory addressed by ES:DI pair.
- // ! - Hardcoded register.
- //
- case 'F':
- case 'H':
- case 'X':
- case 'Y':
- case '!':
- break;
- //
- // G - General register specified in Reg field of ModR/M byte.
- //
- case 'G':
- *ModRmExists = TRUE;
- break;
- //
- // I - Immediate data is encoded in subsequent bytes.
- //
- case 'I':
- switch (Width) {
- case X86_WIDTH_BYTE:
- *ImmediateSize = 1;
- break;
- case X86_WIDTH_WORD:
- *ImmediateSize = 2;
- break;
- case X86_WIDTH_LONG:
- *ImmediateSize = 4;
- break;
- case 'v':
- case 'z':
- if ((Instruction->Rex & X64_REX_W) != 0) {
- if (Width == 'v') {
- *ImmediateSize = 8;
- } else {
- *ImmediateSize = 4;
- }
- } else {
- *ImmediateSize = 4;
- if (Instruction->OperandOverride == TRUE) {
- *ImmediateSize = 2;
- }
- }
- break;
- }
- break;
- //
- // O - Direct Offset. No ModR/M byte, offset of operand is encoded in
- // instruction. No SIB.
- //
- case 'O':
- *ImmediateSize = 4;
- if (Instruction->AddressOverride != FALSE) {
- *ImmediateSize = 2;
- }
- break;
- //
- // J - Instruction contains relative offset.
- //
- case 'J':
- switch (Width) {
- case X86_WIDTH_BYTE:
- *DisplacementSize = 1;
- break;
- case X86_WIDTH_WORD:
- *DisplacementSize = 2;
- break;
- case X86_WIDTH_LONG:
- *DisplacementSize = 4;
- break;
- case 'v':
- case 'z':
- *DisplacementSize = 4;
- if ((Instruction->Rex & X64_REX_W) != 0) {
- if (Width == 'v') {
- *DisplacementSize = 8;
- }
- } else {
- if (Instruction->AddressOverride == TRUE) {
- *DisplacementSize = 2;
- }
- }
- break;
- }
- break;
- default:
- assert(FALSE);
- return FALSE;
- }
- //
- // Now that the target has been processed, loop again to process the
- // source.
- //
- ParseCount += 1;
- if (ParseCount == 1) {
- if (Instruction->Definition.Source[0] == '\0') {
- break;
- }
- Type = Instruction->Definition.Source[0];
- Width = Instruction->Definition.Source[1];
- } else {
- if (Instruction->Definition.Third[0] == '\0') {
- break;
- }
- Type = Instruction->Definition.Third[0];
- Width = Instruction->Definition.Third[1];
- }
- } while (ParseCount < 3);
- //
- // Handle the cmpcc instructions that actually have an extra immediate on
- // them.
- //
- if (strncmp(Instruction->Definition.Mnemonic, "cmpcc", 5) == 0) {
- *ImmediateSize = 1;
- }
- return TRUE;
- }
- PSTR
- DbgpX86RegisterName (
- PX86_INSTRUCTION Instruction,
- X86_REGISTER_VALUE RegisterNumber,
- CHAR Type
- )
- /*++
- Routine Description:
- This routine reads a register number and a width and returns a string
- representing that register. The register number should be in the same format
- as specified in the REG bits of the ModR/M byte.
- Arguments:
- Instruction - Supplies the remaining register context.
- RegisterNumber - Supplies which register to print out, as specified by the
- REG bits of the ModR/M byte.
- Type - Supplies a width or special register format.
- Return Value:
- The register specifed, in string form.
- --*/
- {
- BOOL LongNames;
- switch (Type) {
- case X86_WIDTH_BYTE:
- LongNames = Instruction->Rex != 0;
- return DbgX86RegisterNames8Bit[LongNames][RegisterNumber];
- case X86_WIDTH_WORD:
- return DbgX86RegisterNames16Bit[RegisterNumber];
- case X86_WIDTH_LONG:
- return DbgX86RegisterNames32Bit[RegisterNumber];
- case X86_WIDTH_LONGLONG:
- return DbgX86RegisterNames64Bit[RegisterNumber];
- case X86_WIDTH_OWORD:
- return DbgX86XmmRegisterNames[RegisterNumber];
- case X86_WIDTH_YWORD:
- return DbgX86YmmRegisterNames[RegisterNumber];
- case X86_FLOATING_POINT_REGISTER:
- return DbgX87RegisterNames[RegisterNumber];
- case X86_CONTROL_REGISTER:
- return DbgX86ControlRegisterNames[RegisterNumber];
- case X86_DEBUG_REGISTER:
- return DbgX86DebugRegisterNames[RegisterNumber];
- case X86_SEGMENT_REGISTER:
- return DbgX86SegmentRegisterNames[RegisterNumber];
- default:
- break;
- }
- assert(FALSE);
- return "ERR";
- }
- INT
- DbgpX86GetDisplacement (
- PX86_INSTRUCTION Instruction,
- PSTR Buffer,
- ULONG BufferLength,
- PLONGLONG DisplacementValue
- )
- /*++
- Routine Description:
- This routine prints an address displacement value.
- Arguments:
- Instruction - Supplies a pointer to the instruction containing the
- displacement.
- Buffer - Supplies a pointer to the output buffer the displacement will be
- printed to.
- BufferLength - Supplies the length of the buffer in bytes.
- DisplacementValue - Supplies a pointer to the variable that will receive the
- numerical displacement value. This can be NULL.
- Return Value:
- Returns the length of the buffer consumed, not including the null
- terminator.
- --*/
- {
- LONGLONG Displacement;
- INT Length;
- if ((BufferLength < 1) || (Instruction == NULL)) {
- return 0;
- }
- Buffer[0] = '\0';
- if (Instruction->Displacement == 0) {
- return 0;
- }
- switch (Instruction->DisplacementSize) {
- case 1:
- Displacement = (SCHAR)Instruction->Displacement;
- break;
- case 2:
- Displacement = (SHORT)Instruction->Displacement;
- break;
- case 4:
- Displacement = (LONG)Instruction->Displacement;
- break;
- case 8:
- Displacement = (LONGLONG)Instruction->Displacement;
- break;
- default:
- return 0;
- }
- if (Displacement < 0) {
- Length = snprintf(Buffer, BufferLength, "-0x%llx", -Displacement);
- } else {
- Length = snprintf(Buffer, BufferLength, "+0x%llx", Displacement);
- }
- if (DisplacementValue != NULL) {
- *DisplacementValue = Displacement;
- }
- return Length;
- }
- PX86_INSTRUCTION_DEFINITION
- DbgpX86GetTwoByteInstruction (
- PX86_INSTRUCTION Instruction
- )
- /*++
- Routine Description:
- This routine finds a two-byte instruction definition corresponding to the
- instruction opcode and prefixes.
- Arguments:
- Instruction - Supplies a pointer to the instruction containing the
- two byte opcode and any prefixes.
- Return Value:
- Returns a pointer to the instruction definition, or NULL if one could not
- be found.
- --*/
- {
- PX86_INSTRUCTION_DEFINITION Definition;
- ULONG InstructionIndex;
- ULONG InstructionLength;
- UCHAR Prefix;
- ULONG PrefixIndex;
- PrefixIndex = 0;
- InstructionLength = sizeof(DbgX86TwoByteInstructions) /
- sizeof(DbgX86TwoByteInstructions[0]);
- //
- // First search through the array looking for a version with the first
- // corresponding prefix.
- //
- while (Instruction->Prefix[PrefixIndex] != 0) {
- InstructionIndex = 0;
- Prefix = Instruction->Prefix[PrefixIndex];
- while (InstructionIndex < InstructionLength) {
- if ((DbgX86TwoByteInstructions[InstructionIndex].Prefix ==
- Prefix) &&
- (DbgX86TwoByteInstructions[InstructionIndex].Opcode ==
- Instruction->Opcode2)) {
- Definition =
- &(DbgX86TwoByteInstructions[InstructionIndex].Instruction);
- switch (Prefix) {
- case X86_PREFIX_REP:
- case X86_PREFIX_REPN:
- Instruction->Rep = "";
- break;
- case X86_PREFIX_LOCK:
- Instruction->Lock = "";
- break;
- default:
- break;
- }
- return Definition;
- }
- InstructionIndex += 1;
- }
- PrefixIndex += 1;
- }
- //
- // The search for the specific prefix instruction was not successful, or
- // no prefixes were present. Search for the opcode with a prefix of zero,
- // indicating that the prefix field is not applicable.
- //
- InstructionIndex = 0;
- while (InstructionIndex < InstructionLength) {
- if ((DbgX86TwoByteInstructions[InstructionIndex].Opcode ==
- Instruction->Opcode2) &&
- (DbgX86TwoByteInstructions[InstructionIndex].Prefix == 0)) {
- return &(DbgX86TwoByteInstructions[InstructionIndex].Instruction);
- }
- InstructionIndex += 1;
- }
- //
- // The search yielded no results. Return NULL.
- //
- return NULL;
- }
- BOOL
- DbgpX86DecodeFloatingPointInstruction (
- PX86_INSTRUCTION Instruction
- )
- /*++
- Routine Description:
- This routine decodes the given x87 floating point instruction by
- manipulating the instruction definition.
- Arguments:
- Instruction - Supplies a pointer to the instruction.
- Return Value:
- TRUE on success.
- FALSE if the instruction is invalid. Well, let's be more PC and say that no
- instruction is "invalid", only "executionally challenged".
- --*/
- {
- BYTE Index;
- BYTE Mod;
- BYTE ModRm;
- BYTE Opcode;
- BYTE Opcode2;
- ModRm = Instruction->ModRm;
- Mod = X86_MODRM_MOD(Instruction->ModRm);
- Opcode = Instruction->Opcode - X87_ESCAPE_OFFSET;
- Opcode2 = (ModRm & X86_REG_MASK) >> X86_REG_SHIFT;
- //
- // Reset the group to 0 so that after this routine tweaks everything it
- // gets treated like a normal instruction.
- //
- Instruction->Definition.Group = 0;
- Instruction->Definition.Mnemonic = NULL;
- //
- // If the ModR/M byte does not specify a register, then use the big
- // table to figure out the mnemonic.
- //
- if (Mod != X86ModValueRegister) {
- Instruction->Definition.Mnemonic = DbgX87Instructions[Opcode][Opcode2];
- if (Instruction->Definition.Mnemonic == NULL) {
- return FALSE;
- }
- return TRUE;
- }
- switch (Opcode) {
- //
- // Handle D8 instructions.
- //
- case 0:
- Instruction->Definition.Mnemonic = DbgX87Instructions[0][Opcode2];
- //
- // The fcom and fcomp instructions take only ST(i). Everything else
- // has two operands, st, and st(i).
- //
- if ((ModRm & X87_FCOM_MASK) == X87_FCOM_OPCODE) {
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- } else {
- Instruction->Definition.Target = X87_ST0_TARGET;
- Instruction->Definition.Source = X87_REGISTER_TARGET;
- }
- break;
- //
- // Handle D9 instructions.
- //
- case 1:
- switch (Opcode2) {
- //
- // C0-C7 is FLD ST(i).
- //
- case 0:
- Instruction->Definition.Mnemonic = X87_FLD_MNEMONIC;
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- break;
- //
- // C8-CF is FXCH ST(i).
- //
- case 1:
- Instruction->Definition.Mnemonic = X87_FXCH_MNEMONIC;
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- break;
- //
- // D0-D7 is just a NOP (really only at D0, but let it slide).
- //
- case 2:
- Instruction->Definition.Mnemonic = X87_NOP_MNEMONIC;
- Instruction->Definition.Target = "";
- break;
- //
- // D8-DF is FSTP1 ST(i).
- //
- case 3:
- Instruction->Definition.Mnemonic = X87_FSTP1_MNEMONIC;
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- break;
- //
- // E0-FF is a grab bag of instructions with no operands.
- //
- default:
- Instruction->Definition.Mnemonic =
- DbgX87D9E0Instructions[ModRm - X87_D9_E0_OFFSET];
- Instruction->Definition.Target = "";
- break;
- }
- break;
- //
- // Handle DA instructions.
- //
- case 2:
- //
- // The fucompp instruction lives off by itself in a wasteland.
- //
- if (ModRm == X87_FUCOMPP_OPCODE) {
- Instruction->Definition.Mnemonic = X87_FUCOMPP_MNEMONIC;
- Instruction->Definition.Target = "";
- } else {
- //
- // There are 8 instructions (4 valid), each of which take the form
- // xxx ST, ST(i). So each instruction takes up 8 bytes.
- //
- Index = (ModRm & X87_DA_C0_MASK) >> X87_DA_CO_SHIFT;
- Instruction->Definition.Mnemonic = DbgX87DAC0Instructions[Index];
- Instruction->Definition.Target = X87_ST0_TARGET;
- Instruction->Definition.Source = X87_REGISTER_TARGET;
- }
- break;
- //
- // Handle DB instructions.
- //
- case 3:
- Index = (ModRm & X87_DB_C0_MASK) >> X87_DB_C0_SHIFT;
- //
- // There's a small rash of inidividual instructions in the E0-E7
- // range.
- //
- if (Index == X87_DB_E0_INDEX) {
- Index = ModRm & X87_DB_E0_MASK;
- Instruction->Definition.Mnemonic = DbgX87DBE0Instructions[Index];
- Instruction->Definition.Target = "";
- //
- // Otherwise there are swaths of instructions that take up 8 bytes
- // each as they take the form xxx ST, ST(i).
- //
- } else {
- Instruction->Definition.Mnemonic = DbgX87DBC0Instructions[Index];
- Instruction->Definition.Target = X87_ST0_TARGET;
- Instruction->Definition.Source = X87_REGISTER_TARGET;
- }
- break;
- //
- // DC is the same as D8, except it handles doubles instead of singles
- // (floats). There's one other annoying detail which is that the FSUB and
- // FSUBR are switched above 0xC0. The same goes for FDIV and FDIVR.
- //
- case 4:
- Instruction->Definition.Mnemonic = DbgX87DCC0Instructions[Opcode2];
- //
- // The fcom and fcomp instructions take only ST(i). Everything else
- // has two operands, st, and st(i).
- //
- if ((ModRm & X87_FCOM_MASK) == X87_FCOM_OPCODE) {
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- } else {
- Instruction->Definition.Target = X87_ST0_TARGET;
- Instruction->Definition.Source = X87_REGISTER_TARGET;
- }
- break;
- //
- // Handle DD instructions.
- //
- case 5:
- Instruction->Definition.Mnemonic = DbgX87DDC0Instructions[Opcode2];
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- break;
- //
- // Handle DE instructions.
- //
- case 6:
- Instruction->Definition.Mnemonic = DbgX87DEC0Instructions[Opcode2];
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- Instruction->Definition.Source = X87_ST0_TARGET;
- break;
- //
- // Handle DF instructions.
- //
- case 7:
- Index = (ModRm & X87_DF_C0_MASK) >> X87_DF_C0_SHIFT;
- //
- // There's a small rash of individual instructions in the E0-E7
- // range. They're pretty old school.
- //
- if (Index == X87_DF_E0_INDEX) {
- Index = ModRm & X87_DF_E0_MASK;
- if (Index < X87_DF_E0_COUNT) {
- Instruction->Definition.Mnemonic =
- DbgX87DFE0Instructions[Index];
- Instruction->Definition.Target = X87_DF_E0_TARGET;
- }
- } else {
- Instruction->Definition.Mnemonic = DbgX87DFC0Instructions[Opcode2];
- Instruction->Definition.Target = X87_REGISTER_TARGET;
- Instruction->Definition.Source = X87_ST0_TARGET;
- }
- break;
- //
- // This function was inappropriately called.
- //
- default:
- assert(FALSE);
- break;
- }
- if (Instruction->Definition.Mnemonic == NULL) {
- return FALSE;
- }
- return TRUE;
- }
|