1 Star 0 Fork 126

wanglmb/qemu

forked from src-openEuler/qemu 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
该仓库未声明开源许可证文件(LICENSE),使用请关注具体项目描述及其代码上游依赖。
克隆/下载
sw_64-Added-sw64-architecture-related-updates.patch 211.33 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108
From 91b0065ca578a6e494b39736f746fcddddfc2978 Mon Sep 17 00:00:00 2001
From: Lu Feifei <lufeifei@wxiat.com>
Date: Wed, 26 Jul 2023 14:19:42 +0800
Subject: [PATCH] sw_64: Added sw64 architecture related updates
Signed-off-by: Lu Feifei <lufeifei@wxiat.com>
---
configs/targets/sw64-linux-user.mak | 5 +
configs/targets/sw64-softmmu.mak | 1 +
disas/sw64.c | 41 +-
gdb-xml/sw64-core.xml | 43 +
hw/rtc/sun4v-rtc.c | 11 -
hw/sw64/Kconfig | 5 +-
hw/sw64/core3.c | 25 +-
hw/sw64/core3_board.c | 73 +-
hw/sw64/sw64_iommu.c | 11 +-
linux-headers/asm-sw64/kvm.h | 14 +
linux-user/elfload.c | 16 +
linux-user/host/sw64/host-signal.h | 46 +
linux-user/host/sw64/hostdep.h | 14 +
linux-user/sw64/cpu_loop.c | 5 +-
linux-user/sw64/meson.build | 5 +
linux-user/sw64/signal.c | 33 +-
linux-user/sw64/syscall.tbl | 488 +++++
linux-user/sw64/syscallhdr.sh | 32 +
linux-user/sw64/target_cpu.h | 15 +-
linux-user/sw64/target_errno_defs.h | 204 ++
linux-user/sw64/target_signal.h | 2 +
linux-user/sw64/target_syscall.h | 12 +-
linux-user/sw64/termbits.h | 1 +
linux-user/syscall_defs.h | 46 +-
pc-bios/core3-hmcode | Bin 225904 -> 227168 bytes
pc-bios/core3-reset | Bin 5032 -> 229200 bytes
pc-bios/uefi-bios-sw | Bin 3145728 -> 3145728 bytes
target/sw64/Makefile.objs | 1 +
target/sw64/cpu-param.h | 8 +-
target/sw64/cpu.c | 163 +-
target/sw64/cpu.h | 17 +-
target/sw64/gdbstub.c | 56 +
target/sw64/helper.c | 142 +-
target/sw64/kvm.c | 146 +-
target/sw64/kvm_sw64.h | 9 +
target/sw64/machine.c | 2 +-
target/sw64/meson.build | 1 +
target/sw64/translate.c | 2 +-
tcg/sw64/tcg-target.c.inc | 2839 +++++++++++++++------------
tcg/sw64/tcg-target.h | 3 +
40 files changed, 3043 insertions(+), 1494 deletions(-)
create mode 100644 configs/targets/sw64-linux-user.mak
create mode 100644 gdb-xml/sw64-core.xml
create mode 100644 linux-user/host/sw64/host-signal.h
create mode 100755 linux-user/host/sw64/hostdep.h
create mode 100644 linux-user/sw64/meson.build
create mode 100644 linux-user/sw64/syscall.tbl
create mode 100644 linux-user/sw64/syscallhdr.sh
create mode 100644 linux-user/sw64/target_errno_defs.h
mode change 100755 => 100644 pc-bios/core3-hmcode
create mode 100644 target/sw64/gdbstub.c
diff --git a/configs/targets/sw64-linux-user.mak b/configs/targets/sw64-linux-user.mak
new file mode 100644
index 0000000000..ae00665692
--- /dev/null
+++ b/configs/targets/sw64-linux-user.mak
@@ -0,0 +1,5 @@
+TARGET_ARCH=sw64
+TARGET_SYSTBL_ABI=common
+TARGET_SYSTBL=syscall.tbl
+TARGET_ALIGNED_ONLY=y
+TARGET_XML_FILES= gdb-xml/sw64-core.xml
diff --git a/configs/targets/sw64-softmmu.mak b/configs/targets/sw64-softmmu.mak
index 37cc2e05a6..9cf002df8c 100644
--- a/configs/targets/sw64-softmmu.mak
+++ b/configs/targets/sw64-softmmu.mak
@@ -6,3 +6,4 @@ TARGET_ARCH=sw64
TARGET_BASE_ARCH=sw64
TARGET_ABI_DIR=sw64
TARGET_SUPPORTS_MTTCG=y
+TARGET_XML_FILES= gdb-xml/sw64-core.xml
diff --git a/disas/sw64.c b/disas/sw64.c
index c5bd578e07..16504c673a 100755
--- a/disas/sw64.c
+++ b/disas/sw64.c
@@ -62,7 +62,7 @@ extern const unsigned sw_64_num_opcodes;
#define SW_OPCODE_CORE3 0x0002 /* Core3 private insns. */
#define SW_LITOP(i) (((i) >> 26) & 0x3D)
-#define SW_OPCODE_NOHM (~(SW_OPCODE_BASE|SW_OPCODE_CORE3))
+#define SW_OPCODE_NOHMCODE (~(SW_OPCODE_BASE|SW_OPCODE_CORE3))
/* A macro to extract the major opcode from an instruction. */
#define SW_OP(i) (((i) >> 26) & 0x3F)
@@ -328,18 +328,6 @@ static int extract_bdisp(unsigned insn, int *invalid ATTRIBUTE_UNUSED)
return 4 * (((insn & 0x1FFFFF) ^ 0x100000) - 0x100000);
}
-static unsigned insert_bdisp26(unsigned insn, int value, const char **errmsg)
-{
- if (errmsg != (const char **)NULL && (value & 3))
- *errmsg = "branch operand unaligned";
- return insn | ((value / 4) & 0x3FFFFFF);
-}
-
-static int extract_bdisp26(unsigned insn, int *invalid ATTRIBUTE_UNUSED)
-{
- return 4 * (((insn & 0x3FFFFFF) ^ 0x2000000) - 0x2000000);
-}
-
/* The hint field of a JMP/JSR insn. */
/* sw use 16 bits hint disp. */
static unsigned insert_jhint(unsigned insn, int value, const char **errmsg)
@@ -480,13 +468,9 @@ const struct sw_64_operand sw_64_operands[] = {
{ 16, 0, -HWINDEX, SW_OPERAND_UNSIGNED, 0, 0 },
/* The 13-bit branch hint for the core3 hw_jmp/jsr (pal1e) insn. */
-#define HWJMPHINT (HWINDEX + 1)
- { 8, 0, -HWJMPHINT,
- SW_OPERAND_RELATIVE | SW_OPERAND_DEFAULT_ZERO | SW_OPERAND_NOOVERFLOW,
- insert_sw4hwjhint, extract_sw4hwjhint },
/* for the third operand of ternary operands integer insn. */
-#define R3 (HWJMPHINT + 1)
+#define R3 (HWINDEX + 1)
{ 5, 5, 0, SW_OPERAND_IR, 0, 0 },
/* The plain fp register fields */
#define F3 (R3 + 1)
@@ -494,19 +478,10 @@ const struct sw_64_operand sw_64_operands[] = {
/* sw simd settle instruction lit */
#define FMALIT (F3 + 1)
{ 5, 5, -FMALIT, SW_OPERAND_UNSIGNED, 0, 0 }, //V1.1
-#define LMDISP (FMALIT + 1)
- { 15, 0, -LMDISP, SW_OPERAND_UNSIGNED, 0, 0 },
-#define RPIINDEX (LMDISP + 1)
+#define RPIINDEX (FMALIT + 1)
{ 8, 0, -RPIINDEX, SW_OPERAND_UNSIGNED, 0, 0 },
#define ATMDISP (RPIINDEX + 1)
{ 12, 0, -ATMDISP, SW_OPERAND_SIGNED, 0, 0 },
-#define DISP13 (ATMDISP + 1)
- { 13, 13, -DISP13, SW_OPERAND_SIGNED, 0, 0},
-#define BDISP26 (DISP13 + 1)
- { 26, 0, 222,
- SW_OPERAND_RELATIVE, insert_bdisp26, extract_bdisp26 },
-#define DPFTH (BDISP26 + 1)
- { 5, 21, -DPFTH, SW_OPERAND_UNSIGNED, 0, 0}
};
const unsigned sw_64_num_operands = sizeof(sw_64_operands) / sizeof(*sw_64_operands);
@@ -578,7 +553,7 @@ const unsigned sw_64_num_operands = sizeof(sw_64_operands) / sizeof(*sw_64_opera
#define PRIRET_MASK (OP_MASK | 0x100000)
#define PRIRET(oo,h) PRIRET_(oo,h), PRIRET_MASK
-/* sw rpi_rcsr,rpi_wcsr. */
+/* sw pri_rcsr,pri_wcsr. */
#define CSR_(oo,ff) (OP(oo) | (((ff) & 0xFF) << 8))
#define CSR_MASK (OP_MASK | 0xFF00)
#define CSR(oo,ff) CSR_(oo,ff), CSR_MASK
@@ -610,8 +585,6 @@ const unsigned sw_64_num_operands = sizeof(sw_64_operands) / sizeof(*sw_64_opera
#define ARG_FMEM { FA, MDISP, PRB }
#define ARG_OPR { RA, RB, DRC1 }
-#define ARG_OPRCAS { RA, RB, RC }
-
#define ARG_OPRL { RA, LIT, DRC1 }
#define ARG_OPRZ1 { ZA, RB, DRC1 }
#define ARG_OPRLZ1 { ZA, LIT, RC }
@@ -625,9 +598,6 @@ const unsigned sw_64_num_operands = sizeof(sw_64_operands) / sizeof(*sw_64_opera
#define ARG_FMAL { FA,FB,FMALIT, DFC1 }
#define ARG_ATMEM { RA, ATMDISP, PRB }
#define ARG_VUAMEM { FA, ATMDISP, PRB }
-#define ARG_OPRLZ3 { RA, LIT, ZC }
-
-#define ARG_DISP13 {DISP13, RC}
/* The opcode table.
@@ -662,6 +632,7 @@ const struct sw_64_opcode sw_64_opcodes[] = {
{ "jmp", MEM(0x03), BASE, { RA, CPRB, JMPHINT } },
{ "br", BRA(0x04), BASE, { ZA, BDISP } },
{ "br", BRA(0x04), BASE, ARG_BRA },
+ { "bsr", BRA(0x05), BASE, { ZA, BDISP } },
{ "bsr", BRA(0x05), BASE, ARG_BRA },
{ "memb", MFC(0x06,0x0000), BASE, ARG_NONE },
{ "imemb", MFC(0x06,0x0001), BASE, ARG_NONE },
@@ -1110,7 +1081,7 @@ int print_insn_sw_64(bfd_vma memaddr, struct disassemble_info *info)
regnames = vms_regnames;
else
regnames = osf_regnames;
- isa_mask = SW_OPCODE_NOHM;
+ isa_mask = SW_OPCODE_NOHMCODE;
switch (info->mach) {
case bfd_mach_sw_64_core3:
isa_mask |= SW_OPCODE_BASE | SW_OPCODE_CORE3;
diff --git a/gdb-xml/sw64-core.xml b/gdb-xml/sw64-core.xml
new file mode 100644
index 0000000000..24527c175b
--- /dev/null
+++ b/gdb-xml/sw64-core.xml
@@ -0,0 +1,43 @@
+<?xml version="1.0"?>
+<!-- Copyright (C) 2023 Free Software Foundation, Inc.
+
+ Copying and distribution of this file, with or without modification,
+ are permitted in any medium without royalty provided the copyright
+ notice and this notice are preserved. -->
+
+<!DOCTYPE feature SYSTEM "gdb-target.dtd">
+<feature name="org.gnu.gdb.sw_64.cpu">
+ <reg name="v0" bitsize="64" regnum="0"/>
+ <reg name="t0" bitsize="64"/>
+ <reg name="t1" bitsize="64"/>
+ <reg name="t2" bitsize="64"/>
+ <reg name="t3" bitsize="64"/>
+ <reg name="t4" bitsize="64"/>
+ <reg name="t5" bitsize="64"/>
+ <reg name="t6" bitsize="64"/>
+ <reg name="t7" bitsize="64"/>
+ <reg name="s0" bitsize="64"/>
+ <reg name="s1" bitsize="64"/>
+ <reg name="s2" bitsize="64"/>
+ <reg name="s3" bitsize="64"/>
+ <reg name="s4" bitsize="64"/>
+ <reg name="s5" bitsize="64"/>
+ <reg name="fp" bitsize="64"/>
+ <reg name="a0" bitsize="64"/>
+ <reg name="a1" bitsize="64"/>
+ <reg name="a2" bitsize="64"/>
+ <reg name="a3" bitsize="64"/>
+ <reg name="a4" bitsize="64"/>
+ <reg name="a5" bitsize="64"/>
+ <reg name="t8" bitsize="64"/>
+ <reg name="t9" bitsize="64"/>
+ <reg name="t10" bitsize="64"/>
+ <reg name="t11" bitsize="64"/>
+ <reg name="ra" bitsize="64"/>
+ <reg name="t12" bitsize="64"/>
+ <reg name="at" bitsize="64"/>
+ <reg name="gp" bitsize="64"/>
+ <reg name="sp" bitsize="64"/>
+ <reg name="zero" bitsize="64"/>
+ <reg name="pc" bitsize="64" regnum="64"/>
+</feature>
diff --git a/hw/rtc/sun4v-rtc.c b/hw/rtc/sun4v-rtc.c
index 58a0cff483..e037acd1b5 100644
--- a/hw/rtc/sun4v-rtc.c
+++ b/hw/rtc/sun4v-rtc.c
@@ -32,17 +32,10 @@ static uint64_t sun4v_rtc_read(void *opaque, hwaddr addr,
unsigned size)
{
uint64_t val = get_clock_realtime() / NANOSECONDS_PER_SECOND;
-#if defined(__sw_64__)
- if (addr & 4ULL) {
- /* accessing the high 32 bits */
- val >>= 32;
- }
-#else
if (!(addr & 4ULL)) {
/* accessing the high 32 bits */
val >>= 32;
}
-#endif
trace_sun4v_rtc_read(addr, val);
return val;
}
@@ -56,11 +49,7 @@ static void sun4v_rtc_write(void *opaque, hwaddr addr,
static const MemoryRegionOps sun4v_rtc_ops = {
.read = sun4v_rtc_read,
.write = sun4v_rtc_write,
-#if defined(__sw_64__)
- .endianness = DEVICE_LITTLE_ENDIAN,
-#else
.endianness = DEVICE_NATIVE_ENDIAN,
-#endif
};
void sun4v_rtc_init(hwaddr addr)
diff --git a/hw/sw64/Kconfig b/hw/sw64/Kconfig
index 2bf19e8234..0dc49576a5 100644
--- a/hw/sw64/Kconfig
+++ b/hw/sw64/Kconfig
@@ -7,5 +7,8 @@ config CORE3
select SUN4V_RTC
select VIRTIO_MMIO
select SERIAL
- select IDE_CMD646
select VIRTIO_VGA
+ select IDE_CMD646
+ select ISA_BUS
+ select PCKBD
+ select MSI_NONBROKEN
diff --git a/hw/sw64/core3.c b/hw/sw64/core3.c
index dbe4ed6fa1..eceeb3bec3 100644
--- a/hw/sw64/core3.c
+++ b/hw/sw64/core3.c
@@ -25,6 +25,10 @@
#include "core.h"
#include "hw/boards.h"
#include "sysemu/numa.h"
+#include "qemu/uuid.h"
+#include "qemu/bswap.h"
+
+#define VMUUID 0xFF40
static uint64_t cpu_sw64_virt_to_phys(void *opaque, uint64_t addr)
{
@@ -69,6 +73,7 @@ static const CPUArchIdList *sw64_possible_cpu_arch_ids(MachineState *ms)
ms->possible_cpus->cpus[i].vcpus_count = 1;
ms->possible_cpus->cpus[i].arch_id = i;
ms->possible_cpus->cpus[i].props.has_thread_id = true;
+ ms->possible_cpus->cpus[i].props.has_core_id = true;
ms->possible_cpus->cpus[i].props.core_id = i;
}
@@ -96,6 +101,7 @@ static void core3_init(MachineState *machine)
uint64_t kernel_entry, kernel_low, kernel_high;
BOOT_PARAMS *core3_boot_params = g_new0(BOOT_PARAMS, 1);
uint64_t param_offset;
+ QemuUUID uuid_out_put;
memset(cpus, 0, sizeof(cpus));
@@ -112,6 +118,9 @@ static void core3_init(MachineState *machine)
rom_add_blob_fixed("ram_size", (char *)&buf, 0x8, 0x2040);
+ uuid_out_put = qemu_uuid;
+ uuid_out_put = qemu_uuid_bswap(uuid_out_put);
+ pstrcpy_targphys("vm-uuid", VMUUID, 0x12, (char *)&(uuid_out_put));
param_offset = 0x90B000UL;
core3_boot_params->cmdline = param_offset | 0xfff0000000000000UL;
rom_add_blob_fixed("core3_boot_params", (core3_boot_params), 0x48, 0x90A100);
@@ -137,13 +146,24 @@ static void core3_init(MachineState *machine)
/* Start all cpus at the hmcode RESET entry point. */
for (i = 0; i < machine->smp.cpus; ++i) {
- cpus[i]->env.pc = hmcode_entry;
+ if (kvm_enabled())
+ cpus[i]->env.pc = init_pc;
+ else
+ cpus[i]->env.pc = hmcode_entry;
cpus[i]->env.hm_entry = hmcode_entry;
}
if (!kernel_filename) {
uefi_filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, "uefi-bios-sw");
- load_image_targphys(uefi_filename, 0x2f00000UL, -1);
+ if (uefi_filename == NULL) {
+ error_report("no virtual bios provided");
+ exit(1);
+ }
+ size = load_image_targphys(uefi_filename, 0x2f00000UL, -1);
+ if (size < 0) {
+ error_report("could not load virtual bios: '%s'", uefi_filename);
+ exit(1);
+ }
g_free(uefi_filename);
} else {
/* Load a kernel. */
@@ -170,6 +190,7 @@ static void core3_machine_init(MachineClass *mc)
mc->init = core3_init;
mc->block_default_type = IF_IDE;
mc->max_cpus = MAX_CPUS_CORE3;
+ mc->pci_allow_0_address = true;
mc->is_default = 0;
mc->reset = board_reset;
mc->possible_cpu_arch_ids = sw64_possible_cpu_arch_ids;
diff --git a/hw/sw64/core3_board.c b/hw/sw64/core3_board.c
index 7853e01edb..7f623cf773 100644
--- a/hw/sw64/core3_board.c
+++ b/hw/sw64/core3_board.c
@@ -16,17 +16,27 @@
#include "hw/ide/ahci.h"
#include "sysemu/numa.h"
#include "sysemu/kvm.h"
-#include "hw/rtc/sun4v-rtc.h"
+#include "sysemu/cpus.h"
#include "hw/pci/msi.h"
#include "hw/sw64/sw64_iommu.h"
+#include "hw/loader.h"
+#include "hw/nvram/fw_cfg.h"
#define TYPE_SWBOARD_PCI_HOST_BRIDGE "core_board-pcihost"
#define SWBOARD_PCI_HOST_BRIDGE(obj) \
OBJECT_CHECK(BoardState, (obj), TYPE_SWBOARD_PCI_HOST_BRIDGE)
+#define CORE3_MAX_CPUS_MASK 0x3ff
+#define CORE3_CORES_SHIFT 10
+#define CORE3_CORES_MASK 0x3ff
+#define CORE3_THREADS_SHIFT 20
+#define CORE3_THREADS_MASK 0xfff
+
#define MAX_IDE_BUS 2
#define SW_PIN_TO_IRQ 16
+#define SW_FW_CFG_P_BASE (0x804920000000ULL)
+
typedef struct SWBoard {
SW64CPU *cpu[MAX_CPUS_CORE3];
} SWBoard;
@@ -43,6 +53,16 @@ typedef struct TimerState {
int order;
} TimerState;
+static void sw_create_fw_cfg(hwaddr addr)
+{
+ MachineState *ms = MACHINE(qdev_get_machine());
+ uint16_t smp_cpus = ms->smp.cpus;
+ FWCfgState *fw_cfg;
+ fw_cfg = fw_cfg_init_mem_wide(addr + 8, addr, 8, addr + 16, &address_space_memory);
+ fw_cfg_add_i16(fw_cfg, FW_CFG_NB_CPUS, smp_cpus);
+ rom_set_fw(fw_cfg);
+}
+
#ifndef CONFIG_KVM
static void swboard_alarm_timer(void *opaque)
{
@@ -65,10 +85,13 @@ static PCIINTxRoute sw_route_intx_pin_to_irq(void *opaque, int pin)
static uint64_t convert_bit(int n)
{
- uint64_t ret = (1UL << n) - 1;
+ uint64_t ret;
if (n == 64)
ret = 0xffffffffffffffffUL;
+ else
+ ret = (1UL << n) - 1;
+
return ret;
}
@@ -76,6 +99,9 @@ static uint64_t mcu_read(void *opaque, hwaddr addr, unsigned size)
{
MachineState *ms = MACHINE(qdev_get_machine());
unsigned int smp_cpus = ms->smp.cpus;
+ unsigned int smp_threads = ms->smp.threads;
+ unsigned int smp_cores = ms->smp.cores;
+ unsigned int max_cpus = ms->smp.max_cpus;
uint64_t ret = 0;
switch (addr) {
case 0x0000:
@@ -86,6 +112,12 @@ static uint64_t mcu_read(void *opaque, hwaddr addr, unsigned size)
ret |= (1UL << i);
}
break;
+ case 0x0080:
+ /* SMP_INFO */
+ ret = (smp_threads & CORE3_THREADS_MASK) << CORE3_THREADS_SHIFT;
+ ret += (smp_cores & CORE3_CORES_MASK) << CORE3_CORES_SHIFT;
+ ret += max_cpus & CORE3_MAX_CPUS_MASK;
+ break;
/*IO_START*/
case 0x1300:
ret = 0x1;
@@ -186,7 +218,7 @@ static void intpu_write(void *opaque, hwaddr addr, uint64_t val,
val &= 0x1f;
cpu = bs->sboard.cpu[val];
cpu->env.csr[II_REQ] = 0x100000;
- cpu_interrupt(CPU(cpu),CPU_INTERRUPT_IIMAIL);
+ cpu_interrupt(CPU(cpu),CPU_INTERRUPT_II0);
break;
default:
fprintf(stderr, "Unsupported IPU addr: 0x%04lx\n", addr);
@@ -254,6 +286,33 @@ static const MemoryRegionOps msi_ops = {
},
};
+static uint64_t rtc_read(void *opaque, hwaddr addr, unsigned size)
+{
+ uint64_t val = get_clock_realtime() / NANOSECONDS_PER_SECOND;
+ return val;
+}
+
+static void rtc_write(void *opaque, hwaddr addr, uint64_t val,
+ unsigned size)
+{
+}
+
+static const MemoryRegionOps rtc_ops = {
+ .read = rtc_read,
+ .write = rtc_write,
+ .endianness = DEVICE_LITTLE_ENDIAN,
+ .valid =
+ {
+ .min_access_size = 1,
+ .max_access_size = 8,
+ },
+ .impl =
+ {
+ .min_access_size = 1,
+ .max_access_size = 8,
+ },
+};
+
static uint64_t ignore_read(void *opaque, hwaddr addr, unsigned size)
{
return 1;
@@ -392,7 +451,7 @@ void core3_board_init(SW64CPU *cpus[MAX_CPUS], MemoryRegion *ram)
MemoryRegion *mem_ep64 = g_new(MemoryRegion, 1);
MemoryRegion *conf_piu0 = g_new(MemoryRegion, 1);
MemoryRegion *io_ep = g_new(MemoryRegion, 1);
-
+ MemoryRegion *io_rtc = g_new(MemoryRegion, 1);
MachineState *ms = MACHINE(qdev_get_machine());
unsigned int smp_cpus = ms->smp.cpus;
@@ -452,6 +511,10 @@ void core3_board_init(SW64CPU *cpus[MAX_CPUS], MemoryRegion *ram)
"pci0-ep-conf-io", 4 * GB);
memory_region_add_subregion(get_system_memory(), 0x880600000000ULL,
conf_piu0);
+ memory_region_init_io(io_rtc, OBJECT(bs), &rtc_ops, b,
+ "sw64-rtc", 0x08ULL);
+ memory_region_add_subregion(get_system_memory(), 0x804910000000ULL,
+ io_rtc);
#ifdef SW64_VT_IOMMU
sw64_vt_iommu_init(b);
#endif
@@ -476,7 +539,7 @@ void core3_board_init(SW64CPU *cpus[MAX_CPUS], MemoryRegion *ram)
DEVICE_LITTLE_ENDIAN);
}
pci_create_simple(phb->bus, -1, "nec-usb-xhci");
- sun4v_rtc_init(0x804910000000ULL);
+ sw_create_fw_cfg(SW_FW_CFG_P_BASE);
}
static const TypeInfo swboard_pcihost_info = {
diff --git a/hw/sw64/sw64_iommu.c b/hw/sw64/sw64_iommu.c
index 8ded65f213..1ede2a2ce4 100644
--- a/hw/sw64/sw64_iommu.c
+++ b/hw/sw64/sw64_iommu.c
@@ -124,7 +124,7 @@ static int get_pte(dma_addr_t baseaddr, uint64_t *pte)
/* TODO: guarantee 64-bit single-copy atomicity */
ret = dma_memory_read(&address_space_memory, baseaddr,
- (uint8_t *)pte, sizeof(*pte));
+ (uint8_t *)pte, sizeof(*pte), MEMTXATTRS_UNSPECIFIED);
if (ret != MEMTX_OK)
return -EINVAL;
@@ -195,15 +195,18 @@ static void swvt_ptiotlb_inv_all(SW64IOMMUState *s)
g_hash_table_remove_all(s->ptiotlb);
}
-static void swvt_lookup_ptiotlb(SW64IOMMUState *s, uint16_t source_id,
- hwaddr addr, IOMMUTLBEntry *entry)
+static IOMMUTLBEntry *swvt_lookup_ptiotlb(SW64IOMMUState *s, uint16_t source_id,
+ hwaddr addr)
{
SW64PTIOTLBKey ptkey;
+ IOMMUTLBEntry *entry = NULL;
ptkey.source_id = source_id;
ptkey.iova = addr;
entry = g_hash_table_lookup(s->ptiotlb, &ptkey);
+
+ return entry;
}
static IOMMUTLBEntry sw64_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr,
@@ -230,7 +233,7 @@ static IOMMUTLBEntry sw64_translate_iommu(IOMMUMemoryRegion *iommu, hwaddr addr,
aligned_addr = addr & IOMMU_PAGE_MASK_8K;
- swvt_lookup_ptiotlb(s, aligned_addr, source_id, cached_entry);
+ cached_entry = swvt_lookup_ptiotlb(s, source_id, aligned_addr);
if (cached_entry)
goto out;
diff --git a/linux-headers/asm-sw64/kvm.h b/linux-headers/asm-sw64/kvm.h
index b0ce2ca346..5de7014b52 100644
--- a/linux-headers/asm-sw64/kvm.h
+++ b/linux-headers/asm-sw64/kvm.h
@@ -2,6 +2,9 @@
#define __LINUX_KVM_SW64_H
#include <linux/types.h>
+
+#define __KVM_HAVE_GUEST_DEBUG
+
/*
* for KVM_GET_REGS and KVM_SET_REGS
*/
@@ -88,6 +91,16 @@ struct vcpucb {
unsigned long exit_reason;
unsigned long ipaddr;
unsigned long vcpu_irq_vector;
+ unsigned long pri_base;
+ unsigned long stack_pc_dfault;
+ unsigned long guest_p20;
+ unsigned long guest_dfault_double;
+ unsigned long guest_irqs_pending;
+ unsigned long guest_hm_r30;
+ unsigned long migration_mark;
+ unsigned long guest_longtime;
+ unsigned long guest_longtime_offset;
+ unsigned long reserved[3];
};
/*
@@ -100,6 +113,7 @@ struct kvm_fpu {
* KVM SW_64 specific structures and definitions
*/
struct kvm_debug_exit_arch {
+ unsigned long epc;
};
/* for KVM_SET_GUEST_DEBUG */
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 2625af99dd..e274c0bd33 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1549,6 +1549,22 @@ static inline void init_thread(struct target_pt_regs *regs,
#endif /* TARGET_HPPA */
+#ifdef TARGET_SW64
+
+#define ELF_CLASS ELFCLASS64
+#define ELF_ARCH EM_SW64
+
+#define ELF_START_MMAP (0x30000000000ULL)
+
+static inline void init_thread(struct target_pt_regs *regs,
+ struct image_info *infop)
+{
+ regs->pc = infop->entry;
+ regs->usp = infop->start_stack;
+}
+
+#endif /* TARGET_SW64 */
+
#ifdef TARGET_XTENSA
#define ELF_START_MMAP 0x20000000
diff --git a/linux-user/host/sw64/host-signal.h b/linux-user/host/sw64/host-signal.h
new file mode 100644
index 0000000000..11d6e97605
--- /dev/null
+++ b/linux-user/host/sw64/host-signal.h
@@ -0,0 +1,46 @@
+/*
+ * host-signal.h: signal info dependent on the host architecture
+ *
+ * Copyright (c) 2023 wxiat
+ *
+ * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef SW64_HOST_SIGNAL_H
+#define SW64_HOST_SIGNAL_H
+
+static inline uintptr_t host_signal_pc(ucontext_t *uc)
+{
+ return uc->uc_mcontext.sc_pc;
+}
+
+static inline void host_signal_set_pc(ucontext_t *uc, uintptr_t pc)
+{
+ uc->uc_mcontext.sc_pc = pc;
+}
+
+static inline bool host_signal_write(siginfo_t *info, ucontext_t *uc)
+{
+ uint32_t *pc = (uint32_t *)host_signal_pc(uc);
+ uint32_t insn = *pc;
+
+ /* XXX: need kernel patch to get write flag faster */
+ switch (insn >> 26) {
+ case 0x0d: /* stw */
+ case 0x0e: /* stb */
+ case 0x0f: /* stq_u */
+ case 0x24: /* stf */
+ case 0x25: /* stg */
+ case 0x26: /* sts */
+ case 0x27: /* stt */
+ case 0x2c: /* stl */
+ case 0x2d: /* stq */
+ case 0x2e: /* stl_c */
+ case 0x2f: /* stq_c */
+ return true;
+ }
+ return false;
+}
+
+#endif
diff --git a/linux-user/host/sw64/hostdep.h b/linux-user/host/sw64/hostdep.h
new file mode 100755
index 0000000000..b30ac70100
--- /dev/null
+++ b/linux-user/host/sw64/hostdep.h
@@ -0,0 +1,14 @@
+/*
+ * hostdep.h : things which are dependent on the host architecture
+ *
+ * * Written by Wang Yuanheng
+ *
+ * Copyright (C) 2023 wxiat
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef SW_64_HOSTDEP_H
+#define SW_64_HOSTDEP_H
+#endif
diff --git a/linux-user/sw64/cpu_loop.c b/linux-user/sw64/cpu_loop.c
index 3f2fde0fba..389b753401 100644
--- a/linux-user/sw64/cpu_loop.c
+++ b/linux-user/sw64/cpu_loop.c
@@ -18,8 +18,11 @@
*/
#include "qemu/osdep.h"
+#include "qemu-common.h"
#include "qemu.h"
+#include "user-internals.h"
#include "cpu_loop-common.h"
+#include "signal-common.h"
void cpu_loop(CPUSW64State *env)
{
@@ -89,7 +92,7 @@ void cpu_loop(CPUSW64State *env)
}
process_pending_signals (env);
- /* Most of the traps imply a transition through HMcode, which
+ /* Most of the traps imply a transition through hmcode, which
implies an REI instruction has been executed. Which means
that RX and LOCK_ADDR should be cleared. But there are a
few exceptions for traps internal to QEMU. */
diff --git a/linux-user/sw64/meson.build b/linux-user/sw64/meson.build
new file mode 100644
index 0000000000..eda0056782
--- /dev/null
+++ b/linux-user/sw64/meson.build
@@ -0,0 +1,5 @@
+syscall_nr_generators += {
+ 'sw64': generator(sh,
+ arguments: [ meson.current_source_dir() / 'syscallhdr.sh', '@INPUT@', '@OUTPUT@', '@EXTRA_ARGS@' ],
+ output: '@BASENAME@_nr.h')
+}
diff --git a/linux-user/sw64/signal.c b/linux-user/sw64/signal.c
index 5822e808d3..572e192a95 100644
--- a/linux-user/sw64/signal.c
+++ b/linux-user/sw64/signal.c
@@ -18,6 +18,7 @@
*/
#include "qemu/osdep.h"
#include "qemu.h"
+#include "user-internals.h"
#include "signal-common.h"
#include "linux-user/trace.h"
@@ -138,8 +139,8 @@ void setup_frame(int sig, struct target_sigaction *ka,
setup_sigcontext(&frame->sc, env, frame_addr, set);
- if (ka->sa_restorer) {
- r26 = ka->sa_restorer;
+ if (ka->ka_restorer) {
+ r26 = ka->ka_restorer;
} else {
__put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
__put_user(INSN_LDI_R0 + TARGET_NR_sigreturn,
@@ -192,8 +193,8 @@ void setup_rt_frame(int sig, struct target_sigaction *ka,
__put_user(set->sig[i], &frame->uc.tuc_sigmask.sig[i]);
}
- if (ka->sa_restorer) {
- r26 = ka->sa_restorer;
+ if (ka->ka_restorer) {
+ r26 = ka->ka_restorer;
} else {
__put_user(INSN_MOV_R30_R16, &frame->retcode[0]);
__put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn,
@@ -256,11 +257,7 @@ long do_rt_sigreturn(CPUSW64State *env)
set_sigmask(&set);
restore_sigcontext(env, &frame->uc.tuc_mcontext);
- if (do_sigaltstack(frame_addr + offsetof(struct target_rt_sigframe,
- uc.tuc_stack),
- 0, env->ir[IDX_SP]) == -EFAULT) {
- goto badframe;
- }
+ target_restore_altstack(&frame->uc.tuc_stack, env);
unlock_user_struct(frame, frame_addr, 0);
return -TARGET_QEMU_ESIGRETURN;
@@ -271,3 +268,21 @@ badframe:
force_sig(TARGET_SIGSEGV);
return -TARGET_QEMU_ESIGRETURN;
}
+
+void setup_sigtramp(abi_ulong sigtramp_page)
+{
+ uint32_t *tramp = lock_user(VERIFY_WRITE, sigtramp_page, 6 * 4, 0);
+ assert(tramp != NULL);
+
+ default_sigreturn = sigtramp_page;
+ __put_user(INSN_MOV_R30_R16, &tramp[0]);
+ __put_user(INSN_LDI_R0 + TARGET_NR_sigreturn, &tramp[1]);
+ __put_user(INSN_CALLSYS, &tramp[2]);
+
+ default_rt_sigreturn = sigtramp_page + 3 * 4;
+ __put_user(INSN_MOV_R30_R16, &tramp[3]);
+ __put_user(INSN_LDI_R0 + TARGET_NR_rt_sigreturn, &tramp[4]);
+ __put_user(INSN_CALLSYS, &tramp[5]);
+
+ unlock_user(tramp, sigtramp_page, 6 * 4);
+}
diff --git a/linux-user/sw64/syscall.tbl b/linux-user/sw64/syscall.tbl
new file mode 100644
index 0000000000..d007c7bb07
--- /dev/null
+++ b/linux-user/sw64/syscall.tbl
@@ -0,0 +1,488 @@
+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+#
+# system call numbers and entry vectors for sw64
+#
+# The format is:
+# <number> <abi> <name> <entry point>
+#
+# The <abi> is always "common" for this file
+#
+0 common osf_syscall sw64_syscall_zero
+1 common exit sys_exit
+2 common fork sw64_fork
+3 common read sys_read
+4 common write sys_write
+5 common osf_old_open sys_ni_syscall
+6 common close sys_close
+7 common osf_wait4 sys_osf_wait4
+8 common osf_old_creat sys_ni_syscall
+9 common link sys_link
+10 common unlink sys_unlink
+11 common osf_execve sys_ni_syscall
+12 common chdir sys_chdir
+13 common fchdir sys_fchdir
+14 common mknod sys_mknod
+15 common chmod sys_chmod
+16 common chown sys_chown
+17 common brk sys_osf_brk
+18 common osf_getfsstat sys_ni_syscall
+19 common lseek sys_lseek
+20 common getxpid sys_getxpid
+21 common osf_mount sys_osf_mount
+22 common umount2 sys_umount
+23 common setuid sys_setuid
+24 common getxuid sys_getxuid
+25 common exec_with_loader sys_ni_syscall
+26 common ptrace sys_ptrace
+27 common osf_nrecvmsg sys_ni_syscall
+28 common osf_nsendmsg sys_ni_syscall
+29 common osf_nrecvfrom sys_ni_syscall
+30 common osf_naccept sys_ni_syscall
+31 common osf_ngetpeername sys_ni_syscall
+32 common osf_ngetsockname sys_ni_syscall
+33 common access sys_access
+34 common osf_chflags sys_ni_syscall
+35 common osf_fchflags sys_ni_syscall
+36 common sync sys_sync
+37 common kill sys_kill
+38 common osf_old_stat sys_ni_syscall
+39 common setpgid sys_setpgid
+40 common osf_old_lstat sys_ni_syscall
+41 common dup sys_dup
+42 common pipe sys_sw64_pipe
+43 common osf_set_program_attributes sys_osf_set_program_attributes
+44 common osf_profil sys_ni_syscall
+45 common open sys_open
+46 common osf_old_sigaction sys_ni_syscall
+47 common getxgid sys_getxgid
+48 common osf_sigprocmask sys_osf_sigprocmask
+49 common osf_getlogin sys_ni_syscall
+50 common osf_setlogin sys_ni_syscall
+51 common acct sys_acct
+52 common sigpending sys_sigpending
+54 common ioctl sys_ioctl
+55 common osf_reboot sys_ni_syscall
+56 common osf_revoke sys_ni_syscall
+57 common symlink sys_symlink
+58 common readlink sys_readlink
+59 common execve sys_execve
+60 common umask sys_umask
+61 common chroot sys_chroot
+62 common osf_old_fstat sys_ni_syscall
+63 common getpgrp sys_getpgrp
+64 common getpagesize sys_getpagesize
+65 common osf_mremap sys_ni_syscall
+66 common vfork sw64_vfork
+67 common stat sys_newstat
+68 common lstat sys_newlstat
+69 common osf_sbrk sys_ni_syscall
+70 common osf_sstk sys_ni_syscall
+71 common mmap sys_osf_mmap
+72 common osf_old_vadvise sys_ni_syscall
+73 common munmap sys_munmap
+74 common mprotect sys_mprotect
+75 common madvise sys_madvise
+76 common vhangup sys_vhangup
+77 common osf_kmodcall sys_ni_syscall
+78 common osf_mincore sys_ni_syscall
+79 common getgroups sys_getgroups
+80 common setgroups sys_setgroups
+81 common osf_old_getpgrp sys_ni_syscall
+82 common setpgrp sys_setpgid
+83 common osf_setitimer compat_sys_setitimer
+84 common osf_old_wait sys_ni_syscall
+85 common osf_table sys_ni_syscall
+86 common osf_getitimer compat_sys_getitimer
+87 common gethostname sys_gethostname
+88 common sethostname sys_sethostname
+89 common getdtablesize sys_getdtablesize
+90 common dup2 sys_dup2
+91 common fstat sys_newfstat
+92 common fcntl sys_fcntl
+93 common osf_select sys_osf_select
+94 common poll sys_poll
+95 common fsync sys_fsync
+96 common setpriority sys_setpriority
+97 common socket sys_socket
+98 common connect sys_connect
+99 common accept sys_accept
+100 common getpriority sys_osf_getpriority
+101 common send sys_send
+102 common recv sys_recv
+103 common sigreturn sys_sigreturn
+104 common bind sys_bind
+105 common setsockopt sys_setsockopt
+106 common listen sys_listen
+107 common osf_plock sys_ni_syscall
+108 common osf_old_sigvec sys_ni_syscall
+109 common osf_old_sigblock sys_ni_syscall
+110 common osf_old_sigsetmask sys_ni_syscall
+111 common sigsuspend sys_sigsuspend
+112 common osf_sigstack sys_osf_sigstack
+113 common recvmsg sys_recvmsg
+114 common sendmsg sys_sendmsg
+115 common osf_old_vtrace sys_ni_syscall
+116 common osf_gettimeofday sys_osf_gettimeofday
+117 common osf_getrusage sys_osf_getrusage
+118 common getsockopt sys_getsockopt
+120 common readv sys_osf_readv
+121 common writev sys_osf_writev
+122 common osf_settimeofday sys_osf_settimeofday
+123 common fchown sys_fchown
+124 common fchmod sys_fchmod
+125 common recvfrom sys_recvfrom
+126 common setreuid sys_setreuid
+127 common setregid sys_setregid
+128 common rename sys_rename
+129 common truncate sys_truncate
+130 common ftruncate sys_ftruncate
+131 common flock sys_flock
+132 common setgid sys_setgid
+133 common sendto sys_sendto
+134 common shutdown sys_shutdown
+135 common socketpair sys_socketpair
+136 common mkdir sys_mkdir
+137 common rmdir sys_rmdir
+138 common osf_utimes sys_osf_utimes
+139 common osf_old_sigreturn sys_ni_syscall
+140 common osf_adjtime sys_ni_syscall
+141 common getpeername sys_getpeername
+142 common osf_gethostid sys_ni_syscall
+143 common osf_sethostid sys_ni_syscall
+144 common getrlimit sys_getrlimit
+145 common setrlimit sys_setrlimit
+146 common osf_old_killpg sys_ni_syscall
+147 common setsid sys_setsid
+148 common quotactl sys_quotactl
+149 common osf_oldquota sys_ni_syscall
+150 common getsockname sys_getsockname
+153 common osf_pid_block sys_ni_syscall
+154 common osf_pid_unblock sys_ni_syscall
+156 common sigaction sys_osf_sigaction
+157 common osf_sigwaitprim sys_ni_syscall
+158 common osf_nfssvc sys_ni_syscall
+159 common osf_getdirentries sys_osf_getdirentries
+160 common osf_statfs sys_osf_statfs
+161 common osf_fstatfs sys_osf_fstatfs
+163 common osf_asynch_daemon sys_ni_syscall
+164 common osf_getfh sys_ni_syscall
+165 common osf_getdomainname sys_osf_getdomainname
+166 common setdomainname sys_setdomainname
+169 common osf_exportfs sys_ni_syscall
+181 common osf_alt_plock sys_ni_syscall
+184 common osf_getmnt sys_ni_syscall
+187 common osf_alt_sigpending sys_ni_syscall
+188 common osf_alt_setsid sys_ni_syscall
+199 common osf_swapon sys_swapon
+200 common msgctl sys_old_msgctl
+201 common msgget sys_msgget
+202 common msgrcv sys_msgrcv
+203 common msgsnd sys_msgsnd
+204 common semctl sys_old_semctl
+205 common semget sys_semget
+206 common semop sys_semop
+207 common osf_utsname sys_osf_utsname
+208 common lchown sys_lchown
+209 common shmat sys_shmat
+210 common shmctl sys_old_shmctl
+211 common shmdt sys_shmdt
+212 common shmget sys_shmget
+213 common osf_mvalid sys_ni_syscall
+214 common osf_getaddressconf sys_ni_syscall
+215 common osf_msleep sys_ni_syscall
+216 common osf_mwakeup sys_ni_syscall
+217 common msync sys_msync
+218 common osf_signal sys_ni_syscall
+219 common osf_utc_gettime sys_ni_syscall
+220 common osf_utc_adjtime sys_ni_syscall
+222 common osf_security sys_ni_syscall
+223 common osf_kloadcall sys_ni_syscall
+224 common osf_stat sys_osf_stat
+225 common osf_lstat sys_osf_lstat
+226 common osf_fstat sys_osf_fstat
+227 common osf_statfs64 sys_osf_statfs64
+228 common osf_fstatfs64 sys_osf_fstatfs64
+233 common getpgid sys_getpgid
+234 common getsid sys_getsid
+235 common sigaltstack sys_sigaltstack
+236 common osf_waitid sys_ni_syscall
+237 common osf_priocntlset sys_ni_syscall
+238 common osf_sigsendset sys_ni_syscall
+239 common osf_set_speculative sys_ni_syscall
+240 common osf_msfs_syscall sys_ni_syscall
+241 common osf_sysinfo sys_osf_sysinfo
+242 common osf_uadmin sys_ni_syscall
+243 common osf_fuser sys_ni_syscall
+244 common osf_proplist_syscall sys_osf_proplist_syscall
+245 common osf_ntp_adjtime sys_ni_syscall
+246 common osf_ntp_gettime sys_ni_syscall
+247 common osf_pathconf sys_ni_syscall
+248 common osf_fpathconf sys_ni_syscall
+250 common osf_uswitch sys_ni_syscall
+251 common osf_usleep_thread sys_osf_usleep_thread
+252 common osf_audcntl sys_ni_syscall
+253 common osf_audgen sys_ni_syscall
+254 common sysfs sys_sysfs
+255 common osf_subsys_info sys_ni_syscall
+256 common osf_getsysinfo sys_osf_getsysinfo
+257 common osf_setsysinfo sys_osf_setsysinfo
+258 common osf_afs_syscall sys_ni_syscall
+259 common osf_swapctl sys_ni_syscall
+260 common osf_memcntl sys_ni_syscall
+261 common osf_fdatasync sys_ni_syscall
+300 common bdflush sys_bdflush
+301 common sethae sys_sethae
+302 common mount sys_mount
+303 common old_adjtimex sys_old_adjtimex
+304 common swapoff sys_swapoff
+305 common getdents sys_getdents
+306 common create_module sys_ni_syscall
+307 common init_module sys_init_module
+308 common delete_module sys_delete_module
+309 common get_kernel_syms sys_ni_syscall
+310 common syslog sys_syslog
+311 common reboot sys_reboot
+312 common clone sw64_clone
+313 common uselib sys_uselib
+314 common mlock sys_mlock
+315 common munlock sys_munlock
+316 common mlockall sys_mlockall
+317 common munlockall sys_munlockall
+318 common sysinfo sys_sysinfo
+319 common _sysctl sys_ni_syscall
+# 320 was sys_idle
+321 common oldumount sys_oldumount
+322 common swapon sys_swapon
+323 common times sys_times
+324 common personality sys_personality
+325 common setfsuid sys_setfsuid
+326 common setfsgid sys_setfsgid
+327 common ustat sys_ustat
+328 common statfs sys_statfs
+329 common fstatfs sys_fstatfs
+330 common sched_setparam sys_sched_setparam
+331 common sched_getparam sys_sched_getparam
+332 common sched_setscheduler sys_sched_setscheduler
+333 common sched_getscheduler sys_sched_getscheduler
+334 common sched_yield sys_sched_yield
+335 common sched_get_priority_max sys_sched_get_priority_max
+336 common sched_get_priority_min sys_sched_get_priority_min
+337 common sched_rr_get_interval sys_sched_rr_get_interval
+338 common afs_syscall sys_ni_syscall
+339 common uname sys_newuname
+340 common nanosleep sys_nanosleep
+341 common mremap sys_mremap
+342 common nfsservctl sys_ni_syscall
+343 common setresuid sys_setresuid
+344 common getresuid sys_getresuid
+345 common pciconfig_read sys_pciconfig_read
+346 common pciconfig_write sys_pciconfig_write
+347 common query_module sys_ni_syscall
+348 common prctl sys_prctl
+349 common pread64 sys_pread64
+350 common pwrite64 sys_pwrite64
+351 common rt_sigreturn sys_rt_sigreturn
+352 common rt_sigaction sys_rt_sigaction
+353 common rt_sigprocmask sys_rt_sigprocmask
+354 common rt_sigpending sys_rt_sigpending
+355 common rt_sigtimedwait sys_rt_sigtimedwait
+356 common rt_sigqueueinfo sys_rt_sigqueueinfo
+357 common rt_sigsuspend sys_rt_sigsuspend
+358 common select sys_select
+359 common gettimeofday sys_gettimeofday
+360 common settimeofday sys_settimeofday
+361 common getitimer sys_getitimer
+362 common setitimer sys_setitimer
+363 common utimes sys_utimes
+364 common getrusage sys_getrusage
+365 common wait4 sys_wait4
+366 common adjtimex sys_adjtimex
+367 common getcwd sys_getcwd
+368 common capget sys_capget
+369 common capset sys_capset
+370 common sendfile sys_sendfile64
+371 common setresgid sys_setresgid
+372 common getresgid sys_getresgid
+373 common dipc sys_ni_syscall
+374 common pivot_root sys_pivot_root
+375 common mincore sys_mincore
+376 common pciconfig_iobase sys_pciconfig_iobase
+377 common getdents64 sys_getdents64
+378 common gettid sys_gettid
+379 common readahead sys_readahead
+# 380 is unused
+381 common tkill sys_tkill
+382 common setxattr sys_setxattr
+383 common lsetxattr sys_lsetxattr
+384 common fsetxattr sys_fsetxattr
+385 common getxattr sys_getxattr
+386 common lgetxattr sys_lgetxattr
+387 common fgetxattr sys_fgetxattr
+388 common listxattr sys_listxattr
+389 common llistxattr sys_llistxattr
+390 common flistxattr sys_flistxattr
+391 common removexattr sys_removexattr
+392 common lremovexattr sys_lremovexattr
+393 common fremovexattr sys_fremovexattr
+394 common futex sys_futex
+395 common sched_setaffinity sys_sched_setaffinity
+396 common sched_getaffinity sys_sched_getaffinity
+397 common tuxcall sys_ni_syscall
+398 common io_setup sys_io_setup
+399 common io_destroy sys_io_destroy
+400 common io_getevents sys_io_getevents
+401 common io_submit sys_io_submit
+402 common io_cancel sys_io_cancel
+405 common exit_group sys_exit_group
+406 common lookup_dcookie sys_lookup_dcookie
+407 common epoll_create sys_epoll_create
+408 common epoll_ctl sys_epoll_ctl
+409 common epoll_wait sys_epoll_wait
+410 common remap_file_pages sys_remap_file_pages
+411 common set_tid_address sys_set_tid_address
+412 common restart_syscall sys_restart_syscall
+413 common fadvise64 sys_fadvise64
+414 common timer_create sys_timer_create
+415 common timer_settime sys_timer_settime
+416 common timer_gettime sys_timer_gettime
+417 common timer_getoverrun sys_timer_getoverrun
+418 common timer_delete sys_timer_delete
+419 common clock_settime sys_clock_settime
+420 common clock_gettime sys_clock_gettime
+421 common clock_getres sys_clock_getres
+422 common clock_nanosleep sys_clock_nanosleep
+423 common semtimedop sys_semtimedop
+424 common tgkill sys_tgkill
+425 common stat64 sys_stat64
+426 common lstat64 sys_lstat64
+427 common fstat64 sys_fstat64
+428 common vserver sys_ni_syscall
+429 common mbind sys_ni_syscall
+430 common get_mempolicy sys_ni_syscall
+431 common set_mempolicy sys_ni_syscall
+432 common mq_open sys_mq_open
+433 common mq_unlink sys_mq_unlink
+434 common mq_timedsend sys_mq_timedsend
+435 common mq_timedreceive sys_mq_timedreceive
+436 common mq_notify sys_mq_notify
+437 common mq_getsetattr sys_mq_getsetattr
+438 common waitid sys_waitid
+439 common add_key sys_add_key
+440 common request_key sys_request_key
+441 common keyctl sys_keyctl
+442 common ioprio_set sys_ioprio_set
+443 common ioprio_get sys_ioprio_get
+444 common inotify_init sys_inotify_init
+445 common inotify_add_watch sys_inotify_add_watch
+446 common inotify_rm_watch sys_inotify_rm_watch
+447 common fdatasync sys_fdatasync
+448 common kexec_load sys_kexec_load
+449 common migrate_pages sys_migrate_pages
+450 common openat sys_openat
+451 common mkdirat sys_mkdirat
+452 common mknodat sys_mknodat
+453 common fchownat sys_fchownat
+454 common futimesat sys_futimesat
+455 common fstatat64 sys_fstatat64
+456 common unlinkat sys_unlinkat
+457 common renameat sys_renameat
+458 common linkat sys_linkat
+459 common symlinkat sys_symlinkat
+460 common readlinkat sys_readlinkat
+461 common fchmodat sys_fchmodat
+462 common faccessat sys_faccessat
+463 common pselect6 sys_pselect6
+464 common ppoll sys_ppoll
+465 common unshare sys_unshare
+466 common set_robust_list sys_set_robust_list
+467 common get_robust_list sys_get_robust_list
+468 common splice sys_splice
+469 common sync_file_range sys_sync_file_range
+470 common tee sys_tee
+471 common vmsplice sys_vmsplice
+472 common move_pages sys_move_pages
+473 common getcpu sys_getcpu
+474 common epoll_pwait sys_epoll_pwait
+475 common utimensat sys_utimensat
+476 common signalfd sys_signalfd
+477 common timerfd sys_ni_syscall
+478 common eventfd sys_eventfd
+479 common recvmmsg sys_recvmmsg
+480 common fallocate sys_fallocate
+481 common timerfd_create sys_timerfd_create
+482 common timerfd_settime sys_timerfd_settime
+483 common timerfd_gettime sys_timerfd_gettime
+484 common signalfd4 sys_signalfd4
+485 common eventfd2 sys_eventfd2
+486 common epoll_create1 sys_epoll_create1
+487 common dup3 sys_dup3
+488 common pipe2 sys_pipe2
+489 common inotify_init1 sys_inotify_init1
+490 common preadv sys_preadv
+491 common pwritev sys_pwritev
+492 common rt_tgsigqueueinfo sys_rt_tgsigqueueinfo
+493 common perf_event_open sys_perf_event_open
+494 common fanotify_init sys_fanotify_init
+495 common fanotify_mark sys_fanotify_mark
+496 common prlimit64 sys_prlimit64
+497 common name_to_handle_at sys_name_to_handle_at
+498 common open_by_handle_at sys_open_by_handle_at
+499 common clock_adjtime sys_clock_adjtime
+500 common syncfs sys_syncfs
+501 common setns sys_setns
+502 common accept4 sys_accept4
+503 common sendmmsg sys_sendmmsg
+504 common process_vm_readv sys_process_vm_readv
+505 common process_vm_writev sys_process_vm_writev
+506 common kcmp sys_kcmp
+507 common finit_module sys_finit_module
+508 common sched_setattr sys_sched_setattr
+509 common sched_getattr sys_sched_getattr
+510 common renameat2 sys_renameat2
+511 common getrandom sys_getrandom
+512 common memfd_create sys_memfd_create
+513 common execveat sys_execveat
+514 common seccomp sys_seccomp
+515 common bpf sys_bpf
+516 common userfaultfd sys_userfaultfd
+517 common membarrier sys_membarrier
+518 common mlock2 sys_mlock2
+519 common copy_file_range sys_copy_file_range
+520 common preadv2 sys_preadv2
+521 common pwritev2 sys_pwritev2
+522 common statx sys_statx
+523 common io_pgetevents sys_io_pgetevents
+524 common pkey_mprotect sys_pkey_mprotect
+525 common pkey_alloc sys_pkey_alloc
+526 common pkey_free sys_pkey_free
+527 common rseq sys_rseq
+528 common statfs64 sys_statfs64
+529 common fstatfs64 sys_fstatfs64
+530 common getegid sys_getegid
+531 common geteuid sys_geteuid
+532 common getppid sys_getppid
+# all other architectures have common numbers for new syscall, sw64
+# is the exception.
+534 common pidfd_send_signal sys_pidfd_send_signal
+535 common io_uring_setup sys_io_uring_setup
+536 common io_uring_enter sys_io_uring_enter
+537 common io_uring_register sys_io_uring_register
+538 common open_tree sys_open_tree
+539 common move_mount sys_move_mount
+540 common fsopen sys_fsopen
+541 common fsconfig sys_fsconfig
+542 common fsmount sys_fsmount
+543 common fspick sys_fspick
+544 common pidfd_open sys_pidfd_open
+# 545 reserved for clone3
+546 common close_range sys_close_range
+547 common openat2 sys_openat2
+548 common pidfd_getfd sys_pidfd_getfd
+549 common faccessat2 sys_faccessat2
+550 common process_madvise sys_process_madvise
+551 common epoll_pwait2 sys_epoll_pwait2
+552 common mount_setattr sys_mount_setattr
+# 553 reserved for quotactl_path
+554 common landlock_create_ruleset sys_landlock_create_ruleset
+555 common landlock_add_rule sys_landlock_add_rule
+556 common landlock_restrict_self sys_landlock_restrict_self
diff --git a/linux-user/sw64/syscallhdr.sh b/linux-user/sw64/syscallhdr.sh
new file mode 100644
index 0000000000..46c166d8ae
--- /dev/null
+++ b/linux-user/sw64/syscallhdr.sh
@@ -0,0 +1,32 @@
+#!/bin/sh
+# SPDX-License-Identifier: GPL-2.0
+
+in="$1"
+out="$2"
+my_abis=`echo "($3)" | tr ',' '|'`
+prefix="$4"
+offset="$5"
+
+fileguard=LINUX_USER_SW64_`basename "$out" | sed \
+ -e 'y/abcdefghijklmnopqrstuvwxyz/ABCDEFGHIJKLMNOPQRSTUVWXYZ/' \
+ -e 's/[^A-Z0-9_]/_/g' -e 's/__/_/g'`
+grep -E "^[0-9A-Fa-fXx]+[[:space:]]+${my_abis}" "$in" | sort -n | (
+ printf "#ifndef %s\n" "${fileguard}"
+ printf "#define %s\n" "${fileguard}"
+ printf "\n"
+
+ nxt=0
+ while read nr abi name entry ; do
+ if [ -z "$offset" ]; then
+ printf "#define TARGET_NR_%s%s\t%s\n" \
+ "${prefix}" "${name}" "${nr}"
+ else
+ printf "#define TARGET_NR_%s%s\t(%s + %s)\n" \
+ "${prefix}" "${name}" "${offset}" "${nr}"
+ fi
+ nxt=$((nr+1))
+ done
+
+ printf "\n"
+ printf "#endif /* %s */" "${fileguard}"
+) > "$out"
diff --git a/linux-user/sw64/target_cpu.h b/linux-user/sw64/target_cpu.h
index 1b87c8ba6d..63afa699c3 100644
--- a/linux-user/sw64/target_cpu.h
+++ b/linux-user/sw64/target_cpu.h
@@ -17,13 +17,26 @@
#ifndef SW64_TARGET_CPU_H
#define SW64_TARGET_CPU_H
-static inline void cpu_clone_regs(CPUSW64State *env, target_ulong newsp)
+static inline void cpu_clone_regs_child(CPUSW64State *env, target_ulong newsp, unsigned flags)
{
if (newsp) {
env->ir[IDX_SP] = newsp;
}
env->ir[IDX_V0] = 0;
env->ir[IDX_A3] = 0;
+ env->ir[IDX_A4] = 1; /* OSF/1 secondary return: child */
+}
+
+static inline void cpu_clone_regs_parent(CPUSW64State *env, unsigned flags)
+{
+ /*
+ * OSF/1 secondary return: parent
+ * Note that the kernel does not do this if SETTLS, because the
+ * settls argument register is still live after copy_thread.
+ */
+ if (!(flags & CLONE_SETTLS)) {
+ env->ir[IDX_A4] = 0;
+ }
}
static inline void cpu_set_tls(CPUSW64State *env, target_ulong newtls)
diff --git a/linux-user/sw64/target_errno_defs.h b/linux-user/sw64/target_errno_defs.h
new file mode 100644
index 0000000000..fd637f5bc9
--- /dev/null
+++ b/linux-user/sw64/target_errno_defs.h
@@ -0,0 +1,204 @@
+#ifndef sw64_TARGET_ERRNO_DEFS_H
+#define sw64_TARGET_ERRNO_DEFS_H
+
+#include "../generic/target_errno_defs.h"
+
+/*
+ * Generic target errno overridden with definitions taken
+ * from asm-sw64/errno.h
+ */
+#undef TARGET_EWOULDBLOCK
+#define TARGET_EWOULDBLOCK TARGET_EAGAIN
+#undef TARGET_EDEADLK
+#define TARGET_EDEADLK 11
+#undef TARGET_EAGAIN
+#define TARGET_EAGAIN 35
+#undef TARGET_EINPROGRESS
+#define TARGET_EINPROGRESS 36
+#undef TARGET_EALREADY
+#define TARGET_EALREADY 37
+#undef TARGET_ENOTSOCK
+#define TARGET_ENOTSOCK 38
+#undef TARGET_EDESTADDRREQ
+#define TARGET_EDESTADDRREQ 39
+#undef TARGET_EMSGSIZE
+#define TARGET_EMSGSIZE 40
+#undef TARGET_EPROTOTYPE
+#define TARGET_EPROTOTYPE 41
+#undef TARGET_ENOPROTOOPT
+#define TARGET_ENOPROTOOPT 42
+#undef TARGET_EPROTONOSUPPORT
+#define TARGET_EPROTONOSUPPORT 43
+#undef TARGET_ESOCKTNOSUPPORT
+#define TARGET_ESOCKTNOSUPPORT 44
+#undef TARGET_EOPNOTSUPP
+#define TARGET_EOPNOTSUPP 45
+#undef TARGET_EPFNOSUPPORT
+#define TARGET_EPFNOSUPPORT 46
+#undef TARGET_EAFNOSUPPORT
+#define TARGET_EAFNOSUPPORT 47
+#undef TARGET_EADDRINUSE
+#define TARGET_EADDRINUSE 48
+#undef TARGET_EADDRNOTAVAIL
+#define TARGET_EADDRNOTAVAIL 49
+#undef TARGET_ENETDOWN
+#define TARGET_ENETDOWN 50
+#undef TARGET_ENETUNREACH
+#define TARGET_ENETUNREACH 51
+#undef TARGET_ENETRESET
+#define TARGET_ENETRESET 52
+#undef TARGET_ECONNABORTED
+#define TARGET_ECONNABORTED 53
+#undef TARGET_ECONNRESET
+#define TARGET_ECONNRESET 54
+#undef TARGET_ENOBUFS
+#define TARGET_ENOBUFS 55
+#undef TARGET_EISCONN
+#define TARGET_EISCONN 56
+#undef TARGET_ENOTCONN
+#define TARGET_ENOTCONN 57
+#undef TARGET_ESHUTDOWN
+#define TARGET_ESHUTDOWN 58
+#undef TARGET_ETOOMANYREFS
+#define TARGET_ETOOMANYREFS 59
+#undef TARGET_ETIMEDOUT
+#define TARGET_ETIMEDOUT 60
+#undef TARGET_ECONNREFUSED
+#define TARGET_ECONNREFUSED 61
+#undef TARGET_ELOOP
+#define TARGET_ELOOP 62
+#undef TARGET_ENAMETOOLONG
+#define TARGET_ENAMETOOLONG 63
+#undef TARGET_EHOSTDOWN
+#define TARGET_EHOSTDOWN 64
+#undef TARGET_EHOSTUNREACH
+#define TARGET_EHOSTUNREACH 65
+#undef TARGET_ENOTEMPTY
+#define TARGET_ENOTEMPTY 66
+/* Unused 67 */
+#undef TARGET_EUSERS
+#define TARGET_EUSERS 68
+#undef TARGET_EDQUOT
+#define TARGET_EDQUOT 69
+#undef TARGET_ESTALE
+#define TARGET_ESTALE 70
+#undef TARGET_EREMOTE
+#define TARGET_EREMOTE 71
+/* Unused 72-76 */
+#undef TARGET_ENOLCK
+#define TARGET_ENOLCK 77
+#undef TARGET_ENOSYS
+#define TARGET_ENOSYS 78
+/* Unused 79 */
+#undef TARGET_ENOMSG
+#define TARGET_ENOMSG 80
+#undef TARGET_EIDRM
+#define TARGET_EIDRM 81
+#undef TARGET_ENOSR
+#define TARGET_ENOSR 82
+#undef TARGET_ETIME
+#define TARGET_ETIME 83
+#undef TARGET_EBADMSG
+#define TARGET_EBADMSG 84
+#undef TARGET_EPROTO
+#define TARGET_EPROTO 85
+#undef TARGET_ENODATA
+#define TARGET_ENODATA 86
+#undef TARGET_ENOSTR
+#define TARGET_ENOSTR 87
+#undef TARGET_ECHRNG
+#define TARGET_ECHRNG 88
+#undef TARGET_EL2NSYNC
+#define TARGET_EL2NSYNC 89
+#undef TARGET_EL3HLT
+#define TARGET_EL3HLT 90
+#undef TARGET_EL3RST
+#define TARGET_EL3RST 91
+#undef TARGET_ENOPKG
+#define TARGET_ENOPKG 92
+#undef TARGET_ELNRNG
+#define TARGET_ELNRNG 93
+#undef TARGET_EUNATCH
+#define TARGET_EUNATCH 94
+#undef TARGET_ENOCSI
+#define TARGET_ENOCSI 95
+#undef TARGET_EL2HLT
+#define TARGET_EL2HLT 96
+#undef TARGET_EBADE
+#define TARGET_EBADE 97
+#undef TARGET_EBADR
+#define TARGET_EBADR 98
+#undef TARGET_EXFULL
+#define TARGET_EXFULL 99
+#undef TARGET_ENOANO
+#define TARGET_ENOANO 100
+#undef TARGET_EBADRQC
+#define TARGET_EBADRQC 101
+#undef TARGET_EBADSLT
+#define TARGET_EBADSLT 102
+/* Unused 103 */
+#undef TARGET_EBFONT
+#define TARGET_EBFONT 104
+#undef TARGET_ENONET
+#define TARGET_ENONET 105
+#undef TARGET_ENOLINK
+#define TARGET_ENOLINK 106
+#undef TARGET_EADV
+#define TARGET_EADV 107
+#undef TARGET_ESRMNT
+#define TARGET_ESRMNT 108
+#undef TARGET_ECOMM
+#define TARGET_ECOMM 109
+#undef TARGET_EMULTIHOP
+#define TARGET_EMULTIHOP 110
+#undef TARGET_EDOTDOT
+#define TARGET_EDOTDOT 111
+#undef TARGET_EOVERFLOW
+#define TARGET_EOVERFLOW 112
+#undef TARGET_ENOTUNIQ
+#define TARGET_ENOTUNIQ 113
+#undef TARGET_EBADFD
+#define TARGET_EBADFD 114
+#undef TARGET_EREMCHG
+#define TARGET_EREMCHG 115
+#undef TARGET_EILSEQ
+#define TARGET_EILSEQ 116
+/* Same as default 117-121 */
+#undef TARGET_ELIBACC
+#define TARGET_ELIBACC 122
+#undef TARGET_ELIBBAD
+#define TARGET_ELIBBAD 123
+#undef TARGET_ELIBSCN
+#define TARGET_ELIBSCN 124
+#undef TARGET_ELIBMAX
+#define TARGET_ELIBMAX 125
+#undef TARGET_ELIBEXEC
+#define TARGET_ELIBEXEC 126
+#undef TARGET_ERESTART
+#define TARGET_ERESTART 127
+#undef TARGET_ESTRPIPE
+#define TARGET_ESTRPIPE 128
+#undef TARGET_ENOMEDIUM
+#define TARGET_ENOMEDIUM 129
+#undef TARGET_EMEDIUMTYPE
+#define TARGET_EMEDIUMTYPE 130
+#undef TARGET_ECANCELED
+#define TARGET_ECANCELED 131
+#undef TARGET_ENOKEY
+#define TARGET_ENOKEY 132
+#undef TARGET_EKEYEXPIRED
+#define TARGET_EKEYEXPIRED 133
+#undef TARGET_EKEYREVOKED
+#define TARGET_EKEYREVOKED 134
+#undef TARGET_EKEYREJECTED
+#define TARGET_EKEYREJECTED 135
+#undef TARGET_EOWNERDEAD
+#define TARGET_EOWNERDEAD 136
+#undef TARGET_ENOTRECOVERABLE
+#define TARGET_ENOTRECOVERABLE 137
+#undef TARGET_ERFKILL
+#define TARGET_ERFKILL 138
+#undef TARGET_EHWPOISON
+#define TARGET_EHWPOISON 139
+
+#endif
diff --git a/linux-user/sw64/target_signal.h b/linux-user/sw64/target_signal.h
index 6393a7542f..8cc1693b05 100644
--- a/linux-user/sw64/target_signal.h
+++ b/linux-user/sw64/target_signal.h
@@ -95,4 +95,6 @@ typedef struct target_sigaltstack {
#define TARGET_GEN_SUBRNG7 -25
#define TARGET_ARCH_HAS_SETUP_FRAME
+#define TARGET_ARCH_HAS_KA_RESTORER
+#define TARGET_ARCH_HAS_SIGTRAMP_PAGE 1
#endif /* SW64_TARGET_SIGNAL_H */
diff --git a/linux-user/sw64/target_syscall.h b/linux-user/sw64/target_syscall.h
index c901ae95d8..418905110c 100644
--- a/linux-user/sw64/target_syscall.h
+++ b/linux-user/sw64/target_syscall.h
@@ -23,22 +23,26 @@ struct target_pt_regs {
abi_ulong r27;
abi_ulong r28;
abi_ulong hae;
-/* JRP - These are the values provided to a0-a2 by HMcode */
+/* JRP - These are the values provided to a0-a2 by hmcode */
abi_ulong trap_a0;
abi_ulong trap_a1;
abi_ulong trap_a2;
-/* These are saved by HMcode: */
+/* These are saved by hmcode: */
abi_ulong ps;
abi_ulong pc;
abi_ulong gp;
abi_ulong r16;
abi_ulong r17;
abi_ulong r18;
+/* Those is needed by qemu to temporary store the user stack pointer */
+ abi_ulong usp;
+ abi_ulong unique;
};
-#define TARGET_MLOCKALL_MCL_CURRENT 0x2000
-#define TARGET_MLOCKALL_MCL_FUTURE 0x4000
+#define TARGET_MCL_CURRENT 0x2000
+#define TARGET_MCL_FUTURE 0x4000
+#define TARGET_MCL_ONFAULT 0x8000
#define UNAME_MACHINE "sw64"
#define UNAME_MINIMUM_RELEASE "2.6.32"
diff --git a/linux-user/sw64/termbits.h b/linux-user/sw64/termbits.h
index 37dd77120c..5c40efcb20 100644
--- a/linux-user/sw64/termbits.h
+++ b/linux-user/sw64/termbits.h
@@ -156,6 +156,7 @@ struct target_termios {
#define TARGET_FLUSHO 0x00800000
#define TARGET_PENDIN 0x20000000
#define TARGET_IEXTEN 0x00000400
+#define TARGET_EXTPROC 0x10000000
#define TARGET_FIOCLEX TARGET_IO('f', 1)
#define TARGET_FIONCLEX TARGET_IO('f', 2)
diff --git a/linux-user/syscall_defs.h b/linux-user/syscall_defs.h
index 04ca5fe7a0..a04f399278 100644
--- a/linux-user/syscall_defs.h
+++ b/linux-user/syscall_defs.h
@@ -85,7 +85,7 @@
#elif defined(TARGET_PPC) || defined(TARGET_ALPHA) || \
defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE) || \
- defined(TARGET_MIPS)
+ defined(TARGET_MIPS) || defined(TARGET_SW64)
#define TARGET_IOC_SIZEBITS 13
#define TARGET_IOC_DIRBITS 3
@@ -2270,6 +2270,50 @@ struct target_stat {
int __unused[2];
};
+#elif defined(TARGET_SW64)
+
+struct target_stat {
+ unsigned int st_dev;
+ unsigned int st_ino;
+ unsigned int st_mode;
+ unsigned int st_nlink;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned int st_rdev;
+ abi_long st_size;
+ abi_ulong target_st_atime;
+ abi_ulong target_st_mtime;
+ abi_ulong target_st_ctime;
+ unsigned int st_blksize;
+ unsigned int st_blocks;
+ unsigned int st_flags;
+ unsigned int st_gen;
+};
+
+#define TARGET_HAS_STRUCT_STAT64
+struct target_stat64 {
+ abi_ulong st_dev;
+ abi_ulong st_ino;
+ abi_ulong st_rdev;
+ abi_long st_size;
+ abi_ulong st_blocks;
+
+ unsigned int st_mode;
+ unsigned int st_uid;
+ unsigned int st_gid;
+ unsigned int st_blksize;
+ unsigned int st_nlink;
+ unsigned int __pad0;
+
+ abi_ulong target_st_atime;
+ abi_ulong target_st_atime_nsec;
+ abi_ulong target_st_mtime;
+ abi_ulong target_st_mtime_nsec;
+ abi_ulong target_st_ctime;
+ abi_ulong target_st_ctime_nsec;
+ abi_long __unused[3];
+};
+
#else
#error unsupported CPU
#endif
diff --git a/target/sw64/Makefile.objs b/target/sw64/Makefile.objs
index 1e549d141c..c702eaa26d 100644
--- a/target/sw64/Makefile.objs
+++ b/target/sw64/Makefile.objs
@@ -2,3 +2,4 @@ obj-$(CONFIG_SOFTMMU) += machine.o
obj-y += cpu.o translate.o profile.o helper.o
obj-y += int_helper.o float_helper.o simd_helper.o helper.o exception.o
obj-$(CONFIG_KVM) += kvm.o
+obj-y += gdbstub.o
diff --git a/target/sw64/cpu-param.h b/target/sw64/cpu-param.h
index 978a3cd572..464cfb3dc1 100644
--- a/target/sw64/cpu-param.h
+++ b/target/sw64/cpu-param.h
@@ -7,18 +7,12 @@
#ifndef SW64_CPU_PARAM_H
#define SW64_CPU_PARAM_H 1
-#define TARGET_LONG_BITS 64 /* if use th-1 ,TARGET_PAGE_BITS is 12 */
+#define TARGET_LONG_BITS 64
#define TARGET_PAGE_BITS 13
-#ifdef CONFIG_USER_ONLY
#define TARGET_VIRT_ADDR_SPACE_BITS 64
-#else
#define TARGET_PHYS_ADDR_SPACE_BITS 48
-#define TARGET_VIRT_ADDR_SPACE_BITS 64
-#endif
-#ifndef CONFIG_USER_ONLY
#define NB_MMU_MODES 4
-#endif
#endif
diff --git a/target/sw64/cpu.c b/target/sw64/cpu.c
index 89c21850e1..8987361346 100644
--- a/target/sw64/cpu.c
+++ b/target/sw64/cpu.c
@@ -26,7 +26,6 @@
#include "sysemu/reset.h"
#include "hw/qdev-properties.h"
-
static void sw64_cpu_set_pc(CPUState *cs, vaddr value)
{
SW64CPU *cpu = SW64_CPU(cs);
@@ -36,7 +35,6 @@ static void sw64_cpu_set_pc(CPUState *cs, vaddr value)
static void sw64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
{
-#ifndef CONFIG_KVM
SW64CPU *cpu = SW64_CPU(cs);
CPUSW64State *env = &cpu->env;
int i;
@@ -91,7 +89,6 @@ static void sw64_cpu_dump_state(CPUState *cs, FILE *f, int flags)
qemu_fprintf(f, "\n");
}
qemu_fprintf(f, "\n");
-#endif
}
#ifndef CONFIG_USER_ONLY
@@ -137,7 +134,6 @@ static void core3_init(Object *obj)
CPUSW64State *env = cs->env_ptr;
#ifdef CONFIG_USER_ONLY
env->fpcr = 0x680e800000000000;
- parallel_cpus = true;
#endif
set_feature(env, SW64_FEATURE_CORE3);
}
@@ -168,7 +164,7 @@ bool sw64_cpu_has_work(CPUState *cs)
* wake up by hard interrupt, timer, ii, mail or mchk.
*/
return cs->interrupt_request & (CPU_INTERRUPT_HARD | CPU_INTERRUPT_TIMER |
- CPU_INTERRUPT_IIMAIL | CPU_INTERRUPT_MCHK);
+ CPU_INTERRUPT_II0| CPU_INTERRUPT_MCHK);
}
static void sw64_cpu_initfn(Object *obj)
@@ -204,136 +200,6 @@ static void sw64_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr, vaddr
}
#endif
-#define a0(func) (((func & 0xFF) >> 6) & 0x1)
-#define a1(func) ((((func & 0xFF) >> 6) & 0x2) >> 1)
-
-#define t(func) ((a0(func) ^ a1(func)) & 0x1)
-#define b0(func) (t(func) | a0(func))
-#define b1(func) ((~t(func) & 1) | a1(func))
-
-#define START_SYS_CALL_ADDR(func) \
- (b1(func) << 14) | (b0(func) << 13) | ((func & 0x3F) << 7)
-
-static void sw64_cpu_do_interrupt(CPUState *cs)
-{
- int i = cs->exception_index;
-
- cs->exception_index = -1;
-#if !defined(CONFIG_USER_ONLY)
- SW64CPU *cpu = SW64_CPU(cs);
- CPUSW64State *env = &cpu->env;
- switch (i) {
- case EXCP_OPCDEC:
- cpu_abort(cs, "ILLEGAL INSN");
- break;
- case EXCP_CALL_SYS:
- i = START_SYS_CALL_ADDR(env->error_code);
- if (i <= 0x3F) {
- i += 0x4000;
- } else if (i >= 0x40 && i <= 0x7F) {
- i += 0x2000;
- } else if (i >= 0x80 && i <= 0x8F) {
- i += 0x6000;
- }
- break;
- case EXCP_ARITH:
- env->error_code = -1;
- env->csr[EXC_PC] = env->pc - 4;
- env->csr[EXC_SUM] = 1;
- i = 0xB80;
- break;
- case EXCP_UNALIGN:
- i = 0xB00;
- env->csr[EXC_PC] = env->pc - 4;
- break;
- case EXCP_CLK_INTERRUPT:
- case EXCP_DEV_INTERRUPT:
- i = 0xE80;
- break;
- case EXCP_MMFAULT:
- i = 0x980;
- env->csr[EXC_PC] = env->pc;
- break;
- case EXCP_IIMAIL:
- env->csr[EXC_PC] = env->pc;
- i = 0xE00;
- break;
- default:
- break;
- }
- env->pc = env->hm_entry + i;
- env->flags = ENV_FLAG_HM_MODE;
-#else
- switch (i) {
- case EXCP_OPCDEC:
- cpu_abort(cs, "ILLEGAL INSN");
- break;
- case EXCP_CALL_SYS:
- default:
- break;
- }
-#endif
-}
-
-#ifndef CONFIG_USER_ONLY
-static bool sw64_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
-{
- SW64CPU *cpu = SW64_CPU(cs);
- CPUSW64State *env = &cpu->env;
- int idx = -1;
- /* We never take interrupts while in Hardmode. */
- if (env->flags & ENV_FLAG_HM_MODE)
- return false;
-
- if (interrupt_request & CPU_INTERRUPT_IIMAIL) {
- idx = EXCP_IIMAIL;
- env->csr[INT_STAT] |= 1UL << 6;
- if ((env->csr[IER] & env->csr[INT_STAT]) == 0)
- return false;
- cs->interrupt_request &= ~CPU_INTERRUPT_IIMAIL;
- goto done;
- }
-
- if (interrupt_request & CPU_INTERRUPT_TIMER) {
- idx = EXCP_CLK_INTERRUPT;
- env->csr[INT_STAT] |= 1UL << 4;
- if ((env->csr[IER] & env->csr[INT_STAT]) == 0)
- return false;
- cs->interrupt_request &= ~CPU_INTERRUPT_TIMER;
- goto done;
- }
-
- if (interrupt_request & CPU_INTERRUPT_HARD) {
- idx = EXCP_DEV_INTERRUPT;
- env->csr[INT_STAT] |= 1UL << 12;
- if ((env->csr[IER] & env->csr[INT_STAT]) == 0)
- return false;
- cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
- goto done;
- }
-
- if (interrupt_request & CPU_INTERRUPT_PCIE) {
- idx = EXCP_DEV_INTERRUPT;
- env->csr[INT_STAT] |= 1UL << 1;
- env->csr[INT_PCI_INT] = 0x10;
- if ((env->csr[IER] & env->csr[INT_STAT]) == 0)
- return false;
- cs->interrupt_request &= ~CPU_INTERRUPT_PCIE;
- goto done;
- }
-
-done:
- if (idx >= 0) {
- cs->exception_index = idx;
- env->error_code = 0;
- env->csr[EXC_PC] = env->pc;
- sw64_cpu_do_interrupt(cs);
- return true;
- }
- return false;
-}
-#endif
-
static void sw64_cpu_reset(DeviceState *dev)
{
CPUState *s = CPU(dev);
@@ -370,17 +236,15 @@ static const struct SysemuCPUOps sw64_sysemu_ops = {
#include "hw/core/tcg-cpu-ops.h"
static const struct TCGCPUOps sw64_tcg_ops = {
-#ifdef CONFIG_TCG
.initialize = sw64_translate_init,
- .tlb_fill = sw64_cpu_tlb_fill,
-#endif /* CONFIG_TCG */
-#if !defined(CONFIG_USER_ONLY)
+#ifndef CONFIG_USER_ONLY
+ .tlb_fill = sw64_cpu_tlb_fill,
.do_unaligned_access = sw64_cpu_do_unaligned_access,
.cpu_exec_interrupt = sw64_cpu_exec_interrupt,
.do_transaction_failed = sw64_cpu_do_transaction_failed,
-#endif /* !CONFIG_USER_ONLY */
.do_interrupt = sw64_cpu_do_interrupt,
+#endif /* !CONFIG_USER_ONLY */
};
static void sw64_cpu_class_init(ObjectClass *oc, void *data)
@@ -389,21 +253,26 @@ static void sw64_cpu_class_init(ObjectClass *oc, void *data)
CPUClass *cc = CPU_CLASS(oc);
SW64CPUClass *scc = SW64_CPU_CLASS(oc);
- device_class_set_parent_realize(dc, sw64_cpu_realizefn,
- &scc->parent_realize);
- device_class_set_parent_reset(dc, sw64_cpu_reset, &scc->parent_reset);
- device_class_set_props(dc, sw64_cpu_properties);
+ device_class_set_parent_realize(dc, sw64_cpu_realizefn, &scc->parent_realize);
+ device_class_set_parent_reset(dc, sw64_cpu_reset, &scc->parent_reset);
+ device_class_set_props(dc, sw64_cpu_properties);
cc->class_by_name = sw64_cpu_class_by_name;
+#ifndef CONFIG_USER_ONLY
dc->vmsd = &vmstate_sw64_cpu;
+ cc->sysemu_ops = &sw64_sysemu_ops;
+#endif
cc->has_work = sw64_cpu_has_work;
cc->set_pc = sw64_cpu_set_pc;
cc->disas_set_info = sw64_cpu_disas_set_info;
cc->dump_state = sw64_cpu_dump_state;
+
+ cc->gdb_read_register = sw64_cpu_gdb_read_register;
+ cc->gdb_write_register = sw64_cpu_gdb_write_register;
+ cc->gdb_num_core_regs = 67;
+ cc->gdb_core_xml_file = "sw64-core.xml";
+
cc->tcg_ops = &sw64_tcg_ops;
-#ifndef CONFIG_USER_ONLY
- cc->sysemu_ops = &sw64_sysemu_ops;
-#endif
}
static const SW64CPUInfo sw64_cpus[] =
diff --git a/target/sw64/cpu.h b/target/sw64/cpu.h
index 5a490e2b4a..4e14891e84 100644
--- a/target/sw64/cpu.h
+++ b/target/sw64/cpu.h
@@ -60,6 +60,8 @@
#define MCU_CLOCK 25000000
+#define init_pc 0xffffffff80011100
+
typedef struct CPUSW64State CPUSW64State;
typedef CPUSW64State CPUArchState;
typedef SW64CPU ArchCPU;
@@ -136,7 +138,7 @@ struct SW64CPU {
CPUSW64State env;
uint64_t k_regs[158];
- uint64_t k_vcb[36];
+ uint64_t k_vcb[48];
QEMUTimer *alarm_timer;
target_ulong irq;
uint32_t cid;
@@ -227,6 +229,8 @@ static inline SW64CPU *sw64_env_get_cpu(CPUSW64State *env)
#define SW64_CPU_TYPE_SUFFIX "-" TYPE_SW64_CPU
#define SW64_CPU_TYPE_NAME(name) (name SW64_CPU_TYPE_SUFFIX)
int cpu_sw64_signal_handler(int host_signum, void *pinfo, void *puc);
+int sw64_cpu_gdb_read_register(CPUState *cs, uint8_t *buf, int reg);
+int sw64_cpu_gdb_write_register(CPUState *cs, uint8_t *buf, int reg);
bool sw64_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
MMUAccessType access_type, int mmu_idx,
bool probe, uintptr_t retaddr);
@@ -236,6 +240,10 @@ void sw64_stl_phys(CPUState *cs, hwaddr addr, uint64_t val);
uint64_t sw64_ldw_phys(CPUState *cs, hwaddr addr);
void sw64_stw_phys(CPUState *cs, hwaddr addr, uint64_t val);
uint64_t cpu_sw64_load_fpcr(CPUSW64State *env);
+#ifndef CONFIG_USER_ONLY
+void sw64_cpu_do_interrupt(CPUState *cs);
+bool sw64_cpu_exec_interrupt(CPUState *cpu, int int_req);
+#endif
void cpu_sw64_store_fpcr(CPUSW64State *env, uint64_t val);
void sw64_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
MMUAccessType access_type, int mmu_idx,
@@ -245,7 +253,7 @@ extern struct VMStateDescription vmstate_sw64_cpu;
/* SW64-specific interrupt pending bits */
#define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_EXT_0
-#define CPU_INTERRUPT_IIMAIL CPU_INTERRUPT_TGT_EXT_1
+#define CPU_INTERRUPT_II0 CPU_INTERRUPT_TGT_EXT_1
#define CPU_INTERRUPT_MCHK CPU_INTERRUPT_TGT_EXT_2
#define CPU_INTERRUPT_PCIE CPU_INTERRUPT_TGT_EXT_3
#define CPU_INTERRUPT_WAKEUP CPU_INTERRUPT_TGT_EXT_3
@@ -281,11 +289,14 @@ enum {
SWCSR(PTBR, 0x8),
SWCSR(PRI_BASE, 0x10),
SWCSR(TIMER_CTL, 0x2a),
+ SWCSR(TIMER_TH, 0x2b),
SWCSR(INT_STAT, 0x30),
SWCSR(INT_CLR, 0x31),
SWCSR(IER, 0x32),
SWCSR(INT_PCI_INT, 0x33),
SWCSR(DVA, 0x4e),
+ SWCSR(SOFT_CID, 0xc9),
+ SWCSR(SHTCLOCK, 0xca),
};
#include "exec/cpu-all.h"
@@ -302,7 +313,7 @@ void sw64_translate_init(void);
enum {
EXCP_NONE,
EXCP_HALT,
- EXCP_IIMAIL,
+ EXCP_II0,
EXCP_OPCDEC,
EXCP_CALL_SYS,
EXCP_ARITH,
diff --git a/target/sw64/gdbstub.c b/target/sw64/gdbstub.c
new file mode 100644
index 0000000000..da4d39d215
--- /dev/null
+++ b/target/sw64/gdbstub.c
@@ -0,0 +1,56 @@
+/*
+ * SW64 gdb server stub
+ *
+ * Copyright (c) 2023 Lu Feifei
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, see <http://www.gnu.org/licenses/>.
+ */
+#include "qemu/osdep.h"
+#include "qemu-common.h"
+#include "cpu.h"
+#include "exec/gdbstub.h"
+
+int sw64_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ SW64CPU *cpu = SW64_CPU(cs);
+ CPUSW64State *env = &cpu->env;
+
+ if (n < 31) {
+ return gdb_get_regl(mem_buf, env->ir[n]);
+ } else if (n == 31) {
+ return gdb_get_regl(mem_buf, 0);
+ } else if (n == 64) {
+ return gdb_get_regl(mem_buf, env->pc);
+ }
+ return 0;
+}
+
+int sw64_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
+{
+ SW64CPU *cpu = SW64_CPU(cs);
+ CPUSW64State *env = &cpu->env;
+
+ if (n < 31) {
+ env->ir[n] = ldtul_p(mem_buf);
+ return sizeof(target_ulong);
+ } else if (n == 31) {
+ /* discard writes to r31 */
+ return sizeof(target_ulong);
+ } else if (n == 64) {
+ env->pc = ldtul_p(mem_buf);
+ return sizeof(target_ulong);
+ }
+
+ return 0;
+}
diff --git a/target/sw64/helper.c b/target/sw64/helper.c
index 0cc0af7087..e317c08f0a 100644
--- a/target/sw64/helper.c
+++ b/target/sw64/helper.c
@@ -23,18 +23,7 @@
#include "hw/core/cpu.h"
#include "exec/memattrs.h"
-#if defined(CONFIG_USER_ONLY)
-bool sw64_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
- MMUAccessType access_type, int mmu_idx,
- bool probe, uintptr_t retaddr)
-{
- SW64CPU *cpu = SW64_CPU(cs);
-
- cs->exception_index = EXCP_MMFAULT;
- cpu->env.trap_arg0 = address;
- cpu_loop_exit_restore(cs, retaddr);
-}
-#else
+#ifndef CONFIG_USER_ONLY
static target_ulong ldq_phys_clear(CPUState *cs, target_ulong phys)
{
return ldq_phys(cs->as, phys & ~(3UL));
@@ -49,7 +38,7 @@ static int get_sw64_physical_address(CPUSW64State *env, target_ulong addr,
int prot = 0;
int ret = MM_K_ACV;
target_ulong L1pte, L2pte, L3pte, L4pte;
- target_ulong pt, index, pte_pfn_s;
+ target_ulong pt = 0, index = 0, pte_pfn_s = 0;
if (((addr >> 28) & 0xffffffff8) == 0xffffffff8) {
phys = (~(0xffffffff80000000)) & addr;
@@ -217,6 +206,124 @@ do_pgmiss:
done:
return (fail >= 0 ? -1 : phys);
}
+
+#define a0(func) (((func & 0xFF) >> 6) & 0x1)
+#define a1(func) ((((func & 0xFF) >> 6) & 0x2) >> 1)
+
+#define t(func) ((a0(func) ^ a1(func)) & 0x1)
+#define b0(func) (t(func) | a0(func))
+#define b1(func) ((~t(func) & 1) | a1(func))
+
+#define START_SYS_CALL_ADDR(func) \
+ (b1(func) << 14) | (b0(func) << 13) | ((func & 0x3F) << 7)
+
+void sw64_cpu_do_interrupt(CPUState *cs)
+{
+ int i = cs->exception_index;
+
+ cs->exception_index = -1;
+ SW64CPU *cpu = SW64_CPU(cs);
+ CPUSW64State *env = &cpu->env;
+ switch (i) {
+ case EXCP_OPCDEC:
+ cpu_abort(cs, "ILLEGAL INSN");
+ break;
+ case EXCP_CALL_SYS:
+ i = START_SYS_CALL_ADDR(env->error_code);
+ if (i <= 0x3F) {
+ i += 0x4000;
+ } else if (i >= 0x40 && i <= 0x7F) {
+ i += 0x2000;
+ } else if (i >= 0x80 && i <= 0x8F) {
+ i += 0x6000;
+ }
+ break;
+ case EXCP_ARITH:
+ env->error_code = -1;
+ env->csr[EXC_PC] = env->pc - 4;
+ env->csr[EXC_SUM] = 1;
+ i = 0xB80;
+ break;
+ case EXCP_UNALIGN:
+ i = 0xB00;
+ env->csr[EXC_PC] = env->pc - 4;
+ break;
+ case EXCP_CLK_INTERRUPT:
+ case EXCP_DEV_INTERRUPT:
+ i = 0xE80;
+ break;
+ case EXCP_MMFAULT:
+ i = 0x980;
+ env->csr[EXC_PC] = env->pc;
+ break;
+ case EXCP_II0:
+ env->csr[EXC_PC] = env->pc;
+ i = 0xE00;
+ break;
+ default:
+ break;
+ }
+ env->pc = env->hm_entry + i;
+ env->flags = ENV_FLAG_HM_MODE;
+}
+
+bool sw64_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
+{
+ SW64CPU *cpu = SW64_CPU(cs);
+ CPUSW64State *env = &cpu->env;
+ int idx = -1;
+ /* We never take interrupts while in PALmode. */
+ if (env->flags & ENV_FLAG_HM_MODE)
+ return false;
+
+ if (interrupt_request & CPU_INTERRUPT_II0) {
+ idx = EXCP_II0;
+ env->csr[INT_STAT] |= 1UL << 6;
+ if ((env->csr[IER] & env->csr[INT_STAT]) == 0)
+ return false;
+ cs->interrupt_request &= ~CPU_INTERRUPT_II0;
+ goto done;
+ }
+
+ if (interrupt_request & CPU_INTERRUPT_TIMER) {
+ idx = EXCP_CLK_INTERRUPT;
+ env->csr[INT_STAT] |= 1UL << 4;
+ if ((env->csr[IER] & env->csr[INT_STAT]) == 0)
+ return false;
+ cs->interrupt_request &= ~CPU_INTERRUPT_TIMER;
+ goto done;
+ }
+
+ if (interrupt_request & CPU_INTERRUPT_HARD) {
+ idx = EXCP_DEV_INTERRUPT;
+ env->csr[INT_STAT] |= 1UL << 12;
+ if ((env->csr[IER] & env->csr[INT_STAT]) == 0)
+ return false;
+ cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
+ goto done;
+ }
+
+ if (interrupt_request & CPU_INTERRUPT_PCIE) {
+ idx = EXCP_DEV_INTERRUPT;
+ env->csr[INT_STAT] |= 1UL << 1;
+ env->csr[INT_PCI_INT] = 0x10;
+ if ((env->csr[IER] & env->csr[INT_STAT]) == 0)
+ return false;
+ cs->interrupt_request &= ~CPU_INTERRUPT_PCIE;
+ goto done;
+ }
+
+done:
+ if (idx >= 0) {
+ cs->exception_index = idx;
+ env->error_code = 0;
+ env->csr[EXC_PC] = env->pc;
+ sw64_cpu_do_interrupt(cs);
+ return true;
+ }
+
+ return false;
+}
#endif
static void update_fpcr_status_mask(CPUSW64State* env) {
@@ -286,7 +393,9 @@ void cpu_sw64_store_fpcr(CPUSW64State* env, uint64_t val) {
uint64_t helper_read_csr(CPUSW64State *env, uint64_t index)
{
if (index == PRI_BASE)
- return 0x10000;
+ env->csr[index] = 0x10000;
+ if (index == SHTCLOCK)
+ env->csr[index] = qemu_clock_get_ns(QEMU_CLOCK_HOST) / 40;
return env->csr[index];
}
@@ -311,9 +420,12 @@ void helper_write_csr(CPUSW64State *env, uint64_t index, uint64_t va)
(index == ITB_IS) || (index == PTBR)) {
tlb_flush(cs);
}
- if (index == INT_CLR || index == INT_PCI_INT) {
+ if (index == INT_CLR) {
env->csr[INT_STAT] &= ~va;
}
+ if ((index == TIMER_CTL) && (va == 1)) {
+ timer_mod(cpu->alarm_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + env->csr[TIMER_TH]);
+ }
if (index == TIMER_CTL && env->csr[index] == 1) {
timer_mod(cpu->alarm_timer, qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + 1000000000 / 250);
diff --git a/target/sw64/kvm.c b/target/sw64/kvm.c
index fc134c83fb..c38db7cabe 100644
--- a/target/sw64/kvm.c
+++ b/target/sw64/kvm.c
@@ -25,7 +25,6 @@
#include "hw/boards.h"
#include "qemu/log.h"
-#define init_pc 0xffffffff80011000
const KVMCapabilityInfo kvm_arch_required_capabilities[] = {
KVM_CAP_LAST_INFO
};
@@ -71,6 +70,7 @@ void kvm_sw64_reset_vcpu(SW64CPU *cpu)
CPUState *cs = CPU(cpu);
struct kvm_regs *regs;
int ret;
+ struct vcpucb *vcb;
regs = (struct kvm_regs *)cpu->k_regs;
regs->pc = init_pc;
@@ -82,6 +82,9 @@ void kvm_sw64_reset_vcpu(SW64CPU *cpu)
abort();
}
+ vcb = (struct vcpucb *)cpu->k_vcb;
+ vcb->vcpu_irq_disabled = 1;
+
ret = kvm_vcpu_ioctl(cs, KVM_SW64_VCPU_INIT, NULL);
if (ret < 0) {
@@ -113,12 +116,38 @@ int kvm_arch_destroy_vcpu(CPUState *cs)
int kvm_arch_get_registers(CPUState *cs)
{
- int ret;
+ int ret, i;
SW64CPU *cpu = SW64_CPU(cs);
+ CPUSW64State *env = &cpu->env;
+
ret = kvm_vcpu_ioctl(cs, KVM_GET_REGS, &cpu->k_regs);
if (ret < 0)
return ret;
- return kvm_vcpu_ioctl(cs, KVM_SW64_GET_VCB, &cpu->k_vcb);
+
+ ret = kvm_vcpu_ioctl(cs, KVM_SW64_GET_VCB, &cpu->k_vcb);
+ if (ret < 0)
+ return ret;
+
+ for (i = 0; i < 16; i++)
+ env->ir[i] = cpu->k_regs[i];
+
+ env->ir[16] = cpu->k_regs[155];
+ env->ir[17] = cpu->k_regs[156];
+ env->ir[18] = cpu->k_regs[157];
+
+ for (i = 19; i < 29; i++)
+ env->ir[i] = cpu->k_regs[i-3];
+
+ env->ir[29] = cpu->k_regs[154];
+
+ if (cpu->k_regs[152] >> 3)
+ env->ir[30] = cpu->k_vcb[3]; /* usp */
+ else
+ env->ir[30] = cpu->k_vcb[2]; /* ksp */
+
+ env->pc = cpu->k_regs[153];
+
+ return 0;
}
int kvm_arch_put_registers(CPUState *cs, int level)
@@ -126,15 +155,88 @@ int kvm_arch_put_registers(CPUState *cs, int level)
int ret;
SW64CPU *cpu = SW64_CPU(cs);
struct vcpucb *vcb;
+
+ if (level == KVM_PUT_RUNTIME_STATE) {
+ int i;
+ CPUSW64State *env = &cpu->env;
+
+ for (i = 0; i < 16; i++)
+ cpu->k_regs[i] = env->ir[i];
+
+ for (i = 19; i < 29; i++)
+ cpu->k_regs[i-3] = env->ir[i];
+
+ cpu->k_regs[155] = env->ir[16];
+ cpu->k_regs[156] = env->ir[17];
+ cpu->k_regs[157] = env->ir[18];
+
+ cpu->k_regs[154] = env->ir[29];
+
+ if (cpu->k_regs[152] >> 3)
+ cpu->k_vcb[3] = env->ir[30]; /* usp */
+ else
+ cpu->k_vcb[2] = env->ir[30]; /* ksp */
+
+ cpu->k_regs[153] = env->pc;
+ }
+
ret = kvm_vcpu_ioctl(cs, KVM_SET_REGS, &cpu->k_regs);
if (ret < 0)
return ret;
vcb = (struct vcpucb *)cpu->k_vcb;
vcb->whami = kvm_arch_vcpu_id(cs);
fprintf(stderr,"vcpu %ld init.\n", vcb->whami);
+
+ if (level == KVM_PUT_RESET_STATE)
+ vcb->pcbb = 0;
+
return kvm_vcpu_ioctl(cs, KVM_SW64_SET_VCB, &cpu->k_vcb);
}
+static const uint32_t brk_insn = 0x00000080;
+
+int kvm_arch_insert_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
+{
+ if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 0) ||
+ cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk_insn, 4, 1)) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int kvm_arch_remove_sw_breakpoint(CPUState *cs, struct kvm_sw_breakpoint *bp)
+{
+ static uint32_t brk;
+
+ if (cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&brk, 4, 0) ||
+ brk != brk_insn ||
+ cpu_memory_rw_debug(cs, bp->pc, (uint8_t *)&bp->saved_insn, 4, 1)) {
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+int kvm_arch_insert_hw_breakpoint(target_ulong addr,
+ target_ulong len, int type)
+{
+ qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+ return -EINVAL;
+}
+
+int kvm_arch_remove_hw_breakpoint(target_ulong addr,
+ target_ulong len, int type)
+{
+ qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+ return -EINVAL;
+}
+
+void kvm_arch_remove_all_hw_breakpoints(void)
+{
+ qemu_log_mask(LOG_UNIMP, "%s: not implemented\n", __func__);
+}
+
int kvm_arch_add_msi_route_post(struct kvm_irq_routing_entry *route,
int vector, PCIDevice *dev)
{
@@ -156,10 +258,42 @@ MemTxAttrs kvm_arch_post_run(CPUState *cs, struct kvm_run *run)
return MEMTXATTRS_UNSPECIFIED;
}
+bool kvm_sw64_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit)
+{
+ SW64CPU *cpu = SW64_CPU(cs);
+ CPUSW64State *env = &cpu->env;
+
+ /* Ensure PC is synchronised */
+ kvm_cpu_synchronize_state(cs);
+
+ if (cs->singlestep_enabled) {
+ return true;
+ } else if (kvm_find_sw_breakpoint(cs, debug_exit->epc)) {
+ return true;
+ } else {
+ error_report("%s: unhandled debug exit (%"PRIx64", %"PRIx64")",
+ __func__, env->pc, debug_exit->epc);
+ }
+
+ return false;
+}
int kvm_arch_handle_exit(CPUState *cs, struct kvm_run *run)
{
- return -1;
+ int ret = 0;
+
+ switch (run->exit_reason) {
+ case KVM_EXIT_DEBUG:
+ if (kvm_sw64_handle_debug(cs, &run->debug.arch)) {
+ ret = EXCP_DEBUG;
+ } /* otherwise return to guest */
+ break;
+ default:
+ qemu_log_mask(LOG_UNIMP, "%s: un-handled exit reason %d\n",
+ __func__, run->exit_reason);
+ break;
+ }
+ return ret;
}
bool kvm_arch_stop_on_emulation_error(CPUState *cs)
@@ -213,3 +347,7 @@ bool kvm_arch_cpu_check_are_resettable(void)
{
return true;
}
+
+void kvm_arch_accel_class_init(ObjectClass *oc)
+{
+}
diff --git a/target/sw64/kvm_sw64.h b/target/sw64/kvm_sw64.h
index 5ebd4ec6fd..81dd760008 100644
--- a/target/sw64/kvm_sw64.h
+++ b/target/sw64/kvm_sw64.h
@@ -44,4 +44,13 @@ typedef struct SW64HostCPUClass {
uint32_t target;
const char *dtb_compatible;
} SW64HostCPUClass;
+
+/**
+ * kvm_sw64_handle_debug:
+ * @cs: CPUState
+ * @debug_exit: debug part of the KVM exit structure
+ *
+ * Returns: TRUE if the debug exception was handled.
+ */
+bool kvm_sw64_handle_debug(CPUState *cs, struct kvm_debug_exit_arch *debug_exit);
#endif
diff --git a/target/sw64/machine.c b/target/sw64/machine.c
index df18d3faba..93b1968ad8 100644
--- a/target/sw64/machine.c
+++ b/target/sw64/machine.c
@@ -11,7 +11,7 @@ VMStateDescription vmstate_sw64_cpu = {
.fields = (VMStateField[]) {
#ifdef CONFIG_KVM
VMSTATE_UINTTL_ARRAY(k_regs, SW64CPU, 158),
- VMSTATE_UINTTL_ARRAY(k_vcb, SW64CPU, 36),
+ VMSTATE_UINTTL_ARRAY(k_vcb, SW64CPU, 48),
#endif
VMSTATE_END_OF_LIST()
}
diff --git a/target/sw64/meson.build b/target/sw64/meson.build
index ee49e45927..332f2c2ee6 100644
--- a/target/sw64/meson.build
+++ b/target/sw64/meson.build
@@ -4,6 +4,7 @@ sw64_ss.add(files(
'exception.c',
'float_helper.c',
'helper.c',
+ 'gdbstub.c',
'int_helper.c',
'profile.c',
'simd_helper.c',
diff --git a/target/sw64/translate.c b/target/sw64/translate.c
index 37b7e89077..1e725b9294 100644
--- a/target/sw64/translate.c
+++ b/target/sw64/translate.c
@@ -2298,7 +2298,7 @@ DisasJumpType translate_one(DisasContextBase *dcbase, uint32_t insn,
/* RCID */
if (disp16 && unlikely(ra == 31)) break;
va = load_gir(ctx, ra);
- read_csr(0xc4, va);
+ read_csr(0xc9, va);
break;
case 0x0080:
/* HALT */
diff --git a/tcg/sw64/tcg-target.c.inc b/tcg/sw64/tcg-target.c.inc
index 982f159e23..da938a7382 100755
--- a/tcg/sw64/tcg-target.c.inc
+++ b/tcg/sw64/tcg-target.c.inc
@@ -10,7 +10,6 @@
the size of the operation performed. If we know the values match, it
makes things much cleaner. */
QEMU_BUILD_BUG_ON(TCG_TYPE_I32 != 0 || TCG_TYPE_I64 != 1);
-static const tcg_insn_unit *tb_ret_addr;
#ifdef CONFIG_DEBUG_TCG
static const char * const tcg_target_reg_names[TCG_TARGET_NB_REGS] = {
@@ -33,13 +32,14 @@ static const int tcg_target_reg_alloc_order[] = {
TCG_REG_X0, TCG_REG_X1, TCG_REG_X2, TCG_REG_X3, TCG_REG_X4,
TCG_REG_X5, TCG_REG_X6, TCG_REG_X7, TCG_REG_X8,
- TCG_REG_X22, TCG_REG_X23, TCG_REG_X24, /*TCG_REG_X25, TCG_REG_X26, TCG_REG_X27, */
+ TCG_REG_X22, TCG_REG_X23, /* TCG_REG_X24, TCG_REG_X25, TCG_REG_X26, TCG_REG_X27, */
/* TCG_REG_SP=TCG_REG_X15 saved for system*/
TCG_REG_X16, TCG_REG_X17, TCG_REG_X18, TCG_REG_X19, TCG_REG_X20, TCG_REG_X21, TCG_REG_X28, /* TCG_REG_X29, TCG_REG_X30, TCG_REG_X31 */
/* TCG_REG_TMP=TCG_REG_X27 reserved as temporary register */
/* TCG_REG_TMP2=TCG_REG_X25 reserved as temporary register */
+ /* TCG_REG_TMP3=TCG_REG_X24 reserved as temporary register */
/* TCG_REG_RA=TCG_REG_X26 reserved as temporary */
/* TCG_REG_GP=TCG_REG_X29 gp saved for system*/
/* TCG_REG_SP=TCG_REG_X30 sp saved for system*/
@@ -66,27 +66,103 @@ static const int tcg_target_call_oarg_regs[1] = {
#define TCG_REG_TMP TCG_REG_X27
#define TCG_REG_TMP2 TCG_REG_X25
+#define TCG_REG_TMP3 TCG_REG_X24
#define TCG_FLOAT_TMP TCG_REG_F10
#define TCG_FLOAT_TMP2 TCG_REG_F11
+#define REG0(I) (const_args[I] ? TCG_REG_ZERO : (TCGReg)args[I])
+#define tcg_out_insn_jump tcg_out_insn_ldst
+#define tcg_out_insn_bitReg tcg_out_insn_simpleReg
+#define zeroExt 0
+#define sigExt 1
+#define noPara 0//represent this parament of function isnot needed.
+
+#ifndef CONFIG_SOFTMMU
+#define USE_GUEST_BASE (guest_base != 0 || TARGET_LONG_BITS == 32)
+#define TCG_REG_GUEST_BASE TCG_REG_X14
+#endif
+
+static bool reloc_pc21(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
+{
+ const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
+ ptrdiff_t offset = target - src_rx -1;
+
+ if (offset == sextract64(offset, 0, 21)) {
+ /* read instruction, mask away previous PC_REL21 parameter contents,
+ set the proper offset, then write back the instruction. */
+ *src_rw = deposit32(*src_rw, 0, 21, offset);
+ return true;
+ }
+ return false;
+}
+
+static bool patch_reloc(tcg_insn_unit *code_ptr, int type, intptr_t value, intptr_t addend)
+{
+ tcg_debug_assert(addend == 0);
+ switch (type) {
+ case R_SW_64_BRADDR:
+ value = value;
+ return reloc_pc21(code_ptr, (const tcg_insn_unit *)value);
+ default:
+ g_assert_not_reached();
+ }
+}
+
+/*
+* contact with "tcg-target-con-str.h"
+*/
+#define TCG_CT_CONST_ZERO 0x100
+#define TCG_CT_CONST_LONG 0x200
+#define TCG_CT_CONST_MONE 0x400
+#define TCG_CT_CONST_ORRI 0x800
+#define TCG_CT_CONST_WORD 0X1000
+#define TCG_CT_CONST_U8 0x2000
+#define TCG_CT_CONST_S8 0X4000
+
#define ALL_GENERAL_REGS 0xffffffffu
+#define ALL_VECTOR_REGS 0xffffffff00000000ull
+
+#ifdef CONFIG_SOFTMMU
+#define ALL_QLDST_REGS \
+ (ALL_GENERAL_REGS & ~((1 << TCG_REG_X0) | (1 << TCG_REG_X1) | \
+ (1 << TCG_REG_X2) | (1 << TCG_REG_X3)))
+#else
#define ALL_QLDST_REGS ALL_GENERAL_REGS
-#define PUSH_SIZE ((15-9+1+1) * 8)
-#define FRAME_SIZE \
- ((PUSH_SIZE \
- + TCG_STATIC_CALL_ARGS_SIZE \
- + CPU_TEMP_BUF_NLONGS * sizeof(long) \
- + TCG_TARGET_STACK_ALIGN - 1) \
- & ~(TCG_TARGET_STACK_ALIGN - 1))
-
-/* We encode the format of the insn into the beginning of the name, so that
- we can have the preprocessor help "typecheck" the insn vs the output
- function. We don't have nice names for the formats, so we use the section
- number of the architecture reference manual in which the instruction
- group is described. */
-#define OPC_OP(x) ((x & 0x3f) << 26)
-#define OPC_FUNC(x) ((x & 0xff) << 5)
-#define OPC_FUNC_COMPLEX(x) ((x & 0xff) << 10)
+#endif
+
+/* sw test if a constant matches the constraint */
+static bool tcg_target_const_match(tcg_target_long val, TCGType type, int ct)
+{
+ if (ct & TCG_CT_CONST) {
+ return 1;
+ }
+ if (type == TCG_TYPE_I32) {
+ val = (int32_t)val;
+ }
+ if ((ct & TCG_CT_CONST_U8) && 0 <= val && val <= 255) {
+ return 1;
+ }
+ if ((ct & TCG_CT_CONST_LONG)) {
+ return 1;
+ }
+ if ((ct & TCG_CT_CONST_MONE)) {
+ return 1;
+ }
+ if ((ct & TCG_CT_CONST_ORRI)) {
+ return 1;
+ }
+ if ((ct & TCG_CT_CONST_WORD)) {
+ return 1;
+ }
+ if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
+ return 1;
+ }
+ return 0;
+}
+
+#define OPC_OP(x) (((x) & 0x3f) << 26)
+#define OPC_FUNC(x) (((x) & 0xff) << 5)
+#define OPC_FUNC_COMPLEX(x) (((x) & 0xff) << 10)
typedef enum {
OPC_NOP =0X43ff075f,
OPC_SYS_CALL =OPC_OP(0x00),
@@ -103,7 +179,7 @@ typedef enum {
OPC_VLDD =OPC_OP(0x0D),
OPC_VSTS =OPC_OP(0x0E),
OPC_VSTD =OPC_OP(0x0F),
-
+
OPC_LDBU =OPC_OP(0x20),
OPC_LDHU =OPC_OP(0x21),
OPC_LDW =OPC_OP(0x22),
@@ -120,7 +196,7 @@ typedef enum {
OPC_PRI_ST =OPC_OP(0x2D),
OPC_FSTS =OPC_OP(0x2E),
OPC_FSTD =OPC_OP(0x2F),
-
+
OPC_BEQ =OPC_OP(0x30),
OPC_BNE =OPC_OP(0x31),
OPC_BLT =OPC_OP(0x32),
@@ -129,7 +205,7 @@ typedef enum {
OPC_BGE =OPC_OP(0x35),
OPC_BLBC =OPC_OP(0x36),
OPC_BLBS =OPC_OP(0x37),
-
+
OPC_FBEQ =OPC_OP(0x38),
OPC_FBNE =OPC_OP(0x39),
OPC_FBLT =OPC_OP(0x3A),
@@ -138,7 +214,7 @@ typedef enum {
OPC_FBGE =OPC_OP(0x3D),
OPC_LDI =OPC_OP(0x3E),
OPC_LDIH =OPC_OP(0x3F),
-
+
OPC_ADDW =(OPC_OP(0x10) | OPC_FUNC(0x0)),
OPC_ADDW_I =(OPC_OP(0x12) | OPC_FUNC(0x0)),
OPC_SUBW =(OPC_OP(0x10) | OPC_FUNC(0x1)),
@@ -147,62 +223,62 @@ typedef enum {
OPC_S4ADDW_I =(OPC_OP(0x12) | OPC_FUNC(0x02)),
OPC_S4SUBW =(OPC_OP(0x10) | OPC_FUNC(0x03)),
OPC_S4SUBW_I =(OPC_OP(0x12) | OPC_FUNC(0x03)),
-
+
OPC_S8ADDW =(OPC_OP(0x10) | OPC_FUNC(0x04)),
OPC_S8ADDW_I =(OPC_OP(0x12) | OPC_FUNC(0x04)),
OPC_S8SUBW =(OPC_OP(0x10) | OPC_FUNC(0x05)),
OPC_S8SUBW_I =(OPC_OP(0x12) | OPC_FUNC(0x05)),
-
+
OPC_ADDL =(OPC_OP(0x10) | OPC_FUNC(0x8)),
OPC_ADDL_I =(OPC_OP(0x12) | OPC_FUNC(0x8)),
OPC_SUBL =(OPC_OP(0x10) | OPC_FUNC(0x9)),
OPC_SUBL_I =(OPC_OP(0x12) | OPC_FUNC(0x9)),
-
+
OPC_S4ADDL =(OPC_OP(0x10) | OPC_FUNC(0xA)),
OPC_S4ADDL_I =(OPC_OP(0x12) | OPC_FUNC(0xA)),
OPC_S4SUBL =(OPC_OP(0x10) | OPC_FUNC(0xB)),
OPC_S4SUBL_I =(OPC_OP(0x12) | OPC_FUNC(0xB)),
-
+
OPC_S8ADDL =(OPC_OP(0x10) | OPC_FUNC(0xC)),
OPC_S8ADDL_I =(OPC_OP(0x12) | OPC_FUNC(0xC)),
OPC_S8SUBL =(OPC_OP(0x10) | OPC_FUNC(0xD)),
OPC_S8SUBL_I =(OPC_OP(0x12) | OPC_FUNC(0xD)),
-
+
OPC_MULW =(OPC_OP(0x10) | OPC_FUNC(0x10)),
OPC_MULW_I =(OPC_OP(0x12) | OPC_FUNC(0x10)),
OPC_MULL =(OPC_OP(0x10) | OPC_FUNC(0x18)),
OPC_MULL_I =(OPC_OP(0x12) | OPC_FUNC(0x18)),
-
+
OPC_UMULH =(OPC_OP(0x10) | OPC_FUNC(0x19)),
OPC_UMULH_I =(OPC_OP(0x12) | OPC_FUNC(0x19)),
-
+
OPC_CTPOP =(OPC_OP(0x10) | OPC_FUNC(0x58)),
OPC_CTLZ =(OPC_OP(0x10) | OPC_FUNC(0x59)),
OPC_CTTZ =(OPC_OP(0x10) | OPC_FUNC(0x5A)),
-
+
OPC_ZAP =(OPC_OP(0x10) | OPC_FUNC(0x68)),
OPC_ZAP_I =(OPC_OP(0x12) | OPC_FUNC(0x68)),
OPC_ZAPNOT =(OPC_OP(0x10) | OPC_FUNC(0x69)),
OPC_ZAPNOT_I =(OPC_OP(0x12) | OPC_FUNC(0x69)),
-
+
OPC_SEXTB =(OPC_OP(0x10) | OPC_FUNC(0x6A)),
OPC_SEXTB_I =(OPC_OP(0x12) | OPC_FUNC(0x6A)),
OPC_SEXTH =(OPC_OP(0x10) | OPC_FUNC(0x6B)),
OPC_SEXTH_I =(OPC_OP(0x12) | OPC_FUNC(0x6B)),
-
+
OPC_CMPEQ =(OPC_OP(0x10) | OPC_FUNC(0x28)),
OPC_CMPEQ_I =(OPC_OP(0x12) | OPC_FUNC(0x28)),
-
+
OPC_CMPLT =(OPC_OP(0x10) | OPC_FUNC(0x29)),
OPC_CMPLT_I =(OPC_OP(0x12) | OPC_FUNC(0x29)),
OPC_CMPLE =(OPC_OP(0x10) | OPC_FUNC(0x2A)),
OPC_CMPLE_I =(OPC_OP(0x12) | OPC_FUNC(0x2A)),
-
+
OPC_CMPULT =(OPC_OP(0x10) | OPC_FUNC(0x2B)),
OPC_CMPULT_I =(OPC_OP(0x12) | OPC_FUNC(0x2B)),
OPC_CMPULE =(OPC_OP(0x10) | OPC_FUNC(0x2C)),
OPC_CMPULE_I =(OPC_OP(0x12) | OPC_FUNC(0x2C)),
-
+
OPC_AND =(OPC_OP(0x10) | OPC_FUNC(0x38)),
OPC_BIC =(OPC_OP(0x10) | OPC_FUNC(0x39)),
OPC_BIS =(OPC_OP(0x10) | OPC_FUNC(0x3A)),
@@ -216,14 +292,14 @@ typedef enum {
OPC_ORNOT_I =(OPC_OP(0x12) | OPC_FUNC(0x3B)),
OPC_XOR_I =(OPC_OP(0x12) | OPC_FUNC(0x3C)),
OPC_EQV_I =(OPC_OP(0x12) | OPC_FUNC(0x3D)),
-
+
OPC_SLL =(OPC_OP(0x10) | OPC_FUNC(0x48)),
OPC_SRL =(OPC_OP(0x10) | OPC_FUNC(0x49)),
OPC_SRA =(OPC_OP(0x10) | OPC_FUNC(0x4A)),
OPC_SLL_I =(OPC_OP(0x12) | OPC_FUNC(0x48)),
OPC_SRL_I =(OPC_OP(0x12) | OPC_FUNC(0x49)),
OPC_SRA_I =(OPC_OP(0x12) | OPC_FUNC(0x4A)),
-
+
OPC_SELEQ =(OPC_OP(0x11) | OPC_FUNC_COMPLEX(0x00)),
OPC_SELGE =(OPC_OP(0x11) | OPC_FUNC_COMPLEX(0x01)),
OPC_SELGT =(OPC_OP(0x11) | OPC_FUNC_COMPLEX(0x02)),
@@ -240,7 +316,7 @@ typedef enum {
OPC_SELNE_I =(OPC_OP(0x13) | OPC_FUNC_COMPLEX(0x05)),
OPC_SELLBC_I =(OPC_OP(0x13) | OPC_FUNC_COMPLEX(0x06)),
OPC_SELLBS_I =(OPC_OP(0x13) | OPC_FUNC_COMPLEX(0x07)),
-
+
OPC_INS0B =(OPC_OP(0x10) | OPC_FUNC(0x40)),
OPC_INS1B =(OPC_OP(0x10) | OPC_FUNC(0x41)),
OPC_INS2B =(OPC_OP(0x10) | OPC_FUNC(0x42)),
@@ -258,39 +334,39 @@ typedef enum {
OPC_INS6B_I =(OPC_OP(0x12) | OPC_FUNC(0x46)),
OPC_INS7B_I =(OPC_OP(0x12) | OPC_FUNC(0x47)),
- OPC_EXT0B =(OPC_OP(0x10) | OPC_FUNC(0x50)),
- OPC_EXT1B =(OPC_OP(0x10) | OPC_FUNC(0x51)),
- OPC_EXT2B =(OPC_OP(0x10) | OPC_FUNC(0x52)),
- OPC_EXT3B =(OPC_OP(0x10) | OPC_FUNC(0x53)),
- OPC_EXT4B =(OPC_OP(0x10) | OPC_FUNC(0x54)),
- OPC_EXT5B =(OPC_OP(0x10) | OPC_FUNC(0x55)),
- OPC_EXT6B =(OPC_OP(0x10) | OPC_FUNC(0x56)),
- OPC_EXT7B =(OPC_OP(0x10) | OPC_FUNC(0x57)),
- OPC_EXT0B_I =(OPC_OP(0x12) | OPC_FUNC(0x50)),
- OPC_EXT1B_I =(OPC_OP(0x12) | OPC_FUNC(0x51)),
- OPC_EXT2B_I =(OPC_OP(0x12) | OPC_FUNC(0x52)),
- OPC_EXT3B_I =(OPC_OP(0x12) | OPC_FUNC(0x53)),
- OPC_EXT4B_I =(OPC_OP(0x12) | OPC_FUNC(0x54)),
- OPC_EXT5B_I =(OPC_OP(0x12) | OPC_FUNC(0x55)),
- OPC_EXT6B_I =(OPC_OP(0x12) | OPC_FUNC(0x56)),
- OPC_EXT7B_I =(OPC_OP(0x12) | OPC_FUNC(0x57)),
+ OPC_EXTLB =(OPC_OP(0x10) | OPC_FUNC(0x50)),
+ OPC_EXTLH =(OPC_OP(0x10) | OPC_FUNC(0x51)),
+ OPC_EXTLW =(OPC_OP(0x10) | OPC_FUNC(0x52)),
+ OPC_EXTLL =(OPC_OP(0x10) | OPC_FUNC(0x53)),
+ OPC_EXTHB =(OPC_OP(0x10) | OPC_FUNC(0x54)),
+ OPC_EXTHH =(OPC_OP(0x10) | OPC_FUNC(0x55)),
+ OPC_EXTHW =(OPC_OP(0x10) | OPC_FUNC(0x56)),
+ OPC_EXTHL =(OPC_OP(0x10) | OPC_FUNC(0x57)),
+ OPC_EXTLB_I =(OPC_OP(0x12) | OPC_FUNC(0x50)),
+ OPC_EXTLH_I =(OPC_OP(0x12) | OPC_FUNC(0x51)),
+ OPC_EXTLW_I =(OPC_OP(0x12) | OPC_FUNC(0x52)),
+ OPC_EXTLL_I =(OPC_OP(0x12) | OPC_FUNC(0x53)),
+ OPC_EXTHB_I =(OPC_OP(0x12) | OPC_FUNC(0x54)),
+ OPC_EXTHH_I =(OPC_OP(0x12) | OPC_FUNC(0x55)),
+ OPC_EXTHW_I =(OPC_OP(0x12) | OPC_FUNC(0x56)),
+ OPC_EXTHL_I =(OPC_OP(0x12) | OPC_FUNC(0x57)),
- OPC_MASK0B =(OPC_OP(0x10) | OPC_FUNC(0x60)),
- OPC_MASK1B =(OPC_OP(0x10) | OPC_FUNC(0x61)),
- OPC_MASK2B =(OPC_OP(0x10) | OPC_FUNC(0x62)),
- OPC_MASK3B =(OPC_OP(0x10) | OPC_FUNC(0x63)),
- OPC_MASK4B =(OPC_OP(0x10) | OPC_FUNC(0x64)),
- OPC_MASK5B =(OPC_OP(0x10) | OPC_FUNC(0x65)),
- OPC_MASK6B =(OPC_OP(0x10) | OPC_FUNC(0x66)),
- OPC_MASK7B =(OPC_OP(0x10) | OPC_FUNC(0x67)),
- OPC_MASK0B_I =(OPC_OP(0x12) | OPC_FUNC(0x60)),
- OPC_MASK1B_I =(OPC_OP(0x12) | OPC_FUNC(0x61)),
- OPC_MASK2B_I =(OPC_OP(0x12) | OPC_FUNC(0x62)),
- OPC_MASK3B_I =(OPC_OP(0x12) | OPC_FUNC(0x63)),
- OPC_MASK4B_I =(OPC_OP(0x12) | OPC_FUNC(0x64)),
- OPC_MASK5B_I =(OPC_OP(0x12) | OPC_FUNC(0x65)),
- OPC_MASK6B_I =(OPC_OP(0x12) | OPC_FUNC(0x66)),
- OPC_MASK7B_I =(OPC_OP(0x12) | OPC_FUNC(0x67)),
+ OPC_MASKLB =(OPC_OP(0x10) | OPC_FUNC(0x60)),
+ OPC_MASKLH =(OPC_OP(0x10) | OPC_FUNC(0x61)),
+ OPC_MASKLW =(OPC_OP(0x10) | OPC_FUNC(0x62)),
+ OPC_MASKLL =(OPC_OP(0x10) | OPC_FUNC(0x63)),
+ OPC_MASKHB =(OPC_OP(0x10) | OPC_FUNC(0x64)),
+ OPC_MASKHH =(OPC_OP(0x10) | OPC_FUNC(0x65)),
+ OPC_MASKHW =(OPC_OP(0x10) | OPC_FUNC(0x66)),
+ OPC_MASKHL =(OPC_OP(0x10) | OPC_FUNC(0x67)),
+ OPC_MASKLB_I =(OPC_OP(0x12) | OPC_FUNC(0x60)),
+ OPC_MASKLH_I =(OPC_OP(0x12) | OPC_FUNC(0x61)),
+ OPC_MASKLW_I =(OPC_OP(0x12) | OPC_FUNC(0x62)),
+ OPC_MASKLL_I =(OPC_OP(0x12) | OPC_FUNC(0x63)),
+ OPC_MASKHB_I =(OPC_OP(0x12) | OPC_FUNC(0x64)),
+ OPC_MASKHH_I =(OPC_OP(0x12) | OPC_FUNC(0x65)),
+ OPC_MASKHW_I =(OPC_OP(0x12) | OPC_FUNC(0x66)),
+ OPC_MASKHL_I =(OPC_OP(0x12) | OPC_FUNC(0x67)),
OPC_CNPGEB =(OPC_OP(0x10) | OPC_FUNC(0x6C)),
OPC_CNPGEB_I =(OPC_OP(0x12) | OPC_FUNC(0x6C)),
@@ -337,168 +413,162 @@ typedef enum {
OPC_FSQRTD = (OPC_OP(0x18) | OPC_FUNC(0x09)),
}SW_64Insn;
-static void tcg_out_insn_br(TCGContext *s, SW_64Insn insn, TCGReg rd, intptr_t imm64);
-static void tcg_out_insn_ldst(TCGContext *s, SW_64Insn insn, TCGReg rd, TCGReg rn, intptr_t imm16);
-static void tcg_out_insn_simpleReg(TCGContext *s, SW_64Insn insn, TCGReg rd, TCGReg rn, TCGReg rm);
-static void tcg_out_insn_simple(TCGContext *s, SW_64Insn insn_Imm, SW_64Insn insn_Reg, TCGReg rd, TCGReg rn, intptr_t imm64);
-static void tcg_out_insn_simpleImm(TCGContext *s, SW_64Insn insn_Imm, TCGReg rd, TCGReg rn, intptr_t imm64);
-static void tcg_out_insn_bitImm(TCGContext *s, SW_64Insn insn_Imm, TCGReg rd, TCGReg rn, unsigned long imm64);
-static void tcg_out_insn_bit(TCGContext *s, SW_64Insn insn_Imm, SW_64Insn insn_Reg, TCGReg rd, TCGReg rn, unsigned long imm64);
-static void tcg_out_insn_complexReg(TCGContext *s, SW_64Insn insn, TCGReg cond, TCGReg rd, TCGReg rn, TCGReg rm);
-static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,TCGReg a1,TCGReg a2, bool const_b, TCGReg v1, TCGReg v2);
-static bool reloc_pc21(tcg_insn_unit *src_rw, const tcg_insn_unit *target);
-static inline uint32_t tcg_in32(TCGContext *s);
-static void tcg_out_movr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn);
-static void tcg_out_ldst(TCGContext *s, SW_64Insn insn, TCGReg rd, TCGReg rn, intptr_t offset, bool sign);
-static void tcg_out_cond_cmp(TCGContext *s, TCGCond cond, TCGReg ret, TCGArg a, TCGArg b, bool const_b);
-static void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd, TCGReg rn, int64_t aimm);
-static inline void tcg_out_extr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm, unsigned int m);
-static inline void tcg_out_rotl_Reg(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm);
-static inline void tcg_out_rotr_Reg(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm);
-static inline void tcg_out_rotl_Imm(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int m);
-static inline void tcg_out_rotr_Imm(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int m);
-static void tcg_out_cltz(TCGContext *s, SW_64Insn opc_clz, TCGType ext, TCGReg rd, TCGReg rn, TCGArg b, bool const_b);
-static inline void tcg_out_bswap16u(TCGContext *s, TCGReg rd, TCGReg rn);
-static inline void tcg_out_bswap16s(TCGContext *s, TCGReg rd, TCGReg rn);
-static inline void tcg_out_bswap32u(TCGContext *s, TCGReg rd, TCGReg rn);
-static inline void tcg_out_bswap32s(TCGContext *s, TCGReg rd, TCGReg rn);
-static inline void tcg_out_bswap64(TCGContext *s, TCGReg rd, TCGReg rn);
-static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, MemOpIdx oi);
-static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, MemOpIdx oi, TCGType ext);
-static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret, TCGReg arg1, TCGReg arg2);
-static void tcg_out_extract(TCGContext *s, TCGReg rd, TCGReg rn, int pos, int len);
-static void tcg_out_dep(TCGContext *s, TCGReg rd, TCGReg rn, int pos, int len);
-static void tcg_out_mulsh64(TCGContext *s, TCGReg rd, TCGReg rn, TCGReg rm);
-
-#define tcg_out_insn_jump tcg_out_insn_ldst
-#define tcg_out_insn_bitReg tcg_out_insn_simpleReg
+static inline uint32_t tcg_in32(TCGContext *s)
+{
+ uint32_t v = *(uint32_t *)s->code_ptr;
+ return v;
+}
-static void tcg_target_init(TCGContext *s)
+/*
+ * SW instruction format of br(alias jump)
+ * insn = opcode[31,26]:Rd[25,21]:disp[20,0],
+ */
+static void tcg_out_insn_br(TCGContext *s, SW_64Insn insn, TCGReg rd, intptr_t imm64)
{
- tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffffu;
- tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffffu;
- tcg_target_available_regs[TCG_TYPE_V64] = 0xffffffff00000000ull;
- tcg_target_available_regs[TCG_TYPE_V128] = 0xffffffff00000000ull;
- tcg_target_call_clobber_regs = -1ull;
-
- //sw_64 callee saved x9-x15
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X9);
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X10);
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X11);
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X12);
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X13);
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X14);
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X15);
-
- //sw_64 callee saved f2~f9
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F2);
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F3);
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F4);
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F5);
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F6);
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F7);
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F8);
- tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F9);
+ tcg_debug_assert(imm64 <= 0xfffff && imm64 >= -0x100000);
+ tcg_out32(s, insn | (rd & 0x1f) << 21 | (imm64 & 0x1fffff));
+}
- s->reserved_regs = 0;
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP);
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP); //TCG_REG_X27
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2); //TCG_REG_X25
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA); //TCG_REG_X26
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_X29); /*sw_64 platform register */
- tcg_regset_set_reg(s->reserved_regs, TCG_FLOAT_TMP); /*sw_64 platform register */
- tcg_regset_set_reg(s->reserved_regs, TCG_FLOAT_TMP2); /*sw_64 platform register */
+/*
+ * SW instruction format of (load and store)
+ * insn = opcode[31,26]:rd[25,21]:rn[20,16]:disp[15,0]
+ */
+static void tcg_out_insn_ldst(TCGContext *s, SW_64Insn insn, TCGReg rd, TCGReg rn, intptr_t imm16)
+{
+ tcg_debug_assert(imm16 <= 0x7fff && imm16 >= -0x8000);
+ tcg_out32(s, insn | (rd & 0x1f) << 21 | (rn & 0x1f) << 16 | (imm16 & 0xffff));
}
+/*
+ * SW instruction format of simple operator for Register
+ * insn = opcode[31,26]:rn(ra)[25,21]:rn(rb)[20,16]:Zeors[15,13]:function[12,5]:rd(rc)[4,0]
+ */
+static void tcg_out_insn_simpleReg(TCGContext *s, SW_64Insn insn,TCGReg rd, TCGReg rn, TCGReg rm)
+{
+ tcg_out32(s, insn | (rn & 0x1f) << 21 | (rm & 0x1f) << 16 | (rd & 0x1f));
+}
-#ifndef CONFIG_SOFTMMU
- #define USE_GUEST_BASE guest_base != 0
- #define TCG_REG_GUEST_BASE TCG_REG_X14
-#endif
+/*
+ * SW instruction format of simple operator for imm
+ * insn = opcode[31,26]:rn(ra)[25,21]:disp[20,13]:function[12,5]:rd(rc)[4,0]
+ */
+static void tcg_out_simple(TCGContext *s, SW_64Insn insn_Imm, SW_64Insn insn_Reg, TCGReg rd, TCGReg rn, intptr_t imm64)
+{
+ if (imm64 <= 0x7f && imm64 >= -0x80) {
+ tcg_out32(s, insn_Imm | (rn & 0x1f) << 21 | (imm64 & 0xff) << 13 | (rd & 0x1f));
+ } else {
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP3, imm64);
+ tcg_out_insn_simpleReg(s, insn_Reg, rd, rn, TCG_REG_TMP3);
+ }
+}
+static void tcg_out_insn_simpleImm(TCGContext *s, SW_64Insn insn_Imm, TCGReg rd, TCGReg rn, unsigned long imm64)
+{
+ tcg_debug_assert(imm64 <= 255);
+ tcg_out32(s, insn_Imm | (rn & 0x1f) << 21 | (imm64 & 0xff) << 13 | (rd & 0x1f));
+}
-#define zeroExt 0
-#define sigExt 1
+/*
+ * sw bit operation: and bis etc
+ */
+static void tcg_out_bit(TCGContext *s, SW_64Insn insn_Imm, SW_64Insn insn_Reg, TCGReg rd, TCGReg rn, unsigned long imm64)
+{
+ if (imm64 <= 255) {
+ tcg_out32(s, insn_Imm | (rn & 0x1f) << 21 | (imm64 & 0xff) << 13 | (rd & 0x1f));
+ } else {
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, imm64);
+ tcg_out_insn_bitReg(s, insn_Reg, rd, rn, TCG_REG_TMP);
+ }
+}
+/*
+ * SW instruction format of complex operator
+ * insn = opcode[31,26]:rd[25,21]:rn[20,16],function[15,10]:rm[9,5]:rx[4,0]
+ */
+static void tcg_out_insn_complexReg(TCGContext *s, SW_64Insn insn, TCGReg cond, TCGReg rd, TCGReg rn, TCGReg rm)
+{
+ tcg_out32(s, insn | (cond & 0x1f) << 21 | (rn & 0x1f) << 16 | (rm & 0x1f) << 5 | (rd & 0x1f));
+}
-static void tcg_target_qemu_prologue(TCGContext *s)
+static void tcg_out_insn_complexImm(TCGContext *s, SW_64Insn insn, TCGReg cond, TCGReg rd, intptr_t imm8, TCGReg rm)
{
- TCGReg r;
- int ofs;
-
- /* allocate space for all saved registers */
- /* subl $sp,PUSH_SIZE,$sp */
- tcg_out_insn_simple(s, OPC_SUBL_I, OPC_SUBL, TCG_REG_SP, TCG_REG_SP, PUSH_SIZE);
-
- /* Push (FP, LR) */
- /* stl $fp,0($sp) */
- tcg_out_insn_ldst(s, OPC_STL, TCG_REG_FP, TCG_REG_SP, 0);
- /* stl $26,8($sp) */
- tcg_out_insn_ldst(s, OPC_STL, TCG_REG_RA, TCG_REG_SP, 8);
+ tcg_out32(s, insn | (cond & 0x1f) << 21 | (imm8 & 0xff) << 13 | (rm & 0x1f) << 5 | (rd & 0x1f));
+}
+static void tcg_out_movr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn)
+{
+ if (ext == TCG_TYPE_I64) {
+ tcg_out_insn_simpleReg(s, OPC_BIS, rd, rn, TCG_REG_ZERO);
+ } else {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rn, 0xf);
+ }
+}
- /* Set up frame pointer for canonical unwinding. */
- /* TCG_REG_FP=TCG_REG_SP */
- tcg_out_movr(s, TCG_TYPE_I64, TCG_REG_FP, TCG_REG_SP);
+static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, tcg_target_long orig)
+{
+ tcg_target_long l0=0, l1=0, l2=0, l3=0, extra=0;
+ tcg_target_long val = orig;
+ TCGReg rs = TCG_REG_ZERO;
- /* Store callee-preserved regs x9..x14. */
- for (r = TCG_REG_X9; r <= TCG_REG_X14; r += 1){
- ofs = (r - TCG_REG_X9 + 2) * 8;
- tcg_out_insn_ldst(s, OPC_STL, r, TCG_REG_SP, ofs);
+ if (TCG_TARGET_REG_BITS == 64 && type == TCG_TYPE_I32) {
+ val = (int32_t)val;//val64bit
}
- /* Make stack space for TCG locals. */
- /* subl $sp,FRAME_SIZE-PUSH_SIZE,$sp */
- tcg_out_insn_simple(s, OPC_SUBL_I, OPC_SUBL, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE - PUSH_SIZE);
+ if (orig == (int16_t)orig) {
+ tcg_out_insn_ldst(s, OPC_LDI, rd, TCG_REG_ZERO, (int16_t)orig);
+ return;
+ }
- /* Inform TCG about how to find TCG locals with register, offset, size. */
- tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE,
- CPU_TEMP_BUF_NLONGS * sizeof(long));
+ if (orig == (uint8_t)orig) {
+ tcg_out_insn_simpleImm(s, OPC_BIS_I, rd, TCG_REG_ZERO, (uint8_t)orig);
+ return;
+ }
-#if !defined(CONFIG_SOFTMMU)
- if (USE_GUEST_BASE) {
- tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, guest_base);
- tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE);
+ if (type == TCG_TYPE_I32) {
+ val = (int32_t)val;
}
-#endif
-
- /* TCG_AREG0=tcg_target_call_iarg_regs[0], on sw, we mov $16 to $9 */
- tcg_out_mov(s, TCG_TYPE_I64, TCG_AREG0, tcg_target_call_iarg_regs[0]);
- tcg_out_insn_jump(s, OPC_JMP, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], 0);
- /*
- * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
- * and fall through to the rest of the epilogue.
- */
- tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, 0);
+ l0 = (int16_t)val;
+ val = (val - l0) >> 16;
+ l1 = (int16_t)val;
- /* TB epilogue */
- tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
+ if (orig >> 31 == -1 || orig >> 31 == 0) {
+ if (l1 < 0 && orig >= 0) {
+ extra = 0x4000;
+ l1 = (int16_t)(val - 0x4000);
+ }
+ } else {
+ val = (val - l1) >> 16;
+ l2 = (int16_t)val;
+ val = (val - l2) >> 16;
+ l3 = (int16_t)val;
- /* Remove TCG locals stack space. */
- /* addl $sp,FRAME_SIZE-PUSH_SIZE,$sp */
- tcg_out_insn_simple(s, OPC_ADDL_I, OPC_ADDL, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE - PUSH_SIZE);
+ if (l3) {
+ tcg_out_insn_ldst(s, OPC_LDIH, rd, rs, l3);
+ rs = rd;
+ }
+ if (l2) {
+ tcg_out_insn_ldst(s, OPC_LDI, rd, rs, l2);
+ rs = rd;
+ }
+ if (l3 || l2)
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, rd, rd, 32);
+ }
- /* Restore registers x9..x14. */
- for (r = TCG_REG_X9; r <= TCG_REG_X14; r += 1) {
- int ofs = (r - TCG_REG_X9 + 2) * 8;
- tcg_out_insn_ldst(s, OPC_LDL, r, TCG_REG_SP, ofs);
+ if (l1) {
+ tcg_out_insn_ldst(s, OPC_LDIH, rd, rs, l1);
+ rs = rd;
}
-
- /* Pop (FP, LR) */
- /* ldl $fp,0($sp) */
- tcg_out_insn_ldst(s, OPC_LDL, TCG_REG_FP, TCG_REG_SP, 0);
- /* ldl $26,8($sp) */
- tcg_out_insn_ldst(s, OPC_LDL, TCG_REG_RA, TCG_REG_SP, 8);
-
- /* restore SP to previous frame. */
- /* addl $sp,PUSH_SIZE,$sp */
- tcg_out_insn_simple(s, OPC_ADDL_I, OPC_ADDL, TCG_REG_SP, TCG_REG_SP, PUSH_SIZE);
-
- tcg_out_insn_jump(s, OPC_RET, TCG_REG_ZERO, TCG_REG_RA, 0);
+ if (extra) {
+ tcg_out_insn_ldst(s, OPC_LDIH, rd, rs, extra);
+ rs = rd;
+ }
+
+ tcg_out_insn_ldst(s, OPC_LDI, rd, rs, l0);
+ if (type == TCG_TYPE_I32) {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ }
}
static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
@@ -513,614 +583,541 @@ static bool tcg_out_mov(TCGContext *s, TCGType type, TCGReg ret, TCGReg arg)
tcg_out_movr(s, type, ret, arg);
break;
} else if (ret < 32) {
+ tcg_debug_assert(0);
break;
} else if (arg < 32) {
+ tcg_debug_assert(0);
break;
}
/* FALLTHRU */
+ case TCG_TYPE_V64:
+ case TCG_TYPE_V128:
+ tcg_debug_assert(0);
+ break;
default:
g_assert_not_reached();
}
return true;
}
+static inline void tcg_out_sxt(TCGContext *s, TCGType ext, MemOp s_bits,
+ TCGReg rd, TCGReg rn)
+{
+ /*
+ * Using ALIASes SXTB, SXTH, SXTW, of SBFM Xd, Xn, #0, #7|15|31
+ * int bits = (8 << s_bits) - 1;
+ * tcg_out_sbfm(s, ext, rd, rn, 0, bits);
+ */
+ switch (s_bits) {
+ case MO_8:
+ tcg_out_insn_simpleReg(s, OPC_SEXTB, rd, TCG_REG_ZERO, rn);
+ break;
+ case MO_16:
+ tcg_out_insn_simpleReg(s, OPC_SEXTH, rd, TCG_REG_ZERO, rn);
+ break;
+ case MO_32:
+ tcg_out_insn_simpleReg(s, OPC_ADDW, rd, rn, TCG_REG_ZERO);
+ break;
+ default:
+ tcg_debug_assert(0);
+ break;
+ }
+ if (ext == TCG_TYPE_I32) {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ }
+}
-static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
+/*
+ * counting heading/tailing zero numbers
+ */
+static void tcg_out_ctz64(TCGContext *s, SW_64Insn opc, TCGReg rd, TCGReg rn, TCGArg b, bool const_b)
{
- switch (op) {
- case INDEX_op_goto_ptr:
- return C_O0_I1(r);
+ if (const_b && b == 64) {
+ if (opc == OPC_CTLZ) {
+ tcg_out_insn_simpleReg(s, OPC_CTLZ, rd, TCG_REG_ZERO, rn);
+ } else {
+ tcg_out_insn_simpleReg(s, OPC_CTTZ, rd, TCG_REG_ZERO, rn);
+ }
+ } else {
+ if (opc == OPC_CTLZ) {
+ tcg_out_insn_simpleReg(s, OPC_CTLZ, TCG_REG_TMP2, TCG_REG_ZERO, rn);
+ } else {
+ tcg_out_insn_simpleReg(s, OPC_CTTZ, TCG_REG_TMP2, TCG_REG_ZERO, rn);
+ }
+ if (const_b) {
+ if (b == -1) {
+ tcg_out_insn_bitReg(s, OPC_ORNOT, rd, TCG_REG_ZERO, TCG_REG_ZERO);
+ tcg_out_insn_complexReg(s, OPC_SELNE, rn, rd, TCG_REG_TMP2, rd);
+ } else if (b == 0) {
+ tcg_out_insn_complexReg(s, OPC_SELNE, rn, rd, TCG_REG_TMP2, TCG_REG_ZERO);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_I64, rd, b);
+ tcg_out_insn_complexReg(s, OPC_SELNE, rn, rd, TCG_REG_TMP2, rd);
+ }
+ } else {
+ tcg_out_insn_complexReg(s, OPC_SELNE, rn, rd, TCG_REG_TMP2, b);
+ }
+ }
+}
- case INDEX_op_ld8u_i32:
- case INDEX_op_ld8s_i32:
- case INDEX_op_ld16u_i32:
- case INDEX_op_ld16s_i32:
- case INDEX_op_ld_i32:
- case INDEX_op_ld8u_i64:
- case INDEX_op_ld8s_i64:
- case INDEX_op_ld16u_i64:
- case INDEX_op_ld16s_i64:
- case INDEX_op_ld32u_i64:
- case INDEX_op_ld32s_i64:
- case INDEX_op_ld_i64:
- case INDEX_op_neg_i32:
- case INDEX_op_neg_i64:
- case INDEX_op_not_i32:
- case INDEX_op_not_i64:
- case INDEX_op_bswap16_i32:
- case INDEX_op_bswap32_i32:
- case INDEX_op_bswap16_i64:
- case INDEX_op_bswap32_i64:
- case INDEX_op_bswap64_i64:
- case INDEX_op_ext8s_i32:
- case INDEX_op_ext16s_i32:
- case INDEX_op_ext8u_i32:
- case INDEX_op_ext16u_i32:
- case INDEX_op_ext8s_i64:
- case INDEX_op_ext16s_i64:
- case INDEX_op_ext32s_i64:
- case INDEX_op_ext8u_i64:
- case INDEX_op_ext16u_i64:
- case INDEX_op_ext32u_i64:
- case INDEX_op_ext_i32_i64:
- case INDEX_op_extu_i32_i64:
- case INDEX_op_extract_i32:
- case INDEX_op_extract_i64:
- case INDEX_op_sextract_i32:
- case INDEX_op_sextract_i64:
- return C_O1_I1(r, r);
+/*
+ * counting heading/tailing zero numbers
+ */
+static void tcg_out_ctz32(TCGContext *s, SW_64Insn opc, TCGReg rd, TCGReg rn, TCGArg b, bool const_b)
+{
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_REG_TMP, rn, 0xf);
- case INDEX_op_st8_i32:
- case INDEX_op_st16_i32:
- case INDEX_op_st_i32:
- case INDEX_op_st8_i64:
- case INDEX_op_st16_i64:
- case INDEX_op_st32_i64:
- case INDEX_op_st_i64:
- return C_O0_I2(rZ, r);
+ if (const_b && b == 32) {
+ if (opc == OPC_CTLZ) {
+ tcg_out_insn_simpleReg(s, OPC_CTLZ, rd, TCG_REG_ZERO, TCG_REG_TMP);
+ tcg_out_insn_simpleImm(s, OPC_SUBW_I, rd, rd, 32);
+ } else {
+ tcg_out_insn_simpleReg(s, OPC_CTTZ, rd, TCG_REG_ZERO, TCG_REG_TMP);
+ tcg_out_insn_complexImm(s, OPC_SELEQ_I, TCG_REG_TMP, rd, 32, rd);
+ }
+ } else {
+ if (opc == OPC_CTLZ) {
+ tcg_out_insn_simpleReg(s, OPC_CTLZ, TCG_REG_TMP2, TCG_REG_ZERO, TCG_REG_TMP);
+ tcg_out_insn_simpleImm(s, OPC_SUBW_I, TCG_REG_TMP2, TCG_REG_TMP2, 32);
+ } else {
+ tcg_out_insn_simpleReg(s, OPC_CTTZ, TCG_REG_TMP2, TCG_REG_ZERO, TCG_REG_TMP);
+ tcg_out_insn_complexImm(s, OPC_SELEQ_I, TCG_REG_TMP, TCG_REG_TMP2, 32, TCG_REG_TMP2);
+ }
+ if (const_b) {
+ if (b == -1) {
+ tcg_out_insn_bitReg(s, OPC_ORNOT, rd, TCG_REG_ZERO, TCG_REG_ZERO);
+ tcg_out_insn_complexReg(s, OPC_SELNE, TCG_REG_TMP, rd, TCG_REG_TMP2, rd);
+ } else if (b == 0) {
+ tcg_out_insn_complexReg(s, OPC_SELNE, TCG_REG_TMP, rd, TCG_REG_TMP2, TCG_REG_ZERO);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_I32, rd, b);
+ tcg_out_insn_complexReg(s, OPC_SELNE, TCG_REG_TMP, rd, TCG_REG_TMP2, rd);
+ }
+ } else {
+ tcg_out_insn_complexReg(s, OPC_SELNE, TCG_REG_TMP, rd, TCG_REG_TMP2, b);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ }
+ }
+}
- case INDEX_op_add_i32:
- case INDEX_op_add_i64:
- case INDEX_op_sub_i32:
- case INDEX_op_sub_i64:
- return C_O1_I2(r, r, rU);//rA
+/*
+ * memory protect for order of (ld and st)
+ */
+static void tcg_out_mb(TCGContext *s)
+{
+ tcg_out32(s, OPC_MEMB);
+}
- case INDEX_op_setcond_i32:
- case INDEX_op_setcond_i64:
- return C_O1_I2(r, r, rU);//compare,rA
+static inline void tcg_out_bswap16(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn)
+{
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP2, rn, 1);
- case INDEX_op_mul_i32:
- case INDEX_op_mul_i64:
- case INDEX_op_div_i32:
- case INDEX_op_div_i64:
- case INDEX_op_divu_i32:
- case INDEX_op_divu_i64:
- case INDEX_op_rem_i32:
- case INDEX_op_rem_i64:
- case INDEX_op_remu_i32:
- case INDEX_op_remu_i64:
- case INDEX_op_muluh_i64:
- case INDEX_op_mulsh_i64:
- return C_O1_I2(r, r, r);
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 0);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 8);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
- case INDEX_op_and_i32:
- case INDEX_op_and_i64:
- case INDEX_op_or_i32:
- case INDEX_op_or_i64:
- case INDEX_op_xor_i32:
- case INDEX_op_xor_i64:
- case INDEX_op_andc_i32:
- case INDEX_op_andc_i64:
- case INDEX_op_orc_i32:
- case INDEX_op_orc_i64:
- case INDEX_op_eqv_i32:
- case INDEX_op_eqv_i64:
- return C_O1_I2(r, r, rU);//rL
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 3);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 16);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
- case INDEX_op_shl_i32:
- case INDEX_op_shr_i32:
- case INDEX_op_sar_i32:
- case INDEX_op_rotl_i32:
- case INDEX_op_rotr_i32:
- case INDEX_op_shl_i64:
- case INDEX_op_shr_i64:
- case INDEX_op_sar_i64:
- case INDEX_op_rotl_i64:
- case INDEX_op_rotr_i64:
- return C_O1_I2(r, r, ri);
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 2);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 24);
- case INDEX_op_clz_i32:
- case INDEX_op_clz_i64:
- return C_O1_I2(r, r, r); //rAL
+ if (ext == TCG_TYPE_I32) {
+ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP2, TCG_REG_TMP);
+ } else {
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
- case INDEX_op_ctz_i32:
- case INDEX_op_ctz_i64:
- return C_O1_I2(r, r, r);//rAL
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 5);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 32);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
- case INDEX_op_brcond_i32:
- case INDEX_op_brcond_i64:
- return C_O0_I2(r, rU);//rA
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 4);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 40);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
- case INDEX_op_movcond_i32:
- case INDEX_op_movcond_i64:
- return C_O1_I4(r, r, rU, rZ, rZ);//rA->rU
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 7);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 48);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
- case INDEX_op_qemu_ld_i32:
- case INDEX_op_qemu_ld_i64:
- return C_O1_I1(r, l);
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 6);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 56);
+ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP2, TCG_REG_TMP);
+ }
+}
- case INDEX_op_qemu_st_i32:
- case INDEX_op_qemu_st_i64:
- return C_O0_I2(lZ, l);
+static void tcg_out_bswap32(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn)
+{
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP2, rn, 3);
- case INDEX_op_deposit_i32:
- case INDEX_op_deposit_i64:
- return C_O1_I2(r, 0, rZ);
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 2);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 8);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
- case INDEX_op_extract2_i32:
- case INDEX_op_extract2_i64:
- return C_O1_I2(r, rZ, rZ);
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 1);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 16);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
- case INDEX_op_add2_i32:
- case INDEX_op_add2_i64:
- case INDEX_op_sub2_i32:
- case INDEX_op_sub2_i64:
- return C_O2_I4(r, r, rZ, rZ, rA, rMZ);
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 0);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 24);
- case INDEX_op_add_vec:
- case INDEX_op_sub_vec:
- case INDEX_op_mul_vec:
- case INDEX_op_xor_vec:
- case INDEX_op_ssadd_vec:
- case INDEX_op_sssub_vec:
- case INDEX_op_usadd_vec:
- case INDEX_op_ussub_vec:
- case INDEX_op_smax_vec:
- case INDEX_op_smin_vec:
- case INDEX_op_umax_vec:
- case INDEX_op_umin_vec:
- case INDEX_op_shlv_vec:
- case INDEX_op_shrv_vec:
- case INDEX_op_sarv_vec:
- return C_O1_I2(w, w, w);
- case INDEX_op_not_vec:
- case INDEX_op_neg_vec:
- case INDEX_op_abs_vec:
- case INDEX_op_shli_vec:
- case INDEX_op_shri_vec:
- case INDEX_op_sari_vec:
- return C_O1_I1(w, w);
- case INDEX_op_ld_vec:
- case INDEX_op_dupm_vec:
- return C_O1_I1(w, r);
- case INDEX_op_st_vec:
- return C_O0_I2(w, r);
- case INDEX_op_dup_vec:
- return C_O1_I1(w, wr);
- case INDEX_op_or_vec:
- case INDEX_op_andc_vec:
- return C_O1_I2(w, w, wO);
- case INDEX_op_and_vec:
- case INDEX_op_orc_vec:
- return C_O1_I2(w, w, wN);
- case INDEX_op_cmp_vec:
- return C_O1_I2(w, w, wZ);
- case INDEX_op_bitsel_vec:
- return C_O1_I3(w, w, w, w);
+ if (ext == TCG_TYPE_I32) {
+ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP2, TCG_REG_TMP);
+ } else {
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
- default:
- g_assert_not_reached();
- }
-}
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 7);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 32);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 6);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 40);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
-static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
-{
- int i;
- for (i = 0; i < count; ++i) {
- p[i] = OPC_NOP;
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 5);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 48);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
+
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 4);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 56);
+ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP2, TCG_REG_TMP);
}
}
-/* SW instruction format of syscall
- * insn = opcode[31,26]:Function[25,0],
- */
-
-/* SW instruction format of br(alias jump)
- * insn = opcode[31,26]:Rd[25,21]:disp[20,0],
- */
-static void tcg_out_insn_br(TCGContext *s, SW_64Insn insn, TCGReg rd, intptr_t imm64)
+static void tcg_out_bswap64(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn)
{
- tcg_debug_assert(imm64 <= 0xfffff && imm64 >= -0x100000);
- tcg_out32(s, insn | (rd & 0x1f) << 21 | (imm64 & 0x1fffff));
-}
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP2, rn, 7);
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 6);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 8);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
-/* SW instruction format of (load and store)
- * insn = opcode[31,26]:rd[25,21]:rn[20,16]:disp[15,0]
- */
-static void tcg_out_insn_ldst(TCGContext *s, SW_64Insn insn, TCGReg rd, TCGReg rn, intptr_t imm16)
-{
- tcg_debug_assert(imm16 <= 0x7fff && imm16 >= -0x8000);
- tcg_out32(s, insn | (rd & 0x1f) << 21 | (rn & 0x1f) << 16 | (imm16 & 0xffff));
-}
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 5);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 16);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 4);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 24);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
-/* SW instruction format of simple operator for Register
- * insn = opcode[31,26]:rn(ra)[25,21]:rn(rb)[20,16]:Zeors[15,13]:function[12,5]:rd(rc)[4,0]
- */
-static void tcg_out_insn_simpleReg(TCGContext *s, SW_64Insn insn, TCGReg rd, TCGReg rn, TCGReg rm)
-{
- tcg_out32(s, insn | (rn & 0x1f) << 21 | (rm & 0x1f) << 16 | (rd & 0x1f));
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 3);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 32);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
+
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 2);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 40);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
+
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 1);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 48);
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_TMP);
+
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, TCG_REG_TMP, rn, 0);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, 56);
+ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP2, TCG_REG_TMP);
}
-/* SW instruction format of simple operator for imm
- * insn = opcode[31,26]:rn(ra)[25,21]:disp[20,13]:function[12,5]:rd(rc)[4,0]
- */
-static void tcg_out_insn_simple(TCGContext *s, SW_64Insn insn_Imm, SW_64Insn insn_Reg, TCGReg rd, TCGReg rn, intptr_t imm64)
+static void tcg_out_extract(TCGContext *s, TCGReg rd, TCGReg rn, int lsb, int len)
{
- if(imm64 <= 0x7f && imm64 >= -0x80) {
- tcg_out32(s, insn_Imm | (rn & 0x1f) << 21 | (imm64 & 0xff) << 13 | (rd & 0x1f));
- }
- else {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, imm64);
- tcg_out_insn_simpleReg(s, insn_Reg, rd, rn, TCG_REG_TMP);
- }
-}
+ //get 000..111..0000
+ tcg_out_insn_bitReg(s, OPC_ORNOT, TCG_REG_TMP, TCG_REG_ZERO, TCG_REG_ZERO);
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, TCG_REG_TMP, TCG_REG_TMP, 64 - len);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, lsb);
+ /* get rn[lsb, lsb+len-1]-->rd[lsb, lsb+len-1] */
+ tcg_out_insn_bitReg(s, OPC_AND, rd, rn, TCG_REG_TMP);
+ /* rd[lsb, lsb+len-1] --> rd[0, len-1] */
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, rd, rd, lsb);
+}
-static void tcg_out_insn_simpleImm(TCGContext *s, SW_64Insn insn_Imm, TCGReg rd, TCGReg rn, intptr_t imm64)
+static void tcg_out_dep(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, int lsb, int len)
{
- tcg_debug_assert(imm64 <= 0x7f && imm64 >= -0x80);
- tcg_out32(s, insn_Imm | (rn & 0x1f) << 21 | (imm64 & 0xff) << 13 | (rd & 0x1f));
+ tcg_out_insn_bitReg(s, OPC_ORNOT, TCG_REG_TMP, TCG_REG_ZERO, TCG_REG_ZERO);
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, TCG_REG_TMP, TCG_REG_TMP, 64 - len);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, lsb);
+
+ /* TCG_REG_TMP2 = rn[msb,lsb] */
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP2, rn, 64-len);
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, TCG_REG_TMP2, TCG_REG_TMP2, 64-len-lsb);
+ /* clear rd[msb,lsb] */
+ tcg_out_insn_bitReg(s, OPC_BIC, rd, rd, TCG_REG_TMP);
+ /* rd = rd[63:msb+1]:rn[msb,lsb]:rd[lsb-1,0] */
+ tcg_out_insn_bitReg(s, OPC_BIS, rd, rd, TCG_REG_TMP2);
+
+ if (ext == TCG_TYPE_I32) {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ }
}
-static void tcg_out_insn_bitImm(TCGContext *s, SW_64Insn insn_Imm, TCGReg rd, TCGReg rn, unsigned long imm64)
+static void tcg_out_mulsh64(TCGContext *s, TCGReg rd, TCGReg rn, TCGReg rm)
{
- tcg_debug_assert(imm64 <= 255);
- tcg_out32(s, insn_Imm | (rn & 0x1f) << 21 | (imm64 & 0xff) << 13 | (rd & 0x1f));
+ tcg_out_insn_simpleReg(s, OPC_UMULH, TCG_REG_TMP, rn, rm);
+
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, TCG_REG_TMP2, rn, 63);
+ tcg_out_insn_complexReg(s, OPC_SELEQ, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_ZERO, rm);
+ tcg_out_insn_simpleReg(s, OPC_SUBL, TCG_REG_TMP, TCG_REG_TMP, TCG_REG_TMP2);
+
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, TCG_REG_TMP2, rm, 63);
+ tcg_out_insn_complexReg(s, OPC_SELEQ, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_ZERO, rn);
+ tcg_out_insn_simpleReg(s, OPC_SUBL, rd, TCG_REG_TMP, TCG_REG_TMP2);
}
-/* sw bit operation: and bis etc */
-static void tcg_out_insn_bit(TCGContext *s, SW_64Insn insn_Imm, SW_64Insn insn_Reg, TCGReg rd, TCGReg rn, unsigned long imm64)
+
+static void tcg_out_sar(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGArg a2, bool c2)
{
- if (imm64 <= 255) {
- tcg_out32(s, insn_Imm | (rn & 0x1f) << 21 | (imm64 & 0xff) << 13 | (rd & 0x1f));
- }
- else {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, imm64);
- tcg_out_insn_bitReg(s, insn_Reg, rd, rn, TCG_REG_TMP);
+ unsigned int bits = ext ? 64 : 32;
+ unsigned int max = bits - 1;
+ if (ext == TCG_TYPE_I32) {
+ tcg_out_insn_simpleReg(s, OPC_ADDW, TCG_REG_TMP, rn, TCG_REG_ZERO);
+
+ if (c2) {
+ tcg_out_insn_simpleImm(s, OPC_SRA_I, rd, TCG_REG_TMP, a2 & max);
+ } else {
+ tcg_out_insn_bitReg(s, OPC_SRA, rd, TCG_REG_TMP, a2);
+ }
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ } else {
+ if (c2) {
+ tcg_out_insn_simpleImm(s, OPC_SRA_I, rd, rn, a2 & max);
+ } else {
+ tcg_out_insn_bitReg(s, OPC_SRA, rd, rn, a2);
+ }
}
}
-/* SW instruction format of complex operator
- * insn = opcode[31,26]:rd[25,21]:rn[20,16],function[15,10]:rm[9,5]:rx[4,0]
+/*
+ * memory <=> Reg in (B H W L) bytes
*/
-static void tcg_out_insn_complexReg(TCGContext *s, SW_64Insn insn, TCGReg cond, TCGReg rd, TCGReg rn, TCGReg rm)
-{
- tcg_out32(s, insn | (cond & 0x1f) << 21 | (rn & 0x1f) << 16 | (rm & 0x1f) << 5 | (rd & 0x1f));
-}
-
-static bool reloc_pc21(tcg_insn_unit *src_rw, const tcg_insn_unit *target)
+static void tcg_out_ldst(TCGContext *s, SW_64Insn insn, TCGReg rd, TCGReg rn, intptr_t offset, bool sign)
{
- const tcg_insn_unit *src_rx = tcg_splitwx_to_rx(src_rw);
- ptrdiff_t offset = target - (src_rx + 1) ;
+ if (offset != sextract64(offset, 0, 15)) {
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP2, offset);
+ tcg_out_insn_simpleReg(s, OPC_ADDL, TCG_REG_TMP2, TCG_REG_TMP2, rn);
+ tcg_out_insn_ldst(s, insn, rd, TCG_REG_TMP2, 0);
+ } else {
+ tcg_out_insn_ldst(s, insn, rd, rn, offset);
+ }
- if (offset == sextract64(offset, 0, 21)) {
- /* read instruction, mask away previous PC_REL21 parameter contents,
- set the proper offset, then write back the instruction. */
- *src_rw = deposit32(*src_rw, 0, 21, offset);
- return true;
+ switch (insn) {
+ case OPC_LDBU:
+ if (sign)
+ tcg_out_insn_simpleReg(s, OPC_SEXTB, rd, TCG_REG_ZERO, rd);
+ break;
+ case OPC_LDHU:
+ if (sign)
+ tcg_out_insn_simpleReg(s, OPC_SEXTH, rd, TCG_REG_ZERO, rd);
+ break;
+ case OPC_LDW:
+ if (!sign)
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ break;
+ default:
+ break;
}
- return false;
}
-/* sw*/
-static bool patch_reloc(tcg_insn_unit *code_ptr, int type, intptr_t value, intptr_t addend)
+static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg rd, TCGReg rn, intptr_t ofs)
{
- tcg_debug_assert(addend == 0);
switch (type) {
- case R_SW_64_BRADDR:
- return reloc_pc21(code_ptr, (const tcg_insn_unit *)value);
+ case TCG_TYPE_I32:
+ tcg_out_ldst(s, OPC_LDW, rd, rn, ofs, zeroExt);
+ break;
+ case TCG_TYPE_I64:
+ tcg_out_ldst(s, OPC_LDL, rd, rn, ofs, sigExt);
+ break;
+ case TCG_TYPE_V64:
+ case TCG_TYPE_V128:
+ tcg_debug_assert(0);
+ break;
default:
g_assert_not_reached();
}
}
-static inline uint32_t tcg_in32(TCGContext *s)
+static void tcg_out_st(TCGContext *s, TCGType type, TCGReg rd,TCGReg rn, intptr_t ofs)
{
- uint32_t v = *(uint32_t *)s->code_ptr;
- return v;
-}
-
-/*SW Register to register move using ADDL*/
-static void tcg_out_movr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn)
-{
- tcg_out_insn_simpleReg(s, OPC_BIS, rd, rn, TCG_REG_ZERO);
- if (ext == TCG_TYPE_I32){
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ switch (type) {
+ case TCG_TYPE_I32:
+ tcg_out_ldst(s, OPC_STW, rd, rn, ofs, noPara);
+ break;
+ case TCG_TYPE_I64:
+ tcg_out_ldst(s, OPC_STL, rd, rn, ofs, noPara);
+ break;
+ case TCG_TYPE_V64:
+ case TCG_TYPE_V128:
+ tcg_debug_assert(0);
+ break;
+ default:
+ g_assert_not_reached();
}
}
-/*sw
- *put imm into rd
- */
-static void tcg_out_movi(TCGContext *s, TCGType type, TCGReg rd, tcg_target_long orig)
+static void tcg_out_cond_cmp(TCGContext *s, TCGType ext, TCGCond cond, TCGReg ret, TCGArg a, tcg_target_long b, bool const_b)
{
- long l0, l1, l2=0, l3=0, extra=0;
- tcg_target_long val = orig;
- TCGReg rs = TCG_REG_ZERO;
-
- if (type == TCG_TYPE_I32)
- val = (int32_t)val;
-
- l0 = (int16_t)val;
- val = (val - l0) >> 16;
- l1 = (int16_t)val;
-
- if (orig >> 31 == -1 || orig >> 31 == 0) {
- if (l1 < 0 && orig >= 0) {
- extra = 0x4000;
- l1 = (int16_t)(val - 0x4000);
- }
- } else {
- val = (val - l1) >> 16;
- l2 = (int16_t)val;
- val = (val - l2) >> 16;
- l3 = (int16_t)val;
-
- if (l3) {
- tcg_out_insn_ldst(s, OPC_LDIH, rd, rs, l3);
- rs = rd;
- }
- if (l2) {
- tcg_out_insn_ldst(s, OPC_LDI, rd, rs, l2);
- rs = rd;
- }
- if (l3 || l2)
- tcg_out_insn_simpleImm(s, OPC_SLL_I, rd, rd, 32);
- }
-
- if (l1) {
- tcg_out_insn_ldst(s, OPC_LDIH, rd, rs, l1);
- rs = rd;
+ if (const_b && (b < 0 || b > 0xff)) {
+ tcg_out_movi(s, ext, TCG_REG_TMP2, b);
+ b = TCG_REG_TMP2;
+ const_b = 0;
}
-
- if (extra) {
- tcg_out_insn_ldst(s, OPC_LDIH, rd, rs, extra);
- rs = rd;
- }
-
- tcg_out_insn_ldst(s, OPC_LDI, rd, rs, l0);
-}
-
-/*sw
-* memory <=> Reg in (B H W L) bytes
-*/
-static void tcg_out_ldst(TCGContext *s, SW_64Insn insn, TCGReg rd, TCGReg rn, intptr_t offset, bool sign)
-{
- int16_t lo = offset;
- if (offset != lo) {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, offset - lo);
- if (rn != TCG_REG_ZERO) {
- tcg_out_insn_simpleReg(s, OPC_ADDL, TCG_REG_TMP, TCG_REG_TMP, rn);
+ if (ext == TCG_TYPE_I32) {
+ tcg_out_insn_simpleReg(s, OPC_ADDW, a, a, TCG_REG_ZERO);
+ if (!const_b) {
+ tcg_out_insn_simpleReg(s, OPC_ADDW, b, b, TCG_REG_ZERO);
+ } else {
+ b = (int32_t)b;
}
- tcg_out_insn_ldst(s, insn, rd, TCG_REG_TMP, lo);
- }
- else {
- tcg_out_insn_ldst(s, insn, rd, rn, lo);
}
- switch (insn) {
- case OPC_LDBU:
- if (sign)
- tcg_out_insn_simpleReg(s, OPC_SEXTB, rd, TCG_REG_ZERO, rd); //for micro-op:INDEX_op_ld8s_i32/64,set rd[63,8]=1
- break;
- case OPC_LDHU:
- if (sign)
- tcg_out_insn_simpleReg(s, OPC_SEXTH, rd, TCG_REG_ZERO, rd); //for micro-op:INDEX_op_ld16s_i32/64,set rd[63,16]=1
- break;
- case OPC_LDW:
- if (!sign)
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf); //for micro-op:INDEX_op_ld32u_i32/64,set rd[63,32]=0
- break;
- default:
- break;
- }
-}
-
-/* TCG_REG_TMP stores result_of_condition_compare */
-static void tcg_out_cond_cmp(TCGContext *s, TCGCond cond, TCGReg ret, TCGArg a, TCGArg b, bool const_b)
-{
if (const_b) {
- switch(cond) {
- case TCG_COND_ALWAYS:
- case TCG_COND_NEVER:
- break;
- case TCG_COND_EQ:
- case TCG_COND_NE:
- tcg_out_insn_simple(s, OPC_CMPEQ_I, OPC_CMPEQ, ret, a, b);
- break;
- case TCG_COND_LT:
- case TCG_COND_GE:
- tcg_out_insn_simple(s, OPC_CMPLT_I, OPC_CMPLT, ret, a, b);
- break;
- case TCG_COND_LE:
- case TCG_COND_GT:
- tcg_out_insn_simple(s, OPC_CMPLE_I, OPC_CMPLE, ret, a, b);
- break;
- case TCG_COND_LTU:
- case TCG_COND_GEU:
- tcg_out_insn_simple(s, OPC_CMPULT_I, OPC_CMPULT, ret, a, b);
- break;
- case TCG_COND_LEU:
- case TCG_COND_GTU:
- tcg_out_insn_simple(s, OPC_CMPULE_I, OPC_CMPULE, ret, a, b);
- break;
- }//cond
- }//if (const_b)
- else {
- switch(cond) {
- case TCG_COND_ALWAYS:
- case TCG_COND_NEVER:
- break;
- case TCG_COND_EQ:
- case TCG_COND_NE:
- tcg_out_insn_simpleReg(s, OPC_CMPEQ, ret, a, b);
- break;
- case TCG_COND_LT:
- case TCG_COND_GE:
- tcg_out_insn_simpleReg(s, OPC_CMPLT, ret, a, b);
- break;
- case TCG_COND_LE:
- case TCG_COND_GT:
- tcg_out_insn_simpleReg(s, OPC_CMPLE, ret, a, b);
- break;
- case TCG_COND_LTU:
- case TCG_COND_GEU:
- tcg_out_insn_simpleReg(s, OPC_CMPULT, ret, a, b);
- break;
- case TCG_COND_LEU:
- case TCG_COND_GTU:
- tcg_out_insn_simpleReg(s, OPC_CMPULE, ret, a, b);
- break;
- }//cond
- }//else
- switch(cond) {
- case TCG_COND_ALWAYS:
- case TCG_COND_NEVER:
+ switch (cond) {
case TCG_COND_EQ:
+ case TCG_COND_NE:
+ tcg_out_insn_simpleImm(s, OPC_CMPEQ_I, ret, a, b);
+ break;
case TCG_COND_LT:
+ case TCG_COND_GE:
+ tcg_out_insn_simpleImm(s, OPC_CMPLT_I, ret, a, b);
+ break;
case TCG_COND_LE:
+ case TCG_COND_GT:
+ tcg_out_insn_simpleImm(s, OPC_CMPLE_I, ret, a, b);
+ break;
case TCG_COND_LTU:
+ case TCG_COND_GEU:
+ tcg_out_insn_simpleImm(s, OPC_CMPULT_I, ret, a, b);
+ break;
case TCG_COND_LEU:
+ case TCG_COND_GTU:
+ tcg_out_insn_simpleImm(s, OPC_CMPULE_I, ret, a, b);
break;
- case TCG_COND_NE:
- case TCG_COND_GE:
- case TCG_COND_GT:
- case TCG_COND_GEU:
- case TCG_COND_GTU:
- tcg_out_insn_bitImm(s, OPC_XOR_I, ret, ret, 0x1);
+ default:
+ tcg_debug_assert(0);
+ break;
+ }
+ } else {
+ switch (cond) {
+ case TCG_COND_EQ:
+ case TCG_COND_NE:
+ tcg_out_insn_simpleReg(s, OPC_CMPEQ, ret, a, b);
break;
+ case TCG_COND_LT:
+ case TCG_COND_GE:
+ tcg_out_insn_simpleReg(s, OPC_CMPLT, ret, a, b);
+ break;
+ case TCG_COND_LE:
+ case TCG_COND_GT:
+ tcg_out_insn_simpleReg(s, OPC_CMPLE, ret, a, b);
+ break;
+ case TCG_COND_LTU:
+ case TCG_COND_GEU:
+ tcg_out_insn_simpleReg(s, OPC_CMPULT, ret, a, b);
+ break;
+ case TCG_COND_LEU:
+ case TCG_COND_GTU:
+ tcg_out_insn_simpleReg(s, OPC_CMPULE, ret, a, b);
+ break;
+ default:
+ tcg_debug_assert(0);
+ break;
+ }
+ }
+
+ if (ext == TCG_TYPE_I32) {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a, a, 0xf);
+ if (!const_b) {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, b, b, 0xf);
+ }
+ }
+
+ switch (cond) {
+ case TCG_COND_NE:
+ case TCG_COND_GE:
+ case TCG_COND_GT:
+ case TCG_COND_GEU:
+ case TCG_COND_GTU:
+ tcg_out_insn_simpleImm(s, OPC_XOR_I, ret, ret, 0x1);
+ break;
+ case TCG_COND_ALWAYS:
+ case TCG_COND_NEVER:
+ tcg_debug_assert(0);
+ break;
+ default:
+ break;
}
}
-/* sw
+/*
* step1 tcg_out_cmp() ,"eq" and "ne" in the same case with the same insn;
* store compare result by TCG_REG_TMP, for step2;
* step2: jump address with compare result. in last "switch" section, we diff qe/ne by different case with different insn.
*/
-static void tcg_out_brcond(TCGContext *s, TCGType ext, TCGCond cond, TCGArg a, TCGArg b, bool b_const, TCGLabel *l)
+static void tcg_out_brcond(TCGContext *s, TCGType ext, TCGCond cond, TCGArg a, tcg_target_long b, bool b_const, TCGLabel *l)
{
intptr_t offset;
bool need_cmp;
if (b_const && b == 0 && (cond == TCG_COND_EQ || cond == TCG_COND_NE)) {
need_cmp = false;
+ if (ext == TCG_TYPE_I32) {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_REG_TMP, a, 0xf);
+ } else {
+ tcg_out_insn_bitReg(s, OPC_BIS, TCG_REG_TMP, a, TCG_REG_ZERO);
+ }
} else {
need_cmp = true;
- tcg_out_cond_cmp(s, cond, TCG_REG_TMP, a, b, b_const);
+ tcg_out_cond_cmp(s, ext, cond, TCG_REG_TMP, a, b, b_const);
}
if (!l->has_value) {
tcg_out_reloc(s, s->code_ptr, R_SW_64_BRADDR, l, 0);
- offset=0; //offset = tcg_in32(s) >> 5; br $31, 0, do not jump here!
+ offset=0; //offset = tcg_in32(s) >> 5;//luo br $31, 0, do not jump here!
} else {
- offset = tcg_pcrel_diff(s, l->u.value_ptr) ;
- offset = offset >> 2;
+ offset = tcg_pcrel_diff(s, l->u.value_ptr);
+ offset = offset - 4;
+ offset = offset >> 2;
tcg_debug_assert(offset == sextract64(offset, 0, 21));
}
if (need_cmp) {
- tcg_out_insn_br(s, OPC_BGT, TCG_REG_TMP, offset); //a cond b,jmp
+ tcg_out_insn_br(s, OPC_BGT, TCG_REG_TMP, offset);
} else if (cond == TCG_COND_EQ) {
- tcg_out_insn_br(s, OPC_BEQ, a, offset);
+ tcg_out_insn_br(s, OPC_BEQ, TCG_REG_TMP, offset);
} else {
- tcg_out_insn_br(s, OPC_BNE, a, offset);
- }
-}
-
-/*sw
- * contact with "tcg-target-con-str.h"
- */
-#define TCG_CT_CONST_ZERO 0x100
-#define TCG_CT_CONST_LONG 0x200
-#define TCG_CT_CONST_MONE 0x400
-#define TCG_CT_CONST_ORRI 0x800
-#define TCG_CT_CONST_WORD 0X1000
-#define TCG_CT_CONST_U8 0x2000
-#define TCG_CT_CONST_S8 0X4000
-
-#define ALL_GENERAL_REGS 0xffffffffu
-#define ALL_VECTOR_REGS 0xffffffff00000000ull
-
-
-#ifdef CONFIG_SOFTMMU
-/*sw #define ALL_QLDST_REGS */
-#else
- #define ALL_QLDST_REGS ALL_GENERAL_REGS
-#endif
-
-/* sw test if a constant matches the constraint */
-static bool tcg_target_const_match(int64_t val, TCGType type, int ct)
-{
- if (ct & TCG_CT_CONST) {
- return 1;
- }
- if (type == TCG_TYPE_I32) {
- val = (int32_t)val;
- }
- if ((ct & TCG_CT_CONST_U8) && 0 <= val && val <= 255) {
- return 1;
- }
- if ((ct & TCG_CT_CONST_LONG)) {
- return 1;
- }
- if ((ct & TCG_CT_CONST_MONE)) {
- return 1;
- }
- if ((ct & TCG_CT_CONST_ORRI)) {
- return 1;
- }
- if ((ct & TCG_CT_CONST_WORD)) {
- return 1;
- }
- if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
- return 1;
+ tcg_out_insn_br(s, OPC_BNE, TCG_REG_TMP, offset);
}
- return 0;
}
-static void tcg_out_ld(TCGContext *s, TCGType type, TCGReg rd, TCGReg rn, intptr_t ofs)
+static void tcg_out_setcond(TCGContext *s, TCGType ext, TCGCond cond, TCGReg ret,
+ TCGReg a, tcg_target_long b, bool const_b)
{
- switch (type) {
- case TCG_TYPE_I32:
- tcg_out_ldst(s, OPC_LDW, rd, rn, ofs, sigExt);
- break;
- case TCG_TYPE_I64:
- tcg_out_ldst(s, OPC_LDL, rd, rn, ofs, sigExt);
+ switch (cond) {
+ case TCG_COND_EQ:
+ case TCG_COND_LT:
+ case TCG_COND_LE:
+ case TCG_COND_LTU:
+ case TCG_COND_LEU:
+ case TCG_COND_NE:
+ case TCG_COND_GE:
+ case TCG_COND_GT:
+ case TCG_COND_GEU:
+ case TCG_COND_GTU:
+ tcg_out_cond_cmp(s, ext, cond, ret, a, b, const_b);
break;
default:
- g_assert_not_reached();
+ tcg_abort();
+ break;
}
}
-static void tcg_out_st(TCGContext *s, TCGType type, TCGReg rd, TCGReg rn, intptr_t ofs)
+static void tcg_out_movcond(TCGContext *s, TCGType ext, TCGCond cond, TCGReg ret,
+ TCGReg a1, tcg_target_long a2, bool const_b, TCGReg v1, TCGReg v2)
{
- switch (type) {
- case TCG_TYPE_I32:
- tcg_out_insn_ldst(s, OPC_STW, rd, rn, ofs);
- break;
- case TCG_TYPE_I64:
- tcg_out_insn_ldst(s, OPC_STL, rd, rn, ofs);
- break;
- default:
- g_assert_not_reached();
- }
+ tcg_out_cond_cmp(s, ext, cond, TCG_REG_TMP, a1, a2, const_b);
+ tcg_out_insn_complexReg(s, OPC_SELLBS, TCG_REG_TMP, ret, v1, v2);
}
-static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, TCGReg base, intptr_t ofs)
+static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,TCGReg base, intptr_t ofs)
{
if (type <= TCG_TYPE_I64 && val == 0) {
tcg_out_st(s, type, TCG_REG_ZERO, base, ofs);
@@ -1129,66 +1126,123 @@ static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val, TCGReg b
return false;
}
-static void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd, TCGReg rn, int64_t imm64)
+static void tcg_out_addsubi(TCGContext *s, int ext, TCGReg rd,TCGReg rn, int64_t imm64)
{
- if (imm64 >= 0) {
- if(0 <=imm64 && imm64 <= 255) {
- /* we use tcg_out_insn_bitImm because imm64 is between 0~255 */
- tcg_out_insn_bitImm(s, OPC_ADDL_I, rd, rn, imm64);
- }//aimm>0 && aimm == sextract64(aim, 0, 8)
- else {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, imm64);
- tcg_out_insn_simpleReg(s, OPC_ADDL, rd, rn, TCG_REG_TMP);
- }//aimm>0 && aimm != sextract64(aim, 0, 8)
+ if (ext == TCG_TYPE_I64) {
+ if (imm64 >= 0) {
+ if (0 <=imm64 && imm64 <= 255) {
+ /* we use tcg_out_insn_simpleImm because imm64 is between 0~255 */
+ tcg_out_insn_simpleImm(s, OPC_ADDL_I, rd, rn, imm64);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, imm64);
+ tcg_out_insn_simpleReg(s, OPC_ADDL, rd, rn, TCG_REG_TMP);
+ }
+ } else {
+ if (0 < -imm64 && -imm64 <= 255) {
+ /* we use tcg_out_insn_simpleImm because -imm64 is between 0~255 */
+ tcg_out_insn_simpleImm(s, OPC_SUBL_I, rd, rn, -imm64);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, -imm64);
+ tcg_out_insn_simpleReg(s, OPC_SUBL, rd, rn, TCG_REG_TMP);
+ }
+ }
} else {
- if(0 < -imm64 && -imm64 <= 255) {
- /* we use tcg_out_insn_bitImm because -imm64 is between 0~255 */
- tcg_out_insn_bitImm(s, OPC_SUBL_I, rd, rn, -imm64);
- }//aimm<0 && aimm == sextract64(aim, 0, 8)
- else {
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, -imm64);
- tcg_out_insn_simpleReg(s, OPC_SUBL, rd, rn, TCG_REG_TMP);
- }//aimm<0 && aimm != sextract64(aim, 0, 8)
+ if (imm64 >= 0) {
+ if (0 <=imm64 && imm64 <= 255) {
+ /* we use tcg_out_insn_simpleImm because imm64 is between 0~255 */
+ tcg_out_insn_simpleImm(s, OPC_ADDW_I, rd, rn, imm64);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_TMP, imm64);
+ tcg_out_insn_simpleReg(s, OPC_ADDW, rd, rn, TCG_REG_TMP);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ }
+ } else {
+ if (0 < -imm64 && -imm64 <= 255) {
+ /* we use tcg_out_insn_simpleImm because -imm64 is between 0~255 */
+ tcg_out_insn_simpleImm(s, OPC_SUBW_I, rd, rn, -imm64);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ } else {
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_TMP, -imm64);
+ tcg_out_insn_simpleReg(s, OPC_SUBW, rd, rn, TCG_REG_TMP);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ }
+ }
}
}
static void tcg_out_goto(TCGContext *s, const tcg_insn_unit *target)
{
- ptrdiff_t offset = tcg_pcrel_diff(s, target) >> 2;
+ ptrdiff_t offset = (tcg_pcrel_diff(s, target) - 4) >> 2;
tcg_debug_assert(offset == sextract64(offset, 0, 21));
tcg_out_insn_br(s, OPC_BR, TCG_REG_ZERO, offset);
}
static void tcg_out_goto_long(TCGContext *s, const tcg_insn_unit *target)
{
- ptrdiff_t offset = tcg_pcrel_diff(s, target) >> 2;
- if (0 <= offset && offset <= 0x1fffff) {
+ ptrdiff_t offset = (tcg_pcrel_diff(s, target) - 4) >> 2;
+ if (offset == sextract64(offset, 0 ,21)) {
tcg_out_insn_br(s, OPC_BR, TCG_REG_ZERO, offset);
} else {
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, (intptr_t)target);
- tcg_out_insn_jump(s, OPC_JMP, TCG_REG_ZERO, TCG_REG_TMP, 0);
+ tcg_out_insn_jump(s, OPC_JMP, TCG_REG_ZERO, TCG_REG_TMP, noPara);
}
}
-
-/*sw
-* call subroutine
-*/
static void tcg_out_call(TCGContext *s, const tcg_insn_unit *target)
{
- ptrdiff_t offset = tcg_pcrel_diff(s, target) >> 2;
+ ptrdiff_t offset = (tcg_pcrel_diff(s, target) - 4) >> 2;
if (offset == sextract64(offset, 0, 21)) {
tcg_out_insn_br(s, OPC_BSR, TCG_REG_RA, offset);
} else {
tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP, (intptr_t)target);
- tcg_out_insn_jump(s, OPC_CALL, TCG_REG_RA, TCG_REG_TMP, 0);
+ tcg_out_insn_jump(s, OPC_CALL, TCG_REG_RA, TCG_REG_TMP, noPara);
+ }
+}
+
+static void modify_direct_addr(uintptr_t addr, uintptr_t jmp_rw, uintptr_t jmp_rx)
+{
+ tcg_target_long l0=0, l1=0;
+ tcg_target_long val = addr;
+ TCGReg rs = TCG_REG_ZERO;
+ TCGReg rd = TCG_REG_TMP;
+ tcg_insn_unit i_nop=0, i1=0, i2=0;
+ uint64_t pair = 0;
+ i_nop = OPC_NOP;
+ uintptr_t jmp = jmp_rw;
+
+ l0 = (int16_t)val;
+ val = (val - l0) >> 16;
+ l1 = (int16_t)val;
+ if (l1) {
+ i1 = OPC_LDIH | (rd & 0x1f) << 21 | (rs & 0x1f) << 16 | (l1 & 0xffff);
+ } else {
+ i1 = i_nop;
}
+ i2 = OPC_LDI | (rd & 0x1f) << 21 | (rs & 0x1f) << 16 | (l0 & 0xffff);
+ pair = (uint64_t)i1 << 32 | i2;
+ qatomic_set((uint64_t *)jmp, pair);
+ flush_idcache_range(jmp_rx, jmp_rw, 8);
}
void tb_target_set_jmp_target(uintptr_t tc_ptr, uintptr_t jmp_rx, uintptr_t jmp_rw, uintptr_t addr)
{
- tcg_debug_assert(0);
- //sw not support
+ tcg_insn_unit i1, i2;
+ uint64_t pair;
+
+ ptrdiff_t offset = addr - jmp_rx -4;
+
+ if (offset == sextract64(offset, 0, 21)) {
+ i1 = OPC_BR | (TCG_REG_ZERO & 0x1f) << 21| ((offset >> 2) & 0x1fffff);
+ i2 = OPC_NOP;
+ pair = (uint64_t)i2 << 32 | i1;
+ qatomic_set((uint64_t *)jmp_rw, pair);
+ flush_idcache_range(jmp_rx, jmp_rw, 8);
+ } else if (offset == sextract64(offset, 0, 32)) {
+ modify_direct_addr(addr, jmp_rw, jmp_rx);
+ } else {
+ tcg_debug_assert("tb_target");
+ }
}
static inline void tcg_out_goto_label(TCGContext *s, TCGLabel *l)
@@ -1201,8 +1255,8 @@ static inline void tcg_out_goto_label(TCGContext *s, TCGLabel *l)
}
}
-/* sw
- * resut: rd=rn(64,64-m]:rm(64-m,0]
+/*
+ * result: rd=rn(64,64-m]:rm(64-m,0]
* 1: rn(m,0]--->TCG_REG_TMP(64,64-m]
* 2: rm(64,64-m]--->rm(64-m,0]
* 3: rd=TCG_REG_TMP(64,64-m]:rm(64-m,0]
@@ -1211,84 +1265,442 @@ static inline void tcg_out_extr(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn
{
int bits = ext ? 64 : 32;
int max = bits - 1;
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_REG_TMP, rn, bits - (m & max));
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP2, rm, (m & max));
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, rn, bits - (m & max));
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, TCG_REG_TMP2, rm, (m & max));
tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2);
}
-/* sw
- * loop right shift
- */
static inline void tcg_out_rotr_Imm(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int m)
{
- int bits = ext ? 64 : 32;
- int max = bits - 1;
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_REG_TMP, rn, bits - (m & max));
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP2, rn, (m & max));
- tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2);
+ unsigned int bits = ext ? 64 : 32;
+ unsigned int max = bits - 1;
+ if (ext == TCG_TYPE_I64) {
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, rn, bits - (m & max));
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, TCG_REG_TMP2, rn, (m & max));
+ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2);
+ } else {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rn, 0xf);
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP, rd, bits - (m & max));
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, TCG_REG_TMP2, rd, (m & max));
+ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ }
}
-/* sw loop right shift
- */
static inline void tcg_out_rotr_Reg(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm)
{
- int bits = ext ? 64 : 32;
- //get TCG_REG_TMP=64-[rm]
+ unsigned int bits = ext ? 64 : 32;
tcg_out_insn_simpleImm(s, OPC_SUBL_I, TCG_REG_TMP, rm, bits);
- tcg_out_insn_bitReg(s, OPC_ORNOT, TCG_REG_TMP, TCG_REG_ZERO, TCG_REG_TMP);
+ tcg_out_insn_bitReg(s, OPC_SUBL, TCG_REG_TMP, TCG_REG_ZERO, TCG_REG_TMP);
- tcg_out_insn_bitReg(s, OPC_SLL, TCG_REG_TMP2, rn, TCG_REG_TMP); //get rn right part to TCG_REG_TMP
- tcg_out_insn_bitReg(s, OPC_SRL, TCG_REG_TMP, rn, rm); //get rn left part to TCG_REG_TMP
- tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2);
+ if (ext == TCG_TYPE_I64) {
+ tcg_out_insn_bitReg(s, OPC_SLL, TCG_REG_TMP2, rn, TCG_REG_TMP);
+ tcg_out_insn_bitReg(s, OPC_SRL, TCG_REG_TMP, rn, rm);
+ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2);
+ } else {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rn, 0xf);
+ tcg_out_insn_bitReg(s, OPC_SLL, TCG_REG_TMP2, rd, TCG_REG_TMP);
+ tcg_out_insn_bitReg(s, OPC_SRL, TCG_REG_TMP, rd, rm);
+ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ }
}
-/* sw
- * loop left shift
- */
static inline void tcg_out_rotl_Imm(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, unsigned int m)
{
- int bits = ext ? 64 : 32;
- int max = bits - 1;
+ unsigned int bits = ext ? 64 : 32;
+ unsigned int max = bits - 1;
+
+ if (ext == TCG_TYPE_I64) {
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, TCG_REG_TMP, rn, bits -(m & max));
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP2, rn, (m & max));
+ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2);
+ } else {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rn, 0xf);
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, TCG_REG_TMP, rd, bits -(m & max));
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, TCG_REG_TMP2, rd, (m & max));
+ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ }
+}
+
+static inline void tcg_out_rotl_Reg(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm)
+{
+ unsigned int bits = ext ? 64 : 32;
+ tcg_out_insn_simpleImm(s, OPC_SUBL_I, TCG_REG_TMP, rm, bits);
+ tcg_out_insn_bitReg(s, OPC_SUBL, TCG_REG_TMP, TCG_REG_ZERO, TCG_REG_TMP);
+
+ if (ext == TCG_TYPE_I64) {
+ tcg_out_insn_bitReg(s, OPC_SRL, TCG_REG_TMP2, rn, TCG_REG_TMP);
+ tcg_out_insn_bitReg(s, OPC_SLL, TCG_REG_TMP, rn, rm);
+ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2);
+ } else {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rn, 0xf);
+ tcg_out_insn_bitReg(s, OPC_SRL, TCG_REG_TMP2, rd, TCG_REG_TMP);
+ tcg_out_insn_bitReg(s, OPC_SLL, TCG_REG_TMP, rd, rm);
+ tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, rd, rd, 0xf);
+ }
+}
+
+#ifdef CONFIG_SOFTMMU
+#include "../tcg-ldst.c.inc"
+
+static void * const qemu_ld_helpers[(MO_SIZE | MO_BSWAP) + 1] = {
+ [MO_UB] = helper_ret_ldub_mmu,
+ [MO_LEUW] = helper_le_lduw_mmu,
+ [MO_LEUL] = helper_le_ldul_mmu,
+ [MO_LEQ] = helper_le_ldq_mmu,
+ [MO_BEUW] = helper_be_lduw_mmu,
+ [MO_BEUL] = helper_be_ldul_mmu,
+ [MO_BEQ] = helper_be_ldq_mmu,
+};
+
+static void * const qemu_st_helpers[(MO_SIZE | MO_BSWAP) + 1] = {
+ [MO_UB] = helper_ret_stb_mmu,
+ [MO_LEUW] = helper_le_stw_mmu,
+ [MO_LEUL] = helper_le_stl_mmu,
+ [MO_LEQ] = helper_le_stq_mmu,
+ [MO_BEUW] = helper_be_stw_mmu,
+ [MO_BEUL] = helper_be_stl_mmu,
+ [MO_BEQ] = helper_be_stq_mmu,
+};
+
+static inline void tcg_out_adr(TCGContext *s, TCGReg rd, const void *target)
+{
+ ptrdiff_t offset = tcg_pcrel_diff(s, target);
+ tcg_debug_assert(offset == sextract64(offset, 0, 21));
+ tcg_out_insn_br(s, OPC_BR, rd, 0);
+ tcg_out_insn_simpleImm(s, OPC_SUBL_I, rd, rd, 4);
+ if (offset >= 0) {
+ tcg_out_simple(s, OPC_ADDL_I, OPC_ADDL, rd, rd, offset);
+ } else {
+ tcg_out_simple(s, OPC_SUBL_I, OPC_SUBL, rd, rd, -offset);
+ }
+}
+
+static bool tcg_out_qemu_ld_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
+{
+ MemOpIdx oi = lb->oi;
+ MemOp opc = get_memop(oi);
+ MemOp size = opc & MO_SIZE;
+
+ if (!reloc_pc21(lb->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
+ return false;
+ }
+
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X16, TCG_AREG0);
+ tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X17, lb->addrlo_reg);
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X18, oi);
+ tcg_out_adr(s, TCG_REG_X19, lb->raddr);
+ tcg_out_call(s, qemu_ld_helpers[opc & (MO_BSWAP | MO_SIZE)]);
+ if (opc & MO_SIGN) {
+ tcg_out_sxt(s, lb->type, size, lb->datalo_reg, TCG_REG_X0);
+ } else {
+ tcg_out_mov(s, size == MO_64, lb->datalo_reg, TCG_REG_X0);
+ }
+
+ tcg_out_goto(s, lb->raddr);
+ return true;
+}
+
+static bool tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *lb)
+{
+ MemOpIdx oi = lb->oi;
+ MemOp opc = get_memop(oi);
+ MemOp size = opc & MO_SIZE;
+
+ if (!reloc_pc21(lb->label_ptr[0], tcg_splitwx_to_rx(s->code_ptr))) {
+ return false;
+ }
+
+ tcg_out_mov(s, TCG_TYPE_PTR, TCG_REG_X16, TCG_AREG0);
+ tcg_out_mov(s, TARGET_LONG_BITS == 64, TCG_REG_X17, lb->addrlo_reg);
+ tcg_out_mov(s, size == MO_64, TCG_REG_X18, lb->datalo_reg);
+ tcg_out_movi(s, TCG_TYPE_I32, TCG_REG_X19, oi);
+ tcg_out_adr(s, TCG_REG_X20, lb->raddr);
+ tcg_out_call(s, qemu_st_helpers[opc & (MO_BSWAP | MO_SIZE)]);
+ tcg_out_goto(s, lb->raddr);
+ return true;
+}
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP, rn, bits -(m & max));
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_REG_TMP2, rn, (m & max)); //get rn left part to TCG_REG_TMP
- tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2); //get rn right part to left
+static void add_qemu_ldst_label(TCGContext *s, bool is_ld, MemOpIdx oi,
+ TCGType ext, TCGReg data_reg, TCGReg addr_reg,
+ tcg_insn_unit *raddr, tcg_insn_unit *label_ptr)
+{
+ TCGLabelQemuLdst *label = new_ldst_label(s);
+
+ label->is_ld = is_ld;
+ label->oi = oi;
+ label->type = ext;
+ label->datalo_reg = data_reg;
+ label->addrlo_reg = addr_reg;
+ label->raddr = tcg_splitwx_to_rx(raddr);
+ label->label_ptr[0] = label_ptr;
}
+/* We expect to use a 7-bit scaled negative offset from ENV. */
+QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) > 0);
+QEMU_BUILD_BUG_ON(TLB_MASK_TABLE_OFS(0) < -512);
+
+/* These offsets are built into the LDP below. */
+QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, mask) != 0);
+QEMU_BUILD_BUG_ON(offsetof(CPUTLBDescFast, table) != 8);
-/* sw loop left shift
+/*
+ * Load and compare a TLB entry, emitting the conditional jump to the
+ * slow path for the failure case, which will be patched later when finalizing
+ * the slow path. Generated code returns the host addend in X1,
+ * clobbers X0,X2,X3,TMP.
*/
-static inline void tcg_out_rotl_Reg(TCGContext *s, TCGType ext, TCGReg rd, TCGReg rn, TCGReg rm)
+static void tcg_out_tlb_read(TCGContext *s, TCGReg addr_reg, MemOp opc,
+ tcg_insn_unit **label_ptr, int mem_index,
+ bool is_read)
+{
+ unsigned a_bits = get_alignment_bits(opc);
+ unsigned s_bits = opc & MO_SIZE;
+ unsigned a_mask = (1u << a_bits) - 1;
+ unsigned s_mask = (1u << s_bits) - 1;
+ TCGReg x3;
+ TCGType mask_type;
+ uint64_t compare_mask;
+
+ mask_type = (TARGET_PAGE_BITS + CPU_TLB_DYN_MAX_BITS > 32
+ ? TCG_TYPE_I64 : TCG_TYPE_I32);
+
+ /* Load env_tlb(env)->f[mmu_idx].{mask,table} into {x0,x1}. */
+ tcg_out_insn_ldst(s, OPC_LDL, TCG_REG_X0, TCG_AREG0, TLB_MASK_TABLE_OFS(mem_index));
+ tcg_out_insn_ldst(s, OPC_LDL, TCG_REG_X1, TCG_AREG0, TLB_MASK_TABLE_OFS(mem_index)+8);
+
+ /* Extract the TLB index from the address into X0. */
+ if (mask_type == TCG_TYPE_I64) {
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, TCG_REG_TMP, addr_reg, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
+ tcg_out_insn_bitReg(s, OPC_AND, TCG_REG_X0, TCG_REG_X0, TCG_REG_TMP);
+ } else {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_REG_TMP, addr_reg, 0xf);
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, TCG_REG_TMP, TCG_REG_TMP, TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
+ tcg_out_insn_bitReg(s, OPC_AND, TCG_REG_X0, TCG_REG_X0, TCG_REG_TMP);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_REG_X0, TCG_REG_X0, 0xf);
+ }
+ /* Add the tlb_table pointer, creating the CPUTLBEntry address into X1. */
+ tcg_out_insn_simpleReg(s, OPC_ADDL, TCG_REG_X1, TCG_REG_X1, TCG_REG_X0);
+
+ /* Load the tlb comparator into X0, and the fast path addend into X1. */
+ tcg_out_ld(s, TCG_TYPE_TL, TCG_REG_X0, TCG_REG_X1, is_read
+ ? offsetof(CPUTLBEntry, addr_read)
+ : offsetof(CPUTLBEntry, addr_write));
+ tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_X1, TCG_REG_X1,
+ offsetof(CPUTLBEntry, addend));
+
+ /* For aligned accesses, we check the first byte and include the alignment
+ bits within the address. For unaligned access, we check that we don't
+ cross pages using the address of the last byte of the access. */
+ if (a_bits >= s_bits) {
+ x3 = addr_reg;
+ } else {
+ if (s_mask >= a_mask) {
+ tcg_out_simple(s, OPC_ADDL_I, OPC_ADDL, TCG_REG_X3, addr_reg, s_mask - a_mask);
+ } else {
+ tcg_out_simple(s, OPC_SUBL_I, OPC_SUBL, TCG_REG_X3, addr_reg, a_mask - s_mask);
+ }
+
+ if (TARGET_LONG_BITS != 64) {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_REG_X3, TCG_REG_X3, 0xf);
+ }
+ x3 = TCG_REG_X3;
+ }
+ compare_mask = (uint64_t)TARGET_PAGE_MASK | a_mask;
+
+ /* Store the page mask part of the address into X3. */
+ tcg_out_bit(s, OPC_AND_I, OPC_AND, TCG_REG_X3, x3, compare_mask);
+ if (TARGET_LONG_BITS != 64) {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_REG_X3, TCG_REG_X3, 0xf);
+ }
+
+ /* Perform the address comparison. */
+ tcg_out_cond_cmp(s, TARGET_LONG_BITS == 64, TCG_COND_NE, TCG_REG_TMP, TCG_REG_X0, TCG_REG_X3, 0);
+
+ /* If not equal, we jump to the slow path. */
+ *label_ptr = s->code_ptr;
+ tcg_out_insn_br(s, OPC_BGT, TCG_REG_TMP, 0);
+}
+
+#endif /* CONFIG_SOFTMMU */
+
+static void tcg_out_qemu_ld_direct(TCGContext *s, MemOp memop, TCGType ext,
+ TCGReg data_r, TCGReg addr_r,
+ TCGType otype, TCGReg off_r)
+{
+ if (otype == TCG_TYPE_I32) {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_REG_TMP, off_r, 0xf);
+ tcg_out_insn_simpleReg(s, OPC_ADDL, TCG_REG_TMP, addr_r, TCG_REG_TMP);
+ } else {
+ tcg_out_insn_simpleReg(s, OPC_ADDL, TCG_REG_TMP, addr_r, off_r);
+ }
+
+ const MemOp bswap = memop & MO_BSWAP;
+
+ switch (memop & MO_SSIZE) {
+ case MO_UB:
+ tcg_out_ldst(s, OPC_LDBU, data_r, TCG_REG_TMP, 0, zeroExt);
+ break;
+ case MO_SB:
+ tcg_out_ldst(s, OPC_LDBU, data_r, TCG_REG_TMP, 0, sigExt);
+ if (ext == TCG_TYPE_I32) {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, data_r, data_r, 0xf);
+ }
+ break;
+ case MO_UW:
+ tcg_out_ldst(s, OPC_LDHU, data_r, TCG_REG_TMP, 0, zeroExt);
+ if (bswap) {
+ tcg_out_bswap16(s, ext, data_r, data_r);
+ }
+ break;
+ case MO_SW:
+ if (bswap) {
+ tcg_out_ldst(s, OPC_LDHU, data_r, TCG_REG_TMP, 0, zeroExt);
+ tcg_out_bswap16(s, ext, data_r, data_r);
+ tcg_out_insn_simpleReg(s, OPC_SEXTH, data_r, TCG_REG_ZERO, data_r);
+ } else {
+ tcg_out_ldst(s, OPC_LDHU, data_r, TCG_REG_TMP, 0, sigExt);
+ }
+
+ if (ext == TCG_TYPE_I32) {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, data_r, data_r, 0xf);
+ }
+ break;
+ case MO_UL:
+ tcg_out_ldst(s, OPC_LDW, data_r, TCG_REG_TMP, 0, zeroExt);
+ if (bswap) {
+ tcg_out_bswap32(s, ext, data_r, data_r);
+ }
+ break;
+ case MO_SL:
+ if (bswap) {
+ tcg_out_ldst(s, OPC_LDW, data_r, TCG_REG_TMP, 0, zeroExt);
+ tcg_out_bswap32(s, ext, data_r, data_r);
+ tcg_out_insn_simpleReg(s, OPC_ADDW, data_r, data_r, TCG_REG_ZERO);
+ } else {
+ tcg_out_ldst(s, OPC_LDW, data_r, TCG_REG_TMP, 0, sigExt);
+ }
+ break;
+ case MO_Q:
+ tcg_out_ldst(s, OPC_LDL, data_r, TCG_REG_TMP, 0, zeroExt);
+ if (bswap) {
+ tcg_out_bswap64(s, ext, data_r, data_r);
+ }
+ break;
+ default:
+ tcg_abort();
+ }
+}
+
+static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, MemOpIdx oi, TCGType ext)
+{
+ MemOp memop = get_memop(oi);
+ const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64: TCG_TYPE_I32;
+#ifdef CONFIG_SOFTMMU
+ unsigned mem_index = get_mmuidx(oi);
+ tcg_insn_unit *label_ptr;
+
+ tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, mem_index, 1);
+ tcg_out_qemu_ld_direct(s, memop, ext, data_reg,
+ TCG_REG_X1, otype, addr_reg);
+ add_qemu_ldst_label(s, true, oi, ext, data_reg, addr_reg,
+ s->code_ptr, label_ptr);
+#else /* !CONFIG_SOFTMMU */
+ if (USE_GUEST_BASE) {
+ tcg_out_qemu_ld_direct(s, memop, ext, data_reg, TCG_REG_GUEST_BASE, otype, addr_reg);
+ } else {
+ tcg_out_qemu_ld_direct(s, memop, ext, data_reg, addr_reg, TCG_TYPE_I64, TCG_REG_ZERO);
+ }
+#endif /* CONFIG_SOFTMMU */
+}
+
+static void tcg_out_qemu_st_direct(TCGContext *s, MemOp memop,
+ TCGReg data_r, TCGReg addr_r,
+ TCGType otype, TCGReg off_r)
{
- int bits = ext ? 64 : 32;
- tcg_out_insn_simpleImm(s, OPC_SUBL_I, TCG_REG_TMP, rm, bits); //rm = 64-rm
- tcg_out_insn_bitReg(s, OPC_ORNOT, TCG_REG_TMP, TCG_REG_ZERO, TCG_REG_TMP);
+ if (otype == TCG_TYPE_I32) {
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_REG_TMP, off_r, 0xf);
+ tcg_out_insn_simpleReg(s, OPC_ADDL, TCG_REG_TMP, addr_r, TCG_REG_TMP);
+ } else {
+ tcg_out_insn_simpleReg(s, OPC_ADDL, TCG_REG_TMP, addr_r, off_r);
+ }
+
+ const MemOp bswap = memop & MO_BSWAP;
- tcg_out_insn_bitReg(s, OPC_SRL, TCG_REG_TMP2, rn, TCG_REG_TMP); //get rn left part to TCG_REG_TMP
- tcg_out_insn_bitReg(s, OPC_SLL, TCG_REG_TMP, rn, rm); //get rn right part to left
- tcg_out_insn_bitReg(s, OPC_BIS, rd, TCG_REG_TMP, TCG_REG_TMP2);
+ switch (memop & MO_SIZE) {
+ case MO_8:
+ tcg_out_ldst(s, OPC_STB, data_r, TCG_REG_TMP, 0, 0);
+ break;
+ case MO_16:
+ if (bswap && data_r != TCG_REG_ZERO) {
+ tcg_out_bswap16(s, TCG_TYPE_I32, TCG_REG_TMP3, data_r);
+ data_r = TCG_REG_TMP3;
+ }
+ tcg_out_ldst(s, OPC_STH, data_r, TCG_REG_TMP, 0, 0);
+ break;
+ case MO_32:
+ if (bswap && data_r != TCG_REG_ZERO) {
+ tcg_out_bswap32(s, TCG_TYPE_I32, TCG_REG_TMP3, data_r);
+ data_r = TCG_REG_TMP3;
+ }
+ tcg_out_ldst(s, OPC_STW, data_r, TCG_REG_TMP, 0, 0);
+ break;
+ case MO_64:
+ if (bswap && data_r != TCG_REG_ZERO) {
+ tcg_out_bswap64(s, TCG_TYPE_I64, TCG_REG_TMP3, data_r);
+ data_r = TCG_REG_TMP3;
+ }
+ tcg_out_ldst(s, OPC_STL, data_r, TCG_REG_TMP, 0, 0);
+ break;
+ default:
+ tcg_abort();
+ }
}
+static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
+ MemOpIdx oi)
+{
+ MemOp memop = get_memop(oi);
+ const TCGType otype = TARGET_LONG_BITS == 64 ? TCG_TYPE_I64: TCG_TYPE_I32;
+#ifdef CONFIG_SOFTMMU
+ unsigned mem_index = get_mmuidx(oi);
+ tcg_insn_unit *label_ptr;
+
+ tcg_out_tlb_read(s, addr_reg, memop, &label_ptr, mem_index, 0);
+ tcg_out_qemu_st_direct(s, memop, data_reg, TCG_REG_X1, otype, addr_reg);
+ add_qemu_ldst_label(s, false, oi, (memop & MO_SIZE)== MO_64, data_reg, addr_reg, s->code_ptr, label_ptr);
+#else /* !CONFIG_SOFTMMU */
+ if (USE_GUEST_BASE) {
+ tcg_out_qemu_st_direct(s, memop, data_reg, TCG_REG_GUEST_BASE, otype, addr_reg);
+ } else {
+ tcg_out_qemu_st_direct(s, memop, data_reg, addr_reg, TCG_TYPE_I64, TCG_REG_ZERO);
+ }
+#endif /* CONFIG_SOFTMMU */
+}
+static const tcg_insn_unit *tb_ret_addr;
-static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg args[TCG_MAX_OP_ARGS], const int const_args[TCG_MAX_OP_ARGS])
+static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg args[TCG_MAX_OP_ARGS],
+ const int const_args[TCG_MAX_OP_ARGS])
{
/* 99% of the time, we can signal the use of extension registers
- by looking to see if the opcode handles 64-bit data. */
+ * by looking to see if the opcode handles 64-bit data. */
TCGType ext = (tcg_op_defs[opc].flags & TCG_OPF_64BIT) != 0;
- /* Hoist the loads of the most common arguments. */
+ /* Hoist the loads of the most common arguments. */
TCGArg a0 = args[0];
TCGArg a1 = args[1];
TCGArg a2 = args[2];
int c2 = const_args[2];
/* Some operands are defined with "rZ" constraint, a register or
- the zero register. These need not actually test args[I] == 0. */
- #define REG0(I) (const_args[I] ? TCG_REG_ZERO : (TCGReg)args[I])
+ * the zero register. These need not actually test args[I] == 0. */
switch (opc) {
case INDEX_op_exit_tb:
- /* Reuse the zeroing that exists for goto_ptr. */
+ /* Reuse the zeroing that exists for goto_ptr. */
if (a0 == 0) {
tcg_out_goto_long(s, tcg_code_gen_epilogue);
} else {
@@ -1296,34 +1708,39 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg args[TCG_MAX_O
tcg_out_goto_long(s, tb_ret_addr);
}
break;
-
case INDEX_op_goto_tb:
if (s->tb_jmp_insn_offset != NULL) {
/* TCG_TARGET_HAS_direct_jump */
- tcg_debug_assert(0);
- /* not support here */
+ /* Ensure that ADRP+ADD are 8-byte aligned so that an atomic
+ write can be used to patch the target address. */
+ if ((uintptr_t)s->code_ptr & 7) {
+ tcg_out32(s, OPC_NOP);
+ }
+ s->tb_jmp_insn_offset[a0] = tcg_current_code_size(s);
+ tcg_out32(s, OPC_NOP);
+ tcg_out32(s, OPC_NOP);
} else {
/* !TCG_TARGET_HAS_direct_jump */
tcg_debug_assert(s->tb_jmp_target_addr != NULL);
tcg_out_ld(s, TCG_TYPE_PTR, TCG_REG_TMP, TCG_REG_ZERO, (uintptr_t)(s->tb_jmp_target_addr + a0));
}
- tcg_out_insn_jump(s, OPC_JMP, TCG_REG_ZERO, TCG_REG_TMP, 0);
+ tcg_out_insn_jump(s, OPC_JMP, TCG_REG_ZERO, TCG_REG_TMP, noPara);
set_jmp_reset_offset(s, a0);
break;
-
case INDEX_op_goto_ptr:
- tcg_out_insn_jump(s, OPC_JMP, TCG_REG_ZERO, a0, 0);
+ tcg_out_insn_jump(s, OPC_JMP, TCG_REG_ZERO, a0, noPara);
break;
-
case INDEX_op_br:
tcg_out_goto_label(s, arg_label(a0));
break;
-
case INDEX_op_ld8u_i32:
case INDEX_op_ld8u_i64:
tcg_out_ldst(s, OPC_LDBU, a0, a1, a2, 0);
break;
case INDEX_op_ld8s_i32:
+ tcg_out_ldst(s, OPC_LDBU, a0, a1, a2, 1);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
+ break;
case INDEX_op_ld8s_i64:
tcg_out_ldst(s, OPC_LDBU, a0, a1, a2, 1);
break;
@@ -1332,11 +1749,14 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg args[TCG_MAX_O
tcg_out_ldst(s, OPC_LDHU, a0, a1, a2, 0);
break;
case INDEX_op_ld16s_i32:
+ tcg_out_ldst(s, OPC_LDHU, a0, a1, a2, 1);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
+ break;
case INDEX_op_ld16s_i64:
tcg_out_ldst(s, OPC_LDHU, a0, a1, a2, 1);
break;
case INDEX_op_ld_i32:
- tcg_out_ldst(s, OPC_LDW, a0, a1, a2, 1);
+ tcg_out_ldst(s, OPC_LDW, a0, a1, a2, 0);
break;
case INDEX_op_ld32u_i64:
tcg_out_ldst(s, OPC_LDW, a0, a1, a2, 0);
@@ -1349,26 +1769,26 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg args[TCG_MAX_O
break;
case INDEX_op_st8_i32:
case INDEX_op_st8_i64:
- tcg_out_ldst(s, OPC_STB, a0, a1, a2, 0);
+ tcg_out_ldst(s, OPC_STB, REG0(0), a1, a2, 0);
break;
case INDEX_op_st16_i32:
case INDEX_op_st16_i64:
- tcg_out_ldst(s, OPC_STH, a0, a1, a2, 0);
+ tcg_out_ldst(s, OPC_STH, REG0(0), a1, a2, 0);
break;
case INDEX_op_st_i32:
case INDEX_op_st32_i64:
- tcg_out_ldst(s, OPC_STW, a0, a1, a2, 0);
+ tcg_out_ldst(s, OPC_STW, REG0(0), a1, a2, 0);
break;
case INDEX_op_st_i64:
- tcg_out_ldst(s, OPC_STL, a0, a1, a2, 0);
+ tcg_out_ldst(s, OPC_STL, REG0(0), a1, a2, 0);
break;
-
case INDEX_op_add_i32:
a2 = (int32_t)a2;
if (c2) {
tcg_out_addsubi(s, ext, a0, a1, a2);
} else {
- tcg_out_insn_simpleReg(s, OPC_ADDL, a0, a1, a2);
+ tcg_out_insn_simpleReg(s, OPC_ADDW, a0, a1, a2);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
}
break;
case INDEX_op_add_i64:
@@ -1378,13 +1798,13 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg args[TCG_MAX_O
tcg_out_insn_simpleReg(s, OPC_ADDL, a0, a1, a2);
}
break;
-
case INDEX_op_sub_i32:
a2 = (int32_t)a2;
if (c2) {
tcg_out_addsubi(s, ext, a0, a1, -a2);
} else {
- tcg_out_insn_simpleReg(s, OPC_SUBL, a0, a1, a2);
+ tcg_out_insn_simpleReg(s, OPC_SUBW, a0, a1, a2);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
}
break;
case INDEX_op_sub_i64:
@@ -1394,230 +1814,207 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg args[TCG_MAX_O
tcg_out_insn_simpleReg(s, OPC_SUBL, a0, a1, a2);
}
break;
-
- case INDEX_op_neg_i64:
case INDEX_op_neg_i32:
+ tcg_out_insn_bitReg(s, OPC_SUBW, a0, TCG_REG_ZERO, a1);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
+ break;
+ case INDEX_op_neg_i64:
tcg_out_insn_bitReg(s, OPC_SUBL, a0, TCG_REG_ZERO, a1);
break;
-
case INDEX_op_and_i32:
- a2 = (int32_t)a2;
if (c2) {
- tcg_out_insn_bit(s, OPC_AND_I, OPC_AND, a0, a1, a2);
+ a2 = (int32_t)a2;
+ tcg_out_bit(s, OPC_AND_I, OPC_AND, a0, a1, a2);
} else {
tcg_out_insn_bitReg(s, OPC_AND, a0, a1, a2);
}
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
break;
case INDEX_op_and_i64:
if (c2) {
- tcg_out_insn_bit(s, OPC_AND_I, OPC_AND, a0, a1, a2);
+ tcg_out_bit(s, OPC_AND_I, OPC_AND, a0, a1, a2);
} else {
tcg_out_insn_bitReg(s, OPC_AND, a0, a1, a2);
}
break;
case INDEX_op_andc_i32:
- a2 = (int32_t)a2;
- tcg_debug_assert(0);
- if (c2) {
- tcg_out_insn_bit(s, OPC_AND_I, OPC_AND, a0, a1, ~a2);
- } else {
- tcg_out_insn_bitReg(s, OPC_BIC, a0, a1, a2);
- }
- break;
case INDEX_op_andc_i64:
tcg_debug_assert(0);
- if (c2) {
- tcg_out_insn_bit(s, OPC_AND_I, OPC_AND, a0, a1, ~a2);
- } else {
- tcg_out_insn_bitReg(s, OPC_BIC, a0, a1, a2);
- }
break;
-
case INDEX_op_or_i32:
- a2 = (int32_t)a2;
if (c2) {
- tcg_out_insn_bit(s, OPC_BIS_I, OPC_BIS, a0, a1, a2);
+ a2 = (int32_t)a2;
+ tcg_out_bit(s, OPC_BIS_I, OPC_BIS, a0, a1, a2);
} else {
tcg_out_insn_bitReg(s, OPC_BIS, a0, a1, a2);
}
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
break;
case INDEX_op_or_i64:
if (c2) {
- tcg_out_insn_bit(s, OPC_BIS_I, OPC_BIS, a0, a1, a2);
+ tcg_out_bit(s, OPC_BIS_I, OPC_BIS, a0, a1, a2);
} else {
tcg_out_insn_bitReg(s, OPC_BIS, a0, a1, a2);
}
break;
-
case INDEX_op_orc_i32:
- a2 = (int32_t)a2;
- tcg_debug_assert(0);
if (c2) {
- tcg_out_insn_bit(s, OPC_BIS_I, OPC_BIS, a0, a1, ~a2);
+ a2 = (int32_t)a2;
+ tcg_out_bit(s, OPC_BIS_I, OPC_BIS, a0, a1, ~a2);
} else {
tcg_out_insn_bitReg(s, OPC_ORNOT, a0, a1, a2);
}
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
break;
case INDEX_op_orc_i64:
- tcg_debug_assert(0);
if (c2) {
- tcg_out_insn_bit(s, OPC_BIS_I, OPC_BIS, a0, a1, ~a2);
+ tcg_out_bit(s, OPC_BIS_I, OPC_BIS, a0, a1, ~a2);
} else {
tcg_out_insn_bitReg(s, OPC_ORNOT, a0, a1, a2);
}
break;
-
case INDEX_op_xor_i32:
- a2 = (int32_t)a2;
if (c2) {
- tcg_out_insn_bit(s, OPC_XOR_I, OPC_XOR, a0, a1, a2);
+ a2 = (int32_t)a2;
+ tcg_out_bit(s, OPC_XOR_I, OPC_XOR, a0, a1, a2);
} else {
tcg_out_insn_bitReg(s, OPC_XOR, a0, a1, a2);
}
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
break;
case INDEX_op_xor_i64:
if (c2) {
- tcg_out_insn_bit(s, OPC_XOR_I, OPC_XOR, a0, a1, a2);
+ tcg_out_bit(s, OPC_XOR_I, OPC_XOR, a0, a1, a2);
} else {
tcg_out_insn_bitReg(s, OPC_XOR, a0, a1, a2);
}
break;
-
case INDEX_op_eqv_i32:
- a2 = (int32_t)a2;
- tcg_debug_assert(0);
- if (c2) {
- tcg_out_insn_bit(s, OPC_XOR_I, OPC_XOR, a0, a1, ~a2);
- } else {
- tcg_out_insn_bitReg(s, OPC_EQV, a0, a1, a2);
- }
- break;
-
case INDEX_op_eqv_i64:
tcg_debug_assert(0);
- if (c2) {
- tcg_out_insn_bit(s, OPC_XOR_I, OPC_XOR, a0, a1, ~a2);
- } else {
- tcg_out_insn_bitReg(s, OPC_EQV, a0, a1, a2);
- }
break;
-
- case INDEX_op_not_i64:
case INDEX_op_not_i32:
tcg_out_insn_bitReg(s, OPC_ORNOT, a0, TCG_REG_ZERO, a1);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
+ break;
+ case INDEX_op_not_i64:
+ tcg_out_insn_bitReg(s, OPC_ORNOT, a0, TCG_REG_ZERO, a1);
break;
-
- case INDEX_op_mul_i64:
case INDEX_op_mul_i32:
- tcg_out_insn_simpleReg(s, OPC_MULL, a0, a1, a2);
+ tcg_out_insn_simpleReg(s, OPC_MULL, a0, a1, a2);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
+ break;
+ case INDEX_op_mul_i64:
+ tcg_out_insn_simpleReg(s, OPC_MULL, a0, a1, a2);
break;
-
- case INDEX_op_div_i64: /* a0=a1/a2 singed divide*/
case INDEX_op_div_i32:
+ case INDEX_op_div_i64:
tcg_debug_assert(0);
break;
- case INDEX_op_divu_i64: /* a0=a1/a2 unsigned divide */
case INDEX_op_divu_i32:
+ case INDEX_op_divu_i64:
tcg_debug_assert(0);
break;
-
- case INDEX_op_rem_i64: /* if a1=17,a2=4, 17/4=4...1, a0=1 */
case INDEX_op_rem_i32:
+ case INDEX_op_rem_i64:
tcg_debug_assert(0);
break;
- case INDEX_op_remu_i64:
case INDEX_op_remu_i32:
+ case INDEX_op_remu_i64:
tcg_debug_assert(0);
break;
-
- case INDEX_op_shl_i64:
case INDEX_op_shl_i32: /* sw logical left*/
if (c2) {
- int bits = ext ? 64 : 32;
- int max = bits - 1;
- tcg_out_insn_bitImm(s, OPC_SLL_I, a0, a1, a2&max);
+ unsigned int bits = ext ? 64 : 32;
+ unsigned int max = bits - 1;
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, a0, a1, a2&max);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
+ } else {
+ tcg_out_insn_bitReg(s, OPC_SLL, a0, a1, a2);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
+ }
+ break;
+ case INDEX_op_shl_i64:
+ if (c2) {
+ unsigned int bits = ext ? 64 : 32;
+ unsigned int max = bits - 1;
+ tcg_out_insn_simpleImm(s, OPC_SLL_I, a0, a1, a2&max);
} else {
tcg_out_insn_bitReg(s, OPC_SLL, a0, a1, a2);
}
break;
-
- case INDEX_op_shr_i64:
case INDEX_op_shr_i32: /* sw logical right */
+ a2 = (int32_t)a2;
if (c2) {
int bits = ext ? 64 : 32;
int max = bits - 1;
- tcg_out_insn_bitImm(s, OPC_SRL_I, a0, a1, a2&max);
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, a0, a1, a2&max);
} else {
tcg_out_insn_bitReg(s, OPC_SRL, a0, a1, a2);
}
break;
-
- case INDEX_op_sar_i64:
- case INDEX_op_sar_i32: /* sw arithmetic right*/
+ case INDEX_op_shr_i64:
if (c2) {
int bits = ext ? 64 : 32;
int max = bits - 1;
- tcg_out_insn_bitImm(s, OPC_SRA_I, a0, a1, a2&max);
+ tcg_out_insn_simpleImm(s, OPC_SRL_I, a0, a1, a2&max);
} else {
- tcg_out_insn_bitReg(s, OPC_SRA, a0, a1, a2);
+ tcg_out_insn_bitReg(s, OPC_SRL, a0, a1, a2);
}
break;
-
- case INDEX_op_rotr_i64:
+ case INDEX_op_sar_i32:
+ a2 = (int32_t)a2;
+ tcg_out_sar(s, ext, a0, a1, a2, c2);
+ break;
+ case INDEX_op_sar_i64: /* sw arithmetic right*/
+ tcg_out_sar(s, ext, a0, a1, a2, c2);
+ break;
case INDEX_op_rotr_i32: /* loop shift */
+ case INDEX_op_rotr_i64:
if (c2) {/* loop right shift a2*/
tcg_out_rotr_Imm(s, ext, a0, a1, a2);
} else {
tcg_out_rotr_Reg(s, ext, a0, a1, a2);
}
break;
-
- case INDEX_op_rotl_i64:
case INDEX_op_rotl_i32: /* loop shift */
+ case INDEX_op_rotl_i64: /* sw */
if (c2) {/* loop left shift a2*/
tcg_out_rotl_Imm(s, ext, a0, a1, a2);
} else {
tcg_out_rotl_Reg(s, ext, a0, a1, a2);
}
break;
-
- case INDEX_op_clz_i64: /* counting leading zero numbers */
case INDEX_op_clz_i32:
- tcg_out_cltz(s, OPC_CTLZ, ext, a0, a1, a2, c2);
+ tcg_out_ctz32(s, OPC_CTLZ, a0, a1, a2, c2);
+ break;
+ case INDEX_op_clz_i64: /* counting leading zero numbers */
+ tcg_out_ctz64(s, OPC_CTLZ, a0, a1, a2, c2);
break;
- case INDEX_op_ctz_i64: /* counting tailing zero numbers */
case INDEX_op_ctz_i32:
- tcg_out_cltz(s, OPC_CTTZ, ext, a0, a1, a2, c2);
+ tcg_out_ctz32(s, OPC_CTTZ, a0, a1, a2, c2);
break;
-
- case INDEX_op_brcond_i32:
- a1 = (int32_t)a1;
- tcg_out_brcond(s, ext, a2, a0, a1, const_args[1], arg_label(args[3]));
+ case INDEX_op_ctz_i64: /* counting tailing zero numbers */
+ tcg_out_ctz64(s, OPC_CTTZ, a0, a1, a2, c2);
break;
-
+ case INDEX_op_brcond_i32:
case INDEX_op_brcond_i64:
tcg_out_brcond(s, ext, a2, a0, a1, const_args[1], arg_label(args[3]));
break;
-
case INDEX_op_setcond_i32:
a2 = (int32_t)a2;
- tcg_out_setcond(s, args[3], a0, a1, a2);
+ tcg_out_setcond(s, ext, args[3], a0, a1, a2, c2);
break;
-
case INDEX_op_setcond_i64:
- tcg_out_setcond(s, args[3], a0, a1, a2);
+ tcg_out_setcond(s, ext, args[3], a0, a1, a2, c2);
break;
-
case INDEX_op_movcond_i32:
a2 = (int32_t)a2;
- tcg_out_movcond(s, args[5], a0, a1, a2, c2, REG0(3), REG0(4));
+ tcg_out_movcond(s, ext, args[5], a0, a1, a2, c2, REG0(3), REG0(4));
break;
-
- /* FALLTHRU */
case INDEX_op_movcond_i64:
- tcg_out_movcond(s, args[5], a0, a1, a2, c2, REG0(3), REG0(4));
+ tcg_out_movcond(s, ext, args[5], a0, a1, a2, c2, REG0(3), REG0(4));
break;
-
case INDEX_op_qemu_ld_i32:
case INDEX_op_qemu_ld_i64:
tcg_out_qemu_ld(s, a0, a1, a2, ext);
@@ -1626,443 +2023,399 @@ static void tcg_out_op(TCGContext *s, TCGOpcode opc, const TCGArg args[TCG_MAX_O
case INDEX_op_qemu_st_i64:
tcg_out_qemu_st(s, REG0(0), a1, a2);
break;
-
- case INDEX_op_bswap64_i64: /* 0x123456789abcdef--->0xefcdab8967452301 */
- tcg_debug_assert(0);
- tcg_out_bswap64(s, a0, a1);
- break;
- case INDEX_op_bswap32_i64: /* 0x123456789abcdef--->0x67452301efcdab89 */
- tcg_debug_assert(0);
- tcg_out_bswap32u(s, a0, a1);
+ case INDEX_op_bswap64_i64:
+ tcg_out_bswap64(s, ext, a0, a1);
break;
case INDEX_op_bswap32_i32:
- tcg_debug_assert(0);
+ case INDEX_op_bswap32_i64:
+ tcg_out_bswap32(s, ext, a0, a1);
break;
- case INDEX_op_bswap16_i64: /* 0x123456789abcdef--->0x23016745ab89efcd */
case INDEX_op_bswap16_i32:
- tcg_debug_assert(0);
+ case INDEX_op_bswap16_i64:
+ tcg_out_bswap16(s, ext, a0, a1);
break;
-
- case INDEX_op_ext8s_i64:
case INDEX_op_ext8s_i32:
+ tcg_out_insn_simpleReg(s, OPC_SEXTB, a0, TCG_REG_ZERO, a1);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
+ break;
+ case INDEX_op_ext8s_i64:
tcg_out_insn_simpleReg(s, OPC_SEXTB, a0, TCG_REG_ZERO, a1);
break;
- case INDEX_op_ext16s_i64:
case INDEX_op_ext16s_i32:
+ tcg_out_insn_simpleReg(s, OPC_SEXTH, a0, TCG_REG_ZERO, a1);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a0, 0xf);
+ break;
+ case INDEX_op_ext16s_i64:
tcg_out_insn_simpleReg(s, OPC_SEXTH, a0, TCG_REG_ZERO, a1);
break;
case INDEX_op_ext_i32_i64:
case INDEX_op_ext32s_i64:
tcg_out_insn_simpleReg(s, OPC_ADDW, a0, TCG_REG_ZERO, a1);
break;
- case INDEX_op_ext8u_i64:
case INDEX_op_ext8u_i32:
- tcg_out_insn_simpleImm(s, OPC_EXT0B_I, a0, a1, 0x0);
+ case INDEX_op_ext8u_i64:
+ tcg_out_insn_simpleImm(s, OPC_EXTLB_I, a0, a1, 0x0);
break;
- case INDEX_op_ext16u_i64:
case INDEX_op_ext16u_i32:
- tcg_out_insn_simpleImm(s, OPC_EXT1B_I, a0, a1, 0x0);
+ case INDEX_op_ext16u_i64:
+ tcg_out_insn_simpleImm(s, OPC_EXTLH_I, a0, a1, 0x0);
break;
case INDEX_op_extu_i32_i64:
case INDEX_op_ext32u_i64:
- tcg_out_movr(s, TCG_TYPE_I32, a0, a1);
+ tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, a0, a1, 0xf);
break;
-
- case INDEX_op_deposit_i64:
case INDEX_op_deposit_i32:
- tcg_out_dep(s, a0, a2, args[3], args[4]);
+ case INDEX_op_deposit_i64:
+ tcg_out_dep(s, ext, a0, REG0(2), args[3], args[4]);
break;
-
- case INDEX_op_extract_i64:
case INDEX_op_extract_i32:
+ case INDEX_op_extract_i64:
tcg_out_extract(s, a0, a1, a2, args[3]);
break;
-
- case INDEX_op_sextract_i64:
case INDEX_op_sextract_i32:
+ case INDEX_op_sextract_i64:
+ tcg_debug_assert(0);
+ break;
+ case INDEX_op_extract2_i32: /* extract REG0(2) right args[3] bit to REG0(1) left ,save to a0*/
+ case INDEX_op_extract2_i64:
+ tcg_debug_assert(0);
+ break;
+ case INDEX_op_add2_i32:
+ case INDEX_op_add2_i64:
+ tcg_debug_assert(0);
+ break;
+ case INDEX_op_sub2_i32:
+ case INDEX_op_sub2_i64:
tcg_debug_assert(0);
break;
+ case INDEX_op_muluh_i64:
+ tcg_out_insn_simpleReg(s, OPC_UMULH, a0, a1, a2);
+ break;
+ case INDEX_op_mulsh_i64:
+ tcg_out_mulsh64(s, a0, a1, a2);
+ break;
+ case INDEX_op_mb:
+ tcg_out_mb(s);
+ break;
+ case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
+ break;
+ case INDEX_op_mov_i64:
+ break;
+ case INDEX_op_call: /* Always emitted via tcg_out_call. */
+ default:
+ g_assert_not_reached();
+ }
+#undef REG0
+}
+static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
+{
+ switch (op) {
+ case INDEX_op_goto_ptr:
+ return C_O0_I1(r);
+ case INDEX_op_ld8u_i32:
+ case INDEX_op_ld8s_i32:
+ case INDEX_op_ld16u_i32:
+ case INDEX_op_ld16s_i32:
+ case INDEX_op_ld_i32:
+ case INDEX_op_ld8u_i64:
+ case INDEX_op_ld8s_i64:
+ case INDEX_op_ld16u_i64:
+ case INDEX_op_ld16s_i64:
+ case INDEX_op_ld32u_i64:
+ case INDEX_op_ld32s_i64:
+ case INDEX_op_ld_i64:
+ case INDEX_op_neg_i32:
+ case INDEX_op_neg_i64:
+ case INDEX_op_not_i32:
+ case INDEX_op_not_i64:
+ case INDEX_op_bswap16_i32:
+ case INDEX_op_bswap32_i32:
+ case INDEX_op_bswap16_i64:
+ case INDEX_op_bswap32_i64:
+ case INDEX_op_bswap64_i64:
+ case INDEX_op_ext8s_i32:
+ case INDEX_op_ext16s_i32:
+ case INDEX_op_ext8u_i32:
+ case INDEX_op_ext16u_i32:
+ case INDEX_op_ext8s_i64:
+ case INDEX_op_ext16s_i64:
+ case INDEX_op_ext32s_i64:
+ case INDEX_op_ext8u_i64:
+ case INDEX_op_ext16u_i64:
+ case INDEX_op_ext32u_i64:
+ case INDEX_op_ext_i32_i64:
+ case INDEX_op_extu_i32_i64:
+ case INDEX_op_extract_i32:
+ case INDEX_op_extract_i64:
+ case INDEX_op_sextract_i32:
+ case INDEX_op_sextract_i64:
+ return C_O1_I1(r, r);
+ case INDEX_op_st8_i32:
+ case INDEX_op_st16_i32:
+ case INDEX_op_st_i32:
+ case INDEX_op_st8_i64:
+ case INDEX_op_st16_i64:
+ case INDEX_op_st32_i64:
+ case INDEX_op_st_i64:
+ return C_O0_I2(rZ, r);
+ case INDEX_op_add_i32:
+ case INDEX_op_add_i64:
+ case INDEX_op_sub_i32:
+ case INDEX_op_sub_i64:
+ return C_O1_I2(r, r, rU);
+ case INDEX_op_setcond_i32:
+ case INDEX_op_setcond_i64:
+ return C_O1_I2(r, r, rU);
+ case INDEX_op_mul_i32:
+ case INDEX_op_mul_i64:
+ case INDEX_op_div_i32:
+ case INDEX_op_div_i64:
+ case INDEX_op_divu_i32:
+ case INDEX_op_divu_i64:
+ case INDEX_op_rem_i32:
+ case INDEX_op_rem_i64:
+ case INDEX_op_remu_i32:
+ case INDEX_op_remu_i64:
+ case INDEX_op_muluh_i64:
+ case INDEX_op_mulsh_i64:
+ return C_O1_I2(r, r, r);
+ case INDEX_op_and_i32:
+ case INDEX_op_and_i64:
+ case INDEX_op_or_i32:
+ case INDEX_op_or_i64:
+ case INDEX_op_xor_i32:
+ case INDEX_op_xor_i64:
+ case INDEX_op_andc_i32:
+ case INDEX_op_andc_i64:
+ case INDEX_op_orc_i32:
+ case INDEX_op_orc_i64:
+ case INDEX_op_eqv_i32:
+ case INDEX_op_eqv_i64:
+ return C_O1_I2(r, r, rU);
+ case INDEX_op_shl_i32:
+ case INDEX_op_shr_i32:
+ case INDEX_op_sar_i32:
+ case INDEX_op_rotl_i32:
+ case INDEX_op_rotr_i32:
+ case INDEX_op_shl_i64:
+ case INDEX_op_shr_i64:
+ case INDEX_op_sar_i64:
+ case INDEX_op_rotl_i64:
+ case INDEX_op_rotr_i64:
+ return C_O1_I2(r, r, ri);
+ case INDEX_op_clz_i32:
+ case INDEX_op_clz_i64:
+ return C_O1_I2(r, r, r);
+ case INDEX_op_ctz_i32:
+ case INDEX_op_ctz_i64:
+ return C_O1_I2(r, r, r);
+ case INDEX_op_brcond_i32:
+ case INDEX_op_brcond_i64:
+ return C_O0_I2(r, rU);
+ case INDEX_op_movcond_i32:
+ case INDEX_op_movcond_i64:
+ return C_O1_I4(r, r, rU, rZ, rZ);
+ case INDEX_op_qemu_ld_i32:
+ case INDEX_op_qemu_ld_i64:
+ return C_O1_I1(r, l);
+ case INDEX_op_qemu_st_i32:
+ case INDEX_op_qemu_st_i64:
+ return C_O0_I2(lZ, l);
+ case INDEX_op_deposit_i32:
+ case INDEX_op_deposit_i64:
+ return C_O1_I2(r, 0, rZ);
+ case INDEX_op_extract2_i32:
case INDEX_op_extract2_i64:
- case INDEX_op_extract2_i32: /* extract REG0(2) right args[3] bit to REG0(1) left ,save to a0*/
- tcg_debug_assert(0);
- break;
-
+ return C_O1_I2(r, rZ, rZ);
case INDEX_op_add2_i32:
- tcg_debug_assert(0);
- break;
case INDEX_op_add2_i64:
- tcg_debug_assert(0);
- break;
case INDEX_op_sub2_i32:
- tcg_debug_assert(0);
- break;
case INDEX_op_sub2_i64:
- tcg_debug_assert(0);
- break;
-
- case INDEX_op_muluh_i64:
- tcg_out_insn_simpleReg(s, OPC_UMULH, a0, a1, a2);
- break;
- case INDEX_op_mulsh_i64: /* sw not support */
- tcg_out_mulsh64(s, a0, a1, a2);
- break;
-
- case INDEX_op_mb:
- break;
-
- case INDEX_op_mov_i32: /* Always emitted via tcg_out_mov. */
- case INDEX_op_mov_i64:
- case INDEX_op_call: /* Always emitted via tcg_out_call. */
+ return C_O2_I4(r, r, rZ, rZ, rA, rMZ);
+ case INDEX_op_add_vec:
+ case INDEX_op_sub_vec:
+ case INDEX_op_mul_vec:
+ case INDEX_op_xor_vec:
+ case INDEX_op_ssadd_vec:
+ case INDEX_op_sssub_vec:
+ case INDEX_op_usadd_vec:
+ case INDEX_op_ussub_vec:
+ case INDEX_op_smax_vec:
+ case INDEX_op_smin_vec:
+ case INDEX_op_umax_vec:
+ case INDEX_op_umin_vec:
+ case INDEX_op_shlv_vec:
+ case INDEX_op_shrv_vec:
+ case INDEX_op_sarv_vec:
+ return C_O1_I2(w, w, w);
+ case INDEX_op_not_vec:
+ case INDEX_op_neg_vec:
+ case INDEX_op_abs_vec:
+ case INDEX_op_shli_vec:
+ case INDEX_op_shri_vec:
+ case INDEX_op_sari_vec:
+ return C_O1_I1(w, w);
+ case INDEX_op_ld_vec:
+ case INDEX_op_dupm_vec:
+ return C_O1_I1(w, r);
+ case INDEX_op_st_vec:
+ return C_O0_I2(w, r);
+ case INDEX_op_dup_vec:
+ return C_O1_I1(w, wr);
+ case INDEX_op_or_vec:
+ case INDEX_op_andc_vec:
+ return C_O1_I2(w, w, wO);
+ case INDEX_op_and_vec:
+ case INDEX_op_orc_vec:
+ return C_O1_I2(w, w, wN);
+ case INDEX_op_cmp_vec:
+ return C_O1_I2(w, w, wZ);
+ case INDEX_op_bitsel_vec:
+ return C_O1_I3(w, w, w, w);
default:
g_assert_not_reached();
}
-
-#undef REG0
}
-
-/*sw
-* counting heading/tailing zero numbers
-*/
-static void tcg_out_cltz(TCGContext *s, SW_64Insn opc_clz, TCGType ext, TCGReg rd,
- TCGReg rn, TCGArg b, bool const_b)
-{
- /* cond1. b is a const, and b=64 or b=32 */
- if (const_b && b == (ext ? 64 : 32)) {
- /* count rn zero numbers, and writes to rd */
- tcg_out_insn_simpleReg(s, opc_clz, rd, TCG_REG_ZERO, rn);
- }else {
- /* TCG_REG_TMP= counting rn heading/tailing zero numbers */
- tcg_out_insn_simpleReg(s, opc_clz, TCG_REG_TMP, TCG_REG_ZERO, rn);
-
- if (const_b) {
- if (b == -1) {
- /* cond2. b is const and b=-1 */
- /* if rn != 0 , rd= counting rn heading/tailing zero numbers, else rd = 0xffffffffffffffff*/
- tcg_out_insn_bitReg(s, OPC_ORNOT, TCG_REG_TMP2, TCG_REG_ZERO, TCG_REG_ZERO);
- tcg_out_insn_complexReg(s, OPC_SELNE, rn, rd, TCG_REG_TMP, TCG_REG_TMP2);
- }
- else if (b == 0) {
- /* cond3. b is const and b=0 */
- /* if rn != 0 , rd=counting rn heading/tailing zero numbers , else rd = TCG_REG_ZERO */
- tcg_out_insn_complexReg(s, OPC_SELNE, rn, rd, TCG_REG_TMP, TCG_REG_ZERO);
- } else {
- /* cond4. b is const */
- tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_TMP2, b);
- /* if rn != 0 , rd=counting rn heading/tailing zero numbers , else mov b to rd */
- tcg_out_insn_complexReg(s, OPC_SELNE, rn, rd, TCG_REG_TMP, TCG_REG_TMP2);
- }
- }
- else {
- /* if b is register */
- tcg_out_insn_complexReg(s, OPC_SELNE, rn, rd, TCG_REG_TMP, b);
- }
- }
-}
-
-/*sw
- * unsigned 16bit, ab->ba
- */
-static inline void tcg_out_bswap16u(TCGContext *s, TCGReg rd, TCGReg rn)
+static void tcg_target_init(TCGContext *s)
{
- TCGReg TCG_TMP0 = rn;
- TCGReg TCG_TMP1 = rd;
- /*t1=00b0*/
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP1, TCG_TMP0, 8);
- /*t1=(0000)000a*/
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP0, TCG_TMP0, 8);
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP0, TCG_TMP0, 0x1);
- /*t1=ooba*/
- tcg_out_insn_simpleReg(s, OPC_BIS, TCG_TMP1, TCG_TMP1, TCG_TMP0);
-}
+ tcg_target_available_regs[TCG_TYPE_I32] = 0xffffffffu;
+ tcg_target_available_regs[TCG_TYPE_I64] = 0xffffffffu;
+ tcg_target_available_regs[TCG_TYPE_V64] = 0xffffffff00000000ull;
+ tcg_target_available_regs[TCG_TYPE_V128] = 0xffffffff00000000ull;
+ tcg_target_call_clobber_regs = -1ull;
-/*sw
- * signed 16bit, ab->ssba
- */
-static inline void tcg_out_bswap16s(TCGContext *s, TCGReg rd, TCGReg rn)
-{
- TCGReg TCG_TMP0 = rn;
- TCGReg TCG_TMP1 = TCG_REG_TMP;
- TCGReg TCG_TMP2 = rn;
- /*t1=(ssss)ssb0*/
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP1, TCG_TMP0, 8);
- tcg_out_insn_simpleImm(s, OPC_ZAP_I, TCG_TMP1, TCG_TMP1, 0x2);
- tcg_out_insn_simpleReg(s, OPC_SEXTH, TCG_TMP1, TCG_REG_ZERO, TCG_TMP1);
- /*t2=(0000)000a*/
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP2, TCG_TMP0, 8);
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP2, TCG_TMP2, 0x1);
- /*t2=(ssss)ssba*/
- tcg_out_insn_simpleReg(s, OPC_BIS, TCG_TMP1, TCG_TMP1, TCG_TMP2);
-}
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X9);
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X10);
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X11);
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X12);
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X13);
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X14);
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_X15);
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F2);
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F3);
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F4);
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F5);
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F6);
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F7);
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F8);
+ tcg_regset_reset_reg(tcg_target_call_clobber_regs, TCG_REG_F9);
-/*sw
- * signed 32bit, abcd -> ssdcba
- */
-static inline void tcg_out_bswap32s(TCGContext *s, TCGReg rd, TCGReg rn)
-{
- TCGReg TCG_TMP0 = rn;
- TCGReg TCG_TMP3 = rd;
- TCGReg TCG_TMP1 = TCG_REG_TMP;
- TCGReg TCG_TMP2 = TCG_REG_TMP2;
- /*swap32 -- 32-bit swap. a0 = abcd.*/
-
- /* t3 = (ssss)d000 */
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP3, TCG_TMP0, 24);
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP3, TCG_TMP3, 0x0f);
- tcg_out_insn_simpleReg(s, OPC_SEXTB, TCG_TMP1, TCG_REG_ZERO, TCG_TMP0);
- tcg_out_insn_simpleImm(s, OPC_ZAP_I, TCG_TMP1, TCG_TMP1, 0x0f);
- tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1);
-
- /* t1 = 000a */
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP1, TCG_TMP0, 24);
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP1, 0x1);
-
- /* t2 = 00c0 */
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP2, TCG_TMP0, 0x2);
-
- /* t3 = (ssss)d00a */
- tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1);
-
- /* t1 = 0abc */
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP1, TCG_TMP0, 8);
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP1, 0x7);
-
- /* t2 = 0c00 */
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP2, TCG_TMP2, 8);
- /* t1 = 00b0 */
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP1, 0x2);
- /* t3 = (ssss)dc0a */
- tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP2);
- /* t3 = (ssss)dcba -- delay slot */
- tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1);
+ s->reserved_regs = 0;
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_SP);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_FP);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP2);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_TMP3);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_RA);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_X29);
+ tcg_regset_set_reg(s->reserved_regs, TCG_FLOAT_TMP);
+ tcg_regset_set_reg(s->reserved_regs, TCG_FLOAT_TMP2);
}
-/*sw
- * unsigned 32bit, abcd->dcba
- */
-static void tcg_out_bswap32u(TCGContext *s, TCGReg rd, TCGReg rn)
-{
- TCGReg TCG_TMP0 = rn;
- TCGReg TCG_TMP3 = rd;
- TCGReg TCG_TMP1 = TCG_REG_TMP;
- TCGReg TCG_TMP2 = TCG_REG_TMP2;
-
- /*bswap32u -- unsigned 32-bit swap. a0 = ....abcd.*/
- /* t1 = (0000)000d */
- tcg_out_insn_bitImm(s, OPC_AND_I, TCG_TMP1, TCG_TMP0, 0xff);
- /* t3 = 000a */
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP3, TCG_TMP0, 24);
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP3, TCG_TMP3, 0x1);
- /* t1 = (0000)d000 */
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP1, TCG_TMP1, 24);
- /* t2 = 00c0 */
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP2, TCG_TMP0, 0x2);
- /* t3 = d00a */
- tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1);
- /* t1 = 0abc */
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP1, TCG_TMP0, 8);
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP1, 0x7);
- /* t2 = 0c00 */
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP2, TCG_TMP2, 8);
- /* t1 = 00b0 */
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP1, 0x2);
- /* t3 = dc0a */
- tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP2);
- /* t3 = dcba -- delay slot */
- tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1);
-}
+
+#define PUSH_SIZE ((15-9+1+1) * 8)
+#define FRAME_SIZE \
+ ((PUSH_SIZE \
+ + TCG_STATIC_CALL_ARGS_SIZE \
+ + CPU_TEMP_BUF_NLONGS * sizeof(long) \
+ + TCG_TARGET_STACK_ALIGN - 1) \
+ & ~(TCG_TARGET_STACK_ALIGN - 1))
+/* We're expecting a 2 byte uleb128 encoded value. */
+QEMU_BUILD_BUG_ON(FRAME_SIZE >= (1 << 14));
-/*sw
- * swap 64bit, abcdefgh->hgfedcba
- */
-static void tcg_out_bswap64(TCGContext *s, TCGReg rd, TCGReg rn)
+/* We're expecting to use a single ADDI insn. */
+QEMU_BUILD_BUG_ON(FRAME_SIZE - PUSH_SIZE > 0xfff);
+
+static void tcg_target_qemu_prologue(TCGContext *s)
{
+ TCGReg r;
+ int ofs;
- TCGReg TCG_TMP0 = rn;
- TCGReg TCG_TMP3 = rd;
- TCGReg TCG_TMP1 = TCG_REG_TMP;
- TCGReg TCG_TMP2 = TCG_REG_TMP2;
-
- /* bswap64 -- 64-bit swap. a0 = abcdefgh*/
-
- /* t3 = h0000000 */
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP3, TCG_TMP0, 56);
- /* t1 = 0000000a */
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP1, TCG_TMP0, 56);
- /* t2 = 000000g0 */
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP2, TCG_TMP0, 0x2);
- /* t3 = h000000a */
- tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1);
- /* t1 = 00000abc */
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP1, TCG_TMP0, 40);
- /* t2 = 0g000000 */
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP2, TCG_TMP2, 40);
- /* t1 = 000000b0 */
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP1, 0x2);
- /* t3 = hg00000a */
- tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP2);
- /* t2 = 0000abcd */
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP2, TCG_TMP0, 32);
- /* t3 = hg0000ba */
- tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1);
- /* t1 = 000000c0 */
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP2, 0x2);
- /* t2 = 0000000d */
- tcg_out_insn_bitImm(s, OPC_AND_I, TCG_TMP2, TCG_TMP2, 0xff);
- /* t1 = 00000c00 */
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP1, TCG_TMP1, 8);
- /* t2 = 0000d000 */
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP2, TCG_TMP2, 24);
- /* t3 = hg000cba */
- tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1);
- /* t1 = 00abcdef */
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_TMP1, TCG_TMP0, 16);
- /* t3 = hg00dcba */
- tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP2);
- /* t2 = 0000000f */
- tcg_out_insn_bitImm(s, OPC_AND_I, TCG_TMP2, TCG_TMP1, 0xff);
- /* t1 = 000000e0 */
- tcg_out_insn_simpleImm(s, OPC_ZAPNOT_I, TCG_TMP1, TCG_TMP1, 0x2);
- /* t2 = 00f00000 */
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP2, TCG_TMP2, 40);
- /* t1 = 000e0000 */
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_TMP1, TCG_TMP1, 24);
- /* t3 = hgf0dcba */
- tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP2);
- /* t3 = hgfedcba -- delay slot */
- tcg_out_insn_bitReg(s, OPC_BIS, TCG_TMP3, TCG_TMP3, TCG_TMP1);
+ /* allocate space for all saved registers */
+ /* subl $sp,PUSH_SIZE,$sp */
+ tcg_out_simple(s, OPC_SUBL_I, OPC_SUBL, TCG_REG_SP, TCG_REG_SP, PUSH_SIZE);
-}
+ /* Push (FP, LR) */
+ /* stl $fp,0($sp) */
+ tcg_out_insn_ldst(s, OPC_STL, TCG_REG_FP, TCG_REG_SP, 0);
+ /* stl $26,8($sp) */
+ tcg_out_insn_ldst(s, OPC_STL, TCG_REG_RA, TCG_REG_SP, 8);
-static void tcg_out_qemu_ld(TCGContext *s, TCGReg data_reg, TCGReg addr_reg, MemOpIdx oi, TCGType ext)
-{
-#ifndef CONFIG_SOFTMMU
- MemOp memop = get_memop(oi);
- const TCGType otype = TCG_TYPE_I64;
- if (USE_GUEST_BASE) {
- tcg_out_insn_simpleReg(s, OPC_ADDL, TCG_REG_GUEST_BASE, TCG_REG_GUEST_BASE, addr_reg);
- tcg_out_qemu_ld_direct(s, memop, data_reg, TCG_REG_GUEST_BASE, otype, 0);
- } else {
- tcg_out_qemu_ld_direct(s, memop, data_reg, addr_reg, TCG_TYPE_I64, 0);
+ /* Set up frame pointer for canonical unwinding. */
+ /* TCG_REG_FP=TCG_REG_SP */
+ tcg_out_movr(s, TCG_TYPE_I64, TCG_REG_FP, TCG_REG_SP);
+
+ /* Store callee-preserved regs x9..x14. */
+ for (r = TCG_REG_X9; r <= TCG_REG_X14; r += 1){
+ ofs = (r - TCG_REG_X9 + 2) * 8;
+ tcg_out_insn_ldst(s, OPC_STL, r, TCG_REG_SP, ofs);
}
-#endif /* CONFIG_SOFTMMU */
-}
+ /* Make stack space for TCG locals. */
+ /* subl $sp,FRAME_SIZE-PUSH_SIZE,$sp */
+ tcg_out_simple(s, OPC_SUBL_I, OPC_SUBL, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE - PUSH_SIZE);
-static void tcg_out_qemu_st(TCGContext *s, TCGReg data_reg, TCGReg addr_reg,
- MemOpIdx oi)
-{
-#ifndef CONFIG_SOFTMMU
- MemOp memop = get_memop(oi);
- const TCGType otype = TCG_TYPE_I64;
+ /* Inform TCG about how to find TCG locals with register, offset, size. */
+ tcg_set_frame(s, TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE,
+ CPU_TEMP_BUF_NLONGS * sizeof(long));
+#ifndef CONFIG_SOFTMMU
if (USE_GUEST_BASE) {
- tcg_out_insn_simpleReg(s, OPC_ADDL, TCG_REG_GUEST_BASE, TCG_REG_GUEST_BASE, addr_reg);
- tcg_out_qemu_st_direct(s, memop, data_reg, TCG_REG_GUEST_BASE, otype, 0);
- } else {
- tcg_out_qemu_st_direct(s, memop, data_reg, addr_reg, TCG_TYPE_I64, 0);
+ tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_GUEST_BASE, guest_base);
+ tcg_regset_set_reg(s->reserved_regs, TCG_REG_GUEST_BASE);
}
-#endif /* CONFIG_SOFTMMU */
-}
-
-
-/*sw
- * if cond is successful, ret=1, otherwise ret = 0
- */
-static void tcg_out_setcond(TCGContext *s, TCGCond cond, TCGReg ret,
- TCGReg arg1, TCGReg arg2)
-{
- switch(cond) {
- case TCG_COND_EQ:
- case TCG_COND_LT:
- case TCG_COND_LE:
- case TCG_COND_LTU:
- case TCG_COND_LEU:
- case TCG_COND_NE:
- case TCG_COND_GE:
- case TCG_COND_GT:
- case TCG_COND_GEU:
- case TCG_COND_GTU:
- tcg_out_cond_cmp(s, cond, ret, arg1, arg2, 0);
- break;
- default:
- tcg_abort();
- break;
- }
-}
-/*sw
- * cond(a1,a2), yes:v1->ret, no:v2->ret
- */
-static void tcg_out_movcond(TCGContext *s, TCGCond cond, TCGReg ret,
- TCGReg a1, TCGReg a2, bool const_b, TCGReg v1, TCGReg v2)
-{
- tcg_out_cond_cmp(s, cond, TCG_REG_TMP, a1, a2, const_b);
- tcg_out_insn_complexReg(s, OPC_SELLBS, TCG_REG_TMP, ret, v1, v2);
-}
-
-
+#endif
-/*sw
- * extract rn[lsb, lsb+len-1] -> rd[0, len-1]
- */
-static void tcg_out_extract(TCGContext *s, TCGReg rd, TCGReg rn, int lsb, int len)
-{
- //get 000..111..0000
- tcg_out_insn_bitReg(s, OPC_ORNOT, TCG_REG_TMP, TCG_REG_ZERO, TCG_REG_ZERO);
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP, TCG_REG_TMP, 64 - len);
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, lsb);
- /* get rn[lsb, lsb+len-1]-->rd[lsb, lsb+len-1] */
- tcg_out_insn_bitReg(s, OPC_AND, rd, rn, TCG_REG_TMP);
+ /* TCG_AREG0=tcg_target_call_iarg_regs[0], on sw, we mov $16 to $9 */
+ tcg_out_mov(s, TCG_TYPE_I64, TCG_AREG0, tcg_target_call_iarg_regs[0]);
+ tcg_out_insn_jump(s, OPC_JMP, TCG_REG_ZERO, tcg_target_call_iarg_regs[1], noPara);
- /* rd[lsb, lsb+len-1] --> rd[0, len-1] */
- tcg_out_insn_bitImm(s, OPC_SRL_I, rd, rd, lsb);
-}
+ /*
+ * Return path for goto_ptr. Set return value to 0, a-la exit_tb,
+ * and fall through to the rest of the epilogue.
+ */
+ tcg_code_gen_epilogue = tcg_splitwx_to_rx(s->code_ptr);
+ tcg_out_movi(s, TCG_TYPE_I64, TCG_REG_X0, 0);
+ /* TB epilogue */
+ tb_ret_addr = tcg_splitwx_to_rx(s->code_ptr);
-/*sw
- * depos: rd = rd[63:msb+1]:rn[msb,lsb]:rd[lsb-1,0]
- * len = msb -lsb + 1
- */
-static void tcg_out_dep(TCGContext *s, TCGReg rd, TCGReg rn, int lsb, int len)
-{
+ /* Remove TCG locals stack space. */
+ /* addl $sp,FRAME_SIZE-PUSH_SIZE,$sp */
+ tcg_out_simple(s, OPC_ADDL_I, OPC_ADDL, TCG_REG_SP, TCG_REG_SP, FRAME_SIZE - PUSH_SIZE);
- //get 000..111..0000
- tcg_out_insn_bitReg(s, OPC_ORNOT, TCG_REG_TMP, TCG_REG_ZERO, TCG_REG_ZERO);
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP, TCG_REG_TMP, 64 - len);
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_REG_TMP, TCG_REG_TMP, lsb);
+ /* Restore registers x9..x14. */
+ for (r = TCG_REG_X9; r <= TCG_REG_X14; r += 1) {
+ int ofs = (r - TCG_REG_X9 + 2) * 8;
+ tcg_out_insn_ldst(s, OPC_LDL, r, TCG_REG_SP, ofs);
+ }
- /* TCG_REG_TMP2 = rn[msb,lsb] */
- tcg_out_insn_bitImm(s, OPC_SLL_I, TCG_REG_TMP2, rn, 64-len);
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP2, TCG_REG_TMP2, 64-len-lsb);
+ /* Pop (FP, LR) */
+ /* ldl $fp,0($sp) */
+ tcg_out_insn_ldst(s, OPC_LDL, TCG_REG_FP, TCG_REG_SP, 0);
+ /* ldl $26,8($sp) */
+ tcg_out_insn_ldst(s, OPC_LDL, TCG_REG_RA, TCG_REG_SP, 8);
- /* clear rd[msb,lsb] */
- tcg_out_insn_bitReg(s, OPC_BIC, rd, rd, TCG_REG_TMP);
- /* rd = rd[63:msb+1]:rn[msb,lsb]:rd[lsb-1,0] */
- tcg_out_insn_bitReg(s, OPC_BIS, rd, rd, TCG_REG_TMP2);
+ /* restore SP to previous frame. */
+ /* addl $sp,PUSH_SIZE,$sp */
+ tcg_out_simple(s, OPC_ADDL_I, OPC_ADDL, TCG_REG_SP, TCG_REG_SP, PUSH_SIZE);
+
+ tcg_out_insn_jump(s, OPC_RET, TCG_REG_ZERO, TCG_REG_RA, noPara);
}
-/*sw
- * get val_s64(rn) * val_s64(rm) -> res_128
- * res[127:64] -> rd
- * warn:maybe rd=rn or rm
- */
-static void tcg_out_mulsh64(TCGContext *s, TCGReg rd, TCGReg rn, TCGReg rm)
+static void tcg_out_nop_fill(tcg_insn_unit *p, int count)
{
- tcg_out_insn_simpleReg(s, OPC_UMULH, TCG_REG_TMP, rn, rm);
-
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP2, rn, 63);
- tcg_out_insn_complexReg(s, OPC_SELEQ, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_ZERO, rm);
- tcg_out_insn_simpleReg(s, OPC_SUBL, TCG_REG_TMP, TCG_REG_TMP, TCG_REG_TMP2);
-
- tcg_out_insn_bitImm(s, OPC_SRL_I, TCG_REG_TMP2, rm, 63);
- tcg_out_insn_complexReg(s, OPC_SELEQ, TCG_REG_TMP2, TCG_REG_TMP2, TCG_REG_ZERO, rn);
- tcg_out_insn_simpleReg(s, OPC_SUBL, rd, TCG_REG_TMP, TCG_REG_TMP2);
+ int i;
+ for (i = 0; i < count; ++i) {
+ p[i] = OPC_NOP;
+ }
}
typedef struct {
@@ -2071,9 +2424,11 @@ typedef struct {
uint8_t fde_reg_ofs[8 * 2];
} DebugFrame;
+/*
+ * GDB doesn't appear to require proper setting of ELF_HOST_FLAGS,
+ * which is good because they're really quite complicated for SW64.
+ */
#define ELF_HOST_MACHINE EM_SW_64
-/* GDB doesn't appear to require proper setting of ELF_HOST_FLAGS,
- which is good because they're really quite complicated for SW_64. */
static const DebugFrame debug_frame = {
.h.cie.len = sizeof(DebugFrameCIE) - 4, /* length after .len member */
diff --git a/tcg/sw64/tcg-target.h b/tcg/sw64/tcg-target.h
index 3093e4fece..91681a0c75 100755
--- a/tcg/sw64/tcg-target.h
+++ b/tcg/sw64/tcg-target.h
@@ -119,5 +119,8 @@ typedef enum {
#define TCG_TARGET_HAS_MEMORY_BSWAP 0
/* optional instructions */
void tb_target_set_jmp_target(uintptr_t, uintptr_t, uintptr_t, uintptr_t);
+#ifdef CONFIG_SOFTMMU
+#define TCG_TARGET_NEED_LDST_LABELS
+#endif
#define TCG_TARGET_NEED_POOL_LABELS
#endif /* SW_64_TCG_TARGET_H */
--
2.41.0.windows.1
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/wanglmb/qemu.git
git@gitee.com:wanglmb/qemu.git
wanglmb
qemu
qemu
master

搜索帮助