123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140 |
- // cmd/7l/asm.c, cmd/7l/asmout.c, cmd/7l/optab.c, cmd/7l/span.c, cmd/ld/sub.c, cmd/ld/mod.c, from Vita Nuova.
- // https://code.google.com/p/ken-cc/source/browse/
- //
- // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
- // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
- // Portions Copyright © 1997-1999 Vita Nuova Limited
- // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
- // Portions Copyright © 2004,2006 Bruce Ellis
- // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
- // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
- // Portions Copyright © 2009 The Go Authors. All rights reserved.
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to deal
- // in the Software without restriction, including without limitation the rights
- // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- // copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- // THE SOFTWARE.
- package arm64
- import (
- "github.com/twitchyliquid64/golang-asm/obj"
- "github.com/twitchyliquid64/golang-asm/objabi"
- "fmt"
- "log"
- "math"
- "sort"
- )
- // ctxt7 holds state while assembling a single function.
- // Each function gets a fresh ctxt7.
- // This allows for multiple functions to be safely concurrently assembled.
- type ctxt7 struct {
- ctxt *obj.Link
- newprog obj.ProgAlloc
- cursym *obj.LSym
- blitrl *obj.Prog
- elitrl *obj.Prog
- autosize int32
- extrasize int32
- instoffset int64
- pc int64
- pool struct {
- start uint32
- size uint32
- }
- }
- const (
- funcAlign = 16
- )
- const (
- REGFROM = 1
- )
- type Optab struct {
- as obj.As
- a1 uint8
- a2 uint8
- a3 uint8
- a4 uint8
- type_ int8
- size int8
- param int16
- flag int8
- scond uint16
- }
- func IsAtomicInstruction(as obj.As) bool {
- _, ok := atomicInstructions[as]
- return ok
- }
- // known field values of an instruction.
- var atomicInstructions = map[obj.As]uint32{
- ALDADDAD: 3<<30 | 0x1c5<<21 | 0x00<<10,
- ALDADDAW: 2<<30 | 0x1c5<<21 | 0x00<<10,
- ALDADDAH: 1<<30 | 0x1c5<<21 | 0x00<<10,
- ALDADDAB: 0<<30 | 0x1c5<<21 | 0x00<<10,
- ALDADDALD: 3<<30 | 0x1c7<<21 | 0x00<<10,
- ALDADDALW: 2<<30 | 0x1c7<<21 | 0x00<<10,
- ALDADDALH: 1<<30 | 0x1c7<<21 | 0x00<<10,
- ALDADDALB: 0<<30 | 0x1c7<<21 | 0x00<<10,
- ALDADDD: 3<<30 | 0x1c1<<21 | 0x00<<10,
- ALDADDW: 2<<30 | 0x1c1<<21 | 0x00<<10,
- ALDADDH: 1<<30 | 0x1c1<<21 | 0x00<<10,
- ALDADDB: 0<<30 | 0x1c1<<21 | 0x00<<10,
- ALDADDLD: 3<<30 | 0x1c3<<21 | 0x00<<10,
- ALDADDLW: 2<<30 | 0x1c3<<21 | 0x00<<10,
- ALDADDLH: 1<<30 | 0x1c3<<21 | 0x00<<10,
- ALDADDLB: 0<<30 | 0x1c3<<21 | 0x00<<10,
- ALDANDAD: 3<<30 | 0x1c5<<21 | 0x04<<10,
- ALDANDAW: 2<<30 | 0x1c5<<21 | 0x04<<10,
- ALDANDAH: 1<<30 | 0x1c5<<21 | 0x04<<10,
- ALDANDAB: 0<<30 | 0x1c5<<21 | 0x04<<10,
- ALDANDALD: 3<<30 | 0x1c7<<21 | 0x04<<10,
- ALDANDALW: 2<<30 | 0x1c7<<21 | 0x04<<10,
- ALDANDALH: 1<<30 | 0x1c7<<21 | 0x04<<10,
- ALDANDALB: 0<<30 | 0x1c7<<21 | 0x04<<10,
- ALDANDD: 3<<30 | 0x1c1<<21 | 0x04<<10,
- ALDANDW: 2<<30 | 0x1c1<<21 | 0x04<<10,
- ALDANDH: 1<<30 | 0x1c1<<21 | 0x04<<10,
- ALDANDB: 0<<30 | 0x1c1<<21 | 0x04<<10,
- ALDANDLD: 3<<30 | 0x1c3<<21 | 0x04<<10,
- ALDANDLW: 2<<30 | 0x1c3<<21 | 0x04<<10,
- ALDANDLH: 1<<30 | 0x1c3<<21 | 0x04<<10,
- ALDANDLB: 0<<30 | 0x1c3<<21 | 0x04<<10,
- ALDEORAD: 3<<30 | 0x1c5<<21 | 0x08<<10,
- ALDEORAW: 2<<30 | 0x1c5<<21 | 0x08<<10,
- ALDEORAH: 1<<30 | 0x1c5<<21 | 0x08<<10,
- ALDEORAB: 0<<30 | 0x1c5<<21 | 0x08<<10,
- ALDEORALD: 3<<30 | 0x1c7<<21 | 0x08<<10,
- ALDEORALW: 2<<30 | 0x1c7<<21 | 0x08<<10,
- ALDEORALH: 1<<30 | 0x1c7<<21 | 0x08<<10,
- ALDEORALB: 0<<30 | 0x1c7<<21 | 0x08<<10,
- ALDEORD: 3<<30 | 0x1c1<<21 | 0x08<<10,
- ALDEORW: 2<<30 | 0x1c1<<21 | 0x08<<10,
- ALDEORH: 1<<30 | 0x1c1<<21 | 0x08<<10,
- ALDEORB: 0<<30 | 0x1c1<<21 | 0x08<<10,
- ALDEORLD: 3<<30 | 0x1c3<<21 | 0x08<<10,
- ALDEORLW: 2<<30 | 0x1c3<<21 | 0x08<<10,
- ALDEORLH: 1<<30 | 0x1c3<<21 | 0x08<<10,
- ALDEORLB: 0<<30 | 0x1c3<<21 | 0x08<<10,
- ALDORAD: 3<<30 | 0x1c5<<21 | 0x0c<<10,
- ALDORAW: 2<<30 | 0x1c5<<21 | 0x0c<<10,
- ALDORAH: 1<<30 | 0x1c5<<21 | 0x0c<<10,
- ALDORAB: 0<<30 | 0x1c5<<21 | 0x0c<<10,
- ALDORALD: 3<<30 | 0x1c7<<21 | 0x0c<<10,
- ALDORALW: 2<<30 | 0x1c7<<21 | 0x0c<<10,
- ALDORALH: 1<<30 | 0x1c7<<21 | 0x0c<<10,
- ALDORALB: 0<<30 | 0x1c7<<21 | 0x0c<<10,
- ALDORD: 3<<30 | 0x1c1<<21 | 0x0c<<10,
- ALDORW: 2<<30 | 0x1c1<<21 | 0x0c<<10,
- ALDORH: 1<<30 | 0x1c1<<21 | 0x0c<<10,
- ALDORB: 0<<30 | 0x1c1<<21 | 0x0c<<10,
- ALDORLD: 3<<30 | 0x1c3<<21 | 0x0c<<10,
- ALDORLW: 2<<30 | 0x1c3<<21 | 0x0c<<10,
- ALDORLH: 1<<30 | 0x1c3<<21 | 0x0c<<10,
- ALDORLB: 0<<30 | 0x1c3<<21 | 0x0c<<10,
- ASWPAD: 3<<30 | 0x1c5<<21 | 0x20<<10,
- ASWPAW: 2<<30 | 0x1c5<<21 | 0x20<<10,
- ASWPAH: 1<<30 | 0x1c5<<21 | 0x20<<10,
- ASWPAB: 0<<30 | 0x1c5<<21 | 0x20<<10,
- ASWPALD: 3<<30 | 0x1c7<<21 | 0x20<<10,
- ASWPALW: 2<<30 | 0x1c7<<21 | 0x20<<10,
- ASWPALH: 1<<30 | 0x1c7<<21 | 0x20<<10,
- ASWPALB: 0<<30 | 0x1c7<<21 | 0x20<<10,
- ASWPD: 3<<30 | 0x1c1<<21 | 0x20<<10,
- ASWPW: 2<<30 | 0x1c1<<21 | 0x20<<10,
- ASWPH: 1<<30 | 0x1c1<<21 | 0x20<<10,
- ASWPB: 0<<30 | 0x1c1<<21 | 0x20<<10,
- ASWPLD: 3<<30 | 0x1c3<<21 | 0x20<<10,
- ASWPLW: 2<<30 | 0x1c3<<21 | 0x20<<10,
- ASWPLH: 1<<30 | 0x1c3<<21 | 0x20<<10,
- ASWPLB: 0<<30 | 0x1c3<<21 | 0x20<<10,
- }
- var oprange [ALAST & obj.AMask][]Optab
- var xcmp [C_NCLASS][C_NCLASS]bool
- const (
- S32 = 0 << 31
- S64 = 1 << 31
- Sbit = 1 << 29
- LSL0_32 = 2 << 13
- LSL0_64 = 3 << 13
- )
- func OPDP2(x uint32) uint32 {
- return 0<<30 | 0<<29 | 0xd6<<21 | x<<10
- }
- func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 {
- return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15
- }
- func OPBcc(x uint32) uint32 {
- return 0x2A<<25 | 0<<24 | 0<<4 | x&15
- }
- func OPBLR(x uint32) uint32 {
- /* x=0, JMP; 1, CALL; 2, RET */
- return 0x6B<<25 | 0<<23 | x<<21 | 0x1F<<16 | 0<<10
- }
- func SYSOP(l uint32, op0 uint32, op1 uint32, crn uint32, crm uint32, op2 uint32, rt uint32) uint32 {
- return 0x354<<22 | l<<21 | op0<<19 | op1<<16 | crn&15<<12 | crm&15<<8 | op2<<5 | rt
- }
- func SYSHINT(x uint32) uint32 {
- return SYSOP(0, 0, 3, 2, 0, x, 0x1F)
- }
- func LDSTR12U(sz uint32, v uint32, opc uint32) uint32 {
- return sz<<30 | 7<<27 | v<<26 | 1<<24 | opc<<22
- }
- func LDSTR9S(sz uint32, v uint32, opc uint32) uint32 {
- return sz<<30 | 7<<27 | v<<26 | 0<<24 | opc<<22
- }
- func LD2STR(o uint32) uint32 {
- return o &^ (3 << 22)
- }
- func LDSTX(sz uint32, o2 uint32, l uint32, o1 uint32, o0 uint32) uint32 {
- return sz<<30 | 0x8<<24 | o2<<23 | l<<22 | o1<<21 | o0<<15
- }
- func FPCMP(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 {
- return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<14 | 8<<10 | op2
- }
- func FPCCMP(m uint32, s uint32, type_ uint32, op uint32) uint32 {
- return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | 1<<10 | op<<4
- }
- func FPOP1S(m uint32, s uint32, type_ uint32, op uint32) uint32 {
- return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<15 | 0x10<<10
- }
- func FPOP2S(m uint32, s uint32, type_ uint32, op uint32) uint32 {
- return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<12 | 2<<10
- }
- func FPOP3S(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 {
- return m<<31 | s<<29 | 0x1F<<24 | type_<<22 | op<<21 | op2<<15
- }
- func FPCVTI(sf uint32, s uint32, type_ uint32, rmode uint32, op uint32) uint32 {
- return sf<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | rmode<<19 | op<<16 | 0<<10
- }
- func ADR(p uint32, o uint32, rt uint32) uint32 {
- return p<<31 | (o&3)<<29 | 0x10<<24 | ((o>>2)&0x7FFFF)<<5 | rt&31
- }
- func OPBIT(x uint32) uint32 {
- return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10
- }
- func MOVCONST(d int64, s int, rt int) uint32 {
- return uint32(((d>>uint(s*16))&0xFFFF)<<5) | uint32(s)&3<<21 | uint32(rt&31)
- }
- const (
- // Optab.flag
- LFROM = 1 << 0 // p.From uses constant pool
- LTO = 1 << 1 // p.To uses constant pool
- NOTUSETMP = 1 << 2 // p expands to multiple instructions, but does NOT use REGTMP
- )
- var optab = []Optab{
- /* struct Optab:
- OPCODE, from, prog->reg, from3, to, type,size,param,flag,scond */
- {obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0},
- /* arithmetic operations */
- {AADD, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
- {AADD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
- {AADC, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
- {AADC, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
- {ANEG, C_REG, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0},
- {ANEG, C_NONE, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0},
- {ANGC, C_REG, C_NONE, C_NONE, C_REG, 17, 4, 0, 0, 0},
- {ACMP, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0},
- {AADD, C_ADDCON, C_RSP, C_NONE, C_RSP, 2, 4, 0, 0, 0},
- {AADD, C_ADDCON, C_NONE, C_NONE, C_RSP, 2, 4, 0, 0, 0},
- {ACMP, C_ADDCON, C_RSP, C_NONE, C_NONE, 2, 4, 0, 0, 0},
- {AADD, C_MOVCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0},
- {AADD, C_MOVCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0},
- {ACMP, C_MOVCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0},
- {AADD, C_BITCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0},
- {AADD, C_BITCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0},
- {ACMP, C_BITCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0},
- {AADD, C_ADDCON2, C_RSP, C_NONE, C_RSP, 48, 8, 0, NOTUSETMP, 0},
- {AADD, C_ADDCON2, C_NONE, C_NONE, C_RSP, 48, 8, 0, NOTUSETMP, 0},
- {AADD, C_MOVCON2, C_RSP, C_NONE, C_RSP, 13, 12, 0, 0, 0},
- {AADD, C_MOVCON2, C_NONE, C_NONE, C_RSP, 13, 12, 0, 0, 0},
- {AADD, C_MOVCON3, C_RSP, C_NONE, C_RSP, 13, 16, 0, 0, 0},
- {AADD, C_MOVCON3, C_NONE, C_NONE, C_RSP, 13, 16, 0, 0, 0},
- {AADD, C_VCON, C_RSP, C_NONE, C_RSP, 13, 20, 0, 0, 0},
- {AADD, C_VCON, C_NONE, C_NONE, C_RSP, 13, 20, 0, 0, 0},
- {ACMP, C_MOVCON2, C_REG, C_NONE, C_NONE, 13, 12, 0, 0, 0},
- {ACMP, C_MOVCON3, C_REG, C_NONE, C_NONE, 13, 16, 0, 0, 0},
- {ACMP, C_VCON, C_REG, C_NONE, C_NONE, 13, 20, 0, 0, 0},
- {AADD, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
- {AADD, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
- {AMVN, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
- {ACMP, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0},
- {ANEG, C_SHIFT, C_NONE, C_NONE, C_REG, 26, 4, 0, 0, 0},
- {AADD, C_REG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0},
- {AADD, C_REG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
- {ACMP, C_REG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0},
- {AADD, C_EXTREG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0},
- {AADD, C_EXTREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
- {AMVN, C_EXTREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
- {ACMP, C_EXTREG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0},
- {AADD, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
- {AADD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
- {AMUL, C_REG, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
- {AMUL, C_REG, C_NONE, C_NONE, C_REG, 15, 4, 0, 0, 0},
- {AMADD, C_REG, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
- {AREM, C_REG, C_REG, C_NONE, C_REG, 16, 8, 0, 0, 0},
- {AREM, C_REG, C_NONE, C_NONE, C_REG, 16, 8, 0, 0, 0},
- {ASDIV, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
- {ASDIV, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
- {AFADDS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
- {AFADDS, C_FREG, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
- {AFMSUBD, C_FREG, C_FREG, C_FREG, C_FREG, 15, 4, 0, 0, 0},
- {AFCMPS, C_FREG, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0},
- {AFCMPS, C_FCON, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0},
- {AVADDP, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
- {AVADD, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
- {AVADD, C_VREG, C_VREG, C_NONE, C_VREG, 89, 4, 0, 0, 0},
- {AVADD, C_VREG, C_NONE, C_NONE, C_VREG, 89, 4, 0, 0, 0},
- {AVADDV, C_ARNG, C_NONE, C_NONE, C_VREG, 85, 4, 0, 0, 0},
- /* logical operations */
- {AAND, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
- {AAND, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
- {AANDS, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
- {AANDS, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
- {ATST, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0},
- {AAND, C_MBCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0},
- {AAND, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
- {AANDS, C_MBCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0},
- {AANDS, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
- {ATST, C_MBCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0},
- {AAND, C_BITCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0},
- {AAND, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
- {AANDS, C_BITCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0},
- {AANDS, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
- {ATST, C_BITCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0},
- {AAND, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0},
- {AAND, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0},
- {AANDS, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0},
- {AANDS, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0},
- {ATST, C_MOVCON, C_REG, C_NONE, C_NONE, 62, 8, 0, 0, 0},
- {AAND, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0},
- {AAND, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0},
- {AAND, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0},
- {AAND, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 0},
- {AAND, C_VCON, C_REG, C_NONE, C_REG, 28, 20, 0, 0, 0},
- {AAND, C_VCON, C_NONE, C_NONE, C_REG, 28, 20, 0, 0, 0},
- {AANDS, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0},
- {AANDS, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0},
- {AANDS, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0},
- {AANDS, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 0},
- {AANDS, C_VCON, C_REG, C_NONE, C_REG, 28, 20, 0, 0, 0},
- {AANDS, C_VCON, C_NONE, C_NONE, C_REG, 28, 20, 0, 0, 0},
- {ATST, C_MOVCON2, C_REG, C_NONE, C_NONE, 28, 12, 0, 0, 0},
- {ATST, C_MOVCON3, C_REG, C_NONE, C_NONE, 28, 16, 0, 0, 0},
- {ATST, C_VCON, C_REG, C_NONE, C_NONE, 28, 20, 0, 0, 0},
- {AAND, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
- {AAND, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
- {AANDS, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
- {AANDS, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
- {ATST, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0},
- {AMOVD, C_RSP, C_NONE, C_NONE, C_RSP, 24, 4, 0, 0, 0},
- {AMVN, C_REG, C_NONE, C_NONE, C_REG, 24, 4, 0, 0, 0},
- {AMOVB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0},
- {AMOVBU, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0},
- {AMOVH, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVHU */
- {AMOVW, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVWU */
- /* TODO: MVN C_SHIFT */
- /* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */
- {AMOVW, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
- {AMOVD, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
- {AMOVW, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
- {AMOVD, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
- {AMOVW, C_MOVCON2, C_NONE, C_NONE, C_REG, 12, 8, 0, NOTUSETMP, 0},
- {AMOVD, C_MOVCON2, C_NONE, C_NONE, C_REG, 12, 8, 0, NOTUSETMP, 0},
- {AMOVD, C_MOVCON3, C_NONE, C_NONE, C_REG, 12, 12, 0, NOTUSETMP, 0},
- {AMOVD, C_VCON, C_NONE, C_NONE, C_REG, 12, 16, 0, NOTUSETMP, 0},
- {AMOVK, C_VCON, C_NONE, C_NONE, C_REG, 33, 4, 0, 0, 0},
- {AMOVD, C_AACON, C_NONE, C_NONE, C_RSP, 4, 4, REGFROM, 0, 0},
- {AMOVD, C_AACON2, C_NONE, C_NONE, C_RSP, 4, 8, REGFROM, 0, 0},
- /* load long effective stack address (load int32 offset and add) */
- {AMOVD, C_LACON, C_NONE, C_NONE, C_RSP, 34, 8, REGSP, LFROM, 0},
- // Move a large constant to a Vn.
- {AFMOVQ, C_VCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0},
- {AFMOVD, C_VCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0},
- {AFMOVS, C_LCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0},
- /* jump operations */
- {AB, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
- {ABL, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
- {AB, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
- {ABL, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
- {ABL, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
- {ABL, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
- {obj.ARET, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
- {obj.ARET, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
- {ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 7, 4, 0, 0, 0},
- {ACBZ, C_REG, C_NONE, C_NONE, C_SBRA, 39, 4, 0, 0, 0},
- {ATBZ, C_VCON, C_REG, C_NONE, C_SBRA, 40, 4, 0, 0, 0},
- {AERET, C_NONE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
- // get a PC-relative address
- {AADRP, C_SBRA, C_NONE, C_NONE, C_REG, 60, 4, 0, 0, 0},
- {AADR, C_SBRA, C_NONE, C_NONE, C_REG, 61, 4, 0, 0, 0},
- {ACLREX, C_NONE, C_NONE, C_NONE, C_VCON, 38, 4, 0, 0, 0},
- {ACLREX, C_NONE, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0},
- {ABFM, C_VCON, C_REG, C_VCON, C_REG, 42, 4, 0, 0, 0},
- {ABFI, C_VCON, C_REG, C_VCON, C_REG, 43, 4, 0, 0, 0},
- {AEXTR, C_VCON, C_REG, C_REG, C_REG, 44, 4, 0, 0, 0},
- {ASXTB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0},
- {ACLS, C_REG, C_NONE, C_NONE, C_REG, 46, 4, 0, 0, 0},
- {ALSL, C_VCON, C_REG, C_NONE, C_REG, 8, 4, 0, 0, 0},
- {ALSL, C_VCON, C_NONE, C_NONE, C_REG, 8, 4, 0, 0, 0},
- {ALSL, C_REG, C_NONE, C_NONE, C_REG, 9, 4, 0, 0, 0},
- {ALSL, C_REG, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
- {ASVC, C_VCON, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
- {ASVC, C_NONE, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
- {ADWORD, C_NONE, C_NONE, C_NONE, C_VCON, 11, 8, 0, NOTUSETMP, 0},
- {ADWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 11, 8, 0, NOTUSETMP, 0},
- {ADWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 11, 8, 0, NOTUSETMP, 0},
- {ADWORD, C_NONE, C_NONE, C_NONE, C_LACON, 11, 8, 0, NOTUSETMP, 0},
- {AWORD, C_NONE, C_NONE, C_NONE, C_LCON, 14, 4, 0, 0, 0},
- {AWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 14, 4, 0, 0, 0},
- {AWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 14, 4, 0, 0, 0},
- {AMOVW, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, NOTUSETMP, 0},
- {AMOVD, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, NOTUSETMP, 0},
- {AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
- {AMOVBU, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
- {AMOVH, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
- {AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
- {AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
- {AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
- {AMOVBU, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
- {AMOVH, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
- {AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
- {AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
- {AMOVD, C_GOTADDR, C_NONE, C_NONE, C_REG, 71, 8, 0, 0, 0},
- {AMOVD, C_TLS_LE, C_NONE, C_NONE, C_REG, 69, 4, 0, 0, 0},
- {AMOVD, C_TLS_IE, C_NONE, C_NONE, C_REG, 70, 8, 0, 0, 0},
- {AFMOVS, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
- {AFMOVS, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0},
- {AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
- {AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0},
- {AFMOVS, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0},
- {AFMOVS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
- {AFMOVD, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0},
- {AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
- {AFMOVS, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
- {AFMOVS, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
- {AFMOVD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
- {AFMOVD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
- {AFCVTZSD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
- {ASCVTFD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
- {AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
- {AVMOV, C_ELEM, C_NONE, C_NONE, C_REG, 73, 4, 0, 0, 0},
- {AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, 92, 4, 0, 0, 0},
- {AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0},
- {AVMOV, C_REG, C_NONE, C_NONE, C_ARNG, 82, 4, 0, 0, 0},
- {AVMOV, C_REG, C_NONE, C_NONE, C_ELEM, 78, 4, 0, 0, 0},
- {AVMOV, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0},
- {AVDUP, C_ELEM, C_NONE, C_NONE, C_ARNG, 79, 4, 0, 0, 0},
- {AVMOVI, C_ADDCON, C_NONE, C_NONE, C_ARNG, 86, 4, 0, 0, 0},
- {AVFMLA, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
- {AVEXT, C_VCON, C_ARNG, C_ARNG, C_ARNG, 94, 4, 0, 0, 0},
- {AVTBL, C_ARNG, C_NONE, C_LIST, C_ARNG, 100, 4, 0, 0, 0},
- {AVUSHR, C_VCON, C_ARNG, C_NONE, C_ARNG, 95, 4, 0, 0, 0},
- {AVZIP1, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
- {AVUSHLL, C_VCON, C_ARNG, C_NONE, C_ARNG, 102, 4, 0, 0, 0},
- {AVUXTL, C_ARNG, C_NONE, C_NONE, C_ARNG, 102, 4, 0, 0, 0},
- /* conditional operations */
- {ACSEL, C_COND, C_REG, C_REG, C_REG, 18, 4, 0, 0, 0},
- {ACINC, C_COND, C_REG, C_NONE, C_REG, 18, 4, 0, 0, 0},
- {ACSET, C_COND, C_NONE, C_NONE, C_REG, 18, 4, 0, 0, 0},
- {AFCSELD, C_COND, C_FREG, C_FREG, C_FREG, 18, 4, 0, 0, 0},
- {ACCMN, C_COND, C_REG, C_REG, C_VCON, 19, 4, 0, 0, 0},
- {ACCMN, C_COND, C_REG, C_VCON, C_VCON, 19, 4, 0, 0, 0},
- {AFCCMPS, C_COND, C_FREG, C_FREG, C_VCON, 57, 4, 0, 0, 0},
- /* scaled 12-bit unsigned displacement store */
- {AMOVB, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0},
- {AMOVB, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0},
- {AMOVBU, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0},
- {AMOVBU, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0},
- {AMOVH, C_REG, C_NONE, C_NONE, C_UAUTO8K, 20, 4, REGSP, 0, 0},
- {AMOVH, C_REG, C_NONE, C_NONE, C_UOREG8K, 20, 4, 0, 0, 0},
- {AMOVW, C_REG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
- {AMOVW, C_REG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
- {AMOVD, C_REG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0},
- {AMOVD, C_REG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0},
- {AFMOVS, C_FREG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
- {AFMOVS, C_FREG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
- {AFMOVD, C_FREG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0},
- {AFMOVD, C_FREG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0},
- /* unscaled 9-bit signed displacement store */
- {AMOVB, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
- {AMOVB, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
- {AMOVBU, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
- {AMOVBU, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
- {AMOVH, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
- {AMOVH, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
- {AMOVW, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
- {AMOVW, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
- {AMOVD, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
- {AMOVD, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
- {AFMOVS, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
- {AFMOVS, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
- {AFMOVD, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
- {AFMOVD, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
- /* scaled 12-bit unsigned displacement load */
- {AMOVB, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
- {AMOVB, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
- {AMOVBU, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
- {AMOVBU, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
- {AMOVH, C_UAUTO8K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
- {AMOVH, C_UOREG8K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
- {AMOVW, C_UAUTO16K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
- {AMOVW, C_UOREG16K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
- {AMOVD, C_UAUTO32K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
- {AMOVD, C_UOREG32K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
- {AFMOVS, C_UAUTO16K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
- {AFMOVS, C_UOREG16K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
- {AFMOVD, C_UAUTO32K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
- {AFMOVD, C_UOREG32K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
- /* unscaled 9-bit signed displacement load */
- {AMOVB, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
- {AMOVB, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
- {AMOVBU, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
- {AMOVBU, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
- {AMOVH, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
- {AMOVH, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
- {AMOVW, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
- {AMOVW, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
- {AMOVD, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
- {AMOVD, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
- {AFMOVS, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
- {AFMOVS, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
- {AFMOVD, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
- {AFMOVD, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
- /* long displacement store */
- {AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
- {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
- {AMOVBU, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
- {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
- {AMOVH, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
- {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
- {AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
- {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
- {AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
- {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
- {AFMOVS, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
- {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
- {AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
- {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
- /* long displacement load */
- {AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
- {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
- {AMOVBU, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
- {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
- {AMOVH, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
- {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
- {AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
- {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
- {AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
- {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
- {AFMOVS, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
- {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
- {AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
- {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
- /* pre/post-indexed load (unscaled, signed 9-bit offset) */
- {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
- {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
- {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
- {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
- {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
- {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
- {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
- {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
- {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
- {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
- {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
- {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
- {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
- {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
- /* pre/post-indexed store (unscaled, signed 9-bit offset) */
- {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
- {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
- {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
- {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
- {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
- {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
- {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
- {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
- {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
- {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
- {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
- {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
- {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
- {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
- /* load with shifted or extended register offset */
- {AMOVD, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
- {AMOVW, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
- {AMOVH, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
- {AMOVB, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
- {AMOVBU, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
- {AFMOVS, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0},
- {AFMOVD, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0},
- /* store with extended register offset */
- {AMOVD, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
- {AMOVW, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
- {AMOVH, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
- {AMOVB, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
- {AFMOVS, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
- {AFMOVD, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
- /* pre/post-indexed/signed-offset load/store register pair
- (unscaled, signed 10-bit quad-aligned and long offset) */
- {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
- {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
- {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
- {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
- {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
- {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
- {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
- {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
- {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
- {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
- {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
- {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
- {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
- {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE},
- {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST},
- {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
- {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
- {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
- {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
- {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
- {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
- {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
- {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
- {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
- {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
- {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
- {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
- {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
- {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE},
- {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST},
- {ALDP, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, 0},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPRE},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPOST},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, 0},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPRE},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPOST},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, 0},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPRE},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPOST},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, 0},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPRE},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPOST},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, 0},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPRE},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPOST},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPRE},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPOST},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST},
- {ASTP, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
- // differ from LDP/STP for C_NSAUTO_4/C_PSAUTO_4/C_NSOREG_4/C_PSOREG_4
- {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
- {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
- {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
- {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
- {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
- {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
- {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
- {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
- {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
- {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
- {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
- {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
- {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
- {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE},
- {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST},
- {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
- {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
- {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
- {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
- {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
- {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
- {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
- {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
- {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
- {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
- {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
- {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
- {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
- {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE},
- {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST},
- {ALDPW, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, 0},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPRE},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPOST},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, 0},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPRE},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPOST},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, 0},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPRE},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPOST},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, 0},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPRE},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPOST},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, 0},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPRE},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPOST},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPRE},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPOST},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST},
- {ASTPW, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
- {ASWPD, C_REG, C_NONE, C_NONE, C_ZOREG, 47, 4, 0, 0, 0}, // RegTo2=C_REG
- {ASWPD, C_REG, C_NONE, C_NONE, C_ZAUTO, 47, 4, REGSP, 0, 0}, // RegTo2=C_REG
- {ALDAR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
- {ALDXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
- {ALDAXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
- {ALDXP, C_ZOREG, C_NONE, C_NONE, C_PAIR, 58, 4, 0, 0, 0},
- {ASTLR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_NONE
- {ASTXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG
- {ASTLXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG
- {ASTXP, C_PAIR, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0},
- /* VLD[1-4]/VST[1-4] */
- {AVLD1, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0},
- {AVLD1, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
- {AVLD1, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
- {AVLD1R, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0},
- {AVLD1R, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
- {AVLD1R, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
- {AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST},
- {AVLD1, C_ROFF, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST},
- {AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, 0},
- {AVST1, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
- {AVST1, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
- {AVST1, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
- {AVST2, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
- {AVST2, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
- {AVST2, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
- {AVST3, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
- {AVST3, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
- {AVST3, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
- {AVST4, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
- {AVST4, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
- {AVST4, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
- {AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, C_XPOST},
- {AVST1, C_ELEM, C_NONE, C_NONE, C_ROFF, 96, 4, 0, 0, C_XPOST},
- {AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, 0},
- /* special */
- {AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0},
- {AMRS, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0},
- {AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0},
- {AMSR, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0},
- {AMOVD, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0},
- {AMSR, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0},
- {APRFM, C_UOREG32K, C_NONE, C_NONE, C_SPR, 91, 4, 0, 0, 0},
- {APRFM, C_UOREG32K, C_NONE, C_NONE, C_LCON, 91, 4, 0, 0, 0},
- {ADMB, C_VCON, C_NONE, C_NONE, C_NONE, 51, 4, 0, 0, 0},
- {AHINT, C_VCON, C_NONE, C_NONE, C_NONE, 52, 4, 0, 0, 0},
- {ASYS, C_VCON, C_NONE, C_NONE, C_NONE, 50, 4, 0, 0, 0},
- {ASYS, C_VCON, C_REG, C_NONE, C_NONE, 50, 4, 0, 0, 0},
- {ASYSL, C_VCON, C_NONE, C_NONE, C_REG, 50, 4, 0, 0, 0},
- /* encryption instructions */
- {AAESD, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0}, // for compatibility with old code
- {AAESD, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0}, // recommend using the new one for better readability
- {ASHA1C, C_VREG, C_REG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
- {ASHA1C, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
- {ASHA1H, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0},
- {ASHA1SU0, C_ARNG, C_ARNG, C_NONE, C_ARNG, 1, 4, 0, 0, 0},
- {ASHA256H, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
- {AVREV32, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0},
- {AVPMULL, C_ARNG, C_ARNG, C_NONE, C_ARNG, 93, 4, 0, 0, 0},
- {obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0},
- {obj.APCDATA, C_VCON, C_NONE, C_NONE, C_VCON, 0, 0, 0, 0, 0},
- {obj.AFUNCDATA, C_VCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
- {obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
- {obj.ANOP, C_LCON, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // nop variants, see #40689
- {obj.ANOP, C_REG, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
- {obj.ANOP, C_VREG, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
- {obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL
- {obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL
- {obj.APCALIGN, C_LCON, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // align code
- {obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
- }
- /*
- * valid pstate field values, and value to use in instruction
- */
- var pstatefield = []struct {
- reg int16
- enc uint32
- }{
- {REG_SPSel, 0<<16 | 4<<12 | 5<<5},
- {REG_DAIFSet, 3<<16 | 4<<12 | 6<<5},
- {REG_DAIFClr, 3<<16 | 4<<12 | 7<<5},
- }
- var prfopfield = []struct {
- reg int16
- enc uint32
- }{
- {REG_PLDL1KEEP, 0},
- {REG_PLDL1STRM, 1},
- {REG_PLDL2KEEP, 2},
- {REG_PLDL2STRM, 3},
- {REG_PLDL3KEEP, 4},
- {REG_PLDL3STRM, 5},
- {REG_PLIL1KEEP, 8},
- {REG_PLIL1STRM, 9},
- {REG_PLIL2KEEP, 10},
- {REG_PLIL2STRM, 11},
- {REG_PLIL3KEEP, 12},
- {REG_PLIL3STRM, 13},
- {REG_PSTL1KEEP, 16},
- {REG_PSTL1STRM, 17},
- {REG_PSTL2KEEP, 18},
- {REG_PSTL2STRM, 19},
- {REG_PSTL3KEEP, 20},
- {REG_PSTL3STRM, 21},
- }
- // Used for padinng NOOP instruction
- const OP_NOOP = 0xd503201f
- // align code to a certain length by padding bytes.
- func pcAlignPadLength(pc int64, alignedValue int64, ctxt *obj.Link) int {
- if !((alignedValue&(alignedValue-1) == 0) && 8 <= alignedValue && alignedValue <= 2048) {
- ctxt.Diag("alignment value of an instruction must be a power of two and in the range [8, 2048], got %d\n", alignedValue)
- }
- return int(-pc & (alignedValue - 1))
- }
- func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
- if ctxt.Retpoline {
- ctxt.Diag("-spectre=ret not supported on arm64")
- ctxt.Retpoline = false // don't keep printing
- }
- p := cursym.Func.Text
- if p == nil || p.Link == nil { // handle external functions and ELF section symbols
- return
- }
- if oprange[AAND&obj.AMask] == nil {
- ctxt.Diag("arm64 ops not initialized, call arm64.buildop first")
- }
- c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset & 0xffffffff), extrasize: int32(p.To.Offset >> 32)}
- p.To.Offset &= 0xffffffff // extrasize is no longer needed
- bflag := 1
- pc := int64(0)
- p.Pc = pc
- var m int
- var o *Optab
- for p = p.Link; p != nil; p = p.Link {
- if p.As == ADWORD && (pc&7) != 0 {
- pc += 4
- }
- p.Pc = pc
- o = c.oplook(p)
- m = int(o.size)
- if m == 0 {
- switch p.As {
- case obj.APCALIGN:
- alignedValue := p.From.Offset
- m = pcAlignPadLength(pc, alignedValue, ctxt)
- // Update the current text symbol alignment value.
- if int32(alignedValue) > cursym.Func.Align {
- cursym.Func.Align = int32(alignedValue)
- }
- break
- case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
- continue
- default:
- c.ctxt.Diag("zero-width instruction\n%v", p)
- }
- }
- switch o.flag & (LFROM | LTO) {
- case LFROM:
- c.addpool(p, &p.From)
- case LTO:
- c.addpool(p, &p.To)
- break
- }
- if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */
- c.checkpool(p, 0)
- }
- pc += int64(m)
- if c.blitrl != nil {
- c.checkpool(p, 1)
- }
- }
- c.cursym.Size = pc
- /*
- * if any procedure is large enough to
- * generate a large SBRA branch, then
- * generate extra passes putting branches
- * around jmps to fix. this is rare.
- */
- for bflag != 0 {
- bflag = 0
- pc = 0
- for p = c.cursym.Func.Text.Link; p != nil; p = p.Link {
- if p.As == ADWORD && (pc&7) != 0 {
- pc += 4
- }
- p.Pc = pc
- o = c.oplook(p)
- /* very large branches */
- if (o.type_ == 7 || o.type_ == 39 || o.type_ == 40) && p.To.Target() != nil { // 7: BEQ and like, 39: CBZ and like, 40: TBZ and like
- otxt := p.To.Target().Pc - pc
- var toofar bool
- switch o.type_ {
- case 7, 39: // branch instruction encodes 19 bits
- toofar = otxt <= -(1<<20)+10 || otxt >= (1<<20)-10
- case 40: // branch instruction encodes 14 bits
- toofar = otxt <= -(1<<15)+10 || otxt >= (1<<15)-10
- }
- if toofar {
- q := c.newprog()
- q.Link = p.Link
- p.Link = q
- q.As = AB
- q.To.Type = obj.TYPE_BRANCH
- q.To.SetTarget(p.To.Target())
- p.To.SetTarget(q)
- q = c.newprog()
- q.Link = p.Link
- p.Link = q
- q.As = AB
- q.To.Type = obj.TYPE_BRANCH
- q.To.SetTarget(q.Link.Link)
- bflag = 1
- }
- }
- m = int(o.size)
- if m == 0 {
- switch p.As {
- case obj.APCALIGN:
- alignedValue := p.From.Offset
- m = pcAlignPadLength(pc, alignedValue, ctxt)
- break
- case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
- continue
- default:
- c.ctxt.Diag("zero-width instruction\n%v", p)
- }
- }
- pc += int64(m)
- }
- }
- pc += -pc & (funcAlign - 1)
- c.cursym.Size = pc
- /*
- * lay out the code, emitting code and data relocations.
- */
- c.cursym.Grow(c.cursym.Size)
- bp := c.cursym.P
- psz := int32(0)
- var i int
- var out [6]uint32
- for p := c.cursym.Func.Text.Link; p != nil; p = p.Link {
- c.pc = p.Pc
- o = c.oplook(p)
- // need to align DWORDs on 8-byte boundary. The ISA doesn't
- // require it, but the various 64-bit loads we generate assume it.
- if o.as == ADWORD && psz%8 != 0 {
- bp[3] = 0
- bp[2] = bp[3]
- bp[1] = bp[2]
- bp[0] = bp[1]
- bp = bp[4:]
- psz += 4
- }
- if int(o.size) > 4*len(out) {
- log.Fatalf("out array in span7 is too small, need at least %d for %v", o.size/4, p)
- }
- if p.As == obj.APCALIGN {
- alignedValue := p.From.Offset
- v := pcAlignPadLength(p.Pc, alignedValue, c.ctxt)
- for i = 0; i < int(v/4); i++ {
- // emit ANOOP instruction by the padding size
- c.ctxt.Arch.ByteOrder.PutUint32(bp, OP_NOOP)
- bp = bp[4:]
- psz += 4
- }
- } else {
- c.asmout(p, o, out[:])
- for i = 0; i < int(o.size/4); i++ {
- c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
- bp = bp[4:]
- psz += 4
- }
- }
- }
- // Mark nonpreemptible instruction sequences.
- // We use REGTMP as a scratch register during call injection,
- // so instruction sequences that use REGTMP are unsafe to
- // preempt asynchronously.
- obj.MarkUnsafePoints(c.ctxt, c.cursym.Func.Text, c.newprog, c.isUnsafePoint, c.isRestartable)
- }
- // isUnsafePoint returns whether p is an unsafe point.
- func (c *ctxt7) isUnsafePoint(p *obj.Prog) bool {
- // If p explicitly uses REGTMP, it's unsafe to preempt, because the
- // preemption sequence clobbers REGTMP.
- return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP
- }
- // isRestartable returns whether p is a multi-instruction sequence that,
- // if preempted, can be restarted.
- func (c *ctxt7) isRestartable(p *obj.Prog) bool {
- if c.isUnsafePoint(p) {
- return false
- }
- // If p is a multi-instruction sequence with uses REGTMP inserted by
- // the assembler in order to materialize a large constant/offset, we
- // can restart p (at the start of the instruction sequence), recompute
- // the content of REGTMP, upon async preemption. Currently, all cases
- // of assembler-inserted REGTMP fall into this category.
- // If p doesn't use REGTMP, it can be simply preempted, so we don't
- // mark it.
- o := c.oplook(p)
- return o.size > 4 && o.flag&NOTUSETMP == 0
- }
- /*
- * when the first reference to the literal pool threatens
- * to go out of range of a 1Mb PC-relative offset
- * drop the pool now, and branch round it.
- */
- func (c *ctxt7) checkpool(p *obj.Prog, skip int) {
- if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) {
- c.flushpool(p, skip)
- } else if p.Link == nil {
- c.flushpool(p, 2)
- }
- }
- func (c *ctxt7) flushpool(p *obj.Prog, skip int) {
- if c.blitrl != nil {
- if skip != 0 {
- if c.ctxt.Debugvlog && skip == 1 {
- fmt.Printf("note: flush literal pool at %#x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start)
- }
- q := c.newprog()
- q.As = AB
- q.To.Type = obj.TYPE_BRANCH
- q.To.SetTarget(p.Link)
- q.Link = c.blitrl
- q.Pos = p.Pos
- c.blitrl = q
- } else if p.Pc+int64(c.pool.size)-int64(c.pool.start) < maxPCDisp {
- return
- }
- // The line number for constant pool entries doesn't really matter.
- // We set it to the line number of the preceding instruction so that
- // there are no deltas to encode in the pc-line tables.
- for q := c.blitrl; q != nil; q = q.Link {
- q.Pos = p.Pos
- }
- c.elitrl.Link = p.Link
- p.Link = c.blitrl
- c.blitrl = nil /* BUG: should refer back to values until out-of-range */
- c.elitrl = nil
- c.pool.size = 0
- c.pool.start = 0
- }
- }
- /*
- * MOVD foo(SB), R is actually
- * MOVD addr, REGTMP
- * MOVD REGTMP, R
- * where addr is the address of the DWORD containing the address of foo.
- *
- * TODO: hash
- */
- func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) {
- cls := c.aclass(a)
- lit := c.instoffset
- t := c.newprog()
- t.As = AWORD
- sz := 4
- if a.Type == obj.TYPE_CONST {
- if lit != int64(int32(lit)) && uint64(lit) != uint64(uint32(lit)) {
- // out of range -0x80000000 ~ 0xffffffff, must store 64-bit
- t.As = ADWORD
- sz = 8
- } // else store 32-bit
- } else if p.As == AMOVD && a.Type != obj.TYPE_MEM || cls == C_ADDR || cls == C_VCON || lit != int64(int32(lit)) || uint64(lit) != uint64(uint32(lit)) {
- // conservative: don't know if we want signed or unsigned extension.
- // in case of ambiguity, store 64-bit
- t.As = ADWORD
- sz = 8
- }
- switch cls {
- // TODO(aram): remove.
- default:
- if a.Name != obj.NAME_EXTERN {
- fmt.Printf("addpool: %v in %v shouldn't go to default case\n", DRconv(cls), p)
- }
- t.To.Offset = a.Offset
- t.To.Sym = a.Sym
- t.To.Type = a.Type
- t.To.Name = a.Name
- /* This is here because MOV uint12<<12, R is disabled in optab.
- Because of this, we need to load the constant from memory. */
- case C_ADDCON:
- fallthrough
- case C_ZAUTO,
- C_PSAUTO,
- C_PSAUTO_8,
- C_PSAUTO_4,
- C_PPAUTO,
- C_UAUTO4K_8,
- C_UAUTO4K_4,
- C_UAUTO4K_2,
- C_UAUTO4K,
- C_UAUTO8K_8,
- C_UAUTO8K_4,
- C_UAUTO8K,
- C_UAUTO16K_8,
- C_UAUTO16K,
- C_UAUTO32K,
- C_NSAUTO_8,
- C_NSAUTO_4,
- C_NSAUTO,
- C_NPAUTO,
- C_NAUTO4K,
- C_LAUTO,
- C_PPOREG,
- C_PSOREG,
- C_PSOREG_4,
- C_PSOREG_8,
- C_UOREG4K_8,
- C_UOREG4K_4,
- C_UOREG4K_2,
- C_UOREG4K,
- C_UOREG8K_8,
- C_UOREG8K_4,
- C_UOREG8K,
- C_UOREG16K_8,
- C_UOREG16K,
- C_UOREG32K,
- C_NSOREG_8,
- C_NSOREG_4,
- C_NSOREG,
- C_NPOREG,
- C_NOREG4K,
- C_LOREG,
- C_LACON,
- C_ADDCON2,
- C_LCON,
- C_VCON:
- if a.Name == obj.NAME_EXTERN {
- fmt.Printf("addpool: %v in %v needs reloc\n", DRconv(cls), p)
- }
- t.To.Type = obj.TYPE_CONST
- t.To.Offset = lit
- break
- }
- for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
- if q.To == t.To {
- p.Pool = q
- return
- }
- }
- q := c.newprog()
- *q = *t
- q.Pc = int64(c.pool.size)
- if c.blitrl == nil {
- c.blitrl = q
- c.pool.start = uint32(p.Pc)
- } else {
- c.elitrl.Link = q
- }
- c.elitrl = q
- c.pool.size = -c.pool.size & (funcAlign - 1)
- c.pool.size += uint32(sz)
- p.Pool = q
- }
- func (c *ctxt7) regoff(a *obj.Addr) uint32 {
- c.instoffset = 0
- c.aclass(a)
- return uint32(c.instoffset)
- }
- func isSTLXRop(op obj.As) bool {
- switch op {
- case ASTLXR, ASTLXRW, ASTLXRB, ASTLXRH,
- ASTXR, ASTXRW, ASTXRB, ASTXRH:
- return true
- }
- return false
- }
- func isSTXPop(op obj.As) bool {
- switch op {
- case ASTXP, ASTLXP, ASTXPW, ASTLXPW:
- return true
- }
- return false
- }
- func isANDop(op obj.As) bool {
- switch op {
- case AAND, AORR, AEOR, AANDS, ATST,
- ABIC, AEON, AORN, ABICS:
- return true
- }
- return false
- }
- func isANDWop(op obj.As) bool {
- switch op {
- case AANDW, AORRW, AEORW, AANDSW, ATSTW,
- ABICW, AEONW, AORNW, ABICSW:
- return true
- }
- return false
- }
- func isADDop(op obj.As) bool {
- switch op {
- case AADD, AADDS, ASUB, ASUBS, ACMN, ACMP:
- return true
- }
- return false
- }
- func isADDWop(op obj.As) bool {
- switch op {
- case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW:
- return true
- }
- return false
- }
- func isRegShiftOrExt(a *obj.Addr) bool {
- return (a.Index-obj.RBaseARM64)®_EXT != 0 || (a.Index-obj.RBaseARM64)®_LSL != 0
- }
- // Maximum PC-relative displacement.
- // The actual limit is ±2²⁰, but we are conservative
- // to avoid needing to recompute the literal pool flush points
- // as span-dependent jumps are enlarged.
- const maxPCDisp = 512 * 1024
- // ispcdisp reports whether v is a valid PC-relative displacement.
- func ispcdisp(v int32) bool {
- return -maxPCDisp < v && v < maxPCDisp && v&3 == 0
- }
- func isaddcon(v int64) bool {
- /* uimm12 or uimm24? */
- if v < 0 {
- return false
- }
- if (v & 0xFFF) == 0 {
- v >>= 12
- }
- return v <= 0xFFF
- }
- func isaddcon2(v int64) bool {
- return 0 <= v && v <= 0xFFFFFF
- }
- // isbitcon reports whether a constant can be encoded into a logical instruction.
- // bitcon has a binary form of repetition of a bit sequence of length 2, 4, 8, 16, 32, or 64,
- // which itself is a rotate (w.r.t. the length of the unit) of a sequence of ones.
- // special cases: 0 and -1 are not bitcon.
- // this function needs to run against virtually all the constants, so it needs to be fast.
- // for this reason, bitcon testing and bitcon encoding are separate functions.
- func isbitcon(x uint64) bool {
- if x == 1<<64-1 || x == 0 {
- return false
- }
- // determine the period and sign-extend a unit to 64 bits
- switch {
- case x != x>>32|x<<32:
- // period is 64
- // nothing to do
- case x != x>>16|x<<48:
- // period is 32
- x = uint64(int64(int32(x)))
- case x != x>>8|x<<56:
- // period is 16
- x = uint64(int64(int16(x)))
- case x != x>>4|x<<60:
- // period is 8
- x = uint64(int64(int8(x)))
- default:
- // period is 4 or 2, always true
- // 0001, 0010, 0100, 1000 -- 0001 rotate
- // 0011, 0110, 1100, 1001 -- 0011 rotate
- // 0111, 1011, 1101, 1110 -- 0111 rotate
- // 0101, 1010 -- 01 rotate, repeat
- return true
- }
- return sequenceOfOnes(x) || sequenceOfOnes(^x)
- }
- // sequenceOfOnes tests whether a constant is a sequence of ones in binary, with leading and trailing zeros
- func sequenceOfOnes(x uint64) bool {
- y := x & -x // lowest set bit of x. x is good iff x+y is a power of 2
- y += x
- return (y-1)&y == 0
- }
- // bitconEncode returns the encoding of a bitcon used in logical instructions
- // x is known to be a bitcon
- // a bitcon is a sequence of n ones at low bits (i.e. 1<<n-1), right rotated
- // by R bits, and repeated with period of 64, 32, 16, 8, 4, or 2.
- // it is encoded in logical instructions with 3 bitfields
- // N (1 bit) : R (6 bits) : S (6 bits), where
- // N=1 -- period=64
- // N=0, S=0xxxxx -- period=32
- // N=0, S=10xxxx -- period=16
- // N=0, S=110xxx -- period=8
- // N=0, S=1110xx -- period=4
- // N=0, S=11110x -- period=2
- // R is the shift amount, low bits of S = n-1
- func bitconEncode(x uint64, mode int) uint32 {
- var period uint32
- // determine the period and sign-extend a unit to 64 bits
- switch {
- case x != x>>32|x<<32:
- period = 64
- case x != x>>16|x<<48:
- period = 32
- x = uint64(int64(int32(x)))
- case x != x>>8|x<<56:
- period = 16
- x = uint64(int64(int16(x)))
- case x != x>>4|x<<60:
- period = 8
- x = uint64(int64(int8(x)))
- case x != x>>2|x<<62:
- period = 4
- x = uint64(int64(x<<60) >> 60)
- default:
- period = 2
- x = uint64(int64(x<<62) >> 62)
- }
- neg := false
- if int64(x) < 0 {
- x = ^x
- neg = true
- }
- y := x & -x // lowest set bit of x.
- s := log2(y)
- n := log2(x+y) - s // x (or ^x) is a sequence of n ones left shifted by s bits
- if neg {
- // ^x is a sequence of n ones left shifted by s bits
- // adjust n, s for x
- s = n + s
- n = period - n
- }
- N := uint32(0)
- if mode == 64 && period == 64 {
- N = 1
- }
- R := (period - s) & (period - 1) & uint32(mode-1) // shift amount of right rotate
- S := (n - 1) | 63&^(period<<1-1) // low bits = #ones - 1, high bits encodes period
- return N<<22 | R<<16 | S<<10
- }
- func log2(x uint64) uint32 {
- if x == 0 {
- panic("log2 of 0")
- }
- n := uint32(0)
- if x >= 1<<32 {
- x >>= 32
- n += 32
- }
- if x >= 1<<16 {
- x >>= 16
- n += 16
- }
- if x >= 1<<8 {
- x >>= 8
- n += 8
- }
- if x >= 1<<4 {
- x >>= 4
- n += 4
- }
- if x >= 1<<2 {
- x >>= 2
- n += 2
- }
- if x >= 1<<1 {
- x >>= 1
- n += 1
- }
- return n
- }
- func autoclass(l int64) int {
- if l == 0 {
- return C_ZAUTO
- }
- if l < 0 {
- if l >= -256 && (l&7) == 0 {
- return C_NSAUTO_8
- }
- if l >= -256 && (l&3) == 0 {
- return C_NSAUTO_4
- }
- if l >= -256 {
- return C_NSAUTO
- }
- if l >= -512 && (l&7) == 0 {
- return C_NPAUTO
- }
- if l >= -4095 {
- return C_NAUTO4K
- }
- return C_LAUTO
- }
- if l <= 255 {
- if (l & 7) == 0 {
- return C_PSAUTO_8
- }
- if (l & 3) == 0 {
- return C_PSAUTO_4
- }
- return C_PSAUTO
- }
- if l <= 504 && l&7 == 0 {
- return C_PPAUTO
- }
- if l <= 4095 {
- if l&7 == 0 {
- return C_UAUTO4K_8
- }
- if l&3 == 0 {
- return C_UAUTO4K_4
- }
- if l&1 == 0 {
- return C_UAUTO4K_2
- }
- return C_UAUTO4K
- }
- if l <= 8190 {
- if l&7 == 0 {
- return C_UAUTO8K_8
- }
- if l&3 == 0 {
- return C_UAUTO8K_4
- }
- if l&1 == 0 {
- return C_UAUTO8K
- }
- }
- if l <= 16380 {
- if l&7 == 0 {
- return C_UAUTO16K_8
- }
- if l&3 == 0 {
- return C_UAUTO16K
- }
- }
- if l <= 32760 && (l&7) == 0 {
- return C_UAUTO32K
- }
- return C_LAUTO
- }
- func oregclass(l int64) int {
- return autoclass(l) - C_ZAUTO + C_ZOREG
- }
- /*
- * given an offset v and a class c (see above)
- * return the offset value to use in the instruction,
- * scaled if necessary
- */
- func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 {
- s := 0
- if cls >= C_SEXT1 && cls <= C_SEXT16 {
- s = cls - C_SEXT1
- } else {
- switch cls {
- case C_UAUTO4K, C_UOREG4K, C_ZOREG:
- s = 0
- case C_UAUTO8K, C_UOREG8K:
- s = 1
- case C_UAUTO16K, C_UOREG16K:
- s = 2
- case C_UAUTO32K, C_UOREG32K:
- s = 3
- default:
- c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p)
- }
- }
- vs := v >> uint(s)
- if vs<<uint(s) != v {
- c.ctxt.Diag("odd offset: %d\n%v", v, p)
- }
- return vs
- }
- /*
- * if v contains a single 16-bit value aligned
- * on a 16-bit field, and thus suitable for movk/movn,
- * return the field index 0 to 3; otherwise return -1
- */
- func movcon(v int64) int {
- for s := 0; s < 64; s += 16 {
- if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 {
- return s / 16
- }
- }
- return -1
- }
- func rclass(r int16) int {
- switch {
- case REG_R0 <= r && r <= REG_R30: // not 31
- return C_REG
- case r == REGZERO:
- return C_ZCON
- case REG_F0 <= r && r <= REG_F31:
- return C_FREG
- case REG_V0 <= r && r <= REG_V31:
- return C_VREG
- case COND_EQ <= r && r <= COND_NV:
- return C_COND
- case r == REGSP:
- return C_RSP
- case r >= REG_ARNG && r < REG_ELEM:
- return C_ARNG
- case r >= REG_ELEM && r < REG_ELEM_END:
- return C_ELEM
- case r >= REG_UXTB && r < REG_SPECIAL:
- return C_EXTREG
- case r >= REG_SPECIAL:
- return C_SPR
- }
- return C_GOK
- }
- // con32class reclassifies the constant of 32-bit instruction. Because the constant type is 32-bit,
- // but saved in Offset which type is int64, con32class treats it as uint32 type and reclassifies it.
- func (c *ctxt7) con32class(a *obj.Addr) int {
- v := uint32(a.Offset)
- if v == 0 {
- return C_ZCON
- }
- if isaddcon(int64(v)) {
- if v <= 0xFFF {
- if isbitcon(uint64(a.Offset)) {
- return C_ABCON0
- }
- return C_ADDCON0
- }
- if isbitcon(uint64(a.Offset)) {
- return C_ABCON
- }
- if movcon(int64(v)) >= 0 {
- return C_AMCON
- }
- if movcon(int64(^v)) >= 0 {
- return C_AMCON
- }
- return C_ADDCON
- }
- t := movcon(int64(v))
- if t >= 0 {
- if isbitcon(uint64(a.Offset)) {
- return C_MBCON
- }
- return C_MOVCON
- }
- t = movcon(int64(^v))
- if t >= 0 {
- if isbitcon(uint64(a.Offset)) {
- return C_MBCON
- }
- return C_MOVCON
- }
- if isbitcon(uint64(a.Offset)) {
- return C_BITCON
- }
- if 0 <= v && v <= 0xffffff {
- return C_ADDCON2
- }
- return C_LCON
- }
- // con64class reclassifies the constant of C_VCON and C_LCON class.
- func (c *ctxt7) con64class(a *obj.Addr) int {
- zeroCount := 0
- negCount := 0
- for i := uint(0); i < 4; i++ {
- immh := uint32(a.Offset >> (i * 16) & 0xffff)
- if immh == 0 {
- zeroCount++
- } else if immh == 0xffff {
- negCount++
- }
- }
- if zeroCount >= 3 || negCount >= 3 {
- return C_MOVCON
- } else if zeroCount == 2 || negCount == 2 {
- return C_MOVCON2
- } else if zeroCount == 1 || negCount == 1 {
- return C_MOVCON3
- } else {
- return C_VCON
- }
- }
- func (c *ctxt7) aclass(a *obj.Addr) int {
- switch a.Type {
- case obj.TYPE_NONE:
- return C_NONE
- case obj.TYPE_REG:
- return rclass(a.Reg)
- case obj.TYPE_REGREG:
- return C_PAIR
- case obj.TYPE_SHIFT:
- return C_SHIFT
- case obj.TYPE_REGLIST:
- return C_LIST
- case obj.TYPE_MEM:
- // The base register should be an integer register.
- if int16(REG_F0) <= a.Reg && a.Reg <= int16(REG_V31) {
- break
- }
- switch a.Name {
- case obj.NAME_EXTERN, obj.NAME_STATIC:
- if a.Sym == nil {
- break
- }
- c.instoffset = a.Offset
- if a.Sym != nil { // use relocation
- if a.Sym.Type == objabi.STLSBSS {
- if c.ctxt.Flag_shared {
- return C_TLS_IE
- } else {
- return C_TLS_LE
- }
- }
- return C_ADDR
- }
- return C_LEXT
- case obj.NAME_GOTREF:
- return C_GOTADDR
- case obj.NAME_AUTO:
- if a.Reg == REGSP {
- // unset base register for better printing, since
- // a.Offset is still relative to pseudo-SP.
- a.Reg = obj.REG_NONE
- }
- // The frame top 8 or 16 bytes are for FP
- c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
- return autoclass(c.instoffset)
- case obj.NAME_PARAM:
- if a.Reg == REGSP {
- // unset base register for better printing, since
- // a.Offset is still relative to pseudo-FP.
- a.Reg = obj.REG_NONE
- }
- c.instoffset = int64(c.autosize) + a.Offset + 8
- return autoclass(c.instoffset)
- case obj.NAME_NONE:
- if a.Index != 0 {
- if a.Offset != 0 {
- if isRegShiftOrExt(a) {
- // extended or shifted register offset, (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2).
- return C_ROFF
- }
- return C_GOK
- }
- // register offset, (Rn)(Rm)
- return C_ROFF
- }
- c.instoffset = a.Offset
- return oregclass(c.instoffset)
- }
- return C_GOK
- case obj.TYPE_FCONST:
- return C_FCON
- case obj.TYPE_TEXTSIZE:
- return C_TEXTSIZE
- case obj.TYPE_CONST, obj.TYPE_ADDR:
- switch a.Name {
- case obj.NAME_NONE:
- c.instoffset = a.Offset
- if a.Reg != 0 && a.Reg != REGZERO {
- break
- }
- v := c.instoffset
- if v == 0 {
- return C_ZCON
- }
- if isaddcon(v) {
- if v <= 0xFFF {
- if isbitcon(uint64(v)) {
- return C_ABCON0
- }
- return C_ADDCON0
- }
- if isbitcon(uint64(v)) {
- return C_ABCON
- }
- if movcon(v) >= 0 {
- return C_AMCON
- }
- if movcon(^v) >= 0 {
- return C_AMCON
- }
- return C_ADDCON
- }
- t := movcon(v)
- if t >= 0 {
- if isbitcon(uint64(v)) {
- return C_MBCON
- }
- return C_MOVCON
- }
- t = movcon(^v)
- if t >= 0 {
- if isbitcon(uint64(v)) {
- return C_MBCON
- }
- return C_MOVCON
- }
- if isbitcon(uint64(v)) {
- return C_BITCON
- }
- if 0 <= v && v <= 0xffffff {
- return C_ADDCON2
- }
- if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) {
- return C_LCON
- }
- return C_VCON
- case obj.NAME_EXTERN, obj.NAME_STATIC:
- if a.Sym == nil {
- return C_GOK
- }
- if a.Sym.Type == objabi.STLSBSS {
- c.ctxt.Diag("taking address of TLS variable is not supported")
- }
- c.instoffset = a.Offset
- return C_VCONADDR
- case obj.NAME_AUTO:
- if a.Reg == REGSP {
- // unset base register for better printing, since
- // a.Offset is still relative to pseudo-SP.
- a.Reg = obj.REG_NONE
- }
- // The frame top 8 or 16 bytes are for FP
- c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
- case obj.NAME_PARAM:
- if a.Reg == REGSP {
- // unset base register for better printing, since
- // a.Offset is still relative to pseudo-FP.
- a.Reg = obj.REG_NONE
- }
- c.instoffset = int64(c.autosize) + a.Offset + 8
- default:
- return C_GOK
- }
- cf := c.instoffset
- if isaddcon(cf) || isaddcon(-cf) {
- return C_AACON
- }
- if isaddcon2(cf) {
- return C_AACON2
- }
- return C_LACON
- case obj.TYPE_BRANCH:
- return C_SBRA
- }
- return C_GOK
- }
- func oclass(a *obj.Addr) int {
- return int(a.Class) - 1
- }
- func (c *ctxt7) oplook(p *obj.Prog) *Optab {
- a1 := int(p.Optab)
- if a1 != 0 {
- return &optab[a1-1]
- }
- a1 = int(p.From.Class)
- if a1 == 0 {
- a0 := c.aclass(&p.From)
- // do not break C_ADDCON2 when S bit is set
- if (p.As == AADDS || p.As == AADDSW || p.As == ASUBS || p.As == ASUBSW) && a0 == C_ADDCON2 {
- a0 = C_LCON
- }
- a1 = a0 + 1
- p.From.Class = int8(a1)
- // more specific classification of 32-bit integers
- if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE {
- if p.As == AMOVW || isADDWop(p.As) {
- ra0 := c.con32class(&p.From)
- // do not break C_ADDCON2 when S bit is set
- if (p.As == AADDSW || p.As == ASUBSW) && ra0 == C_ADDCON2 {
- ra0 = C_LCON
- }
- a1 = ra0 + 1
- p.From.Class = int8(a1)
- }
- if isANDWop(p.As) && a0 != C_BITCON {
- // For 32-bit logical instruction with constant,
- // the BITCON test is special in that it looks at
- // the 64-bit which has the high 32-bit as a copy
- // of the low 32-bit. We have handled that and
- // don't pass it to con32class.
- a1 = c.con32class(&p.From) + 1
- p.From.Class = int8(a1)
- }
- if ((p.As == AMOVD) || isANDop(p.As) || isADDop(p.As)) && (a0 == C_LCON || a0 == C_VCON) {
- a1 = c.con64class(&p.From) + 1
- p.From.Class = int8(a1)
- }
- }
- }
- a1--
- a3 := C_NONE + 1
- if p.GetFrom3() != nil {
- a3 = int(p.GetFrom3().Class)
- if a3 == 0 {
- a3 = c.aclass(p.GetFrom3()) + 1
- p.GetFrom3().Class = int8(a3)
- }
- }
- a3--
- a4 := int(p.To.Class)
- if a4 == 0 {
- a4 = c.aclass(&p.To) + 1
- p.To.Class = int8(a4)
- }
- a4--
- a2 := C_NONE
- if p.Reg != 0 {
- a2 = rclass(p.Reg)
- }
- if false {
- fmt.Printf("oplook %v %d %d %d %d\n", p.As, a1, a2, a3, a4)
- fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
- }
- ops := oprange[p.As&obj.AMask]
- c1 := &xcmp[a1]
- c2 := &xcmp[a2]
- c3 := &xcmp[a3]
- c4 := &xcmp[a4]
- c5 := &xcmp[p.Scond>>5]
- for i := range ops {
- op := &ops[i]
- if (int(op.a2) == a2 || c2[op.a2]) && c5[op.scond>>5] && c1[op.a1] && c3[op.a3] && c4[op.a4] {
- p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
- return op
- }
- }
- c.ctxt.Diag("illegal combination: %v %v %v %v %v, %d %d", p, DRconv(a1), DRconv(a2), DRconv(a3), DRconv(a4), p.From.Type, p.To.Type)
- // Turn illegal instruction into an UNDEF, avoid crashing in asmout
- return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0}
- }
- func cmp(a int, b int) bool {
- if a == b {
- return true
- }
- switch a {
- case C_RSP:
- if b == C_REG {
- return true
- }
- case C_REG:
- if b == C_ZCON {
- return true
- }
- case C_ADDCON0:
- if b == C_ZCON || b == C_ABCON0 {
- return true
- }
- case C_ADDCON:
- if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON {
- return true
- }
- case C_BITCON:
- if b == C_ABCON0 || b == C_ABCON || b == C_MBCON {
- return true
- }
- case C_MOVCON:
- if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_AMCON {
- return true
- }
- case C_ADDCON2:
- if b == C_ZCON || b == C_ADDCON || b == C_ADDCON0 {
- return true
- }
- case C_LCON:
- if b == C_ZCON || b == C_BITCON || b == C_ADDCON || b == C_ADDCON0 || b == C_ABCON || b == C_ABCON0 || b == C_MBCON || b == C_MOVCON || b == C_ADDCON2 || b == C_AMCON {
- return true
- }
- case C_MOVCON2:
- return cmp(C_LCON, b)
- case C_VCON:
- return cmp(C_LCON, b)
- case C_LACON:
- if b == C_AACON || b == C_AACON2 {
- return true
- }
- case C_SEXT2:
- if b == C_SEXT1 {
- return true
- }
- case C_SEXT4:
- if b == C_SEXT1 || b == C_SEXT2 {
- return true
- }
- case C_SEXT8:
- if b >= C_SEXT1 && b <= C_SEXT4 {
- return true
- }
- case C_SEXT16:
- if b >= C_SEXT1 && b <= C_SEXT8 {
- return true
- }
- case C_LEXT:
- if b >= C_SEXT1 && b <= C_SEXT16 {
- return true
- }
- case C_NSAUTO_4:
- if b == C_NSAUTO_8 {
- return true
- }
- case C_NSAUTO:
- switch b {
- case C_NSAUTO_4, C_NSAUTO_8:
- return true
- }
- case C_NPAUTO:
- switch b {
- case C_NSAUTO_8:
- return true
- }
- case C_NAUTO4K:
- switch b {
- case C_NSAUTO_8, C_NSAUTO_4, C_NSAUTO, C_NPAUTO:
- return true
- }
- case C_PSAUTO_8:
- if b == C_ZAUTO {
- return true
- }
- case C_PSAUTO_4:
- switch b {
- case C_ZAUTO, C_PSAUTO_8:
- return true
- }
- case C_PSAUTO:
- switch b {
- case C_ZAUTO, C_PSAUTO_8, C_PSAUTO_4:
- return true
- }
- case C_PPAUTO:
- switch b {
- case C_ZAUTO, C_PSAUTO_8:
- return true
- }
- case C_UAUTO4K:
- switch b {
- case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8,
- C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8:
- return true
- }
- case C_UAUTO8K:
- switch b {
- case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO,
- C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8:
- return true
- }
- case C_UAUTO16K:
- switch b {
- case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO,
- C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO16K_8:
- return true
- }
- case C_UAUTO32K:
- switch b {
- case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8,
- C_PPAUTO, C_UAUTO4K_8, C_UAUTO8K_8, C_UAUTO16K_8:
- return true
- }
- case C_LAUTO:
- switch b {
- case C_ZAUTO, C_NSAUTO, C_NSAUTO_4, C_NSAUTO_8, C_NPAUTO,
- C_NAUTO4K, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO,
- C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8,
- C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8,
- C_UAUTO16K, C_UAUTO16K_8,
- C_UAUTO32K:
- return true
- }
- case C_NSOREG_4:
- if b == C_NSOREG_8 {
- return true
- }
- case C_NSOREG:
- switch b {
- case C_NSOREG_4, C_NSOREG_8:
- return true
- }
- case C_NPOREG:
- switch b {
- case C_NSOREG_8:
- return true
- }
- case C_NOREG4K:
- switch b {
- case C_NSOREG_8, C_NSOREG_4, C_NSOREG, C_NPOREG:
- return true
- }
- case C_PSOREG_4:
- switch b {
- case C_ZOREG, C_PSOREG_8:
- return true
- }
- case C_PSOREG:
- switch b {
- case C_ZOREG, C_PSOREG_8, C_PSOREG_4:
- return true
- }
- case C_PPOREG:
- switch b {
- case C_ZOREG, C_PSOREG_8:
- return true
- }
- case C_UOREG4K:
- switch b {
- case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
- C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8:
- return true
- }
- case C_UOREG8K:
- switch b {
- case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
- C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8,
- C_UOREG8K_4, C_UOREG8K_8:
- return true
- }
- case C_UOREG16K:
- switch b {
- case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
- C_PPOREG, C_UOREG4K_4, C_UOREG4K_8, C_UOREG8K_4,
- C_UOREG8K_8, C_UOREG16K_8:
- return true
- }
- case C_UOREG32K:
- switch b {
- case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
- C_PPOREG, C_UOREG4K_8, C_UOREG8K_8, C_UOREG16K_8:
- return true
- }
- case C_LOREG:
- switch b {
- case C_ZOREG, C_NSOREG, C_NSOREG_4, C_NSOREG_8, C_NPOREG,
- C_NOREG4K, C_PSOREG_4, C_PSOREG_8, C_PSOREG, C_PPOREG,
- C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8,
- C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8,
- C_UOREG16K, C_UOREG16K_8,
- C_UOREG32K:
- return true
- }
- case C_LBRA:
- if b == C_SBRA {
- return true
- }
- }
- return false
- }
- type ocmp []Optab
- func (x ocmp) Len() int {
- return len(x)
- }
- func (x ocmp) Swap(i, j int) {
- x[i], x[j] = x[j], x[i]
- }
- func (x ocmp) Less(i, j int) bool {
- p1 := &x[i]
- p2 := &x[j]
- if p1.as != p2.as {
- return p1.as < p2.as
- }
- if p1.a1 != p2.a1 {
- return p1.a1 < p2.a1
- }
- if p1.a2 != p2.a2 {
- return p1.a2 < p2.a2
- }
- if p1.a3 != p2.a3 {
- return p1.a3 < p2.a3
- }
- if p1.a4 != p2.a4 {
- return p1.a4 < p2.a4
- }
- if p1.scond != p2.scond {
- return p1.scond < p2.scond
- }
- return false
- }
- func oprangeset(a obj.As, t []Optab) {
- oprange[a&obj.AMask] = t
- }
- func buildop(ctxt *obj.Link) {
- if oprange[AAND&obj.AMask] != nil {
- // Already initialized; stop now.
- // This happens in the cmd/asm tests,
- // each of which re-initializes the arch.
- return
- }
- var n int
- for i := 0; i < C_GOK; i++ {
- for n = 0; n < C_GOK; n++ {
- if cmp(n, i) {
- xcmp[i][n] = true
- }
- }
- }
- for n = 0; optab[n].as != obj.AXXX; n++ {
- }
- sort.Sort(ocmp(optab[:n]))
- for i := 0; i < n; i++ {
- r := optab[i].as
- start := i
- for optab[i].as == r {
- i++
- }
- t := optab[start:i]
- i--
- oprangeset(r, t)
- switch r {
- default:
- ctxt.Diag("unknown op in build: %v", r)
- ctxt.DiagFlush()
- log.Fatalf("bad code")
- case AADD:
- oprangeset(AADDS, t)
- oprangeset(ASUB, t)
- oprangeset(ASUBS, t)
- oprangeset(AADDW, t)
- oprangeset(AADDSW, t)
- oprangeset(ASUBW, t)
- oprangeset(ASUBSW, t)
- case AAND: /* logical immediate, logical shifted register */
- oprangeset(AANDW, t)
- oprangeset(AEOR, t)
- oprangeset(AEORW, t)
- oprangeset(AORR, t)
- oprangeset(AORRW, t)
- oprangeset(ABIC, t)
- oprangeset(ABICW, t)
- oprangeset(AEON, t)
- oprangeset(AEONW, t)
- oprangeset(AORN, t)
- oprangeset(AORNW, t)
- case AANDS: /* logical immediate, logical shifted register, set flags, cannot target RSP */
- oprangeset(AANDSW, t)
- oprangeset(ABICS, t)
- oprangeset(ABICSW, t)
- case ANEG:
- oprangeset(ANEGS, t)
- oprangeset(ANEGSW, t)
- oprangeset(ANEGW, t)
- case AADC: /* rn=Rd */
- oprangeset(AADCW, t)
- oprangeset(AADCS, t)
- oprangeset(AADCSW, t)
- oprangeset(ASBC, t)
- oprangeset(ASBCW, t)
- oprangeset(ASBCS, t)
- oprangeset(ASBCSW, t)
- case ANGC: /* rn=REGZERO */
- oprangeset(ANGCW, t)
- oprangeset(ANGCS, t)
- oprangeset(ANGCSW, t)
- case ACMP:
- oprangeset(ACMPW, t)
- oprangeset(ACMN, t)
- oprangeset(ACMNW, t)
- case ATST:
- oprangeset(ATSTW, t)
- /* register/register, and shifted */
- case AMVN:
- oprangeset(AMVNW, t)
- case AMOVK:
- oprangeset(AMOVKW, t)
- oprangeset(AMOVN, t)
- oprangeset(AMOVNW, t)
- oprangeset(AMOVZ, t)
- oprangeset(AMOVZW, t)
- case ASWPD:
- for i := range atomicInstructions {
- oprangeset(i, t)
- }
- case ABEQ:
- oprangeset(ABNE, t)
- oprangeset(ABCS, t)
- oprangeset(ABHS, t)
- oprangeset(ABCC, t)
- oprangeset(ABLO, t)
- oprangeset(ABMI, t)
- oprangeset(ABPL, t)
- oprangeset(ABVS, t)
- oprangeset(ABVC, t)
- oprangeset(ABHI, t)
- oprangeset(ABLS, t)
- oprangeset(ABGE, t)
- oprangeset(ABLT, t)
- oprangeset(ABGT, t)
- oprangeset(ABLE, t)
- case ALSL:
- oprangeset(ALSLW, t)
- oprangeset(ALSR, t)
- oprangeset(ALSRW, t)
- oprangeset(AASR, t)
- oprangeset(AASRW, t)
- oprangeset(AROR, t)
- oprangeset(ARORW, t)
- case ACLS:
- oprangeset(ACLSW, t)
- oprangeset(ACLZ, t)
- oprangeset(ACLZW, t)
- oprangeset(ARBIT, t)
- oprangeset(ARBITW, t)
- oprangeset(AREV, t)
- oprangeset(AREVW, t)
- oprangeset(AREV16, t)
- oprangeset(AREV16W, t)
- oprangeset(AREV32, t)
- case ASDIV:
- oprangeset(ASDIVW, t)
- oprangeset(AUDIV, t)
- oprangeset(AUDIVW, t)
- oprangeset(ACRC32B, t)
- oprangeset(ACRC32CB, t)
- oprangeset(ACRC32CH, t)
- oprangeset(ACRC32CW, t)
- oprangeset(ACRC32CX, t)
- oprangeset(ACRC32H, t)
- oprangeset(ACRC32W, t)
- oprangeset(ACRC32X, t)
- case AMADD:
- oprangeset(AMADDW, t)
- oprangeset(AMSUB, t)
- oprangeset(AMSUBW, t)
- oprangeset(ASMADDL, t)
- oprangeset(ASMSUBL, t)
- oprangeset(AUMADDL, t)
- oprangeset(AUMSUBL, t)
- case AREM:
- oprangeset(AREMW, t)
- oprangeset(AUREM, t)
- oprangeset(AUREMW, t)
- case AMUL:
- oprangeset(AMULW, t)
- oprangeset(AMNEG, t)
- oprangeset(AMNEGW, t)
- oprangeset(ASMNEGL, t)
- oprangeset(ASMULL, t)
- oprangeset(ASMULH, t)
- oprangeset(AUMNEGL, t)
- oprangeset(AUMULH, t)
- oprangeset(AUMULL, t)
- case AMOVB:
- oprangeset(AMOVBU, t)
- case AMOVH:
- oprangeset(AMOVHU, t)
- case AMOVW:
- oprangeset(AMOVWU, t)
- case ABFM:
- oprangeset(ABFMW, t)
- oprangeset(ASBFM, t)
- oprangeset(ASBFMW, t)
- oprangeset(AUBFM, t)
- oprangeset(AUBFMW, t)
- case ABFI:
- oprangeset(ABFIW, t)
- oprangeset(ABFXIL, t)
- oprangeset(ABFXILW, t)
- oprangeset(ASBFIZ, t)
- oprangeset(ASBFIZW, t)
- oprangeset(ASBFX, t)
- oprangeset(ASBFXW, t)
- oprangeset(AUBFIZ, t)
- oprangeset(AUBFIZW, t)
- oprangeset(AUBFX, t)
- oprangeset(AUBFXW, t)
- case AEXTR:
- oprangeset(AEXTRW, t)
- case ASXTB:
- oprangeset(ASXTBW, t)
- oprangeset(ASXTH, t)
- oprangeset(ASXTHW, t)
- oprangeset(ASXTW, t)
- oprangeset(AUXTB, t)
- oprangeset(AUXTH, t)
- oprangeset(AUXTW, t)
- oprangeset(AUXTBW, t)
- oprangeset(AUXTHW, t)
- case ACCMN:
- oprangeset(ACCMNW, t)
- oprangeset(ACCMP, t)
- oprangeset(ACCMPW, t)
- case ACSEL:
- oprangeset(ACSELW, t)
- oprangeset(ACSINC, t)
- oprangeset(ACSINCW, t)
- oprangeset(ACSINV, t)
- oprangeset(ACSINVW, t)
- oprangeset(ACSNEG, t)
- oprangeset(ACSNEGW, t)
- case ACINC:
- // aliases Rm=Rn, !cond
- oprangeset(ACINCW, t)
- oprangeset(ACINV, t)
- oprangeset(ACINVW, t)
- oprangeset(ACNEG, t)
- oprangeset(ACNEGW, t)
- // aliases, Rm=Rn=REGZERO, !cond
- case ACSET:
- oprangeset(ACSETW, t)
- oprangeset(ACSETM, t)
- oprangeset(ACSETMW, t)
- case AMOVD,
- AMOVBU,
- AB,
- ABL,
- AWORD,
- ADWORD,
- obj.ARET,
- obj.ATEXT:
- break
- case ALDP:
- oprangeset(AFLDPD, t)
- case ASTP:
- oprangeset(AFSTPD, t)
- case ASTPW:
- oprangeset(AFSTPS, t)
- case ALDPW:
- oprangeset(ALDPSW, t)
- oprangeset(AFLDPS, t)
- case AERET:
- oprangeset(AWFE, t)
- oprangeset(AWFI, t)
- oprangeset(AYIELD, t)
- oprangeset(ASEV, t)
- oprangeset(ASEVL, t)
- oprangeset(ANOOP, t)
- oprangeset(ADRPS, t)
- case ACBZ:
- oprangeset(ACBZW, t)
- oprangeset(ACBNZ, t)
- oprangeset(ACBNZW, t)
- case ATBZ:
- oprangeset(ATBNZ, t)
- case AADR, AADRP:
- break
- case ACLREX:
- break
- case ASVC:
- oprangeset(AHVC, t)
- oprangeset(AHLT, t)
- oprangeset(ASMC, t)
- oprangeset(ABRK, t)
- oprangeset(ADCPS1, t)
- oprangeset(ADCPS2, t)
- oprangeset(ADCPS3, t)
- case AFADDS:
- oprangeset(AFADDD, t)
- oprangeset(AFSUBS, t)
- oprangeset(AFSUBD, t)
- oprangeset(AFMULS, t)
- oprangeset(AFMULD, t)
- oprangeset(AFNMULS, t)
- oprangeset(AFNMULD, t)
- oprangeset(AFDIVS, t)
- oprangeset(AFMAXD, t)
- oprangeset(AFMAXS, t)
- oprangeset(AFMIND, t)
- oprangeset(AFMINS, t)
- oprangeset(AFMAXNMD, t)
- oprangeset(AFMAXNMS, t)
- oprangeset(AFMINNMD, t)
- oprangeset(AFMINNMS, t)
- oprangeset(AFDIVD, t)
- case AFMSUBD:
- oprangeset(AFMSUBS, t)
- oprangeset(AFMADDS, t)
- oprangeset(AFMADDD, t)
- oprangeset(AFNMSUBS, t)
- oprangeset(AFNMSUBD, t)
- oprangeset(AFNMADDS, t)
- oprangeset(AFNMADDD, t)
- case AFCVTSD:
- oprangeset(AFCVTDS, t)
- oprangeset(AFABSD, t)
- oprangeset(AFABSS, t)
- oprangeset(AFNEGD, t)
- oprangeset(AFNEGS, t)
- oprangeset(AFSQRTD, t)
- oprangeset(AFSQRTS, t)
- oprangeset(AFRINTNS, t)
- oprangeset(AFRINTND, t)
- oprangeset(AFRINTPS, t)
- oprangeset(AFRINTPD, t)
- oprangeset(AFRINTMS, t)
- oprangeset(AFRINTMD, t)
- oprangeset(AFRINTZS, t)
- oprangeset(AFRINTZD, t)
- oprangeset(AFRINTAS, t)
- oprangeset(AFRINTAD, t)
- oprangeset(AFRINTXS, t)
- oprangeset(AFRINTXD, t)
- oprangeset(AFRINTIS, t)
- oprangeset(AFRINTID, t)
- oprangeset(AFCVTDH, t)
- oprangeset(AFCVTHS, t)
- oprangeset(AFCVTHD, t)
- oprangeset(AFCVTSH, t)
- case AFCMPS:
- oprangeset(AFCMPD, t)
- oprangeset(AFCMPES, t)
- oprangeset(AFCMPED, t)
- case AFCCMPS:
- oprangeset(AFCCMPD, t)
- oprangeset(AFCCMPES, t)
- oprangeset(AFCCMPED, t)
- case AFCSELD:
- oprangeset(AFCSELS, t)
- case AFMOVS, AFMOVD, AFMOVQ:
- break
- case AFCVTZSD:
- oprangeset(AFCVTZSDW, t)
- oprangeset(AFCVTZSS, t)
- oprangeset(AFCVTZSSW, t)
- oprangeset(AFCVTZUD, t)
- oprangeset(AFCVTZUDW, t)
- oprangeset(AFCVTZUS, t)
- oprangeset(AFCVTZUSW, t)
- case ASCVTFD:
- oprangeset(ASCVTFS, t)
- oprangeset(ASCVTFWD, t)
- oprangeset(ASCVTFWS, t)
- oprangeset(AUCVTFD, t)
- oprangeset(AUCVTFS, t)
- oprangeset(AUCVTFWD, t)
- oprangeset(AUCVTFWS, t)
- case ASYS:
- oprangeset(AAT, t)
- oprangeset(ADC, t)
- oprangeset(AIC, t)
- oprangeset(ATLBI, t)
- case ASYSL, AHINT:
- break
- case ADMB:
- oprangeset(ADSB, t)
- oprangeset(AISB, t)
- case AMRS, AMSR:
- break
- case ALDAR:
- oprangeset(ALDARW, t)
- oprangeset(ALDARB, t)
- oprangeset(ALDARH, t)
- fallthrough
- case ALDXR:
- oprangeset(ALDXRB, t)
- oprangeset(ALDXRH, t)
- oprangeset(ALDXRW, t)
- case ALDAXR:
- oprangeset(ALDAXRB, t)
- oprangeset(ALDAXRH, t)
- oprangeset(ALDAXRW, t)
- case ALDXP:
- oprangeset(ALDXPW, t)
- oprangeset(ALDAXP, t)
- oprangeset(ALDAXPW, t)
- case ASTLR:
- oprangeset(ASTLRB, t)
- oprangeset(ASTLRH, t)
- oprangeset(ASTLRW, t)
- case ASTXR:
- oprangeset(ASTXRB, t)
- oprangeset(ASTXRH, t)
- oprangeset(ASTXRW, t)
- case ASTLXR:
- oprangeset(ASTLXRB, t)
- oprangeset(ASTLXRH, t)
- oprangeset(ASTLXRW, t)
- case ASTXP:
- oprangeset(ASTLXP, t)
- oprangeset(ASTLXPW, t)
- oprangeset(ASTXPW, t)
- case AVADDP:
- oprangeset(AVAND, t)
- oprangeset(AVCMEQ, t)
- oprangeset(AVORR, t)
- oprangeset(AVEOR, t)
- oprangeset(AVBSL, t)
- oprangeset(AVBIT, t)
- oprangeset(AVCMTST, t)
- oprangeset(AVUZP1, t)
- oprangeset(AVUZP2, t)
- oprangeset(AVBIF, t)
- case AVADD:
- oprangeset(AVSUB, t)
- case AAESD:
- oprangeset(AAESE, t)
- oprangeset(AAESMC, t)
- oprangeset(AAESIMC, t)
- oprangeset(ASHA1SU1, t)
- oprangeset(ASHA256SU0, t)
- oprangeset(ASHA512SU0, t)
- case ASHA1C:
- oprangeset(ASHA1P, t)
- oprangeset(ASHA1M, t)
- case ASHA256H:
- oprangeset(ASHA256H2, t)
- oprangeset(ASHA512H, t)
- oprangeset(ASHA512H2, t)
- case ASHA1SU0:
- oprangeset(ASHA256SU1, t)
- oprangeset(ASHA512SU1, t)
- case AVADDV:
- oprangeset(AVUADDLV, t)
- case AVFMLA:
- oprangeset(AVFMLS, t)
- case AVPMULL:
- oprangeset(AVPMULL2, t)
- case AVUSHR:
- oprangeset(AVSHL, t)
- oprangeset(AVSRI, t)
- case AVREV32:
- oprangeset(AVCNT, t)
- oprangeset(AVRBIT, t)
- oprangeset(AVREV64, t)
- oprangeset(AVREV16, t)
- case AVZIP1:
- oprangeset(AVZIP2, t)
- case AVUXTL:
- oprangeset(AVUXTL2, t)
- case AVUSHLL:
- oprangeset(AVUSHLL2, t)
- case AVLD1R:
- oprangeset(AVLD2, t)
- oprangeset(AVLD2R, t)
- oprangeset(AVLD3, t)
- oprangeset(AVLD3R, t)
- oprangeset(AVLD4, t)
- oprangeset(AVLD4R, t)
- case ASHA1H,
- AVCNT,
- AVMOV,
- AVLD1,
- AVST1,
- AVST2,
- AVST3,
- AVST4,
- AVTBL,
- AVDUP,
- AVMOVI,
- APRFM,
- AVEXT:
- break
- case obj.ANOP,
- obj.AUNDEF,
- obj.AFUNCDATA,
- obj.APCALIGN,
- obj.APCDATA,
- obj.ADUFFZERO,
- obj.ADUFFCOPY:
- break
- }
- }
- }
- // chipfloat7() checks if the immediate constants available in FMOVS/FMOVD instructions.
- // For details of the range of constants available, see
- // http://infocenter.arm.com/help/topic/com.arm.doc.dui0473m/dom1359731199385.html.
- func (c *ctxt7) chipfloat7(e float64) int {
- ei := math.Float64bits(e)
- l := uint32(int32(ei))
- h := uint32(int32(ei >> 32))
- if l != 0 || h&0xffff != 0 {
- return -1
- }
- h1 := h & 0x7fc00000
- if h1 != 0x40000000 && h1 != 0x3fc00000 {
- return -1
- }
- n := 0
- // sign bit (a)
- if h&0x80000000 != 0 {
- n |= 1 << 7
- }
- // exp sign bit (b)
- if h1 == 0x3fc00000 {
- n |= 1 << 6
- }
- // rest of exp and mantissa (cd-efgh)
- n |= int((h >> 16) & 0x3f)
- //print("match %.8lux %.8lux %d\n", l, h, n);
- return n
- }
- /* form offset parameter to SYS; special register number */
- func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int {
- return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5
- }
- func SYSARG4(op1 int, Cn int, Cm int, op2 int) int {
- return SYSARG5(0, op1, Cn, Cm, op2)
- }
- // checkUnpredictable checks if the sourse and transfer registers are the same register.
- // ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same.
- func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) {
- if wback && rn != REGSP && (rn == rt1 || rn == rt2) {
- c.ctxt.Diag("constrained unpredictable behavior: %v", p)
- }
- if isload && rt1 == rt2 {
- c.ctxt.Diag("constrained unpredictable behavior: %v", p)
- }
- }
- /* checkindex checks if index >= 0 && index <= maxindex */
- func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) {
- if index < 0 || index > maxindex {
- c.ctxt.Diag("register element index out of range 0 to %d: %v", maxindex, p)
- }
- }
- /* checkoffset checks whether the immediate offset is valid for VLD[1-4].P and VST[1-4].P */
- func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) {
- var offset, list, n, expect int64
- switch as {
- case AVLD1, AVLD2, AVLD3, AVLD4, AVLD1R, AVLD2R, AVLD3R, AVLD4R:
- offset = p.From.Offset
- list = p.To.Offset
- case AVST1, AVST2, AVST3, AVST4:
- offset = p.To.Offset
- list = p.From.Offset
- default:
- c.ctxt.Diag("invalid operation on op %v", p.As)
- }
- opcode := (list >> 12) & 15
- q := (list >> 30) & 1
- size := (list >> 10) & 3
- if offset == 0 {
- return
- }
- switch opcode {
- case 0x7:
- n = 1 // one register
- case 0xa:
- n = 2 // two registers
- case 0x6:
- n = 3 // three registers
- case 0x2:
- n = 4 // four registers
- default:
- c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
- }
- switch as {
- case AVLD1R, AVLD2R, AVLD3R, AVLD4R:
- if offset != n*(1<<uint(size)) {
- c.ctxt.Diag("invalid post-increment offset: %v", p)
- }
- default:
- if !(q == 0 && offset == n*8) && !(q == 1 && offset == n*16) {
- c.ctxt.Diag("invalid post-increment offset: %v", p)
- }
- }
- switch as {
- case AVLD1, AVST1:
- return
- case AVLD1R:
- expect = 1
- case AVLD2, AVST2, AVLD2R:
- expect = 2
- case AVLD3, AVST3, AVLD3R:
- expect = 3
- case AVLD4, AVST4, AVLD4R:
- expect = 4
- }
- if expect != n {
- c.ctxt.Diag("expected %d registers, got %d: %v.", expect, n, p)
- }
- }
- /* checkShiftAmount checks whether the index shift amount is valid */
- /* for load with register offset instructions */
- func (c *ctxt7) checkShiftAmount(p *obj.Prog, a *obj.Addr) {
- var amount int16
- amount = (a.Index >> 5) & 7
- switch p.As {
- case AMOVB, AMOVBU:
- if amount != 0 {
- c.ctxt.Diag("invalid index shift amount: %v", p)
- }
- case AMOVH, AMOVHU:
- if amount != 1 && amount != 0 {
- c.ctxt.Diag("invalid index shift amount: %v", p)
- }
- case AMOVW, AMOVWU, AFMOVS:
- if amount != 2 && amount != 0 {
- c.ctxt.Diag("invalid index shift amount: %v", p)
- }
- case AMOVD, AFMOVD:
- if amount != 3 && amount != 0 {
- c.ctxt.Diag("invalid index shift amount: %v", p)
- }
- default:
- panic("invalid operation")
- }
- }
- func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
- var os [5]uint32
- o1 := uint32(0)
- o2 := uint32(0)
- o3 := uint32(0)
- o4 := uint32(0)
- o5 := uint32(0)
- if false { /*debug['P']*/
- fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
- }
- switch o.type_ {
- default:
- c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
- case 0: /* pseudo ops */
- break
- case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */
- o1 = c.oprrr(p, p.As)
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- r := int(p.Reg)
- if p.To.Type == obj.TYPE_NONE {
- rt = REGZERO
- }
- if r == 0 {
- r = rt
- }
- o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
- case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */
- o1 = c.opirr(p, p.As)
- rt := int(p.To.Reg)
- if p.To.Type == obj.TYPE_NONE {
- if (o1 & Sbit) == 0 {
- c.ctxt.Diag("ineffective ZR destination\n%v", p)
- }
- rt = REGZERO
- }
- r := int(p.Reg)
- if r == 0 {
- r = rt
- }
- v := int32(c.regoff(&p.From))
- o1 = c.oaddi(p, int32(o1), v, r, rt)
- case 3: /* op R<<n[,R],R (shifted register) */
- o1 = c.oprrr(p, p.As)
- amount := (p.From.Offset >> 10) & 63
- is64bit := o1 & (1 << 31)
- if is64bit == 0 && amount >= 32 {
- c.ctxt.Diag("shift amount out of range 0 to 31: %v", p)
- }
- o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
- rt := int(p.To.Reg)
- if p.To.Type == obj.TYPE_NONE {
- rt = REGZERO
- }
- r := int(p.Reg)
- if p.As == AMVN || p.As == AMVNW {
- r = REGZERO
- } else if r == 0 {
- r = rt
- }
- o1 |= (uint32(r&31) << 5) | uint32(rt&31)
- case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R; mov $addcon2, R */
- rt := int(p.To.Reg)
- r := int(o.param)
- if r == 0 {
- r = REGZERO
- } else if r == REGFROM {
- r = int(p.From.Reg)
- }
- if r == 0 {
- r = REGSP
- }
- v := int32(c.regoff(&p.From))
- var op int32
- if v < 0 {
- v = -v
- op = int32(c.opirr(p, ASUB))
- } else {
- op = int32(c.opirr(p, AADD))
- }
- if int(o.size) == 8 {
- o1 = c.oaddi(p, op, v&0xfff000, r, REGTMP)
- o2 = c.oaddi(p, op, v&0x000fff, REGTMP, rt)
- break
- }
- o1 = c.oaddi(p, op, v, r, rt)
- case 5: /* b s; bl s */
- o1 = c.opbra(p, p.As)
- if p.To.Sym == nil {
- o1 |= uint32(c.brdist(p, 0, 26, 2))
- break
- }
- rel := obj.Addrel(c.cursym)
- rel.Off = int32(c.pc)
- rel.Siz = 4
- rel.Sym = p.To.Sym
- rel.Add = p.To.Offset
- rel.Type = objabi.R_CALLARM64
- case 6: /* b ,O(R); bl ,O(R) */
- o1 = c.opbrr(p, p.As)
- o1 |= uint32(p.To.Reg&31) << 5
- rel := obj.Addrel(c.cursym)
- rel.Off = int32(c.pc)
- rel.Siz = 0
- rel.Type = objabi.R_CALLIND
- case 7: /* beq s */
- o1 = c.opbra(p, p.As)
- o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
- case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */
- rt := int(p.To.Reg)
- rf := int(p.Reg)
- if rf == 0 {
- rf = rt
- }
- v := int32(p.From.Offset)
- switch p.As {
- case AASR:
- o1 = c.opbfm(p, ASBFM, int(v), 63, rf, rt)
- case AASRW:
- o1 = c.opbfm(p, ASBFMW, int(v), 31, rf, rt)
- case ALSL:
- o1 = c.opbfm(p, AUBFM, int((64-v)&63), int(63-v), rf, rt)
- case ALSLW:
- o1 = c.opbfm(p, AUBFMW, int((32-v)&31), int(31-v), rf, rt)
- case ALSR:
- o1 = c.opbfm(p, AUBFM, int(v), 63, rf, rt)
- case ALSRW:
- o1 = c.opbfm(p, AUBFMW, int(v), 31, rf, rt)
- case AROR:
- o1 = c.opextr(p, AEXTR, v, rf, rf, rt)
- case ARORW:
- o1 = c.opextr(p, AEXTRW, v, rf, rf, rt)
- default:
- c.ctxt.Diag("bad shift $con\n%v", p)
- break
- }
- case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */
- o1 = c.oprrr(p, p.As)
- r := int(p.Reg)
- if r == 0 {
- r = int(p.To.Reg)
- }
- o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31)
- case 10: /* brk/hvc/.../svc [$con] */
- o1 = c.opimm(p, p.As)
- if p.From.Type != obj.TYPE_NONE {
- o1 |= uint32((p.From.Offset & 0xffff) << 5)
- }
- case 11: /* dword */
- c.aclass(&p.To)
- o1 = uint32(c.instoffset)
- o2 = uint32(c.instoffset >> 32)
- if p.To.Sym != nil {
- rel := obj.Addrel(c.cursym)
- rel.Off = int32(c.pc)
- rel.Siz = 8
- rel.Sym = p.To.Sym
- rel.Add = p.To.Offset
- rel.Type = objabi.R_ADDR
- o2 = 0
- o1 = o2
- }
- case 12: /* movT $vcon, reg */
- // NOTE: this case does not use REGTMP. If it ever does,
- // remove the NOTUSETMP flag in optab.
- num := c.omovlconst(p.As, p, &p.From, int(p.To.Reg), os[:])
- if num == 0 {
- c.ctxt.Diag("invalid constant: %v", p)
- }
- o1 = os[0]
- o2 = os[1]
- o3 = os[2]
- o4 = os[3]
- case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
- o := uint32(0)
- num := uint8(0)
- cls := oclass(&p.From)
- if isADDWop(p.As) {
- if !cmp(C_LCON, cls) {
- c.ctxt.Diag("illegal combination: %v", p)
- }
- num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
- } else {
- num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
- }
- if num == 0 {
- c.ctxt.Diag("invalid constant: %v", p)
- }
- rt := int(p.To.Reg)
- if p.To.Type == obj.TYPE_NONE {
- rt = REGZERO
- }
- r := int(p.Reg)
- if r == 0 {
- r = rt
- }
- if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
- o = c.opxrrr(p, p.As, false)
- o |= REGTMP & 31 << 16
- o |= LSL0_64
- } else {
- o = c.oprrr(p, p.As)
- o |= REGTMP & 31 << 16 /* shift is 0 */
- }
- o |= uint32(r&31) << 5
- o |= uint32(rt & 31)
- os[num] = o
- o1 = os[0]
- o2 = os[1]
- o3 = os[2]
- o4 = os[3]
- o5 = os[4]
- case 14: /* word */
- if c.aclass(&p.To) == C_ADDR {
- c.ctxt.Diag("address constant needs DWORD\n%v", p)
- }
- o1 = uint32(c.instoffset)
- if p.To.Sym != nil {
- // This case happens with words generated
- // in the PC stream as part of the literal pool.
- rel := obj.Addrel(c.cursym)
- rel.Off = int32(c.pc)
- rel.Siz = 4
- rel.Sym = p.To.Sym
- rel.Add = p.To.Offset
- rel.Type = objabi.R_ADDR
- o1 = 0
- }
- case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub/fmadd/fmsub/fnmadd/fnmsub Rm,Ra,Rn,Rd */
- o1 = c.oprrr(p, p.As)
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- var r int
- var ra int
- if p.From3Type() == obj.TYPE_REG {
- r = int(p.GetFrom3().Reg)
- ra = int(p.Reg)
- if ra == 0 {
- ra = REGZERO
- }
- } else {
- r = int(p.Reg)
- if r == 0 {
- r = rt
- }
- ra = REGZERO
- }
- o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31)
- case 16: /* XremY R[,R],R -> XdivY; XmsubY */
- o1 = c.oprrr(p, p.As)
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- r := int(p.Reg)
- if r == 0 {
- r = rt
- }
- o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31
- o2 = c.oprrr(p, AMSUBW)
- o2 |= o1 & (1 << 31) /* same size */
- o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31)
- case 17: /* op Rm,[Rn],Rd; default Rn=ZR */
- o1 = c.oprrr(p, p.As)
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- r := int(p.Reg)
- if p.To.Type == obj.TYPE_NONE {
- rt = REGZERO
- }
- if r == 0 {
- r = REGZERO
- }
- o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
- case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */
- o1 = c.oprrr(p, p.As)
- cond := int(p.From.Reg)
- if cond < COND_EQ || cond > COND_NV {
- c.ctxt.Diag("invalid condition: %v", p)
- } else {
- cond -= COND_EQ
- }
- r := int(p.Reg)
- var rf int
- if r != 0 {
- if p.From3Type() == obj.TYPE_NONE {
- /* CINC/CINV/CNEG */
- rf = r
- cond ^= 1
- } else {
- rf = int(p.GetFrom3().Reg) /* CSEL */
- }
- } else {
- /* CSET */
- rf = REGZERO
- r = rf
- cond ^= 1
- }
- rt := int(p.To.Reg)
- o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31)
- case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */
- nzcv := int(p.To.Offset)
- cond := int(p.From.Reg)
- if cond < COND_EQ || cond > COND_NV {
- c.ctxt.Diag("invalid condition\n%v", p)
- } else {
- cond -= COND_EQ
- }
- var rf int
- if p.GetFrom3().Type == obj.TYPE_REG {
- o1 = c.oprrr(p, p.As)
- rf = int(p.GetFrom3().Reg) /* Rm */
- } else {
- o1 = c.opirr(p, p.As)
- rf = int(p.GetFrom3().Offset & 0x1F)
- }
- o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv)
- case 20: /* movT R,O(R) -> strT */
- v := int32(c.regoff(&p.To))
- sz := int32(1 << uint(movesize(p.As)))
- r := int(p.To.Reg)
- if r == 0 {
- r = int(o.param)
- }
- if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
- o1 = c.olsr9s(p, int32(c.opstr9(p, p.As)), v, r, int(p.From.Reg))
- } else {
- v = int32(c.offsetshift(p, int64(v), int(o.a4)))
- o1 = c.olsr12u(p, int32(c.opstr12(p, p.As)), v, r, int(p.From.Reg))
- }
- case 21: /* movT O(R),R -> ldrT */
- v := int32(c.regoff(&p.From))
- sz := int32(1 << uint(movesize(p.As)))
- r := int(p.From.Reg)
- if r == 0 {
- r = int(o.param)
- }
- if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
- o1 = c.olsr9s(p, int32(c.opldr9(p, p.As)), v, r, int(p.To.Reg))
- } else {
- v = int32(c.offsetshift(p, int64(v), int(o.a1)))
- //print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1);
- o1 = c.olsr12u(p, int32(c.opldr12(p, p.As)), v, r, int(p.To.Reg))
- }
- case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */
- if p.From.Reg != REGSP && p.From.Reg == p.To.Reg {
- c.ctxt.Diag("constrained unpredictable behavior: %v", p)
- }
- v := int32(p.From.Offset)
- if v < -256 || v > 255 {
- c.ctxt.Diag("offset out of range [-255,254]: %v", p)
- }
- o1 = c.opldrpp(p, p.As)
- if o.scond == C_XPOST {
- o1 |= 1 << 10
- } else {
- o1 |= 3 << 10
- }
- o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31)
- case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */
- if p.To.Reg != REGSP && p.From.Reg == p.To.Reg {
- c.ctxt.Diag("constrained unpredictable behavior: %v", p)
- }
- v := int32(p.To.Offset)
- if v < -256 || v > 255 {
- c.ctxt.Diag("offset out of range [-255,254]: %v", p)
- }
- o1 = LD2STR(c.opldrpp(p, p.As))
- if o.scond == C_XPOST {
- o1 |= 1 << 10
- } else {
- o1 |= 3 << 10
- }
- o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31)
- case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- s := rf == REGSP || rt == REGSP
- if p.As == AMVN || p.As == AMVNW {
- if s {
- c.ctxt.Diag("illegal SP reference\n%v", p)
- }
- o1 = c.oprrr(p, p.As)
- o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
- } else if s {
- o1 = c.opirr(p, p.As)
- o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
- } else {
- o1 = c.oprrr(p, p.As)
- o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
- }
- case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */
- o1 = c.oprrr(p, p.As)
- rf := int(p.From.Reg)
- if rf == C_NONE {
- rf = int(p.To.Reg)
- }
- rt := int(p.To.Reg)
- o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
- case 26: /* negX Rm<<s, Rd -> subX Rm<<s, ZR, Rd */
- o1 = c.oprrr(p, p.As)
- o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
- rt := int(p.To.Reg)
- o1 |= (REGZERO & 31 << 5) | uint32(rt&31)
- case 27: /* op Rm<<n[,Rn],Rd (extended register) */
- if (p.From.Reg-obj.RBaseARM64)®_EXT != 0 {
- amount := (p.From.Reg >> 5) & 7
- if amount > 4 {
- c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
- }
- o1 = c.opxrrr(p, p.As, true)
- o1 |= c.encRegShiftOrExt(&p.From, p.From.Reg) /* includes reg, op, etc */
- } else {
- o1 = c.opxrrr(p, p.As, false)
- o1 |= uint32(p.From.Reg&31) << 16
- }
- rt := int(p.To.Reg)
- if p.To.Type == obj.TYPE_NONE {
- rt = REGZERO
- }
- r := int(p.Reg)
- if r == 0 {
- r = rt
- }
- o1 |= (uint32(r&31) << 5) | uint32(rt&31)
- case 28: /* logop $vcon, [R], R (64 bit literal) */
- o := uint32(0)
- num := uint8(0)
- cls := oclass(&p.From)
- if isANDWop(p.As) {
- if !cmp(C_LCON, cls) {
- c.ctxt.Diag("illegal combination: %v", p)
- }
- num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
- } else {
- num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
- }
- if num == 0 {
- c.ctxt.Diag("invalid constant: %v", p)
- }
- rt := int(p.To.Reg)
- if p.To.Type == obj.TYPE_NONE {
- rt = REGZERO
- }
- r := int(p.Reg)
- if r == 0 {
- r = rt
- }
- o = c.oprrr(p, p.As)
- o |= REGTMP & 31 << 16 /* shift is 0 */
- o |= uint32(r&31) << 5
- o |= uint32(rt & 31)
- os[num] = o
- o1 = os[0]
- o2 = os[1]
- o3 = os[2]
- o4 = os[3]
- o5 = os[4]
- case 29: /* op Rn, Rd */
- fc := c.aclass(&p.From)
- tc := c.aclass(&p.To)
- if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZCON || tc == C_REG || tc == C_ZCON) {
- // FMOV Rx, Fy or FMOV Fy, Rx
- o1 = FPCVTI(0, 0, 0, 0, 6)
- if p.As == AFMOVD {
- o1 |= 1<<31 | 1<<22 // 64-bit
- }
- if fc == C_REG || fc == C_ZCON {
- o1 |= 1 << 16 // FMOV Rx, Fy
- }
- } else {
- o1 = c.oprrr(p, p.As)
- }
- o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31)
- case 30: /* movT R,L(R) -> strT */
- // if offset L can be split into hi+lo, and both fit into instructions, do
- // add $hi, R, Rtmp
- // str R, lo(Rtmp)
- // otherwise, use constant pool
- // mov $L, Rtmp (from constant pool)
- // str R, (R+Rtmp)
- s := movesize(o.as)
- if s < 0 {
- c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
- }
- r := int(p.To.Reg)
- if r == 0 {
- r = int(o.param)
- }
- v := int32(c.regoff(&p.To))
- var hi int32
- if v < 0 || (v&((1<<uint(s))-1)) != 0 {
- // negative or unaligned offset, use constant pool
- goto storeusepool
- }
- hi = v - (v & (0xFFF << uint(s)))
- if hi&0xFFF != 0 {
- c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
- }
- if hi&^0xFFF000 != 0 {
- // hi doesn't fit into an ADD instruction
- goto storeusepool
- }
- o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
- o2 = c.olsr12u(p, int32(c.opstr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg))
- break
- storeusepool:
- if r == REGTMP || p.From.Reg == REGTMP {
- c.ctxt.Diag("REGTMP used in large offset store: %v", p)
- }
- o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
- o2 = c.olsxrr(p, int32(c.opstrr(p, p.As, false)), int(p.From.Reg), r, REGTMP)
- case 31: /* movT L(R), R -> ldrT */
- // if offset L can be split into hi+lo, and both fit into instructions, do
- // add $hi, R, Rtmp
- // ldr lo(Rtmp), R
- // otherwise, use constant pool
- // mov $L, Rtmp (from constant pool)
- // ldr (R+Rtmp), R
- s := movesize(o.as)
- if s < 0 {
- c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
- }
- r := int(p.From.Reg)
- if r == 0 {
- r = int(o.param)
- }
- v := int32(c.regoff(&p.From))
- var hi int32
- if v < 0 || (v&((1<<uint(s))-1)) != 0 {
- // negative or unaligned offset, use constant pool
- goto loadusepool
- }
- hi = v - (v & (0xFFF << uint(s)))
- if (hi & 0xFFF) != 0 {
- c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
- }
- if hi&^0xFFF000 != 0 {
- // hi doesn't fit into an ADD instruction
- goto loadusepool
- }
- o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
- o2 = c.olsr12u(p, int32(c.opldr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg))
- break
- loadusepool:
- if r == REGTMP || p.From.Reg == REGTMP {
- c.ctxt.Diag("REGTMP used in large offset load: %v", p)
- }
- o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
- o2 = c.olsxrr(p, int32(c.opldrr(p, p.As, false)), int(p.To.Reg), r, REGTMP)
- case 32: /* mov $con, R -> movz/movn */
- o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg))
- case 33: /* movk $uimm16 << pos */
- o1 = c.opirr(p, p.As)
- d := p.From.Offset
- s := movcon(d)
- if s < 0 || s >= 4 {
- c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p)
- }
- if (o1&S64) == 0 && s >= 2 {
- c.ctxt.Diag("illegal bit position\n%v", p)
- }
- if ((d >> uint(s*16)) >> 16) != 0 {
- c.ctxt.Diag("requires uimm16\n%v", p)
- }
- rt := int(p.To.Reg)
- o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31))
- case 34: /* mov $lacon,R */
- o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
- if o1 == 0 {
- break
- }
- o2 = c.opxrrr(p, AADD, false)
- o2 |= REGTMP & 31 << 16
- o2 |= LSL0_64
- r := int(p.From.Reg)
- if r == 0 {
- r = int(o.param)
- }
- o2 |= uint32(r&31) << 5
- o2 |= uint32(p.To.Reg & 31)
- case 35: /* mov SPR,R -> mrs */
- o1 = c.oprrr(p, AMRS)
- // SysRegEnc function returns the system register encoding and accessFlags.
- _, v, accessFlags := SysRegEnc(p.From.Reg)
- if v == 0 {
- c.ctxt.Diag("illegal system register:\n%v", p)
- }
- if (o1 & (v &^ (3 << 19))) != 0 {
- c.ctxt.Diag("MRS register value overlap\n%v", p)
- }
- if accessFlags&SR_READ == 0 {
- c.ctxt.Diag("system register is not readable: %v", p)
- }
- o1 |= v
- o1 |= uint32(p.To.Reg & 31)
- case 36: /* mov R,SPR */
- o1 = c.oprrr(p, AMSR)
- // SysRegEnc function returns the system register encoding and accessFlags.
- _, v, accessFlags := SysRegEnc(p.To.Reg)
- if v == 0 {
- c.ctxt.Diag("illegal system register:\n%v", p)
- }
- if (o1 & (v &^ (3 << 19))) != 0 {
- c.ctxt.Diag("MSR register value overlap\n%v", p)
- }
- if accessFlags&SR_WRITE == 0 {
- c.ctxt.Diag("system register is not writable: %v", p)
- }
- o1 |= v
- o1 |= uint32(p.From.Reg & 31)
- case 37: /* mov $con,PSTATEfield -> MSR [immediate] */
- if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 {
- c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p)
- }
- o1 = c.opirr(p, AMSR)
- o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */
- v := uint32(0)
- for i := 0; i < len(pstatefield); i++ {
- if pstatefield[i].reg == p.To.Reg {
- v = pstatefield[i].enc
- break
- }
- }
- if v == 0 {
- c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p)
- }
- o1 |= v
- case 38: /* clrex [$imm] */
- o1 = c.opimm(p, p.As)
- if p.To.Type == obj.TYPE_NONE {
- o1 |= 0xF << 8
- } else {
- o1 |= uint32((p.To.Offset & 0xF) << 8)
- }
- case 39: /* cbz R, rel */
- o1 = c.opirr(p, p.As)
- o1 |= uint32(p.From.Reg & 31)
- o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
- case 40: /* tbz */
- o1 = c.opirr(p, p.As)
- v := int32(p.From.Offset)
- if v < 0 || v > 63 {
- c.ctxt.Diag("illegal bit number\n%v", p)
- }
- o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19)
- o1 |= uint32(c.brdist(p, 0, 14, 2) << 5)
- o1 |= uint32(p.Reg & 31)
- case 41: /* eret, nop, others with no operands */
- o1 = c.op0(p, p.As)
- case 42: /* bfm R,r,s,R */
- o1 = c.opbfm(p, p.As, int(p.From.Offset), int(p.GetFrom3().Offset), int(p.Reg), int(p.To.Reg))
- case 43: /* bfm aliases */
- r := int(p.From.Offset)
- s := int(p.GetFrom3().Offset)
- rf := int(p.Reg)
- rt := int(p.To.Reg)
- if rf == 0 {
- rf = rt
- }
- switch p.As {
- case ABFI:
- if r != 0 {
- r = 64 - r
- }
- o1 = c.opbfm(p, ABFM, r, s-1, rf, rt)
- case ABFIW:
- if r != 0 {
- r = 32 - r
- }
- o1 = c.opbfm(p, ABFMW, r, s-1, rf, rt)
- case ABFXIL:
- o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt)
- case ABFXILW:
- o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt)
- case ASBFIZ:
- if r != 0 {
- r = 64 - r
- }
- o1 = c.opbfm(p, ASBFM, r, s-1, rf, rt)
- case ASBFIZW:
- if r != 0 {
- r = 32 - r
- }
- o1 = c.opbfm(p, ASBFMW, r, s-1, rf, rt)
- case ASBFX:
- o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt)
- case ASBFXW:
- o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt)
- case AUBFIZ:
- if r != 0 {
- r = 64 - r
- }
- o1 = c.opbfm(p, AUBFM, r, s-1, rf, rt)
- case AUBFIZW:
- if r != 0 {
- r = 32 - r
- }
- o1 = c.opbfm(p, AUBFMW, r, s-1, rf, rt)
- case AUBFX:
- o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt)
- case AUBFXW:
- o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt)
- default:
- c.ctxt.Diag("bad bfm alias\n%v", p)
- break
- }
- case 44: /* extr $b, Rn, Rm, Rd */
- o1 = c.opextr(p, p.As, int32(p.From.Offset), int(p.GetFrom3().Reg), int(p.Reg), int(p.To.Reg))
- case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- as := p.As
- if rf == REGZERO {
- as = AMOVWU /* clearer in disassembly */
- }
- switch as {
- case AMOVB, ASXTB:
- o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt)
- case AMOVH, ASXTH:
- o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt)
- case AMOVW, ASXTW:
- o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt)
- case AMOVBU, AUXTB:
- o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt)
- case AMOVHU, AUXTH:
- o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt)
- case AMOVWU:
- o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
- case AUXTW:
- o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt)
- case ASXTBW:
- o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt)
- case ASXTHW:
- o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt)
- case AUXTBW:
- o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt)
- case AUXTHW:
- o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt)
- default:
- c.ctxt.Diag("bad sxt %v", as)
- break
- }
- case 46: /* cls */
- o1 = c.opbit(p, p.As)
- o1 |= uint32(p.From.Reg&31) << 5
- o1 |= uint32(p.To.Reg & 31)
- case 47: /* SWPx/LDADDx/LDANDx/LDEORx/LDORx Rs, (Rb), Rt */
- rs := p.From.Reg
- rt := p.RegTo2
- rb := p.To.Reg
- fields := atomicInstructions[p.As]
- // rt can't be sp. rt can't be r31 when field A is 0, A bit is the 23rd bit.
- if rt == REG_RSP || (rt == REGZERO && (fields&(1<<23) == 0)) {
- c.ctxt.Diag("illegal destination register: %v\n", p)
- }
- o1 |= fields | uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
- case 48: /* ADD $C_ADDCON2, Rm, Rd */
- // NOTE: this case does not use REGTMP. If it ever does,
- // remove the NOTUSETMP flag in optab.
- op := c.opirr(p, p.As)
- if op&Sbit != 0 {
- c.ctxt.Diag("can not break addition/subtraction when S bit is set", p)
- }
- rt := int(p.To.Reg)
- r := int(p.Reg)
- if r == 0 {
- r = rt
- }
- o1 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0x000fff, r, rt)
- o2 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0xfff000, rt, rt)
- case 50: /* sys/sysl */
- o1 = c.opirr(p, p.As)
- if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 {
- c.ctxt.Diag("illegal SYS argument\n%v", p)
- }
- o1 |= uint32(p.From.Offset)
- if p.To.Type == obj.TYPE_REG {
- o1 |= uint32(p.To.Reg & 31)
- } else if p.Reg != 0 {
- o1 |= uint32(p.Reg & 31)
- } else {
- o1 |= 0x1F
- }
- case 51: /* dmb */
- o1 = c.opirr(p, p.As)
- if p.From.Type == obj.TYPE_CONST {
- o1 |= uint32((p.From.Offset & 0xF) << 8)
- }
- case 52: /* hint */
- o1 = c.opirr(p, p.As)
- o1 |= uint32((p.From.Offset & 0x7F) << 5)
- case 53: /* and/or/eor/bic/tst/... $bitcon, Rn, Rd */
- a := p.As
- rt := int(p.To.Reg)
- if p.To.Type == obj.TYPE_NONE {
- rt = REGZERO
- }
- r := int(p.Reg)
- if r == 0 {
- r = rt
- }
- mode := 64
- v := uint64(p.From.Offset)
- switch p.As {
- case AANDW, AORRW, AEORW, AANDSW, ATSTW:
- mode = 32
- case ABIC, AORN, AEON, ABICS:
- v = ^v
- case ABICW, AORNW, AEONW, ABICSW:
- v = ^v
- mode = 32
- }
- o1 = c.opirr(p, a)
- o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31)
- case 54: /* floating point arith */
- o1 = c.oprrr(p, p.As)
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- r := int(p.Reg)
- if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */
- r = rf
- rf = 0
- } else if r == 0 {
- r = rt
- }
- o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
- case 55: /* floating-point constant */
- var rf int
- o1 = 0xf<<25 | 1<<21 | 1<<12
- rf = c.chipfloat7(p.From.Val.(float64))
- if rf < 0 {
- c.ctxt.Diag("invalid floating-point immediate\n%v", p)
- }
- if p.As == AFMOVD {
- o1 |= 1 << 22
- }
- o1 |= (uint32(rf&0xff) << 13) | uint32(p.To.Reg&31)
- case 56: /* floating point compare */
- o1 = c.oprrr(p, p.As)
- var rf int
- if p.From.Type == obj.TYPE_FCONST {
- o1 |= 8 /* zero */
- rf = 0
- } else {
- rf = int(p.From.Reg)
- }
- rt := int(p.Reg)
- o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5
- case 57: /* floating point conditional compare */
- o1 = c.oprrr(p, p.As)
- cond := int(p.From.Reg)
- if cond < COND_EQ || cond > COND_NV {
- c.ctxt.Diag("invalid condition\n%v", p)
- } else {
- cond -= COND_EQ
- }
- nzcv := int(p.To.Offset)
- if nzcv&^0xF != 0 {
- c.ctxt.Diag("implausible condition\n%v", p)
- }
- rf := int(p.Reg)
- if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 {
- c.ctxt.Diag("illegal FCCMP\n%v", p)
- break
- }
- rt := int(p.GetFrom3().Reg)
- o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv)
- case 58: /* ldar/ldarb/ldarh/ldaxp/ldxp/ldaxr/ldxr */
- o1 = c.opload(p, p.As)
- o1 |= 0x1F << 16
- o1 |= uint32(p.From.Reg&31) << 5
- if p.As == ALDXP || p.As == ALDXPW || p.As == ALDAXP || p.As == ALDAXPW {
- if int(p.To.Reg) == int(p.To.Offset) {
- c.ctxt.Diag("constrained unpredictable behavior: %v", p)
- }
- o1 |= uint32(p.To.Offset&31) << 10
- } else {
- o1 |= 0x1F << 10
- }
- o1 |= uint32(p.To.Reg & 31)
- case 59: /* stxr/stlxr/stxp/stlxp */
- s := p.RegTo2
- n := p.To.Reg
- t := p.From.Reg
- if isSTLXRop(p.As) {
- if s == t || (s == n && n != REGSP) {
- c.ctxt.Diag("constrained unpredictable behavior: %v", p)
- }
- } else if isSTXPop(p.As) {
- t2 := int16(p.From.Offset)
- if (s == t || s == t2) || (s == n && n != REGSP) {
- c.ctxt.Diag("constrained unpredictable behavior: %v", p)
- }
- }
- if s == REG_RSP {
- c.ctxt.Diag("illegal destination register: %v\n", p)
- }
- o1 = c.opstore(p, p.As)
- if p.RegTo2 != obj.REG_NONE {
- o1 |= uint32(p.RegTo2&31) << 16
- } else {
- o1 |= 0x1F << 16
- }
- if isSTXPop(p.As) {
- o1 |= uint32(p.From.Offset&31) << 10
- }
- o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31)
- case 60: /* adrp label,r */
- d := c.brdist(p, 12, 21, 0)
- o1 = ADR(1, uint32(d), uint32(p.To.Reg))
- case 61: /* adr label, r */
- d := c.brdist(p, 0, 21, 0)
- o1 = ADR(0, uint32(d), uint32(p.To.Reg))
- case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */
- if p.Reg == REGTMP {
- c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
- }
- if isADDWop(p.As) || isANDWop(p.As) {
- o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
- } else {
- o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
- }
- rt := int(p.To.Reg)
- if p.To.Type == obj.TYPE_NONE {
- rt = REGZERO
- }
- r := int(p.Reg)
- if r == 0 {
- r = rt
- }
- if p.To.Reg == REGSP || r == REGSP {
- o2 = c.opxrrr(p, p.As, false)
- o2 |= REGTMP & 31 << 16
- o2 |= LSL0_64
- } else {
- o2 = c.oprrr(p, p.As)
- o2 |= REGTMP & 31 << 16 /* shift is 0 */
- }
- o2 |= uint32(r&31) << 5
- o2 |= uint32(rt & 31)
- /* reloc ops */
- case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */
- o1 = ADR(1, 0, REGTMP)
- o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
- rel := obj.Addrel(c.cursym)
- rel.Off = int32(c.pc)
- rel.Siz = 8
- rel.Sym = p.To.Sym
- rel.Add = p.To.Offset
- rel.Type = objabi.R_ADDRARM64
- o3 = c.olsr12u(p, int32(c.opstr12(p, p.As)), 0, REGTMP, int(p.From.Reg))
- case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */
- o1 = ADR(1, 0, REGTMP)
- o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
- rel := obj.Addrel(c.cursym)
- rel.Off = int32(c.pc)
- rel.Siz = 8
- rel.Sym = p.From.Sym
- rel.Add = p.From.Offset
- rel.Type = objabi.R_ADDRARM64
- o3 = c.olsr12u(p, int32(c.opldr12(p, p.As)), 0, REGTMP, int(p.To.Reg))
- case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */
- v := int32(c.regoff(&p.From))
- r := int(p.From.Reg)
- if r == obj.REG_NONE {
- r = int(o.param)
- }
- if r == obj.REG_NONE {
- c.ctxt.Diag("invalid ldp source: %v\n", p)
- }
- o1 |= c.opldpstp(p, o, v, uint32(r), uint32(p.To.Reg), uint32(p.To.Offset), 1)
- case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */
- r := int(p.To.Reg)
- if r == obj.REG_NONE {
- r = int(o.param)
- }
- if r == obj.REG_NONE {
- c.ctxt.Diag("invalid stp destination: %v\n", p)
- }
- v := int32(c.regoff(&p.To))
- o1 = c.opldpstp(p, o, v, uint32(r), uint32(p.From.Reg), uint32(p.From.Offset), 0)
- case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */
- // NOTE: this case does not use REGTMP. If it ever does,
- // remove the NOTUSETMP flag in optab.
- if p.As == AMOVW {
- c.ctxt.Diag("invalid load of 32-bit address: %v", p)
- }
- o1 = ADR(1, 0, uint32(p.To.Reg))
- o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31)
- rel := obj.Addrel(c.cursym)
- rel.Off = int32(c.pc)
- rel.Siz = 8
- rel.Sym = p.From.Sym
- rel.Add = p.From.Offset
- rel.Type = objabi.R_ADDRARM64
- case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */
- o1 = c.opirr(p, AMOVZ)
- o1 |= uint32(p.To.Reg & 31)
- rel := obj.Addrel(c.cursym)
- rel.Off = int32(c.pc)
- rel.Siz = 4
- rel.Sym = p.From.Sym
- rel.Type = objabi.R_ARM64_TLS_LE
- if p.From.Offset != 0 {
- c.ctxt.Diag("invalid offset on MOVW $tlsvar")
- }
- case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
- o1 = ADR(1, 0, REGTMP)
- o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
- rel := obj.Addrel(c.cursym)
- rel.Off = int32(c.pc)
- rel.Siz = 8
- rel.Sym = p.From.Sym
- rel.Add = 0
- rel.Type = objabi.R_ARM64_TLS_IE
- if p.From.Offset != 0 {
- c.ctxt.Diag("invalid offset on MOVW $tlsvar")
- }
- case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */
- o1 = ADR(1, 0, REGTMP)
- o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
- rel := obj.Addrel(c.cursym)
- rel.Off = int32(c.pc)
- rel.Siz = 8
- rel.Sym = p.From.Sym
- rel.Add = 0
- rel.Type = objabi.R_ARM64_GOTPCREL
- case 72: /* vaddp/vand/vcmeq/vorr/vadd/veor/vfmla/vfmls/vbit/vbsl/vcmtst/vsub/vbif/vuzip1/vuzip2 Vm.<T>, Vn.<T>, Vd.<T> */
- af := int((p.From.Reg >> 5) & 15)
- af3 := int((p.Reg >> 5) & 15)
- at := int((p.To.Reg >> 5) & 15)
- if af != af3 || af != at {
- c.ctxt.Diag("operand mismatch: %v", p)
- break
- }
- o1 = c.oprrr(p, p.As)
- rf := int((p.From.Reg) & 31)
- rt := int((p.To.Reg) & 31)
- r := int((p.Reg) & 31)
- Q := 0
- size := 0
- switch af {
- case ARNG_16B:
- Q = 1
- size = 0
- case ARNG_2D:
- Q = 1
- size = 3
- case ARNG_2S:
- Q = 0
- size = 2
- case ARNG_4H:
- Q = 0
- size = 1
- case ARNG_4S:
- Q = 1
- size = 2
- case ARNG_8B:
- Q = 0
- size = 0
- case ARNG_8H:
- Q = 1
- size = 1
- default:
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- switch p.As {
- case AVORR, AVAND, AVEOR, AVBIT, AVBSL, AVBIF:
- if af != ARNG_16B && af != ARNG_8B {
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- case AVFMLA, AVFMLS:
- if af != ARNG_2D && af != ARNG_2S && af != ARNG_4S {
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- }
- switch p.As {
- case AVAND, AVEOR:
- size = 0
- case AVBSL:
- size = 1
- case AVORR, AVBIT, AVBIF:
- size = 2
- case AVFMLA, AVFMLS:
- if af == ARNG_2D {
- size = 1
- } else {
- size = 0
- }
- }
- o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
- case 73: /* vmov V.<T>[index], R */
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- imm5 := 0
- o1 = 7<<25 | 0xf<<10
- index := int(p.From.Index)
- switch (p.From.Reg >> 5) & 15 {
- case ARNG_B:
- c.checkindex(p, index, 15)
- imm5 |= 1
- imm5 |= index << 1
- case ARNG_H:
- c.checkindex(p, index, 7)
- imm5 |= 2
- imm5 |= index << 2
- case ARNG_S:
- c.checkindex(p, index, 3)
- imm5 |= 4
- imm5 |= index << 3
- case ARNG_D:
- c.checkindex(p, index, 1)
- imm5 |= 8
- imm5 |= index << 4
- o1 |= 1 << 30
- default:
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
- case 74:
- // add $O, R, Rtmp or sub $O, R, Rtmp
- // ldp (Rtmp), (R1, R2)
- r := int(p.From.Reg)
- if r == obj.REG_NONE {
- r = int(o.param)
- }
- if r == obj.REG_NONE {
- c.ctxt.Diag("invalid ldp source: %v", p)
- }
- v := int32(c.regoff(&p.From))
- if v > 0 {
- if v > 4095 {
- c.ctxt.Diag("offset out of range: %v", p)
- }
- o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
- }
- if v < 0 {
- if v < -4095 {
- c.ctxt.Diag("offset out of range: %v", p)
- }
- o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP)
- }
- o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
- case 75:
- // mov $L, Rtmp (from constant pool)
- // add Rtmp, R, Rtmp
- // ldp (Rtmp), (R1, R2)
- r := int(p.From.Reg)
- if r == obj.REG_NONE {
- r = int(o.param)
- }
- if r == obj.REG_NONE {
- c.ctxt.Diag("invalid ldp source: %v", p)
- }
- o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
- o2 = c.opxrrr(p, AADD, false)
- o2 |= (REGTMP & 31) << 16
- o2 |= uint32(r&31) << 5
- o2 |= uint32(REGTMP & 31)
- o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
- case 76:
- // add $O, R, Rtmp or sub $O, R, Rtmp
- // stp (R1, R2), (Rtmp)
- r := int(p.To.Reg)
- if r == obj.REG_NONE {
- r = int(o.param)
- }
- if r == obj.REG_NONE {
- c.ctxt.Diag("invalid stp destination: %v", p)
- }
- v := int32(c.regoff(&p.To))
- if v > 0 {
- if v > 4095 {
- c.ctxt.Diag("offset out of range: %v", p)
- }
- o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
- }
- if v < 0 {
- if v < -4095 {
- c.ctxt.Diag("offset out of range: %v", p)
- }
- o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP)
- }
- o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
- case 77:
- // mov $L, Rtmp (from constant pool)
- // add Rtmp, R, Rtmp
- // stp (R1, R2), (Rtmp)
- r := int(p.To.Reg)
- if r == obj.REG_NONE {
- r = int(o.param)
- }
- if r == obj.REG_NONE {
- c.ctxt.Diag("invalid stp destination: %v", p)
- }
- o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
- o2 = c.opxrrr(p, AADD, false)
- o2 |= REGTMP & 31 << 16
- o2 |= uint32(r&31) << 5
- o2 |= uint32(REGTMP & 31)
- o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
- case 78: /* vmov R, V.<T>[index] */
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- imm5 := 0
- o1 = 1<<30 | 7<<25 | 7<<10
- index := int(p.To.Index)
- switch (p.To.Reg >> 5) & 15 {
- case ARNG_B:
- c.checkindex(p, index, 15)
- imm5 |= 1
- imm5 |= index << 1
- case ARNG_H:
- c.checkindex(p, index, 7)
- imm5 |= 2
- imm5 |= index << 2
- case ARNG_S:
- c.checkindex(p, index, 3)
- imm5 |= 4
- imm5 |= index << 3
- case ARNG_D:
- c.checkindex(p, index, 1)
- imm5 |= 8
- imm5 |= index << 4
- default:
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
- case 79: /* vdup Vn.<T>[index], Vd.<T> */
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- o1 = 7<<25 | 1<<10
- var imm5, Q int
- index := int(p.From.Index)
- switch (p.To.Reg >> 5) & 15 {
- case ARNG_16B:
- c.checkindex(p, index, 15)
- Q = 1
- imm5 = 1
- imm5 |= index << 1
- case ARNG_2D:
- c.checkindex(p, index, 1)
- Q = 1
- imm5 = 8
- imm5 |= index << 4
- case ARNG_2S:
- c.checkindex(p, index, 3)
- Q = 0
- imm5 = 4
- imm5 |= index << 3
- case ARNG_4H:
- c.checkindex(p, index, 7)
- Q = 0
- imm5 = 2
- imm5 |= index << 2
- case ARNG_4S:
- c.checkindex(p, index, 3)
- Q = 1
- imm5 = 4
- imm5 |= index << 3
- case ARNG_8B:
- c.checkindex(p, index, 15)
- Q = 0
- imm5 = 1
- imm5 |= index << 1
- case ARNG_8H:
- c.checkindex(p, index, 7)
- Q = 1
- imm5 = 2
- imm5 |= index << 2
- default:
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16)
- o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
- case 80: /* vmov V.<T>[index], Vn */
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- imm5 := 0
- index := int(p.From.Index)
- switch p.As {
- case AVMOV:
- o1 = 1<<30 | 15<<25 | 1<<10
- switch (p.From.Reg >> 5) & 15 {
- case ARNG_B:
- c.checkindex(p, index, 15)
- imm5 |= 1
- imm5 |= index << 1
- case ARNG_H:
- c.checkindex(p, index, 7)
- imm5 |= 2
- imm5 |= index << 2
- case ARNG_S:
- c.checkindex(p, index, 3)
- imm5 |= 4
- imm5 |= index << 3
- case ARNG_D:
- c.checkindex(p, index, 1)
- imm5 |= 8
- imm5 |= index << 4
- default:
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- default:
- c.ctxt.Diag("unsupported op %v", p.As)
- }
- o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
- case 81: /* vld[1-4]|vld[1-4]r (Rn), [Vt1.<T>, Vt2.<T>, ...] */
- c.checkoffset(p, p.As)
- r := int(p.From.Reg)
- o1 = c.oprrr(p, p.As)
- if o.scond == C_XPOST {
- o1 |= 1 << 23
- if p.From.Index == 0 {
- // immediate offset variant
- o1 |= 0x1f << 16
- } else {
- // register offset variant
- if isRegShiftOrExt(&p.From) {
- c.ctxt.Diag("invalid extended register op: %v\n", p)
- }
- o1 |= uint32(p.From.Index&0x1f) << 16
- }
- }
- o1 |= uint32(p.To.Offset)
- // cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset
- // add opcode(bit 12-15) for vld1, mask it off if it's not vld1
- o1 = c.maskOpvldvst(p, o1)
- o1 |= uint32(r&31) << 5
- case 82: /* vmov Rn, Vd.<T> */
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- o1 = 7<<25 | 3<<10
- var imm5, Q uint32
- switch (p.To.Reg >> 5) & 15 {
- case ARNG_16B:
- Q = 1
- imm5 = 1
- case ARNG_2D:
- Q = 1
- imm5 = 8
- case ARNG_2S:
- Q = 0
- imm5 = 4
- case ARNG_4H:
- Q = 0
- imm5 = 2
- case ARNG_4S:
- Q = 1
- imm5 = 4
- case ARNG_8B:
- Q = 0
- imm5 = 1
- case ARNG_8H:
- Q = 1
- imm5 = 2
- default:
- c.ctxt.Diag("invalid arrangement on VMOV Rn, Vd.<T>: %v\n", p)
- }
- o1 |= (Q & 1 << 30) | (imm5 & 0x1f << 16)
- o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
- case 83: /* vmov Vn.<T>, Vd.<T> */
- af := int((p.From.Reg >> 5) & 15)
- at := int((p.To.Reg >> 5) & 15)
- if af != at {
- c.ctxt.Diag("invalid arrangement: %v\n", p)
- }
- o1 = c.oprrr(p, p.As)
- rf := int((p.From.Reg) & 31)
- rt := int((p.To.Reg) & 31)
- var Q, size uint32
- switch af {
- case ARNG_8B:
- Q = 0
- size = 0
- case ARNG_16B:
- Q = 1
- size = 0
- case ARNG_4H:
- Q = 0
- size = 1
- case ARNG_8H:
- Q = 1
- size = 1
- case ARNG_2S:
- Q = 0
- size = 2
- case ARNG_4S:
- Q = 1
- size = 2
- default:
- c.ctxt.Diag("invalid arrangement: %v\n", p)
- }
- if (p.As == AVMOV || p.As == AVRBIT || p.As == AVCNT) && (af != ARNG_16B && af != ARNG_8B) {
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- if p.As == AVREV32 && (af == ARNG_2S || af == ARNG_4S) {
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- if p.As == AVREV16 && af != ARNG_8B && af != ARNG_16B {
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- if p.As == AVMOV {
- o1 |= uint32(rf&31) << 16
- }
- if p.As == AVRBIT {
- size = 1
- }
- o1 |= (Q&1)<<30 | (size&3)<<22 | uint32(rf&31)<<5 | uint32(rt&31)
- case 84: /* vst[1-4] [Vt1.<T>, Vt2.<T>, ...], (Rn) */
- c.checkoffset(p, p.As)
- r := int(p.To.Reg)
- o1 = 3 << 26
- if o.scond == C_XPOST {
- o1 |= 1 << 23
- if p.To.Index == 0 {
- // immediate offset variant
- o1 |= 0x1f << 16
- } else {
- // register offset variant
- if isRegShiftOrExt(&p.To) {
- c.ctxt.Diag("invalid extended register: %v\n", p)
- }
- o1 |= uint32(p.To.Index&31) << 16
- }
- }
- o1 |= uint32(p.From.Offset)
- // cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset
- // add opcode(bit 12-15) for vst1, mask it off if it's not vst1
- o1 = c.maskOpvldvst(p, o1)
- o1 |= uint32(r&31) << 5
- case 85: /* vaddv/vuaddlv Vn.<T>, Vd*/
- af := int((p.From.Reg >> 5) & 15)
- o1 = c.oprrr(p, p.As)
- rf := int((p.From.Reg) & 31)
- rt := int((p.To.Reg) & 31)
- Q := 0
- size := 0
- switch af {
- case ARNG_8B:
- Q = 0
- size = 0
- case ARNG_16B:
- Q = 1
- size = 0
- case ARNG_4H:
- Q = 0
- size = 1
- case ARNG_8H:
- Q = 1
- size = 1
- case ARNG_4S:
- Q = 1
- size = 2
- default:
- c.ctxt.Diag("invalid arrangement: %v\n", p)
- }
- o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31)
- case 86: /* vmovi $imm8, Vd.<T>*/
- at := int((p.To.Reg >> 5) & 15)
- r := int(p.From.Offset)
- if r > 255 || r < 0 {
- c.ctxt.Diag("immediate constant out of range: %v\n", p)
- }
- rt := int((p.To.Reg) & 31)
- Q := 0
- switch at {
- case ARNG_8B:
- Q = 0
- case ARNG_16B:
- Q = 1
- default:
- c.ctxt.Diag("invalid arrangement: %v\n", p)
- }
- o1 = 0xf<<24 | 0xe<<12 | 1<<10
- o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31)
- case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */
- o1 = ADR(1, 0, REGTMP)
- o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
- rel := obj.Addrel(c.cursym)
- rel.Off = int32(c.pc)
- rel.Siz = 8
- rel.Sym = p.To.Sym
- rel.Add = p.To.Offset
- rel.Type = objabi.R_ADDRARM64
- o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
- case 88: /* ldp addr(SB), (r,r) -> adrp + add + ldp */
- o1 = ADR(1, 0, REGTMP)
- o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
- rel := obj.Addrel(c.cursym)
- rel.Off = int32(c.pc)
- rel.Siz = 8
- rel.Sym = p.From.Sym
- rel.Add = p.From.Offset
- rel.Type = objabi.R_ADDRARM64
- o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
- case 89: /* vadd/vsub Vm, Vn, Vd */
- switch p.As {
- case AVADD:
- o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
- case AVSUB:
- o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
- default:
- c.ctxt.Diag("bad opcode: %v\n", p)
- break
- }
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- r := int(p.Reg)
- if r == 0 {
- r = rt
- }
- o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
- // This is supposed to be something that stops execution.
- // It's not supposed to be reached, ever, but if it is, we'd
- // like to be able to tell how we got there. Assemble as
- // 0xbea71700 which is guaranteed to raise undefined instruction
- // exception.
- case 90:
- o1 = 0xbea71700
- case 91: /* prfm imm(Rn), <prfop | $imm5> */
- imm := uint32(p.From.Offset)
- r := p.From.Reg
- v := uint32(0xff)
- if p.To.Type == obj.TYPE_CONST {
- v = uint32(p.To.Offset)
- if v > 31 {
- c.ctxt.Diag("illegal prefetch operation\n%v", p)
- }
- } else {
- for i := 0; i < len(prfopfield); i++ {
- if prfopfield[i].reg == p.To.Reg {
- v = prfopfield[i].enc
- break
- }
- }
- if v == 0xff {
- c.ctxt.Diag("illegal prefetch operation:\n%v", p)
- }
- }
- o1 = c.opldrpp(p, p.As)
- o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31))
- case 92: /* vmov Vn.<T>[index], Vd.<T>[index] */
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- imm4 := 0
- imm5 := 0
- o1 = 3<<29 | 7<<25 | 1<<10
- index1 := int(p.To.Index)
- index2 := int(p.From.Index)
- if ((p.To.Reg >> 5) & 15) != ((p.From.Reg >> 5) & 15) {
- c.ctxt.Diag("operand mismatch: %v", p)
- }
- switch (p.To.Reg >> 5) & 15 {
- case ARNG_B:
- c.checkindex(p, index1, 15)
- c.checkindex(p, index2, 15)
- imm5 |= 1
- imm5 |= index1 << 1
- imm4 |= index2
- case ARNG_H:
- c.checkindex(p, index1, 7)
- c.checkindex(p, index2, 7)
- imm5 |= 2
- imm5 |= index1 << 2
- imm4 |= index2 << 1
- case ARNG_S:
- c.checkindex(p, index1, 3)
- c.checkindex(p, index2, 3)
- imm5 |= 4
- imm5 |= index1 << 3
- imm4 |= index2 << 2
- case ARNG_D:
- c.checkindex(p, index1, 1)
- c.checkindex(p, index2, 1)
- imm5 |= 8
- imm5 |= index1 << 4
- imm4 |= index2 << 3
- default:
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- o1 |= (uint32(imm5&0x1f) << 16) | (uint32(imm4&0xf) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
- case 93: /* vpmull{2} Vm.<T>, Vn.<T>, Vd */
- af := int((p.From.Reg >> 5) & 15)
- at := int((p.To.Reg >> 5) & 15)
- a := int((p.Reg >> 5) & 15)
- var Q, size uint32
- if p.As == AVPMULL {
- Q = 0
- } else {
- Q = 1
- }
- var fArng int
- switch at {
- case ARNG_8H:
- if Q == 0 {
- fArng = ARNG_8B
- } else {
- fArng = ARNG_16B
- }
- size = 0
- case ARNG_1Q:
- if Q == 0 {
- fArng = ARNG_1D
- } else {
- fArng = ARNG_2D
- }
- size = 3
- default:
- c.ctxt.Diag("invalid arrangement on Vd.<T>: %v", p)
- }
- if af != a || af != fArng {
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- o1 = c.oprrr(p, p.As)
- rf := int((p.From.Reg) & 31)
- rt := int((p.To.Reg) & 31)
- r := int((p.Reg) & 31)
- o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
- case 94: /* vext $imm4, Vm.<T>, Vn.<T>, Vd.<T> */
- af := int(((p.GetFrom3().Reg) >> 5) & 15)
- at := int((p.To.Reg >> 5) & 15)
- a := int((p.Reg >> 5) & 15)
- index := int(p.From.Offset)
- if af != a || af != at {
- c.ctxt.Diag("invalid arrangement: %v", p)
- break
- }
- var Q uint32
- var b int
- if af == ARNG_8B {
- Q = 0
- b = 7
- } else if af == ARNG_16B {
- Q = 1
- b = 15
- } else {
- c.ctxt.Diag("invalid arrangement, should be B8 or B16: %v", p)
- break
- }
- if index < 0 || index > b {
- c.ctxt.Diag("illegal offset: %v", p)
- }
- o1 = c.opirr(p, p.As)
- rf := int((p.GetFrom3().Reg) & 31)
- rt := int((p.To.Reg) & 31)
- r := int((p.Reg) & 31)
- o1 |= ((Q & 1) << 30) | (uint32(r&31) << 16) | (uint32(index&15) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
- case 95: /* vushr $shift, Vn.<T>, Vd.<T> */
- at := int((p.To.Reg >> 5) & 15)
- af := int((p.Reg >> 5) & 15)
- shift := int(p.From.Offset)
- if af != at {
- c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
- }
- var Q uint32
- var imax, esize int
- switch af {
- case ARNG_8B, ARNG_4H, ARNG_2S:
- Q = 0
- case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D:
- Q = 1
- default:
- c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
- }
- switch af {
- case ARNG_8B, ARNG_16B:
- imax = 15
- esize = 8
- case ARNG_4H, ARNG_8H:
- imax = 31
- esize = 16
- case ARNG_2S, ARNG_4S:
- imax = 63
- esize = 32
- case ARNG_2D:
- imax = 127
- esize = 64
- }
- imm := 0
- switch p.As {
- case AVUSHR, AVSRI:
- imm = esize*2 - shift
- if imm < esize || imm > imax {
- c.ctxt.Diag("shift out of range: %v", p)
- }
- case AVSHL:
- imm = esize + shift
- if imm > imax {
- c.ctxt.Diag("shift out of range: %v", p)
- }
- default:
- c.ctxt.Diag("invalid instruction %v\n", p)
- }
- o1 = c.opirr(p, p.As)
- rt := int((p.To.Reg) & 31)
- rf := int((p.Reg) & 31)
- o1 |= ((Q & 1) << 30) | (uint32(imm&127) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
- case 96: /* vst1 Vt1.<T>[index], offset(Rn) */
- af := int((p.From.Reg >> 5) & 15)
- rt := int((p.From.Reg) & 31)
- rf := int((p.To.Reg) & 31)
- r := int(p.To.Index & 31)
- index := int(p.From.Index)
- offset := int32(c.regoff(&p.To))
- if o.scond == C_XPOST {
- if (p.To.Index != 0) && (offset != 0) {
- c.ctxt.Diag("invalid offset: %v", p)
- }
- if p.To.Index == 0 && offset == 0 {
- c.ctxt.Diag("invalid offset: %v", p)
- }
- }
- if offset != 0 {
- r = 31
- }
- var Q, S, size int
- var opcode uint32
- switch af {
- case ARNG_B:
- c.checkindex(p, index, 15)
- if o.scond == C_XPOST && offset != 0 && offset != 1 {
- c.ctxt.Diag("invalid offset: %v", p)
- }
- Q = index >> 3
- S = (index >> 2) & 1
- size = index & 3
- opcode = 0
- case ARNG_H:
- c.checkindex(p, index, 7)
- if o.scond == C_XPOST && offset != 0 && offset != 2 {
- c.ctxt.Diag("invalid offset: %v", p)
- }
- Q = index >> 2
- S = (index >> 1) & 1
- size = (index & 1) << 1
- opcode = 2
- case ARNG_S:
- c.checkindex(p, index, 3)
- if o.scond == C_XPOST && offset != 0 && offset != 4 {
- c.ctxt.Diag("invalid offset: %v", p)
- }
- Q = index >> 1
- S = index & 1
- size = 0
- opcode = 4
- case ARNG_D:
- c.checkindex(p, index, 1)
- if o.scond == C_XPOST && offset != 0 && offset != 8 {
- c.ctxt.Diag("invalid offset: %v", p)
- }
- Q = index
- S = 0
- size = 1
- opcode = 4
- default:
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- if o.scond == C_XPOST {
- o1 |= 27 << 23
- } else {
- o1 |= 26 << 23
- }
- o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
- case 97: /* vld1 offset(Rn), vt.<T>[index] */
- at := int((p.To.Reg >> 5) & 15)
- rt := int((p.To.Reg) & 31)
- rf := int((p.From.Reg) & 31)
- r := int(p.From.Index & 31)
- index := int(p.To.Index)
- offset := int32(c.regoff(&p.From))
- if o.scond == C_XPOST {
- if (p.From.Index != 0) && (offset != 0) {
- c.ctxt.Diag("invalid offset: %v", p)
- }
- if p.From.Index == 0 && offset == 0 {
- c.ctxt.Diag("invalid offset: %v", p)
- }
- }
- if offset != 0 {
- r = 31
- }
- Q := 0
- S := 0
- size := 0
- var opcode uint32
- switch at {
- case ARNG_B:
- c.checkindex(p, index, 15)
- if o.scond == C_XPOST && offset != 0 && offset != 1 {
- c.ctxt.Diag("invalid offset: %v", p)
- }
- Q = index >> 3
- S = (index >> 2) & 1
- size = index & 3
- opcode = 0
- case ARNG_H:
- c.checkindex(p, index, 7)
- if o.scond == C_XPOST && offset != 0 && offset != 2 {
- c.ctxt.Diag("invalid offset: %v", p)
- }
- Q = index >> 2
- S = (index >> 1) & 1
- size = (index & 1) << 1
- opcode = 2
- case ARNG_S:
- c.checkindex(p, index, 3)
- if o.scond == C_XPOST && offset != 0 && offset != 4 {
- c.ctxt.Diag("invalid offset: %v", p)
- }
- Q = index >> 1
- S = index & 1
- size = 0
- opcode = 4
- case ARNG_D:
- c.checkindex(p, index, 1)
- if o.scond == C_XPOST && offset != 0 && offset != 8 {
- c.ctxt.Diag("invalid offset: %v", p)
- }
- Q = index
- S = 0
- size = 1
- opcode = 4
- default:
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- if o.scond == C_XPOST {
- o1 |= 110 << 21
- } else {
- o1 |= 106 << 21
- }
- o1 |= (uint32(Q&1) << 30) | (uint32(r&31) << 16) | ((opcode & 7) << 13) | (uint32(S&1) << 12) | (uint32(size&3) << 10) | (uint32(rf&31) << 5) | uint32(rt&31)
- case 98: /* MOVD (Rn)(Rm.SXTW[<<amount]),Rd */
- if isRegShiftOrExt(&p.From) {
- // extended or shifted offset register.
- c.checkShiftAmount(p, &p.From)
- o1 = c.opldrr(p, p.As, true)
- o1 |= c.encRegShiftOrExt(&p.From, p.From.Index) /* includes reg, op, etc */
- } else {
- // (Rn)(Rm), no extension or shift.
- o1 = c.opldrr(p, p.As, false)
- o1 |= uint32(p.From.Index&31) << 16
- }
- o1 |= uint32(p.From.Reg&31) << 5
- rt := int(p.To.Reg)
- o1 |= uint32(rt & 31)
- case 99: /* MOVD Rt, (Rn)(Rm.SXTW[<<amount]) */
- if isRegShiftOrExt(&p.To) {
- // extended or shifted offset register.
- c.checkShiftAmount(p, &p.To)
- o1 = c.opstrr(p, p.As, true)
- o1 |= c.encRegShiftOrExt(&p.To, p.To.Index) /* includes reg, op, etc */
- } else {
- // (Rn)(Rm), no extension or shift.
- o1 = c.opstrr(p, p.As, false)
- o1 |= uint32(p.To.Index&31) << 16
- }
- o1 |= uint32(p.To.Reg&31) << 5
- rf := int(p.From.Reg)
- o1 |= uint32(rf & 31)
- case 100: /* VTBL Vn.<T>, [Vt1.<T>, Vt2.<T>, ...], Vd.<T> */
- af := int((p.From.Reg >> 5) & 15)
- at := int((p.To.Reg >> 5) & 15)
- if af != at {
- c.ctxt.Diag("invalid arrangement: %v\n", p)
- }
- var q, len uint32
- switch af {
- case ARNG_8B:
- q = 0
- case ARNG_16B:
- q = 1
- default:
- c.ctxt.Diag("invalid arrangement: %v", p)
- }
- rf := int(p.From.Reg)
- rt := int(p.To.Reg)
- offset := int(p.GetFrom3().Offset)
- opcode := (offset >> 12) & 15
- switch opcode {
- case 0x7:
- len = 0 // one register
- case 0xa:
- len = 1 // two register
- case 0x6:
- len = 2 // three registers
- case 0x2:
- len = 3 // four registers
- default:
- c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
- }
- o1 = q<<30 | 0xe<<24 | len<<13
- o1 |= (uint32(rf&31) << 16) | uint32(offset&31)<<5 | uint32(rt&31)
- case 101: // FOMVQ/FMOVD $vcon, Vd -> load from constant pool.
- o1 = c.omovlit(p.As, p, &p.From, int(p.To.Reg))
- case 102: /* vushll, vushll2, vuxtl, vuxtl2 */
- o1 = c.opirr(p, p.As)
- rf := p.Reg
- af := uint8((p.Reg >> 5) & 15)
- at := uint8((p.To.Reg >> 5) & 15)
- shift := int(p.From.Offset)
- if p.As == AVUXTL || p.As == AVUXTL2 {
- rf = p.From.Reg
- af = uint8((p.From.Reg >> 5) & 15)
- shift = 0
- }
- pack := func(q, x, y uint8) uint32 {
- return uint32(q)<<16 | uint32(x)<<8 | uint32(y)
- }
- var Q uint8 = uint8(o1>>30) & 1
- var immh, width uint8
- switch pack(Q, af, at) {
- case pack(0, ARNG_8B, ARNG_8H):
- immh, width = 1, 8
- case pack(1, ARNG_16B, ARNG_8H):
- immh, width = 1, 8
- case pack(0, ARNG_4H, ARNG_4S):
- immh, width = 2, 16
- case pack(1, ARNG_8H, ARNG_4S):
- immh, width = 2, 16
- case pack(0, ARNG_2S, ARNG_2D):
- immh, width = 4, 32
- case pack(1, ARNG_4S, ARNG_2D):
- immh, width = 4, 32
- default:
- c.ctxt.Diag("operand mismatch: %v\n", p)
- }
- if !(0 <= shift && shift <= int(width-1)) {
- c.ctxt.Diag("shift amount out of range: %v\n", p)
- }
- o1 |= uint32(immh)<<19 | uint32(shift)<<16 | uint32(rf&31)<<5 | uint32(p.To.Reg&31)
- }
- out[0] = o1
- out[1] = o2
- out[2] = o3
- out[3] = o4
- out[4] = o5
- }
- /*
- * basic Rm op Rn -> Rd (using shifted register with 0)
- * also op Rn -> Rt
- * also Rm*Rn op Ra -> Rd
- * also Vm op Vn -> Vd
- */
- func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 {
- switch a {
- case AADC:
- return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
- case AADCW:
- return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
- case AADCS:
- return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
- case AADCSW:
- return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
- case ANGC, ASBC:
- return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
- case ANGCS, ASBCS:
- return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
- case ANGCW, ASBCW:
- return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
- case ANGCSW, ASBCSW:
- return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
- case AADD:
- return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
- case AADDW:
- return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
- case ACMN, AADDS:
- return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
- case ACMNW, AADDSW:
- return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
- case ASUB:
- return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
- case ASUBW:
- return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
- case ACMP, ASUBS:
- return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
- case ACMPW, ASUBSW:
- return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
- case AAND:
- return S64 | 0<<29 | 0xA<<24
- case AANDW:
- return S32 | 0<<29 | 0xA<<24
- case AMOVD, AORR:
- return S64 | 1<<29 | 0xA<<24
- // case AMOVW:
- case AMOVWU, AORRW:
- return S32 | 1<<29 | 0xA<<24
- case AEOR:
- return S64 | 2<<29 | 0xA<<24
- case AEORW:
- return S32 | 2<<29 | 0xA<<24
- case AANDS, ATST:
- return S64 | 3<<29 | 0xA<<24
- case AANDSW, ATSTW:
- return S32 | 3<<29 | 0xA<<24
- case ABIC:
- return S64 | 0<<29 | 0xA<<24 | 1<<21
- case ABICW:
- return S32 | 0<<29 | 0xA<<24 | 1<<21
- case ABICS:
- return S64 | 3<<29 | 0xA<<24 | 1<<21
- case ABICSW:
- return S32 | 3<<29 | 0xA<<24 | 1<<21
- case AEON:
- return S64 | 2<<29 | 0xA<<24 | 1<<21
- case AEONW:
- return S32 | 2<<29 | 0xA<<24 | 1<<21
- case AMVN, AORN:
- return S64 | 1<<29 | 0xA<<24 | 1<<21
- case AMVNW, AORNW:
- return S32 | 1<<29 | 0xA<<24 | 1<<21
- case AASR:
- return S64 | OPDP2(10) /* also ASRV */
- case AASRW:
- return S32 | OPDP2(10)
- case ALSL:
- return S64 | OPDP2(8)
- case ALSLW:
- return S32 | OPDP2(8)
- case ALSR:
- return S64 | OPDP2(9)
- case ALSRW:
- return S32 | OPDP2(9)
- case AROR:
- return S64 | OPDP2(11)
- case ARORW:
- return S32 | OPDP2(11)
- case ACCMN:
- return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */
- case ACCMNW:
- return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
- case ACCMP:
- return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
- case ACCMPW:
- return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
- case ACRC32B:
- return S32 | OPDP2(16)
- case ACRC32H:
- return S32 | OPDP2(17)
- case ACRC32W:
- return S32 | OPDP2(18)
- case ACRC32X:
- return S64 | OPDP2(19)
- case ACRC32CB:
- return S32 | OPDP2(20)
- case ACRC32CH:
- return S32 | OPDP2(21)
- case ACRC32CW:
- return S32 | OPDP2(22)
- case ACRC32CX:
- return S64 | OPDP2(23)
- case ACSEL:
- return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
- case ACSELW:
- return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
- case ACSET:
- return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
- case ACSETW:
- return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
- case ACSETM:
- return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
- case ACSETMW:
- return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
- case ACINC, ACSINC:
- return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
- case ACINCW, ACSINCW:
- return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
- case ACINV, ACSINV:
- return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
- case ACINVW, ACSINVW:
- return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
- case ACNEG, ACSNEG:
- return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
- case ACNEGW, ACSNEGW:
- return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
- case AMUL, AMADD:
- return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
- case AMULW, AMADDW:
- return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
- case AMNEG, AMSUB:
- return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
- case AMNEGW, AMSUBW:
- return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
- case AMRS:
- return SYSOP(1, 2, 0, 0, 0, 0, 0)
- case AMSR:
- return SYSOP(0, 2, 0, 0, 0, 0, 0)
- case ANEG:
- return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
- case ANEGW:
- return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
- case ANEGS:
- return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
- case ANEGSW:
- return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
- case AREM, ASDIV:
- return S64 | OPDP2(3)
- case AREMW, ASDIVW:
- return S32 | OPDP2(3)
- case ASMULL, ASMADDL:
- return OPDP3(1, 0, 1, 0)
- case ASMNEGL, ASMSUBL:
- return OPDP3(1, 0, 1, 1)
- case ASMULH:
- return OPDP3(1, 0, 2, 0)
- case AUMULL, AUMADDL:
- return OPDP3(1, 0, 5, 0)
- case AUMNEGL, AUMSUBL:
- return OPDP3(1, 0, 5, 1)
- case AUMULH:
- return OPDP3(1, 0, 6, 0)
- case AUREM, AUDIV:
- return S64 | OPDP2(2)
- case AUREMW, AUDIVW:
- return S32 | OPDP2(2)
- case AAESE:
- return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10
- case AAESD:
- return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10
- case AAESMC:
- return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10
- case AAESIMC:
- return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10
- case ASHA1C:
- return 0x5E<<24 | 0<<12
- case ASHA1P:
- return 0x5E<<24 | 1<<12
- case ASHA1M:
- return 0x5E<<24 | 2<<12
- case ASHA1SU0:
- return 0x5E<<24 | 3<<12
- case ASHA256H:
- return 0x5E<<24 | 4<<12
- case ASHA256H2:
- return 0x5E<<24 | 5<<12
- case ASHA256SU1:
- return 0x5E<<24 | 6<<12
- case ASHA1H:
- return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10
- case ASHA1SU1:
- return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10
- case ASHA256SU0:
- return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10
- case ASHA512H:
- return 0xCE<<24 | 3<<21 | 8<<12
- case ASHA512H2:
- return 0xCE<<24 | 3<<21 | 8<<12 | 4<<8
- case ASHA512SU1:
- return 0xCE<<24 | 3<<21 | 8<<12 | 8<<8
- case ASHA512SU0:
- return 0xCE<<24 | 3<<22 | 8<<12
- case AFCVTZSD:
- return FPCVTI(1, 0, 1, 3, 0)
- case AFCVTZSDW:
- return FPCVTI(0, 0, 1, 3, 0)
- case AFCVTZSS:
- return FPCVTI(1, 0, 0, 3, 0)
- case AFCVTZSSW:
- return FPCVTI(0, 0, 0, 3, 0)
- case AFCVTZUD:
- return FPCVTI(1, 0, 1, 3, 1)
- case AFCVTZUDW:
- return FPCVTI(0, 0, 1, 3, 1)
- case AFCVTZUS:
- return FPCVTI(1, 0, 0, 3, 1)
- case AFCVTZUSW:
- return FPCVTI(0, 0, 0, 3, 1)
- case ASCVTFD:
- return FPCVTI(1, 0, 1, 0, 2)
- case ASCVTFS:
- return FPCVTI(1, 0, 0, 0, 2)
- case ASCVTFWD:
- return FPCVTI(0, 0, 1, 0, 2)
- case ASCVTFWS:
- return FPCVTI(0, 0, 0, 0, 2)
- case AUCVTFD:
- return FPCVTI(1, 0, 1, 0, 3)
- case AUCVTFS:
- return FPCVTI(1, 0, 0, 0, 3)
- case AUCVTFWD:
- return FPCVTI(0, 0, 1, 0, 3)
- case AUCVTFWS:
- return FPCVTI(0, 0, 0, 0, 3)
- case AFADDS:
- return FPOP2S(0, 0, 0, 2)
- case AFADDD:
- return FPOP2S(0, 0, 1, 2)
- case AFSUBS:
- return FPOP2S(0, 0, 0, 3)
- case AFSUBD:
- return FPOP2S(0, 0, 1, 3)
- case AFMADDD:
- return FPOP3S(0, 0, 1, 0, 0)
- case AFMADDS:
- return FPOP3S(0, 0, 0, 0, 0)
- case AFMSUBD:
- return FPOP3S(0, 0, 1, 0, 1)
- case AFMSUBS:
- return FPOP3S(0, 0, 0, 0, 1)
- case AFNMADDD:
- return FPOP3S(0, 0, 1, 1, 0)
- case AFNMADDS:
- return FPOP3S(0, 0, 0, 1, 0)
- case AFNMSUBD:
- return FPOP3S(0, 0, 1, 1, 1)
- case AFNMSUBS:
- return FPOP3S(0, 0, 0, 1, 1)
- case AFMULS:
- return FPOP2S(0, 0, 0, 0)
- case AFMULD:
- return FPOP2S(0, 0, 1, 0)
- case AFDIVS:
- return FPOP2S(0, 0, 0, 1)
- case AFDIVD:
- return FPOP2S(0, 0, 1, 1)
- case AFMAXS:
- return FPOP2S(0, 0, 0, 4)
- case AFMINS:
- return FPOP2S(0, 0, 0, 5)
- case AFMAXD:
- return FPOP2S(0, 0, 1, 4)
- case AFMIND:
- return FPOP2S(0, 0, 1, 5)
- case AFMAXNMS:
- return FPOP2S(0, 0, 0, 6)
- case AFMAXNMD:
- return FPOP2S(0, 0, 1, 6)
- case AFMINNMS:
- return FPOP2S(0, 0, 0, 7)
- case AFMINNMD:
- return FPOP2S(0, 0, 1, 7)
- case AFNMULS:
- return FPOP2S(0, 0, 0, 8)
- case AFNMULD:
- return FPOP2S(0, 0, 1, 8)
- case AFCMPS:
- return FPCMP(0, 0, 0, 0, 0)
- case AFCMPD:
- return FPCMP(0, 0, 1, 0, 0)
- case AFCMPES:
- return FPCMP(0, 0, 0, 0, 16)
- case AFCMPED:
- return FPCMP(0, 0, 1, 0, 16)
- case AFCCMPS:
- return FPCCMP(0, 0, 0, 0)
- case AFCCMPD:
- return FPCCMP(0, 0, 1, 0)
- case AFCCMPES:
- return FPCCMP(0, 0, 0, 1)
- case AFCCMPED:
- return FPCCMP(0, 0, 1, 1)
- case AFCSELS:
- return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10
- case AFCSELD:
- return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10
- case AFMOVS:
- return FPOP1S(0, 0, 0, 0)
- case AFABSS:
- return FPOP1S(0, 0, 0, 1)
- case AFNEGS:
- return FPOP1S(0, 0, 0, 2)
- case AFSQRTS:
- return FPOP1S(0, 0, 0, 3)
- case AFCVTSD:
- return FPOP1S(0, 0, 0, 5)
- case AFCVTSH:
- return FPOP1S(0, 0, 0, 7)
- case AFRINTNS:
- return FPOP1S(0, 0, 0, 8)
- case AFRINTPS:
- return FPOP1S(0, 0, 0, 9)
- case AFRINTMS:
- return FPOP1S(0, 0, 0, 10)
- case AFRINTZS:
- return FPOP1S(0, 0, 0, 11)
- case AFRINTAS:
- return FPOP1S(0, 0, 0, 12)
- case AFRINTXS:
- return FPOP1S(0, 0, 0, 14)
- case AFRINTIS:
- return FPOP1S(0, 0, 0, 15)
- case AFMOVD:
- return FPOP1S(0, 0, 1, 0)
- case AFABSD:
- return FPOP1S(0, 0, 1, 1)
- case AFNEGD:
- return FPOP1S(0, 0, 1, 2)
- case AFSQRTD:
- return FPOP1S(0, 0, 1, 3)
- case AFCVTDS:
- return FPOP1S(0, 0, 1, 4)
- case AFCVTDH:
- return FPOP1S(0, 0, 1, 7)
- case AFRINTND:
- return FPOP1S(0, 0, 1, 8)
- case AFRINTPD:
- return FPOP1S(0, 0, 1, 9)
- case AFRINTMD:
- return FPOP1S(0, 0, 1, 10)
- case AFRINTZD:
- return FPOP1S(0, 0, 1, 11)
- case AFRINTAD:
- return FPOP1S(0, 0, 1, 12)
- case AFRINTXD:
- return FPOP1S(0, 0, 1, 14)
- case AFRINTID:
- return FPOP1S(0, 0, 1, 15)
- case AFCVTHS:
- return FPOP1S(0, 0, 3, 4)
- case AFCVTHD:
- return FPOP1S(0, 0, 3, 5)
- case AVADD:
- return 7<<25 | 1<<21 | 1<<15 | 1<<10
- case AVSUB:
- return 0x17<<25 | 1<<21 | 1<<15 | 1<<10
- case AVADDP:
- return 7<<25 | 1<<21 | 1<<15 | 15<<10
- case AVAND:
- return 7<<25 | 1<<21 | 7<<10
- case AVCMEQ:
- return 1<<29 | 0x71<<21 | 0x23<<10
- case AVCNT:
- return 0xE<<24 | 0x10<<17 | 5<<12 | 2<<10
- case AVZIP1:
- return 0xE<<24 | 3<<12 | 2<<10
- case AVZIP2:
- return 0xE<<24 | 1<<14 | 3<<12 | 2<<10
- case AVEOR:
- return 1<<29 | 0x71<<21 | 7<<10
- case AVORR:
- return 7<<25 | 5<<21 | 7<<10
- case AVREV16:
- return 3<<26 | 2<<24 | 1<<21 | 3<<11
- case AVREV32:
- return 11<<26 | 2<<24 | 1<<21 | 1<<11
- case AVREV64:
- return 3<<26 | 2<<24 | 1<<21 | 1<<11
- case AVMOV:
- return 7<<25 | 5<<21 | 7<<10
- case AVADDV:
- return 7<<25 | 3<<20 | 3<<15 | 7<<11
- case AVUADDLV:
- return 1<<29 | 7<<25 | 3<<20 | 7<<11
- case AVFMLA:
- return 7<<25 | 0<<23 | 1<<21 | 3<<14 | 3<<10
- case AVFMLS:
- return 7<<25 | 1<<23 | 1<<21 | 3<<14 | 3<<10
- case AVPMULL, AVPMULL2:
- return 0xE<<24 | 1<<21 | 0x38<<10
- case AVRBIT:
- return 0x2E<<24 | 1<<22 | 0x10<<17 | 5<<12 | 2<<10
- case AVLD1, AVLD2, AVLD3, AVLD4:
- return 3<<26 | 1<<22
- case AVLD1R, AVLD3R:
- return 0xD<<24 | 1<<22
- case AVLD2R, AVLD4R:
- return 0xD<<24 | 3<<21
- case AVBIF:
- return 1<<29 | 7<<25 | 7<<21 | 7<<10
- case AVBIT:
- return 1<<29 | 0x75<<21 | 7<<10
- case AVBSL:
- return 1<<29 | 0x73<<21 | 7<<10
- case AVCMTST:
- return 0xE<<24 | 1<<21 | 0x23<<10
- case AVUZP1:
- return 7<<25 | 3<<11
- case AVUZP2:
- return 7<<25 | 1<<14 | 3<<11
- }
- c.ctxt.Diag("%v: bad rrr %d %v", p, a, a)
- return 0
- }
- /*
- * imm -> Rd
- * imm op Rn -> Rd
- */
- func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 {
- switch a {
- /* op $addcon, Rn, Rd */
- case AMOVD, AADD:
- return S64 | 0<<30 | 0<<29 | 0x11<<24
- case ACMN, AADDS:
- return S64 | 0<<30 | 1<<29 | 0x11<<24
- case AMOVW, AADDW:
- return S32 | 0<<30 | 0<<29 | 0x11<<24
- case ACMNW, AADDSW:
- return S32 | 0<<30 | 1<<29 | 0x11<<24
- case ASUB:
- return S64 | 1<<30 | 0<<29 | 0x11<<24
- case ACMP, ASUBS:
- return S64 | 1<<30 | 1<<29 | 0x11<<24
- case ASUBW:
- return S32 | 1<<30 | 0<<29 | 0x11<<24
- case ACMPW, ASUBSW:
- return S32 | 1<<30 | 1<<29 | 0x11<<24
- /* op $imm(SB), Rd; op label, Rd */
- case AADR:
- return 0<<31 | 0x10<<24
- case AADRP:
- return 1<<31 | 0x10<<24
- /* op $bimm, Rn, Rd */
- case AAND, ABIC:
- return S64 | 0<<29 | 0x24<<23
- case AANDW, ABICW:
- return S32 | 0<<29 | 0x24<<23 | 0<<22
- case AORR, AORN:
- return S64 | 1<<29 | 0x24<<23
- case AORRW, AORNW:
- return S32 | 1<<29 | 0x24<<23 | 0<<22
- case AEOR, AEON:
- return S64 | 2<<29 | 0x24<<23
- case AEORW, AEONW:
- return S32 | 2<<29 | 0x24<<23 | 0<<22
- case AANDS, ABICS, ATST:
- return S64 | 3<<29 | 0x24<<23
- case AANDSW, ABICSW, ATSTW:
- return S32 | 3<<29 | 0x24<<23 | 0<<22
- case AASR:
- return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */
- case AASRW:
- return S32 | 0<<29 | 0x26<<23 | 0<<22
- /* op $width, $lsb, Rn, Rd */
- case ABFI:
- return S64 | 2<<29 | 0x26<<23 | 1<<22
- /* alias of BFM */
- case ABFIW:
- return S32 | 2<<29 | 0x26<<23 | 0<<22
- /* op $imms, $immr, Rn, Rd */
- case ABFM:
- return S64 | 1<<29 | 0x26<<23 | 1<<22
- case ABFMW:
- return S32 | 1<<29 | 0x26<<23 | 0<<22
- case ASBFM:
- return S64 | 0<<29 | 0x26<<23 | 1<<22
- case ASBFMW:
- return S32 | 0<<29 | 0x26<<23 | 0<<22
- case AUBFM:
- return S64 | 2<<29 | 0x26<<23 | 1<<22
- case AUBFMW:
- return S32 | 2<<29 | 0x26<<23 | 0<<22
- case ABFXIL:
- return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */
- case ABFXILW:
- return S32 | 1<<29 | 0x26<<23 | 0<<22
- case AEXTR:
- return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21
- case AEXTRW:
- return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21
- case ACBNZ:
- return S64 | 0x1A<<25 | 1<<24
- case ACBNZW:
- return S32 | 0x1A<<25 | 1<<24
- case ACBZ:
- return S64 | 0x1A<<25 | 0<<24
- case ACBZW:
- return S32 | 0x1A<<25 | 0<<24
- case ACCMN:
- return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
- case ACCMNW:
- return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
- case ACCMP:
- return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
- case ACCMPW:
- return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
- case AMOVK:
- return S64 | 3<<29 | 0x25<<23
- case AMOVKW:
- return S32 | 3<<29 | 0x25<<23
- case AMOVN:
- return S64 | 0<<29 | 0x25<<23
- case AMOVNW:
- return S32 | 0<<29 | 0x25<<23
- case AMOVZ:
- return S64 | 2<<29 | 0x25<<23
- case AMOVZW:
- return S32 | 2<<29 | 0x25<<23
- case AMSR:
- return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */
- case AAT,
- ADC,
- AIC,
- ATLBI,
- ASYS:
- return SYSOP(0, 1, 0, 0, 0, 0, 0)
- case ASYSL:
- return SYSOP(1, 1, 0, 0, 0, 0, 0)
- case ATBZ:
- return 0x36 << 24
- case ATBNZ:
- return 0x37 << 24
- case ADSB:
- return SYSOP(0, 0, 3, 3, 0, 4, 0x1F)
- case ADMB:
- return SYSOP(0, 0, 3, 3, 0, 5, 0x1F)
- case AISB:
- return SYSOP(0, 0, 3, 3, 0, 6, 0x1F)
- case AHINT:
- return SYSOP(0, 0, 3, 2, 0, 0, 0x1F)
- case AVEXT:
- return 0x2E<<24 | 0<<23 | 0<<21 | 0<<15
- case AVUSHR:
- return 0x5E<<23 | 1<<10
- case AVSHL:
- return 0x1E<<23 | 21<<10
- case AVSRI:
- return 0x5E<<23 | 17<<10
- case AVUSHLL, AVUXTL:
- return 1<<29 | 15<<24 | 0x29<<10
- case AVUSHLL2, AVUXTL2:
- return 3<<29 | 15<<24 | 0x29<<10
- }
- c.ctxt.Diag("%v: bad irr %v", p, a)
- return 0
- }
- func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 {
- switch a {
- case ACLS:
- return S64 | OPBIT(5)
- case ACLSW:
- return S32 | OPBIT(5)
- case ACLZ:
- return S64 | OPBIT(4)
- case ACLZW:
- return S32 | OPBIT(4)
- case ARBIT:
- return S64 | OPBIT(0)
- case ARBITW:
- return S32 | OPBIT(0)
- case AREV:
- return S64 | OPBIT(3)
- case AREVW:
- return S32 | OPBIT(2)
- case AREV16:
- return S64 | OPBIT(1)
- case AREV16W:
- return S32 | OPBIT(1)
- case AREV32:
- return S64 | OPBIT(2)
- default:
- c.ctxt.Diag("bad bit op\n%v", p)
- return 0
- }
- }
- /*
- * add/subtract sign or zero-extended register
- */
- func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, extend bool) uint32 {
- extension := uint32(0)
- if !extend {
- switch a {
- case AADD, ACMN, AADDS, ASUB, ACMP, ASUBS:
- extension = LSL0_64
- case AADDW, ACMNW, AADDSW, ASUBW, ACMPW, ASUBSW:
- extension = LSL0_32
- }
- }
- switch a {
- case AADD:
- return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
- case AADDW:
- return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
- case ACMN, AADDS:
- return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
- case ACMNW, AADDSW:
- return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
- case ASUB:
- return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
- case ASUBW:
- return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
- case ACMP, ASUBS:
- return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
- case ACMPW, ASUBSW:
- return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
- }
- c.ctxt.Diag("bad opxrrr %v\n%v", a, p)
- return 0
- }
- func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 {
- switch a {
- case ASVC:
- return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */
- case AHVC:
- return 0xD4<<24 | 0<<21 | 2
- case ASMC:
- return 0xD4<<24 | 0<<21 | 3
- case ABRK:
- return 0xD4<<24 | 1<<21 | 0
- case AHLT:
- return 0xD4<<24 | 2<<21 | 0
- case ADCPS1:
- return 0xD4<<24 | 5<<21 | 1
- case ADCPS2:
- return 0xD4<<24 | 5<<21 | 2
- case ADCPS3:
- return 0xD4<<24 | 5<<21 | 3
- case ACLREX:
- return SYSOP(0, 0, 3, 3, 0, 2, 0x1F)
- }
- c.ctxt.Diag("%v: bad imm %v", p, a)
- return 0
- }
- func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 {
- v := int64(0)
- t := int64(0)
- q := p.To.Target()
- if q == nil {
- // TODO: don't use brdist for this case, as it isn't a branch.
- // (Calls from omovlit, and maybe adr/adrp opcodes as well.)
- q = p.Pool
- }
- if q != nil {
- v = (q.Pc >> uint(preshift)) - (c.pc >> uint(preshift))
- if (v & ((1 << uint(shift)) - 1)) != 0 {
- c.ctxt.Diag("misaligned label\n%v", p)
- }
- v >>= uint(shift)
- t = int64(1) << uint(flen-1)
- if v < -t || v >= t {
- c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, q)
- panic("branch too far")
- }
- }
- return v & ((t << 1) - 1)
- }
- /*
- * pc-relative branches
- */
- func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 {
- switch a {
- case ABEQ:
- return OPBcc(0x0)
- case ABNE:
- return OPBcc(0x1)
- case ABCS:
- return OPBcc(0x2)
- case ABHS:
- return OPBcc(0x2)
- case ABCC:
- return OPBcc(0x3)
- case ABLO:
- return OPBcc(0x3)
- case ABMI:
- return OPBcc(0x4)
- case ABPL:
- return OPBcc(0x5)
- case ABVS:
- return OPBcc(0x6)
- case ABVC:
- return OPBcc(0x7)
- case ABHI:
- return OPBcc(0x8)
- case ABLS:
- return OPBcc(0x9)
- case ABGE:
- return OPBcc(0xa)
- case ABLT:
- return OPBcc(0xb)
- case ABGT:
- return OPBcc(0xc)
- case ABLE:
- return OPBcc(0xd) /* imm19<<5 | cond */
- case AB:
- return 0<<31 | 5<<26 /* imm26 */
- case obj.ADUFFZERO, obj.ADUFFCOPY, ABL:
- return 1<<31 | 5<<26
- }
- c.ctxt.Diag("%v: bad bra %v", p, a)
- return 0
- }
- func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 {
- switch a {
- case ABL:
- return OPBLR(1) /* BLR */
- case AB:
- return OPBLR(0) /* BR */
- case obj.ARET:
- return OPBLR(2) /* RET */
- }
- c.ctxt.Diag("%v: bad brr %v", p, a)
- return 0
- }
- func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 {
- switch a {
- case ADRPS:
- return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5
- case AERET:
- return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5
- case ANOOP:
- return SYSHINT(0)
- case AYIELD:
- return SYSHINT(1)
- case AWFE:
- return SYSHINT(2)
- case AWFI:
- return SYSHINT(3)
- case ASEV:
- return SYSHINT(4)
- case ASEVL:
- return SYSHINT(5)
- }
- c.ctxt.Diag("%v: bad op0 %v", p, a)
- return 0
- }
- /*
- * register offset
- */
- func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 {
- switch a {
- case ALDAR:
- return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10
- case ALDARW:
- return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10
- case ALDARB:
- return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10
- case ALDARH:
- return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10
- case ALDAXP:
- return LDSTX(3, 0, 1, 1, 1)
- case ALDAXPW:
- return LDSTX(2, 0, 1, 1, 1)
- case ALDAXR:
- return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10
- case ALDAXRW:
- return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10
- case ALDAXRB:
- return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10
- case ALDAXRH:
- return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10
- case ALDXR:
- return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10
- case ALDXRB:
- return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10
- case ALDXRH:
- return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10
- case ALDXRW:
- return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10
- case ALDXP:
- return LDSTX(3, 0, 1, 1, 0)
- case ALDXPW:
- return LDSTX(2, 0, 1, 1, 0)
- case AMOVNP:
- return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
- case AMOVNPW:
- return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
- }
- c.ctxt.Diag("bad opload %v\n%v", a, p)
- return 0
- }
- func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 {
- switch a {
- case ASTLR:
- return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10
- case ASTLRB:
- return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10
- case ASTLRH:
- return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10
- case ASTLP:
- return LDSTX(3, 0, 0, 1, 1)
- case ASTLPW:
- return LDSTX(2, 0, 0, 1, 1)
- case ASTLRW:
- return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10
- case ASTLXP:
- return LDSTX(3, 0, 0, 1, 1)
- case ASTLXPW:
- return LDSTX(2, 0, 0, 1, 1)
- case ASTLXR:
- return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10
- case ASTLXRB:
- return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10
- case ASTLXRH:
- return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10
- case ASTLXRW:
- return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10
- case ASTXR:
- return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10
- case ASTXRB:
- return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10
- case ASTXRH:
- return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10
- case ASTXP:
- return LDSTX(3, 0, 0, 1, 0)
- case ASTXPW:
- return LDSTX(2, 0, 0, 1, 0)
- case ASTXRW:
- return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10
- case AMOVNP:
- return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
- case AMOVNPW:
- return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
- }
- c.ctxt.Diag("bad opstore %v\n%v", a, p)
- return 0
- }
- /*
- * load/store register (unsigned immediate) C3.3.13
- * these produce 64-bit values (when there's an option)
- */
- func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
- if v < 0 || v >= (1<<12) {
- c.ctxt.Diag("offset out of range: %d\n%v", v, p)
- }
- o |= (v & 0xFFF) << 10
- o |= int32(b&31) << 5
- o |= int32(r & 31)
- return uint32(o)
- }
- func (c *ctxt7) opldr12(p *obj.Prog, a obj.As) uint32 {
- switch a {
- case AMOVD:
- return LDSTR12U(3, 0, 1) /* imm12<<10 | Rn<<5 | Rt */
- case AMOVW:
- return LDSTR12U(2, 0, 2)
- case AMOVWU:
- return LDSTR12U(2, 0, 1)
- case AMOVH:
- return LDSTR12U(1, 0, 2)
- case AMOVHU:
- return LDSTR12U(1, 0, 1)
- case AMOVB:
- return LDSTR12U(0, 0, 2)
- case AMOVBU:
- return LDSTR12U(0, 0, 1)
- case AFMOVS:
- return LDSTR12U(2, 1, 1)
- case AFMOVD:
- return LDSTR12U(3, 1, 1)
- }
- c.ctxt.Diag("bad opldr12 %v\n%v", a, p)
- return 0
- }
- func (c *ctxt7) opstr12(p *obj.Prog, a obj.As) uint32 {
- return LD2STR(c.opldr12(p, a))
- }
- /*
- * load/store register (unscaled immediate) C3.3.12
- */
- func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
- if v < -256 || v > 255 {
- c.ctxt.Diag("offset out of range: %d\n%v", v, p)
- }
- o |= (v & 0x1FF) << 12
- o |= int32(b&31) << 5
- o |= int32(r & 31)
- return uint32(o)
- }
- func (c *ctxt7) opldr9(p *obj.Prog, a obj.As) uint32 {
- switch a {
- case AMOVD:
- return LDSTR9S(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */
- case AMOVW:
- return LDSTR9S(2, 0, 2)
- case AMOVWU:
- return LDSTR9S(2, 0, 1)
- case AMOVH:
- return LDSTR9S(1, 0, 2)
- case AMOVHU:
- return LDSTR9S(1, 0, 1)
- case AMOVB:
- return LDSTR9S(0, 0, 2)
- case AMOVBU:
- return LDSTR9S(0, 0, 1)
- case AFMOVS:
- return LDSTR9S(2, 1, 1)
- case AFMOVD:
- return LDSTR9S(3, 1, 1)
- }
- c.ctxt.Diag("bad opldr9 %v\n%v", a, p)
- return 0
- }
- func (c *ctxt7) opstr9(p *obj.Prog, a obj.As) uint32 {
- return LD2STR(c.opldr9(p, a))
- }
- func (c *ctxt7) opldrpp(p *obj.Prog, a obj.As) uint32 {
- switch a {
- case AMOVD:
- return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 /* simm9<<12 | Rn<<5 | Rt */
- case AMOVW:
- return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
- case AMOVWU:
- return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
- case AMOVH:
- return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
- case AMOVHU:
- return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
- case AMOVB:
- return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
- case AMOVBU:
- return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
- case AFMOVS:
- return 2<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22
- case AFMOVD:
- return 3<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22
- case APRFM:
- return 0xf9<<24 | 2<<22
- }
- c.ctxt.Diag("bad opldr %v\n%v", a, p)
- return 0
- }
- // olsxrr attaches register operands to a load/store opcode supplied in o.
- // The result either encodes a load of r from (r1+r2) or a store of r to (r1+r2).
- func (c *ctxt7) olsxrr(p *obj.Prog, o int32, r int, r1 int, r2 int) uint32 {
- o |= int32(r1&31) << 5
- o |= int32(r2&31) << 16
- o |= int32(r & 31)
- return uint32(o)
- }
- // opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
- // for load instruction with register offset.
- // The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
- func (c *ctxt7) opldrr(p *obj.Prog, a obj.As, extension bool) uint32 {
- OptionS := uint32(0x1a)
- if extension {
- OptionS = uint32(0) // option value and S value have been encoded into p.From.Offset.
- }
- switch a {
- case AMOVD:
- return OptionS<<10 | 0x3<<21 | 0x1f<<27
- case AMOVW:
- return OptionS<<10 | 0x5<<21 | 0x17<<27
- case AMOVWU:
- return OptionS<<10 | 0x3<<21 | 0x17<<27
- case AMOVH:
- return OptionS<<10 | 0x5<<21 | 0x0f<<27
- case AMOVHU:
- return OptionS<<10 | 0x3<<21 | 0x0f<<27
- case AMOVB:
- return OptionS<<10 | 0x5<<21 | 0x07<<27
- case AMOVBU:
- return OptionS<<10 | 0x3<<21 | 0x07<<27
- case AFMOVS:
- return OptionS<<10 | 0x3<<21 | 0x17<<27 | 1<<26
- case AFMOVD:
- return OptionS<<10 | 0x3<<21 | 0x1f<<27 | 1<<26
- }
- c.ctxt.Diag("bad opldrr %v\n%v", a, p)
- return 0
- }
- // opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
- // for store instruction with register offset.
- // The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
- func (c *ctxt7) opstrr(p *obj.Prog, a obj.As, extension bool) uint32 {
- OptionS := uint32(0x1a)
- if extension {
- OptionS = uint32(0) // option value and S value have been encoded into p.To.Offset.
- }
- switch a {
- case AMOVD:
- return OptionS<<10 | 0x1<<21 | 0x1f<<27
- case AMOVW, AMOVWU:
- return OptionS<<10 | 0x1<<21 | 0x17<<27
- case AMOVH, AMOVHU:
- return OptionS<<10 | 0x1<<21 | 0x0f<<27
- case AMOVB, AMOVBU:
- return OptionS<<10 | 0x1<<21 | 0x07<<27
- case AFMOVS:
- return OptionS<<10 | 0x1<<21 | 0x17<<27 | 1<<26
- case AFMOVD:
- return OptionS<<10 | 0x1<<21 | 0x1f<<27 | 1<<26
- }
- c.ctxt.Diag("bad opstrr %v\n%v", a, p)
- return 0
- }
- func (c *ctxt7) oaddi(p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 {
- if (v & 0xFFF000) != 0 {
- if v&0xFFF != 0 {
- c.ctxt.Diag("%v misuses oaddi", p)
- }
- v >>= 12
- o1 |= 1 << 22
- }
- o1 |= ((v & 0xFFF) << 10) | (int32(r&31) << 5) | int32(rt&31)
- return uint32(o1)
- }
- /*
- * load a literal value into dr
- */
- func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 {
- var o1 int32
- if p.Pool == nil { /* not in literal pool */
- c.aclass(a)
- c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset))
- /* TODO: could be clever, and use general constant builder */
- o1 = int32(c.opirr(p, AADD))
- v := int32(c.instoffset)
- if v != 0 && (v&0xFFF) == 0 {
- v >>= 12
- o1 |= 1 << 22 /* shift, by 12 */
- }
- o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31)
- } else {
- fp, w := 0, 0
- switch as {
- case AFMOVS:
- fp = 1
- w = 0 /* 32-bit SIMD/FP */
- case AFMOVD:
- fp = 1
- w = 1 /* 64-bit SIMD/FP */
- case AFMOVQ:
- fp = 1
- w = 2 /* 128-bit SIMD/FP */
- case AMOVD:
- if p.Pool.As == ADWORD {
- w = 1 /* 64-bit */
- } else if p.Pool.To.Offset < 0 {
- w = 2 /* 32-bit, sign-extended to 64-bit */
- } else if p.Pool.To.Offset >= 0 {
- w = 0 /* 32-bit, zero-extended to 64-bit */
- } else {
- c.ctxt.Diag("invalid operand %v in %v", a, p)
- }
- case AMOVBU, AMOVHU, AMOVWU:
- w = 0 /* 32-bit, zero-extended to 64-bit */
- case AMOVB, AMOVH, AMOVW:
- w = 2 /* 32-bit, sign-extended to 64-bit */
- default:
- c.ctxt.Diag("invalid operation %v in %v", as, p)
- }
- v := int32(c.brdist(p, 0, 19, 2))
- o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27)
- o1 |= (v & 0x7FFFF) << 5
- o1 |= int32(dr & 31)
- }
- return uint32(o1)
- }
- // load a constant (MOVCON or BITCON) in a into rt
- func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) {
- if cls := oclass(a); cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0 {
- // or $bitcon, REGZERO, rt
- mode := 64
- var as1 obj.As
- switch as {
- case AMOVW:
- as1 = AORRW
- mode = 32
- case AMOVD:
- as1 = AORR
- }
- o1 = c.opirr(p, as1)
- o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31)
- return o1
- }
- if as == AMOVW {
- d := uint32(a.Offset)
- s := movcon(int64(d))
- if s < 0 || 16*s >= 32 {
- d = ^d
- s = movcon(int64(d))
- if s < 0 || 16*s >= 32 {
- c.ctxt.Diag("impossible 32-bit move wide: %#x\n%v", uint32(a.Offset), p)
- }
- o1 = c.opirr(p, AMOVNW)
- } else {
- o1 = c.opirr(p, AMOVZW)
- }
- o1 |= MOVCONST(int64(d), s, rt)
- }
- if as == AMOVD {
- d := a.Offset
- s := movcon(d)
- if s < 0 || 16*s >= 64 {
- d = ^d
- s = movcon(d)
- if s < 0 || 16*s >= 64 {
- c.ctxt.Diag("impossible 64-bit move wide: %#x\n%v", uint64(a.Offset), p)
- }
- o1 = c.opirr(p, AMOVN)
- } else {
- o1 = c.opirr(p, AMOVZ)
- }
- o1 |= MOVCONST(d, s, rt)
- }
- return o1
- }
- // load a 32-bit/64-bit large constant (LCON or VCON) in a.Offset into rt
- // put the instruction sequence in os and return the number of instructions.
- func (c *ctxt7) omovlconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int, os []uint32) (num uint8) {
- switch as {
- case AMOVW:
- d := uint32(a.Offset)
- // use MOVZW and MOVKW to load a constant to rt
- os[0] = c.opirr(p, AMOVZW)
- os[0] |= MOVCONST(int64(d), 0, rt)
- os[1] = c.opirr(p, AMOVKW)
- os[1] |= MOVCONST(int64(d), 1, rt)
- return 2
- case AMOVD:
- d := a.Offset
- dn := ^d
- var immh [4]uint64
- var i int
- zeroCount := int(0)
- negCount := int(0)
- for i = 0; i < 4; i++ {
- immh[i] = uint64((d >> uint(i*16)) & 0xffff)
- if immh[i] == 0 {
- zeroCount++
- } else if immh[i] == 0xffff {
- negCount++
- }
- }
- if zeroCount == 4 || negCount == 4 {
- c.ctxt.Diag("the immediate should be MOVCON: %v", p)
- }
- switch {
- case zeroCount == 3:
- // one MOVZ
- for i = 0; i < 4; i++ {
- if immh[i] != 0 {
- os[0] = c.opirr(p, AMOVZ)
- os[0] |= MOVCONST(d, i, rt)
- break
- }
- }
- return 1
- case negCount == 3:
- // one MOVN
- for i = 0; i < 4; i++ {
- if immh[i] != 0xffff {
- os[0] = c.opirr(p, AMOVN)
- os[0] |= MOVCONST(dn, i, rt)
- break
- }
- }
- return 1
- case zeroCount == 2:
- // one MOVZ and one MOVK
- for i = 0; i < 4; i++ {
- if immh[i] != 0 {
- os[0] = c.opirr(p, AMOVZ)
- os[0] |= MOVCONST(d, i, rt)
- i++
- break
- }
- }
- for ; i < 4; i++ {
- if immh[i] != 0 {
- os[1] = c.opirr(p, AMOVK)
- os[1] |= MOVCONST(d, i, rt)
- }
- }
- return 2
- case negCount == 2:
- // one MOVN and one MOVK
- for i = 0; i < 4; i++ {
- if immh[i] != 0xffff {
- os[0] = c.opirr(p, AMOVN)
- os[0] |= MOVCONST(dn, i, rt)
- i++
- break
- }
- }
- for ; i < 4; i++ {
- if immh[i] != 0xffff {
- os[1] = c.opirr(p, AMOVK)
- os[1] |= MOVCONST(d, i, rt)
- }
- }
- return 2
- case zeroCount == 1:
- // one MOVZ and two MOVKs
- for i = 0; i < 4; i++ {
- if immh[i] != 0 {
- os[0] = c.opirr(p, AMOVZ)
- os[0] |= MOVCONST(d, i, rt)
- i++
- break
- }
- }
- for j := 1; i < 4; i++ {
- if immh[i] != 0 {
- os[j] = c.opirr(p, AMOVK)
- os[j] |= MOVCONST(d, i, rt)
- j++
- }
- }
- return 3
- case negCount == 1:
- // one MOVN and two MOVKs
- for i = 0; i < 4; i++ {
- if immh[i] != 0xffff {
- os[0] = c.opirr(p, AMOVN)
- os[0] |= MOVCONST(dn, i, rt)
- i++
- break
- }
- }
- for j := 1; i < 4; i++ {
- if immh[i] != 0xffff {
- os[j] = c.opirr(p, AMOVK)
- os[j] |= MOVCONST(d, i, rt)
- j++
- }
- }
- return 3
- default:
- // one MOVZ and 3 MOVKs
- os[0] = c.opirr(p, AMOVZ)
- os[0] |= MOVCONST(d, 0, rt)
- for i = 1; i < 4; i++ {
- os[i] = c.opirr(p, AMOVK)
- os[i] |= MOVCONST(d, i, rt)
- }
- return 4
- }
- default:
- return 0
- }
- }
- func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 {
- var b uint32
- o := c.opirr(p, a)
- if (o & (1 << 31)) == 0 {
- b = 32
- } else {
- b = 64
- }
- if r < 0 || uint32(r) >= b {
- c.ctxt.Diag("illegal bit number\n%v", p)
- }
- o |= (uint32(r) & 0x3F) << 16
- if s < 0 || uint32(s) >= b {
- c.ctxt.Diag("illegal bit number\n%v", p)
- }
- o |= (uint32(s) & 0x3F) << 10
- o |= (uint32(rf&31) << 5) | uint32(rt&31)
- return o
- }
- func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 {
- var b uint32
- o := c.opirr(p, a)
- if (o & (1 << 31)) != 0 {
- b = 63
- } else {
- b = 31
- }
- if v < 0 || uint32(v) > b {
- c.ctxt.Diag("illegal bit number\n%v", p)
- }
- o |= uint32(v) << 10
- o |= uint32(rn&31) << 5
- o |= uint32(rm&31) << 16
- o |= uint32(rt & 31)
- return o
- }
- /* genrate instruction encoding for LDP/LDPW/LDPSW/STP/STPW */
- func (c *ctxt7) opldpstp(p *obj.Prog, o *Optab, vo int32, rbase, rl, rh, ldp uint32) uint32 {
- wback := false
- if o.scond == C_XPOST || o.scond == C_XPRE {
- wback = true
- }
- switch p.As {
- case ALDP, ALDPW, ALDPSW:
- c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset))
- case ASTP, ASTPW:
- if wback == true {
- c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset))
- }
- case AFLDPD, AFLDPS:
- c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset))
- }
- var ret uint32
- // check offset
- switch p.As {
- case AFLDPD, AFSTPD:
- if vo < -512 || vo > 504 || vo%8 != 0 {
- c.ctxt.Diag("invalid offset %v\n", p)
- }
- vo /= 8
- ret = 1<<30 | 1<<26
- case ALDP, ASTP:
- if vo < -512 || vo > 504 || vo%8 != 0 {
- c.ctxt.Diag("invalid offset %v\n", p)
- }
- vo /= 8
- ret = 2 << 30
- case AFLDPS, AFSTPS:
- if vo < -256 || vo > 252 || vo%4 != 0 {
- c.ctxt.Diag("invalid offset %v\n", p)
- }
- vo /= 4
- ret = 1 << 26
- case ALDPW, ASTPW:
- if vo < -256 || vo > 252 || vo%4 != 0 {
- c.ctxt.Diag("invalid offset %v\n", p)
- }
- vo /= 4
- ret = 0
- case ALDPSW:
- if vo < -256 || vo > 252 || vo%4 != 0 {
- c.ctxt.Diag("invalid offset %v\n", p)
- }
- vo /= 4
- ret = 1 << 30
- default:
- c.ctxt.Diag("invalid instruction %v\n", p)
- }
- // check register pair
- switch p.As {
- case AFLDPD, AFLDPS, AFSTPD, AFSTPS:
- if rl < REG_F0 || REG_F31 < rl || rh < REG_F0 || REG_F31 < rh {
- c.ctxt.Diag("invalid register pair %v\n", p)
- }
- case ALDP, ALDPW, ALDPSW:
- if rl < REG_R0 || REG_R30 < rl || rh < REG_R0 || REG_R30 < rh {
- c.ctxt.Diag("invalid register pair %v\n", p)
- }
- case ASTP, ASTPW:
- if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh {
- c.ctxt.Diag("invalid register pair %v\n", p)
- }
- }
- // other conditional flag bits
- switch o.scond {
- case C_XPOST:
- ret |= 1 << 23
- case C_XPRE:
- ret |= 3 << 23
- default:
- ret |= 2 << 23
- }
- ret |= 5<<27 | (ldp&1)<<22 | uint32(vo&0x7f)<<15 | (rh&31)<<10 | (rbase&31)<<5 | (rl & 31)
- return ret
- }
- func (c *ctxt7) maskOpvldvst(p *obj.Prog, o1 uint32) uint32 {
- if p.As == AVLD1 || p.As == AVST1 {
- return o1
- }
- o1 &^= 0xf000 // mask out "opcode" field (bit 12-15)
- switch p.As {
- case AVLD1R, AVLD2R:
- o1 |= 0xC << 12
- case AVLD3R, AVLD4R:
- o1 |= 0xE << 12
- case AVLD2, AVST2:
- o1 |= 8 << 12
- case AVLD3, AVST3:
- o1 |= 4 << 12
- case AVLD4, AVST4:
- default:
- c.ctxt.Diag("unsupported instruction:%v\n", p.As)
- }
- return o1
- }
- /*
- * size in log2(bytes)
- */
- func movesize(a obj.As) int {
- switch a {
- case AMOVD:
- return 3
- case AMOVW, AMOVWU:
- return 2
- case AMOVH, AMOVHU:
- return 1
- case AMOVB, AMOVBU:
- return 0
- case AFMOVS:
- return 2
- case AFMOVD:
- return 3
- default:
- return -1
- }
- }
- // rm is the Rm register value, o is the extension, amount is the left shift value.
- func roff(rm int16, o uint32, amount int16) uint32 {
- return uint32(rm&31)<<16 | o<<13 | uint32(amount)<<10
- }
- // encRegShiftOrExt returns the encoding of shifted/extended register, Rx<<n and Rx.UXTW<<n, etc.
- func (c *ctxt7) encRegShiftOrExt(a *obj.Addr, r int16) uint32 {
- var num, rm int16
- num = (r >> 5) & 7
- rm = r & 31
- switch {
- case REG_UXTB <= r && r < REG_UXTH:
- return roff(rm, 0, num)
- case REG_UXTH <= r && r < REG_UXTW:
- return roff(rm, 1, num)
- case REG_UXTW <= r && r < REG_UXTX:
- if a.Type == obj.TYPE_MEM {
- if num == 0 {
- return roff(rm, 2, 2)
- } else {
- return roff(rm, 2, 6)
- }
- } else {
- return roff(rm, 2, num)
- }
- case REG_UXTX <= r && r < REG_SXTB:
- return roff(rm, 3, num)
- case REG_SXTB <= r && r < REG_SXTH:
- return roff(rm, 4, num)
- case REG_SXTH <= r && r < REG_SXTW:
- return roff(rm, 5, num)
- case REG_SXTW <= r && r < REG_SXTX:
- if a.Type == obj.TYPE_MEM {
- if num == 0 {
- return roff(rm, 6, 2)
- } else {
- return roff(rm, 6, 6)
- }
- } else {
- return roff(rm, 6, num)
- }
- case REG_SXTX <= r && r < REG_SPECIAL:
- if a.Type == obj.TYPE_MEM {
- if num == 0 {
- return roff(rm, 7, 2)
- } else {
- return roff(rm, 7, 6)
- }
- } else {
- return roff(rm, 7, num)
- }
- case REG_LSL <= r && r < (REG_LSL+1<<8):
- return roff(rm, 3, 6)
- default:
- c.ctxt.Diag("unsupported register extension type.")
- }
- return 0
- }
|