123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140714171427143714471457146714771487149715071517152715371547155715671577158715971607161716271637164716571667167716871697170717171727173717471757176717771787179718071817182718371847185718671877188718971907191719271937194719571967197719871997200720172027203720472057206720772087209721072117212721372147215721672177218721972207221722272237224722572267227722872297230723172327233723472357236723772387239724072417242724372447245724672477248724972507251725272537254725572567257725872597260726172627263726472657266726772687269727072717272727372747275727672777278727972807281728272837284728572867287728872897290729172927293729472957296729772987299730073017302730373047305730673077308730973107311731273137314731573167317731873197320732173227323732473257326732773287329733073317332733373347335733673377338733973407341734273437344734573467347734873497350735173527353735473557356735773587359736073617362736373647365736673677368736973707371737273737374737573767377737873797380738173827383738473857386738773887389739073917392739373947395739673977398739974007401740274037404740574067407740874097410741174127413741474157416741774187419742074217422742374247425742674277428742974307431743274337434743574367437743874397440744174427443744474457446744774487449745074517452745374547455745674577458745974607461746274637464746574667467746874697470747174727473747474757476747774787479748074817482748374847485748674877488748974907491749274937494749574967497749874997500750175027503750475057506750775087509751075117512751375147515751675177518751975207521752275237524752575267527752875297530753175327533753475357536753775387539754075417542754375447545754675477548754975507551755275537554755575567557755875597560756175627563756475657566756775687569757075717572757375747575757675777578757975807581758275837584758575867587758875897590759175927593759475957596759775987599760076017602760376047605760676077608760976107611761276137614761576167617761876197620762176227623762476257626762776287629763076317632763376347635763676377638763976407641764276437644764576467647764876497650765176527653765476557656765776587659766076617662766376647665766676677668766976707671767276737674767576767677767876797680768176827683768476857686768776887689769076917692769376947695769676977698769977007701770277037704770577067707770877097710771177127713771477157716771777187719772077217722772377247725772677277728772977307731773277337734773577367737773877397740774177427743774477457746774777487749775077517752775377547755775677577758775977607761776277637764776577667767776877697770777177727773777477757776777777787779778077817782778377847785778677877788778977907791779277937794779577967797779877997800780178027803780478057806780778087809781078117812781378147815781678177818781978207821782278237824782578267827782878297830783178327833783478357836783778387839784078417842784378447845784678477848784978507851785278537854785578567857785878597860786178627863786478657866786778687869787078717872787378747875787678777878787978807881788278837884788578867887788878897890789178927893789478957896789778987899790079017902790379047905790679077908790979107911791279137914791579167917791879197920792179227923792479257926792779287929793079317932793379347935793679377938793979407941794279437944794579467947794879497950795179527953795479557956795779587959796079617962796379647965796679677968796979707971797279737974797579767977797879797980798179827983798479857986798779887989799079917992799379947995799679977998799980008001800280038004800580068007800880098010801180128013801480158016801780188019802080218022802380248025802680278028802980308031803280338034803580368037803880398040804180428043804480458046804780488049805080518052805380548055805680578058805980608061806280638064806580668067806880698070807180728073807480758076807780788079808080818082808380848085808680878088808980908091809280938094809580968097809880998100810181028103810481058106810781088109811081118112811381148115811681178118811981208121812281238124812581268127812881298130813181328133813481358136813781388139814081418142814381448145814681478148814981508151815281538154815581568157815881598160816181628163816481658166816781688169817081718172817381748175817681778178817981808181818281838184818581868187818881898190819181928193819481958196819781988199820082018202820382048205820682078208820982108211821282138214821582168217821882198220822182228223822482258226822782288229823082318232823382348235823682378238823982408241824282438244824582468247824882498250825182528253825482558256825782588259826082618262826382648265826682678268826982708271827282738274827582768277827882798280828182828283828482858286828782888289829082918292829382948295829682978298829983008301830283038304830583068307830883098310831183128313831483158316831783188319832083218322832383248325832683278328832983308331833283338334833583368337833883398340834183428343834483458346834783488349835083518352835383548355835683578358835983608361836283638364836583668367836883698370837183728373837483758376837783788379838083818382838383848385838683878388838983908391839283938394839583968397839883998400840184028403840484058406840784088409841084118412841384148415841684178418841984208421842284238424842584268427842884298430843184328433843484358436843784388439844084418442844384448445844684478448844984508451845284538454845584568457845884598460846184628463846484658466846784688469847084718472847384748475847684778478847984808481848284838484848584868487848884898490849184928493849484958496849784988499850085018502850385048505850685078508850985108511851285138514851585168517851885198520852185228523852485258526852785288529853085318532853385348535853685378538853985408541854285438544854585468547854885498550855185528553855485558556855785588559856085618562856385648565856685678568856985708571857285738574857585768577857885798580858185828583858485858586858785888589859085918592859385948595859685978598859986008601860286038604860586068607860886098610861186128613861486158616861786188619862086218622862386248625862686278628862986308631863286338634863586368637863886398640864186428643864486458646864786488649865086518652865386548655865686578658865986608661866286638664866586668667866886698670867186728673867486758676867786788679868086818682868386848685868686878688868986908691869286938694869586968697869886998700870187028703870487058706870787088709871087118712871387148715871687178718871987208721872287238724872587268727872887298730873187328733873487358736873787388739874087418742874387448745874687478748874987508751875287538754875587568757875887598760876187628763876487658766876787688769877087718772877387748775877687778778877987808781878287838784878587868787878887898790879187928793879487958796879787988799880088018802880388048805880688078808880988108811881288138814881588168817881888198820882188228823882488258826882788288829883088318832883388348835883688378838883988408841884288438844884588468847884888498850885188528853885488558856885788588859886088618862886388648865886688678868886988708871887288738874887588768877887888798880888188828883888488858886888788888889889088918892889388948895889688978898889989008901890289038904890589068907890889098910891189128913891489158916891789188919892089218922892389248925892689278928892989308931893289338934893589368937893889398940894189428943894489458946894789488949895089518952895389548955895689578958895989608961896289638964896589668967896889698970897189728973897489758976897789788979898089818982898389848985898689878988898989908991899289938994899589968997899889999000900190029003900490059006900790089009901090119012901390149015901690179018901990209021902290239024902590269027902890299030903190329033903490359036903790389039904090419042904390449045904690479048904990509051905290539054905590569057905890599060906190629063906490659066906790689069907090719072907390749075907690779078907990809081908290839084908590869087908890899090909190929093909490959096909790989099910091019102910391049105910691079108910991109111911291139114911591169117911891199120912191229123912491259126912791289129913091319132913391349135913691379138913991409141914291439144914591469147914891499150915191529153915491559156915791589159916091619162916391649165916691679168916991709171917291739174917591769177917891799180918191829183918491859186918791889189919091919192919391949195919691979198919992009201920292039204920592069207920892099210921192129213921492159216921792189219922092219222922392249225922692279228922992309231923292339234923592369237923892399240924192429243 |
- /*++
- Copyright (c) 2014 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:
- armdis.c
- Abstract:
- This module implements support for the ARM disassembler.
- Author:
- Evan Green 20-Mar-2014
- Environment:
- Debug
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include "dbgrtl.h"
- #include "disasm.h"
- #include "armdis.h"
- #include "thmdis.h"
- #include <string.h>
- #include <stdio.h>
- //
- // ---------------------------------------------------------------- Definitions
- //
- //
- // Define the bitmask of vector list printing flags.
- //
- #define DBG_ARM_VECTOR_LIST_FLAG_ALL_LANES 0x00000001
- #define DBG_ARM_VECTOR_LIST_FLAG_INDEX 0x00000002
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- VOID
- DbgpArmDecodeUnconditional (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeDataProcessingAndMiscellaneous (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeMediaInstruction (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeBranchAndBlockTransfer (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeCoprocessorSupervisor (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeMemoryHintSimdMisc (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeStoreReturnState (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeReturnFromException (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeBranch (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeUndefined (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeUnpredictable (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeNop (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeChangeProcessorState (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSetEndianness (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodePreloadInstruction (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeClearExclusive (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeDataSynchronizationBarrier (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeDataMemoryBarrier (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeInstructionSynchronizationBarrier (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeParallelAdditionSubtraction (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodePackingInstructions (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeExtensionWithRotation (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSelectBytes (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodePackHalfword (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeReverse (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSaturate (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSumofAbsoluteDifferences (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeBitFieldInstructions (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodePermanentlyUndefined (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeLoadStore (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeExtraLoadStore (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeLoadStoreMultiple (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeDataProcessing (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeLoadImmediate (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeMiscellaneous (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeMsrImmediateAndHints (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeMultiply (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSynchronization (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSupervisorCall (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeFloatingPointTwoRegisters (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeFloatingPointThreeRegisters (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeFloatingPointVectorConvert (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeFloatingPointVectorCompare (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdSmallMove (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdSpecialMove (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdDuplicate (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdLoadStoreRegister (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdLoadStoreMultiple (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdElementLoadAllLanes (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdElementLoadStoreSingle (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdElementLoadStoreMultiple (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdThreeRegistersSameLength (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdOneRegister (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdTwoRegistersWithShift (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdThreeRegistersDifferentLength (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdTwoRegistersWithScalar (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdTwoRegistersMiscellaneous (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdVectorExtract (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdVectorTableLookup (
- PARM_DISASSEMBLY Context
- );
- VOID
- DbgpArmDecodeSimdVectorDuplicate (
- PARM_DISASSEMBLY Context
- );
- PSTR
- DbgpArmGetLoadStoreTypeString (
- ULONG Instruction
- );
- PSTR
- DbgpArmGetBankedRegisterString (
- ULONG Instruction
- );
- VOID
- DbgpArmPrintStatusRegister (
- PSTR Operand,
- ULONG Instruction
- );
- VOID
- DbgpArmPrintVectorList (
- PSTR Destination,
- ULONG DestinationSize,
- ULONG VectorStart,
- ULONG VectorCount,
- ULONG VectorIncrement,
- PSTR VectorTypeString,
- ULONG VectorIndex,
- ULONG Flags
- );
- VOID
- DbgpArmDecodeImmediateShift (
- PSTR Destination,
- ULONG DestinationSize,
- ULONG Register,
- ULONG Type,
- ULONG Immediate
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- //
- // Define decode tables.
- //
- ARM_DECODE_BRANCH DbgArmTopLevelTable[] = {
- {0xF0000000, 0xF0000000, 0, DbgpArmDecodeUnconditional},
- {0x0C000000, 0x00000000, 0, DbgpArmDecodeDataProcessingAndMiscellaneous},
- {0x0E000010, 0x06000010, 0, DbgpArmDecodeMediaInstruction},
- {0x0C000000, 0x04000000, 0, DbgpArmDecodeLoadStore},
- {0x0C000000, 0x08000000, 0, DbgpArmDecodeBranchAndBlockTransfer},
- {0x0C000000, 0x0C000000, 0, DbgpArmDecodeCoprocessorSupervisor},
- };
- ARM_DECODE_BRANCH DbgArmUnconditionalTable[] = {
- {0x08000000, 0x00000000, 0, DbgpArmDecodeMemoryHintSimdMisc},
- {0x0E500000, 0x08400000, 0, DbgpArmDecodeStoreReturnState},
- {0x0E500000, 0x08100000, 0, DbgpArmDecodeReturnFromException},
- {0x0E000000, 0x0A000000, 0, DbgpArmDecodeBranch},
- {0x0F000010, 0x0E000000, 0, DbgpArmDecodeCoprocessorMove},
- {0x000000E0, 0x000000A0, 0, DbgpArmDecodeUndefined},
- {0x0FE00000, 0x0C400000, 0, DbgpArmDecodeCoprocessorMoveTwo},
- {0x0FA00000, 0x0C000000, 0, DbgpArmDecodeUndefined},
- {0x0E000000, 0x0C000000, 0, DbgpArmDecodeCoprocessorLoadStore},
- {0x0F100010, 0x0E000010, 0, DbgpArmDecodeCoprocessorMove},
- {0x0F100010, 0x0E100010, 0, DbgpArmDecodeCoprocessorMove},
- };
- ARM_DECODE_BRANCH DbgArmMemoryHintSimdMiscTable[] = {
- {0x07F10020, 0x01000000, 0, DbgpArmDecodeChangeProcessorState},
- {0x07F100F0, 0x01010000, 0, DbgpArmDecodeSetEndianness},
- {0x06000000, 0x02000000, 0, DbgpArmDecodeSimdDataProcessing},
- {0x07100000, 0x04000000, 0, DbgpArmDecodeSimdElementLoadStore},
- {0x07700000, 0x04100000, 0, DbgpArmDecodeNop},
- {0x07700000, 0x04500000, 0, DbgpArmDecodePreloadInstruction},
- {0x07300000, 0x04300000, 0, DbgpArmDecodeUnpredictable},
- {0x077F0000, 0x051F0000, 0, DbgpArmDecodeUnpredictable},
- {0x07300000, 0x05100000, 0, DbgpArmDecodePreloadInstruction},
- {0x07F00000, 0x05300000, 0, DbgpArmDecodeUnpredictable},
- {0x07F000F0, 0x05700000, 0, DbgpArmDecodeUnpredictable},
- {0x07F000E0, 0x05700020, 0, DbgpArmDecodeUnpredictable},
- {0x07F000F0, 0x05700070, 0, DbgpArmDecodeUnpredictable},
- {0x07F00080, 0x05700080, 0, DbgpArmDecodeUnpredictable},
- {0x07F000F0, 0x05700010, 0, DbgpArmDecodeClearExclusive},
- {0x07F000F0, 0x05700040, 0, DbgpArmDecodeDataSynchronizationBarrier},
- {0x07F000F0, 0x05700050, 0, DbgpArmDecodeDataMemoryBarrier},
- {0x07F000F0, 0x05700060, 0, DbgpArmDecodeInstructionSynchronizationBarrier},
- {0x07B00000, 0x05B00000, 0, DbgpArmDecodeUnpredictable},
- {0x07700010, 0x06100000, 0, DbgpArmDecodeNop},
- {0x07700010, 0x06500000, 0, DbgpArmDecodePreloadInstruction},
- {0x07300010, 0x07100000, 0, DbgpArmDecodePreloadInstruction},
- {0x06300010, 0x06300000, 0, DbgpArmDecodeUnpredictable},
- {0x07F000F0, 0x07F000F0, 0, DbgpArmDecodeUndefined},
- };
- ARM_DECODE_BRANCH DbgArmSimdDataProcessingTable[] = {
- {0x00800000, 0x00000000, 0, DbgpArmDecodeSimdThreeRegistersSameLength},
- {0x00B80090, 0x00800010, 0, DbgpArmDecodeSimdOneRegister},
- {0x00800010, 0x00800010, 0, DbgpArmDecodeSimdTwoRegistersWithShift},
- {0x00A00050, 0x00800000, 0, DbgpArmDecodeSimdThreeRegistersDifferentLength},
- {0x00B00050, 0x00A00000, 0, DbgpArmDecodeSimdThreeRegistersDifferentLength},
- {0x00A00050, 0x00800040, 0, DbgpArmDecodeSimdTwoRegistersWithScalar},
- {0x00B00050, 0x00A00040, 0, DbgpArmDecodeSimdTwoRegistersWithScalar},
- {0x01B00010, 0x00B00000, 0, DbgpArmDecodeSimdVectorExtract},
- {0x01B00810, 0x01B00000, 0, DbgpArmDecodeSimdTwoRegistersMiscellaneous},
- {0x01B00C10, 0x01B00800, 0, DbgpArmDecodeSimdVectorTableLookup},
- {0x01B00F90, 0x01B00C00, 0, DbgpArmDecodeSimdVectorDuplicate},
- };
- ARM_DECODE_BRANCH DbgArmSimdElementLoadStoreTable[] = {
- {0x00A00C00, 0x00A00C00, 0, DbgpArmDecodeSimdElementLoadAllLanes},
- {0x00800000, 0x00800000, 0, DbgpArmDecodeSimdElementLoadStoreSingle},
- {0x00800000, 0x00000000, 0, DbgpArmDecodeSimdElementLoadStoreMultiple},
- };
- ARM_DECODE_BRANCH DbgArmDataProcessingAndMiscellaneousTable[] = {
- {0x03900080, 0x01000000, 0, DbgpArmDecodeMiscellaneous},
- {0x03900090, 0x01000080, 0, DbgpArmDecodeMultiply},
- {0x02000010, 0x00000000, 0, DbgpArmDecodeDataProcessing},
- {0x02000090, 0x00000010, 0, DbgpArmDecodeDataProcessing},
- {0x030000F0, 0x00000090, 0, DbgpArmDecodeMultiply},
- {0x030000F0, 0x01000090, 0, DbgpArmDecodeSynchronization},
- {0x032000F0, 0x002000B0, 0, DbgpArmDecodeExtraLoadStore},
- {0x032000D0, 0x002000D0, 0, DbgpArmDecodeExtraLoadStore},
- {0x020000F0, 0x000000B0, 0, DbgpArmDecodeExtraLoadStore},
- {0x020000D0, 0x000000D0, 0, DbgpArmDecodeExtraLoadStore},
- {0x03F00000, 0x03000000, 0, DbgpArmDecodeLoadImmediate},
- {0x03F00000, 0x03400000, 0, DbgpArmDecodeLoadImmediate},
- {0x03B00000, 0x03200000, 0, DbgpArmDecodeMsrImmediateAndHints},
- {0x02000000, 0x02000000, 0, DbgpArmDecodeDataProcessing},
- };
- ARM_DECODE_BRANCH DbgArmMediaInstructionTable[] = {
- {0x01800000, 0x00000000, 0, DbgpArmDecodeParallelAdditionSubtraction},
- {0x01800000, 0x00800000, 0, DbgpArmDecodePackingInstructions},
- {0x01800000, 0x01000000, 0, DbgpArmDecodeMultiply},
- {0x01F000E0, 0x01800000, 0, DbgpArmDecodeSumofAbsoluteDifferences},
- {0x01A00060, 0x01A00040, 0, DbgpArmDecodeBitFieldInstructions},
- {0x01E00060, 0x01C00000, 0, DbgpArmDecodeBitFieldInstructions},
- {0xF1F000E0, 0xE1F000E0, 0, DbgpArmDecodePermanentlyUndefined},
- };
- ARM_DECODE_BRANCH DbgArmPackingInstructionTable[] = {
- {0x000000E0, 0x00000060, 0, DbgpArmDecodeExtensionWithRotation},
- {0x007000E0, 0x000000A0, 0, DbgpArmDecodeSelectBytes},
- {0x00700020, 0x00000000, 0, DbgpArmDecodePackHalfword},
- {0x00300060, 0x00300020, 0, DbgpArmDecodeReverse},
- {0x003000E0, 0x00200020, 0, DbgpArmDecodeSaturate},
- {0x00200020, 0x00200000, 0, DbgpArmDecodeSaturate}
- };
- ARM_DECODE_BRANCH DbgArmBranchAndBlockTransferTable[] = {
- {0x02000000, 0x02000000, 0, DbgpArmDecodeBranch},
- {0x02000000, 0x00000000, 0, DbgpArmDecodeLoadStoreMultiple},
- };
- ARM_DECODE_BRANCH DbgArmCoprocessorSupervisorTable[] = {
- {0x03E00000, 0x00000000, 0, DbgpArmDecodeUndefined},
- {0x03000000, 0x03000000, 0, DbgpArmDecodeSupervisorCall},
- {0x03E00E00, 0x00400A00, 0, DbgpArmDecodeSimd64BitTransfers},
- {0x02000E00, 0x00000A00, 0, DbgpArmDecodeSimdLoadStore},
- {0x03000E10, 0x02000A00, 0, DbgpArmDecodeFloatingPoint},
- {0x03000E10, 0x02000A10, 0, DbgpArmDecodeSimdSmallTransfers},
- {0x03E00000, 0x00400000, 0, DbgpArmDecodeCoprocessorMoveTwo},
- {0x02000000, 0x00000000, 0, DbgpArmDecodeCoprocessorLoadStore},
- {0x03000000, 0x02000000, 0, DbgpArmDecodeCoprocessorMove},
- };
- ARM_DECODE_BRANCH DbgArmFloatingPointTable[] = {
- {0x00B00040, 0x00B00000, 0, DbgpArmDecodeFloatingPointTwoRegisters},
- {0x00BE0040, 0x00B00040, 0, DbgpArmDecodeFloatingPointTwoRegisters},
- {0x00BE0040, 0x00B20040, 0, DbgpArmDecodeFloatingPointVectorConvert},
- {0x00BE0040, 0x00B40040, 0, DbgpArmDecodeFloatingPointVectorCompare},
- {0x00BF00C0, 0x00B700C0, 0, DbgpArmDecodeFloatingPointVectorConvert},
- {0x00BF0040, 0x00B80040, 0, DbgpArmDecodeFloatingPointVectorConvert},
- {0x00BE0040, 0x00BA0040, 0, DbgpArmDecodeFloatingPointVectorConvert},
- {0x00BE0040, 0x00BC0040, 0, DbgpArmDecodeFloatingPointVectorConvert},
- {0x00BE0040, 0x00BE0040, 0, DbgpArmDecodeFloatingPointVectorConvert},
- {0x00B00000, 0x00B00000, 0, DbgpArmDecodeUndefined},
- {0x00B00040, 0x00800040, 0, DbgpArmDecodeUndefined},
- {0x00000000, 0x00000000, 0, DbgpArmDecodeFloatingPointThreeRegisters},
- };
- ARM_DECODE_BRANCH DbgArmSimdSmallTransferTable[] = {
- {0x00F00100, 0x00000000, 0, DbgpArmDecodeSimdSmallMove},
- {0x00F00100, 0x00E00000, 0, DbgpArmDecodeSimdSpecialMove},
- {0x00900100, 0x00000100, 0, DbgpArmDecodeSimdSmallMove},
- {0x00900140, 0x00800100, 0, DbgpArmDecodeSimdDuplicate},
- {0x00F00100, 0x00100000, 0, DbgpArmDecodeSimdSmallMove},
- {0x00F00100, 0x00F00000, 0, DbgpArmDecodeSimdSpecialMove},
- {0x00100100, 0x00100100, 0, DbgpArmDecodeSimdSmallMove},
- };
- ARM_DECODE_BRANCH DbgArmSimdLoadStoreTable[] = {
- {0x01200000, 0x01000000, 0, DbgpArmDecodeSimdLoadStoreRegister},
- {0x01800000, 0x00800000, 0, DbgpArmDecodeSimdLoadStoreMultiple},
- {0x01800000, 0x01000000, 0, DbgpArmDecodeSimdLoadStoreMultiple},
- };
- PSTR DbgArmRegisterNames[] = {
- "r0",
- "r1",
- "r2",
- "r3",
- "r4",
- "r5",
- "r6",
- "r7",
- "r8",
- "r9",
- "r10",
- "fp",
- "ip",
- "sp",
- "lr",
- "pc",
- "f0"
- "f1",
- "f2",
- "f3",
- "f4",
- "f5",
- "f6",
- "f7",
- "fps",
- "cpsr"
- };
- PSTR DbgArmSpecialRegisterNames[16] = {
- "fpsid",
- "fpscr",
- "<arch>",
- "<arch>",
- "<arch>",
- "<arch>",
- "mvfr1",
- "mvfr0",
- "fpexc",
- "fpinst",
- "fpinst2",
- "<arch>",
- "<arch>",
- "<arch>",
- "<arch>",
- "<arch>",
- };
- PSTR DbgArmConditionCodes[16] = {
- "eq",
- "ne",
- "cs",
- "cc",
- "mi",
- "pl",
- "vs",
- "vc",
- "hi",
- "ls",
- "ge",
- "lt",
- "gt",
- "le",
- "",
- "",
- };
- PSTR DbgArmDataProcessingMnemonics[16] = {
- "and",
- "eor",
- "sub",
- "rsb",
- "add",
- "adc",
- "sbc",
- "rsc",
- "tst",
- "teq",
- "cmp",
- "cmn",
- "orr",
- "mov",
- "bic",
- "mvn"
- };
- PSTR DbgArmSynchronizationMnemonics[8] = {
- "strex",
- "ldrex",
- "strexd",
- "ldrexd",
- "strexb",
- "ldrexb",
- "strexh",
- "ldrexh"
- };
- PSTR DbgArmBankedRegisters[64] = {
- "r8_usr",
- "r9_usr",
- "r10_usr",
- "r11_usr",
- "r12_usr",
- "sp_usr",
- "lr_usr",
- "UNPREDICTABLE",
- "r8_fiq",
- "r9_fiq",
- "r10_fiq",
- "r11_fiq",
- "r12_fiq",
- "sp_fiq",
- "lr_fiq",
- "UNPREDICTABLE",
- "lr_irq",
- "sp_irq",
- "lr_svc",
- "sp_svc",
- "lr_abr",
- "sp_abt",
- "lr_und",
- "sp_und",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "lr_mon",
- "sp_mon",
- "elr_hyp",
- "sp_hyp",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "spsr_fiq",
- "UNPREDICTABLE",
- "spsr_irq",
- "UNPREDICTABLE",
- "spsr_svc",
- "UNPREDICTABLE",
- "spsr_abt",
- "UNPREDICTABLE",
- "spsr_und",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "UNPREDICTABLE",
- "spsr_mon",
- "spsr_hyp"
- };
- PSTR DbgArmParallelArithmeticMnemonics[2][24] = {
- {
- "sadd16",
- "sasx",
- "ssax",
- "ssub16",
- "sadd8",
- NULL,
- NULL,
- "ssub8",
- "qadd16",
- "qasx",
- "qsax",
- "qsub16",
- "qadd8",
- NULL,
- NULL,
- "qsub8",
- "shadd16",
- "shasx",
- "shsax",
- "shsub16",
- "shadd8",
- NULL,
- NULL,
- "shsub8"
- },
- {
- "uadd16",
- "uasx",
- "usax",
- "usub16",
- "uadd8",
- NULL,
- NULL,
- "usub8",
- "uqadd16",
- "uqasx"
- "uqsax"
- "uqsub16",
- "uqadd8",
- NULL,
- NULL,
- "uqsub8",
- "uhadd16",
- "uhasx",
- "uhsax",
- "uhsub16",
- "uhadd8",
- NULL,
- NULL,
- "uhsub8"
- }
- };
- PSTR DbgArmExtensionRotationMnemonics[2][8] = {
- {
- "sxtab16",
- NULL,
- "sxtab",
- "sxtah",
- "uxtab16",
- NULL,
- "uxtab",
- "uxtah"
- },
- {
- "sxtb16",
- NULL,
- "sxtb",
- "sxth",
- "uxtb16",
- NULL,
- "uxtb",
- "uxth"
- }
- };
- PSTR DbgArmReverseMnemonics[4] = {
- "rev",
- "rbit",
- "rev16",
- "revsh"
- };
- PSTR DbgArmSimdElementLoadStoreMultipleElementSuffix[] = {
- ARM_SIMD_ELEMENT_LOAD_STORE_4_ELEMENT_SUFFIX,
- ARM_SIMD_ELEMENT_LOAD_STORE_4_ELEMENT_SUFFIX,
- ARM_SIMD_ELEMENT_LOAD_STORE_1_ELEMENT_SUFFIX,
- ARM_SIMD_ELEMENT_LOAD_STORE_2_ELEMENT_SUFFIX,
- ARM_SIMD_ELEMENT_LOAD_STORE_3_ELEMENT_SUFFIX,
- ARM_SIMD_ELEMENT_LOAD_STORE_3_ELEMENT_SUFFIX,
- ARM_SIMD_ELEMENT_LOAD_STORE_1_ELEMENT_SUFFIX,
- ARM_SIMD_ELEMENT_LOAD_STORE_1_ELEMENT_SUFFIX,
- ARM_SIMD_ELEMENT_LOAD_STORE_2_ELEMENT_SUFFIX,
- ARM_SIMD_ELEMENT_LOAD_STORE_2_ELEMENT_SUFFIX,
- ARM_SIMD_ELEMENT_LOAD_STORE_1_ELEMENT_SUFFIX
- };
- ULONG DbgArmSimdElementLoadStoreMultipleVectorCount[] = {
- 4, 4, 4, 4, 3, 3, 1, 2, 2, 2
- };
- //
- // ------------------------------------------------------------------ Functions
- //
- BOOL
- DbgpArmDisassemble (
- ULONGLONG InstructionPointer,
- PBYTE InstructionStream,
- PSTR Buffer,
- ULONG BufferLength,
- PDISASSEMBLED_INSTRUCTION Disassembly,
- MACHINE_LANGUAGE Language
- )
- /*++
- Routine Description:
- This routine decodes one instruction from an ARM 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 machine language to interpret this stream as.
- Return Value:
- TRUE on success.
- FALSE if the instruction was unknown.
- --*/
- {
- ULONG ConditionCode;
- ARM_DISASSEMBLY Context;
- BOOL Decoded;
- BOOL Result;
- RtlZeroMemory(Disassembly, sizeof(DISASSEMBLED_INSTRUCTION));
- if (BufferLength < ARM_INSTRUCTION_SIZE) {
- Result = FALSE;
- goto ArmDisassembleEnd;
- }
- RtlZeroMemory(&Context, sizeof(ARM_DISASSEMBLY));
- Context.Result = Disassembly;
- Context.InstructionPointer = InstructionPointer;
- //
- // Get the instruction word. Always take the max, four bytes, even if the
- // instruction might only end up being two.
- //
- Context.Instruction = *((PULONG)InstructionStream);
- //
- // If this is Thumb, then just call the thumb decode function and skip the
- // rest of this.
- //
- if (Language == MachineLanguageThumb2) {
- DbgpThumbDecode(&Context);
- Result = TRUE;
- goto ArmDisassembleEnd;
- }
- //
- // Use the ARM tables to decode the instruction.
- //
- ASSERT(Language == MachineLanguageArm);
- strcpy(Context.Mnemonic, "Unknown");
- Decoded = ARM_DECODE_WITH_TABLE(&Context, DbgArmTopLevelTable);
- if (Decoded != FALSE) {
- ConditionCode = Context.Instruction >> ARM_CONDITION_SHIFT;
- strcat(Context.Mnemonic, DbgArmConditionCodes[ConditionCode]);
- }
- Result = TRUE;
- Disassembly->BinaryLength = 4;
- ArmDisassembleEnd:
- if ((strlen(Context.Mnemonic) +
- strlen(Context.PostConditionMnemonicSuffix) +
- strlen(Context.Operand1) +
- strlen(Context.Operand2) +
- strlen(Context.Operand3) +
- strlen(Context.Operand4) + 5) > BufferLength) {
- Result = FALSE;
- }
- if (Result != FALSE) {
- strcat(Context.Mnemonic, Context.PostConditionMnemonicSuffix);
- strcpy(Buffer, Context.Mnemonic);
- Disassembly->Mnemonic = Buffer;
- Buffer += strlen(Context.Mnemonic) + 1;
- BufferLength -= strlen(Context.Mnemonic) + 1;
- if (*(Context.Operand1) != '\0') {
- strcpy(Buffer, Context.Operand1);
- Disassembly->DestinationOperand = Buffer;
- Buffer += strlen(Context.Operand1) + 1;
- BufferLength -= strlen(Context.Operand1) + 1;
- }
- if (*(Context.Operand2) != '\0') {
- strcpy(Buffer, Context.Operand2);
- Disassembly->SourceOperand = Buffer;
- Buffer += strlen(Context.Operand2) + 1;
- BufferLength -= strlen(Context.Operand2) + 1;
- }
- if (*(Context.Operand3) != '\0') {
- strcpy(Buffer, Context.Operand3);
- Disassembly->ThirdOperand = Buffer;
- Buffer += strlen(Context.Operand3) + 1;
- BufferLength -= strlen(Context.Operand3) + 1;
- }
- if (*(Context.Operand4) != '\0') {
- strcpy(Buffer, Context.Operand4);
- Disassembly->FourthOperand = Buffer;
- }
- }
- return Result;
- }
- BOOL
- DbgpArmDecodeWithTable (
- PARM_DISASSEMBLY Context,
- PARM_DECODE_BRANCH Table,
- ULONG TableSize
- )
- /*++
- Routine Description:
- This routine checks the masks and values specified by the given table, and
- calls the appropriate disassembly routine.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Table - Supplies a pointer to the decode branch table.
- TableSize - Supplies the number of elements in the table.
- Return Value:
- TRUE if a match was found.
- --*/
- {
- ULONG Instruction;
- ULONG Mask;
- ULONG Shift;
- ULONG TableIndex;
- ULONG Value;
- Instruction = Context->Instruction;
- for (TableIndex = 0; TableIndex < TableSize; TableIndex += 1) {
- Shift = Table[TableIndex].Shift;
- Mask = Table[TableIndex].Mask << Shift;
- Value = Table[TableIndex].Value << Shift;
- if ((Instruction & Mask) == Value) {
- //
- // Call the disassembly routine, this table entry matched.
- //
- Table[TableIndex].Disassemble(Context);
- return TRUE;
- }
- }
- //
- // Nothing matched.
- //
- return FALSE;
- }
- VOID
- DbgpArmDecodeCoprocessorMove (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a coprocessor move instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Condition;
- ULONG Coprocessor;
- ULONG Instruction;
- PSTR MnemonicSuffix;
- ULONG Opcode1;
- ULONG Opcode2;
- ULONG RegisterD;
- ULONG RegisterM;
- ULONG RegisterN;
- Instruction = Context->Instruction;
- //
- // Get the basic fields for CDP, MRC, and MCR instructions.
- //
- Coprocessor = (Instruction & ARM_COPROCESSOR_NUMBER_MASK) >>
- ARM_COPROCESSOR_NUMBER_SHIFT;
- RegisterD = (Instruction & ARM_DESTINATION_REGISTER_MASK) >>
- ARM_DESTINATION_REGISTER_SHIFT;
- RegisterN = (Instruction & ARM_COPROCESSOR_RN_MASK) >>
- ARM_COPROCESSOR_RN_SHIFT;
- RegisterM = (Instruction & ARM_COPROCESSOR_RM_MASK) >>
- ARM_COPROCESSOR_RM_SHIFT;
- Opcode2 = (Instruction & ARM_COPROCESSOR_OPCODE2_MASK) >>
- ARM_COPROCESSOR_OPCODE2_SHIFT;
- //
- // CDP has a different opcode 1 shift, so this needs to be adjusted for
- // that instruction.
- //
- Opcode1 = (Instruction & ARM_MCR_MRC_OPCODE1_MASK) >>
- ARM_MCR_MRC_OPCODE1_SHIFT;
- //
- // If the CDP bit is 0, then this instruction is a CDP instruction.
- //
- if ((Instruction & ARM_COPROCESSOR_CDP_BIT) == 0) {
- BaseMnemonic = ARM_CDP_MNEMONIC;
- Opcode1 = (Instruction & ARM_CDP_OPCODE1_MASK) >> ARM_CDP_OPCODE1_SHIFT;
- sprintf(Context->Operand2, "c%d", RegisterD);
- //
- // If it's not a CDP instruction, check the other constant bit, which if
- // set indicates a MRC, if clear indicates MCR.
- //
- } else if ((Instruction & ARM_COPROCESSOR_MRC_BIT) != 0) {
- BaseMnemonic = ARM_MRC_MNEMONIC;
- sprintf(Context->Operand2, "r%d", RegisterD);
- } else {
- BaseMnemonic = ARM_MCR_MNEMONIC;
- sprintf(Context->Operand2, "r%d", RegisterD);
- }
- //
- // If the condition is 0xF, then these are CDP2, MRC2, and MCR2
- // instructions.
- //
- MnemonicSuffix = "";
- Condition = Context->Instruction >> ARM_CONDITION_SHIFT;
- if (Condition == ARM_CONDITION_UNCONDITIONAL) {
- MnemonicSuffix = "2";
- }
- sprintf(Context->Mnemonic, "%s%s", BaseMnemonic, MnemonicSuffix);
- sprintf(Context->Operand1, "p%d, %d", Coprocessor, Opcode1);
- sprintf(Context->Operand3, "c%d, c%d, %d", RegisterN, RegisterM, Opcode2);
- return;
- }
- VOID
- DbgpArmDecodeCoprocessorMoveTwo (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a coprocessor move instruction to/from two ARM
- registers.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Condition;
- ULONG Coprocessor;
- ULONG Instruction;
- PSTR MnemonicSuffix;
- ULONG Opcode1;
- ULONG RegisterM;
- ULONG RegisterT;
- ULONG RegisterT2;
- Instruction = Context->Instruction;
- //
- // Get the basic fields for MRRC and MCRR instructions.
- //
- Coprocessor = (Instruction & ARM_COPROCESSOR_NUMBER_MASK) >>
- ARM_COPROCESSOR_NUMBER_SHIFT;
- RegisterT = (Instruction & ARM_DESTINATION_REGISTER_MASK) >>
- ARM_DESTINATION_REGISTER_SHIFT;
- RegisterT2 = (Instruction & ARM_DESTINATION_REGISTER2_MASK) >>
- ARM_DESTINATION_REGISTER2_SHIFT;
- RegisterM = (Instruction & ARM_COPROCESSOR_RM_MASK) >>
- ARM_COPROCESSOR_RM_SHIFT;
- Opcode1 = (Instruction & ARM_MCRR_MRRC_OPCODE1_MASK) >>
- ARM_MCRR_MRRC_OPCODE1_SHIFT;
- //
- // Check the non-constant bit to determine if this is MRRC or MCRR.
- //
- if ((Instruction & ARM_COPROCESSOR_MRRC_BIT) != 0) {
- BaseMnemonic = ARM_MRRC_MNEMONIC;
- } else {
- BaseMnemonic = ARM_MCRR_MNEMONIC;
- }
- //
- // If the condition is 0xF, then these are MRRC2 and MCRR2 instructions.
- //
- MnemonicSuffix = "";
- Condition = Context->Instruction >> ARM_CONDITION_SHIFT;
- if (Condition == ARM_CONDITION_UNCONDITIONAL) {
- MnemonicSuffix = "2";
- }
- sprintf(Context->Mnemonic, "%s%s", BaseMnemonic, MnemonicSuffix);
- sprintf(Context->Operand1, "p%d, %d", Coprocessor, Opcode1);
- sprintf(Context->Operand2,
- "%s, %s",
- DbgArmRegisterNames[RegisterT],
- DbgArmRegisterNames[RegisterT2]);
- sprintf(Context->Operand3, "c%d", RegisterM);
- return;
- }
- VOID
- DbgpArmDecodeCoprocessorLoadStore (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a coprocessor data instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Condition;
- UCHAR CoprocessorDestination;
- UCHAR CoprocessorNumber;
- PSTR FirstSuffix;
- ULONG Immediate8;
- ULONG Instruction;
- UCHAR Rn;
- PSTR SecondSuffix;
- UCHAR SignCharacter;
- UCHAR WriteBack;
- Instruction = Context->Instruction;
- //
- // Determine whether it's a long load/store or regular.
- //
- SecondSuffix = "";
- if ((Instruction & ARM_COPROCESSOR_DATA_LONG_BIT) != 0) {
- SecondSuffix = ARM_COPROCESSOR_LONG_MNEMONIC;
- }
- //
- // Determine whether the immediate is added or subtracted.
- //
- if ((Instruction & ARM_ADD_SUBTRACT_BIT) != 0) {
- SignCharacter = '+';
- } else {
- SignCharacter = '-';
- }
- //
- // Get the register numbers and values involved.
- //
- CoprocessorDestination =
- (Instruction & ARM_COPROCESSOR_DATA_DESTINATION_MASK) >>
- ARM_COPROCESSOR_DATA_DESTINATION_SHIFT;
- Rn = (Instruction & ARM_COPROCESSOR_RN_MASK) >> ARM_COPROCESSOR_RN_SHIFT;
- Immediate8 = (UCHAR)(Instruction & 0xFF);
- CoprocessorNumber = (Instruction & ARM_COPROCESSOR_NUMBER_MASK) >>
- ARM_COPROCESSOR_NUMBER_SHIFT;
- //
- // Determine the mnemonic.
- //
- if ((Instruction & ARM_LOAD_BIT) != 0) {
- BaseMnemonic = ARM_COPROCESSOR_LOAD_MNEMONIC;
- } else {
- BaseMnemonic = ARM_COPROCESSOR_STORE_MNEMONIC;
- }
- //
- // If the condition is 0xF, then these are MRRC2 and MCRR2 instructions.
- //
- FirstSuffix = "";
- Condition = Context->Instruction >> ARM_CONDITION_SHIFT;
- if (Condition == ARM_CONDITION_UNCONDITIONAL) {
- FirstSuffix = "2";
- }
- sprintf(Context->Mnemonic,
- "%s%s%s",
- BaseMnemonic,
- FirstSuffix,
- SecondSuffix);
- //
- // Write out the first two operands.
- //
- sprintf(Context->Operand1, "p%d", CoprocessorNumber);
- sprintf(Context->Operand2, "c%d", CoprocessorDestination);
- //
- // Depending on the addressing mode, write out the third operand. If the
- // pre-index bit is set, the addressing mode is either pre-indexed or
- // offset.
- //
- if ((Instruction & ARM_PREINDEX_BIT) != 0) {
- if ((Instruction & ARM_WRITE_BACK_BIT) != 0) {
- WriteBack = '!';
- } else {
- WriteBack = ' ';
- }
- sprintf(Context->Operand3,
- "[%s, #%c%d]%c",
- DbgArmRegisterNames[Rn],
- SignCharacter,
- Immediate8 * 4,
- WriteBack);
- //
- // The pre-index bit is not set, so the addressing mode is either post-
- // indexed or unindexed.
- //
- } else {
- if ((Instruction & ARM_WRITE_BACK_BIT) != 0) {
- sprintf(Context->Operand3,
- "[%s], #%c%d",
- DbgArmRegisterNames[Rn],
- SignCharacter,
- Immediate8 * 4);
- } else {
- sprintf(Context->Operand3,
- "[%s], {%d}",
- DbgArmRegisterNames[Rn],
- Immediate8);
- }
- }
- return;
- }
- VOID
- DbgpArmDecodeFloatingPoint (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a floating point data processing instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ARM_DECODE_WITH_TABLE(Context, DbgArmFloatingPointTable);
- return;
- }
- VOID
- DbgpArmDecodeSimdSmallTransfers (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a transfers between SIMD and floating point 8-bit,
- 16-bit, and 32-bit registers and the ARM core.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ARM_DECODE_WITH_TABLE(Context, DbgArmSimdSmallTransferTable);
- return;
- }
- VOID
- DbgpArmDecodeSimd64BitTransfers (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a transfers between SIMD and floating point 64-bit
- registers and the ARM core.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ULONG Instruction;
- PSTR RegisterString;
- ULONG Rt;
- ULONG Rt2;
- ULONG Vector;
- PSTR VectorString;
- Instruction = Context->Instruction;
- Vector = (Instruction & ARM_SIMD_TRANSFER_64_VECTOR_MASK) >>
- ARM_SIMD_TRANSFER_64_VECTOR_SHIFT;
- Rt = (Instruction & ARM_SIMD_TRANSFER_64_RT_MASK) >>
- ARM_SIMD_TRANSFER_64_RT_SHIFT;
- Rt2 = (Instruction & ARM_SIMD_TRANSFER_64_RT2_MASK) >>
- ARM_SIMD_TRANSFER_64_RT2_SHIFT;
- if ((Instruction & ARM_SIMD_TRANSFER_64_TO_REGISTER) != 0) {
- RegisterString = Context->Operand1;
- VectorString = Context->Operand2;
- } else {
- VectorString = Context->Operand1;
- RegisterString = Context->Operand2;
- }
- strcpy(Context->Mnemonic, ARM_VMOV_MNEMONIC);
- sprintf(RegisterString,
- "%s, %s",
- DbgArmRegisterNames[Rt],
- DbgArmRegisterNames[Rt2]);
- if ((Instruction & ARM_SIMD_TRANSFER_64_DOUBLE) != 0) {
- if ((Instruction & ARM_SIMD_TRANSFER_64_VECTOR_BIT) != 0) {
- Vector |= (1 << 4);
- }
- sprintf(VectorString,
- "%s%d",
- ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR,
- Vector);
- } else {
- Vector <<= 1;
- if ((Instruction & ARM_SIMD_TRANSFER_64_VECTOR_BIT) != 0) {
- Vector |= 1;
- }
- sprintf(VectorString,
- "%s%d, %s%d",
- ARM_FLOATING_POINT_SINGLE_PRECISION_VECTOR,
- Vector,
- ARM_FLOATING_POINT_SINGLE_PRECISION_VECTOR,
- Vector + 1);
- }
- return;
- }
- VOID
- DbgpArmDecodeSimdLoadStore (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a load/store instructions involving SIMD and floating
- point registers.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ARM_DECODE_WITH_TABLE(Context, DbgArmSimdLoadStoreTable);
- return;
- }
- VOID
- DbgpArmDecodeSimdElementLoadStore (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a SIMD element and structure load and store
- instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ARM_DECODE_WITH_TABLE(Context, DbgArmSimdElementLoadStoreTable);
- return;
- }
- VOID
- DbgpArmDecodeSimdDataProcessing (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the SIMD data processing instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ARM_DECODE_WITH_TABLE(Context, DbgArmSimdDataProcessingTable);
- return;
- }
- VOID
- DbgpArmDecodeRegisterList (
- PSTR Destination,
- ULONG DestinationSize,
- ULONG RegisterList
- )
- /*++
- Routine Description:
- This routine converts an ARM register list to a string.
- Arguments:
- Destination - Supplies a pointer to the destination string.
- DestinationSize - Supplies the size of the destination string.
- RegisterList - Supplies the register bitmask.
- Return Value:
- None.
- --*/
- {
- ULONG CurrentRegister;
- BOOL FirstRegister;
- strcpy(Destination, "{");
- //
- // Loop through the registers, adding the ones specified in the bitfield.
- //
- FirstRegister = TRUE;
- for (CurrentRegister = 0; CurrentRegister < 16; CurrentRegister += 1) {
- if ((RegisterList & 0x00000001) != 0) {
- if (FirstRegister == FALSE) {
- strcat(Destination, ", ");
- }
- strcat(Destination, DbgArmRegisterNames[CurrentRegister]);
- FirstRegister = FALSE;
- }
- RegisterList = RegisterList >> 1;
- }
- strcat(Destination, "}");
- return;
- }
- VOID
- DbgpArmPrintMode (
- PSTR Destination,
- ULONG Mode
- )
- /*++
- Routine Description:
- This routine prints the given ARM processor mode.
- Arguments:
- Destination - Supplies a pointer where the mode will be printed.
- Mode - Supplies the mode to print. Only the bottom 5 bits will be examined.
- Return Value:
- None.
- --*/
- {
- PSTR ModeString;
- Mode &= ARM_MODE_MASK;
- ModeString = NULL;
- if (Mode == ARM_MODE_USER) {
- ModeString = ARM_MODE_USER_STRING;
- } else if (Mode == ARM_MODE_FIQ) {
- ModeString = ARM_MODE_FIQ_STRING;
- } else if (Mode == ARM_MODE_IRQ) {
- ModeString = ARM_MODE_IRQ_STRING;
- } else if (Mode == ARM_MODE_SVC) {
- ModeString = ARM_MODE_SVC_STRING;
- } else if (Mode == ARM_MODE_ABORT) {
- ModeString = ARM_MODE_ABORT_STRING;
- } else if (Mode == ARM_MODE_UNDEF) {
- ModeString = ARM_MODE_UNDEF_STRING;
- } else if (Mode == ARM_MODE_SYSTEM) {
- ModeString = ARM_MODE_SYSTEM_STRING;
- }
- if (ModeString != NULL) {
- sprintf(Destination, "#%s", ModeString);
- } else {
- sprintf(Destination, "%02X", Mode);
- }
- return;
- }
- VOID
- DbgpArmPrintBarrierMode (
- PSTR Destination,
- ULONG Mode
- )
- /*++
- Routine Description:
- This routine prints the memory barrier (dsb, dmb, isb) type. For full
- system (sy), nothing is printed.
- Arguments:
- Destination - Supplies a pointer where the mode will be printed.
- Mode - Supplies the mode to print. Only the bottom 4 bits will be examined.
- Return Value:
- None.
- --*/
- {
- PSTR ModeString;
- ModeString = NULL;
- Mode &= ARM_BARRIER_MODE_MASK;
- if (Mode == ARM_BARRIER_MODE_FULL) {
- ModeString = ARM_BARRIER_MODE_FULL_STRING;
- } else if (Mode == ARM_BARRIER_MODE_ST) {
- ModeString = ARM_BARRIER_MODE_ST_STRING;
- } else if (Mode == ARM_BARRIER_MODE_ISH) {
- ModeString = ARM_BARRIER_MODE_ISH_STRING;
- } else if (Mode == ARM_BARRIER_MODE_ISHST) {
- ModeString = ARM_BARRIER_MODE_ISHST_STRING;
- } else if (Mode == ARM_BARRIER_MODE_NSH) {
- ModeString = ARM_BARRIER_MODE_NSH_STRING;
- } else if (Mode == ARM_BARRIER_MODE_NSHST) {
- ModeString = ARM_BARRIER_MODE_NSHST_STRING;
- } else if (Mode == ARM_BARRIER_MODE_OSH) {
- ModeString = ARM_BARRIER_MODE_OSH_STRING;
- } else if (Mode == ARM_BARRIER_MODE_OSHST) {
- ModeString = ARM_BARRIER_MODE_OSHST_STRING;
- }
- if (ModeString != NULL) {
- strcpy(Destination, ModeString);
- } else {
- sprintf(Destination, "#%02X", Mode);
- }
- return;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- VOID
- DbgpArmDecodeUnconditional (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes instructions with the unconditional condition code 0xF.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ARM_DECODE_WITH_TABLE(Context, DbgArmUnconditionalTable);
- return;
- }
- VOID
- DbgpArmDecodeDataProcessingAndMiscellaneous (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the data processing and miscellaneous instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ARM_DECODE_WITH_TABLE(Context, DbgArmDataProcessingAndMiscellaneousTable);
- return;
- }
- VOID
- DbgpArmDecodeMediaInstruction (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an instruction that falls into the Media Extension
- class of instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ARM_DECODE_WITH_TABLE(Context, DbgArmMediaInstructionTable);
- return;
- }
- VOID
- DbgpArmDecodeBranchAndBlockTransfer (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes both branch and block transfer instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ARM_DECODE_WITH_TABLE(Context, DbgArmBranchAndBlockTransferTable);
- return;
- }
- VOID
- DbgpArmDecodeCoprocessorSupervisor (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a coprocessor move or supervisor instruction. This
- routine also decodes floating point instructions and SIMD to floating point
- transfers.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ARM_DECODE_WITH_TABLE(Context, DbgArmCoprocessorSupervisorTable);
- return;
- }
- VOID
- DbgpArmDecodeMemoryHintSimdMisc (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes instructions that are either memory hints, advanced
- SIMD instructions, or miscellaneous instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ARM_DECODE_WITH_TABLE(Context, DbgArmMemoryHintSimdMiscTable);
- return;
- }
- VOID
- DbgpArmDecodeStoreReturnState (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the store return state (SRS) instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR MnemonicSuffix;
- INT Result;
- MnemonicSuffix = DbgpArmGetLoadStoreTypeString(Context->Instruction);
- sprintf(Context->Mnemonic, "%s%s", ARM_SRS_MNEMONIC, MnemonicSuffix);
- DbgpArmPrintMode(Context->Operand2, Context->Instruction);
- if ((Context->Instruction & ARM_WRITE_BACK_BIT) != 0) {
- Result = snprintf(Context->Operand1,
- sizeof(Context->Operand1),
- "%s!, %s",
- DbgArmRegisterNames[ARM_STACK_REGISTER],
- Context->Operand2);
- } else {
- Result = snprintf(Context->Operand1,
- sizeof(Context->Operand1),
- "%s, %s",
- DbgArmRegisterNames[ARM_STACK_REGISTER],
- Context->Operand2);
- }
- if (Result < 0) {
- Context->Operand1[0] = '\0';
- }
- Context->Operand2[0] = '\0';
- return;
- }
- VOID
- DbgpArmDecodeReturnFromException (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the return from exception (RFE) instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR MnemonicSuffix;
- ULONG Rn;
- Rn = (Context->Instruction & ARM_UNCONDITIONAL_RN_MASK) >>
- ARM_UNCONDITIONAL_RN_SHIFT;
- MnemonicSuffix = DbgpArmGetLoadStoreTypeString(Context->Instruction);
- sprintf(Context->Mnemonic, "%s%s", ARM_RFE_MNEMONIC, MnemonicSuffix);
- if ((Context->Instruction & ARM_WRITE_BACK_BIT) != 0) {
- sprintf(Context->Operand1, "%s!", DbgArmRegisterNames[Rn]);
- } else {
- sprintf(Context->Operand1, "%s", DbgArmRegisterNames[Rn]);
- }
- return;
- }
- VOID
- DbgpArmDecodeBranch (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the branch instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Condition;
- ULONG Instruction;
- LONG Offset;
- ULONGLONG OperandAddress;
- Instruction = Context->Instruction;
- Offset = (Instruction & ARM_IMMEDIATE24_MASK) << 2;
- //
- // If the condition is set to unconditional, then this is a BLX
- // instruction. The current instruction set is ARM and the target
- // instruction set is Thumb.
- //
- Condition = Instruction >> ARM_CONDITION_SHIFT;
- if (Condition == ARM_CONDITION_UNCONDITIONAL) {
- BaseMnemonic = ARM_BLX_MNEMONIC;
- if ((Instruction & ARM_BLX_H_BIT) != 0) {
- Offset |= 0x2;
- }
- //
- // Or in the bottom bit as this is a transition to Thumb mode and all
- // addresses should off by 1.
- //
- Offset |= 0x1;
- //
- // Otherwise if the link bit is set, then it is a BL instruction with the
- // current and target instruction set both being ARM.
- //
- } else if ((Instruction & ARM_BRANCH_LINK_BIT) != 0) {
- BaseMnemonic = ARM_BL_MNEMONIC;
- //
- // Otherwise it is just a plain branch instruction.
- //
- } else {
- BaseMnemonic = ARM_B_MNEMONIC;
- }
- //
- // Sign-extend the offset.
- //
- if ((Offset & 0x02000000) != 0) {
- Offset |= 0xFC000000;
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- //
- // The immediate value in the instruction is relative to the PC value of
- // this instruction, which is this instruction's address plus 8.
- //
- OperandAddress = Context->InstructionPointer + 8;
- OperandAddress += (LONGLONG)Offset;
- Context->Result->OperandAddress = OperandAddress;
- Context->Result->AddressIsDestination = TRUE;
- Context->Result->AddressIsValid = TRUE;
- snprintf(Context->Operand1,
- sizeof(Context->Operand1),
- "[0x%08llx]",
- OperandAddress);
- return;
- }
- VOID
- DbgpArmDecodeUndefined (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine catches undefined corners of the instruction space.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- strcpy(Context->Mnemonic, "Undefined");
- return;
- }
- VOID
- DbgpArmDecodeUnpredictable (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine catches unpredictable corners of the instruction space.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- strcpy(Context->Mnemonic, "Unpredictable");
- return;
- }
- VOID
- DbgpArmDecodeNop (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine handles instructions that are treated as no operation.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- strcpy(Context->Mnemonic, "NOP");
- return;
- }
- VOID
- DbgpArmDecodeChangeProcessorState (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the change processor state instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ULONG Instruction;
- Instruction = Context->Instruction;
- if ((Instruction & ARM_CPS_IMOD_DISABLE) != 0) {
- strcpy(Context->Mnemonic, ARM_CPS_MNEMONIC_DISABLE);
- } else {
- strcpy(Context->Mnemonic, ARM_CPS_MNEMONIC_ENABLE);
- }
- Context->Operand1[0] = '\0';
- if ((Instruction & ARM_CPS_FLAG_A) != 0) {
- strcat(Context->Operand1, ARM_CPS_FLAG_A_STRING);
- }
- if ((Instruction & ARM_CPS_FLAG_I) != 0) {
- strcat(Context->Operand1, ARM_CPS_FLAG_I_STRING);
- }
- if ((Instruction & ARM_CPS_FLAG_F) != 0) {
- strcat(Context->Operand1, ARM_CPS_FLAG_F_STRING);
- }
- if ((Instruction & ARM_MODE_MASK) != 0) {
- DbgpArmPrintMode(Context->Operand2, Instruction);
- if ((Instruction &
- (ARM_CPS_FLAG_A | ARM_CPS_FLAG_I | ARM_CPS_FLAG_F)) != 0) {
- strcat(Context->Operand1, ", ");
- }
- strcat(Context->Operand1, Context->Operand2);
- Context->Operand2[0] = '\0';
- }
- return;
- }
- VOID
- DbgpArmDecodeSetEndianness (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the set endianness instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- if ((Context->Instruction & ARM_SETEND_BIG_ENDIAN) != 0) {
- strcpy(Context->Operand1, ARM_SETEND_BE_STRING);
- } else {
- strcpy(Context->Operand1, ARM_SETEND_LE_STRING);
- }
- strcpy(Context->Mnemonic, ARM_SETEND_MNEMONIC);
- return;
- }
- VOID
- DbgpArmDecodePreloadInstruction (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the preload instructions, both the immediate/literal
- versions and the register based versions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Immediate;
- ULONG Instruction;
- PSTR MnemonicSuffix;
- LONG Offset;
- ULONGLONG OperandAddress;
- ULONG RegisterM;
- ULONG RegisterN;
- CHAR ShiftString[35];
- CHAR SignCharacter;
- //
- // Sort out the bits that are common to the immediate and register preload
- // instructions.
- //
- Instruction = Context->Instruction;
- MnemonicSuffix = "";
- if ((Instruction & ARM_PRELOAD_DATA_BIT) != 0) {
- BaseMnemonic = ARM_PRELOAD_DATA_MNEMONIC;
- if ((Instruction & ARM_PRELOAD_DATA_READ_BIT) == 0) {
- MnemonicSuffix = "w";
- }
- } else {
- BaseMnemonic = ARM_PRELOAD_MNEMONIC;
- }
- RegisterN = (Instruction & ARM_PRELOAD_RN_MASK) >> ARM_PRELOAD_RN_SHIFT;
- if ((Instruction & ARM_PRELOAD_ADD_BIT) != 0) {
- SignCharacter = '+';
- } else {
- SignCharacter = '-';
- }
- sprintf(Context->Mnemonic, "%s%s", BaseMnemonic, MnemonicSuffix);
- //
- // If this is a register preload instruction, get the second register and
- // calculate the shift value.
- //
- if ((Instruction & ARM_PRELOAD_REGISTER_BIT) != 0) {
- Immediate = (Instruction & ARM_PRELOAD_IMMEDIATE5_MASK) >>
- ARM_PRELOAD_IMMEDIATE5_SHIFT;
- RegisterM = (Instruction & ARM_PRELOAD_RM_MASK) >> ARM_PRELOAD_RM_SHIFT;
- DbgpArmDecodeImmediateShift(ShiftString,
- sizeof(ShiftString),
- RegisterM,
- (Instruction & ARM_SHIFT_TYPE),
- Immediate);
- sprintf(Context->Operand1,
- "[%s, %c%s]",
- DbgArmRegisterNames[RegisterN],
- SignCharacter,
- ShiftString);
- //
- // Otherwise build out the immediate/literal value.
- //
- } else {
- Offset = (Instruction & ARM_PRELOAD_IMMEDIATE12_MASK) >>
- ARM_PRELOAD_IMMEDIATE12_SHIFT;
- //
- // If the register is the PC, then the immediate value in the
- // instruction is relative to the PC value of this instruction, which
- // is this instruction's address plus 8.
- //
- if (RegisterN == ARM_PC_REGISTER) {
- OperandAddress = Context->InstructionPointer + 8;
- if ((Instruction & ARM_PRELOAD_ADD_BIT) == 0) {
- Offset = -Offset;
- }
- OperandAddress += (LONGLONG)Offset;
- Context->Result->OperandAddress = OperandAddress;
- Context->Result->AddressIsDestination = TRUE;
- Context->Result->AddressIsValid = TRUE;
- snprintf(Context->Operand1,
- sizeof(Context->Operand1),
- "[0x%08llx]",
- OperandAddress);
- } else {
- snprintf(Context->Operand1,
- sizeof(Context->Operand1),
- "[%s, #%c%d]",
- DbgArmRegisterNames[RegisterN],
- SignCharacter,
- Offset);
- }
- }
- return;
- }
- VOID
- DbgpArmDecodeClearExclusive (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the clear exclusive instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- strcpy(Context->Mnemonic, ARM_CLREX_MNEMONIC);
- return;
- }
- VOID
- DbgpArmDecodeDataSynchronizationBarrier (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the data synchronization barrier instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- DbgpArmPrintBarrierMode(Context->Operand1, Context->Instruction);
- strcpy(Context->Mnemonic, ARM_DSB_MNEMONIC);
- return;
- }
- VOID
- DbgpArmDecodeDataMemoryBarrier (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the data memory barrier instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- DbgpArmPrintBarrierMode(Context->Operand1, Context->Instruction);
- strcpy(Context->Mnemonic, ARM_DMB_MNEMONIC);
- return;
- }
- VOID
- DbgpArmDecodeInstructionSynchronizationBarrier (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the instruction synchronization barrier instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- DbgpArmPrintBarrierMode(Context->Operand1, Context->Instruction);
- strcpy(Context->Mnemonic, ARM_ISB_MNEMONIC);
- return;
- }
- VOID
- DbgpArmDecodeParallelAdditionSubtraction (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the parallel addition and subtraction instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Instruction;
- ULONG Op2;
- ULONG ParallelOp;
- ULONG Rd;
- ULONG Rm;
- ULONG Rn;
- ULONG Unsigned;
- Instruction = Context->Instruction;
- Unsigned = 0;
- if ((Instruction & ARM_PARALLEL_ARITHMETIC_UNSIGNED) != 0) {
- Unsigned = 1;
- }
- ParallelOp = (Instruction & ARM_PARALLEL_ARITHMETIC_OP1_MASK) >>
- ARM_PARALLEL_ARITHMETIC_OP1_SHIFT;
- Op2 = (Instruction & ARM_PARALLEL_ARITHMETIC_OP2_MASK) >>
- ARM_PARALLEL_ARITHMETIC_OP2_SHIFT;
- ParallelOp |= ((Op2 - 1) << 2);
- BaseMnemonic = NULL;
- if (ParallelOp < ARM_PARALLEL_ARITHMETIC_OP_MAX) {
- BaseMnemonic = DbgArmParallelArithmeticMnemonics[Unsigned][ParallelOp];
- }
- if (BaseMnemonic == NULL) {
- DbgpArmDecodeUndefined(Context);
- return;
- }
- Rn = (Instruction & ARM_PARALLEL_ARITHMETIC_RN_MASK) >>
- ARM_PARALLEL_ARITHMETIC_RN_SHIFT;
- Rd = (Instruction & ARM_PARALLEL_ARITHMETIC_RD_MASK) >>
- ARM_PARALLEL_ARITHMETIC_RD_SHIFT;
- Rm = (Instruction & ARM_PARALLEL_ARITHMETIC_RM_MASK) >>
- ARM_PARALLEL_ARITHMETIC_RM_SHIFT;
- strcpy(Context->Mnemonic, BaseMnemonic);
- strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
- strcpy(Context->Operand2, DbgArmRegisterNames[Rn]);
- strcpy(Context->Operand3, DbgArmRegisterNames[Rm]);
- return;
- }
- VOID
- DbgpArmDecodePackingInstructions (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the packing, unpacking, saturation, and reversal
- instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ARM_DECODE_WITH_TABLE(Context, DbgArmPackingInstructionTable);
- return;
- }
- VOID
- DbgpArmDecodeExtensionWithRotation (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes extension with rotation instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Instruction;
- ULONG Op1;
- ULONG Rd;
- ULONG Rm;
- PSTR RmString;
- ULONG Rn;
- ULONG Rotation;
- PSTR RotationString;
- BOOL TwoRegisters;
- Instruction = Context->Instruction;
- Rn = (Instruction & ARM_PACKING_RN_MASK) >> ARM_PACKING_RN_SHIFT;
- Rd = (Instruction & ARM_PACKING_RD_MASK) >> ARM_PACKING_RD_SHIFT;
- Rm = (Instruction & ARM_PACKING_RM_MASK) >> ARM_PACKING_RM_SHIFT;
- Op1 = (Instruction & ARM_PACKING_OP1_MASK) >> ARM_PACKING_OP1_SHIFT;
- TwoRegisters = FALSE;
- if (Rn == 0xF) {
- BaseMnemonic = DbgArmExtensionRotationMnemonics[1][Op1];
- RmString = Context->Operand2;
- RotationString = Context->Operand3;
- TwoRegisters = TRUE;
- } else {
- BaseMnemonic = DbgArmExtensionRotationMnemonics[0][Op1];
- RmString = Context->Operand3;
- RotationString = Context->Operand4;
- }
- Rotation = (Instruction & ARM_PACKING_ROTATION_MASK) >>
- ARM_PACKING_ROTATION_SHIFT;
- Rotation <<= 3;
- //
- // If no mnemonic was found for the given op value, then the instruction is
- // undefined.
- //
- if (BaseMnemonic == NULL) {
- DbgpArmDecodeUndefined(Context);
- return;
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
- if (TwoRegisters == FALSE) {
- strcpy(Context->Operand2, DbgArmRegisterNames[Rn]);
- }
- strcpy(RmString, DbgArmRegisterNames[Rm]);
- if (Rotation != 0) {
- sprintf(RotationString, "%s #%d", ARM_ROR_MNEMONIC, Rotation);
- }
- return;
- }
- VOID
- DbgpArmDecodeSelectBytes (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the select byte instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ULONG Instruction;
- ULONG Rd;
- ULONG Rm;
- ULONG Rn;
- Instruction = Context->Instruction;
- Rn = (Instruction & ARM_PACKING_RN_MASK) >> ARM_PACKING_RN_SHIFT;
- Rd = (Instruction & ARM_PACKING_RD_MASK) >> ARM_PACKING_RD_SHIFT;
- Rm = (Instruction & ARM_PACKING_RM_MASK) >> ARM_PACKING_RM_SHIFT;
- strcpy(Context->Mnemonic, ARM_SEL_MNEMONIC);
- strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
- strcpy(Context->Operand2, DbgArmRegisterNames[Rn]);
- strcpy(Context->Operand3, DbgArmRegisterNames[Rm]);
- return;
- }
- VOID
- DbgpArmDecodePackHalfword (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the pack halfword instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Immediate;
- ULONG Instruction;
- ULONG Rd;
- ULONG Rm;
- ULONG Rn;
- PSTR ShiftMnemonic;
- Instruction = Context->Instruction;
- Rn = (Instruction & ARM_PACKING_RN_MASK) >> ARM_PACKING_RN_SHIFT;
- Rd = (Instruction & ARM_PACKING_RD_MASK) >> ARM_PACKING_RD_SHIFT;
- Rm = (Instruction & ARM_PACKING_RM_MASK) >> ARM_PACKING_RM_SHIFT;
- Immediate = (Instruction & ARM_PACKING_IMMEDIATE5_MASK) >>
- ARM_PACKING_IMMEDIATE5_SHIFT;
- if ((Instruction & ARM_PACKING_TB_BIT) != 0) {
- BaseMnemonic = ARM_PKHTB_MNEMONIC;
- ShiftMnemonic = ARM_ASR_MNEMONIC;
- if (Immediate == 0) {
- Immediate = 32;
- }
- } else {
- BaseMnemonic = ARM_PKHBT_MNEMONIC;
- ShiftMnemonic = ARM_LSL_MNEMONIC;
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
- strcpy(Context->Operand2, DbgArmRegisterNames[Rn]);
- strcpy(Context->Operand3, DbgArmRegisterNames[Rm]);
- if (Immediate != 0) {
- sprintf(Context->Operand4, "%s #%d", ShiftMnemonic, Immediate);
- }
- return;
- }
- VOID
- DbgpArmDecodeReverse (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the reverse instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Instruction;
- ULONG Op1;
- ULONG Op2;
- ULONG Rd;
- ULONG ReverseIndex;
- ULONG Rm;
- Instruction = Context->Instruction;
- Rd = (Instruction & ARM_PACKING_RD_MASK) >> ARM_PACKING_RD_SHIFT;
- Rm = (Instruction & ARM_PACKING_RM_MASK) >> ARM_PACKING_RM_SHIFT;
- Op1 = (Instruction & ARM_PACKING_OP1_MASK) >> ARM_PACKING_OP1_SHIFT;
- Op2 = (Instruction & ARM_PACKING_OP2_MASK) >> ARM_PACKING_OP2_SHIFT;
- ReverseIndex = (Op1 & ARM_PACKING_OP1_REV_MASK) >>
- ARM_PACKING_OP1_REV_SHIFT;
- ReverseIndex |= ((Op2 & ARM_PACKING_OP2_REV_MASK) >>
- ARM_PACKING_OP2_REV_SHIFT) << 1;
- BaseMnemonic = DbgArmReverseMnemonics[ReverseIndex];
- strcpy(Context->Mnemonic, BaseMnemonic);
- strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
- strcpy(Context->Operand2, DbgArmRegisterNames[Rm]);
- return;
- }
- VOID
- DbgpArmDecodeSaturate (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the saturate instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ULONG Instruction;
- PSTR MnemonicPrefix;
- PSTR MnemonicSuffix;
- ULONG Rd;
- ULONG Rm;
- ULONG SaturateImmediate;
- ULONG ShiftImmediate;
- PSTR ShiftMnemonic;
- Instruction = Context->Instruction;
- Rd = (Instruction & ARM_PACKING_RD_MASK) >> ARM_PACKING_RD_SHIFT;
- Rm = (Instruction & ARM_PACKING_RM_MASK) >> ARM_PACKING_RM_SHIFT;
- SaturateImmediate = (Instruction & ARM_PACKING_SAT_IMMEDIATE_MASK) >>
- ARM_PACKING_SAT_IMMEDIATE_SHIFT;
- MnemonicPrefix = ARM_USAT_MNEMONIC;
- if ((Instruction & ARM_PACKING_SAT_UNSIGNED) == 0) {
- SaturateImmediate += 1;
- MnemonicPrefix = ARM_SSAT_MNEMONIC;
- }
- //
- // If this is a two 16-bit saturate, then there is no shift at the end.
- //
- ShiftImmediate = 0;
- MnemonicSuffix = ARM_SAT16_MNEMONIC;
- if ((Instruction & ARM_PACKING_SAT16_BIT) == 0) {
- MnemonicSuffix = "";
- ShiftImmediate = (Instruction & ARM_PACKING_IMMEDIATE5_MASK) >>
- ARM_PACKING_IMMEDIATE5_SHIFT;
- ShiftMnemonic = ARM_LSL_MNEMONIC;
- if ((Instruction & ARM_PACKING_SHIFT_BIT) != 0) {
- ShiftMnemonic = ARM_ASR_MNEMONIC;
- if (ShiftImmediate == 0) {
- ShiftImmediate = 32;
- }
- }
- }
- sprintf(Context->Mnemonic,
- "%s%s%s",
- MnemonicPrefix,
- ARM_SAT_MNEMONIC,
- MnemonicSuffix);
- strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
- sprintf(Context->Operand2, "#%d", SaturateImmediate);
- strcpy(Context->Operand3, DbgArmRegisterNames[Rm]);
- if (ShiftImmediate != 0) {
- sprintf(Context->Operand4, "%s #%d", ShiftMnemonic, ShiftImmediate);
- }
- return;
- }
- VOID
- DbgpArmDecodeSumofAbsoluteDifferences (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the sum of absolute differences instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Instruction;
- ULONG RegisterA;
- ULONG RegisterD;
- ULONG RegisterM;
- ULONG RegisterN;
- BOOL ThreeOperands;
- Instruction = Context->Instruction;
- RegisterA = (Instruction & ARM_USAD_RA_MASK) >> ARM_USAD_RA_SHIFT;
- RegisterD = (Instruction & ARM_USAD_RD_MASK) >> ARM_USAD_RD_SHIFT;
- RegisterM = (Instruction & ARM_USAD_RM_MASK) >> ARM_USAD_RM_SHIFT;
- RegisterN = (Instruction & ARM_USAD_RN_MASK) >> ARM_USAD_RN_SHIFT;
- if (RegisterD == 0xF) {
- BaseMnemonic = ARM_USAD_MNEMONIC;
- ThreeOperands = TRUE;
- } else {
- BaseMnemonic = ARM_USADA_MNEMONIC;
- ThreeOperands = FALSE;
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- strcpy(Context->Operand1, DbgArmRegisterNames[RegisterD]);
- strcpy(Context->Operand2, DbgArmRegisterNames[RegisterN]);
- strcpy(Context->Operand3, DbgArmRegisterNames[RegisterM]);
- if (ThreeOperands == FALSE) {
- strcpy(Context->Operand1, DbgArmRegisterNames[RegisterA]);
- }
- return;
- }
- VOID
- DbgpArmDecodeBitFieldInstructions (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the bit field instructions.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Instruction;
- ULONG Lsb;
- PSTR LsbString;
- BOOL OneRegister;
- ULONG RegisterD;
- ULONG RegisterN;
- ULONG Width;
- Instruction = Context->Instruction;
- RegisterD = (Instruction & ARM_BIT_FIELD_RD_MASK) >> ARM_BIT_FIELD_RD_SHIFT;
- RegisterN = (Instruction & ARM_BIT_FIELD_RN_MASK) >> ARM_BIT_FIELD_RN_SHIFT;
- Lsb = (Instruction & ARM_BIT_FIELD_LSB_MASK) >> ARM_BIT_FIELD_LSB_SHIFT;
- Width = (Instruction & ARM_BIT_FIELD_WIDTH_MINUS_1_MASK) >>
- ARM_BIT_FIELD_WIDTH_MINUS_1_SHIFT;
- Width += 1;
- OneRegister = FALSE;
- if ((Instruction & ARM_BIT_FIELD_EXTRACT_BIT) != 0) {
- if ((Instruction & ARM_BIT_FIELD_UNSIGNED_BIT) != 0) {
- BaseMnemonic = ARM_UBFX_MNEMONIC;
- } else {
- BaseMnemonic = ARM_SBFX_MNEMONIC;
- }
- } else {
- if (RegisterN == 0xF) {
- BaseMnemonic = ARM_BFC_MNEMONIC;
- OneRegister = TRUE;
- } else {
- BaseMnemonic = ARM_BFI_MNEMONIC;
- }
- Width -= Lsb;
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- strcpy(Context->Operand1, DbgArmRegisterNames[RegisterD]);
- if (OneRegister == FALSE) {
- strcpy(Context->Operand2, DbgArmRegisterNames[RegisterN]);
- LsbString = Context->Operand3;
- } else {
- LsbString = Context->Operand2;
- }
- sprintf(LsbString, "#%d, #%d", Lsb, Width);
- return;
- }
- VOID
- DbgpArmDecodePermanentlyUndefined (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes the permanently undefined instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ULONG Value;
- strcpy(Context->Mnemonic, ARM_UNDEFINED_INSTRUCTION_MNEMONIC);
- Value = ARM_SERVICE_BUILD_IMMEDIATE12_4(Context->Instruction);
- sprintf(Context->Operand1, "#%d ; 0x%x", Value, Value);
- return;
- }
- VOID
- DbgpArmDecodeLoadStore (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a load/store to a word or single byte.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- UCHAR BaseRegister;
- UCHAR DestinationRegister;
- ULONG Instruction;
- PSTR MnemonicSuffix;
- ULONG Offset;
- UCHAR OffsetRegister;
- CHAR ShiftString[15];
- UCHAR ShiftValue;
- UCHAR Sign;
- UCHAR WriteBack;
- BaseMnemonic = "";
- MnemonicSuffix = "";
- Instruction = Context->Instruction;
- //
- // Get the destination register.
- //
- DestinationRegister = (Instruction & ARM_DESTINATION_REGISTER_MASK) >>
- ARM_DESTINATION_REGISTER_SHIFT;
- //
- // Determine the mnemonic.
- //
- if ((Instruction & ARM_LOAD_BIT) != 0) {
- BaseMnemonic = ARM_LOAD_MNEMONIC;
- } else {
- BaseMnemonic = ARM_STORE_MNEMONIC;
- }
- //
- // Determine the suffix. The translate bit only applies if P == 0.
- //
- if ((Instruction & ARM_LOAD_STORE_BYTE_BIT) != 0) {
- if (((Instruction & ARM_PREINDEX_BIT) == 0) &&
- ((Instruction & ARM_LOAD_STORE_TRANSLATE_BIT) != 0)) {
- MnemonicSuffix = ARM_TRANSLATE_BYTE_SUFFIX;
- } else {
- MnemonicSuffix = ARM_BYTE_TRANSFER_SUFFIX;
- }
- } else if (((Instruction & ARM_PREINDEX_BIT) == 0) &&
- ((Instruction & ARM_LOAD_STORE_TRANSLATE_BIT) != 0)) {
- MnemonicSuffix = ARM_TRANSLATE_SUFFIX;
- }
- sprintf(Context->Mnemonic, "%s%s", BaseMnemonic, MnemonicSuffix);
- //
- // For immediate and register offsets, determine the sign of the offset.
- //
- if ((Instruction & ARM_ADD_SUBTRACT_BIT) != 0) {
- Sign = '+';
- } else {
- Sign = '-';
- }
- //
- // For pre-index and offset modes, determine whether a writeback is
- // performed.
- //
- WriteBack = 0;
- if ((Instruction & ARM_WRITE_BACK_BIT) != 0) {
- WriteBack = '!';
- }
- BaseRegister = (Instruction & ARM_LOAD_STORE_BASE_MASK) >>
- ARM_LOAD_STORE_BASE_SHIFT;
- //
- // Print the operand in the correct addressing form. There are 9 unique
- // forms. Start with the immediate bit, which when 0 means the immediate
- // form is used.
- //
- if ((Instruction & ARM_IMMEDIATE_BIT) == 0) {
- Offset = Instruction & 0x00000FFF;
- //
- // Post-Indexed addressing.
- //
- if ((Instruction & ARM_PREINDEX_BIT) == 0) {
- if (Offset == 0) {
- sprintf(Context->Operand2,
- "[%s]",
- DbgArmRegisterNames[BaseRegister]);
- } else {
- sprintf(Context->Operand2,
- "[%s], #%c%d",
- DbgArmRegisterNames[BaseRegister],
- Sign,
- Offset);
- }
- //
- // Pre-indexed or offset addressing.
- //
- } else {
- if (Offset == 0) {
- sprintf(Context->Operand2,
- "[%s]%c",
- DbgArmRegisterNames[BaseRegister],
- WriteBack);
- } else {
- sprintf(Context->Operand2,
- "[%s, #%c%d]%c",
- DbgArmRegisterNames[BaseRegister],
- Sign,
- Offset,
- WriteBack);
- }
- }
- //
- // Register offset/index or scaled register offset/index.
- //
- } else {
- //
- // Decode the shifted register string.
- //
- OffsetRegister = Instruction & ARM_OFFSET_REGISTER;
- ShiftValue = (Instruction & ARM_LOAD_STORE_SHIFT_VALUE_MASK) >>
- ARM_LOAD_STORE_SHIFT_VALUE_SHIFT;
- DbgpArmDecodeImmediateShift(ShiftString,
- sizeof(ShiftString),
- OffsetRegister,
- (Instruction & ARM_SHIFT_TYPE),
- ShiftValue);
- //
- // Check out the pre-index bit. If it's zero, the addressing mode is
- // post-indexed.
- //
- if ((Instruction & ARM_PREINDEX_BIT) == 0) {
- sprintf(Context->Operand2,
- "[%s], %c%s",
- DbgArmRegisterNames[BaseRegister],
- Sign,
- ShiftString);
- //
- // Pre-indexed or offset addressing.
- //
- } else {
- sprintf(Context->Operand2,
- "[%s, %c%s]%c",
- DbgArmRegisterNames[BaseRegister],
- Sign,
- ShiftString,
- WriteBack);
- }
- }
- //
- // Write the first operand.
- //
- strcpy(Context->Operand1, DbgArmRegisterNames[DestinationRegister]);
- return;
- }
- VOID
- DbgpArmDecodeExtraLoadStore (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an "extra load/store" in both the register and
- immediate forms.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- UCHAR BaseRegister;
- UCHAR DestinationRegister;
- ULONG Instruction;
- PSTR MnemonicSuffix;
- UCHAR Offset;
- UCHAR OffsetRegister;
- UCHAR Sign;
- UCHAR WriteBack;
- BaseMnemonic = "ERR";
- MnemonicSuffix = "";
- Instruction = Context->Instruction;
- //
- // Determine whether or not this is a load or store, and what data size it
- // is.
- //
- switch (Instruction & ARM_HALF_WORD_TRANSFER_MASK) {
- case ARM_STORE_HALF_WORD:
- BaseMnemonic = ARM_STORE_MNEMONIC;
- MnemonicSuffix = ARM_HALF_WORD_SUFFIX;
- break;
- case ARM_LOAD_DOUBLE_WORD:
- BaseMnemonic = ARM_LOAD_MNEMONIC;
- MnemonicSuffix = ARM_DOUBLE_WORD_SUFFIX;
- break;
- case ARM_STORE_DOUBLE_WORD:
- BaseMnemonic = ARM_STORE_MNEMONIC;
- MnemonicSuffix = ARM_DOUBLE_WORD_SUFFIX;
- break;
- case ARM_LOAD_UNSIGNED_HALF_WORD:
- BaseMnemonic = ARM_LOAD_MNEMONIC;
- MnemonicSuffix = ARM_HALF_WORD_SUFFIX;
- break;
- case ARM_LOAD_SIGNED_BYTE:
- BaseMnemonic = ARM_LOAD_MNEMONIC;
- MnemonicSuffix = ARM_SIGNED_BYTE_SUFFIX;
- break;
- case ARM_LOAD_SIGNED_HALF_WORD:
- BaseMnemonic = ARM_LOAD_MNEMONIC;
- MnemonicSuffix = ARM_SIGNED_HALF_WORD_SUFFIX;
- break;
- //
- // Invalid configuration.
- //
- default:
- return;
- }
- snprintf(Context->Mnemonic,
- ARM_OPERAND_LENGTH,
- "%s%s",
- BaseMnemonic,
- MnemonicSuffix);
- //
- // Determine whether to add or subtract the offset.
- //
- if ((Instruction & ARM_ADD_SUBTRACT_BIT) != 0) {
- Sign = '+';
- } else {
- Sign = '-';
- }
- //
- // For pre-indexed addressing modes, determine whether or not the calculated
- // address is written back. (If it's not, that's called offset addressing).
- //
- WriteBack = 0;
- if ((Instruction & ARM_WRITE_BACK_BIT) != 0) {
- WriteBack = '!';
- }
- //
- // Print the destination register in the first operand.
- //
- DestinationRegister = (Instruction & ARM_DESTINATION_REGISTER_MASK) >>
- ARM_DESTINATION_REGISTER_SHIFT;
- sprintf(Context->Operand1, "%s", DbgArmRegisterNames[DestinationRegister]);
- BaseRegister = (Instruction & 0x000F0000) >> 16;
- //
- // Handle the register form.
- //
- if ((Instruction & ARM_HALF_WORD_REGISTER_MASK) ==
- ARM_HALF_WORD_REGISTER_VALUE) {
- OffsetRegister = Instruction & 0x0000000F;
- //
- // If P is 0, then it's post-indexed addressing. W had better be zero
- // in this case. Post-indexed addressing means the base register is
- // used as the address, then the offset register is added to the base
- // and written back to the base. It takes the form of [Rn], +/-Rm.
- //
- if ((Instruction & ARM_PREINDEX_BIT) == 0) {
- if ((Instruction & ARM_WRITE_BACK_BIT) != 0) {
- return;
- }
- sprintf(Context->Operand2,
- "[%s], %c%s",
- DbgArmRegisterNames[BaseRegister],
- Sign,
- DbgArmRegisterNames[OffsetRegister]);
- //
- // P is 1, which means the addressing form is either pre-indexed or
- // offset based. Pre-indexed means the offset register is added to the
- // base to form the address, and is then written back. Offset addressing
- // is the same but no writeback is performed.
- //
- } else {
- sprintf(Context->Operand2,
- "[%s, %c%s]%c",
- DbgArmRegisterNames[BaseRegister],
- Sign,
- DbgArmRegisterNames[OffsetRegister],
- WriteBack);
- }
- //
- // Handle the immediate form.
- //
- } else {
- Offset = ((Instruction & 0x00000F00) >> 4) | (Instruction & 0x0000000F);
- //
- // Like in the register form, P == 0 indicates post-indexed addressing.
- // W must be zero (just don't print if it it's not).
- //
- if ((Instruction & ARM_PREINDEX_BIT) == 0) {
- sprintf(Context->Operand2,
- "[%s], #%c%d",
- DbgArmRegisterNames[BaseRegister],
- Sign,
- Offset);
- //
- // Like the register case P == 1 means the addressing form is either
- // pre-indexed or offset based, depending on the U bit. If it is
- // offset based (i.e. no write-back) and the offset is zero, don't
- // print the offset.
- //
- } else if ((WriteBack == 0) && (Offset == 0)) {
- sprintf(Context->Operand2,
- "[%s]",
- DbgArmRegisterNames[BaseRegister]);
- } else {
- sprintf(Context->Operand2,
- "[%s, #%c%d]%c",
- DbgArmRegisterNames[BaseRegister],
- Sign,
- Offset,
- WriteBack);
- }
- }
- return;
- }
- VOID
- DbgpArmDecodeLoadStoreMultiple (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a block load or store of multiple registers.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Instruction;
- PSTR MnemonicSuffix;
- ULONG Operation;
- BOOL PushPop;
- UCHAR Register;
- ULONG RegisterList;
- ULONG RegisterListCount;
- PSTR RegisterListString;
- Instruction = Context->Instruction;
- PushPop = FALSE;
- Operation = Instruction & ARM_LOAD_STORE_OP_MASK;
- Register = (Instruction & ARM_LOAD_STORE_REGISTER_MASK) >>
- ARM_LOAD_STORE_REGISTER_SHIFT;
- RegisterList = Instruction & ARM_REGISTER_LIST_MASK;
- RegisterListCount = RtlCountSetBits32(RegisterList);
- //
- // If the instruction is targeting the stack register, then it may be a
- // push or a pop.
- //
- if ((Register == ARM_STACK_REGISTER) &&
- (RegisterListCount > 1) &&
- ((Operation == ARM_LOAD_STORE_OP_POP) ||
- (Operation == ARM_LOAD_STORE_OP_PUSH))) {
- if ((Instruction & ARM_LOAD_BIT) != 0) {
- BaseMnemonic = ARM_LOAD_POP_MNEMONIC;
- } else {
- BaseMnemonic = ARM_STORE_PUSH_MNEMONIC;
- }
- MnemonicSuffix = "";
- PushPop = TRUE;
- //
- // Otherwise determine if it is a load or a store and get the appropriate
- // suffix.
- //
- } else {
- if ((Instruction & ARM_LOAD_BIT) != 0) {
- BaseMnemonic = ARM_LOAD_MULTIPLE_MNEMONIC;
- } else {
- BaseMnemonic = ARM_STORE_MULTIPLE_MNEMONIC;
- }
- MnemonicSuffix = DbgpArmGetLoadStoreTypeString(Instruction);
- }
- snprintf(Context->Mnemonic,
- ARM_OPERAND_LENGTH,
- "%s%s",
- BaseMnemonic,
- MnemonicSuffix);
- //
- // Write the register (the first operand). Add the ! if the operation does
- // a write back. Push/pop operations are always write back.
- //
- if (PushPop == FALSE) {
- if ((Instruction & ARM_WRITE_BACK_BIT) != 0) {
- sprintf(Context->Operand1, "%s!", DbgArmRegisterNames[Register]);
- } else {
- sprintf(Context->Operand1, "%s", DbgArmRegisterNames[Register]);
- }
- RegisterListString = Context->Operand2;
- } else {
- RegisterListString = Context->Operand1;
- }
- //
- // Get the list of registers to be loaded or stored.
- //
- DbgpArmDecodeRegisterList(RegisterListString,
- ARM_OPERAND_LENGTH,
- RegisterList);
- //
- // Indicate whether or not the saved PSR (SPSR) should be used instead of
- // the current PSR (CPSR). This is typically only used for returning from
- // exceptions.
- //
- if ((Instruction & ARM_USE_SAVED_PSR_BIT) != 0) {
- strcat(RegisterListString, "^");
- }
- return;
- }
- VOID
- DbgpArmDecodeDataProcessing (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a standard data processing instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- UCHAR DestinationRegister;
- UCHAR ImmediateShift;
- ULONG ImmediateValue;
- ULONG Instruction;
- PSTR MnemonicSuffix;
- UCHAR Opcode;
- UCHAR Operand2Register;
- UCHAR OperandRegister;
- UCHAR ShiftRegister;
- CHAR ShiftString[35];
- PSTR ShiftType;
- Instruction = Context->Instruction;
- MnemonicSuffix = "";
- ShiftString[0] = '\0';
- //
- // Get the opcode.
- //
- Opcode = (Instruction & ARM_DATA_PROCESSING_OP_MASK) >>
- ARM_DATA_PROCESSING_OP_SHIFT;
- //
- // Ignore the low bit.
- //
- Opcode >>= 1;
- BaseMnemonic = DbgArmDataProcessingMnemonics[Opcode];
- //
- // Determine whether to add the S bit. Compare instructions don't need the
- // S because it's assumed (it's the whole point of a compare to set the
- // flags).
- //
- if (((Instruction & ARM_SET_FLAGS_BIT) != 0) &&
- ((Opcode < ARM_DATA_PROCESSING_COMPARE_INSTRUCTION_MIN) ||
- (Opcode > ARM_DATA_PROCESSING_COMPARE_INSTRUCTION_MAX))) {
- MnemonicSuffix = ARM_SET_FLAGS_MNEMONIC;
- }
- //
- // Build the shift operand string.
- //
- if ((Context->Instruction & ARM_IMMEDIATE_BIT) != 0) {
- //
- // The immediate form takes an 8-bit integer and shifts it by any even
- // number in the shift_imm bits.
- //
- ImmediateValue = Instruction & ARM_DATA_PROCESSING_IMMEDIATE8_MASK;
- ImmediateShift = ((Instruction &
- ARM_DATA_PROCESSING_IMMEDIATE_ROTATE_MASK) >>
- ARM_DATA_PROCESSING_IMMEDIATE_ROTATE_SHIFT) * 2;
- //
- // Rotate the value right by the specified number of bits.
- //
- while (ImmediateShift > 0) {
- ImmediateShift -= 1;
- if ((ImmediateValue & 0x1) != 0) {
- ImmediateValue = (ImmediateValue >> 1) | 0x80000000;
- } else {
- ImmediateValue = ImmediateValue >> 1;
- }
- }
- sprintf(ShiftString, "#%d ; 0x%x", ImmediateValue, ImmediateValue);
- } else {
- Operand2Register = Instruction &
- ARM_DATA_PROCESSING_OPERAND2_REGISTER_MASK;
- //
- // The register form can be shifted, by either an immediate or another
- // register. Handle the register shift case first.
- //
- if ((Instruction &
- ARM_DATA_PROCESSING_REGISTER_REGISTER_SHIFT_BIT) != 0) {
- ShiftRegister = (Instruction &
- ARM_DATA_PROCESSING_SHIFT_REGISTER_MASK) >>
- ARM_DATA_PROCESSING_SHIFT_REGISTER_SHIFT;
- ShiftType = "ERR";
- switch (Instruction & ARM_SHIFT_TYPE) {
- case ARM_SHIFT_LSL:
- ShiftType = ARM_LSL_MNEMONIC;
- break;
- case ARM_SHIFT_LSR:
- ShiftType = ARM_LSR_MNEMONIC;
- break;
- case ARM_SHIFT_ASR:
- ShiftType = ARM_ASR_MNEMONIC;
- break;
- case ARM_SHIFT_ROR:
- ShiftType = ARM_ROR_MNEMONIC;
- break;
- //
- // This case should never hit since all 4 bit combinations were
- // handled.
- //
- default:
- break;
- }
- //
- // If this is the move instruction, then the canonical form
- // actually uses the shift mnemonic for the instruction mnemonic.
- //
- if (Opcode == ARM_DATA_PROCESSING_MOVE_OPCODE) {
- BaseMnemonic = ShiftType;
- sprintf(ShiftString,
- "%s, %s",
- DbgArmRegisterNames[Operand2Register],
- DbgArmRegisterNames[ShiftRegister]);
- } else {
- sprintf(ShiftString,
- "%s, %s %s",
- DbgArmRegisterNames[Operand2Register],
- ShiftType,
- DbgArmRegisterNames[ShiftRegister]);
- }
- //
- // Shift by an immediate value.
- //
- } else {
- ImmediateValue = (Instruction &
- ARM_DATA_PROCESSING_SHIFT_IMMEDIATE_MASK) >>
- ARM_DATA_PROCESSING_SHIFT_IMMEDIATE_SHIFT;
- //
- // If this is a move instruction, then it may have a canonical
- // form.
- //
- if (Opcode == ARM_DATA_PROCESSING_MOVE_OPCODE) {
- ShiftType = NULL;
- switch (Instruction & ARM_SHIFT_TYPE) {
- case ARM_SHIFT_LSL:
- if (ImmediateValue != 0) {
- ShiftType = ARM_LSL_MNEMONIC;
- }
- break;
- case ARM_SHIFT_LSR:
- if (ImmediateValue == 0) {
- ImmediateValue = 32;
- }
- ShiftType = ARM_LSR_MNEMONIC;
- break;
- case ARM_SHIFT_ASR:
- if (ImmediateValue == 0) {
- ImmediateValue = 32;
- }
- ShiftType = ARM_ASR_MNEMONIC;
- break;
- case ARM_SHIFT_ROR:
- if (ImmediateValue == 0) {
- ShiftType = ARM_RRX_MNEMONIC;
- } else {
- ShiftType = ARM_ROR_MNEMONIC;
- }
- break;
- //
- // This case should never hit since all 4 bit combinations were
- // handled.
- //
- default:
- break;
- }
- //
- // If a shift type was set, then use the canonical form and
- // override the base mnemonic.
- //
- if (ShiftType != NULL) {
- BaseMnemonic = ShiftType;
- }
- //
- // A MOV with no shift and RRX do no print an immediate value.
- // There are the only cases where the immediate value is 0.
- //
- if (ImmediateValue == 0) {
- sprintf(ShiftString,
- "%s",
- DbgArmRegisterNames[Operand2Register]);
- } else {
- sprintf(ShiftString,
- "%s, #%d",
- DbgArmRegisterNames[Operand2Register],
- ImmediateValue);
- }
- } else {
- DbgpArmDecodeImmediateShift(ShiftString,
- sizeof(ShiftString),
- Operand2Register,
- (Instruction & ARM_SHIFT_TYPE),
- ImmediateValue);
- }
- }
- }
- //
- // Print out the mnemonic, it may have been modified while computing the
- // shift string.
- //
- snprintf(Context->Mnemonic,
- ARM_OPERAND_LENGTH,
- "%s%s",
- BaseMnemonic,
- MnemonicSuffix);
- DestinationRegister = (Instruction & ARM_DESTINATION_REGISTER_MASK) >>
- ARM_DESTINATION_REGISTER_SHIFT;
- OperandRegister = (Instruction &
- ARM_DATA_PROCESSING_OPERAND_REGISTER_MASK) >>
- ARM_DATA_PROCESSING_OPERAND_REGISTER_SHIFT;
- //
- // Print the operands depending on the opcode. Compare instructions take
- // the form Rn, <shifter_operand>
- //
- if ((Opcode >= ARM_DATA_PROCESSING_COMPARE_INSTRUCTION_MIN) &&
- (Opcode <= ARM_DATA_PROCESSING_COMPARE_INSTRUCTION_MAX)) {
- strcpy(Context->Operand1, DbgArmRegisterNames[OperandRegister]);
- strcpy(Context->Operand2, ShiftString);
- //
- // Move instructions take the form Rd, <shift_operand>.
- //
- } else if ((Opcode == ARM_DATA_PROCESSING_MOVE_OPCODE) ||
- (Opcode == ARM_DATA_PROCESSING_MOVE_NOT_OPCODE)) {
- strcpy(Context->Operand1, DbgArmRegisterNames[DestinationRegister]);
- strcpy(Context->Operand2, ShiftString);
- //
- // All normal data processing instructions take the form Rd, Rn,
- // <shift_operand>.
- //
- } else {
- strcpy(Context->Operand1, DbgArmRegisterNames[DestinationRegister]);
- strcpy(Context->Operand2, DbgArmRegisterNames[OperandRegister]);
- strcpy(Context->Operand3, ShiftString);
- }
- return;
- }
- VOID
- DbgpArmDecodeLoadImmediate (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a 16-bit immediate load instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- UCHAR DestinationRegister;
- ULONG ImmediateValue;
- ULONG Instruction;
- Instruction = Context->Instruction;
- //
- // Get the opcode.
- //
- switch (Instruction & ARM_IMMEDIATE_LOAD_OP_MASK) {
- case ARM_IMMEDIATE_LOAD_OP_MOVW:
- BaseMnemonic = ARM_MOVW_MNEMONIC;
- break;
- case ARM_IMMEDIATE_LOAD_OP_MOVT:
- BaseMnemonic = ARM_MOVT_MNEMONIC;
- break;
- //
- // Invalid configuration.
- //
- default:
- return;
- }
- snprintf(Context->Mnemonic,
- ARM_OPERAND_LENGTH,
- "%s",
- BaseMnemonic);
- //
- // Build the immediate value string.
- //
- ImmediateValue = (Instruction & ARM_IMMEDIATE_LOAD_IMMEDIATE4_MASK) >>
- ARM_IMMEDIATE_LOAD_IMMEDIATE4_SHIFT;
- ImmediateValue <<= 12;
- ImmediateValue |= ((Instruction & ARM_IMMEDIATE_LOAD_IMMEDIATE12_MASK) >>
- ARM_IMMEDIATE_LOAD_IMMEDIATE12_SHIFT);
- //
- // Determine the destination register.
- //
- DestinationRegister = (Instruction & ARM_DESTINATION_REGISTER_MASK) >>
- ARM_DESTINATION_REGISTER_SHIFT;
- //
- // The 16 immediate load instructions take the form Rn, <immediate_operand>
- //
- strcpy(Context->Operand1, DbgArmRegisterNames[DestinationRegister]);
- sprintf(Context->Operand2, "#%d ; 0x%x", ImmediateValue, ImmediateValue);
- return;
- }
- VOID
- DbgpArmDecodeMiscellaneous (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a miscellaneous instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ULONG Instruction;
- PSTR Mnemonic;
- ULONG Op;
- ULONG Op2;
- ULONG R0;
- ULONG Rd;
- LONG Value;
- Mnemonic = "ERR";
- Instruction = Context->Instruction;
- Op2 = (Instruction & ARM_MISCELLANEOUS1_OP2_MASK) >>
- ARM_MISCELLANEOUS1_OP2_SHIFT;
- Op = (Instruction & ARM_MISCELLANEOUS1_OP_MASK) >>
- ARM_MISCELLANEOUS1_OP_SHIFT;
- R0 = Instruction & ARM_MOVE_STATUS_R0_MASK;
- //
- // Handle an MSR or MRS instruction.
- //
- if (Op2 == ARM_MISCELLANEOUS1_OP2_STATUS) {
- Rd = (Instruction & ARM_MOVE_STATUS_RD_MASK) >>
- ARM_MOVE_STATUS_RD_SHIFT;
- //
- // Handle an MSR.
- //
- if ((Op & ARM_MISCELLANEOUS1_OP_MSR) != 0) {
- Mnemonic = ARM_MSR_MNEMONIC;
- strcpy(Context->Operand2, DbgArmRegisterNames[R0]);
- //
- // Handle banked MSR vs non-banked.
- //
- if ((Instruction & ARM_MOVE_STATUS_BANKED) != 0) {
- strcpy(Context->Operand1,
- DbgpArmGetBankedRegisterString(Instruction));
- } else {
- DbgpArmPrintStatusRegister(Context->Operand1, Instruction);
- }
- //
- // This is an MRS instruction.
- //
- } else {
- Mnemonic = ARM_MRS_MNEMONIC;
- strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
- if ((Instruction & ARM_MOVE_STATUS_BANKED) != 0) {
- strcpy(Context->Operand2,
- DbgpArmGetBankedRegisterString(Instruction));
- } else {
- DbgpArmPrintStatusRegister(Context->Operand2, Instruction);
- }
- }
- //
- // Handle either a BX or CLZ.
- //
- } else if (Op2 == ARM_MISCELLANEOUS1_OP2_BX_CLZ) {
- if (Op == ARM_MISCELLANEOUS1_OP_BX) {
- Mnemonic = ARM_BX_MNEMONIC;
- } else if (Op == ARM_MISCELLANEOUS1_OP_CLZ) {
- Mnemonic = ARM_CLZ_MNEMONIC;
- }
- strcpy(Context->Operand1, DbgArmRegisterNames[R0]);
- //
- // Handle a BXJ (register).
- //
- } else if (Op2 == ARM_MISCELLANEOUS1_OP2_BXJ) {
- Mnemonic = ARM_BXJ_MNEMONIC;
- strcpy(Context->Operand1, DbgArmRegisterNames[R0]);
- //
- // Handle a BLX (register).
- //
- } else if (Op2 == ARM_MISCELLANEOUS1_OP2_BLX) {
- Mnemonic = ARM_BLX_MNEMONIC;
- strcpy(Context->Operand1, DbgArmRegisterNames[R0]);
- //
- // Handle (or don't) saturating addition or subtraction.
- //
- } else if (Op2 == ARM_MISCELLANEOUS1_OP2_SATURATING_ADDITION) {
- //
- // Handle a simple ERET.
- //
- } else if (Op2 == ARM_MISCELLANEOUS1_OP2_ERET) {
- Mnemonic = ARM_ERET_MNEMONIC;
- //
- // Handle a service call: BKPT, HVC, or SMC.
- //
- } else if (Op2 == ARM_MISCELLANEOUS1_OP2_SERVICE) {
- Value = ARM_SERVICE_BUILD_IMMEDIATE12_4(Instruction);
- if ((Value & 0x00008000) != 0) {
- Value |= 0xFFFF0000;
- }
- if (Op == ARM_MISCELLANEOUS1_OP_BKPT) {
- Mnemonic = ARM_BKPT_MNEMONIC;
- sprintf(Context->Operand1, "#%d", Value);
- } else if (Op == ARM_MISCELLANEOUS1_OP_HVC) {
- Mnemonic = ARM_HVC_MNEMONIC;
- sprintf(Context->Operand1, "#%d", Value);
- } else if (Op == ARM_MISCELLANEOUS1_OP_SMC) {
- Mnemonic = ARM_SMC_MNEMONIC;
- sprintf(Context->Operand1, "#%d", Value & 0xF);
- }
- }
- strcpy(Context->Mnemonic, Mnemonic);
- return;
- }
- VOID
- DbgpArmDecodeMsrImmediateAndHints (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an MSR immediate instruction or memory hints.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- LONG Immediate;
- ULONG Instruction;
- PSTR Mnemonic;
- ULONG Op1;
- ULONG Op2;
- Mnemonic = "";
- Instruction = Context->Instruction;
- Op1 = (Instruction & ARM_HINTS_OP1_MASK) >> ARM_HINTS_OP1_SHIFT;
- Op2 = Instruction & ARM_HINTS_OP2_MASK;
- if (Op1 == ARM_HINTS_OP1_HINTS) {
- if (Op2 == ARM_HINTS_OP2_NOP) {
- Mnemonic = ARM_NOP_MNEMONIC;
- } else if (Op2 == ARM_HINTS_OP2_YIELD) {
- Mnemonic = ARM_YIELD_MNEMONIC;
- } else if (Op2 == ARM_HINTS_OP2_WFE) {
- Mnemonic = ARM_WFE_MNEMONIC;
- } else if (Op2 == ARM_HINTS_OP2_WFI) {
- Mnemonic = ARM_WFI_MNEMONIC;
- } else if (Op2 == ARM_HINTS_OP2_SEV) {
- Mnemonic = ARM_SEV_MNEMONIC;
- } else if ((Op2 & ARM_HINTS_OP2_DBG_MASK) == ARM_HINTS_OP2_DBG_VALUE) {
- Mnemonic = ARM_DBG_MNEMONIC;
- sprintf(Context->Operand1,
- "#%d",
- Op2 & ARM_HINTS_OP2_DBG_OPTION_MASK);
- }
- //
- // If not hints, then this is an MSR (immediate) instruction.
- //
- } else {
- Mnemonic = ARM_MSR_MNEMONIC;
- DbgpArmPrintStatusRegister(Context->Operand1, Instruction);
- Immediate = Instruction & ARM_MSR_IMMEDIATE12_MASK;
- if ((Immediate & 0x00001000) != 0) {
- Immediate |= 0xFFFFF000;
- }
- sprintf(Context->Operand2, "#%d ; 0x%x", Immediate, Immediate);
- }
- strcpy(Context->Mnemonic, Mnemonic);
- return;
- }
- VOID
- DbgpArmDecodeMultiply (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a multiply or long multiply instruction. This function
- assumes that the instruction is in fact a multiply instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Instruction;
- BOOL LongMultiply;
- PSTR MnemonicSuffix;
- PSTR MultiplyHalves;
- PSTR PreConditionMnemonicSuffix;
- UCHAR Rd;
- UCHAR RdHigh;
- UCHAR RdLow;
- UCHAR Rm;
- UCHAR Rn;
- PSTR Rounded;
- UCHAR Rs;
- BOOL ThreeOperands;
- PSTR XBit;
- MultiplyHalves = NULL;
- LongMultiply = FALSE;
- Rounded = NULL;
- ThreeOperands = FALSE;
- XBit = NULL;
- Instruction = Context->Instruction;
- BaseMnemonic = "ERR";
- PreConditionMnemonicSuffix = "";
- MnemonicSuffix = "";
- //
- // Get the top and bottom bits. These bits aren't actually defined for all
- // multiply instructions, so they'll get ignored in some cases.
- //
- if ((Instruction & ARM_MULTIPLY_SOURCE_HIGH) != 0) {
- if ((Instruction & ARM_MULTIPLY_DESTINATION_HIGH) != 0) {
- MultiplyHalves = ARM_MULTIPLY_TOP_TOP;
- } else {
- MultiplyHalves = ARM_MULTIPLY_TOP_BOTTOM;
- }
- } else {
- if ((Instruction & ARM_MULTIPLY_DESTINATION_HIGH) != 0) {
- MultiplyHalves = ARM_MULTIPLY_BOTTOM_TOP;
- } else {
- MultiplyHalves = ARM_MULTIPLY_BOTTOM_BOTTOM;
- }
- }
- //
- // Get the X bit, which indicates that the multiplications are
- // bottom * top and top * bottom. If X is cleared, the multiplications are
- // bottom * bottom and top * top.
- //
- if ((Instruction & ARM_MULTIPLY_X_BIT) != 0) {
- XBit = ARM_MULTIPLY_X_MNEMONIC;
- }
- //
- // Get the rounding bit, which indicates for a couple of instructions that
- // the multiplication is rounded.
- //
- if ((Instruction & ARM_MULTIPLY_ROUND_BIT) != 0) {
- Rounded = ARM_MULTIPLY_ROUND_MNEMONIC;
- }
- //
- // For a non-long multiply, get the 4 registers.
- //
- Rd = (Instruction & ARM_MULTIPLY_RD_MASK) >> ARM_MULTIPLY_RD_SHIFT;
- Rm = (Instruction & ARM_MULTIPLY_RM_MASK) >> ARM_MULTIPLY_RM_SHIFT;
- Rn = (Instruction & ARM_MULTIPLY_RN_MASK) >> ARM_MULTIPLY_RN_SHIFT;
- Rs = (Instruction & ARM_MULTIPLY_RS_MASK) >> ARM_MULTIPLY_RS_SHIFT;
- //
- // For long multiplies, get the high and low destination registers. Rs and
- // Rm are the same as for non-long multiplies.
- //
- RdHigh = (Instruction & ARM_MULTIPLY_RD_HIGH_MASK) >>
- ARM_MULTIPLY_RD_HIGH_SHIFT;
- RdLow = (Instruction & ARM_MULTIPLY_RD_LOW_MASK) >>
- ARM_MULTIPLY_RD_LOW_SHIFT;
- //
- // Get the mnemonic and characteristics of the instruction.
- //
- switch (Instruction & ARM_MULTIPLY_OPCODE_MASK) {
- //
- // Standard Multiply and accumulate.
- //
- case ARM_MLA_MASK | ARM_SET_FLAGS_BIT:
- MnemonicSuffix = ARM_SET_FLAGS_MNEMONIC;
- //
- // Fall through.
- //
- case ARM_MLA_MASK:
- BaseMnemonic = ARM_MLA_MNEMONIC;
- break;
- //
- // Standard Multiply.
- //
- case ARM_MUL_MASK | ARM_SET_FLAGS_BIT:
- MnemonicSuffix = ARM_SET_FLAGS_MNEMONIC;
- //
- // Fall through.
- //
- case ARM_MUL_MASK:
- BaseMnemonic =ARM_MUL_MNEMONIC;
- ThreeOperands = TRUE;
- break;
- //
- // Signed half word multiply and accumulate.
- //
- case ARM_SMLA_MASK:
- BaseMnemonic = ARM_SMLA_MNEMONIC;
- PreConditionMnemonicSuffix = MultiplyHalves;
- break;
- //
- // Signed half word multiply accumulate, dual,
- // Signed half word multiply subtract, dual,
- // Signed dual multiply add, and
- // Signed dual multiply subtract.
- //
- case ARM_SMLXD_MASK:
- if ((Instruction & ARM_SMLXD_OPCODE2_MASK) == ARM_SMLAD_OPCODE2_VALUE) {
- if (Rn == 0xF) {
- BaseMnemonic = ARM_SMUAD_MNEMONIC;
- ThreeOperands = TRUE;
- } else {
- BaseMnemonic = ARM_SMLAD_MNEMONIC;
- }
- } else if ((Instruction & ARM_SMLXD_OPCODE2_MASK) ==
- ARM_SMLSD_OPCODE2_VALUE) {
- if (Rn == 0xF) {
- BaseMnemonic = ARM_SMUSD_MNEMONIC;
- ThreeOperands = TRUE;
- } else {
- BaseMnemonic = ARM_SMLSD_MNEMONIC;
- }
- } else {
- return;
- }
- PreConditionMnemonicSuffix = XBit;
- break;
- //
- // Signed half word by word, accumulate, and
- // Signed multiply word B and T.
- //
- case ARM_SMLAW_SMULW_MASK:
- if ((Instruction & ARM_SMULW_DIFFERENT_BIT) != 0) {
- BaseMnemonic = ARM_SMULW_MNEMONIC;
- ThreeOperands = TRUE;
- } else {
- BaseMnemonic = ARM_SMLAW_MNEMONIC;
- }
- if ((Instruction & ARM_MULTIPLY_DESTINATION_HIGH) != 0) {
- PreConditionMnemonicSuffix = ARM_MULTIPLY_TOP;
- } else {
- PreConditionMnemonicSuffix = ARM_MULTIPLY_BOTTOM;
- }
- break;
- //
- // Signed multiply accumulate, long.
- //
- case ARM_SMLAL_MASK | ARM_SET_FLAGS_BIT:
- PreConditionMnemonicSuffix = ARM_SET_FLAGS_MNEMONIC;
- //
- // Fall through.
- //
- case ARM_SMLAL_MASK:
- BaseMnemonic = ARM_SMLAL_MNEMONIC;
- LongMultiply = TRUE;
- break;
- //
- // Signed halfword multiply accumulate, long.
- //
- case ARM_SMLAL_XY_MASK:
- BaseMnemonic = ARM_SMLAL_MNEMONIC;
- PreConditionMnemonicSuffix = MultiplyHalves;
- LongMultiply = TRUE;
- break;
- //
- // Signed divide.
- //
- case ARM_SDIV_MASK:
- BaseMnemonic = ARM_SDIV_MNEMONIC;
- ThreeOperands = TRUE;
- break;
- //
- // Unsigned divide.
- //
- case ARM_UDIV_MASK:
- BaseMnemonic = ARM_UDIV_MNEMONIC;
- ThreeOperands = TRUE;
- break;
- //
- // Signed half word multiply accumulate, long dual, and
- // Signed half word multiply subtract, long dual.
- //
- case ARM_SMLXLD_MASK:
- if ((Instruction & ARM_SMLXLD_OPCODE2_MASK) ==
- ARM_SMLALD_OPCODE2_VALUE) {
- BaseMnemonic = ARM_SMLALD_MNEMONIC;
- } else if ((Instruction & ARM_SMLXLD_OPCODE2_MASK) ==
- ARM_SMLSLD_OPCODE2_VALUE) {
- BaseMnemonic = ARM_SMLSLD_MNEMONIC;
- } else {
- return;
- }
- PreConditionMnemonicSuffix = XBit;
- LongMultiply = TRUE;
- break;
- //
- // Signed most significant word multiply accumulate, and
- // Signed most significant word multiply subtract, and
- // Signed most significant word multiply.
- //
- case ARM_SMMLX_MASK:
- if ((Instruction & ARM_SMMLX_OPCODE2_MASK) == ARM_SMMLA_OPCODE2_VALUE) {
- if (Rn == 0xF) {
- BaseMnemonic = ARM_SMMUL_MNEMONIC;
- ThreeOperands = TRUE;
- } else {
- BaseMnemonic = ARM_SMMLA_MNEMONIC;
- }
- } else if ((Instruction & ARM_SMMLX_OPCODE2_MASK) ==
- ARM_SMMLS_OPCODE2_VALUE) {
- BaseMnemonic = ARM_SMMLS_MNEMONIC;
- } else {
- return;
- }
- PreConditionMnemonicSuffix = Rounded;
- break;
- //
- // Signed multiply.
- //
- case ARM_SMUL_MASK:
- BaseMnemonic = ARM_SMUL_MNEMONIC;
- PreConditionMnemonicSuffix = MultiplyHalves;
- ThreeOperands = TRUE;
- break;
- //
- // Signed multiply, long.
- //
- case ARM_SMULL_MASK | ARM_SET_FLAGS_BIT:
- MnemonicSuffix = ARM_SET_FLAGS_MNEMONIC;
- //
- // Fall through.
- //
- case ARM_SMULL_MASK:
- BaseMnemonic = ARM_SMULL_MNEMONIC;
- LongMultiply = TRUE;
- break;
- //
- // Unsigned multiply accumulate accumulate long.
- //
- case ARM_UMAAL_MASK:
- BaseMnemonic = ARM_UMAAL_MNEMONIC;
- LongMultiply = TRUE;
- break;
- //
- // Unsigned multiply accumulate long.
- //
- case ARM_UMLAL_MASK | ARM_SET_FLAGS_BIT:
- MnemonicSuffix = ARM_SET_FLAGS_MNEMONIC;
- //
- // Fall through.
- //
- case ARM_UMLAL_MASK:
- BaseMnemonic = ARM_UMLAL_MNEMONIC;
- LongMultiply = TRUE;
- break;
- //
- // Unsigned multiply long.
- //
- case ARM_UMULL_MASK | ARM_SET_FLAGS_BIT:
- MnemonicSuffix = ARM_SET_FLAGS_MNEMONIC;
- //
- // Fall through.
- //
- case ARM_UMULL_MASK:
- BaseMnemonic = ARM_UMULL_MNEMONIC;
- LongMultiply = TRUE;
- break;
- default:
- return;
- }
- snprintf(Context->Mnemonic,
- ARM_OPERAND_LENGTH,
- "%s%s%s",
- BaseMnemonic,
- PreConditionMnemonicSuffix,
- MnemonicSuffix);
- //
- // Create the operands, depending on whether the instruction was a long
- // multiply or not.
- //
- if (LongMultiply != FALSE) {
- strcpy(Context->Operand1, DbgArmRegisterNames[RdLow]);
- strcpy(Context->Operand2, DbgArmRegisterNames[RdHigh]);
- strcpy(Context->Operand3, DbgArmRegisterNames[Rm]);
- strcpy(Context->Operand4, DbgArmRegisterNames[Rs]);
- } else {
- strcpy(Context->Operand1, DbgArmRegisterNames[Rd]);
- strcpy(Context->Operand2, DbgArmRegisterNames[Rm]);
- strcpy(Context->Operand3, DbgArmRegisterNames[Rs]);
- if (ThreeOperands == FALSE) {
- strcpy(Context->Operand4, DbgArmRegisterNames[Rn]);
- }
- }
- return;
- }
- VOID
- DbgpArmDecodeSynchronization (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a synchronization primitive instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ULONG Instruction;
- PSTR Mnemonic;
- ULONG Op;
- ULONG R0;
- ULONG R12;
- ULONG Rn;
- Instruction = Context->Instruction;
- Op = (Instruction & ARM_SYNCHRONIZATION_OPCODE_MASK) >>
- ARM_SYNCHRONIZATION_OPCODE_SHIFT;
- Rn = (Instruction & ARM_SYNCHRONIZATION_RN_MASK) >>
- ARM_SYNCHRONIZATION_RN_SHIFT;
- R0 = Instruction & ARM_SYNCHRONIZATION_R0_MASK;
- R12 = (Instruction & ARM_SYNCHRONIZATION_R12_MASK) >>
- ARM_SYNCHRONIZATION_R12_SHIFT;
- //
- // If the high bit of the op field is not set, then it's a swap instruction.
- //
- if ((Op & ARM_SYNCHRONIZATION_OPCODE_EXCLUSIVE) == 0) {
- if ((Instruction & ARM_SYNCHRONIZATION_SWAP_BYTE) != 0) {
- Mnemonic = ARM_SWPB_MNEMONIC;
- } else {
- Mnemonic = ARM_SWP_MNEMONIC;
- }
- strcpy(Context->Operand1, DbgArmRegisterNames[R12]);
- strcpy(Context->Operand2, DbgArmRegisterNames[R0]);
- sprintf(Context->Operand3, "[%s]", DbgArmRegisterNames[Rn]);
- //
- // It's an ldrex or strex instruction of some kind.
- //
- } else {
- Op &= ~ARM_SYNCHRONIZATION_OPCODE_EXCLUSIVE;
- Mnemonic = DbgArmSynchronizationMnemonics[Op];
- //
- // If the lowest bit of the op region is set, it's an ldrex{b,h,d}.
- //
- if ((Op & ARM_SYNCHRONIZATION_OPCODE_LOAD) != 0) {
- strcpy(Context->Operand1, DbgArmRegisterNames[R12]);
- sprintf(Context->Operand2, "[%s]", DbgArmRegisterNames[Rn]);
- } else {
- strcpy(Context->Operand1, DbgArmRegisterNames[R12]);
- strcpy(Context->Operand2, DbgArmRegisterNames[R0]);
- sprintf(Context->Operand3, "[%s]", DbgArmRegisterNames[Rn]);
- }
- }
- strcpy(Context->Mnemonic, Mnemonic);
- return;
- }
- VOID
- DbgpArmDecodeSupervisorCall (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a supervisor call instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ULONG Immediate;
- ULONG Instruction;
- Instruction = Context->Instruction;
- Immediate = Instruction & ARM_IMMEDIATE24_MASK;
- strcpy(Context->Mnemonic, ARM_SVC_MNEMONIC);
- sprintf(Context->Operand1, "#%d ; 0x%x", Immediate, Immediate);
- return;
- }
- VOID
- DbgpArmDecodeFloatingPointTwoRegisters (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a two-register floating point data processing
- instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ARM_IMMEDIATE_DOUBLE Double;
- ARM_IMMEDIATE_FLOAT Float;
- ULONG Immediate8;
- ULONG Instruction;
- ULONG Mask;
- PSTR MnemonicSuffix;
- BOOL TwoRegisters;
- ULONG VectorD;
- ULONG VectorM;
- PSTR VectorTypeString;
- Instruction = Context->Instruction;
- //
- // Collect the vector values. If the double-precision (SZ) bit is set, then
- // the extra bit for each vector is the high bit. If the double-precision
- // bit is not set, then the extra bit is the low bit.
- //
- VectorD = (Instruction & ARM_FLOATING_POINT_VD_MASK) >>
- ARM_FLOATING_POINT_VD_SHIFT;
- VectorM = (Instruction & ARM_FLOATING_POINT_VM_MASK) >>
- ARM_FLOATING_POINT_VM_SHIFT;
- if ((Instruction & ARM_FLOATING_POINT_SZ_BIT) != 0) {
- if ((Instruction & ARM_FLOATING_POINT_D_BIT) != 0) {
- VectorD |= (1 << 4);
- }
- if ((Instruction & ARM_FLOATING_POINT_M_BIT) != 0) {
- VectorM |= (1 << 4);
- }
- MnemonicSuffix = ARM_FLOATING_POINT_DOUBLE_PRECISION_SUFFIX;
- VectorTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- } else {
- VectorD <<= 1;
- if ((Instruction & ARM_FLOATING_POINT_D_BIT) != 0) {
- VectorD |= 1;
- }
- VectorM <<= 1;
- if ((Instruction & ARM_FLOATING_POINT_M_BIT) != 0) {
- VectorM |= 1;
- }
- MnemonicSuffix = ARM_FLOATING_POINT_SINGLE_PRECISION_SUFFIX;
- VectorTypeString = ARM_FLOATING_POINT_SINGLE_PRECISION_VECTOR;
- }
- //
- // If the op bit is not set, then this is actually a VMOV immediate and not
- // a two register instruction.
- //
- if ((Instruction & ARM_FLOATING_POINT_OP_BIT) == 0) {
- BaseMnemonic = ARM_VMOV_MNEMONIC;
- Immediate8 = ARM_FLOATING_POINT_BUILD_IMMEDIATE8(Instruction);
- if ((Instruction & ARM_FLOATING_POINT_SZ_BIT) != 0) {
- Double.Immediate = ARM_FLOATING_POINT_BUILD_IMMEDIATE64(Immediate8);
- sprintf(Context->Operand2,
- "#%d ; 0x%llx %g",
- Immediate8,
- Double.Immediate,
- Double.Double);
- } else {
- Float.Immediate= ARM_FLOATING_POINT_BUILD_IMMEDIATE32(Immediate8);
- sprintf(Context->Operand2,
- "#%d ; 0x%x %g",
- Immediate8,
- Float.Immediate,
- Float.Float);
- }
- TwoRegisters = FALSE;
- } else {
- Mask = Instruction & ARM_FLOATING_POINT_TWO_REGISTER_INSTRUCTION_MASK;
- switch (Mask) {
- case ARM_FLOATING_POINT_TWO_REGISTER_INSTRUCTION_VMOV:
- BaseMnemonic = ARM_VMOV_MNEMONIC;
- break;
- case ARM_FLOATING_POINT_TWO_REGISTER_INSTRUCTION_VABS:
- BaseMnemonic = ARM_VABS_MNEMONIC;
- break;
- case ARM_FLOATING_POINT_TWO_REGISTER_INSTRUCTION_VNEG:
- BaseMnemonic = ARM_VNEG_MNEMONIC;
- break;
- case ARM_FLOATING_POINT_TWO_REGISTER_INSTRUCTION_VSQRT:
- BaseMnemonic = ARM_VSQRT_MNEMONIC;
- break;
- default:
- return;
- }
- TwoRegisters = TRUE;
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- strcpy(Context->PostConditionMnemonicSuffix, MnemonicSuffix);
- sprintf(Context->Operand1, "%s%d", VectorTypeString, VectorD);
- if (TwoRegisters != FALSE) {
- sprintf(Context->Operand2, "%s%d", VectorTypeString, VectorM);
- }
- return;
- }
- VOID
- DbgpArmDecodeFloatingPointThreeRegisters (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a three-register floating point data processing
- instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Instruction;
- PSTR MnemonicSuffix;
- ULONG VectorD;
- ULONG VectorM;
- ULONG VectorN;
- PSTR VectorTypeString;
- Instruction = Context->Instruction;
- //
- // Collect the vector values. If the double-precision (SZ) bit is set, then
- // the extra bit for each vector is the high bit. If the double-precision
- // bit is not set, then the extra bit is the low bit.
- //
- VectorD = (Instruction & ARM_FLOATING_POINT_VD_MASK) >>
- ARM_FLOATING_POINT_VD_SHIFT;
- VectorM = (Instruction & ARM_FLOATING_POINT_VM_MASK) >>
- ARM_FLOATING_POINT_VM_SHIFT;
- VectorN = (Instruction & ARM_FLOATING_POINT_VN_MASK) >>
- ARM_FLOATING_POINT_VN_SHIFT;
- if ((Instruction & ARM_FLOATING_POINT_SZ_BIT) != 0) {
- if ((Instruction & ARM_FLOATING_POINT_D_BIT) != 0) {
- VectorD |= (1 << 4);
- }
- if ((Instruction & ARM_FLOATING_POINT_M_BIT) != 0) {
- VectorM |= (1 << 4);
- }
- if ((Instruction & ARM_FLOATING_POINT_N_BIT) != 0) {
- VectorN |= (1 << 4);
- }
- MnemonicSuffix = ARM_FLOATING_POINT_DOUBLE_PRECISION_SUFFIX;
- VectorTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- } else {
- VectorD <<= 1;
- if ((Instruction & ARM_FLOATING_POINT_D_BIT) != 0) {
- VectorD |= 1;
- }
- VectorM <<= 1;
- if ((Instruction & ARM_FLOATING_POINT_M_BIT) != 0) {
- VectorM |= 1;
- }
- VectorN <<= 1;
- if ((Instruction & ARM_FLOATING_POINT_N_BIT) != 0) {
- VectorN |= 1;
- }
- MnemonicSuffix = ARM_FLOATING_POINT_SINGLE_PRECISION_SUFFIX;
- VectorTypeString = ARM_FLOATING_POINT_SINGLE_PRECISION_VECTOR;
- }
- //
- // Get the instruction based on the value of opcode 1 and the op bit.
- //
- BaseMnemonic = "ERR";
- switch (Instruction & ARM_FLOATING_POINT_INSTRUCTION_MASK) {
- case ARM_FLOATING_POINT_INSTRUCTION_VMLA_VMLS:
- if ((Instruction & ARM_FLOATING_POINT_OP_BIT) != 0) {
- BaseMnemonic = ARM_VMLS_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VMLA_MNEMONIC;
- }
- break;
- case ARM_FLOATING_POINT_INSTRUCTION_VNMLA_VNMLS:
- if ((Instruction & ARM_FLOATING_POINT_OP_BIT) != 0) {
- BaseMnemonic = ARM_VNMLS_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VNMLA_MNEMONIC;
- }
- break;
- case ARM_FLOATING_POINT_INSTRUCTION_VMUL_VNMUL:
- if ((Instruction & ARM_FLOATING_POINT_OP_BIT) != 0) {
- BaseMnemonic = ARM_VNMUL_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VMUL_MNEMONIC;
- }
- break;
- case ARM_FLOATING_POINT_INSTRUCTION_VADD_VSUB:
- if ((Instruction & ARM_FLOATING_POINT_OP_BIT) != 0) {
- BaseMnemonic = ARM_VSUB_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VADD_MNEMONIC;
- }
- break;
- case ARM_FLOATING_POINT_INSTRUCTION_VDIV:
- if ((Instruction & ARM_FLOATING_POINT_OP_BIT) != 0) {
- return;
- }
- BaseMnemonic = ARM_VDIV_MNEMONIC;
- break;
- case ARM_FLOATING_POINT_INSTRUCTION_VFNMA_VFNMS:
- if ((Instruction & ARM_FLOATING_POINT_OP_BIT) != 0) {
- BaseMnemonic = ARM_VFNMA_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VFNMS_MNEMONIC;
- }
- break;
- case ARM_FLOATING_POINT_INSTRUCTION_VFMA_VFMS:
- if ((Instruction & ARM_FLOATING_POINT_OP_BIT) != 0) {
- BaseMnemonic = ARM_VFMS_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VFMA_MNEMONIC;
- }
- break;
- default:
- break;
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- strcpy(Context->PostConditionMnemonicSuffix, MnemonicSuffix);
- sprintf(Context->Operand1, "%s%d", VectorTypeString, VectorD);
- sprintf(Context->Operand2, "%s%d", VectorTypeString, VectorN);
- sprintf(Context->Operand3, "%s%d", VectorTypeString, VectorM);
- return;
- }
- VOID
- DbgpArmDecodeFloatingPointVectorConvert (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a floating point vector convert instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR DestinationHalfSuffix;
- PSTR DestinationSuffix;
- PSTR FixedSuffix;
- ULONG FractionBits;
- ULONG Instruction;
- PSTR PreConditionMnemonicSuffix;
- BOOL RepeatVectorD;
- PSTR SourceHalfSuffix;
- PSTR SourceSuffix;
- ULONG VectorD;
- BOOL VectorDDouble;
- PSTR VectorDTypeString;
- ULONG VectorM;
- BOOL VectorMDouble;
- PSTR VectorMTypeString;
- //
- // Save somem values that are common to most instructions.
- //
- Instruction = Context->Instruction;
- RepeatVectorD = FALSE;
- VectorDDouble = FALSE;
- VectorD = (Instruction & ARM_FLOATING_POINT_VD_MASK) >>
- ARM_FLOATING_POINT_VD_SHIFT;
- VectorMDouble = FALSE;
- VectorM = (Instruction & ARM_FLOATING_POINT_VM_MASK) >>
- ARM_FLOATING_POINT_VM_SHIFT;
- DestinationHalfSuffix = ARM_FLOATING_POINT_SINGLE_PRECISION_SUFFIX;
- SourceHalfSuffix = ARM_FLOATING_POINT_HALF_PRECISION_SUFFIX;
- DestinationSuffix = "";
- PreConditionMnemonicSuffix = "";
- SourceSuffix = "";
- //
- // Compute the fraction bits and suffix for the fixed point instructions.
- // The fixed 32-bit and unsigned bit are the same for float to fixed as
- // they are for fixed to float.
- //
- FractionBits = (Instruction & ARM_FLOATING_POINT_IMMEDIATE4_LOW_MASK) >>
- ARM_FLOATING_POINT_IMMEDIATE4_LOW_SHIFT;
- FractionBits <<= 1;
- if ((Instruction & ARM_FLOATING_POINT_I_BIT) != 0) {
- FractionBits |= 1;
- }
- if ((Instruction & ARM_VCVT_FIXED_32_TO_FLOAT) != 0) {
- if ((Instruction & ARM_VCVT_FIXED_UNSIGNED_TO_FLOAT) != 0) {
- FixedSuffix = ARM_FLOATING_POINT_UNSIGNED_INTEGER_SUFFIX;
- } else {
- FixedSuffix = ARM_FLOATING_POINT_SIGNED_INTEGER_SUFFIX;
- }
- FractionBits = 32 - FractionBits;
- } else {
- if ((Instruction & ARM_VCVT_FIXED_UNSIGNED_TO_FLOAT) != 0) {
- FixedSuffix = ARM_FLOATING_POINT_UNSIGNED_HALF_SUFFIX;
- } else {
- FixedSuffix = ARM_FLOATING_POINT_SIGNED_HALF_SUFFIX;
- }
- FractionBits = 16 - FractionBits;
- }
- //
- // Determine the suffices and vector sizes baced on the instruction mask.
- //
- switch (Instruction & ARM_VCVT_MASK) {
- //
- // Handle VCVTT single to half.
- //
- case ARM_VCVT_TOP | ARM_VCVT_SINGLE_TO_HALF:
- DestinationHalfSuffix = ARM_FLOATING_POINT_HALF_PRECISION_SUFFIX;
- SourceHalfSuffix = ARM_FLOATING_POINT_SINGLE_PRECISION_SUFFIX;
- //
- // Fall through.
- //
- //
- // Handle VCVTT half to single.
- //
- case ARM_VCVT_TOP | ARM_VCVT_HALF_TO_SINGLE:
- PreConditionMnemonicSuffix = ARM_FLOATING_POINT_TOP;
- DestinationSuffix = DestinationHalfSuffix;
- SourceSuffix = SourceHalfSuffix;
- break;
- //
- // Handle VCVTB single to half.
- //
- case ARM_VCVT_BOTTOM | ARM_VCVT_SINGLE_TO_HALF:
- DestinationHalfSuffix = ARM_FLOATING_POINT_HALF_PRECISION_SUFFIX;
- SourceHalfSuffix = ARM_FLOATING_POINT_SINGLE_PRECISION_SUFFIX;
- //
- // Fall through.
- //
- //
- // Handle VCVTB half to single.
- //
- case ARM_VCVT_BOTTOM | ARM_VCVT_HALF_TO_SINGLE:
- PreConditionMnemonicSuffix = ARM_FLOATING_POINT_BOTTOM;
- DestinationSuffix = DestinationHalfSuffix;
- SourceSuffix = SourceHalfSuffix;
- break;
- //
- // Handle VCVT single-precision to double-precision conversions and
- // double-precision to single-precision conversion.
- //
- case ARM_VCVT_FLOAT_TO_FLOAT:
- //
- // Here the double bit indicates that the conversion is from a double.
- //
- if ((Instruction & ARM_VCVT_DOUBLE) != 0) {
- VectorMDouble = TRUE;
- SourceSuffix = ARM_FLOATING_POINT_DOUBLE_PRECISION_SUFFIX;
- DestinationSuffix = ARM_FLOATING_POINT_SINGLE_PRECISION_SUFFIX;
- } else {
- VectorDDouble = TRUE;
- SourceSuffix = ARM_FLOATING_POINT_SINGLE_PRECISION_SUFFIX;
- DestinationSuffix = ARM_FLOATING_POINT_DOUBLE_PRECISION_SUFFIX;
- }
- break;
- //
- // Handle conversions from floats to integers.
- //
- case ARM_VCVT_FLOAT_TO_INTEGER:
- case ARM_VCVT_FLOAT_TO_INTEGER | ARM_VCVT_FLOAT_TO_INTEGER_SIGNED:
- case ARM_VCVT_FLOAT_TO_INTEGER | ARM_VCVT_FLOAT_TO_INTEGER_ROUND_TO_ZERO:
- case (ARM_VCVT_FLOAT_TO_INTEGER |
- ARM_VCVT_FLOAT_TO_INTEGER_SIGNED |
- ARM_VCVT_FLOAT_TO_INTEGER_ROUND_TO_ZERO):
- if ((Instruction & ARM_VCVT_DOUBLE) != 0) {
- VectorMDouble = TRUE;
- SourceSuffix = ARM_FLOATING_POINT_DOUBLE_PRECISION_SUFFIX;
- } else {
- SourceSuffix = ARM_FLOATING_POINT_SINGLE_PRECISION_SUFFIX;
- }
- if ((Instruction & ARM_VCVT_FLOAT_TO_INTEGER_SIGNED) != 0) {
- DestinationSuffix = ARM_FLOATING_POINT_SIGNED_INTEGER_SUFFIX;
- } else {
- DestinationSuffix = ARM_FLOATING_POINT_UNSIGNED_INTEGER_SUFFIX;
- }
- if ((Instruction & ARM_VCVT_FLOAT_TO_INTEGER_ROUND_TO_ZERO) == 0) {
- PreConditionMnemonicSuffix = ARM_FLOATING_POINT_ROUNDING;
- }
- break;
- //
- // Handle conversions from integers to floats.
- //
- case ARM_VCVT_INTEGER_TO_FLOAT:
- case ARM_VCVT_INTEGER_TO_FLOAT | ARM_VCVT_INTEGER_TO_FLOAT_SIGNED:
- if ((Instruction & ARM_VCVT_DOUBLE) != 0) {
- VectorDDouble = TRUE;
- DestinationSuffix = ARM_FLOATING_POINT_DOUBLE_PRECISION_SUFFIX;
- } else {
- DestinationSuffix = ARM_FLOATING_POINT_SINGLE_PRECISION_SUFFIX;
- }
- if ((Instruction & ARM_VCVT_INTEGER_TO_FLOAT_SIGNED) != 0) {
- SourceSuffix = ARM_FLOATING_POINT_SIGNED_INTEGER_SUFFIX;
- } else {
- SourceSuffix = ARM_FLOATING_POINT_UNSIGNED_INTEGER_SUFFIX;
- }
- break;
- //
- // Handle conversions from floats to fixed point.
- //
- case ARM_VCVT_FLOAT_TO_FIXED:
- case ARM_VCVT_FLOAT_TO_FIXED | ARM_VCVT_FLOAT_TO_FIXED_UNSIGNED:
- case ARM_VCVT_FLOAT_TO_FIXED | ARM_VCVT_FLOAT_TO_FIXED_32:
- case (ARM_VCVT_FLOAT_TO_FIXED |
- ARM_VCVT_FLOAT_TO_FIXED_UNSIGNED |
- ARM_VCVT_FLOAT_TO_FIXED_32):
- if ((Instruction & ARM_VCVT_DOUBLE) != 0) {
- VectorDDouble = TRUE;
- SourceSuffix = ARM_FLOATING_POINT_DOUBLE_PRECISION_SUFFIX;
- } else {
- SourceSuffix = ARM_FLOATING_POINT_SINGLE_PRECISION_SUFFIX;
- }
- DestinationSuffix = FixedSuffix;
- RepeatVectorD = TRUE;
- break;
- //
- // Handle conversions from fixed point to floats.
- //
- case ARM_VCVT_FIXED_TO_FLOAT:
- case ARM_VCVT_FIXED_TO_FLOAT | ARM_VCVT_FIXED_UNSIGNED_TO_FLOAT:
- case ARM_VCVT_FIXED_TO_FLOAT | ARM_VCVT_FIXED_32_TO_FLOAT:
- case (ARM_VCVT_FIXED_TO_FLOAT |
- ARM_VCVT_FIXED_UNSIGNED_TO_FLOAT |
- ARM_VCVT_FIXED_32_TO_FLOAT):
- if ((Instruction & ARM_VCVT_DOUBLE) != 0) {
- VectorDDouble = TRUE;
- DestinationSuffix = ARM_FLOATING_POINT_DOUBLE_PRECISION_SUFFIX;
- } else {
- DestinationSuffix = ARM_FLOATING_POINT_SINGLE_PRECISION_SUFFIX;
- }
- SourceSuffix = FixedSuffix;
- RepeatVectorD = TRUE;
- break;
- default:
- break;
- }
- //
- // Convert the vectors into the correct double-precision or
- // single-precision values.
- //
- if (VectorDDouble != FALSE) {
- VectorDTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- if ((Instruction & ARM_FLOATING_POINT_D_BIT) != 0) {
- VectorD |= (1 << 4);
- }
- } else {
- VectorDTypeString = ARM_FLOATING_POINT_SINGLE_PRECISION_VECTOR;
- VectorD <<= 1;
- if ((Instruction & ARM_FLOATING_POINT_D_BIT) != 0) {
- VectorD |= 1;
- }
- }
- if (VectorMDouble != FALSE) {
- VectorMTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- if ((Instruction & ARM_FLOATING_POINT_M_BIT) != 0) {
- VectorM |= (1 << 4);
- }
- } else {
- VectorMTypeString = ARM_FLOATING_POINT_SINGLE_PRECISION_VECTOR;
- VectorM <<= 1;
- if ((Instruction & ARM_FLOATING_POINT_M_BIT) != 0) {
- VectorM |= 1;
- }
- }
- sprintf(Context->Mnemonic,
- "%s%s",
- ARM_VCVT_MNEMONIC,
- PreConditionMnemonicSuffix);
- sprintf(Context->PostConditionMnemonicSuffix,
- "%s%s",
- DestinationSuffix,
- SourceSuffix);
- sprintf(Context->Operand1, "%s%d", VectorDTypeString, VectorD);
- if (RepeatVectorD != FALSE) {
- sprintf(Context->Operand2, "%s%d", VectorDTypeString, VectorD);
- } else {
- sprintf(Context->Operand2, "%s%d", VectorMTypeString, VectorM);
- }
- return;
- }
- VOID
- DbgpArmDecodeFloatingPointVectorCompare (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a floating point vector compare instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Instruction;
- PSTR MnemonicSuffix;
- ULONG VectorD;
- ULONG VectorM;
- PSTR VectorTypeString;
- Instruction = Context->Instruction;
- //
- // Collect the vector values. If the double-precision (SZ) bit is set, then
- // the extra bit for each vector is the high bit. If the double-precision
- // bit is not set, then the extra bit is the low bit.
- //
- VectorD = (Instruction & ARM_FLOATING_POINT_VD_MASK) >>
- ARM_FLOATING_POINT_VD_SHIFT;
- VectorM = (Instruction & ARM_FLOATING_POINT_VM_MASK) >>
- ARM_FLOATING_POINT_VM_SHIFT;
- if ((Instruction & ARM_FLOATING_POINT_SZ_BIT) != 0) {
- if ((Instruction & ARM_FLOATING_POINT_D_BIT) != 0) {
- VectorD |= (1 << 4);
- }
- if ((Instruction & ARM_FLOATING_POINT_M_BIT) != 0) {
- VectorM |= (1 << 4);
- }
- MnemonicSuffix = ARM_FLOATING_POINT_DOUBLE_PRECISION_SUFFIX;
- VectorTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- } else {
- VectorD <<= 1;
- if ((Instruction & ARM_FLOATING_POINT_D_BIT) != 0) {
- VectorD |= 1;
- }
- VectorM <<= 1;
- if ((Instruction & ARM_FLOATING_POINT_M_BIT) != 0) {
- VectorM |= 1;
- }
- MnemonicSuffix = ARM_FLOATING_POINT_SINGLE_PRECISION_SUFFIX;
- VectorTypeString = ARM_FLOATING_POINT_SINGLE_PRECISION_VECTOR;
- }
- //
- // Get the base mnemonic and fill out the context.
- //
- if ((Instruction & ARM_FLOATING_POINT_VCMP_E_BIT) != 0) {
- BaseMnemonic = ARM_VCMPE_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VCMP_MNEMONIC;
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- strcpy(Context->PostConditionMnemonicSuffix, MnemonicSuffix);
- sprintf(Context->Operand1, "%s%d", VectorTypeString, VectorD);
- if ((Instruction & ARM_FLOATING_POINT_VCMP_ZERO) != 0) {
- sprintf(Context->Operand2, "#0.0");
- } else {
- sprintf(Context->Operand2, "%s%d", VectorTypeString, VectorM);
- }
- return;
- }
- VOID
- DbgpArmDecodeSimdSmallMove (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes a floating point to ARM register move instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ULONG Instruction;
- ULONG Register;
- PSTR RegisterString;
- ULONG Size;
- PSTR SizeTypeSuffix;
- PSTR SizeValueSuffix;
- ULONG Vector;
- BOOL VectorDouble;
- ULONG VectorIndex;
- PSTR VectorString;
- PSTR VectorTypeString;
- Instruction = Context->Instruction;
- Register = (Instruction & ARM_SIMD_TRANSFER_REGISTER_MASK) >>
- ARM_SIMD_TRANSFER_REGISTER_SHIFT;
- VectorDouble = FALSE;
- Vector = (Instruction & ARM_SIMD_TRANSFER_VECTOR_MASK) >>
- ARM_SIMD_TRANSFER_VECTOR_SHIFT;
- //
- // Determine the mnemonic suffices and vector index for the to/from scalar
- // instructions.
- //
- SizeTypeSuffix = "";
- SizeValueSuffix = "";
- VectorIndex = 0;
- if ((Instruction & ARM_SIMD_TRANSFER_MOVE_SCALAR) != 0) {
- VectorDouble = TRUE;
- Size = ARM_SIMD_TRANSFER_SCALAR_BUILD_SIZE_ENCODING(Instruction);
- if ((Size & ARM_SIMD_TRANSFER_SCALAR_SIZE_8_MASK) ==
- ARM_SIMD_TRANSFER_SCALAR_SIZE_8_VALUE) {
- VectorIndex = (Size & ~ARM_SIMD_TRANSFER_SCALAR_SIZE_8_MASK) >>
- ARM_SIMD_TRANSFER_SCALAR_SIZE_8_SHIFT;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_8;
- } else if ((Size & ARM_SIMD_TRANSFER_SCALAR_SIZE_16_MASK) ==
- ARM_SIMD_TRANSFER_SCALAR_SIZE_16_VALUE) {
- VectorIndex = (Size & ~ARM_SIMD_TRANSFER_SCALAR_SIZE_16_MASK) >>
- ARM_SIMD_TRANSFER_SCALAR_SIZE_16_SHIFT;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_16;
- } else if ((Size & ARM_SIMD_TRANSFER_SCALAR_SIZE_32_MASK) ==
- ARM_SIMD_TRANSFER_SCALAR_SIZE_32_VALUE) {
- VectorIndex = (Size & ~ARM_SIMD_TRANSFER_SCALAR_SIZE_32_MASK) >>
- ARM_SIMD_TRANSFER_SCALAR_SIZE_32_SHIFT;
- if (((Instruction & ARM_SIMD_TRANSFER_TO_REGISTER) != 0) &&
- ((Instruction & ARM_SIMD_TRANSFER_SCALAR_UNSIGNED) != 0)) {
- DbgpArmDecodeUndefined(Context);
- return;
- }
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- } else {
- DbgpArmDecodeUndefined(Context);
- return;
- }
- if ((Instruction & ARM_SIMD_TRANSFER_TO_REGISTER) != 0) {
- if ((Instruction & ARM_SIMD_TRANSFER_SCALAR_UNSIGNED) != 0) {
- SizeTypeSuffix = ARM_SIMD_DATA_UNSIGNED;
- } else {
- SizeTypeSuffix = ARM_SIMD_DATA_SIGNED;
- }
- } else {
- SizeTypeSuffix = ARM_SIMD_DATA_DEFAULT;
- }
- }
- //
- // Finalize the vector and get its type string.
- //
- if (VectorDouble != FALSE) {
- VectorTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- if ((Instruction & ARM_SIMD_TRANSFER_VECTOR_BIT) != 0) {
- Vector |= (1 << 4);
- }
- } else {
- VectorTypeString = ARM_FLOATING_POINT_SINGLE_PRECISION_VECTOR;
- Vector <<= 1;
- if ((Instruction & ARM_SIMD_TRANSFER_VECTOR_BIT) != 0) {
- Vector |= 1;
- }
- }
- if ((Instruction & ARM_SIMD_TRANSFER_TO_REGISTER) != 0) {
- RegisterString = Context->Operand1;
- VectorString = Context->Operand2;
- } else {
- VectorString = Context->Operand1;
- RegisterString = Context->Operand2;
- }
- strcpy(Context->Mnemonic, ARM_VMOV_MNEMONIC);
- sprintf(Context->PostConditionMnemonicSuffix,
- "%s%s",
- SizeTypeSuffix,
- SizeValueSuffix);
- strcpy(RegisterString, DbgArmRegisterNames[Register]);
- if ((Instruction & ARM_SIMD_TRANSFER_MOVE_SCALAR) != 0) {
- sprintf(VectorString,
- "%s%d[%d]",
- VectorTypeString,
- Vector,
- VectorIndex);
- } else {
- sprintf(VectorString, "%s%d", VectorTypeString, Vector);
- }
- return;
- }
- VOID
- DbgpArmDecodeSimdSpecialMove (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an ARM register to special register move instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Instruction;
- ULONG Register;
- PSTR RegisterName;
- ULONG SpecialRegister;
- Instruction = Context->Instruction;
- Register = (Instruction & ARM_SIMD_TRANSFER_REGISTER_MASK) >>
- ARM_SIMD_TRANSFER_REGISTER_SHIFT;
- SpecialRegister = (Instruction & ARM_SIMD_TRANSFER_SPECIAL_MASK) >>
- ARM_SIMD_TRANSFER_SPECIAL_SHIFT;
- if ((Instruction & ARM_SIMD_TRANSFER_TO_REGISTER) != 0) {
- BaseMnemonic = ARM_VMRS_MNEMONIC;
- if ((Register == 0xF) && (SpecialRegister == 1)) {
- RegisterName = ARM_SIMD_APSR_REGISTER;
- } else {
- RegisterName = DbgArmRegisterNames[Register];
- }
- strcpy(Context->Operand1, RegisterName);
- strcpy(Context->Operand2, DbgArmSpecialRegisterNames[SpecialRegister]);
- } else {
- BaseMnemonic = ARM_VMSR_MNEMONIC;
- strcpy(Context->Operand1, DbgArmSpecialRegisterNames[SpecialRegister]);
- strcpy(Context->Operand2, DbgArmRegisterNames[Register]);
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- return;
- }
- VOID
- DbgpArmDecodeSimdDuplicate (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an ARM register to floating point duplicate
- instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ULONG Instruction;
- PSTR MnemonicSuffix;
- ULONG Register;
- ULONG Size;
- ULONG Vector;
- PSTR VectorTypeString;
- Instruction = Context->Instruction;
- Register = (Instruction & ARM_SIMD_TRANSFER_REGISTER_MASK) >>
- ARM_SIMD_TRANSFER_REGISTER_SHIFT;
- Vector = (Instruction & ARM_SIMD_TRANSFER_VECTOR_MASK) >>
- ARM_SIMD_TRANSFER_VECTOR_SHIFT;
- if ((Instruction & ARM_SIMD_TRANSFER_VECTOR_BIT) != 0) {
- Vector |= (1 << 4);
- }
- //
- // Determine the size of the transfers.
- //
- Size = ARM_SIMD_TRANSFER_DUP_BUILD_SIZE_ENCODING(Instruction);
- switch (Size) {
- case ARM_SIMD_TRANSFER_DUP_SIZE_8:
- MnemonicSuffix = ARM_SIMD_DATA_SIZE_8;
- break;
- case ARM_SIMD_TRANSFER_DUP_SIZE_16:
- MnemonicSuffix = ARM_SIMD_DATA_SIZE_16;
- break;
- case ARM_SIMD_TRANSFER_DUP_SIZE_32:
- MnemonicSuffix = ARM_SIMD_DATA_SIZE_32;
- break;
- default:
- DbgpArmDecodeUndefined(Context);
- return;
- }
- //
- // Get the vector type.
- //
- if ((Instruction & ARM_SIMD_TRANSFER_DUP_QUADWORD) != 0) {
- VectorTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- } else {
- VectorTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- }
- strcpy(Context->Mnemonic, ARM_VDUP_MNEMONIC);
- strcpy(Context->PostConditionMnemonicSuffix, MnemonicSuffix);
- sprintf(Context->Operand1, "%s%d", VectorTypeString, Vector);
- strcpy(Context->Operand2, DbgArmRegisterNames[Register]);
- return;
- }
- VOID
- DbgpArmDecodeSimdLoadStoreRegister (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an SIMD and floating point register load/store
- instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Instruction;
- ULONG Offset;
- ULONG Register;
- CHAR Sign;
- ULONG Vector;
- PSTR VectorTypeString;
- Instruction = Context->Instruction;
- Register = (Instruction & ARM_SIMD_LOAD_STORE_REGISTER_MASK) >>
- ARM_SIMD_LOAD_STORE_REGISTER_SHIFT;
- if ((Instruction & ARM_LOAD_BIT) != 0) {
- BaseMnemonic = ARM_VLD_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VST_MNEMONIC;
- }
- //
- // Get the correct vector value based on whether it is single or double
- // precision.
- //
- Vector = (Instruction & ARM_SIMD_LOAD_STORE_VECTOR_MASK) >>
- ARM_SIMD_LOAD_STORE_VECTOR_SHIFT;
- if ((Instruction & ARM_SIMD_LOAD_STORE_DOUBLE) != 0) {
- if ((Instruction & ARM_SIMD_LOAD_STORE_VECTOR_BIT) != 0) {
- Vector |= (1 << 4);
- }
- VectorTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- } else {
- Vector <<= 1;
- if ((Instruction & ARM_SIMD_LOAD_STORE_VECTOR_BIT) != 0) {
- Vector |= 1;
- }
- VectorTypeString = ARM_FLOATING_POINT_SINGLE_PRECISION_VECTOR;
- }
- //
- // Get the immediate offset and its sign.
- //
- Offset = (Instruction & ARM_SIMD_LOAD_STORE_IMMEDIATE8_MASK) >>
- ARM_SIMD_LOAD_STORE_IMMEDIATE8_SHIFT;
- Offset <<= 2;
- if ((Instruction & ARM_SIMD_LOAD_STORE_ADD_BIT) != 0) {
- Sign = '+';
- } else {
- Sign = '-';
- }
- sprintf(Context->Mnemonic,
- "%s%s",
- BaseMnemonic,
- ARM_FLOATING_POINT_REGISTER);
- sprintf(Context->Operand1, "%s%d", VectorTypeString, Vector);
- if (Offset == 0) {
- sprintf(Context->Operand2, "[%s]", DbgArmRegisterNames[Register]);
- } else {
- sprintf(Context->Operand2,
- "[%s, #%c%d]",
- DbgArmRegisterNames[Register],
- Sign,
- Offset);
- }
- return;
- }
- VOID
- DbgpArmDecodeSimdLoadStoreMultiple (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an SIMD and floating point multiple register
- load/store instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Instruction;
- PSTR MnemonicSuffix;
- ULONG Operation;
- PSTR PreConditionMnemonicSuffix;
- BOOL PushPop;
- ULONG Register;
- ULONG Vector;
- ULONG VectorCount;
- PSTR VectorListString;
- ULONG VectorListStringSize;
- PSTR VectorTypeString;
- PSTR WriteBack;
- Instruction = Context->Instruction;
- Operation = Instruction & ARM_SIMD_LOAD_STORE_OP_MASK;
- Register = (Instruction & ARM_SIMD_LOAD_STORE_REGISTER_MASK) >>
- ARM_SIMD_LOAD_STORE_REGISTER_SHIFT;
- //
- // Determine if this is a load, store, push or pop.
- //
- PushPop = FALSE;
- if ((Register == ARM_STACK_REGISTER) &&
- ((Operation == ARM_SIMD_LOAD_STORE_OP_VPOP) ||
- (Operation == ARM_SIMD_LOAD_STORE_OP_VPUSH))) {
- if ((Instruction & ARM_LOAD_BIT) != 0) {
- BaseMnemonic = ARM_VPOP_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VPUSH_MNEMONIC;
- }
- PreConditionMnemonicSuffix = "";
- MnemonicSuffix = "";
- PushPop = TRUE;
- } else {
- if ((Instruction & ARM_LOAD_BIT) != 0) {
- BaseMnemonic = ARM_VLD_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VST_MNEMONIC;
- }
- PreConditionMnemonicSuffix = ARM_FLOATING_POINT_MULTIPLE;
- MnemonicSuffix = DbgpArmGetLoadStoreTypeString(Instruction);
- }
- sprintf(Context->Mnemonic,
- "%s%s%s",
- BaseMnemonic,
- PreConditionMnemonicSuffix,
- MnemonicSuffix);
- //
- // Gather the starting vector and the vector count.
- //
- VectorCount = (Instruction & ARM_SIMD_LOAD_STORE_IMMEDIATE8_MASK) >>
- ARM_SIMD_LOAD_STORE_IMMEDIATE8_SHIFT;
- Vector = (Instruction & ARM_SIMD_LOAD_STORE_VECTOR_MASK) >>
- ARM_SIMD_LOAD_STORE_VECTOR_SHIFT;
- if ((Instruction & ARM_SIMD_LOAD_STORE_DOUBLE) != 0) {
- if ((Instruction & ARM_SIMD_LOAD_STORE_VECTOR_BIT) != 0) {
- Vector |= (1 << 4);
- }
- VectorCount >>= 1;
- VectorTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- } else {
- Vector <<= 1;
- if ((Instruction & ARM_SIMD_LOAD_STORE_VECTOR_BIT) != 0) {
- Vector |= 1;
- }
- VectorTypeString = ARM_FLOATING_POINT_SINGLE_PRECISION_VECTOR;
- }
- //
- // Write the register (the first operand) nad add the ! if the operation
- // does a write back. Push/pop operations are always write back.
- //
- if (PushPop == FALSE) {
- WriteBack = "";
- if ((Instruction & ARM_WRITE_BACK_BIT) != 0) {
- WriteBack = "!";
- }
- sprintf(Context->Operand1,
- "%s%s",
- DbgArmRegisterNames[Register],
- WriteBack);
- VectorListString = Context->Operand2;
- VectorListStringSize = sizeof(Context->Operand2);
- } else {
- VectorListString = Context->Operand1;
- VectorListStringSize = sizeof(Context->Operand1);
- }
- //
- // Now print the vector list.
- //
- DbgpArmPrintVectorList(VectorListString,
- VectorListStringSize,
- Vector,
- VectorCount,
- 1,
- VectorTypeString,
- 0,
- 0);
- return;
- }
- VOID
- DbgpArmDecodeSimdElementLoadAllLanes (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an SIMD element load to all lanes instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR AlignString;
- PSTR ElementSuffix;
- ULONG Instruction;
- ULONG Rm;
- ULONG Rn;
- PSTR SizeTypeSuffix;
- PSTR SizeValueSuffix;
- ULONG Vector;
- ULONG VectorCount;
- ULONG VectorIncrement;
- PSTR WriteBack;
- Instruction = Context->Instruction;
- Rm = (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_RM_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_RM_SHIFT;
- Rn = (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_RN_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_RN_SHIFT;
- Vector = (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_VECTOR_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_VECTOR_SHIFT;
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_VECTOR_BIT) != 0) {
- Vector |= (1 << 4);
- }
- //
- // Determine the number of elements in the structure being loaded and the
- // number and spacing of the vectors. Also collect the alignment string,
- // which depends on the size and the element count.
- //
- VectorIncrement = 1;
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_ALL_LANES_TWO_BIT) != 0) {
- VectorIncrement = 2;
- }
- AlignString = "";
- ElementSuffix = "";
- VectorCount = 0;
- switch (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_ELEMENT_MASK) {
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_ELEMENT_1:
- ElementSuffix = ARM_SIMD_ELEMENT_LOAD_STORE_1_ELEMENT_SUFFIX;
- VectorCount = 1;
- VectorIncrement = 1;
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_ALL_LANES_TWO_BIT) != 0) {
- VectorCount = 2;
- }
- switch (Instruction & ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_MASK) {
- case ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_16:
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_ALL_LANES_ALIGN) != 0) {
- AlignString = ARM_SIMD_ALIGN_16;
- }
- break;
- case ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_32:
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_ALL_LANES_ALIGN) != 0) {
- AlignString = ARM_SIMD_ALIGN_32;
- }
- break;
- default:
- break;
- }
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_ELEMENT_2:
- ElementSuffix = ARM_SIMD_ELEMENT_LOAD_STORE_2_ELEMENT_SUFFIX;
- VectorCount = 2;
- switch (Instruction & ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_MASK) {
- case ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_8:
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_ALL_LANES_ALIGN) != 0) {
- AlignString = ARM_SIMD_ALIGN_16;
- }
- break;
- case ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_16:
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_ALL_LANES_ALIGN) != 0) {
- AlignString = ARM_SIMD_ALIGN_32;
- }
- break;
- case ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_32:
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_ALL_LANES_ALIGN) != 0) {
- AlignString = ARM_SIMD_ALIGN_64;
- }
- break;
- default:
- break;
- }
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_ELEMENT_3:
- ElementSuffix = ARM_SIMD_ELEMENT_LOAD_STORE_3_ELEMENT_SUFFIX;
- VectorCount = 3;
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_ELEMENT_4:
- ElementSuffix = ARM_SIMD_ELEMENT_LOAD_STORE_4_ELEMENT_SUFFIX;
- VectorCount = 4;
- switch (Instruction & ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_MASK) {
- case ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_8:
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_ALL_LANES_ALIGN) != 0) {
- AlignString = ARM_SIMD_ALIGN_32;
- }
- break;
- case ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_16:
- case ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_32:
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_ALL_LANES_ALIGN) != 0) {
- AlignString = ARM_SIMD_ALIGN_64;
- }
- break;
- default:
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_ALL_LANES_ALIGN) != 0) {
- AlignString = ARM_SIMD_ALIGN_128;
- }
- break;
- }
- break;
- //
- // This should never hit as all values are accounted for above.
- //
- default:
- break;
- }
- //
- // Get the size suffix.
- //
- SizeValueSuffix = "";
- SizeTypeSuffix = ARM_SIMD_DATA_DEFAULT;
- switch (Instruction & ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_MASK) {
- case ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_8:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_8;
- break;
- case ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_16:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_16;
- break;
- case ARM_SIMD_ELEMENT_LOAD_ALL_LANES_SIZE_32:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- break;
- default:
- SizeTypeSuffix = "";
- break;
- }
- sprintf(Context->Mnemonic, "%s%s", ARM_VLD_MNEMONIC, ElementSuffix);
- sprintf(Context->PostConditionMnemonicSuffix,
- "%s%s",
- SizeTypeSuffix,
- SizeValueSuffix);
- //
- // Assemble the vector list.
- //
- DbgpArmPrintVectorList(Context->Operand1,
- sizeof(Context->Operand1),
- Vector,
- VectorCount,
- VectorIncrement,
- ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR,
- 0,
- DBG_ARM_VECTOR_LIST_FLAG_INDEX |
- DBG_ARM_VECTOR_LIST_FLAG_ALL_LANES);
- //
- // Assemble the register operands.
- //
- WriteBack = "";
- if (Rm == ARM_STACK_REGISTER) {
- WriteBack = "!";
- }
- sprintf(Context->Operand2,
- "[%s%s]%s",
- DbgArmRegisterNames[Rn],
- AlignString,
- WriteBack);
- if ((Rm != ARM_STACK_REGISTER) && (Rm != ARM_PC_REGISTER)) {
- strcpy(Context->Operand3, DbgArmRegisterNames[Rm]);
- }
- return;
- }
- VOID
- DbgpArmDecodeSimdElementLoadStoreSingle (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an SIMD element load/store from/to a single structure.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR AlignString;
- ULONG AlignValue;
- PSTR BaseMnemonic;
- PSTR ElementSuffix;
- ULONG Instruction;
- ULONG Rm;
- ULONG Rn;
- PSTR SizeTypeSuffix;
- PSTR SizeValueSuffix;
- ULONG Vector;
- ULONG VectorCount;
- ULONG VectorIncrement;
- ULONG VectorIndex;
- PSTR WriteBack;
- AlignString = "";
- ElementSuffix = "";
- SizeValueSuffix = "";
- SizeTypeSuffix = ARM_SIMD_DATA_DEFAULT;
- //
- // The base mnemonic is either vector load or vector store.
- //
- Instruction = Context->Instruction;
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_BIT) != 0) {
- BaseMnemonic = ARM_VLD_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VST_MNEMONIC;
- }
- Rm = (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_RM_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_RM_SHIFT;
- Rn = (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_RN_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_RN_SHIFT;
- Vector = (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_VECTOR_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_VECTOR_SHIFT;
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_VECTOR_BIT) != 0) {
- Vector |= (1 << 4);
- }
- //
- // Get the size suffix, vector index, vector increment, and alignment value.
- //
- AlignValue = 0;
- VectorIndex = 0;
- VectorIncrement = 1;
- switch (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_MASK) {
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_8:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_8;
- VectorIndex = (Instruction &
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_8_INDEX_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_8_INDEX_SHIFT;
- AlignValue = (Instruction &
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_8_ALIGN_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_8_ALIGN_SHIFT;
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_16:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_16;
- VectorIndex = (Instruction &
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_16_INDEX_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_16_INDEX_SHIFT;
- if ((Instruction &
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_16_INCREMENT) != 0) {
- VectorIncrement = 2;
- }
- AlignValue = (Instruction &
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_16_ALIGN_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_16_ALIGN_SHIFT;
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_32:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- VectorIndex = (Instruction &
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_32_INDEX_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_32_INDEX_SHIFT;
- if ((Instruction &
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_32_INCREMENT) != 0) {
- VectorIncrement = 2;
- }
- AlignValue = (Instruction &
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_32_ALIGN_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_32_ALIGN_SHIFT;
- break;
- default:
- SizeTypeSuffix = "";
- break;
- }
- //
- // Determine the number of elements being loaded/stored and the alignment
- // string.
- //
- VectorCount = 0;
- switch (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_ELEMENT_MASK) {
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_ELEMENT_1:
- ElementSuffix = ARM_SIMD_ELEMENT_LOAD_STORE_1_ELEMENT_SUFFIX;
- VectorCount = 1;
- switch (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_MASK) {
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_16:
- if (AlignValue != 0) {
- AlignString = ARM_SIMD_ALIGN_16;
- }
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_32:
- if (AlignValue != 0) {
- AlignString = ARM_SIMD_ALIGN_32;
- }
- break;
- default:
- break;
- }
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_ELEMENT_2:
- ElementSuffix = ARM_SIMD_ELEMENT_LOAD_STORE_2_ELEMENT_SUFFIX;
- VectorCount = 2;
- switch (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_MASK) {
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_8:
- if (AlignValue != 0) {
- AlignString = ARM_SIMD_ALIGN_16;
- }
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_16:
- if (AlignValue != 0) {
- AlignString = ARM_SIMD_ALIGN_32;
- }
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_32:
- if (AlignValue != 0) {
- AlignString = ARM_SIMD_ALIGN_64;
- }
- break;
- default:
- break;
- }
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_ELEMENT_3:
- ElementSuffix = ARM_SIMD_ELEMENT_LOAD_STORE_3_ELEMENT_SUFFIX;
- VectorCount = 3;
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_ELEMENT_4:
- ElementSuffix = ARM_SIMD_ELEMENT_LOAD_STORE_4_ELEMENT_SUFFIX;
- VectorCount = 4;
- switch (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_MASK) {
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_8:
- if (AlignValue != 0) {
- AlignString = ARM_SIMD_ALIGN_32;
- }
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_16:
- if (AlignValue != 0) {
- AlignString = ARM_SIMD_ALIGN_64;
- }
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_32:
- if (AlignValue ==
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_32_ALIGN_64) {
- AlignString = ARM_SIMD_ALIGN_64;
- } else if (AlignValue ==
- ARM_SIMD_ELEMENT_LOAD_STORE_SINGLE_SIZE_32_ALIGN_128) {
- AlignString = ARM_SIMD_ALIGN_128;
- }
- break;
- default:
- break;
- }
- break;
- //
- // This should never hit as all values are accounted for above.
- //
- default:
- break;
- }
- sprintf(Context->Mnemonic, "%s%s", BaseMnemonic, ElementSuffix);
- sprintf(Context->PostConditionMnemonicSuffix,
- "%s%s",
- SizeTypeSuffix,
- SizeValueSuffix);
- //
- // Assemble the vector list.
- //
- DbgpArmPrintVectorList(Context->Operand1,
- sizeof(Context->Operand1),
- Vector,
- VectorCount,
- VectorIncrement,
- ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR,
- VectorIndex,
- DBG_ARM_VECTOR_LIST_FLAG_INDEX);
- //
- // Assemble the register operands.
- //
- WriteBack = "";
- if (Rm == ARM_STACK_REGISTER) {
- WriteBack = "!";
- }
- sprintf(Context->Operand2,
- "[%s%s]%s",
- DbgArmRegisterNames[Rn],
- AlignString,
- WriteBack);
- if ((Rm != ARM_STACK_REGISTER) && (Rm != ARM_PC_REGISTER)) {
- strcpy(Context->Operand3, DbgArmRegisterNames[Rm]);
- }
- return;
- }
- VOID
- DbgpArmDecodeSimdElementLoadStoreMultiple (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an SIMD element load/store from/to multiple structures.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR AlignString;
- PSTR BaseMnemonic;
- PSTR ElementSuffix;
- ULONG Instruction;
- ULONG Rm;
- ULONG Rn;
- PSTR SizeTypeSuffix;
- PSTR SizeValueSuffix;
- ULONG Type;
- ULONG Vector;
- ULONG VectorCount;
- ULONG VectorIncrement;
- PSTR WriteBack;
- //
- // The base mnemonic is either vector load or vector store.
- //
- Instruction = Context->Instruction;
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_BIT) != 0) {
- BaseMnemonic = ARM_VLD_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VST_MNEMONIC;
- }
- Rm = (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_RM_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_RM_SHIFT;
- Rn = (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_RN_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_RN_SHIFT;
- Vector = (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_VECTOR_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_VECTOR_SHIFT;
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_VECTOR_BIT) != 0) {
- Vector |= (1 << 4);
- }
- //
- // Get the size suffix.
- //
- SizeTypeSuffix = ARM_SIMD_DATA_DEFAULT;
- SizeValueSuffix = "";
- VectorIncrement = 1;
- switch (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_MULTIPLE_SIZE_MASK) {
- case ARM_SIMD_ELEMENT_LOAD_STORE_MULTIPLE_SIZE_8:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_8;
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_MULTIPLE_SIZE_16:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_16;
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_MULTIPLE_SIZE_32:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_MULTIPLE_SIZE_64:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_64;
- break;
- default:
- break;
- }
- //
- // Get the alignment string.
- //
- AlignString = "";
- switch (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_MULTIPLE_ALIGN_MASK) {
- case ARM_SIMD_ELEMENT_LOAD_STORE_MULTIPLE_ALIGN_64:
- AlignString = ARM_SIMD_ALIGN_64;
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_MULTIPLE_ALIGN_128:
- AlignString = ARM_SIMD_ALIGN_128;
- break;
- case ARM_SIMD_ELEMENT_LOAD_STORE_MULTIPLE_ALIGN_256:
- AlignString = ARM_SIMD_ALIGN_256;
- break;
- default:
- break;
- }
- //
- // Determine the number of elements being loaded/stored, the vector count,
- // vector increment based on the type field.
- //
- VectorIncrement = 1;
- if ((Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_MULTIPLE_INCREMENT) != 0) {
- VectorIncrement = 2;
- }
- Type = (Instruction & ARM_SIMD_ELEMENT_LOAD_STORE_MULTIPLE_TYPE_MASK) >>
- ARM_SIMD_ELEMENT_LOAD_STORE_MULTIPLE_TYPE_SHIFT;
- ElementSuffix = DbgArmSimdElementLoadStoreMultipleElementSuffix[Type];
- VectorCount = DbgArmSimdElementLoadStoreMultipleVectorCount[Type];
- sprintf(Context->Mnemonic, "%s%s", BaseMnemonic, ElementSuffix);
- sprintf(Context->PostConditionMnemonicSuffix,
- "%s%s",
- SizeTypeSuffix,
- SizeValueSuffix);
- //
- // Assemble the vector list.
- //
- DbgpArmPrintVectorList(Context->Operand1,
- sizeof(Context->Operand1),
- Vector,
- VectorCount,
- VectorIncrement,
- ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR,
- 0,
- 0);
- //
- // Assemble the register operands.
- //
- WriteBack = "";
- if (Rm == ARM_STACK_REGISTER) {
- WriteBack = "!";
- }
- sprintf(Context->Operand2,
- "[%s%s]%s",
- DbgArmRegisterNames[Rn],
- AlignString,
- WriteBack);
- if ((Rm != ARM_STACK_REGISTER) && (Rm != ARM_PC_REGISTER)) {
- strcpy(Context->Operand3, DbgArmRegisterNames[Rm]);
- }
- return;
- }
- VOID
- DbgpArmDecodeSimdThreeRegistersSameLength (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an SIMD data processing instructions with three
- registers of the same length.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- BOOL FloatSize;
- ULONG Instruction;
- BOOL IntegerSize;
- BOOL NoSizeSuffix;
- BOOL PolynomialSize;
- BOOL SignedSize;
- PSTR SizeTypeSuffix;
- PSTR SizeValueSuffix;
- BOOL TwoVectors;
- ULONG VectorD;
- PSTR VectorDString;
- ULONG VectorM;
- PSTR VectorMString;
- ULONG VectorN;
- PSTR VectorNString;
- PSTR VectorTypeString;
- FloatSize = FALSE;
- IntegerSize = FALSE;
- NoSizeSuffix = FALSE;
- PolynomialSize = FALSE;
- SignedSize = TRUE;
- TwoVectors = FALSE;
- Instruction = Context->Instruction;
- VectorDString = Context->Operand1;
- VectorD = (Instruction & ARM_SIMD_DATA_PROCESSING_VD_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VD_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VD_BIT) != 0) {
- VectorD |= (1 << 4);
- }
- VectorMString = Context->Operand3;
- VectorM = (Instruction & ARM_SIMD_DATA_PROCESSING_VM_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VM_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VM_BIT) != 0) {
- VectorM |= (1 << 4);
- }
- VectorNString = Context->Operand2;
- VectorN = (Instruction & ARM_SIMD_DATA_PROCESSING_VN_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VN_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VN_BIT) != 0) {
- VectorN |= (1 << 4);
- }
- VectorTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_QUADWORD) != 0) {
- VectorTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- }
- //
- // Determine the base mnemonic. Some instructions ignore the size encodings
- // and others have integer or float encodings rather than the default
- // signed/unsigned. Take note so that the correct size suffix can be
- // calculated.
- //
- BaseMnemonic = NULL;
- switch (Instruction & ARM_SIMD_DATA_PROCESSING_3_SAME_OPERATION_MASK) {
- case ARM_SIMD_VHADD_MASK:
- BaseMnemonic = ARM_VHADD_MNEMONIC;
- break;
- case ARM_SIMD_VQADD_MASK:
- BaseMnemonic = ARM_VQADD_MNEMONIC;
- break;
- case ARM_SIMD_VRHADD_MASK:
- BaseMnemonic = ARM_VRHADD_MNEMONIC;
- break;
- case ARM_SIMD_BITWISE_MASK:
- switch (Instruction & ARM_SIMD_BITWISE_OP_MASK) {
- case ARM_SIMD_BITWISE_VAND_VALUE:
- BaseMnemonic = ARM_VAND_MNEMONIC;
- break;
- case ARM_SIMD_BITWISE_VBIC_VALUE:
- BaseMnemonic = ARM_VBIC_MNEMONIC;
- break;
- case ARM_SIMD_BITWISE_VORR_VALUE:
- if (VectorM == VectorN) {
- BaseMnemonic = ARM_VMOV_MNEMONIC;
- TwoVectors = TRUE;
- } else {
- BaseMnemonic = ARM_VORR_MNEMONIC;
- }
- break;
- case ARM_SIMD_BITWISE_VORN_VALUE:
- BaseMnemonic = ARM_VORN_MNEMONIC;
- break;
- case ARM_SIMD_BITWISE_VEOR_VALUE:
- BaseMnemonic = ARM_VEOR_MNEMONIC;
- break;
- case ARM_SIMD_BITWISE_VBSL_VALUE:
- BaseMnemonic = ARM_VBSL_MNEMONIC;
- break;
- case ARM_SIMD_BITWISE_VBIT_VALUE:
- BaseMnemonic = ARM_VBIT_MNEMONIC;
- break;
- case ARM_SIMD_BITWISE_VBIF_VALUE:
- BaseMnemonic = ARM_VBIF_MNEMONIC;
- break;
- default:
- break;
- }
- NoSizeSuffix = TRUE;
- break;
- case ARM_SIMD_VHSUB_MASK:
- BaseMnemonic = ARM_VHSUB_MNEMONIC;
- break;
- case ARM_SIMD_VQSUB_MASK:
- BaseMnemonic = ARM_VQSUB_MNEMONIC;
- break;
- case ARM_SIMD_VCGT_MASK:
- BaseMnemonic = ARM_VCGT_MNEMONIC;
- break;
- case ARM_SIMD_VCGE_MASK:
- BaseMnemonic = ARM_VCGE_MNEMONIC;
- break;
- case ARM_SIMD_VSHL_REG_MASK:
- BaseMnemonic = ARM_VSHL_MNEMONIC;
- VectorMString = Context->Operand2;
- VectorNString = Context->Operand3;
- break;
- case ARM_SIMD_VQSHL_REG_MASK:
- BaseMnemonic = ARM_VQSHL_MNEMONIC;
- VectorMString = Context->Operand2;
- VectorNString = Context->Operand3;
- break;
- case ARM_SIMD_VRSHL_MASK:
- BaseMnemonic = ARM_VRSHL_MNEMONIC;
- VectorMString = Context->Operand2;
- VectorNString = Context->Operand3;
- break;
- case ARM_SIMD_VQRSHL_MASK:
- BaseMnemonic = ARM_VQRSHL_MNEMONIC;
- VectorMString = Context->Operand2;
- VectorNString = Context->Operand3;
- break;
- case ARM_SIMD_VMAX_INT_MASK:
- BaseMnemonic = ARM_VMAX_MNEMONIC;
- break;
- case ARM_SIMD_VMIN_INT_MASK:
- BaseMnemonic = ARM_VMIN_MNEMONIC;
- break;
- case ARM_SIMD_VABD_MASK:
- BaseMnemonic = ARM_VABD_MNEMONIC;
- break;
- case ARM_SIMD_VABA_MASK:
- BaseMnemonic = ARM_VABA_MNEMONIC;
- break;
- case ARM_SIMD_VADD_INT_MASK:
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_UNSIGNED) != 0) {
- BaseMnemonic = ARM_VSUB_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VADD_MNEMONIC;
- }
- IntegerSize = TRUE;
- break;
- case ARM_SIMD_VTST_MASK:
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_UNSIGNED) != 0) {
- BaseMnemonic = ARM_VCEQ_MNEMONIC;
- IntegerSize = TRUE;
- } else {
- BaseMnemonic = ARM_VTST_MNEMONIC;
- SignedSize = FALSE;
- }
- break;
- case ARM_SIMD_VMLA_MASK:
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_UNSIGNED) != 0) {
- BaseMnemonic = ARM_VMLS_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VMLA_MNEMONIC;
- }
- IntegerSize = TRUE;
- break;
- case ARM_SIMD_VMUL_MASK:
- BaseMnemonic = ARM_VMUL_MNEMONIC;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_UNSIGNED) != 0) {
- PolynomialSize = TRUE;
- }
- break;
- case ARM_SIMD_VPMAX_INT_MASK:
- BaseMnemonic = ARM_VPMAX_MNEMONIC;
- break;
- case ARM_SIMD_VPMIN_INT_MASK:
- BaseMnemonic = ARM_VPMIN_MNEMONIC;
- break;
- case ARM_SIMD_VQDMULH_MASK:
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_UNSIGNED) != 0) {
- BaseMnemonic = ARM_VQRDMULH_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VQDMULH_MNEMONIC;
- }
- Instruction &= ~ARM_SIMD_DATA_PROCESSING_UNSIGNED;
- break;
- case ARM_SIMD_VPADD_INT_MASK:
- BaseMnemonic = ARM_VPADD_MNEMONIC;
- IntegerSize = TRUE;
- break;
- case ARM_SIMD_VFMA_MASK:
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VFM_SUBTRACT) != 0) {
- BaseMnemonic = ARM_VFMS_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VFMA_MNEMONIC;
- }
- FloatSize = TRUE;
- break;
- case ARM_SIMD_FP_MATH_MASK:
- case ARM_SIMD_FP_MATH_MASK | ARM_SIMD_FP_MULT:
- switch (Instruction & ARM_SIMD_FP_MATH_OP_MASK) {
- case ARM_SIMD_FP_MATH_VADD_VALUE:
- BaseMnemonic = ARM_VADD_MNEMONIC;
- break;
- case ARM_SIMD_FP_MATH_VSUB_VALUE:
- BaseMnemonic = ARM_VSUB_MNEMONIC;
- break;
- case ARM_SIMD_FP_MATH_VPADD_VALUE:
- BaseMnemonic = ARM_VPADD_MNEMONIC;
- break;
- case ARM_SIMD_FP_MATH_VABD_VALUE:
- BaseMnemonic = ARM_VABD_MNEMONIC;
- break;
- case ARM_SIMD_FP_MATH_VMLA_VALUE:
- BaseMnemonic = ARM_VMLA_MNEMONIC;
- break;
- case ARM_SIMD_FP_MATH_VMLS_VALUE:
- BaseMnemonic = ARM_VMLS_MNEMONIC;
- break;
- case ARM_SIMD_FP_MATH_VMUL_VALUE:
- BaseMnemonic = ARM_VMUL_MNEMONIC;
- break;
- default:
- break;
- }
- FloatSize = TRUE;
- break;
- case ARM_SIMD_COMPARE_MASK:
- case ARM_SIMD_COMPARE_MASK | ARM_SIMD_ABSOLUTE:
- switch (Instruction & ARM_SIMD_COMPARE_OP_MASK) {
- case ARM_SIMD_COMPARE_VCEQ_VALUE:
- BaseMnemonic = ARM_VCEQ_MNEMONIC;
- break;
- case ARM_SIMD_COMPARE_VCGE_VALUE:
- BaseMnemonic = ARM_VCGE_MNEMONIC;
- break;
- case ARM_SIMD_COMPARE_VCGT_VALUE:
- BaseMnemonic = ARM_VCGT_MNEMONIC;
- break;
- case ARM_SIMD_COMPARE_VACGE_VALUE:
- BaseMnemonic = ARM_VACGE_MNEMONIC;
- break;
- case ARM_SIMD_COMPARE_VACGT_VALUE:
- BaseMnemonic = ARM_VACGT_MNEMONIC;
- break;
- default:
- break;
- }
- FloatSize = TRUE;
- break;
- case ARM_SIMD_MIN_MAX_FLOAT_MASK:
- switch (Instruction & ARM_SIMD_MIN_MAX_FLOAT_OP_MASK) {
- case ARM_SIMD_MIN_MAX_FLOAT_VMAX_VALUE:
- BaseMnemonic = ARM_VMAX_MNEMONIC;
- break;
- case ARM_SIMD_MIN_MAX_FLOAT_VMIN_VALUE:
- BaseMnemonic = ARM_VMIN_MNEMONIC;
- break;
- case ARM_SIMD_MIN_MAX_FLOAT_VPMAX_VALUE:
- BaseMnemonic = ARM_VPMAX_MNEMONIC;
- break;
- case ARM_SIMD_MIN_MAX_FLOAT_VPMIN_VALUE:
- BaseMnemonic = ARM_VPMIN_MNEMONIC;
- break;
- default:
- break;
- }
- FloatSize = TRUE;
- break;
- case ARM_SIMD_RECIPROCOL_MASK:
- switch (Instruction & ARM_SIMD_RECIPROCOL_OP_MASK) {
- case ARM_SIMD_RECIPROCOL_VRECPS_VALUE:
- BaseMnemonic = ARM_VRECPS_MNEMONIC;
- break;
- case ARM_SIMD_RECIPROCOL_VRSQRTS_VALUE:
- BaseMnemonic = ARM_VRSQRTS_MNEMONIC;
- break;
- default:
- break;
- }
- FloatSize = TRUE;
- break;
- default:
- break;
- }
- if (BaseMnemonic == NULL) {
- DbgpArmDecodeUndefined(Context);
- return;
- }
- //
- // Parse the instruction assuming it uses the default size suffix.
- //
- SizeTypeSuffix = "";
- SizeValueSuffix = "";
- if (NoSizeSuffix == FALSE) {
- if (FloatSize != FALSE) {
- SizeTypeSuffix = ARM_SIMD_DATA_FLOAT;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- } else if (IntegerSize != FALSE) {
- SizeTypeSuffix = ARM_SIMD_DATA_INTEGER;
- } else if (PolynomialSize != FALSE) {
- SizeTypeSuffix = ARM_SIMD_DATA_POLYNOMIAL;
- } else if (SignedSize == FALSE) {
- SizeTypeSuffix = ARM_SIMD_DATA_DEFAULT;
- } else if ((Instruction & ARM_SIMD_DATA_PROCESSING_UNSIGNED) != 0) {
- SizeTypeSuffix = ARM_SIMD_DATA_UNSIGNED;
- } else {
- SizeTypeSuffix = ARM_SIMD_DATA_SIGNED;
- }
- }
- if ((NoSizeSuffix == FALSE) && (FloatSize == FALSE)) {
- switch (Instruction & ARM_SIMD_DATA_PROCESSING_3_SAME_SIZE_MASK) {
- case ARM_SIMD_DATA_PROCESSING_3_SAME_SIZE_8:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_8;
- break;
- case ARM_SIMD_DATA_PROCESSING_3_SAME_SIZE_16:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_16;
- break;
- case ARM_SIMD_DATA_PROCESSING_3_SAME_SIZE_32:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- break;
- case ARM_SIMD_DATA_PROCESSING_3_SAME_SIZE_64:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_64;
- break;
- default:
- break;
- }
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- sprintf(Context->PostConditionMnemonicSuffix,
- "%s%s",
- SizeTypeSuffix,
- SizeValueSuffix);
- sprintf(VectorDString, "%s%d", VectorTypeString, VectorD);
- sprintf(VectorNString, "%s%d", VectorTypeString, VectorN);
- if (TwoVectors == FALSE) {
- sprintf(VectorMString, "%s%d", VectorTypeString, VectorM);
- }
- return;
- }
- VOID
- DbgpArmDecodeSimdOneRegister (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an SIMD data processing instrution that uses one
- register and a modified immediate value.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Cmode;
- ARM_IMMEDIATE_FLOAT Float;
- ULONGLONG Immediate;
- ULONG Immediate8;
- ULONG Instruction;
- BOOL PrintFloat;
- PSTR SizeTypeSuffix;
- PSTR SizeValueSuffix;
- ULONG Vector;
- PSTR VectorTypeString;
- PrintFloat = FALSE;
- Float.Immediate = 0;
- Instruction = Context->Instruction;
- //
- // Decode the immediate value and the size suffix using the cmode value and
- // the op bit.
- //
- Immediate8 = ARM_SIMD_BUILD_IMMEDIATE8(Instruction);
- Cmode = (Instruction & ARM_SIMD_DATA_PROCESSING_1_REGISTER_CMODE_MASK) >>
- ARM_SIMD_DATA_PROCESSING_1_REGISTER_CMODE_SHIFT;
- switch (Cmode & ARM_SIMD_CMODE_TYPE_MASK) {
- case ARM_SIMD_CMODE_TYPE_I32_NO_SHIFT:
- SizeTypeSuffix = ARM_SIMD_DATA_INTEGER;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- Immediate = Immediate8;
- break;
- case ARM_SIMD_CMODE_TYPE_I32_SHIFT_8:
- SizeTypeSuffix = ARM_SIMD_DATA_INTEGER;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- Immediate = Immediate8 << 8;
- break;
- case ARM_SIMD_CMODE_TYPE_I32_SHIFT_16:
- SizeTypeSuffix = ARM_SIMD_DATA_INTEGER;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- Immediate = Immediate8 << 16;
- break;
- case ARM_SIMD_CMODE_TYPE_I32_SHIFT_24:
- SizeTypeSuffix = ARM_SIMD_DATA_INTEGER;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- Immediate = Immediate8 << 24;
- break;
- case ARM_SIMD_CMODE_TYPE_I16_NO_SHIFT:
- SizeTypeSuffix = ARM_SIMD_DATA_INTEGER;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_16;
- Immediate = Immediate8;
- break;
- case ARM_SIMD_CMODE_TYPE_I16_SHIFT_8:
- SizeTypeSuffix = ARM_SIMD_DATA_INTEGER;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_16;
- Immediate = Immediate8 << 8;
- break;
- case ARM_SIMD_CMODE_TYPE_I32_SHIFT_ONES:
- SizeTypeSuffix = ARM_SIMD_DATA_INTEGER;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- if ((Cmode & ARM_SIMD_CMODE_SHIFT_ONES_16) != 0) {
- Immediate = Immediate8 << 16;
- Immediate |= 0xFFFF;
- } else {
- Immediate = Immediate8 << 8;
- Immediate |= 0xFF;
- }
- break;
- default:
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_1_REGISTER_OP_BIT) != 0) {
- if ((Cmode & ARM_SIMD_CMODE_UNDEFINED) != 0) {
- DbgpArmDecodeUndefined(Context);
- return;
- }
- SizeTypeSuffix = ARM_SIMD_DATA_INTEGER;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_64;
- Immediate = ARM_SIMD_BUILD_IMMEDIATE64(Instruction);
- } else {
- if ((Cmode & ARM_SIMD_CMODE_FLOAT_32) != 0) {
- SizeTypeSuffix = ARM_SIMD_DATA_FLOAT;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- Float.Immediate = ARM_SIMD_BUILD_IMMEDIATE32(Instruction);
- PrintFloat = TRUE;
- } else {
- SizeTypeSuffix = ARM_SIMD_DATA_INTEGER;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_8;
- Immediate = Immediate8;
- }
- }
- break;
- }
- //
- // Get the mnemonic based on the cmode value and the op bit.
- //
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_1_REGISTER_OP_BIT) == 0) {
- //
- // For all modes less than 12, the even modes are vmov and the odds are
- // vorr.
- //
- if ((Cmode < ARM_SIMD_CMODE_NO_OP_VORR_MAX) &&
- ((Cmode & ARM_SIMD_CMODE_NO_OP_VORR_BIT) != 0)) {
- BaseMnemonic = ARM_VORR_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VMOV_MNEMONIC;
- }
- } else {
- //
- // With the two exceptions of cmodes 14 and 15, the odd modes are vbic
- // and the even modes are vmvn.
- //
- if ((Cmode < ARM_SIMD_CMODE_OP_VBIC_MAX) &&
- ((Cmode & ARM_SIMD_CMODE_OP_VBIC_BIT) != 0)) {
- BaseMnemonic = ARM_VBIC_MNEMONIC;
- } else if (Cmode == ARM_SIMD_CMODE_OP_VMOV) {
- BaseMnemonic = ARM_VMOV_MNEMONIC;
- } else if (Cmode == ARM_SIMD_CMODE_OP_UNDEFINED) {
- DbgpArmDecodeUndefined(Context);
- return;
- } else {
- BaseMnemonic = ARM_VMVN_MNEMONIC;
- }
- }
- Vector = (Instruction & ARM_SIMD_DATA_PROCESSING_VD_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VD_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VD_BIT) != 0) {
- Vector |= (1 << 4);
- }
- VectorTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_QUADWORD) != 0) {
- VectorTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- sprintf(Context->PostConditionMnemonicSuffix,
- "%s%s",
- SizeTypeSuffix,
- SizeValueSuffix);
- sprintf(Context->Operand1, "%s%d", VectorTypeString, Vector);
- if (PrintFloat == FALSE) {
- sprintf(Context->Operand2, "#%lld ; 0x%lld", Immediate, Immediate);
- } else {
- sprintf(Context->Operand2,
- "#%d ; 0x%x %g",
- Immediate8,
- Float.Immediate,
- Float.Float);
- }
- return;
- }
- VOID
- DbgpArmDecodeSimdTwoRegistersWithShift (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an SIMD data instruction with two registers and a
- shift amount.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- PSTR DestinationSizeSuffix;
- PSTR DestinationTypeSuffix;
- ULONG Immediate;
- ULONG Immediate6;
- ULONG Instruction;
- PSTR SourceSizeSuffix;
- PSTR SourceTypeSuffix;
- ULONG VectorD;
- PSTR VectorDTypeString;
- ULONG VectorM;
- PSTR VectorMTypeString;
- SourceSizeSuffix = "";
- //
- // Gather the information that is shared by most of the two register shift
- // instructions.
- //
- Instruction = Context->Instruction;
- VectorD = (Instruction & ARM_SIMD_DATA_PROCESSING_VD_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VD_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VD_BIT) != 0) {
- VectorD |= (1 << 4);
- }
- VectorM = (Instruction & ARM_SIMD_DATA_PROCESSING_VM_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VM_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VM_BIT) != 0) {
- VectorM |= (1 << 4);
- }
- VectorDTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- VectorMTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_QUADWORD) != 0) {
- VectorDTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- }
- SourceTypeSuffix = "";
- DestinationTypeSuffix = ARM_SIMD_DATA_SIGNED;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_UNSIGNED) != 0) {
- DestinationTypeSuffix = ARM_SIMD_DATA_UNSIGNED;
- }
- DestinationSizeSuffix = "";
- Immediate6 = (Instruction & ARM_SIMD_2_REGISTER_SHIFT_IMMEDIATE6_MASK) >>
- ARM_SIMD_2_REGISTER_SHIFT_IMMEDIATE6_SHIFT;
- if ((Instruction & ARM_SIMD_2_REGISTER_SHIFT_64) == 0) {
- if ((Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_32) != 0) {
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_32;
- Immediate = 32;
- Immediate -= (Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_32_MASK);
- } else if ((Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_16) != 0) {
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_16;
- Immediate = 16;
- Immediate -= (Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_16_MASK);
- } else if ((Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_8) != 0) {
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_8;
- Immediate = 8;
- Immediate -= (Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_8_MASK);
- } else {
- DbgpArmDecodeUndefined(Context);
- return;
- }
- } else {
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_64;
- Immediate = 64 - Immediate6;
- }
- //
- // Determine the base mnemonic and override any of the size or type
- // information collected above.
- //
- BaseMnemonic = NULL;
- switch (Instruction & ARM_SIMD_2_REGISTER_SHIFT_OPERATION_MASK) {
- case ARM_SIMD_VSHR_MASK:
- BaseMnemonic = ARM_VSHR_MNEMONIC;
- break;
- case ARM_SIMD_VSRA_MASK:
- BaseMnemonic = ARM_VSRA_MNEMONIC;
- break;
- case ARM_SIMD_VRSHR_MASK:
- BaseMnemonic = ARM_VRSHR_MNEMONIC;
- break;
- case ARM_SIMD_VRSRA_MASK:
- BaseMnemonic = ARM_VRSRA_MNEMONIC;
- break;
- case ARM_SIMD_VSRI_MASK:
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_UNSIGNED) != 0) {
- BaseMnemonic = ARM_VSRI_MNEMONIC;
- }
- break;
- case ARM_SIMD_VSHL_MASK:
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_UNSIGNED) != 0) {
- BaseMnemonic = ARM_VSLI_MNEMONIC;
- DestinationTypeSuffix = "";
- } else {
- BaseMnemonic = ARM_VSHL_MNEMONIC;
- DestinationTypeSuffix = ARM_SIMD_DATA_INTEGER;
- }
- break;
- case ARM_SIMD_VQSHLU_MASK:
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_UNSIGNED) != 0) {
- BaseMnemonic = ARM_VQSHLU_MNEMONIC;
- DestinationTypeSuffix = ARM_SIMD_DATA_SIGNED;
- }
- break;
- case ARM_SIMD_VQSHL_IMM_MASK:
- BaseMnemonic = ARM_VQSHL_MNEMONIC;
- break;
- case ARM_SIMD_VSHRN_MASK:
- switch (Instruction & ARM_SIMD_VSHRN_OP_MASK) {
- case ARM_SIMD_VSHRN_OP_VALUE:
- BaseMnemonic = ARM_VSHRN_MNEMONIC;
- DestinationTypeSuffix = ARM_SIMD_DATA_INTEGER;
- break;
- case ARM_SIMD_VRSHRN_OP_VALUE:
- BaseMnemonic = ARM_VRSHRN_MNEMONIC;
- DestinationTypeSuffix = ARM_SIMD_DATA_INTEGER;
- break;
- case ARM_SIMD_VQSHRUN_OP_VALUE:
- BaseMnemonic = ARM_VQSHRUN_MNEMONIC;
- DestinationTypeSuffix = ARM_SIMD_DATA_SIGNED;
- break;
- case ARM_SIMD_VQRSHRUN_OP_VALUE:
- BaseMnemonic = ARM_VQRSHRUN_MNEMONIC;
- DestinationTypeSuffix = ARM_SIMD_DATA_SIGNED;
- break;
- default:
- break;
- }
- //
- // The size suffix is twice that of the normal encoding.
- //
- if ((Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_32) != 0) {
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_64;
- } else if ((Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_16) != 0) {
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_32;
- } else if ((Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_8) != 0) {
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_16;
- }
- VectorDTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- break;
- case ARM_SIMD_VQSHRN_MASK:
- switch (Instruction & ARM_SIMD_VQSHRN_OP_MASK) {
- case ARM_SIMD_VQSHRN_OP_VALUE:
- BaseMnemonic = ARM_VQSHRN_MNEMONIC;
- break;
- case ARM_SIMD_VQRSHRN_OP_VALUE:
- BaseMnemonic = ARM_VQRSHRN_MNEMONIC;
- break;
- default:
- break;
- }
- //
- // The size suffix is twice that of the normal encoding.
- //
- if ((Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_32) != 0) {
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_64;
- } else if ((Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_16) != 0) {
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_32;
- } else if ((Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_8) != 0) {
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_16;
- }
- VectorDTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- break;
- case ARM_SIMD_VSHLL_MASK:
- if ((Instruction & ARM_SIMD_VSHLL_OP_MASK) != ARM_SIMD_VSHLL_OP_VALUE) {
- break;
- }
- //
- // The size suffix is twice that of the normal encoding.
- //
- if ((Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_32) != 0) {
- Immediate = Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_32_MASK;
- } else if ((Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_16) != 0) {
- Immediate = Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_16_MASK;
- } else if ((Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_8) != 0) {
- Immediate = Immediate6 & ARM_SIMD_2_REGISTER_SHIFT_SIZE_8_MASK;
- }
- if (Immediate == 0) {
- BaseMnemonic = ARM_VMOVL_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VSHLL_MNEMONIC;
- }
- VectorDTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- VectorMTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- break;
- case ARM_SIMD_VCVT_TO_FLOAT_MASK:
- BaseMnemonic = ARM_VCVT_MNEMONIC;
- SourceSizeSuffix = ARM_SIMD_DATA_SIZE_32;
- DestinationTypeSuffix = ARM_SIMD_DATA_FLOAT;
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_32;
- Immediate = 64 - Immediate6;
- break;
- case ARM_SIMD_VCVT_TO_FIXED_MASK:
- BaseMnemonic = ARM_VCVT_MNEMONIC;
- SourceTypeSuffix = ARM_SIMD_DATA_FLOAT;
- SourceSizeSuffix = ARM_SIMD_DATA_SIZE_32;
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_32;
- Immediate = 64 - Immediate6;
- break;
- default:
- break;
- }
- if (BaseMnemonic == NULL) {
- DbgpArmDecodeUndefined(Context);
- return;
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- sprintf(Context->PostConditionMnemonicSuffix,
- "%s%s%s%s",
- DestinationTypeSuffix,
- DestinationSizeSuffix,
- SourceTypeSuffix,
- SourceSizeSuffix);
- sprintf(Context->Operand1, "%s%d", VectorDTypeString, VectorD);
- sprintf(Context->Operand2, "%s%d", VectorMTypeString, VectorM);
- sprintf(Context->Operand3, "#%d ; 0x%x", Immediate, Immediate);
- return;
- }
- VOID
- DbgpArmDecodeSimdThreeRegistersDifferentLength (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an SIMD data instruction with three registers of
- different lengths.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Instruction;
- ULONG Size;
- PSTR SizeTypeSuffix;
- PSTR SizeValueSuffix;
- ULONG VectorD;
- PSTR VectorDTypeString;
- ULONG VectorM;
- PSTR VectorMTypeString;
- ULONG VectorN;
- PSTR VectorNTypeString;
- //
- // Gather the values that are common to most of the instructions.
- //
- Instruction = Context->Instruction;
- VectorDTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- VectorD = (Instruction & ARM_SIMD_DATA_PROCESSING_VD_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VD_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VD_BIT) != 0) {
- VectorD |= (1 << 4);
- }
- VectorMTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- VectorM = (Instruction & ARM_SIMD_DATA_PROCESSING_VM_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VM_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VM_BIT) != 0) {
- VectorM |= (1 << 4);
- }
- VectorNTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- VectorN = (Instruction & ARM_SIMD_DATA_PROCESSING_VN_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VN_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VN_BIT) != 0) {
- VectorN |= (1 << 4);
- }
- SizeTypeSuffix = ARM_SIMD_DATA_SIGNED;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_UNSIGNED) != 0) {
- SizeTypeSuffix = ARM_SIMD_DATA_UNSIGNED;
- }
- Size = (Instruction & ARM_SIMD_3_DIFF_SIZE_MASK) >>
- ARM_SIMD_3_DIFF_SIZE_SHIFT;
- //
- // Sort out which instruction is actually being decoded and modify the
- // common values as necessary.
- //
- BaseMnemonic = NULL;
- switch (Instruction & ARM_SIMD_3_DIFF_OPERATION_MASK) {
- case ARM_SIMD_VADDL_MASK:
- BaseMnemonic = ARM_VADDL_MNEMONIC;
- break;
- case ARM_SIMD_VADDW_MASK:
- BaseMnemonic = ARM_VADDW_MNEMONIC;
- VectorNTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- break;
- case ARM_SIMD_VSUBL_MASK:
- BaseMnemonic = ARM_VSUBL_MNEMONIC;
- break;
- case ARM_SIMD_VSUBW_MASK:
- BaseMnemonic = ARM_VSUBW_MNEMONIC;
- VectorNTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- break;
- case ARM_SIMD_VADDHN_MASK:
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_UNSIGNED) != 0) {
- BaseMnemonic = ARM_VRADDHN_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VADDHN_MNEMONIC;
- }
- //
- // The size is double the normal encoding, so add 1 to the encoding.
- //
- Size += 1;
- SizeTypeSuffix = ARM_SIMD_DATA_INTEGER;
- VectorDTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- VectorNTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- break;
- case ARM_SIMD_VABAL_MASK:
- BaseMnemonic = ARM_VABAL_MNEMONIC;
- break;
- case ARM_SIMD_VSUBHN_MASK:
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_UNSIGNED) != 0) {
- BaseMnemonic = ARM_VRSUBHN_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VSUBHN_MNEMONIC;
- }
- //
- // The size is double the normal encoding, so add 1 to the encoding.
- //
- Size += 1;
- SizeTypeSuffix = ARM_SIMD_DATA_INTEGER;
- VectorDTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- VectorNTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- break;
- case ARM_SIMD_VABDL_MASK:
- BaseMnemonic = ARM_VABDL_MNEMONIC;
- break;
- case ARM_SIMD_VMLAL_MASK:
- BaseMnemonic = ARM_VMLAL_MNEMONIC;
- break;
- case ARM_SIMD_VMLSL_MASK:
- BaseMnemonic = ARM_VMLSL_MNEMONIC;
- break;
- case ARM_SIMD_VQDMLAL_MASK:
- BaseMnemonic = ARM_VQDMLAL_MNEMONIC;
- break;
- case ARM_SIMD_VQDMLSL_MASK:
- BaseMnemonic = ARM_VQDMLSL_MNEMONIC;
- break;
- case ARM_SIMD_VMULL_INT_MASK:
- BaseMnemonic = ARM_VMULL_MNEMONIC;
- break;
- case ARM_SIMD_VQDMULL_MASK:
- BaseMnemonic = ARM_VQDMULL_MNEMONIC;
- break;
- case ARM_SIMD_VMULL_POLY_MASK:
- BaseMnemonic = ARM_VMULL_MNEMONIC;
- SizeTypeSuffix = ARM_SIMD_DATA_POLYNOMIAL;
- break;
- default:
- break;
- }
- if (BaseMnemonic == NULL) {
- DbgpArmDecodeUndefined(Context);
- return;
- }
- //
- // Get the size suffix now that it has been adjusted for the particular
- // instruction being decoded.
- //
- switch (Size) {
- case ARM_SIMD_3_DIFF_SIZE_8:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_8;
- break;
- case ARM_SIMD_3_DIFF_SIZE_16:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_16;
- break;
- case ARM_SIMD_3_DIFF_SIZE_32:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- break;
- case ARM_SIMD_3_DIFF_SIZE_64:
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_64;
- break;
- //
- // This should never hit as all possible values are accounted for.
- //
- default:
- SizeValueSuffix = "";
- break;
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- sprintf(Context->PostConditionMnemonicSuffix,
- "%s%s",
- SizeTypeSuffix,
- SizeValueSuffix);
- sprintf(Context->Operand1, "%s%d", VectorDTypeString, VectorD);
- sprintf(Context->Operand2, "%s%d", VectorNTypeString, VectorN);
- sprintf(Context->Operand3, "%s%d", VectorMTypeString, VectorM);
- return;
- }
- VOID
- DbgpArmDecodeSimdTwoRegistersWithScalar (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an SIMD data instruction with two registers and a
- scalar.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- BOOL FloatValid;
- ULONG Instruction;
- BOOL QuadwordValid;
- PSTR SizeTypeSuffix;
- PSTR SizeValueSuffix;
- ULONG VectorD;
- PSTR VectorDTypeString;
- ULONG VectorM;
- ULONG VectorMIndex;
- ULONG VectorN;
- PSTR VectorNTypeString;
- Instruction = Context->Instruction;
- VectorDTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- VectorD = (Instruction & ARM_SIMD_DATA_PROCESSING_VD_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VD_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VD_BIT) != 0) {
- VectorD |= (1 << 4);
- }
- VectorNTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- VectorN = (Instruction & ARM_SIMD_DATA_PROCESSING_VN_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VN_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VN_BIT) != 0) {
- VectorN |= (1 << 4);
- }
- //
- // Vector M stores both the vector and the index. The division of the bits
- // depend on the instruction's encoded size.
- //
- VectorM = (Instruction & ARM_SIMD_DATA_PROCESSING_VM_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VM_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VM_BIT) != 0) {
- VectorM |= (1 << 4);
- }
- switch (Instruction & ARM_SIMD_2_REGISTER_SCALAR_SIZE_MASK) {
- case ARM_SIMD_2_REGISTER_SCALAR_SIZE_16:
- VectorMIndex = (VectorM &
- ARM_SIMD_2_REGISTER_SCALAR_SIZE_16_VM_INDEX_MASK) >>
- ARM_SIMD_2_REGISTER_SCALAR_SIZE_16_VM_INDEX_SHIFT;
- VectorM = (VectorM &
- ARM_SIMD_2_REGISTER_SCALAR_SIZE_16_VM_VECTOR_MASK) >>
- ARM_SIMD_2_REGISTER_SCALAR_SIZE_16_VM_VECTOR_SHIFT;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_16;
- break;
- case ARM_SIMD_2_REGISTER_SCALAR_SIZE_32:
- VectorMIndex = (VectorM &
- ARM_SIMD_2_REGISTER_SCALAR_SIZE_32_VM_INDEX_MASK) >>
- ARM_SIMD_2_REGISTER_SCALAR_SIZE_32_VM_INDEX_SHIFT;
- VectorM = (VectorM &
- ARM_SIMD_2_REGISTER_SCALAR_SIZE_32_VM_VECTOR_MASK) >>
- ARM_SIMD_2_REGISTER_SCALAR_SIZE_32_VM_VECTOR_SHIFT;
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- break;
- default:
- DbgpArmDecodeUndefined(Context);
- return;
- }
- SizeTypeSuffix = ARM_SIMD_DATA_SIGNED;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_UNSIGNED) != 0) {
- SizeTypeSuffix = ARM_SIMD_DATA_UNSIGNED;
- }
- //
- // Get the base mnemonic and finalize the type suffix.
- //
- FloatValid = FALSE;
- QuadwordValid = FALSE;
- BaseMnemonic = NULL;
- switch (Instruction & ARM_SIMD_2_REGISTER_SCALAR_OPERATION_MASK) {
- case ARM_SIMD_2_REGISTER_SCALAR_VMLA_MASK:
- case (ARM_SIMD_2_REGISTER_SCALAR_VMLA_MASK |
- ARM_SIMD_2_REGISTER_SCALAR_FLOAT):
- FloatValid = TRUE;
- QuadwordValid = TRUE;
- BaseMnemonic = ARM_VMLA_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_SCALAR_VMLS_MASK:
- case (ARM_SIMD_2_REGISTER_SCALAR_VMLS_MASK |
- ARM_SIMD_2_REGISTER_SCALAR_FLOAT):
- FloatValid = TRUE;
- QuadwordValid = TRUE;
- BaseMnemonic = ARM_VMLS_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_SCALAR_VMLAL_MASK:
- BaseMnemonic = ARM_VMLAL_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_SCALAR_VMLSL_MASK:
- BaseMnemonic = ARM_VMLSL_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_SCALAR_VQDMLAL_MASK:
- BaseMnemonic = ARM_VQDMLAL_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_SCALAR_VQDMLSL_MASK:
- BaseMnemonic = ARM_VQDMLSL_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_SCALAR_VMUL_MASK:
- case (ARM_SIMD_2_REGISTER_SCALAR_VMUL_MASK |
- ARM_SIMD_2_REGISTER_SCALAR_FLOAT):
- FloatValid = TRUE;
- QuadwordValid = TRUE;
- BaseMnemonic = ARM_VMUL_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_SCALAR_VMULL_MASK:
- BaseMnemonic = ARM_VMULL_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_SCALAR_VQDMULL_MASK:
- BaseMnemonic = ARM_VQDMULL_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_SCALAR_VQDMULH_MASK:
- QuadwordValid = TRUE;
- BaseMnemonic = ARM_VQDMULH_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_SCALAR_VQRDMULH_MASK:
- QuadwordValid = TRUE;
- BaseMnemonic = ARM_VQRDMULH_MNEMONIC;
- break;
- default:
- break;
- }
- if (BaseMnemonic == NULL) {
- DbgpArmDecodeUndefined(Context);
- return;
- }
- //
- // Process the quadword and float bits if they are valid for the
- // instruction being decoded.
- //
- if (QuadwordValid != FALSE) {
- if ((Instruction & ARM_SIMD_2_REGISTER_SCALAR_QUADWORD) != 0) {
- VectorNTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- } else {
- VectorDTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- }
- }
- if (FloatValid != FALSE) {
- if ((Instruction & ARM_SIMD_2_REGISTER_SCALAR_FLOAT) != 0) {
- SizeTypeSuffix = ARM_SIMD_DATA_FLOAT;
- } else {
- SizeTypeSuffix = ARM_SIMD_DATA_INTEGER;
- }
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- sprintf(Context->PostConditionMnemonicSuffix,
- "%s%s",
- SizeTypeSuffix,
- SizeValueSuffix);
- sprintf(Context->Operand1, "%s%d", VectorDTypeString, VectorD);
- sprintf(Context->Operand2, "%s%d", VectorNTypeString, VectorN);
- sprintf(Context->Operand3,
- "%s%d[%d]",
- ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR,
- VectorM,
- VectorMIndex);
- return;
- }
- VOID
- DbgpArmDecodeSimdTwoRegistersMiscellaneous (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an SIMD data vector extract instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- PSTR DestinationSizeSuffix;
- PSTR DestinationTypeSuffix;
- BOOL GetSizeSuffix;
- ULONG Immediate;
- ULONG Instruction;
- BOOL PrintImmediate;
- ULONG Size;
- PSTR SourceSizeSuffix;
- PSTR SourceTypeSuffix;
- ULONG VectorD;
- PSTR VectorDTypeString;
- ULONG VectorM;
- PSTR VectorMTypeString;
- Instruction = Context->Instruction;
- VectorDTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- VectorD = (Instruction & ARM_SIMD_DATA_PROCESSING_VD_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VD_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VD_BIT) != 0) {
- VectorD |= (1 << 4);
- }
- VectorMTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- VectorM = (Instruction & ARM_SIMD_DATA_PROCESSING_VM_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VM_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VM_BIT) != 0) {
- VectorM |= (1 << 4);
- }
- SourceSizeSuffix = "";
- SourceTypeSuffix = "";
- DestinationTypeSuffix = ARM_SIMD_DATA_DEFAULT;
- DestinationSizeSuffix = "";
- GetSizeSuffix = TRUE;
- Size = (Instruction & ARM_SIMD_2_REGISTER_MISC_SIZE_MASK) >>
- ARM_SIMD_2_REGISTER_MISC_SIZE_SHIFT;
- //
- // Some instructions include an immediate value. Default to not print it.
- //
- Immediate = 0;
- PrintImmediate = FALSE;
- //
- // Determine the base mnemonic and perform and instruction specific
- // modifications to the vector and size information.
- //
- BaseMnemonic = NULL;
- switch (Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_MASK) {
- case ARM_SIMD_2_REGISTER_MISC_TYPE_0:
- switch (Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_0_OP_MASK) {
- case ARM_SIMD_2_REGISTER_MISC_TYPE_0_VREV64_MASK:
- BaseMnemonic = ARM_VREV64_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_0_VREV32_MASK:
- BaseMnemonic = ARM_VREV32_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_0_VREV16_MASK:
- BaseMnemonic = ARM_VREV16_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_0_VPADDL_MASK:
- case (ARM_SIMD_2_REGISTER_MISC_TYPE_0_VPADDL_MASK |
- ARM_SIMD_2_REGISTER_MISC_TYPE_0_UNSIGNED):
- if ((Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_0_UNSIGNED) != 0) {
- DestinationTypeSuffix = ARM_SIMD_DATA_UNSIGNED;
- } else {
- DestinationTypeSuffix = ARM_SIMD_DATA_SIGNED;
- }
- BaseMnemonic = ARM_VPADDL_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_0_VCLS_MASK:
- DestinationTypeSuffix = ARM_SIMD_DATA_SIGNED;
- BaseMnemonic = ARM_VCLS_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_0_VCLZ_MASK:
- DestinationTypeSuffix = ARM_SIMD_DATA_INTEGER;
- BaseMnemonic = ARM_VCLZ_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_0_VCNT_MASK:
- BaseMnemonic = ARM_VCNT_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_0_VMVN_MASK:
- GetSizeSuffix = FALSE;
- DestinationTypeSuffix = "";
- BaseMnemonic = ARM_VMVN_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_0_VPADAL_MASK:
- case (ARM_SIMD_2_REGISTER_MISC_TYPE_0_VPADAL_MASK |
- ARM_SIMD_2_REGISTER_MISC_TYPE_0_UNSIGNED):
- if ((Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_0_UNSIGNED) != 0) {
- DestinationTypeSuffix = ARM_SIMD_DATA_UNSIGNED;
- } else {
- DestinationTypeSuffix = ARM_SIMD_DATA_SIGNED;
- }
- BaseMnemonic = ARM_VPADAL_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_0_VQABS_MASK:
- DestinationTypeSuffix = ARM_SIMD_DATA_SIGNED;
- BaseMnemonic = ARM_VQABS_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_0_VQNEG_MASK:
- DestinationTypeSuffix = ARM_SIMD_DATA_SIGNED;
- BaseMnemonic = ARM_VQNEG_MNEMONIC;
- break;
- default:
- break;
- }
- //
- // All of the type 0 instructions depend on the quadword bit.
- //
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_QUADWORD) != 0) {
- VectorDTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- }
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_1:
- //
- // The majority of these instructions have an immediate 0 value and
- // default to being signed.
- //
- PrintImmediate = TRUE;
- DestinationTypeSuffix = ARM_SIMD_DATA_SIGNED;
- switch (Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_1_OP_MASK) {
- case ARM_SIMD_2_REGISTER_MISC_TYPE_1_VCGT_MASK:
- BaseMnemonic = ARM_VCGT_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_1_VCGE_MASK:
- BaseMnemonic = ARM_VCGE_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_1_VCEQ_MASK:
- DestinationTypeSuffix = ARM_SIMD_DATA_INTEGER;
- BaseMnemonic = ARM_VCEQ_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_1_VCLE_MASK:
- BaseMnemonic = ARM_VCLE_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_1_VCLT_MASK:
- BaseMnemonic = ARM_VCLT_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_1_VABS_MASK:
- PrintImmediate = FALSE;
- BaseMnemonic = ARM_VABS_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_1_VNEG_MASK:
- PrintImmediate = FALSE;
- BaseMnemonic = ARM_VNEG_MNEMONIC;
- break;
- default:
- break;
- }
- //
- // All of the type 1 instructions depend on the type specific float bit.
- //
- if ((Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_1_FLOAT) != 0) {
- DestinationTypeSuffix = ARM_SIMD_DATA_FLOAT;
- }
- //
- // All of the type 1 instructions depend on the quadword bit.
- //
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_QUADWORD) != 0) {
- VectorDTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- }
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_2:
- switch (Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_2_OP_MASK) {
- case ARM_SIMD_2_REGISTER_MISC_TYPE_2_VSWP_MASK:
- GetSizeSuffix = FALSE;
- DestinationTypeSuffix = "";
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_QUADWORD) != 0) {
- VectorDTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- }
- BaseMnemonic = ARM_VSWP_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_2_VTRN_MASK:
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_QUADWORD) != 0) {
- VectorDTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- }
- BaseMnemonic = ARM_VTRN_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_2_VUZP_MASK:
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_QUADWORD) != 0) {
- VectorDTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- }
- BaseMnemonic = ARM_VUZP_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_2_VZIP_MASK:
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_QUADWORD) != 0) {
- VectorDTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- }
- BaseMnemonic = ARM_VZIP_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_2_VMOVN_MASK:
- if ((Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_2_UNSIGNED) != 0) {
- BaseMnemonic = ARM_VQMOVUN_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VMOVN_MNEMONIC;
- }
- DestinationTypeSuffix = ARM_SIMD_DATA_INTEGER;
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- //
- // The size encodings are doubled, so add 1 to get the correct
- // destination size suffix below.
- //
- Size += 1;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_2_VQMOVN_MASK:
- if ((Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_2_UNSIGNED) != 0) {
- DestinationTypeSuffix = ARM_SIMD_DATA_UNSIGNED;
- } else {
- DestinationTypeSuffix = ARM_SIMD_DATA_SIGNED;
- }
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- //
- // The size encodings are doubled, so add 1 to get the correct
- // destination size suffix below.
- //
- Size += 1;
- BaseMnemonic = ARM_VQMOVN_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_2_VSHLL_MASK:
- if ((Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_2_UNSIGNED) != 0) {
- break;
- }
- Immediate = Size;
- VectorDTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- BaseMnemonic = ARM_VSHLL_MNEMONIC;
- DestinationTypeSuffix = ARM_SIMD_DATA_INTEGER;
- PrintImmediate = TRUE;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_2_VCVT_HALF_TO_SINGLE_MASK:
- VectorDTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- DestinationTypeSuffix = ARM_SIMD_DATA_FLOAT;
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_32;
- SourceTypeSuffix = ARM_SIMD_DATA_FLOAT;
- SourceSizeSuffix = ARM_SIMD_DATA_SIZE_16;
- GetSizeSuffix = FALSE;
- BaseMnemonic = ARM_VCVT_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_2_VCVT_SINGLE_TO_HALF_MASK:
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- DestinationTypeSuffix = ARM_SIMD_DATA_FLOAT;
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_16;
- SourceTypeSuffix = ARM_SIMD_DATA_FLOAT;
- SourceSizeSuffix = ARM_SIMD_DATA_SIZE_32;
- GetSizeSuffix = FALSE;
- BaseMnemonic = ARM_VCVT_MNEMONIC;
- break;
- default:
- break;
- }
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_3:
- switch (Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_3_OP_MASK) {
- case ARM_SIMD_2_REGISTER_MISC_TYPE_3_VRECPE_MASK:
- if ((Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_3_FLOAT) != 0) {
- DestinationTypeSuffix = ARM_SIMD_DATA_FLOAT;
- } else {
- DestinationTypeSuffix = ARM_SIMD_DATA_UNSIGNED;
- }
- BaseMnemonic = ARM_VRECPE_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_3_VRSQRTE_MASK:
- if ((Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_3_FLOAT) != 0) {
- DestinationTypeSuffix = ARM_SIMD_DATA_FLOAT;
- } else {
- DestinationTypeSuffix = ARM_SIMD_DATA_UNSIGNED;
- }
- BaseMnemonic = ARM_VRSQRTE_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_3_VCVT_TO_INTEGER_MASK:
- if ((Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_3_UNSIGNED) != 0) {
- DestinationTypeSuffix = ARM_SIMD_DATA_UNSIGNED;
- } else {
- DestinationTypeSuffix = ARM_SIMD_DATA_SIGNED;
- }
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_32;
- SourceTypeSuffix = ARM_SIMD_DATA_FLOAT;
- SourceSizeSuffix = ARM_SIMD_DATA_SIZE_32;
- GetSizeSuffix = FALSE;
- BaseMnemonic = ARM_VCVT_MNEMONIC;
- break;
- case ARM_SIMD_2_REGISTER_MISC_TYPE_3_VCVT_FROM_INTEGER_MASK:
- if ((Instruction & ARM_SIMD_2_REGISTER_MISC_TYPE_3_UNSIGNED) != 0) {
- SourceTypeSuffix = ARM_SIMD_DATA_UNSIGNED;
- } else {
- SourceTypeSuffix = ARM_SIMD_DATA_SIGNED;
- }
- SourceSizeSuffix = ARM_SIMD_DATA_SIZE_32;
- DestinationTypeSuffix = ARM_SIMD_DATA_FLOAT;
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_32;
- GetSizeSuffix = FALSE;
- BaseMnemonic = ARM_VCVT_MNEMONIC;
- break;
- default:
- break;
- }
- //
- // All of the type 3 instructions depend on the quadword bit.
- //
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_QUADWORD) != 0) {
- VectorDTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- VectorMTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- }
- break;
- default:
- break;
- }
- if (BaseMnemonic == NULL) {
- DbgpArmDecodeUndefined(Context);
- return;
- }
- if (GetSizeSuffix != FALSE) {
- switch (Size) {
- case ARM_SIMD_2_REGISTER_MISC_SIZE_8:
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_8;
- break;
- case ARM_SIMD_2_REGISTER_MISC_SIZE_16:
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_16;
- break;
- case ARM_SIMD_2_REGISTER_MISC_SIZE_32:
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_32;
- break;
- case ARM_SIMD_2_REGISTER_MISC_SIZE_64:
- DestinationSizeSuffix = ARM_SIMD_DATA_SIZE_64;
- break;
- default:
- return;
- }
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- sprintf(Context->PostConditionMnemonicSuffix,
- "%s%s%s%s",
- DestinationTypeSuffix,
- DestinationSizeSuffix,
- SourceTypeSuffix,
- SourceSizeSuffix);
- sprintf(Context->Operand1, "%s%d", VectorDTypeString, VectorD);
- sprintf(Context->Operand2, "%s%d", VectorMTypeString, VectorM);
- if (PrintImmediate != FALSE) {
- sprintf(Context->Operand3, "#%d ; 0x%x", Immediate, Immediate);
- }
- return;
- }
- VOID
- DbgpArmDecodeSimdVectorExtract (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an SIMD data vector extract instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ULONG Immediate;
- ULONG Instruction;
- ULONG VectorD;
- ULONG VectorM;
- ULONG VectorN;
- PSTR VectorTypeString;
- Instruction = Context->Instruction;
- VectorD = (Instruction & ARM_SIMD_DATA_PROCESSING_VD_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VD_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VD_BIT) != 0) {
- VectorD |= (1 << 4);
- }
- VectorM = (Instruction & ARM_SIMD_DATA_PROCESSING_VM_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VM_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VM_BIT) != 0) {
- VectorM |= (1 << 4);
- }
- VectorN = (Instruction & ARM_SIMD_DATA_PROCESSING_VN_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VN_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VN_BIT) != 0) {
- VectorN |= (1 << 4);
- }
- VectorTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_QUADWORD) != 0) {
- VectorTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- }
- Immediate = (Instruction & ARM_SIMD_VEXT_IMMEDIATE4_MASK) >>
- ARM_SIMD_VEXT_IMMEDIATE4_SHIFT;
- strcpy(Context->Mnemonic, ARM_VEXT_MNEMONIC);
- sprintf(Context->PostConditionMnemonicSuffix,
- "%s%s",
- ARM_SIMD_DATA_DEFAULT,
- ARM_SIMD_DATA_SIZE_8);
- sprintf(Context->Operand1, "%s%d", VectorTypeString, VectorD);
- sprintf(Context->Operand2, "%s%d", VectorTypeString, VectorN);
- sprintf(Context->Operand3, "%s%d", VectorTypeString, VectorM);
- sprintf(Context->Operand4, "#%d ; 0x%x", Immediate, Immediate);
- return;
- }
- VOID
- DbgpArmDecodeSimdVectorTableLookup (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an SIMD vector table lookup instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- PSTR BaseMnemonic;
- ULONG Instruction;
- ULONG VectorCount;
- ULONG VectorD;
- ULONG VectorM;
- ULONG VectorN;
- Instruction = Context->Instruction;
- VectorD = (Instruction & ARM_SIMD_DATA_PROCESSING_VD_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VD_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VD_BIT) != 0) {
- VectorD |= (1 << 4);
- }
- VectorM = (Instruction & ARM_SIMD_DATA_PROCESSING_VM_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VM_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VM_BIT) != 0) {
- VectorM |= (1 << 4);
- }
- VectorN = (Instruction & ARM_SIMD_DATA_PROCESSING_VN_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VN_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VN_BIT) != 0) {
- VectorN |= (1 << 4);
- }
- VectorCount = (Instruction & ARM_SIMD_VTB_LENGTH_MASK) >>
- ARM_SIMD_VTB_LENGTH_SHIFT;
- VectorCount += 1;
- if ((Instruction & ARM_SIMD_VTB_EXTENSION) != 0) {
- BaseMnemonic = ARM_VTBX_MNEMONIC;
- } else {
- BaseMnemonic = ARM_VTBL_MNEMONIC;
- }
- strcpy(Context->Mnemonic, BaseMnemonic);
- sprintf(Context->PostConditionMnemonicSuffix,
- "%s%s",
- ARM_SIMD_DATA_DEFAULT,
- ARM_SIMD_DATA_SIZE_8);
- sprintf(Context->Operand1,
- "%s%d",
- ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR,
- VectorD);
- DbgpArmPrintVectorList(Context->Operand2,
- sizeof(Context->Operand2),
- VectorN,
- VectorCount,
- 1,
- ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR,
- 0,
- 0);
- sprintf(Context->Operand3,
- "%s%d",
- ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR,
- VectorM);
- return;
- }
- VOID
- DbgpArmDecodeSimdVectorDuplicate (
- PARM_DISASSEMBLY Context
- )
- /*++
- Routine Description:
- This routine decodes an SIMD data vector duplicate instruction.
- Arguments:
- Context - Supplies a pointer to the disassembly context.
- Return Value:
- None.
- --*/
- {
- ULONG Instruction;
- PSTR SizeTypeSuffix;
- PSTR SizeValueSuffix;
- ULONG VectorD;
- PSTR VectorDTypeString;
- ULONG VectorM;
- ULONG VectorMIndex;
- Instruction = Context->Instruction;
- SizeTypeSuffix = ARM_SIMD_DATA_DEFAULT;
- SizeValueSuffix = "";
- VectorMIndex = 0;
- VectorD = (Instruction & ARM_SIMD_DATA_PROCESSING_VD_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VD_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VD_BIT) != 0) {
- VectorD |= (1 << 4);
- }
- VectorM = (Instruction & ARM_SIMD_DATA_PROCESSING_VM_MASK) >>
- ARM_SIMD_DATA_PROCESSING_VM_SHIFT;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_VM_BIT) != 0) {
- VectorM |= (1 << 4);
- }
- if ((Instruction & ARM_SIMD_VDUP_SIZE_8_MASK) ==
- ARM_SIMD_VDUP_SIZE_8_VALUE) {
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_8;
- VectorMIndex = (Instruction & ARM_SIMD_VDUP_SIZE_8_INDEX_MASK) >>
- ARM_SIMD_VDUP_SIZE_8_INDEX_SHIFT;
- } else if ((Instruction & ARM_SIMD_VDUP_SIZE_16_MASK) ==
- ARM_SIMD_VDUP_SIZE_16_VALUE) {
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_16;
- VectorMIndex = (Instruction & ARM_SIMD_VDUP_SIZE_16_INDEX_MASK) >>
- ARM_SIMD_VDUP_SIZE_16_INDEX_SHIFT;
- } else if ((Instruction & ARM_SIMD_VDUP_SIZE_32_MASK) ==
- ARM_SIMD_VDUP_SIZE_32_VALUE) {
- SizeValueSuffix = ARM_SIMD_DATA_SIZE_32;
- VectorMIndex = (Instruction & ARM_SIMD_VDUP_SIZE_32_INDEX_MASK) >>
- ARM_SIMD_VDUP_SIZE_32_INDEX_SHIFT;
- } else {
- SizeTypeSuffix = "";
- }
- VectorDTypeString = ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR;
- if ((Instruction & ARM_SIMD_DATA_PROCESSING_QUADWORD) != 0) {
- VectorDTypeString = ARM_FLOATING_POINT_QUADWORD_VECTOR;
- }
- strcpy(Context->Mnemonic, ARM_VDUP_MNEMONIC);
- sprintf(Context->PostConditionMnemonicSuffix,
- "%s%s",
- SizeTypeSuffix,
- SizeValueSuffix);
- sprintf(Context->Operand1, "%s%d", VectorDTypeString, VectorD);
- sprintf(Context->Operand2,
- "%s%d[%d]",
- ARM_FLOATING_POINT_DOUBLE_PRECISION_VECTOR,
- VectorM,
- VectorMIndex);
- return;
- }
- PSTR
- DbgpArmGetLoadStoreTypeString (
- ULONG Instruction
- )
- /*++
- Routine Description:
- This routine returns the push/pop type string.
- Arguments:
- Instruction - Supplies the instruction. The push/pop type is always in the
- same bits.
- Return Value:
- Returns a static string for the push/pop type.
- --*/
- {
- switch (Instruction & ARM_LOAD_STORE_TYPE_MASK) {
- case ARM_LOAD_STORE_INCREMENT_AFTER:
- return ARM_INCREMENT_AFTER_SUFFIX;
- case ARM_LOAD_STORE_INCREMENT_BEFORE:
- return ARM_INCREMENT_BEFORE_SUFFIX;
- case ARM_LOAD_STORE_DECREMENT_AFTER:
- return ARM_DECREMENT_AFTER_SUFFIX;
- case ARM_LOAD_STORE_DECREMENT_BEFORE:
- return ARM_DECREMENT_BEFORE_SUFFIX;
- default:
- break;
- }
- return "";
- }
- PSTR
- DbgpArmGetBankedRegisterString (
- ULONG Instruction
- )
- /*++
- Routine Description:
- This routine returns the banked register/mode string, encoded in
- instructions as the m1 and R fields.
- Arguments:
- Instruction - Supplies the instruction.
- Return Value:
- Returns a static string for the encoding mode.
- --*/
- {
- ULONG Index;
- Index = (Instruction & ARM_BANKED_MODE_MASK) >> ARM_BANKED_MODE_SHIFT;
- if ((Instruction & ARM_BANKED_MODE_R_BIT) != 0) {
- Index |= 0x20;
- }
- return DbgArmBankedRegisters[Index];
- }
- VOID
- DbgpArmPrintStatusRegister (
- PSTR Operand,
- ULONG Instruction
- )
- /*++
- Routine Description:
- This routine prints the status register and flags for a given instruction.
- Arguments:
- Operand - Supplies the buffer where the completed string will be returned.
- Instruction - Supplies the instruction.
- Return Value:
- None.
- --*/
- {
- ULONG ExtraFlagCount;
- CHAR ExtraFlags[5];
- PSTR Register;
- memset(ExtraFlags, 0, sizeof(ExtraFlags));
- ExtraFlagCount = 0;
- if ((Instruction & ARM_MOVE_STATUS_SPSR) != 0) {
- Register = ARM_SPSR_STRING;
- } else {
- Register = ARM_CPSR_STRING;
- }
- if ((Instruction & ARM_MSR_MASK_C) != 0) {
- ExtraFlags[ExtraFlagCount] = ARM_MSR_MASK_C_FLAG;
- ExtraFlagCount += 1;
- }
- if ((Instruction & ARM_MSR_MASK_X) != 0) {
- ExtraFlags[ExtraFlagCount] = ARM_MSR_MASK_X_FLAG;
- ExtraFlagCount += 1;
- }
- if ((Instruction & ARM_MSR_MASK_S) != 0) {
- ExtraFlags[ExtraFlagCount] = ARM_MSR_MASK_S_FLAG;
- ExtraFlagCount += 1;
- }
- if ((Instruction & ARM_MSR_MASK_F) != 0) {
- ExtraFlags[ExtraFlagCount] = ARM_MSR_MASK_F_FLAG;
- ExtraFlagCount += 1;
- }
- sprintf(Operand, "%s_%s", Register, ExtraFlags);
- return;
- }
- VOID
- DbgpArmPrintVectorList (
- PSTR Destination,
- ULONG DestinationSize,
- ULONG VectorStart,
- ULONG VectorCount,
- ULONG VectorIncrement,
- PSTR VectorTypeString,
- ULONG VectorIndex,
- ULONG Flags
- )
- /*++
- Routine Description:
- This routine converts a count of vectors starting at a given vector into
- a string.
- Arguments:
- Destination - Supplies a pointer to the destination string.
- DestinationSize - Supplies the size of the destination string.
- VectorStart - Supplies the starting vector.
- VectorCount - Supplies the total number of vectors to convert.
- VectorIncrement - Supplies the interval between vectors.
- VectorTypeString - Supplies the character to use to describe each vector.
- VectorIndex - Supplies the option index into each vector.
- Flags - Supplies a bitmask of flags. See DBG_ARM_VECTOR_LIST_FLAG_* for
- definitions.
- Return Value:
- None.
- --*/
- {
- ULONG CurrentVector;
- PSTR Separator;
- INT Size;
- CHAR VectorString[16];
- if (DestinationSize > 1) {
- strcpy(Destination, "{");
- Size = strlen(Destination);
- Destination += Size;
- DestinationSize -= Size;
- }
- Separator = "";
- for (CurrentVector = VectorStart;
- CurrentVector < VectorStart + VectorCount;
- CurrentVector += VectorIncrement) {
- if ((Flags & DBG_ARM_VECTOR_LIST_FLAG_INDEX) != 0) {
- if ((Flags & DBG_ARM_VECTOR_LIST_FLAG_ALL_LANES) != 0) {
- snprintf(VectorString,
- sizeof(VectorString),
- "%s%s%d[]",
- Separator,
- VectorTypeString,
- CurrentVector);
- } else {
- snprintf(VectorString,
- sizeof(VectorString),
- "%s%s%d[%d]",
- Separator,
- VectorTypeString,
- CurrentVector,
- VectorIndex);
- }
- } else {
- snprintf(VectorString,
- sizeof(VectorString),
- "%s%s%d",
- Separator,
- VectorTypeString,
- CurrentVector);
- }
- Size = strlen(VectorString);
- if (Size < DestinationSize) {
- strcpy(Destination, VectorString);
- Destination += Size;
- DestinationSize -= Size;
- }
- Separator = ", ";
- }
- if (DestinationSize > 1) {
- strcpy(Destination, "}");
- }
- return;
- }
- VOID
- DbgpArmDecodeImmediateShift (
- PSTR Destination,
- ULONG DestinationSize,
- ULONG Register,
- ULONG Type,
- ULONG Immediate
- )
- /*++
- Routine Description:
- This routine converts a register, type and immediate value into a string
- representing the register shifted by the immediate value.
- Arguments:
- Destination - Supplies a pointer to the destination string.
- DestinationSize - Supplies the size of the destination string.
- Register - Supplies the register that is to be shifted.
- Type - Supplies the type of shift. See ARM_SHIFT_* for definitions.
- Immediate - Supplies the immediate value by which to shift.
- Return Value:
- None.
- --*/
- {
- PSTR RegisterName;
- PSTR ShiftType;
- ShiftType = NULL;
- switch (Type) {
- case ARM_SHIFT_LSL:
- if (Immediate != 0) {
- ShiftType = ARM_LSL_MNEMONIC;
- }
- break;
- case ARM_SHIFT_LSR:
- if (Immediate == 0) {
- Immediate = 32;
- }
- ShiftType = ARM_LSR_MNEMONIC;
- break;
- case ARM_SHIFT_ASR:
- if (Immediate == 0) {
- Immediate = 32;
- }
- ShiftType = ARM_ASR_MNEMONIC;
- break;
- case ARM_SHIFT_ROR:
- if (Immediate == 0) {
- ShiftType = ARM_RRX_MNEMONIC;
- } else {
- ShiftType = ARM_ROR_MNEMONIC;
- }
- break;
- //
- // This case should never hit since all 4 bit combinations are
- // covered.
- //
- default:
- break;
- }
- RegisterName = DbgArmRegisterNames[Register];
- if (Immediate != 0) {
- sprintf(Destination, "%s, %s #%d", RegisterName, ShiftType, Immediate);
- } else if (ShiftType != NULL) {
- sprintf(Destination, "%s, %s", RegisterName, ShiftType);
- } else {
- sprintf(Destination, "%s", RegisterName);
- }
- return;
- }
|