aasmcpu.pas 214 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805
  1. {
  2. Copyright (c) 2003 by Florian Klaempfl
  3. Contains the assembler object for the ARM
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published by
  6. the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. unit aasmcpu;
  18. {$i fpcdefs.inc}
  19. interface
  20. uses
  21. globtype,globals,verbose,
  22. aasmbase,aasmtai,aasmdata,aasmsym,
  23. ogbase,
  24. symtype,
  25. cpubase,cpuinfo,cgbase,cgutils,
  26. sysutils;
  27. const
  28. { "mov reg,reg" source operand number }
  29. O_MOV_SOURCE = 1;
  30. { "mov reg,reg" source operand number }
  31. O_MOV_DEST = 0;
  32. { Operand types }
  33. OT_NONE = $00000000;
  34. OT_BITS8 = $00000001; { size, and other attributes, of the operand }
  35. OT_BITS16 = $00000002;
  36. OT_BITS32 = $00000004;
  37. OT_BITS64 = $00000008; { FPU only }
  38. OT_BITS80 = $00000010;
  39. OT_FAR = $00000020; { this means 16:16 or 16:32, like in CALL/JMP }
  40. OT_NEAR = $00000040;
  41. OT_SHORT = $00000080;
  42. OT_BITSTINY = $00000100; { fpu constant }
  43. OT_BITSSHIFTER =
  44. $00000200;
  45. OT_SIZE_MASK = $000003FF; { all the size attributes }
  46. OT_NON_SIZE = $0FFFF800;
  47. OT_OPT_SIZE = $F0000000;
  48. OT_SIGNED = $00000100; { the operand need to be signed -128-127 }
  49. OT_TO = $00000200; { operand is followed by a colon }
  50. { reverse effect in FADD, FSUB &c }
  51. OT_COLON = $00000400;
  52. OT_SHIFTEROP = $00000800;
  53. OT_REGISTER = $00001000;
  54. OT_IMMEDIATE = $00002000;
  55. OT_REGLIST = $00008000;
  56. OT_IMM8 = $00002001;
  57. OT_IMM24 = $00002002;
  58. OT_IMM32 = $00002004;
  59. OT_IMM64 = $00002008;
  60. OT_IMM80 = $00002010;
  61. OT_IMMTINY = $00002100;
  62. OT_IMMSHIFTER= $00002200;
  63. OT_IMMEDIATEZERO = $10002200;
  64. OT_IMMEDIATEMM = $00002400;
  65. OT_IMMEDIATE24 = OT_IMM24;
  66. OT_SHIFTIMM = OT_SHIFTEROP or OT_IMMSHIFTER;
  67. OT_SHIFTIMMEDIATE = OT_SHIFTIMM;
  68. OT_IMMEDIATESHIFTER = OT_IMMSHIFTER;
  69. OT_IMMEDIATEFPU = OT_IMMTINY;
  70. OT_REGMEM = $00200000; { for r/m, ie EA, operands }
  71. OT_REGNORM = $00201000; { 'normal' reg, qualifies as EA }
  72. OT_REG8 = $00201001;
  73. OT_REG16 = $00201002;
  74. OT_REG32 = $00201004;
  75. OT_REGLO = $10201004; { lower reg (r0-r7) }
  76. OT_REGSP = $20201004;
  77. OT_REG64 = $00201008;
  78. OT_VREG = $00201010; { vector register }
  79. OT_REGF = $00201020; { coproc register }
  80. OT_REGS = $00201040; { special register with mask }
  81. OT_MEMORY = $00204000; { register number in 'basereg' }
  82. OT_MEM8 = $00204001;
  83. OT_MEM16 = $00204002;
  84. OT_MEM32 = $00204004;
  85. OT_MEM64 = $00204008;
  86. OT_MEM80 = $00204010;
  87. { word/byte load/store }
  88. OT_AM2 = $00010000;
  89. { misc ld/st operations, thumb reg indexed }
  90. OT_AM3 = $00020000;
  91. { multiple ld/st operations or thumb imm indexed }
  92. OT_AM4 = $00040000;
  93. { co proc. ld/st operations or thumb sp+imm indexed }
  94. OT_AM5 = $00080000;
  95. { exclusive ld/st operations or thumb pc+imm indexed }
  96. OT_AM6 = $00100000;
  97. OT_AMMASK = $001f0000;
  98. { IT instruction }
  99. OT_CONDITION = $00200000;
  100. OT_MODEFLAGS = $00400000;
  101. OT_MEMORYAM2 = OT_MEMORY or OT_AM2;
  102. OT_MEMORYAM3 = OT_MEMORY or OT_AM3;
  103. OT_MEMORYAM4 = OT_MEMORY or OT_AM4;
  104. OT_MEMORYAM5 = OT_MEMORY or OT_AM5;
  105. OT_MEMORYAM6 = OT_MEMORY or OT_AM6;
  106. OT_FPUREG = $01000000; { floating point stack registers }
  107. OT_REG_SMASK = $00070000; { special register operands: these may be treated differently }
  108. { a mask for the following }
  109. OT_MEM_OFFS = $00604000; { special type of EA }
  110. { simple [address] offset }
  111. OT_ONENESS = $00800000; { special type of immediate operand }
  112. { so UNITY == IMMEDIATE | ONENESS }
  113. OT_UNITY = $00802000; { for shift/rotate instructions }
  114. instabentries = {$i armnop.inc}
  115. maxinfolen = 5;
  116. IF_NONE = $00000000;
  117. IF_EXTENSIONS = $0000000F;
  118. IF_NEON = $00000001;
  119. IF_ARMMASK = $000F0000;
  120. IF_ARM32 = $00010000;
  121. IF_THUMB = $00020000;
  122. IF_THUMB32 = $00040000;
  123. IF_WIDE = $00080000;
  124. IF_ARMvMASK = $0FF00000;
  125. IF_ARMv4 = $00100000;
  126. IF_ARMv4T = $00200000;
  127. IF_ARMv5 = $00300000;
  128. IF_ARMv5T = $00400000;
  129. IF_ARMv5TE = $00500000;
  130. IF_ARMv5TEJ = $00600000;
  131. IF_ARMv6 = $00700000;
  132. IF_ARMv6K = $00800000;
  133. IF_ARMv6T2 = $00900000;
  134. IF_ARMv6Z = $00A00000;
  135. IF_ARMv6M = $00B00000;
  136. IF_ARMv7 = $00C00000;
  137. IF_ARMv7A = $00D00000;
  138. IF_ARMv7R = $00E00000;
  139. IF_ARMv7M = $00F00000;
  140. IF_ARMv7EM = $01000000;
  141. IF_FPMASK = $c0000F00;
  142. IF_FPA = $00000100;
  143. IF_VFPv2 = $00000200;
  144. IF_VFPv3 = $00000400;
  145. IF_VFPv4 = $00000800;
  146. IF_VFPv5 = $80000000;
  147. { if the instruction can change in a second pass }
  148. IF_PASS2 = $80000000;
  149. type
  150. TInsTabCache=array[TasmOp] of longint;
  151. PInsTabCache=^TInsTabCache;
  152. tinsentry = record
  153. opcode : tasmop;
  154. ops : byte;
  155. optypes : array[0..5] of longint;
  156. code : array[0..maxinfolen] of char;
  157. flags : longword;
  158. end;
  159. pinsentry=^tinsentry;
  160. taicpuflag = (cf_wideformat,cf_inIT,cf_lastinIT,cf_thumb);
  161. taicpuflags = set of taicpuflag;
  162. const
  163. InsTab : array[0..instabentries-1] of TInsEntry={$i armtab.inc}
  164. var
  165. InsTabCache : PInsTabCache;
  166. type
  167. taicpu = class(tai_cpu_abstract_sym)
  168. oppostfix : TOpPostfix;
  169. roundingmode : troundingmode;
  170. flags : taicpuflags;
  171. procedure loadshifterop(opidx:longint;const so:tshifterop);
  172. procedure loadregset(opidx:longint; regsetregtype: tregistertype; regsetsubregtype: tsubregister; const s:tcpuregisterset; ausermode: boolean=false);
  173. procedure loadconditioncode(opidx:longint;const acond:tasmcond);
  174. procedure loadmodeflags(opidx:longint;const _modeflags:tcpumodeflags);
  175. procedure loadspecialreg(opidx:longint;const areg:tregister; const aflags:tspecialregflags);
  176. procedure loadrealconst(opidx:longint;const _value:bestreal);
  177. constructor op_none(op : tasmop);
  178. constructor op_reg(op : tasmop;_op1 : tregister);
  179. constructor op_ref(op : tasmop;const _op1 : treference);
  180. constructor op_const(op : tasmop;_op1 : longint);
  181. constructor op_reg_reg(op : tasmop;_op1,_op2 : tregister);
  182. constructor op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
  183. constructor op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
  184. constructor op_regset(op:tasmop; regtype: tregistertype; subreg: tsubregister; _op1: tcpuregisterset);
  185. constructor op_ref_regset(op:tasmop; _op1: treference; regtype: tregistertype; subreg: tsubregister; _op2: tcpuregisterset);
  186. constructor op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
  187. constructor op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
  188. constructor op_reg_const_const(op : tasmop;_op1 : tregister; _op2,_op3: aint);
  189. constructor op_reg_reg_const_const(op : tasmop;_op1,_op2 : tregister; _op3,_op4: aint);
  190. constructor op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
  191. constructor op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
  192. constructor op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
  193. constructor op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister;_op4 : tshifterop);
  194. { SFM/LFM }
  195. constructor op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
  196. { ITxxx }
  197. constructor op_cond(op: tasmop; cond: tasmcond);
  198. { CPSxx }
  199. constructor op_modeflags(op: tasmop; _modeflags: tcpumodeflags);
  200. constructor op_modeflags_const(op: tasmop; _modeflags: tcpumodeflags; a: aint);
  201. { MSR }
  202. constructor op_specialreg_reg(op: tasmop; specialreg: tregister; specialregflags: tspecialregflags; _op2: tregister);
  203. { *M*LL }
  204. constructor op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
  205. constructor op_reg_realconst(op : tasmop;_op1: tregister;_op2: bestreal);
  206. { this is for Jmp instructions }
  207. constructor op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
  208. constructor op_sym(op : tasmop;_op1 : tasmsymbol);
  209. constructor op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
  210. constructor op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
  211. constructor op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  212. function is_same_reg_move(regtype: Tregistertype):boolean; override;
  213. function spilling_get_operation_type(opnr: longint): topertype;override;
  214. function spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;override;
  215. { assembler }
  216. public
  217. { the next will reset all instructions that can change in pass 2 }
  218. procedure ResetPass1;override;
  219. procedure ResetPass2;override;
  220. function CheckIfValid:boolean;
  221. function GetString:string;
  222. function Pass1(objdata:TObjData):longint;override;
  223. procedure Pass2(objdata:TObjData);override;
  224. protected
  225. procedure ppuloadoper(ppufile:tcompilerppufile;var o:toper);override;
  226. procedure ppuwriteoper(ppufile:tcompilerppufile;const o:toper);override;
  227. procedure ppubuildderefimploper(var o:toper);override;
  228. procedure ppuderefoper(var o:toper);override;
  229. private
  230. { arm version info }
  231. fArmVMask,
  232. fArmMask : longword;
  233. { next fields are filled in pass1, so pass2 is faster }
  234. inssize : shortint;
  235. insoffset : longint;
  236. LastInsOffset : longint; { need to be public to be reset }
  237. insentry : PInsEntry;
  238. procedure BuildArmMasks(objdata:TObjData);
  239. function InsEnd:longint;
  240. procedure create_ot(objdata:TObjData);
  241. function Matches(p:PInsEntry):longint;
  242. function calcsize(p:PInsEntry):shortint;
  243. procedure gencode(objdata:TObjData);
  244. function NeedAddrPrefix(opidx:byte):boolean;
  245. procedure Swapoperands;
  246. function FindInsentry(objdata:TObjData):boolean;
  247. end;
  248. tai_align = class(tai_align_abstract)
  249. { nothing to add }
  250. end;
  251. function spilling_create_load(const ref:treference;r:tregister):Taicpu;
  252. function spilling_create_store(r:tregister; const ref:treference):Taicpu;
  253. function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
  254. function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
  255. function setcondition(i : taicpu;c : tasmcond) : taicpu;
  256. { inserts pc relative symbols at places where they are reachable
  257. and transforms special instructions to valid instruction encodings }
  258. procedure finalizearmcode(list,listtoinsert : TAsmList);
  259. { inserts .pdata section and dummy function prolog needed for arm-wince exception handling }
  260. procedure InsertPData;
  261. procedure InitAsm;
  262. procedure DoneAsm;
  263. implementation
  264. uses
  265. itcpugas,aoptcpu,
  266. systems,symdef;
  267. procedure taicpu.loadshifterop(opidx:longint;const so:tshifterop);
  268. begin
  269. allocate_oper(opidx+1);
  270. with oper[opidx]^ do
  271. begin
  272. if typ<>top_shifterop then
  273. begin
  274. clearop(opidx);
  275. new(shifterop);
  276. end;
  277. shifterop^:=so;
  278. typ:=top_shifterop;
  279. if assigned(add_reg_instruction_hook) then
  280. add_reg_instruction_hook(self,shifterop^.rs);
  281. end;
  282. end;
  283. procedure taicpu.loadrealconst(opidx:longint;const _value:bestreal);
  284. begin
  285. allocate_oper(opidx+1);
  286. with oper[opidx]^ do
  287. begin
  288. if typ<>top_realconst then
  289. clearop(opidx);
  290. val_real:=_value;
  291. typ:=top_realconst;
  292. end;
  293. end;
  294. procedure taicpu.loadregset(opidx:longint; regsetregtype: tregistertype; regsetsubregtype: tsubregister; const s:tcpuregisterset; ausermode: boolean);
  295. var
  296. i : byte;
  297. begin
  298. allocate_oper(opidx+1);
  299. with oper[opidx]^ do
  300. begin
  301. if typ<>top_regset then
  302. begin
  303. clearop(opidx);
  304. new(regset);
  305. end;
  306. regset^:=s;
  307. regtyp:=regsetregtype;
  308. subreg:=regsetsubregtype;
  309. usermode:=ausermode;
  310. typ:=top_regset;
  311. case regsetregtype of
  312. R_INTREGISTER:
  313. for i:=RS_R0 to RS_R15 do
  314. begin
  315. if assigned(add_reg_instruction_hook) and (i in regset^) then
  316. add_reg_instruction_hook(self,newreg(R_INTREGISTER,i,regsetsubregtype));
  317. end;
  318. R_MMREGISTER:
  319. { both RS_S0 and RS_D0 range from 0 to 31 }
  320. for i:=RS_D0 to RS_D31 do
  321. begin
  322. if assigned(add_reg_instruction_hook) and (i in regset^) then
  323. add_reg_instruction_hook(self,newreg(R_MMREGISTER,i,regsetsubregtype));
  324. end;
  325. else
  326. internalerror(2019050932);
  327. end;
  328. end;
  329. end;
  330. procedure taicpu.loadconditioncode(opidx:longint;const acond:tasmcond);
  331. begin
  332. allocate_oper(opidx+1);
  333. with oper[opidx]^ do
  334. begin
  335. if typ<>top_conditioncode then
  336. clearop(opidx);
  337. cc:=acond;
  338. typ:=top_conditioncode;
  339. end;
  340. end;
  341. procedure taicpu.loadmodeflags(opidx: longint; const _modeflags: tcpumodeflags);
  342. begin
  343. allocate_oper(opidx+1);
  344. with oper[opidx]^ do
  345. begin
  346. if typ<>top_modeflags then
  347. clearop(opidx);
  348. modeflags:=_modeflags;
  349. typ:=top_modeflags;
  350. end;
  351. end;
  352. procedure taicpu.loadspecialreg(opidx: longint; const areg: tregister; const aflags: tspecialregflags);
  353. begin
  354. allocate_oper(opidx+1);
  355. with oper[opidx]^ do
  356. begin
  357. if typ<>top_specialreg then
  358. clearop(opidx);
  359. specialreg:=areg;
  360. specialflags:=aflags;
  361. typ:=top_specialreg;
  362. end;
  363. end;
  364. {*****************************************************************************
  365. taicpu Constructors
  366. *****************************************************************************}
  367. constructor taicpu.op_none(op : tasmop);
  368. begin
  369. inherited create(op);
  370. end;
  371. { for pld }
  372. constructor taicpu.op_ref(op : tasmop;const _op1 : treference);
  373. begin
  374. inherited create(op);
  375. ops:=1;
  376. loadref(0,_op1);
  377. end;
  378. constructor taicpu.op_reg(op : tasmop;_op1 : tregister);
  379. begin
  380. inherited create(op);
  381. ops:=1;
  382. loadreg(0,_op1);
  383. end;
  384. constructor taicpu.op_const(op : tasmop;_op1 : longint);
  385. begin
  386. inherited create(op);
  387. ops:=1;
  388. loadconst(0,aint(_op1));
  389. end;
  390. constructor taicpu.op_reg_reg(op : tasmop;_op1,_op2 : tregister);
  391. begin
  392. inherited create(op);
  393. ops:=2;
  394. loadreg(0,_op1);
  395. loadreg(1,_op2);
  396. end;
  397. constructor taicpu.op_reg_const(op:tasmop; _op1: tregister; _op2: aint);
  398. begin
  399. inherited create(op);
  400. ops:=2;
  401. loadreg(0,_op1);
  402. loadconst(1,aint(_op2));
  403. end;
  404. constructor taicpu.op_regset(op: tasmop; regtype: tregistertype; subreg: tsubregister; _op1: tcpuregisterset);
  405. begin
  406. inherited create(op);
  407. ops:=1;
  408. loadregset(0,regtype,subreg,_op1);
  409. end;
  410. constructor taicpu.op_ref_regset(op:tasmop; _op1: treference; regtype: tregistertype; subreg: tsubregister; _op2: tcpuregisterset);
  411. begin
  412. inherited create(op);
  413. ops:=2;
  414. loadref(0,_op1);
  415. loadregset(1,regtype,subreg,_op2);
  416. end;
  417. constructor taicpu.op_reg_ref(op : tasmop;_op1 : tregister;const _op2 : treference);
  418. begin
  419. inherited create(op);
  420. ops:=2;
  421. loadreg(0,_op1);
  422. loadref(1,_op2);
  423. end;
  424. constructor taicpu.op_reg_reg_reg(op : tasmop;_op1,_op2,_op3 : tregister);
  425. begin
  426. inherited create(op);
  427. ops:=3;
  428. loadreg(0,_op1);
  429. loadreg(1,_op2);
  430. loadreg(2,_op3);
  431. end;
  432. constructor taicpu.op_reg_reg_reg_reg(op : tasmop;_op1,_op2,_op3,_op4 : tregister);
  433. begin
  434. inherited create(op);
  435. ops:=4;
  436. loadreg(0,_op1);
  437. loadreg(1,_op2);
  438. loadreg(2,_op3);
  439. loadreg(3,_op4);
  440. end;
  441. constructor taicpu.op_reg_realconst(op : tasmop; _op1 : tregister; _op2 : bestreal);
  442. begin
  443. inherited create(op);
  444. ops:=2;
  445. loadreg(0,_op1);
  446. loadrealconst(1,_op2);
  447. end;
  448. constructor taicpu.op_reg_reg_const(op : tasmop;_op1,_op2 : tregister; _op3: aint);
  449. begin
  450. inherited create(op);
  451. ops:=3;
  452. loadreg(0,_op1);
  453. loadreg(1,_op2);
  454. loadconst(2,aint(_op3));
  455. end;
  456. constructor taicpu.op_reg_const_const(op : tasmop;_op1 : tregister; _op2,_op3: aint);
  457. begin
  458. inherited create(op);
  459. ops:=3;
  460. loadreg(0,_op1);
  461. loadconst(1,aint(_op2));
  462. loadconst(2,aint(_op3));
  463. end;
  464. constructor taicpu.op_reg_reg_const_const(op: tasmop; _op1, _op2: tregister; _op3, _op4: aint);
  465. begin
  466. inherited create(op);
  467. ops:=4;
  468. loadreg(0,_op1);
  469. loadreg(1,_op2);
  470. loadconst(2,aint(_op3));
  471. loadconst(3,aint(_op4));
  472. end;
  473. constructor taicpu.op_reg_const_ref(op : tasmop;_op1 : tregister;_op2 : aint;_op3 : treference);
  474. begin
  475. inherited create(op);
  476. ops:=3;
  477. loadreg(0,_op1);
  478. loadconst(1,_op2);
  479. loadref(2,_op3);
  480. end;
  481. constructor taicpu.op_cond(op: tasmop; cond: tasmcond);
  482. begin
  483. inherited create(op);
  484. ops:=1;
  485. loadconditioncode(0, cond);
  486. end;
  487. constructor taicpu.op_modeflags(op: tasmop; _modeflags: tcpumodeflags);
  488. begin
  489. inherited create(op);
  490. ops := 1;
  491. loadmodeflags(0,_modeflags);
  492. end;
  493. constructor taicpu.op_modeflags_const(op: tasmop; _modeflags: tcpumodeflags; a: aint);
  494. begin
  495. inherited create(op);
  496. ops := 2;
  497. loadmodeflags(0,_modeflags);
  498. loadconst(1,a);
  499. end;
  500. constructor taicpu.op_specialreg_reg(op: tasmop; specialreg: tregister; specialregflags: tspecialregflags; _op2: tregister);
  501. begin
  502. inherited create(op);
  503. ops:=2;
  504. loadspecialreg(0,specialreg,specialregflags);
  505. loadreg(1,_op2);
  506. end;
  507. constructor taicpu.op_reg_reg_sym_ofs(op : tasmop;_op1,_op2 : tregister; _op3: tasmsymbol;_op3ofs: longint);
  508. begin
  509. inherited create(op);
  510. ops:=3;
  511. loadreg(0,_op1);
  512. loadreg(1,_op2);
  513. loadsymbol(0,_op3,_op3ofs);
  514. end;
  515. constructor taicpu.op_reg_reg_ref(op : tasmop;_op1,_op2 : tregister; const _op3: treference);
  516. begin
  517. inherited create(op);
  518. ops:=3;
  519. loadreg(0,_op1);
  520. loadreg(1,_op2);
  521. loadref(2,_op3);
  522. end;
  523. constructor taicpu.op_reg_reg_shifterop(op : tasmop;_op1,_op2 : tregister;_op3 : tshifterop);
  524. begin
  525. inherited create(op);
  526. ops:=3;
  527. loadreg(0,_op1);
  528. loadreg(1,_op2);
  529. loadshifterop(2,_op3);
  530. end;
  531. constructor taicpu.op_reg_reg_reg_shifterop(op : tasmop;_op1,_op2,_op3 : tregister;_op4 : tshifterop);
  532. begin
  533. inherited create(op);
  534. ops:=4;
  535. loadreg(0,_op1);
  536. loadreg(1,_op2);
  537. loadreg(2,_op3);
  538. loadshifterop(3,_op4);
  539. end;
  540. constructor taicpu.op_cond_sym(op : tasmop;cond:TAsmCond;_op1 : tasmsymbol);
  541. begin
  542. inherited create(op);
  543. condition:=cond;
  544. ops:=1;
  545. loadsymbol(0,_op1,0);
  546. end;
  547. constructor taicpu.op_sym(op : tasmop;_op1 : tasmsymbol);
  548. begin
  549. inherited create(op);
  550. ops:=1;
  551. loadsymbol(0,_op1,0);
  552. end;
  553. constructor taicpu.op_sym_ofs(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint);
  554. begin
  555. inherited create(op);
  556. ops:=1;
  557. loadsymbol(0,_op1,_op1ofs);
  558. end;
  559. constructor taicpu.op_reg_sym_ofs(op : tasmop;_op1 : tregister;_op2:tasmsymbol;_op2ofs : longint);
  560. begin
  561. inherited create(op);
  562. ops:=2;
  563. loadreg(0,_op1);
  564. loadsymbol(1,_op2,_op2ofs);
  565. end;
  566. constructor taicpu.op_sym_ofs_ref(op : tasmop;_op1 : tasmsymbol;_op1ofs:longint;const _op2 : treference);
  567. begin
  568. inherited create(op);
  569. ops:=2;
  570. loadsymbol(0,_op1,_op1ofs);
  571. loadref(1,_op2);
  572. end;
  573. function taicpu.is_same_reg_move(regtype: Tregistertype):boolean;
  574. begin
  575. { allow the register allocator to remove unnecessary moves }
  576. result:=(
  577. ((opcode=A_MOV) and (regtype = R_INTREGISTER)) or
  578. ((opcode=A_MVF) and (regtype = R_FPUREGISTER)) or
  579. ((opcode in [A_FCPYS, A_FCPYD]) and (regtype = R_MMREGISTER)) or
  580. ((opcode in [A_VMOV]) and (regtype = R_MMREGISTER) and (oppostfix in [PF_F32,PF_F64]))
  581. ) and
  582. ((oppostfix in [PF_None,PF_D]) or (opcode = A_VMOV)) and
  583. (condition=C_None) and
  584. (ops=2) and
  585. (oper[0]^.typ=top_reg) and
  586. (oper[1]^.typ=top_reg) and
  587. (oper[0]^.reg=oper[1]^.reg);
  588. end;
  589. function spilling_create_load(const ref:treference;r:tregister):Taicpu;
  590. begin
  591. case getregtype(r) of
  592. R_INTREGISTER :
  593. result:=taicpu.op_reg_ref(A_LDR,r,ref);
  594. R_FPUREGISTER :
  595. { use lfm because we don't know the current internal format
  596. and avoid exceptions
  597. }
  598. result:=taicpu.op_reg_const_ref(A_LFM,r,1,ref);
  599. R_MMREGISTER :
  600. result:=taicpu.op_reg_ref(A_VLDR,r,ref);
  601. else
  602. internalerror(2004010415);
  603. end;
  604. end;
  605. function spilling_create_store(r:tregister; const ref:treference):Taicpu;
  606. begin
  607. case getregtype(r) of
  608. R_INTREGISTER :
  609. result:=taicpu.op_reg_ref(A_STR,r,ref);
  610. R_FPUREGISTER :
  611. { use sfm because we don't know the current internal format
  612. and avoid exceptions
  613. }
  614. result:=taicpu.op_reg_const_ref(A_SFM,r,1,ref);
  615. R_MMREGISTER :
  616. result:=taicpu.op_reg_ref(A_VSTR,r,ref);
  617. else
  618. internalerror(2004010416);
  619. end;
  620. end;
  621. function taicpu.spilling_get_operation_type(opnr: longint): topertype;
  622. begin
  623. if GenerateThumbCode then
  624. case opcode of
  625. A_ADC,A_ADD,A_AND,A_BIC,
  626. A_EOR,A_CLZ,A_RBIT,
  627. A_LDR,A_LDRB,A_LDRBT,A_LDRH,A_LDRSB,
  628. A_LDRSH,A_LDRT,
  629. A_MOV,A_MVN,A_MLA,A_MUL,
  630. A_ORR,A_RSB,A_RSC,A_SBC,A_SUB,
  631. A_SWP,A_SWPB,
  632. A_LDF,A_FLT,A_FIX,
  633. A_ADF,A_DVF,A_FDV,A_FML,
  634. A_RFS,A_RFC,A_RDF,
  635. A_RMF,A_RPW,A_RSF,A_SUF,A_ABS,A_ACS,A_ASN,A_ATN,A_COS,
  636. A_EXP,A_LOG,A_LGN,A_MVF,A_MNF,A_FRD,A_MUF,A_POL,A_RND,A_SIN,A_SQT,A_TAN,
  637. A_LFM,
  638. A_FLDS,A_FLDD,
  639. A_FMRX,A_FMXR,A_FMSTAT,
  640. A_FMSR,A_FMRS,A_FMDRR,
  641. A_FCPYS,A_FCPYD,A_FCVTSD,A_FCVTDS,
  642. A_FABSS,A_FABSD,A_FSQRTS,A_FSQRTD,A_FMULS,A_FMULD,
  643. A_FADDS,A_FADDD,A_FSUBS,A_FSUBD,A_FDIVS,A_FDIVD,
  644. A_FMACS,A_FMACD,A_FMSCS,A_FMSCD,A_FNMACS,A_FNMACD,
  645. A_FNMSCS,A_FNMSCD,A_FNMULS,A_FNMULD,
  646. A_FMDHR,A_FMRDH,A_FMDLR,A_FMRDL,
  647. A_FNEGS,A_FNEGD,
  648. A_FSITOS,A_FSITOD,A_FTOSIS,A_FTOSID,
  649. A_FTOUIS,A_FTOUID,A_FUITOS,A_FUITOD,
  650. A_SXTB16,A_UXTB16,
  651. A_UXTB,A_UXTH,A_SXTB,A_SXTH,
  652. A_NEG,
  653. A_VABS,A_VADD,A_VCVT,A_VDIV,A_VLDR,A_VMOV,A_VMUL,A_VNEG,A_VSQRT,A_VSUB,
  654. A_MRS,A_MSR:
  655. if opnr=0 then
  656. result:=operand_readwrite
  657. else
  658. result:=operand_read;
  659. A_BKPT,A_B,A_BL,A_BLX,A_BX,
  660. A_CMN,A_CMP,A_TEQ,A_TST,
  661. A_CMF,A_CMFE,A_WFS,A_CNF,
  662. A_FCMPS,A_FCMPD,A_FCMPES,A_FCMPED,A_FCMPEZS,A_FCMPEZD,
  663. A_FCMPZS,A_FCMPZD,
  664. A_VCMP,A_VCMPE:
  665. result:=operand_read;
  666. A_SMLAL,A_UMLAL:
  667. if opnr in [0,1] then
  668. result:=operand_readwrite
  669. else
  670. result:=operand_read;
  671. A_SMULL,A_UMULL,
  672. A_FMRRD:
  673. if opnr in [0,1] then
  674. result:=operand_readwrite
  675. else
  676. result:=operand_read;
  677. A_STR,A_STRB,A_STRBT,
  678. A_STRH,A_STRT,A_STF,A_SFM,
  679. A_FSTS,A_FSTD,
  680. A_VSTR:
  681. { important is what happens with the involved registers }
  682. if opnr=0 then
  683. result := operand_read
  684. else
  685. { check for pre/post indexed }
  686. result := operand_read;
  687. //Thumb2
  688. A_LSL, A_LSR, A_ROR, A_ASR, A_SDIV, A_UDIV, A_MOVW, A_MOVT, A_MLS, A_BFI,
  689. A_SMMLA,A_SMMLS:
  690. if opnr in [0] then
  691. result:=operand_readwrite
  692. else
  693. result:=operand_read;
  694. A_BFC:
  695. if opnr in [0] then
  696. result:=operand_readwrite
  697. else
  698. result:=operand_read;
  699. A_LDREX:
  700. if opnr in [0] then
  701. result:=operand_readwrite
  702. else
  703. result:=operand_read;
  704. A_STREX:
  705. result:=operand_write;
  706. else
  707. internalerror(200403151);
  708. end
  709. else
  710. case opcode of
  711. A_ADC,A_ADD,A_AND,A_BIC,A_ORN,
  712. A_EOR,A_CLZ,A_RBIT,
  713. A_LDR,A_LDRB,A_LDRBT,A_LDRH,A_LDRSB,
  714. A_LDRSH,A_LDRT,
  715. A_MOV,A_MVN,A_MLA,A_MUL,
  716. A_ORR,A_RSB,A_RSC,A_SBC,A_SUB,
  717. A_SWP,A_SWPB,
  718. A_LDF,A_FLT,A_FIX,
  719. A_ADF,A_DVF,A_FDV,A_FML,
  720. A_RFS,A_RFC,A_RDF,
  721. A_RMF,A_RPW,A_RSF,A_SUF,A_ABS,A_ACS,A_ASN,A_ATN,A_COS,
  722. A_EXP,A_LOG,A_LGN,A_MVF,A_MNF,A_FRD,A_MUF,A_POL,A_RND,A_SIN,A_SQT,A_TAN,
  723. A_LFM,
  724. A_FLDS,A_FLDD,
  725. A_FMRX,A_FMXR,A_FMSTAT,
  726. A_FMSR,A_FMRS,A_FMDRR,
  727. A_FCPYS,A_FCPYD,A_FCVTSD,A_FCVTDS,
  728. A_FABSS,A_FABSD,A_FSQRTS,A_FSQRTD,A_FMULS,A_FMULD,
  729. A_FADDS,A_FADDD,A_FSUBS,A_FSUBD,A_FDIVS,A_FDIVD,
  730. A_FMACS,A_FMACD,A_FMSCS,A_FMSCD,A_FNMACS,A_FNMACD,
  731. A_FNMSCS,A_FNMSCD,A_FNMULS,A_FNMULD,
  732. A_FMDHR,A_FMRDH,A_FMDLR,A_FMRDL,
  733. A_FNEGS,A_FNEGD,
  734. A_FSITOS,A_FSITOD,A_FTOSIS,A_FTOSID,
  735. A_FTOUIS,A_FTOUID,A_FUITOS,A_FUITOD,
  736. A_SXTB16,A_UXTB16,
  737. A_UXTB,A_UXTH,A_SXTB,A_SXTH,
  738. A_NEG,
  739. A_VABS,A_VADD,A_VCVT,A_VDIV,A_VLDR,A_VMOV,A_VMUL,A_VNEG,A_VSQRT,A_VSUB,
  740. A_VEOR,
  741. A_VMRS,A_VMSR,
  742. A_MRS,A_MSR:
  743. if opnr=0 then
  744. result:=operand_write
  745. else
  746. result:=operand_read;
  747. A_BKPT,A_B,A_BL,A_BLX,A_BX,
  748. A_CMN,A_CMP,A_TEQ,A_TST,
  749. A_CMF,A_CMFE,A_WFS,A_CNF,
  750. A_FCMPS,A_FCMPD,A_FCMPES,A_FCMPED,A_FCMPEZS,A_FCMPEZD,
  751. A_FCMPZS,A_FCMPZD,
  752. A_VCMP,A_VCMPE:
  753. result:=operand_read;
  754. A_SMLAL,A_UMLAL:
  755. if opnr in [0,1] then
  756. result:=operand_readwrite
  757. else
  758. result:=operand_read;
  759. A_SMULL,A_UMULL,
  760. A_FMRRD:
  761. if opnr in [0,1] then
  762. result:=operand_write
  763. else
  764. result:=operand_read;
  765. A_STR,A_STRB,A_STRBT,
  766. A_STRH,A_STRT,A_STF,A_SFM,
  767. A_FSTS,A_FSTD,
  768. A_VSTR:
  769. { important is what happens with the involved registers }
  770. if opnr=0 then
  771. result := operand_read
  772. else
  773. { check for pre/post indexed }
  774. result := operand_read;
  775. //Thumb2
  776. A_LSL, A_LSR, A_ROR, A_ASR, A_SDIV, A_UDIV, A_MOVW, A_MOVT, A_MLS, A_BFI,
  777. A_QADD,
  778. A_PKHTB,A_PKHBT,
  779. A_SMMLA,A_SMMLS,A_SMUAD,A_SMUSD:
  780. if opnr in [0] then
  781. result:=operand_write
  782. else
  783. result:=operand_read;
  784. A_VFMA,A_VFMS,A_VFNMA,A_VFNMS,
  785. A_BFC:
  786. if opnr in [0] then
  787. result:=operand_readwrite
  788. else
  789. result:=operand_read;
  790. A_LDREX:
  791. if opnr in [0] then
  792. result:=operand_write
  793. else
  794. result:=operand_read;
  795. A_STREX:
  796. result:=operand_write;
  797. else
  798. begin
  799. writeln(opcode);
  800. internalerror(2004031502);
  801. end;
  802. end;
  803. end;
  804. function taicpu.spilling_get_operation_type_ref(opnr: longint; reg: tregister): topertype;
  805. begin
  806. result := operand_read;
  807. if (oper[opnr]^.ref^.base = reg) and
  808. (oper[opnr]^.ref^.addressmode in [AM_PREINDEXED,AM_POSTINDEXED]) then
  809. result := operand_readwrite;
  810. end;
  811. procedure BuildInsTabCache;
  812. var
  813. i : longint;
  814. begin
  815. new(instabcache);
  816. FillChar(instabcache^,sizeof(tinstabcache),$ff);
  817. i:=0;
  818. while (i<InsTabEntries) do
  819. begin
  820. if InsTabCache^[InsTab[i].Opcode]=-1 then
  821. InsTabCache^[InsTab[i].Opcode]:=i;
  822. inc(i);
  823. end;
  824. end;
  825. procedure InitAsm;
  826. begin
  827. if not assigned(instabcache) then
  828. BuildInsTabCache;
  829. end;
  830. procedure DoneAsm;
  831. begin
  832. if assigned(instabcache) then
  833. begin
  834. dispose(instabcache);
  835. instabcache:=nil;
  836. end;
  837. end;
  838. function setoppostfix(i : taicpu;pf : toppostfix) : taicpu;
  839. begin
  840. i.oppostfix:=pf;
  841. result:=i;
  842. end;
  843. function setroundingmode(i : taicpu;rm : troundingmode) : taicpu;
  844. begin
  845. i.roundingmode:=rm;
  846. result:=i;
  847. end;
  848. function setcondition(i : taicpu;c : tasmcond) : taicpu;
  849. begin
  850. i.condition:=c;
  851. result:=i;
  852. end;
  853. Function SimpleGetNextInstruction(Current: tai; Var Next: tai): Boolean;
  854. Begin
  855. Current:=tai(Current.Next);
  856. While Assigned(Current) And (Current.typ In SkipInstr) Do
  857. Current:=tai(Current.Next);
  858. Next:=Current;
  859. If Assigned(Next) And Not(Next.typ In SkipInstr) Then
  860. Result:=True
  861. Else
  862. Begin
  863. Next:=Nil;
  864. Result:=False;
  865. End;
  866. End;
  867. (*
  868. function armconstequal(hp1,hp2: tai): boolean;
  869. begin
  870. result:=false;
  871. if hp1.typ<>hp2.typ then
  872. exit;
  873. case hp1.typ of
  874. tai_const:
  875. result:=
  876. (tai_const(hp2).sym=tai_const(hp).sym) and
  877. (tai_const(hp2).value=tai_const(hp).value) and
  878. (tai(hp2.previous).typ=ait_label);
  879. tai_const:
  880. result:=
  881. (tai_const(hp2).sym=tai_const(hp).sym) and
  882. (tai_const(hp2).value=tai_const(hp).value) and
  883. (tai(hp2.previous).typ=ait_label);
  884. end;
  885. end;
  886. *)
  887. procedure insertpcrelativedata(list,listtoinsert : TAsmList);
  888. var
  889. limit: longint;
  890. { FLD/FST VFP instructions have a limit of +/- 1024, not 4096, this
  891. function checks the next count instructions if the limit must be
  892. decreased }
  893. procedure CheckLimit(hp : tai;count : integer);
  894. var
  895. i : Integer;
  896. begin
  897. for i:=1 to count do
  898. if SimpleGetNextInstruction(hp,hp) and
  899. (tai(hp).typ=ait_instruction) and
  900. ((taicpu(hp).opcode=A_FLDS) or
  901. (taicpu(hp).opcode=A_FLDD) or
  902. (taicpu(hp).opcode=A_VLDR) or
  903. (taicpu(hp).opcode=A_LDF) or
  904. (taicpu(hp).opcode=A_STF)) then
  905. limit:=254;
  906. end;
  907. function is_case_dispatch(hp: taicpu): boolean;
  908. begin
  909. result:=
  910. ((taicpu(hp).opcode in [A_ADD,A_LDR]) and
  911. not(GenerateThumbCode or GenerateThumb2Code) and
  912. (taicpu(hp).oper[0]^.typ=top_reg) and
  913. (taicpu(hp).oper[0]^.reg=NR_PC)) or
  914. ((taicpu(hp).opcode=A_MOV) and (GenerateThumbCode) and
  915. (taicpu(hp).oper[0]^.typ=top_reg) and
  916. (taicpu(hp).oper[0]^.reg=NR_PC)) or
  917. (taicpu(hp).opcode=A_TBH) or
  918. (taicpu(hp).opcode=A_TBB);
  919. end;
  920. var
  921. curinspos,
  922. penalty,
  923. lastinspos,
  924. { increased for every data element > 4 bytes inserted }
  925. extradataoffset,
  926. curop : longint;
  927. curtai,
  928. inserttai : tai;
  929. curdatatai,hp,hp2 : tai;
  930. curdata : TAsmList;
  931. l : tasmlabel;
  932. doinsert,
  933. removeref : boolean;
  934. multiplier : byte;
  935. begin
  936. curdata:=TAsmList.create;
  937. lastinspos:=-1;
  938. curinspos:=0;
  939. extradataoffset:=0;
  940. if GenerateThumbCode then
  941. begin
  942. multiplier:=2;
  943. limit:=504;
  944. end
  945. else
  946. begin
  947. limit:=1016;
  948. multiplier:=1;
  949. end;
  950. curtai:=tai(list.first);
  951. doinsert:=false;
  952. while assigned(curtai) do
  953. begin
  954. { instruction? }
  955. case curtai.typ of
  956. ait_instruction:
  957. begin
  958. { walk through all operand of the instruction }
  959. for curop:=0 to taicpu(curtai).ops-1 do
  960. begin
  961. { reference? }
  962. if (taicpu(curtai).oper[curop]^.typ=top_ref) then
  963. begin
  964. { pc relative symbol? }
  965. curdatatai:=tai(taicpu(curtai).oper[curop]^.ref^.symboldata);
  966. if assigned(curdatatai) then
  967. begin
  968. { create a new copy of a data entry on arm thumb if the entry has been inserted already
  969. before because arm thumb does not allow pc relative negative offsets }
  970. if (GenerateThumbCode) and
  971. tai_label(curdatatai).inserted then
  972. begin
  973. current_asmdata.getjumplabel(l);
  974. hp:=tai_label.create(l);
  975. listtoinsert.Concat(hp);
  976. hp2:=tai(curdatatai.Next.GetCopy);
  977. hp2.Next:=nil;
  978. hp2.Previous:=nil;
  979. listtoinsert.Concat(hp2);
  980. taicpu(curtai).oper[curop]^.ref^.symboldata:=hp;
  981. taicpu(curtai).oper[curop]^.ref^.symbol:=l;
  982. l.increfs;
  983. curdatatai:=hp;
  984. end;
  985. { move only if we're at the first reference of a label }
  986. if not(tai_label(curdatatai).moved) then
  987. begin
  988. tai_label(curdatatai).moved:=true;
  989. { check if symbol already used. }
  990. { if yes, reuse the symbol }
  991. hp:=tai(curdatatai.next);
  992. removeref:=false;
  993. if assigned(hp) then
  994. begin
  995. case hp.typ of
  996. ait_const:
  997. begin
  998. if (tai_const(hp).consttype=aitconst_64bit) then
  999. inc(extradataoffset,multiplier);
  1000. end;
  1001. ait_realconst:
  1002. begin
  1003. inc(extradataoffset,multiplier*(((tai_realconst(hp).savesize-4)+3) div 4));
  1004. end;
  1005. else
  1006. ;
  1007. end;
  1008. { check if the same constant has been already inserted into the currently handled list,
  1009. if yes, reuse it }
  1010. if (hp.typ=ait_const) then
  1011. begin
  1012. hp2:=tai(curdata.first);
  1013. while assigned(hp2) do
  1014. begin
  1015. if (hp2.typ=ait_const) and (tai_const(hp2).sym=tai_const(hp).sym)
  1016. and (tai_const(hp2).value=tai_const(hp).value) and (tai(hp2.previous).typ=ait_label) and
  1017. { gottpoff and tlsgd symbols are PC relative, so we cannot reuse them }
  1018. (not(tai_const(hp2).consttype in [aitconst_gottpoff,aitconst_tlsgd,aitconst_tlsdesc])) then
  1019. begin
  1020. with taicpu(curtai).oper[curop]^.ref^ do
  1021. begin
  1022. symboldata:=hp2.previous;
  1023. symbol:=tai_label(hp2.previous).labsym;
  1024. end;
  1025. removeref:=true;
  1026. break;
  1027. end;
  1028. hp2:=tai(hp2.next);
  1029. end;
  1030. end;
  1031. end;
  1032. { move or remove symbol reference }
  1033. repeat
  1034. hp:=tai(curdatatai.next);
  1035. listtoinsert.remove(curdatatai);
  1036. if removeref then
  1037. curdatatai.free
  1038. else
  1039. curdata.concat(curdatatai);
  1040. curdatatai:=hp;
  1041. until (curdatatai=nil) or (curdatatai.typ=ait_label);
  1042. if lastinspos=-1 then
  1043. lastinspos:=curinspos;
  1044. end;
  1045. end;
  1046. end;
  1047. end;
  1048. inc(curinspos,multiplier);
  1049. end;
  1050. ait_align:
  1051. begin
  1052. { code is always 4 byte aligned, so we don't have to take care of .align 2 which would
  1053. requires also incrementing curinspos by 1 }
  1054. inc(curinspos,(tai_align(curtai).aligntype div 4)*multiplier);
  1055. end;
  1056. ait_const:
  1057. begin
  1058. inc(curinspos,multiplier);
  1059. if (tai_const(curtai).consttype=aitconst_64bit) then
  1060. inc(curinspos,multiplier);
  1061. end;
  1062. ait_realconst:
  1063. begin
  1064. inc(curinspos,multiplier*((tai_realconst(hp).savesize+3) div 4));
  1065. end;
  1066. else
  1067. ;
  1068. end;
  1069. { special case for case jump tables }
  1070. penalty:=0;
  1071. if SimpleGetNextInstruction(curtai,hp) and
  1072. (tai(hp).typ=ait_instruction) then
  1073. begin
  1074. case taicpu(hp).opcode of
  1075. A_MOV,
  1076. A_LDR,
  1077. A_ADD,
  1078. A_TBH,
  1079. A_TBB:
  1080. { approximation if we hit a case jump table }
  1081. if is_case_dispatch(taicpu(hp)) then
  1082. begin
  1083. penalty:=multiplier;
  1084. hp:=tai(hp.next);
  1085. { skip register allocations and comments inserted by the optimizer as well as a label and align
  1086. as jump tables for thumb might have }
  1087. while assigned(hp) and (hp.typ in [ait_comment,ait_regalloc,ait_label,ait_align]) do
  1088. hp:=tai(hp.next);
  1089. while assigned(hp) and (hp.typ=ait_const) do
  1090. begin
  1091. inc(penalty,multiplier);
  1092. hp:=tai(hp.next);
  1093. end;
  1094. end;
  1095. A_IT:
  1096. begin
  1097. if GenerateThumb2Code then
  1098. penalty:=multiplier;
  1099. { check if the next instruction fits as well
  1100. or if we splitted after the it so split before }
  1101. CheckLimit(hp,1);
  1102. end;
  1103. A_ITE,
  1104. A_ITT:
  1105. begin
  1106. if GenerateThumb2Code then
  1107. penalty:=2*multiplier;
  1108. { check if the next two instructions fit as well
  1109. or if we splitted them so split before }
  1110. CheckLimit(hp,2);
  1111. end;
  1112. A_ITEE,
  1113. A_ITTE,
  1114. A_ITET,
  1115. A_ITTT:
  1116. begin
  1117. if GenerateThumb2Code then
  1118. penalty:=3*multiplier;
  1119. { check if the next three instructions fit as well
  1120. or if we splitted them so split before }
  1121. CheckLimit(hp,3);
  1122. end;
  1123. A_ITEEE,
  1124. A_ITTEE,
  1125. A_ITETE,
  1126. A_ITTTE,
  1127. A_ITEET,
  1128. A_ITTET,
  1129. A_ITETT,
  1130. A_ITTTT:
  1131. begin
  1132. if GenerateThumb2Code then
  1133. penalty:=4*multiplier;
  1134. { check if the next three instructions fit as well
  1135. or if we splitted them so split before }
  1136. CheckLimit(hp,4);
  1137. end;
  1138. else
  1139. ;
  1140. end;
  1141. end;
  1142. CheckLimit(curtai,1);
  1143. { don't miss an insert }
  1144. doinsert:=doinsert or
  1145. (not(curdata.empty) and
  1146. (curinspos-lastinspos+penalty+extradataoffset>limit));
  1147. { split only at real instructions else the test below fails }
  1148. if doinsert and (curtai.typ=ait_instruction) and
  1149. (
  1150. { don't split loads of pc to lr and the following move }
  1151. not(
  1152. (taicpu(curtai).opcode=A_MOV) and
  1153. (taicpu(curtai).oper[0]^.typ=top_reg) and
  1154. (taicpu(curtai).oper[0]^.reg=NR_R14) and
  1155. (taicpu(curtai).oper[1]^.typ=top_reg) and
  1156. (taicpu(curtai).oper[1]^.reg=NR_PC)
  1157. )
  1158. ) and
  1159. (
  1160. { do not insert data after a B instruction due to their limited range }
  1161. not((GenerateThumbCode) and
  1162. (taicpu(curtai).opcode=A_B)
  1163. )
  1164. ) then
  1165. begin
  1166. lastinspos:=-1;
  1167. extradataoffset:=0;
  1168. if GenerateThumbCode then
  1169. limit:=502
  1170. else
  1171. limit:=1016;
  1172. { if this is an add/tbh/tbb-based jumptable, go back to the
  1173. previous instruction, because inserting data between the
  1174. dispatch instruction and the table would mess up the
  1175. addresses }
  1176. inserttai:=curtai;
  1177. if is_case_dispatch(taicpu(inserttai)) and
  1178. ((taicpu(inserttai).opcode=A_ADD) or
  1179. (taicpu(inserttai).opcode=A_TBH) or
  1180. (taicpu(inserttai).opcode=A_TBB)) then
  1181. begin
  1182. repeat
  1183. inserttai:=tai(inserttai.previous);
  1184. until inserttai.typ=ait_instruction;
  1185. { if it's an add-based jump table, then also skip the
  1186. pc-relative load }
  1187. if taicpu(curtai).opcode=A_ADD then
  1188. repeat
  1189. inserttai:=tai(inserttai.previous);
  1190. until inserttai.typ=ait_instruction;
  1191. end
  1192. else
  1193. { on arm thumb, insert the data always after all labels etc. following an instruction so it
  1194. is prevent that a bxx yyy; bl xxx; yyyy: sequence gets separated ( we never insert on arm thumb after
  1195. bxx) and the distance of bxx gets too long }
  1196. if GenerateThumbCode then
  1197. while assigned(tai(inserttai.Next)) and (tai(inserttai.Next).typ in SkipInstr+[ait_label]) do
  1198. inserttai:=tai(inserttai.next);
  1199. doinsert:=false;
  1200. current_asmdata.getjumplabel(l);
  1201. { align jump in thumb .text section to 4 bytes }
  1202. if not(curdata.empty) and (GenerateThumbCode) then
  1203. curdata.Insert(tai_align.Create(4));
  1204. curdata.insert(taicpu.op_sym(A_B,l));
  1205. curdata.concat(tai_label.create(l));
  1206. { mark all labels as inserted, arm thumb
  1207. needs this, so data referencing an already inserted label can be
  1208. duplicated because arm thumb does not allow negative pc relative offset }
  1209. hp2:=tai(curdata.first);
  1210. while assigned(hp2) do
  1211. begin
  1212. if hp2.typ=ait_label then
  1213. tai_label(hp2).inserted:=true;
  1214. hp2:=tai(hp2.next);
  1215. end;
  1216. { continue with the last inserted label because we use later
  1217. on SimpleGetNextInstruction, so if we used curtai.next (which
  1218. is then equal curdata.last.previous) we could over see one
  1219. instruction }
  1220. hp:=tai(curdata.Last);
  1221. list.insertlistafter(inserttai,curdata);
  1222. curtai:=hp;
  1223. end
  1224. else
  1225. curtai:=tai(curtai.next);
  1226. end;
  1227. { align jump in thumb .text section to 4 bytes }
  1228. if not(curdata.empty) and (GenerateThumbCode or GenerateThumb2Code) then
  1229. curdata.Insert(tai_align.Create(4));
  1230. list.concatlist(curdata);
  1231. curdata.free;
  1232. end;
  1233. procedure ensurethumb2encodings(list: TAsmList);
  1234. var
  1235. curtai: tai;
  1236. op2reg: TRegister;
  1237. begin
  1238. { Do Thumb-2 16bit -> 32bit transformations }
  1239. curtai:=tai(list.first);
  1240. while assigned(curtai) do
  1241. begin
  1242. case curtai.typ of
  1243. ait_instruction:
  1244. begin
  1245. case taicpu(curtai).opcode of
  1246. A_ADD:
  1247. begin
  1248. { Set wide flag for ADD Rd,Rn,Rm where registers are over R7(high register set) }
  1249. if taicpu(curtai).ops = 3 then
  1250. begin
  1251. if taicpu(curtai).oper[2]^.typ in [top_reg,top_shifterop] then
  1252. begin
  1253. if taicpu(curtai).oper[2]^.typ = top_reg then
  1254. op2reg := taicpu(curtai).oper[2]^.reg
  1255. else if taicpu(curtai).oper[2]^.shifterop^.rs <> NR_NO then
  1256. op2reg := taicpu(curtai).oper[2]^.shifterop^.rs
  1257. else
  1258. op2reg := NR_NO;
  1259. if op2reg <> NR_NO then
  1260. begin
  1261. if (taicpu(curtai).oper[0]^.reg >= NR_R8) or
  1262. (taicpu(curtai).oper[1]^.reg >= NR_R8) or
  1263. (op2reg >= NR_R8) then
  1264. begin
  1265. include(taicpu(curtai).flags,cf_wideformat);
  1266. { Handle special cases where register rules are violated by optimizer/user }
  1267. { if d == 13 || (d == 15 && S == ‘0’) || n == 15 || m IN [13,15] then UNPREDICTABLE; }
  1268. { Transform ADD.W Rx, Ry, R13 into ADD.W Rx, R13, Ry }
  1269. if (op2reg = NR_R13) and (taicpu(curtai).oper[2]^.typ = top_reg) then
  1270. begin
  1271. taicpu(curtai).oper[2]^.reg := taicpu(curtai).oper[1]^.reg;
  1272. taicpu(curtai).oper[1]^.reg := op2reg;
  1273. end;
  1274. end;
  1275. end;
  1276. end;
  1277. end;
  1278. end;
  1279. else;
  1280. end;
  1281. end;
  1282. else
  1283. ;
  1284. end;
  1285. curtai:=tai(curtai.Next);
  1286. end;
  1287. end;
  1288. procedure ensurethumbencodings(list: TAsmList);
  1289. var
  1290. curtai: tai;
  1291. begin
  1292. { Do Thumb 16bit transformations to form valid instruction forms }
  1293. curtai:=tai(list.first);
  1294. while assigned(curtai) do
  1295. begin
  1296. case curtai.typ of
  1297. ait_instruction:
  1298. begin
  1299. case taicpu(curtai).opcode of
  1300. A_STM:
  1301. begin
  1302. if (taicpu(curtai).ops=2) and
  1303. (taicpu(curtai).oper[0]^.typ=top_ref) and
  1304. (taicpu(curtai).oper[0]^.ref^.index=NR_STACK_POINTER_REG) and
  1305. (taicpu(curtai).oper[0]^.ref^.addressmode=AM_PREINDEXED) and
  1306. (taicpu(curtai).oppostfix in [PF_FD,PF_DB]) then
  1307. begin
  1308. taicpu(curtai).oppostfix:=PF_None;
  1309. taicpu(curtai).loadregset(0, taicpu(curtai).oper[1]^.regtyp, taicpu(curtai).oper[1]^.subreg, taicpu(curtai).oper[1]^.regset^);
  1310. taicpu(curtai).ops:=1;
  1311. taicpu(curtai).opcode:=A_PUSH;
  1312. end;
  1313. end;
  1314. A_LDM:
  1315. begin
  1316. if (taicpu(curtai).ops=2) and
  1317. (taicpu(curtai).oper[0]^.typ=top_ref) and
  1318. (taicpu(curtai).oper[0]^.ref^.index=NR_STACK_POINTER_REG) and
  1319. (taicpu(curtai).oper[0]^.ref^.addressmode=AM_PREINDEXED) and
  1320. (taicpu(curtai).oppostfix in [PF_FD,PF_IA]) then
  1321. begin
  1322. taicpu(curtai).oppostfix:=PF_None;
  1323. taicpu(curtai).loadregset(0, taicpu(curtai).oper[1]^.regtyp, taicpu(curtai).oper[1]^.subreg, taicpu(curtai).oper[1]^.regset^);
  1324. taicpu(curtai).ops:=1;
  1325. taicpu(curtai).opcode:=A_POP;
  1326. end;
  1327. end;
  1328. A_ADD,
  1329. A_AND,A_EOR,A_ORR,A_BIC,
  1330. A_LSL,A_LSR,A_ASR,A_ROR,
  1331. A_ADC,A_SBC:
  1332. begin
  1333. if (taicpu(curtai).ops = 3) and
  1334. (taicpu(curtai).oper[2]^.typ=top_reg) and
  1335. (taicpu(curtai).oper[0]^.reg=taicpu(curtai).oper[1]^.reg) and
  1336. (taicpu(curtai).oper[0]^.reg<>NR_STACK_POINTER_REG) then
  1337. begin
  1338. taicpu(curtai).oper[1]^.reg:=taicpu(curtai).oper[2]^.reg;
  1339. taicpu(curtai).ops:=2;
  1340. end;
  1341. end;
  1342. else
  1343. ;
  1344. end;
  1345. end;
  1346. else
  1347. ;
  1348. end;
  1349. curtai:=tai(curtai.Next);
  1350. end;
  1351. end;
  1352. function getMergedInstruction(FirstOp,LastOp:TAsmOp;InvertLast:boolean) : TAsmOp;
  1353. const
  1354. opTable: array[A_IT..A_ITTTT] of string =
  1355. ('T','TE','TT','TEE','TTE','TET','TTT',
  1356. 'TEEE','TTEE','TETE','TTTE',
  1357. 'TEET','TTET','TETT','TTTT');
  1358. invertedOpTable: array[A_IT..A_ITTTT] of string =
  1359. ('E','ET','EE','ETT','EET','ETE','EEE',
  1360. 'ETTT','EETT','ETET','EEET',
  1361. 'ETTE','EETE','ETEE','EEEE');
  1362. var
  1363. resStr : string;
  1364. i : TAsmOp;
  1365. begin
  1366. if InvertLast then
  1367. resStr := opTable[FirstOp]+invertedOpTable[LastOp]
  1368. else
  1369. resStr := opTable[FirstOp]+opTable[LastOp];
  1370. if length(resStr) > 4 then
  1371. internalerror(2012100805);
  1372. for i := low(opTable) to high(opTable) do
  1373. if opTable[i] = resStr then
  1374. exit(i);
  1375. internalerror(2012100806);
  1376. end;
  1377. procedure foldITInstructions(list: TAsmList);
  1378. var
  1379. curtai,hp1 : tai;
  1380. levels,i : LongInt;
  1381. begin
  1382. curtai:=tai(list.First);
  1383. while assigned(curtai) do
  1384. begin
  1385. case curtai.typ of
  1386. ait_instruction:
  1387. begin
  1388. if IsIT(taicpu(curtai).opcode) then
  1389. begin
  1390. levels := GetITLevels(taicpu(curtai).opcode);
  1391. if levels < 4 then
  1392. begin
  1393. i:=levels;
  1394. hp1:=tai(curtai.Next);
  1395. while assigned(hp1) and
  1396. (i > 0) do
  1397. begin
  1398. if hp1.typ=ait_instruction then
  1399. begin
  1400. dec(i);
  1401. if (i = 0) and
  1402. mustbelast(hp1) then
  1403. begin
  1404. hp1:=nil;
  1405. break;
  1406. end;
  1407. end;
  1408. hp1:=tai(hp1.Next);
  1409. end;
  1410. if assigned(hp1) then
  1411. begin
  1412. // We are pointing at the first instruction after the IT block
  1413. while assigned(hp1) and
  1414. (hp1.typ<>ait_instruction) do
  1415. hp1:=tai(hp1.Next);
  1416. if assigned(hp1) and
  1417. (hp1.typ=ait_instruction) and
  1418. IsIT(taicpu(hp1).opcode) then
  1419. begin
  1420. if (levels+GetITLevels(taicpu(hp1).opcode) <= 4) and
  1421. ((taicpu(curtai).oper[0]^.cc=taicpu(hp1).oper[0]^.cc) or
  1422. (taicpu(curtai).oper[0]^.cc=inverse_cond(taicpu(hp1).oper[0]^.cc))) then
  1423. begin
  1424. taicpu(curtai).opcode:=getMergedInstruction(taicpu(curtai).opcode,
  1425. taicpu(hp1).opcode,
  1426. taicpu(curtai).oper[0]^.cc=inverse_cond(taicpu(hp1).oper[0]^.cc));
  1427. list.Remove(hp1);
  1428. hp1.Free;
  1429. end;
  1430. end;
  1431. end;
  1432. end;
  1433. end;
  1434. end
  1435. else
  1436. ;
  1437. end;
  1438. curtai:=tai(curtai.Next);
  1439. end;
  1440. end;
  1441. {$push}
  1442. { Disable range and overflow checking here }
  1443. {$R-}{$Q-}
  1444. procedure fix_invalid_imms(list: TAsmList);
  1445. var
  1446. curtai: tai;
  1447. sh: byte;
  1448. begin
  1449. curtai:=tai(list.First);
  1450. while assigned(curtai) do
  1451. begin
  1452. case curtai.typ of
  1453. ait_instruction:
  1454. begin
  1455. if (taicpu(curtai).opcode in [A_AND,A_BIC]) and
  1456. (taicpu(curtai).ops=3) and
  1457. (taicpu(curtai).oper[2]^.typ=top_const) and
  1458. (not is_shifter_const(taicpu(curtai).oper[2]^.val,sh)) and
  1459. is_shifter_const((not taicpu(curtai).oper[2]^.val) and $FFFFFFFF,sh) then
  1460. begin
  1461. case taicpu(curtai).opcode of
  1462. A_AND: taicpu(curtai).opcode:=A_BIC;
  1463. A_BIC: taicpu(curtai).opcode:=A_AND;
  1464. else
  1465. internalerror(2019050931);
  1466. end;
  1467. taicpu(curtai).oper[2]^.val:=(not taicpu(curtai).oper[2]^.val) and $FFFFFFFF;
  1468. end
  1469. else if (taicpu(curtai).opcode in [A_SUB,A_ADD]) and
  1470. (taicpu(curtai).ops=3) and
  1471. (taicpu(curtai).oper[2]^.typ=top_const) and
  1472. (not is_shifter_const(taicpu(curtai).oper[2]^.val,sh)) and
  1473. is_shifter_const(-taicpu(curtai).oper[2]^.val,sh) then
  1474. begin
  1475. case taicpu(curtai).opcode of
  1476. A_ADD: taicpu(curtai).opcode:=A_SUB;
  1477. A_SUB: taicpu(curtai).opcode:=A_ADD;
  1478. else
  1479. internalerror(2019050930);
  1480. end;
  1481. taicpu(curtai).oper[2]^.val:=-taicpu(curtai).oper[2]^.val;
  1482. end;
  1483. end;
  1484. else
  1485. ;
  1486. end;
  1487. curtai:=tai(curtai.Next);
  1488. end;
  1489. end;
  1490. {$pop}
  1491. procedure gather_it_info(list: TAsmList);
  1492. var
  1493. curtai: tai;
  1494. in_it: boolean;
  1495. it_count: longint;
  1496. begin
  1497. in_it:=false;
  1498. it_count:=0;
  1499. curtai:=tai(list.First);
  1500. while assigned(curtai) do
  1501. begin
  1502. case curtai.typ of
  1503. ait_instruction:
  1504. begin
  1505. case taicpu(curtai).opcode of
  1506. A_IT..A_ITTTT:
  1507. begin
  1508. if in_it then
  1509. Message1(asmw_e_invalid_opcode_and_operands, 'ITxx instruction is inside another ITxx instruction')
  1510. else
  1511. begin
  1512. in_it:=true;
  1513. it_count:=GetITLevels(taicpu(curtai).opcode);
  1514. end;
  1515. end;
  1516. else
  1517. begin
  1518. if in_it then
  1519. include(taicpu(curtai).flags,cf_inIT)
  1520. else
  1521. exclude(taicpu(curtai).flags,cf_inIT);
  1522. if in_it and (it_count=1) then
  1523. include(taicpu(curtai).flags,cf_lastinIT)
  1524. else
  1525. exclude(taicpu(curtai).flags,cf_lastinIT);
  1526. if in_it then
  1527. begin
  1528. dec(it_count);
  1529. if it_count <= 0 then
  1530. in_it:=false;
  1531. end;
  1532. end;
  1533. end;
  1534. end;
  1535. else
  1536. ;
  1537. end;
  1538. curtai:=tai(curtai.Next);
  1539. end;
  1540. end;
  1541. { Expands pseudo instructions ( mov r1,r2,lsl #4 -> lsl r1,r2,#4) }
  1542. procedure expand_instructions(list: TAsmList);
  1543. var
  1544. curtai: tai;
  1545. begin
  1546. curtai:=tai(list.First);
  1547. while assigned(curtai) do
  1548. begin
  1549. case curtai.typ of
  1550. ait_instruction:
  1551. begin
  1552. case taicpu(curtai).opcode of
  1553. A_MOV:
  1554. begin
  1555. if (taicpu(curtai).ops=3) and
  1556. (taicpu(curtai).oper[2]^.typ=top_shifterop) then
  1557. begin
  1558. case taicpu(curtai).oper[2]^.shifterop^.shiftmode of
  1559. SM_NONE: ;
  1560. SM_LSL: taicpu(curtai).opcode:=A_LSL;
  1561. SM_LSR: taicpu(curtai).opcode:=A_LSR;
  1562. SM_ASR: taicpu(curtai).opcode:=A_ASR;
  1563. SM_ROR: taicpu(curtai).opcode:=A_ROR;
  1564. SM_RRX: taicpu(curtai).opcode:=A_RRX;
  1565. end;
  1566. if taicpu(curtai).oper[2]^.shifterop^.shiftmode=SM_RRX then
  1567. taicpu(curtai).ops:=2;
  1568. if taicpu(curtai).oper[2]^.shifterop^.rs=NR_NO then
  1569. taicpu(curtai).loadconst(2, taicpu(curtai).oper[2]^.shifterop^.shiftimm)
  1570. else
  1571. taicpu(curtai).loadreg(2, taicpu(curtai).oper[2]^.shifterop^.rs);
  1572. end;
  1573. end;
  1574. A_NEG:
  1575. begin
  1576. taicpu(curtai).opcode:=A_RSB;
  1577. taicpu(curtai).oppostfix:=PF_S; // NEG should always set flags (according to documentation NEG<c> = RSBS<c>)
  1578. if taicpu(curtai).ops=2 then
  1579. begin
  1580. taicpu(curtai).loadconst(2,0);
  1581. taicpu(curtai).ops:=3;
  1582. end
  1583. else
  1584. begin
  1585. taicpu(curtai).loadconst(1,0);
  1586. taicpu(curtai).ops:=2;
  1587. end;
  1588. end;
  1589. A_SWI:
  1590. begin
  1591. taicpu(curtai).opcode:=A_SVC;
  1592. end;
  1593. else
  1594. ;
  1595. end;
  1596. end;
  1597. else
  1598. ;
  1599. end;
  1600. curtai:=tai(curtai.Next);
  1601. end;
  1602. end;
  1603. procedure finalizearmcode(list, listtoinsert: TAsmList);
  1604. begin
  1605. { Don't expand pseudo instructions when using GAS, it breaks on some thumb instructions }
  1606. if target_asm.id<>as_gas then
  1607. expand_instructions(list);
  1608. { Do Thumb-2 16bit -> 32bit transformations }
  1609. if GenerateThumb2Code then
  1610. begin
  1611. ensurethumbencodings(list);
  1612. ensurethumb2encodings(list);
  1613. foldITInstructions(list);
  1614. end
  1615. else if GenerateThumbCode then
  1616. ensurethumbencodings(list);
  1617. gather_it_info(list);
  1618. fix_invalid_imms(list);
  1619. insertpcrelativedata(list, listtoinsert);
  1620. end;
  1621. procedure InsertPData;
  1622. var
  1623. prolog: TAsmList;
  1624. begin
  1625. prolog:=TAsmList.create;
  1626. new_section(prolog,sec_code,'FPC_EH_PROLOG',sizeof(pint),secorder_begin);
  1627. prolog.concat(Tai_const.Createname('_ARM_ExceptionHandler', 0));
  1628. prolog.concat(Tai_const.Create_32bit(0));
  1629. prolog.concat(Tai_symbol.Createname_global('FPC_EH_CODE_START',AT_METADATA,0,voidpointertype));
  1630. { dummy function }
  1631. prolog.concat(taicpu.op_reg_reg(A_MOV,NR_R15,NR_R14));
  1632. current_asmdata.asmlists[al_start].insertList(prolog);
  1633. prolog.Free;
  1634. new_section(current_asmdata.asmlists[al_end],sec_pdata,'',sizeof(pint));
  1635. current_asmdata.asmlists[al_end].concat(Tai_const.Createname('FPC_EH_CODE_START', 0));
  1636. current_asmdata.asmlists[al_end].concat(Tai_const.Create_32bit(longint($ffffff01)));
  1637. end;
  1638. (*
  1639. Floating point instruction format information, taken from the linux kernel
  1640. ARM Floating Point Instruction Classes
  1641. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  1642. |c o n d|1 1 0 P|U|u|W|L| Rn |v| Fd |0|0|0|1| o f f s e t | CPDT
  1643. |c o n d|1 1 0 P|U|w|W|L| Rn |x| Fd |0|0|1|0| o f f s e t | CPDT (copro 2)
  1644. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  1645. |c o n d|1 1 1 0|a|b|c|d|e| Fn |j| Fd |0|0|0|1|f|g|h|0|i| Fm | CPDO
  1646. |c o n d|1 1 1 0|a|b|c|L|e| Fn | Rd |0|0|0|1|f|g|h|1|i| Fm | CPRT
  1647. |c o n d|1 1 1 0|a|b|c|1|e| Fn |1|1|1|1|0|0|0|1|f|g|h|1|i| Fm | comparisons
  1648. | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | |
  1649. CPDT data transfer instructions
  1650. LDF, STF, LFM (copro 2), SFM (copro 2)
  1651. CPDO dyadic arithmetic instructions
  1652. ADF, MUF, SUF, RSF, DVF, RDF,
  1653. POW, RPW, RMF, FML, FDV, FRD, POL
  1654. CPDO monadic arithmetic instructions
  1655. MVF, MNF, ABS, RND, SQT, LOG, LGN, EXP,
  1656. SIN, COS, TAN, ASN, ACS, ATN, URD, NRM
  1657. CPRT joint arithmetic/data transfer instructions
  1658. FIX (arithmetic followed by load/store)
  1659. FLT (load/store followed by arithmetic)
  1660. CMF, CNF CMFE, CNFE (comparisons)
  1661. WFS, RFS (write/read floating point status register)
  1662. WFC, RFC (write/read floating point control register)
  1663. cond condition codes
  1664. P pre/post index bit: 0 = postindex, 1 = preindex
  1665. U up/down bit: 0 = stack grows down, 1 = stack grows up
  1666. W write back bit: 1 = update base register (Rn)
  1667. L load/store bit: 0 = store, 1 = load
  1668. Rn base register
  1669. Rd destination/source register
  1670. Fd floating point destination register
  1671. Fn floating point source register
  1672. Fm floating point source register or floating point constant
  1673. uv transfer length (TABLE 1)
  1674. wx register count (TABLE 2)
  1675. abcd arithmetic opcode (TABLES 3 & 4)
  1676. ef destination size (rounding precision) (TABLE 5)
  1677. gh rounding mode (TABLE 6)
  1678. j dyadic/monadic bit: 0 = dyadic, 1 = monadic
  1679. i constant bit: 1 = constant (TABLE 6)
  1680. */
  1681. /*
  1682. TABLE 1
  1683. +-------------------------+---+---+---------+---------+
  1684. | Precision | u | v | FPSR.EP | length |
  1685. +-------------------------+---+---+---------+---------+
  1686. | Single | 0 | 0 | x | 1 words |
  1687. | Double | 1 | 1 | x | 2 words |
  1688. | Extended | 1 | 1 | x | 3 words |
  1689. | Packed decimal | 1 | 1 | 0 | 3 words |
  1690. | Expanded packed decimal | 1 | 1 | 1 | 4 words |
  1691. +-------------------------+---+---+---------+---------+
  1692. Note: x = don't care
  1693. */
  1694. /*
  1695. TABLE 2
  1696. +---+---+---------------------------------+
  1697. | w | x | Number of registers to transfer |
  1698. +---+---+---------------------------------+
  1699. | 0 | 1 | 1 |
  1700. | 1 | 0 | 2 |
  1701. | 1 | 1 | 3 |
  1702. | 0 | 0 | 4 |
  1703. +---+---+---------------------------------+
  1704. */
  1705. /*
  1706. TABLE 3: Dyadic Floating Point Opcodes
  1707. +---+---+---+---+----------+-----------------------+-----------------------+
  1708. | a | b | c | d | Mnemonic | Description | Operation |
  1709. +---+---+---+---+----------+-----------------------+-----------------------+
  1710. | 0 | 0 | 0 | 0 | ADF | Add | Fd := Fn + Fm |
  1711. | 0 | 0 | 0 | 1 | MUF | Multiply | Fd := Fn * Fm |
  1712. | 0 | 0 | 1 | 0 | SUF | Subtract | Fd := Fn - Fm |
  1713. | 0 | 0 | 1 | 1 | RSF | Reverse subtract | Fd := Fm - Fn |
  1714. | 0 | 1 | 0 | 0 | DVF | Divide | Fd := Fn / Fm |
  1715. | 0 | 1 | 0 | 1 | RDF | Reverse divide | Fd := Fm / Fn |
  1716. | 0 | 1 | 1 | 0 | POW | Power | Fd := Fn ^ Fm |
  1717. | 0 | 1 | 1 | 1 | RPW | Reverse power | Fd := Fm ^ Fn |
  1718. | 1 | 0 | 0 | 0 | RMF | Remainder | Fd := IEEE rem(Fn/Fm) |
  1719. | 1 | 0 | 0 | 1 | FML | Fast Multiply | Fd := Fn * Fm |
  1720. | 1 | 0 | 1 | 0 | FDV | Fast Divide | Fd := Fn / Fm |
  1721. | 1 | 0 | 1 | 1 | FRD | Fast reverse divide | Fd := Fm / Fn |
  1722. | 1 | 1 | 0 | 0 | POL | Polar angle (ArcTan2) | Fd := arctan2(Fn,Fm) |
  1723. | 1 | 1 | 0 | 1 | | undefined instruction | trap |
  1724. | 1 | 1 | 1 | 0 | | undefined instruction | trap |
  1725. | 1 | 1 | 1 | 1 | | undefined instruction | trap |
  1726. +---+---+---+---+----------+-----------------------+-----------------------+
  1727. Note: POW, RPW, POL are deprecated, and are available for backwards
  1728. compatibility only.
  1729. */
  1730. /*
  1731. TABLE 4: Monadic Floating Point Opcodes
  1732. +---+---+---+---+----------+-----------------------+-----------------------+
  1733. | a | b | c | d | Mnemonic | Description | Operation |
  1734. +---+---+---+---+----------+-----------------------+-----------------------+
  1735. | 0 | 0 | 0 | 0 | MVF | Move | Fd := Fm |
  1736. | 0 | 0 | 0 | 1 | MNF | Move negated | Fd := - Fm |
  1737. | 0 | 0 | 1 | 0 | ABS | Absolute value | Fd := abs(Fm) |
  1738. | 0 | 0 | 1 | 1 | RND | Round to integer | Fd := int(Fm) |
  1739. | 0 | 1 | 0 | 0 | SQT | Square root | Fd := sqrt(Fm) |
  1740. | 0 | 1 | 0 | 1 | LOG | Log base 10 | Fd := log10(Fm) |
  1741. | 0 | 1 | 1 | 0 | LGN | Log base e | Fd := ln(Fm) |
  1742. | 0 | 1 | 1 | 1 | EXP | Exponent | Fd := e ^ Fm |
  1743. | 1 | 0 | 0 | 0 | SIN | Sine | Fd := sin(Fm) |
  1744. | 1 | 0 | 0 | 1 | COS | Cosine | Fd := cos(Fm) |
  1745. | 1 | 0 | 1 | 0 | TAN | Tangent | Fd := tan(Fm) |
  1746. | 1 | 0 | 1 | 1 | ASN | Arc Sine | Fd := arcsin(Fm) |
  1747. | 1 | 1 | 0 | 0 | ACS | Arc Cosine | Fd := arccos(Fm) |
  1748. | 1 | 1 | 0 | 1 | ATN | Arc Tangent | Fd := arctan(Fm) |
  1749. | 1 | 1 | 1 | 0 | URD | Unnormalized round | Fd := int(Fm) |
  1750. | 1 | 1 | 1 | 1 | NRM | Normalize | Fd := norm(Fm) |
  1751. +---+---+---+---+----------+-----------------------+-----------------------+
  1752. Note: LOG, LGN, EXP, SIN, COS, TAN, ASN, ACS, ATN are deprecated, and are
  1753. available for backwards compatibility only.
  1754. */
  1755. /*
  1756. TABLE 5
  1757. +-------------------------+---+---+
  1758. | Rounding Precision | e | f |
  1759. +-------------------------+---+---+
  1760. | IEEE Single precision | 0 | 0 |
  1761. | IEEE Double precision | 0 | 1 |
  1762. | IEEE Extended precision | 1 | 0 |
  1763. | undefined (trap) | 1 | 1 |
  1764. +-------------------------+---+---+
  1765. */
  1766. /*
  1767. TABLE 5
  1768. +---------------------------------+---+---+
  1769. | Rounding Mode | g | h |
  1770. +---------------------------------+---+---+
  1771. | Round to nearest (default) | 0 | 0 |
  1772. | Round toward plus infinity | 0 | 1 |
  1773. | Round toward negative infinity | 1 | 0 |
  1774. | Round toward zero | 1 | 1 |
  1775. +---------------------------------+---+---+
  1776. *)
  1777. function taicpu.GetString:string;
  1778. var
  1779. i : longint;
  1780. s : string;
  1781. addsize : boolean;
  1782. begin
  1783. s:='['+gas_op2str[opcode];
  1784. for i:=0 to ops-1 do
  1785. begin
  1786. with oper[i]^ do
  1787. begin
  1788. if i=0 then
  1789. s:=s+' '
  1790. else
  1791. s:=s+',';
  1792. { type }
  1793. addsize:=false;
  1794. if (ot and OT_VREG)=OT_VREG then
  1795. s:=s+'vreg'
  1796. else
  1797. if (ot and OT_FPUREG)=OT_FPUREG then
  1798. s:=s+'fpureg'
  1799. else
  1800. if (ot and OT_REGS)=OT_REGS then
  1801. s:=s+'sreg'
  1802. else
  1803. if (ot and OT_REGF)=OT_REGF then
  1804. s:=s+'creg'
  1805. else
  1806. if (ot and OT_REGISTER)=OT_REGISTER then
  1807. begin
  1808. s:=s+'reg';
  1809. addsize:=true;
  1810. end
  1811. else
  1812. if (ot and OT_REGLIST)=OT_REGLIST then
  1813. begin
  1814. s:=s+'reglist';
  1815. addsize:=false;
  1816. end
  1817. else
  1818. if (ot and OT_IMMEDIATE)=OT_IMMEDIATE then
  1819. begin
  1820. s:=s+'imm';
  1821. addsize:=true;
  1822. end
  1823. else
  1824. if (ot and OT_MEMORY)=OT_MEMORY then
  1825. begin
  1826. s:=s+'mem';
  1827. addsize:=true;
  1828. if (ot and OT_AM2)<>0 then
  1829. s:=s+' am2 '
  1830. else if (ot and OT_AM6)<>0 then
  1831. s:=s+' am2 ';
  1832. end
  1833. else
  1834. if (ot and OT_SHIFTEROP)=OT_SHIFTEROP then
  1835. begin
  1836. s:=s+'shifterop';
  1837. addsize:=false;
  1838. end
  1839. else
  1840. s:=s+'???';
  1841. { size }
  1842. if addsize then
  1843. begin
  1844. if (ot and OT_BITS8)<>0 then
  1845. s:=s+'8'
  1846. else
  1847. if (ot and OT_BITS16)<>0 then
  1848. s:=s+'24'
  1849. else
  1850. if (ot and OT_BITS32)<>0 then
  1851. s:=s+'32'
  1852. else
  1853. if (ot and OT_BITSSHIFTER)<>0 then
  1854. s:=s+'shifter'
  1855. else
  1856. s:=s+'??';
  1857. { signed }
  1858. if (ot and OT_SIGNED)<>0 then
  1859. s:=s+'s';
  1860. end;
  1861. end;
  1862. end;
  1863. GetString:=s+']';
  1864. end;
  1865. procedure taicpu.ResetPass1;
  1866. begin
  1867. { we need to reset everything here, because the choosen insentry
  1868. can be invalid for a new situation where the previously optimized
  1869. insentry is not correct }
  1870. InsEntry:=nil;
  1871. InsSize:=0;
  1872. LastInsOffset:=-1;
  1873. end;
  1874. procedure taicpu.ResetPass2;
  1875. begin
  1876. { we are here in a second pass, check if the instruction can be optimized }
  1877. if assigned(InsEntry) and
  1878. ((InsEntry^.flags and IF_PASS2)<>0) then
  1879. begin
  1880. InsEntry:=nil;
  1881. InsSize:=0;
  1882. end;
  1883. LastInsOffset:=-1;
  1884. end;
  1885. function taicpu.CheckIfValid:boolean;
  1886. begin
  1887. Result:=False; { unimplemented }
  1888. end;
  1889. function taicpu.Pass1(objdata:TObjData):longint;
  1890. var
  1891. ldr2op : array[PF_B..PF_T] of tasmop = (
  1892. A_LDRB,A_LDRSB,A_LDRBT,A_LDRH,A_LDRSH,A_LDRT);
  1893. str2op : array[PF_B..PF_T] of tasmop = (
  1894. A_STRB,A_None,A_STRBT,A_STRH,A_None,A_STRT);
  1895. begin
  1896. Pass1:=0;
  1897. { Save the old offset and set the new offset }
  1898. InsOffset:=ObjData.CurrObjSec.Size;
  1899. { Error? }
  1900. if (Insentry=nil) and (InsSize=-1) then
  1901. exit;
  1902. { set the file postion }
  1903. current_filepos:=fileinfo;
  1904. { tranlate LDR+postfix to complete opcode }
  1905. if (opcode=A_LDR) and (oppostfix=PF_D) then
  1906. begin
  1907. opcode:=A_LDRD;
  1908. oppostfix:=PF_None;
  1909. end
  1910. else if (opcode=A_LDR) and (oppostfix<>PF_None) then
  1911. begin
  1912. if (oppostfix in [low(ldr2op)..high(ldr2op)]) then
  1913. opcode:=ldr2op[oppostfix]
  1914. else
  1915. internalerror(2005091001);
  1916. if opcode=A_None then
  1917. internalerror(2005091004);
  1918. { postfix has been added to opcode }
  1919. oppostfix:=PF_None;
  1920. end
  1921. else if (opcode=A_STR) and (oppostfix=PF_D) then
  1922. begin
  1923. opcode:=A_STRD;
  1924. oppostfix:=PF_None;
  1925. end
  1926. else if (opcode=A_STR) and (oppostfix<>PF_None) then
  1927. begin
  1928. if (oppostfix in [low(str2op)..high(str2op)]) then
  1929. opcode:=str2op[oppostfix]
  1930. else
  1931. internalerror(2005091002);
  1932. if opcode=A_None then
  1933. internalerror(2005091003);
  1934. { postfix has been added to opcode }
  1935. oppostfix:=PF_None;
  1936. end;
  1937. { Get InsEntry }
  1938. if FindInsEntry(objdata) then
  1939. begin
  1940. InsSize:=4;
  1941. if insentry^.code[0] in [#$60..#$6C] then
  1942. InsSize:=2;
  1943. LastInsOffset:=InsOffset;
  1944. Pass1:=InsSize;
  1945. exit;
  1946. end;
  1947. LastInsOffset:=-1;
  1948. end;
  1949. procedure taicpu.Pass2(objdata:TObjData);
  1950. begin
  1951. { error in pass1 ? }
  1952. if insentry=nil then
  1953. exit;
  1954. current_filepos:=fileinfo;
  1955. { Generate the instruction }
  1956. GenCode(objdata);
  1957. end;
  1958. procedure taicpu.ppuloadoper(ppufile:tcompilerppufile;var o:toper);
  1959. begin
  1960. end;
  1961. procedure taicpu.ppuwriteoper(ppufile:tcompilerppufile;const o:toper);
  1962. begin
  1963. end;
  1964. procedure taicpu.ppubuildderefimploper(var o:toper);
  1965. begin
  1966. end;
  1967. procedure taicpu.ppuderefoper(var o:toper);
  1968. begin
  1969. end;
  1970. procedure taicpu.BuildArmMasks(objdata:TObjData);
  1971. const
  1972. Masks: array[tcputype] of longint =
  1973. (
  1974. IF_NONE,
  1975. IF_ARMv4,
  1976. IF_ARMv4,
  1977. IF_ARMv4,
  1978. IF_ARMv4T or IF_ARMv4,
  1979. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T,
  1980. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE,
  1981. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ,
  1982. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6,
  1983. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K,
  1984. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2,
  1985. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2 or IF_ARMv6Z,
  1986. IF_ARMv4T or IF_ARMv5T or IF_ARMv6M,
  1987. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2 or IF_ARMv6Z or IF_ARMv7,
  1988. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2 or IF_ARMv6Z or IF_ARMv7 or IF_ARMv7A,
  1989. IF_ARMv4T or IF_ARMv4 or IF_ARMv5 or IF_ARMv5T or IF_ARMv5TE or IF_ARMv5TEJ or IF_armv6 or IF_ARMv6K or IF_ARMv6T2 or IF_ARMv6Z or IF_ARMv7 or IF_ARMv7A or IF_ARMv7R,
  1990. IF_ARMv4T or IF_ARMv5T or IF_ARMv6T2 or IF_ARMv7M,
  1991. IF_ARMv4T or IF_ARMv5T or IF_ARMv6T2 or IF_ARMv7M or IF_ARMv7EM
  1992. );
  1993. FPUMasks: array[tfputype] of longword =
  1994. (
  1995. { fpu_none } IF_NONE,
  1996. { fpu_soft } IF_NONE,
  1997. { fpu_libgcc } IF_NONE,
  1998. { fpu_fpa } IF_FPA,
  1999. { fpu_fpa10 } IF_FPA,
  2000. { fpu_fpa11 } IF_FPA,
  2001. { fpu_vfpv2 } IF_VFPv2,
  2002. { fpu_vfpv3 } IF_VFPv2 or IF_VFPv3,
  2003. { fpu_neon_vfpv3 } IF_VFPv2 or IF_VFPv3 or IF_NEON,
  2004. { fpu_vfpv3_d16 } IF_VFPv2 or IF_VFPv3,
  2005. { fpu_fpv4_s16 } IF_NONE,
  2006. { fpu_vfpv4 } IF_VFPv2 or IF_VFPv3 or IF_VFPv4,
  2007. { fpu_vfpv4 } IF_VFPv2 or IF_VFPv3 or IF_VFPv4,
  2008. { fpu_neon_vfpv4 } IF_VFPv2 or IF_VFPv3 or IF_VFPv4 or IF_NEON,
  2009. { fpu_fpv5_d16 } IF_VFPv2 or IF_VFPv3 or IF_VFPv4 or IF_VFPv5,
  2010. { fpu_fpv5_sp_d16} IF_VFPv2 or IF_VFPv3 or IF_VFPv4 or IF_VFPv5,
  2011. { fpu_fp_armv8 } IF_VFPv2 or IF_VFPv3 or IF_VFPv4 or IF_VFPv5
  2012. );
  2013. begin
  2014. fArmVMask:=Masks[current_settings.cputype] or FPUMasks[current_settings.fputype];
  2015. if cf_thumb in flags then
  2016. begin
  2017. fArmMask:=IF_THUMB;
  2018. if CPUARM_HAS_THUMB2 in cpu_capabilities[current_settings.cputype] then
  2019. fArmMask:=fArmMask or IF_THUMB32;
  2020. end
  2021. else
  2022. fArmMask:=IF_ARM32;
  2023. end;
  2024. function taicpu.InsEnd:longint;
  2025. begin
  2026. Result:=0; { unimplemented }
  2027. end;
  2028. procedure taicpu.create_ot(objdata:TObjData);
  2029. var
  2030. i,l,relsize : longint;
  2031. dummy : byte;
  2032. currsym : TObjSymbol;
  2033. begin
  2034. if ops=0 then
  2035. exit;
  2036. { update oper[].ot field }
  2037. for i:=0 to ops-1 do
  2038. with oper[i]^ do
  2039. begin
  2040. case typ of
  2041. top_regset:
  2042. begin
  2043. ot:=OT_REGLIST;
  2044. end;
  2045. top_reg :
  2046. begin
  2047. case getregtype(reg) of
  2048. R_INTREGISTER:
  2049. begin
  2050. ot:=OT_REG32 or OT_SHIFTEROP;
  2051. if getsupreg(reg)<8 then
  2052. ot:=ot or OT_REGLO
  2053. else if reg=NR_STACK_POINTER_REG then
  2054. ot:=ot or OT_REGSP;
  2055. end;
  2056. R_FPUREGISTER:
  2057. ot:=OT_FPUREG;
  2058. R_MMREGISTER:
  2059. ot:=OT_VREG;
  2060. R_SPECIALREGISTER:
  2061. ot:=OT_REGF;
  2062. else
  2063. internalerror(2005090901);
  2064. end;
  2065. end;
  2066. top_ref :
  2067. begin
  2068. if ref^.refaddr=addr_no then
  2069. begin
  2070. { create ot field }
  2071. { we should get the size here dependend on the
  2072. instruction }
  2073. if (ot and OT_SIZE_MASK)=0 then
  2074. ot:=OT_MEMORY or OT_BITS32
  2075. else
  2076. ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
  2077. if (ref^.base=NR_NO) and (ref^.index=NR_NO) then
  2078. ot:=ot or OT_MEM_OFFS;
  2079. { if we need to fix a reference, we do it here }
  2080. { pc relative addressing }
  2081. if (ref^.base=NR_NO) and
  2082. (ref^.index=NR_NO) and
  2083. (ref^.shiftmode=SM_None)
  2084. { at least we should check if the destination symbol
  2085. is in a text section }
  2086. { and
  2087. (ref^.symbol^.owner="text") } then
  2088. ref^.base:=NR_PC;
  2089. { determine possible address modes }
  2090. if GenerateThumbCode or
  2091. GenerateThumb2Code then
  2092. begin
  2093. if (ref^.addressmode<>AM_OFFSET) then
  2094. ot:=ot or OT_AM2
  2095. else if (ref^.base=NR_PC) then
  2096. ot:=ot or OT_AM6
  2097. else if (ref^.base=NR_STACK_POINTER_REG) then
  2098. ot:=ot or OT_AM5
  2099. else if ref^.index=NR_NO then
  2100. ot:=ot or OT_AM4
  2101. else
  2102. ot:=ot or OT_AM3;
  2103. end;
  2104. if (ref^.base<>NR_NO) and
  2105. (opcode in [A_LDREX,A_LDREXB,A_LDREXH,A_LDREXD,
  2106. A_STREX,A_STREXB,A_STREXH,A_STREXD]) and
  2107. (
  2108. (ref^.addressmode=AM_OFFSET) and
  2109. (ref^.index=NR_NO) and
  2110. (ref^.shiftmode=SM_None) and
  2111. (ref^.offset=0)
  2112. ) then
  2113. ot:=ot or OT_AM6
  2114. else if (ref^.base<>NR_NO) and
  2115. (
  2116. (
  2117. (ref^.index=NR_NO) and
  2118. (ref^.shiftmode=SM_None) and
  2119. (ref^.offset>=-4097) and
  2120. (ref^.offset<=4097)
  2121. ) or
  2122. (
  2123. (ref^.shiftmode=SM_None) and
  2124. (ref^.offset=0)
  2125. ) or
  2126. (
  2127. (ref^.index<>NR_NO) and
  2128. (ref^.shiftmode<>SM_None) and
  2129. (ref^.shiftimm<=32) and
  2130. (ref^.offset=0)
  2131. )
  2132. ) then
  2133. ot:=ot or OT_AM2;
  2134. if (ref^.index<>NR_NO) and
  2135. (oppostfix in [PF_None,PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA,
  2136. PF_IAD,PF_DBD,PF_FDD,PF_EAD,
  2137. PF_IAS,PF_DBS,PF_FDS,PF_EAS,
  2138. PF_IAX,PF_DBX,PF_FDX,PF_EAX]) and
  2139. (
  2140. (ref^.base=NR_NO) and
  2141. (ref^.shiftmode=SM_None) and
  2142. (ref^.offset=0)
  2143. ) then
  2144. ot:=ot or OT_AM4;
  2145. end
  2146. else
  2147. begin
  2148. l:=ref^.offset;
  2149. currsym:=ObjData.symbolref(ref^.symbol);
  2150. if assigned(currsym) then
  2151. inc(l,currsym.address);
  2152. relsize:=(InsOffset+2)-l;
  2153. if (relsize<-33554428) or (relsize>33554428) then
  2154. ot:=OT_IMM32
  2155. else
  2156. ot:=OT_IMM24;
  2157. end;
  2158. end;
  2159. top_local :
  2160. begin
  2161. { we should get the size here dependend on the
  2162. instruction }
  2163. if (ot and OT_SIZE_MASK)=0 then
  2164. ot:=OT_MEMORY or OT_BITS32
  2165. else
  2166. ot:=OT_MEMORY or (ot and OT_SIZE_MASK);
  2167. end;
  2168. top_const :
  2169. begin
  2170. ot:=OT_IMMEDIATE;
  2171. if (val=0) then
  2172. ot:=ot_immediatezero
  2173. else if is_shifter_const(val,dummy) then
  2174. ot:=OT_IMMSHIFTER
  2175. else if GenerateThumb2Code and is_thumb32_imm(val) then
  2176. ot:=OT_IMMSHIFTER
  2177. else
  2178. ot:=OT_IMM32
  2179. end;
  2180. top_none :
  2181. begin
  2182. { generated when there was an error in the
  2183. assembler reader. It never happends when generating
  2184. assembler }
  2185. end;
  2186. top_shifterop:
  2187. begin
  2188. ot:=OT_SHIFTEROP;
  2189. end;
  2190. top_conditioncode:
  2191. begin
  2192. ot:=OT_CONDITION;
  2193. end;
  2194. top_specialreg:
  2195. begin
  2196. ot:=OT_REGS;
  2197. end;
  2198. top_modeflags:
  2199. begin
  2200. ot:=OT_MODEFLAGS;
  2201. end;
  2202. top_realconst:
  2203. begin
  2204. ot:=OT_IMMEDIATEMM;
  2205. end;
  2206. else
  2207. internalerror(2004022623);
  2208. end;
  2209. end;
  2210. end;
  2211. function taicpu.Matches(p:PInsEntry):longint;
  2212. { * IF_SM stands for Size Match: any operand whose size is not
  2213. * explicitly specified by the template is `really' intended to be
  2214. * the same size as the first size-specified operand.
  2215. * Non-specification is tolerated in the input instruction, but
  2216. * _wrong_ specification is not.
  2217. *
  2218. * IF_SM2 invokes Size Match on only the first _two_ operands, for
  2219. * three-operand instructions such as SHLD: it implies that the
  2220. * first two operands must match in size, but that the third is
  2221. * required to be _unspecified_.
  2222. *
  2223. * IF_SB invokes Size Byte: operands with unspecified size in the
  2224. * template are really bytes, and so no non-byte specification in
  2225. * the input instruction will be tolerated. IF_SW similarly invokes
  2226. * Size Word, and IF_SD invokes Size Doubleword.
  2227. *
  2228. * (The default state if neither IF_SM nor IF_SM2 is specified is
  2229. * that any operand with unspecified size in the template is
  2230. * required to have unspecified size in the instruction too...)
  2231. }
  2232. var
  2233. i{,j,asize,oprs} : longint;
  2234. {siz : array[0..3] of longint;}
  2235. begin
  2236. Matches:=100;
  2237. { Check the opcode and operands }
  2238. if (p^.opcode<>opcode) or (p^.ops<>ops) then
  2239. begin
  2240. Matches:=0;
  2241. exit;
  2242. end;
  2243. { check ARM instruction version }
  2244. if (p^.flags and fArmVMask)=0 then
  2245. begin
  2246. Matches:=0;
  2247. exit;
  2248. end;
  2249. { check ARM instruction type }
  2250. if (p^.flags and fArmMask)=0 then
  2251. begin
  2252. Matches:=0;
  2253. exit;
  2254. end;
  2255. { Check wideformat flag }
  2256. if (cf_wideformat in flags) and ((p^.flags and IF_WIDE)=0) then
  2257. begin
  2258. matches:=0;
  2259. exit;
  2260. end;
  2261. { Check that no spurious colons or TOs are present }
  2262. for i:=0 to p^.ops-1 do
  2263. if (oper[i]^.ot and (not p^.optypes[i]) and (OT_COLON or OT_TO))<>0 then
  2264. begin
  2265. Matches:=0;
  2266. exit;
  2267. end;
  2268. { Check that the operand flags all match up }
  2269. for i:=0 to p^.ops-1 do
  2270. begin
  2271. if ((p^.optypes[i] and (not oper[i]^.ot)) or
  2272. ((p^.optypes[i] and OT_SIZE_MASK) and
  2273. ((p^.optypes[i] xor oper[i]^.ot) and OT_SIZE_MASK)))<>0 then
  2274. begin
  2275. if ((p^.optypes[i] and (not oper[i]^.ot) and OT_NON_SIZE) or
  2276. (oper[i]^.ot and OT_SIZE_MASK))<>0 then
  2277. begin
  2278. Matches:=0;
  2279. exit;
  2280. end
  2281. else if ((p^.optypes[i] and OT_OPT_SIZE)<>0) and
  2282. ((p^.optypes[i] and OT_OPT_SIZE)<>(oper[i]^.ot and OT_OPT_SIZE)) then
  2283. begin
  2284. Matches:=0;
  2285. exit;
  2286. end
  2287. else
  2288. Matches:=1;
  2289. end;
  2290. end;
  2291. { check postfixes:
  2292. the existance of a certain postfix requires a
  2293. particular code }
  2294. { update condition flags
  2295. or floating point single }
  2296. if (oppostfix=PF_S) and
  2297. not(p^.code[0] in [#$04..#$0F,#$14..#$16,#$29,#$30,#$60..#$6B,#$80..#$82,#$A0..#$A2,#$44,#$94,#$42,#$92]) then
  2298. begin
  2299. Matches:=0;
  2300. exit;
  2301. end;
  2302. { floating point size }
  2303. if (oppostfix in [PF_D,PF_E,PF_P,PF_EP]) and
  2304. not(p^.code[0] in [
  2305. // FPA
  2306. #$A0..#$A2,
  2307. // old-school VFP
  2308. #$42,#$92,
  2309. // vldm/vstm
  2310. #$44,#$94]) then
  2311. begin
  2312. Matches:=0;
  2313. exit;
  2314. end;
  2315. { multiple load/store address modes }
  2316. if (oppostfix in [PF_IA,PF_IB,PF_DA,PF_DB,PF_FD,PF_FA,PF_ED,PF_EA]) and
  2317. not(p^.code[0] in [
  2318. // ldr,str,ldrb,strb
  2319. #$17,
  2320. // stm,ldm
  2321. #$26,#$69,#$8C,
  2322. // vldm/vstm
  2323. #$44,#$94
  2324. ]) then
  2325. begin
  2326. Matches:=0;
  2327. exit;
  2328. end;
  2329. { we shouldn't see any opsize prefixes here }
  2330. if (oppostfix in [PF_B,PF_SB,PF_BT,PF_H,PF_SH,PF_T]) then
  2331. begin
  2332. Matches:=0;
  2333. exit;
  2334. end;
  2335. if (roundingmode<>RM_None) and not(p^.code[0] in []) then
  2336. begin
  2337. Matches:=0;
  2338. exit;
  2339. end;
  2340. { Check thumb flags }
  2341. if p^.code[0] in [#$60..#$61] then
  2342. begin
  2343. if (p^.code[0]=#$60) and
  2344. (GenerateThumb2Code and
  2345. ((not(cf_inIT in flags)) and (oppostfix<>PF_S)) or
  2346. ((cf_inIT in flags) and (condition=C_None))) then
  2347. begin
  2348. Matches:=0;
  2349. exit;
  2350. end
  2351. else if (p^.code[0]=#$61) and
  2352. (oppostfix=PF_S) then
  2353. begin
  2354. Matches:=0;
  2355. exit;
  2356. end;
  2357. end
  2358. else if p^.code[0]=#$62 then
  2359. begin
  2360. if GenerateThumb2Code and
  2361. (condition<>C_None) and
  2362. (not(cf_inIT in flags)) and
  2363. (not(cf_lastinIT in flags)) then
  2364. begin
  2365. Matches:=0;
  2366. exit;
  2367. end;
  2368. end
  2369. else if p^.code[0]=#$63 then
  2370. begin
  2371. if cf_inIT in flags then
  2372. begin
  2373. Matches:=0;
  2374. exit;
  2375. end;
  2376. end
  2377. else if p^.code[0]=#$64 then
  2378. begin
  2379. if (opcode=A_MUL) then
  2380. begin
  2381. if (ops=3) and
  2382. ((oper[2]^.typ<>top_reg) or
  2383. (oper[0]^.reg<>oper[2]^.reg)) then
  2384. begin
  2385. matches:=0;
  2386. exit;
  2387. end;
  2388. end;
  2389. end
  2390. else if p^.code[0]=#$6B then
  2391. begin
  2392. if (cf_inIT in flags) or
  2393. (oppostfix<>PF_S) then
  2394. begin
  2395. Matches:=0;
  2396. exit;
  2397. end;
  2398. end;
  2399. { Check operand sizes }
  2400. { as default an untyped size can get all the sizes, this is different
  2401. from nasm, but else we need to do a lot checking which opcodes want
  2402. size or not with the automatic size generation }
  2403. (*
  2404. asize:=longint($ffffffff);
  2405. if (p^.flags and IF_SB)<>0 then
  2406. asize:=OT_BITS8
  2407. else if (p^.flags and IF_SW)<>0 then
  2408. asize:=OT_BITS16
  2409. else if (p^.flags and IF_SD)<>0 then
  2410. asize:=OT_BITS32;
  2411. if (p^.flags and IF_ARMASK)<>0 then
  2412. begin
  2413. siz[0]:=0;
  2414. siz[1]:=0;
  2415. siz[2]:=0;
  2416. if (p^.flags and IF_AR0)<>0 then
  2417. siz[0]:=asize
  2418. else if (p^.flags and IF_AR1)<>0 then
  2419. siz[1]:=asize
  2420. else if (p^.flags and IF_AR2)<>0 then
  2421. siz[2]:=asize;
  2422. end
  2423. else
  2424. begin
  2425. { we can leave because the size for all operands is forced to be
  2426. the same
  2427. but not if IF_SB IF_SW or IF_SD is set PM }
  2428. if asize=-1 then
  2429. exit;
  2430. siz[0]:=asize;
  2431. siz[1]:=asize;
  2432. siz[2]:=asize;
  2433. end;
  2434. if (p^.flags and (IF_SM or IF_SM2))<>0 then
  2435. begin
  2436. if (p^.flags and IF_SM2)<>0 then
  2437. oprs:=2
  2438. else
  2439. oprs:=p^.ops;
  2440. for i:=0 to oprs-1 do
  2441. if ((p^.optypes[i] and OT_SIZE_MASK) <> 0) then
  2442. begin
  2443. for j:=0 to oprs-1 do
  2444. siz[j]:=p^.optypes[i] and OT_SIZE_MASK;
  2445. break;
  2446. end;
  2447. end
  2448. else
  2449. oprs:=2;
  2450. { Check operand sizes }
  2451. for i:=0 to p^.ops-1 do
  2452. begin
  2453. if ((p^.optypes[i] and OT_SIZE_MASK)=0) and
  2454. ((oper[i]^.ot and OT_SIZE_MASK and (not siz[i]))<>0) and
  2455. { Immediates can always include smaller size }
  2456. ((oper[i]^.ot and OT_IMMEDIATE)=0) and
  2457. (((p^.optypes[i] and OT_SIZE_MASK) or siz[i])<(oper[i]^.ot and OT_SIZE_MASK)) then
  2458. Matches:=2;
  2459. end;
  2460. *)
  2461. end;
  2462. function taicpu.calcsize(p:PInsEntry):shortint;
  2463. begin
  2464. result:=4;
  2465. end;
  2466. function taicpu.NeedAddrPrefix(opidx:byte):boolean;
  2467. begin
  2468. Result:=False; { unimplemented }
  2469. end;
  2470. procedure taicpu.Swapoperands;
  2471. begin
  2472. end;
  2473. function taicpu.FindInsentry(objdata:TObjData):boolean;
  2474. var
  2475. i : longint;
  2476. begin
  2477. result:=false;
  2478. { Things which may only be done once, not when a second pass is done to
  2479. optimize }
  2480. if (Insentry=nil) or ((InsEntry^.flags and IF_PASS2)<>0) then
  2481. begin
  2482. { create the .ot fields }
  2483. create_ot(objdata);
  2484. BuildArmMasks(objdata);
  2485. { set the file postion }
  2486. current_filepos:=fileinfo;
  2487. end
  2488. else
  2489. begin
  2490. { we've already an insentry so it's valid }
  2491. result:=true;
  2492. exit;
  2493. end;
  2494. { Lookup opcode in the table }
  2495. InsSize:=-1;
  2496. i:=instabcache^[opcode];
  2497. if i=-1 then
  2498. begin
  2499. Message1(asmw_e_opcode_not_in_table,gas_op2str[opcode]);
  2500. exit;
  2501. end;
  2502. insentry:=@instab[i];
  2503. while (insentry^.opcode=opcode) do
  2504. begin
  2505. if matches(insentry)=100 then
  2506. begin
  2507. result:=true;
  2508. exit;
  2509. end;
  2510. inc(i);
  2511. insentry:=@instab[i];
  2512. end;
  2513. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  2514. { No instruction found, set insentry to nil and inssize to -1 }
  2515. insentry:=nil;
  2516. inssize:=-1;
  2517. end;
  2518. procedure taicpu.gencode(objdata:TObjData);
  2519. const
  2520. CondVal : array[TAsmCond] of byte=(
  2521. $E, $0, $1, $2, $3, $4, $5, $6, $7, $8, $9, $A,
  2522. $B, $C, $D, $E, 0);
  2523. var
  2524. bytes, rd, rm, rn, d, m, n : dword;
  2525. bytelen : longint;
  2526. dp_operation : boolean;
  2527. i_field : byte;
  2528. currsym : TObjSymbol;
  2529. offset : longint;
  2530. refoper : poper;
  2531. msb : longint;
  2532. r: byte;
  2533. singlerec : tcompsinglerec;
  2534. doublerec : tcompdoublerec;
  2535. procedure setshifterop(op : byte);
  2536. var
  2537. r : byte;
  2538. imm : dword;
  2539. count : integer;
  2540. begin
  2541. case oper[op]^.typ of
  2542. top_const:
  2543. begin
  2544. i_field:=1;
  2545. if oper[op]^.val and $ff=oper[op]^.val then
  2546. bytes:=bytes or dword(oper[op]^.val)
  2547. else
  2548. begin
  2549. { calc rotate and adjust imm }
  2550. count:=0;
  2551. r:=0;
  2552. imm:=dword(oper[op]^.val);
  2553. repeat
  2554. imm:=RolDWord(imm, 2);
  2555. inc(r);
  2556. inc(count);
  2557. if count > 32 then
  2558. begin
  2559. message1(asmw_e_invalid_opcode_and_operands, 'invalid shifter imm');
  2560. exit;
  2561. end;
  2562. until (imm and $ff)=imm;
  2563. bytes:=bytes or (r shl 8) or imm;
  2564. end;
  2565. end;
  2566. top_reg:
  2567. begin
  2568. i_field:=0;
  2569. bytes:=bytes or getsupreg(oper[op]^.reg);
  2570. { does a real shifter op follow? }
  2571. if (op+1<opercnt) and (oper[op+1]^.typ=top_shifterop) then
  2572. with oper[op+1]^.shifterop^ do
  2573. begin
  2574. bytes:=bytes or ((shiftimm and $1F) shl 7);
  2575. if shiftmode<>SM_RRX then
  2576. bytes:=bytes or (ord(shiftmode) - ord(SM_LSL)) shl 5
  2577. else
  2578. bytes:=bytes or (3 shl 5);
  2579. if getregtype(rs) <> R_INVALIDREGISTER then
  2580. begin
  2581. bytes:=bytes or (1 shl 4);
  2582. bytes:=bytes or (getsupreg(rs) shl 8);
  2583. end
  2584. end;
  2585. end;
  2586. else
  2587. internalerror(2005091103);
  2588. end;
  2589. end;
  2590. function MakeRegList(reglist: tcpuregisterset): word;
  2591. var
  2592. i, w: integer;
  2593. begin
  2594. result:=0;
  2595. w:=0;
  2596. for i:=RS_R0 to RS_R15 do
  2597. begin
  2598. if i in reglist then
  2599. result:=result or (1 shl w);
  2600. inc(w);
  2601. end;
  2602. end;
  2603. function getcoproc(reg: tregister): byte;
  2604. begin
  2605. if reg=NR_p15 then
  2606. result:=15
  2607. else
  2608. begin
  2609. Message1(asmw_e_invalid_opcode_and_operands,'Invalid coprocessor port');
  2610. result:=0;
  2611. end;
  2612. end;
  2613. function getcoprocreg(reg: tregister): byte;
  2614. var
  2615. tmpr: tregister;
  2616. begin
  2617. { FIXME: temp variable r is needed here to avoid Internal error 20060521 }
  2618. { while compiling the compiler. }
  2619. tmpr:=NR_CR0;
  2620. result:=getsupreg(reg)-getsupreg(tmpr);
  2621. end;
  2622. function getmmreg(reg: tregister): byte;
  2623. begin
  2624. case reg of
  2625. NR_D0: result:=0;
  2626. NR_D1: result:=1;
  2627. NR_D2: result:=2;
  2628. NR_D3: result:=3;
  2629. NR_D4: result:=4;
  2630. NR_D5: result:=5;
  2631. NR_D6: result:=6;
  2632. NR_D7: result:=7;
  2633. NR_D8: result:=8;
  2634. NR_D9: result:=9;
  2635. NR_D10: result:=10;
  2636. NR_D11: result:=11;
  2637. NR_D12: result:=12;
  2638. NR_D13: result:=13;
  2639. NR_D14: result:=14;
  2640. NR_D15: result:=15;
  2641. NR_D16: result:=16;
  2642. NR_D17: result:=17;
  2643. NR_D18: result:=18;
  2644. NR_D19: result:=19;
  2645. NR_D20: result:=20;
  2646. NR_D21: result:=21;
  2647. NR_D22: result:=22;
  2648. NR_D23: result:=23;
  2649. NR_D24: result:=24;
  2650. NR_D25: result:=25;
  2651. NR_D26: result:=26;
  2652. NR_D27: result:=27;
  2653. NR_D28: result:=28;
  2654. NR_D29: result:=29;
  2655. NR_D30: result:=30;
  2656. NR_D31: result:=31;
  2657. NR_S0: result:=0;
  2658. NR_S1: result:=1;
  2659. NR_S2: result:=2;
  2660. NR_S3: result:=3;
  2661. NR_S4: result:=4;
  2662. NR_S5: result:=5;
  2663. NR_S6: result:=6;
  2664. NR_S7: result:=7;
  2665. NR_S8: result:=8;
  2666. NR_S9: result:=9;
  2667. NR_S10: result:=10;
  2668. NR_S11: result:=11;
  2669. NR_S12: result:=12;
  2670. NR_S13: result:=13;
  2671. NR_S14: result:=14;
  2672. NR_S15: result:=15;
  2673. NR_S16: result:=16;
  2674. NR_S17: result:=17;
  2675. NR_S18: result:=18;
  2676. NR_S19: result:=19;
  2677. NR_S20: result:=20;
  2678. NR_S21: result:=21;
  2679. NR_S22: result:=22;
  2680. NR_S23: result:=23;
  2681. NR_S24: result:=24;
  2682. NR_S25: result:=25;
  2683. NR_S26: result:=26;
  2684. NR_S27: result:=27;
  2685. NR_S28: result:=28;
  2686. NR_S29: result:=29;
  2687. NR_S30: result:=30;
  2688. NR_S31: result:=31;
  2689. else
  2690. result:=0;
  2691. end;
  2692. end;
  2693. procedure encodethumbimm(imm: longword);
  2694. var
  2695. imm12, tmp: tcgint;
  2696. shift: integer;
  2697. found: boolean;
  2698. begin
  2699. found:=true;
  2700. if (imm and $FF) = imm then
  2701. imm12:=imm
  2702. else if ((imm shr 16)=(imm and $FFFF)) and
  2703. ((imm and $FF00FF00) = 0) then
  2704. imm12:=(imm and $ff) or ($1 shl 8)
  2705. else if ((imm shr 16)=(imm and $FFFF)) and
  2706. ((imm and $00FF00FF) = 0) then
  2707. imm12:=((imm shr 8) and $ff) or ($2 shl 8)
  2708. else if ((imm shr 16)=(imm and $FFFF)) and
  2709. (((imm shr 8) and $FF)=(imm and $FF)) then
  2710. imm12:=(imm and $ff) or ($3 shl 8)
  2711. else
  2712. begin
  2713. found:=false;
  2714. imm12:=0;
  2715. for shift:=1 to 31 do
  2716. begin
  2717. tmp:=RolDWord(imm,shift);
  2718. if ((tmp and $FF)=tmp) and
  2719. ((tmp and $80)=$80) then
  2720. begin
  2721. imm12:=(tmp and $7F) or (shift shl 7);
  2722. found:=true;
  2723. break;
  2724. end;
  2725. end;
  2726. end;
  2727. if found then
  2728. begin
  2729. bytes:=bytes or (imm12 and $FF);
  2730. bytes:=bytes or (((imm12 shr 8) and $7) shl 12);
  2731. bytes:=bytes or (((imm12 shr 11) and $1) shl 26);
  2732. end
  2733. else
  2734. Message1(asmw_e_value_exceeds_bounds, IntToStr(imm));
  2735. end;
  2736. procedure setthumbshift(op: byte; is_sat: boolean = false);
  2737. var
  2738. shift,typ: byte;
  2739. begin
  2740. shift:=0;
  2741. typ:=0;
  2742. case oper[op]^.shifterop^.shiftmode of
  2743. SM_None: ;
  2744. SM_LSL: begin typ:=0; shift:=oper[op]^.shifterop^.shiftimm; end;
  2745. SM_LSR: begin typ:=1; shift:=oper[op]^.shifterop^.shiftimm; if shift=32 then shift:=0; end;
  2746. SM_ASR: begin typ:=2; shift:=oper[op]^.shifterop^.shiftimm; if shift=32 then shift:=0; end;
  2747. SM_ROR: begin typ:=3; shift:=oper[op]^.shifterop^.shiftimm; if shift=0 then message(asmw_e_invalid_opcode_and_operands); end;
  2748. SM_RRX: begin typ:=3; shift:=0; end;
  2749. end;
  2750. if is_sat then
  2751. begin
  2752. bytes:=bytes or ((typ and 1) shl 5);
  2753. bytes:=bytes or ((typ shr 1) shl 21);
  2754. end
  2755. else
  2756. bytes:=bytes or (typ shl 4);
  2757. bytes:=bytes or (shift and $3) shl 6;
  2758. bytes:=bytes or ((shift and $1C) shr 2) shl 12;
  2759. end;
  2760. begin
  2761. bytes:=$0;
  2762. bytelen:=4;
  2763. i_field:=0;
  2764. { evaluate and set condition code }
  2765. bytes:=bytes or (CondVal[condition] shl 28);
  2766. { condition code allowed? }
  2767. { setup rest of the instruction }
  2768. case insentry^.code[0] of
  2769. #$01: // B/BL
  2770. begin
  2771. { set instruction code }
  2772. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2773. { set offset }
  2774. if oper[0]^.typ=top_const then
  2775. bytes:=bytes or ((oper[0]^.val shr 2) and $ffffff)
  2776. else
  2777. begin
  2778. currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
  2779. { tlscall is not relative so ignore the offset }
  2780. if oper[0]^.ref^.refaddr<>addr_tlscall then
  2781. bytes:=bytes or (((oper[0]^.ref^.offset-8) shr 2) and $ffffff);
  2782. if (opcode<>A_BL) or (condition<>C_None) then
  2783. objdata.writereloc(aint(bytes),4,currsym,RELOC_RELATIVE_24)
  2784. else
  2785. case oper[0]^.ref^.refaddr of
  2786. addr_pic:
  2787. objdata.writereloc(aint(bytes),4,currsym,RELOC_ARM_CALL);
  2788. addr_full:
  2789. objdata.writereloc(aint(bytes),4,currsym,RELOC_RELATIVE_CALL);
  2790. addr_tlscall:
  2791. objdata.writereloc(aint(bytes),4,currsym,RELOC_TLS_CALL);
  2792. else
  2793. Internalerror(2019092903);
  2794. end;
  2795. exit;
  2796. end;
  2797. end;
  2798. #$02:
  2799. begin
  2800. { set instruction code }
  2801. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2802. { set code }
  2803. bytes:=bytes or (oper[0]^.val and $FFFFFF);
  2804. end;
  2805. #$03:
  2806. begin // BLX/BX
  2807. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2808. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2809. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  2810. bytes:=bytes or ord(insentry^.code[4]);
  2811. bytes:=bytes or getsupreg(oper[0]^.reg);
  2812. end;
  2813. #$04..#$07: // SUB
  2814. begin
  2815. { set instruction code }
  2816. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2817. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2818. { set destination }
  2819. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  2820. { set Rn }
  2821. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  2822. { create shifter op }
  2823. setshifterop(2);
  2824. { set I field }
  2825. bytes:=bytes or (i_field shl 25);
  2826. { set S if necessary }
  2827. if oppostfix=PF_S then
  2828. bytes:=bytes or (1 shl 20);
  2829. end;
  2830. #$08,#$0A,#$0B: // MOV
  2831. begin
  2832. { set instruction code }
  2833. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2834. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2835. { set destination }
  2836. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  2837. { create shifter op }
  2838. setshifterop(1);
  2839. { set I field }
  2840. bytes:=bytes or (i_field shl 25);
  2841. { set S if necessary }
  2842. if oppostfix=PF_S then
  2843. bytes:=bytes or (1 shl 20);
  2844. end;
  2845. #$0C,#$0E,#$0F: // CMP
  2846. begin
  2847. { set instruction code }
  2848. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2849. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2850. { set destination }
  2851. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
  2852. { create shifter op }
  2853. setshifterop(1);
  2854. { set I field }
  2855. bytes:=bytes or (i_field shl 25);
  2856. { always set S bit }
  2857. bytes:=bytes or (1 shl 20);
  2858. end;
  2859. #$10: // MRS
  2860. begin
  2861. { set instruction code }
  2862. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2863. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2864. { set destination }
  2865. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  2866. case oper[1]^.reg of
  2867. NR_APSR,NR_CPSR:;
  2868. NR_SPSR:
  2869. begin
  2870. bytes:=bytes or (1 shl 22);
  2871. end;
  2872. else
  2873. Message(asmw_e_invalid_opcode_and_operands);
  2874. end;
  2875. end;
  2876. #$12,#$13: // MSR
  2877. begin
  2878. { set instruction code }
  2879. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2880. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2881. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  2882. { set destination }
  2883. if oper[0]^.typ=top_specialreg then
  2884. begin
  2885. if (oper[0]^.specialreg<>NR_CPSR) and
  2886. (oper[0]^.specialreg<>NR_SPSR) then
  2887. Message1(asmw_e_invalid_opcode_and_operands, '"Invalid special reg"');
  2888. if srC in oper[0]^.specialflags then
  2889. bytes:=bytes or (1 shl 16);
  2890. if srX in oper[0]^.specialflags then
  2891. bytes:=bytes or (1 shl 17);
  2892. if srS in oper[0]^.specialflags then
  2893. bytes:=bytes or (1 shl 18);
  2894. if srF in oper[0]^.specialflags then
  2895. bytes:=bytes or (1 shl 19);
  2896. { Set R bit }
  2897. if oper[0]^.specialreg=NR_SPSR then
  2898. bytes:=bytes or (1 shl 22);
  2899. end
  2900. else
  2901. case oper[0]^.reg of
  2902. NR_APSR_nzcvq: bytes:=bytes or (2 shl 18);
  2903. NR_APSR_g: bytes:=bytes or (1 shl 18);
  2904. NR_APSR_nzcvqg: bytes:=bytes or (3 shl 18);
  2905. else
  2906. Message1(asmw_e_invalid_opcode_and_operands, 'Invalid combination APSR bits used');
  2907. end;
  2908. setshifterop(1);
  2909. end;
  2910. #$14: // MUL/MLA r1,r2,r3
  2911. begin
  2912. { set instruction code }
  2913. bytes:=bytes or ord(insentry^.code[1]) shl 24;
  2914. bytes:=bytes or ord(insentry^.code[2]) shl 16;
  2915. bytes:=bytes or ord(insentry^.code[3]);
  2916. { set regs }
  2917. bytes:=bytes or getsupreg(oper[0]^.reg) shl 16;
  2918. bytes:=bytes or getsupreg(oper[1]^.reg);
  2919. bytes:=bytes or getsupreg(oper[2]^.reg) shl 8;
  2920. if oppostfix in [PF_S] then
  2921. bytes:=bytes or (1 shl 20);
  2922. end;
  2923. #$15: // MUL/MLA r1,r2,r3,r4
  2924. begin
  2925. { set instruction code }
  2926. bytes:=bytes or ord(insentry^.code[1]) shl 24;
  2927. bytes:=bytes or ord(insentry^.code[2]) shl 16;
  2928. bytes:=bytes or ord(insentry^.code[3]) shl 4;
  2929. { set regs }
  2930. bytes:=bytes or getsupreg(oper[0]^.reg) shl 16;
  2931. bytes:=bytes or getsupreg(oper[1]^.reg);
  2932. bytes:=bytes or getsupreg(oper[2]^.reg) shl 8;
  2933. if ops>3 then
  2934. bytes:=bytes or getsupreg(oper[3]^.reg) shl 12
  2935. else
  2936. bytes:=bytes or ord(insentry^.code[4]) shl 12;
  2937. if oppostfix in [PF_R,PF_X] then
  2938. bytes:=bytes or (1 shl 5);
  2939. if oppostfix in [PF_S] then
  2940. bytes:=bytes or (1 shl 20);
  2941. end;
  2942. #$16: // MULL r1,r2,r3,r4
  2943. begin
  2944. { set instruction code }
  2945. bytes:=bytes or ord(insentry^.code[1]) shl 24;
  2946. bytes:=bytes or ord(insentry^.code[2]) shl 16;
  2947. bytes:=bytes or ord(insentry^.code[3]) shl 4;
  2948. { set regs }
  2949. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  2950. if (ops=3) and (opcode=A_PKHTB) then
  2951. begin
  2952. bytes:=bytes or getsupreg(oper[1]^.reg);
  2953. bytes:=bytes or getsupreg(oper[2]^.reg) shl 16;
  2954. end
  2955. else
  2956. begin
  2957. bytes:=bytes or getsupreg(oper[1]^.reg) shl 16;
  2958. bytes:=bytes or getsupreg(oper[2]^.reg);
  2959. end;
  2960. if ops=4 then
  2961. begin
  2962. if oper[3]^.typ=top_shifterop then
  2963. begin
  2964. if opcode in [A_PKHBT,A_PKHTB] then
  2965. begin
  2966. if ((opcode=A_PKHTB) and
  2967. (oper[3]^.shifterop^.shiftmode <> SM_ASR)) or
  2968. ((opcode=A_PKHBT) and
  2969. (oper[3]^.shifterop^.shiftmode <> SM_LSL)) or
  2970. (oper[3]^.shifterop^.rs<>NR_NO) then
  2971. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  2972. bytes:=bytes or ((oper[3]^.shifterop^.shiftimm and $1F) shl 7);
  2973. end
  2974. else
  2975. begin
  2976. if (oper[3]^.shifterop^.shiftmode<>sm_ror) or
  2977. (oper[3]^.shifterop^.rs<>NR_NO) or
  2978. (not (oper[3]^.shifterop^.shiftimm in [0,8,16,24])) then
  2979. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  2980. bytes:=bytes or (((oper[3]^.shifterop^.shiftimm shr 3) and $3) shl 10);
  2981. end;
  2982. end
  2983. else
  2984. bytes:=bytes or getsupreg(oper[3]^.reg) shl 8;
  2985. end;
  2986. if PF_S=oppostfix then
  2987. bytes:=bytes or (1 shl 20);
  2988. if PF_X=oppostfix then
  2989. bytes:=bytes or (1 shl 5);
  2990. end;
  2991. #$17: // LDR/STR
  2992. begin
  2993. { set instruction code }
  2994. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  2995. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  2996. { set Rn and Rd }
  2997. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  2998. bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
  2999. if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
  3000. begin
  3001. { set offset }
  3002. offset:=0;
  3003. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  3004. if assigned(currsym) then
  3005. offset:=currsym.offset-insoffset-8;
  3006. offset:=offset+oper[1]^.ref^.offset;
  3007. if offset>=0 then
  3008. { set U flag }
  3009. bytes:=bytes or (1 shl 23)
  3010. else
  3011. offset:=-offset;
  3012. bytes:=bytes or (offset and $FFF);
  3013. end
  3014. else
  3015. begin
  3016. { set U flag }
  3017. if oper[1]^.ref^.signindex>=0 then
  3018. bytes:=bytes or (1 shl 23);
  3019. { set I flag }
  3020. bytes:=bytes or (1 shl 25);
  3021. bytes:=bytes or getsupreg(oper[1]^.ref^.index);
  3022. { set shift }
  3023. with oper[1]^.ref^ do
  3024. if shiftmode<>SM_None then
  3025. begin
  3026. bytes:=bytes or ((shiftimm and $1F) shl 7);
  3027. if shiftmode<>SM_RRX then
  3028. bytes:=bytes or (ord(shiftmode) - ord(SM_LSL)) shl 5
  3029. else
  3030. bytes:=bytes or (3 shl 5);
  3031. end
  3032. end;
  3033. { set W bit }
  3034. if oper[1]^.ref^.addressmode=AM_PREINDEXED then
  3035. bytes:=bytes or (1 shl 21);
  3036. { set P bit if necessary }
  3037. if oper[1]^.ref^.addressmode<>AM_POSTINDEXED then
  3038. bytes:=bytes or (1 shl 24);
  3039. end;
  3040. #$18: // LDREX/STREX
  3041. begin
  3042. { set instruction code }
  3043. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3044. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3045. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3046. bytes:=bytes or ord(insentry^.code[4]);
  3047. { set Rn and Rd }
  3048. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  3049. if (ops=3) then
  3050. begin
  3051. if opcode<>A_LDREXD then
  3052. bytes:=bytes or getsupreg(oper[1]^.reg);
  3053. bytes:=bytes or (getsupreg(oper[2]^.ref^.base) shl 16);
  3054. end
  3055. else if (ops=4) then // STREXD
  3056. begin
  3057. if opcode<>A_LDREXD then
  3058. bytes:=bytes or getsupreg(oper[1]^.reg);
  3059. bytes:=bytes or (getsupreg(oper[3]^.ref^.base) shl 16);
  3060. end
  3061. else
  3062. bytes:=bytes or (getsupreg(oper[1]^.ref^.base) shl 16);
  3063. end;
  3064. #$19: // LDRD/STRD
  3065. begin
  3066. { set instruction code }
  3067. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3068. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3069. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3070. bytes:=bytes or ord(insentry^.code[4]);
  3071. { set Rn and Rd }
  3072. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  3073. refoper:=oper[1];
  3074. if ops=3 then
  3075. refoper:=oper[2];
  3076. bytes:=bytes or getsupreg(refoper^.ref^.base) shl 16;
  3077. if getregtype(refoper^.ref^.index)=R_INVALIDREGISTER then
  3078. begin
  3079. bytes:=bytes or (1 shl 22);
  3080. { set offset }
  3081. offset:=0;
  3082. currsym:=objdata.symbolref(refoper^.ref^.symbol);
  3083. if assigned(currsym) then
  3084. offset:=currsym.offset-insoffset-8;
  3085. offset:=offset+refoper^.ref^.offset;
  3086. if offset>=0 then
  3087. { set U flag }
  3088. bytes:=bytes or (1 shl 23)
  3089. else
  3090. offset:=-offset;
  3091. bytes:=bytes or (offset and $F);
  3092. bytes:=bytes or ((offset and $F0) shl 4);
  3093. end
  3094. else
  3095. begin
  3096. { set U flag }
  3097. if refoper^.ref^.signindex>=0 then
  3098. bytes:=bytes or (1 shl 23);
  3099. bytes:=bytes or getsupreg(refoper^.ref^.index);
  3100. end;
  3101. { set W bit }
  3102. if refoper^.ref^.addressmode=AM_PREINDEXED then
  3103. bytes:=bytes or (1 shl 21);
  3104. { set P bit if necessary }
  3105. if refoper^.ref^.addressmode<>AM_POSTINDEXED then
  3106. bytes:=bytes or (1 shl 24);
  3107. end;
  3108. #$1A: // QADD/QSUB
  3109. begin
  3110. { set instruction code }
  3111. bytes:=bytes or ord(insentry^.code[1]) shl 24;
  3112. bytes:=bytes or ord(insentry^.code[2]) shl 16;
  3113. bytes:=bytes or ord(insentry^.code[3]) shl 4;
  3114. { set regs }
  3115. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  3116. bytes:=bytes or getsupreg(oper[1]^.reg) shl 0;
  3117. bytes:=bytes or getsupreg(oper[2]^.reg) shl 16;
  3118. end;
  3119. #$1B:
  3120. begin
  3121. { set instruction code }
  3122. bytes:=bytes or ord(insentry^.code[1]) shl 24;
  3123. bytes:=bytes or ord(insentry^.code[2]) shl 16;
  3124. bytes:=bytes or ord(insentry^.code[3]) shl 4;
  3125. { set regs }
  3126. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  3127. bytes:=bytes or getsupreg(oper[1]^.reg);
  3128. if ops=3 then
  3129. begin
  3130. if (oper[2]^.shifterop^.shiftmode<>sm_ror) or
  3131. (oper[2]^.shifterop^.rs<>NR_NO) or
  3132. (not (oper[2]^.shifterop^.shiftimm in [0,8,16,24])) then
  3133. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  3134. bytes:=bytes or (((oper[2]^.shifterop^.shiftimm shr 3) and $3) shl 10);
  3135. end;
  3136. end;
  3137. #$1C: // MCR/MRC
  3138. begin
  3139. { set instruction code }
  3140. bytes:=bytes or ord(insentry^.code[1]) shl 24;
  3141. bytes:=bytes or ord(insentry^.code[2]) shl 16;
  3142. bytes:=bytes or ord(insentry^.code[3]) shl 4;
  3143. { set regs and operands }
  3144. bytes:=bytes or getcoproc(oper[0]^.reg) shl 8;
  3145. bytes:=bytes or ((oper[1]^.val and $7) shl 21);
  3146. bytes:=bytes or getsupreg(oper[2]^.reg) shl 12;
  3147. bytes:=bytes or getcoprocreg(oper[3]^.reg) shl 16;
  3148. bytes:=bytes or getcoprocreg(oper[4]^.reg);
  3149. if ops > 5 then
  3150. bytes:=bytes or ((oper[5]^.val and $7) shl 5);
  3151. end;
  3152. #$1D: // MCRR/MRRC
  3153. begin
  3154. { set instruction code }
  3155. bytes:=bytes or ord(insentry^.code[1]) shl 24;
  3156. bytes:=bytes or ord(insentry^.code[2]) shl 16;
  3157. bytes:=bytes or ord(insentry^.code[3]) shl 4;
  3158. { set regs and operands }
  3159. bytes:=bytes or getcoproc(oper[0]^.reg) shl 8;
  3160. bytes:=bytes or ((oper[1]^.val and $7) shl 4);
  3161. bytes:=bytes or getsupreg(oper[2]^.reg) shl 12;
  3162. bytes:=bytes or getsupreg(oper[3]^.reg) shl 16;
  3163. bytes:=bytes or getcoprocreg(oper[4]^.reg);
  3164. end;
  3165. #$1E: // LDRHT/STRHT
  3166. begin
  3167. { set instruction code }
  3168. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3169. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3170. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3171. bytes:=bytes or ord(insentry^.code[4]);
  3172. { set Rn and Rd }
  3173. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  3174. refoper:=oper[1];
  3175. bytes:=bytes or getsupreg(refoper^.ref^.base) shl 16;
  3176. if getregtype(refoper^.ref^.index)=R_INVALIDREGISTER then
  3177. begin
  3178. bytes:=bytes or (1 shl 22);
  3179. { set offset }
  3180. offset:=0;
  3181. currsym:=objdata.symbolref(refoper^.ref^.symbol);
  3182. if assigned(currsym) then
  3183. offset:=currsym.offset-insoffset-8;
  3184. offset:=offset+refoper^.ref^.offset;
  3185. if offset>=0 then
  3186. { set U flag }
  3187. bytes:=bytes or (1 shl 23)
  3188. else
  3189. offset:=-offset;
  3190. bytes:=bytes or (offset and $F);
  3191. bytes:=bytes or ((offset and $F0) shl 4);
  3192. end
  3193. else
  3194. begin
  3195. { set U flag }
  3196. if refoper^.ref^.signindex>=0 then
  3197. bytes:=bytes or (1 shl 23);
  3198. bytes:=bytes or getsupreg(refoper^.ref^.index);
  3199. end;
  3200. end;
  3201. #$22: // LDRH/STRH
  3202. begin
  3203. { set instruction code }
  3204. bytes:=bytes or (ord(insentry^.code[1]) shl 16);
  3205. bytes:=bytes or ord(insentry^.code[2]);
  3206. { src/dest register (Rd) }
  3207. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  3208. { base register (Rn) }
  3209. bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
  3210. if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
  3211. begin
  3212. bytes:=bytes or (1 shl 22); // with immediate offset
  3213. offset:=oper[1]^.ref^.offset;
  3214. if offset>=0 then
  3215. { set U flag }
  3216. bytes:=bytes or (1 shl 23)
  3217. else
  3218. offset:=-offset;
  3219. bytes:=bytes or (offset and $F);
  3220. bytes:=bytes or ((offset and $F0) shl 4);
  3221. end
  3222. else
  3223. begin
  3224. { set U flag }
  3225. if oper[1]^.ref^.signindex>=0 then
  3226. bytes:=bytes or (1 shl 23);
  3227. bytes:=bytes or getsupreg(oper[1]^.ref^.index);
  3228. end;
  3229. { set W bit }
  3230. if oper[1]^.ref^.addressmode=AM_PREINDEXED then
  3231. bytes:=bytes or (1 shl 21);
  3232. { set P bit if necessary }
  3233. if oper[1]^.ref^.addressmode<>AM_POSTINDEXED then
  3234. bytes:=bytes or (1 shl 24);
  3235. end;
  3236. #$25: // PLD/PLI
  3237. begin
  3238. { set instruction code }
  3239. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3240. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3241. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3242. bytes:=bytes or ord(insentry^.code[4]);
  3243. { set Rn and Rd }
  3244. bytes:=bytes or getsupreg(oper[0]^.ref^.base) shl 16;
  3245. if getregtype(oper[0]^.ref^.index)=R_INVALIDREGISTER then
  3246. begin
  3247. { set offset }
  3248. offset:=0;
  3249. currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
  3250. if assigned(currsym) then
  3251. offset:=currsym.offset-insoffset-8;
  3252. offset:=offset+oper[0]^.ref^.offset;
  3253. if offset>=0 then
  3254. begin
  3255. { set U flag }
  3256. bytes:=bytes or (1 shl 23);
  3257. bytes:=bytes or offset
  3258. end
  3259. else
  3260. begin
  3261. offset:=-offset;
  3262. bytes:=bytes or offset
  3263. end;
  3264. end
  3265. else
  3266. begin
  3267. bytes:=bytes or (1 shl 25);
  3268. { set U flag }
  3269. if oper[0]^.ref^.signindex>=0 then
  3270. bytes:=bytes or (1 shl 23);
  3271. bytes:=bytes or getsupreg(oper[0]^.ref^.index);
  3272. { set shift }
  3273. with oper[0]^.ref^ do
  3274. if shiftmode<>SM_None then
  3275. begin
  3276. bytes:=bytes or ((shiftimm and $1F) shl 7);
  3277. if shiftmode<>SM_RRX then
  3278. bytes:=bytes or (ord(shiftmode) - ord(SM_LSL)) shl 5
  3279. else
  3280. bytes:=bytes or (3 shl 5);
  3281. end
  3282. end;
  3283. end;
  3284. #$26: // LDM/STM
  3285. begin
  3286. { set instruction code }
  3287. bytes:=bytes or (ord(insentry^.code[1]) shl 20);
  3288. if ops>1 then
  3289. begin
  3290. if oper[0]^.typ=top_ref then
  3291. begin
  3292. { set W bit }
  3293. if oper[0]^.ref^.addressmode=AM_PREINDEXED then
  3294. bytes:=bytes or (1 shl 21);
  3295. { set Rn }
  3296. bytes:=bytes or (getsupreg(oper[0]^.ref^.index) shl 16);
  3297. end
  3298. else { typ=top_reg }
  3299. begin
  3300. { set Rn }
  3301. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
  3302. end;
  3303. if oper[1]^.usermode then
  3304. begin
  3305. if (oper[0]^.typ=top_ref) then
  3306. begin
  3307. if (opcode=A_LDM) and
  3308. (RS_PC in oper[1]^.regset^) then
  3309. begin
  3310. // Valid exception return
  3311. end
  3312. else
  3313. Message(asmw_e_invalid_opcode_and_operands);
  3314. end;
  3315. bytes:=bytes or (1 shl 22);
  3316. end;
  3317. { reglist }
  3318. bytes:=bytes or MakeRegList(oper[1]^.regset^);
  3319. end
  3320. else
  3321. begin
  3322. { push/pop }
  3323. { Set W and Rn to SP }
  3324. if opcode=A_PUSH then
  3325. bytes:=bytes or (1 shl 21);
  3326. bytes:=bytes or ($D shl 16);
  3327. { reglist }
  3328. bytes:=bytes or MakeRegList(oper[0]^.regset^);
  3329. end;
  3330. { set P bit }
  3331. if (opcode=A_LDM) and (oppostfix in [PF_ED,PF_EA,PF_IB,PF_DB])
  3332. or (opcode=A_STM) and (oppostfix in [PF_FA,PF_FD,PF_IB,PF_DB])
  3333. or (opcode=A_PUSH) then
  3334. bytes:=bytes or (1 shl 24);
  3335. { set U bit }
  3336. if (opcode=A_LDM) and (oppostfix in [PF_None,PF_ED,PF_FD,PF_IB,PF_IA])
  3337. or (opcode=A_STM) and (oppostfix in [PF_None,PF_FA,PF_EA,PF_IB,PF_IA])
  3338. or (opcode=A_POP) then
  3339. bytes:=bytes or (1 shl 23);
  3340. end;
  3341. #$27: // SWP/SWPB
  3342. begin
  3343. { set instruction code }
  3344. bytes:=bytes or (ord(insentry^.code[1]) shl 20);
  3345. bytes:=bytes or (ord(insentry^.code[2]) shl 4);
  3346. { set regs }
  3347. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3348. bytes:=bytes or getsupreg(oper[1]^.reg);
  3349. if ops=3 then
  3350. bytes:=bytes or (getsupreg(oper[2]^.ref^.base) shl 16);
  3351. end;
  3352. #$28: // BX/BLX
  3353. begin
  3354. { set instruction code }
  3355. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3356. { set offset }
  3357. if oper[0]^.typ=top_const then
  3358. bytes:=bytes or ((oper[0]^.val shr 2) and $ffffff)
  3359. else
  3360. begin
  3361. currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
  3362. if (currsym.bind<>AB_LOCAL) and (currsym.objsection<>objdata.CurrObjSec) then
  3363. begin
  3364. bytes:=bytes or $fffffe; // TODO: Not sure this is right, but it matches the output of gas
  3365. objdata.writereloc(oper[0]^.ref^.offset,0,currsym,RELOC_RELATIVE_24_THUMB);
  3366. end
  3367. else
  3368. begin
  3369. offset:=((currsym.offset-insoffset-8) and $3fffffe);
  3370. { Turn BLX into BL if the destination isn't odd, could happen with recursion }
  3371. if not odd(offset shr 1) then
  3372. bytes:=(bytes and $EB000000) or $EB000000;
  3373. bytes:=bytes or ((offset shr 2) and $ffffff);
  3374. bytes:=bytes or ((offset shr 1) and $1) shl 24;
  3375. end;
  3376. end;
  3377. end;
  3378. #$29: // SUB
  3379. begin
  3380. { set instruction code }
  3381. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3382. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3383. { set regs }
  3384. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3385. { set S if necessary }
  3386. if oppostfix=PF_S then
  3387. bytes:=bytes or (1 shl 20);
  3388. end;
  3389. #$2A:
  3390. begin
  3391. { set instruction code }
  3392. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3393. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3394. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3395. bytes:=bytes or ord(insentry^.code[4]);
  3396. { set opers }
  3397. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3398. if opcode in [A_SSAT, A_SSAT16] then
  3399. bytes:=bytes or (((oper[1]^.val-1) and $1F) shl 16)
  3400. else
  3401. bytes:=bytes or ((oper[1]^.val and $1F) shl 16);
  3402. bytes:=bytes or getsupreg(oper[2]^.reg);
  3403. if (ops>3) and
  3404. (oper[3]^.typ=top_shifterop) and
  3405. (oper[3]^.shifterop^.rs=NR_NO) then
  3406. begin
  3407. bytes:=bytes or ((oper[3]^.shifterop^.shiftimm and $1F) shl 7);
  3408. if oper[3]^.shifterop^.shiftmode=SM_ASR then
  3409. bytes:=bytes or (1 shl 6)
  3410. else if oper[3]^.shifterop^.shiftmode<>SM_LSL then
  3411. Message1(asmw_e_invalid_opcode_and_operands,GetString);
  3412. end;
  3413. end;
  3414. #$2B: // SETEND
  3415. begin
  3416. { set instruction code }
  3417. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3418. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3419. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3420. bytes:=bytes or ord(insentry^.code[4]);
  3421. { set endian specifier }
  3422. bytes:=bytes or ((oper[0]^.val and 1) shl 9);
  3423. end;
  3424. #$2C: // MOVW
  3425. begin
  3426. { set instruction code }
  3427. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3428. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3429. { set destination }
  3430. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3431. { set imm }
  3432. bytes:=bytes or (oper[1]^.val and $FFF);
  3433. bytes:=bytes or ((oper[1]^.val and $F000) shl 4);
  3434. end;
  3435. #$2D: // BFX
  3436. begin
  3437. { set instruction code }
  3438. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3439. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3440. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3441. bytes:=bytes or ord(insentry^.code[4]);
  3442. if ops=3 then
  3443. begin
  3444. msb:=(oper[1]^.val+oper[2]^.val-1);
  3445. { set destination }
  3446. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3447. { set immediates }
  3448. bytes:=bytes or ((oper[1]^.val and $1F) shl 7);
  3449. bytes:=bytes or ((msb and $1F) shl 16);
  3450. end
  3451. else
  3452. begin
  3453. if opcode in [A_BFC,A_BFI] then
  3454. msb:=(oper[2]^.val+oper[3]^.val-1)
  3455. else
  3456. msb:=oper[3]^.val-1;
  3457. { set destination }
  3458. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3459. bytes:=bytes or getsupreg(oper[1]^.reg);
  3460. { set immediates }
  3461. bytes:=bytes or ((oper[2]^.val and $1F) shl 7);
  3462. bytes:=bytes or ((msb and $1F) shl 16);
  3463. end;
  3464. end;
  3465. #$2E: // Cache stuff
  3466. begin
  3467. { set instruction code }
  3468. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3469. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3470. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3471. bytes:=bytes or ord(insentry^.code[4]);
  3472. { set code }
  3473. bytes:=bytes or (oper[0]^.val and $F);
  3474. end;
  3475. #$2F: // Nop
  3476. begin
  3477. { set instruction code }
  3478. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3479. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3480. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3481. bytes:=bytes or ord(insentry^.code[4]);
  3482. end;
  3483. #$30: // Shifts
  3484. begin
  3485. { set instruction code }
  3486. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3487. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3488. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3489. bytes:=bytes or ord(insentry^.code[4]);
  3490. { set destination }
  3491. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3492. bytes:=bytes or getsupreg(oper[1]^.reg);
  3493. if ops>2 then
  3494. begin
  3495. { set shift }
  3496. if oper[2]^.typ=top_reg then
  3497. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 8)
  3498. else
  3499. bytes:=bytes or ((oper[2]^.val and $1F) shl 7);
  3500. end;
  3501. { set S if necessary }
  3502. if oppostfix=PF_S then
  3503. bytes:=bytes or (1 shl 20);
  3504. end;
  3505. #$31: // BKPT
  3506. begin
  3507. { set instruction code }
  3508. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3509. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3510. bytes:=bytes or (ord(insentry^.code[3]) shl 0);
  3511. { set imm }
  3512. bytes:=bytes or (oper[0]^.val and $FFF0) shl 4;
  3513. bytes:=bytes or (oper[0]^.val and $F);
  3514. end;
  3515. #$32: // CLZ/REV
  3516. begin
  3517. { set instruction code }
  3518. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3519. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3520. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3521. bytes:=bytes or ord(insentry^.code[4]);
  3522. { set regs }
  3523. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3524. bytes:=bytes or getsupreg(oper[1]^.reg);
  3525. end;
  3526. #$33:
  3527. begin
  3528. { set instruction code }
  3529. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3530. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3531. { set regs }
  3532. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3533. if oper[1]^.typ=top_ref then
  3534. begin
  3535. { set offset }
  3536. offset:=0;
  3537. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  3538. if assigned(currsym) then
  3539. offset:=currsym.offset-insoffset-8;
  3540. offset:=offset+oper[1]^.ref^.offset;
  3541. if offset>=0 then
  3542. begin
  3543. { set U flag }
  3544. bytes:=bytes or (1 shl 23);
  3545. bytes:=bytes or offset
  3546. end
  3547. else
  3548. begin
  3549. bytes:=bytes or (1 shl 22);
  3550. offset:=-offset;
  3551. bytes:=bytes or offset
  3552. end;
  3553. end
  3554. else
  3555. begin
  3556. if is_shifter_const(oper[1]^.val,r) then
  3557. begin
  3558. setshifterop(1);
  3559. bytes:=bytes or (1 shl 23);
  3560. end
  3561. else
  3562. begin
  3563. bytes:=bytes or (1 shl 22);
  3564. oper[1]^.val:=-oper[1]^.val;
  3565. setshifterop(1);
  3566. end;
  3567. end;
  3568. end;
  3569. #$40,#$90: // VMOV
  3570. begin
  3571. { set instruction code }
  3572. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3573. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3574. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3575. bytes:=bytes or ord(insentry^.code[4]);
  3576. { set regs }
  3577. Rd:=0;
  3578. Rn:=0;
  3579. Rm:=0;
  3580. case oppostfix of
  3581. PF_None:
  3582. begin
  3583. if ops=4 then
  3584. begin
  3585. if (getregtype(oper[0]^.reg)=R_MMREGISTER) and
  3586. (getregtype(oper[2]^.reg)=R_INTREGISTER) then
  3587. begin
  3588. Rd:=getmmreg(oper[0]^.reg);
  3589. Rm:=getsupreg(oper[2]^.reg);
  3590. Rn:=getsupreg(oper[3]^.reg);
  3591. end
  3592. else if (getregtype(oper[0]^.reg)=R_INTREGISTER) and
  3593. (getregtype(oper[2]^.reg)=R_MMREGISTER) then
  3594. begin
  3595. Rm:=getsupreg(oper[0]^.reg);
  3596. Rn:=getsupreg(oper[1]^.reg);
  3597. Rd:=getmmreg(oper[2]^.reg);
  3598. end
  3599. else
  3600. message(asmw_e_invalid_opcode_and_operands);
  3601. bytes:=bytes or (((Rd and $1E) shr 1) shl 0);
  3602. bytes:=bytes or ((Rd and $1) shl 5);
  3603. bytes:=bytes or (Rm shl 12);
  3604. bytes:=bytes or (Rn shl 16);
  3605. end
  3606. else if ops=3 then
  3607. begin
  3608. if (getregtype(oper[0]^.reg)=R_MMREGISTER) and
  3609. (getregtype(oper[1]^.reg)=R_INTREGISTER) then
  3610. begin
  3611. Rd:=getmmreg(oper[0]^.reg);
  3612. Rm:=getsupreg(oper[1]^.reg);
  3613. Rn:=getsupreg(oper[2]^.reg);
  3614. end
  3615. else if (getregtype(oper[0]^.reg)=R_INTREGISTER) and
  3616. (getregtype(oper[2]^.reg)=R_MMREGISTER) then
  3617. begin
  3618. Rm:=getsupreg(oper[0]^.reg);
  3619. Rn:=getsupreg(oper[1]^.reg);
  3620. Rd:=getmmreg(oper[2]^.reg);
  3621. end
  3622. else
  3623. message(asmw_e_invalid_opcode_and_operands);
  3624. bytes:=bytes or ((Rd and $F) shl 0);
  3625. bytes:=bytes or ((Rd and $10) shl 1);
  3626. bytes:=bytes or (Rm shl 12);
  3627. bytes:=bytes or (Rn shl 16);
  3628. end
  3629. else if ops=2 then
  3630. begin
  3631. if (getregtype(oper[0]^.reg)=R_MMREGISTER) and
  3632. (getregtype(oper[1]^.reg)=R_INTREGISTER) then
  3633. begin
  3634. Rd:=getmmreg(oper[0]^.reg);
  3635. Rm:=getsupreg(oper[1]^.reg);
  3636. end
  3637. else if (getregtype(oper[0]^.reg)=R_INTREGISTER) and
  3638. (getregtype(oper[1]^.reg)=R_MMREGISTER) then
  3639. begin
  3640. Rm:=getsupreg(oper[0]^.reg);
  3641. Rd:=getmmreg(oper[1]^.reg);
  3642. end
  3643. else
  3644. message(asmw_e_invalid_opcode_and_operands);
  3645. bytes:=bytes or (((Rd and $1E) shr 1) shl 16);
  3646. bytes:=bytes or ((Rd and $1) shl 7);
  3647. bytes:=bytes or (Rm shl 12);
  3648. end;
  3649. end;
  3650. PF_F32:
  3651. begin
  3652. if (getregtype(oper[0]^.reg)<>R_MMREGISTER) then
  3653. Message(asmw_e_invalid_opcode_and_operands);
  3654. case oper[1]^.typ of
  3655. top_realconst:
  3656. begin
  3657. if not(IsVFPFloatImmediate(s32real,oper[1]^.val_real)) then
  3658. Message(asmw_e_invalid_opcode_and_operands);
  3659. singlerec.value:=oper[1]^.val_real;
  3660. singlerec:=tcompsinglerec(NtoLE(DWord(singlerec)));
  3661. bytes:=bytes or ((singlerec.bytes[2] shr 3) and $f);
  3662. bytes:=bytes or (DWord((singlerec.bytes[2] shr 7) and $1) shl 16) or (DWord(singlerec.bytes[3] and $3) shl 17) or (DWord((singlerec.bytes[3] shr 7) and $1) shl 19);
  3663. end;
  3664. top_reg:
  3665. begin
  3666. if getregtype(oper[1]^.reg)<>R_MMREGISTER then
  3667. Message(asmw_e_invalid_opcode_and_operands);
  3668. Rm:=getmmreg(oper[1]^.reg);
  3669. bytes:=bytes or (((Rm and $1E) shr 1) shl 0);
  3670. bytes:=bytes or ((Rm and $1) shl 5);
  3671. end;
  3672. else
  3673. Message(asmw_e_invalid_opcode_and_operands);
  3674. end;
  3675. Rd:=getmmreg(oper[0]^.reg);
  3676. bytes:=bytes or (((Rd and $1E) shr 1) shl 12);
  3677. bytes:=bytes or ((Rd and $1) shl 22);
  3678. end;
  3679. PF_F64:
  3680. begin
  3681. if (getregtype(oper[0]^.reg)<>R_MMREGISTER) then
  3682. Message(asmw_e_invalid_opcode_and_operands);
  3683. case oper[1]^.typ of
  3684. top_realconst:
  3685. begin
  3686. if not(IsVFPFloatImmediate(s64real,oper[1]^.val_real)) then
  3687. Message(asmw_e_invalid_opcode_and_operands);
  3688. doublerec.value:=oper[1]^.val_real;
  3689. doublerec:=tcompdoublerec(NtoLE(QWord(doublerec)));
  3690. // 32c: eeb41b00 vmov.f64 d1, #64 ; 0x40
  3691. // 32c: eeb61b00 vmov.f64 d1, #96 ; 0x60
  3692. bytes:=bytes or (doublerec.bytes[6] and $f);
  3693. bytes:=bytes or (DWord((doublerec.bytes[6] shr 4) and $7) shl 16) or (DWord((doublerec.bytes[7] shr 7) and $1) shl 19);
  3694. end;
  3695. top_reg:
  3696. begin
  3697. if getregtype(oper[1]^.reg)<>R_MMREGISTER then
  3698. Message(asmw_e_invalid_opcode_and_operands);
  3699. Rm:=getmmreg(oper[1]^.reg);
  3700. bytes:=bytes or (Rm and $F);
  3701. bytes:=bytes or ((Rm and $10) shl 1);
  3702. end;
  3703. else
  3704. Message(asmw_e_invalid_opcode_and_operands);
  3705. end;
  3706. Rd:=getmmreg(oper[0]^.reg);
  3707. bytes:=bytes or (1 shl 8);
  3708. bytes:=bytes or ((Rd and $F) shl 12);
  3709. bytes:=bytes or (((Rd and $10) shr 4) shl 22);
  3710. end;
  3711. else
  3712. Message(asmw_e_invalid_opcode_and_operands);
  3713. end;
  3714. end;
  3715. #$41,#$91: // VMRS/VMSR
  3716. begin
  3717. { set instruction code }
  3718. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3719. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3720. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3721. bytes:=bytes or ord(insentry^.code[4]);
  3722. { set regs }
  3723. if (opcode=A_VMRS) or
  3724. (opcode=A_FMRX) then
  3725. begin
  3726. case oper[1]^.reg of
  3727. NR_FPSID: Rn:=$0;
  3728. NR_FPSCR: Rn:=$1;
  3729. NR_MVFR1: Rn:=$6;
  3730. NR_MVFR0: Rn:=$7;
  3731. NR_FPEXC: Rn:=$8;
  3732. else
  3733. Rn:=0;
  3734. message(asmw_e_invalid_opcode_and_operands);
  3735. end;
  3736. bytes:=bytes or (Rn shl 16);
  3737. if oper[0]^.reg=NR_APSR_nzcv then
  3738. bytes:=bytes or ($F shl 12)
  3739. else
  3740. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  3741. end
  3742. else
  3743. begin
  3744. case oper[0]^.reg of
  3745. NR_FPSID: Rn:=$0;
  3746. NR_FPSCR: Rn:=$1;
  3747. NR_FPEXC: Rn:=$8;
  3748. else
  3749. Rn:=0;
  3750. message(asmw_e_invalid_opcode_and_operands);
  3751. end;
  3752. bytes:=bytes or (Rn shl 16);
  3753. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 12);
  3754. end;
  3755. end;
  3756. #$42,#$92: // VMUL
  3757. begin
  3758. { set instruction code }
  3759. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3760. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3761. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3762. bytes:=bytes or ord(insentry^.code[4]);
  3763. { set regs }
  3764. if ops=3 then
  3765. begin
  3766. Rd:=getmmreg(oper[0]^.reg);
  3767. Rn:=getmmreg(oper[1]^.reg);
  3768. Rm:=getmmreg(oper[2]^.reg);
  3769. end
  3770. else if ops=1 then
  3771. begin
  3772. Rd:=getmmreg(oper[0]^.reg);
  3773. Rn:=0;
  3774. Rm:=0;
  3775. end
  3776. else if oper[1]^.typ=top_const then
  3777. begin
  3778. Rd:=getmmreg(oper[0]^.reg);
  3779. Rn:=0;
  3780. Rm:=0;
  3781. end
  3782. else
  3783. begin
  3784. Rd:=getmmreg(oper[0]^.reg);
  3785. Rn:=0;
  3786. Rm:=getmmreg(oper[1]^.reg);
  3787. end;
  3788. if (oppostfix=PF_F32) or (insentry^.code[5]=#1) then
  3789. begin
  3790. D:=rd and $1; Rd:=Rd shr 1;
  3791. N:=rn and $1; Rn:=Rn shr 1;
  3792. M:=rm and $1; Rm:=Rm shr 1;
  3793. end
  3794. else
  3795. begin
  3796. D:=(rd shr 4) and $1; Rd:=Rd and $F;
  3797. N:=(rn shr 4) and $1; Rn:=Rn and $F;
  3798. M:=(rm shr 4) and $1; Rm:=Rm and $F;
  3799. bytes:=bytes or (1 shl 8);
  3800. end;
  3801. bytes:=bytes or (Rd shl 12);
  3802. bytes:=bytes or (Rn shl 16);
  3803. bytes:=bytes or (Rm shl 0);
  3804. bytes:=bytes or (D shl 22);
  3805. bytes:=bytes or (N shl 7);
  3806. bytes:=bytes or (M shl 5);
  3807. end;
  3808. #$43,#$93: // VCVT
  3809. begin
  3810. { set instruction code }
  3811. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  3812. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  3813. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  3814. bytes:=bytes or ord(insentry^.code[4]);
  3815. { set regs }
  3816. Rd:=getmmreg(oper[0]^.reg);
  3817. Rm:=getmmreg(oper[1]^.reg);
  3818. if (ops=2) and
  3819. (oppostfix in [PF_F32F64,PF_F64F32]) then
  3820. begin
  3821. if oppostfix=PF_F32F64 then
  3822. begin
  3823. bytes:=bytes or (1 shl 8);
  3824. D:=rd and $1; Rd:=Rd shr 1;
  3825. M:=(rm shr 4) and $1; Rm:=Rm and $F;
  3826. end
  3827. else
  3828. begin
  3829. D:=(rd shr 4) and $1; Rd:=Rd and $F;
  3830. M:=rm and $1; Rm:=Rm shr 1;
  3831. end;
  3832. bytes:=bytes and $FFF0FFFF;
  3833. bytes:=bytes or ($7 shl 16);
  3834. bytes:=bytes or (Rd shl 12);
  3835. bytes:=bytes or (Rm shl 0);
  3836. bytes:=bytes or (D shl 22);
  3837. bytes:=bytes or (M shl 5);
  3838. end
  3839. else if (ops=2) and
  3840. (oppostfix=PF_None) then
  3841. begin
  3842. d:=0;
  3843. case getsubreg(oper[0]^.reg) of
  3844. R_SUBNONE:
  3845. rd:=getsupreg(oper[0]^.reg);
  3846. R_SUBFS:
  3847. begin
  3848. rd:=getmmreg(oper[0]^.reg);
  3849. d:=rd and 1;
  3850. rd:=rd shr 1;
  3851. end;
  3852. R_SUBFD:
  3853. begin
  3854. rd:=getmmreg(oper[0]^.reg);
  3855. d:=(rd shr 4) and 1;
  3856. rd:=rd and $F;
  3857. end;
  3858. else
  3859. internalerror(2019050929);
  3860. end;
  3861. m:=0;
  3862. case getsubreg(oper[1]^.reg) of
  3863. R_SUBNONE:
  3864. rm:=getsupreg(oper[1]^.reg);
  3865. R_SUBFS:
  3866. begin
  3867. rm:=getmmreg(oper[1]^.reg);
  3868. m:=rm and 1;
  3869. rm:=rm shr 1;
  3870. end;
  3871. R_SUBFD:
  3872. begin
  3873. rm:=getmmreg(oper[1]^.reg);
  3874. m:=(rm shr 4) and 1;
  3875. rm:=rm and $F;
  3876. end;
  3877. else
  3878. internalerror(2019050928);
  3879. end;
  3880. bytes:=bytes or (Rd shl 12);
  3881. bytes:=bytes or (Rm shl 0);
  3882. bytes:=bytes or (D shl 22);
  3883. bytes:=bytes or (M shl 5);
  3884. end
  3885. else if ops=2 then
  3886. begin
  3887. case oppostfix of
  3888. PF_S32F64,
  3889. PF_U32F64,
  3890. PF_F64S32,
  3891. PF_F64U32:
  3892. bytes:=bytes or (1 shl 8);
  3893. else
  3894. ;
  3895. end;
  3896. if oppostfix in [PF_S32F32,PF_S32F64,PF_U32F32,PF_U32F64] then
  3897. begin
  3898. case oppostfix of
  3899. PF_S32F64,
  3900. PF_S32F32:
  3901. bytes:=bytes or (1 shl 16);
  3902. else
  3903. ;
  3904. end;
  3905. bytes:=bytes or (1 shl 18);
  3906. D:=rd and $1; Rd:=Rd shr 1;
  3907. if oppostfix in [PF_S32F64,PF_U32F64] then
  3908. begin
  3909. M:=(rm shr 4) and $1; Rm:=Rm and $F;
  3910. end
  3911. else
  3912. begin
  3913. M:=rm and $1; Rm:=Rm shr 1;
  3914. end;
  3915. end
  3916. else
  3917. begin
  3918. case oppostfix of
  3919. PF_F64S32,
  3920. PF_F32S32:
  3921. bytes:=bytes or (1 shl 7);
  3922. else
  3923. bytes:=bytes and $FFFFFF7F;
  3924. end;
  3925. M:=rm and $1; Rm:=Rm shr 1;
  3926. if oppostfix in [PF_F64S32,PF_F64U32] then
  3927. begin
  3928. D:=(rd shr 4) and $1; Rd:=Rd and $F;
  3929. end
  3930. else
  3931. begin
  3932. D:=rd and $1; Rd:=Rd shr 1;
  3933. end
  3934. end;
  3935. bytes:=bytes or (Rd shl 12);
  3936. bytes:=bytes or (Rm shl 0);
  3937. bytes:=bytes or (D shl 22);
  3938. bytes:=bytes or (M shl 5);
  3939. end
  3940. else
  3941. begin
  3942. if rd<>rm then
  3943. message(asmw_e_invalid_opcode_and_operands);
  3944. case oppostfix of
  3945. PF_S32F32,PF_U32F32,
  3946. PF_F32S32,PF_F32U32,
  3947. PF_S32F64,PF_U32F64,
  3948. PF_F64S32,PF_F64U32:
  3949. begin
  3950. if not (oper[2]^.val in [1..32]) then
  3951. message1(asmw_e_invalid_opcode_and_operands, 'fbits not within 1-32');
  3952. bytes:=bytes or (1 shl 7);
  3953. rn:=32;
  3954. end;
  3955. PF_S16F64,PF_U16F64,
  3956. PF_F64S16,PF_F64U16,
  3957. PF_S16F32,PF_U16F32,
  3958. PF_F32S16,PF_F32U16:
  3959. begin
  3960. if not (oper[2]^.val in [0..16]) then
  3961. message1(asmw_e_invalid_opcode_and_operands, 'fbits not within 0-16');
  3962. rn:=16;
  3963. end;
  3964. else
  3965. Rn:=0;
  3966. message(asmw_e_invalid_opcode_and_operands);
  3967. end;
  3968. case oppostfix of
  3969. PF_S16F64,PF_U16F64,
  3970. PF_S32F64,PF_U32F64,
  3971. PF_F64S16,PF_F64U16,
  3972. PF_F64S32,PF_F64U32:
  3973. begin
  3974. bytes:=bytes or (1 shl 8);
  3975. D:=(rd shr 4) and $1; Rd:=Rd and $F;
  3976. end;
  3977. else
  3978. begin
  3979. D:=rd and $1; Rd:=Rd shr 1;
  3980. end;
  3981. end;
  3982. case oppostfix of
  3983. PF_U16F64,PF_U16F32,
  3984. PF_U32F32,PF_U32F64,
  3985. PF_F64U16,PF_F32U16,
  3986. PF_F32U32,PF_F64U32:
  3987. bytes:=bytes or (1 shl 16);
  3988. else
  3989. ;
  3990. end;
  3991. if oppostfix in [PF_S32F32,PF_S32F64,PF_U32F32,PF_U32F64,PF_S16F32,PF_S16F64,PF_U16F32,PF_U16F64] then
  3992. bytes:=bytes or (1 shl 18);
  3993. bytes:=bytes or (Rd shl 12);
  3994. bytes:=bytes or (D shl 22);
  3995. rn:=rn-oper[2]^.val;
  3996. bytes:=bytes or ((rn and $1) shl 5);
  3997. bytes:=bytes or ((rn and $1E) shr 1);
  3998. end;
  3999. end;
  4000. #$44,#$94: // VLDM/VSTM/VPUSH/VPOP
  4001. begin
  4002. { set instruction code }
  4003. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4004. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4005. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4006. { set regs }
  4007. if ops=2 then
  4008. begin
  4009. if oper[0]^.typ=top_ref then
  4010. begin
  4011. Rn:=getsupreg(oper[0]^.ref^.index);
  4012. if oper[0]^.ref^.addressmode<>AM_OFFSET then
  4013. begin
  4014. { set W }
  4015. bytes:=bytes or (1 shl 21);
  4016. end
  4017. else if oppostfix in [PF_DB,PF_DBS,PF_DBD,PF_DBX] then
  4018. message1(asmw_e_invalid_opcode_and_operands, 'Invalid postfix without writeback');
  4019. end
  4020. else
  4021. begin
  4022. Rn:=getsupreg(oper[0]^.reg);
  4023. if oppostfix in [PF_DB,PF_DBS,PF_DBD,PF_DBX] then
  4024. message1(asmw_e_invalid_opcode_and_operands, 'Invalid postfix without writeback');
  4025. end;
  4026. bytes:=bytes or (Rn shl 16);
  4027. { Set PU bits }
  4028. case oppostfix of
  4029. PF_None,
  4030. PF_IA,PF_IAS,PF_IAD,PF_IAX:
  4031. bytes:=bytes or (1 shl 23);
  4032. PF_DB,PF_DBS,PF_DBD,PF_DBX:
  4033. bytes:=bytes or (2 shl 23);
  4034. else
  4035. ;
  4036. end;
  4037. case oppostfix of
  4038. PF_IAX,PF_DBX,PF_FDX,PF_EAX:
  4039. begin
  4040. bytes:=bytes or (1 shl 8);
  4041. bytes:=bytes or (1 shl 0); // Offset is odd
  4042. end;
  4043. else
  4044. ;
  4045. end;
  4046. dp_operation:=(oper[1]^.subreg=R_SUBFD);
  4047. if oper[1]^.regset^=[] then
  4048. message1(asmw_e_invalid_opcode_and_operands, 'Regset cannot be empty');
  4049. rd:=0;
  4050. for r:=0 to 31 do
  4051. if r in oper[1]^.regset^ then
  4052. begin
  4053. rd:=r;
  4054. break;
  4055. end;
  4056. rn:=32-rd;
  4057. for r:=rd+1 to 31 do
  4058. if not(r in oper[1]^.regset^) then
  4059. begin
  4060. rn:=r-rd;
  4061. break;
  4062. end;
  4063. if dp_operation then
  4064. begin
  4065. bytes:=bytes or (1 shl 8);
  4066. bytes:=bytes or (rn*2);
  4067. bytes:=bytes or ((rd and $F) shl 12);
  4068. bytes:=bytes or (((rd and $10) shr 4) shl 22);
  4069. end
  4070. else
  4071. begin
  4072. bytes:=bytes or rn;
  4073. bytes:=bytes or ((rd and $1) shl 22);
  4074. bytes:=bytes or (((rd and $1E) shr 1) shl 12);
  4075. end;
  4076. end
  4077. else { VPUSH/VPOP }
  4078. begin
  4079. dp_operation:=(oper[0]^.subreg=R_SUBFD);
  4080. if oper[0]^.regset^=[] then
  4081. message1(asmw_e_invalid_opcode_and_operands, 'Regset cannot be empty');
  4082. rd:=0;
  4083. for r:=0 to 31 do
  4084. if r in oper[0]^.regset^ then
  4085. begin
  4086. rd:=r;
  4087. break;
  4088. end;
  4089. rn:=32-rd;
  4090. for r:=rd+1 to 31 do
  4091. if not(r in oper[0]^.regset^) then
  4092. begin
  4093. rn:=r-rd;
  4094. break;
  4095. end;
  4096. if dp_operation then
  4097. begin
  4098. bytes:=bytes or (1 shl 8);
  4099. bytes:=bytes or (rn*2);
  4100. bytes:=bytes or ((rd and $F) shl 12);
  4101. bytes:=bytes or (((rd and $10) shr 4) shl 22);
  4102. end
  4103. else
  4104. begin
  4105. bytes:=bytes or rn;
  4106. bytes:=bytes or ((rd and $1) shl 22);
  4107. bytes:=bytes or (((rd and $1E) shr 1) shl 12);
  4108. end;
  4109. end;
  4110. end;
  4111. #$45,#$95: // VLDR/VSTR
  4112. begin
  4113. { set instruction code }
  4114. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4115. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4116. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4117. { set regs }
  4118. rd:=getmmreg(oper[0]^.reg);
  4119. if getsubreg(oper[0]^.reg)=R_SUBFD then
  4120. begin
  4121. bytes:=bytes or (1 shl 8);
  4122. bytes:=bytes or ((rd and $F) shl 12);
  4123. bytes:=bytes or (((rd and $10) shr 4) shl 22);
  4124. end
  4125. else
  4126. begin
  4127. bytes:=bytes or (((rd and $1E) shr 1) shl 12);
  4128. bytes:=bytes or ((rd and $1) shl 22);
  4129. end;
  4130. { set ref }
  4131. bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
  4132. if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
  4133. begin
  4134. { set offset }
  4135. offset:=0;
  4136. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  4137. if assigned(currsym) then
  4138. offset:=currsym.offset-insoffset-8;
  4139. offset:=offset+oper[1]^.ref^.offset;
  4140. offset:=offset div 4;
  4141. if offset>=0 then
  4142. begin
  4143. { set U flag }
  4144. bytes:=bytes or (1 shl 23);
  4145. bytes:=bytes or offset
  4146. end
  4147. else
  4148. begin
  4149. offset:=-offset;
  4150. bytes:=bytes or offset
  4151. end;
  4152. end
  4153. else
  4154. message(asmw_e_invalid_opcode_and_operands);
  4155. end;
  4156. #$46: { System instructions }
  4157. begin
  4158. { set instruction code }
  4159. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4160. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4161. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4162. { set regs }
  4163. if (oper[0]^.typ=top_modeflags) then
  4164. begin
  4165. if mfA in oper[0]^.modeflags then bytes:=bytes or (1 shl 8);
  4166. if mfI in oper[0]^.modeflags then bytes:=bytes or (1 shl 7);
  4167. if mfF in oper[0]^.modeflags then bytes:=bytes or (1 shl 6);
  4168. end;
  4169. if (ops=2) then
  4170. bytes:=bytes or (oper[1]^.val and $1F)
  4171. else if (ops=1) and
  4172. (oper[0]^.typ=top_const) then
  4173. bytes:=bytes or (oper[0]^.val and $1F);
  4174. end;
  4175. #$60: { Thumb }
  4176. begin
  4177. bytelen:=2;
  4178. bytes:=0;
  4179. { set opcode }
  4180. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4181. bytes:=bytes or ord(insentry^.code[2]);
  4182. { set regs }
  4183. if ops=2 then
  4184. begin
  4185. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4186. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 3);
  4187. if (oper[1]^.typ=top_reg) then
  4188. bytes:=bytes or ((getsupreg(oper[1]^.reg) and $7) shl 6)
  4189. else
  4190. bytes:=bytes or ((oper[1]^.val and $1F) shl 6);
  4191. end
  4192. else if ops=3 then
  4193. begin
  4194. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4195. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
  4196. if (oper[2]^.typ=top_reg) then
  4197. bytes:=bytes or ((getsupreg(oper[2]^.reg) and $7) shl 6)
  4198. else
  4199. bytes:=bytes or ((oper[2]^.val and $1F) shl 6);
  4200. end
  4201. else if ops=1 then
  4202. begin
  4203. if oper[0]^.typ=top_const then
  4204. bytes:=bytes or (oper[0]^.val and $FF);
  4205. end;
  4206. end;
  4207. #$61: { Thumb }
  4208. begin
  4209. bytelen:=2;
  4210. bytes:=0;
  4211. { set opcode }
  4212. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4213. bytes:=bytes or ord(insentry^.code[2]);
  4214. { set regs }
  4215. if ops=2 then
  4216. begin
  4217. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4218. bytes:=bytes or ((getsupreg(oper[0]^.reg) and $8) shr 3) shl 7;
  4219. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
  4220. end
  4221. else if ops=1 then
  4222. begin
  4223. if oper[0]^.typ=top_const then
  4224. bytes:=bytes or (oper[0]^.val and $FF);
  4225. end;
  4226. end;
  4227. #$62..#$63: { Thumb branches }
  4228. begin
  4229. bytelen:=2;
  4230. bytes:=0;
  4231. { set opcode }
  4232. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4233. bytes:=bytes or ord(insentry^.code[2]);
  4234. if insentry^.code[0]=#$63 then
  4235. bytes:=bytes or (CondVal[condition] shl 8);
  4236. if oper[0]^.typ=top_const then
  4237. begin
  4238. if insentry^.code[0]=#$63 then
  4239. bytes:=bytes or (((oper[0]^.val shr 1)-1) and $FF)
  4240. else
  4241. bytes:=bytes or (((oper[0]^.val shr 1)-1) and $3FF);
  4242. end
  4243. else if oper[0]^.typ=top_reg then
  4244. begin
  4245. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 3);
  4246. end
  4247. else if oper[0]^.typ=top_ref then
  4248. begin
  4249. offset:=0;
  4250. currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
  4251. if assigned(currsym) then
  4252. offset:=currsym.offset-insoffset-8;
  4253. offset:=offset+oper[0]^.ref^.offset;
  4254. if insentry^.code[0]=#$63 then
  4255. bytes:=bytes or (((offset+4) shr 1) and $FF)
  4256. else
  4257. bytes:=bytes or (((offset+4) shr 1) and $7FF);
  4258. end
  4259. end;
  4260. #$64: { Thumb: Special encodings }
  4261. begin
  4262. bytelen:=2;
  4263. bytes:=0;
  4264. { set opcode }
  4265. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4266. bytes:=bytes or ord(insentry^.code[2]);
  4267. case opcode of
  4268. A_SUB:
  4269. begin
  4270. if (ops=3) and
  4271. (oper[2]^.typ=top_const) then
  4272. bytes:=bytes or ((oper[2]^.val shr 2) and $7F)
  4273. else if (ops=2) and
  4274. (oper[1]^.typ=top_const) then
  4275. bytes:=bytes or ((oper[1]^.val shr 2) and $7F);
  4276. end;
  4277. A_MUL:
  4278. if (ops in [2,3]) then
  4279. begin
  4280. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4281. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
  4282. end;
  4283. A_ADD:
  4284. begin
  4285. if ops=2 then
  4286. begin
  4287. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4288. bytes:=bytes or (getsupreg(oper[1]^.reg) shl $3);
  4289. end
  4290. else if (oper[0]^.reg<>NR_STACK_POINTER_REG) and
  4291. (oper[2]^.typ=top_const) then
  4292. begin
  4293. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7) shl 8;
  4294. bytes:=bytes or ((oper[2]^.val shr 2) and $7F);
  4295. end
  4296. else if (oper[0]^.reg<>NR_STACK_POINTER_REG) and
  4297. (oper[2]^.typ=top_reg) then
  4298. begin
  4299. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4300. bytes:=bytes or ((getsupreg(oper[0]^.reg) and $8) shr 3) shl 7;
  4301. end
  4302. else
  4303. begin
  4304. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4305. bytes:=bytes or ((oper[2]^.val shr 2) and $7F);
  4306. end;
  4307. end;
  4308. else
  4309. internalerror(2019050926);
  4310. end;
  4311. end;
  4312. #$65: { Thumb load/store }
  4313. begin
  4314. bytelen:=2;
  4315. bytes:=0;
  4316. { set opcode }
  4317. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4318. bytes:=bytes or ord(insentry^.code[2]);
  4319. { set regs }
  4320. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4321. bytes:=bytes or (getsupreg(oper[1]^.ref^.base) shl 3);
  4322. bytes:=bytes or (getsupreg(oper[1]^.ref^.index) shl 6);
  4323. end;
  4324. #$66: { Thumb load/store }
  4325. begin
  4326. bytelen:=2;
  4327. bytes:=0;
  4328. { set opcode }
  4329. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4330. bytes:=bytes or ord(insentry^.code[2]);
  4331. { set regs }
  4332. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4333. bytes:=bytes or (getsupreg(oper[1]^.ref^.base) shl 3);
  4334. { set offset }
  4335. offset:=0;
  4336. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  4337. if assigned(currsym) then
  4338. offset:=currsym.offset-(insoffset+4) and (not longword(3));
  4339. offset:=(offset+oper[1]^.ref^.offset);
  4340. bytes:=bytes or (((offset shr ord(insentry^.code[3])) and $1F) shl 6);
  4341. end;
  4342. #$67: { Thumb load/store }
  4343. begin
  4344. bytelen:=2;
  4345. bytes:=0;
  4346. { set opcode }
  4347. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4348. bytes:=bytes or ord(insentry^.code[2]);
  4349. { set regs }
  4350. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4351. if oper[1]^.typ=top_ref then
  4352. begin
  4353. { set offset }
  4354. offset:=0;
  4355. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  4356. if assigned(currsym) then
  4357. offset:=currsym.offset-(insoffset+4) and (not longword(3));
  4358. offset:=(offset+oper[1]^.ref^.offset);
  4359. bytes:=bytes or ((offset shr ord(insentry^.code[3])) and $FF);
  4360. end
  4361. else
  4362. bytes:=bytes or ((oper[1]^.val shr ord(insentry^.code[3])) and $FF);
  4363. end;
  4364. #$68: { Thumb CB[N]Z }
  4365. begin
  4366. bytelen:=2;
  4367. bytes:=0;
  4368. { set opcode }
  4369. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4370. { set opers }
  4371. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4372. if oper[1]^.typ=top_ref then
  4373. begin
  4374. offset:=0;
  4375. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  4376. if assigned(currsym) then
  4377. offset:=currsym.offset-insoffset-8;
  4378. offset:=offset+oper[1]^.ref^.offset;
  4379. offset:=offset div 2;
  4380. end
  4381. else
  4382. offset:=oper[1]^.val div 2;
  4383. bytes:=bytes or ((offset) and $1F) shl 3;
  4384. bytes:=bytes or ((offset shr 5) and 1) shl 9;
  4385. end;
  4386. #$69: { Thumb: Push/Pop/Stm/Ldm }
  4387. begin
  4388. bytelen:=2;
  4389. bytes:=0;
  4390. { set opcode }
  4391. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4392. case opcode of
  4393. A_PUSH:
  4394. begin
  4395. for r:=0 to 7 do
  4396. if r in oper[0]^.regset^ then
  4397. bytes:=bytes or (1 shl r);
  4398. if RS_R14 in oper[0]^.regset^ then
  4399. bytes:=bytes or (1 shl 8);
  4400. end;
  4401. A_POP:
  4402. begin
  4403. for r:=0 to 7 do
  4404. if r in oper[0]^.regset^ then
  4405. bytes:=bytes or (1 shl r);
  4406. if RS_R15 in oper[0]^.regset^ then
  4407. bytes:=bytes or (1 shl 8);
  4408. end;
  4409. A_STM:
  4410. begin
  4411. for r:=0 to 7 do
  4412. if r in oper[1]^.regset^ then
  4413. bytes:=bytes or (1 shl r);
  4414. if oper[0]^.typ=top_ref then
  4415. bytes:=bytes or (getsupreg(oper[0]^.ref^.index) shl 8)
  4416. else
  4417. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4418. end;
  4419. A_LDM:
  4420. begin
  4421. for r:=0 to 7 do
  4422. if r in oper[1]^.regset^ then
  4423. bytes:=bytes or (1 shl r);
  4424. if oper[0]^.typ=top_ref then
  4425. bytes:=bytes or (getsupreg(oper[0]^.ref^.index) shl 8)
  4426. else
  4427. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4428. end;
  4429. else
  4430. internalerror(2019050925);
  4431. end;
  4432. end;
  4433. #$6A: { Thumb: IT }
  4434. begin
  4435. bytelen:=2;
  4436. bytes:=0;
  4437. { set opcode }
  4438. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4439. bytes:=bytes or (ord(insentry^.code[2]) shl 0);
  4440. bytes:=bytes or (CondVal[oper[0]^.cc] shl 4);
  4441. i_field:=(bytes shr 4) and 1;
  4442. i_field:=(i_field shl 1) or i_field;
  4443. i_field:=(i_field shl 2) or i_field;
  4444. bytes:=bytes or ((i_field and ord(insentry^.code[3])) xor (ord(insentry^.code[3]) shr 4));
  4445. end;
  4446. #$6B: { Thumb: Data processing (misc) }
  4447. begin
  4448. bytelen:=2;
  4449. bytes:=0;
  4450. { set opcode }
  4451. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4452. bytes:=bytes or ord(insentry^.code[2]);
  4453. { set regs }
  4454. if ops>=2 then
  4455. begin
  4456. if oper[1]^.typ=top_const then
  4457. begin
  4458. bytes:=bytes or ((getsupreg(oper[0]^.reg) and $7) shl 8);
  4459. bytes:=bytes or (oper[1]^.val and $FF);
  4460. end
  4461. else if oper[1]^.typ=top_reg then
  4462. begin
  4463. bytes:=bytes or (getsupreg(oper[0]^.reg) and $7);
  4464. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 3);
  4465. end;
  4466. end
  4467. else if ops=1 then
  4468. begin
  4469. if oper[0]^.typ=top_const then
  4470. bytes:=bytes or (oper[0]^.val and $FF);
  4471. end;
  4472. end;
  4473. #$6C: { Thumb: CPS }
  4474. begin
  4475. bytelen:=2;
  4476. bytes:=0;
  4477. { set opcode }
  4478. bytes:=bytes or (ord(insentry^.code[1]) shl 8);
  4479. bytes:=bytes or ord(insentry^.code[2]);
  4480. if mfA in oper[0]^.modeflags then bytes:=bytes or (1 shl 2);
  4481. if mfI in oper[0]^.modeflags then bytes:=bytes or (1 shl 1);
  4482. if mfF in oper[0]^.modeflags then bytes:=bytes or (1 shl 0);
  4483. end;
  4484. #$80: { Thumb-2: Dataprocessing }
  4485. begin
  4486. bytes:=0;
  4487. { set instruction code }
  4488. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4489. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4490. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4491. bytes:=bytes or ord(insentry^.code[4]);
  4492. if ops=1 then
  4493. begin
  4494. if oper[0]^.typ=top_reg then
  4495. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16)
  4496. else if oper[0]^.typ=top_const then
  4497. bytes:=bytes or (oper[0]^.val and $F);
  4498. end
  4499. else if (ops=2) and
  4500. (opcode in [A_CMP,A_CMN,A_TEQ,A_TST]) then
  4501. begin
  4502. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
  4503. if oper[1]^.typ=top_const then
  4504. encodethumbimm(oper[1]^.val)
  4505. else if oper[1]^.typ=top_reg then
  4506. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4507. end
  4508. else if (ops=3) and
  4509. (opcode in [A_CMP,A_CMN,A_TEQ,A_TST]) then
  4510. begin
  4511. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
  4512. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4513. if oper[2]^.typ=top_shifterop then
  4514. setthumbshift(2)
  4515. else if oper[2]^.typ=top_reg then
  4516. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 12);
  4517. end
  4518. else if (ops=2) and
  4519. (opcode in [A_REV,A_RBIT,A_REV16,A_REVSH,A_CLZ]) then
  4520. begin
  4521. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4522. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4523. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4524. end
  4525. else if ops=2 then
  4526. begin
  4527. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4528. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
  4529. if oper[1]^.typ=top_const then
  4530. encodethumbimm(oper[1]^.val)
  4531. else if oper[1]^.typ=top_reg then
  4532. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4533. end
  4534. else if ops=3 then
  4535. begin
  4536. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4537. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4538. if oper[2]^.typ=top_const then
  4539. encodethumbimm(oper[2]^.val)
  4540. else if oper[2]^.typ=top_reg then
  4541. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
  4542. end
  4543. else if ops=4 then
  4544. begin
  4545. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4546. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4547. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
  4548. if oper[3]^.typ=top_shifterop then
  4549. setthumbshift(3)
  4550. else if oper[3]^.typ=top_reg then
  4551. bytes:=bytes or (getsupreg(oper[3]^.reg) shl 12);
  4552. end;
  4553. if oppostfix=PF_S then
  4554. bytes:=bytes or (1 shl 20)
  4555. else if oppostfix=PF_X then
  4556. bytes:=bytes or (1 shl 4)
  4557. else if oppostfix=PF_R then
  4558. bytes:=bytes or (1 shl 4);
  4559. end;
  4560. #$81: { Thumb-2: Dataprocessing misc }
  4561. begin
  4562. bytes:=0;
  4563. { set instruction code }
  4564. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4565. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4566. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4567. bytes:=bytes or ord(insentry^.code[4]);
  4568. if ops=3 then
  4569. begin
  4570. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4571. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4572. if oper[2]^.typ=top_const then
  4573. begin
  4574. bytes:=bytes or (oper[2]^.val and $FF);
  4575. bytes:=bytes or ((oper[2]^.val and $700) shr 8) shl 12;
  4576. bytes:=bytes or ((oper[2]^.val and $800) shr 11) shl 26;
  4577. end;
  4578. end
  4579. else if ops=2 then
  4580. begin
  4581. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4582. offset:=0;
  4583. if oper[1]^.typ=top_const then
  4584. begin
  4585. offset:=oper[1]^.val;
  4586. end
  4587. else if oper[1]^.typ=top_ref then
  4588. begin
  4589. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  4590. if assigned(currsym) then
  4591. offset:=currsym.offset-insoffset-8;
  4592. offset:=offset+oper[1]^.ref^.offset;
  4593. offset:=offset;
  4594. end;
  4595. bytes:=bytes or (offset and $FF);
  4596. bytes:=bytes or ((offset and $700) shr 8) shl 12;
  4597. bytes:=bytes or ((offset and $800) shr 11) shl 26;
  4598. bytes:=bytes or ((offset and $F000) shr 12) shl 16;
  4599. end;
  4600. if oppostfix=PF_S then
  4601. bytes:=bytes or (1 shl 20);
  4602. end;
  4603. #$82: { Thumb-2: Shifts }
  4604. begin
  4605. bytes:=0;
  4606. { set instruction code }
  4607. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4608. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4609. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4610. bytes:=bytes or ord(insentry^.code[4]);
  4611. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4612. if oper[1]^.typ=top_reg then
  4613. begin
  4614. offset:=2;
  4615. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4616. end
  4617. else
  4618. begin
  4619. offset:=1;
  4620. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 0);
  4621. end;
  4622. if oper[offset]^.typ=top_const then
  4623. begin
  4624. bytes:=bytes or (oper[offset]^.val and $3) shl 6;
  4625. bytes:=bytes or (oper[offset]^.val and $1C) shl 10;
  4626. end
  4627. else if oper[offset]^.typ=top_reg then
  4628. bytes:=bytes or (getsupreg(oper[offset]^.reg) shl 16);
  4629. if (ops>=(offset+2)) and
  4630. (oper[offset+1]^.typ=top_const) then
  4631. bytes:=bytes or (oper[offset+1]^.val and $1F);
  4632. if oppostfix=PF_S then
  4633. bytes:=bytes or (1 shl 20);
  4634. end;
  4635. #$84: { Thumb-2: Shifts(width-1) }
  4636. begin
  4637. bytes:=0;
  4638. { set instruction code }
  4639. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4640. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4641. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4642. bytes:=bytes or ord(insentry^.code[4]);
  4643. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4644. if oper[1]^.typ=top_reg then
  4645. begin
  4646. offset:=2;
  4647. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4648. end
  4649. else
  4650. offset:=1;
  4651. if oper[offset]^.typ=top_const then
  4652. begin
  4653. bytes:=bytes or (oper[offset]^.val and $3) shl 6;
  4654. bytes:=bytes or (oper[offset]^.val and $1C) shl 10;
  4655. end;
  4656. if (ops>=(offset+2)) and
  4657. (oper[offset+1]^.typ=top_const) then
  4658. begin
  4659. if opcode in [A_BFI,A_BFC] then
  4660. i_field:=oper[offset+1]^.val+oper[offset]^.val-1
  4661. else
  4662. i_field:=oper[offset+1]^.val-1;
  4663. bytes:=bytes or (i_field and $1F);
  4664. end;
  4665. if oppostfix=PF_S then
  4666. bytes:=bytes or (1 shl 20);
  4667. end;
  4668. #$83: { Thumb-2: Saturation }
  4669. begin
  4670. bytes:=0;
  4671. { set instruction code }
  4672. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4673. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4674. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4675. bytes:=bytes or ord(insentry^.code[4]);
  4676. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4677. bytes:=bytes or (oper[1]^.val and $1F);
  4678. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 16);
  4679. if ops=4 then
  4680. setthumbshift(3,true);
  4681. end;
  4682. #$85: { Thumb-2: Long multiplications }
  4683. begin
  4684. bytes:=0;
  4685. { set instruction code }
  4686. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4687. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4688. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4689. bytes:=bytes or ord(insentry^.code[4]);
  4690. if ops=4 then
  4691. begin
  4692. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  4693. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 8);
  4694. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 16);
  4695. bytes:=bytes or (getsupreg(oper[3]^.reg) shl 0);
  4696. end;
  4697. if oppostfix=PF_S then
  4698. bytes:=bytes or (1 shl 20)
  4699. else if oppostfix=PF_X then
  4700. bytes:=bytes or (1 shl 4);
  4701. end;
  4702. #$86: { Thumb-2: Extension ops }
  4703. begin
  4704. bytes:=0;
  4705. { set instruction code }
  4706. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4707. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4708. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4709. bytes:=bytes or ord(insentry^.code[4]);
  4710. if ops=2 then
  4711. begin
  4712. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4713. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4714. end
  4715. else if ops=3 then
  4716. begin
  4717. if oper[2]^.typ=top_shifterop then
  4718. begin
  4719. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4720. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  4721. bytes:=bytes or ((oper[2]^.shifterop^.shiftimm shr 3) shl 4);
  4722. end
  4723. else
  4724. begin
  4725. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4726. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4727. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
  4728. end;
  4729. end
  4730. else if ops=4 then
  4731. begin
  4732. if oper[3]^.typ=top_shifterop then
  4733. begin
  4734. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  4735. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  4736. bytes:=bytes or (getsupreg(oper[2]^.reg) shl 0);
  4737. bytes:=bytes or ((oper[3]^.shifterop^.shiftimm shr 3) shl 4);
  4738. end;
  4739. end;
  4740. end;
  4741. #$87: { Thumb-2: PLD/PLI }
  4742. begin
  4743. { set instruction code }
  4744. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4745. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4746. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4747. bytes:=bytes or ord(insentry^.code[4]);
  4748. { set Rn and Rd }
  4749. bytes:=bytes or getsupreg(oper[0]^.ref^.base) shl 16;
  4750. if getregtype(oper[0]^.ref^.index)=R_INVALIDREGISTER then
  4751. begin
  4752. { set offset }
  4753. offset:=0;
  4754. currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
  4755. if assigned(currsym) then
  4756. offset:=currsym.offset-insoffset-8;
  4757. offset:=offset+oper[0]^.ref^.offset;
  4758. if offset>=0 then
  4759. begin
  4760. { set U flag }
  4761. bytes:=bytes or (1 shl 23);
  4762. bytes:=bytes or (offset and $FFF);
  4763. end
  4764. else
  4765. begin
  4766. bytes:=bytes or ($3 shl 10);
  4767. offset:=-offset;
  4768. bytes:=bytes or (offset and $FF);
  4769. end;
  4770. end
  4771. else
  4772. begin
  4773. bytes:=bytes or getsupreg(oper[0]^.ref^.index);
  4774. { set shift }
  4775. with oper[0]^.ref^ do
  4776. if shiftmode=SM_LSL then
  4777. bytes:=bytes or ((shiftimm and $1F) shl 4);
  4778. end;
  4779. end;
  4780. #$88: { Thumb-2: LDR/STR }
  4781. begin
  4782. { set instruction code }
  4783. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4784. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4785. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4786. bytes:=bytes or (ord(insentry^.code[4]) shl 0);
  4787. { set Rn and Rd }
  4788. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  4789. bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
  4790. if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
  4791. begin
  4792. { set offset }
  4793. offset:=0;
  4794. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  4795. if assigned(currsym) then
  4796. offset:=currsym.offset-insoffset-8;
  4797. offset:=(offset+oper[1]^.ref^.offset) shr ord(insentry^.code[5]);
  4798. if offset>=0 then
  4799. begin
  4800. if (offset>255) and
  4801. (not (opcode in [A_LDRT,A_LDRSBT,A_LDRSHT,A_LDRBT,A_LDRHT])) then
  4802. bytes:=bytes or (1 shl 23);
  4803. { set U flag }
  4804. if (oper[1]^.ref^.addressmode<>AM_OFFSET) then
  4805. begin
  4806. bytes:=bytes or (1 shl 9);
  4807. bytes:=bytes or (1 shl 11);
  4808. end;
  4809. bytes:=bytes or offset
  4810. end
  4811. else
  4812. begin
  4813. bytes:=bytes or (1 shl 11);
  4814. offset:=-offset;
  4815. bytes:=bytes or offset
  4816. end;
  4817. end
  4818. else
  4819. begin
  4820. { set I flag }
  4821. bytes:=bytes or (1 shl 25);
  4822. bytes:=bytes or getsupreg(oper[1]^.ref^.index);
  4823. { set shift }
  4824. with oper[1]^.ref^ do
  4825. if shiftmode<>SM_None then
  4826. bytes:=bytes or ((shiftimm and $1F) shl 4);
  4827. end;
  4828. if not (opcode in [A_LDRT,A_LDRSBT,A_LDRSHT,A_LDRBT,A_LDRHT]) then
  4829. begin
  4830. { set W bit }
  4831. if oper[1]^.ref^.addressmode<>AM_OFFSET then
  4832. bytes:=bytes or (1 shl 8);
  4833. { set P bit if necessary }
  4834. if oper[1]^.ref^.addressmode<>AM_POSTINDEXED then
  4835. bytes:=bytes or (1 shl 10);
  4836. end;
  4837. end;
  4838. #$89: { Thumb-2: LDRD/STRD }
  4839. begin
  4840. { set instruction code }
  4841. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4842. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4843. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4844. bytes:=bytes or (ord(insentry^.code[4]) shl 0);
  4845. { set Rn and Rd }
  4846. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  4847. bytes:=bytes or getsupreg(oper[1]^.reg) shl 8;
  4848. bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
  4849. if getregtype(oper[2]^.ref^.index)=R_INVALIDREGISTER then
  4850. begin
  4851. { set offset }
  4852. offset:=0;
  4853. currsym:=objdata.symbolref(oper[2]^.ref^.symbol);
  4854. if assigned(currsym) then
  4855. offset:=currsym.offset-insoffset-8;
  4856. offset:=(offset+oper[2]^.ref^.offset) div 4;
  4857. if offset>=0 then
  4858. begin
  4859. { set U flag }
  4860. bytes:=bytes or (1 shl 23);
  4861. bytes:=bytes or offset
  4862. end
  4863. else
  4864. begin
  4865. offset:=-offset;
  4866. bytes:=bytes or offset
  4867. end;
  4868. end
  4869. else
  4870. begin
  4871. message(asmw_e_invalid_opcode_and_operands);
  4872. end;
  4873. { set W bit }
  4874. if oper[2]^.ref^.addressmode<>AM_OFFSET then
  4875. bytes:=bytes or (1 shl 21);
  4876. { set P bit if necessary }
  4877. if oper[2]^.ref^.addressmode<>AM_POSTINDEXED then
  4878. bytes:=bytes or (1 shl 24);
  4879. end;
  4880. #$8A: { Thumb-2: LDREX }
  4881. begin
  4882. { set instruction code }
  4883. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4884. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4885. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4886. bytes:=bytes or (ord(insentry^.code[4]) shl 0);
  4887. { set Rn and Rd }
  4888. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  4889. if (ops=2) and (opcode in [A_LDREX]) then
  4890. begin
  4891. bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
  4892. if getregtype(oper[1]^.ref^.index)=R_INVALIDREGISTER then
  4893. begin
  4894. { set offset }
  4895. offset:=0;
  4896. currsym:=objdata.symbolref(oper[1]^.ref^.symbol);
  4897. if assigned(currsym) then
  4898. offset:=currsym.offset-insoffset-8;
  4899. offset:=(offset+oper[1]^.ref^.offset) div 4;
  4900. if offset>=0 then
  4901. begin
  4902. bytes:=bytes or offset
  4903. end
  4904. else
  4905. begin
  4906. message(asmw_e_invalid_opcode_and_operands);
  4907. end;
  4908. end
  4909. else
  4910. begin
  4911. message(asmw_e_invalid_opcode_and_operands);
  4912. end;
  4913. end
  4914. else if (ops=2) then
  4915. begin
  4916. bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
  4917. end
  4918. else
  4919. begin
  4920. bytes:=bytes or getsupreg(oper[1]^.reg) shl 8;
  4921. bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
  4922. end;
  4923. end;
  4924. #$8B: { Thumb-2: STREX }
  4925. begin
  4926. { set instruction code }
  4927. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4928. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4929. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4930. bytes:=bytes or (ord(insentry^.code[4]) shl 0);
  4931. { set Rn and Rd }
  4932. if (ops=3) and (opcode in [A_STREX]) then
  4933. begin
  4934. bytes:=bytes or getsupreg(oper[0]^.reg) shl 8;
  4935. bytes:=bytes or getsupreg(oper[1]^.reg) shl 12;
  4936. bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
  4937. if getregtype(oper[2]^.ref^.index)=R_INVALIDREGISTER then
  4938. begin
  4939. { set offset }
  4940. offset:=0;
  4941. currsym:=objdata.symbolref(oper[2]^.ref^.symbol);
  4942. if assigned(currsym) then
  4943. offset:=currsym.offset-insoffset-8;
  4944. offset:=(offset+oper[2]^.ref^.offset) div 4;
  4945. if offset>=0 then
  4946. begin
  4947. bytes:=bytes or offset
  4948. end
  4949. else
  4950. begin
  4951. message(asmw_e_invalid_opcode_and_operands);
  4952. end;
  4953. end
  4954. else
  4955. begin
  4956. message(asmw_e_invalid_opcode_and_operands);
  4957. end;
  4958. end
  4959. else if (ops=3) then
  4960. begin
  4961. bytes:=bytes or getsupreg(oper[0]^.reg) shl 0;
  4962. bytes:=bytes or getsupreg(oper[1]^.reg) shl 12;
  4963. bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
  4964. end
  4965. else
  4966. begin
  4967. bytes:=bytes or getsupreg(oper[0]^.reg) shl 0;
  4968. bytes:=bytes or getsupreg(oper[1]^.reg) shl 12;
  4969. bytes:=bytes or getsupreg(oper[2]^.reg) shl 8;
  4970. bytes:=bytes or getsupreg(oper[3]^.ref^.base) shl 16;
  4971. end;
  4972. end;
  4973. #$8C: { Thumb-2: LDM/STM }
  4974. begin
  4975. { set instruction code }
  4976. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  4977. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  4978. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  4979. bytes:=bytes or (ord(insentry^.code[4]) shl 0);
  4980. if oper[0]^.typ=top_reg then
  4981. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16)
  4982. else
  4983. begin
  4984. bytes:=bytes or (getsupreg(oper[0]^.ref^.base) shl 16);
  4985. if oper[0]^.ref^.addressmode<>AM_OFFSET then
  4986. bytes:=bytes or (1 shl 21);
  4987. end;
  4988. for r:=0 to 15 do
  4989. if r in oper[1]^.regset^ then
  4990. bytes:=bytes or (1 shl r);
  4991. case oppostfix of
  4992. PF_None,PF_IA,PF_FD: bytes:=bytes or ($1 shl 23);
  4993. PF_DB,PF_EA: bytes:=bytes or ($2 shl 23);
  4994. else
  4995. message1(asmw_e_invalid_opcode_and_operands, '"Invalid Postfix"');
  4996. end;
  4997. end;
  4998. #$8D: { Thumb-2: BL/BLX }
  4999. begin
  5000. { set instruction code }
  5001. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  5002. bytes:=bytes or (ord(insentry^.code[2]) shl 8);
  5003. { set offset }
  5004. if oper[0]^.typ=top_const then
  5005. offset:=(oper[0]^.val shr 1) and $FFFFFF
  5006. else
  5007. begin
  5008. currsym:=objdata.symbolref(oper[0]^.ref^.symbol);
  5009. if (currsym.bind<>AB_LOCAL) and (currsym.objsection<>objdata.CurrObjSec) then
  5010. begin
  5011. objdata.writereloc(oper[0]^.ref^.offset,0,currsym,RELOC_RELATIVE_24_THUMB);
  5012. offset:=$FFFFFE
  5013. end
  5014. else
  5015. offset:=((currsym.offset-insoffset-8) shr 1) and $FFFFFF;
  5016. end;
  5017. bytes:=bytes or ((offset shr 00) and $7FF) shl 0;
  5018. bytes:=bytes or ((offset shr 11) and $3FF) shl 16;
  5019. bytes:=bytes or (((offset shr 21) xor (offset shr 23) xor 1) and $1) shl 11;
  5020. bytes:=bytes or (((offset shr 22) xor (offset shr 23) xor 1) and $1) shl 13;
  5021. bytes:=bytes or ((offset shr 23) and $1) shl 26;
  5022. end;
  5023. #$8E: { Thumb-2: TBB/TBH }
  5024. begin
  5025. { set instruction code }
  5026. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  5027. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  5028. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  5029. bytes:=bytes or ord(insentry^.code[4]);
  5030. { set Rn and Rm }
  5031. bytes:=bytes or getsupreg(oper[0]^.ref^.base) shl 16;
  5032. if getregtype(oper[0]^.ref^.index)=R_INVALIDREGISTER then
  5033. message(asmw_e_invalid_effective_address)
  5034. else
  5035. begin
  5036. bytes:=bytes or getsupreg(oper[0]^.ref^.index);
  5037. if (opcode=A_TBH) and
  5038. (oper[0]^.ref^.shiftmode<>SM_LSL) and
  5039. (oper[0]^.ref^.shiftimm<>1) then
  5040. message(asmw_e_invalid_effective_address);
  5041. end;
  5042. end;
  5043. #$8F: { Thumb-2: CPSxx }
  5044. begin
  5045. { set opcode }
  5046. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  5047. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  5048. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  5049. bytes:=bytes or ord(insentry^.code[4]);
  5050. if (oper[0]^.typ=top_modeflags) then
  5051. begin
  5052. if mfA in oper[0]^.modeflags then bytes:=bytes or (1 shl 7);
  5053. if mfI in oper[0]^.modeflags then bytes:=bytes or (1 shl 6);
  5054. if mfF in oper[0]^.modeflags then bytes:=bytes or (1 shl 5);
  5055. end;
  5056. if (ops=2) then
  5057. bytes:=bytes or (oper[1]^.val and $1F)
  5058. else if (ops=1) and
  5059. (oper[0]^.typ=top_const) then
  5060. bytes:=bytes or (oper[0]^.val and $1F);
  5061. end;
  5062. #$96: { Thumb-2: MSR/MRS }
  5063. begin
  5064. { set instruction code }
  5065. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  5066. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  5067. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  5068. bytes:=bytes or ord(insentry^.code[4]);
  5069. if opcode=A_MRS then
  5070. begin
  5071. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 8);
  5072. case oper[1]^.reg of
  5073. NR_MSP: bytes:=bytes or $08;
  5074. NR_PSP: bytes:=bytes or $09;
  5075. NR_IPSR: bytes:=bytes or $05;
  5076. NR_EPSR: bytes:=bytes or $06;
  5077. NR_APSR: bytes:=bytes or $00;
  5078. NR_PRIMASK: bytes:=bytes or $10;
  5079. NR_BASEPRI: bytes:=bytes or $11;
  5080. NR_BASEPRI_MAX: bytes:=bytes or $12;
  5081. NR_FAULTMASK: bytes:=bytes or $13;
  5082. NR_CONTROL: bytes:=bytes or $14;
  5083. else
  5084. Message(asmw_e_invalid_opcode_and_operands);
  5085. end;
  5086. end
  5087. else
  5088. begin
  5089. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 16);
  5090. case oper[0]^.reg of
  5091. NR_APSR,
  5092. NR_APSR_nzcvqg: bytes:=bytes or $C00;
  5093. NR_APSR_g: bytes:=bytes or $400;
  5094. NR_APSR_nzcvq: bytes:=bytes or $800;
  5095. NR_MSP: bytes:=bytes or $08;
  5096. NR_PSP: bytes:=bytes or $09;
  5097. NR_PRIMASK: bytes:=bytes or $10;
  5098. NR_BASEPRI: bytes:=bytes or $11;
  5099. NR_BASEPRI_MAX: bytes:=bytes or $12;
  5100. NR_FAULTMASK: bytes:=bytes or $13;
  5101. NR_CONTROL: bytes:=bytes or $14;
  5102. else
  5103. Message(asmw_e_invalid_opcode_and_operands);
  5104. end;
  5105. end;
  5106. end;
  5107. #$A0: { FPA: CPDT(LDF/STF) }
  5108. begin
  5109. { set instruction code }
  5110. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  5111. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  5112. bytes:=bytes or (ord(insentry^.code[3]) shl 8);
  5113. bytes:=bytes or ord(insentry^.code[4]);
  5114. if ops=2 then
  5115. begin
  5116. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  5117. bytes:=bytes or getsupreg(oper[1]^.ref^.base) shl 16;
  5118. bytes:=bytes or ((oper[1]^.ref^.offset shr 2) and $FF);
  5119. if oper[1]^.ref^.offset>=0 then
  5120. bytes:=bytes or (1 shl 23);
  5121. if oper[1]^.ref^.addressmode<>AM_OFFSET then
  5122. bytes:=bytes or (1 shl 21);
  5123. if oper[1]^.ref^.addressmode=AM_PREINDEXED then
  5124. bytes:=bytes or (1 shl 24);
  5125. case oppostfix of
  5126. PF_S: bytes:=bytes or (0 shl 22) or (0 shl 15);
  5127. PF_D: bytes:=bytes or (0 shl 22) or (1 shl 15);
  5128. PF_E: bytes:=bytes or (1 shl 22) or (0 shl 15);
  5129. PF_P: bytes:=bytes or (1 shl 22) or (1 shl 15);
  5130. PF_EP: ;
  5131. else
  5132. message1(asmw_e_invalid_opcode_and_operands, '"Invalid postfix"');
  5133. end;
  5134. end
  5135. else
  5136. begin
  5137. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  5138. case oper[1]^.val of
  5139. 1: bytes:=bytes or (1 shl 15);
  5140. 2: bytes:=bytes or (1 shl 22);
  5141. 3: bytes:=bytes or (1 shl 22) or (1 shl 15);
  5142. 4: ;
  5143. else
  5144. message1(asmw_e_invalid_opcode_and_operands, 'Invalid count for LFM/SFM');
  5145. end;
  5146. bytes:=bytes or getsupreg(oper[2]^.ref^.base) shl 16;
  5147. bytes:=bytes or ((oper[2]^.ref^.offset shr 2) and $FF);
  5148. if oper[2]^.ref^.offset>=0 then
  5149. bytes:=bytes or (1 shl 23);
  5150. if oper[2]^.ref^.addressmode<>AM_OFFSET then
  5151. bytes:=bytes or (1 shl 21);
  5152. if oper[2]^.ref^.addressmode=AM_PREINDEXED then
  5153. bytes:=bytes or (1 shl 24);
  5154. end;
  5155. end;
  5156. #$A1: { FPA: CPDO }
  5157. begin
  5158. { set instruction code }
  5159. bytes:=bytes or ($E shl 24);
  5160. bytes:=bytes or (ord(insentry^.code[1]) shl 15);
  5161. bytes:=bytes or ((ord(insentry^.code[2]) shr 1) shl 20);
  5162. bytes:=bytes or (1 shl 8);
  5163. bytes:=bytes or getsupreg(oper[0]^.reg) shl 12;
  5164. if ops=2 then
  5165. begin
  5166. if oper[1]^.typ=top_reg then
  5167. bytes:=bytes or getsupreg(oper[1]^.reg) shl 0
  5168. else
  5169. case oper[1]^.val of
  5170. 0: bytes:=bytes or $8;
  5171. 1: bytes:=bytes or $9;
  5172. 2: bytes:=bytes or $A;
  5173. 3: bytes:=bytes or $B;
  5174. 4: bytes:=bytes or $C;
  5175. 5: bytes:=bytes or $D;
  5176. //0.5: bytes:=bytes or $E;
  5177. 10: bytes:=bytes or $F;
  5178. else
  5179. Message(asmw_e_invalid_opcode_and_operands);
  5180. end;
  5181. end
  5182. else
  5183. begin
  5184. bytes:=bytes or getsupreg(oper[1]^.reg) shl 16;
  5185. if oper[2]^.typ=top_reg then
  5186. bytes:=bytes or getsupreg(oper[2]^.reg) shl 0
  5187. else
  5188. case oper[2]^.val of
  5189. 0: bytes:=bytes or $8;
  5190. 1: bytes:=bytes or $9;
  5191. 2: bytes:=bytes or $A;
  5192. 3: bytes:=bytes or $B;
  5193. 4: bytes:=bytes or $C;
  5194. 5: bytes:=bytes or $D;
  5195. //0.5: bytes:=bytes or $E;
  5196. 10: bytes:=bytes or $F;
  5197. else
  5198. Message(asmw_e_invalid_opcode_and_operands);
  5199. end;
  5200. end;
  5201. case roundingmode of
  5202. RM_NONE: ;
  5203. RM_P: bytes:=bytes or (1 shl 5);
  5204. RM_M: bytes:=bytes or (2 shl 5);
  5205. RM_Z: bytes:=bytes or (3 shl 5);
  5206. end;
  5207. case oppostfix of
  5208. PF_S: bytes:=bytes or (0 shl 19) or (0 shl 7);
  5209. PF_D: bytes:=bytes or (0 shl 19) or (1 shl 7);
  5210. PF_E: bytes:=bytes or (1 shl 19) or (0 shl 7);
  5211. else
  5212. message1(asmw_e_invalid_opcode_and_operands, 'Precision cannot be undefined');
  5213. end;
  5214. end;
  5215. #$A2: { FPA: CPDO }
  5216. begin
  5217. { set instruction code }
  5218. bytes:=bytes or (ord(insentry^.code[1]) shl 24);
  5219. bytes:=bytes or (ord(insentry^.code[2]) shl 16);
  5220. bytes:=bytes or ($11 shl 4);
  5221. case opcode of
  5222. A_FLT:
  5223. begin
  5224. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
  5225. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 12);
  5226. case roundingmode of
  5227. RM_NONE: ;
  5228. RM_P: bytes:=bytes or (1 shl 5);
  5229. RM_M: bytes:=bytes or (2 shl 5);
  5230. RM_Z: bytes:=bytes or (3 shl 5);
  5231. end;
  5232. case oppostfix of
  5233. PF_S: bytes:=bytes or (0 shl 19) or (0 shl 7);
  5234. PF_D: bytes:=bytes or (0 shl 19) or (1 shl 7);
  5235. PF_E: bytes:=bytes or (1 shl 19) or (0 shl 7);
  5236. else
  5237. message1(asmw_e_invalid_opcode_and_operands, 'Precision cannot be undefined');
  5238. end;
  5239. end;
  5240. A_FIX:
  5241. begin
  5242. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  5243. bytes:=bytes or (getsupreg(oper[1]^.reg) shl 0);
  5244. case roundingmode of
  5245. RM_NONE: ;
  5246. RM_P: bytes:=bytes or (1 shl 5);
  5247. RM_M: bytes:=bytes or (2 shl 5);
  5248. RM_Z: bytes:=bytes or (3 shl 5);
  5249. end;
  5250. end;
  5251. A_WFS,A_RFS,A_WFC,A_RFC:
  5252. begin
  5253. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 12);
  5254. end;
  5255. A_CMF,A_CNF,A_CMFE,A_CNFE:
  5256. begin
  5257. bytes:=bytes or (getsupreg(oper[0]^.reg) shl 16);
  5258. if oper[1]^.typ=top_reg then
  5259. bytes:=bytes or getsupreg(oper[1]^.reg) shl 0
  5260. else
  5261. case oper[1]^.val of
  5262. 0: bytes:=bytes or $8;
  5263. 1: bytes:=bytes or $9;
  5264. 2: bytes:=bytes or $A;
  5265. 3: bytes:=bytes or $B;
  5266. 4: bytes:=bytes or $C;
  5267. 5: bytes:=bytes or $D;
  5268. //0.5: bytes:=bytes or $E;
  5269. 10: bytes:=bytes or $F;
  5270. else
  5271. Message(asmw_e_invalid_opcode_and_operands);
  5272. end;
  5273. end;
  5274. else
  5275. Message1(asmw_e_invalid_opcode_and_operands, '"Unsupported opcode"');
  5276. end;
  5277. end;
  5278. #$fe: // No written data
  5279. begin
  5280. exit;
  5281. end;
  5282. #$ff:
  5283. internalerror(2005091101);
  5284. else
  5285. begin
  5286. writeln(ord(insentry^.code[0]), ' - ', opcode);
  5287. internalerror(2005091102);
  5288. end;
  5289. end;
  5290. { Todo: Decide whether the code above should take care of writing data in an order that makes senes }
  5291. if (insentry^.code[0] in [#$80..#$96]) and (bytelen=4) then
  5292. bytes:=((bytes shr 16) and $FFFF) or ((bytes and $FFFF) shl 16);
  5293. { we're finished, write code }
  5294. objdata.writebytes(bytes,bytelen);
  5295. end;
  5296. begin
  5297. cai_align:=tai_align;
  5298. end.