asm7.go 173 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708670967106711671267136714671567166717671867196720672167226723672467256726672767286729673067316732673367346735673667376738673967406741674267436744674567466747674867496750675167526753675467556756675767586759676067616762676367646765676667676768676967706771677267736774677567766777677867796780678167826783678467856786678767886789679067916792679367946795679667976798679968006801680268036804680568066807680868096810681168126813681468156816681768186819682068216822682368246825682668276828682968306831683268336834683568366837683868396840684168426843684468456846684768486849685068516852685368546855685668576858685968606861686268636864686568666867686868696870687168726873687468756876687768786879688068816882688368846885688668876888688968906891689268936894689568966897689868996900690169026903690469056906690769086909691069116912691369146915691669176918691969206921692269236924692569266927692869296930693169326933693469356936693769386939694069416942694369446945694669476948694969506951695269536954695569566957695869596960696169626963696469656966696769686969697069716972697369746975697669776978697969806981698269836984698569866987698869896990699169926993699469956996699769986999700070017002700370047005700670077008700970107011701270137014701570167017701870197020702170227023702470257026702770287029703070317032703370347035703670377038703970407041704270437044704570467047704870497050705170527053705470557056705770587059706070617062706370647065706670677068706970707071707270737074707570767077707870797080708170827083708470857086708770887089709070917092709370947095709670977098709971007101710271037104710571067107710871097110711171127113711471157116711771187119712071217122712371247125712671277128712971307131713271337134713571367137713871397140
  1. // 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.
  2. // https://code.google.com/p/ken-cc/source/browse/
  3. //
  4. // Copyright © 1994-1999 Lucent Technologies Inc. All rights reserved.
  5. // Portions Copyright © 1995-1997 C H Forsyth (forsyth@terzarima.net)
  6. // Portions Copyright © 1997-1999 Vita Nuova Limited
  7. // Portions Copyright © 2000-2007 Vita Nuova Holdings Limited (www.vitanuova.com)
  8. // Portions Copyright © 2004,2006 Bruce Ellis
  9. // Portions Copyright © 2005-2007 C H Forsyth (forsyth@terzarima.net)
  10. // Revisions Copyright © 2000-2007 Lucent Technologies Inc. and others
  11. // Portions Copyright © 2009 The Go Authors. All rights reserved.
  12. //
  13. // Permission is hereby granted, free of charge, to any person obtaining a copy
  14. // of this software and associated documentation files (the "Software"), to deal
  15. // in the Software without restriction, including without limitation the rights
  16. // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  17. // copies of the Software, and to permit persons to whom the Software is
  18. // furnished to do so, subject to the following conditions:
  19. //
  20. // The above copyright notice and this permission notice shall be included in
  21. // all copies or substantial portions of the Software.
  22. //
  23. // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  24. // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  25. // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  26. // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  27. // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  28. // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  29. // THE SOFTWARE.
  30. package arm64
  31. import (
  32. "github.com/twitchyliquid64/golang-asm/obj"
  33. "github.com/twitchyliquid64/golang-asm/objabi"
  34. "fmt"
  35. "log"
  36. "math"
  37. "sort"
  38. )
  39. // ctxt7 holds state while assembling a single function.
  40. // Each function gets a fresh ctxt7.
  41. // This allows for multiple functions to be safely concurrently assembled.
  42. type ctxt7 struct {
  43. ctxt *obj.Link
  44. newprog obj.ProgAlloc
  45. cursym *obj.LSym
  46. blitrl *obj.Prog
  47. elitrl *obj.Prog
  48. autosize int32
  49. extrasize int32
  50. instoffset int64
  51. pc int64
  52. pool struct {
  53. start uint32
  54. size uint32
  55. }
  56. }
  57. const (
  58. funcAlign = 16
  59. )
  60. const (
  61. REGFROM = 1
  62. )
  63. type Optab struct {
  64. as obj.As
  65. a1 uint8
  66. a2 uint8
  67. a3 uint8
  68. a4 uint8
  69. type_ int8
  70. size int8
  71. param int16
  72. flag int8
  73. scond uint16
  74. }
  75. func IsAtomicInstruction(as obj.As) bool {
  76. _, ok := atomicInstructions[as]
  77. return ok
  78. }
  79. // known field values of an instruction.
  80. var atomicInstructions = map[obj.As]uint32{
  81. ALDADDAD: 3<<30 | 0x1c5<<21 | 0x00<<10,
  82. ALDADDAW: 2<<30 | 0x1c5<<21 | 0x00<<10,
  83. ALDADDAH: 1<<30 | 0x1c5<<21 | 0x00<<10,
  84. ALDADDAB: 0<<30 | 0x1c5<<21 | 0x00<<10,
  85. ALDADDALD: 3<<30 | 0x1c7<<21 | 0x00<<10,
  86. ALDADDALW: 2<<30 | 0x1c7<<21 | 0x00<<10,
  87. ALDADDALH: 1<<30 | 0x1c7<<21 | 0x00<<10,
  88. ALDADDALB: 0<<30 | 0x1c7<<21 | 0x00<<10,
  89. ALDADDD: 3<<30 | 0x1c1<<21 | 0x00<<10,
  90. ALDADDW: 2<<30 | 0x1c1<<21 | 0x00<<10,
  91. ALDADDH: 1<<30 | 0x1c1<<21 | 0x00<<10,
  92. ALDADDB: 0<<30 | 0x1c1<<21 | 0x00<<10,
  93. ALDADDLD: 3<<30 | 0x1c3<<21 | 0x00<<10,
  94. ALDADDLW: 2<<30 | 0x1c3<<21 | 0x00<<10,
  95. ALDADDLH: 1<<30 | 0x1c3<<21 | 0x00<<10,
  96. ALDADDLB: 0<<30 | 0x1c3<<21 | 0x00<<10,
  97. ALDANDAD: 3<<30 | 0x1c5<<21 | 0x04<<10,
  98. ALDANDAW: 2<<30 | 0x1c5<<21 | 0x04<<10,
  99. ALDANDAH: 1<<30 | 0x1c5<<21 | 0x04<<10,
  100. ALDANDAB: 0<<30 | 0x1c5<<21 | 0x04<<10,
  101. ALDANDALD: 3<<30 | 0x1c7<<21 | 0x04<<10,
  102. ALDANDALW: 2<<30 | 0x1c7<<21 | 0x04<<10,
  103. ALDANDALH: 1<<30 | 0x1c7<<21 | 0x04<<10,
  104. ALDANDALB: 0<<30 | 0x1c7<<21 | 0x04<<10,
  105. ALDANDD: 3<<30 | 0x1c1<<21 | 0x04<<10,
  106. ALDANDW: 2<<30 | 0x1c1<<21 | 0x04<<10,
  107. ALDANDH: 1<<30 | 0x1c1<<21 | 0x04<<10,
  108. ALDANDB: 0<<30 | 0x1c1<<21 | 0x04<<10,
  109. ALDANDLD: 3<<30 | 0x1c3<<21 | 0x04<<10,
  110. ALDANDLW: 2<<30 | 0x1c3<<21 | 0x04<<10,
  111. ALDANDLH: 1<<30 | 0x1c3<<21 | 0x04<<10,
  112. ALDANDLB: 0<<30 | 0x1c3<<21 | 0x04<<10,
  113. ALDEORAD: 3<<30 | 0x1c5<<21 | 0x08<<10,
  114. ALDEORAW: 2<<30 | 0x1c5<<21 | 0x08<<10,
  115. ALDEORAH: 1<<30 | 0x1c5<<21 | 0x08<<10,
  116. ALDEORAB: 0<<30 | 0x1c5<<21 | 0x08<<10,
  117. ALDEORALD: 3<<30 | 0x1c7<<21 | 0x08<<10,
  118. ALDEORALW: 2<<30 | 0x1c7<<21 | 0x08<<10,
  119. ALDEORALH: 1<<30 | 0x1c7<<21 | 0x08<<10,
  120. ALDEORALB: 0<<30 | 0x1c7<<21 | 0x08<<10,
  121. ALDEORD: 3<<30 | 0x1c1<<21 | 0x08<<10,
  122. ALDEORW: 2<<30 | 0x1c1<<21 | 0x08<<10,
  123. ALDEORH: 1<<30 | 0x1c1<<21 | 0x08<<10,
  124. ALDEORB: 0<<30 | 0x1c1<<21 | 0x08<<10,
  125. ALDEORLD: 3<<30 | 0x1c3<<21 | 0x08<<10,
  126. ALDEORLW: 2<<30 | 0x1c3<<21 | 0x08<<10,
  127. ALDEORLH: 1<<30 | 0x1c3<<21 | 0x08<<10,
  128. ALDEORLB: 0<<30 | 0x1c3<<21 | 0x08<<10,
  129. ALDORAD: 3<<30 | 0x1c5<<21 | 0x0c<<10,
  130. ALDORAW: 2<<30 | 0x1c5<<21 | 0x0c<<10,
  131. ALDORAH: 1<<30 | 0x1c5<<21 | 0x0c<<10,
  132. ALDORAB: 0<<30 | 0x1c5<<21 | 0x0c<<10,
  133. ALDORALD: 3<<30 | 0x1c7<<21 | 0x0c<<10,
  134. ALDORALW: 2<<30 | 0x1c7<<21 | 0x0c<<10,
  135. ALDORALH: 1<<30 | 0x1c7<<21 | 0x0c<<10,
  136. ALDORALB: 0<<30 | 0x1c7<<21 | 0x0c<<10,
  137. ALDORD: 3<<30 | 0x1c1<<21 | 0x0c<<10,
  138. ALDORW: 2<<30 | 0x1c1<<21 | 0x0c<<10,
  139. ALDORH: 1<<30 | 0x1c1<<21 | 0x0c<<10,
  140. ALDORB: 0<<30 | 0x1c1<<21 | 0x0c<<10,
  141. ALDORLD: 3<<30 | 0x1c3<<21 | 0x0c<<10,
  142. ALDORLW: 2<<30 | 0x1c3<<21 | 0x0c<<10,
  143. ALDORLH: 1<<30 | 0x1c3<<21 | 0x0c<<10,
  144. ALDORLB: 0<<30 | 0x1c3<<21 | 0x0c<<10,
  145. ASWPAD: 3<<30 | 0x1c5<<21 | 0x20<<10,
  146. ASWPAW: 2<<30 | 0x1c5<<21 | 0x20<<10,
  147. ASWPAH: 1<<30 | 0x1c5<<21 | 0x20<<10,
  148. ASWPAB: 0<<30 | 0x1c5<<21 | 0x20<<10,
  149. ASWPALD: 3<<30 | 0x1c7<<21 | 0x20<<10,
  150. ASWPALW: 2<<30 | 0x1c7<<21 | 0x20<<10,
  151. ASWPALH: 1<<30 | 0x1c7<<21 | 0x20<<10,
  152. ASWPALB: 0<<30 | 0x1c7<<21 | 0x20<<10,
  153. ASWPD: 3<<30 | 0x1c1<<21 | 0x20<<10,
  154. ASWPW: 2<<30 | 0x1c1<<21 | 0x20<<10,
  155. ASWPH: 1<<30 | 0x1c1<<21 | 0x20<<10,
  156. ASWPB: 0<<30 | 0x1c1<<21 | 0x20<<10,
  157. ASWPLD: 3<<30 | 0x1c3<<21 | 0x20<<10,
  158. ASWPLW: 2<<30 | 0x1c3<<21 | 0x20<<10,
  159. ASWPLH: 1<<30 | 0x1c3<<21 | 0x20<<10,
  160. ASWPLB: 0<<30 | 0x1c3<<21 | 0x20<<10,
  161. }
  162. var oprange [ALAST & obj.AMask][]Optab
  163. var xcmp [C_NCLASS][C_NCLASS]bool
  164. const (
  165. S32 = 0 << 31
  166. S64 = 1 << 31
  167. Sbit = 1 << 29
  168. LSL0_32 = 2 << 13
  169. LSL0_64 = 3 << 13
  170. )
  171. func OPDP2(x uint32) uint32 {
  172. return 0<<30 | 0<<29 | 0xd6<<21 | x<<10
  173. }
  174. func OPDP3(sf uint32, op54 uint32, op31 uint32, o0 uint32) uint32 {
  175. return sf<<31 | op54<<29 | 0x1B<<24 | op31<<21 | o0<<15
  176. }
  177. func OPBcc(x uint32) uint32 {
  178. return 0x2A<<25 | 0<<24 | 0<<4 | x&15
  179. }
  180. func OPBLR(x uint32) uint32 {
  181. /* x=0, JMP; 1, CALL; 2, RET */
  182. return 0x6B<<25 | 0<<23 | x<<21 | 0x1F<<16 | 0<<10
  183. }
  184. func SYSOP(l uint32, op0 uint32, op1 uint32, crn uint32, crm uint32, op2 uint32, rt uint32) uint32 {
  185. return 0x354<<22 | l<<21 | op0<<19 | op1<<16 | crn&15<<12 | crm&15<<8 | op2<<5 | rt
  186. }
  187. func SYSHINT(x uint32) uint32 {
  188. return SYSOP(0, 0, 3, 2, 0, x, 0x1F)
  189. }
  190. func LDSTR12U(sz uint32, v uint32, opc uint32) uint32 {
  191. return sz<<30 | 7<<27 | v<<26 | 1<<24 | opc<<22
  192. }
  193. func LDSTR9S(sz uint32, v uint32, opc uint32) uint32 {
  194. return sz<<30 | 7<<27 | v<<26 | 0<<24 | opc<<22
  195. }
  196. func LD2STR(o uint32) uint32 {
  197. return o &^ (3 << 22)
  198. }
  199. func LDSTX(sz uint32, o2 uint32, l uint32, o1 uint32, o0 uint32) uint32 {
  200. return sz<<30 | 0x8<<24 | o2<<23 | l<<22 | o1<<21 | o0<<15
  201. }
  202. func FPCMP(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 {
  203. return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<14 | 8<<10 | op2
  204. }
  205. func FPCCMP(m uint32, s uint32, type_ uint32, op uint32) uint32 {
  206. return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | 1<<10 | op<<4
  207. }
  208. func FPOP1S(m uint32, s uint32, type_ uint32, op uint32) uint32 {
  209. return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<15 | 0x10<<10
  210. }
  211. func FPOP2S(m uint32, s uint32, type_ uint32, op uint32) uint32 {
  212. return m<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | op<<12 | 2<<10
  213. }
  214. func FPOP3S(m uint32, s uint32, type_ uint32, op uint32, op2 uint32) uint32 {
  215. return m<<31 | s<<29 | 0x1F<<24 | type_<<22 | op<<21 | op2<<15
  216. }
  217. func FPCVTI(sf uint32, s uint32, type_ uint32, rmode uint32, op uint32) uint32 {
  218. return sf<<31 | s<<29 | 0x1E<<24 | type_<<22 | 1<<21 | rmode<<19 | op<<16 | 0<<10
  219. }
  220. func ADR(p uint32, o uint32, rt uint32) uint32 {
  221. return p<<31 | (o&3)<<29 | 0x10<<24 | ((o>>2)&0x7FFFF)<<5 | rt&31
  222. }
  223. func OPBIT(x uint32) uint32 {
  224. return 1<<30 | 0<<29 | 0xD6<<21 | 0<<16 | x<<10
  225. }
  226. func MOVCONST(d int64, s int, rt int) uint32 {
  227. return uint32(((d>>uint(s*16))&0xFFFF)<<5) | uint32(s)&3<<21 | uint32(rt&31)
  228. }
  229. const (
  230. // Optab.flag
  231. LFROM = 1 << 0 // p.From uses constant pool
  232. LTO = 1 << 1 // p.To uses constant pool
  233. NOTUSETMP = 1 << 2 // p expands to multiple instructions, but does NOT use REGTMP
  234. )
  235. var optab = []Optab{
  236. /* struct Optab:
  237. OPCODE, from, prog->reg, from3, to, type,size,param,flag,scond */
  238. {obj.ATEXT, C_ADDR, C_NONE, C_NONE, C_TEXTSIZE, 0, 0, 0, 0, 0},
  239. /* arithmetic operations */
  240. {AADD, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
  241. {AADD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
  242. {AADC, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
  243. {AADC, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
  244. {ANEG, C_REG, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0},
  245. {ANEG, C_NONE, C_NONE, C_NONE, C_REG, 25, 4, 0, 0, 0},
  246. {ANGC, C_REG, C_NONE, C_NONE, C_REG, 17, 4, 0, 0, 0},
  247. {ACMP, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0},
  248. {AADD, C_ADDCON, C_RSP, C_NONE, C_RSP, 2, 4, 0, 0, 0},
  249. {AADD, C_ADDCON, C_NONE, C_NONE, C_RSP, 2, 4, 0, 0, 0},
  250. {ACMP, C_ADDCON, C_RSP, C_NONE, C_NONE, 2, 4, 0, 0, 0},
  251. {AADD, C_MOVCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0},
  252. {AADD, C_MOVCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0},
  253. {ACMP, C_MOVCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0},
  254. {AADD, C_BITCON, C_RSP, C_NONE, C_RSP, 62, 8, 0, 0, 0},
  255. {AADD, C_BITCON, C_NONE, C_NONE, C_RSP, 62, 8, 0, 0, 0},
  256. {ACMP, C_BITCON, C_RSP, C_NONE, C_NONE, 62, 8, 0, 0, 0},
  257. {AADD, C_ADDCON2, C_RSP, C_NONE, C_RSP, 48, 8, 0, NOTUSETMP, 0},
  258. {AADD, C_ADDCON2, C_NONE, C_NONE, C_RSP, 48, 8, 0, NOTUSETMP, 0},
  259. {AADD, C_MOVCON2, C_RSP, C_NONE, C_RSP, 13, 12, 0, 0, 0},
  260. {AADD, C_MOVCON2, C_NONE, C_NONE, C_RSP, 13, 12, 0, 0, 0},
  261. {AADD, C_MOVCON3, C_RSP, C_NONE, C_RSP, 13, 16, 0, 0, 0},
  262. {AADD, C_MOVCON3, C_NONE, C_NONE, C_RSP, 13, 16, 0, 0, 0},
  263. {AADD, C_VCON, C_RSP, C_NONE, C_RSP, 13, 20, 0, 0, 0},
  264. {AADD, C_VCON, C_NONE, C_NONE, C_RSP, 13, 20, 0, 0, 0},
  265. {ACMP, C_MOVCON2, C_REG, C_NONE, C_NONE, 13, 12, 0, 0, 0},
  266. {ACMP, C_MOVCON3, C_REG, C_NONE, C_NONE, 13, 16, 0, 0, 0},
  267. {ACMP, C_VCON, C_REG, C_NONE, C_NONE, 13, 20, 0, 0, 0},
  268. {AADD, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
  269. {AADD, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
  270. {AMVN, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
  271. {ACMP, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0},
  272. {ANEG, C_SHIFT, C_NONE, C_NONE, C_REG, 26, 4, 0, 0, 0},
  273. {AADD, C_REG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0},
  274. {AADD, C_REG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
  275. {ACMP, C_REG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0},
  276. {AADD, C_EXTREG, C_RSP, C_NONE, C_RSP, 27, 4, 0, 0, 0},
  277. {AADD, C_EXTREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
  278. {AMVN, C_EXTREG, C_NONE, C_NONE, C_RSP, 27, 4, 0, 0, 0},
  279. {ACMP, C_EXTREG, C_RSP, C_NONE, C_NONE, 27, 4, 0, 0, 0},
  280. {AADD, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
  281. {AADD, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
  282. {AMUL, C_REG, C_REG, C_NONE, C_REG, 15, 4, 0, 0, 0},
  283. {AMUL, C_REG, C_NONE, C_NONE, C_REG, 15, 4, 0, 0, 0},
  284. {AMADD, C_REG, C_REG, C_REG, C_REG, 15, 4, 0, 0, 0},
  285. {AREM, C_REG, C_REG, C_NONE, C_REG, 16, 8, 0, 0, 0},
  286. {AREM, C_REG, C_NONE, C_NONE, C_REG, 16, 8, 0, 0, 0},
  287. {ASDIV, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
  288. {ASDIV, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
  289. {AFADDS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
  290. {AFADDS, C_FREG, C_FREG, C_NONE, C_FREG, 54, 4, 0, 0, 0},
  291. {AFMSUBD, C_FREG, C_FREG, C_FREG, C_FREG, 15, 4, 0, 0, 0},
  292. {AFCMPS, C_FREG, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0},
  293. {AFCMPS, C_FCON, C_FREG, C_NONE, C_NONE, 56, 4, 0, 0, 0},
  294. {AVADDP, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
  295. {AVADD, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
  296. {AVADD, C_VREG, C_VREG, C_NONE, C_VREG, 89, 4, 0, 0, 0},
  297. {AVADD, C_VREG, C_NONE, C_NONE, C_VREG, 89, 4, 0, 0, 0},
  298. {AVADDV, C_ARNG, C_NONE, C_NONE, C_VREG, 85, 4, 0, 0, 0},
  299. /* logical operations */
  300. {AAND, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
  301. {AAND, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
  302. {AANDS, C_REG, C_REG, C_NONE, C_REG, 1, 4, 0, 0, 0},
  303. {AANDS, C_REG, C_NONE, C_NONE, C_REG, 1, 4, 0, 0, 0},
  304. {ATST, C_REG, C_REG, C_NONE, C_NONE, 1, 4, 0, 0, 0},
  305. {AAND, C_MBCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0},
  306. {AAND, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
  307. {AANDS, C_MBCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0},
  308. {AANDS, C_MBCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
  309. {ATST, C_MBCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0},
  310. {AAND, C_BITCON, C_REG, C_NONE, C_RSP, 53, 4, 0, 0, 0},
  311. {AAND, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
  312. {AANDS, C_BITCON, C_REG, C_NONE, C_REG, 53, 4, 0, 0, 0},
  313. {AANDS, C_BITCON, C_NONE, C_NONE, C_REG, 53, 4, 0, 0, 0},
  314. {ATST, C_BITCON, C_REG, C_NONE, C_NONE, 53, 4, 0, 0, 0},
  315. {AAND, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0},
  316. {AAND, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0},
  317. {AANDS, C_MOVCON, C_REG, C_NONE, C_REG, 62, 8, 0, 0, 0},
  318. {AANDS, C_MOVCON, C_NONE, C_NONE, C_REG, 62, 8, 0, 0, 0},
  319. {ATST, C_MOVCON, C_REG, C_NONE, C_NONE, 62, 8, 0, 0, 0},
  320. {AAND, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0},
  321. {AAND, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0},
  322. {AAND, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0},
  323. {AAND, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 0},
  324. {AAND, C_VCON, C_REG, C_NONE, C_REG, 28, 20, 0, 0, 0},
  325. {AAND, C_VCON, C_NONE, C_NONE, C_REG, 28, 20, 0, 0, 0},
  326. {AANDS, C_MOVCON2, C_REG, C_NONE, C_REG, 28, 12, 0, 0, 0},
  327. {AANDS, C_MOVCON2, C_NONE, C_NONE, C_REG, 28, 12, 0, 0, 0},
  328. {AANDS, C_MOVCON3, C_REG, C_NONE, C_REG, 28, 16, 0, 0, 0},
  329. {AANDS, C_MOVCON3, C_NONE, C_NONE, C_REG, 28, 16, 0, 0, 0},
  330. {AANDS, C_VCON, C_REG, C_NONE, C_REG, 28, 20, 0, 0, 0},
  331. {AANDS, C_VCON, C_NONE, C_NONE, C_REG, 28, 20, 0, 0, 0},
  332. {ATST, C_MOVCON2, C_REG, C_NONE, C_NONE, 28, 12, 0, 0, 0},
  333. {ATST, C_MOVCON3, C_REG, C_NONE, C_NONE, 28, 16, 0, 0, 0},
  334. {ATST, C_VCON, C_REG, C_NONE, C_NONE, 28, 20, 0, 0, 0},
  335. {AAND, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
  336. {AAND, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
  337. {AANDS, C_SHIFT, C_REG, C_NONE, C_REG, 3, 4, 0, 0, 0},
  338. {AANDS, C_SHIFT, C_NONE, C_NONE, C_REG, 3, 4, 0, 0, 0},
  339. {ATST, C_SHIFT, C_REG, C_NONE, C_NONE, 3, 4, 0, 0, 0},
  340. {AMOVD, C_RSP, C_NONE, C_NONE, C_RSP, 24, 4, 0, 0, 0},
  341. {AMVN, C_REG, C_NONE, C_NONE, C_REG, 24, 4, 0, 0, 0},
  342. {AMOVB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0},
  343. {AMOVBU, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0},
  344. {AMOVH, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVHU */
  345. {AMOVW, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0}, /* also MOVWU */
  346. /* TODO: MVN C_SHIFT */
  347. /* MOVs that become MOVK/MOVN/MOVZ/ADD/SUB/OR */
  348. {AMOVW, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
  349. {AMOVD, C_MOVCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
  350. {AMOVW, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
  351. {AMOVD, C_BITCON, C_NONE, C_NONE, C_REG, 32, 4, 0, 0, 0},
  352. {AMOVW, C_MOVCON2, C_NONE, C_NONE, C_REG, 12, 8, 0, NOTUSETMP, 0},
  353. {AMOVD, C_MOVCON2, C_NONE, C_NONE, C_REG, 12, 8, 0, NOTUSETMP, 0},
  354. {AMOVD, C_MOVCON3, C_NONE, C_NONE, C_REG, 12, 12, 0, NOTUSETMP, 0},
  355. {AMOVD, C_VCON, C_NONE, C_NONE, C_REG, 12, 16, 0, NOTUSETMP, 0},
  356. {AMOVK, C_VCON, C_NONE, C_NONE, C_REG, 33, 4, 0, 0, 0},
  357. {AMOVD, C_AACON, C_NONE, C_NONE, C_RSP, 4, 4, REGFROM, 0, 0},
  358. {AMOVD, C_AACON2, C_NONE, C_NONE, C_RSP, 4, 8, REGFROM, 0, 0},
  359. /* load long effective stack address (load int32 offset and add) */
  360. {AMOVD, C_LACON, C_NONE, C_NONE, C_RSP, 34, 8, REGSP, LFROM, 0},
  361. // Move a large constant to a Vn.
  362. {AFMOVQ, C_VCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0},
  363. {AFMOVD, C_VCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0},
  364. {AFMOVS, C_LCON, C_NONE, C_NONE, C_VREG, 101, 4, 0, LFROM, 0},
  365. /* jump operations */
  366. {AB, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
  367. {ABL, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0},
  368. {AB, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
  369. {ABL, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
  370. {ABL, C_REG, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
  371. {ABL, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
  372. {obj.ARET, C_NONE, C_NONE, C_NONE, C_REG, 6, 4, 0, 0, 0},
  373. {obj.ARET, C_NONE, C_NONE, C_NONE, C_ZOREG, 6, 4, 0, 0, 0},
  374. {ABEQ, C_NONE, C_NONE, C_NONE, C_SBRA, 7, 4, 0, 0, 0},
  375. {ACBZ, C_REG, C_NONE, C_NONE, C_SBRA, 39, 4, 0, 0, 0},
  376. {ATBZ, C_VCON, C_REG, C_NONE, C_SBRA, 40, 4, 0, 0, 0},
  377. {AERET, C_NONE, C_NONE, C_NONE, C_NONE, 41, 4, 0, 0, 0},
  378. // get a PC-relative address
  379. {AADRP, C_SBRA, C_NONE, C_NONE, C_REG, 60, 4, 0, 0, 0},
  380. {AADR, C_SBRA, C_NONE, C_NONE, C_REG, 61, 4, 0, 0, 0},
  381. {ACLREX, C_NONE, C_NONE, C_NONE, C_VCON, 38, 4, 0, 0, 0},
  382. {ACLREX, C_NONE, C_NONE, C_NONE, C_NONE, 38, 4, 0, 0, 0},
  383. {ABFM, C_VCON, C_REG, C_VCON, C_REG, 42, 4, 0, 0, 0},
  384. {ABFI, C_VCON, C_REG, C_VCON, C_REG, 43, 4, 0, 0, 0},
  385. {AEXTR, C_VCON, C_REG, C_REG, C_REG, 44, 4, 0, 0, 0},
  386. {ASXTB, C_REG, C_NONE, C_NONE, C_REG, 45, 4, 0, 0, 0},
  387. {ACLS, C_REG, C_NONE, C_NONE, C_REG, 46, 4, 0, 0, 0},
  388. {ALSL, C_VCON, C_REG, C_NONE, C_REG, 8, 4, 0, 0, 0},
  389. {ALSL, C_VCON, C_NONE, C_NONE, C_REG, 8, 4, 0, 0, 0},
  390. {ALSL, C_REG, C_NONE, C_NONE, C_REG, 9, 4, 0, 0, 0},
  391. {ALSL, C_REG, C_REG, C_NONE, C_REG, 9, 4, 0, 0, 0},
  392. {ASVC, C_VCON, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
  393. {ASVC, C_NONE, C_NONE, C_NONE, C_NONE, 10, 4, 0, 0, 0},
  394. {ADWORD, C_NONE, C_NONE, C_NONE, C_VCON, 11, 8, 0, NOTUSETMP, 0},
  395. {ADWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 11, 8, 0, NOTUSETMP, 0},
  396. {ADWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 11, 8, 0, NOTUSETMP, 0},
  397. {ADWORD, C_NONE, C_NONE, C_NONE, C_LACON, 11, 8, 0, NOTUSETMP, 0},
  398. {AWORD, C_NONE, C_NONE, C_NONE, C_LCON, 14, 4, 0, 0, 0},
  399. {AWORD, C_NONE, C_NONE, C_NONE, C_LEXT, 14, 4, 0, 0, 0},
  400. {AWORD, C_NONE, C_NONE, C_NONE, C_ADDR, 14, 4, 0, 0, 0},
  401. {AMOVW, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, NOTUSETMP, 0},
  402. {AMOVD, C_VCONADDR, C_NONE, C_NONE, C_REG, 68, 8, 0, NOTUSETMP, 0},
  403. {AMOVB, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
  404. {AMOVBU, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
  405. {AMOVH, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
  406. {AMOVW, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
  407. {AMOVD, C_REG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
  408. {AMOVB, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
  409. {AMOVBU, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
  410. {AMOVH, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
  411. {AMOVW, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
  412. {AMOVD, C_ADDR, C_NONE, C_NONE, C_REG, 65, 12, 0, 0, 0},
  413. {AMOVD, C_GOTADDR, C_NONE, C_NONE, C_REG, 71, 8, 0, 0, 0},
  414. {AMOVD, C_TLS_LE, C_NONE, C_NONE, C_REG, 69, 4, 0, 0, 0},
  415. {AMOVD, C_TLS_IE, C_NONE, C_NONE, C_REG, 70, 8, 0, 0, 0},
  416. {AFMOVS, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
  417. {AFMOVS, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0},
  418. {AFMOVD, C_FREG, C_NONE, C_NONE, C_ADDR, 64, 12, 0, 0, 0},
  419. {AFMOVD, C_ADDR, C_NONE, C_NONE, C_FREG, 65, 12, 0, 0, 0},
  420. {AFMOVS, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0},
  421. {AFMOVS, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
  422. {AFMOVD, C_FCON, C_NONE, C_NONE, C_FREG, 55, 4, 0, 0, 0},
  423. {AFMOVD, C_FREG, C_NONE, C_NONE, C_FREG, 54, 4, 0, 0, 0},
  424. {AFMOVS, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
  425. {AFMOVS, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
  426. {AFMOVD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
  427. {AFMOVD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
  428. {AFCVTZSD, C_FREG, C_NONE, C_NONE, C_REG, 29, 4, 0, 0, 0},
  429. {ASCVTFD, C_REG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
  430. {AFCVTSD, C_FREG, C_NONE, C_NONE, C_FREG, 29, 4, 0, 0, 0},
  431. {AVMOV, C_ELEM, C_NONE, C_NONE, C_REG, 73, 4, 0, 0, 0},
  432. {AVMOV, C_ELEM, C_NONE, C_NONE, C_ELEM, 92, 4, 0, 0, 0},
  433. {AVMOV, C_ELEM, C_NONE, C_NONE, C_VREG, 80, 4, 0, 0, 0},
  434. {AVMOV, C_REG, C_NONE, C_NONE, C_ARNG, 82, 4, 0, 0, 0},
  435. {AVMOV, C_REG, C_NONE, C_NONE, C_ELEM, 78, 4, 0, 0, 0},
  436. {AVMOV, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0},
  437. {AVDUP, C_ELEM, C_NONE, C_NONE, C_ARNG, 79, 4, 0, 0, 0},
  438. {AVMOVI, C_ADDCON, C_NONE, C_NONE, C_ARNG, 86, 4, 0, 0, 0},
  439. {AVFMLA, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
  440. {AVEXT, C_VCON, C_ARNG, C_ARNG, C_ARNG, 94, 4, 0, 0, 0},
  441. {AVTBL, C_ARNG, C_NONE, C_LIST, C_ARNG, 100, 4, 0, 0, 0},
  442. {AVUSHR, C_VCON, C_ARNG, C_NONE, C_ARNG, 95, 4, 0, 0, 0},
  443. {AVZIP1, C_ARNG, C_ARNG, C_NONE, C_ARNG, 72, 4, 0, 0, 0},
  444. {AVUSHLL, C_VCON, C_ARNG, C_NONE, C_ARNG, 102, 4, 0, 0, 0},
  445. {AVUXTL, C_ARNG, C_NONE, C_NONE, C_ARNG, 102, 4, 0, 0, 0},
  446. /* conditional operations */
  447. {ACSEL, C_COND, C_REG, C_REG, C_REG, 18, 4, 0, 0, 0},
  448. {ACINC, C_COND, C_REG, C_NONE, C_REG, 18, 4, 0, 0, 0},
  449. {ACSET, C_COND, C_NONE, C_NONE, C_REG, 18, 4, 0, 0, 0},
  450. {AFCSELD, C_COND, C_FREG, C_FREG, C_FREG, 18, 4, 0, 0, 0},
  451. {ACCMN, C_COND, C_REG, C_REG, C_VCON, 19, 4, 0, 0, 0},
  452. {ACCMN, C_COND, C_REG, C_VCON, C_VCON, 19, 4, 0, 0, 0},
  453. {AFCCMPS, C_COND, C_FREG, C_FREG, C_VCON, 57, 4, 0, 0, 0},
  454. /* scaled 12-bit unsigned displacement store */
  455. {AMOVB, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0},
  456. {AMOVB, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0},
  457. {AMOVBU, C_REG, C_NONE, C_NONE, C_UAUTO4K, 20, 4, REGSP, 0, 0},
  458. {AMOVBU, C_REG, C_NONE, C_NONE, C_UOREG4K, 20, 4, 0, 0, 0},
  459. {AMOVH, C_REG, C_NONE, C_NONE, C_UAUTO8K, 20, 4, REGSP, 0, 0},
  460. {AMOVH, C_REG, C_NONE, C_NONE, C_UOREG8K, 20, 4, 0, 0, 0},
  461. {AMOVW, C_REG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
  462. {AMOVW, C_REG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
  463. {AMOVD, C_REG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0},
  464. {AMOVD, C_REG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0},
  465. {AFMOVS, C_FREG, C_NONE, C_NONE, C_UAUTO16K, 20, 4, REGSP, 0, 0},
  466. {AFMOVS, C_FREG, C_NONE, C_NONE, C_UOREG16K, 20, 4, 0, 0, 0},
  467. {AFMOVD, C_FREG, C_NONE, C_NONE, C_UAUTO32K, 20, 4, REGSP, 0, 0},
  468. {AFMOVD, C_FREG, C_NONE, C_NONE, C_UOREG32K, 20, 4, 0, 0, 0},
  469. /* unscaled 9-bit signed displacement store */
  470. {AMOVB, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
  471. {AMOVB, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
  472. {AMOVBU, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
  473. {AMOVBU, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
  474. {AMOVH, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
  475. {AMOVH, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
  476. {AMOVW, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
  477. {AMOVW, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
  478. {AMOVD, C_REG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
  479. {AMOVD, C_REG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
  480. {AFMOVS, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
  481. {AFMOVS, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
  482. {AFMOVD, C_FREG, C_NONE, C_NONE, C_NSAUTO, 20, 4, REGSP, 0, 0},
  483. {AFMOVD, C_FREG, C_NONE, C_NONE, C_NSOREG, 20, 4, 0, 0, 0},
  484. /* scaled 12-bit unsigned displacement load */
  485. {AMOVB, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
  486. {AMOVB, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
  487. {AMOVBU, C_UAUTO4K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
  488. {AMOVBU, C_UOREG4K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
  489. {AMOVH, C_UAUTO8K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
  490. {AMOVH, C_UOREG8K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
  491. {AMOVW, C_UAUTO16K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
  492. {AMOVW, C_UOREG16K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
  493. {AMOVD, C_UAUTO32K, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
  494. {AMOVD, C_UOREG32K, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
  495. {AFMOVS, C_UAUTO16K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
  496. {AFMOVS, C_UOREG16K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
  497. {AFMOVD, C_UAUTO32K, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
  498. {AFMOVD, C_UOREG32K, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
  499. /* unscaled 9-bit signed displacement load */
  500. {AMOVB, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
  501. {AMOVB, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
  502. {AMOVBU, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
  503. {AMOVBU, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
  504. {AMOVH, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
  505. {AMOVH, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
  506. {AMOVW, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
  507. {AMOVW, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
  508. {AMOVD, C_NSAUTO, C_NONE, C_NONE, C_REG, 21, 4, REGSP, 0, 0},
  509. {AMOVD, C_NSOREG, C_NONE, C_NONE, C_REG, 21, 4, 0, 0, 0},
  510. {AFMOVS, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
  511. {AFMOVS, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
  512. {AFMOVD, C_NSAUTO, C_NONE, C_NONE, C_FREG, 21, 4, REGSP, 0, 0},
  513. {AFMOVD, C_NSOREG, C_NONE, C_NONE, C_FREG, 21, 4, 0, 0, 0},
  514. /* long displacement store */
  515. {AMOVB, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
  516. {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
  517. {AMOVBU, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
  518. {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
  519. {AMOVH, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
  520. {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
  521. {AMOVW, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
  522. {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
  523. {AMOVD, C_REG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
  524. {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
  525. {AFMOVS, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
  526. {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
  527. {AFMOVD, C_FREG, C_NONE, C_NONE, C_LAUTO, 30, 8, REGSP, LTO, 0},
  528. {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 30, 8, 0, LTO, 0},
  529. /* long displacement load */
  530. {AMOVB, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
  531. {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
  532. {AMOVBU, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
  533. {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
  534. {AMOVH, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
  535. {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
  536. {AMOVW, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
  537. {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
  538. {AMOVD, C_LAUTO, C_NONE, C_NONE, C_REG, 31, 8, REGSP, LFROM, 0},
  539. {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 31, 8, 0, LFROM, 0},
  540. {AFMOVS, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
  541. {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
  542. {AFMOVD, C_LAUTO, C_NONE, C_NONE, C_FREG, 31, 8, REGSP, LFROM, 0},
  543. {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 31, 8, 0, LFROM, 0},
  544. /* pre/post-indexed load (unscaled, signed 9-bit offset) */
  545. {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
  546. {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
  547. {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
  548. {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
  549. {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPOST},
  550. {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
  551. {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPOST},
  552. {AMOVD, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
  553. {AMOVW, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
  554. {AMOVH, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
  555. {AMOVB, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
  556. {AMOVBU, C_LOREG, C_NONE, C_NONE, C_REG, 22, 4, 0, 0, C_XPRE},
  557. {AFMOVS, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
  558. {AFMOVD, C_LOREG, C_NONE, C_NONE, C_FREG, 22, 4, 0, 0, C_XPRE},
  559. /* pre/post-indexed store (unscaled, signed 9-bit offset) */
  560. {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
  561. {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
  562. {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
  563. {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
  564. {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
  565. {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
  566. {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPOST},
  567. {AMOVD, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
  568. {AMOVW, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
  569. {AMOVH, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
  570. {AMOVB, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
  571. {AMOVBU, C_REG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
  572. {AFMOVS, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
  573. {AFMOVD, C_FREG, C_NONE, C_NONE, C_LOREG, 23, 4, 0, 0, C_XPRE},
  574. /* load with shifted or extended register offset */
  575. {AMOVD, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
  576. {AMOVW, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
  577. {AMOVH, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
  578. {AMOVB, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
  579. {AMOVBU, C_ROFF, C_NONE, C_NONE, C_REG, 98, 4, 0, 0, 0},
  580. {AFMOVS, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0},
  581. {AFMOVD, C_ROFF, C_NONE, C_NONE, C_FREG, 98, 4, 0, 0, 0},
  582. /* store with extended register offset */
  583. {AMOVD, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
  584. {AMOVW, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
  585. {AMOVH, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
  586. {AMOVB, C_REG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
  587. {AFMOVS, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
  588. {AFMOVD, C_FREG, C_NONE, C_NONE, C_ROFF, 99, 4, 0, 0, 0},
  589. /* pre/post-indexed/signed-offset load/store register pair
  590. (unscaled, signed 10-bit quad-aligned and long offset) */
  591. {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
  592. {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
  593. {ALDP, C_NPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
  594. {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
  595. {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
  596. {ALDP, C_PPAUTO, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
  597. {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
  598. {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
  599. {ALDP, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
  600. {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
  601. {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
  602. {ALDP, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
  603. {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
  604. {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE},
  605. {ALDP, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST},
  606. {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
  607. {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
  608. {ALDP, C_NPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
  609. {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
  610. {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
  611. {ALDP, C_PPOREG, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
  612. {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
  613. {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
  614. {ALDP, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
  615. {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
  616. {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
  617. {ALDP, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
  618. {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
  619. {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE},
  620. {ALDP, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST},
  621. {ALDP, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
  622. {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, 0},
  623. {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPRE},
  624. {ASTP, C_PAIR, C_NONE, C_NONE, C_NPAUTO, 67, 4, REGSP, 0, C_XPOST},
  625. {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, 0},
  626. {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPRE},
  627. {ASTP, C_PAIR, C_NONE, C_NONE, C_PPAUTO, 67, 4, REGSP, 0, C_XPOST},
  628. {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
  629. {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE},
  630. {ASTP, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST},
  631. {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, 0},
  632. {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPRE},
  633. {ASTP, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPOST},
  634. {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
  635. {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE},
  636. {ASTP, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST},
  637. {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, 0},
  638. {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPRE},
  639. {ASTP, C_PAIR, C_NONE, C_NONE, C_NPOREG, 67, 4, 0, 0, C_XPOST},
  640. {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, 0},
  641. {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPRE},
  642. {ASTP, C_PAIR, C_NONE, C_NONE, C_PPOREG, 67, 4, 0, 0, C_XPOST},
  643. {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
  644. {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE},
  645. {ASTP, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST},
  646. {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0},
  647. {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPRE},
  648. {ASTP, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPOST},
  649. {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
  650. {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE},
  651. {ASTP, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST},
  652. {ASTP, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
  653. // differ from LDP/STP for C_NSAUTO_4/C_PSAUTO_4/C_NSOREG_4/C_PSOREG_4
  654. {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
  655. {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
  656. {ALDPW, C_NSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
  657. {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, 0},
  658. {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPRE},
  659. {ALDPW, C_PSAUTO_4, C_NONE, C_NONE, C_PAIR, 66, 4, REGSP, 0, C_XPOST},
  660. {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
  661. {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
  662. {ALDPW, C_UAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
  663. {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, 0},
  664. {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPRE},
  665. {ALDPW, C_NAUTO4K, C_NONE, C_NONE, C_PAIR, 74, 8, REGSP, 0, C_XPOST},
  666. {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, 0},
  667. {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPRE},
  668. {ALDPW, C_LAUTO, C_NONE, C_NONE, C_PAIR, 75, 12, REGSP, LFROM, C_XPOST},
  669. {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
  670. {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
  671. {ALDPW, C_NSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
  672. {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, 0},
  673. {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPRE},
  674. {ALDPW, C_PSOREG_4, C_NONE, C_NONE, C_PAIR, 66, 4, 0, 0, C_XPOST},
  675. {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
  676. {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
  677. {ALDPW, C_UOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
  678. {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, 0},
  679. {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPRE},
  680. {ALDPW, C_NOREG4K, C_NONE, C_NONE, C_PAIR, 74, 8, 0, 0, C_XPOST},
  681. {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, 0},
  682. {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPRE},
  683. {ALDPW, C_LOREG, C_NONE, C_NONE, C_PAIR, 75, 12, 0, LFROM, C_XPOST},
  684. {ALDPW, C_ADDR, C_NONE, C_NONE, C_PAIR, 88, 12, 0, 0, 0},
  685. {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, 0},
  686. {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPRE},
  687. {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSAUTO_4, 67, 4, REGSP, 0, C_XPOST},
  688. {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, 0},
  689. {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPRE},
  690. {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSAUTO_4, 67, 4, REGSP, 0, C_XPOST},
  691. {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, 0},
  692. {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPRE},
  693. {ASTPW, C_PAIR, C_NONE, C_NONE, C_UAUTO4K, 76, 8, REGSP, 0, C_XPOST},
  694. {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, 0},
  695. {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPRE},
  696. {ASTPW, C_PAIR, C_NONE, C_NONE, C_NAUTO4K, 76, 12, REGSP, 0, C_XPOST},
  697. {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, 0},
  698. {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPRE},
  699. {ASTPW, C_PAIR, C_NONE, C_NONE, C_LAUTO, 77, 12, REGSP, LTO, C_XPOST},
  700. {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, 0},
  701. {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPRE},
  702. {ASTPW, C_PAIR, C_NONE, C_NONE, C_NSOREG_4, 67, 4, 0, 0, C_XPOST},
  703. {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, 0},
  704. {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPRE},
  705. {ASTPW, C_PAIR, C_NONE, C_NONE, C_PSOREG_4, 67, 4, 0, 0, C_XPOST},
  706. {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, 0},
  707. {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPRE},
  708. {ASTPW, C_PAIR, C_NONE, C_NONE, C_UOREG4K, 76, 8, 0, 0, C_XPOST},
  709. {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, 0},
  710. {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPRE},
  711. {ASTPW, C_PAIR, C_NONE, C_NONE, C_NOREG4K, 76, 8, 0, 0, C_XPOST},
  712. {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, 0},
  713. {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPRE},
  714. {ASTPW, C_PAIR, C_NONE, C_NONE, C_LOREG, 77, 12, 0, LTO, C_XPOST},
  715. {ASTPW, C_PAIR, C_NONE, C_NONE, C_ADDR, 87, 12, 0, 0, 0},
  716. {ASWPD, C_REG, C_NONE, C_NONE, C_ZOREG, 47, 4, 0, 0, 0}, // RegTo2=C_REG
  717. {ASWPD, C_REG, C_NONE, C_NONE, C_ZAUTO, 47, 4, REGSP, 0, 0}, // RegTo2=C_REG
  718. {ALDAR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
  719. {ALDXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
  720. {ALDAXR, C_ZOREG, C_NONE, C_NONE, C_REG, 58, 4, 0, 0, 0},
  721. {ALDXP, C_ZOREG, C_NONE, C_NONE, C_PAIR, 58, 4, 0, 0, 0},
  722. {ASTLR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_NONE
  723. {ASTXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG
  724. {ASTLXR, C_REG, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0}, // RegTo2=C_REG
  725. {ASTXP, C_PAIR, C_NONE, C_NONE, C_ZOREG, 59, 4, 0, 0, 0},
  726. /* VLD[1-4]/VST[1-4] */
  727. {AVLD1, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0},
  728. {AVLD1, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
  729. {AVLD1, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
  730. {AVLD1R, C_ZOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, 0},
  731. {AVLD1R, C_LOREG, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
  732. {AVLD1R, C_ROFF, C_NONE, C_NONE, C_LIST, 81, 4, 0, 0, C_XPOST},
  733. {AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST},
  734. {AVLD1, C_ROFF, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, C_XPOST},
  735. {AVLD1, C_LOREG, C_NONE, C_NONE, C_ELEM, 97, 4, 0, 0, 0},
  736. {AVST1, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
  737. {AVST1, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
  738. {AVST1, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
  739. {AVST2, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
  740. {AVST2, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
  741. {AVST2, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
  742. {AVST3, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
  743. {AVST3, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
  744. {AVST3, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
  745. {AVST4, C_LIST, C_NONE, C_NONE, C_ZOREG, 84, 4, 0, 0, 0},
  746. {AVST4, C_LIST, C_NONE, C_NONE, C_LOREG, 84, 4, 0, 0, C_XPOST},
  747. {AVST4, C_LIST, C_NONE, C_NONE, C_ROFF, 84, 4, 0, 0, C_XPOST},
  748. {AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, C_XPOST},
  749. {AVST1, C_ELEM, C_NONE, C_NONE, C_ROFF, 96, 4, 0, 0, C_XPOST},
  750. {AVST1, C_ELEM, C_NONE, C_NONE, C_LOREG, 96, 4, 0, 0, 0},
  751. /* special */
  752. {AMOVD, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0},
  753. {AMRS, C_SPR, C_NONE, C_NONE, C_REG, 35, 4, 0, 0, 0},
  754. {AMOVD, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0},
  755. {AMSR, C_REG, C_NONE, C_NONE, C_SPR, 36, 4, 0, 0, 0},
  756. {AMOVD, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0},
  757. {AMSR, C_VCON, C_NONE, C_NONE, C_SPR, 37, 4, 0, 0, 0},
  758. {APRFM, C_UOREG32K, C_NONE, C_NONE, C_SPR, 91, 4, 0, 0, 0},
  759. {APRFM, C_UOREG32K, C_NONE, C_NONE, C_LCON, 91, 4, 0, 0, 0},
  760. {ADMB, C_VCON, C_NONE, C_NONE, C_NONE, 51, 4, 0, 0, 0},
  761. {AHINT, C_VCON, C_NONE, C_NONE, C_NONE, 52, 4, 0, 0, 0},
  762. {ASYS, C_VCON, C_NONE, C_NONE, C_NONE, 50, 4, 0, 0, 0},
  763. {ASYS, C_VCON, C_REG, C_NONE, C_NONE, 50, 4, 0, 0, 0},
  764. {ASYSL, C_VCON, C_NONE, C_NONE, C_REG, 50, 4, 0, 0, 0},
  765. /* encryption instructions */
  766. {AAESD, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0}, // for compatibility with old code
  767. {AAESD, C_ARNG, C_NONE, C_NONE, C_ARNG, 29, 4, 0, 0, 0}, // recommend using the new one for better readability
  768. {ASHA1C, C_VREG, C_REG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
  769. {ASHA1C, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
  770. {ASHA1H, C_VREG, C_NONE, C_NONE, C_VREG, 29, 4, 0, 0, 0},
  771. {ASHA1SU0, C_ARNG, C_ARNG, C_NONE, C_ARNG, 1, 4, 0, 0, 0},
  772. {ASHA256H, C_ARNG, C_VREG, C_NONE, C_VREG, 1, 4, 0, 0, 0},
  773. {AVREV32, C_ARNG, C_NONE, C_NONE, C_ARNG, 83, 4, 0, 0, 0},
  774. {AVPMULL, C_ARNG, C_ARNG, C_NONE, C_ARNG, 93, 4, 0, 0, 0},
  775. {obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0},
  776. {obj.APCDATA, C_VCON, C_NONE, C_NONE, C_VCON, 0, 0, 0, 0, 0},
  777. {obj.AFUNCDATA, C_VCON, C_NONE, C_NONE, C_ADDR, 0, 0, 0, 0, 0},
  778. {obj.ANOP, C_NONE, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
  779. {obj.ANOP, C_LCON, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // nop variants, see #40689
  780. {obj.ANOP, C_REG, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
  781. {obj.ANOP, C_VREG, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0},
  782. {obj.ADUFFZERO, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL
  783. {obj.ADUFFCOPY, C_NONE, C_NONE, C_NONE, C_SBRA, 5, 4, 0, 0, 0}, // same as AB/ABL
  784. {obj.APCALIGN, C_LCON, C_NONE, C_NONE, C_NONE, 0, 0, 0, 0, 0}, // align code
  785. {obj.AXXX, C_NONE, C_NONE, C_NONE, C_NONE, 0, 4, 0, 0, 0},
  786. }
  787. /*
  788. * valid pstate field values, and value to use in instruction
  789. */
  790. var pstatefield = []struct {
  791. reg int16
  792. enc uint32
  793. }{
  794. {REG_SPSel, 0<<16 | 4<<12 | 5<<5},
  795. {REG_DAIFSet, 3<<16 | 4<<12 | 6<<5},
  796. {REG_DAIFClr, 3<<16 | 4<<12 | 7<<5},
  797. }
  798. var prfopfield = []struct {
  799. reg int16
  800. enc uint32
  801. }{
  802. {REG_PLDL1KEEP, 0},
  803. {REG_PLDL1STRM, 1},
  804. {REG_PLDL2KEEP, 2},
  805. {REG_PLDL2STRM, 3},
  806. {REG_PLDL3KEEP, 4},
  807. {REG_PLDL3STRM, 5},
  808. {REG_PLIL1KEEP, 8},
  809. {REG_PLIL1STRM, 9},
  810. {REG_PLIL2KEEP, 10},
  811. {REG_PLIL2STRM, 11},
  812. {REG_PLIL3KEEP, 12},
  813. {REG_PLIL3STRM, 13},
  814. {REG_PSTL1KEEP, 16},
  815. {REG_PSTL1STRM, 17},
  816. {REG_PSTL2KEEP, 18},
  817. {REG_PSTL2STRM, 19},
  818. {REG_PSTL3KEEP, 20},
  819. {REG_PSTL3STRM, 21},
  820. }
  821. // Used for padinng NOOP instruction
  822. const OP_NOOP = 0xd503201f
  823. // align code to a certain length by padding bytes.
  824. func pcAlignPadLength(pc int64, alignedValue int64, ctxt *obj.Link) int {
  825. if !((alignedValue&(alignedValue-1) == 0) && 8 <= alignedValue && alignedValue <= 2048) {
  826. ctxt.Diag("alignment value of an instruction must be a power of two and in the range [8, 2048], got %d\n", alignedValue)
  827. }
  828. return int(-pc & (alignedValue - 1))
  829. }
  830. func span7(ctxt *obj.Link, cursym *obj.LSym, newprog obj.ProgAlloc) {
  831. if ctxt.Retpoline {
  832. ctxt.Diag("-spectre=ret not supported on arm64")
  833. ctxt.Retpoline = false // don't keep printing
  834. }
  835. p := cursym.Func.Text
  836. if p == nil || p.Link == nil { // handle external functions and ELF section symbols
  837. return
  838. }
  839. if oprange[AAND&obj.AMask] == nil {
  840. ctxt.Diag("arm64 ops not initialized, call arm64.buildop first")
  841. }
  842. c := ctxt7{ctxt: ctxt, newprog: newprog, cursym: cursym, autosize: int32(p.To.Offset & 0xffffffff), extrasize: int32(p.To.Offset >> 32)}
  843. p.To.Offset &= 0xffffffff // extrasize is no longer needed
  844. bflag := 1
  845. pc := int64(0)
  846. p.Pc = pc
  847. var m int
  848. var o *Optab
  849. for p = p.Link; p != nil; p = p.Link {
  850. if p.As == ADWORD && (pc&7) != 0 {
  851. pc += 4
  852. }
  853. p.Pc = pc
  854. o = c.oplook(p)
  855. m = int(o.size)
  856. if m == 0 {
  857. switch p.As {
  858. case obj.APCALIGN:
  859. alignedValue := p.From.Offset
  860. m = pcAlignPadLength(pc, alignedValue, ctxt)
  861. // Update the current text symbol alignment value.
  862. if int32(alignedValue) > cursym.Func.Align {
  863. cursym.Func.Align = int32(alignedValue)
  864. }
  865. break
  866. case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
  867. continue
  868. default:
  869. c.ctxt.Diag("zero-width instruction\n%v", p)
  870. }
  871. }
  872. switch o.flag & (LFROM | LTO) {
  873. case LFROM:
  874. c.addpool(p, &p.From)
  875. case LTO:
  876. c.addpool(p, &p.To)
  877. break
  878. }
  879. if p.As == AB || p.As == obj.ARET || p.As == AERET { /* TODO: other unconditional operations */
  880. c.checkpool(p, 0)
  881. }
  882. pc += int64(m)
  883. if c.blitrl != nil {
  884. c.checkpool(p, 1)
  885. }
  886. }
  887. c.cursym.Size = pc
  888. /*
  889. * if any procedure is large enough to
  890. * generate a large SBRA branch, then
  891. * generate extra passes putting branches
  892. * around jmps to fix. this is rare.
  893. */
  894. for bflag != 0 {
  895. bflag = 0
  896. pc = 0
  897. for p = c.cursym.Func.Text.Link; p != nil; p = p.Link {
  898. if p.As == ADWORD && (pc&7) != 0 {
  899. pc += 4
  900. }
  901. p.Pc = pc
  902. o = c.oplook(p)
  903. /* very large branches */
  904. 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
  905. otxt := p.To.Target().Pc - pc
  906. var toofar bool
  907. switch o.type_ {
  908. case 7, 39: // branch instruction encodes 19 bits
  909. toofar = otxt <= -(1<<20)+10 || otxt >= (1<<20)-10
  910. case 40: // branch instruction encodes 14 bits
  911. toofar = otxt <= -(1<<15)+10 || otxt >= (1<<15)-10
  912. }
  913. if toofar {
  914. q := c.newprog()
  915. q.Link = p.Link
  916. p.Link = q
  917. q.As = AB
  918. q.To.Type = obj.TYPE_BRANCH
  919. q.To.SetTarget(p.To.Target())
  920. p.To.SetTarget(q)
  921. q = c.newprog()
  922. q.Link = p.Link
  923. p.Link = q
  924. q.As = AB
  925. q.To.Type = obj.TYPE_BRANCH
  926. q.To.SetTarget(q.Link.Link)
  927. bflag = 1
  928. }
  929. }
  930. m = int(o.size)
  931. if m == 0 {
  932. switch p.As {
  933. case obj.APCALIGN:
  934. alignedValue := p.From.Offset
  935. m = pcAlignPadLength(pc, alignedValue, ctxt)
  936. break
  937. case obj.ANOP, obj.AFUNCDATA, obj.APCDATA:
  938. continue
  939. default:
  940. c.ctxt.Diag("zero-width instruction\n%v", p)
  941. }
  942. }
  943. pc += int64(m)
  944. }
  945. }
  946. pc += -pc & (funcAlign - 1)
  947. c.cursym.Size = pc
  948. /*
  949. * lay out the code, emitting code and data relocations.
  950. */
  951. c.cursym.Grow(c.cursym.Size)
  952. bp := c.cursym.P
  953. psz := int32(0)
  954. var i int
  955. var out [6]uint32
  956. for p := c.cursym.Func.Text.Link; p != nil; p = p.Link {
  957. c.pc = p.Pc
  958. o = c.oplook(p)
  959. // need to align DWORDs on 8-byte boundary. The ISA doesn't
  960. // require it, but the various 64-bit loads we generate assume it.
  961. if o.as == ADWORD && psz%8 != 0 {
  962. bp[3] = 0
  963. bp[2] = bp[3]
  964. bp[1] = bp[2]
  965. bp[0] = bp[1]
  966. bp = bp[4:]
  967. psz += 4
  968. }
  969. if int(o.size) > 4*len(out) {
  970. log.Fatalf("out array in span7 is too small, need at least %d for %v", o.size/4, p)
  971. }
  972. if p.As == obj.APCALIGN {
  973. alignedValue := p.From.Offset
  974. v := pcAlignPadLength(p.Pc, alignedValue, c.ctxt)
  975. for i = 0; i < int(v/4); i++ {
  976. // emit ANOOP instruction by the padding size
  977. c.ctxt.Arch.ByteOrder.PutUint32(bp, OP_NOOP)
  978. bp = bp[4:]
  979. psz += 4
  980. }
  981. } else {
  982. c.asmout(p, o, out[:])
  983. for i = 0; i < int(o.size/4); i++ {
  984. c.ctxt.Arch.ByteOrder.PutUint32(bp, out[i])
  985. bp = bp[4:]
  986. psz += 4
  987. }
  988. }
  989. }
  990. // Mark nonpreemptible instruction sequences.
  991. // We use REGTMP as a scratch register during call injection,
  992. // so instruction sequences that use REGTMP are unsafe to
  993. // preempt asynchronously.
  994. obj.MarkUnsafePoints(c.ctxt, c.cursym.Func.Text, c.newprog, c.isUnsafePoint, c.isRestartable)
  995. }
  996. // isUnsafePoint returns whether p is an unsafe point.
  997. func (c *ctxt7) isUnsafePoint(p *obj.Prog) bool {
  998. // If p explicitly uses REGTMP, it's unsafe to preempt, because the
  999. // preemption sequence clobbers REGTMP.
  1000. return p.From.Reg == REGTMP || p.To.Reg == REGTMP || p.Reg == REGTMP
  1001. }
  1002. // isRestartable returns whether p is a multi-instruction sequence that,
  1003. // if preempted, can be restarted.
  1004. func (c *ctxt7) isRestartable(p *obj.Prog) bool {
  1005. if c.isUnsafePoint(p) {
  1006. return false
  1007. }
  1008. // If p is a multi-instruction sequence with uses REGTMP inserted by
  1009. // the assembler in order to materialize a large constant/offset, we
  1010. // can restart p (at the start of the instruction sequence), recompute
  1011. // the content of REGTMP, upon async preemption. Currently, all cases
  1012. // of assembler-inserted REGTMP fall into this category.
  1013. // If p doesn't use REGTMP, it can be simply preempted, so we don't
  1014. // mark it.
  1015. o := c.oplook(p)
  1016. return o.size > 4 && o.flag&NOTUSETMP == 0
  1017. }
  1018. /*
  1019. * when the first reference to the literal pool threatens
  1020. * to go out of range of a 1Mb PC-relative offset
  1021. * drop the pool now, and branch round it.
  1022. */
  1023. func (c *ctxt7) checkpool(p *obj.Prog, skip int) {
  1024. if c.pool.size >= 0xffff0 || !ispcdisp(int32(p.Pc+4+int64(c.pool.size)-int64(c.pool.start)+8)) {
  1025. c.flushpool(p, skip)
  1026. } else if p.Link == nil {
  1027. c.flushpool(p, 2)
  1028. }
  1029. }
  1030. func (c *ctxt7) flushpool(p *obj.Prog, skip int) {
  1031. if c.blitrl != nil {
  1032. if skip != 0 {
  1033. if c.ctxt.Debugvlog && skip == 1 {
  1034. fmt.Printf("note: flush literal pool at %#x: len=%d ref=%x\n", uint64(p.Pc+4), c.pool.size, c.pool.start)
  1035. }
  1036. q := c.newprog()
  1037. q.As = AB
  1038. q.To.Type = obj.TYPE_BRANCH
  1039. q.To.SetTarget(p.Link)
  1040. q.Link = c.blitrl
  1041. q.Pos = p.Pos
  1042. c.blitrl = q
  1043. } else if p.Pc+int64(c.pool.size)-int64(c.pool.start) < maxPCDisp {
  1044. return
  1045. }
  1046. // The line number for constant pool entries doesn't really matter.
  1047. // We set it to the line number of the preceding instruction so that
  1048. // there are no deltas to encode in the pc-line tables.
  1049. for q := c.blitrl; q != nil; q = q.Link {
  1050. q.Pos = p.Pos
  1051. }
  1052. c.elitrl.Link = p.Link
  1053. p.Link = c.blitrl
  1054. c.blitrl = nil /* BUG: should refer back to values until out-of-range */
  1055. c.elitrl = nil
  1056. c.pool.size = 0
  1057. c.pool.start = 0
  1058. }
  1059. }
  1060. /*
  1061. * MOVD foo(SB), R is actually
  1062. * MOVD addr, REGTMP
  1063. * MOVD REGTMP, R
  1064. * where addr is the address of the DWORD containing the address of foo.
  1065. *
  1066. * TODO: hash
  1067. */
  1068. func (c *ctxt7) addpool(p *obj.Prog, a *obj.Addr) {
  1069. cls := c.aclass(a)
  1070. lit := c.instoffset
  1071. t := c.newprog()
  1072. t.As = AWORD
  1073. sz := 4
  1074. if a.Type == obj.TYPE_CONST {
  1075. if lit != int64(int32(lit)) && uint64(lit) != uint64(uint32(lit)) {
  1076. // out of range -0x80000000 ~ 0xffffffff, must store 64-bit
  1077. t.As = ADWORD
  1078. sz = 8
  1079. } // else store 32-bit
  1080. } 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)) {
  1081. // conservative: don't know if we want signed or unsigned extension.
  1082. // in case of ambiguity, store 64-bit
  1083. t.As = ADWORD
  1084. sz = 8
  1085. }
  1086. switch cls {
  1087. // TODO(aram): remove.
  1088. default:
  1089. if a.Name != obj.NAME_EXTERN {
  1090. fmt.Printf("addpool: %v in %v shouldn't go to default case\n", DRconv(cls), p)
  1091. }
  1092. t.To.Offset = a.Offset
  1093. t.To.Sym = a.Sym
  1094. t.To.Type = a.Type
  1095. t.To.Name = a.Name
  1096. /* This is here because MOV uint12<<12, R is disabled in optab.
  1097. Because of this, we need to load the constant from memory. */
  1098. case C_ADDCON:
  1099. fallthrough
  1100. case C_ZAUTO,
  1101. C_PSAUTO,
  1102. C_PSAUTO_8,
  1103. C_PSAUTO_4,
  1104. C_PPAUTO,
  1105. C_UAUTO4K_8,
  1106. C_UAUTO4K_4,
  1107. C_UAUTO4K_2,
  1108. C_UAUTO4K,
  1109. C_UAUTO8K_8,
  1110. C_UAUTO8K_4,
  1111. C_UAUTO8K,
  1112. C_UAUTO16K_8,
  1113. C_UAUTO16K,
  1114. C_UAUTO32K,
  1115. C_NSAUTO_8,
  1116. C_NSAUTO_4,
  1117. C_NSAUTO,
  1118. C_NPAUTO,
  1119. C_NAUTO4K,
  1120. C_LAUTO,
  1121. C_PPOREG,
  1122. C_PSOREG,
  1123. C_PSOREG_4,
  1124. C_PSOREG_8,
  1125. C_UOREG4K_8,
  1126. C_UOREG4K_4,
  1127. C_UOREG4K_2,
  1128. C_UOREG4K,
  1129. C_UOREG8K_8,
  1130. C_UOREG8K_4,
  1131. C_UOREG8K,
  1132. C_UOREG16K_8,
  1133. C_UOREG16K,
  1134. C_UOREG32K,
  1135. C_NSOREG_8,
  1136. C_NSOREG_4,
  1137. C_NSOREG,
  1138. C_NPOREG,
  1139. C_NOREG4K,
  1140. C_LOREG,
  1141. C_LACON,
  1142. C_ADDCON2,
  1143. C_LCON,
  1144. C_VCON:
  1145. if a.Name == obj.NAME_EXTERN {
  1146. fmt.Printf("addpool: %v in %v needs reloc\n", DRconv(cls), p)
  1147. }
  1148. t.To.Type = obj.TYPE_CONST
  1149. t.To.Offset = lit
  1150. break
  1151. }
  1152. for q := c.blitrl; q != nil; q = q.Link { /* could hash on t.t0.offset */
  1153. if q.To == t.To {
  1154. p.Pool = q
  1155. return
  1156. }
  1157. }
  1158. q := c.newprog()
  1159. *q = *t
  1160. q.Pc = int64(c.pool.size)
  1161. if c.blitrl == nil {
  1162. c.blitrl = q
  1163. c.pool.start = uint32(p.Pc)
  1164. } else {
  1165. c.elitrl.Link = q
  1166. }
  1167. c.elitrl = q
  1168. c.pool.size = -c.pool.size & (funcAlign - 1)
  1169. c.pool.size += uint32(sz)
  1170. p.Pool = q
  1171. }
  1172. func (c *ctxt7) regoff(a *obj.Addr) uint32 {
  1173. c.instoffset = 0
  1174. c.aclass(a)
  1175. return uint32(c.instoffset)
  1176. }
  1177. func isSTLXRop(op obj.As) bool {
  1178. switch op {
  1179. case ASTLXR, ASTLXRW, ASTLXRB, ASTLXRH,
  1180. ASTXR, ASTXRW, ASTXRB, ASTXRH:
  1181. return true
  1182. }
  1183. return false
  1184. }
  1185. func isSTXPop(op obj.As) bool {
  1186. switch op {
  1187. case ASTXP, ASTLXP, ASTXPW, ASTLXPW:
  1188. return true
  1189. }
  1190. return false
  1191. }
  1192. func isANDop(op obj.As) bool {
  1193. switch op {
  1194. case AAND, AORR, AEOR, AANDS, ATST,
  1195. ABIC, AEON, AORN, ABICS:
  1196. return true
  1197. }
  1198. return false
  1199. }
  1200. func isANDWop(op obj.As) bool {
  1201. switch op {
  1202. case AANDW, AORRW, AEORW, AANDSW, ATSTW,
  1203. ABICW, AEONW, AORNW, ABICSW:
  1204. return true
  1205. }
  1206. return false
  1207. }
  1208. func isADDop(op obj.As) bool {
  1209. switch op {
  1210. case AADD, AADDS, ASUB, ASUBS, ACMN, ACMP:
  1211. return true
  1212. }
  1213. return false
  1214. }
  1215. func isADDWop(op obj.As) bool {
  1216. switch op {
  1217. case AADDW, AADDSW, ASUBW, ASUBSW, ACMNW, ACMPW:
  1218. return true
  1219. }
  1220. return false
  1221. }
  1222. func isRegShiftOrExt(a *obj.Addr) bool {
  1223. return (a.Index-obj.RBaseARM64)&REG_EXT != 0 || (a.Index-obj.RBaseARM64)&REG_LSL != 0
  1224. }
  1225. // Maximum PC-relative displacement.
  1226. // The actual limit is ±2²⁰, but we are conservative
  1227. // to avoid needing to recompute the literal pool flush points
  1228. // as span-dependent jumps are enlarged.
  1229. const maxPCDisp = 512 * 1024
  1230. // ispcdisp reports whether v is a valid PC-relative displacement.
  1231. func ispcdisp(v int32) bool {
  1232. return -maxPCDisp < v && v < maxPCDisp && v&3 == 0
  1233. }
  1234. func isaddcon(v int64) bool {
  1235. /* uimm12 or uimm24? */
  1236. if v < 0 {
  1237. return false
  1238. }
  1239. if (v & 0xFFF) == 0 {
  1240. v >>= 12
  1241. }
  1242. return v <= 0xFFF
  1243. }
  1244. func isaddcon2(v int64) bool {
  1245. return 0 <= v && v <= 0xFFFFFF
  1246. }
  1247. // isbitcon reports whether a constant can be encoded into a logical instruction.
  1248. // bitcon has a binary form of repetition of a bit sequence of length 2, 4, 8, 16, 32, or 64,
  1249. // which itself is a rotate (w.r.t. the length of the unit) of a sequence of ones.
  1250. // special cases: 0 and -1 are not bitcon.
  1251. // this function needs to run against virtually all the constants, so it needs to be fast.
  1252. // for this reason, bitcon testing and bitcon encoding are separate functions.
  1253. func isbitcon(x uint64) bool {
  1254. if x == 1<<64-1 || x == 0 {
  1255. return false
  1256. }
  1257. // determine the period and sign-extend a unit to 64 bits
  1258. switch {
  1259. case x != x>>32|x<<32:
  1260. // period is 64
  1261. // nothing to do
  1262. case x != x>>16|x<<48:
  1263. // period is 32
  1264. x = uint64(int64(int32(x)))
  1265. case x != x>>8|x<<56:
  1266. // period is 16
  1267. x = uint64(int64(int16(x)))
  1268. case x != x>>4|x<<60:
  1269. // period is 8
  1270. x = uint64(int64(int8(x)))
  1271. default:
  1272. // period is 4 or 2, always true
  1273. // 0001, 0010, 0100, 1000 -- 0001 rotate
  1274. // 0011, 0110, 1100, 1001 -- 0011 rotate
  1275. // 0111, 1011, 1101, 1110 -- 0111 rotate
  1276. // 0101, 1010 -- 01 rotate, repeat
  1277. return true
  1278. }
  1279. return sequenceOfOnes(x) || sequenceOfOnes(^x)
  1280. }
  1281. // sequenceOfOnes tests whether a constant is a sequence of ones in binary, with leading and trailing zeros
  1282. func sequenceOfOnes(x uint64) bool {
  1283. y := x & -x // lowest set bit of x. x is good iff x+y is a power of 2
  1284. y += x
  1285. return (y-1)&y == 0
  1286. }
  1287. // bitconEncode returns the encoding of a bitcon used in logical instructions
  1288. // x is known to be a bitcon
  1289. // a bitcon is a sequence of n ones at low bits (i.e. 1<<n-1), right rotated
  1290. // by R bits, and repeated with period of 64, 32, 16, 8, 4, or 2.
  1291. // it is encoded in logical instructions with 3 bitfields
  1292. // N (1 bit) : R (6 bits) : S (6 bits), where
  1293. // N=1 -- period=64
  1294. // N=0, S=0xxxxx -- period=32
  1295. // N=0, S=10xxxx -- period=16
  1296. // N=0, S=110xxx -- period=8
  1297. // N=0, S=1110xx -- period=4
  1298. // N=0, S=11110x -- period=2
  1299. // R is the shift amount, low bits of S = n-1
  1300. func bitconEncode(x uint64, mode int) uint32 {
  1301. var period uint32
  1302. // determine the period and sign-extend a unit to 64 bits
  1303. switch {
  1304. case x != x>>32|x<<32:
  1305. period = 64
  1306. case x != x>>16|x<<48:
  1307. period = 32
  1308. x = uint64(int64(int32(x)))
  1309. case x != x>>8|x<<56:
  1310. period = 16
  1311. x = uint64(int64(int16(x)))
  1312. case x != x>>4|x<<60:
  1313. period = 8
  1314. x = uint64(int64(int8(x)))
  1315. case x != x>>2|x<<62:
  1316. period = 4
  1317. x = uint64(int64(x<<60) >> 60)
  1318. default:
  1319. period = 2
  1320. x = uint64(int64(x<<62) >> 62)
  1321. }
  1322. neg := false
  1323. if int64(x) < 0 {
  1324. x = ^x
  1325. neg = true
  1326. }
  1327. y := x & -x // lowest set bit of x.
  1328. s := log2(y)
  1329. n := log2(x+y) - s // x (or ^x) is a sequence of n ones left shifted by s bits
  1330. if neg {
  1331. // ^x is a sequence of n ones left shifted by s bits
  1332. // adjust n, s for x
  1333. s = n + s
  1334. n = period - n
  1335. }
  1336. N := uint32(0)
  1337. if mode == 64 && period == 64 {
  1338. N = 1
  1339. }
  1340. R := (period - s) & (period - 1) & uint32(mode-1) // shift amount of right rotate
  1341. S := (n - 1) | 63&^(period<<1-1) // low bits = #ones - 1, high bits encodes period
  1342. return N<<22 | R<<16 | S<<10
  1343. }
  1344. func log2(x uint64) uint32 {
  1345. if x == 0 {
  1346. panic("log2 of 0")
  1347. }
  1348. n := uint32(0)
  1349. if x >= 1<<32 {
  1350. x >>= 32
  1351. n += 32
  1352. }
  1353. if x >= 1<<16 {
  1354. x >>= 16
  1355. n += 16
  1356. }
  1357. if x >= 1<<8 {
  1358. x >>= 8
  1359. n += 8
  1360. }
  1361. if x >= 1<<4 {
  1362. x >>= 4
  1363. n += 4
  1364. }
  1365. if x >= 1<<2 {
  1366. x >>= 2
  1367. n += 2
  1368. }
  1369. if x >= 1<<1 {
  1370. x >>= 1
  1371. n += 1
  1372. }
  1373. return n
  1374. }
  1375. func autoclass(l int64) int {
  1376. if l == 0 {
  1377. return C_ZAUTO
  1378. }
  1379. if l < 0 {
  1380. if l >= -256 && (l&7) == 0 {
  1381. return C_NSAUTO_8
  1382. }
  1383. if l >= -256 && (l&3) == 0 {
  1384. return C_NSAUTO_4
  1385. }
  1386. if l >= -256 {
  1387. return C_NSAUTO
  1388. }
  1389. if l >= -512 && (l&7) == 0 {
  1390. return C_NPAUTO
  1391. }
  1392. if l >= -4095 {
  1393. return C_NAUTO4K
  1394. }
  1395. return C_LAUTO
  1396. }
  1397. if l <= 255 {
  1398. if (l & 7) == 0 {
  1399. return C_PSAUTO_8
  1400. }
  1401. if (l & 3) == 0 {
  1402. return C_PSAUTO_4
  1403. }
  1404. return C_PSAUTO
  1405. }
  1406. if l <= 504 && l&7 == 0 {
  1407. return C_PPAUTO
  1408. }
  1409. if l <= 4095 {
  1410. if l&7 == 0 {
  1411. return C_UAUTO4K_8
  1412. }
  1413. if l&3 == 0 {
  1414. return C_UAUTO4K_4
  1415. }
  1416. if l&1 == 0 {
  1417. return C_UAUTO4K_2
  1418. }
  1419. return C_UAUTO4K
  1420. }
  1421. if l <= 8190 {
  1422. if l&7 == 0 {
  1423. return C_UAUTO8K_8
  1424. }
  1425. if l&3 == 0 {
  1426. return C_UAUTO8K_4
  1427. }
  1428. if l&1 == 0 {
  1429. return C_UAUTO8K
  1430. }
  1431. }
  1432. if l <= 16380 {
  1433. if l&7 == 0 {
  1434. return C_UAUTO16K_8
  1435. }
  1436. if l&3 == 0 {
  1437. return C_UAUTO16K
  1438. }
  1439. }
  1440. if l <= 32760 && (l&7) == 0 {
  1441. return C_UAUTO32K
  1442. }
  1443. return C_LAUTO
  1444. }
  1445. func oregclass(l int64) int {
  1446. return autoclass(l) - C_ZAUTO + C_ZOREG
  1447. }
  1448. /*
  1449. * given an offset v and a class c (see above)
  1450. * return the offset value to use in the instruction,
  1451. * scaled if necessary
  1452. */
  1453. func (c *ctxt7) offsetshift(p *obj.Prog, v int64, cls int) int64 {
  1454. s := 0
  1455. if cls >= C_SEXT1 && cls <= C_SEXT16 {
  1456. s = cls - C_SEXT1
  1457. } else {
  1458. switch cls {
  1459. case C_UAUTO4K, C_UOREG4K, C_ZOREG:
  1460. s = 0
  1461. case C_UAUTO8K, C_UOREG8K:
  1462. s = 1
  1463. case C_UAUTO16K, C_UOREG16K:
  1464. s = 2
  1465. case C_UAUTO32K, C_UOREG32K:
  1466. s = 3
  1467. default:
  1468. c.ctxt.Diag("bad class: %v\n%v", DRconv(cls), p)
  1469. }
  1470. }
  1471. vs := v >> uint(s)
  1472. if vs<<uint(s) != v {
  1473. c.ctxt.Diag("odd offset: %d\n%v", v, p)
  1474. }
  1475. return vs
  1476. }
  1477. /*
  1478. * if v contains a single 16-bit value aligned
  1479. * on a 16-bit field, and thus suitable for movk/movn,
  1480. * return the field index 0 to 3; otherwise return -1
  1481. */
  1482. func movcon(v int64) int {
  1483. for s := 0; s < 64; s += 16 {
  1484. if (uint64(v) &^ (uint64(0xFFFF) << uint(s))) == 0 {
  1485. return s / 16
  1486. }
  1487. }
  1488. return -1
  1489. }
  1490. func rclass(r int16) int {
  1491. switch {
  1492. case REG_R0 <= r && r <= REG_R30: // not 31
  1493. return C_REG
  1494. case r == REGZERO:
  1495. return C_ZCON
  1496. case REG_F0 <= r && r <= REG_F31:
  1497. return C_FREG
  1498. case REG_V0 <= r && r <= REG_V31:
  1499. return C_VREG
  1500. case COND_EQ <= r && r <= COND_NV:
  1501. return C_COND
  1502. case r == REGSP:
  1503. return C_RSP
  1504. case r >= REG_ARNG && r < REG_ELEM:
  1505. return C_ARNG
  1506. case r >= REG_ELEM && r < REG_ELEM_END:
  1507. return C_ELEM
  1508. case r >= REG_UXTB && r < REG_SPECIAL:
  1509. return C_EXTREG
  1510. case r >= REG_SPECIAL:
  1511. return C_SPR
  1512. }
  1513. return C_GOK
  1514. }
  1515. // con32class reclassifies the constant of 32-bit instruction. Because the constant type is 32-bit,
  1516. // but saved in Offset which type is int64, con32class treats it as uint32 type and reclassifies it.
  1517. func (c *ctxt7) con32class(a *obj.Addr) int {
  1518. v := uint32(a.Offset)
  1519. if v == 0 {
  1520. return C_ZCON
  1521. }
  1522. if isaddcon(int64(v)) {
  1523. if v <= 0xFFF {
  1524. if isbitcon(uint64(a.Offset)) {
  1525. return C_ABCON0
  1526. }
  1527. return C_ADDCON0
  1528. }
  1529. if isbitcon(uint64(a.Offset)) {
  1530. return C_ABCON
  1531. }
  1532. if movcon(int64(v)) >= 0 {
  1533. return C_AMCON
  1534. }
  1535. if movcon(int64(^v)) >= 0 {
  1536. return C_AMCON
  1537. }
  1538. return C_ADDCON
  1539. }
  1540. t := movcon(int64(v))
  1541. if t >= 0 {
  1542. if isbitcon(uint64(a.Offset)) {
  1543. return C_MBCON
  1544. }
  1545. return C_MOVCON
  1546. }
  1547. t = movcon(int64(^v))
  1548. if t >= 0 {
  1549. if isbitcon(uint64(a.Offset)) {
  1550. return C_MBCON
  1551. }
  1552. return C_MOVCON
  1553. }
  1554. if isbitcon(uint64(a.Offset)) {
  1555. return C_BITCON
  1556. }
  1557. if 0 <= v && v <= 0xffffff {
  1558. return C_ADDCON2
  1559. }
  1560. return C_LCON
  1561. }
  1562. // con64class reclassifies the constant of C_VCON and C_LCON class.
  1563. func (c *ctxt7) con64class(a *obj.Addr) int {
  1564. zeroCount := 0
  1565. negCount := 0
  1566. for i := uint(0); i < 4; i++ {
  1567. immh := uint32(a.Offset >> (i * 16) & 0xffff)
  1568. if immh == 0 {
  1569. zeroCount++
  1570. } else if immh == 0xffff {
  1571. negCount++
  1572. }
  1573. }
  1574. if zeroCount >= 3 || negCount >= 3 {
  1575. return C_MOVCON
  1576. } else if zeroCount == 2 || negCount == 2 {
  1577. return C_MOVCON2
  1578. } else if zeroCount == 1 || negCount == 1 {
  1579. return C_MOVCON3
  1580. } else {
  1581. return C_VCON
  1582. }
  1583. }
  1584. func (c *ctxt7) aclass(a *obj.Addr) int {
  1585. switch a.Type {
  1586. case obj.TYPE_NONE:
  1587. return C_NONE
  1588. case obj.TYPE_REG:
  1589. return rclass(a.Reg)
  1590. case obj.TYPE_REGREG:
  1591. return C_PAIR
  1592. case obj.TYPE_SHIFT:
  1593. return C_SHIFT
  1594. case obj.TYPE_REGLIST:
  1595. return C_LIST
  1596. case obj.TYPE_MEM:
  1597. // The base register should be an integer register.
  1598. if int16(REG_F0) <= a.Reg && a.Reg <= int16(REG_V31) {
  1599. break
  1600. }
  1601. switch a.Name {
  1602. case obj.NAME_EXTERN, obj.NAME_STATIC:
  1603. if a.Sym == nil {
  1604. break
  1605. }
  1606. c.instoffset = a.Offset
  1607. if a.Sym != nil { // use relocation
  1608. if a.Sym.Type == objabi.STLSBSS {
  1609. if c.ctxt.Flag_shared {
  1610. return C_TLS_IE
  1611. } else {
  1612. return C_TLS_LE
  1613. }
  1614. }
  1615. return C_ADDR
  1616. }
  1617. return C_LEXT
  1618. case obj.NAME_GOTREF:
  1619. return C_GOTADDR
  1620. case obj.NAME_AUTO:
  1621. if a.Reg == REGSP {
  1622. // unset base register for better printing, since
  1623. // a.Offset is still relative to pseudo-SP.
  1624. a.Reg = obj.REG_NONE
  1625. }
  1626. // The frame top 8 or 16 bytes are for FP
  1627. c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
  1628. return autoclass(c.instoffset)
  1629. case obj.NAME_PARAM:
  1630. if a.Reg == REGSP {
  1631. // unset base register for better printing, since
  1632. // a.Offset is still relative to pseudo-FP.
  1633. a.Reg = obj.REG_NONE
  1634. }
  1635. c.instoffset = int64(c.autosize) + a.Offset + 8
  1636. return autoclass(c.instoffset)
  1637. case obj.NAME_NONE:
  1638. if a.Index != 0 {
  1639. if a.Offset != 0 {
  1640. if isRegShiftOrExt(a) {
  1641. // extended or shifted register offset, (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2).
  1642. return C_ROFF
  1643. }
  1644. return C_GOK
  1645. }
  1646. // register offset, (Rn)(Rm)
  1647. return C_ROFF
  1648. }
  1649. c.instoffset = a.Offset
  1650. return oregclass(c.instoffset)
  1651. }
  1652. return C_GOK
  1653. case obj.TYPE_FCONST:
  1654. return C_FCON
  1655. case obj.TYPE_TEXTSIZE:
  1656. return C_TEXTSIZE
  1657. case obj.TYPE_CONST, obj.TYPE_ADDR:
  1658. switch a.Name {
  1659. case obj.NAME_NONE:
  1660. c.instoffset = a.Offset
  1661. if a.Reg != 0 && a.Reg != REGZERO {
  1662. break
  1663. }
  1664. v := c.instoffset
  1665. if v == 0 {
  1666. return C_ZCON
  1667. }
  1668. if isaddcon(v) {
  1669. if v <= 0xFFF {
  1670. if isbitcon(uint64(v)) {
  1671. return C_ABCON0
  1672. }
  1673. return C_ADDCON0
  1674. }
  1675. if isbitcon(uint64(v)) {
  1676. return C_ABCON
  1677. }
  1678. if movcon(v) >= 0 {
  1679. return C_AMCON
  1680. }
  1681. if movcon(^v) >= 0 {
  1682. return C_AMCON
  1683. }
  1684. return C_ADDCON
  1685. }
  1686. t := movcon(v)
  1687. if t >= 0 {
  1688. if isbitcon(uint64(v)) {
  1689. return C_MBCON
  1690. }
  1691. return C_MOVCON
  1692. }
  1693. t = movcon(^v)
  1694. if t >= 0 {
  1695. if isbitcon(uint64(v)) {
  1696. return C_MBCON
  1697. }
  1698. return C_MOVCON
  1699. }
  1700. if isbitcon(uint64(v)) {
  1701. return C_BITCON
  1702. }
  1703. if 0 <= v && v <= 0xffffff {
  1704. return C_ADDCON2
  1705. }
  1706. if uint64(v) == uint64(uint32(v)) || v == int64(int32(v)) {
  1707. return C_LCON
  1708. }
  1709. return C_VCON
  1710. case obj.NAME_EXTERN, obj.NAME_STATIC:
  1711. if a.Sym == nil {
  1712. return C_GOK
  1713. }
  1714. if a.Sym.Type == objabi.STLSBSS {
  1715. c.ctxt.Diag("taking address of TLS variable is not supported")
  1716. }
  1717. c.instoffset = a.Offset
  1718. return C_VCONADDR
  1719. case obj.NAME_AUTO:
  1720. if a.Reg == REGSP {
  1721. // unset base register for better printing, since
  1722. // a.Offset is still relative to pseudo-SP.
  1723. a.Reg = obj.REG_NONE
  1724. }
  1725. // The frame top 8 or 16 bytes are for FP
  1726. c.instoffset = int64(c.autosize) + a.Offset - int64(c.extrasize)
  1727. case obj.NAME_PARAM:
  1728. if a.Reg == REGSP {
  1729. // unset base register for better printing, since
  1730. // a.Offset is still relative to pseudo-FP.
  1731. a.Reg = obj.REG_NONE
  1732. }
  1733. c.instoffset = int64(c.autosize) + a.Offset + 8
  1734. default:
  1735. return C_GOK
  1736. }
  1737. cf := c.instoffset
  1738. if isaddcon(cf) || isaddcon(-cf) {
  1739. return C_AACON
  1740. }
  1741. if isaddcon2(cf) {
  1742. return C_AACON2
  1743. }
  1744. return C_LACON
  1745. case obj.TYPE_BRANCH:
  1746. return C_SBRA
  1747. }
  1748. return C_GOK
  1749. }
  1750. func oclass(a *obj.Addr) int {
  1751. return int(a.Class) - 1
  1752. }
  1753. func (c *ctxt7) oplook(p *obj.Prog) *Optab {
  1754. a1 := int(p.Optab)
  1755. if a1 != 0 {
  1756. return &optab[a1-1]
  1757. }
  1758. a1 = int(p.From.Class)
  1759. if a1 == 0 {
  1760. a0 := c.aclass(&p.From)
  1761. // do not break C_ADDCON2 when S bit is set
  1762. if (p.As == AADDS || p.As == AADDSW || p.As == ASUBS || p.As == ASUBSW) && a0 == C_ADDCON2 {
  1763. a0 = C_LCON
  1764. }
  1765. a1 = a0 + 1
  1766. p.From.Class = int8(a1)
  1767. // more specific classification of 32-bit integers
  1768. if p.From.Type == obj.TYPE_CONST && p.From.Name == obj.NAME_NONE {
  1769. if p.As == AMOVW || isADDWop(p.As) {
  1770. ra0 := c.con32class(&p.From)
  1771. // do not break C_ADDCON2 when S bit is set
  1772. if (p.As == AADDSW || p.As == ASUBSW) && ra0 == C_ADDCON2 {
  1773. ra0 = C_LCON
  1774. }
  1775. a1 = ra0 + 1
  1776. p.From.Class = int8(a1)
  1777. }
  1778. if isANDWop(p.As) && a0 != C_BITCON {
  1779. // For 32-bit logical instruction with constant,
  1780. // the BITCON test is special in that it looks at
  1781. // the 64-bit which has the high 32-bit as a copy
  1782. // of the low 32-bit. We have handled that and
  1783. // don't pass it to con32class.
  1784. a1 = c.con32class(&p.From) + 1
  1785. p.From.Class = int8(a1)
  1786. }
  1787. if ((p.As == AMOVD) || isANDop(p.As) || isADDop(p.As)) && (a0 == C_LCON || a0 == C_VCON) {
  1788. a1 = c.con64class(&p.From) + 1
  1789. p.From.Class = int8(a1)
  1790. }
  1791. }
  1792. }
  1793. a1--
  1794. a3 := C_NONE + 1
  1795. if p.GetFrom3() != nil {
  1796. a3 = int(p.GetFrom3().Class)
  1797. if a3 == 0 {
  1798. a3 = c.aclass(p.GetFrom3()) + 1
  1799. p.GetFrom3().Class = int8(a3)
  1800. }
  1801. }
  1802. a3--
  1803. a4 := int(p.To.Class)
  1804. if a4 == 0 {
  1805. a4 = c.aclass(&p.To) + 1
  1806. p.To.Class = int8(a4)
  1807. }
  1808. a4--
  1809. a2 := C_NONE
  1810. if p.Reg != 0 {
  1811. a2 = rclass(p.Reg)
  1812. }
  1813. if false {
  1814. fmt.Printf("oplook %v %d %d %d %d\n", p.As, a1, a2, a3, a4)
  1815. fmt.Printf("\t\t%d %d\n", p.From.Type, p.To.Type)
  1816. }
  1817. ops := oprange[p.As&obj.AMask]
  1818. c1 := &xcmp[a1]
  1819. c2 := &xcmp[a2]
  1820. c3 := &xcmp[a3]
  1821. c4 := &xcmp[a4]
  1822. c5 := &xcmp[p.Scond>>5]
  1823. for i := range ops {
  1824. op := &ops[i]
  1825. if (int(op.a2) == a2 || c2[op.a2]) && c5[op.scond>>5] && c1[op.a1] && c3[op.a3] && c4[op.a4] {
  1826. p.Optab = uint16(cap(optab) - cap(ops) + i + 1)
  1827. return op
  1828. }
  1829. }
  1830. 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)
  1831. // Turn illegal instruction into an UNDEF, avoid crashing in asmout
  1832. return &Optab{obj.AUNDEF, C_NONE, C_NONE, C_NONE, C_NONE, 90, 4, 0, 0, 0}
  1833. }
  1834. func cmp(a int, b int) bool {
  1835. if a == b {
  1836. return true
  1837. }
  1838. switch a {
  1839. case C_RSP:
  1840. if b == C_REG {
  1841. return true
  1842. }
  1843. case C_REG:
  1844. if b == C_ZCON {
  1845. return true
  1846. }
  1847. case C_ADDCON0:
  1848. if b == C_ZCON || b == C_ABCON0 {
  1849. return true
  1850. }
  1851. case C_ADDCON:
  1852. if b == C_ZCON || b == C_ABCON0 || b == C_ADDCON0 || b == C_ABCON || b == C_AMCON {
  1853. return true
  1854. }
  1855. case C_BITCON:
  1856. if b == C_ABCON0 || b == C_ABCON || b == C_MBCON {
  1857. return true
  1858. }
  1859. case C_MOVCON:
  1860. if b == C_MBCON || b == C_ZCON || b == C_ADDCON0 || b == C_AMCON {
  1861. return true
  1862. }
  1863. case C_ADDCON2:
  1864. if b == C_ZCON || b == C_ADDCON || b == C_ADDCON0 {
  1865. return true
  1866. }
  1867. case C_LCON:
  1868. 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 {
  1869. return true
  1870. }
  1871. case C_MOVCON2:
  1872. return cmp(C_LCON, b)
  1873. case C_VCON:
  1874. return cmp(C_LCON, b)
  1875. case C_LACON:
  1876. if b == C_AACON || b == C_AACON2 {
  1877. return true
  1878. }
  1879. case C_SEXT2:
  1880. if b == C_SEXT1 {
  1881. return true
  1882. }
  1883. case C_SEXT4:
  1884. if b == C_SEXT1 || b == C_SEXT2 {
  1885. return true
  1886. }
  1887. case C_SEXT8:
  1888. if b >= C_SEXT1 && b <= C_SEXT4 {
  1889. return true
  1890. }
  1891. case C_SEXT16:
  1892. if b >= C_SEXT1 && b <= C_SEXT8 {
  1893. return true
  1894. }
  1895. case C_LEXT:
  1896. if b >= C_SEXT1 && b <= C_SEXT16 {
  1897. return true
  1898. }
  1899. case C_NSAUTO_4:
  1900. if b == C_NSAUTO_8 {
  1901. return true
  1902. }
  1903. case C_NSAUTO:
  1904. switch b {
  1905. case C_NSAUTO_4, C_NSAUTO_8:
  1906. return true
  1907. }
  1908. case C_NPAUTO:
  1909. switch b {
  1910. case C_NSAUTO_8:
  1911. return true
  1912. }
  1913. case C_NAUTO4K:
  1914. switch b {
  1915. case C_NSAUTO_8, C_NSAUTO_4, C_NSAUTO, C_NPAUTO:
  1916. return true
  1917. }
  1918. case C_PSAUTO_8:
  1919. if b == C_ZAUTO {
  1920. return true
  1921. }
  1922. case C_PSAUTO_4:
  1923. switch b {
  1924. case C_ZAUTO, C_PSAUTO_8:
  1925. return true
  1926. }
  1927. case C_PSAUTO:
  1928. switch b {
  1929. case C_ZAUTO, C_PSAUTO_8, C_PSAUTO_4:
  1930. return true
  1931. }
  1932. case C_PPAUTO:
  1933. switch b {
  1934. case C_ZAUTO, C_PSAUTO_8:
  1935. return true
  1936. }
  1937. case C_UAUTO4K:
  1938. switch b {
  1939. case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8,
  1940. C_PPAUTO, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8:
  1941. return true
  1942. }
  1943. case C_UAUTO8K:
  1944. switch b {
  1945. case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO,
  1946. C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8:
  1947. return true
  1948. }
  1949. case C_UAUTO16K:
  1950. switch b {
  1951. case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO,
  1952. C_UAUTO4K_4, C_UAUTO4K_8, C_UAUTO8K_4, C_UAUTO8K_8, C_UAUTO16K_8:
  1953. return true
  1954. }
  1955. case C_UAUTO32K:
  1956. switch b {
  1957. case C_ZAUTO, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8,
  1958. C_PPAUTO, C_UAUTO4K_8, C_UAUTO8K_8, C_UAUTO16K_8:
  1959. return true
  1960. }
  1961. case C_LAUTO:
  1962. switch b {
  1963. case C_ZAUTO, C_NSAUTO, C_NSAUTO_4, C_NSAUTO_8, C_NPAUTO,
  1964. C_NAUTO4K, C_PSAUTO, C_PSAUTO_4, C_PSAUTO_8, C_PPAUTO,
  1965. C_UAUTO4K, C_UAUTO4K_2, C_UAUTO4K_4, C_UAUTO4K_8,
  1966. C_UAUTO8K, C_UAUTO8K_4, C_UAUTO8K_8,
  1967. C_UAUTO16K, C_UAUTO16K_8,
  1968. C_UAUTO32K:
  1969. return true
  1970. }
  1971. case C_NSOREG_4:
  1972. if b == C_NSOREG_8 {
  1973. return true
  1974. }
  1975. case C_NSOREG:
  1976. switch b {
  1977. case C_NSOREG_4, C_NSOREG_8:
  1978. return true
  1979. }
  1980. case C_NPOREG:
  1981. switch b {
  1982. case C_NSOREG_8:
  1983. return true
  1984. }
  1985. case C_NOREG4K:
  1986. switch b {
  1987. case C_NSOREG_8, C_NSOREG_4, C_NSOREG, C_NPOREG:
  1988. return true
  1989. }
  1990. case C_PSOREG_4:
  1991. switch b {
  1992. case C_ZOREG, C_PSOREG_8:
  1993. return true
  1994. }
  1995. case C_PSOREG:
  1996. switch b {
  1997. case C_ZOREG, C_PSOREG_8, C_PSOREG_4:
  1998. return true
  1999. }
  2000. case C_PPOREG:
  2001. switch b {
  2002. case C_ZOREG, C_PSOREG_8:
  2003. return true
  2004. }
  2005. case C_UOREG4K:
  2006. switch b {
  2007. case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
  2008. C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8:
  2009. return true
  2010. }
  2011. case C_UOREG8K:
  2012. switch b {
  2013. case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
  2014. C_PPOREG, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8,
  2015. C_UOREG8K_4, C_UOREG8K_8:
  2016. return true
  2017. }
  2018. case C_UOREG16K:
  2019. switch b {
  2020. case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
  2021. C_PPOREG, C_UOREG4K_4, C_UOREG4K_8, C_UOREG8K_4,
  2022. C_UOREG8K_8, C_UOREG16K_8:
  2023. return true
  2024. }
  2025. case C_UOREG32K:
  2026. switch b {
  2027. case C_ZOREG, C_PSOREG_4, C_PSOREG_8, C_PSOREG,
  2028. C_PPOREG, C_UOREG4K_8, C_UOREG8K_8, C_UOREG16K_8:
  2029. return true
  2030. }
  2031. case C_LOREG:
  2032. switch b {
  2033. case C_ZOREG, C_NSOREG, C_NSOREG_4, C_NSOREG_8, C_NPOREG,
  2034. C_NOREG4K, C_PSOREG_4, C_PSOREG_8, C_PSOREG, C_PPOREG,
  2035. C_UOREG4K, C_UOREG4K_2, C_UOREG4K_4, C_UOREG4K_8,
  2036. C_UOREG8K, C_UOREG8K_4, C_UOREG8K_8,
  2037. C_UOREG16K, C_UOREG16K_8,
  2038. C_UOREG32K:
  2039. return true
  2040. }
  2041. case C_LBRA:
  2042. if b == C_SBRA {
  2043. return true
  2044. }
  2045. }
  2046. return false
  2047. }
  2048. type ocmp []Optab
  2049. func (x ocmp) Len() int {
  2050. return len(x)
  2051. }
  2052. func (x ocmp) Swap(i, j int) {
  2053. x[i], x[j] = x[j], x[i]
  2054. }
  2055. func (x ocmp) Less(i, j int) bool {
  2056. p1 := &x[i]
  2057. p2 := &x[j]
  2058. if p1.as != p2.as {
  2059. return p1.as < p2.as
  2060. }
  2061. if p1.a1 != p2.a1 {
  2062. return p1.a1 < p2.a1
  2063. }
  2064. if p1.a2 != p2.a2 {
  2065. return p1.a2 < p2.a2
  2066. }
  2067. if p1.a3 != p2.a3 {
  2068. return p1.a3 < p2.a3
  2069. }
  2070. if p1.a4 != p2.a4 {
  2071. return p1.a4 < p2.a4
  2072. }
  2073. if p1.scond != p2.scond {
  2074. return p1.scond < p2.scond
  2075. }
  2076. return false
  2077. }
  2078. func oprangeset(a obj.As, t []Optab) {
  2079. oprange[a&obj.AMask] = t
  2080. }
  2081. func buildop(ctxt *obj.Link) {
  2082. if oprange[AAND&obj.AMask] != nil {
  2083. // Already initialized; stop now.
  2084. // This happens in the cmd/asm tests,
  2085. // each of which re-initializes the arch.
  2086. return
  2087. }
  2088. var n int
  2089. for i := 0; i < C_GOK; i++ {
  2090. for n = 0; n < C_GOK; n++ {
  2091. if cmp(n, i) {
  2092. xcmp[i][n] = true
  2093. }
  2094. }
  2095. }
  2096. for n = 0; optab[n].as != obj.AXXX; n++ {
  2097. }
  2098. sort.Sort(ocmp(optab[:n]))
  2099. for i := 0; i < n; i++ {
  2100. r := optab[i].as
  2101. start := i
  2102. for optab[i].as == r {
  2103. i++
  2104. }
  2105. t := optab[start:i]
  2106. i--
  2107. oprangeset(r, t)
  2108. switch r {
  2109. default:
  2110. ctxt.Diag("unknown op in build: %v", r)
  2111. ctxt.DiagFlush()
  2112. log.Fatalf("bad code")
  2113. case AADD:
  2114. oprangeset(AADDS, t)
  2115. oprangeset(ASUB, t)
  2116. oprangeset(ASUBS, t)
  2117. oprangeset(AADDW, t)
  2118. oprangeset(AADDSW, t)
  2119. oprangeset(ASUBW, t)
  2120. oprangeset(ASUBSW, t)
  2121. case AAND: /* logical immediate, logical shifted register */
  2122. oprangeset(AANDW, t)
  2123. oprangeset(AEOR, t)
  2124. oprangeset(AEORW, t)
  2125. oprangeset(AORR, t)
  2126. oprangeset(AORRW, t)
  2127. oprangeset(ABIC, t)
  2128. oprangeset(ABICW, t)
  2129. oprangeset(AEON, t)
  2130. oprangeset(AEONW, t)
  2131. oprangeset(AORN, t)
  2132. oprangeset(AORNW, t)
  2133. case AANDS: /* logical immediate, logical shifted register, set flags, cannot target RSP */
  2134. oprangeset(AANDSW, t)
  2135. oprangeset(ABICS, t)
  2136. oprangeset(ABICSW, t)
  2137. case ANEG:
  2138. oprangeset(ANEGS, t)
  2139. oprangeset(ANEGSW, t)
  2140. oprangeset(ANEGW, t)
  2141. case AADC: /* rn=Rd */
  2142. oprangeset(AADCW, t)
  2143. oprangeset(AADCS, t)
  2144. oprangeset(AADCSW, t)
  2145. oprangeset(ASBC, t)
  2146. oprangeset(ASBCW, t)
  2147. oprangeset(ASBCS, t)
  2148. oprangeset(ASBCSW, t)
  2149. case ANGC: /* rn=REGZERO */
  2150. oprangeset(ANGCW, t)
  2151. oprangeset(ANGCS, t)
  2152. oprangeset(ANGCSW, t)
  2153. case ACMP:
  2154. oprangeset(ACMPW, t)
  2155. oprangeset(ACMN, t)
  2156. oprangeset(ACMNW, t)
  2157. case ATST:
  2158. oprangeset(ATSTW, t)
  2159. /* register/register, and shifted */
  2160. case AMVN:
  2161. oprangeset(AMVNW, t)
  2162. case AMOVK:
  2163. oprangeset(AMOVKW, t)
  2164. oprangeset(AMOVN, t)
  2165. oprangeset(AMOVNW, t)
  2166. oprangeset(AMOVZ, t)
  2167. oprangeset(AMOVZW, t)
  2168. case ASWPD:
  2169. for i := range atomicInstructions {
  2170. oprangeset(i, t)
  2171. }
  2172. case ABEQ:
  2173. oprangeset(ABNE, t)
  2174. oprangeset(ABCS, t)
  2175. oprangeset(ABHS, t)
  2176. oprangeset(ABCC, t)
  2177. oprangeset(ABLO, t)
  2178. oprangeset(ABMI, t)
  2179. oprangeset(ABPL, t)
  2180. oprangeset(ABVS, t)
  2181. oprangeset(ABVC, t)
  2182. oprangeset(ABHI, t)
  2183. oprangeset(ABLS, t)
  2184. oprangeset(ABGE, t)
  2185. oprangeset(ABLT, t)
  2186. oprangeset(ABGT, t)
  2187. oprangeset(ABLE, t)
  2188. case ALSL:
  2189. oprangeset(ALSLW, t)
  2190. oprangeset(ALSR, t)
  2191. oprangeset(ALSRW, t)
  2192. oprangeset(AASR, t)
  2193. oprangeset(AASRW, t)
  2194. oprangeset(AROR, t)
  2195. oprangeset(ARORW, t)
  2196. case ACLS:
  2197. oprangeset(ACLSW, t)
  2198. oprangeset(ACLZ, t)
  2199. oprangeset(ACLZW, t)
  2200. oprangeset(ARBIT, t)
  2201. oprangeset(ARBITW, t)
  2202. oprangeset(AREV, t)
  2203. oprangeset(AREVW, t)
  2204. oprangeset(AREV16, t)
  2205. oprangeset(AREV16W, t)
  2206. oprangeset(AREV32, t)
  2207. case ASDIV:
  2208. oprangeset(ASDIVW, t)
  2209. oprangeset(AUDIV, t)
  2210. oprangeset(AUDIVW, t)
  2211. oprangeset(ACRC32B, t)
  2212. oprangeset(ACRC32CB, t)
  2213. oprangeset(ACRC32CH, t)
  2214. oprangeset(ACRC32CW, t)
  2215. oprangeset(ACRC32CX, t)
  2216. oprangeset(ACRC32H, t)
  2217. oprangeset(ACRC32W, t)
  2218. oprangeset(ACRC32X, t)
  2219. case AMADD:
  2220. oprangeset(AMADDW, t)
  2221. oprangeset(AMSUB, t)
  2222. oprangeset(AMSUBW, t)
  2223. oprangeset(ASMADDL, t)
  2224. oprangeset(ASMSUBL, t)
  2225. oprangeset(AUMADDL, t)
  2226. oprangeset(AUMSUBL, t)
  2227. case AREM:
  2228. oprangeset(AREMW, t)
  2229. oprangeset(AUREM, t)
  2230. oprangeset(AUREMW, t)
  2231. case AMUL:
  2232. oprangeset(AMULW, t)
  2233. oprangeset(AMNEG, t)
  2234. oprangeset(AMNEGW, t)
  2235. oprangeset(ASMNEGL, t)
  2236. oprangeset(ASMULL, t)
  2237. oprangeset(ASMULH, t)
  2238. oprangeset(AUMNEGL, t)
  2239. oprangeset(AUMULH, t)
  2240. oprangeset(AUMULL, t)
  2241. case AMOVB:
  2242. oprangeset(AMOVBU, t)
  2243. case AMOVH:
  2244. oprangeset(AMOVHU, t)
  2245. case AMOVW:
  2246. oprangeset(AMOVWU, t)
  2247. case ABFM:
  2248. oprangeset(ABFMW, t)
  2249. oprangeset(ASBFM, t)
  2250. oprangeset(ASBFMW, t)
  2251. oprangeset(AUBFM, t)
  2252. oprangeset(AUBFMW, t)
  2253. case ABFI:
  2254. oprangeset(ABFIW, t)
  2255. oprangeset(ABFXIL, t)
  2256. oprangeset(ABFXILW, t)
  2257. oprangeset(ASBFIZ, t)
  2258. oprangeset(ASBFIZW, t)
  2259. oprangeset(ASBFX, t)
  2260. oprangeset(ASBFXW, t)
  2261. oprangeset(AUBFIZ, t)
  2262. oprangeset(AUBFIZW, t)
  2263. oprangeset(AUBFX, t)
  2264. oprangeset(AUBFXW, t)
  2265. case AEXTR:
  2266. oprangeset(AEXTRW, t)
  2267. case ASXTB:
  2268. oprangeset(ASXTBW, t)
  2269. oprangeset(ASXTH, t)
  2270. oprangeset(ASXTHW, t)
  2271. oprangeset(ASXTW, t)
  2272. oprangeset(AUXTB, t)
  2273. oprangeset(AUXTH, t)
  2274. oprangeset(AUXTW, t)
  2275. oprangeset(AUXTBW, t)
  2276. oprangeset(AUXTHW, t)
  2277. case ACCMN:
  2278. oprangeset(ACCMNW, t)
  2279. oprangeset(ACCMP, t)
  2280. oprangeset(ACCMPW, t)
  2281. case ACSEL:
  2282. oprangeset(ACSELW, t)
  2283. oprangeset(ACSINC, t)
  2284. oprangeset(ACSINCW, t)
  2285. oprangeset(ACSINV, t)
  2286. oprangeset(ACSINVW, t)
  2287. oprangeset(ACSNEG, t)
  2288. oprangeset(ACSNEGW, t)
  2289. case ACINC:
  2290. // aliases Rm=Rn, !cond
  2291. oprangeset(ACINCW, t)
  2292. oprangeset(ACINV, t)
  2293. oprangeset(ACINVW, t)
  2294. oprangeset(ACNEG, t)
  2295. oprangeset(ACNEGW, t)
  2296. // aliases, Rm=Rn=REGZERO, !cond
  2297. case ACSET:
  2298. oprangeset(ACSETW, t)
  2299. oprangeset(ACSETM, t)
  2300. oprangeset(ACSETMW, t)
  2301. case AMOVD,
  2302. AMOVBU,
  2303. AB,
  2304. ABL,
  2305. AWORD,
  2306. ADWORD,
  2307. obj.ARET,
  2308. obj.ATEXT:
  2309. break
  2310. case ALDP:
  2311. oprangeset(AFLDPD, t)
  2312. case ASTP:
  2313. oprangeset(AFSTPD, t)
  2314. case ASTPW:
  2315. oprangeset(AFSTPS, t)
  2316. case ALDPW:
  2317. oprangeset(ALDPSW, t)
  2318. oprangeset(AFLDPS, t)
  2319. case AERET:
  2320. oprangeset(AWFE, t)
  2321. oprangeset(AWFI, t)
  2322. oprangeset(AYIELD, t)
  2323. oprangeset(ASEV, t)
  2324. oprangeset(ASEVL, t)
  2325. oprangeset(ANOOP, t)
  2326. oprangeset(ADRPS, t)
  2327. case ACBZ:
  2328. oprangeset(ACBZW, t)
  2329. oprangeset(ACBNZ, t)
  2330. oprangeset(ACBNZW, t)
  2331. case ATBZ:
  2332. oprangeset(ATBNZ, t)
  2333. case AADR, AADRP:
  2334. break
  2335. case ACLREX:
  2336. break
  2337. case ASVC:
  2338. oprangeset(AHVC, t)
  2339. oprangeset(AHLT, t)
  2340. oprangeset(ASMC, t)
  2341. oprangeset(ABRK, t)
  2342. oprangeset(ADCPS1, t)
  2343. oprangeset(ADCPS2, t)
  2344. oprangeset(ADCPS3, t)
  2345. case AFADDS:
  2346. oprangeset(AFADDD, t)
  2347. oprangeset(AFSUBS, t)
  2348. oprangeset(AFSUBD, t)
  2349. oprangeset(AFMULS, t)
  2350. oprangeset(AFMULD, t)
  2351. oprangeset(AFNMULS, t)
  2352. oprangeset(AFNMULD, t)
  2353. oprangeset(AFDIVS, t)
  2354. oprangeset(AFMAXD, t)
  2355. oprangeset(AFMAXS, t)
  2356. oprangeset(AFMIND, t)
  2357. oprangeset(AFMINS, t)
  2358. oprangeset(AFMAXNMD, t)
  2359. oprangeset(AFMAXNMS, t)
  2360. oprangeset(AFMINNMD, t)
  2361. oprangeset(AFMINNMS, t)
  2362. oprangeset(AFDIVD, t)
  2363. case AFMSUBD:
  2364. oprangeset(AFMSUBS, t)
  2365. oprangeset(AFMADDS, t)
  2366. oprangeset(AFMADDD, t)
  2367. oprangeset(AFNMSUBS, t)
  2368. oprangeset(AFNMSUBD, t)
  2369. oprangeset(AFNMADDS, t)
  2370. oprangeset(AFNMADDD, t)
  2371. case AFCVTSD:
  2372. oprangeset(AFCVTDS, t)
  2373. oprangeset(AFABSD, t)
  2374. oprangeset(AFABSS, t)
  2375. oprangeset(AFNEGD, t)
  2376. oprangeset(AFNEGS, t)
  2377. oprangeset(AFSQRTD, t)
  2378. oprangeset(AFSQRTS, t)
  2379. oprangeset(AFRINTNS, t)
  2380. oprangeset(AFRINTND, t)
  2381. oprangeset(AFRINTPS, t)
  2382. oprangeset(AFRINTPD, t)
  2383. oprangeset(AFRINTMS, t)
  2384. oprangeset(AFRINTMD, t)
  2385. oprangeset(AFRINTZS, t)
  2386. oprangeset(AFRINTZD, t)
  2387. oprangeset(AFRINTAS, t)
  2388. oprangeset(AFRINTAD, t)
  2389. oprangeset(AFRINTXS, t)
  2390. oprangeset(AFRINTXD, t)
  2391. oprangeset(AFRINTIS, t)
  2392. oprangeset(AFRINTID, t)
  2393. oprangeset(AFCVTDH, t)
  2394. oprangeset(AFCVTHS, t)
  2395. oprangeset(AFCVTHD, t)
  2396. oprangeset(AFCVTSH, t)
  2397. case AFCMPS:
  2398. oprangeset(AFCMPD, t)
  2399. oprangeset(AFCMPES, t)
  2400. oprangeset(AFCMPED, t)
  2401. case AFCCMPS:
  2402. oprangeset(AFCCMPD, t)
  2403. oprangeset(AFCCMPES, t)
  2404. oprangeset(AFCCMPED, t)
  2405. case AFCSELD:
  2406. oprangeset(AFCSELS, t)
  2407. case AFMOVS, AFMOVD, AFMOVQ:
  2408. break
  2409. case AFCVTZSD:
  2410. oprangeset(AFCVTZSDW, t)
  2411. oprangeset(AFCVTZSS, t)
  2412. oprangeset(AFCVTZSSW, t)
  2413. oprangeset(AFCVTZUD, t)
  2414. oprangeset(AFCVTZUDW, t)
  2415. oprangeset(AFCVTZUS, t)
  2416. oprangeset(AFCVTZUSW, t)
  2417. case ASCVTFD:
  2418. oprangeset(ASCVTFS, t)
  2419. oprangeset(ASCVTFWD, t)
  2420. oprangeset(ASCVTFWS, t)
  2421. oprangeset(AUCVTFD, t)
  2422. oprangeset(AUCVTFS, t)
  2423. oprangeset(AUCVTFWD, t)
  2424. oprangeset(AUCVTFWS, t)
  2425. case ASYS:
  2426. oprangeset(AAT, t)
  2427. oprangeset(ADC, t)
  2428. oprangeset(AIC, t)
  2429. oprangeset(ATLBI, t)
  2430. case ASYSL, AHINT:
  2431. break
  2432. case ADMB:
  2433. oprangeset(ADSB, t)
  2434. oprangeset(AISB, t)
  2435. case AMRS, AMSR:
  2436. break
  2437. case ALDAR:
  2438. oprangeset(ALDARW, t)
  2439. oprangeset(ALDARB, t)
  2440. oprangeset(ALDARH, t)
  2441. fallthrough
  2442. case ALDXR:
  2443. oprangeset(ALDXRB, t)
  2444. oprangeset(ALDXRH, t)
  2445. oprangeset(ALDXRW, t)
  2446. case ALDAXR:
  2447. oprangeset(ALDAXRB, t)
  2448. oprangeset(ALDAXRH, t)
  2449. oprangeset(ALDAXRW, t)
  2450. case ALDXP:
  2451. oprangeset(ALDXPW, t)
  2452. oprangeset(ALDAXP, t)
  2453. oprangeset(ALDAXPW, t)
  2454. case ASTLR:
  2455. oprangeset(ASTLRB, t)
  2456. oprangeset(ASTLRH, t)
  2457. oprangeset(ASTLRW, t)
  2458. case ASTXR:
  2459. oprangeset(ASTXRB, t)
  2460. oprangeset(ASTXRH, t)
  2461. oprangeset(ASTXRW, t)
  2462. case ASTLXR:
  2463. oprangeset(ASTLXRB, t)
  2464. oprangeset(ASTLXRH, t)
  2465. oprangeset(ASTLXRW, t)
  2466. case ASTXP:
  2467. oprangeset(ASTLXP, t)
  2468. oprangeset(ASTLXPW, t)
  2469. oprangeset(ASTXPW, t)
  2470. case AVADDP:
  2471. oprangeset(AVAND, t)
  2472. oprangeset(AVCMEQ, t)
  2473. oprangeset(AVORR, t)
  2474. oprangeset(AVEOR, t)
  2475. oprangeset(AVBSL, t)
  2476. oprangeset(AVBIT, t)
  2477. oprangeset(AVCMTST, t)
  2478. oprangeset(AVUZP1, t)
  2479. oprangeset(AVUZP2, t)
  2480. oprangeset(AVBIF, t)
  2481. case AVADD:
  2482. oprangeset(AVSUB, t)
  2483. case AAESD:
  2484. oprangeset(AAESE, t)
  2485. oprangeset(AAESMC, t)
  2486. oprangeset(AAESIMC, t)
  2487. oprangeset(ASHA1SU1, t)
  2488. oprangeset(ASHA256SU0, t)
  2489. oprangeset(ASHA512SU0, t)
  2490. case ASHA1C:
  2491. oprangeset(ASHA1P, t)
  2492. oprangeset(ASHA1M, t)
  2493. case ASHA256H:
  2494. oprangeset(ASHA256H2, t)
  2495. oprangeset(ASHA512H, t)
  2496. oprangeset(ASHA512H2, t)
  2497. case ASHA1SU0:
  2498. oprangeset(ASHA256SU1, t)
  2499. oprangeset(ASHA512SU1, t)
  2500. case AVADDV:
  2501. oprangeset(AVUADDLV, t)
  2502. case AVFMLA:
  2503. oprangeset(AVFMLS, t)
  2504. case AVPMULL:
  2505. oprangeset(AVPMULL2, t)
  2506. case AVUSHR:
  2507. oprangeset(AVSHL, t)
  2508. oprangeset(AVSRI, t)
  2509. case AVREV32:
  2510. oprangeset(AVCNT, t)
  2511. oprangeset(AVRBIT, t)
  2512. oprangeset(AVREV64, t)
  2513. oprangeset(AVREV16, t)
  2514. case AVZIP1:
  2515. oprangeset(AVZIP2, t)
  2516. case AVUXTL:
  2517. oprangeset(AVUXTL2, t)
  2518. case AVUSHLL:
  2519. oprangeset(AVUSHLL2, t)
  2520. case AVLD1R:
  2521. oprangeset(AVLD2, t)
  2522. oprangeset(AVLD2R, t)
  2523. oprangeset(AVLD3, t)
  2524. oprangeset(AVLD3R, t)
  2525. oprangeset(AVLD4, t)
  2526. oprangeset(AVLD4R, t)
  2527. case ASHA1H,
  2528. AVCNT,
  2529. AVMOV,
  2530. AVLD1,
  2531. AVST1,
  2532. AVST2,
  2533. AVST3,
  2534. AVST4,
  2535. AVTBL,
  2536. AVDUP,
  2537. AVMOVI,
  2538. APRFM,
  2539. AVEXT:
  2540. break
  2541. case obj.ANOP,
  2542. obj.AUNDEF,
  2543. obj.AFUNCDATA,
  2544. obj.APCALIGN,
  2545. obj.APCDATA,
  2546. obj.ADUFFZERO,
  2547. obj.ADUFFCOPY:
  2548. break
  2549. }
  2550. }
  2551. }
  2552. // chipfloat7() checks if the immediate constants available in FMOVS/FMOVD instructions.
  2553. // For details of the range of constants available, see
  2554. // http://infocenter.arm.com/help/topic/com.arm.doc.dui0473m/dom1359731199385.html.
  2555. func (c *ctxt7) chipfloat7(e float64) int {
  2556. ei := math.Float64bits(e)
  2557. l := uint32(int32(ei))
  2558. h := uint32(int32(ei >> 32))
  2559. if l != 0 || h&0xffff != 0 {
  2560. return -1
  2561. }
  2562. h1 := h & 0x7fc00000
  2563. if h1 != 0x40000000 && h1 != 0x3fc00000 {
  2564. return -1
  2565. }
  2566. n := 0
  2567. // sign bit (a)
  2568. if h&0x80000000 != 0 {
  2569. n |= 1 << 7
  2570. }
  2571. // exp sign bit (b)
  2572. if h1 == 0x3fc00000 {
  2573. n |= 1 << 6
  2574. }
  2575. // rest of exp and mantissa (cd-efgh)
  2576. n |= int((h >> 16) & 0x3f)
  2577. //print("match %.8lux %.8lux %d\n", l, h, n);
  2578. return n
  2579. }
  2580. /* form offset parameter to SYS; special register number */
  2581. func SYSARG5(op0 int, op1 int, Cn int, Cm int, op2 int) int {
  2582. return op0<<19 | op1<<16 | Cn<<12 | Cm<<8 | op2<<5
  2583. }
  2584. func SYSARG4(op1 int, Cn int, Cm int, op2 int) int {
  2585. return SYSARG5(0, op1, Cn, Cm, op2)
  2586. }
  2587. // checkUnpredictable checks if the sourse and transfer registers are the same register.
  2588. // ARM64 manual says it is "constrained unpredictable" if the src and dst registers of STP/LDP are same.
  2589. func (c *ctxt7) checkUnpredictable(p *obj.Prog, isload bool, wback bool, rn int16, rt1 int16, rt2 int16) {
  2590. if wback && rn != REGSP && (rn == rt1 || rn == rt2) {
  2591. c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  2592. }
  2593. if isload && rt1 == rt2 {
  2594. c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  2595. }
  2596. }
  2597. /* checkindex checks if index >= 0 && index <= maxindex */
  2598. func (c *ctxt7) checkindex(p *obj.Prog, index, maxindex int) {
  2599. if index < 0 || index > maxindex {
  2600. c.ctxt.Diag("register element index out of range 0 to %d: %v", maxindex, p)
  2601. }
  2602. }
  2603. /* checkoffset checks whether the immediate offset is valid for VLD[1-4].P and VST[1-4].P */
  2604. func (c *ctxt7) checkoffset(p *obj.Prog, as obj.As) {
  2605. var offset, list, n, expect int64
  2606. switch as {
  2607. case AVLD1, AVLD2, AVLD3, AVLD4, AVLD1R, AVLD2R, AVLD3R, AVLD4R:
  2608. offset = p.From.Offset
  2609. list = p.To.Offset
  2610. case AVST1, AVST2, AVST3, AVST4:
  2611. offset = p.To.Offset
  2612. list = p.From.Offset
  2613. default:
  2614. c.ctxt.Diag("invalid operation on op %v", p.As)
  2615. }
  2616. opcode := (list >> 12) & 15
  2617. q := (list >> 30) & 1
  2618. size := (list >> 10) & 3
  2619. if offset == 0 {
  2620. return
  2621. }
  2622. switch opcode {
  2623. case 0x7:
  2624. n = 1 // one register
  2625. case 0xa:
  2626. n = 2 // two registers
  2627. case 0x6:
  2628. n = 3 // three registers
  2629. case 0x2:
  2630. n = 4 // four registers
  2631. default:
  2632. c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
  2633. }
  2634. switch as {
  2635. case AVLD1R, AVLD2R, AVLD3R, AVLD4R:
  2636. if offset != n*(1<<uint(size)) {
  2637. c.ctxt.Diag("invalid post-increment offset: %v", p)
  2638. }
  2639. default:
  2640. if !(q == 0 && offset == n*8) && !(q == 1 && offset == n*16) {
  2641. c.ctxt.Diag("invalid post-increment offset: %v", p)
  2642. }
  2643. }
  2644. switch as {
  2645. case AVLD1, AVST1:
  2646. return
  2647. case AVLD1R:
  2648. expect = 1
  2649. case AVLD2, AVST2, AVLD2R:
  2650. expect = 2
  2651. case AVLD3, AVST3, AVLD3R:
  2652. expect = 3
  2653. case AVLD4, AVST4, AVLD4R:
  2654. expect = 4
  2655. }
  2656. if expect != n {
  2657. c.ctxt.Diag("expected %d registers, got %d: %v.", expect, n, p)
  2658. }
  2659. }
  2660. /* checkShiftAmount checks whether the index shift amount is valid */
  2661. /* for load with register offset instructions */
  2662. func (c *ctxt7) checkShiftAmount(p *obj.Prog, a *obj.Addr) {
  2663. var amount int16
  2664. amount = (a.Index >> 5) & 7
  2665. switch p.As {
  2666. case AMOVB, AMOVBU:
  2667. if amount != 0 {
  2668. c.ctxt.Diag("invalid index shift amount: %v", p)
  2669. }
  2670. case AMOVH, AMOVHU:
  2671. if amount != 1 && amount != 0 {
  2672. c.ctxt.Diag("invalid index shift amount: %v", p)
  2673. }
  2674. case AMOVW, AMOVWU, AFMOVS:
  2675. if amount != 2 && amount != 0 {
  2676. c.ctxt.Diag("invalid index shift amount: %v", p)
  2677. }
  2678. case AMOVD, AFMOVD:
  2679. if amount != 3 && amount != 0 {
  2680. c.ctxt.Diag("invalid index shift amount: %v", p)
  2681. }
  2682. default:
  2683. panic("invalid operation")
  2684. }
  2685. }
  2686. func (c *ctxt7) asmout(p *obj.Prog, o *Optab, out []uint32) {
  2687. var os [5]uint32
  2688. o1 := uint32(0)
  2689. o2 := uint32(0)
  2690. o3 := uint32(0)
  2691. o4 := uint32(0)
  2692. o5 := uint32(0)
  2693. if false { /*debug['P']*/
  2694. fmt.Printf("%x: %v\ttype %d\n", uint32(p.Pc), p, o.type_)
  2695. }
  2696. switch o.type_ {
  2697. default:
  2698. c.ctxt.Diag("%v: unknown asm %d", p, o.type_)
  2699. case 0: /* pseudo ops */
  2700. break
  2701. case 1: /* op Rm,[Rn],Rd; default Rn=Rd -> op Rm<<0,[Rn,]Rd (shifted register) */
  2702. o1 = c.oprrr(p, p.As)
  2703. rf := int(p.From.Reg)
  2704. rt := int(p.To.Reg)
  2705. r := int(p.Reg)
  2706. if p.To.Type == obj.TYPE_NONE {
  2707. rt = REGZERO
  2708. }
  2709. if r == 0 {
  2710. r = rt
  2711. }
  2712. o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  2713. case 2: /* add/sub $(uimm12|uimm24)[,R],R; cmp $(uimm12|uimm24),R */
  2714. o1 = c.opirr(p, p.As)
  2715. rt := int(p.To.Reg)
  2716. if p.To.Type == obj.TYPE_NONE {
  2717. if (o1 & Sbit) == 0 {
  2718. c.ctxt.Diag("ineffective ZR destination\n%v", p)
  2719. }
  2720. rt = REGZERO
  2721. }
  2722. r := int(p.Reg)
  2723. if r == 0 {
  2724. r = rt
  2725. }
  2726. v := int32(c.regoff(&p.From))
  2727. o1 = c.oaddi(p, int32(o1), v, r, rt)
  2728. case 3: /* op R<<n[,R],R (shifted register) */
  2729. o1 = c.oprrr(p, p.As)
  2730. amount := (p.From.Offset >> 10) & 63
  2731. is64bit := o1 & (1 << 31)
  2732. if is64bit == 0 && amount >= 32 {
  2733. c.ctxt.Diag("shift amount out of range 0 to 31: %v", p)
  2734. }
  2735. o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
  2736. rt := int(p.To.Reg)
  2737. if p.To.Type == obj.TYPE_NONE {
  2738. rt = REGZERO
  2739. }
  2740. r := int(p.Reg)
  2741. if p.As == AMVN || p.As == AMVNW {
  2742. r = REGZERO
  2743. } else if r == 0 {
  2744. r = rt
  2745. }
  2746. o1 |= (uint32(r&31) << 5) | uint32(rt&31)
  2747. case 4: /* mov $addcon, R; mov $recon, R; mov $racon, R; mov $addcon2, R */
  2748. rt := int(p.To.Reg)
  2749. r := int(o.param)
  2750. if r == 0 {
  2751. r = REGZERO
  2752. } else if r == REGFROM {
  2753. r = int(p.From.Reg)
  2754. }
  2755. if r == 0 {
  2756. r = REGSP
  2757. }
  2758. v := int32(c.regoff(&p.From))
  2759. var op int32
  2760. if v < 0 {
  2761. v = -v
  2762. op = int32(c.opirr(p, ASUB))
  2763. } else {
  2764. op = int32(c.opirr(p, AADD))
  2765. }
  2766. if int(o.size) == 8 {
  2767. o1 = c.oaddi(p, op, v&0xfff000, r, REGTMP)
  2768. o2 = c.oaddi(p, op, v&0x000fff, REGTMP, rt)
  2769. break
  2770. }
  2771. o1 = c.oaddi(p, op, v, r, rt)
  2772. case 5: /* b s; bl s */
  2773. o1 = c.opbra(p, p.As)
  2774. if p.To.Sym == nil {
  2775. o1 |= uint32(c.brdist(p, 0, 26, 2))
  2776. break
  2777. }
  2778. rel := obj.Addrel(c.cursym)
  2779. rel.Off = int32(c.pc)
  2780. rel.Siz = 4
  2781. rel.Sym = p.To.Sym
  2782. rel.Add = p.To.Offset
  2783. rel.Type = objabi.R_CALLARM64
  2784. case 6: /* b ,O(R); bl ,O(R) */
  2785. o1 = c.opbrr(p, p.As)
  2786. o1 |= uint32(p.To.Reg&31) << 5
  2787. rel := obj.Addrel(c.cursym)
  2788. rel.Off = int32(c.pc)
  2789. rel.Siz = 0
  2790. rel.Type = objabi.R_CALLIND
  2791. case 7: /* beq s */
  2792. o1 = c.opbra(p, p.As)
  2793. o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
  2794. case 8: /* lsl $c,[R],R -> ubfm $(W-1)-c,$(-c MOD (W-1)),Rn,Rd */
  2795. rt := int(p.To.Reg)
  2796. rf := int(p.Reg)
  2797. if rf == 0 {
  2798. rf = rt
  2799. }
  2800. v := int32(p.From.Offset)
  2801. switch p.As {
  2802. case AASR:
  2803. o1 = c.opbfm(p, ASBFM, int(v), 63, rf, rt)
  2804. case AASRW:
  2805. o1 = c.opbfm(p, ASBFMW, int(v), 31, rf, rt)
  2806. case ALSL:
  2807. o1 = c.opbfm(p, AUBFM, int((64-v)&63), int(63-v), rf, rt)
  2808. case ALSLW:
  2809. o1 = c.opbfm(p, AUBFMW, int((32-v)&31), int(31-v), rf, rt)
  2810. case ALSR:
  2811. o1 = c.opbfm(p, AUBFM, int(v), 63, rf, rt)
  2812. case ALSRW:
  2813. o1 = c.opbfm(p, AUBFMW, int(v), 31, rf, rt)
  2814. case AROR:
  2815. o1 = c.opextr(p, AEXTR, v, rf, rf, rt)
  2816. case ARORW:
  2817. o1 = c.opextr(p, AEXTRW, v, rf, rf, rt)
  2818. default:
  2819. c.ctxt.Diag("bad shift $con\n%v", p)
  2820. break
  2821. }
  2822. case 9: /* lsl Rm,[Rn],Rd -> lslv Rm, Rn, Rd */
  2823. o1 = c.oprrr(p, p.As)
  2824. r := int(p.Reg)
  2825. if r == 0 {
  2826. r = int(p.To.Reg)
  2827. }
  2828. o1 |= (uint32(p.From.Reg&31) << 16) | (uint32(r&31) << 5) | uint32(p.To.Reg&31)
  2829. case 10: /* brk/hvc/.../svc [$con] */
  2830. o1 = c.opimm(p, p.As)
  2831. if p.From.Type != obj.TYPE_NONE {
  2832. o1 |= uint32((p.From.Offset & 0xffff) << 5)
  2833. }
  2834. case 11: /* dword */
  2835. c.aclass(&p.To)
  2836. o1 = uint32(c.instoffset)
  2837. o2 = uint32(c.instoffset >> 32)
  2838. if p.To.Sym != nil {
  2839. rel := obj.Addrel(c.cursym)
  2840. rel.Off = int32(c.pc)
  2841. rel.Siz = 8
  2842. rel.Sym = p.To.Sym
  2843. rel.Add = p.To.Offset
  2844. rel.Type = objabi.R_ADDR
  2845. o2 = 0
  2846. o1 = o2
  2847. }
  2848. case 12: /* movT $vcon, reg */
  2849. // NOTE: this case does not use REGTMP. If it ever does,
  2850. // remove the NOTUSETMP flag in optab.
  2851. num := c.omovlconst(p.As, p, &p.From, int(p.To.Reg), os[:])
  2852. if num == 0 {
  2853. c.ctxt.Diag("invalid constant: %v", p)
  2854. }
  2855. o1 = os[0]
  2856. o2 = os[1]
  2857. o3 = os[2]
  2858. o4 = os[3]
  2859. case 13: /* addop $vcon, [R], R (64 bit literal); cmp $lcon,R -> addop $lcon,R, ZR */
  2860. o := uint32(0)
  2861. num := uint8(0)
  2862. cls := oclass(&p.From)
  2863. if isADDWop(p.As) {
  2864. if !cmp(C_LCON, cls) {
  2865. c.ctxt.Diag("illegal combination: %v", p)
  2866. }
  2867. num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
  2868. } else {
  2869. num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
  2870. }
  2871. if num == 0 {
  2872. c.ctxt.Diag("invalid constant: %v", p)
  2873. }
  2874. rt := int(p.To.Reg)
  2875. if p.To.Type == obj.TYPE_NONE {
  2876. rt = REGZERO
  2877. }
  2878. r := int(p.Reg)
  2879. if r == 0 {
  2880. r = rt
  2881. }
  2882. if p.To.Type != obj.TYPE_NONE && (p.To.Reg == REGSP || r == REGSP) {
  2883. o = c.opxrrr(p, p.As, false)
  2884. o |= REGTMP & 31 << 16
  2885. o |= LSL0_64
  2886. } else {
  2887. o = c.oprrr(p, p.As)
  2888. o |= REGTMP & 31 << 16 /* shift is 0 */
  2889. }
  2890. o |= uint32(r&31) << 5
  2891. o |= uint32(rt & 31)
  2892. os[num] = o
  2893. o1 = os[0]
  2894. o2 = os[1]
  2895. o3 = os[2]
  2896. o4 = os[3]
  2897. o5 = os[4]
  2898. case 14: /* word */
  2899. if c.aclass(&p.To) == C_ADDR {
  2900. c.ctxt.Diag("address constant needs DWORD\n%v", p)
  2901. }
  2902. o1 = uint32(c.instoffset)
  2903. if p.To.Sym != nil {
  2904. // This case happens with words generated
  2905. // in the PC stream as part of the literal pool.
  2906. rel := obj.Addrel(c.cursym)
  2907. rel.Off = int32(c.pc)
  2908. rel.Siz = 4
  2909. rel.Sym = p.To.Sym
  2910. rel.Add = p.To.Offset
  2911. rel.Type = objabi.R_ADDR
  2912. o1 = 0
  2913. }
  2914. case 15: /* mul/mneg/umulh/umull r,[r,]r; madd/msub/fmadd/fmsub/fnmadd/fnmsub Rm,Ra,Rn,Rd */
  2915. o1 = c.oprrr(p, p.As)
  2916. rf := int(p.From.Reg)
  2917. rt := int(p.To.Reg)
  2918. var r int
  2919. var ra int
  2920. if p.From3Type() == obj.TYPE_REG {
  2921. r = int(p.GetFrom3().Reg)
  2922. ra = int(p.Reg)
  2923. if ra == 0 {
  2924. ra = REGZERO
  2925. }
  2926. } else {
  2927. r = int(p.Reg)
  2928. if r == 0 {
  2929. r = rt
  2930. }
  2931. ra = REGZERO
  2932. }
  2933. o1 |= (uint32(rf&31) << 16) | (uint32(ra&31) << 10) | (uint32(r&31) << 5) | uint32(rt&31)
  2934. case 16: /* XremY R[,R],R -> XdivY; XmsubY */
  2935. o1 = c.oprrr(p, p.As)
  2936. rf := int(p.From.Reg)
  2937. rt := int(p.To.Reg)
  2938. r := int(p.Reg)
  2939. if r == 0 {
  2940. r = rt
  2941. }
  2942. o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | REGTMP&31
  2943. o2 = c.oprrr(p, AMSUBW)
  2944. o2 |= o1 & (1 << 31) /* same size */
  2945. o2 |= (uint32(rf&31) << 16) | (uint32(r&31) << 10) | (REGTMP & 31 << 5) | uint32(rt&31)
  2946. case 17: /* op Rm,[Rn],Rd; default Rn=ZR */
  2947. o1 = c.oprrr(p, p.As)
  2948. rf := int(p.From.Reg)
  2949. rt := int(p.To.Reg)
  2950. r := int(p.Reg)
  2951. if p.To.Type == obj.TYPE_NONE {
  2952. rt = REGZERO
  2953. }
  2954. if r == 0 {
  2955. r = REGZERO
  2956. }
  2957. o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  2958. case 18: /* csel cond,Rn,Rm,Rd; cinc/cinv/cneg cond,Rn,Rd; cset cond,Rd */
  2959. o1 = c.oprrr(p, p.As)
  2960. cond := int(p.From.Reg)
  2961. if cond < COND_EQ || cond > COND_NV {
  2962. c.ctxt.Diag("invalid condition: %v", p)
  2963. } else {
  2964. cond -= COND_EQ
  2965. }
  2966. r := int(p.Reg)
  2967. var rf int
  2968. if r != 0 {
  2969. if p.From3Type() == obj.TYPE_NONE {
  2970. /* CINC/CINV/CNEG */
  2971. rf = r
  2972. cond ^= 1
  2973. } else {
  2974. rf = int(p.GetFrom3().Reg) /* CSEL */
  2975. }
  2976. } else {
  2977. /* CSET */
  2978. rf = REGZERO
  2979. r = rf
  2980. cond ^= 1
  2981. }
  2982. rt := int(p.To.Reg)
  2983. o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(r&31) << 5) | uint32(rt&31)
  2984. case 19: /* CCMN cond, (Rm|uimm5),Rn, uimm4 -> ccmn Rn,Rm,uimm4,cond */
  2985. nzcv := int(p.To.Offset)
  2986. cond := int(p.From.Reg)
  2987. if cond < COND_EQ || cond > COND_NV {
  2988. c.ctxt.Diag("invalid condition\n%v", p)
  2989. } else {
  2990. cond -= COND_EQ
  2991. }
  2992. var rf int
  2993. if p.GetFrom3().Type == obj.TYPE_REG {
  2994. o1 = c.oprrr(p, p.As)
  2995. rf = int(p.GetFrom3().Reg) /* Rm */
  2996. } else {
  2997. o1 = c.opirr(p, p.As)
  2998. rf = int(p.GetFrom3().Offset & 0x1F)
  2999. }
  3000. o1 |= (uint32(rf&31) << 16) | (uint32(cond&15) << 12) | (uint32(p.Reg&31) << 5) | uint32(nzcv)
  3001. case 20: /* movT R,O(R) -> strT */
  3002. v := int32(c.regoff(&p.To))
  3003. sz := int32(1 << uint(movesize(p.As)))
  3004. r := int(p.To.Reg)
  3005. if r == 0 {
  3006. r = int(o.param)
  3007. }
  3008. if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
  3009. o1 = c.olsr9s(p, int32(c.opstr9(p, p.As)), v, r, int(p.From.Reg))
  3010. } else {
  3011. v = int32(c.offsetshift(p, int64(v), int(o.a4)))
  3012. o1 = c.olsr12u(p, int32(c.opstr12(p, p.As)), v, r, int(p.From.Reg))
  3013. }
  3014. case 21: /* movT O(R),R -> ldrT */
  3015. v := int32(c.regoff(&p.From))
  3016. sz := int32(1 << uint(movesize(p.As)))
  3017. r := int(p.From.Reg)
  3018. if r == 0 {
  3019. r = int(o.param)
  3020. }
  3021. if v < 0 || v%sz != 0 { /* unscaled 9-bit signed */
  3022. o1 = c.olsr9s(p, int32(c.opldr9(p, p.As)), v, r, int(p.To.Reg))
  3023. } else {
  3024. v = int32(c.offsetshift(p, int64(v), int(o.a1)))
  3025. //print("offset=%lld v=%ld a1=%d\n", instoffset, v, o->a1);
  3026. o1 = c.olsr12u(p, int32(c.opldr12(p, p.As)), v, r, int(p.To.Reg))
  3027. }
  3028. case 22: /* movT (R)O!,R; movT O(R)!, R -> ldrT */
  3029. if p.From.Reg != REGSP && p.From.Reg == p.To.Reg {
  3030. c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3031. }
  3032. v := int32(p.From.Offset)
  3033. if v < -256 || v > 255 {
  3034. c.ctxt.Diag("offset out of range [-255,254]: %v", p)
  3035. }
  3036. o1 = c.opldrpp(p, p.As)
  3037. if o.scond == C_XPOST {
  3038. o1 |= 1 << 10
  3039. } else {
  3040. o1 |= 3 << 10
  3041. }
  3042. o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.From.Reg&31) << 5) | uint32(p.To.Reg&31)
  3043. case 23: /* movT R,(R)O!; movT O(R)!, R -> strT */
  3044. if p.To.Reg != REGSP && p.From.Reg == p.To.Reg {
  3045. c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3046. }
  3047. v := int32(p.To.Offset)
  3048. if v < -256 || v > 255 {
  3049. c.ctxt.Diag("offset out of range [-255,254]: %v", p)
  3050. }
  3051. o1 = LD2STR(c.opldrpp(p, p.As))
  3052. if o.scond == C_XPOST {
  3053. o1 |= 1 << 10
  3054. } else {
  3055. o1 |= 3 << 10
  3056. }
  3057. o1 |= ((uint32(v) & 0x1FF) << 12) | (uint32(p.To.Reg&31) << 5) | uint32(p.From.Reg&31)
  3058. case 24: /* mov/mvn Rs,Rd -> add $0,Rs,Rd or orr Rs,ZR,Rd */
  3059. rf := int(p.From.Reg)
  3060. rt := int(p.To.Reg)
  3061. s := rf == REGSP || rt == REGSP
  3062. if p.As == AMVN || p.As == AMVNW {
  3063. if s {
  3064. c.ctxt.Diag("illegal SP reference\n%v", p)
  3065. }
  3066. o1 = c.oprrr(p, p.As)
  3067. o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  3068. } else if s {
  3069. o1 = c.opirr(p, p.As)
  3070. o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  3071. } else {
  3072. o1 = c.oprrr(p, p.As)
  3073. o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  3074. }
  3075. case 25: /* negX Rs, Rd -> subX Rs<<0, ZR, Rd */
  3076. o1 = c.oprrr(p, p.As)
  3077. rf := int(p.From.Reg)
  3078. if rf == C_NONE {
  3079. rf = int(p.To.Reg)
  3080. }
  3081. rt := int(p.To.Reg)
  3082. o1 |= (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  3083. case 26: /* negX Rm<<s, Rd -> subX Rm<<s, ZR, Rd */
  3084. o1 = c.oprrr(p, p.As)
  3085. o1 |= uint32(p.From.Offset) /* includes reg, op, etc */
  3086. rt := int(p.To.Reg)
  3087. o1 |= (REGZERO & 31 << 5) | uint32(rt&31)
  3088. case 27: /* op Rm<<n[,Rn],Rd (extended register) */
  3089. if (p.From.Reg-obj.RBaseARM64)&REG_EXT != 0 {
  3090. amount := (p.From.Reg >> 5) & 7
  3091. if amount > 4 {
  3092. c.ctxt.Diag("shift amount out of range 0 to 4: %v", p)
  3093. }
  3094. o1 = c.opxrrr(p, p.As, true)
  3095. o1 |= c.encRegShiftOrExt(&p.From, p.From.Reg) /* includes reg, op, etc */
  3096. } else {
  3097. o1 = c.opxrrr(p, p.As, false)
  3098. o1 |= uint32(p.From.Reg&31) << 16
  3099. }
  3100. rt := int(p.To.Reg)
  3101. if p.To.Type == obj.TYPE_NONE {
  3102. rt = REGZERO
  3103. }
  3104. r := int(p.Reg)
  3105. if r == 0 {
  3106. r = rt
  3107. }
  3108. o1 |= (uint32(r&31) << 5) | uint32(rt&31)
  3109. case 28: /* logop $vcon, [R], R (64 bit literal) */
  3110. o := uint32(0)
  3111. num := uint8(0)
  3112. cls := oclass(&p.From)
  3113. if isANDWop(p.As) {
  3114. if !cmp(C_LCON, cls) {
  3115. c.ctxt.Diag("illegal combination: %v", p)
  3116. }
  3117. num = c.omovlconst(AMOVW, p, &p.From, REGTMP, os[:])
  3118. } else {
  3119. num = c.omovlconst(AMOVD, p, &p.From, REGTMP, os[:])
  3120. }
  3121. if num == 0 {
  3122. c.ctxt.Diag("invalid constant: %v", p)
  3123. }
  3124. rt := int(p.To.Reg)
  3125. if p.To.Type == obj.TYPE_NONE {
  3126. rt = REGZERO
  3127. }
  3128. r := int(p.Reg)
  3129. if r == 0 {
  3130. r = rt
  3131. }
  3132. o = c.oprrr(p, p.As)
  3133. o |= REGTMP & 31 << 16 /* shift is 0 */
  3134. o |= uint32(r&31) << 5
  3135. o |= uint32(rt & 31)
  3136. os[num] = o
  3137. o1 = os[0]
  3138. o2 = os[1]
  3139. o3 = os[2]
  3140. o4 = os[3]
  3141. o5 = os[4]
  3142. case 29: /* op Rn, Rd */
  3143. fc := c.aclass(&p.From)
  3144. tc := c.aclass(&p.To)
  3145. if (p.As == AFMOVD || p.As == AFMOVS) && (fc == C_REG || fc == C_ZCON || tc == C_REG || tc == C_ZCON) {
  3146. // FMOV Rx, Fy or FMOV Fy, Rx
  3147. o1 = FPCVTI(0, 0, 0, 0, 6)
  3148. if p.As == AFMOVD {
  3149. o1 |= 1<<31 | 1<<22 // 64-bit
  3150. }
  3151. if fc == C_REG || fc == C_ZCON {
  3152. o1 |= 1 << 16 // FMOV Rx, Fy
  3153. }
  3154. } else {
  3155. o1 = c.oprrr(p, p.As)
  3156. }
  3157. o1 |= uint32(p.From.Reg&31)<<5 | uint32(p.To.Reg&31)
  3158. case 30: /* movT R,L(R) -> strT */
  3159. // if offset L can be split into hi+lo, and both fit into instructions, do
  3160. // add $hi, R, Rtmp
  3161. // str R, lo(Rtmp)
  3162. // otherwise, use constant pool
  3163. // mov $L, Rtmp (from constant pool)
  3164. // str R, (R+Rtmp)
  3165. s := movesize(o.as)
  3166. if s < 0 {
  3167. c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
  3168. }
  3169. r := int(p.To.Reg)
  3170. if r == 0 {
  3171. r = int(o.param)
  3172. }
  3173. v := int32(c.regoff(&p.To))
  3174. var hi int32
  3175. if v < 0 || (v&((1<<uint(s))-1)) != 0 {
  3176. // negative or unaligned offset, use constant pool
  3177. goto storeusepool
  3178. }
  3179. hi = v - (v & (0xFFF << uint(s)))
  3180. if hi&0xFFF != 0 {
  3181. c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
  3182. }
  3183. if hi&^0xFFF000 != 0 {
  3184. // hi doesn't fit into an ADD instruction
  3185. goto storeusepool
  3186. }
  3187. o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
  3188. o2 = c.olsr12u(p, int32(c.opstr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.From.Reg))
  3189. break
  3190. storeusepool:
  3191. if r == REGTMP || p.From.Reg == REGTMP {
  3192. c.ctxt.Diag("REGTMP used in large offset store: %v", p)
  3193. }
  3194. o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
  3195. o2 = c.olsxrr(p, int32(c.opstrr(p, p.As, false)), int(p.From.Reg), r, REGTMP)
  3196. case 31: /* movT L(R), R -> ldrT */
  3197. // if offset L can be split into hi+lo, and both fit into instructions, do
  3198. // add $hi, R, Rtmp
  3199. // ldr lo(Rtmp), R
  3200. // otherwise, use constant pool
  3201. // mov $L, Rtmp (from constant pool)
  3202. // ldr (R+Rtmp), R
  3203. s := movesize(o.as)
  3204. if s < 0 {
  3205. c.ctxt.Diag("unexpected long move, op %v tab %v\n%v", p.As, o.as, p)
  3206. }
  3207. r := int(p.From.Reg)
  3208. if r == 0 {
  3209. r = int(o.param)
  3210. }
  3211. v := int32(c.regoff(&p.From))
  3212. var hi int32
  3213. if v < 0 || (v&((1<<uint(s))-1)) != 0 {
  3214. // negative or unaligned offset, use constant pool
  3215. goto loadusepool
  3216. }
  3217. hi = v - (v & (0xFFF << uint(s)))
  3218. if (hi & 0xFFF) != 0 {
  3219. c.ctxt.Diag("internal: miscalculated offset %d [%d]\n%v", v, s, p)
  3220. }
  3221. if hi&^0xFFF000 != 0 {
  3222. // hi doesn't fit into an ADD instruction
  3223. goto loadusepool
  3224. }
  3225. o1 = c.oaddi(p, int32(c.opirr(p, AADD)), hi, r, REGTMP)
  3226. o2 = c.olsr12u(p, int32(c.opldr12(p, p.As)), ((v-hi)>>uint(s))&0xFFF, REGTMP, int(p.To.Reg))
  3227. break
  3228. loadusepool:
  3229. if r == REGTMP || p.From.Reg == REGTMP {
  3230. c.ctxt.Diag("REGTMP used in large offset load: %v", p)
  3231. }
  3232. o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  3233. o2 = c.olsxrr(p, int32(c.opldrr(p, p.As, false)), int(p.To.Reg), r, REGTMP)
  3234. case 32: /* mov $con, R -> movz/movn */
  3235. o1 = c.omovconst(p.As, p, &p.From, int(p.To.Reg))
  3236. case 33: /* movk $uimm16 << pos */
  3237. o1 = c.opirr(p, p.As)
  3238. d := p.From.Offset
  3239. s := movcon(d)
  3240. if s < 0 || s >= 4 {
  3241. c.ctxt.Diag("bad constant for MOVK: %#x\n%v", uint64(d), p)
  3242. }
  3243. if (o1&S64) == 0 && s >= 2 {
  3244. c.ctxt.Diag("illegal bit position\n%v", p)
  3245. }
  3246. if ((d >> uint(s*16)) >> 16) != 0 {
  3247. c.ctxt.Diag("requires uimm16\n%v", p)
  3248. }
  3249. rt := int(p.To.Reg)
  3250. o1 |= uint32((((d >> uint(s*16)) & 0xFFFF) << 5) | int64((uint32(s)&3)<<21) | int64(rt&31))
  3251. case 34: /* mov $lacon,R */
  3252. o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  3253. if o1 == 0 {
  3254. break
  3255. }
  3256. o2 = c.opxrrr(p, AADD, false)
  3257. o2 |= REGTMP & 31 << 16
  3258. o2 |= LSL0_64
  3259. r := int(p.From.Reg)
  3260. if r == 0 {
  3261. r = int(o.param)
  3262. }
  3263. o2 |= uint32(r&31) << 5
  3264. o2 |= uint32(p.To.Reg & 31)
  3265. case 35: /* mov SPR,R -> mrs */
  3266. o1 = c.oprrr(p, AMRS)
  3267. // SysRegEnc function returns the system register encoding and accessFlags.
  3268. _, v, accessFlags := SysRegEnc(p.From.Reg)
  3269. if v == 0 {
  3270. c.ctxt.Diag("illegal system register:\n%v", p)
  3271. }
  3272. if (o1 & (v &^ (3 << 19))) != 0 {
  3273. c.ctxt.Diag("MRS register value overlap\n%v", p)
  3274. }
  3275. if accessFlags&SR_READ == 0 {
  3276. c.ctxt.Diag("system register is not readable: %v", p)
  3277. }
  3278. o1 |= v
  3279. o1 |= uint32(p.To.Reg & 31)
  3280. case 36: /* mov R,SPR */
  3281. o1 = c.oprrr(p, AMSR)
  3282. // SysRegEnc function returns the system register encoding and accessFlags.
  3283. _, v, accessFlags := SysRegEnc(p.To.Reg)
  3284. if v == 0 {
  3285. c.ctxt.Diag("illegal system register:\n%v", p)
  3286. }
  3287. if (o1 & (v &^ (3 << 19))) != 0 {
  3288. c.ctxt.Diag("MSR register value overlap\n%v", p)
  3289. }
  3290. if accessFlags&SR_WRITE == 0 {
  3291. c.ctxt.Diag("system register is not writable: %v", p)
  3292. }
  3293. o1 |= v
  3294. o1 |= uint32(p.From.Reg & 31)
  3295. case 37: /* mov $con,PSTATEfield -> MSR [immediate] */
  3296. if (uint64(p.From.Offset) &^ uint64(0xF)) != 0 {
  3297. c.ctxt.Diag("illegal immediate for PSTATE field\n%v", p)
  3298. }
  3299. o1 = c.opirr(p, AMSR)
  3300. o1 |= uint32((p.From.Offset & 0xF) << 8) /* Crm */
  3301. v := uint32(0)
  3302. for i := 0; i < len(pstatefield); i++ {
  3303. if pstatefield[i].reg == p.To.Reg {
  3304. v = pstatefield[i].enc
  3305. break
  3306. }
  3307. }
  3308. if v == 0 {
  3309. c.ctxt.Diag("illegal PSTATE field for immediate move\n%v", p)
  3310. }
  3311. o1 |= v
  3312. case 38: /* clrex [$imm] */
  3313. o1 = c.opimm(p, p.As)
  3314. if p.To.Type == obj.TYPE_NONE {
  3315. o1 |= 0xF << 8
  3316. } else {
  3317. o1 |= uint32((p.To.Offset & 0xF) << 8)
  3318. }
  3319. case 39: /* cbz R, rel */
  3320. o1 = c.opirr(p, p.As)
  3321. o1 |= uint32(p.From.Reg & 31)
  3322. o1 |= uint32(c.brdist(p, 0, 19, 2) << 5)
  3323. case 40: /* tbz */
  3324. o1 = c.opirr(p, p.As)
  3325. v := int32(p.From.Offset)
  3326. if v < 0 || v > 63 {
  3327. c.ctxt.Diag("illegal bit number\n%v", p)
  3328. }
  3329. o1 |= ((uint32(v) & 0x20) << (31 - 5)) | ((uint32(v) & 0x1F) << 19)
  3330. o1 |= uint32(c.brdist(p, 0, 14, 2) << 5)
  3331. o1 |= uint32(p.Reg & 31)
  3332. case 41: /* eret, nop, others with no operands */
  3333. o1 = c.op0(p, p.As)
  3334. case 42: /* bfm R,r,s,R */
  3335. o1 = c.opbfm(p, p.As, int(p.From.Offset), int(p.GetFrom3().Offset), int(p.Reg), int(p.To.Reg))
  3336. case 43: /* bfm aliases */
  3337. r := int(p.From.Offset)
  3338. s := int(p.GetFrom3().Offset)
  3339. rf := int(p.Reg)
  3340. rt := int(p.To.Reg)
  3341. if rf == 0 {
  3342. rf = rt
  3343. }
  3344. switch p.As {
  3345. case ABFI:
  3346. if r != 0 {
  3347. r = 64 - r
  3348. }
  3349. o1 = c.opbfm(p, ABFM, r, s-1, rf, rt)
  3350. case ABFIW:
  3351. if r != 0 {
  3352. r = 32 - r
  3353. }
  3354. o1 = c.opbfm(p, ABFMW, r, s-1, rf, rt)
  3355. case ABFXIL:
  3356. o1 = c.opbfm(p, ABFM, r, r+s-1, rf, rt)
  3357. case ABFXILW:
  3358. o1 = c.opbfm(p, ABFMW, r, r+s-1, rf, rt)
  3359. case ASBFIZ:
  3360. if r != 0 {
  3361. r = 64 - r
  3362. }
  3363. o1 = c.opbfm(p, ASBFM, r, s-1, rf, rt)
  3364. case ASBFIZW:
  3365. if r != 0 {
  3366. r = 32 - r
  3367. }
  3368. o1 = c.opbfm(p, ASBFMW, r, s-1, rf, rt)
  3369. case ASBFX:
  3370. o1 = c.opbfm(p, ASBFM, r, r+s-1, rf, rt)
  3371. case ASBFXW:
  3372. o1 = c.opbfm(p, ASBFMW, r, r+s-1, rf, rt)
  3373. case AUBFIZ:
  3374. if r != 0 {
  3375. r = 64 - r
  3376. }
  3377. o1 = c.opbfm(p, AUBFM, r, s-1, rf, rt)
  3378. case AUBFIZW:
  3379. if r != 0 {
  3380. r = 32 - r
  3381. }
  3382. o1 = c.opbfm(p, AUBFMW, r, s-1, rf, rt)
  3383. case AUBFX:
  3384. o1 = c.opbfm(p, AUBFM, r, r+s-1, rf, rt)
  3385. case AUBFXW:
  3386. o1 = c.opbfm(p, AUBFMW, r, r+s-1, rf, rt)
  3387. default:
  3388. c.ctxt.Diag("bad bfm alias\n%v", p)
  3389. break
  3390. }
  3391. case 44: /* extr $b, Rn, Rm, Rd */
  3392. o1 = c.opextr(p, p.As, int32(p.From.Offset), int(p.GetFrom3().Reg), int(p.Reg), int(p.To.Reg))
  3393. case 45: /* sxt/uxt[bhw] R,R; movT R,R -> sxtT R,R */
  3394. rf := int(p.From.Reg)
  3395. rt := int(p.To.Reg)
  3396. as := p.As
  3397. if rf == REGZERO {
  3398. as = AMOVWU /* clearer in disassembly */
  3399. }
  3400. switch as {
  3401. case AMOVB, ASXTB:
  3402. o1 = c.opbfm(p, ASBFM, 0, 7, rf, rt)
  3403. case AMOVH, ASXTH:
  3404. o1 = c.opbfm(p, ASBFM, 0, 15, rf, rt)
  3405. case AMOVW, ASXTW:
  3406. o1 = c.opbfm(p, ASBFM, 0, 31, rf, rt)
  3407. case AMOVBU, AUXTB:
  3408. o1 = c.opbfm(p, AUBFM, 0, 7, rf, rt)
  3409. case AMOVHU, AUXTH:
  3410. o1 = c.opbfm(p, AUBFM, 0, 15, rf, rt)
  3411. case AMOVWU:
  3412. o1 = c.oprrr(p, as) | (uint32(rf&31) << 16) | (REGZERO & 31 << 5) | uint32(rt&31)
  3413. case AUXTW:
  3414. o1 = c.opbfm(p, AUBFM, 0, 31, rf, rt)
  3415. case ASXTBW:
  3416. o1 = c.opbfm(p, ASBFMW, 0, 7, rf, rt)
  3417. case ASXTHW:
  3418. o1 = c.opbfm(p, ASBFMW, 0, 15, rf, rt)
  3419. case AUXTBW:
  3420. o1 = c.opbfm(p, AUBFMW, 0, 7, rf, rt)
  3421. case AUXTHW:
  3422. o1 = c.opbfm(p, AUBFMW, 0, 15, rf, rt)
  3423. default:
  3424. c.ctxt.Diag("bad sxt %v", as)
  3425. break
  3426. }
  3427. case 46: /* cls */
  3428. o1 = c.opbit(p, p.As)
  3429. o1 |= uint32(p.From.Reg&31) << 5
  3430. o1 |= uint32(p.To.Reg & 31)
  3431. case 47: /* SWPx/LDADDx/LDANDx/LDEORx/LDORx Rs, (Rb), Rt */
  3432. rs := p.From.Reg
  3433. rt := p.RegTo2
  3434. rb := p.To.Reg
  3435. fields := atomicInstructions[p.As]
  3436. // rt can't be sp. rt can't be r31 when field A is 0, A bit is the 23rd bit.
  3437. if rt == REG_RSP || (rt == REGZERO && (fields&(1<<23) == 0)) {
  3438. c.ctxt.Diag("illegal destination register: %v\n", p)
  3439. }
  3440. o1 |= fields | uint32(rs&31)<<16 | uint32(rb&31)<<5 | uint32(rt&31)
  3441. case 48: /* ADD $C_ADDCON2, Rm, Rd */
  3442. // NOTE: this case does not use REGTMP. If it ever does,
  3443. // remove the NOTUSETMP flag in optab.
  3444. op := c.opirr(p, p.As)
  3445. if op&Sbit != 0 {
  3446. c.ctxt.Diag("can not break addition/subtraction when S bit is set", p)
  3447. }
  3448. rt := int(p.To.Reg)
  3449. r := int(p.Reg)
  3450. if r == 0 {
  3451. r = rt
  3452. }
  3453. o1 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0x000fff, r, rt)
  3454. o2 = c.oaddi(p, int32(op), int32(c.regoff(&p.From))&0xfff000, rt, rt)
  3455. case 50: /* sys/sysl */
  3456. o1 = c.opirr(p, p.As)
  3457. if (p.From.Offset &^ int64(SYSARG4(0x7, 0xF, 0xF, 0x7))) != 0 {
  3458. c.ctxt.Diag("illegal SYS argument\n%v", p)
  3459. }
  3460. o1 |= uint32(p.From.Offset)
  3461. if p.To.Type == obj.TYPE_REG {
  3462. o1 |= uint32(p.To.Reg & 31)
  3463. } else if p.Reg != 0 {
  3464. o1 |= uint32(p.Reg & 31)
  3465. } else {
  3466. o1 |= 0x1F
  3467. }
  3468. case 51: /* dmb */
  3469. o1 = c.opirr(p, p.As)
  3470. if p.From.Type == obj.TYPE_CONST {
  3471. o1 |= uint32((p.From.Offset & 0xF) << 8)
  3472. }
  3473. case 52: /* hint */
  3474. o1 = c.opirr(p, p.As)
  3475. o1 |= uint32((p.From.Offset & 0x7F) << 5)
  3476. case 53: /* and/or/eor/bic/tst/... $bitcon, Rn, Rd */
  3477. a := p.As
  3478. rt := int(p.To.Reg)
  3479. if p.To.Type == obj.TYPE_NONE {
  3480. rt = REGZERO
  3481. }
  3482. r := int(p.Reg)
  3483. if r == 0 {
  3484. r = rt
  3485. }
  3486. mode := 64
  3487. v := uint64(p.From.Offset)
  3488. switch p.As {
  3489. case AANDW, AORRW, AEORW, AANDSW, ATSTW:
  3490. mode = 32
  3491. case ABIC, AORN, AEON, ABICS:
  3492. v = ^v
  3493. case ABICW, AORNW, AEONW, ABICSW:
  3494. v = ^v
  3495. mode = 32
  3496. }
  3497. o1 = c.opirr(p, a)
  3498. o1 |= bitconEncode(v, mode) | uint32(r&31)<<5 | uint32(rt&31)
  3499. case 54: /* floating point arith */
  3500. o1 = c.oprrr(p, p.As)
  3501. rf := int(p.From.Reg)
  3502. rt := int(p.To.Reg)
  3503. r := int(p.Reg)
  3504. if (o1&(0x1F<<24)) == (0x1E<<24) && (o1&(1<<11)) == 0 { /* monadic */
  3505. r = rf
  3506. rf = 0
  3507. } else if r == 0 {
  3508. r = rt
  3509. }
  3510. o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  3511. case 55: /* floating-point constant */
  3512. var rf int
  3513. o1 = 0xf<<25 | 1<<21 | 1<<12
  3514. rf = c.chipfloat7(p.From.Val.(float64))
  3515. if rf < 0 {
  3516. c.ctxt.Diag("invalid floating-point immediate\n%v", p)
  3517. }
  3518. if p.As == AFMOVD {
  3519. o1 |= 1 << 22
  3520. }
  3521. o1 |= (uint32(rf&0xff) << 13) | uint32(p.To.Reg&31)
  3522. case 56: /* floating point compare */
  3523. o1 = c.oprrr(p, p.As)
  3524. var rf int
  3525. if p.From.Type == obj.TYPE_FCONST {
  3526. o1 |= 8 /* zero */
  3527. rf = 0
  3528. } else {
  3529. rf = int(p.From.Reg)
  3530. }
  3531. rt := int(p.Reg)
  3532. o1 |= uint32(rf&31)<<16 | uint32(rt&31)<<5
  3533. case 57: /* floating point conditional compare */
  3534. o1 = c.oprrr(p, p.As)
  3535. cond := int(p.From.Reg)
  3536. if cond < COND_EQ || cond > COND_NV {
  3537. c.ctxt.Diag("invalid condition\n%v", p)
  3538. } else {
  3539. cond -= COND_EQ
  3540. }
  3541. nzcv := int(p.To.Offset)
  3542. if nzcv&^0xF != 0 {
  3543. c.ctxt.Diag("implausible condition\n%v", p)
  3544. }
  3545. rf := int(p.Reg)
  3546. if p.GetFrom3() == nil || p.GetFrom3().Reg < REG_F0 || p.GetFrom3().Reg > REG_F31 {
  3547. c.ctxt.Diag("illegal FCCMP\n%v", p)
  3548. break
  3549. }
  3550. rt := int(p.GetFrom3().Reg)
  3551. o1 |= uint32(rf&31)<<16 | uint32(cond&15)<<12 | uint32(rt&31)<<5 | uint32(nzcv)
  3552. case 58: /* ldar/ldarb/ldarh/ldaxp/ldxp/ldaxr/ldxr */
  3553. o1 = c.opload(p, p.As)
  3554. o1 |= 0x1F << 16
  3555. o1 |= uint32(p.From.Reg&31) << 5
  3556. if p.As == ALDXP || p.As == ALDXPW || p.As == ALDAXP || p.As == ALDAXPW {
  3557. if int(p.To.Reg) == int(p.To.Offset) {
  3558. c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3559. }
  3560. o1 |= uint32(p.To.Offset&31) << 10
  3561. } else {
  3562. o1 |= 0x1F << 10
  3563. }
  3564. o1 |= uint32(p.To.Reg & 31)
  3565. case 59: /* stxr/stlxr/stxp/stlxp */
  3566. s := p.RegTo2
  3567. n := p.To.Reg
  3568. t := p.From.Reg
  3569. if isSTLXRop(p.As) {
  3570. if s == t || (s == n && n != REGSP) {
  3571. c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3572. }
  3573. } else if isSTXPop(p.As) {
  3574. t2 := int16(p.From.Offset)
  3575. if (s == t || s == t2) || (s == n && n != REGSP) {
  3576. c.ctxt.Diag("constrained unpredictable behavior: %v", p)
  3577. }
  3578. }
  3579. if s == REG_RSP {
  3580. c.ctxt.Diag("illegal destination register: %v\n", p)
  3581. }
  3582. o1 = c.opstore(p, p.As)
  3583. if p.RegTo2 != obj.REG_NONE {
  3584. o1 |= uint32(p.RegTo2&31) << 16
  3585. } else {
  3586. o1 |= 0x1F << 16
  3587. }
  3588. if isSTXPop(p.As) {
  3589. o1 |= uint32(p.From.Offset&31) << 10
  3590. }
  3591. o1 |= uint32(p.To.Reg&31)<<5 | uint32(p.From.Reg&31)
  3592. case 60: /* adrp label,r */
  3593. d := c.brdist(p, 12, 21, 0)
  3594. o1 = ADR(1, uint32(d), uint32(p.To.Reg))
  3595. case 61: /* adr label, r */
  3596. d := c.brdist(p, 0, 21, 0)
  3597. o1 = ADR(0, uint32(d), uint32(p.To.Reg))
  3598. case 62: /* op $movcon, [R], R -> mov $movcon, REGTMP + op REGTMP, [R], R */
  3599. if p.Reg == REGTMP {
  3600. c.ctxt.Diag("cannot use REGTMP as source: %v\n", p)
  3601. }
  3602. if isADDWop(p.As) || isANDWop(p.As) {
  3603. o1 = c.omovconst(AMOVW, p, &p.From, REGTMP)
  3604. } else {
  3605. o1 = c.omovconst(AMOVD, p, &p.From, REGTMP)
  3606. }
  3607. rt := int(p.To.Reg)
  3608. if p.To.Type == obj.TYPE_NONE {
  3609. rt = REGZERO
  3610. }
  3611. r := int(p.Reg)
  3612. if r == 0 {
  3613. r = rt
  3614. }
  3615. if p.To.Reg == REGSP || r == REGSP {
  3616. o2 = c.opxrrr(p, p.As, false)
  3617. o2 |= REGTMP & 31 << 16
  3618. o2 |= LSL0_64
  3619. } else {
  3620. o2 = c.oprrr(p, p.As)
  3621. o2 |= REGTMP & 31 << 16 /* shift is 0 */
  3622. }
  3623. o2 |= uint32(r&31) << 5
  3624. o2 |= uint32(rt & 31)
  3625. /* reloc ops */
  3626. case 64: /* movT R,addr -> adrp + add + movT R, (REGTMP) */
  3627. o1 = ADR(1, 0, REGTMP)
  3628. o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  3629. rel := obj.Addrel(c.cursym)
  3630. rel.Off = int32(c.pc)
  3631. rel.Siz = 8
  3632. rel.Sym = p.To.Sym
  3633. rel.Add = p.To.Offset
  3634. rel.Type = objabi.R_ADDRARM64
  3635. o3 = c.olsr12u(p, int32(c.opstr12(p, p.As)), 0, REGTMP, int(p.From.Reg))
  3636. case 65: /* movT addr,R -> adrp + add + movT (REGTMP), R */
  3637. o1 = ADR(1, 0, REGTMP)
  3638. o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  3639. rel := obj.Addrel(c.cursym)
  3640. rel.Off = int32(c.pc)
  3641. rel.Siz = 8
  3642. rel.Sym = p.From.Sym
  3643. rel.Add = p.From.Offset
  3644. rel.Type = objabi.R_ADDRARM64
  3645. o3 = c.olsr12u(p, int32(c.opldr12(p, p.As)), 0, REGTMP, int(p.To.Reg))
  3646. case 66: /* ldp O(R)!, (r1, r2); ldp (R)O!, (r1, r2) */
  3647. v := int32(c.regoff(&p.From))
  3648. r := int(p.From.Reg)
  3649. if r == obj.REG_NONE {
  3650. r = int(o.param)
  3651. }
  3652. if r == obj.REG_NONE {
  3653. c.ctxt.Diag("invalid ldp source: %v\n", p)
  3654. }
  3655. o1 |= c.opldpstp(p, o, v, uint32(r), uint32(p.To.Reg), uint32(p.To.Offset), 1)
  3656. case 67: /* stp (r1, r2), O(R)!; stp (r1, r2), (R)O! */
  3657. r := int(p.To.Reg)
  3658. if r == obj.REG_NONE {
  3659. r = int(o.param)
  3660. }
  3661. if r == obj.REG_NONE {
  3662. c.ctxt.Diag("invalid stp destination: %v\n", p)
  3663. }
  3664. v := int32(c.regoff(&p.To))
  3665. o1 = c.opldpstp(p, o, v, uint32(r), uint32(p.From.Reg), uint32(p.From.Offset), 0)
  3666. case 68: /* movT $vconaddr(SB), reg -> adrp + add + reloc */
  3667. // NOTE: this case does not use REGTMP. If it ever does,
  3668. // remove the NOTUSETMP flag in optab.
  3669. if p.As == AMOVW {
  3670. c.ctxt.Diag("invalid load of 32-bit address: %v", p)
  3671. }
  3672. o1 = ADR(1, 0, uint32(p.To.Reg))
  3673. o2 = c.opirr(p, AADD) | uint32(p.To.Reg&31)<<5 | uint32(p.To.Reg&31)
  3674. rel := obj.Addrel(c.cursym)
  3675. rel.Off = int32(c.pc)
  3676. rel.Siz = 8
  3677. rel.Sym = p.From.Sym
  3678. rel.Add = p.From.Offset
  3679. rel.Type = objabi.R_ADDRARM64
  3680. case 69: /* LE model movd $tlsvar, reg -> movz reg, 0 + reloc */
  3681. o1 = c.opirr(p, AMOVZ)
  3682. o1 |= uint32(p.To.Reg & 31)
  3683. rel := obj.Addrel(c.cursym)
  3684. rel.Off = int32(c.pc)
  3685. rel.Siz = 4
  3686. rel.Sym = p.From.Sym
  3687. rel.Type = objabi.R_ARM64_TLS_LE
  3688. if p.From.Offset != 0 {
  3689. c.ctxt.Diag("invalid offset on MOVW $tlsvar")
  3690. }
  3691. case 70: /* IE model movd $tlsvar, reg -> adrp REGTMP, 0; ldr reg, [REGTMP, #0] + relocs */
  3692. o1 = ADR(1, 0, REGTMP)
  3693. o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
  3694. rel := obj.Addrel(c.cursym)
  3695. rel.Off = int32(c.pc)
  3696. rel.Siz = 8
  3697. rel.Sym = p.From.Sym
  3698. rel.Add = 0
  3699. rel.Type = objabi.R_ARM64_TLS_IE
  3700. if p.From.Offset != 0 {
  3701. c.ctxt.Diag("invalid offset on MOVW $tlsvar")
  3702. }
  3703. case 71: /* movd sym@GOT, reg -> adrp REGTMP, #0; ldr reg, [REGTMP, #0] + relocs */
  3704. o1 = ADR(1, 0, REGTMP)
  3705. o2 = c.olsr12u(p, int32(c.opldr12(p, AMOVD)), 0, REGTMP, int(p.To.Reg))
  3706. rel := obj.Addrel(c.cursym)
  3707. rel.Off = int32(c.pc)
  3708. rel.Siz = 8
  3709. rel.Sym = p.From.Sym
  3710. rel.Add = 0
  3711. rel.Type = objabi.R_ARM64_GOTPCREL
  3712. case 72: /* vaddp/vand/vcmeq/vorr/vadd/veor/vfmla/vfmls/vbit/vbsl/vcmtst/vsub/vbif/vuzip1/vuzip2 Vm.<T>, Vn.<T>, Vd.<T> */
  3713. af := int((p.From.Reg >> 5) & 15)
  3714. af3 := int((p.Reg >> 5) & 15)
  3715. at := int((p.To.Reg >> 5) & 15)
  3716. if af != af3 || af != at {
  3717. c.ctxt.Diag("operand mismatch: %v", p)
  3718. break
  3719. }
  3720. o1 = c.oprrr(p, p.As)
  3721. rf := int((p.From.Reg) & 31)
  3722. rt := int((p.To.Reg) & 31)
  3723. r := int((p.Reg) & 31)
  3724. Q := 0
  3725. size := 0
  3726. switch af {
  3727. case ARNG_16B:
  3728. Q = 1
  3729. size = 0
  3730. case ARNG_2D:
  3731. Q = 1
  3732. size = 3
  3733. case ARNG_2S:
  3734. Q = 0
  3735. size = 2
  3736. case ARNG_4H:
  3737. Q = 0
  3738. size = 1
  3739. case ARNG_4S:
  3740. Q = 1
  3741. size = 2
  3742. case ARNG_8B:
  3743. Q = 0
  3744. size = 0
  3745. case ARNG_8H:
  3746. Q = 1
  3747. size = 1
  3748. default:
  3749. c.ctxt.Diag("invalid arrangement: %v", p)
  3750. }
  3751. switch p.As {
  3752. case AVORR, AVAND, AVEOR, AVBIT, AVBSL, AVBIF:
  3753. if af != ARNG_16B && af != ARNG_8B {
  3754. c.ctxt.Diag("invalid arrangement: %v", p)
  3755. }
  3756. case AVFMLA, AVFMLS:
  3757. if af != ARNG_2D && af != ARNG_2S && af != ARNG_4S {
  3758. c.ctxt.Diag("invalid arrangement: %v", p)
  3759. }
  3760. }
  3761. switch p.As {
  3762. case AVAND, AVEOR:
  3763. size = 0
  3764. case AVBSL:
  3765. size = 1
  3766. case AVORR, AVBIT, AVBIF:
  3767. size = 2
  3768. case AVFMLA, AVFMLS:
  3769. if af == ARNG_2D {
  3770. size = 1
  3771. } else {
  3772. size = 0
  3773. }
  3774. }
  3775. o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  3776. case 73: /* vmov V.<T>[index], R */
  3777. rf := int(p.From.Reg)
  3778. rt := int(p.To.Reg)
  3779. imm5 := 0
  3780. o1 = 7<<25 | 0xf<<10
  3781. index := int(p.From.Index)
  3782. switch (p.From.Reg >> 5) & 15 {
  3783. case ARNG_B:
  3784. c.checkindex(p, index, 15)
  3785. imm5 |= 1
  3786. imm5 |= index << 1
  3787. case ARNG_H:
  3788. c.checkindex(p, index, 7)
  3789. imm5 |= 2
  3790. imm5 |= index << 2
  3791. case ARNG_S:
  3792. c.checkindex(p, index, 3)
  3793. imm5 |= 4
  3794. imm5 |= index << 3
  3795. case ARNG_D:
  3796. c.checkindex(p, index, 1)
  3797. imm5 |= 8
  3798. imm5 |= index << 4
  3799. o1 |= 1 << 30
  3800. default:
  3801. c.ctxt.Diag("invalid arrangement: %v", p)
  3802. }
  3803. o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  3804. case 74:
  3805. // add $O, R, Rtmp or sub $O, R, Rtmp
  3806. // ldp (Rtmp), (R1, R2)
  3807. r := int(p.From.Reg)
  3808. if r == obj.REG_NONE {
  3809. r = int(o.param)
  3810. }
  3811. if r == obj.REG_NONE {
  3812. c.ctxt.Diag("invalid ldp source: %v", p)
  3813. }
  3814. v := int32(c.regoff(&p.From))
  3815. if v > 0 {
  3816. if v > 4095 {
  3817. c.ctxt.Diag("offset out of range: %v", p)
  3818. }
  3819. o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
  3820. }
  3821. if v < 0 {
  3822. if v < -4095 {
  3823. c.ctxt.Diag("offset out of range: %v", p)
  3824. }
  3825. o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP)
  3826. }
  3827. o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
  3828. case 75:
  3829. // mov $L, Rtmp (from constant pool)
  3830. // add Rtmp, R, Rtmp
  3831. // ldp (Rtmp), (R1, R2)
  3832. r := int(p.From.Reg)
  3833. if r == obj.REG_NONE {
  3834. r = int(o.param)
  3835. }
  3836. if r == obj.REG_NONE {
  3837. c.ctxt.Diag("invalid ldp source: %v", p)
  3838. }
  3839. o1 = c.omovlit(AMOVD, p, &p.From, REGTMP)
  3840. o2 = c.opxrrr(p, AADD, false)
  3841. o2 |= (REGTMP & 31) << 16
  3842. o2 |= uint32(r&31) << 5
  3843. o2 |= uint32(REGTMP & 31)
  3844. o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
  3845. case 76:
  3846. // add $O, R, Rtmp or sub $O, R, Rtmp
  3847. // stp (R1, R2), (Rtmp)
  3848. r := int(p.To.Reg)
  3849. if r == obj.REG_NONE {
  3850. r = int(o.param)
  3851. }
  3852. if r == obj.REG_NONE {
  3853. c.ctxt.Diag("invalid stp destination: %v", p)
  3854. }
  3855. v := int32(c.regoff(&p.To))
  3856. if v > 0 {
  3857. if v > 4095 {
  3858. c.ctxt.Diag("offset out of range: %v", p)
  3859. }
  3860. o1 = c.oaddi(p, int32(c.opirr(p, AADD)), v, r, REGTMP)
  3861. }
  3862. if v < 0 {
  3863. if v < -4095 {
  3864. c.ctxt.Diag("offset out of range: %v", p)
  3865. }
  3866. o1 = c.oaddi(p, int32(c.opirr(p, ASUB)), -v, r, REGTMP)
  3867. }
  3868. o2 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
  3869. case 77:
  3870. // mov $L, Rtmp (from constant pool)
  3871. // add Rtmp, R, Rtmp
  3872. // stp (R1, R2), (Rtmp)
  3873. r := int(p.To.Reg)
  3874. if r == obj.REG_NONE {
  3875. r = int(o.param)
  3876. }
  3877. if r == obj.REG_NONE {
  3878. c.ctxt.Diag("invalid stp destination: %v", p)
  3879. }
  3880. o1 = c.omovlit(AMOVD, p, &p.To, REGTMP)
  3881. o2 = c.opxrrr(p, AADD, false)
  3882. o2 |= REGTMP & 31 << 16
  3883. o2 |= uint32(r&31) << 5
  3884. o2 |= uint32(REGTMP & 31)
  3885. o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
  3886. case 78: /* vmov R, V.<T>[index] */
  3887. rf := int(p.From.Reg)
  3888. rt := int(p.To.Reg)
  3889. imm5 := 0
  3890. o1 = 1<<30 | 7<<25 | 7<<10
  3891. index := int(p.To.Index)
  3892. switch (p.To.Reg >> 5) & 15 {
  3893. case ARNG_B:
  3894. c.checkindex(p, index, 15)
  3895. imm5 |= 1
  3896. imm5 |= index << 1
  3897. case ARNG_H:
  3898. c.checkindex(p, index, 7)
  3899. imm5 |= 2
  3900. imm5 |= index << 2
  3901. case ARNG_S:
  3902. c.checkindex(p, index, 3)
  3903. imm5 |= 4
  3904. imm5 |= index << 3
  3905. case ARNG_D:
  3906. c.checkindex(p, index, 1)
  3907. imm5 |= 8
  3908. imm5 |= index << 4
  3909. default:
  3910. c.ctxt.Diag("invalid arrangement: %v", p)
  3911. }
  3912. o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  3913. case 79: /* vdup Vn.<T>[index], Vd.<T> */
  3914. rf := int(p.From.Reg)
  3915. rt := int(p.To.Reg)
  3916. o1 = 7<<25 | 1<<10
  3917. var imm5, Q int
  3918. index := int(p.From.Index)
  3919. switch (p.To.Reg >> 5) & 15 {
  3920. case ARNG_16B:
  3921. c.checkindex(p, index, 15)
  3922. Q = 1
  3923. imm5 = 1
  3924. imm5 |= index << 1
  3925. case ARNG_2D:
  3926. c.checkindex(p, index, 1)
  3927. Q = 1
  3928. imm5 = 8
  3929. imm5 |= index << 4
  3930. case ARNG_2S:
  3931. c.checkindex(p, index, 3)
  3932. Q = 0
  3933. imm5 = 4
  3934. imm5 |= index << 3
  3935. case ARNG_4H:
  3936. c.checkindex(p, index, 7)
  3937. Q = 0
  3938. imm5 = 2
  3939. imm5 |= index << 2
  3940. case ARNG_4S:
  3941. c.checkindex(p, index, 3)
  3942. Q = 1
  3943. imm5 = 4
  3944. imm5 |= index << 3
  3945. case ARNG_8B:
  3946. c.checkindex(p, index, 15)
  3947. Q = 0
  3948. imm5 = 1
  3949. imm5 |= index << 1
  3950. case ARNG_8H:
  3951. c.checkindex(p, index, 7)
  3952. Q = 1
  3953. imm5 = 2
  3954. imm5 |= index << 2
  3955. default:
  3956. c.ctxt.Diag("invalid arrangement: %v", p)
  3957. }
  3958. o1 |= (uint32(Q&1) << 30) | (uint32(imm5&0x1f) << 16)
  3959. o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  3960. case 80: /* vmov V.<T>[index], Vn */
  3961. rf := int(p.From.Reg)
  3962. rt := int(p.To.Reg)
  3963. imm5 := 0
  3964. index := int(p.From.Index)
  3965. switch p.As {
  3966. case AVMOV:
  3967. o1 = 1<<30 | 15<<25 | 1<<10
  3968. switch (p.From.Reg >> 5) & 15 {
  3969. case ARNG_B:
  3970. c.checkindex(p, index, 15)
  3971. imm5 |= 1
  3972. imm5 |= index << 1
  3973. case ARNG_H:
  3974. c.checkindex(p, index, 7)
  3975. imm5 |= 2
  3976. imm5 |= index << 2
  3977. case ARNG_S:
  3978. c.checkindex(p, index, 3)
  3979. imm5 |= 4
  3980. imm5 |= index << 3
  3981. case ARNG_D:
  3982. c.checkindex(p, index, 1)
  3983. imm5 |= 8
  3984. imm5 |= index << 4
  3985. default:
  3986. c.ctxt.Diag("invalid arrangement: %v", p)
  3987. }
  3988. default:
  3989. c.ctxt.Diag("unsupported op %v", p.As)
  3990. }
  3991. o1 |= (uint32(imm5&0x1f) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  3992. case 81: /* vld[1-4]|vld[1-4]r (Rn), [Vt1.<T>, Vt2.<T>, ...] */
  3993. c.checkoffset(p, p.As)
  3994. r := int(p.From.Reg)
  3995. o1 = c.oprrr(p, p.As)
  3996. if o.scond == C_XPOST {
  3997. o1 |= 1 << 23
  3998. if p.From.Index == 0 {
  3999. // immediate offset variant
  4000. o1 |= 0x1f << 16
  4001. } else {
  4002. // register offset variant
  4003. if isRegShiftOrExt(&p.From) {
  4004. c.ctxt.Diag("invalid extended register op: %v\n", p)
  4005. }
  4006. o1 |= uint32(p.From.Index&0x1f) << 16
  4007. }
  4008. }
  4009. o1 |= uint32(p.To.Offset)
  4010. // cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset
  4011. // add opcode(bit 12-15) for vld1, mask it off if it's not vld1
  4012. o1 = c.maskOpvldvst(p, o1)
  4013. o1 |= uint32(r&31) << 5
  4014. case 82: /* vmov Rn, Vd.<T> */
  4015. rf := int(p.From.Reg)
  4016. rt := int(p.To.Reg)
  4017. o1 = 7<<25 | 3<<10
  4018. var imm5, Q uint32
  4019. switch (p.To.Reg >> 5) & 15 {
  4020. case ARNG_16B:
  4021. Q = 1
  4022. imm5 = 1
  4023. case ARNG_2D:
  4024. Q = 1
  4025. imm5 = 8
  4026. case ARNG_2S:
  4027. Q = 0
  4028. imm5 = 4
  4029. case ARNG_4H:
  4030. Q = 0
  4031. imm5 = 2
  4032. case ARNG_4S:
  4033. Q = 1
  4034. imm5 = 4
  4035. case ARNG_8B:
  4036. Q = 0
  4037. imm5 = 1
  4038. case ARNG_8H:
  4039. Q = 1
  4040. imm5 = 2
  4041. default:
  4042. c.ctxt.Diag("invalid arrangement on VMOV Rn, Vd.<T>: %v\n", p)
  4043. }
  4044. o1 |= (Q & 1 << 30) | (imm5 & 0x1f << 16)
  4045. o1 |= (uint32(rf&31) << 5) | uint32(rt&31)
  4046. case 83: /* vmov Vn.<T>, Vd.<T> */
  4047. af := int((p.From.Reg >> 5) & 15)
  4048. at := int((p.To.Reg >> 5) & 15)
  4049. if af != at {
  4050. c.ctxt.Diag("invalid arrangement: %v\n", p)
  4051. }
  4052. o1 = c.oprrr(p, p.As)
  4053. rf := int((p.From.Reg) & 31)
  4054. rt := int((p.To.Reg) & 31)
  4055. var Q, size uint32
  4056. switch af {
  4057. case ARNG_8B:
  4058. Q = 0
  4059. size = 0
  4060. case ARNG_16B:
  4061. Q = 1
  4062. size = 0
  4063. case ARNG_4H:
  4064. Q = 0
  4065. size = 1
  4066. case ARNG_8H:
  4067. Q = 1
  4068. size = 1
  4069. case ARNG_2S:
  4070. Q = 0
  4071. size = 2
  4072. case ARNG_4S:
  4073. Q = 1
  4074. size = 2
  4075. default:
  4076. c.ctxt.Diag("invalid arrangement: %v\n", p)
  4077. }
  4078. if (p.As == AVMOV || p.As == AVRBIT || p.As == AVCNT) && (af != ARNG_16B && af != ARNG_8B) {
  4079. c.ctxt.Diag("invalid arrangement: %v", p)
  4080. }
  4081. if p.As == AVREV32 && (af == ARNG_2S || af == ARNG_4S) {
  4082. c.ctxt.Diag("invalid arrangement: %v", p)
  4083. }
  4084. if p.As == AVREV16 && af != ARNG_8B && af != ARNG_16B {
  4085. c.ctxt.Diag("invalid arrangement: %v", p)
  4086. }
  4087. if p.As == AVMOV {
  4088. o1 |= uint32(rf&31) << 16
  4089. }
  4090. if p.As == AVRBIT {
  4091. size = 1
  4092. }
  4093. o1 |= (Q&1)<<30 | (size&3)<<22 | uint32(rf&31)<<5 | uint32(rt&31)
  4094. case 84: /* vst[1-4] [Vt1.<T>, Vt2.<T>, ...], (Rn) */
  4095. c.checkoffset(p, p.As)
  4096. r := int(p.To.Reg)
  4097. o1 = 3 << 26
  4098. if o.scond == C_XPOST {
  4099. o1 |= 1 << 23
  4100. if p.To.Index == 0 {
  4101. // immediate offset variant
  4102. o1 |= 0x1f << 16
  4103. } else {
  4104. // register offset variant
  4105. if isRegShiftOrExt(&p.To) {
  4106. c.ctxt.Diag("invalid extended register: %v\n", p)
  4107. }
  4108. o1 |= uint32(p.To.Index&31) << 16
  4109. }
  4110. }
  4111. o1 |= uint32(p.From.Offset)
  4112. // cmd/asm/internal/arch/arm64.go:ARM64RegisterListOffset
  4113. // add opcode(bit 12-15) for vst1, mask it off if it's not vst1
  4114. o1 = c.maskOpvldvst(p, o1)
  4115. o1 |= uint32(r&31) << 5
  4116. case 85: /* vaddv/vuaddlv Vn.<T>, Vd*/
  4117. af := int((p.From.Reg >> 5) & 15)
  4118. o1 = c.oprrr(p, p.As)
  4119. rf := int((p.From.Reg) & 31)
  4120. rt := int((p.To.Reg) & 31)
  4121. Q := 0
  4122. size := 0
  4123. switch af {
  4124. case ARNG_8B:
  4125. Q = 0
  4126. size = 0
  4127. case ARNG_16B:
  4128. Q = 1
  4129. size = 0
  4130. case ARNG_4H:
  4131. Q = 0
  4132. size = 1
  4133. case ARNG_8H:
  4134. Q = 1
  4135. size = 1
  4136. case ARNG_4S:
  4137. Q = 1
  4138. size = 2
  4139. default:
  4140. c.ctxt.Diag("invalid arrangement: %v\n", p)
  4141. }
  4142. o1 |= (uint32(Q&1) << 30) | (uint32(size&3) << 22) | (uint32(rf&31) << 5) | uint32(rt&31)
  4143. case 86: /* vmovi $imm8, Vd.<T>*/
  4144. at := int((p.To.Reg >> 5) & 15)
  4145. r := int(p.From.Offset)
  4146. if r > 255 || r < 0 {
  4147. c.ctxt.Diag("immediate constant out of range: %v\n", p)
  4148. }
  4149. rt := int((p.To.Reg) & 31)
  4150. Q := 0
  4151. switch at {
  4152. case ARNG_8B:
  4153. Q = 0
  4154. case ARNG_16B:
  4155. Q = 1
  4156. default:
  4157. c.ctxt.Diag("invalid arrangement: %v\n", p)
  4158. }
  4159. o1 = 0xf<<24 | 0xe<<12 | 1<<10
  4160. o1 |= (uint32(Q&1) << 30) | (uint32((r>>5)&7) << 16) | (uint32(r&0x1f) << 5) | uint32(rt&31)
  4161. case 87: /* stp (r,r), addr(SB) -> adrp + add + stp */
  4162. o1 = ADR(1, 0, REGTMP)
  4163. o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  4164. rel := obj.Addrel(c.cursym)
  4165. rel.Off = int32(c.pc)
  4166. rel.Siz = 8
  4167. rel.Sym = p.To.Sym
  4168. rel.Add = p.To.Offset
  4169. rel.Type = objabi.R_ADDRARM64
  4170. o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.From.Reg), uint32(p.From.Offset), 0)
  4171. case 88: /* ldp addr(SB), (r,r) -> adrp + add + ldp */
  4172. o1 = ADR(1, 0, REGTMP)
  4173. o2 = c.opirr(p, AADD) | REGTMP&31<<5 | REGTMP&31
  4174. rel := obj.Addrel(c.cursym)
  4175. rel.Off = int32(c.pc)
  4176. rel.Siz = 8
  4177. rel.Sym = p.From.Sym
  4178. rel.Add = p.From.Offset
  4179. rel.Type = objabi.R_ADDRARM64
  4180. o3 |= c.opldpstp(p, o, 0, uint32(REGTMP), uint32(p.To.Reg), uint32(p.To.Offset), 1)
  4181. case 89: /* vadd/vsub Vm, Vn, Vd */
  4182. switch p.As {
  4183. case AVADD:
  4184. o1 = 5<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
  4185. case AVSUB:
  4186. o1 = 7<<28 | 7<<25 | 7<<21 | 1<<15 | 1<<10
  4187. default:
  4188. c.ctxt.Diag("bad opcode: %v\n", p)
  4189. break
  4190. }
  4191. rf := int(p.From.Reg)
  4192. rt := int(p.To.Reg)
  4193. r := int(p.Reg)
  4194. if r == 0 {
  4195. r = rt
  4196. }
  4197. o1 |= (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  4198. // This is supposed to be something that stops execution.
  4199. // It's not supposed to be reached, ever, but if it is, we'd
  4200. // like to be able to tell how we got there. Assemble as
  4201. // 0xbea71700 which is guaranteed to raise undefined instruction
  4202. // exception.
  4203. case 90:
  4204. o1 = 0xbea71700
  4205. case 91: /* prfm imm(Rn), <prfop | $imm5> */
  4206. imm := uint32(p.From.Offset)
  4207. r := p.From.Reg
  4208. v := uint32(0xff)
  4209. if p.To.Type == obj.TYPE_CONST {
  4210. v = uint32(p.To.Offset)
  4211. if v > 31 {
  4212. c.ctxt.Diag("illegal prefetch operation\n%v", p)
  4213. }
  4214. } else {
  4215. for i := 0; i < len(prfopfield); i++ {
  4216. if prfopfield[i].reg == p.To.Reg {
  4217. v = prfopfield[i].enc
  4218. break
  4219. }
  4220. }
  4221. if v == 0xff {
  4222. c.ctxt.Diag("illegal prefetch operation:\n%v", p)
  4223. }
  4224. }
  4225. o1 = c.opldrpp(p, p.As)
  4226. o1 |= (uint32(r&31) << 5) | (uint32((imm>>3)&0xfff) << 10) | (uint32(v & 31))
  4227. case 92: /* vmov Vn.<T>[index], Vd.<T>[index] */
  4228. rf := int(p.From.Reg)
  4229. rt := int(p.To.Reg)
  4230. imm4 := 0
  4231. imm5 := 0
  4232. o1 = 3<<29 | 7<<25 | 1<<10
  4233. index1 := int(p.To.Index)
  4234. index2 := int(p.From.Index)
  4235. if ((p.To.Reg >> 5) & 15) != ((p.From.Reg >> 5) & 15) {
  4236. c.ctxt.Diag("operand mismatch: %v", p)
  4237. }
  4238. switch (p.To.Reg >> 5) & 15 {
  4239. case ARNG_B:
  4240. c.checkindex(p, index1, 15)
  4241. c.checkindex(p, index2, 15)
  4242. imm5 |= 1
  4243. imm5 |= index1 << 1
  4244. imm4 |= index2
  4245. case ARNG_H:
  4246. c.checkindex(p, index1, 7)
  4247. c.checkindex(p, index2, 7)
  4248. imm5 |= 2
  4249. imm5 |= index1 << 2
  4250. imm4 |= index2 << 1
  4251. case ARNG_S:
  4252. c.checkindex(p, index1, 3)
  4253. c.checkindex(p, index2, 3)
  4254. imm5 |= 4
  4255. imm5 |= index1 << 3
  4256. imm4 |= index2 << 2
  4257. case ARNG_D:
  4258. c.checkindex(p, index1, 1)
  4259. c.checkindex(p, index2, 1)
  4260. imm5 |= 8
  4261. imm5 |= index1 << 4
  4262. imm4 |= index2 << 3
  4263. default:
  4264. c.ctxt.Diag("invalid arrangement: %v", p)
  4265. }
  4266. o1 |= (uint32(imm5&0x1f) << 16) | (uint32(imm4&0xf) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
  4267. case 93: /* vpmull{2} Vm.<T>, Vn.<T>, Vd */
  4268. af := int((p.From.Reg >> 5) & 15)
  4269. at := int((p.To.Reg >> 5) & 15)
  4270. a := int((p.Reg >> 5) & 15)
  4271. var Q, size uint32
  4272. if p.As == AVPMULL {
  4273. Q = 0
  4274. } else {
  4275. Q = 1
  4276. }
  4277. var fArng int
  4278. switch at {
  4279. case ARNG_8H:
  4280. if Q == 0 {
  4281. fArng = ARNG_8B
  4282. } else {
  4283. fArng = ARNG_16B
  4284. }
  4285. size = 0
  4286. case ARNG_1Q:
  4287. if Q == 0 {
  4288. fArng = ARNG_1D
  4289. } else {
  4290. fArng = ARNG_2D
  4291. }
  4292. size = 3
  4293. default:
  4294. c.ctxt.Diag("invalid arrangement on Vd.<T>: %v", p)
  4295. }
  4296. if af != a || af != fArng {
  4297. c.ctxt.Diag("invalid arrangement: %v", p)
  4298. }
  4299. o1 = c.oprrr(p, p.As)
  4300. rf := int((p.From.Reg) & 31)
  4301. rt := int((p.To.Reg) & 31)
  4302. r := int((p.Reg) & 31)
  4303. o1 |= ((Q & 1) << 30) | ((size & 3) << 22) | (uint32(rf&31) << 16) | (uint32(r&31) << 5) | uint32(rt&31)
  4304. case 94: /* vext $imm4, Vm.<T>, Vn.<T>, Vd.<T> */
  4305. af := int(((p.GetFrom3().Reg) >> 5) & 15)
  4306. at := int((p.To.Reg >> 5) & 15)
  4307. a := int((p.Reg >> 5) & 15)
  4308. index := int(p.From.Offset)
  4309. if af != a || af != at {
  4310. c.ctxt.Diag("invalid arrangement: %v", p)
  4311. break
  4312. }
  4313. var Q uint32
  4314. var b int
  4315. if af == ARNG_8B {
  4316. Q = 0
  4317. b = 7
  4318. } else if af == ARNG_16B {
  4319. Q = 1
  4320. b = 15
  4321. } else {
  4322. c.ctxt.Diag("invalid arrangement, should be B8 or B16: %v", p)
  4323. break
  4324. }
  4325. if index < 0 || index > b {
  4326. c.ctxt.Diag("illegal offset: %v", p)
  4327. }
  4328. o1 = c.opirr(p, p.As)
  4329. rf := int((p.GetFrom3().Reg) & 31)
  4330. rt := int((p.To.Reg) & 31)
  4331. r := int((p.Reg) & 31)
  4332. o1 |= ((Q & 1) << 30) | (uint32(r&31) << 16) | (uint32(index&15) << 11) | (uint32(rf&31) << 5) | uint32(rt&31)
  4333. case 95: /* vushr $shift, Vn.<T>, Vd.<T> */
  4334. at := int((p.To.Reg >> 5) & 15)
  4335. af := int((p.Reg >> 5) & 15)
  4336. shift := int(p.From.Offset)
  4337. if af != at {
  4338. c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
  4339. }
  4340. var Q uint32
  4341. var imax, esize int
  4342. switch af {
  4343. case ARNG_8B, ARNG_4H, ARNG_2S:
  4344. Q = 0
  4345. case ARNG_16B, ARNG_8H, ARNG_4S, ARNG_2D:
  4346. Q = 1
  4347. default:
  4348. c.ctxt.Diag("invalid arrangement on op Vn.<T>, Vd.<T>: %v", p)
  4349. }
  4350. switch af {
  4351. case ARNG_8B, ARNG_16B:
  4352. imax = 15
  4353. esize = 8
  4354. case ARNG_4H, ARNG_8H:
  4355. imax = 31
  4356. esize = 16
  4357. case ARNG_2S, ARNG_4S:
  4358. imax = 63
  4359. esize = 32
  4360. case ARNG_2D:
  4361. imax = 127
  4362. esize = 64
  4363. }
  4364. imm := 0
  4365. switch p.As {
  4366. case AVUSHR, AVSRI:
  4367. imm = esize*2 - shift
  4368. if imm < esize || imm > imax {
  4369. c.ctxt.Diag("shift out of range: %v", p)
  4370. }
  4371. case AVSHL:
  4372. imm = esize + shift
  4373. if imm > imax {
  4374. c.ctxt.Diag("shift out of range: %v", p)
  4375. }
  4376. default:
  4377. c.ctxt.Diag("invalid instruction %v\n", p)
  4378. }
  4379. o1 = c.opirr(p, p.As)
  4380. rt := int((p.To.Reg) & 31)
  4381. rf := int((p.Reg) & 31)
  4382. o1 |= ((Q & 1) << 30) | (uint32(imm&127) << 16) | (uint32(rf&31) << 5) | uint32(rt&31)
  4383. case 96: /* vst1 Vt1.<T>[index], offset(Rn) */
  4384. af := int((p.From.Reg >> 5) & 15)
  4385. rt := int((p.From.Reg) & 31)
  4386. rf := int((p.To.Reg) & 31)
  4387. r := int(p.To.Index & 31)
  4388. index := int(p.From.Index)
  4389. offset := int32(c.regoff(&p.To))
  4390. if o.scond == C_XPOST {
  4391. if (p.To.Index != 0) && (offset != 0) {
  4392. c.ctxt.Diag("invalid offset: %v", p)
  4393. }
  4394. if p.To.Index == 0 && offset == 0 {
  4395. c.ctxt.Diag("invalid offset: %v", p)
  4396. }
  4397. }
  4398. if offset != 0 {
  4399. r = 31
  4400. }
  4401. var Q, S, size int
  4402. var opcode uint32
  4403. switch af {
  4404. case ARNG_B:
  4405. c.checkindex(p, index, 15)
  4406. if o.scond == C_XPOST && offset != 0 && offset != 1 {
  4407. c.ctxt.Diag("invalid offset: %v", p)
  4408. }
  4409. Q = index >> 3
  4410. S = (index >> 2) & 1
  4411. size = index & 3
  4412. opcode = 0
  4413. case ARNG_H:
  4414. c.checkindex(p, index, 7)
  4415. if o.scond == C_XPOST && offset != 0 && offset != 2 {
  4416. c.ctxt.Diag("invalid offset: %v", p)
  4417. }
  4418. Q = index >> 2
  4419. S = (index >> 1) & 1
  4420. size = (index & 1) << 1
  4421. opcode = 2
  4422. case ARNG_S:
  4423. c.checkindex(p, index, 3)
  4424. if o.scond == C_XPOST && offset != 0 && offset != 4 {
  4425. c.ctxt.Diag("invalid offset: %v", p)
  4426. }
  4427. Q = index >> 1
  4428. S = index & 1
  4429. size = 0
  4430. opcode = 4
  4431. case ARNG_D:
  4432. c.checkindex(p, index, 1)
  4433. if o.scond == C_XPOST && offset != 0 && offset != 8 {
  4434. c.ctxt.Diag("invalid offset: %v", p)
  4435. }
  4436. Q = index
  4437. S = 0
  4438. size = 1
  4439. opcode = 4
  4440. default:
  4441. c.ctxt.Diag("invalid arrangement: %v", p)
  4442. }
  4443. if o.scond == C_XPOST {
  4444. o1 |= 27 << 23
  4445. } else {
  4446. o1 |= 26 << 23
  4447. }
  4448. 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)
  4449. case 97: /* vld1 offset(Rn), vt.<T>[index] */
  4450. at := int((p.To.Reg >> 5) & 15)
  4451. rt := int((p.To.Reg) & 31)
  4452. rf := int((p.From.Reg) & 31)
  4453. r := int(p.From.Index & 31)
  4454. index := int(p.To.Index)
  4455. offset := int32(c.regoff(&p.From))
  4456. if o.scond == C_XPOST {
  4457. if (p.From.Index != 0) && (offset != 0) {
  4458. c.ctxt.Diag("invalid offset: %v", p)
  4459. }
  4460. if p.From.Index == 0 && offset == 0 {
  4461. c.ctxt.Diag("invalid offset: %v", p)
  4462. }
  4463. }
  4464. if offset != 0 {
  4465. r = 31
  4466. }
  4467. Q := 0
  4468. S := 0
  4469. size := 0
  4470. var opcode uint32
  4471. switch at {
  4472. case ARNG_B:
  4473. c.checkindex(p, index, 15)
  4474. if o.scond == C_XPOST && offset != 0 && offset != 1 {
  4475. c.ctxt.Diag("invalid offset: %v", p)
  4476. }
  4477. Q = index >> 3
  4478. S = (index >> 2) & 1
  4479. size = index & 3
  4480. opcode = 0
  4481. case ARNG_H:
  4482. c.checkindex(p, index, 7)
  4483. if o.scond == C_XPOST && offset != 0 && offset != 2 {
  4484. c.ctxt.Diag("invalid offset: %v", p)
  4485. }
  4486. Q = index >> 2
  4487. S = (index >> 1) & 1
  4488. size = (index & 1) << 1
  4489. opcode = 2
  4490. case ARNG_S:
  4491. c.checkindex(p, index, 3)
  4492. if o.scond == C_XPOST && offset != 0 && offset != 4 {
  4493. c.ctxt.Diag("invalid offset: %v", p)
  4494. }
  4495. Q = index >> 1
  4496. S = index & 1
  4497. size = 0
  4498. opcode = 4
  4499. case ARNG_D:
  4500. c.checkindex(p, index, 1)
  4501. if o.scond == C_XPOST && offset != 0 && offset != 8 {
  4502. c.ctxt.Diag("invalid offset: %v", p)
  4503. }
  4504. Q = index
  4505. S = 0
  4506. size = 1
  4507. opcode = 4
  4508. default:
  4509. c.ctxt.Diag("invalid arrangement: %v", p)
  4510. }
  4511. if o.scond == C_XPOST {
  4512. o1 |= 110 << 21
  4513. } else {
  4514. o1 |= 106 << 21
  4515. }
  4516. 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)
  4517. case 98: /* MOVD (Rn)(Rm.SXTW[<<amount]),Rd */
  4518. if isRegShiftOrExt(&p.From) {
  4519. // extended or shifted offset register.
  4520. c.checkShiftAmount(p, &p.From)
  4521. o1 = c.opldrr(p, p.As, true)
  4522. o1 |= c.encRegShiftOrExt(&p.From, p.From.Index) /* includes reg, op, etc */
  4523. } else {
  4524. // (Rn)(Rm), no extension or shift.
  4525. o1 = c.opldrr(p, p.As, false)
  4526. o1 |= uint32(p.From.Index&31) << 16
  4527. }
  4528. o1 |= uint32(p.From.Reg&31) << 5
  4529. rt := int(p.To.Reg)
  4530. o1 |= uint32(rt & 31)
  4531. case 99: /* MOVD Rt, (Rn)(Rm.SXTW[<<amount]) */
  4532. if isRegShiftOrExt(&p.To) {
  4533. // extended or shifted offset register.
  4534. c.checkShiftAmount(p, &p.To)
  4535. o1 = c.opstrr(p, p.As, true)
  4536. o1 |= c.encRegShiftOrExt(&p.To, p.To.Index) /* includes reg, op, etc */
  4537. } else {
  4538. // (Rn)(Rm), no extension or shift.
  4539. o1 = c.opstrr(p, p.As, false)
  4540. o1 |= uint32(p.To.Index&31) << 16
  4541. }
  4542. o1 |= uint32(p.To.Reg&31) << 5
  4543. rf := int(p.From.Reg)
  4544. o1 |= uint32(rf & 31)
  4545. case 100: /* VTBL Vn.<T>, [Vt1.<T>, Vt2.<T>, ...], Vd.<T> */
  4546. af := int((p.From.Reg >> 5) & 15)
  4547. at := int((p.To.Reg >> 5) & 15)
  4548. if af != at {
  4549. c.ctxt.Diag("invalid arrangement: %v\n", p)
  4550. }
  4551. var q, len uint32
  4552. switch af {
  4553. case ARNG_8B:
  4554. q = 0
  4555. case ARNG_16B:
  4556. q = 1
  4557. default:
  4558. c.ctxt.Diag("invalid arrangement: %v", p)
  4559. }
  4560. rf := int(p.From.Reg)
  4561. rt := int(p.To.Reg)
  4562. offset := int(p.GetFrom3().Offset)
  4563. opcode := (offset >> 12) & 15
  4564. switch opcode {
  4565. case 0x7:
  4566. len = 0 // one register
  4567. case 0xa:
  4568. len = 1 // two register
  4569. case 0x6:
  4570. len = 2 // three registers
  4571. case 0x2:
  4572. len = 3 // four registers
  4573. default:
  4574. c.ctxt.Diag("invalid register numbers in ARM64 register list: %v", p)
  4575. }
  4576. o1 = q<<30 | 0xe<<24 | len<<13
  4577. o1 |= (uint32(rf&31) << 16) | uint32(offset&31)<<5 | uint32(rt&31)
  4578. case 101: // FOMVQ/FMOVD $vcon, Vd -> load from constant pool.
  4579. o1 = c.omovlit(p.As, p, &p.From, int(p.To.Reg))
  4580. case 102: /* vushll, vushll2, vuxtl, vuxtl2 */
  4581. o1 = c.opirr(p, p.As)
  4582. rf := p.Reg
  4583. af := uint8((p.Reg >> 5) & 15)
  4584. at := uint8((p.To.Reg >> 5) & 15)
  4585. shift := int(p.From.Offset)
  4586. if p.As == AVUXTL || p.As == AVUXTL2 {
  4587. rf = p.From.Reg
  4588. af = uint8((p.From.Reg >> 5) & 15)
  4589. shift = 0
  4590. }
  4591. pack := func(q, x, y uint8) uint32 {
  4592. return uint32(q)<<16 | uint32(x)<<8 | uint32(y)
  4593. }
  4594. var Q uint8 = uint8(o1>>30) & 1
  4595. var immh, width uint8
  4596. switch pack(Q, af, at) {
  4597. case pack(0, ARNG_8B, ARNG_8H):
  4598. immh, width = 1, 8
  4599. case pack(1, ARNG_16B, ARNG_8H):
  4600. immh, width = 1, 8
  4601. case pack(0, ARNG_4H, ARNG_4S):
  4602. immh, width = 2, 16
  4603. case pack(1, ARNG_8H, ARNG_4S):
  4604. immh, width = 2, 16
  4605. case pack(0, ARNG_2S, ARNG_2D):
  4606. immh, width = 4, 32
  4607. case pack(1, ARNG_4S, ARNG_2D):
  4608. immh, width = 4, 32
  4609. default:
  4610. c.ctxt.Diag("operand mismatch: %v\n", p)
  4611. }
  4612. if !(0 <= shift && shift <= int(width-1)) {
  4613. c.ctxt.Diag("shift amount out of range: %v\n", p)
  4614. }
  4615. o1 |= uint32(immh)<<19 | uint32(shift)<<16 | uint32(rf&31)<<5 | uint32(p.To.Reg&31)
  4616. }
  4617. out[0] = o1
  4618. out[1] = o2
  4619. out[2] = o3
  4620. out[3] = o4
  4621. out[4] = o5
  4622. }
  4623. /*
  4624. * basic Rm op Rn -> Rd (using shifted register with 0)
  4625. * also op Rn -> Rt
  4626. * also Rm*Rn op Ra -> Rd
  4627. * also Vm op Vn -> Vd
  4628. */
  4629. func (c *ctxt7) oprrr(p *obj.Prog, a obj.As) uint32 {
  4630. switch a {
  4631. case AADC:
  4632. return S64 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
  4633. case AADCW:
  4634. return S32 | 0<<30 | 0<<29 | 0xd0<<21 | 0<<10
  4635. case AADCS:
  4636. return S64 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
  4637. case AADCSW:
  4638. return S32 | 0<<30 | 1<<29 | 0xd0<<21 | 0<<10
  4639. case ANGC, ASBC:
  4640. return S64 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
  4641. case ANGCS, ASBCS:
  4642. return S64 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
  4643. case ANGCW, ASBCW:
  4644. return S32 | 1<<30 | 0<<29 | 0xd0<<21 | 0<<10
  4645. case ANGCSW, ASBCSW:
  4646. return S32 | 1<<30 | 1<<29 | 0xd0<<21 | 0<<10
  4647. case AADD:
  4648. return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  4649. case AADDW:
  4650. return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  4651. case ACMN, AADDS:
  4652. return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  4653. case ACMNW, AADDSW:
  4654. return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  4655. case ASUB:
  4656. return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  4657. case ASUBW:
  4658. return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  4659. case ACMP, ASUBS:
  4660. return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  4661. case ACMPW, ASUBSW:
  4662. return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 0<<21 | 0<<10
  4663. case AAND:
  4664. return S64 | 0<<29 | 0xA<<24
  4665. case AANDW:
  4666. return S32 | 0<<29 | 0xA<<24
  4667. case AMOVD, AORR:
  4668. return S64 | 1<<29 | 0xA<<24
  4669. // case AMOVW:
  4670. case AMOVWU, AORRW:
  4671. return S32 | 1<<29 | 0xA<<24
  4672. case AEOR:
  4673. return S64 | 2<<29 | 0xA<<24
  4674. case AEORW:
  4675. return S32 | 2<<29 | 0xA<<24
  4676. case AANDS, ATST:
  4677. return S64 | 3<<29 | 0xA<<24
  4678. case AANDSW, ATSTW:
  4679. return S32 | 3<<29 | 0xA<<24
  4680. case ABIC:
  4681. return S64 | 0<<29 | 0xA<<24 | 1<<21
  4682. case ABICW:
  4683. return S32 | 0<<29 | 0xA<<24 | 1<<21
  4684. case ABICS:
  4685. return S64 | 3<<29 | 0xA<<24 | 1<<21
  4686. case ABICSW:
  4687. return S32 | 3<<29 | 0xA<<24 | 1<<21
  4688. case AEON:
  4689. return S64 | 2<<29 | 0xA<<24 | 1<<21
  4690. case AEONW:
  4691. return S32 | 2<<29 | 0xA<<24 | 1<<21
  4692. case AMVN, AORN:
  4693. return S64 | 1<<29 | 0xA<<24 | 1<<21
  4694. case AMVNW, AORNW:
  4695. return S32 | 1<<29 | 0xA<<24 | 1<<21
  4696. case AASR:
  4697. return S64 | OPDP2(10) /* also ASRV */
  4698. case AASRW:
  4699. return S32 | OPDP2(10)
  4700. case ALSL:
  4701. return S64 | OPDP2(8)
  4702. case ALSLW:
  4703. return S32 | OPDP2(8)
  4704. case ALSR:
  4705. return S64 | OPDP2(9)
  4706. case ALSRW:
  4707. return S32 | OPDP2(9)
  4708. case AROR:
  4709. return S64 | OPDP2(11)
  4710. case ARORW:
  4711. return S32 | OPDP2(11)
  4712. case ACCMN:
  4713. return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* cond<<12 | nzcv<<0 */
  4714. case ACCMNW:
  4715. return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
  4716. case ACCMP:
  4717. return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  4718. case ACCMPW:
  4719. return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 0<<11 | 0<<10 | 0<<4
  4720. case ACRC32B:
  4721. return S32 | OPDP2(16)
  4722. case ACRC32H:
  4723. return S32 | OPDP2(17)
  4724. case ACRC32W:
  4725. return S32 | OPDP2(18)
  4726. case ACRC32X:
  4727. return S64 | OPDP2(19)
  4728. case ACRC32CB:
  4729. return S32 | OPDP2(20)
  4730. case ACRC32CH:
  4731. return S32 | OPDP2(21)
  4732. case ACRC32CW:
  4733. return S32 | OPDP2(22)
  4734. case ACRC32CX:
  4735. return S64 | OPDP2(23)
  4736. case ACSEL:
  4737. return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  4738. case ACSELW:
  4739. return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  4740. case ACSET:
  4741. return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  4742. case ACSETW:
  4743. return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  4744. case ACSETM:
  4745. return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  4746. case ACSETMW:
  4747. return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  4748. case ACINC, ACSINC:
  4749. return S64 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  4750. case ACINCW, ACSINCW:
  4751. return S32 | 0<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  4752. case ACINV, ACSINV:
  4753. return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  4754. case ACINVW, ACSINVW:
  4755. return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 0<<10
  4756. case ACNEG, ACSNEG:
  4757. return S64 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  4758. case ACNEGW, ACSNEGW:
  4759. return S32 | 1<<30 | 0<<29 | 0xD4<<21 | 0<<11 | 1<<10
  4760. case AMUL, AMADD:
  4761. return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
  4762. case AMULW, AMADDW:
  4763. return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 0<<15
  4764. case AMNEG, AMSUB:
  4765. return S64 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
  4766. case AMNEGW, AMSUBW:
  4767. return S32 | 0<<29 | 0x1B<<24 | 0<<21 | 1<<15
  4768. case AMRS:
  4769. return SYSOP(1, 2, 0, 0, 0, 0, 0)
  4770. case AMSR:
  4771. return SYSOP(0, 2, 0, 0, 0, 0, 0)
  4772. case ANEG:
  4773. return S64 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
  4774. case ANEGW:
  4775. return S32 | 1<<30 | 0<<29 | 0xB<<24 | 0<<21
  4776. case ANEGS:
  4777. return S64 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
  4778. case ANEGSW:
  4779. return S32 | 1<<30 | 1<<29 | 0xB<<24 | 0<<21
  4780. case AREM, ASDIV:
  4781. return S64 | OPDP2(3)
  4782. case AREMW, ASDIVW:
  4783. return S32 | OPDP2(3)
  4784. case ASMULL, ASMADDL:
  4785. return OPDP3(1, 0, 1, 0)
  4786. case ASMNEGL, ASMSUBL:
  4787. return OPDP3(1, 0, 1, 1)
  4788. case ASMULH:
  4789. return OPDP3(1, 0, 2, 0)
  4790. case AUMULL, AUMADDL:
  4791. return OPDP3(1, 0, 5, 0)
  4792. case AUMNEGL, AUMSUBL:
  4793. return OPDP3(1, 0, 5, 1)
  4794. case AUMULH:
  4795. return OPDP3(1, 0, 6, 0)
  4796. case AUREM, AUDIV:
  4797. return S64 | OPDP2(2)
  4798. case AUREMW, AUDIVW:
  4799. return S32 | OPDP2(2)
  4800. case AAESE:
  4801. return 0x4E<<24 | 2<<20 | 8<<16 | 4<<12 | 2<<10
  4802. case AAESD:
  4803. return 0x4E<<24 | 2<<20 | 8<<16 | 5<<12 | 2<<10
  4804. case AAESMC:
  4805. return 0x4E<<24 | 2<<20 | 8<<16 | 6<<12 | 2<<10
  4806. case AAESIMC:
  4807. return 0x4E<<24 | 2<<20 | 8<<16 | 7<<12 | 2<<10
  4808. case ASHA1C:
  4809. return 0x5E<<24 | 0<<12
  4810. case ASHA1P:
  4811. return 0x5E<<24 | 1<<12
  4812. case ASHA1M:
  4813. return 0x5E<<24 | 2<<12
  4814. case ASHA1SU0:
  4815. return 0x5E<<24 | 3<<12
  4816. case ASHA256H:
  4817. return 0x5E<<24 | 4<<12
  4818. case ASHA256H2:
  4819. return 0x5E<<24 | 5<<12
  4820. case ASHA256SU1:
  4821. return 0x5E<<24 | 6<<12
  4822. case ASHA1H:
  4823. return 0x5E<<24 | 2<<20 | 8<<16 | 0<<12 | 2<<10
  4824. case ASHA1SU1:
  4825. return 0x5E<<24 | 2<<20 | 8<<16 | 1<<12 | 2<<10
  4826. case ASHA256SU0:
  4827. return 0x5E<<24 | 2<<20 | 8<<16 | 2<<12 | 2<<10
  4828. case ASHA512H:
  4829. return 0xCE<<24 | 3<<21 | 8<<12
  4830. case ASHA512H2:
  4831. return 0xCE<<24 | 3<<21 | 8<<12 | 4<<8
  4832. case ASHA512SU1:
  4833. return 0xCE<<24 | 3<<21 | 8<<12 | 8<<8
  4834. case ASHA512SU0:
  4835. return 0xCE<<24 | 3<<22 | 8<<12
  4836. case AFCVTZSD:
  4837. return FPCVTI(1, 0, 1, 3, 0)
  4838. case AFCVTZSDW:
  4839. return FPCVTI(0, 0, 1, 3, 0)
  4840. case AFCVTZSS:
  4841. return FPCVTI(1, 0, 0, 3, 0)
  4842. case AFCVTZSSW:
  4843. return FPCVTI(0, 0, 0, 3, 0)
  4844. case AFCVTZUD:
  4845. return FPCVTI(1, 0, 1, 3, 1)
  4846. case AFCVTZUDW:
  4847. return FPCVTI(0, 0, 1, 3, 1)
  4848. case AFCVTZUS:
  4849. return FPCVTI(1, 0, 0, 3, 1)
  4850. case AFCVTZUSW:
  4851. return FPCVTI(0, 0, 0, 3, 1)
  4852. case ASCVTFD:
  4853. return FPCVTI(1, 0, 1, 0, 2)
  4854. case ASCVTFS:
  4855. return FPCVTI(1, 0, 0, 0, 2)
  4856. case ASCVTFWD:
  4857. return FPCVTI(0, 0, 1, 0, 2)
  4858. case ASCVTFWS:
  4859. return FPCVTI(0, 0, 0, 0, 2)
  4860. case AUCVTFD:
  4861. return FPCVTI(1, 0, 1, 0, 3)
  4862. case AUCVTFS:
  4863. return FPCVTI(1, 0, 0, 0, 3)
  4864. case AUCVTFWD:
  4865. return FPCVTI(0, 0, 1, 0, 3)
  4866. case AUCVTFWS:
  4867. return FPCVTI(0, 0, 0, 0, 3)
  4868. case AFADDS:
  4869. return FPOP2S(0, 0, 0, 2)
  4870. case AFADDD:
  4871. return FPOP2S(0, 0, 1, 2)
  4872. case AFSUBS:
  4873. return FPOP2S(0, 0, 0, 3)
  4874. case AFSUBD:
  4875. return FPOP2S(0, 0, 1, 3)
  4876. case AFMADDD:
  4877. return FPOP3S(0, 0, 1, 0, 0)
  4878. case AFMADDS:
  4879. return FPOP3S(0, 0, 0, 0, 0)
  4880. case AFMSUBD:
  4881. return FPOP3S(0, 0, 1, 0, 1)
  4882. case AFMSUBS:
  4883. return FPOP3S(0, 0, 0, 0, 1)
  4884. case AFNMADDD:
  4885. return FPOP3S(0, 0, 1, 1, 0)
  4886. case AFNMADDS:
  4887. return FPOP3S(0, 0, 0, 1, 0)
  4888. case AFNMSUBD:
  4889. return FPOP3S(0, 0, 1, 1, 1)
  4890. case AFNMSUBS:
  4891. return FPOP3S(0, 0, 0, 1, 1)
  4892. case AFMULS:
  4893. return FPOP2S(0, 0, 0, 0)
  4894. case AFMULD:
  4895. return FPOP2S(0, 0, 1, 0)
  4896. case AFDIVS:
  4897. return FPOP2S(0, 0, 0, 1)
  4898. case AFDIVD:
  4899. return FPOP2S(0, 0, 1, 1)
  4900. case AFMAXS:
  4901. return FPOP2S(0, 0, 0, 4)
  4902. case AFMINS:
  4903. return FPOP2S(0, 0, 0, 5)
  4904. case AFMAXD:
  4905. return FPOP2S(0, 0, 1, 4)
  4906. case AFMIND:
  4907. return FPOP2S(0, 0, 1, 5)
  4908. case AFMAXNMS:
  4909. return FPOP2S(0, 0, 0, 6)
  4910. case AFMAXNMD:
  4911. return FPOP2S(0, 0, 1, 6)
  4912. case AFMINNMS:
  4913. return FPOP2S(0, 0, 0, 7)
  4914. case AFMINNMD:
  4915. return FPOP2S(0, 0, 1, 7)
  4916. case AFNMULS:
  4917. return FPOP2S(0, 0, 0, 8)
  4918. case AFNMULD:
  4919. return FPOP2S(0, 0, 1, 8)
  4920. case AFCMPS:
  4921. return FPCMP(0, 0, 0, 0, 0)
  4922. case AFCMPD:
  4923. return FPCMP(0, 0, 1, 0, 0)
  4924. case AFCMPES:
  4925. return FPCMP(0, 0, 0, 0, 16)
  4926. case AFCMPED:
  4927. return FPCMP(0, 0, 1, 0, 16)
  4928. case AFCCMPS:
  4929. return FPCCMP(0, 0, 0, 0)
  4930. case AFCCMPD:
  4931. return FPCCMP(0, 0, 1, 0)
  4932. case AFCCMPES:
  4933. return FPCCMP(0, 0, 0, 1)
  4934. case AFCCMPED:
  4935. return FPCCMP(0, 0, 1, 1)
  4936. case AFCSELS:
  4937. return 0x1E<<24 | 0<<22 | 1<<21 | 3<<10
  4938. case AFCSELD:
  4939. return 0x1E<<24 | 1<<22 | 1<<21 | 3<<10
  4940. case AFMOVS:
  4941. return FPOP1S(0, 0, 0, 0)
  4942. case AFABSS:
  4943. return FPOP1S(0, 0, 0, 1)
  4944. case AFNEGS:
  4945. return FPOP1S(0, 0, 0, 2)
  4946. case AFSQRTS:
  4947. return FPOP1S(0, 0, 0, 3)
  4948. case AFCVTSD:
  4949. return FPOP1S(0, 0, 0, 5)
  4950. case AFCVTSH:
  4951. return FPOP1S(0, 0, 0, 7)
  4952. case AFRINTNS:
  4953. return FPOP1S(0, 0, 0, 8)
  4954. case AFRINTPS:
  4955. return FPOP1S(0, 0, 0, 9)
  4956. case AFRINTMS:
  4957. return FPOP1S(0, 0, 0, 10)
  4958. case AFRINTZS:
  4959. return FPOP1S(0, 0, 0, 11)
  4960. case AFRINTAS:
  4961. return FPOP1S(0, 0, 0, 12)
  4962. case AFRINTXS:
  4963. return FPOP1S(0, 0, 0, 14)
  4964. case AFRINTIS:
  4965. return FPOP1S(0, 0, 0, 15)
  4966. case AFMOVD:
  4967. return FPOP1S(0, 0, 1, 0)
  4968. case AFABSD:
  4969. return FPOP1S(0, 0, 1, 1)
  4970. case AFNEGD:
  4971. return FPOP1S(0, 0, 1, 2)
  4972. case AFSQRTD:
  4973. return FPOP1S(0, 0, 1, 3)
  4974. case AFCVTDS:
  4975. return FPOP1S(0, 0, 1, 4)
  4976. case AFCVTDH:
  4977. return FPOP1S(0, 0, 1, 7)
  4978. case AFRINTND:
  4979. return FPOP1S(0, 0, 1, 8)
  4980. case AFRINTPD:
  4981. return FPOP1S(0, 0, 1, 9)
  4982. case AFRINTMD:
  4983. return FPOP1S(0, 0, 1, 10)
  4984. case AFRINTZD:
  4985. return FPOP1S(0, 0, 1, 11)
  4986. case AFRINTAD:
  4987. return FPOP1S(0, 0, 1, 12)
  4988. case AFRINTXD:
  4989. return FPOP1S(0, 0, 1, 14)
  4990. case AFRINTID:
  4991. return FPOP1S(0, 0, 1, 15)
  4992. case AFCVTHS:
  4993. return FPOP1S(0, 0, 3, 4)
  4994. case AFCVTHD:
  4995. return FPOP1S(0, 0, 3, 5)
  4996. case AVADD:
  4997. return 7<<25 | 1<<21 | 1<<15 | 1<<10
  4998. case AVSUB:
  4999. return 0x17<<25 | 1<<21 | 1<<15 | 1<<10
  5000. case AVADDP:
  5001. return 7<<25 | 1<<21 | 1<<15 | 15<<10
  5002. case AVAND:
  5003. return 7<<25 | 1<<21 | 7<<10
  5004. case AVCMEQ:
  5005. return 1<<29 | 0x71<<21 | 0x23<<10
  5006. case AVCNT:
  5007. return 0xE<<24 | 0x10<<17 | 5<<12 | 2<<10
  5008. case AVZIP1:
  5009. return 0xE<<24 | 3<<12 | 2<<10
  5010. case AVZIP2:
  5011. return 0xE<<24 | 1<<14 | 3<<12 | 2<<10
  5012. case AVEOR:
  5013. return 1<<29 | 0x71<<21 | 7<<10
  5014. case AVORR:
  5015. return 7<<25 | 5<<21 | 7<<10
  5016. case AVREV16:
  5017. return 3<<26 | 2<<24 | 1<<21 | 3<<11
  5018. case AVREV32:
  5019. return 11<<26 | 2<<24 | 1<<21 | 1<<11
  5020. case AVREV64:
  5021. return 3<<26 | 2<<24 | 1<<21 | 1<<11
  5022. case AVMOV:
  5023. return 7<<25 | 5<<21 | 7<<10
  5024. case AVADDV:
  5025. return 7<<25 | 3<<20 | 3<<15 | 7<<11
  5026. case AVUADDLV:
  5027. return 1<<29 | 7<<25 | 3<<20 | 7<<11
  5028. case AVFMLA:
  5029. return 7<<25 | 0<<23 | 1<<21 | 3<<14 | 3<<10
  5030. case AVFMLS:
  5031. return 7<<25 | 1<<23 | 1<<21 | 3<<14 | 3<<10
  5032. case AVPMULL, AVPMULL2:
  5033. return 0xE<<24 | 1<<21 | 0x38<<10
  5034. case AVRBIT:
  5035. return 0x2E<<24 | 1<<22 | 0x10<<17 | 5<<12 | 2<<10
  5036. case AVLD1, AVLD2, AVLD3, AVLD4:
  5037. return 3<<26 | 1<<22
  5038. case AVLD1R, AVLD3R:
  5039. return 0xD<<24 | 1<<22
  5040. case AVLD2R, AVLD4R:
  5041. return 0xD<<24 | 3<<21
  5042. case AVBIF:
  5043. return 1<<29 | 7<<25 | 7<<21 | 7<<10
  5044. case AVBIT:
  5045. return 1<<29 | 0x75<<21 | 7<<10
  5046. case AVBSL:
  5047. return 1<<29 | 0x73<<21 | 7<<10
  5048. case AVCMTST:
  5049. return 0xE<<24 | 1<<21 | 0x23<<10
  5050. case AVUZP1:
  5051. return 7<<25 | 3<<11
  5052. case AVUZP2:
  5053. return 7<<25 | 1<<14 | 3<<11
  5054. }
  5055. c.ctxt.Diag("%v: bad rrr %d %v", p, a, a)
  5056. return 0
  5057. }
  5058. /*
  5059. * imm -> Rd
  5060. * imm op Rn -> Rd
  5061. */
  5062. func (c *ctxt7) opirr(p *obj.Prog, a obj.As) uint32 {
  5063. switch a {
  5064. /* op $addcon, Rn, Rd */
  5065. case AMOVD, AADD:
  5066. return S64 | 0<<30 | 0<<29 | 0x11<<24
  5067. case ACMN, AADDS:
  5068. return S64 | 0<<30 | 1<<29 | 0x11<<24
  5069. case AMOVW, AADDW:
  5070. return S32 | 0<<30 | 0<<29 | 0x11<<24
  5071. case ACMNW, AADDSW:
  5072. return S32 | 0<<30 | 1<<29 | 0x11<<24
  5073. case ASUB:
  5074. return S64 | 1<<30 | 0<<29 | 0x11<<24
  5075. case ACMP, ASUBS:
  5076. return S64 | 1<<30 | 1<<29 | 0x11<<24
  5077. case ASUBW:
  5078. return S32 | 1<<30 | 0<<29 | 0x11<<24
  5079. case ACMPW, ASUBSW:
  5080. return S32 | 1<<30 | 1<<29 | 0x11<<24
  5081. /* op $imm(SB), Rd; op label, Rd */
  5082. case AADR:
  5083. return 0<<31 | 0x10<<24
  5084. case AADRP:
  5085. return 1<<31 | 0x10<<24
  5086. /* op $bimm, Rn, Rd */
  5087. case AAND, ABIC:
  5088. return S64 | 0<<29 | 0x24<<23
  5089. case AANDW, ABICW:
  5090. return S32 | 0<<29 | 0x24<<23 | 0<<22
  5091. case AORR, AORN:
  5092. return S64 | 1<<29 | 0x24<<23
  5093. case AORRW, AORNW:
  5094. return S32 | 1<<29 | 0x24<<23 | 0<<22
  5095. case AEOR, AEON:
  5096. return S64 | 2<<29 | 0x24<<23
  5097. case AEORW, AEONW:
  5098. return S32 | 2<<29 | 0x24<<23 | 0<<22
  5099. case AANDS, ABICS, ATST:
  5100. return S64 | 3<<29 | 0x24<<23
  5101. case AANDSW, ABICSW, ATSTW:
  5102. return S32 | 3<<29 | 0x24<<23 | 0<<22
  5103. case AASR:
  5104. return S64 | 0<<29 | 0x26<<23 /* alias of SBFM */
  5105. case AASRW:
  5106. return S32 | 0<<29 | 0x26<<23 | 0<<22
  5107. /* op $width, $lsb, Rn, Rd */
  5108. case ABFI:
  5109. return S64 | 2<<29 | 0x26<<23 | 1<<22
  5110. /* alias of BFM */
  5111. case ABFIW:
  5112. return S32 | 2<<29 | 0x26<<23 | 0<<22
  5113. /* op $imms, $immr, Rn, Rd */
  5114. case ABFM:
  5115. return S64 | 1<<29 | 0x26<<23 | 1<<22
  5116. case ABFMW:
  5117. return S32 | 1<<29 | 0x26<<23 | 0<<22
  5118. case ASBFM:
  5119. return S64 | 0<<29 | 0x26<<23 | 1<<22
  5120. case ASBFMW:
  5121. return S32 | 0<<29 | 0x26<<23 | 0<<22
  5122. case AUBFM:
  5123. return S64 | 2<<29 | 0x26<<23 | 1<<22
  5124. case AUBFMW:
  5125. return S32 | 2<<29 | 0x26<<23 | 0<<22
  5126. case ABFXIL:
  5127. return S64 | 1<<29 | 0x26<<23 | 1<<22 /* alias of BFM */
  5128. case ABFXILW:
  5129. return S32 | 1<<29 | 0x26<<23 | 0<<22
  5130. case AEXTR:
  5131. return S64 | 0<<29 | 0x27<<23 | 1<<22 | 0<<21
  5132. case AEXTRW:
  5133. return S32 | 0<<29 | 0x27<<23 | 0<<22 | 0<<21
  5134. case ACBNZ:
  5135. return S64 | 0x1A<<25 | 1<<24
  5136. case ACBNZW:
  5137. return S32 | 0x1A<<25 | 1<<24
  5138. case ACBZ:
  5139. return S64 | 0x1A<<25 | 0<<24
  5140. case ACBZW:
  5141. return S32 | 0x1A<<25 | 0<<24
  5142. case ACCMN:
  5143. return S64 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  5144. case ACCMNW:
  5145. return S32 | 0<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
  5146. case ACCMP:
  5147. return S64 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4 /* imm5<<16 | cond<<12 | nzcv<<0 */
  5148. case ACCMPW:
  5149. return S32 | 1<<30 | 1<<29 | 0xD2<<21 | 1<<11 | 0<<10 | 0<<4
  5150. case AMOVK:
  5151. return S64 | 3<<29 | 0x25<<23
  5152. case AMOVKW:
  5153. return S32 | 3<<29 | 0x25<<23
  5154. case AMOVN:
  5155. return S64 | 0<<29 | 0x25<<23
  5156. case AMOVNW:
  5157. return S32 | 0<<29 | 0x25<<23
  5158. case AMOVZ:
  5159. return S64 | 2<<29 | 0x25<<23
  5160. case AMOVZW:
  5161. return S32 | 2<<29 | 0x25<<23
  5162. case AMSR:
  5163. return SYSOP(0, 0, 0, 4, 0, 0, 0x1F) /* MSR (immediate) */
  5164. case AAT,
  5165. ADC,
  5166. AIC,
  5167. ATLBI,
  5168. ASYS:
  5169. return SYSOP(0, 1, 0, 0, 0, 0, 0)
  5170. case ASYSL:
  5171. return SYSOP(1, 1, 0, 0, 0, 0, 0)
  5172. case ATBZ:
  5173. return 0x36 << 24
  5174. case ATBNZ:
  5175. return 0x37 << 24
  5176. case ADSB:
  5177. return SYSOP(0, 0, 3, 3, 0, 4, 0x1F)
  5178. case ADMB:
  5179. return SYSOP(0, 0, 3, 3, 0, 5, 0x1F)
  5180. case AISB:
  5181. return SYSOP(0, 0, 3, 3, 0, 6, 0x1F)
  5182. case AHINT:
  5183. return SYSOP(0, 0, 3, 2, 0, 0, 0x1F)
  5184. case AVEXT:
  5185. return 0x2E<<24 | 0<<23 | 0<<21 | 0<<15
  5186. case AVUSHR:
  5187. return 0x5E<<23 | 1<<10
  5188. case AVSHL:
  5189. return 0x1E<<23 | 21<<10
  5190. case AVSRI:
  5191. return 0x5E<<23 | 17<<10
  5192. case AVUSHLL, AVUXTL:
  5193. return 1<<29 | 15<<24 | 0x29<<10
  5194. case AVUSHLL2, AVUXTL2:
  5195. return 3<<29 | 15<<24 | 0x29<<10
  5196. }
  5197. c.ctxt.Diag("%v: bad irr %v", p, a)
  5198. return 0
  5199. }
  5200. func (c *ctxt7) opbit(p *obj.Prog, a obj.As) uint32 {
  5201. switch a {
  5202. case ACLS:
  5203. return S64 | OPBIT(5)
  5204. case ACLSW:
  5205. return S32 | OPBIT(5)
  5206. case ACLZ:
  5207. return S64 | OPBIT(4)
  5208. case ACLZW:
  5209. return S32 | OPBIT(4)
  5210. case ARBIT:
  5211. return S64 | OPBIT(0)
  5212. case ARBITW:
  5213. return S32 | OPBIT(0)
  5214. case AREV:
  5215. return S64 | OPBIT(3)
  5216. case AREVW:
  5217. return S32 | OPBIT(2)
  5218. case AREV16:
  5219. return S64 | OPBIT(1)
  5220. case AREV16W:
  5221. return S32 | OPBIT(1)
  5222. case AREV32:
  5223. return S64 | OPBIT(2)
  5224. default:
  5225. c.ctxt.Diag("bad bit op\n%v", p)
  5226. return 0
  5227. }
  5228. }
  5229. /*
  5230. * add/subtract sign or zero-extended register
  5231. */
  5232. func (c *ctxt7) opxrrr(p *obj.Prog, a obj.As, extend bool) uint32 {
  5233. extension := uint32(0)
  5234. if !extend {
  5235. switch a {
  5236. case AADD, ACMN, AADDS, ASUB, ACMP, ASUBS:
  5237. extension = LSL0_64
  5238. case AADDW, ACMNW, AADDSW, ASUBW, ACMPW, ASUBSW:
  5239. extension = LSL0_32
  5240. }
  5241. }
  5242. switch a {
  5243. case AADD:
  5244. return S64 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5245. case AADDW:
  5246. return S32 | 0<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5247. case ACMN, AADDS:
  5248. return S64 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5249. case ACMNW, AADDSW:
  5250. return S32 | 0<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5251. case ASUB:
  5252. return S64 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5253. case ASUBW:
  5254. return S32 | 1<<30 | 0<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5255. case ACMP, ASUBS:
  5256. return S64 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5257. case ACMPW, ASUBSW:
  5258. return S32 | 1<<30 | 1<<29 | 0x0b<<24 | 0<<22 | 1<<21 | extension
  5259. }
  5260. c.ctxt.Diag("bad opxrrr %v\n%v", a, p)
  5261. return 0
  5262. }
  5263. func (c *ctxt7) opimm(p *obj.Prog, a obj.As) uint32 {
  5264. switch a {
  5265. case ASVC:
  5266. return 0xD4<<24 | 0<<21 | 1 /* imm16<<5 */
  5267. case AHVC:
  5268. return 0xD4<<24 | 0<<21 | 2
  5269. case ASMC:
  5270. return 0xD4<<24 | 0<<21 | 3
  5271. case ABRK:
  5272. return 0xD4<<24 | 1<<21 | 0
  5273. case AHLT:
  5274. return 0xD4<<24 | 2<<21 | 0
  5275. case ADCPS1:
  5276. return 0xD4<<24 | 5<<21 | 1
  5277. case ADCPS2:
  5278. return 0xD4<<24 | 5<<21 | 2
  5279. case ADCPS3:
  5280. return 0xD4<<24 | 5<<21 | 3
  5281. case ACLREX:
  5282. return SYSOP(0, 0, 3, 3, 0, 2, 0x1F)
  5283. }
  5284. c.ctxt.Diag("%v: bad imm %v", p, a)
  5285. return 0
  5286. }
  5287. func (c *ctxt7) brdist(p *obj.Prog, preshift int, flen int, shift int) int64 {
  5288. v := int64(0)
  5289. t := int64(0)
  5290. q := p.To.Target()
  5291. if q == nil {
  5292. // TODO: don't use brdist for this case, as it isn't a branch.
  5293. // (Calls from omovlit, and maybe adr/adrp opcodes as well.)
  5294. q = p.Pool
  5295. }
  5296. if q != nil {
  5297. v = (q.Pc >> uint(preshift)) - (c.pc >> uint(preshift))
  5298. if (v & ((1 << uint(shift)) - 1)) != 0 {
  5299. c.ctxt.Diag("misaligned label\n%v", p)
  5300. }
  5301. v >>= uint(shift)
  5302. t = int64(1) << uint(flen-1)
  5303. if v < -t || v >= t {
  5304. c.ctxt.Diag("branch too far %#x vs %#x [%p]\n%v\n%v", v, t, c.blitrl, p, q)
  5305. panic("branch too far")
  5306. }
  5307. }
  5308. return v & ((t << 1) - 1)
  5309. }
  5310. /*
  5311. * pc-relative branches
  5312. */
  5313. func (c *ctxt7) opbra(p *obj.Prog, a obj.As) uint32 {
  5314. switch a {
  5315. case ABEQ:
  5316. return OPBcc(0x0)
  5317. case ABNE:
  5318. return OPBcc(0x1)
  5319. case ABCS:
  5320. return OPBcc(0x2)
  5321. case ABHS:
  5322. return OPBcc(0x2)
  5323. case ABCC:
  5324. return OPBcc(0x3)
  5325. case ABLO:
  5326. return OPBcc(0x3)
  5327. case ABMI:
  5328. return OPBcc(0x4)
  5329. case ABPL:
  5330. return OPBcc(0x5)
  5331. case ABVS:
  5332. return OPBcc(0x6)
  5333. case ABVC:
  5334. return OPBcc(0x7)
  5335. case ABHI:
  5336. return OPBcc(0x8)
  5337. case ABLS:
  5338. return OPBcc(0x9)
  5339. case ABGE:
  5340. return OPBcc(0xa)
  5341. case ABLT:
  5342. return OPBcc(0xb)
  5343. case ABGT:
  5344. return OPBcc(0xc)
  5345. case ABLE:
  5346. return OPBcc(0xd) /* imm19<<5 | cond */
  5347. case AB:
  5348. return 0<<31 | 5<<26 /* imm26 */
  5349. case obj.ADUFFZERO, obj.ADUFFCOPY, ABL:
  5350. return 1<<31 | 5<<26
  5351. }
  5352. c.ctxt.Diag("%v: bad bra %v", p, a)
  5353. return 0
  5354. }
  5355. func (c *ctxt7) opbrr(p *obj.Prog, a obj.As) uint32 {
  5356. switch a {
  5357. case ABL:
  5358. return OPBLR(1) /* BLR */
  5359. case AB:
  5360. return OPBLR(0) /* BR */
  5361. case obj.ARET:
  5362. return OPBLR(2) /* RET */
  5363. }
  5364. c.ctxt.Diag("%v: bad brr %v", p, a)
  5365. return 0
  5366. }
  5367. func (c *ctxt7) op0(p *obj.Prog, a obj.As) uint32 {
  5368. switch a {
  5369. case ADRPS:
  5370. return 0x6B<<25 | 5<<21 | 0x1F<<16 | 0x1F<<5
  5371. case AERET:
  5372. return 0x6B<<25 | 4<<21 | 0x1F<<16 | 0<<10 | 0x1F<<5
  5373. case ANOOP:
  5374. return SYSHINT(0)
  5375. case AYIELD:
  5376. return SYSHINT(1)
  5377. case AWFE:
  5378. return SYSHINT(2)
  5379. case AWFI:
  5380. return SYSHINT(3)
  5381. case ASEV:
  5382. return SYSHINT(4)
  5383. case ASEVL:
  5384. return SYSHINT(5)
  5385. }
  5386. c.ctxt.Diag("%v: bad op0 %v", p, a)
  5387. return 0
  5388. }
  5389. /*
  5390. * register offset
  5391. */
  5392. func (c *ctxt7) opload(p *obj.Prog, a obj.As) uint32 {
  5393. switch a {
  5394. case ALDAR:
  5395. return LDSTX(3, 1, 1, 0, 1) | 0x1F<<10
  5396. case ALDARW:
  5397. return LDSTX(2, 1, 1, 0, 1) | 0x1F<<10
  5398. case ALDARB:
  5399. return LDSTX(0, 1, 1, 0, 1) | 0x1F<<10
  5400. case ALDARH:
  5401. return LDSTX(1, 1, 1, 0, 1) | 0x1F<<10
  5402. case ALDAXP:
  5403. return LDSTX(3, 0, 1, 1, 1)
  5404. case ALDAXPW:
  5405. return LDSTX(2, 0, 1, 1, 1)
  5406. case ALDAXR:
  5407. return LDSTX(3, 0, 1, 0, 1) | 0x1F<<10
  5408. case ALDAXRW:
  5409. return LDSTX(2, 0, 1, 0, 1) | 0x1F<<10
  5410. case ALDAXRB:
  5411. return LDSTX(0, 0, 1, 0, 1) | 0x1F<<10
  5412. case ALDAXRH:
  5413. return LDSTX(1, 0, 1, 0, 1) | 0x1F<<10
  5414. case ALDXR:
  5415. return LDSTX(3, 0, 1, 0, 0) | 0x1F<<10
  5416. case ALDXRB:
  5417. return LDSTX(0, 0, 1, 0, 0) | 0x1F<<10
  5418. case ALDXRH:
  5419. return LDSTX(1, 0, 1, 0, 0) | 0x1F<<10
  5420. case ALDXRW:
  5421. return LDSTX(2, 0, 1, 0, 0) | 0x1F<<10
  5422. case ALDXP:
  5423. return LDSTX(3, 0, 1, 1, 0)
  5424. case ALDXPW:
  5425. return LDSTX(2, 0, 1, 1, 0)
  5426. case AMOVNP:
  5427. return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  5428. case AMOVNPW:
  5429. return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  5430. }
  5431. c.ctxt.Diag("bad opload %v\n%v", a, p)
  5432. return 0
  5433. }
  5434. func (c *ctxt7) opstore(p *obj.Prog, a obj.As) uint32 {
  5435. switch a {
  5436. case ASTLR:
  5437. return LDSTX(3, 1, 0, 0, 1) | 0x1F<<10
  5438. case ASTLRB:
  5439. return LDSTX(0, 1, 0, 0, 1) | 0x1F<<10
  5440. case ASTLRH:
  5441. return LDSTX(1, 1, 0, 0, 1) | 0x1F<<10
  5442. case ASTLP:
  5443. return LDSTX(3, 0, 0, 1, 1)
  5444. case ASTLPW:
  5445. return LDSTX(2, 0, 0, 1, 1)
  5446. case ASTLRW:
  5447. return LDSTX(2, 1, 0, 0, 1) | 0x1F<<10
  5448. case ASTLXP:
  5449. return LDSTX(3, 0, 0, 1, 1)
  5450. case ASTLXPW:
  5451. return LDSTX(2, 0, 0, 1, 1)
  5452. case ASTLXR:
  5453. return LDSTX(3, 0, 0, 0, 1) | 0x1F<<10
  5454. case ASTLXRB:
  5455. return LDSTX(0, 0, 0, 0, 1) | 0x1F<<10
  5456. case ASTLXRH:
  5457. return LDSTX(1, 0, 0, 0, 1) | 0x1F<<10
  5458. case ASTLXRW:
  5459. return LDSTX(2, 0, 0, 0, 1) | 0x1F<<10
  5460. case ASTXR:
  5461. return LDSTX(3, 0, 0, 0, 0) | 0x1F<<10
  5462. case ASTXRB:
  5463. return LDSTX(0, 0, 0, 0, 0) | 0x1F<<10
  5464. case ASTXRH:
  5465. return LDSTX(1, 0, 0, 0, 0) | 0x1F<<10
  5466. case ASTXP:
  5467. return LDSTX(3, 0, 0, 1, 0)
  5468. case ASTXPW:
  5469. return LDSTX(2, 0, 0, 1, 0)
  5470. case ASTXRW:
  5471. return LDSTX(2, 0, 0, 0, 0) | 0x1F<<10
  5472. case AMOVNP:
  5473. return S64 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  5474. case AMOVNPW:
  5475. return S32 | 0<<30 | 5<<27 | 0<<26 | 0<<23 | 1<<22
  5476. }
  5477. c.ctxt.Diag("bad opstore %v\n%v", a, p)
  5478. return 0
  5479. }
  5480. /*
  5481. * load/store register (unsigned immediate) C3.3.13
  5482. * these produce 64-bit values (when there's an option)
  5483. */
  5484. func (c *ctxt7) olsr12u(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
  5485. if v < 0 || v >= (1<<12) {
  5486. c.ctxt.Diag("offset out of range: %d\n%v", v, p)
  5487. }
  5488. o |= (v & 0xFFF) << 10
  5489. o |= int32(b&31) << 5
  5490. o |= int32(r & 31)
  5491. return uint32(o)
  5492. }
  5493. func (c *ctxt7) opldr12(p *obj.Prog, a obj.As) uint32 {
  5494. switch a {
  5495. case AMOVD:
  5496. return LDSTR12U(3, 0, 1) /* imm12<<10 | Rn<<5 | Rt */
  5497. case AMOVW:
  5498. return LDSTR12U(2, 0, 2)
  5499. case AMOVWU:
  5500. return LDSTR12U(2, 0, 1)
  5501. case AMOVH:
  5502. return LDSTR12U(1, 0, 2)
  5503. case AMOVHU:
  5504. return LDSTR12U(1, 0, 1)
  5505. case AMOVB:
  5506. return LDSTR12U(0, 0, 2)
  5507. case AMOVBU:
  5508. return LDSTR12U(0, 0, 1)
  5509. case AFMOVS:
  5510. return LDSTR12U(2, 1, 1)
  5511. case AFMOVD:
  5512. return LDSTR12U(3, 1, 1)
  5513. }
  5514. c.ctxt.Diag("bad opldr12 %v\n%v", a, p)
  5515. return 0
  5516. }
  5517. func (c *ctxt7) opstr12(p *obj.Prog, a obj.As) uint32 {
  5518. return LD2STR(c.opldr12(p, a))
  5519. }
  5520. /*
  5521. * load/store register (unscaled immediate) C3.3.12
  5522. */
  5523. func (c *ctxt7) olsr9s(p *obj.Prog, o int32, v int32, b int, r int) uint32 {
  5524. if v < -256 || v > 255 {
  5525. c.ctxt.Diag("offset out of range: %d\n%v", v, p)
  5526. }
  5527. o |= (v & 0x1FF) << 12
  5528. o |= int32(b&31) << 5
  5529. o |= int32(r & 31)
  5530. return uint32(o)
  5531. }
  5532. func (c *ctxt7) opldr9(p *obj.Prog, a obj.As) uint32 {
  5533. switch a {
  5534. case AMOVD:
  5535. return LDSTR9S(3, 0, 1) /* simm9<<12 | Rn<<5 | Rt */
  5536. case AMOVW:
  5537. return LDSTR9S(2, 0, 2)
  5538. case AMOVWU:
  5539. return LDSTR9S(2, 0, 1)
  5540. case AMOVH:
  5541. return LDSTR9S(1, 0, 2)
  5542. case AMOVHU:
  5543. return LDSTR9S(1, 0, 1)
  5544. case AMOVB:
  5545. return LDSTR9S(0, 0, 2)
  5546. case AMOVBU:
  5547. return LDSTR9S(0, 0, 1)
  5548. case AFMOVS:
  5549. return LDSTR9S(2, 1, 1)
  5550. case AFMOVD:
  5551. return LDSTR9S(3, 1, 1)
  5552. }
  5553. c.ctxt.Diag("bad opldr9 %v\n%v", a, p)
  5554. return 0
  5555. }
  5556. func (c *ctxt7) opstr9(p *obj.Prog, a obj.As) uint32 {
  5557. return LD2STR(c.opldr9(p, a))
  5558. }
  5559. func (c *ctxt7) opldrpp(p *obj.Prog, a obj.As) uint32 {
  5560. switch a {
  5561. case AMOVD:
  5562. return 3<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22 /* simm9<<12 | Rn<<5 | Rt */
  5563. case AMOVW:
  5564. return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
  5565. case AMOVWU:
  5566. return 2<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
  5567. case AMOVH:
  5568. return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
  5569. case AMOVHU:
  5570. return 1<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
  5571. case AMOVB:
  5572. return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 2<<22
  5573. case AMOVBU:
  5574. return 0<<30 | 7<<27 | 0<<26 | 0<<24 | 1<<22
  5575. case AFMOVS:
  5576. return 2<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22
  5577. case AFMOVD:
  5578. return 3<<30 | 7<<27 | 1<<26 | 0<<24 | 1<<22
  5579. case APRFM:
  5580. return 0xf9<<24 | 2<<22
  5581. }
  5582. c.ctxt.Diag("bad opldr %v\n%v", a, p)
  5583. return 0
  5584. }
  5585. // olsxrr attaches register operands to a load/store opcode supplied in o.
  5586. // The result either encodes a load of r from (r1+r2) or a store of r to (r1+r2).
  5587. func (c *ctxt7) olsxrr(p *obj.Prog, o int32, r int, r1 int, r2 int) uint32 {
  5588. o |= int32(r1&31) << 5
  5589. o |= int32(r2&31) << 16
  5590. o |= int32(r & 31)
  5591. return uint32(o)
  5592. }
  5593. // opldrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
  5594. // for load instruction with register offset.
  5595. // The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
  5596. func (c *ctxt7) opldrr(p *obj.Prog, a obj.As, extension bool) uint32 {
  5597. OptionS := uint32(0x1a)
  5598. if extension {
  5599. OptionS = uint32(0) // option value and S value have been encoded into p.From.Offset.
  5600. }
  5601. switch a {
  5602. case AMOVD:
  5603. return OptionS<<10 | 0x3<<21 | 0x1f<<27
  5604. case AMOVW:
  5605. return OptionS<<10 | 0x5<<21 | 0x17<<27
  5606. case AMOVWU:
  5607. return OptionS<<10 | 0x3<<21 | 0x17<<27
  5608. case AMOVH:
  5609. return OptionS<<10 | 0x5<<21 | 0x0f<<27
  5610. case AMOVHU:
  5611. return OptionS<<10 | 0x3<<21 | 0x0f<<27
  5612. case AMOVB:
  5613. return OptionS<<10 | 0x5<<21 | 0x07<<27
  5614. case AMOVBU:
  5615. return OptionS<<10 | 0x3<<21 | 0x07<<27
  5616. case AFMOVS:
  5617. return OptionS<<10 | 0x3<<21 | 0x17<<27 | 1<<26
  5618. case AFMOVD:
  5619. return OptionS<<10 | 0x3<<21 | 0x1f<<27 | 1<<26
  5620. }
  5621. c.ctxt.Diag("bad opldrr %v\n%v", a, p)
  5622. return 0
  5623. }
  5624. // opstrr returns the ARM64 opcode encoding corresponding to the obj.As opcode
  5625. // for store instruction with register offset.
  5626. // The offset register can be (Rn)(Rm.UXTW<<2) or (Rn)(Rm<<2) or (Rn)(Rm).
  5627. func (c *ctxt7) opstrr(p *obj.Prog, a obj.As, extension bool) uint32 {
  5628. OptionS := uint32(0x1a)
  5629. if extension {
  5630. OptionS = uint32(0) // option value and S value have been encoded into p.To.Offset.
  5631. }
  5632. switch a {
  5633. case AMOVD:
  5634. return OptionS<<10 | 0x1<<21 | 0x1f<<27
  5635. case AMOVW, AMOVWU:
  5636. return OptionS<<10 | 0x1<<21 | 0x17<<27
  5637. case AMOVH, AMOVHU:
  5638. return OptionS<<10 | 0x1<<21 | 0x0f<<27
  5639. case AMOVB, AMOVBU:
  5640. return OptionS<<10 | 0x1<<21 | 0x07<<27
  5641. case AFMOVS:
  5642. return OptionS<<10 | 0x1<<21 | 0x17<<27 | 1<<26
  5643. case AFMOVD:
  5644. return OptionS<<10 | 0x1<<21 | 0x1f<<27 | 1<<26
  5645. }
  5646. c.ctxt.Diag("bad opstrr %v\n%v", a, p)
  5647. return 0
  5648. }
  5649. func (c *ctxt7) oaddi(p *obj.Prog, o1 int32, v int32, r int, rt int) uint32 {
  5650. if (v & 0xFFF000) != 0 {
  5651. if v&0xFFF != 0 {
  5652. c.ctxt.Diag("%v misuses oaddi", p)
  5653. }
  5654. v >>= 12
  5655. o1 |= 1 << 22
  5656. }
  5657. o1 |= ((v & 0xFFF) << 10) | (int32(r&31) << 5) | int32(rt&31)
  5658. return uint32(o1)
  5659. }
  5660. /*
  5661. * load a literal value into dr
  5662. */
  5663. func (c *ctxt7) omovlit(as obj.As, p *obj.Prog, a *obj.Addr, dr int) uint32 {
  5664. var o1 int32
  5665. if p.Pool == nil { /* not in literal pool */
  5666. c.aclass(a)
  5667. c.ctxt.Logf("omovlit add %d (%#x)\n", c.instoffset, uint64(c.instoffset))
  5668. /* TODO: could be clever, and use general constant builder */
  5669. o1 = int32(c.opirr(p, AADD))
  5670. v := int32(c.instoffset)
  5671. if v != 0 && (v&0xFFF) == 0 {
  5672. v >>= 12
  5673. o1 |= 1 << 22 /* shift, by 12 */
  5674. }
  5675. o1 |= ((v & 0xFFF) << 10) | (REGZERO & 31 << 5) | int32(dr&31)
  5676. } else {
  5677. fp, w := 0, 0
  5678. switch as {
  5679. case AFMOVS:
  5680. fp = 1
  5681. w = 0 /* 32-bit SIMD/FP */
  5682. case AFMOVD:
  5683. fp = 1
  5684. w = 1 /* 64-bit SIMD/FP */
  5685. case AFMOVQ:
  5686. fp = 1
  5687. w = 2 /* 128-bit SIMD/FP */
  5688. case AMOVD:
  5689. if p.Pool.As == ADWORD {
  5690. w = 1 /* 64-bit */
  5691. } else if p.Pool.To.Offset < 0 {
  5692. w = 2 /* 32-bit, sign-extended to 64-bit */
  5693. } else if p.Pool.To.Offset >= 0 {
  5694. w = 0 /* 32-bit, zero-extended to 64-bit */
  5695. } else {
  5696. c.ctxt.Diag("invalid operand %v in %v", a, p)
  5697. }
  5698. case AMOVBU, AMOVHU, AMOVWU:
  5699. w = 0 /* 32-bit, zero-extended to 64-bit */
  5700. case AMOVB, AMOVH, AMOVW:
  5701. w = 2 /* 32-bit, sign-extended to 64-bit */
  5702. default:
  5703. c.ctxt.Diag("invalid operation %v in %v", as, p)
  5704. }
  5705. v := int32(c.brdist(p, 0, 19, 2))
  5706. o1 = (int32(w) << 30) | (int32(fp) << 26) | (3 << 27)
  5707. o1 |= (v & 0x7FFFF) << 5
  5708. o1 |= int32(dr & 31)
  5709. }
  5710. return uint32(o1)
  5711. }
  5712. // load a constant (MOVCON or BITCON) in a into rt
  5713. func (c *ctxt7) omovconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int) (o1 uint32) {
  5714. if cls := oclass(a); cls == C_BITCON || cls == C_ABCON || cls == C_ABCON0 {
  5715. // or $bitcon, REGZERO, rt
  5716. mode := 64
  5717. var as1 obj.As
  5718. switch as {
  5719. case AMOVW:
  5720. as1 = AORRW
  5721. mode = 32
  5722. case AMOVD:
  5723. as1 = AORR
  5724. }
  5725. o1 = c.opirr(p, as1)
  5726. o1 |= bitconEncode(uint64(a.Offset), mode) | uint32(REGZERO&31)<<5 | uint32(rt&31)
  5727. return o1
  5728. }
  5729. if as == AMOVW {
  5730. d := uint32(a.Offset)
  5731. s := movcon(int64(d))
  5732. if s < 0 || 16*s >= 32 {
  5733. d = ^d
  5734. s = movcon(int64(d))
  5735. if s < 0 || 16*s >= 32 {
  5736. c.ctxt.Diag("impossible 32-bit move wide: %#x\n%v", uint32(a.Offset), p)
  5737. }
  5738. o1 = c.opirr(p, AMOVNW)
  5739. } else {
  5740. o1 = c.opirr(p, AMOVZW)
  5741. }
  5742. o1 |= MOVCONST(int64(d), s, rt)
  5743. }
  5744. if as == AMOVD {
  5745. d := a.Offset
  5746. s := movcon(d)
  5747. if s < 0 || 16*s >= 64 {
  5748. d = ^d
  5749. s = movcon(d)
  5750. if s < 0 || 16*s >= 64 {
  5751. c.ctxt.Diag("impossible 64-bit move wide: %#x\n%v", uint64(a.Offset), p)
  5752. }
  5753. o1 = c.opirr(p, AMOVN)
  5754. } else {
  5755. o1 = c.opirr(p, AMOVZ)
  5756. }
  5757. o1 |= MOVCONST(d, s, rt)
  5758. }
  5759. return o1
  5760. }
  5761. // load a 32-bit/64-bit large constant (LCON or VCON) in a.Offset into rt
  5762. // put the instruction sequence in os and return the number of instructions.
  5763. func (c *ctxt7) omovlconst(as obj.As, p *obj.Prog, a *obj.Addr, rt int, os []uint32) (num uint8) {
  5764. switch as {
  5765. case AMOVW:
  5766. d := uint32(a.Offset)
  5767. // use MOVZW and MOVKW to load a constant to rt
  5768. os[0] = c.opirr(p, AMOVZW)
  5769. os[0] |= MOVCONST(int64(d), 0, rt)
  5770. os[1] = c.opirr(p, AMOVKW)
  5771. os[1] |= MOVCONST(int64(d), 1, rt)
  5772. return 2
  5773. case AMOVD:
  5774. d := a.Offset
  5775. dn := ^d
  5776. var immh [4]uint64
  5777. var i int
  5778. zeroCount := int(0)
  5779. negCount := int(0)
  5780. for i = 0; i < 4; i++ {
  5781. immh[i] = uint64((d >> uint(i*16)) & 0xffff)
  5782. if immh[i] == 0 {
  5783. zeroCount++
  5784. } else if immh[i] == 0xffff {
  5785. negCount++
  5786. }
  5787. }
  5788. if zeroCount == 4 || negCount == 4 {
  5789. c.ctxt.Diag("the immediate should be MOVCON: %v", p)
  5790. }
  5791. switch {
  5792. case zeroCount == 3:
  5793. // one MOVZ
  5794. for i = 0; i < 4; i++ {
  5795. if immh[i] != 0 {
  5796. os[0] = c.opirr(p, AMOVZ)
  5797. os[0] |= MOVCONST(d, i, rt)
  5798. break
  5799. }
  5800. }
  5801. return 1
  5802. case negCount == 3:
  5803. // one MOVN
  5804. for i = 0; i < 4; i++ {
  5805. if immh[i] != 0xffff {
  5806. os[0] = c.opirr(p, AMOVN)
  5807. os[0] |= MOVCONST(dn, i, rt)
  5808. break
  5809. }
  5810. }
  5811. return 1
  5812. case zeroCount == 2:
  5813. // one MOVZ and one MOVK
  5814. for i = 0; i < 4; i++ {
  5815. if immh[i] != 0 {
  5816. os[0] = c.opirr(p, AMOVZ)
  5817. os[0] |= MOVCONST(d, i, rt)
  5818. i++
  5819. break
  5820. }
  5821. }
  5822. for ; i < 4; i++ {
  5823. if immh[i] != 0 {
  5824. os[1] = c.opirr(p, AMOVK)
  5825. os[1] |= MOVCONST(d, i, rt)
  5826. }
  5827. }
  5828. return 2
  5829. case negCount == 2:
  5830. // one MOVN and one MOVK
  5831. for i = 0; i < 4; i++ {
  5832. if immh[i] != 0xffff {
  5833. os[0] = c.opirr(p, AMOVN)
  5834. os[0] |= MOVCONST(dn, i, rt)
  5835. i++
  5836. break
  5837. }
  5838. }
  5839. for ; i < 4; i++ {
  5840. if immh[i] != 0xffff {
  5841. os[1] = c.opirr(p, AMOVK)
  5842. os[1] |= MOVCONST(d, i, rt)
  5843. }
  5844. }
  5845. return 2
  5846. case zeroCount == 1:
  5847. // one MOVZ and two MOVKs
  5848. for i = 0; i < 4; i++ {
  5849. if immh[i] != 0 {
  5850. os[0] = c.opirr(p, AMOVZ)
  5851. os[0] |= MOVCONST(d, i, rt)
  5852. i++
  5853. break
  5854. }
  5855. }
  5856. for j := 1; i < 4; i++ {
  5857. if immh[i] != 0 {
  5858. os[j] = c.opirr(p, AMOVK)
  5859. os[j] |= MOVCONST(d, i, rt)
  5860. j++
  5861. }
  5862. }
  5863. return 3
  5864. case negCount == 1:
  5865. // one MOVN and two MOVKs
  5866. for i = 0; i < 4; i++ {
  5867. if immh[i] != 0xffff {
  5868. os[0] = c.opirr(p, AMOVN)
  5869. os[0] |= MOVCONST(dn, i, rt)
  5870. i++
  5871. break
  5872. }
  5873. }
  5874. for j := 1; i < 4; i++ {
  5875. if immh[i] != 0xffff {
  5876. os[j] = c.opirr(p, AMOVK)
  5877. os[j] |= MOVCONST(d, i, rt)
  5878. j++
  5879. }
  5880. }
  5881. return 3
  5882. default:
  5883. // one MOVZ and 3 MOVKs
  5884. os[0] = c.opirr(p, AMOVZ)
  5885. os[0] |= MOVCONST(d, 0, rt)
  5886. for i = 1; i < 4; i++ {
  5887. os[i] = c.opirr(p, AMOVK)
  5888. os[i] |= MOVCONST(d, i, rt)
  5889. }
  5890. return 4
  5891. }
  5892. default:
  5893. return 0
  5894. }
  5895. }
  5896. func (c *ctxt7) opbfm(p *obj.Prog, a obj.As, r int, s int, rf int, rt int) uint32 {
  5897. var b uint32
  5898. o := c.opirr(p, a)
  5899. if (o & (1 << 31)) == 0 {
  5900. b = 32
  5901. } else {
  5902. b = 64
  5903. }
  5904. if r < 0 || uint32(r) >= b {
  5905. c.ctxt.Diag("illegal bit number\n%v", p)
  5906. }
  5907. o |= (uint32(r) & 0x3F) << 16
  5908. if s < 0 || uint32(s) >= b {
  5909. c.ctxt.Diag("illegal bit number\n%v", p)
  5910. }
  5911. o |= (uint32(s) & 0x3F) << 10
  5912. o |= (uint32(rf&31) << 5) | uint32(rt&31)
  5913. return o
  5914. }
  5915. func (c *ctxt7) opextr(p *obj.Prog, a obj.As, v int32, rn int, rm int, rt int) uint32 {
  5916. var b uint32
  5917. o := c.opirr(p, a)
  5918. if (o & (1 << 31)) != 0 {
  5919. b = 63
  5920. } else {
  5921. b = 31
  5922. }
  5923. if v < 0 || uint32(v) > b {
  5924. c.ctxt.Diag("illegal bit number\n%v", p)
  5925. }
  5926. o |= uint32(v) << 10
  5927. o |= uint32(rn&31) << 5
  5928. o |= uint32(rm&31) << 16
  5929. o |= uint32(rt & 31)
  5930. return o
  5931. }
  5932. /* genrate instruction encoding for LDP/LDPW/LDPSW/STP/STPW */
  5933. func (c *ctxt7) opldpstp(p *obj.Prog, o *Optab, vo int32, rbase, rl, rh, ldp uint32) uint32 {
  5934. wback := false
  5935. if o.scond == C_XPOST || o.scond == C_XPRE {
  5936. wback = true
  5937. }
  5938. switch p.As {
  5939. case ALDP, ALDPW, ALDPSW:
  5940. c.checkUnpredictable(p, true, wback, p.From.Reg, p.To.Reg, int16(p.To.Offset))
  5941. case ASTP, ASTPW:
  5942. if wback == true {
  5943. c.checkUnpredictable(p, false, true, p.To.Reg, p.From.Reg, int16(p.From.Offset))
  5944. }
  5945. case AFLDPD, AFLDPS:
  5946. c.checkUnpredictable(p, true, false, p.From.Reg, p.To.Reg, int16(p.To.Offset))
  5947. }
  5948. var ret uint32
  5949. // check offset
  5950. switch p.As {
  5951. case AFLDPD, AFSTPD:
  5952. if vo < -512 || vo > 504 || vo%8 != 0 {
  5953. c.ctxt.Diag("invalid offset %v\n", p)
  5954. }
  5955. vo /= 8
  5956. ret = 1<<30 | 1<<26
  5957. case ALDP, ASTP:
  5958. if vo < -512 || vo > 504 || vo%8 != 0 {
  5959. c.ctxt.Diag("invalid offset %v\n", p)
  5960. }
  5961. vo /= 8
  5962. ret = 2 << 30
  5963. case AFLDPS, AFSTPS:
  5964. if vo < -256 || vo > 252 || vo%4 != 0 {
  5965. c.ctxt.Diag("invalid offset %v\n", p)
  5966. }
  5967. vo /= 4
  5968. ret = 1 << 26
  5969. case ALDPW, ASTPW:
  5970. if vo < -256 || vo > 252 || vo%4 != 0 {
  5971. c.ctxt.Diag("invalid offset %v\n", p)
  5972. }
  5973. vo /= 4
  5974. ret = 0
  5975. case ALDPSW:
  5976. if vo < -256 || vo > 252 || vo%4 != 0 {
  5977. c.ctxt.Diag("invalid offset %v\n", p)
  5978. }
  5979. vo /= 4
  5980. ret = 1 << 30
  5981. default:
  5982. c.ctxt.Diag("invalid instruction %v\n", p)
  5983. }
  5984. // check register pair
  5985. switch p.As {
  5986. case AFLDPD, AFLDPS, AFSTPD, AFSTPS:
  5987. if rl < REG_F0 || REG_F31 < rl || rh < REG_F0 || REG_F31 < rh {
  5988. c.ctxt.Diag("invalid register pair %v\n", p)
  5989. }
  5990. case ALDP, ALDPW, ALDPSW:
  5991. if rl < REG_R0 || REG_R30 < rl || rh < REG_R0 || REG_R30 < rh {
  5992. c.ctxt.Diag("invalid register pair %v\n", p)
  5993. }
  5994. case ASTP, ASTPW:
  5995. if rl < REG_R0 || REG_R31 < rl || rh < REG_R0 || REG_R31 < rh {
  5996. c.ctxt.Diag("invalid register pair %v\n", p)
  5997. }
  5998. }
  5999. // other conditional flag bits
  6000. switch o.scond {
  6001. case C_XPOST:
  6002. ret |= 1 << 23
  6003. case C_XPRE:
  6004. ret |= 3 << 23
  6005. default:
  6006. ret |= 2 << 23
  6007. }
  6008. ret |= 5<<27 | (ldp&1)<<22 | uint32(vo&0x7f)<<15 | (rh&31)<<10 | (rbase&31)<<5 | (rl & 31)
  6009. return ret
  6010. }
  6011. func (c *ctxt7) maskOpvldvst(p *obj.Prog, o1 uint32) uint32 {
  6012. if p.As == AVLD1 || p.As == AVST1 {
  6013. return o1
  6014. }
  6015. o1 &^= 0xf000 // mask out "opcode" field (bit 12-15)
  6016. switch p.As {
  6017. case AVLD1R, AVLD2R:
  6018. o1 |= 0xC << 12
  6019. case AVLD3R, AVLD4R:
  6020. o1 |= 0xE << 12
  6021. case AVLD2, AVST2:
  6022. o1 |= 8 << 12
  6023. case AVLD3, AVST3:
  6024. o1 |= 4 << 12
  6025. case AVLD4, AVST4:
  6026. default:
  6027. c.ctxt.Diag("unsupported instruction:%v\n", p.As)
  6028. }
  6029. return o1
  6030. }
  6031. /*
  6032. * size in log2(bytes)
  6033. */
  6034. func movesize(a obj.As) int {
  6035. switch a {
  6036. case AMOVD:
  6037. return 3
  6038. case AMOVW, AMOVWU:
  6039. return 2
  6040. case AMOVH, AMOVHU:
  6041. return 1
  6042. case AMOVB, AMOVBU:
  6043. return 0
  6044. case AFMOVS:
  6045. return 2
  6046. case AFMOVD:
  6047. return 3
  6048. default:
  6049. return -1
  6050. }
  6051. }
  6052. // rm is the Rm register value, o is the extension, amount is the left shift value.
  6053. func roff(rm int16, o uint32, amount int16) uint32 {
  6054. return uint32(rm&31)<<16 | o<<13 | uint32(amount)<<10
  6055. }
  6056. // encRegShiftOrExt returns the encoding of shifted/extended register, Rx<<n and Rx.UXTW<<n, etc.
  6057. func (c *ctxt7) encRegShiftOrExt(a *obj.Addr, r int16) uint32 {
  6058. var num, rm int16
  6059. num = (r >> 5) & 7
  6060. rm = r & 31
  6061. switch {
  6062. case REG_UXTB <= r && r < REG_UXTH:
  6063. return roff(rm, 0, num)
  6064. case REG_UXTH <= r && r < REG_UXTW:
  6065. return roff(rm, 1, num)
  6066. case REG_UXTW <= r && r < REG_UXTX:
  6067. if a.Type == obj.TYPE_MEM {
  6068. if num == 0 {
  6069. return roff(rm, 2, 2)
  6070. } else {
  6071. return roff(rm, 2, 6)
  6072. }
  6073. } else {
  6074. return roff(rm, 2, num)
  6075. }
  6076. case REG_UXTX <= r && r < REG_SXTB:
  6077. return roff(rm, 3, num)
  6078. case REG_SXTB <= r && r < REG_SXTH:
  6079. return roff(rm, 4, num)
  6080. case REG_SXTH <= r && r < REG_SXTW:
  6081. return roff(rm, 5, num)
  6082. case REG_SXTW <= r && r < REG_SXTX:
  6083. if a.Type == obj.TYPE_MEM {
  6084. if num == 0 {
  6085. return roff(rm, 6, 2)
  6086. } else {
  6087. return roff(rm, 6, 6)
  6088. }
  6089. } else {
  6090. return roff(rm, 6, num)
  6091. }
  6092. case REG_SXTX <= r && r < REG_SPECIAL:
  6093. if a.Type == obj.TYPE_MEM {
  6094. if num == 0 {
  6095. return roff(rm, 7, 2)
  6096. } else {
  6097. return roff(rm, 7, 6)
  6098. }
  6099. } else {
  6100. return roff(rm, 7, num)
  6101. }
  6102. case REG_LSL <= r && r < (REG_LSL+1<<8):
  6103. return roff(rm, 3, 6)
  6104. default:
  6105. c.ctxt.Diag("unsupported register extension type.")
  6106. }
  6107. return 0
  6108. }