bfin-sim.c 178 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465
  1. /* Simulator for Analog Devices Blackfin processors.
  2. Copyright (C) 2005-2015 Free Software Foundation, Inc.
  3. Contributed by Analog Devices, Inc.
  4. This file is part of simulators.
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 3 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program. If not, see <http://www.gnu.org/licenses/>. */
  15. #include "config.h"
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <string.h>
  19. #include <inttypes.h>
  20. #include "opcode/bfin.h"
  21. #include "sim-main.h"
  22. #include "dv-bfin_cec.h"
  23. #include "dv-bfin_mmu.h"
  24. #define HOST_LONG_WORD_SIZE (sizeof (long) * 8)
  25. #define SIGNEXTEND(v, n) \
  26. (((bs32)(v) << (HOST_LONG_WORD_SIZE - (n))) >> (HOST_LONG_WORD_SIZE - (n)))
  27. static __attribute__ ((noreturn)) void
  28. illegal_instruction (SIM_CPU *cpu)
  29. {
  30. TRACE_INSN (cpu, "ILLEGAL INSTRUCTION");
  31. while (1)
  32. cec_exception (cpu, VEC_UNDEF_I);
  33. }
  34. static __attribute__ ((noreturn)) void
  35. illegal_instruction_combination (SIM_CPU *cpu)
  36. {
  37. TRACE_INSN (cpu, "ILLEGAL INSTRUCTION COMBINATION");
  38. while (1)
  39. cec_exception (cpu, VEC_ILGAL_I);
  40. }
  41. static __attribute__ ((noreturn)) void
  42. illegal_instruction_or_combination (SIM_CPU *cpu)
  43. {
  44. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  45. illegal_instruction_combination (cpu);
  46. else
  47. illegal_instruction (cpu);
  48. }
  49. static __attribute__ ((noreturn)) void
  50. unhandled_instruction (SIM_CPU *cpu, const char *insn)
  51. {
  52. SIM_DESC sd = CPU_STATE (cpu);
  53. bu16 iw0, iw1;
  54. bu32 iw2;
  55. TRACE_EVENTS (cpu, "unhandled instruction");
  56. iw0 = IFETCH (PCREG);
  57. iw1 = IFETCH (PCREG + 2);
  58. iw2 = ((bu32)iw0 << 16) | iw1;
  59. sim_io_eprintf (sd, "Unhandled instruction at 0x%08x (%s opcode 0x", PCREG, insn);
  60. if ((iw0 & 0xc000) == 0xc000)
  61. sim_io_eprintf (sd, "%08x", iw2);
  62. else
  63. sim_io_eprintf (sd, "%04x", iw0);
  64. sim_io_eprintf (sd, ") ... aborting\n");
  65. illegal_instruction (cpu);
  66. }
  67. static const char * const astat_names[] =
  68. {
  69. [ 0] = "AZ",
  70. [ 1] = "AN",
  71. [ 2] = "AC0_COPY",
  72. [ 3] = "V_COPY",
  73. [ 4] = "ASTAT_4",
  74. [ 5] = "CC",
  75. [ 6] = "AQ",
  76. [ 7] = "ASTAT_7",
  77. [ 8] = "RND_MOD",
  78. [ 9] = "ASTAT_9",
  79. [10] = "ASTAT_10",
  80. [11] = "ASTAT_11",
  81. [12] = "AC0",
  82. [13] = "AC1",
  83. [14] = "ASTAT_14",
  84. [15] = "ASTAT_15",
  85. [16] = "AV0",
  86. [17] = "AV0S",
  87. [18] = "AV1",
  88. [19] = "AV1S",
  89. [20] = "ASTAT_20",
  90. [21] = "ASTAT_21",
  91. [22] = "ASTAT_22",
  92. [23] = "ASTAT_23",
  93. [24] = "V",
  94. [25] = "VS",
  95. [26] = "ASTAT_26",
  96. [27] = "ASTAT_27",
  97. [28] = "ASTAT_28",
  98. [29] = "ASTAT_29",
  99. [30] = "ASTAT_30",
  100. [31] = "ASTAT_31",
  101. };
  102. typedef enum
  103. {
  104. c_0, c_1, c_4, c_2, c_uimm2, c_uimm3, c_imm3, c_pcrel4,
  105. c_imm4, c_uimm4s4, c_uimm4s4d, c_uimm4, c_uimm4s2, c_negimm5s4, c_imm5,
  106. c_imm5d, c_uimm5, c_imm6, c_imm7, c_imm7d, c_imm8, c_uimm8, c_pcrel8,
  107. c_uimm8s4, c_pcrel8s4, c_lppcrel10, c_pcrel10, c_pcrel12, c_imm16s4,
  108. c_luimm16, c_imm16, c_imm16d, c_huimm16, c_rimm16, c_imm16s2, c_uimm16s4,
  109. c_uimm16s4d, c_uimm16, c_pcrel24, c_uimm32, c_imm32, c_huimm32, c_huimm32e,
  110. } const_forms_t;
  111. static const struct
  112. {
  113. const char *name;
  114. const int nbits;
  115. const char reloc;
  116. const char issigned;
  117. const char pcrel;
  118. const char scale;
  119. const char offset;
  120. const char negative;
  121. const char positive;
  122. const char decimal;
  123. const char leading;
  124. const char exact;
  125. } constant_formats[] =
  126. {
  127. { "0", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  128. { "1", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  129. { "4", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  130. { "2", 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  131. { "uimm2", 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  132. { "uimm3", 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  133. { "imm3", 3, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  134. { "pcrel4", 4, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
  135. { "imm4", 4, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  136. { "uimm4s4", 4, 0, 0, 0, 2, 0, 0, 1, 0, 0, 0},
  137. { "uimm4s4d", 4, 0, 0, 0, 2, 0, 0, 1, 1, 0, 0},
  138. { "uimm4", 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  139. { "uimm4s2", 4, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0},
  140. { "negimm5s4", 5, 0, 1, 0, 2, 0, 1, 0, 0, 0, 0},
  141. { "imm5", 5, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  142. { "imm5d", 5, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0},
  143. { "uimm5", 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  144. { "imm6", 6, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  145. { "imm7", 7, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  146. { "imm7d", 7, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
  147. { "imm8", 8, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  148. { "uimm8", 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  149. { "pcrel8", 8, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
  150. { "uimm8s4", 8, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
  151. { "pcrel8s4", 8, 1, 1, 1, 2, 0, 0, 0, 0, 0, 0},
  152. { "lppcrel10", 10, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0},
  153. { "pcrel10", 10, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
  154. { "pcrel12", 12, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
  155. { "imm16s4", 16, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0},
  156. { "luimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  157. { "imm16", 16, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  158. { "imm16d", 16, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
  159. { "huimm16", 16, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  160. { "rimm16", 16, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0},
  161. { "imm16s2", 16, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0},
  162. { "uimm16s4", 16, 0, 0, 0, 2, 0, 0, 0, 0, 0, 0},
  163. { "uimm16s4d", 16, 0, 0, 0, 2, 0, 0, 0, 1, 0, 0},
  164. { "uimm16", 16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  165. { "pcrel24", 24, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0},
  166. { "uimm32", 32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  167. { "imm32", 32, 0, 1, 0, 0, 0, 0, 0, 1, 3, 0},
  168. { "huimm32", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0},
  169. { "huimm32e", 32, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1},
  170. };
  171. static const char *
  172. fmtconst_str (const_forms_t cf, bs32 x, bu32 pc)
  173. {
  174. static char buf[60];
  175. if (constant_formats[cf].reloc)
  176. {
  177. bu32 ea = (((constant_formats[cf].pcrel ? SIGNEXTEND (x, constant_formats[cf].nbits)
  178. : x) + constant_formats[cf].offset) << constant_formats[cf].scale);
  179. if (constant_formats[cf].pcrel)
  180. ea += pc;
  181. /*if (outf->symbol_at_address_func (ea, outf) || !constant_formats[cf].exact)
  182. {
  183. outf->print_address_func (ea, outf);
  184. return "";
  185. }
  186. else*/
  187. {
  188. sprintf (buf, "%#x", x);
  189. return buf;
  190. }
  191. }
  192. /* Negative constants have an implied sign bit. */
  193. if (constant_formats[cf].negative)
  194. {
  195. int nb = constant_formats[cf].nbits + 1;
  196. x = x | (1 << constant_formats[cf].nbits);
  197. x = SIGNEXTEND (x, nb);
  198. }
  199. else
  200. x = constant_formats[cf].issigned ? SIGNEXTEND (x, constant_formats[cf].nbits) : x;
  201. if (constant_formats[cf].offset)
  202. x += constant_formats[cf].offset;
  203. if (constant_formats[cf].scale)
  204. x <<= constant_formats[cf].scale;
  205. if (constant_formats[cf].decimal)
  206. sprintf (buf, "%*i", constant_formats[cf].leading, x);
  207. else
  208. {
  209. if (constant_formats[cf].issigned && x < 0)
  210. sprintf (buf, "-0x%x", abs (x));
  211. else
  212. sprintf (buf, "0x%x", x);
  213. }
  214. return buf;
  215. }
  216. static bu32
  217. fmtconst_val (const_forms_t cf, bu32 x, bu32 pc)
  218. {
  219. if (0 && constant_formats[cf].reloc)
  220. {
  221. bu32 ea = (((constant_formats[cf].pcrel
  222. ? (bu32)SIGNEXTEND (x, constant_formats[cf].nbits)
  223. : x) + constant_formats[cf].offset)
  224. << constant_formats[cf].scale);
  225. if (constant_formats[cf].pcrel)
  226. ea += pc;
  227. return ea;
  228. }
  229. /* Negative constants have an implied sign bit. */
  230. if (constant_formats[cf].negative)
  231. {
  232. int nb = constant_formats[cf].nbits + 1;
  233. x = x | (1 << constant_formats[cf].nbits);
  234. x = SIGNEXTEND (x, nb);
  235. }
  236. else if (constant_formats[cf].issigned)
  237. x = SIGNEXTEND (x, constant_formats[cf].nbits);
  238. x += constant_formats[cf].offset;
  239. x <<= constant_formats[cf].scale;
  240. return x;
  241. }
  242. #define uimm16s4(x) fmtconst_val (c_uimm16s4, x, 0)
  243. #define uimm16s4_str(x) fmtconst_str (c_uimm16s4, x, 0)
  244. #define uimm16s4d(x) fmtconst_val (c_uimm16s4d, x, 0)
  245. #define pcrel4(x) fmtconst_val (c_pcrel4, x, pc)
  246. #define pcrel8(x) fmtconst_val (c_pcrel8, x, pc)
  247. #define pcrel8s4(x) fmtconst_val (c_pcrel8s4, x, pc)
  248. #define pcrel10(x) fmtconst_val (c_pcrel10, x, pc)
  249. #define pcrel12(x) fmtconst_val (c_pcrel12, x, pc)
  250. #define negimm5s4(x) fmtconst_val (c_negimm5s4, x, 0)
  251. #define negimm5s4_str(x) fmtconst_str (c_negimm5s4, x, 0)
  252. #define rimm16(x) fmtconst_val (c_rimm16, x, 0)
  253. #define huimm16(x) fmtconst_val (c_huimm16, x, 0)
  254. #define imm16(x) fmtconst_val (c_imm16, x, 0)
  255. #define imm16_str(x) fmtconst_str (c_imm16, x, 0)
  256. #define imm16d(x) fmtconst_val (c_imm16d, x, 0)
  257. #define uimm2(x) fmtconst_val (c_uimm2, x, 0)
  258. #define uimm3(x) fmtconst_val (c_uimm3, x, 0)
  259. #define uimm3_str(x) fmtconst_str (c_uimm3, x, 0)
  260. #define luimm16(x) fmtconst_val (c_luimm16, x, 0)
  261. #define luimm16_str(x) fmtconst_str (c_luimm16, x, 0)
  262. #define uimm4(x) fmtconst_val (c_uimm4, x, 0)
  263. #define uimm4_str(x) fmtconst_str (c_uimm4, x, 0)
  264. #define uimm5(x) fmtconst_val (c_uimm5, x, 0)
  265. #define uimm5_str(x) fmtconst_str (c_uimm5, x, 0)
  266. #define imm16s2(x) fmtconst_val (c_imm16s2, x, 0)
  267. #define imm16s2_str(x) fmtconst_str (c_imm16s2, x, 0)
  268. #define uimm8(x) fmtconst_val (c_uimm8, x, 0)
  269. #define imm16s4(x) fmtconst_val (c_imm16s4, x, 0)
  270. #define imm16s4_str(x) fmtconst_str (c_imm16s4, x, 0)
  271. #define uimm4s2(x) fmtconst_val (c_uimm4s2, x, 0)
  272. #define uimm4s2_str(x) fmtconst_str (c_uimm4s2, x, 0)
  273. #define uimm4s4(x) fmtconst_val (c_uimm4s4, x, 0)
  274. #define uimm4s4_str(x) fmtconst_str (c_uimm4s4, x, 0)
  275. #define uimm4s4d(x) fmtconst_val (c_uimm4s4d, x, 0)
  276. #define lppcrel10(x) fmtconst_val (c_lppcrel10, x, pc)
  277. #define imm3(x) fmtconst_val (c_imm3, x, 0)
  278. #define imm3_str(x) fmtconst_str (c_imm3, x, 0)
  279. #define imm4(x) fmtconst_val (c_imm4, x, 0)
  280. #define uimm8s4(x) fmtconst_val (c_uimm8s4, x, 0)
  281. #define imm5(x) fmtconst_val (c_imm5, x, 0)
  282. #define imm5d(x) fmtconst_val (c_imm5d, x, 0)
  283. #define imm6(x) fmtconst_val (c_imm6, x, 0)
  284. #define imm7(x) fmtconst_val (c_imm7, x, 0)
  285. #define imm7_str(x) fmtconst_str (c_imm7, x, 0)
  286. #define imm7d(x) fmtconst_val (c_imm7d, x, 0)
  287. #define imm8(x) fmtconst_val (c_imm8, x, 0)
  288. #define pcrel24(x) fmtconst_val (c_pcrel24, x, pc)
  289. #define pcrel24_str(x) fmtconst_str (c_pcrel24, x, pc)
  290. #define uimm16(x) fmtconst_val (c_uimm16, x, 0)
  291. #define uimm32(x) fmtconst_val (c_uimm32, x, 0)
  292. #define imm32(x) fmtconst_val (c_imm32, x, 0)
  293. #define huimm32(x) fmtconst_val (c_huimm32, x, 0)
  294. #define huimm32e(x) fmtconst_val (c_huimm32e, x, 0)
  295. /* Table C-4. Core Register Encoding Map. */
  296. const char * const greg_names[] =
  297. {
  298. "R0", "R1", "R2", "R3", "R4", "R5", "R6", "R7",
  299. "P0", "P1", "P2", "P3", "P4", "P5", "SP", "FP",
  300. "I0", "I1", "I2", "I3", "M0", "M1", "M2", "M3",
  301. "B0", "B1", "B2", "B3", "L0", "L1", "L2", "L3",
  302. "A0.X", "A0.W", "A1.X", "A1.W", "<res>", "<res>", "ASTAT", "RETS",
  303. "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>", "<res>",
  304. "LC0", "LT0", "LB0", "LC1", "LT1", "LB1", "CYCLES", "CYCLES2",
  305. "USP", "SEQSTAT", "SYSCFG", "RETI", "RETX", "RETN", "RETE", "EMUDAT",
  306. };
  307. static const char *
  308. get_allreg_name (int grp, int reg)
  309. {
  310. return greg_names[(grp << 3) | reg];
  311. }
  312. static const char *
  313. get_preg_name (int reg)
  314. {
  315. return get_allreg_name (1, reg);
  316. }
  317. static bool
  318. reg_is_reserved (int grp, int reg)
  319. {
  320. return (grp == 4 && (reg == 4 || reg == 5)) || (grp == 5);
  321. }
  322. static bu32 *
  323. get_allreg (SIM_CPU *cpu, int grp, int reg)
  324. {
  325. int fullreg = (grp << 3) | reg;
  326. /* REG_R0, REG_R1, REG_R2, REG_R3, REG_R4, REG_R5, REG_R6, REG_R7,
  327. REG_P0, REG_P1, REG_P2, REG_P3, REG_P4, REG_P5, REG_SP, REG_FP,
  328. REG_I0, REG_I1, REG_I2, REG_I3, REG_M0, REG_M1, REG_M2, REG_M3,
  329. REG_B0, REG_B1, REG_B2, REG_B3, REG_L0, REG_L1, REG_L2, REG_L3,
  330. REG_A0x, REG_A0w, REG_A1x, REG_A1w, , , REG_ASTAT, REG_RETS,
  331. , , , , , , , ,
  332. REG_LC0, REG_LT0, REG_LB0, REG_LC1, REG_LT1, REG_LB1, REG_CYCLES,
  333. REG_CYCLES2,
  334. REG_USP, REG_SEQSTAT, REG_SYSCFG, REG_RETI, REG_RETX, REG_RETN, REG_RETE,
  335. REG_LASTREG */
  336. switch (fullreg >> 2)
  337. {
  338. case 0: case 1: return &DREG (reg);
  339. case 2: case 3: return &PREG (reg);
  340. case 4: return &IREG (reg & 3);
  341. case 5: return &MREG (reg & 3);
  342. case 6: return &BREG (reg & 3);
  343. case 7: return &LREG (reg & 3);
  344. default:
  345. switch (fullreg)
  346. {
  347. case 32: return &AXREG (0);
  348. case 33: return &AWREG (0);
  349. case 34: return &AXREG (1);
  350. case 35: return &AWREG (1);
  351. case 39: return &RETSREG;
  352. case 48: return &LCREG (0);
  353. case 49: return &LTREG (0);
  354. case 50: return &LBREG (0);
  355. case 51: return &LCREG (1);
  356. case 52: return &LTREG (1);
  357. case 53: return &LBREG (1);
  358. case 54: return &CYCLESREG;
  359. case 55: return &CYCLES2REG;
  360. case 56: return &USPREG;
  361. case 57: return &SEQSTATREG;
  362. case 58: return &SYSCFGREG;
  363. case 59: return &RETIREG;
  364. case 60: return &RETXREG;
  365. case 61: return &RETNREG;
  366. case 62: return &RETEREG;
  367. case 63: return &EMUDAT_INREG;
  368. }
  369. illegal_instruction (cpu);
  370. }
  371. }
  372. static const char *
  373. amod0 (int s0, int x0)
  374. {
  375. static const char * const mod0[] = {
  376. "", " (S)", " (CO)", " (SCO)",
  377. };
  378. int i = s0 + (x0 << 1);
  379. if (i < ARRAY_SIZE (mod0))
  380. return mod0[i];
  381. else
  382. return "";
  383. }
  384. static const char *
  385. amod0amod2 (int s0, int x0, int aop0)
  386. {
  387. static const char * const mod02[] = {
  388. "", " (S)", " (CO)", " (SCO)",
  389. "", "", "", "",
  390. " (ASR)", " (S, ASR)", " (CO, ASR)", " (SCO, ASR)",
  391. " (ASL)", " (S, ASL)", " (CO, ASL)", " (SCO, ASL)",
  392. };
  393. int i = s0 + (x0 << 1) + (aop0 << 2);
  394. if (i < ARRAY_SIZE (mod02))
  395. return mod02[i];
  396. else
  397. return "";
  398. }
  399. static const char *
  400. amod1 (int s0, int x0)
  401. {
  402. static const char * const mod1[] = {
  403. " (NS)", " (S)",
  404. };
  405. int i = s0 + (x0 << 1);
  406. if (i < ARRAY_SIZE (mod1))
  407. return mod1[i];
  408. else
  409. return "";
  410. }
  411. static const char *
  412. mac_optmode (int mmod, int MM)
  413. {
  414. static const char * const omode[] = {
  415. [(M_S2RND << 1) + 0] = " (S2RND)",
  416. [(M_T << 1) + 0] = " (T)",
  417. [(M_W32 << 1) + 0] = " (W32)",
  418. [(M_FU << 1) + 0] = " (FU)",
  419. [(M_TFU << 1) + 0] = " (TFU)",
  420. [(M_IS << 1) + 0] = " (IS)",
  421. [(M_ISS2 << 1) + 0] = " (ISS2)",
  422. [(M_IH << 1) + 0] = " (IH)",
  423. [(M_IU << 1) + 0] = " (IU)",
  424. [(M_S2RND << 1) + 1] = " (M, S2RND)",
  425. [(M_T << 1) + 1] = " (M, T)",
  426. [(M_W32 << 1) + 1] = " (M, W32)",
  427. [(M_FU << 1) + 1] = " (M, FU)",
  428. [(M_TFU << 1) + 1] = " (M, TFU)",
  429. [(M_IS << 1) + 1] = " (M, IS)",
  430. [(M_ISS2 << 1) + 1] = " (M, ISS2)",
  431. [(M_IH << 1) + 1] = " (M, IH)",
  432. [(M_IU << 1) + 1] = " (M, IU)",
  433. };
  434. int i = MM + (mmod << 1);
  435. if (i < ARRAY_SIZE (omode) && omode[i])
  436. return omode[i];
  437. else
  438. return "";
  439. }
  440. static const char *
  441. get_store_name (SIM_CPU *cpu, bu32 *p)
  442. {
  443. if (p >= &DREG (0) && p <= &CYCLESREG)
  444. return greg_names[p - &DREG (0)];
  445. else if (p == &AXREG (0))
  446. return greg_names[4 * 8 + 0];
  447. else if (p == &AWREG (0))
  448. return greg_names[4 * 8 + 1];
  449. else if (p == &AXREG (1))
  450. return greg_names[4 * 8 + 2];
  451. else if (p == &AWREG (1))
  452. return greg_names[4 * 8 + 3];
  453. else if (p == &ASTATREG (av0))
  454. return "ASTAT[av0]";
  455. else if (p == &ASTATREG (av0s))
  456. return "ASTAT[av0s]";
  457. else if (p == &ASTATREG (av1))
  458. return "ASTAT[av1]";
  459. else if (p == &ASTATREG (av1s))
  460. return "ASTAT[av1s]";
  461. else if (p == &ASTATREG (v))
  462. return "ASTAT[v]";
  463. else if (p == &ASTATREG (vs))
  464. return "ASTAT[vs]";
  465. else if (p == &ASTATREG (v_copy))
  466. return "ASTAT[v_copy]";
  467. else if (p == &ASTATREG (az))
  468. return "ASTAT[az]";
  469. else if (p == &ASTATREG (an))
  470. return "ASTAT[an]";
  471. else if (p == &ASTATREG (az))
  472. return "ASTAT[az]";
  473. else if (p == &ASTATREG (ac0))
  474. return "ASTAT[ac0]";
  475. else if (p == &ASTATREG (ac0_copy))
  476. return "ASTAT[ac0_copy]";
  477. else
  478. {
  479. /* Worry about this when we start to STORE() it. */
  480. sim_io_eprintf (CPU_STATE (cpu), "STORE(): unknown register\n");
  481. abort ();
  482. }
  483. }
  484. static void
  485. queue_store (SIM_CPU *cpu, bu32 *addr, bu32 val)
  486. {
  487. struct store *s = &BFIN_CPU_STATE.stores[BFIN_CPU_STATE.n_stores];
  488. s->addr = addr;
  489. s->val = val;
  490. TRACE_REGISTER (cpu, "queuing write %s = %#x",
  491. get_store_name (cpu, addr), val);
  492. ++BFIN_CPU_STATE.n_stores;
  493. }
  494. #define STORE(X, Y) \
  495. do { \
  496. if (BFIN_CPU_STATE.n_stores == 20) abort (); \
  497. queue_store (cpu, &(X), (Y)); \
  498. } while (0)
  499. static void
  500. setflags_nz (SIM_CPU *cpu, bu32 val)
  501. {
  502. SET_ASTATREG (az, val == 0);
  503. SET_ASTATREG (an, val >> 31);
  504. }
  505. static void
  506. setflags_nz_2x16 (SIM_CPU *cpu, bu32 val)
  507. {
  508. SET_ASTATREG (an, (bs16)val < 0 || (bs16)(val >> 16) < 0);
  509. SET_ASTATREG (az, (bs16)val == 0 || (bs16)(val >> 16) == 0);
  510. }
  511. static void
  512. setflags_logical (SIM_CPU *cpu, bu32 val)
  513. {
  514. setflags_nz (cpu, val);
  515. SET_ASTATREG (ac0, 0);
  516. SET_ASTATREG (v, 0);
  517. }
  518. static bu32
  519. add_brev (bu32 addend1, bu32 addend2)
  520. {
  521. bu32 mask, b, r;
  522. int i, cy;
  523. mask = 0x80000000;
  524. r = 0;
  525. cy = 0;
  526. for (i = 31; i >= 0; --i)
  527. {
  528. b = ((addend1 & mask) >> i) + ((addend2 & mask) >> i);
  529. b += cy;
  530. cy = b >> 1;
  531. b &= 1;
  532. r |= b << i;
  533. mask >>= 1;
  534. }
  535. return r;
  536. }
  537. /* This is a bit crazy, but we want to simulate the hardware behavior exactly
  538. rather than worry about the circular buffers being used correctly. Which
  539. isn't to say there isn't room for improvement here, just that we want to
  540. be conservative. See also dagsub(). */
  541. static bu32
  542. dagadd (SIM_CPU *cpu, int dagno, bs32 M)
  543. {
  544. bu64 i = IREG (dagno);
  545. bu64 l = LREG (dagno);
  546. bu64 b = BREG (dagno);
  547. bu64 m = (bu32)M;
  548. bu64 LB, IM, IML;
  549. bu32 im32, iml32, lb32, res;
  550. bu64 msb, car;
  551. /* A naïve implementation that mostly works:
  552. res = i + m;
  553. if (l && res >= b + l)
  554. res -= l;
  555. STORE (IREG (dagno), res);
  556. */
  557. msb = (bu64)1 << 31;
  558. car = (bu64)1 << 32;
  559. IM = i + m;
  560. im32 = IM;
  561. LB = l + b;
  562. lb32 = LB;
  563. if (M < 0)
  564. {
  565. IML = i + m + l;
  566. iml32 = IML;
  567. if ((i & msb) || (IM & car))
  568. res = (im32 < b) ? iml32 : im32;
  569. else
  570. res = (im32 < b) ? im32 : iml32;
  571. }
  572. else
  573. {
  574. IML = i + m - l;
  575. iml32 = IML;
  576. if ((IM & car) == (LB & car))
  577. res = (im32 < lb32) ? im32 : iml32;
  578. else
  579. res = (im32 < lb32) ? iml32 : im32;
  580. }
  581. STORE (IREG (dagno), res);
  582. return res;
  583. }
  584. /* See dagadd() notes above. */
  585. static bu32
  586. dagsub (SIM_CPU *cpu, int dagno, bs32 M)
  587. {
  588. bu64 i = IREG (dagno);
  589. bu64 l = LREG (dagno);
  590. bu64 b = BREG (dagno);
  591. bu64 m = (bu32)M;
  592. bu64 mbar = (bu32)(~m + 1);
  593. bu64 LB, IM, IML;
  594. bu32 b32, im32, iml32, lb32, res;
  595. bu64 msb, car;
  596. /* A naïve implementation that mostly works:
  597. res = i - m;
  598. if (l && newi < b)
  599. newi += l;
  600. STORE (IREG (dagno), newi);
  601. */
  602. msb = (bu64)1 << 31;
  603. car = (bu64)1 << 32;
  604. IM = i + mbar;
  605. im32 = IM;
  606. LB = l + b;
  607. lb32 = LB;
  608. if (M < 0)
  609. {
  610. IML = i + mbar - l;
  611. iml32 = IML;
  612. if (!!((i & msb) && (IM & car)) == !!(LB & car))
  613. res = (im32 < lb32) ? im32 : iml32;
  614. else
  615. res = (im32 < lb32) ? iml32 : im32;
  616. }
  617. else
  618. {
  619. IML = i + mbar + l;
  620. iml32 = IML;
  621. b32 = b;
  622. if (M == 0 || IM & car)
  623. res = (im32 < b32) ? iml32 : im32;
  624. else
  625. res = (im32 < b32) ? im32 : iml32;
  626. }
  627. STORE (IREG (dagno), res);
  628. return res;
  629. }
  630. static bu40
  631. ashiftrt (SIM_CPU *cpu, bu40 val, int cnt, int size)
  632. {
  633. int real_cnt = cnt > size ? size : cnt;
  634. bu40 sgn = ~(((val & 0xFFFFFFFFFFull) >> (size - 1)) - 1);
  635. int sgncnt = size - real_cnt;
  636. if (sgncnt > 16)
  637. sgn <<= 16, sgncnt -= 16;
  638. sgn <<= sgncnt;
  639. if (real_cnt > 16)
  640. val >>= 16, real_cnt -= 16;
  641. val >>= real_cnt;
  642. val |= sgn;
  643. SET_ASTATREG (an, val >> (size - 1));
  644. SET_ASTATREG (az, val == 0);
  645. if (size != 40)
  646. SET_ASTATREG (v, 0);
  647. return val;
  648. }
  649. static bu64
  650. lshiftrt (SIM_CPU *cpu, bu64 val, int cnt, int size)
  651. {
  652. int real_cnt = cnt > size ? size : cnt;
  653. if (real_cnt > 16)
  654. val >>= 16, real_cnt -= 16;
  655. val >>= real_cnt;
  656. switch (size)
  657. {
  658. case 16:
  659. val &= 0xFFFF;
  660. break;
  661. case 32:
  662. val &= 0xFFFFFFFF;
  663. break;
  664. case 40:
  665. val &= 0xFFFFFFFFFFull;
  666. break;
  667. default:
  668. illegal_instruction (cpu);
  669. break;
  670. }
  671. SET_ASTATREG (an, val >> (size - 1));
  672. SET_ASTATREG (az, val == 0);
  673. if (size != 40)
  674. SET_ASTATREG (v, 0);
  675. return val;
  676. }
  677. static bu64
  678. lshift (SIM_CPU *cpu, bu64 val, int cnt, int size, bool saturate, bool overflow)
  679. {
  680. int v_i, real_cnt = cnt > size ? size : cnt;
  681. bu64 sgn = ~((val >> (size - 1)) - 1);
  682. int mask_cnt = size - 1;
  683. bu64 masked, new_val = val;
  684. bu64 mask = ~0;
  685. mask <<= mask_cnt;
  686. sgn <<= mask_cnt;
  687. masked = val & mask;
  688. if (real_cnt > 16)
  689. new_val <<= 16, real_cnt -= 16;
  690. new_val <<= real_cnt;
  691. masked = new_val & mask;
  692. /* If an operation would otherwise cause a positive value to overflow
  693. and become negative, instead, saturation limits the result to the
  694. maximum positive value for the size register being used.
  695. Conversely, if an operation would otherwise cause a negative value
  696. to overflow and become positive, saturation limits the result to the
  697. maximum negative value for the register size.
  698. However, it's a little more complex than looking at sign bits, we need
  699. to see if we are shifting the sign information away... */
  700. if (((val << cnt) >> size) == 0
  701. || (((val << cnt) >> size) == ~(~0 << cnt)
  702. && ((new_val >> (size - 1)) & 0x1)))
  703. v_i = 0;
  704. else
  705. v_i = 1;
  706. switch (size)
  707. {
  708. case 16:
  709. new_val &= 0xFFFF;
  710. if (saturate && (v_i || ((val >> (size - 1)) != (new_val >> (size - 1)))))
  711. {
  712. new_val = (val >> (size - 1)) == 0 ? 0x7fff : 0x8000;
  713. v_i = 1;
  714. }
  715. break;
  716. case 32:
  717. new_val &= 0xFFFFFFFF;
  718. masked &= 0xFFFFFFFF;
  719. sgn &= 0xFFFFFFFF;
  720. if (saturate
  721. && (v_i
  722. || (sgn != masked)
  723. || (!sgn && new_val == 0 && val != 0)))
  724. {
  725. new_val = sgn == 0 ? 0x7fffffff : 0x80000000;
  726. v_i = 1;
  727. }
  728. break;
  729. case 40:
  730. new_val &= 0xFFFFFFFFFFull;
  731. masked &= 0xFFFFFFFFFFull;
  732. break;
  733. default:
  734. illegal_instruction (cpu);
  735. break;
  736. }
  737. SET_ASTATREG (an, new_val >> (size - 1));
  738. SET_ASTATREG (az, new_val == 0);
  739. if (size != 40)
  740. {
  741. SET_ASTATREG (v, overflow && v_i);
  742. if (overflow && v_i)
  743. SET_ASTATREG (vs, 1);
  744. }
  745. return new_val;
  746. }
  747. static bu32
  748. algn (bu32 l, bu32 h, bu32 aln)
  749. {
  750. if (aln == 0)
  751. return l;
  752. else
  753. return (l >> (8 * aln)) | (h << (32 - 8 * aln));
  754. }
  755. static bu32
  756. saturate_s16 (bu64 val, bu32 *overflow)
  757. {
  758. if ((bs64)val < -0x8000ll)
  759. {
  760. if (overflow)
  761. *overflow = 1;
  762. return 0x8000;
  763. }
  764. if ((bs64)val > 0x7fff)
  765. {
  766. if (overflow)
  767. *overflow = 1;
  768. return 0x7fff;
  769. }
  770. return val & 0xffff;
  771. }
  772. static bu40
  773. rot40 (bu40 val, int shift, bu32 *cc)
  774. {
  775. const int nbits = 40;
  776. bu40 ret;
  777. shift = CLAMP (shift, -nbits, nbits);
  778. if (shift == 0)
  779. return val;
  780. /* Reduce everything to rotate left. */
  781. if (shift < 0)
  782. shift += nbits + 1;
  783. ret = shift == nbits ? 0 : val << shift;
  784. ret |= shift == 1 ? 0 : val >> ((nbits + 1) - shift);
  785. ret |= (bu40)*cc << (shift - 1);
  786. *cc = (val >> (nbits - shift)) & 1;
  787. return ret;
  788. }
  789. static bu32
  790. rot32 (bu32 val, int shift, bu32 *cc)
  791. {
  792. const int nbits = 32;
  793. bu32 ret;
  794. shift = CLAMP (shift, -nbits, nbits);
  795. if (shift == 0)
  796. return val;
  797. /* Reduce everything to rotate left. */
  798. if (shift < 0)
  799. shift += nbits + 1;
  800. ret = shift == nbits ? 0 : val << shift;
  801. ret |= shift == 1 ? 0 : val >> ((nbits + 1) - shift);
  802. ret |= (bu32)*cc << (shift - 1);
  803. *cc = (val >> (nbits - shift)) & 1;
  804. return ret;
  805. }
  806. static bu32
  807. add32 (SIM_CPU *cpu, bu32 a, bu32 b, int carry, int sat)
  808. {
  809. int flgs = (a >> 31) & 1;
  810. int flgo = (b >> 31) & 1;
  811. bu32 v = a + b;
  812. int flgn = (v >> 31) & 1;
  813. int overflow = (flgs ^ flgn) & (flgo ^ flgn);
  814. if (sat && overflow)
  815. {
  816. v = (bu32)1 << 31;
  817. if (flgn)
  818. v -= 1;
  819. flgn = (v >> 31) & 1;
  820. }
  821. SET_ASTATREG (an, flgn);
  822. if (overflow)
  823. SET_ASTATREG (vs, 1);
  824. SET_ASTATREG (v, overflow);
  825. ASTATREG (v_internal) |= overflow;
  826. SET_ASTATREG (az, v == 0);
  827. if (carry)
  828. SET_ASTATREG (ac0, ~a < b);
  829. return v;
  830. }
  831. static bu32
  832. sub32 (SIM_CPU *cpu, bu32 a, bu32 b, int carry, int sat, int parallel)
  833. {
  834. int flgs = (a >> 31) & 1;
  835. int flgo = (b >> 31) & 1;
  836. bu32 v = a - b;
  837. int flgn = (v >> 31) & 1;
  838. int overflow = (flgs ^ flgo) & (flgn ^ flgs);
  839. if (sat && overflow)
  840. {
  841. v = (bu32)1 << 31;
  842. if (flgn)
  843. v -= 1;
  844. flgn = (v >> 31) & 1;
  845. }
  846. if (!parallel || flgn)
  847. SET_ASTATREG (an, flgn);
  848. if (overflow)
  849. SET_ASTATREG (vs, 1);
  850. if (!parallel || overflow)
  851. SET_ASTATREG (v, overflow);
  852. if (!parallel || overflow)
  853. ASTATREG (v_internal) |= overflow;
  854. if (!parallel || v == 0)
  855. SET_ASTATREG (az, v == 0);
  856. if (carry && (!parallel || b <= a))
  857. SET_ASTATREG (ac0, b <= a);
  858. return v;
  859. }
  860. static bu32
  861. add16 (SIM_CPU *cpu, bu16 a, bu16 b, bu32 *carry, bu32 *overfl,
  862. bu32 *zero, bu32 *neg, int sat, int scale)
  863. {
  864. int flgs = (a >> 15) & 1;
  865. int flgo = (b >> 15) & 1;
  866. bs64 v = (bs16)a + (bs16)b;
  867. int flgn = (v >> 15) & 1;
  868. int overflow = (flgs ^ flgn) & (flgo ^ flgn);
  869. switch (scale)
  870. {
  871. case 0:
  872. break;
  873. case 2:
  874. /* (ASR) */
  875. v = (a >> 1) + (a & 0x8000) + (b >> 1) + (b & 0x8000)
  876. + (((a & 1) + (b & 1)) >> 1);
  877. v |= -(v & 0x8000);
  878. break;
  879. case 3:
  880. /* (ASL) */
  881. v = (v << 1);
  882. break;
  883. default:
  884. illegal_instruction (cpu);
  885. }
  886. flgn = (v >> 15) & 1;
  887. overflow = (flgs ^ flgn) & (flgo ^ flgn);
  888. if (v > (bs64)0xffff)
  889. overflow = 1;
  890. if (sat)
  891. v = saturate_s16 (v, 0);
  892. if (neg)
  893. *neg |= (v >> 15) & 1;
  894. if (overfl)
  895. *overfl |= overflow;
  896. if (zero)
  897. *zero |= (v & 0xFFFF) == 0;
  898. if (carry)
  899. *carry |= ((bu16)~a < (bu16)b);
  900. return v & 0xffff;
  901. }
  902. static bu32
  903. sub16 (SIM_CPU *cpu, bu16 a, bu16 b, bu32 *carry, bu32 *overfl,
  904. bu32 *zero, bu32 *neg, int sat, int scale)
  905. {
  906. int flgs = (a >> 15) & 1;
  907. int flgo = (b >> 15) & 1;
  908. bs64 v = (bs16)a - (bs16)b;
  909. int flgn = (v >> 15) & 1;
  910. int overflow = (flgs ^ flgo) & (flgn ^ flgs);
  911. switch (scale)
  912. {
  913. case 0:
  914. break;
  915. case 2:
  916. /* (ASR) */
  917. if (sat)
  918. v = ((a >> 1) + (a & 0x8000)) - ( (b >> 1) + (b & 0x8000))
  919. + (((a & 1)-(b & 1)));
  920. else
  921. {
  922. v = ((v & 0xFFFF) >> 1);
  923. if ((!flgs & !flgo & flgn)
  924. || (flgs & !flgo & !flgn)
  925. || (flgs & flgo & flgn)
  926. || (flgs & !flgo & flgn))
  927. v |= 0x8000;
  928. }
  929. v |= -(v & 0x8000);
  930. flgn = (v >> 15) & 1;
  931. overflow = (flgs ^ flgo) & (flgn ^ flgs);
  932. break;
  933. case 3:
  934. /* (ASL) */
  935. v <<= 1;
  936. if (v > (bs64)0x7fff || v < (bs64)-0xffff)
  937. overflow = 1;
  938. break;
  939. default:
  940. illegal_instruction (cpu);
  941. }
  942. if (sat)
  943. {
  944. v = saturate_s16 (v, 0);
  945. }
  946. if (neg)
  947. *neg |= (v >> 15) & 1;
  948. if (zero)
  949. *zero |= (v & 0xFFFF) == 0;
  950. if (overfl)
  951. *overfl |= overflow;
  952. if (carry)
  953. *carry |= (bu16)b <= (bu16)a;
  954. return v;
  955. }
  956. static bu32
  957. min32 (SIM_CPU *cpu, bu32 a, bu32 b)
  958. {
  959. int val = a;
  960. if ((bs32)a > (bs32)b)
  961. val = b;
  962. setflags_nz (cpu, val);
  963. SET_ASTATREG (v, 0);
  964. return val;
  965. }
  966. static bu32
  967. max32 (SIM_CPU *cpu, bu32 a, bu32 b)
  968. {
  969. int val = a;
  970. if ((bs32)a < (bs32)b)
  971. val = b;
  972. setflags_nz (cpu, val);
  973. SET_ASTATREG (v, 0);
  974. return val;
  975. }
  976. static bu32
  977. min2x16 (SIM_CPU *cpu, bu32 a, bu32 b)
  978. {
  979. int val = a;
  980. if ((bs16)a > (bs16)b)
  981. val = (val & 0xFFFF0000) | (b & 0xFFFF);
  982. if ((bs16)(a >> 16) > (bs16)(b >> 16))
  983. val = (val & 0xFFFF) | (b & 0xFFFF0000);
  984. setflags_nz_2x16 (cpu, val);
  985. SET_ASTATREG (v, 0);
  986. return val;
  987. }
  988. static bu32
  989. max2x16 (SIM_CPU *cpu, bu32 a, bu32 b)
  990. {
  991. int val = a;
  992. if ((bs16)a < (bs16)b)
  993. val = (val & 0xFFFF0000) | (b & 0xFFFF);
  994. if ((bs16)(a >> 16) < (bs16)(b >> 16))
  995. val = (val & 0xFFFF) | (b & 0xFFFF0000);
  996. setflags_nz_2x16 (cpu, val);
  997. SET_ASTATREG (v, 0);
  998. return val;
  999. }
  1000. static bu32
  1001. add_and_shift (SIM_CPU *cpu, bu32 a, bu32 b, int shift)
  1002. {
  1003. int v;
  1004. ASTATREG (v_internal) = 0;
  1005. v = add32 (cpu, a, b, 0, 0);
  1006. while (shift-- > 0)
  1007. {
  1008. int x = (v >> 30) & 0x3;
  1009. if (x == 1 || x == 2)
  1010. ASTATREG (v_internal) = 1;
  1011. v <<= 1;
  1012. }
  1013. SET_ASTATREG (az, v == 0);
  1014. SET_ASTATREG (an, v & 0x80000000);
  1015. SET_ASTATREG (v, ASTATREG (v_internal));
  1016. if (ASTATREG (v))
  1017. SET_ASTATREG (vs, 1);
  1018. return v;
  1019. }
  1020. static bu32
  1021. xor_reduce (bu64 acc0, bu64 acc1)
  1022. {
  1023. int i;
  1024. bu32 v = 0;
  1025. for (i = 0; i < 40; ++i)
  1026. {
  1027. v ^= (acc0 & acc1 & 1);
  1028. acc0 >>= 1;
  1029. acc1 >>= 1;
  1030. }
  1031. return v;
  1032. }
  1033. /* DIVS ( Dreg, Dreg ) ;
  1034. Initialize for DIVQ. Set the AQ status bit based on the signs of
  1035. the 32-bit dividend and the 16-bit divisor. Left shift the dividend
  1036. one bit. Copy AQ into the dividend LSB. */
  1037. static bu32
  1038. divs (SIM_CPU *cpu, bu32 pquo, bu16 divisor)
  1039. {
  1040. bu16 r = pquo >> 16;
  1041. int aq;
  1042. aq = (r ^ divisor) >> 15; /* Extract msb's and compute quotient bit. */
  1043. SET_ASTATREG (aq, aq); /* Update global quotient state. */
  1044. pquo <<= 1;
  1045. pquo |= aq;
  1046. pquo = (pquo & 0x1FFFF) | (r << 17);
  1047. return pquo;
  1048. }
  1049. /* DIVQ ( Dreg, Dreg ) ;
  1050. Based on AQ status bit, either add or subtract the divisor from
  1051. the dividend. Then set the AQ status bit based on the MSBs of the
  1052. 32-bit dividend and the 16-bit divisor. Left shift the dividend one
  1053. bit. Copy the logical inverse of AQ into the dividend LSB. */
  1054. static bu32
  1055. divq (SIM_CPU *cpu, bu32 pquo, bu16 divisor)
  1056. {
  1057. unsigned short af = pquo >> 16;
  1058. unsigned short r;
  1059. int aq;
  1060. if (ASTATREG (aq))
  1061. r = divisor + af;
  1062. else
  1063. r = af - divisor;
  1064. aq = (r ^ divisor) >> 15; /* Extract msb's and compute quotient bit. */
  1065. SET_ASTATREG (aq, aq); /* Update global quotient state. */
  1066. pquo <<= 1;
  1067. pquo |= !aq;
  1068. pquo = (pquo & 0x1FFFF) | (r << 17);
  1069. return pquo;
  1070. }
  1071. /* ONES ( Dreg ) ;
  1072. Count the number of bits set to 1 in the 32bit value. */
  1073. static bu32
  1074. ones (bu32 val)
  1075. {
  1076. bu32 i;
  1077. bu32 ret;
  1078. ret = 0;
  1079. for (i = 0; i < 32; ++i)
  1080. ret += !!(val & (1 << i));
  1081. return ret;
  1082. }
  1083. static void
  1084. reg_check_sup (SIM_CPU *cpu, int grp, int reg)
  1085. {
  1086. if (grp == 7)
  1087. cec_require_supervisor (cpu);
  1088. }
  1089. static void
  1090. reg_write (SIM_CPU *cpu, int grp, int reg, bu32 value)
  1091. {
  1092. bu32 *whichreg;
  1093. /* ASTAT is special! */
  1094. if (grp == 4 && reg == 6)
  1095. {
  1096. SET_ASTAT (value);
  1097. return;
  1098. }
  1099. /* Check supervisor after get_allreg() so exception order is correct. */
  1100. whichreg = get_allreg (cpu, grp, reg);
  1101. reg_check_sup (cpu, grp, reg);
  1102. if (whichreg == &CYCLES2REG)
  1103. /* Writes to CYCLES2 goes to the shadow. */
  1104. whichreg = &CYCLES2SHDREG;
  1105. else if (whichreg == &SEQSTATREG)
  1106. /* Register is read only -- discard writes. */
  1107. return;
  1108. else if (whichreg == &EMUDAT_INREG)
  1109. /* Writes to EMUDAT goes to the output. */
  1110. whichreg = &EMUDAT_OUTREG;
  1111. else if (whichreg == &LTREG (0) || whichreg == &LTREG (1))
  1112. /* Writes to LT clears LSB automatically. */
  1113. value &= ~0x1;
  1114. else if (whichreg == &AXREG (0) || whichreg == &AXREG (1))
  1115. value &= 0xFF;
  1116. TRACE_REGISTER (cpu, "wrote %s = %#x", get_allreg_name (grp, reg), value);
  1117. *whichreg = value;
  1118. }
  1119. static bu32
  1120. reg_read (SIM_CPU *cpu, int grp, int reg)
  1121. {
  1122. bu32 *whichreg;
  1123. bu32 value;
  1124. /* ASTAT is special! */
  1125. if (grp == 4 && reg == 6)
  1126. return ASTAT;
  1127. /* Check supervisor after get_allreg() so exception order is correct. */
  1128. whichreg = get_allreg (cpu, grp, reg);
  1129. reg_check_sup (cpu, grp, reg);
  1130. value = *whichreg;
  1131. if (whichreg == &CYCLESREG)
  1132. /* Reads of CYCLES reloads CYCLES2 from the shadow. */
  1133. SET_CYCLES2REG (CYCLES2SHDREG);
  1134. else if ((whichreg == &AXREG (1) || whichreg == &AXREG (0)) && (value & 0x80))
  1135. /* Sign extend if necessary. */
  1136. value |= 0xFFFFFF00;
  1137. return value;
  1138. }
  1139. static bu64
  1140. get_extended_cycles (SIM_CPU *cpu)
  1141. {
  1142. return ((bu64)CYCLES2SHDREG << 32) | CYCLESREG;
  1143. }
  1144. /* We can't re-use sim_events_time() because the CYCLES registers may be
  1145. written/cleared/reset/stopped/started at any time by software. */
  1146. static void
  1147. cycles_inc (SIM_CPU *cpu, bu32 inc)
  1148. {
  1149. bu64 cycles;
  1150. bu32 cycles2;
  1151. if (!(SYSCFGREG & SYSCFG_CCEN))
  1152. return;
  1153. cycles = get_extended_cycles (cpu) + inc;
  1154. SET_CYCLESREG (cycles);
  1155. cycles2 = cycles >> 32;
  1156. if (CYCLES2SHDREG != cycles2)
  1157. SET_CYCLES2SHDREG (cycles2);
  1158. }
  1159. static bu64
  1160. get_unextended_acc (SIM_CPU *cpu, int which)
  1161. {
  1162. return ((bu64)(AXREG (which) & 0xff) << 32) | AWREG (which);
  1163. }
  1164. static bu64
  1165. get_extended_acc (SIM_CPU *cpu, int which)
  1166. {
  1167. bu64 acc = AXREG (which);
  1168. /* Sign extend accumulator values before adding. */
  1169. if (acc & 0x80)
  1170. acc |= -0x80;
  1171. else
  1172. acc &= 0xFF;
  1173. acc <<= 32;
  1174. acc |= AWREG (which);
  1175. return acc;
  1176. }
  1177. /* Perform a multiplication of D registers SRC0 and SRC1, sign- or
  1178. zero-extending the result to 64 bit. H0 and H1 determine whether the
  1179. high part or the low part of the source registers is used. Store 1 in
  1180. *PSAT if saturation occurs, 0 otherwise. */
  1181. static bu64
  1182. decode_multfunc (SIM_CPU *cpu, int h0, int h1, int src0, int src1, int mmod,
  1183. int MM, bu32 *psat)
  1184. {
  1185. bu32 s0 = DREG (src0), s1 = DREG (src1);
  1186. bu32 sgn0, sgn1;
  1187. bu32 val;
  1188. bu64 val1;
  1189. if (h0)
  1190. s0 >>= 16;
  1191. if (h1)
  1192. s1 >>= 16;
  1193. s0 &= 0xffff;
  1194. s1 &= 0xffff;
  1195. sgn0 = -(s0 & 0x8000);
  1196. sgn1 = -(s1 & 0x8000);
  1197. if (MM)
  1198. s0 |= sgn0;
  1199. else
  1200. switch (mmod)
  1201. {
  1202. case 0:
  1203. case M_S2RND:
  1204. case M_T:
  1205. case M_IS:
  1206. case M_ISS2:
  1207. case M_IH:
  1208. case M_W32:
  1209. s0 |= sgn0;
  1210. s1 |= sgn1;
  1211. break;
  1212. case M_FU:
  1213. case M_IU:
  1214. case M_TFU:
  1215. break;
  1216. default:
  1217. illegal_instruction (cpu);
  1218. }
  1219. val = s0 * s1;
  1220. /* Perform shift correction if appropriate for the mode. */
  1221. *psat = 0;
  1222. if (!MM && (mmod == 0 || mmod == M_T || mmod == M_S2RND || mmod == M_W32))
  1223. {
  1224. if (val == 0x40000000)
  1225. {
  1226. if (mmod == M_W32)
  1227. val = 0x7fffffff;
  1228. else
  1229. val = 0x80000000;
  1230. *psat = 1;
  1231. }
  1232. else
  1233. val <<= 1;
  1234. }
  1235. val1 = val;
  1236. /* In signed modes, sign extend. */
  1237. if (is_macmod_signed (mmod) || MM)
  1238. val1 |= -(val1 & 0x80000000);
  1239. if (*psat)
  1240. val1 &= 0xFFFFFFFFull;
  1241. return val1;
  1242. }
  1243. static bu40
  1244. saturate_s40_astat (bu64 val, bu32 *v)
  1245. {
  1246. if ((bs64)val < -((bs64)1 << 39))
  1247. {
  1248. *v = 1;
  1249. return -((bs64)1 << 39);
  1250. }
  1251. else if ((bs64)val > ((bs64)1 << 39) - 1)
  1252. {
  1253. *v = 1;
  1254. return ((bu64)1 << 39) - 1;
  1255. }
  1256. *v = 0; /* No overflow. */
  1257. return val;
  1258. }
  1259. static bu40
  1260. saturate_s40 (bu64 val)
  1261. {
  1262. bu32 v;
  1263. return saturate_s40_astat (val, &v);
  1264. }
  1265. static bu32
  1266. saturate_s32 (bu64 val, bu32 *overflow)
  1267. {
  1268. if ((bs64)val < -0x80000000ll)
  1269. {
  1270. if (overflow)
  1271. *overflow = 1;
  1272. return 0x80000000;
  1273. }
  1274. if ((bs64)val > 0x7fffffff)
  1275. {
  1276. if (overflow)
  1277. *overflow = 1;
  1278. return 0x7fffffff;
  1279. }
  1280. return val;
  1281. }
  1282. static bu32
  1283. saturate_u32 (bu64 val, bu32 *overflow)
  1284. {
  1285. if (val > 0xffffffff)
  1286. {
  1287. if (overflow)
  1288. *overflow = 1;
  1289. return 0xffffffff;
  1290. }
  1291. return val;
  1292. }
  1293. static bu32
  1294. saturate_u16 (bu64 val, bu32 *overflow)
  1295. {
  1296. if (val > 0xffff)
  1297. {
  1298. if (overflow)
  1299. *overflow = 1;
  1300. return 0xffff;
  1301. }
  1302. return val;
  1303. }
  1304. static bu64
  1305. rnd16 (bu64 val)
  1306. {
  1307. bu64 sgnbits;
  1308. /* FIXME: Should honour rounding mode. */
  1309. if ((val & 0xffff) > 0x8000
  1310. || ((val & 0xffff) == 0x8000 && (val & 0x10000)))
  1311. val += 0x8000;
  1312. sgnbits = val & 0xffff000000000000ull;
  1313. val >>= 16;
  1314. return val | sgnbits;
  1315. }
  1316. static bu64
  1317. trunc16 (bu64 val)
  1318. {
  1319. bu64 sgnbits = val & 0xffff000000000000ull;
  1320. val >>= 16;
  1321. return val | sgnbits;
  1322. }
  1323. static int
  1324. signbits (bu64 val, int size)
  1325. {
  1326. bu64 mask = (bu64)1 << (size - 1);
  1327. bu64 bit = val & mask;
  1328. int count = 0;
  1329. for (;;)
  1330. {
  1331. mask >>= 1;
  1332. bit >>= 1;
  1333. if (mask == 0)
  1334. break;
  1335. if ((val & mask) != bit)
  1336. break;
  1337. count++;
  1338. }
  1339. if (size == 40)
  1340. count -= 8;
  1341. return count;
  1342. }
  1343. /* Extract a 16 or 32 bit value from a 64 bit multiplication result.
  1344. These 64 bits must be sign- or zero-extended properly from the source
  1345. we want to extract, either a 32 bit multiply or a 40 bit accumulator. */
  1346. static bu32
  1347. extract_mult (SIM_CPU *cpu, bu64 res, int mmod, int MM,
  1348. int fullword, bu32 *overflow)
  1349. {
  1350. if (fullword)
  1351. switch (mmod)
  1352. {
  1353. case 0:
  1354. case M_IS:
  1355. return saturate_s32 (res, overflow);
  1356. case M_IU:
  1357. if (MM)
  1358. return saturate_s32 (res, overflow);
  1359. return saturate_u32 (res, overflow);
  1360. case M_FU:
  1361. if (MM)
  1362. return saturate_s32 (res, overflow);
  1363. return saturate_u32 (res, overflow);
  1364. case M_S2RND:
  1365. case M_ISS2:
  1366. return saturate_s32 (res << 1, overflow);
  1367. default:
  1368. illegal_instruction (cpu);
  1369. }
  1370. else
  1371. switch (mmod)
  1372. {
  1373. case 0:
  1374. case M_W32:
  1375. case M_IH:
  1376. return saturate_s16 (rnd16 (res), overflow);
  1377. case M_IS:
  1378. return saturate_s16 (res, overflow);
  1379. case M_FU:
  1380. if (MM)
  1381. return saturate_s16 (rnd16 (res), overflow);
  1382. return saturate_u16 (rnd16 (res), overflow);
  1383. case M_IU:
  1384. if (MM)
  1385. return saturate_s16 (res, overflow);
  1386. return saturate_u16 (res, overflow);
  1387. case M_T:
  1388. return saturate_s16 (trunc16 (res), overflow);
  1389. case M_TFU:
  1390. if (MM)
  1391. return saturate_s16 (trunc16 (res), overflow);
  1392. return saturate_u16 (trunc16 (res), overflow);
  1393. case M_S2RND:
  1394. return saturate_s16 (rnd16 (res << 1), overflow);
  1395. case M_ISS2:
  1396. return saturate_s16 (res << 1, overflow);
  1397. default:
  1398. illegal_instruction (cpu);
  1399. }
  1400. }
  1401. static bu32
  1402. decode_macfunc (SIM_CPU *cpu, int which, int op, int h0, int h1, int src0,
  1403. int src1, int mmod, int MM, int fullword, bu32 *overflow,
  1404. bu32 *neg)
  1405. {
  1406. bu64 acc;
  1407. bu32 sat = 0, tsat, ret;
  1408. /* Sign extend accumulator if necessary, otherwise unsigned. */
  1409. if (is_macmod_signed (mmod) || MM)
  1410. acc = get_extended_acc (cpu, which);
  1411. else
  1412. acc = get_unextended_acc (cpu, which);
  1413. if (op != 3)
  1414. {
  1415. bu8 sgn0 = (acc >> 31) & 1;
  1416. bu8 sgn40 = (acc >> 39) & 1;
  1417. bu40 nosat_acc;
  1418. /* This can't saturate, so we don't keep track of the sat flag. */
  1419. bu64 res = decode_multfunc (cpu, h0, h1, src0, src1, mmod,
  1420. MM, &tsat);
  1421. /* Perform accumulation. */
  1422. switch (op)
  1423. {
  1424. case 0:
  1425. acc = res;
  1426. sgn0 = (acc >> 31) & 1;
  1427. break;
  1428. case 1:
  1429. acc = acc + res;
  1430. break;
  1431. case 2:
  1432. acc = acc - res;
  1433. break;
  1434. }
  1435. nosat_acc = acc;
  1436. /* Saturate. */
  1437. switch (mmod)
  1438. {
  1439. case 0:
  1440. case M_T:
  1441. case M_IS:
  1442. case M_ISS2:
  1443. case M_S2RND:
  1444. if ((bs64)acc < -((bs64)1 << 39))
  1445. acc = -((bu64)1 << 39), sat = 1;
  1446. else if ((bs64)acc > 0x7fffffffffll)
  1447. acc = 0x7fffffffffull, sat = 1;
  1448. break;
  1449. case M_TFU:
  1450. if (MM)
  1451. {
  1452. if ((bs64)acc < -((bs64)1 << 39))
  1453. acc = -((bu64)1 << 39), sat = 1;
  1454. if ((bs64)acc > 0x7FFFFFFFFFll)
  1455. acc = 0x7FFFFFFFFFull, sat = 1;
  1456. }
  1457. else
  1458. {
  1459. if ((bs64)acc < 0)
  1460. acc = 0, sat = 1;
  1461. if ((bs64)acc > 0xFFFFFFFFFFull)
  1462. acc = 0xFFFFFFFFFFull, sat = 1;
  1463. }
  1464. break;
  1465. case M_IU:
  1466. if (!MM && acc & 0x8000000000000000ull)
  1467. acc = 0x0, sat = 1;
  1468. if (!MM && acc > 0xFFFFFFFFFFull)
  1469. acc = 0xFFFFFFFFFFull, sat = 1;
  1470. if (MM && acc > 0xFFFFFFFFFFull)
  1471. acc &= 0xFFFFFFFFFFull;
  1472. if (acc & 0x8000000000ull)
  1473. acc |= 0xffffff0000000000ull;
  1474. break;
  1475. case M_FU:
  1476. if (MM)
  1477. {
  1478. if ((bs64)acc < -((bs64)1 << 39))
  1479. acc = -((bu64)1 << 39), sat = 1;
  1480. if ((bs64)acc > 0x7FFFFFFFFFll)
  1481. acc = 0x7FFFFFFFFFull, sat = 1;
  1482. else if (acc & 0x8000000000ull)
  1483. acc |= 0xffffff0000000000ull;
  1484. }
  1485. else
  1486. {
  1487. if ((bs64)acc < 0)
  1488. acc = 0x0, sat = 1;
  1489. else if ((bs64)acc > (bs64)0xFFFFFFFFFFll)
  1490. acc = 0xFFFFFFFFFFull, sat = 1;
  1491. }
  1492. break;
  1493. case M_IH:
  1494. if ((bs64)acc < -0x80000000ll)
  1495. acc = -0x80000000ull, sat = 1;
  1496. else if ((bs64)acc > 0x7fffffffll)
  1497. acc = 0x7fffffffull, sat = 1;
  1498. break;
  1499. case M_W32:
  1500. /* check max negative value */
  1501. if (sgn40 && ((acc >> 31) != 0x1ffffffff)
  1502. && ((acc >> 31) != 0x0))
  1503. acc = 0x80000000, sat = 1;
  1504. if (!sat && !sgn40 && ((acc >> 31) != 0x0)
  1505. && ((acc >> 31) != 0x1ffffffff))
  1506. acc = 0x7FFFFFFF, sat = 1;
  1507. acc &= 0xffffffff;
  1508. if (acc & 0x80000000)
  1509. acc |= 0xffffffff00000000ull;
  1510. if (tsat)
  1511. sat = 1;
  1512. break;
  1513. default:
  1514. illegal_instruction (cpu);
  1515. }
  1516. if (acc & 0x8000000000ull)
  1517. *neg = 1;
  1518. STORE (AXREG (which), (acc >> 32) & 0xff);
  1519. STORE (AWREG (which), acc & 0xffffffff);
  1520. STORE (ASTATREG (av[which]), sat);
  1521. if (sat)
  1522. STORE (ASTATREG (avs[which]), sat);
  1523. /* Figure out the overflow bit. */
  1524. if (sat)
  1525. {
  1526. if (fullword)
  1527. *overflow = 1;
  1528. else
  1529. ret = extract_mult (cpu, nosat_acc, mmod, MM, fullword, overflow);
  1530. }
  1531. }
  1532. ret = extract_mult (cpu, acc, mmod, MM, fullword, overflow);
  1533. if (!fullword)
  1534. {
  1535. if (ret & 0x8000)
  1536. *neg = 1;
  1537. }
  1538. else
  1539. {
  1540. if (ret & 0x80000000)
  1541. *neg = 1;
  1542. }
  1543. return ret;
  1544. }
  1545. bu32
  1546. hwloop_get_next_pc (SIM_CPU *cpu, bu32 pc, bu32 insn_len)
  1547. {
  1548. int i;
  1549. if (insn_len == 0)
  1550. return pc;
  1551. /* If our PC has reached the bottom of a hardware loop,
  1552. move back up to the top of the hardware loop. */
  1553. for (i = 1; i >= 0; --i)
  1554. if (LCREG (i) > 1 && pc == LBREG (i))
  1555. {
  1556. BFIN_TRACE_BRANCH (cpu, pc, LTREG (i), i, "Hardware loop %i", i);
  1557. return LTREG (i);
  1558. }
  1559. return pc + insn_len;
  1560. }
  1561. static void
  1562. decode_ProgCtrl_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
  1563. {
  1564. /* ProgCtrl
  1565. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  1566. | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.prgfunc.......|.poprnd........|
  1567. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  1568. int poprnd = ((iw0 >> ProgCtrl_poprnd_bits) & ProgCtrl_poprnd_mask);
  1569. int prgfunc = ((iw0 >> ProgCtrl_prgfunc_bits) & ProgCtrl_prgfunc_mask);
  1570. TRACE_EXTRACT (cpu, "%s: poprnd:%i prgfunc:%i", __func__, poprnd, prgfunc);
  1571. if (prgfunc == 0 && poprnd == 0)
  1572. {
  1573. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_nop);
  1574. TRACE_INSN (cpu, "NOP;");
  1575. }
  1576. else if (prgfunc == 1 && poprnd == 0)
  1577. {
  1578. bu32 newpc = RETSREG;
  1579. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
  1580. TRACE_INSN (cpu, "RTS;");
  1581. IFETCH_CHECK (newpc);
  1582. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1583. illegal_instruction_combination (cpu);
  1584. BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "RTS");
  1585. SET_PCREG (newpc);
  1586. BFIN_CPU_STATE.did_jump = true;
  1587. CYCLE_DELAY = 5;
  1588. }
  1589. else if (prgfunc == 1 && poprnd == 1)
  1590. {
  1591. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
  1592. TRACE_INSN (cpu, "RTI;");
  1593. /* Do not do IFETCH_CHECK here -- LSB has special meaning. */
  1594. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1595. illegal_instruction_combination (cpu);
  1596. cec_return (cpu, -1);
  1597. CYCLE_DELAY = 5;
  1598. }
  1599. else if (prgfunc == 1 && poprnd == 2)
  1600. {
  1601. bu32 newpc = RETXREG;
  1602. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
  1603. TRACE_INSN (cpu, "RTX;");
  1604. /* XXX: Not sure if this is what the hardware does. */
  1605. IFETCH_CHECK (newpc);
  1606. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1607. illegal_instruction_combination (cpu);
  1608. cec_return (cpu, IVG_EVX);
  1609. CYCLE_DELAY = 5;
  1610. }
  1611. else if (prgfunc == 1 && poprnd == 3)
  1612. {
  1613. bu32 newpc = RETNREG;
  1614. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
  1615. TRACE_INSN (cpu, "RTN;");
  1616. /* XXX: Not sure if this is what the hardware does. */
  1617. IFETCH_CHECK (newpc);
  1618. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1619. illegal_instruction_combination (cpu);
  1620. cec_return (cpu, IVG_NMI);
  1621. CYCLE_DELAY = 5;
  1622. }
  1623. else if (prgfunc == 1 && poprnd == 4)
  1624. {
  1625. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
  1626. TRACE_INSN (cpu, "RTE;");
  1627. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1628. illegal_instruction_combination (cpu);
  1629. cec_return (cpu, IVG_EMU);
  1630. CYCLE_DELAY = 5;
  1631. }
  1632. else if (prgfunc == 2 && poprnd == 0)
  1633. {
  1634. SIM_DESC sd = CPU_STATE (cpu);
  1635. sim_events *events = STATE_EVENTS (sd);
  1636. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
  1637. /* XXX: in supervisor mode, utilizes wake up sources
  1638. in user mode, it's a NOP ... */
  1639. TRACE_INSN (cpu, "IDLE;");
  1640. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1641. illegal_instruction_combination (cpu);
  1642. /* Timewarp ! */
  1643. if (events->queue)
  1644. CYCLE_DELAY = events->time_from_event;
  1645. else
  1646. abort (); /* XXX: Should this ever happen ? */
  1647. }
  1648. else if (prgfunc == 2 && poprnd == 3)
  1649. {
  1650. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
  1651. /* Just NOP it. */
  1652. TRACE_INSN (cpu, "CSYNC;");
  1653. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1654. illegal_instruction_combination (cpu);
  1655. CYCLE_DELAY = 10;
  1656. }
  1657. else if (prgfunc == 2 && poprnd == 4)
  1658. {
  1659. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_sync);
  1660. /* Just NOP it. */
  1661. TRACE_INSN (cpu, "SSYNC;");
  1662. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1663. illegal_instruction_combination (cpu);
  1664. /* Really 10+, but no model info for this. */
  1665. CYCLE_DELAY = 10;
  1666. }
  1667. else if (prgfunc == 2 && poprnd == 5)
  1668. {
  1669. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
  1670. TRACE_INSN (cpu, "EMUEXCPT;");
  1671. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1672. illegal_instruction_combination (cpu);
  1673. cec_exception (cpu, VEC_SIM_TRAP);
  1674. }
  1675. else if (prgfunc == 3 && poprnd < 8)
  1676. {
  1677. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
  1678. TRACE_INSN (cpu, "CLI R%i;", poprnd);
  1679. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1680. illegal_instruction_combination (cpu);
  1681. SET_DREG (poprnd, cec_cli (cpu));
  1682. }
  1683. else if (prgfunc == 4 && poprnd < 8)
  1684. {
  1685. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
  1686. TRACE_INSN (cpu, "STI R%i;", poprnd);
  1687. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1688. illegal_instruction_combination (cpu);
  1689. cec_sti (cpu, DREG (poprnd));
  1690. CYCLE_DELAY = 3;
  1691. }
  1692. else if (prgfunc == 5 && poprnd < 8)
  1693. {
  1694. bu32 newpc = PREG (poprnd);
  1695. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
  1696. TRACE_INSN (cpu, "JUMP (%s);", get_preg_name (poprnd));
  1697. IFETCH_CHECK (newpc);
  1698. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1699. illegal_instruction_combination (cpu);
  1700. BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP (Preg)");
  1701. SET_PCREG (newpc);
  1702. BFIN_CPU_STATE.did_jump = true;
  1703. PROFILE_BRANCH_TAKEN (cpu);
  1704. CYCLE_DELAY = 5;
  1705. }
  1706. else if (prgfunc == 6 && poprnd < 8)
  1707. {
  1708. bu32 newpc = PREG (poprnd);
  1709. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
  1710. TRACE_INSN (cpu, "CALL (%s);", get_preg_name (poprnd));
  1711. IFETCH_CHECK (newpc);
  1712. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1713. illegal_instruction_combination (cpu);
  1714. BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "CALL (Preg)");
  1715. /* If we're at the end of a hardware loop, RETS is going to be
  1716. the top of the loop rather than the next instruction. */
  1717. SET_RETSREG (hwloop_get_next_pc (cpu, pc, 2));
  1718. SET_PCREG (newpc);
  1719. BFIN_CPU_STATE.did_jump = true;
  1720. PROFILE_BRANCH_TAKEN (cpu);
  1721. CYCLE_DELAY = 5;
  1722. }
  1723. else if (prgfunc == 7 && poprnd < 8)
  1724. {
  1725. bu32 newpc = pc + PREG (poprnd);
  1726. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
  1727. TRACE_INSN (cpu, "CALL (PC + %s);", get_preg_name (poprnd));
  1728. IFETCH_CHECK (newpc);
  1729. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1730. illegal_instruction_combination (cpu);
  1731. BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "CALL (PC + Preg)");
  1732. SET_RETSREG (hwloop_get_next_pc (cpu, pc, 2));
  1733. SET_PCREG (newpc);
  1734. BFIN_CPU_STATE.did_jump = true;
  1735. PROFILE_BRANCH_TAKEN (cpu);
  1736. CYCLE_DELAY = 5;
  1737. }
  1738. else if (prgfunc == 8 && poprnd < 8)
  1739. {
  1740. bu32 newpc = pc + PREG (poprnd);
  1741. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_branch);
  1742. TRACE_INSN (cpu, "JUMP (PC + %s);", get_preg_name (poprnd));
  1743. IFETCH_CHECK (newpc);
  1744. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1745. illegal_instruction_combination (cpu);
  1746. BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP (PC + Preg)");
  1747. SET_PCREG (newpc);
  1748. BFIN_CPU_STATE.did_jump = true;
  1749. PROFILE_BRANCH_TAKEN (cpu);
  1750. CYCLE_DELAY = 5;
  1751. }
  1752. else if (prgfunc == 9)
  1753. {
  1754. int raise = uimm4 (poprnd);
  1755. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
  1756. TRACE_INSN (cpu, "RAISE %s;", uimm4_str (raise));
  1757. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1758. illegal_instruction_combination (cpu);
  1759. cec_require_supervisor (cpu);
  1760. if (raise == IVG_IVHW)
  1761. cec_hwerr (cpu, HWERR_RAISE_5);
  1762. else
  1763. cec_latch (cpu, raise);
  1764. CYCLE_DELAY = 3; /* XXX: Only if IVG is unmasked. */
  1765. }
  1766. else if (prgfunc == 10)
  1767. {
  1768. int excpt = uimm4 (poprnd);
  1769. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_cec);
  1770. TRACE_INSN (cpu, "EXCPT %s;", uimm4_str (excpt));
  1771. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1772. illegal_instruction_combination (cpu);
  1773. cec_exception (cpu, excpt);
  1774. CYCLE_DELAY = 3;
  1775. }
  1776. else if (prgfunc == 11 && poprnd < 6)
  1777. {
  1778. bu32 addr = PREG (poprnd);
  1779. bu8 byte;
  1780. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ProgCtrl_atomic);
  1781. TRACE_INSN (cpu, "TESTSET (%s);", get_preg_name (poprnd));
  1782. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1783. illegal_instruction_combination (cpu);
  1784. byte = GET_WORD (addr);
  1785. SET_CCREG (byte == 0);
  1786. PUT_BYTE (addr, byte | 0x80);
  1787. /* Also includes memory stalls, but we don't model that. */
  1788. CYCLE_DELAY = 2;
  1789. }
  1790. else
  1791. illegal_instruction_or_combination (cpu);
  1792. }
  1793. static void
  1794. decode_CaCTRL_0 (SIM_CPU *cpu, bu16 iw0)
  1795. {
  1796. /* CaCTRL
  1797. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  1798. | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 1 |.a.|.op....|.reg.......|
  1799. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  1800. int a = ((iw0 >> CaCTRL_a_bits) & CaCTRL_a_mask);
  1801. int op = ((iw0 >> CaCTRL_op_bits) & CaCTRL_op_mask);
  1802. int reg = ((iw0 >> CaCTRL_reg_bits) & CaCTRL_reg_mask);
  1803. bu32 preg = PREG (reg);
  1804. const char * const sinsn[] = { "PREFETCH", "FLUSHINV", "FLUSH", "IFLUSH", };
  1805. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CaCTRL);
  1806. TRACE_EXTRACT (cpu, "%s: a:%i op:%i reg:%i", __func__, a, op, reg);
  1807. TRACE_INSN (cpu, "%s [%s%s];", sinsn[op], get_preg_name (reg), a ? "++" : "");
  1808. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1809. /* None of these can be part of a parallel instruction. */
  1810. illegal_instruction_combination (cpu);
  1811. /* No cache simulation, so these are (mostly) all NOPs.
  1812. XXX: The hardware takes care of masking to cache lines, but need
  1813. to check behavior of the post increment. Should we be aligning
  1814. the value to the cache line before adding the cache line size, or
  1815. do we just add the cache line size ? */
  1816. if (op == 0)
  1817. { /* PREFETCH */
  1818. mmu_check_cache_addr (cpu, preg, false, false);
  1819. }
  1820. else if (op == 1)
  1821. { /* FLUSHINV */
  1822. mmu_check_cache_addr (cpu, preg, true, false);
  1823. }
  1824. else if (op == 2)
  1825. { /* FLUSH */
  1826. mmu_check_cache_addr (cpu, preg, true, false);
  1827. }
  1828. else if (op == 3)
  1829. { /* IFLUSH */
  1830. mmu_check_cache_addr (cpu, preg, false, true);
  1831. }
  1832. if (a)
  1833. SET_PREG (reg, preg + BFIN_L1_CACHE_BYTES);
  1834. }
  1835. static void
  1836. decode_PushPopReg_0 (SIM_CPU *cpu, bu16 iw0)
  1837. {
  1838. /* PushPopReg
  1839. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  1840. | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.W.|.grp.......|.reg.......|
  1841. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  1842. int W = ((iw0 >> PushPopReg_W_bits) & PushPopReg_W_mask);
  1843. int grp = ((iw0 >> PushPopReg_grp_bits) & PushPopReg_grp_mask);
  1844. int reg = ((iw0 >> PushPopReg_reg_bits) & PushPopReg_reg_mask);
  1845. const char *reg_name = get_allreg_name (grp, reg);
  1846. bu32 value;
  1847. bu32 sp = SPREG;
  1848. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PushPopReg);
  1849. TRACE_EXTRACT (cpu, "%s: W:%i grp:%i reg:%i", __func__, W, grp, reg);
  1850. TRACE_DECODE (cpu, "%s: reg:%s", __func__, reg_name);
  1851. /* Can't push/pop reserved registers */
  1852. if (reg_is_reserved (grp, reg))
  1853. illegal_instruction_or_combination (cpu);
  1854. if (W == 0)
  1855. {
  1856. /* Dreg and Preg are not supported by this instruction. */
  1857. if (grp == 0 || grp == 1)
  1858. illegal_instruction_or_combination (cpu);
  1859. TRACE_INSN (cpu, "%s = [SP++];", reg_name);
  1860. /* Can't pop USP while in userspace. */
  1861. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE
  1862. || (grp == 7 && reg == 0 && cec_is_user_mode(cpu)))
  1863. illegal_instruction_combination (cpu);
  1864. /* XXX: The valid register check is in reg_write(), so we might
  1865. incorrectly do a GET_LONG() here ... */
  1866. value = GET_LONG (sp);
  1867. reg_write (cpu, grp, reg, value);
  1868. if (grp == 7 && reg == 3)
  1869. cec_pop_reti (cpu);
  1870. sp += 4;
  1871. }
  1872. else
  1873. {
  1874. TRACE_INSN (cpu, "[--SP] = %s;", reg_name);
  1875. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1876. illegal_instruction_combination (cpu);
  1877. sp -= 4;
  1878. value = reg_read (cpu, grp, reg);
  1879. if (grp == 7 && reg == 3)
  1880. cec_push_reti (cpu);
  1881. PUT_LONG (sp, value);
  1882. }
  1883. /* Note: SP update must be delayed until after all reads/writes; see
  1884. comments in decode_PushPopMultiple_0() for more info. */
  1885. SET_SPREG (sp);
  1886. }
  1887. static void
  1888. decode_PushPopMultiple_0 (SIM_CPU *cpu, bu16 iw0)
  1889. {
  1890. /* PushPopMultiple
  1891. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  1892. | 0 | 0 | 0 | 0 | 0 | 1 | 0 |.d.|.p.|.W.|.dr........|.pr........|
  1893. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  1894. int p = ((iw0 >> PushPopMultiple_p_bits) & PushPopMultiple_p_mask);
  1895. int d = ((iw0 >> PushPopMultiple_d_bits) & PushPopMultiple_d_mask);
  1896. int W = ((iw0 >> PushPopMultiple_W_bits) & PushPopMultiple_W_mask);
  1897. int dr = ((iw0 >> PushPopMultiple_dr_bits) & PushPopMultiple_dr_mask);
  1898. int pr = ((iw0 >> PushPopMultiple_pr_bits) & PushPopMultiple_pr_mask);
  1899. int i;
  1900. bu32 sp = SPREG;
  1901. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PushPopMultiple);
  1902. TRACE_EXTRACT (cpu, "%s: d:%i p:%i W:%i dr:%i pr:%i",
  1903. __func__, d, p, W, dr, pr);
  1904. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1905. illegal_instruction_combination (cpu);
  1906. if ((d == 0 && p == 0) || (p && imm5 (pr) > 5)
  1907. || (d && !p && pr) || (p && !d && dr))
  1908. illegal_instruction (cpu);
  1909. if (W == 1)
  1910. {
  1911. if (d && p)
  1912. TRACE_INSN (cpu, "[--SP] = (R7:%i, P5:%i);", dr, pr);
  1913. else if (d)
  1914. TRACE_INSN (cpu, "[--SP] = (R7:%i);", dr);
  1915. else
  1916. TRACE_INSN (cpu, "[--SP] = (P5:%i);", pr);
  1917. if (d)
  1918. for (i = dr; i < 8; i++)
  1919. {
  1920. sp -= 4;
  1921. PUT_LONG (sp, DREG (i));
  1922. }
  1923. if (p)
  1924. for (i = pr; i < 6; i++)
  1925. {
  1926. sp -= 4;
  1927. PUT_LONG (sp, PREG (i));
  1928. }
  1929. CYCLE_DELAY = 14;
  1930. }
  1931. else
  1932. {
  1933. if (d && p)
  1934. TRACE_INSN (cpu, "(R7:%i, P5:%i) = [SP++];", dr, pr);
  1935. else if (d)
  1936. TRACE_INSN (cpu, "(R7:%i) = [SP++];", dr);
  1937. else
  1938. TRACE_INSN (cpu, "(P5:%i) = [SP++];", pr);
  1939. if (p)
  1940. for (i = 5; i >= pr; i--)
  1941. {
  1942. SET_PREG (i, GET_LONG (sp));
  1943. sp += 4;
  1944. }
  1945. if (d)
  1946. for (i = 7; i >= dr; i--)
  1947. {
  1948. SET_DREG (i, GET_LONG (sp));
  1949. sp += 4;
  1950. }
  1951. CYCLE_DELAY = 11;
  1952. }
  1953. /* Note: SP update must be delayed until after all reads/writes so that
  1954. if an exception does occur, the insn may be re-executed as the
  1955. SP has not yet changed. */
  1956. SET_SPREG (sp);
  1957. }
  1958. static void
  1959. decode_ccMV_0 (SIM_CPU *cpu, bu16 iw0)
  1960. {
  1961. /* ccMV
  1962. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  1963. | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.T.|.d.|.s.|.dst.......|.src.......|
  1964. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  1965. int s = ((iw0 >> CCmv_s_bits) & CCmv_s_mask);
  1966. int d = ((iw0 >> CCmv_d_bits) & CCmv_d_mask);
  1967. int T = ((iw0 >> CCmv_T_bits) & CCmv_T_mask);
  1968. int src = ((iw0 >> CCmv_src_bits) & CCmv_src_mask);
  1969. int dst = ((iw0 >> CCmv_dst_bits) & CCmv_dst_mask);
  1970. int cond = T ? CCREG : ! CCREG;
  1971. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ccMV);
  1972. TRACE_EXTRACT (cpu, "%s: T:%i d:%i s:%i dst:%i src:%i",
  1973. __func__, T, d, s, dst, src);
  1974. TRACE_INSN (cpu, "IF %sCC %s = %s;", T ? "" : "! ",
  1975. get_allreg_name (d, dst),
  1976. get_allreg_name (s, src));
  1977. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  1978. illegal_instruction_combination (cpu);
  1979. if (cond)
  1980. reg_write (cpu, d, dst, reg_read (cpu, s, src));
  1981. }
  1982. static void
  1983. decode_CCflag_0 (SIM_CPU *cpu, bu16 iw0)
  1984. {
  1985. /* CCflag
  1986. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  1987. | 0 | 0 | 0 | 0 | 1 |.I.|.opc.......|.G.|.y.........|.x.........|
  1988. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  1989. int x = ((iw0 >> CCflag_x_bits) & CCflag_x_mask);
  1990. int y = ((iw0 >> CCflag_y_bits) & CCflag_y_mask);
  1991. int I = ((iw0 >> CCflag_I_bits) & CCflag_I_mask);
  1992. int G = ((iw0 >> CCflag_G_bits) & CCflag_G_mask);
  1993. int opc = ((iw0 >> CCflag_opc_bits) & CCflag_opc_mask);
  1994. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CCflag);
  1995. TRACE_EXTRACT (cpu, "%s: I:%i opc:%i G:%i y:%i x:%i",
  1996. __func__, I, opc, G, y, x);
  1997. if (opc > 4)
  1998. {
  1999. bs64 acc0 = get_extended_acc (cpu, 0);
  2000. bs64 acc1 = get_extended_acc (cpu, 1);
  2001. bs64 diff = acc0 - acc1;
  2002. if (x != 0 || y != 0)
  2003. illegal_instruction_or_combination (cpu);
  2004. if (opc == 5 && I == 0 && G == 0)
  2005. {
  2006. TRACE_INSN (cpu, "CC = A0 == A1;");
  2007. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2008. illegal_instruction_combination (cpu);
  2009. SET_CCREG (acc0 == acc1);
  2010. }
  2011. else if (opc == 6 && I == 0 && G == 0)
  2012. {
  2013. TRACE_INSN (cpu, "CC = A0 < A1");
  2014. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2015. illegal_instruction_combination (cpu);
  2016. SET_CCREG (acc0 < acc1);
  2017. }
  2018. else if (opc == 7 && I == 0 && G == 0)
  2019. {
  2020. TRACE_INSN (cpu, "CC = A0 <= A1");
  2021. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2022. illegal_instruction_combination (cpu);
  2023. SET_CCREG (acc0 <= acc1);
  2024. }
  2025. else
  2026. illegal_instruction_or_combination (cpu);
  2027. SET_ASTATREG (az, diff == 0);
  2028. SET_ASTATREG (an, diff < 0);
  2029. SET_ASTATREG (ac0, (bu40)acc1 <= (bu40)acc0);
  2030. }
  2031. else
  2032. {
  2033. int issigned = opc < 3;
  2034. const char *sign = issigned ? "" : " (IU)";
  2035. bu32 srcop = G ? PREG (x) : DREG (x);
  2036. char s = G ? 'P' : 'R';
  2037. bu32 dstop = I ? (issigned ? imm3 (y) : uimm3 (y)) : G ? PREG (y) : DREG (y);
  2038. const char *op;
  2039. char d = G ? 'P' : 'R';
  2040. int flgs = srcop >> 31;
  2041. int flgo = dstop >> 31;
  2042. bu32 result = srcop - dstop;
  2043. int cc;
  2044. int flgn = result >> 31;
  2045. int overflow = (flgs ^ flgo) & (flgn ^ flgs);
  2046. int az = result == 0;
  2047. int ac0 = dstop <= srcop;
  2048. int an;
  2049. if (issigned)
  2050. an = (flgn && !overflow) || (!flgn && overflow);
  2051. else
  2052. an = dstop > srcop;
  2053. switch (opc)
  2054. {
  2055. default: /* Shutup useless gcc warnings. */
  2056. case 0: /* signed */
  2057. op = "==";
  2058. cc = az;
  2059. break;
  2060. case 1: /* signed */
  2061. op = "<";
  2062. cc = an;
  2063. break;
  2064. case 2: /* signed */
  2065. op = "<=";
  2066. cc = an || az;
  2067. break;
  2068. case 3: /* unsigned */
  2069. op = "<";
  2070. cc = !ac0;
  2071. break;
  2072. case 4: /* unsigned */
  2073. op = "<=";
  2074. cc = !ac0 || az;
  2075. break;
  2076. }
  2077. if (I)
  2078. TRACE_INSN (cpu, "CC = %c%i %s %s%s;", s, x, op,
  2079. issigned ? imm3_str (y) : uimm3_str (y), sign);
  2080. else
  2081. {
  2082. TRACE_DECODE (cpu, "%s %c%i:%x %c%i:%x", __func__,
  2083. s, x, srcop, d, y, dstop);
  2084. TRACE_INSN (cpu, "CC = %c%i %s %c%i%s;", s, x, op, d, y, sign);
  2085. }
  2086. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2087. illegal_instruction_combination (cpu);
  2088. SET_CCREG (cc);
  2089. /* Pointer compares only touch CC. */
  2090. if (!G)
  2091. {
  2092. SET_ASTATREG (az, az);
  2093. SET_ASTATREG (an, an);
  2094. SET_ASTATREG (ac0, ac0);
  2095. }
  2096. }
  2097. }
  2098. static void
  2099. decode_CC2dreg_0 (SIM_CPU *cpu, bu16 iw0)
  2100. {
  2101. /* CC2dreg
  2102. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2103. | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 |.op....|.reg.......|
  2104. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2105. int op = ((iw0 >> CC2dreg_op_bits) & CC2dreg_op_mask);
  2106. int reg = ((iw0 >> CC2dreg_reg_bits) & CC2dreg_reg_mask);
  2107. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CC2dreg);
  2108. TRACE_EXTRACT (cpu, "%s: op:%i reg:%i", __func__, op, reg);
  2109. if (op == 0)
  2110. {
  2111. TRACE_INSN (cpu, "R%i = CC;", reg);
  2112. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2113. illegal_instruction_combination (cpu);
  2114. SET_DREG (reg, CCREG);
  2115. }
  2116. else if (op == 1)
  2117. {
  2118. TRACE_INSN (cpu, "CC = R%i;", reg);
  2119. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2120. illegal_instruction_combination (cpu);
  2121. SET_CCREG (DREG (reg) != 0);
  2122. }
  2123. else if (op == 3 && reg == 0)
  2124. {
  2125. TRACE_INSN (cpu, "CC = !CC;");
  2126. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2127. illegal_instruction_combination (cpu);
  2128. SET_CCREG (!CCREG);
  2129. }
  2130. else
  2131. illegal_instruction_or_combination (cpu);
  2132. }
  2133. static void
  2134. decode_CC2stat_0 (SIM_CPU *cpu, bu16 iw0)
  2135. {
  2136. /* CC2stat
  2137. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2138. | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 1 |.D.|.op....|.cbit..............|
  2139. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2140. int D = ((iw0 >> CC2stat_D_bits) & CC2stat_D_mask);
  2141. int op = ((iw0 >> CC2stat_op_bits) & CC2stat_op_mask);
  2142. int cbit = ((iw0 >> CC2stat_cbit_bits) & CC2stat_cbit_mask);
  2143. bu32 pval;
  2144. const char * const op_names[] = { "", "|", "&", "^" } ;
  2145. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CC2stat);
  2146. TRACE_EXTRACT (cpu, "%s: D:%i op:%i cbit:%i", __func__, D, op, cbit);
  2147. TRACE_INSN (cpu, "%s %s= %s;", D ? astat_names[cbit] : "CC",
  2148. op_names[op], D ? "CC" : astat_names[cbit]);
  2149. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2150. illegal_instruction_combination (cpu);
  2151. /* CC = CC; is invalid. */
  2152. if (cbit == 5)
  2153. illegal_instruction (cpu);
  2154. pval = !!(ASTAT & (1 << cbit));
  2155. if (D == 0)
  2156. switch (op)
  2157. {
  2158. case 0: SET_CCREG (pval); break;
  2159. case 1: SET_CCREG (CCREG | pval); break;
  2160. case 2: SET_CCREG (CCREG & pval); break;
  2161. case 3: SET_CCREG (CCREG ^ pval); break;
  2162. }
  2163. else
  2164. {
  2165. switch (op)
  2166. {
  2167. case 0: pval = CCREG; break;
  2168. case 1: pval |= CCREG; break;
  2169. case 2: pval &= CCREG; break;
  2170. case 3: pval ^= CCREG; break;
  2171. }
  2172. TRACE_REGISTER (cpu, "wrote ASTAT[%s] = %i", astat_names[cbit], pval);
  2173. SET_ASTAT ((ASTAT & ~(1 << cbit)) | (pval << cbit));
  2174. }
  2175. }
  2176. static void
  2177. decode_BRCC_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
  2178. {
  2179. /* BRCC
  2180. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2181. | 0 | 0 | 0 | 1 |.T.|.B.|.offset................................|
  2182. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2183. int B = ((iw0 >> BRCC_B_bits) & BRCC_B_mask);
  2184. int T = ((iw0 >> BRCC_T_bits) & BRCC_T_mask);
  2185. int offset = ((iw0 >> BRCC_offset_bits) & BRCC_offset_mask);
  2186. int cond = T ? CCREG : ! CCREG;
  2187. int pcrel = pcrel10 (offset);
  2188. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_BRCC);
  2189. TRACE_EXTRACT (cpu, "%s: T:%i B:%i offset:%#x", __func__, T, B, offset);
  2190. TRACE_DECODE (cpu, "%s: pcrel10:%#x", __func__, pcrel);
  2191. TRACE_INSN (cpu, "IF %sCC JUMP %#x%s;", T ? "" : "! ",
  2192. pcrel, B ? " (bp)" : "");
  2193. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2194. illegal_instruction_combination (cpu);
  2195. if (cond)
  2196. {
  2197. bu32 newpc = pc + pcrel;
  2198. BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "Conditional JUMP");
  2199. SET_PCREG (newpc);
  2200. BFIN_CPU_STATE.did_jump = true;
  2201. PROFILE_BRANCH_TAKEN (cpu);
  2202. CYCLE_DELAY = B ? 5 : 9;
  2203. }
  2204. else
  2205. {
  2206. PROFILE_BRANCH_UNTAKEN (cpu);
  2207. CYCLE_DELAY = B ? 9 : 1;
  2208. }
  2209. }
  2210. static void
  2211. decode_UJUMP_0 (SIM_CPU *cpu, bu16 iw0, bu32 pc)
  2212. {
  2213. /* UJUMP
  2214. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2215. | 0 | 0 | 1 | 0 |.offset........................................|
  2216. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2217. int offset = ((iw0 >> UJump_offset_bits) & UJump_offset_mask);
  2218. int pcrel = pcrel12 (offset);
  2219. bu32 newpc = pc + pcrel;
  2220. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_UJUMP);
  2221. TRACE_EXTRACT (cpu, "%s: offset:%#x", __func__, offset);
  2222. TRACE_DECODE (cpu, "%s: pcrel12:%#x", __func__, pcrel);
  2223. TRACE_INSN (cpu, "JUMP.S %#x;", pcrel);
  2224. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2225. illegal_instruction_combination (cpu);
  2226. BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP.S");
  2227. SET_PCREG (newpc);
  2228. BFIN_CPU_STATE.did_jump = true;
  2229. PROFILE_BRANCH_TAKEN (cpu);
  2230. CYCLE_DELAY = 5;
  2231. }
  2232. static void
  2233. decode_REGMV_0 (SIM_CPU *cpu, bu16 iw0)
  2234. {
  2235. /* REGMV
  2236. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2237. | 0 | 0 | 1 | 1 |.gd........|.gs........|.dst.......|.src.......|
  2238. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2239. int gs = ((iw0 >> RegMv_gs_bits) & RegMv_gs_mask);
  2240. int gd = ((iw0 >> RegMv_gd_bits) & RegMv_gd_mask);
  2241. int src = ((iw0 >> RegMv_src_bits) & RegMv_src_mask);
  2242. int dst = ((iw0 >> RegMv_dst_bits) & RegMv_dst_mask);
  2243. const char *srcreg_name = get_allreg_name (gs, src);
  2244. const char *dstreg_name = get_allreg_name (gd, dst);
  2245. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_REGMV);
  2246. TRACE_EXTRACT (cpu, "%s: gd:%i gs:%i dst:%i src:%i",
  2247. __func__, gd, gs, dst, src);
  2248. TRACE_DECODE (cpu, "%s: dst:%s src:%s", __func__, dstreg_name, srcreg_name);
  2249. TRACE_INSN (cpu, "%s = %s;", dstreg_name, srcreg_name);
  2250. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2251. illegal_instruction_combination (cpu);
  2252. /* Reserved slots cannot be a src/dst. */
  2253. if (reg_is_reserved (gs, src) || reg_is_reserved (gd, dst))
  2254. goto invalid_move;
  2255. /* Standard register moves. */
  2256. if ((gs < 2) /* Dregs/Pregs src */
  2257. || (gd < 2) /* Dregs/Pregs dst */
  2258. || (gs == 4 && src < 4) /* Accumulators src */
  2259. || (gd == 4 && dst < 4 && (gs < 4)) /* Accumulators dst */
  2260. || (gs == 7 && src == 7 && !(gd == 4 && dst < 4)) /* EMUDAT src */
  2261. || (gd == 7 && dst == 7)) /* EMUDAT dst */
  2262. goto valid_move;
  2263. /* dareg = dareg (IMBL) */
  2264. if (gs < 4 && gd < 4)
  2265. goto valid_move;
  2266. /* USP can be src to sysregs, but not dagregs. */
  2267. if ((gs == 7 && src == 0) && (gd >= 4))
  2268. goto valid_move;
  2269. /* USP can move between genregs (only check Accumulators). */
  2270. if (((gs == 7 && src == 0) && (gd == 4 && dst < 4))
  2271. || ((gd == 7 && dst == 0) && (gs == 4 && src < 4)))
  2272. goto valid_move;
  2273. /* Still here ? Invalid reg pair. */
  2274. invalid_move:
  2275. illegal_instruction (cpu);
  2276. valid_move:
  2277. reg_write (cpu, gd, dst, reg_read (cpu, gs, src));
  2278. }
  2279. static void
  2280. decode_ALU2op_0 (SIM_CPU *cpu, bu16 iw0)
  2281. {
  2282. /* ALU2op
  2283. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2284. | 0 | 1 | 0 | 0 | 0 | 0 |.opc...........|.src.......|.dst.......|
  2285. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2286. int src = ((iw0 >> ALU2op_src_bits) & ALU2op_src_mask);
  2287. int opc = ((iw0 >> ALU2op_opc_bits) & ALU2op_opc_mask);
  2288. int dst = ((iw0 >> ALU2op_dst_bits) & ALU2op_dst_mask);
  2289. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_ALU2op);
  2290. TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
  2291. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2292. illegal_instruction_combination (cpu);
  2293. if (opc == 0)
  2294. {
  2295. TRACE_INSN (cpu, "R%i >>>= R%i;", dst, src);
  2296. SET_DREG (dst, ashiftrt (cpu, DREG (dst), DREG (src), 32));
  2297. }
  2298. else if (opc == 1)
  2299. {
  2300. bu32 val;
  2301. TRACE_INSN (cpu, "R%i >>= R%i;", dst, src);
  2302. if (DREG (src) <= 0x1F)
  2303. val = lshiftrt (cpu, DREG (dst), DREG (src), 32);
  2304. else
  2305. val = 0;
  2306. SET_DREG (dst, val);
  2307. }
  2308. else if (opc == 2)
  2309. {
  2310. TRACE_INSN (cpu, "R%i <<= R%i;", dst, src);
  2311. SET_DREG (dst, lshift (cpu, DREG (dst), DREG (src), 32, 0, 0));
  2312. }
  2313. else if (opc == 3)
  2314. {
  2315. TRACE_INSN (cpu, "R%i *= R%i;", dst, src);
  2316. SET_DREG (dst, DREG (dst) * DREG (src));
  2317. CYCLE_DELAY = 3;
  2318. }
  2319. else if (opc == 4)
  2320. {
  2321. TRACE_INSN (cpu, "R%i = (R%i + R%i) << 1;", dst, dst, src);
  2322. SET_DREG (dst, add_and_shift (cpu, DREG (dst), DREG (src), 1));
  2323. }
  2324. else if (opc == 5)
  2325. {
  2326. TRACE_INSN (cpu, "R%i = (R%i + R%i) << 2;", dst, dst, src);
  2327. SET_DREG (dst, add_and_shift (cpu, DREG (dst), DREG (src), 2));
  2328. }
  2329. else if (opc == 8)
  2330. {
  2331. TRACE_INSN (cpu, "DIVQ ( R%i, R%i );", dst, src);
  2332. SET_DREG (dst, divq (cpu, DREG (dst), (bu16)DREG (src)));
  2333. }
  2334. else if (opc == 9)
  2335. {
  2336. TRACE_INSN (cpu, "DIVS ( R%i, R%i );", dst, src);
  2337. SET_DREG (dst, divs (cpu, DREG (dst), (bu16)DREG (src)));
  2338. }
  2339. else if (opc == 10)
  2340. {
  2341. TRACE_INSN (cpu, "R%i = R%i.L (X);", dst, src);
  2342. SET_DREG (dst, (bs32) (bs16) DREG (src));
  2343. setflags_logical (cpu, DREG (dst));
  2344. }
  2345. else if (opc == 11)
  2346. {
  2347. TRACE_INSN (cpu, "R%i = R%i.L (Z);", dst, src);
  2348. SET_DREG (dst, (bu32) (bu16) DREG (src));
  2349. setflags_logical (cpu, DREG (dst));
  2350. }
  2351. else if (opc == 12)
  2352. {
  2353. TRACE_INSN (cpu, "R%i = R%i.B (X);", dst, src);
  2354. SET_DREG (dst, (bs32) (bs8) DREG (src));
  2355. setflags_logical (cpu, DREG (dst));
  2356. }
  2357. else if (opc == 13)
  2358. {
  2359. TRACE_INSN (cpu, "R%i = R%i.B (Z);", dst, src);
  2360. SET_DREG (dst, (bu32) (bu8) DREG (src));
  2361. setflags_logical (cpu, DREG (dst));
  2362. }
  2363. else if (opc == 14)
  2364. {
  2365. bu32 val = DREG (src);
  2366. TRACE_INSN (cpu, "R%i = - R%i;", dst, src);
  2367. SET_DREG (dst, -val);
  2368. setflags_nz (cpu, DREG (dst));
  2369. SET_ASTATREG (v, val == 0x80000000);
  2370. if (ASTATREG (v))
  2371. SET_ASTATREG (vs, 1);
  2372. SET_ASTATREG (ac0, val == 0x0);
  2373. /* XXX: Documentation isn't entirely clear about av0 and av1. */
  2374. }
  2375. else if (opc == 15)
  2376. {
  2377. TRACE_INSN (cpu, "R%i = ~ R%i;", dst, src);
  2378. SET_DREG (dst, ~DREG (src));
  2379. setflags_logical (cpu, DREG (dst));
  2380. }
  2381. else
  2382. illegal_instruction (cpu);
  2383. }
  2384. static void
  2385. decode_PTR2op_0 (SIM_CPU *cpu, bu16 iw0)
  2386. {
  2387. /* PTR2op
  2388. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2389. | 0 | 1 | 0 | 0 | 0 | 1 | 0 |.opc.......|.src.......|.dst.......|
  2390. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2391. int src = ((iw0 >> PTR2op_src_bits) & PTR2op_dst_mask);
  2392. int opc = ((iw0 >> PTR2op_opc_bits) & PTR2op_opc_mask);
  2393. int dst = ((iw0 >> PTR2op_dst_bits) & PTR2op_dst_mask);
  2394. const char *src_name = get_preg_name (src);
  2395. const char *dst_name = get_preg_name (dst);
  2396. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_PTR2op);
  2397. TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
  2398. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2399. illegal_instruction_combination (cpu);
  2400. if (opc == 0)
  2401. {
  2402. TRACE_INSN (cpu, "%s -= %s", dst_name, src_name);
  2403. SET_PREG (dst, PREG (dst) - PREG (src));
  2404. }
  2405. else if (opc == 1)
  2406. {
  2407. TRACE_INSN (cpu, "%s = %s << 2", dst_name, src_name);
  2408. SET_PREG (dst, PREG (src) << 2);
  2409. }
  2410. else if (opc == 3)
  2411. {
  2412. TRACE_INSN (cpu, "%s = %s >> 2", dst_name, src_name);
  2413. SET_PREG (dst, PREG (src) >> 2);
  2414. }
  2415. else if (opc == 4)
  2416. {
  2417. TRACE_INSN (cpu, "%s = %s >> 1", dst_name, src_name);
  2418. SET_PREG (dst, PREG (src) >> 1);
  2419. }
  2420. else if (opc == 5)
  2421. {
  2422. TRACE_INSN (cpu, "%s += %s (BREV)", dst_name, src_name);
  2423. SET_PREG (dst, add_brev (PREG (dst), PREG (src)));
  2424. }
  2425. else if (opc == 6)
  2426. {
  2427. TRACE_INSN (cpu, "%s = (%s + %s) << 1", dst_name, dst_name, src_name);
  2428. SET_PREG (dst, (PREG (dst) + PREG (src)) << 1);
  2429. }
  2430. else if (opc == 7)
  2431. {
  2432. TRACE_INSN (cpu, "%s = (%s + %s) << 2", dst_name, dst_name, src_name);
  2433. SET_PREG (dst, (PREG (dst) + PREG (src)) << 2);
  2434. }
  2435. else
  2436. illegal_instruction (cpu);
  2437. }
  2438. static void
  2439. decode_LOGI2op_0 (SIM_CPU *cpu, bu16 iw0)
  2440. {
  2441. /* LOGI2op
  2442. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2443. | 0 | 1 | 0 | 0 | 1 |.opc.......|.src...............|.dst.......|
  2444. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2445. int src = ((iw0 >> LOGI2op_src_bits) & LOGI2op_src_mask);
  2446. int opc = ((iw0 >> LOGI2op_opc_bits) & LOGI2op_opc_mask);
  2447. int dst = ((iw0 >> LOGI2op_dst_bits) & LOGI2op_dst_mask);
  2448. int uimm = uimm5 (src);
  2449. const char *uimm_str = uimm5_str (uimm);
  2450. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LOGI2op);
  2451. TRACE_EXTRACT (cpu, "%s: opc:%i src:%i dst:%i", __func__, opc, src, dst);
  2452. TRACE_DECODE (cpu, "%s: uimm5:%#x", __func__, uimm);
  2453. if (opc == 0)
  2454. {
  2455. TRACE_INSN (cpu, "CC = ! BITTST (R%i, %s);", dst, uimm_str);
  2456. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2457. illegal_instruction_combination (cpu);
  2458. SET_CCREG ((~DREG (dst) >> uimm) & 1);
  2459. }
  2460. else if (opc == 1)
  2461. {
  2462. TRACE_INSN (cpu, "CC = BITTST (R%i, %s);", dst, uimm_str);
  2463. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2464. illegal_instruction_combination (cpu);
  2465. SET_CCREG ((DREG (dst) >> uimm) & 1);
  2466. }
  2467. else if (opc == 2)
  2468. {
  2469. TRACE_INSN (cpu, "BITSET (R%i, %s);", dst, uimm_str);
  2470. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2471. illegal_instruction_combination (cpu);
  2472. SET_DREG (dst, DREG (dst) | (1 << uimm));
  2473. setflags_logical (cpu, DREG (dst));
  2474. }
  2475. else if (opc == 3)
  2476. {
  2477. TRACE_INSN (cpu, "BITTGL (R%i, %s);", dst, uimm_str);
  2478. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2479. illegal_instruction_combination (cpu);
  2480. SET_DREG (dst, DREG (dst) ^ (1 << uimm));
  2481. setflags_logical (cpu, DREG (dst));
  2482. }
  2483. else if (opc == 4)
  2484. {
  2485. TRACE_INSN (cpu, "BITCLR (R%i, %s);", dst, uimm_str);
  2486. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2487. illegal_instruction_combination (cpu);
  2488. SET_DREG (dst, DREG (dst) & ~(1 << uimm));
  2489. setflags_logical (cpu, DREG (dst));
  2490. }
  2491. else if (opc == 5)
  2492. {
  2493. TRACE_INSN (cpu, "R%i >>>= %s;", dst, uimm_str);
  2494. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2495. illegal_instruction_combination (cpu);
  2496. SET_DREG (dst, ashiftrt (cpu, DREG (dst), uimm, 32));
  2497. }
  2498. else if (opc == 6)
  2499. {
  2500. TRACE_INSN (cpu, "R%i >>= %s;", dst, uimm_str);
  2501. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2502. illegal_instruction_combination (cpu);
  2503. SET_DREG (dst, lshiftrt (cpu, DREG (dst), uimm, 32));
  2504. }
  2505. else if (opc == 7)
  2506. {
  2507. TRACE_INSN (cpu, "R%i <<= %s;", dst, uimm_str);
  2508. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2509. illegal_instruction_combination (cpu);
  2510. SET_DREG (dst, lshift (cpu, DREG (dst), uimm, 32, 0, 0));
  2511. }
  2512. }
  2513. static void
  2514. decode_COMP3op_0 (SIM_CPU *cpu, bu16 iw0)
  2515. {
  2516. /* COMP3op
  2517. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2518. | 0 | 1 | 0 | 1 |.opc.......|.dst.......|.src1......|.src0......|
  2519. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2520. int opc = ((iw0 >> COMP3op_opc_bits) & COMP3op_opc_mask);
  2521. int dst = ((iw0 >> COMP3op_dst_bits) & COMP3op_dst_mask);
  2522. int src0 = ((iw0 >> COMP3op_src0_bits) & COMP3op_src0_mask);
  2523. int src1 = ((iw0 >> COMP3op_src1_bits) & COMP3op_src1_mask);
  2524. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMP3op);
  2525. TRACE_EXTRACT (cpu, "%s: opc:%i dst:%i src1:%i src0:%i",
  2526. __func__, opc, dst, src1, src0);
  2527. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2528. illegal_instruction_combination (cpu);
  2529. if (opc == 0)
  2530. {
  2531. TRACE_INSN (cpu, "R%i = R%i + R%i;", dst, src0, src1);
  2532. SET_DREG (dst, add32 (cpu, DREG (src0), DREG (src1), 1, 0));
  2533. }
  2534. else if (opc == 1)
  2535. {
  2536. TRACE_INSN (cpu, "R%i = R%i - R%i;", dst, src0, src1);
  2537. SET_DREG (dst, sub32 (cpu, DREG (src0), DREG (src1), 1, 0, 0));
  2538. }
  2539. else if (opc == 2)
  2540. {
  2541. TRACE_INSN (cpu, "R%i = R%i & R%i;", dst, src0, src1);
  2542. SET_DREG (dst, DREG (src0) & DREG (src1));
  2543. setflags_logical (cpu, DREG (dst));
  2544. }
  2545. else if (opc == 3)
  2546. {
  2547. TRACE_INSN (cpu, "R%i = R%i | R%i;", dst, src0, src1);
  2548. SET_DREG (dst, DREG (src0) | DREG (src1));
  2549. setflags_logical (cpu, DREG (dst));
  2550. }
  2551. else if (opc == 4)
  2552. {
  2553. TRACE_INSN (cpu, "R%i = R%i ^ R%i;", dst, src0, src1);
  2554. SET_DREG (dst, DREG (src0) ^ DREG (src1));
  2555. setflags_logical (cpu, DREG (dst));
  2556. }
  2557. else
  2558. {
  2559. int shift = opc - 5;
  2560. const char *dst_name = get_preg_name (dst);
  2561. const char *src0_name = get_preg_name (src0);
  2562. const char *src1_name = get_preg_name (src1);
  2563. /* If src0 == src1 this is disassembled as a shift by 1, but this
  2564. distinction doesn't matter for our purposes. */
  2565. if (shift)
  2566. TRACE_INSN (cpu, "%s = (%s + %s) << %#x;",
  2567. dst_name, src0_name, src1_name, shift);
  2568. else
  2569. TRACE_INSN (cpu, "%s = %s + %s",
  2570. dst_name, src0_name, src1_name);
  2571. SET_PREG (dst, PREG (src0) + (PREG (src1) << shift));
  2572. }
  2573. }
  2574. static void
  2575. decode_COMPI2opD_0 (SIM_CPU *cpu, bu16 iw0)
  2576. {
  2577. /* COMPI2opD
  2578. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2579. | 0 | 1 | 1 | 0 | 0 |.op|..src......................|.dst.......|
  2580. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2581. int op = ((iw0 >> COMPI2opD_op_bits) & COMPI2opD_op_mask);
  2582. int dst = ((iw0 >> COMPI2opD_dst_bits) & COMPI2opD_dst_mask);
  2583. int src = ((iw0 >> COMPI2opD_src_bits) & COMPI2opD_src_mask);
  2584. int imm = imm7 (src);
  2585. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMPI2opD);
  2586. TRACE_EXTRACT (cpu, "%s: op:%i src:%i dst:%i", __func__, op, src, dst);
  2587. TRACE_DECODE (cpu, "%s: imm7:%#x", __func__, imm);
  2588. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2589. illegal_instruction_combination (cpu);
  2590. if (op == 0)
  2591. {
  2592. TRACE_INSN (cpu, "R%i = %s (X);", dst, imm7_str (imm));
  2593. SET_DREG (dst, imm);
  2594. }
  2595. else if (op == 1)
  2596. {
  2597. TRACE_INSN (cpu, "R%i += %s;", dst, imm7_str (imm));
  2598. SET_DREG (dst, add32 (cpu, DREG (dst), imm, 1, 0));
  2599. }
  2600. }
  2601. static void
  2602. decode_COMPI2opP_0 (SIM_CPU *cpu, bu16 iw0)
  2603. {
  2604. /* COMPI2opP
  2605. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2606. | 0 | 1 | 1 | 0 | 1 |.op|.src.......................|.dst.......|
  2607. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2608. int op = ((iw0 >> COMPI2opP_op_bits) & COMPI2opP_op_mask);
  2609. int src = ((iw0 >> COMPI2opP_src_bits) & COMPI2opP_src_mask);
  2610. int dst = ((iw0 >> COMPI2opP_dst_bits) & COMPI2opP_dst_mask);
  2611. int imm = imm7 (src);
  2612. const char *dst_name = get_preg_name (dst);
  2613. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_COMPI2opP);
  2614. TRACE_EXTRACT (cpu, "%s: op:%i src:%i dst:%i", __func__, op, src, dst);
  2615. TRACE_DECODE (cpu, "%s: imm:%#x", __func__, imm);
  2616. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  2617. illegal_instruction_combination (cpu);
  2618. if (op == 0)
  2619. {
  2620. TRACE_INSN (cpu, "%s = %s;", dst_name, imm7_str (imm));
  2621. SET_PREG (dst, imm);
  2622. }
  2623. else if (op == 1)
  2624. {
  2625. TRACE_INSN (cpu, "%s += %s;", dst_name, imm7_str (imm));
  2626. SET_PREG (dst, PREG (dst) + imm);
  2627. }
  2628. }
  2629. static void
  2630. decode_LDSTpmod_0 (SIM_CPU *cpu, bu16 iw0)
  2631. {
  2632. /* LDSTpmod
  2633. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2634. | 1 | 0 | 0 | 0 |.W.|.aop...|.reg.......|.idx.......|.ptr.......|
  2635. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2636. int W = ((iw0 >> LDSTpmod_W_bits) & LDSTpmod_W_mask);
  2637. int aop = ((iw0 >> LDSTpmod_aop_bits) & LDSTpmod_aop_mask);
  2638. int idx = ((iw0 >> LDSTpmod_idx_bits) & LDSTpmod_idx_mask);
  2639. int ptr = ((iw0 >> LDSTpmod_ptr_bits) & LDSTpmod_ptr_mask);
  2640. int reg = ((iw0 >> LDSTpmod_reg_bits) & LDSTpmod_reg_mask);
  2641. const char *ptr_name = get_preg_name (ptr);
  2642. const char *idx_name = get_preg_name (idx);
  2643. bu32 addr, val;
  2644. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTpmod);
  2645. TRACE_EXTRACT (cpu, "%s: W:%i aop:%i reg:%i idx:%i ptr:%i",
  2646. __func__, W, aop, reg, idx, ptr);
  2647. if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
  2648. illegal_instruction_combination (cpu);
  2649. if (aop == 1 && W == 0 && idx == ptr)
  2650. {
  2651. TRACE_INSN (cpu, "R%i.L = W[%s];", reg, ptr_name);
  2652. addr = PREG (ptr);
  2653. val = GET_WORD (addr);
  2654. STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | val);
  2655. }
  2656. else if (aop == 2 && W == 0 && idx == ptr)
  2657. {
  2658. TRACE_INSN (cpu, "R%i.H = W[%s];", reg, ptr_name);
  2659. addr = PREG (ptr);
  2660. val = GET_WORD (addr);
  2661. STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (val << 16));
  2662. }
  2663. else if (aop == 1 && W == 1 && idx == ptr)
  2664. {
  2665. TRACE_INSN (cpu, "W[%s] = R%i.L;", ptr_name, reg);
  2666. addr = PREG (ptr);
  2667. PUT_WORD (addr, DREG (reg));
  2668. }
  2669. else if (aop == 2 && W == 1 && idx == ptr)
  2670. {
  2671. TRACE_INSN (cpu, "W[%s] = R%i.H;", ptr_name, reg);
  2672. addr = PREG (ptr);
  2673. PUT_WORD (addr, DREG (reg) >> 16);
  2674. }
  2675. else if (aop == 0 && W == 0)
  2676. {
  2677. TRACE_INSN (cpu, "R%i = [%s ++ %s];", reg, ptr_name, idx_name);
  2678. addr = PREG (ptr);
  2679. val = GET_LONG (addr);
  2680. STORE (DREG (reg), val);
  2681. if (ptr != idx)
  2682. STORE (PREG (ptr), addr + PREG (idx));
  2683. }
  2684. else if (aop == 1 && W == 0)
  2685. {
  2686. TRACE_INSN (cpu, "R%i.L = W[%s ++ %s];", reg, ptr_name, idx_name);
  2687. addr = PREG (ptr);
  2688. val = GET_WORD (addr);
  2689. STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | val);
  2690. if (ptr != idx)
  2691. STORE (PREG (ptr), addr + PREG (idx));
  2692. }
  2693. else if (aop == 2 && W == 0)
  2694. {
  2695. TRACE_INSN (cpu, "R%i.H = W[%s ++ %s];", reg, ptr_name, idx_name);
  2696. addr = PREG (ptr);
  2697. val = GET_WORD (addr);
  2698. STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (val << 16));
  2699. if (ptr != idx)
  2700. STORE (PREG (ptr), addr + PREG (idx));
  2701. }
  2702. else if (aop == 3 && W == 0)
  2703. {
  2704. TRACE_INSN (cpu, "R%i = W[%s ++ %s] (Z);", reg, ptr_name, idx_name);
  2705. addr = PREG (ptr);
  2706. val = GET_WORD (addr);
  2707. STORE (DREG (reg), val);
  2708. if (ptr != idx)
  2709. STORE (PREG (ptr), addr + PREG (idx));
  2710. }
  2711. else if (aop == 3 && W == 1)
  2712. {
  2713. TRACE_INSN (cpu, "R%i = W[%s ++ %s] (X);", reg, ptr_name, idx_name);
  2714. addr = PREG (ptr);
  2715. val = GET_WORD (addr);
  2716. STORE (DREG (reg), (bs32) (bs16) val);
  2717. if (ptr != idx)
  2718. STORE (PREG (ptr), addr + PREG (idx));
  2719. }
  2720. else if (aop == 0 && W == 1)
  2721. {
  2722. TRACE_INSN (cpu, "[%s ++ %s] = R%i;", ptr_name, idx_name, reg);
  2723. addr = PREG (ptr);
  2724. PUT_LONG (addr, DREG (reg));
  2725. if (ptr != idx)
  2726. STORE (PREG (ptr), addr + PREG (idx));
  2727. }
  2728. else if (aop == 1 && W == 1)
  2729. {
  2730. TRACE_INSN (cpu, "W[%s ++ %s] = R%i.L;", ptr_name, idx_name, reg);
  2731. addr = PREG (ptr);
  2732. PUT_WORD (addr, DREG (reg));
  2733. if (ptr != idx)
  2734. STORE (PREG (ptr), addr + PREG (idx));
  2735. }
  2736. else if (aop == 2 && W == 1)
  2737. {
  2738. TRACE_INSN (cpu, "W[%s ++ %s] = R%i.H;", ptr_name, idx_name, reg);
  2739. addr = PREG (ptr);
  2740. PUT_WORD (addr, DREG (reg) >> 16);
  2741. if (ptr != idx)
  2742. STORE (PREG (ptr), addr + PREG (idx));
  2743. }
  2744. else
  2745. illegal_instruction_or_combination (cpu);
  2746. }
  2747. static void
  2748. decode_dagMODim_0 (SIM_CPU *cpu, bu16 iw0)
  2749. {
  2750. /* dagMODim
  2751. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2752. | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 0 |.br| 1 | 1 |.op|.m.....|.i.....|
  2753. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2754. int i = ((iw0 >> DagMODim_i_bits) & DagMODim_i_mask);
  2755. int m = ((iw0 >> DagMODim_m_bits) & DagMODim_m_mask);
  2756. int br = ((iw0 >> DagMODim_br_bits) & DagMODim_br_mask);
  2757. int op = ((iw0 >> DagMODim_op_bits) & DagMODim_op_mask);
  2758. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dagMODim);
  2759. TRACE_EXTRACT (cpu, "%s: br:%i op:%i m:%i i:%i", __func__, br, op, m, i);
  2760. if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
  2761. illegal_instruction_combination (cpu);
  2762. if (op == 0 && br == 1)
  2763. {
  2764. TRACE_INSN (cpu, "I%i += M%i (BREV);", i, m);
  2765. SET_IREG (i, add_brev (IREG (i), MREG (m)));
  2766. }
  2767. else if (op == 0)
  2768. {
  2769. TRACE_INSN (cpu, "I%i += M%i;", i, m);
  2770. dagadd (cpu, i, MREG (m));
  2771. }
  2772. else if (op == 1 && br == 0)
  2773. {
  2774. TRACE_INSN (cpu, "I%i -= M%i;", i, m);
  2775. dagsub (cpu, i, MREG (m));
  2776. }
  2777. else
  2778. illegal_instruction_or_combination (cpu);
  2779. }
  2780. static void
  2781. decode_dagMODik_0 (SIM_CPU *cpu, bu16 iw0)
  2782. {
  2783. /* dagMODik
  2784. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2785. | 1 | 0 | 0 | 1 | 1 | 1 | 1 | 1 | 0 | 1 | 1 | 0 |.op....|.i.....|
  2786. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2787. int i = ((iw0 >> DagMODik_i_bits) & DagMODik_i_mask);
  2788. int op = ((iw0 >> DagMODik_op_bits) & DagMODik_op_mask);
  2789. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dagMODik);
  2790. TRACE_EXTRACT (cpu, "%s: op:%i i:%i", __func__, op, i);
  2791. if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
  2792. illegal_instruction_combination (cpu);
  2793. if (op == 0)
  2794. {
  2795. TRACE_INSN (cpu, "I%i += 2;", i);
  2796. dagadd (cpu, i, 2);
  2797. }
  2798. else if (op == 1)
  2799. {
  2800. TRACE_INSN (cpu, "I%i -= 2;", i);
  2801. dagsub (cpu, i, 2);
  2802. }
  2803. else if (op == 2)
  2804. {
  2805. TRACE_INSN (cpu, "I%i += 4;", i);
  2806. dagadd (cpu, i, 4);
  2807. }
  2808. else if (op == 3)
  2809. {
  2810. TRACE_INSN (cpu, "I%i -= 4;", i);
  2811. dagsub (cpu, i, 4);
  2812. }
  2813. else
  2814. illegal_instruction_or_combination (cpu);
  2815. }
  2816. static void
  2817. decode_dspLDST_0 (SIM_CPU *cpu, bu16 iw0)
  2818. {
  2819. /* dspLDST
  2820. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2821. | 1 | 0 | 0 | 1 | 1 | 1 |.W.|.aop...|.m.....|.i.....|.reg.......|
  2822. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2823. int i = ((iw0 >> DspLDST_i_bits) & DspLDST_i_mask);
  2824. int m = ((iw0 >> DspLDST_m_bits) & DspLDST_m_mask);
  2825. int W = ((iw0 >> DspLDST_W_bits) & DspLDST_W_mask);
  2826. int aop = ((iw0 >> DspLDST_aop_bits) & DspLDST_aop_mask);
  2827. int reg = ((iw0 >> DspLDST_reg_bits) & DspLDST_reg_mask);
  2828. bu32 addr;
  2829. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dspLDST);
  2830. TRACE_EXTRACT (cpu, "%s: aop:%i m:%i i:%i reg:%i", __func__, aop, m, i, reg);
  2831. if (aop == 0 && W == 0 && m == 0)
  2832. {
  2833. TRACE_INSN (cpu, "R%i = [I%i++];", reg, i);
  2834. addr = IREG (i);
  2835. if (DIS_ALGN_EXPT & 0x1)
  2836. addr &= ~3;
  2837. dagadd (cpu, i, 4);
  2838. STORE (DREG (reg), GET_LONG (addr));
  2839. }
  2840. else if (aop == 0 && W == 0 && m == 1)
  2841. {
  2842. TRACE_INSN (cpu, "R%i.L = W[I%i++];", reg, i);
  2843. addr = IREG (i);
  2844. dagadd (cpu, i, 2);
  2845. STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
  2846. }
  2847. else if (aop == 0 && W == 0 && m == 2)
  2848. {
  2849. TRACE_INSN (cpu, "R%i.H = W[I%i++];", reg, i);
  2850. addr = IREG (i);
  2851. dagadd (cpu, i, 2);
  2852. STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
  2853. }
  2854. else if (aop == 1 && W == 0 && m == 0)
  2855. {
  2856. TRACE_INSN (cpu, "R%i = [I%i--];", reg, i);
  2857. addr = IREG (i);
  2858. if (DIS_ALGN_EXPT & 0x1)
  2859. addr &= ~3;
  2860. dagsub (cpu, i, 4);
  2861. STORE (DREG (reg), GET_LONG (addr));
  2862. }
  2863. else if (aop == 1 && W == 0 && m == 1)
  2864. {
  2865. TRACE_INSN (cpu, "R%i.L = W[I%i--];", reg, i);
  2866. addr = IREG (i);
  2867. dagsub (cpu, i, 2);
  2868. STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
  2869. }
  2870. else if (aop == 1 && W == 0 && m == 2)
  2871. {
  2872. TRACE_INSN (cpu, "R%i.H = W[I%i--];", reg, i);
  2873. addr = IREG (i);
  2874. dagsub (cpu, i, 2);
  2875. STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
  2876. }
  2877. else if (aop == 2 && W == 0 && m == 0)
  2878. {
  2879. TRACE_INSN (cpu, "R%i = [I%i];", reg, i);
  2880. addr = IREG (i);
  2881. if (DIS_ALGN_EXPT & 0x1)
  2882. addr &= ~3;
  2883. STORE (DREG (reg), GET_LONG (addr));
  2884. }
  2885. else if (aop == 2 && W == 0 && m == 1)
  2886. {
  2887. TRACE_INSN (cpu, "R%i.L = W[I%i];", reg, i);
  2888. addr = IREG (i);
  2889. STORE (DREG (reg), (DREG (reg) & 0xFFFF0000) | GET_WORD (addr));
  2890. }
  2891. else if (aop == 2 && W == 0 && m == 2)
  2892. {
  2893. TRACE_INSN (cpu, "R%i.H = W[I%i];", reg, i);
  2894. addr = IREG (i);
  2895. STORE (DREG (reg), (DREG (reg) & 0xFFFF) | (GET_WORD (addr) << 16));
  2896. }
  2897. else if (aop == 0 && W == 1 && m == 0)
  2898. {
  2899. TRACE_INSN (cpu, "[I%i++] = R%i;", i, reg);
  2900. addr = IREG (i);
  2901. dagadd (cpu, i, 4);
  2902. PUT_LONG (addr, DREG (reg));
  2903. }
  2904. else if (aop == 0 && W == 1 && m == 1)
  2905. {
  2906. TRACE_INSN (cpu, "W[I%i++] = R%i.L;", i, reg);
  2907. addr = IREG (i);
  2908. dagadd (cpu, i, 2);
  2909. PUT_WORD (addr, DREG (reg));
  2910. }
  2911. else if (aop == 0 && W == 1 && m == 2)
  2912. {
  2913. TRACE_INSN (cpu, "W[I%i++] = R%i.H;", i, reg);
  2914. addr = IREG (i);
  2915. dagadd (cpu, i, 2);
  2916. PUT_WORD (addr, DREG (reg) >> 16);
  2917. }
  2918. else if (aop == 1 && W == 1 && m == 0)
  2919. {
  2920. TRACE_INSN (cpu, "[I%i--] = R%i;", i, reg);
  2921. addr = IREG (i);
  2922. dagsub (cpu, i, 4);
  2923. PUT_LONG (addr, DREG (reg));
  2924. }
  2925. else if (aop == 1 && W == 1 && m == 1)
  2926. {
  2927. TRACE_INSN (cpu, "W[I%i--] = R%i.L;", i, reg);
  2928. addr = IREG (i);
  2929. dagsub (cpu, i, 2);
  2930. PUT_WORD (addr, DREG (reg));
  2931. }
  2932. else if (aop == 1 && W == 1 && m == 2)
  2933. {
  2934. TRACE_INSN (cpu, "W[I%i--] = R%i.H;", i, reg);
  2935. addr = IREG (i);
  2936. dagsub (cpu, i, 2);
  2937. PUT_WORD (addr, DREG (reg) >> 16);
  2938. }
  2939. else if (aop == 2 && W == 1 && m == 0)
  2940. {
  2941. TRACE_INSN (cpu, "[I%i] = R%i;", i, reg);
  2942. addr = IREG (i);
  2943. PUT_LONG (addr, DREG (reg));
  2944. }
  2945. else if (aop == 2 && W == 1 && m == 1)
  2946. {
  2947. TRACE_INSN (cpu, "W[I%i] = R%i.L;", i, reg);
  2948. addr = IREG (i);
  2949. PUT_WORD (addr, DREG (reg));
  2950. }
  2951. else if (aop == 2 && W == 1 && m == 2)
  2952. {
  2953. TRACE_INSN (cpu, "W[I%i] = R%i.H;", i, reg);
  2954. addr = IREG (i);
  2955. PUT_WORD (addr, DREG (reg) >> 16);
  2956. }
  2957. else if (aop == 3 && W == 0)
  2958. {
  2959. TRACE_INSN (cpu, "R%i = [I%i ++ M%i];", reg, i, m);
  2960. addr = IREG (i);
  2961. if (DIS_ALGN_EXPT & 0x1)
  2962. addr &= ~3;
  2963. dagadd (cpu, i, MREG (m));
  2964. STORE (DREG (reg), GET_LONG (addr));
  2965. }
  2966. else if (aop == 3 && W == 1)
  2967. {
  2968. TRACE_INSN (cpu, "[I%i ++ M%i] = R%i;", i, m, reg);
  2969. addr = IREG (i);
  2970. dagadd (cpu, i, MREG (m));
  2971. PUT_LONG (addr, DREG (reg));
  2972. }
  2973. else
  2974. illegal_instruction_or_combination (cpu);
  2975. }
  2976. static void
  2977. decode_LDST_0 (SIM_CPU *cpu, bu16 iw0)
  2978. {
  2979. /* LDST
  2980. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  2981. | 1 | 0 | 0 | 1 |.sz....|.W.|.aop...|.Z.|.ptr.......|.reg.......|
  2982. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  2983. int Z = ((iw0 >> LDST_Z_bits) & LDST_Z_mask);
  2984. int W = ((iw0 >> LDST_W_bits) & LDST_W_mask);
  2985. int sz = ((iw0 >> LDST_sz_bits) & LDST_sz_mask);
  2986. int aop = ((iw0 >> LDST_aop_bits) & LDST_aop_mask);
  2987. int reg = ((iw0 >> LDST_reg_bits) & LDST_reg_mask);
  2988. int ptr = ((iw0 >> LDST_ptr_bits) & LDST_ptr_mask);
  2989. const char * const posts[] = { "++", "--", "" };
  2990. const char *post = posts[aop];
  2991. const char *ptr_name = get_preg_name (ptr);
  2992. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDST);
  2993. TRACE_EXTRACT (cpu, "%s: sz:%i W:%i aop:%i Z:%i ptr:%i reg:%i",
  2994. __func__, sz, W, aop, Z, ptr, reg);
  2995. if (aop == 3 || PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
  2996. illegal_instruction_or_combination (cpu);
  2997. if (W == 0)
  2998. {
  2999. if (sz == 0 && Z == 0)
  3000. {
  3001. TRACE_INSN (cpu, "R%i = [%s%s];", reg, ptr_name, post);
  3002. SET_DREG (reg, GET_LONG (PREG (ptr)));
  3003. }
  3004. else if (sz == 0 && Z == 1)
  3005. {
  3006. TRACE_INSN (cpu, "%s = [%s%s];", get_preg_name (reg), ptr_name, post);
  3007. if (aop < 2 && ptr == reg)
  3008. illegal_instruction_combination (cpu);
  3009. SET_PREG (reg, GET_LONG (PREG (ptr)));
  3010. }
  3011. else if (sz == 1 && Z == 0)
  3012. {
  3013. TRACE_INSN (cpu, "R%i = W[%s%s] (Z);", reg, ptr_name, post);
  3014. SET_DREG (reg, GET_WORD (PREG (ptr)));
  3015. }
  3016. else if (sz == 1 && Z == 1)
  3017. {
  3018. TRACE_INSN (cpu, "R%i = W[%s%s] (X);", reg, ptr_name, post);
  3019. SET_DREG (reg, (bs32) (bs16) GET_WORD (PREG (ptr)));
  3020. }
  3021. else if (sz == 2 && Z == 0)
  3022. {
  3023. TRACE_INSN (cpu, "R%i = B[%s%s] (Z);", reg, ptr_name, post);
  3024. SET_DREG (reg, GET_BYTE (PREG (ptr)));
  3025. }
  3026. else if (sz == 2 && Z == 1)
  3027. {
  3028. TRACE_INSN (cpu, "R%i = B[%s%s] (X);", reg, ptr_name, post);
  3029. SET_DREG (reg, (bs32) (bs8) GET_BYTE (PREG (ptr)));
  3030. }
  3031. else
  3032. illegal_instruction_or_combination (cpu);
  3033. }
  3034. else
  3035. {
  3036. if (sz == 0 && Z == 0)
  3037. {
  3038. TRACE_INSN (cpu, "[%s%s] = R%i;", ptr_name, post, reg);
  3039. PUT_LONG (PREG (ptr), DREG (reg));
  3040. }
  3041. else if (sz == 0 && Z == 1)
  3042. {
  3043. TRACE_INSN (cpu, "[%s%s] = %s;", ptr_name, post, get_preg_name (reg));
  3044. PUT_LONG (PREG (ptr), PREG (reg));
  3045. }
  3046. else if (sz == 1 && Z == 0)
  3047. {
  3048. TRACE_INSN (cpu, "W[%s%s] = R%i;", ptr_name, post, reg);
  3049. PUT_WORD (PREG (ptr), DREG (reg));
  3050. }
  3051. else if (sz == 2 && Z == 0)
  3052. {
  3053. TRACE_INSN (cpu, "B[%s%s] = R%i;", ptr_name, post, reg);
  3054. PUT_BYTE (PREG (ptr), DREG (reg));
  3055. }
  3056. else
  3057. illegal_instruction_or_combination (cpu);
  3058. }
  3059. if (aop == 0)
  3060. SET_PREG (ptr, PREG (ptr) + (1 << (2 - sz)));
  3061. if (aop == 1)
  3062. SET_PREG (ptr, PREG (ptr) - (1 << (2 - sz)));
  3063. }
  3064. static void
  3065. decode_LDSTiiFP_0 (SIM_CPU *cpu, bu16 iw0)
  3066. {
  3067. /* LDSTiiFP
  3068. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  3069. | 1 | 0 | 1 | 1 | 1 | 0 |.W.|.offset............|.reg...........|
  3070. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  3071. /* This isn't exactly a grp:reg as this insn only supports Dregs & Pregs,
  3072. but for our usage, its functionality the same thing. */
  3073. int grp = ((iw0 >> 3) & 0x1);
  3074. int reg = ((iw0 >> LDSTiiFP_reg_bits) & 0x7 /*LDSTiiFP_reg_mask*/);
  3075. int offset = ((iw0 >> LDSTiiFP_offset_bits) & LDSTiiFP_offset_mask);
  3076. int W = ((iw0 >> LDSTiiFP_W_bits) & LDSTiiFP_W_mask);
  3077. bu32 imm = negimm5s4 (offset);
  3078. bu32 ea = FPREG + imm;
  3079. const char *imm_str = negimm5s4_str (offset);
  3080. const char *reg_name = get_allreg_name (grp, reg);
  3081. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTiiFP);
  3082. TRACE_EXTRACT (cpu, "%s: W:%i offset:%#x grp:%i reg:%i", __func__,
  3083. W, offset, grp, reg);
  3084. TRACE_DECODE (cpu, "%s: negimm5s4:%#x", __func__, imm);
  3085. if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
  3086. illegal_instruction_or_combination (cpu);
  3087. if (W == 0)
  3088. {
  3089. TRACE_INSN (cpu, "%s = [FP + %s];", reg_name, imm_str);
  3090. reg_write (cpu, grp, reg, GET_LONG (ea));
  3091. }
  3092. else
  3093. {
  3094. TRACE_INSN (cpu, "[FP + %s] = %s;", imm_str, reg_name);
  3095. PUT_LONG (ea, reg_read (cpu, grp, reg));
  3096. }
  3097. }
  3098. static void
  3099. decode_LDSTii_0 (SIM_CPU *cpu, bu16 iw0)
  3100. {
  3101. /* LDSTii
  3102. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  3103. | 1 | 0 | 1 |.W.|.op....|.offset........|.ptr.......|.reg.......|
  3104. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  3105. int reg = ((iw0 >> LDSTii_reg_bit) & LDSTii_reg_mask);
  3106. int ptr = ((iw0 >> LDSTii_ptr_bit) & LDSTii_ptr_mask);
  3107. int offset = ((iw0 >> LDSTii_offset_bit) & LDSTii_offset_mask);
  3108. int op = ((iw0 >> LDSTii_op_bit) & LDSTii_op_mask);
  3109. int W = ((iw0 >> LDSTii_W_bit) & LDSTii_W_mask);
  3110. bu32 imm, ea;
  3111. const char *imm_str;
  3112. const char *ptr_name = get_preg_name (ptr);
  3113. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTii);
  3114. TRACE_EXTRACT (cpu, "%s: W:%i op:%i offset:%#x ptr:%i reg:%i",
  3115. __func__, W, op, offset, ptr, reg);
  3116. if (op == 0 || op == 3)
  3117. imm = uimm4s4 (offset), imm_str = uimm4s4_str (offset);
  3118. else
  3119. imm = uimm4s2 (offset), imm_str = uimm4s2_str (offset);
  3120. ea = PREG (ptr) + imm;
  3121. TRACE_DECODE (cpu, "%s: uimm4s4/uimm4s2:%#x", __func__, imm);
  3122. if (PARALLEL_GROUP == BFIN_PARALLEL_GROUP2)
  3123. illegal_instruction_combination (cpu);
  3124. if (W == 1 && op == 2)
  3125. illegal_instruction (cpu);
  3126. if (W == 0)
  3127. {
  3128. if (op == 0)
  3129. {
  3130. TRACE_INSN (cpu, "R%i = [%s + %s];", reg, ptr_name, imm_str);
  3131. SET_DREG (reg, GET_LONG (ea));
  3132. }
  3133. else if (op == 1)
  3134. {
  3135. TRACE_INSN (cpu, "R%i = W[%s + %s] (Z);", reg, ptr_name, imm_str);
  3136. SET_DREG (reg, GET_WORD (ea));
  3137. }
  3138. else if (op == 2)
  3139. {
  3140. TRACE_INSN (cpu, "R%i = W[%s + %s] (X);", reg, ptr_name, imm_str);
  3141. SET_DREG (reg, (bs32) (bs16) GET_WORD (ea));
  3142. }
  3143. else if (op == 3)
  3144. {
  3145. TRACE_INSN (cpu, "%s = [%s + %s];",
  3146. get_preg_name (reg), ptr_name, imm_str);
  3147. SET_PREG (reg, GET_LONG (ea));
  3148. }
  3149. }
  3150. else
  3151. {
  3152. if (op == 0)
  3153. {
  3154. TRACE_INSN (cpu, "[%s + %s] = R%i;", ptr_name, imm_str, reg);
  3155. PUT_LONG (ea, DREG (reg));
  3156. }
  3157. else if (op == 1)
  3158. {
  3159. TRACE_INSN (cpu, "W[%s + %s] = R%i;", ptr_name, imm_str, reg);
  3160. PUT_WORD (ea, DREG (reg));
  3161. }
  3162. else if (op == 3)
  3163. {
  3164. TRACE_INSN (cpu, "[%s + %s] = %s;",
  3165. ptr_name, imm_str, get_preg_name (reg));
  3166. PUT_LONG (ea, PREG (reg));
  3167. }
  3168. }
  3169. }
  3170. static void
  3171. decode_LoopSetup_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
  3172. {
  3173. /* LoopSetup
  3174. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  3175. | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 1 |.rop...|.c.|.soffset.......|
  3176. |.reg...........| - | - |.eoffset...............................|
  3177. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  3178. int c = ((iw0 >> (LoopSetup_c_bits - 16)) & LoopSetup_c_mask);
  3179. int reg = ((iw1 >> LoopSetup_reg_bits) & LoopSetup_reg_mask);
  3180. int rop = ((iw0 >> (LoopSetup_rop_bits - 16)) & LoopSetup_rop_mask);
  3181. int soffset = ((iw0 >> (LoopSetup_soffset_bits - 16)) & LoopSetup_soffset_mask);
  3182. int eoffset = ((iw1 >> LoopSetup_eoffset_bits) & LoopSetup_eoffset_mask);
  3183. int spcrel = pcrel4 (soffset);
  3184. int epcrel = lppcrel10 (eoffset);
  3185. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LoopSetup);
  3186. TRACE_EXTRACT (cpu, "%s: rop:%i c:%i soffset:%i reg:%i eoffset:%i",
  3187. __func__, rop, c, soffset, reg, eoffset);
  3188. TRACE_DECODE (cpu, "%s: s_pcrel4:%#x e_lppcrel10:%#x",
  3189. __func__, spcrel, epcrel);
  3190. if (reg > 7)
  3191. illegal_instruction (cpu);
  3192. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  3193. illegal_instruction_combination (cpu);
  3194. if (rop == 0)
  3195. {
  3196. TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i;", spcrel, epcrel, c);
  3197. }
  3198. else if (rop == 1 && reg <= 7)
  3199. {
  3200. TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i = %s;",
  3201. spcrel, epcrel, c, get_preg_name (reg));
  3202. SET_LCREG (c, PREG (reg));
  3203. }
  3204. else if (rop == 3 && reg <= 7)
  3205. {
  3206. TRACE_INSN (cpu, "LSETUP (%#x, %#x) LC%i = %s >> 1;",
  3207. spcrel, epcrel, c, get_preg_name (reg));
  3208. SET_LCREG (c, PREG (reg) >> 1);
  3209. }
  3210. else
  3211. illegal_instruction (cpu);
  3212. SET_LTREG (c, pc + spcrel);
  3213. SET_LBREG (c, pc + epcrel);
  3214. }
  3215. static void
  3216. decode_LDIMMhalf_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
  3217. {
  3218. /* LDIMMhalf
  3219. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  3220. | 1 | 1 | 1 | 0 | 0 | 0 | 0 | 1 |.Z.|.H.|.S.|.grp...|.reg.......|
  3221. |.hword.........................................................|
  3222. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  3223. int H = ((iw0 >> (LDIMMhalf_H_bits - 16)) & LDIMMhalf_H_mask);
  3224. int Z = ((iw0 >> (LDIMMhalf_Z_bits - 16)) & LDIMMhalf_Z_mask);
  3225. int S = ((iw0 >> (LDIMMhalf_S_bits - 16)) & LDIMMhalf_S_mask);
  3226. int reg = ((iw0 >> (LDIMMhalf_reg_bits - 16)) & LDIMMhalf_reg_mask);
  3227. int grp = ((iw0 >> (LDIMMhalf_grp_bits - 16)) & LDIMMhalf_grp_mask);
  3228. int hword = ((iw1 >> LDIMMhalf_hword_bits) & LDIMMhalf_hword_mask);
  3229. bu32 val;
  3230. const char *val_str;
  3231. const char *reg_name = get_allreg_name (grp, reg);
  3232. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDIMMhalf);
  3233. TRACE_EXTRACT (cpu, "%s: Z:%i H:%i S:%i grp:%i reg:%i hword:%#x",
  3234. __func__, Z, H, S, grp, reg, hword);
  3235. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  3236. illegal_instruction_combination (cpu);
  3237. if (S == 1)
  3238. val = imm16 (hword), val_str = imm16_str (hword);
  3239. else
  3240. val = luimm16 (hword), val_str = luimm16_str (hword);
  3241. if (H == 0 && S == 1 && Z == 0)
  3242. {
  3243. TRACE_INSN (cpu, "%s = %s (X);", reg_name, val_str);
  3244. }
  3245. else if (H == 0 && S == 0 && Z == 1)
  3246. {
  3247. TRACE_INSN (cpu, "%s = %s (Z);", reg_name, val_str);
  3248. }
  3249. else if (H == 0 && S == 0 && Z == 0)
  3250. {
  3251. TRACE_INSN (cpu, "%s.L = %s;", reg_name, val_str);
  3252. val = REG_H_L (reg_read (cpu, grp, reg), val);
  3253. }
  3254. else if (H == 1 && S == 0 && Z == 0)
  3255. {
  3256. TRACE_INSN (cpu, "%s.H = %s;", reg_name, val_str);
  3257. val = REG_H_L (val << 16, reg_read (cpu, grp, reg));
  3258. }
  3259. else
  3260. illegal_instruction (cpu);
  3261. reg_write (cpu, grp, reg, val);
  3262. }
  3263. static void
  3264. decode_CALLa_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
  3265. {
  3266. /* CALLa
  3267. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  3268. | 1 | 1 | 1 | 0 | 0 | 0 | 1 |.S.|.msw...........................|
  3269. |.lsw...........................................................|
  3270. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  3271. int S = ((iw0 >> (CALLa_S_bits - 16)) & CALLa_S_mask);
  3272. int lsw = ((iw1 >> 0) & 0xffff);
  3273. int msw = ((iw0 >> 0) & 0xff);
  3274. int pcrel = pcrel24 ((msw << 16) | lsw);
  3275. bu32 newpc = pc + pcrel;
  3276. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_CALLa);
  3277. TRACE_EXTRACT (cpu, "%s: S:%i msw:%#x lsw:%#x", __func__, S, msw, lsw);
  3278. TRACE_DECODE (cpu, "%s: pcrel24:%#x", __func__, pcrel);
  3279. TRACE_INSN (cpu, "%s %#x;", S ? "CALL" : "JUMP.L", pcrel);
  3280. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  3281. illegal_instruction_combination (cpu);
  3282. if (S == 1)
  3283. {
  3284. BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "CALL");
  3285. SET_RETSREG (hwloop_get_next_pc (cpu, pc, 4));
  3286. }
  3287. else
  3288. BFIN_TRACE_BRANCH (cpu, pc, newpc, -1, "JUMP.L");
  3289. SET_PCREG (newpc);
  3290. BFIN_CPU_STATE.did_jump = true;
  3291. PROFILE_BRANCH_TAKEN (cpu);
  3292. CYCLE_DELAY = 5;
  3293. }
  3294. static void
  3295. decode_LDSTidxI_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
  3296. {
  3297. /* LDSTidxI
  3298. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  3299. | 1 | 1 | 1 | 0 | 0 | 1 |.W.|.Z.|.sz....|.ptr.......|.reg.......|
  3300. |.offset........................................................|
  3301. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  3302. int Z = ((iw0 >> (LDSTidxI_Z_bits - 16)) & LDSTidxI_Z_mask);
  3303. int W = ((iw0 >> (LDSTidxI_W_bits - 16)) & LDSTidxI_W_mask);
  3304. int sz = ((iw0 >> (LDSTidxI_sz_bits - 16)) & LDSTidxI_sz_mask);
  3305. int reg = ((iw0 >> (LDSTidxI_reg_bits - 16)) & LDSTidxI_reg_mask);
  3306. int ptr = ((iw0 >> (LDSTidxI_ptr_bits - 16)) & LDSTidxI_ptr_mask);
  3307. int offset = ((iw1 >> LDSTidxI_offset_bits) & LDSTidxI_offset_mask);
  3308. const char *ptr_name = get_preg_name (ptr);
  3309. bu32 imm_16s4 = imm16s4 (offset);
  3310. bu32 imm_16s2 = imm16s2 (offset);
  3311. bu32 imm_16 = imm16 (offset);
  3312. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_LDSTidxI);
  3313. TRACE_EXTRACT (cpu, "%s: W:%i Z:%i sz:%i ptr:%i reg:%i offset:%#x",
  3314. __func__, W, Z, sz, ptr, reg, offset);
  3315. if (sz == 3)
  3316. illegal_instruction (cpu);
  3317. if (W == 0)
  3318. {
  3319. if (sz == 0 && Z == 0)
  3320. {
  3321. TRACE_INSN (cpu, "R%i = [%s + %s];",
  3322. reg, ptr_name, imm16s4_str (offset));
  3323. SET_DREG (reg, GET_LONG (PREG (ptr) + imm_16s4));
  3324. }
  3325. else if (sz == 0 && Z == 1)
  3326. {
  3327. TRACE_INSN (cpu, "%s = [%s + %s];",
  3328. get_preg_name (reg), ptr_name, imm16s4_str (offset));
  3329. SET_PREG (reg, GET_LONG (PREG (ptr) + imm_16s4));
  3330. }
  3331. else if (sz == 1 && Z == 0)
  3332. {
  3333. TRACE_INSN (cpu, "R%i = W[%s + %s] (Z);",
  3334. reg, ptr_name, imm16s2_str (offset));
  3335. SET_DREG (reg, GET_WORD (PREG (ptr) + imm_16s2));
  3336. }
  3337. else if (sz == 1 && Z == 1)
  3338. {
  3339. TRACE_INSN (cpu, "R%i = W[%s + %s] (X);",
  3340. reg, ptr_name, imm16s2_str (offset));
  3341. SET_DREG (reg, (bs32) (bs16) GET_WORD (PREG (ptr) + imm_16s2));
  3342. }
  3343. else if (sz == 2 && Z == 0)
  3344. {
  3345. TRACE_INSN (cpu, "R%i = B[%s + %s] (Z);",
  3346. reg, ptr_name, imm16_str (offset));
  3347. SET_DREG (reg, GET_BYTE (PREG (ptr) + imm_16));
  3348. }
  3349. else if (sz == 2 && Z == 1)
  3350. {
  3351. TRACE_INSN (cpu, "R%i = B[%s + %s] (X);",
  3352. reg, ptr_name, imm16_str (offset));
  3353. SET_DREG (reg, (bs32) (bs8) GET_BYTE (PREG (ptr) + imm_16));
  3354. }
  3355. }
  3356. else
  3357. {
  3358. if (sz != 0 && Z != 0)
  3359. illegal_instruction (cpu);
  3360. if (sz == 0 && Z == 0)
  3361. {
  3362. TRACE_INSN (cpu, "[%s + %s] = R%i;", ptr_name,
  3363. imm16s4_str (offset), reg);
  3364. PUT_LONG (PREG (ptr) + imm_16s4, DREG (reg));
  3365. }
  3366. else if (sz == 0 && Z == 1)
  3367. {
  3368. TRACE_INSN (cpu, "[%s + %s] = %s;",
  3369. ptr_name, imm16s4_str (offset), get_preg_name (reg));
  3370. PUT_LONG (PREG (ptr) + imm_16s4, PREG (reg));
  3371. }
  3372. else if (sz == 1 && Z == 0)
  3373. {
  3374. TRACE_INSN (cpu, "W[%s + %s] = R%i;",
  3375. ptr_name, imm16s2_str (offset), reg);
  3376. PUT_WORD (PREG (ptr) + imm_16s2, DREG (reg));
  3377. }
  3378. else if (sz == 2 && Z == 0)
  3379. {
  3380. TRACE_INSN (cpu, "B[%s + %s] = R%i;",
  3381. ptr_name, imm16_str (offset), reg);
  3382. PUT_BYTE (PREG (ptr) + imm_16, DREG (reg));
  3383. }
  3384. }
  3385. }
  3386. static void
  3387. decode_linkage_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
  3388. {
  3389. /* linkage
  3390. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  3391. | 1 | 1 | 1 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |.R.|
  3392. |.framesize.....................................................|
  3393. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  3394. int R = ((iw0 >> (Linkage_R_bits - 16)) & Linkage_R_mask);
  3395. int framesize = ((iw1 >> Linkage_framesize_bits) & Linkage_framesize_mask);
  3396. bu32 sp;
  3397. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_linkage);
  3398. TRACE_EXTRACT (cpu, "%s: R:%i framesize:%#x", __func__, R, framesize);
  3399. if (R == 0)
  3400. {
  3401. int size = uimm16s4 (framesize);
  3402. sp = SPREG;
  3403. TRACE_INSN (cpu, "LINK %s;", uimm16s4_str (framesize));
  3404. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  3405. illegal_instruction_combination (cpu);
  3406. sp -= 4;
  3407. PUT_LONG (sp, RETSREG);
  3408. sp -= 4;
  3409. PUT_LONG (sp, FPREG);
  3410. SET_FPREG (sp);
  3411. sp -= size;
  3412. CYCLE_DELAY = 3;
  3413. }
  3414. else
  3415. {
  3416. /* Restore SP from FP. */
  3417. sp = FPREG;
  3418. TRACE_INSN (cpu, "UNLINK;");
  3419. if (PARALLEL_GROUP != BFIN_PARALLEL_NONE)
  3420. illegal_instruction_combination (cpu);
  3421. SET_FPREG (GET_LONG (sp));
  3422. sp += 4;
  3423. SET_RETSREG (GET_LONG (sp));
  3424. sp += 4;
  3425. CYCLE_DELAY = 2;
  3426. }
  3427. SET_SPREG (sp);
  3428. }
  3429. static void
  3430. decode_dsp32mac_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
  3431. {
  3432. /* dsp32mac
  3433. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  3434. | 1 | 1 | 0 | 0 |.M.| 0 | 0 |.mmod..........|.MM|.P.|.w1|.op1...|
  3435. |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
  3436. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  3437. int op1 = ((iw0 >> (DSP32Mac_op1_bits - 16)) & DSP32Mac_op1_mask);
  3438. int w1 = ((iw0 >> (DSP32Mac_w1_bits - 16)) & DSP32Mac_w1_mask);
  3439. int P = ((iw0 >> (DSP32Mac_p_bits - 16)) & DSP32Mac_p_mask);
  3440. int MM = ((iw0 >> (DSP32Mac_MM_bits - 16)) & DSP32Mac_MM_mask);
  3441. int mmod = ((iw0 >> (DSP32Mac_mmod_bits - 16)) & DSP32Mac_mmod_mask);
  3442. int M = ((iw0 >> (DSP32Mac_M_bits - 16)) & DSP32Mac_M_mask);
  3443. int w0 = ((iw1 >> DSP32Mac_w0_bits) & DSP32Mac_w0_mask);
  3444. int src0 = ((iw1 >> DSP32Mac_src0_bits) & DSP32Mac_src0_mask);
  3445. int src1 = ((iw1 >> DSP32Mac_src1_bits) & DSP32Mac_src1_mask);
  3446. int dst = ((iw1 >> DSP32Mac_dst_bits) & DSP32Mac_dst_mask);
  3447. int h10 = ((iw1 >> DSP32Mac_h10_bits) & DSP32Mac_h10_mask);
  3448. int h00 = ((iw1 >> DSP32Mac_h00_bits) & DSP32Mac_h00_mask);
  3449. int op0 = ((iw1 >> DSP32Mac_op0_bits) & DSP32Mac_op0_mask);
  3450. int h11 = ((iw1 >> DSP32Mac_h11_bits) & DSP32Mac_h11_mask);
  3451. int h01 = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask);
  3452. bu32 res = DREG (dst);
  3453. bu32 v_0 = 0, v_1 = 0, zero = 0, n_1 = 0, n_0 = 0;
  3454. static const char * const ops[] = { "=", "+=", "-=" };
  3455. char _buf[128], *buf = _buf;
  3456. int _MM = MM;
  3457. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mac);
  3458. TRACE_EXTRACT (cpu, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
  3459. "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
  3460. __func__, M, mmod, MM, P, w1, op1, h01, h11, w0, op0, h00, h10,
  3461. dst, src0, src1);
  3462. if (w0 == 0 && w1 == 0 && op1 == 3 && op0 == 3)
  3463. illegal_instruction (cpu);
  3464. if ((w1 || w0) && mmod == M_W32)
  3465. illegal_instruction (cpu);
  3466. if (((1 << mmod) & (P ? 0x131b : 0x1b5f)) == 0)
  3467. illegal_instruction (cpu);
  3468. /* First handle MAC1 side. */
  3469. if (w1 == 1 || op1 != 3)
  3470. {
  3471. bu32 res1 = decode_macfunc (cpu, 1, op1, h01, h11, src0,
  3472. src1, mmod, MM, P, &v_1, &n_1);
  3473. if (w1)
  3474. buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P);
  3475. if (op1 == 3)
  3476. {
  3477. buf += sprintf (buf, " = A1");
  3478. zero = !!(res1 == 0);
  3479. }
  3480. else
  3481. {
  3482. if (w1)
  3483. buf += sprintf (buf, " = (");
  3484. buf += sprintf (buf, "A1 %s R%i.%c * R%i.%c", ops[op1],
  3485. src0, h01 ? 'H' : 'L',
  3486. src1, h11 ? 'H' : 'L');
  3487. if (w1)
  3488. buf += sprintf (buf, ")");
  3489. }
  3490. if (w1)
  3491. {
  3492. if (P)
  3493. STORE (DREG (dst + 1), res1);
  3494. else
  3495. {
  3496. if (res1 & 0xffff0000)
  3497. illegal_instruction (cpu);
  3498. res = REG_H_L (res1 << 16, res);
  3499. }
  3500. }
  3501. else
  3502. v_1 = 0;
  3503. if (w0 == 1 || op0 != 3)
  3504. {
  3505. if (_MM)
  3506. buf += sprintf (buf, " (M)");
  3507. _MM = 0;
  3508. buf += sprintf (buf, ", ");
  3509. }
  3510. }
  3511. /* Then handle MAC0 side. */
  3512. if (w0 == 1 || op0 != 3)
  3513. {
  3514. bu32 res0 = decode_macfunc (cpu, 0, op0, h00, h10, src0,
  3515. src1, mmod, 0, P, &v_0, &n_0);
  3516. if (w0)
  3517. buf += sprintf (buf, P ? "R%i" : "R%i.L", dst);
  3518. if (op0 == 3)
  3519. {
  3520. buf += sprintf (buf, " = A0");
  3521. zero |= !!(res0 == 0);
  3522. }
  3523. else
  3524. {
  3525. if (w0)
  3526. buf += sprintf (buf, " = (");
  3527. buf += sprintf (buf, "A0 %s R%i.%c * R%i.%c", ops[op0],
  3528. src0, h00 ? 'H' : 'L',
  3529. src1, h10 ? 'H' : 'L');
  3530. if (w0)
  3531. buf += sprintf (buf, ")");
  3532. }
  3533. if (w0)
  3534. {
  3535. if (P)
  3536. STORE (DREG (dst), res0);
  3537. else
  3538. {
  3539. if (res0 & 0xffff0000)
  3540. illegal_instruction (cpu);
  3541. res = REG_H_L (res, res0);
  3542. }
  3543. }
  3544. else
  3545. v_0 = 0;
  3546. }
  3547. TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM));
  3548. if (!P && (w0 || w1))
  3549. {
  3550. STORE (DREG (dst), res);
  3551. SET_ASTATREG (v, v_0 | v_1);
  3552. if (v_0 || v_1)
  3553. SET_ASTATREG (vs, 1);
  3554. }
  3555. else if (P)
  3556. {
  3557. SET_ASTATREG (v, v_0 | v_1);
  3558. if (v_0 || v_1)
  3559. SET_ASTATREG (vs, 1);
  3560. }
  3561. if ((w0 == 1 && op0 == 3) || (w1 == 1 && op1 == 3))
  3562. {
  3563. SET_ASTATREG (az, zero);
  3564. if (!(w0 == 1 && op0 == 3))
  3565. n_0 = 0;
  3566. if (!(w1 == 1 && op1 == 3))
  3567. n_1 = 0;
  3568. SET_ASTATREG (an, n_1 | n_0);
  3569. }
  3570. }
  3571. static void
  3572. decode_dsp32mult_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
  3573. {
  3574. /* dsp32mult
  3575. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  3576. | 1 | 1 | 0 | 0 |.M.| 0 | 1 |.mmod..........|.MM|.P.|.w1|.op1...|
  3577. |.h01|.h11|.w0|.op0...|.h00|.h10|.dst.......|.src0......|.src1..|
  3578. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  3579. int op1 = ((iw0 >> (DSP32Mac_op1_bits - 16)) & DSP32Mac_op1_mask);
  3580. int w1 = ((iw0 >> (DSP32Mac_w1_bits - 16)) & DSP32Mac_w1_mask);
  3581. int P = ((iw0 >> (DSP32Mac_p_bits - 16)) & DSP32Mac_p_mask);
  3582. int MM = ((iw0 >> (DSP32Mac_MM_bits - 16)) & DSP32Mac_MM_mask);
  3583. int mmod = ((iw0 >> (DSP32Mac_mmod_bits - 16)) & DSP32Mac_mmod_mask);
  3584. int M = ((iw0 >> (DSP32Mac_M_bits - 16)) & DSP32Mac_M_mask);
  3585. int w0 = ((iw1 >> DSP32Mac_w0_bits) & DSP32Mac_w0_mask);
  3586. int src0 = ((iw1 >> DSP32Mac_src0_bits) & DSP32Mac_src0_mask);
  3587. int src1 = ((iw1 >> DSP32Mac_src1_bits) & DSP32Mac_src1_mask);
  3588. int dst = ((iw1 >> DSP32Mac_dst_bits) & DSP32Mac_dst_mask);
  3589. int h10 = ((iw1 >> DSP32Mac_h10_bits) & DSP32Mac_h10_mask);
  3590. int h00 = ((iw1 >> DSP32Mac_h00_bits) & DSP32Mac_h00_mask);
  3591. int op0 = ((iw1 >> DSP32Mac_op0_bits) & DSP32Mac_op0_mask);
  3592. int h11 = ((iw1 >> DSP32Mac_h11_bits) & DSP32Mac_h11_mask);
  3593. int h01 = ((iw1 >> DSP32Mac_h01_bits) & DSP32Mac_h01_mask);
  3594. bu32 res = DREG (dst);
  3595. bu32 sat0 = 0, sat1 = 0, v_i0 = 0, v_i1 = 0;
  3596. char _buf[128], *buf = _buf;
  3597. int _MM = MM;
  3598. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mult);
  3599. TRACE_EXTRACT (cpu, "%s: M:%i mmod:%i MM:%i P:%i w1:%i op1:%i h01:%i h11:%i "
  3600. "w0:%i op0:%i h00:%i h10:%i dst:%i src0:%i src1:%i",
  3601. __func__, M, mmod, MM, P, w1, op1, h01, h11, w0, op0, h00, h10,
  3602. dst, src0, src1);
  3603. if (w1 == 0 && w0 == 0)
  3604. illegal_instruction (cpu);
  3605. if (((1 << mmod) & (P ? 0x313 : 0x1b57)) == 0)
  3606. illegal_instruction (cpu);
  3607. if (P && ((dst & 1) || (op1 != 0) || (op0 != 0) || !is_macmod_pmove (mmod)))
  3608. illegal_instruction (cpu);
  3609. if (!P && ((op1 != 0) || (op0 != 0) || !is_macmod_hmove (mmod)))
  3610. illegal_instruction (cpu);
  3611. /* First handle MAC1 side. */
  3612. if (w1)
  3613. {
  3614. bu64 r = decode_multfunc (cpu, h01, h11, src0, src1, mmod, MM, &sat1);
  3615. bu32 res1 = extract_mult (cpu, r, mmod, MM, P, &v_i1);
  3616. buf += sprintf (buf, P ? "R%i" : "R%i.H", dst + P);
  3617. buf += sprintf (buf, " = R%i.%c * R%i.%c",
  3618. src0, h01 ? 'H' : 'L',
  3619. src1, h11 ? 'H' : 'L');
  3620. if (w0)
  3621. {
  3622. if (_MM)
  3623. buf += sprintf (buf, " (M)");
  3624. _MM = 0;
  3625. buf += sprintf (buf, ", ");
  3626. }
  3627. if (P)
  3628. STORE (DREG (dst + 1), res1);
  3629. else
  3630. {
  3631. if (res1 & 0xFFFF0000)
  3632. illegal_instruction (cpu);
  3633. res = REG_H_L (res1 << 16, res);
  3634. }
  3635. }
  3636. /* First handle MAC0 side. */
  3637. if (w0)
  3638. {
  3639. bu64 r = decode_multfunc (cpu, h00, h10, src0, src1, mmod, 0, &sat0);
  3640. bu32 res0 = extract_mult (cpu, r, mmod, 0, P, &v_i0);
  3641. buf += sprintf (buf, P ? "R%i" : "R%i.L", dst);
  3642. buf += sprintf (buf, " = R%i.%c * R%i.%c",
  3643. src0, h01 ? 'H' : 'L',
  3644. src1, h11 ? 'H' : 'L');
  3645. if (P)
  3646. STORE (DREG (dst), res0);
  3647. else
  3648. {
  3649. if (res0 & 0xFFFF0000)
  3650. illegal_instruction (cpu);
  3651. res = REG_H_L (res, res0);
  3652. }
  3653. }
  3654. TRACE_INSN (cpu, "%s%s;", _buf, mac_optmode (mmod, _MM));
  3655. if (!P && (w0 || w1))
  3656. STORE (DREG (dst), res);
  3657. if (w0 || w1)
  3658. {
  3659. bu32 v = sat0 | sat1 | v_i0 | v_i1;
  3660. STORE (ASTATREG (v), v);
  3661. STORE (ASTATREG (v_copy), v);
  3662. if (v)
  3663. STORE (ASTATREG (vs), v);
  3664. }
  3665. }
  3666. static void
  3667. decode_dsp32alu_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
  3668. {
  3669. /* dsp32alu
  3670. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  3671. | 1 | 1 | 0 | 0 |.M.| 1 | 0 | - | - | - |.HL|.aopcde............|
  3672. |.aop...|.s.|.x.|.dst0......|.dst1......|.src0......|.src1......|
  3673. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  3674. int s = ((iw1 >> DSP32Alu_s_bits) & DSP32Alu_s_mask);
  3675. int x = ((iw1 >> DSP32Alu_x_bits) & DSP32Alu_x_mask);
  3676. int aop = ((iw1 >> DSP32Alu_aop_bits) & DSP32Alu_aop_mask);
  3677. int src0 = ((iw1 >> DSP32Alu_src0_bits) & DSP32Alu_src0_mask);
  3678. int src1 = ((iw1 >> DSP32Alu_src1_bits) & DSP32Alu_src1_mask);
  3679. int dst0 = ((iw1 >> DSP32Alu_dst0_bits) & DSP32Alu_dst0_mask);
  3680. int dst1 = ((iw1 >> DSP32Alu_dst1_bits) & DSP32Alu_dst1_mask);
  3681. int M = ((iw0 >> (DSP32Alu_M_bits - 16)) & DSP32Alu_M_mask);
  3682. int HL = ((iw0 >> (DSP32Alu_HL_bits - 16)) & DSP32Alu_HL_mask);
  3683. int aopcde = ((iw0 >> (DSP32Alu_aopcde_bits - 16)) & DSP32Alu_aopcde_mask);
  3684. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32alu);
  3685. TRACE_EXTRACT (cpu, "%s: M:%i HL:%i aopcde:%i aop:%i s:%i x:%i dst0:%i "
  3686. "dst1:%i src0:%i src1:%i",
  3687. __func__, M, HL, aopcde, aop, s, x, dst0, dst1, src0, src1);
  3688. if ((aop == 0 || aop == 2) && aopcde == 9 && x == 0 && s == 0 && HL == 0)
  3689. {
  3690. int a = aop >> 1;
  3691. TRACE_INSN (cpu, "A%i.L = R%i.L;", a, src0);
  3692. SET_AWREG (a, REG_H_L (AWREG (a), DREG (src0)));
  3693. }
  3694. else if ((aop == 0 || aop == 2) && aopcde == 9 && x == 0 && s == 0 && HL == 1)
  3695. {
  3696. int a = aop >> 1;
  3697. TRACE_INSN (cpu, "A%i.H = R%i.H;", a, src0);
  3698. SET_AWREG (a, REG_H_L (DREG (src0), AWREG (a)));
  3699. }
  3700. else if ((aop == 1 || aop == 0) && aopcde == 5 && x == 0 && s == 0)
  3701. {
  3702. bs32 val0 = DREG (src0);
  3703. bs32 val1 = DREG (src1);
  3704. bs32 res;
  3705. bs32 signRes;
  3706. bs32 ovX, sBit1, sBit2, sBitRes1, sBitRes2;
  3707. TRACE_INSN (cpu, "R%i.%s = R%i %s R%i (RND12)", dst0, HL ? "L" : "H",
  3708. src0, aop & 0x1 ? "-" : "+", src1);
  3709. /* If subtract, just invert and add one. */
  3710. if (aop & 0x1)
  3711. {
  3712. if (val1 == 0x80000000)
  3713. val1 = 0x7FFFFFFF;
  3714. else
  3715. val1 = ~val1 + 1;
  3716. }
  3717. /* Get the sign bits, since we need them later. */
  3718. sBit1 = !!(val0 & 0x80000000);
  3719. sBit2 = !!(val1 & 0x80000000);
  3720. res = val0 + val1;
  3721. sBitRes1 = !!(res & 0x80000000);
  3722. /* Round to the 12th bit. */
  3723. res += 0x0800;
  3724. sBitRes2 = !!(res & 0x80000000);
  3725. signRes = res;
  3726. signRes >>= 27;
  3727. /* Overflow if
  3728. pos + pos = neg
  3729. neg + neg = pos
  3730. positive_res + positive_round = neg
  3731. Shift and upper 4 bits where not the same. */
  3732. if ((!(sBit1 ^ sBit2) && (sBit1 ^ sBitRes1))
  3733. || (!sBit1 && !sBit2 && sBitRes2)
  3734. || ((signRes != 0) && (signRes != -1)))
  3735. {
  3736. /* Both X1 and X2 Neg res is neg overflow. */
  3737. if (sBit1 && sBit2)
  3738. res = 0x80000000;
  3739. /* Both X1 and X2 Pos res is pos overflow. */
  3740. else if (!sBit1 && !sBit2)
  3741. res = 0x7FFFFFFF;
  3742. /* Pos+Neg or Neg+Pos take the sign of the result. */
  3743. else if (sBitRes1)
  3744. res = 0x80000000;
  3745. else
  3746. res = 0x7FFFFFFF;
  3747. ovX = 1;
  3748. }
  3749. else
  3750. {
  3751. /* Shift up now after overflow detection. */
  3752. ovX = 0;
  3753. res <<= 4;
  3754. }
  3755. res >>= 16;
  3756. if (HL)
  3757. STORE (DREG (dst0), REG_H_L (res << 16, DREG (dst0)));
  3758. else
  3759. STORE (DREG (dst0), REG_H_L (DREG (dst0), res));
  3760. SET_ASTATREG (az, res == 0);
  3761. SET_ASTATREG (an, res & 0x8000);
  3762. SET_ASTATREG (v, ovX);
  3763. if (ovX)
  3764. SET_ASTATREG (vs, ovX);
  3765. }
  3766. else if ((aop == 2 || aop == 3) && aopcde == 5 && x == 1 && s == 0)
  3767. {
  3768. bs32 val0 = DREG (src0);
  3769. bs32 val1 = DREG (src1);
  3770. bs32 res;
  3771. TRACE_INSN (cpu, "R%i.%s = R%i %s R%i (RND20)", dst0, HL ? "L" : "H",
  3772. src0, aop & 0x1 ? "-" : "+", src1);
  3773. /* If subtract, just invert and add one. */
  3774. if (aop & 0x1)
  3775. val1 = ~val1 + 1;
  3776. res = (val0 >> 4) + (val1 >> 4) + (((val0 & 0xf) + (val1 & 0xf)) >> 4);
  3777. res += 0x8000;
  3778. /* Don't sign extend during the shift. */
  3779. res = ((bu32)res >> 16);
  3780. /* Don't worry about overflows, since we are shifting right. */
  3781. if (HL)
  3782. STORE (DREG (dst0), REG_H_L (res << 16, DREG (dst0)));
  3783. else
  3784. STORE (DREG (dst0), REG_H_L (DREG (dst0), res));
  3785. SET_ASTATREG (az, res == 0);
  3786. SET_ASTATREG (an, res & 0x8000);
  3787. SET_ASTATREG (v, 0);
  3788. }
  3789. else if ((aopcde == 2 || aopcde == 3) && x == 0)
  3790. {
  3791. bu32 s1, s2, val, ac0_i = 0, v_i = 0;
  3792. TRACE_INSN (cpu, "R%i.%c = R%i.%c %c R%i.%c%s;",
  3793. dst0, HL ? 'H' : 'L',
  3794. src0, aop & 2 ? 'H' : 'L',
  3795. aopcde == 2 ? '+' : '-',
  3796. src1, aop & 1 ? 'H' : 'L',
  3797. amod1 (s, x));
  3798. s1 = DREG (src0);
  3799. s2 = DREG (src1);
  3800. if (aop & 1)
  3801. s2 >>= 16;
  3802. if (aop & 2)
  3803. s1 >>= 16;
  3804. if (aopcde == 2)
  3805. val = add16 (cpu, s1, s2, &ac0_i, &v_i, 0, 0, s, 0);
  3806. else
  3807. val = sub16 (cpu, s1, s2, &ac0_i, &v_i, 0, 0, s, 0);
  3808. SET_ASTATREG (ac0, ac0_i);
  3809. SET_ASTATREG (v, v_i);
  3810. if (v_i)
  3811. SET_ASTATREG (vs, v_i);
  3812. if (HL)
  3813. SET_DREG_H (dst0, val << 16);
  3814. else
  3815. SET_DREG_L (dst0, val);
  3816. SET_ASTATREG (an, val & 0x8000);
  3817. SET_ASTATREG (az, val == 0);
  3818. }
  3819. else if ((aop == 0 || aop == 2) && aopcde == 9 && x == 0 && s == 1 && HL == 0)
  3820. {
  3821. int a = aop >> 1;
  3822. TRACE_INSN (cpu, "A%i = R%i;", a, src0);
  3823. SET_AREG32 (a, DREG (src0));
  3824. }
  3825. else if ((aop == 1 || aop == 3) && aopcde == 9 && x == 0 && s == 0 && HL == 0)
  3826. {
  3827. int a = aop >> 1;
  3828. TRACE_INSN (cpu, "A%i.X = R%i.L;", a, src0);
  3829. SET_AXREG (a, (bs8)DREG (src0));
  3830. }
  3831. else if (aop == 3 && aopcde == 11 && x == 0 && HL == 0)
  3832. {
  3833. bu64 acc0 = get_extended_acc (cpu, 0);
  3834. bu64 acc1 = get_extended_acc (cpu, 1);
  3835. bu32 carry = (bu40)acc1 < (bu40)acc0;
  3836. bu32 sat = 0;
  3837. TRACE_INSN (cpu, "A0 -= A1%s;", s ? " (W32)" : "");
  3838. acc0 -= acc1;
  3839. if ((bs64)acc0 < -0x8000000000ll)
  3840. acc0 = -0x8000000000ull, sat = 1;
  3841. else if ((bs64)acc0 >= 0x7fffffffffll)
  3842. acc0 = 0x7fffffffffull, sat = 1;
  3843. if (s == 1)
  3844. {
  3845. /* A0 -= A1 (W32) */
  3846. if (acc0 & (bu64)0x8000000000ll)
  3847. acc0 &= 0x80ffffffffll, sat = 1;
  3848. else
  3849. acc0 &= 0xffffffffll;
  3850. }
  3851. STORE (AXREG (0), (acc0 >> 32) & 0xff);
  3852. STORE (AWREG (0), acc0 & 0xffffffff);
  3853. STORE (ASTATREG (az), acc0 == 0);
  3854. STORE (ASTATREG (an), !!(acc0 & (bu64)0x8000000000ll));
  3855. STORE (ASTATREG (ac0), carry);
  3856. STORE (ASTATREG (ac0_copy), carry);
  3857. STORE (ASTATREG (av0), sat);
  3858. if (sat)
  3859. STORE (ASTATREG (av0s), sat);
  3860. }
  3861. else if ((aop == 0 || aop == 1) && aopcde == 22 && x == 0)
  3862. {
  3863. bu32 s0, s0L, s0H, s1, s1L, s1H;
  3864. bu32 tmp0, tmp1, i;
  3865. const char * const opts[] = { "rndl", "rndh", "tl", "th" };
  3866. TRACE_INSN (cpu, "R%i = BYTEOP2P (R%i:%i, R%i:%i) (%s%s);", dst0,
  3867. src0 + 1, src0, src1 + 1, src1, opts[HL + (aop << 1)],
  3868. s ? ", r" : "");
  3869. if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
  3870. illegal_instruction (cpu);
  3871. s0L = DREG (src0);
  3872. s0H = DREG (src0 + 1);
  3873. s1L = DREG (src1);
  3874. s1H = DREG (src1 + 1);
  3875. if (s)
  3876. {
  3877. s0 = algn (s0H, s0L, IREG (0) & 3);
  3878. s1 = algn (s1H, s1L, IREG (0) & 3);
  3879. }
  3880. else
  3881. {
  3882. s0 = algn (s0L, s0H, IREG (0) & 3);
  3883. s1 = algn (s1L, s1H, IREG (0) & 3);
  3884. }
  3885. i = !aop * 2;
  3886. tmp0 = ((((s1 >> 8) & 0xff) + ((s1 >> 0) & 0xff) +
  3887. ((s0 >> 8) & 0xff) + ((s0 >> 0) & 0xff) + i) >> 2) & 0xff;
  3888. tmp1 = ((((s1 >> 24) & 0xff) + ((s1 >> 16) & 0xff) +
  3889. ((s0 >> 24) & 0xff) + ((s0 >> 16) & 0xff) + i) >> 2) & 0xff;
  3890. STORE (DREG (dst0), (tmp1 << (16 + (HL * 8))) | (tmp0 << (HL * 8)));
  3891. /* Implicit DISALGNEXCPT in parallel. */
  3892. DIS_ALGN_EXPT |= 1;
  3893. }
  3894. else if ((aop == 0 || aop == 1) && aopcde == 8 && x == 0 && s == 0 && HL == 0)
  3895. {
  3896. TRACE_INSN (cpu, "A%i = 0;", aop);
  3897. SET_AREG (aop, 0);
  3898. }
  3899. else if (aop == 2 && aopcde == 8 && x == 0 && s == 0 && HL == 0)
  3900. {
  3901. TRACE_INSN (cpu, "A1 = A0 = 0;");
  3902. SET_AREG (0, 0);
  3903. SET_AREG (1, 0);
  3904. }
  3905. else if ((aop == 0 || aop == 1 || aop == 2) && s == 1 && aopcde == 8
  3906. && x == 0 && HL == 0)
  3907. {
  3908. bs40 acc0 = get_extended_acc (cpu, 0);
  3909. bs40 acc1 = get_extended_acc (cpu, 1);
  3910. bu32 sat;
  3911. if (aop == 0 || aop == 1)
  3912. TRACE_INSN (cpu, "A%i = A%i (S);", aop, aop);
  3913. else
  3914. TRACE_INSN (cpu, "A1 = A1 (S), A0 = A0 (S);");
  3915. if (aop == 0 || aop == 2)
  3916. {
  3917. sat = 0;
  3918. acc0 = saturate_s32 (acc0, &sat);
  3919. acc0 |= -(acc0 & 0x80000000ull);
  3920. SET_AXREG (0, (acc0 >> 31) & 0xFF);
  3921. SET_AWREG (0, acc0 & 0xFFFFFFFF);
  3922. SET_ASTATREG (av0, sat);
  3923. if (sat)
  3924. SET_ASTATREG (av0s, sat);
  3925. }
  3926. else
  3927. acc0 = 1;
  3928. if (aop == 1 || aop == 2)
  3929. {
  3930. sat = 0;
  3931. acc1 = saturate_s32 (acc1, &sat);
  3932. acc1 |= -(acc1 & 0x80000000ull);
  3933. SET_AXREG (1, (acc1 >> 31) & 0xFF);
  3934. SET_AWREG (1, acc1 & 0xFFFFFFFF);
  3935. SET_ASTATREG (av1, sat);
  3936. if (sat)
  3937. SET_ASTATREG (av1s, sat);
  3938. }
  3939. else
  3940. acc1 = 1;
  3941. SET_ASTATREG (az, (acc0 == 0) || (acc1 == 0));
  3942. SET_ASTATREG (an, ((acc0 >> 31) & 1) || ((acc1 >> 31) & 1));
  3943. }
  3944. else if (aop == 3 && aopcde == 8 && x == 0 && HL == 0)
  3945. {
  3946. TRACE_INSN (cpu, "A%i = A%i;", s, !s);
  3947. SET_AXREG (s, AXREG (!s));
  3948. SET_AWREG (s, AWREG (!s));
  3949. }
  3950. else if (aop == 3 && HL == 0 && aopcde == 16 && x == 0 && s == 0)
  3951. {
  3952. int i;
  3953. bu32 az;
  3954. TRACE_INSN (cpu, "A1 = ABS A1 , A0 = ABS A0;");
  3955. az = 0;
  3956. for (i = 0; i < 2; ++i)
  3957. {
  3958. bu32 av;
  3959. bs40 acc = get_extended_acc (cpu, i);
  3960. if (acc >> 39)
  3961. acc = -acc;
  3962. av = acc == ((bs40)1 << 39);
  3963. if (av)
  3964. acc = ((bs40)1 << 39) - 1;
  3965. SET_AREG (i, acc);
  3966. SET_ASTATREG (av[i], av);
  3967. if (av)
  3968. SET_ASTATREG (avs[i], av);
  3969. az |= (acc == 0);
  3970. }
  3971. SET_ASTATREG (az, az);
  3972. SET_ASTATREG (an, 0);
  3973. }
  3974. else if (aop == 0 && aopcde == 23 && x == 0)
  3975. {
  3976. bu32 s0, s0L, s0H, s1, s1L, s1H;
  3977. bs32 tmp0, tmp1;
  3978. TRACE_INSN (cpu, "R%i = BYTEOP3P (R%i:%i, R%i:%i) (%s%s);", dst0,
  3979. src0 + 1, src0, src1 + 1, src1, HL ? "HI" : "LO",
  3980. s ? ", R" : "");
  3981. if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
  3982. illegal_instruction (cpu);
  3983. s0L = DREG (src0);
  3984. s0H = DREG (src0 + 1);
  3985. s1L = DREG (src1);
  3986. s1H = DREG (src1 + 1);
  3987. if (s)
  3988. {
  3989. s0 = algn (s0H, s0L, IREG (0) & 3);
  3990. s1 = algn (s1H, s1L, IREG (1) & 3);
  3991. }
  3992. else
  3993. {
  3994. s0 = algn (s0L, s0H, IREG (0) & 3);
  3995. s1 = algn (s1L, s1H, IREG (1) & 3);
  3996. }
  3997. tmp0 = (bs32)(bs16)(s0 >> 0) + ((s1 >> ( 0 + (8 * !HL))) & 0xff);
  3998. tmp1 = (bs32)(bs16)(s0 >> 16) + ((s1 >> (16 + (8 * !HL))) & 0xff);
  3999. STORE (DREG (dst0), (CLAMP (tmp0, 0, 255) << ( 0 + (8 * HL))) |
  4000. (CLAMP (tmp1, 0, 255) << (16 + (8 * HL))));
  4001. /* Implicit DISALGNEXCPT in parallel. */
  4002. DIS_ALGN_EXPT |= 1;
  4003. }
  4004. else if ((aop == 0 || aop == 1) && aopcde == 16 && x == 0 && s == 0)
  4005. {
  4006. bu32 av;
  4007. bs40 acc;
  4008. TRACE_INSN (cpu, "A%i = ABS A%i;", HL, aop);
  4009. acc = get_extended_acc (cpu, aop);
  4010. if (acc >> 39)
  4011. acc = -acc;
  4012. av = acc == ((bs40)1 << 39);
  4013. if (av)
  4014. acc = ((bs40)1 << 39) - 1;
  4015. SET_AREG (HL, acc);
  4016. SET_ASTATREG (av[HL], av);
  4017. if (av)
  4018. SET_ASTATREG (avs[HL], av);
  4019. SET_ASTATREG (az, acc == 0);
  4020. SET_ASTATREG (an, 0);
  4021. }
  4022. else if (aop == 3 && aopcde == 12 && x == 0 && s == 0)
  4023. {
  4024. bs32 res = DREG (src0);
  4025. bs32 ovX;
  4026. bool sBit_a, sBit_b;
  4027. TRACE_INSN (cpu, "R%i.%s = R%i (RND);", dst0, HL == 0 ? "L" : "H", src0);
  4028. TRACE_DECODE (cpu, "R%i.%s = R%i:%#x (RND);", dst0,
  4029. HL == 0 ? "L" : "H", src0, res);
  4030. sBit_b = !!(res & 0x80000000);
  4031. res += 0x8000;
  4032. sBit_a = !!(res & 0x80000000);
  4033. /* Overflow if the sign bit changed when we rounded. */
  4034. if ((res >> 16) && (sBit_b != sBit_a))
  4035. {
  4036. ovX = 1;
  4037. if (!sBit_b)
  4038. res = 0x7FFF;
  4039. else
  4040. res = 0x8000;
  4041. }
  4042. else
  4043. {
  4044. res = res >> 16;
  4045. ovX = 0;
  4046. }
  4047. if (!HL)
  4048. SET_DREG (dst0, REG_H_L (DREG (dst0), res));
  4049. else
  4050. SET_DREG (dst0, REG_H_L (res << 16, DREG (dst0)));
  4051. SET_ASTATREG (az, res == 0);
  4052. SET_ASTATREG (an, res < 0);
  4053. SET_ASTATREG (v, ovX);
  4054. if (ovX)
  4055. SET_ASTATREG (vs, ovX);
  4056. }
  4057. else if (aop == 3 && HL == 0 && aopcde == 15 && x == 0 && s == 0)
  4058. {
  4059. bu32 hi = (-(bs16)(DREG (src0) >> 16)) << 16;
  4060. bu32 lo = (-(bs16)(DREG (src0) & 0xFFFF)) & 0xFFFF;
  4061. int v, ac0, ac1;
  4062. TRACE_INSN (cpu, "R%i = -R%i (V);", dst0, src0);
  4063. v = ac0 = ac1 = 0;
  4064. if (hi == 0x80000000)
  4065. {
  4066. hi = 0x7fff0000;
  4067. v = 1;
  4068. }
  4069. else if (hi == 0)
  4070. ac1 = 1;
  4071. if (lo == 0x8000)
  4072. {
  4073. lo = 0x7fff;
  4074. v = 1;
  4075. }
  4076. else if (lo == 0)
  4077. ac0 = 1;
  4078. SET_DREG (dst0, hi | lo);
  4079. SET_ASTATREG (v, v);
  4080. if (v)
  4081. SET_ASTATREG (vs, 1);
  4082. SET_ASTATREG (ac0, ac0);
  4083. SET_ASTATREG (ac1, ac1);
  4084. setflags_nz_2x16 (cpu, DREG (dst0));
  4085. }
  4086. else if (aop == 3 && HL == 0 && aopcde == 14 && x == 0 && s == 0)
  4087. {
  4088. TRACE_INSN (cpu, "A1 = - A1 , A0 = - A0;");
  4089. SET_AREG (0, saturate_s40 (-get_extended_acc (cpu, 0)));
  4090. SET_AREG (1, saturate_s40 (-get_extended_acc (cpu, 1)));
  4091. /* XXX: what ASTAT flags need updating ? */
  4092. }
  4093. else if ((aop == 0 || aop == 1) && aopcde == 14 && x == 0 && s == 0)
  4094. {
  4095. bs40 src_acc = get_extended_acc (cpu, aop);
  4096. bu32 v = 0;
  4097. TRACE_INSN (cpu, "A%i = - A%i;", HL, aop);
  4098. SET_AREG (HL, saturate_s40_astat (-src_acc, &v));
  4099. SET_ASTATREG (az, AWREG (HL) == 0 && AXREG (HL) == 0);
  4100. SET_ASTATREG (an, AXREG (HL) >> 7);
  4101. if (HL == 0)
  4102. {
  4103. SET_ASTATREG (ac0, !src_acc);
  4104. SET_ASTATREG (av0, v);
  4105. if (v)
  4106. SET_ASTATREG (av0s, 1);
  4107. }
  4108. else
  4109. {
  4110. SET_ASTATREG (ac1, !src_acc);
  4111. SET_ASTATREG (av1, v);
  4112. if (v)
  4113. SET_ASTATREG (av1s, 1);
  4114. }
  4115. }
  4116. else if (aop == 0 && aopcde == 12 && x == 0 && s == 0 && HL == 0)
  4117. {
  4118. bs16 tmp0_hi = DREG (src0) >> 16;
  4119. bs16 tmp0_lo = DREG (src0);
  4120. bs16 tmp1_hi = DREG (src1) >> 16;
  4121. bs16 tmp1_lo = DREG (src1);
  4122. TRACE_INSN (cpu, "R%i.L = R%i.H = SIGN(R%i.H) * R%i.H + SIGN(R%i.L) * R%i.L;",
  4123. dst0, dst0, src0, src1, src0, src1);
  4124. if ((tmp0_hi >> 15) & 1)
  4125. tmp1_hi = ~tmp1_hi + 1;
  4126. if ((tmp0_lo >> 15) & 1)
  4127. tmp1_lo = ~tmp1_lo + 1;
  4128. tmp1_hi = tmp1_hi + tmp1_lo;
  4129. STORE (DREG (dst0), REG_H_L (tmp1_hi << 16, tmp1_hi));
  4130. }
  4131. else if (aopcde == 0 && HL == 0)
  4132. {
  4133. bu32 s0 = DREG (src0);
  4134. bu32 s1 = DREG (src1);
  4135. bu32 s0h = s0 >> 16;
  4136. bu32 s0l = s0 & 0xFFFF;
  4137. bu32 s1h = s1 >> 16;
  4138. bu32 s1l = s1 & 0xFFFF;
  4139. bu32 t0, t1;
  4140. bu32 ac1_i = 0, ac0_i = 0, v_i = 0, z_i = 0, n_i = 0;
  4141. TRACE_INSN (cpu, "R%i = R%i %c|%c R%i%s;", dst0, src0,
  4142. (aop & 2) ? '-' : '+', (aop & 1) ? '-' : '+', src1,
  4143. amod0 (s, x));
  4144. if (aop & 2)
  4145. t0 = sub16 (cpu, s0h, s1h, &ac1_i, &v_i, &z_i, &n_i, s, 0);
  4146. else
  4147. t0 = add16 (cpu, s0h, s1h, &ac1_i, &v_i, &z_i, &n_i, s, 0);
  4148. if (aop & 1)
  4149. t1 = sub16 (cpu, s0l, s1l, &ac0_i, &v_i, &z_i, &n_i, s, 0);
  4150. else
  4151. t1 = add16 (cpu, s0l, s1l, &ac0_i, &v_i, &z_i, &n_i, s, 0);
  4152. SET_ASTATREG (ac1, ac1_i);
  4153. SET_ASTATREG (ac0, ac0_i);
  4154. SET_ASTATREG (az, z_i);
  4155. SET_ASTATREG (an, n_i);
  4156. SET_ASTATREG (v, v_i);
  4157. if (v_i)
  4158. SET_ASTATREG (vs, v_i);
  4159. t0 &= 0xFFFF;
  4160. t1 &= 0xFFFF;
  4161. if (x)
  4162. SET_DREG (dst0, (t1 << 16) | t0);
  4163. else
  4164. SET_DREG (dst0, (t0 << 16) | t1);
  4165. }
  4166. else if (aop == 1 && aopcde == 12 && x == 0 && s == 0 && HL == 0)
  4167. {
  4168. bs32 val0 = (bs16)(AWREG (0) >> 16) + (bs16)AWREG (0);
  4169. bs32 val1 = (bs16)(AWREG (1) >> 16) + (bs16)AWREG (1);
  4170. TRACE_INSN (cpu, "R%i = A1.L + A1.H, R%i = A0.L + A0.H;", dst1, dst0);
  4171. if (dst0 == dst1)
  4172. illegal_instruction_combination (cpu);
  4173. SET_DREG (dst0, val0);
  4174. SET_DREG (dst1, val1);
  4175. }
  4176. else if ((aop == 0 || aop == 2 || aop == 3) && aopcde == 1)
  4177. {
  4178. bu32 d0, d1;
  4179. bu32 x0, x1;
  4180. bu16 s0L = DREG (src0);
  4181. bu16 s0H = DREG (src0) >> 16;
  4182. bu16 s1L = DREG (src1);
  4183. bu16 s1H = DREG (src1) >> 16;
  4184. bu32 v_i = 0, n_i = 0, z_i = 0;
  4185. TRACE_INSN (cpu, "R%i = R%i %s R%i, R%i = R%i %s R%i%s;",
  4186. dst1, src0, HL ? "+|-" : "+|+", src1,
  4187. dst0, src0, HL ? "-|+" : "-|-", src1,
  4188. amod0amod2 (s, x, aop));
  4189. if (dst0 == dst1)
  4190. illegal_instruction_combination (cpu);
  4191. if (HL == 0)
  4192. {
  4193. x0 = add16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
  4194. x1 = add16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
  4195. d1 = (x0 << 16) | x1;
  4196. x0 = sub16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
  4197. x1 = sub16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
  4198. if (x == 0)
  4199. d0 = (x0 << 16) | x1;
  4200. else
  4201. d0 = (x1 << 16) | x0;
  4202. }
  4203. else
  4204. {
  4205. x0 = add16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
  4206. x1 = sub16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
  4207. d1 = (x0 << 16) | x1;
  4208. x0 = sub16 (cpu, s0H, s1H, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
  4209. x1 = add16 (cpu, s0L, s1L, 0, &v_i, &z_i, &n_i, s, aop) & 0xffff;
  4210. if (x == 0)
  4211. d0 = (x0 << 16) | x1;
  4212. else
  4213. d0 = (x1 << 16) | x0;
  4214. }
  4215. SET_ASTATREG (az, z_i);
  4216. SET_ASTATREG (an, n_i);
  4217. SET_ASTATREG (v, v_i);
  4218. if (v_i)
  4219. SET_ASTATREG (vs, v_i);
  4220. STORE (DREG (dst0), d0);
  4221. STORE (DREG (dst1), d1);
  4222. }
  4223. else if ((aop == 0 || aop == 1 || aop == 2) && aopcde == 11 && x == 0)
  4224. {
  4225. bs40 acc0 = get_extended_acc (cpu, 0);
  4226. bs40 acc1 = get_extended_acc (cpu, 1);
  4227. bu32 v, dreg, sat = 0;
  4228. bu32 carry = !!((bu40)~acc1 < (bu40)acc0);
  4229. if (aop == 0)
  4230. {
  4231. if (s != 0 || HL != 0)
  4232. illegal_instruction (cpu);
  4233. TRACE_INSN (cpu, "R%i = (A0 += A1);", dst0);
  4234. }
  4235. else if (aop == 1)
  4236. {
  4237. if (s != 0)
  4238. illegal_instruction (cpu);
  4239. TRACE_INSN (cpu, "R%i.%c = (A0 += A1);", dst0, HL ? 'H' : 'L');
  4240. }
  4241. else
  4242. {
  4243. if (HL != 0)
  4244. illegal_instruction (cpu);
  4245. TRACE_INSN (cpu, "A0 += A1%s;", s ? " (W32)" : "");
  4246. }
  4247. acc0 += acc1;
  4248. acc0 = saturate_s40_astat (acc0, &v);
  4249. if (aop == 2 && s == 1) /* A0 += A1 (W32) */
  4250. {
  4251. if (acc0 & (bs40)0x8000000000ll)
  4252. acc0 &= 0x80ffffffffll;
  4253. else
  4254. acc0 &= 0xffffffffll;
  4255. }
  4256. STORE (AXREG (0), acc0 >> 32);
  4257. STORE (AWREG (0), acc0);
  4258. SET_ASTATREG (av0, v && acc1);
  4259. if (v)
  4260. SET_ASTATREG (av0s, v);
  4261. if (aop == 0 || aop == 1)
  4262. {
  4263. if (aop) /* Dregs_lo = A0 += A1 */
  4264. {
  4265. dreg = saturate_s32 (rnd16 (acc0) << 16, &sat);
  4266. if (HL)
  4267. STORE (DREG (dst0), REG_H_L (dreg, DREG (dst0)));
  4268. else
  4269. STORE (DREG (dst0), REG_H_L (DREG (dst0), dreg >> 16));
  4270. }
  4271. else /* Dregs = A0 += A1 */
  4272. {
  4273. dreg = saturate_s32 (acc0, &sat);
  4274. STORE (DREG (dst0), dreg);
  4275. }
  4276. STORE (ASTATREG (az), dreg == 0);
  4277. STORE (ASTATREG (an), !!(dreg & 0x80000000));
  4278. STORE (ASTATREG (ac0), carry);
  4279. STORE (ASTATREG (ac0_copy), carry);
  4280. STORE (ASTATREG (v), sat);
  4281. STORE (ASTATREG (v_copy), sat);
  4282. if (sat)
  4283. STORE (ASTATREG (vs), sat);
  4284. }
  4285. else
  4286. {
  4287. STORE (ASTATREG (az), acc0 == 0);
  4288. STORE (ASTATREG (an), !!(acc0 & 0x8000000000ull));
  4289. STORE (ASTATREG (ac0), carry);
  4290. STORE (ASTATREG (ac0_copy), carry);
  4291. }
  4292. }
  4293. else if ((aop == 0 || aop == 1) && aopcde == 10 && x == 0 && s == 0 && HL == 0)
  4294. {
  4295. TRACE_INSN (cpu, "R%i.L = A%i.X;", dst0, aop);
  4296. SET_DREG_L (dst0, (bs8)AXREG (aop));
  4297. }
  4298. else if (aop == 0 && aopcde == 4 && x == 0 && HL == 0)
  4299. {
  4300. TRACE_INSN (cpu, "R%i = R%i + R%i%s;", dst0, src0, src1, amod1 (s, x));
  4301. SET_DREG (dst0, add32 (cpu, DREG (src0), DREG (src1), 1, s));
  4302. }
  4303. else if (aop == 1 && aopcde == 4 && x == 0 && HL == 0)
  4304. {
  4305. TRACE_INSN (cpu, "R%i = R%i - R%i%s;", dst0, src0, src1, amod1 (s, x));
  4306. SET_DREG (dst0, sub32 (cpu, DREG (src0), DREG (src1), 1, s, 0));
  4307. }
  4308. else if (aop == 2 && aopcde == 4 && x == 0 && HL == 0)
  4309. {
  4310. TRACE_INSN (cpu, "R%i = R%i + R%i, R%i = R%i - R%i%s;",
  4311. dst1, src0, src1, dst0, src0, src1, amod1 (s, x));
  4312. if (dst0 == dst1)
  4313. illegal_instruction_combination (cpu);
  4314. STORE (DREG (dst1), add32 (cpu, DREG (src0), DREG (src1), 1, s));
  4315. STORE (DREG (dst0), sub32 (cpu, DREG (src0), DREG (src1), 1, s, 1));
  4316. }
  4317. else if ((aop == 0 || aop == 1) && aopcde == 17 && x == 0 && HL == 0)
  4318. {
  4319. bs40 acc0 = get_extended_acc (cpu, 0);
  4320. bs40 acc1 = get_extended_acc (cpu, 1);
  4321. bs40 val0, val1, sval0, sval1;
  4322. bu32 sat, sat_i;
  4323. TRACE_INSN (cpu, "R%i = A%i + A%i, R%i = A%i - A%i%s",
  4324. dst1, !aop, aop, dst0, !aop, aop, amod1 (s, x));
  4325. TRACE_DECODE (cpu, "R%i = A%i:%#"PRIx64" + A%i:%#"PRIx64", "
  4326. "R%i = A%i:%#"PRIx64" - A%i:%#"PRIx64"%s",
  4327. dst1, !aop, aop ? acc0 : acc1, aop, aop ? acc1 : acc0,
  4328. dst0, !aop, aop ? acc0 : acc1, aop, aop ? acc1 : acc0,
  4329. amod1 (s, x));
  4330. if (dst0 == dst1)
  4331. illegal_instruction_combination (cpu);
  4332. val1 = acc0 + acc1;
  4333. if (aop)
  4334. val0 = acc0 - acc1;
  4335. else
  4336. val0 = acc1 - acc0;
  4337. sval0 = saturate_s32 (val0, &sat);
  4338. sat_i = sat;
  4339. sval1 = saturate_s32 (val1, &sat);
  4340. sat_i |= sat;
  4341. if (s)
  4342. {
  4343. val0 = sval0;
  4344. val1 = sval1;
  4345. }
  4346. STORE (DREG (dst0), val0);
  4347. STORE (DREG (dst1), val1);
  4348. SET_ASTATREG (v, sat_i);
  4349. if (sat_i)
  4350. SET_ASTATREG (vs, sat_i);
  4351. SET_ASTATREG (an, val0 & 0x80000000 || val1 & 0x80000000);
  4352. SET_ASTATREG (az, val0 == 0 || val1 == 0);
  4353. SET_ASTATREG (ac1, (bu40)~acc0 < (bu40)acc1);
  4354. if (aop)
  4355. SET_ASTATREG (ac0, !!((bu40)acc1 <= (bu40)acc0));
  4356. else
  4357. SET_ASTATREG (ac0, !!((bu40)acc0 <= (bu40)acc1));
  4358. }
  4359. else if (aop == 0 && aopcde == 18 && x == 0 && HL == 0)
  4360. {
  4361. bu40 acc0 = get_extended_acc (cpu, 0);
  4362. bu40 acc1 = get_extended_acc (cpu, 1);
  4363. bu32 s0L = DREG (src0);
  4364. bu32 s0H = DREG (src0 + 1);
  4365. bu32 s1L = DREG (src1);
  4366. bu32 s1H = DREG (src1 + 1);
  4367. bu32 s0, s1;
  4368. bs16 tmp0, tmp1, tmp2, tmp3;
  4369. /* This instruction is only defined for register pairs R1:0 and R3:2. */
  4370. if (!((src0 == 0 || src0 == 2) && (src1 == 0 || src1 == 2)))
  4371. illegal_instruction (cpu);
  4372. TRACE_INSN (cpu, "SAA (R%i:%i, R%i:%i)%s", src0 + 1, src0,
  4373. src1 + 1, src1, s ? " (R)" :"");
  4374. /* Bit s determines the order of the two registers from a pair:
  4375. if s=0 the low-order bytes come from the low reg in the pair,
  4376. and if s=1 the low-order bytes come from the high reg. */
  4377. if (s)
  4378. {
  4379. s0 = algn (s0H, s0L, IREG (0) & 3);
  4380. s1 = algn (s1H, s1L, IREG (1) & 3);
  4381. }
  4382. else
  4383. {
  4384. s0 = algn (s0L, s0H, IREG (0) & 3);
  4385. s1 = algn (s1L, s1H, IREG (1) & 3);
  4386. }
  4387. /* Find the absolute difference between pairs, make it
  4388. absolute, then add it to the existing accumulator half. */
  4389. /* Byte 0 */
  4390. tmp0 = ((s0 << 24) >> 24) - ((s1 << 24) >> 24);
  4391. tmp1 = ((s0 << 16) >> 24) - ((s1 << 16) >> 24);
  4392. tmp2 = ((s0 << 8) >> 24) - ((s1 << 8) >> 24);
  4393. tmp3 = ((s0 << 0) >> 24) - ((s1 << 0) >> 24);
  4394. tmp0 = (tmp0 < 0) ? -tmp0 : tmp0;
  4395. tmp1 = (tmp1 < 0) ? -tmp1 : tmp1;
  4396. tmp2 = (tmp2 < 0) ? -tmp2 : tmp2;
  4397. tmp3 = (tmp3 < 0) ? -tmp3 : tmp3;
  4398. s0L = saturate_u16 ((bu32)tmp0 + ((acc0 >> 0) & 0xffff), 0);
  4399. s0H = saturate_u16 ((bu32)tmp1 + ((acc0 >> 16) & 0xffff), 0);
  4400. s1L = saturate_u16 ((bu32)tmp2 + ((acc1 >> 0) & 0xffff), 0);
  4401. s1H = saturate_u16 ((bu32)tmp3 + ((acc1 >> 16) & 0xffff), 0);
  4402. STORE (AWREG (0), (s0H << 16) | (s0L & 0xFFFF));
  4403. STORE (AXREG (0), 0);
  4404. STORE (AWREG (1), (s1H << 16) | (s1L & 0xFFFF));
  4405. STORE (AXREG (1), 0);
  4406. /* Implicit DISALGNEXCPT in parallel. */
  4407. DIS_ALGN_EXPT |= 1;
  4408. }
  4409. else if (aop == 3 && aopcde == 18 && x == 0 && s == 0 && HL == 0)
  4410. {
  4411. TRACE_INSN (cpu, "DISALGNEXCPT");
  4412. DIS_ALGN_EXPT |= 1;
  4413. }
  4414. else if ((aop == 0 || aop == 1) && aopcde == 20 && x == 0 && HL == 0)
  4415. {
  4416. bu32 s0, s0L, s0H, s1, s1L, s1H;
  4417. const char * const opts[] = { "", " (R)", " (T)", " (T, R)" };
  4418. TRACE_INSN (cpu, "R%i = BYTEOP1P (R%i:%i, R%i:%i)%s;", dst0,
  4419. src0 + 1, src0, src1 + 1, src1, opts[s + (aop << 1)]);
  4420. if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
  4421. illegal_instruction (cpu);
  4422. s0L = DREG (src0);
  4423. s0H = DREG (src0 + 1);
  4424. s1L = DREG (src1);
  4425. s1H = DREG (src1 + 1);
  4426. if (s)
  4427. {
  4428. s0 = algn (s0H, s0L, IREG (0) & 3);
  4429. s1 = algn (s1H, s1L, IREG (1) & 3);
  4430. }
  4431. else
  4432. {
  4433. s0 = algn (s0L, s0H, IREG (0) & 3);
  4434. s1 = algn (s1L, s1H, IREG (1) & 3);
  4435. }
  4436. STORE (DREG (dst0),
  4437. (((((s0 >> 0) & 0xff) + ((s1 >> 0) & 0xff) + !aop) >> 1) << 0) |
  4438. (((((s0 >> 8) & 0xff) + ((s1 >> 8) & 0xff) + !aop) >> 1) << 8) |
  4439. (((((s0 >> 16) & 0xff) + ((s1 >> 16) & 0xff) + !aop) >> 1) << 16) |
  4440. (((((s0 >> 24) & 0xff) + ((s1 >> 24) & 0xff) + !aop) >> 1) << 24));
  4441. /* Implicit DISALGNEXCPT in parallel. */
  4442. DIS_ALGN_EXPT |= 1;
  4443. }
  4444. else if (aop == 0 && aopcde == 21 && x == 0 && HL == 0)
  4445. {
  4446. bu32 s0, s0L, s0H, s1, s1L, s1H;
  4447. TRACE_INSN (cpu, "(R%i, R%i) = BYTEOP16P (R%i:%i, R%i:%i)%s;", dst1, dst0,
  4448. src0 + 1, src0, src1 + 1, src1, s ? " (R)" : "");
  4449. if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
  4450. illegal_instruction (cpu);
  4451. if (dst0 == dst1)
  4452. illegal_instruction_combination (cpu);
  4453. s0L = DREG (src0);
  4454. s0H = DREG (src0 + 1);
  4455. s1L = DREG (src1);
  4456. s1H = DREG (src1 + 1);
  4457. if (s)
  4458. {
  4459. s0 = algn (s0H, s0L, IREG (0) & 3);
  4460. s1 = algn (s1H, s1L, IREG (1) & 3);
  4461. }
  4462. else
  4463. {
  4464. s0 = algn (s0L, s0H, IREG (0) & 3);
  4465. s1 = algn (s1L, s1H, IREG (1) & 3);
  4466. }
  4467. STORE (DREG (dst0),
  4468. ((((s0 >> 0) & 0xff) + ((s1 >> 0) & 0xff)) << 0) |
  4469. ((((s0 >> 8) & 0xff) + ((s1 >> 8) & 0xff)) << 16));
  4470. STORE (DREG (dst1),
  4471. ((((s0 >> 16) & 0xff) + ((s1 >> 16) & 0xff)) << 0) |
  4472. ((((s0 >> 24) & 0xff) + ((s1 >> 24) & 0xff)) << 16));
  4473. /* Implicit DISALGNEXCPT in parallel. */
  4474. DIS_ALGN_EXPT |= 1;
  4475. }
  4476. else if (aop == 1 && aopcde == 21 && x == 0 && HL == 0)
  4477. {
  4478. bu32 s0, s0L, s0H, s1, s1L, s1H;
  4479. TRACE_INSN (cpu, "(R%i, R%i) = BYTEOP16M (R%i:%i, R%i:%i)%s;", dst1, dst0,
  4480. src0 + 1, src0, src1 + 1, src1, s ? " (R)" : "");
  4481. if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
  4482. illegal_instruction (cpu);
  4483. if (dst0 == dst1)
  4484. illegal_instruction_combination (cpu);
  4485. s0L = DREG (src0);
  4486. s0H = DREG (src0 + 1);
  4487. s1L = DREG (src1);
  4488. s1H = DREG (src1 + 1);
  4489. if (s)
  4490. {
  4491. s0 = algn (s0H, s0L, IREG (0) & 3);
  4492. s1 = algn (s1H, s1L, IREG (1) & 3);
  4493. }
  4494. else
  4495. {
  4496. s0 = algn (s0L, s0H, IREG (0) & 3);
  4497. s1 = algn (s1L, s1H, IREG (1) & 3);
  4498. }
  4499. STORE (DREG (dst0),
  4500. (((((s0 >> 0) & 0xff) - ((s1 >> 0) & 0xff)) << 0) & 0xffff) |
  4501. (((((s0 >> 8) & 0xff) - ((s1 >> 8) & 0xff)) << 16)));
  4502. STORE (DREG (dst1),
  4503. (((((s0 >> 16) & 0xff) - ((s1 >> 16) & 0xff)) << 0) & 0xffff) |
  4504. (((((s0 >> 24) & 0xff) - ((s1 >> 24) & 0xff)) << 16)));
  4505. /* Implicit DISALGNEXCPT in parallel. */
  4506. DIS_ALGN_EXPT |= 1;
  4507. }
  4508. else if (aop == 1 && aopcde == 7 && x == 0 && s == 0 && HL == 0)
  4509. {
  4510. TRACE_INSN (cpu, "R%i = MIN (R%i, R%i);", dst0, src0, src1);
  4511. SET_DREG (dst0, min32 (cpu, DREG (src0), DREG (src1)));
  4512. }
  4513. else if (aop == 0 && aopcde == 7 && x == 0 && s == 0 && HL == 0)
  4514. {
  4515. TRACE_INSN (cpu, "R%i = MAX (R%i, R%i);", dst0, src0, src1);
  4516. SET_DREG (dst0, max32 (cpu, DREG (src0), DREG (src1)));
  4517. }
  4518. else if (aop == 2 && aopcde == 7 && x == 0 && s == 0 && HL == 0)
  4519. {
  4520. bu32 val = DREG (src0);
  4521. int v;
  4522. TRACE_INSN (cpu, "R%i = ABS R%i;", dst0, src0);
  4523. if (val >> 31)
  4524. val = -val;
  4525. v = (val == 0x80000000);
  4526. if (v)
  4527. val = 0x7fffffff;
  4528. SET_DREG (dst0, val);
  4529. SET_ASTATREG (v, v);
  4530. if (v)
  4531. SET_ASTATREG (vs, 1);
  4532. setflags_nz (cpu, val);
  4533. }
  4534. else if (aop == 3 && aopcde == 7 && x == 0 && HL == 0)
  4535. {
  4536. bu32 val = DREG (src0);
  4537. TRACE_INSN (cpu, "R%i = - R%i%s;", dst0, src0, amod1 (s, 0));
  4538. if (s && val == 0x80000000)
  4539. {
  4540. val = 0x7fffffff;
  4541. SET_ASTATREG (v, 1);
  4542. SET_ASTATREG (vs, 1);
  4543. }
  4544. else if (val == 0x80000000)
  4545. val = 0x80000000;
  4546. else
  4547. val = -val;
  4548. SET_DREG (dst0, val);
  4549. SET_ASTATREG (az, val == 0);
  4550. SET_ASTATREG (an, val & 0x80000000);
  4551. }
  4552. else if (aop == 2 && aopcde == 6 && x == 0 && s == 0 && HL == 0)
  4553. {
  4554. bu32 in = DREG (src0);
  4555. bu32 hi = (in & 0x80000000 ? (bu32)-(bs16)(in >> 16) : in >> 16) << 16;
  4556. bu32 lo = (in & 0x8000 ? (bu32)-(bs16)(in & 0xFFFF) : in) & 0xFFFF;
  4557. int v;
  4558. TRACE_INSN (cpu, "R%i = ABS R%i (V);", dst0, src0);
  4559. v = 0;
  4560. if (hi == 0x80000000)
  4561. {
  4562. hi = 0x7fff0000;
  4563. v = 1;
  4564. }
  4565. if (lo == 0x8000)
  4566. {
  4567. lo = 0x7fff;
  4568. v = 1;
  4569. }
  4570. SET_DREG (dst0, hi | lo);
  4571. SET_ASTATREG (v, v);
  4572. if (v)
  4573. SET_ASTATREG (vs, 1);
  4574. setflags_nz_2x16 (cpu, DREG (dst0));
  4575. }
  4576. else if (aop == 1 && aopcde == 6 && x == 0 && s == 0 && HL == 0)
  4577. {
  4578. TRACE_INSN (cpu, "R%i = MIN (R%i, R%i) (V);", dst0, src0, src1);
  4579. SET_DREG (dst0, min2x16 (cpu, DREG (src0), DREG (src1)));
  4580. }
  4581. else if (aop == 0 && aopcde == 6 && x == 0 && s == 0 && HL == 0)
  4582. {
  4583. TRACE_INSN (cpu, "R%i = MAX (R%i, R%i) (V);", dst0, src0, src1);
  4584. SET_DREG (dst0, max2x16 (cpu, DREG (src0), DREG (src1)));
  4585. }
  4586. else if (aop == 0 && aopcde == 24 && x == 0 && s == 0 && HL == 0)
  4587. {
  4588. TRACE_INSN (cpu, "R%i = BYTEPACK (R%i, R%i);", dst0, src0, src1);
  4589. STORE (DREG (dst0),
  4590. (((DREG (src0) >> 0) & 0xff) << 0) |
  4591. (((DREG (src0) >> 16) & 0xff) << 8) |
  4592. (((DREG (src1) >> 0) & 0xff) << 16) |
  4593. (((DREG (src1) >> 16) & 0xff) << 24));
  4594. /* Implicit DISALGNEXCPT in parallel. */
  4595. DIS_ALGN_EXPT |= 1;
  4596. }
  4597. else if (aop == 1 && aopcde == 24 && x == 0 && HL == 0)
  4598. {
  4599. int order, lo, hi;
  4600. bu64 comb_src;
  4601. bu8 bytea, byteb, bytec, byted;
  4602. TRACE_INSN (cpu, "(R%i, R%i) = BYTEUNPACK R%i:%i%s;",
  4603. dst1, dst0, src0 + 1, src0, s ? " (R)" : "");
  4604. if ((src1 != 0 && src1 != 2) || (src0 != 0 && src0 != 2))
  4605. illegal_instruction (cpu);
  4606. if (dst0 == dst1)
  4607. illegal_instruction_combination (cpu);
  4608. order = IREG (0) & 0x3;
  4609. if (s)
  4610. hi = src0, lo = src0 + 1;
  4611. else
  4612. hi = src0 + 1, lo = src0;
  4613. comb_src = (((bu64)DREG (hi)) << 32) | DREG (lo);
  4614. bytea = (comb_src >> (0 + 8 * order));
  4615. byteb = (comb_src >> (8 + 8 * order));
  4616. bytec = (comb_src >> (16 + 8 * order));
  4617. byted = (comb_src >> (24 + 8 * order));
  4618. STORE (DREG (dst0), bytea | ((bu32)byteb << 16));
  4619. STORE (DREG (dst1), bytec | ((bu32)byted << 16));
  4620. /* Implicit DISALGNEXCPT in parallel. */
  4621. DIS_ALGN_EXPT |= 1;
  4622. }
  4623. else if (aopcde == 13 && HL == 0 && x == 0 && s == 0)
  4624. {
  4625. const char *searchmodes[] = { "GT", "GE", "LT", "LE" };
  4626. bool up_hi, up_lo;
  4627. bs16 a0_lo, a1_lo, src_hi, src_lo;
  4628. TRACE_INSN (cpu, "(R%i, R%i) = SEARCH R%i (%s);",
  4629. dst1, dst0, src0, searchmodes[aop]);
  4630. /* XXX: The parallel version is a bit weird in its limits:
  4631. This instruction can be issued in parallel with the combination of one
  4632. 16-bit length load instruction to the P0 register and one 16-bit NOP.
  4633. No other instructions can be issued in parallel with the Vector Search
  4634. instruction. Note the following legal and illegal forms.
  4635. (r1, r0) = search r2 (LT) || r2 = [p0++p3]; // ILLEGAL
  4636. (r1, r0) = search r2 (LT) || r2 = [p0++]; // LEGAL
  4637. (r1, r0) = search r2 (LT) || r2 = [p0++]; // LEGAL
  4638. Unfortunately, our parallel insn state doesn't (currently) track enough
  4639. details to be able to check this. */
  4640. if (dst0 == dst1)
  4641. illegal_instruction_combination (cpu);
  4642. up_hi = up_lo = false;
  4643. a0_lo = AWREG (0);
  4644. a1_lo = AWREG (1);
  4645. src_lo = DREG (src0);
  4646. src_hi = DREG (src0) >> 16;
  4647. switch (aop)
  4648. {
  4649. case 0:
  4650. up_hi = (src_hi > a1_lo);
  4651. up_lo = (src_lo > a0_lo);
  4652. break;
  4653. case 1:
  4654. up_hi = (src_hi >= a1_lo);
  4655. up_lo = (src_lo >= a0_lo);
  4656. break;
  4657. case 2:
  4658. up_hi = (src_hi < a1_lo);
  4659. up_lo = (src_lo < a0_lo);
  4660. break;
  4661. case 3:
  4662. up_hi = (src_hi <= a1_lo);
  4663. up_lo = (src_lo <= a0_lo);
  4664. break;
  4665. }
  4666. if (up_hi)
  4667. {
  4668. SET_AREG (1, src_hi);
  4669. SET_DREG (dst1, PREG (0));
  4670. }
  4671. else
  4672. SET_AREG (1, a1_lo);
  4673. if (up_lo)
  4674. {
  4675. SET_AREG (0, src_lo);
  4676. SET_DREG (dst0, PREG (0));
  4677. }
  4678. else
  4679. SET_AREG (0, a0_lo);
  4680. }
  4681. else
  4682. illegal_instruction (cpu);
  4683. }
  4684. static void
  4685. decode_dsp32shift_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
  4686. {
  4687. /* dsp32shift
  4688. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  4689. | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 0 | - | - |.sopcde............|
  4690. |.sop...|.HLs...|.dst0......| - | - | - |.src0......|.src1......|
  4691. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  4692. int HLs = ((iw1 >> DSP32Shift_HLs_bits) & DSP32Shift_HLs_mask);
  4693. int sop = ((iw1 >> DSP32Shift_sop_bits) & DSP32Shift_sop_mask);
  4694. int src0 = ((iw1 >> DSP32Shift_src0_bits) & DSP32Shift_src0_mask);
  4695. int src1 = ((iw1 >> DSP32Shift_src1_bits) & DSP32Shift_src1_mask);
  4696. int dst0 = ((iw1 >> DSP32Shift_dst0_bits) & DSP32Shift_dst0_mask);
  4697. int sopcde = ((iw0 >> (DSP32Shift_sopcde_bits - 16)) & DSP32Shift_sopcde_mask);
  4698. int M = ((iw0 >> (DSP32Shift_M_bits - 16)) & DSP32Shift_M_mask);
  4699. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32shift);
  4700. TRACE_EXTRACT (cpu, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i src0:%i src1:%i",
  4701. __func__, M, sopcde, sop, HLs, dst0, src0, src1);
  4702. if ((sop == 0 || sop == 1) && sopcde == 0)
  4703. {
  4704. bu16 val;
  4705. bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
  4706. TRACE_INSN (cpu, "R%i.%c = ASHIFT R%i.%c BY R%i.L%s;",
  4707. dst0, HLs < 2 ? 'L' : 'H',
  4708. src1, HLs & 1 ? 'H' : 'L',
  4709. src0, sop == 1 ? " (S)" : "");
  4710. if ((HLs & 1) == 0)
  4711. val = (bu16)(DREG (src1) & 0xFFFF);
  4712. else
  4713. val = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
  4714. /* Positive shift magnitudes produce Logical Left shifts.
  4715. Negative shift magnitudes produce Arithmetic Right shifts. */
  4716. if (shft <= 0)
  4717. val = ashiftrt (cpu, val, -shft, 16);
  4718. else
  4719. {
  4720. int sgn = (val >> 15) & 0x1;
  4721. val = lshift (cpu, val, shft, 16, sop == 1, 1);
  4722. if (((val >> 15) & 0x1) != sgn)
  4723. {
  4724. SET_ASTATREG (v, 1);
  4725. SET_ASTATREG (vs, 1);
  4726. }
  4727. }
  4728. if ((HLs & 2) == 0)
  4729. STORE (DREG (dst0), REG_H_L (DREG (dst0), val));
  4730. else
  4731. STORE (DREG (dst0), REG_H_L (val << 16, DREG (dst0)));
  4732. }
  4733. else if (sop == 2 && sopcde == 0)
  4734. {
  4735. bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
  4736. bu16 val;
  4737. TRACE_INSN (cpu, "R%i.%c = LSHIFT R%i.%c BY R%i.L;",
  4738. dst0, HLs < 2 ? 'L' : 'H',
  4739. src1, HLs & 1 ? 'H' : 'L', src0);
  4740. if ((HLs & 1) == 0)
  4741. val = (bu16)(DREG (src1) & 0xFFFF);
  4742. else
  4743. val = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
  4744. if (shft < 0)
  4745. val = val >> (-1 * shft);
  4746. else
  4747. val = val << shft;
  4748. if ((HLs & 2) == 0)
  4749. SET_DREG (dst0, REG_H_L (DREG (dst0), val));
  4750. else
  4751. SET_DREG (dst0, REG_H_L (val << 16, DREG (dst0)));
  4752. SET_ASTATREG (az, !((val & 0xFFFF0000) == 0) || ((val & 0xFFFF) == 0));
  4753. SET_ASTATREG (an, (!!(val & 0x80000000)) ^ (!!(val & 0x8000)));
  4754. SET_ASTATREG (v, 0);
  4755. }
  4756. else if (sop == 2 && sopcde == 3 && (HLs == 1 || HLs == 0))
  4757. {
  4758. int shift = imm6 (DREG (src0) & 0xFFFF);
  4759. bu32 cc = CCREG;
  4760. bu40 acc = get_unextended_acc (cpu, HLs);
  4761. TRACE_INSN (cpu, "A%i = ROT A%i BY R%i.L;", HLs, HLs, src0);
  4762. TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i CC:%i", HLs, acc, shift, cc);
  4763. acc = rot40 (acc, shift, &cc);
  4764. SET_AREG (HLs, acc);
  4765. if (shift)
  4766. SET_CCREG (cc);
  4767. }
  4768. else if (sop == 0 && sopcde == 3 && (HLs == 0 || HLs == 1))
  4769. {
  4770. bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
  4771. bu64 acc = get_extended_acc (cpu, HLs);
  4772. bu64 val;
  4773. HLs = !!HLs;
  4774. TRACE_INSN (cpu, "A%i = ASHIFT A%i BY R%i.L;", HLs, HLs, src0);
  4775. TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i", HLs, acc, shft);
  4776. if (shft <= 0)
  4777. val = ashiftrt (cpu, acc, -shft, 40);
  4778. else
  4779. val = lshift (cpu, acc, shft, 40, 0, 0);
  4780. STORE (AXREG (HLs), (val >> 32) & 0xff);
  4781. STORE (AWREG (HLs), (val & 0xffffffff));
  4782. STORE (ASTATREG (av[HLs]), 0);
  4783. }
  4784. else if (sop == 1 && sopcde == 3 && (HLs == 0 || HLs == 1))
  4785. {
  4786. bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
  4787. bu64 acc = get_unextended_acc (cpu, HLs);
  4788. bu64 val;
  4789. HLs = !!HLs;
  4790. TRACE_INSN (cpu, "A%i = LSHIFT A%i BY R%i.L;", HLs, HLs, src0);
  4791. TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i", HLs, acc, shft);
  4792. if (shft <= 0)
  4793. val = lshiftrt (cpu, acc, -shft, 40);
  4794. else
  4795. val = lshift (cpu, acc, shft, 40, 0, 0);
  4796. STORE (AXREG (HLs), (val >> 32) & 0xff);
  4797. STORE (AWREG (HLs), (val & 0xffffffff));
  4798. STORE (ASTATREG (av[HLs]), 0);
  4799. }
  4800. else if (HLs != 0)
  4801. /* All the insns after this point don't use HLs. */
  4802. illegal_instruction (cpu);
  4803. else if ((sop == 0 || sop == 1) && sopcde == 1 && HLs == 0)
  4804. {
  4805. bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
  4806. bu16 val0, val1;
  4807. bu32 astat;
  4808. TRACE_INSN (cpu, "R%i = ASHIFT R%i BY R%i.L (V%s);",
  4809. dst0, src1, src0, sop == 1 ? ",S" : "");
  4810. val0 = (bu16)DREG (src1) & 0xFFFF;
  4811. val1 = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
  4812. if (shft <= 0)
  4813. {
  4814. val0 = ashiftrt (cpu, val0, -shft, 16);
  4815. astat = ASTAT;
  4816. val1 = ashiftrt (cpu, val1, -shft, 16);
  4817. }
  4818. else
  4819. {
  4820. int sgn0 = (val0 >> 15) & 0x1;
  4821. int sgn1 = (val1 >> 15) & 0x1;
  4822. val0 = lshift (cpu, val0, shft, 16, sop == 1, 1);
  4823. astat = ASTAT;
  4824. val1 = lshift (cpu, val1, shft, 16, sop == 1, 1);
  4825. if ((sgn0 != ((val0 >> 15) & 0x1)) || (sgn1 != ((val1 >> 15) & 0x1)))
  4826. {
  4827. SET_ASTATREG (v, 1);
  4828. SET_ASTATREG (vs, 1);
  4829. }
  4830. }
  4831. SET_ASTAT (ASTAT | astat);
  4832. STORE (DREG (dst0), (val1 << 16) | val0);
  4833. }
  4834. else if ((sop == 0 || sop == 1 || sop == 2) && sopcde == 2)
  4835. {
  4836. /* dregs = [LA]SHIFT dregs BY dregs_lo (opt_S) */
  4837. /* sop == 1 : opt_S */
  4838. bu32 v = DREG (src1);
  4839. /* LSHIFT uses sign extended low 6 bits of dregs_lo. */
  4840. bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
  4841. TRACE_INSN (cpu, "R%i = %cSHIFT R%i BY R%i.L%s;", dst0,
  4842. shft && sop != 2 ? 'A' : 'L', src1, src0,
  4843. sop == 1 ? " (S)" : "");
  4844. if (shft < 0)
  4845. {
  4846. if (sop == 2)
  4847. STORE (DREG (dst0), lshiftrt (cpu, v, -shft, 32));
  4848. else
  4849. STORE (DREG (dst0), ashiftrt (cpu, v, -shft, 32));
  4850. }
  4851. else
  4852. {
  4853. bu32 val = lshift (cpu, v, shft, 32, sop == 1, 1);
  4854. STORE (DREG (dst0), val);
  4855. if (((v >> 31) & 0x1) != ((val >> 31) & 0x1))
  4856. {
  4857. SET_ASTATREG (v, 1);
  4858. SET_ASTATREG (vs, 1);
  4859. }
  4860. }
  4861. }
  4862. else if (sop == 3 && sopcde == 2)
  4863. {
  4864. int shift = imm6 (DREG (src0) & 0xFFFF);
  4865. bu32 src = DREG (src1);
  4866. bu32 ret, cc = CCREG;
  4867. TRACE_INSN (cpu, "R%i = ROT R%i BY R%i.L;", dst0, src1, src0);
  4868. TRACE_DECODE (cpu, "R%i:%#x R%i:%#x shift:%i CC:%i",
  4869. dst0, DREG (dst0), src1, src, shift, cc);
  4870. ret = rot32 (src, shift, &cc);
  4871. STORE (DREG (dst0), ret);
  4872. if (shift)
  4873. SET_CCREG (cc);
  4874. }
  4875. else if (sop == 2 && sopcde == 1 && HLs == 0)
  4876. {
  4877. bs32 shft = (bs8)(DREG (src0) << 2) >> 2;
  4878. bu16 val0, val1;
  4879. bu32 astat;
  4880. TRACE_INSN (cpu, "R%i = LSHIFT R%i BY R%i.L (V);", dst0, src1, src0);
  4881. val0 = (bu16)DREG (src1) & 0xFFFF;
  4882. val1 = (bu16)((DREG (src1) & 0xFFFF0000) >> 16);
  4883. if (shft <= 0)
  4884. {
  4885. val0 = lshiftrt (cpu, val0, -shft, 16);
  4886. astat = ASTAT;
  4887. val1 = lshiftrt (cpu, val1, -shft, 16);
  4888. }
  4889. else
  4890. {
  4891. val0 = lshift (cpu, val0, shft, 16, 0, 0);
  4892. astat = ASTAT;
  4893. val1 = lshift (cpu, val1, shft, 16, 0, 0);
  4894. }
  4895. SET_ASTAT (ASTAT | astat);
  4896. STORE (DREG (dst0), (val1 << 16) | val0);
  4897. }
  4898. else if (sopcde == 4)
  4899. {
  4900. bu32 sv0 = DREG (src0);
  4901. bu32 sv1 = DREG (src1);
  4902. TRACE_INSN (cpu, "R%i = PACK (R%i.%c, R%i.%c);", dst0,
  4903. src1, sop & 2 ? 'H' : 'L',
  4904. src0, sop & 1 ? 'H' : 'L');
  4905. if (sop & 1)
  4906. sv0 >>= 16;
  4907. if (sop & 2)
  4908. sv1 >>= 16;
  4909. STORE (DREG (dst0), (sv1 << 16) | (sv0 & 0xFFFF));
  4910. }
  4911. else if (sop == 0 && sopcde == 5)
  4912. {
  4913. bu32 sv1 = DREG (src1);
  4914. TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i;", dst0, src1);
  4915. SET_DREG_L (dst0, signbits (sv1, 32));
  4916. }
  4917. else if (sop == 1 && sopcde == 5)
  4918. {
  4919. bu32 sv1 = DREG (src1);
  4920. TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i.L;", dst0, src1);
  4921. SET_DREG_L (dst0, signbits (sv1, 16));
  4922. }
  4923. else if (sop == 2 && sopcde == 5)
  4924. {
  4925. bu32 sv1 = DREG (src1);
  4926. TRACE_INSN (cpu, "R%i.L = SIGNBITS R%i.H;", dst0, src1);
  4927. SET_DREG_L (dst0, signbits (sv1 >> 16, 16));
  4928. }
  4929. else if ((sop == 0 || sop == 1) && sopcde == 6)
  4930. {
  4931. bu64 acc = AXREG (sop);
  4932. TRACE_INSN (cpu, "R%i.L = SIGNBITS A%i;", dst0, sop);
  4933. acc <<= 32;
  4934. acc |= AWREG (sop);
  4935. SET_DREG_L (dst0, signbits (acc, 40) & 0xFFFF);
  4936. }
  4937. else if (sop == 3 && sopcde == 6)
  4938. {
  4939. bu32 v = ones (DREG (src1));
  4940. TRACE_INSN (cpu, "R%i.L = ONES R%i;", dst0, src1);
  4941. SET_DREG_L (dst0, v);
  4942. }
  4943. else if (sop == 0 && sopcde == 7)
  4944. {
  4945. bu16 sv1 = (bu16)signbits (DREG (src1), 32);
  4946. bu16 sv0 = (bu16)DREG (src0);
  4947. bu16 dst_lo;
  4948. TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i, R%i.L);", dst0, src1, src0);
  4949. if ((sv1 & 0x1f) < (sv0 & 0x1f))
  4950. dst_lo = sv1;
  4951. else
  4952. dst_lo = sv0;
  4953. STORE (DREG (dst0), REG_H_L (DREG (dst0), dst_lo));
  4954. }
  4955. else if (sop == 1 && sopcde == 7)
  4956. {
  4957. /* Exponent adjust on two 16-bit inputs. Select
  4958. smallest norm among 3 inputs. */
  4959. bs16 src1_hi = (DREG (src1) & 0xFFFF0000) >> 16;
  4960. bs16 src1_lo = (DREG (src1) & 0xFFFF);
  4961. bu16 src0_lo = (DREG (src0) & 0xFFFF);
  4962. bu16 tmp_hi, tmp_lo, tmp;
  4963. TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i, R%i.L) (V);", dst0, src1, src0);
  4964. tmp_hi = signbits (src1_hi, 16);
  4965. tmp_lo = signbits (src1_lo, 16);
  4966. if ((tmp_hi & 0xf) < (tmp_lo & 0xf))
  4967. if ((tmp_hi & 0xf) < (src0_lo & 0xf))
  4968. tmp = tmp_hi;
  4969. else
  4970. tmp = src0_lo;
  4971. else
  4972. if ((tmp_lo & 0xf) < (src0_lo & 0xf))
  4973. tmp = tmp_lo;
  4974. else
  4975. tmp = src0_lo;
  4976. STORE (DREG (dst0), REG_H_L (DREG (dst0), tmp));
  4977. }
  4978. else if (sop == 2 && sopcde == 7)
  4979. {
  4980. /* Exponent adjust on single 16-bit register. */
  4981. bu16 tmp;
  4982. bu16 src0_lo = (bu16)(DREG (src0) & 0xFFFF);
  4983. TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i.L, R%i.L);", dst0, src1, src0);
  4984. tmp = signbits (DREG (src1) & 0xFFFF, 16);
  4985. if ((tmp & 0xf) < (src0_lo & 0xf))
  4986. SET_DREG_L (dst0, tmp);
  4987. else
  4988. SET_DREG_L (dst0, src0_lo);
  4989. }
  4990. else if (sop == 3 && sopcde == 7)
  4991. {
  4992. bu16 tmp;
  4993. bu16 src0_lo = (bu16)(DREG (src0) & 0xFFFF);
  4994. TRACE_INSN (cpu, "R%i.L = EXPADJ (R%i.H, R%i.L);", dst0, src1, src0);
  4995. tmp = signbits ((DREG (src1) & 0xFFFF0000) >> 16, 16);
  4996. if ((tmp & 0xf) < (src0_lo & 0xf))
  4997. SET_DREG_L (dst0, tmp);
  4998. else
  4999. SET_DREG_L (dst0, src0_lo);
  5000. }
  5001. else if (sop == 0 && sopcde == 8)
  5002. {
  5003. bu64 acc = get_unextended_acc (cpu, 0);
  5004. bu32 s0, s1;
  5005. TRACE_INSN (cpu, "BITMUX (R%i, R%i, A0) (ASR);", src0, src1);
  5006. if (src0 == src1)
  5007. illegal_instruction_combination (cpu);
  5008. s0 = DREG (src0);
  5009. s1 = DREG (src1);
  5010. acc = (acc >> 2) |
  5011. (((bu64)s0 & 1) << 38) |
  5012. (((bu64)s1 & 1) << 39);
  5013. STORE (DREG (src0), s0 >> 1);
  5014. STORE (DREG (src1), s1 >> 1);
  5015. SET_AREG (0, acc);
  5016. }
  5017. else if (sop == 1 && sopcde == 8)
  5018. {
  5019. bu64 acc = get_unextended_acc (cpu, 0);
  5020. bu32 s0, s1;
  5021. TRACE_INSN (cpu, "BITMUX (R%i, R%i, A0) (ASL);", src0, src1);
  5022. if (src0 == src1)
  5023. illegal_instruction_combination (cpu);
  5024. s0 = DREG (src0);
  5025. s1 = DREG (src1);
  5026. acc = (acc << 2) |
  5027. ((s0 >> 31) & 1) |
  5028. ((s1 >> 30) & 2);
  5029. STORE (DREG (src0), s0 << 1);
  5030. STORE (DREG (src1), s1 << 1);
  5031. SET_AREG (0, acc);
  5032. }
  5033. else if ((sop == 0 || sop == 1) && sopcde == 9)
  5034. {
  5035. bs40 acc0 = get_unextended_acc (cpu, 0);
  5036. bs16 sL, sH, out;
  5037. TRACE_INSN (cpu, "R%i.L = VIT_MAX (R%i) (AS%c);",
  5038. dst0, src1, sop & 1 ? 'R' : 'L');
  5039. sL = DREG (src1);
  5040. sH = DREG (src1) >> 16;
  5041. if (sop & 1)
  5042. acc0 = (acc0 & 0xfeffffffffull) >> 1;
  5043. else
  5044. acc0 <<= 1;
  5045. if (((sH - sL) & 0x8000) == 0)
  5046. {
  5047. out = sH;
  5048. acc0 |= (sop & 1) ? 0x80000000 : 1;
  5049. }
  5050. else
  5051. out = sL;
  5052. SET_AREG (0, acc0);
  5053. STORE (DREG (dst0), REG_H_L (DREG (dst0), out));
  5054. }
  5055. else if ((sop == 2 || sop == 3) && sopcde == 9)
  5056. {
  5057. bs40 acc0 = get_extended_acc (cpu, 0);
  5058. bs16 s0L, s0H, s1L, s1H, out0, out1;
  5059. TRACE_INSN (cpu, "R%i = VIT_MAX (R%i, R%i) (AS%c);",
  5060. dst0, src1, src0, sop & 1 ? 'R' : 'L');
  5061. s0L = DREG (src0);
  5062. s0H = DREG (src0) >> 16;
  5063. s1L = DREG (src1);
  5064. s1H = DREG (src1) >> 16;
  5065. if (sop & 1)
  5066. acc0 >>= 2;
  5067. else
  5068. acc0 <<= 2;
  5069. if (((s0H - s0L) & 0x8000) == 0)
  5070. {
  5071. out0 = s0H;
  5072. acc0 |= (sop & 1) ? 0x40000000 : 2;
  5073. }
  5074. else
  5075. out0 = s0L;
  5076. if (((s1H - s1L) & 0x8000) == 0)
  5077. {
  5078. out1 = s1H;
  5079. acc0 |= (sop & 1) ? 0x80000000 : 1;
  5080. }
  5081. else
  5082. out1 = s1L;
  5083. SET_AREG (0, acc0);
  5084. STORE (DREG (dst0), REG_H_L (out1 << 16, out0));
  5085. }
  5086. else if (sop == 0 && sopcde == 10)
  5087. {
  5088. bu32 v = DREG (src0);
  5089. bu32 x = DREG (src1);
  5090. bu32 mask = (1 << (v & 0x1f)) - 1;
  5091. TRACE_INSN (cpu, "R%i = EXTRACT (R%i, R%i.L) (Z);", dst0, src1, src0);
  5092. x >>= ((v >> 8) & 0x1f);
  5093. x &= mask;
  5094. STORE (DREG (dst0), x);
  5095. setflags_logical (cpu, x);
  5096. }
  5097. else if (sop == 1 && sopcde == 10)
  5098. {
  5099. bu32 v = DREG (src0);
  5100. bu32 x = DREG (src1);
  5101. bu32 sgn = (1 << (v & 0x1f)) >> 1;
  5102. bu32 mask = (1 << (v & 0x1f)) - 1;
  5103. TRACE_INSN (cpu, "R%i = EXTRACT (R%i, R%i.L) (X);", dst0, src1, src0);
  5104. x >>= ((v >> 8) & 0x1f);
  5105. x &= mask;
  5106. if (x & sgn)
  5107. x |= ~mask;
  5108. STORE (DREG (dst0), x);
  5109. setflags_logical (cpu, x);
  5110. }
  5111. else if ((sop == 2 || sop == 3) && sopcde == 10)
  5112. {
  5113. /* The first dregs is the "background" while the second dregs is the
  5114. "foreground". The fg reg is used to overlay the bg reg and is:
  5115. | nnnn nnnn | nnnn nnnn | xxxp pppp | xxxL LLLL |
  5116. n = the fg bit field
  5117. p = bit position in bg reg to start LSB of fg field
  5118. L = number of fg bits to extract
  5119. Using (X) sign-extends the fg bit field. */
  5120. bu32 fg = DREG (src0);
  5121. bu32 bg = DREG (src1);
  5122. bu32 len = fg & 0x1f;
  5123. bu32 mask = (1 << MIN (16, len)) - 1;
  5124. bu32 fgnd = (fg >> 16) & mask;
  5125. int shft = ((fg >> 8) & 0x1f);
  5126. TRACE_INSN (cpu, "R%i = DEPOSIT (R%i, R%i)%s;", dst0, src1, src0,
  5127. sop == 3 ? " (X)" : "");
  5128. if (sop == 3)
  5129. {
  5130. /* Sign extend the fg bit field. */
  5131. mask = -1;
  5132. fgnd = ((bs32)(bs16)(fgnd << (16 - len))) >> (16 - len);
  5133. }
  5134. fgnd <<= shft;
  5135. mask <<= shft;
  5136. bg &= ~mask;
  5137. bg |= fgnd;
  5138. STORE (DREG (dst0), bg);
  5139. setflags_logical (cpu, bg);
  5140. }
  5141. else if (sop == 0 && sopcde == 11)
  5142. {
  5143. bu64 acc0 = get_unextended_acc (cpu, 0);
  5144. TRACE_INSN (cpu, "R%i.L = CC = BXORSHIFT (A0, R%i);", dst0, src0);
  5145. acc0 <<= 1;
  5146. SET_CCREG (xor_reduce (acc0, DREG (src0)));
  5147. SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
  5148. SET_AREG (0, acc0);
  5149. }
  5150. else if (sop == 1 && sopcde == 11)
  5151. {
  5152. bu64 acc0 = get_unextended_acc (cpu, 0);
  5153. TRACE_INSN (cpu, "R%i.L = CC = BXOR (A0, R%i);", dst0, src0);
  5154. SET_CCREG (xor_reduce (acc0, DREG (src0)));
  5155. SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
  5156. }
  5157. else if (sop == 0 && sopcde == 12)
  5158. {
  5159. bu64 acc0 = get_unextended_acc (cpu, 0);
  5160. bu64 acc1 = get_unextended_acc (cpu, 1);
  5161. TRACE_INSN (cpu, "A0 = BXORSHIFT (A0, A1, CC);");
  5162. acc0 = (acc0 << 1) | (CCREG ^ xor_reduce (acc0, acc1));
  5163. SET_AREG (0, acc0);
  5164. }
  5165. else if (sop == 1 && sopcde == 12)
  5166. {
  5167. bu64 acc0 = get_unextended_acc (cpu, 0);
  5168. bu64 acc1 = get_unextended_acc (cpu, 1);
  5169. TRACE_INSN (cpu, "R%i.L = CC = BXOR (A0, A1, CC);", dst0);
  5170. SET_CCREG (CCREG ^ xor_reduce (acc0, acc1));
  5171. acc0 = (acc0 << 1) | CCREG;
  5172. SET_DREG (dst0, REG_H_L (DREG (dst0), CCREG));
  5173. }
  5174. else if ((sop == 0 || sop == 1 || sop == 2) && sopcde == 13)
  5175. {
  5176. int shift = (sop + 1) * 8;
  5177. TRACE_INSN (cpu, "R%i = ALIGN%i (R%i, R%i);", dst0, shift, src1, src0);
  5178. STORE (DREG (dst0), (DREG (src1) << (32 - shift)) | (DREG (src0) >> shift));
  5179. }
  5180. else
  5181. illegal_instruction (cpu);
  5182. }
  5183. static bu64
  5184. sgn_extend (bu40 org, bu40 val, int size)
  5185. {
  5186. bu64 ret = val;
  5187. if (org & (1ULL << (size - 1)))
  5188. {
  5189. /* We need to shift in to the MSB which is set. */
  5190. int n;
  5191. for (n = 40; n >= 0; n--)
  5192. if (ret & (1ULL << n))
  5193. break;
  5194. ret |= (-1ULL << n);
  5195. }
  5196. else
  5197. ret &= ~(-1ULL << 39);
  5198. return ret;
  5199. }
  5200. static void
  5201. decode_dsp32shiftimm_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1)
  5202. {
  5203. /* dsp32shiftimm
  5204. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  5205. | 1 | 1 | 0 | 0 |.M.| 1 | 1 | 0 | 1 | - | - |.sopcde............|
  5206. |.sop...|.HLs...|.dst0......|.immag.................|.src1......|
  5207. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  5208. int src1 = ((iw1 >> DSP32ShiftImm_src1_bits) & DSP32ShiftImm_src1_mask);
  5209. int sop = ((iw1 >> DSP32ShiftImm_sop_bits) & DSP32ShiftImm_sop_mask);
  5210. int bit8 = ((iw1 >> 8) & 0x1);
  5211. int immag = ((iw1 >> DSP32ShiftImm_immag_bits) & DSP32ShiftImm_immag_mask);
  5212. int newimmag = (-(iw1 >> DSP32ShiftImm_immag_bits) & DSP32ShiftImm_immag_mask);
  5213. int dst0 = ((iw1 >> DSP32ShiftImm_dst0_bits) & DSP32ShiftImm_dst0_mask);
  5214. int M = ((iw0 >> (DSP32ShiftImm_M_bits - 16)) & DSP32ShiftImm_M_mask);
  5215. int sopcde = ((iw0 >> (DSP32ShiftImm_sopcde_bits - 16)) & DSP32ShiftImm_sopcde_mask);
  5216. int HLs = ((iw1 >> DSP32ShiftImm_HLs_bits) & DSP32ShiftImm_HLs_mask);
  5217. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32shiftimm);
  5218. TRACE_EXTRACT (cpu, "%s: M:%i sopcde:%i sop:%i HLs:%i dst0:%i immag:%#x src1:%i",
  5219. __func__, M, sopcde, sop, HLs, dst0, immag, src1);
  5220. if (sopcde == 0)
  5221. {
  5222. bu16 in = DREG (src1) >> ((HLs & 1) ? 16 : 0);
  5223. bu16 result;
  5224. bu32 v;
  5225. if (sop == 0)
  5226. {
  5227. TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i;",
  5228. dst0, (HLs & 2) ? 'H' : 'L',
  5229. src1, (HLs & 1) ? 'H' : 'L', newimmag);
  5230. if (newimmag > 16)
  5231. {
  5232. result = lshift (cpu, in, 16 - (newimmag & 0xF), 16, 0, 1);
  5233. if (((result >> 15) & 0x1) != ((in >> 15) & 0x1))
  5234. {
  5235. SET_ASTATREG (v, 1);
  5236. SET_ASTATREG (vs, 1);
  5237. }
  5238. }
  5239. else
  5240. result = ashiftrt (cpu, in, newimmag, 16);
  5241. }
  5242. else if (sop == 1 && bit8 == 0)
  5243. {
  5244. TRACE_INSN (cpu, "R%i.%c = R%i.%c << %i (S);",
  5245. dst0, (HLs & 2) ? 'H' : 'L',
  5246. src1, (HLs & 1) ? 'H' : 'L', immag);
  5247. result = lshift (cpu, in, immag, 16, 1, 1);
  5248. }
  5249. else if (sop == 1 && bit8)
  5250. {
  5251. TRACE_INSN (cpu, "R%i.%c = R%i.%c >>> %i (S);",
  5252. dst0, (HLs & 2) ? 'H' : 'L',
  5253. src1, (HLs & 1) ? 'H' : 'L', newimmag);
  5254. if (newimmag > 16)
  5255. {
  5256. int shift = 32 - newimmag;
  5257. bu16 inshift = in << shift;
  5258. if (((inshift & ~0xFFFF)
  5259. && ((inshift & ~0xFFFF) >> 16) != ~(~0 << shift))
  5260. || (inshift & 0x8000) != (in & 0x8000))
  5261. {
  5262. if (in & 0x8000)
  5263. result = 0x8000;
  5264. else
  5265. result = 0x7fff;
  5266. SET_ASTATREG (v, 1);
  5267. SET_ASTATREG (vs, 1);
  5268. }
  5269. else
  5270. {
  5271. result = inshift;
  5272. SET_ASTATREG (v, 0);
  5273. }
  5274. SET_ASTATREG (az, !result);
  5275. SET_ASTATREG (an, !!(result & 0x8000));
  5276. }
  5277. else
  5278. {
  5279. result = ashiftrt (cpu, in, newimmag, 16);
  5280. result = sgn_extend (in, result, 16);
  5281. }
  5282. }
  5283. else if (sop == 2 && bit8)
  5284. {
  5285. TRACE_INSN (cpu, "R%i.%c = R%i.%c >> %i;",
  5286. dst0, (HLs & 2) ? 'H' : 'L',
  5287. src1, (HLs & 1) ? 'H' : 'L', newimmag);
  5288. result = lshiftrt (cpu, in, newimmag, 16);
  5289. }
  5290. else if (sop == 2 && bit8 == 0)
  5291. {
  5292. TRACE_INSN (cpu, "R%i.%c = R%i.%c << %i;",
  5293. dst0, (HLs & 2) ? 'H' : 'L',
  5294. src1, (HLs & 1) ? 'H' : 'L', immag);
  5295. result = lshift (cpu, in, immag, 16, 0, 1);
  5296. }
  5297. else
  5298. illegal_instruction (cpu);
  5299. v = DREG (dst0);
  5300. if (HLs & 2)
  5301. STORE (DREG (dst0), (v & 0xFFFF) | (result << 16));
  5302. else
  5303. STORE (DREG (dst0), (v & 0xFFFF0000) | result);
  5304. }
  5305. else if (sop == 2 && sopcde == 3 && (HLs == 1 || HLs == 0))
  5306. {
  5307. int shift = imm6 (immag);
  5308. bu32 cc = CCREG;
  5309. bu40 acc = get_unextended_acc (cpu, HLs);
  5310. TRACE_INSN (cpu, "A%i = ROT A%i BY %i;", HLs, HLs, shift);
  5311. TRACE_DECODE (cpu, "A%i:%#"PRIx64" shift:%i CC:%i", HLs, acc, shift, cc);
  5312. acc = rot40 (acc, shift, &cc);
  5313. SET_AREG (HLs, acc);
  5314. if (shift)
  5315. SET_CCREG (cc);
  5316. }
  5317. else if (sop == 0 && sopcde == 3 && bit8 == 1 && HLs < 2)
  5318. {
  5319. /* Arithmetic shift, so shift in sign bit copies. */
  5320. bu64 acc, val;
  5321. int shift = uimm5 (newimmag);
  5322. TRACE_INSN (cpu, "A%i = A%i >>> %i;", HLs, HLs, shift);
  5323. acc = get_extended_acc (cpu, HLs);
  5324. val = acc >> shift;
  5325. /* Sign extend again. */
  5326. val = sgn_extend (acc, val, 40);
  5327. STORE (AXREG (HLs), (val >> 32) & 0xFF);
  5328. STORE (AWREG (HLs), val & 0xFFFFFFFF);
  5329. STORE (ASTATREG (an), !!(val & (1ULL << 39)));
  5330. STORE (ASTATREG (az), !val);
  5331. STORE (ASTATREG (av[HLs]), 0);
  5332. }
  5333. else if (((sop == 0 && sopcde == 3 && bit8 == 0)
  5334. || (sop == 1 && sopcde == 3)) && HLs < 2)
  5335. {
  5336. bu64 acc;
  5337. int shiftup = uimm5 (immag);
  5338. int shiftdn = uimm5 (newimmag);
  5339. TRACE_INSN (cpu, "A%i = A%i %s %i;", HLs, HLs,
  5340. sop == 0 ? "<<" : ">>",
  5341. sop == 0 ? shiftup : shiftdn);
  5342. acc = AXREG (HLs);
  5343. /* Logical shift, so shift in zeroes. */
  5344. acc &= 0xFF;
  5345. acc <<= 32;
  5346. acc |= AWREG (HLs);
  5347. if (sop == 0)
  5348. acc <<= shiftup;
  5349. else
  5350. {
  5351. if (shiftdn <= 32)
  5352. acc >>= shiftdn;
  5353. else
  5354. acc <<= 32 - (shiftdn & 0x1f);
  5355. }
  5356. SET_AREG (HLs, acc);
  5357. SET_ASTATREG (av[HLs], 0);
  5358. SET_ASTATREG (an, !!(acc & 0x8000000000ull));
  5359. SET_ASTATREG (az, (acc & 0xFFFFFFFFFF) == 0);
  5360. }
  5361. else if (HLs != 0)
  5362. /* All the insns after this point don't use HLs. */
  5363. illegal_instruction (cpu);
  5364. else if (sop == 1 && sopcde == 1 && bit8 == 0)
  5365. {
  5366. int count = imm5 (immag);
  5367. bu16 val0 = DREG (src1) >> 16;
  5368. bu16 val1 = DREG (src1) & 0xFFFF;
  5369. bu32 astat;
  5370. TRACE_INSN (cpu, "R%i = R%i << %i (V,S);", dst0, src1, count);
  5371. if (count >= 0)
  5372. {
  5373. val0 = lshift (cpu, val0, count, 16, 1, 1);
  5374. astat = ASTAT;
  5375. val1 = lshift (cpu, val1, count, 16, 1, 1);
  5376. }
  5377. else
  5378. {
  5379. val0 = ashiftrt (cpu, val0, -count, 16);
  5380. astat = ASTAT;
  5381. val1 = ashiftrt (cpu, val1, -count, 16);
  5382. }
  5383. SET_ASTAT (ASTAT | astat);
  5384. STORE (DREG (dst0), (val0 << 16) | val1);
  5385. }
  5386. else if (sop == 2 && sopcde == 1 && bit8 == 1)
  5387. {
  5388. int count = imm5 (newimmag);
  5389. bu16 val0 = DREG (src1) & 0xFFFF;
  5390. bu16 val1 = DREG (src1) >> 16;
  5391. bu32 astat;
  5392. TRACE_INSN (cpu, "R%i = R%i >> %i (V);", dst0, src1, count);
  5393. val0 = lshiftrt (cpu, val0, count, 16);
  5394. astat = ASTAT;
  5395. val1 = lshiftrt (cpu, val1, count, 16);
  5396. SET_ASTAT (ASTAT | astat);
  5397. STORE (DREG (dst0), val0 | (val1 << 16));
  5398. }
  5399. else if (sop == 2 && sopcde == 1 && bit8 == 0)
  5400. {
  5401. int count = imm5 (immag);
  5402. bu16 val0 = DREG (src1) & 0xFFFF;
  5403. bu16 val1 = DREG (src1) >> 16;
  5404. bu32 astat;
  5405. TRACE_INSN (cpu, "R%i = R%i << %i (V);", dst0, src1, count);
  5406. val0 = lshift (cpu, val0, count, 16, 0, 1);
  5407. astat = ASTAT;
  5408. val1 = lshift (cpu, val1, count, 16, 0, 1);
  5409. SET_ASTAT (ASTAT | astat);
  5410. STORE (DREG (dst0), val0 | (val1 << 16));
  5411. }
  5412. else if (sopcde == 1 && (sop == 0 || (sop == 1 && bit8 == 1)))
  5413. {
  5414. int count = uimm5 (newimmag);
  5415. bu16 val0 = DREG (src1) & 0xFFFF;
  5416. bu16 val1 = DREG (src1) >> 16;
  5417. bu32 astat;
  5418. TRACE_INSN (cpu, "R%i = R%i >>> %i %s;", dst0, src1, count,
  5419. sop == 0 ? "(V)" : "(V,S)");
  5420. if (count > 16)
  5421. {
  5422. int sgn0 = (val0 >> 15) & 0x1;
  5423. int sgn1 = (val1 >> 15) & 0x1;
  5424. val0 = lshift (cpu, val0, 16 - (count & 0xF), 16, 0, 1);
  5425. astat = ASTAT;
  5426. val1 = lshift (cpu, val1, 16 - (count & 0xF), 16, 0, 1);
  5427. if ((sgn0 != ((val0 >> 15) & 0x1)) || (sgn1 != ((val1 >> 15) & 0x1)))
  5428. {
  5429. SET_ASTATREG (v, 1);
  5430. SET_ASTATREG (vs, 1);
  5431. }
  5432. }
  5433. else
  5434. {
  5435. val0 = ashiftrt (cpu, val0, count, 16);
  5436. astat = ASTAT;
  5437. val1 = ashiftrt (cpu, val1, count, 16);
  5438. }
  5439. SET_ASTAT (ASTAT | astat);
  5440. STORE (DREG (dst0), REG_H_L (val1 << 16, val0));
  5441. }
  5442. else if (sop == 1 && sopcde == 2)
  5443. {
  5444. int count = imm6 (immag);
  5445. TRACE_INSN (cpu, "R%i = R%i << %i (S);", dst0, src1, count);
  5446. if (count < 0)
  5447. STORE (DREG (dst0), ashiftrt (cpu, DREG (src1), -count, 32));
  5448. else
  5449. STORE (DREG (dst0), lshift (cpu, DREG (src1), count, 32, 1, 1));
  5450. }
  5451. else if (sop == 2 && sopcde == 2)
  5452. {
  5453. int count = imm6 (newimmag);
  5454. TRACE_INSN (cpu, "R%i = R%i >> %i;", dst0, src1, count);
  5455. if (count < 0)
  5456. STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0, 1));
  5457. else
  5458. STORE (DREG (dst0), lshiftrt (cpu, DREG (src1), count, 32));
  5459. }
  5460. else if (sop == 3 && sopcde == 2)
  5461. {
  5462. int shift = imm6 (immag);
  5463. bu32 src = DREG (src1);
  5464. bu32 ret, cc = CCREG;
  5465. TRACE_INSN (cpu, "R%i = ROT R%i BY %i;", dst0, src1, shift);
  5466. TRACE_DECODE (cpu, "R%i:%#x R%i:%#x shift:%i CC:%i",
  5467. dst0, DREG (dst0), src1, src, shift, cc);
  5468. ret = rot32 (src, shift, &cc);
  5469. STORE (DREG (dst0), ret);
  5470. if (shift)
  5471. SET_CCREG (cc);
  5472. }
  5473. else if (sop == 0 && sopcde == 2)
  5474. {
  5475. int count = imm6 (newimmag);
  5476. TRACE_INSN (cpu, "R%i = R%i >>> %i;", dst0, src1, count);
  5477. if (count < 0)
  5478. STORE (DREG (dst0), lshift (cpu, DREG (src1), -count, 32, 0, 1));
  5479. else
  5480. STORE (DREG (dst0), ashiftrt (cpu, DREG (src1), count, 32));
  5481. }
  5482. else
  5483. illegal_instruction (cpu);
  5484. }
  5485. static void
  5486. outc (SIM_CPU *cpu, char ch)
  5487. {
  5488. SIM_DESC sd = CPU_STATE (cpu);
  5489. sim_io_printf (sd, "%c", ch);
  5490. if (ch == '\n')
  5491. sim_io_flush_stdout (sd);
  5492. }
  5493. static void
  5494. decode_psedoDEBUG_0 (SIM_CPU *cpu, bu16 iw0)
  5495. {
  5496. /* psedoDEBUG
  5497. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  5498. | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 0 |.fn....|.grp.......|.reg.......|
  5499. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  5500. SIM_DESC sd = CPU_STATE (cpu);
  5501. int fn = ((iw0 >> PseudoDbg_fn_bits) & PseudoDbg_fn_mask);
  5502. int grp = ((iw0 >> PseudoDbg_grp_bits) & PseudoDbg_grp_mask);
  5503. int reg = ((iw0 >> PseudoDbg_reg_bits) & PseudoDbg_reg_mask);
  5504. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedoDEBUG);
  5505. TRACE_EXTRACT (cpu, "%s: fn:%i grp:%i reg:%i", __func__, fn, grp, reg);
  5506. if ((reg == 0 || reg == 1) && fn == 3)
  5507. {
  5508. TRACE_INSN (cpu, "DBG A%i;", reg);
  5509. sim_io_printf (sd, "DBG : A%i = %#"PRIx64"\n", reg,
  5510. get_unextended_acc (cpu, reg));
  5511. }
  5512. else if (reg == 3 && fn == 3)
  5513. {
  5514. TRACE_INSN (cpu, "ABORT;");
  5515. cec_exception (cpu, VEC_SIM_ABORT);
  5516. SET_DREG (0, 1);
  5517. }
  5518. else if (reg == 4 && fn == 3)
  5519. {
  5520. TRACE_INSN (cpu, "HLT;");
  5521. cec_exception (cpu, VEC_SIM_HLT);
  5522. SET_DREG (0, 0);
  5523. }
  5524. else if (reg == 5 && fn == 3)
  5525. unhandled_instruction (cpu, "DBGHALT");
  5526. else if (reg == 6 && fn == 3)
  5527. unhandled_instruction (cpu, "DBGCMPLX (dregs)");
  5528. else if (reg == 7 && fn == 3)
  5529. unhandled_instruction (cpu, "DBG");
  5530. else if (grp == 0 && fn == 2)
  5531. {
  5532. TRACE_INSN (cpu, "OUTC R%i;", reg);
  5533. outc (cpu, DREG (reg));
  5534. }
  5535. else if (fn == 0)
  5536. {
  5537. const char *reg_name = get_allreg_name (grp, reg);
  5538. TRACE_INSN (cpu, "DBG %s;", reg_name);
  5539. sim_io_printf (sd, "DBG : %s = 0x%08x\n", reg_name,
  5540. reg_read (cpu, grp, reg));
  5541. }
  5542. else if (fn == 1)
  5543. unhandled_instruction (cpu, "PRNT allregs");
  5544. else
  5545. illegal_instruction (cpu);
  5546. }
  5547. static void
  5548. decode_psedoOChar_0 (SIM_CPU *cpu, bu16 iw0)
  5549. {
  5550. /* psedoOChar
  5551. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  5552. | 1 | 1 | 1 | 1 | 1 | 0 | 0 | 1 |.ch............................|
  5553. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  5554. int ch = ((iw0 >> PseudoChr_ch_bits) & PseudoChr_ch_mask);
  5555. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedoOChar);
  5556. TRACE_EXTRACT (cpu, "%s: ch:%#x", __func__, ch);
  5557. TRACE_INSN (cpu, "OUTC %#x;", ch);
  5558. outc (cpu, ch);
  5559. }
  5560. static void
  5561. decode_psedodbg_assert_0 (SIM_CPU *cpu, bu16 iw0, bu16 iw1, bu32 pc)
  5562. {
  5563. /* psedodbg_assert
  5564. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+
  5565. | 1 | 1 | 1 | 1 | 0 | - | - | - | dbgop |.grp.......|.regtest...|
  5566. |.expected......................................................|
  5567. +---+---+---+---|---+---+---+---|---+---+---+---|---+---+---+---+ */
  5568. SIM_DESC sd = CPU_STATE (cpu);
  5569. int expected = ((iw1 >> PseudoDbg_Assert_expected_bits) & PseudoDbg_Assert_expected_mask);
  5570. int dbgop = ((iw0 >> (PseudoDbg_Assert_dbgop_bits - 16)) & PseudoDbg_Assert_dbgop_mask);
  5571. int grp = ((iw0 >> (PseudoDbg_Assert_grp_bits - 16)) & PseudoDbg_Assert_grp_mask);
  5572. int regtest = ((iw0 >> (PseudoDbg_Assert_regtest_bits - 16)) & PseudoDbg_Assert_regtest_mask);
  5573. int offset;
  5574. bu16 actual;
  5575. bu32 val = reg_read (cpu, grp, regtest);
  5576. const char *reg_name = get_allreg_name (grp, regtest);
  5577. const char *dbg_name, *dbg_appd;
  5578. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_psedodbg_assert);
  5579. TRACE_EXTRACT (cpu, "%s: dbgop:%i grp:%i regtest:%i expected:%#x",
  5580. __func__, dbgop, grp, regtest, expected);
  5581. if (dbgop == 0 || dbgop == 2)
  5582. {
  5583. dbg_name = dbgop == 0 ? "DBGA" : "DBGAL";
  5584. dbg_appd = dbgop == 0 ? ".L" : "";
  5585. offset = 0;
  5586. }
  5587. else if (dbgop == 1 || dbgop == 3)
  5588. {
  5589. dbg_name = dbgop == 1 ? "DBGA" : "DBGAH";
  5590. dbg_appd = dbgop == 1 ? ".H" : "";
  5591. offset = 16;
  5592. }
  5593. else
  5594. illegal_instruction (cpu);
  5595. actual = val >> offset;
  5596. TRACE_INSN (cpu, "%s (%s%s, 0x%x);", dbg_name, reg_name, dbg_appd, expected);
  5597. if (actual != expected)
  5598. {
  5599. sim_io_printf (sd, "FAIL at %#x: %s (%s%s, 0x%04x); actual value %#x\n",
  5600. pc, dbg_name, reg_name, dbg_appd, expected, actual);
  5601. /* Decode the actual ASTAT bits that are different. */
  5602. if (grp == 4 && regtest == 6)
  5603. {
  5604. int i;
  5605. sim_io_printf (sd, "Expected ASTAT:\n");
  5606. for (i = 0; i < 16; ++i)
  5607. sim_io_printf (sd, " %8s%c%i%s",
  5608. astat_names[i + offset],
  5609. (((expected >> i) & 1) != ((actual >> i) & 1))
  5610. ? '!' : ' ',
  5611. (expected >> i) & 1,
  5612. i == 7 ? "\n" : "");
  5613. sim_io_printf (sd, "\n");
  5614. sim_io_printf (sd, "Actual ASTAT:\n");
  5615. for (i = 0; i < 16; ++i)
  5616. sim_io_printf (sd, " %8s%c%i%s",
  5617. astat_names[i + offset],
  5618. (((expected >> i) & 1) != ((actual >> i) & 1))
  5619. ? '!' : ' ',
  5620. (actual >> i) & 1,
  5621. i == 7 ? "\n" : "");
  5622. sim_io_printf (sd, "\n");
  5623. }
  5624. cec_exception (cpu, VEC_SIM_DBGA);
  5625. SET_DREG (0, 1);
  5626. }
  5627. }
  5628. static bu32
  5629. _interp_insn_bfin (SIM_CPU *cpu, bu32 pc)
  5630. {
  5631. bu32 insn_len;
  5632. bu16 iw0, iw1;
  5633. BFIN_CPU_STATE.multi_pc = pc;
  5634. iw0 = IFETCH (pc);
  5635. if ((iw0 & 0xc000) != 0xc000)
  5636. {
  5637. /* 16-bit opcode. */
  5638. insn_len = 2;
  5639. if (INSN_LEN == 0)
  5640. INSN_LEN = insn_len;
  5641. TRACE_EXTRACT (cpu, "%s: iw0:%#x", __func__, iw0);
  5642. if ((iw0 & 0xFF00) == 0x0000)
  5643. decode_ProgCtrl_0 (cpu, iw0, pc);
  5644. else if ((iw0 & 0xFFC0) == 0x0240)
  5645. decode_CaCTRL_0 (cpu, iw0);
  5646. else if ((iw0 & 0xFF80) == 0x0100)
  5647. decode_PushPopReg_0 (cpu, iw0);
  5648. else if ((iw0 & 0xFE00) == 0x0400)
  5649. decode_PushPopMultiple_0 (cpu, iw0);
  5650. else if ((iw0 & 0xFE00) == 0x0600)
  5651. decode_ccMV_0 (cpu, iw0);
  5652. else if ((iw0 & 0xF800) == 0x0800)
  5653. decode_CCflag_0 (cpu, iw0);
  5654. else if ((iw0 & 0xFFE0) == 0x0200)
  5655. decode_CC2dreg_0 (cpu, iw0);
  5656. else if ((iw0 & 0xFF00) == 0x0300)
  5657. decode_CC2stat_0 (cpu, iw0);
  5658. else if ((iw0 & 0xF000) == 0x1000)
  5659. decode_BRCC_0 (cpu, iw0, pc);
  5660. else if ((iw0 & 0xF000) == 0x2000)
  5661. decode_UJUMP_0 (cpu, iw0, pc);
  5662. else if ((iw0 & 0xF000) == 0x3000)
  5663. decode_REGMV_0 (cpu, iw0);
  5664. else if ((iw0 & 0xFC00) == 0x4000)
  5665. decode_ALU2op_0 (cpu, iw0);
  5666. else if ((iw0 & 0xFE00) == 0x4400)
  5667. decode_PTR2op_0 (cpu, iw0);
  5668. else if ((iw0 & 0xF800) == 0x4800)
  5669. decode_LOGI2op_0 (cpu, iw0);
  5670. else if ((iw0 & 0xF000) == 0x5000)
  5671. decode_COMP3op_0 (cpu, iw0);
  5672. else if ((iw0 & 0xF800) == 0x6000)
  5673. decode_COMPI2opD_0 (cpu, iw0);
  5674. else if ((iw0 & 0xF800) == 0x6800)
  5675. decode_COMPI2opP_0 (cpu, iw0);
  5676. else if ((iw0 & 0xF000) == 0x8000)
  5677. decode_LDSTpmod_0 (cpu, iw0);
  5678. else if ((iw0 & 0xFF60) == 0x9E60)
  5679. decode_dagMODim_0 (cpu, iw0);
  5680. else if ((iw0 & 0xFFF0) == 0x9F60)
  5681. decode_dagMODik_0 (cpu, iw0);
  5682. else if ((iw0 & 0xFC00) == 0x9C00)
  5683. decode_dspLDST_0 (cpu, iw0);
  5684. else if ((iw0 & 0xF000) == 0x9000)
  5685. decode_LDST_0 (cpu, iw0);
  5686. else if ((iw0 & 0xFC00) == 0xB800)
  5687. decode_LDSTiiFP_0 (cpu, iw0);
  5688. else if ((iw0 & 0xE000) == 0xA000)
  5689. decode_LDSTii_0 (cpu, iw0);
  5690. else
  5691. {
  5692. TRACE_EXTRACT (cpu, "%s: no matching 16-bit pattern", __func__);
  5693. illegal_instruction_or_combination (cpu);
  5694. }
  5695. return insn_len;
  5696. }
  5697. /* Grab the next 16 bits to determine if it's a 32-bit or 64-bit opcode. */
  5698. iw1 = IFETCH (pc + 2);
  5699. if ((iw0 & BIT_MULTI_INS) && (iw0 & 0xe800) != 0xe800 /* not linkage */)
  5700. {
  5701. SIM_DESC sd = CPU_STATE (cpu);
  5702. trace_prefix (sd, cpu, NULL_CIA, pc, TRACE_LINENUM_P (cpu),
  5703. NULL, 0, "|| %#"PRIx64, sim_events_time (sd));
  5704. insn_len = 8;
  5705. PARALLEL_GROUP = BFIN_PARALLEL_GROUP0;
  5706. }
  5707. else
  5708. insn_len = 4;
  5709. TRACE_EXTRACT (cpu, "%s: iw0:%#x iw1:%#x insn_len:%i", __func__,
  5710. iw0, iw1, insn_len);
  5711. /* Only cache on first run through (in case of parallel insns). */
  5712. if (INSN_LEN == 0)
  5713. INSN_LEN = insn_len;
  5714. else
  5715. /* Once you're past the first slot, only 16bit insns are valid. */
  5716. illegal_instruction_combination (cpu);
  5717. if ((iw0 & 0xf7ff) == 0xc003 && (iw1 & 0xfe00) == 0x1800)
  5718. {
  5719. PROFILE_COUNT_INSN (cpu, pc, BFIN_INSN_dsp32mac);
  5720. TRACE_INSN (cpu, "MNOP;");
  5721. }
  5722. else if (((iw0 & 0xFF80) == 0xE080) && ((iw1 & 0x0C00) == 0x0000))
  5723. decode_LoopSetup_0 (cpu, iw0, iw1, pc);
  5724. else if (((iw0 & 0xFF00) == 0xE100) && ((iw1 & 0x0000) == 0x0000))
  5725. decode_LDIMMhalf_0 (cpu, iw0, iw1);
  5726. else if (((iw0 & 0xFE00) == 0xE200) && ((iw1 & 0x0000) == 0x0000))
  5727. decode_CALLa_0 (cpu, iw0, iw1, pc);
  5728. else if (((iw0 & 0xFC00) == 0xE400) && ((iw1 & 0x0000) == 0x0000))
  5729. decode_LDSTidxI_0 (cpu, iw0, iw1);
  5730. else if (((iw0 & 0xFFFE) == 0xE800) && ((iw1 & 0x0000) == 0x0000))
  5731. decode_linkage_0 (cpu, iw0, iw1);
  5732. else if (((iw0 & 0xF600) == 0xC000) && ((iw1 & 0x0000) == 0x0000))
  5733. decode_dsp32mac_0 (cpu, iw0, iw1);
  5734. else if (((iw0 & 0xF600) == 0xC200) && ((iw1 & 0x0000) == 0x0000))
  5735. decode_dsp32mult_0 (cpu, iw0, iw1);
  5736. else if (((iw0 & 0xF7C0) == 0xC400) && ((iw1 & 0x0000) == 0x0000))
  5737. decode_dsp32alu_0 (cpu, iw0, iw1);
  5738. else if (((iw0 & 0xF7E0) == 0xC600) && ((iw1 & 0x01C0) == 0x0000))
  5739. decode_dsp32shift_0 (cpu, iw0, iw1);
  5740. else if (((iw0 & 0xF7E0) == 0xC680) && ((iw1 & 0x0000) == 0x0000))
  5741. decode_dsp32shiftimm_0 (cpu, iw0, iw1);
  5742. else if ((iw0 & 0xFF00) == 0xF800)
  5743. decode_psedoDEBUG_0 (cpu, iw0), insn_len = 2;
  5744. else if ((iw0 & 0xFF00) == 0xF900)
  5745. decode_psedoOChar_0 (cpu, iw0), insn_len = 2;
  5746. else if (((iw0 & 0xFF00) == 0xF000) && ((iw1 & 0x0000) == 0x0000))
  5747. decode_psedodbg_assert_0 (cpu, iw0, iw1, pc);
  5748. else
  5749. {
  5750. TRACE_EXTRACT (cpu, "%s: no matching 32-bit pattern", __func__);
  5751. illegal_instruction (cpu);
  5752. }
  5753. return insn_len;
  5754. }
  5755. bu32
  5756. interp_insn_bfin (SIM_CPU *cpu, bu32 pc)
  5757. {
  5758. int i;
  5759. bu32 insn_len;
  5760. BFIN_CPU_STATE.n_stores = 0;
  5761. PARALLEL_GROUP = BFIN_PARALLEL_NONE;
  5762. DIS_ALGN_EXPT &= ~1;
  5763. CYCLE_DELAY = 1;
  5764. INSN_LEN = 0;
  5765. insn_len = _interp_insn_bfin (cpu, pc);
  5766. /* Proper display of multiple issue instructions. */
  5767. if (insn_len == 8)
  5768. {
  5769. PARALLEL_GROUP = BFIN_PARALLEL_GROUP1;
  5770. _interp_insn_bfin (cpu, pc + 4);
  5771. PARALLEL_GROUP = BFIN_PARALLEL_GROUP2;
  5772. _interp_insn_bfin (cpu, pc + 6);
  5773. }
  5774. for (i = 0; i < BFIN_CPU_STATE.n_stores; i++)
  5775. {
  5776. bu32 *addr = BFIN_CPU_STATE.stores[i].addr;
  5777. *addr = BFIN_CPU_STATE.stores[i].val;
  5778. TRACE_REGISTER (cpu, "dequeuing write %s = %#x",
  5779. get_store_name (cpu, addr), *addr);
  5780. }
  5781. cycles_inc (cpu, CYCLE_DELAY);
  5782. /* Set back to zero in case a pending CEC event occurs
  5783. after this this insn. */
  5784. INSN_LEN = 0;
  5785. return insn_len;
  5786. }