1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721 |
- /* tc-nds32.c -- Assemble for the nds32
- Copyright (C) 2012-2015 Free Software Foundation, Inc.
- Contributed by Andes Technology Corporation.
- This file is part of GAS, the GNU Assembler.
- GAS is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3, or (at your option)
- any later version.
- GAS is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with GAS; see the file COPYING. If not, write to the Free
- Software Foundation, 51 Franklin Street - Fifth Floor, Boston, MA
- 02110-1301, USA. */
- #include "as.h"
- #include "safe-ctype.h"
- #include "subsegs.h"
- #include "symcat.h"
- #include "dwarf2dbg.h"
- #include "dw2gencfi.h"
- #include "opcodes/nds32-asm.h"
- #include "elf/nds32.h"
- #include "bfd/elf32-nds32.h"
- #include "hash.h"
- #include "sb.h"
- #include "macro.h"
- #include "struc-symbol.h"
- #include "opcode/nds32.h"
- #include <stdio.h>
- /* GAS definitions. */
- /* Characters which start a comment. */
- const char comment_chars[] = "!";
- /* Characters which start a comment when they appear at the start of a line. */
- const char line_comment_chars[] = "#!";
- /* Characters which separate lines (null and newline are by default). */
- const char line_separator_chars[] = ";";
- /* Characters which may be used as the exponent character
- in a floating point number. */
- const char EXP_CHARS[] = "eE";
- /* Characters which may be used to indicate a floating point constant. */
- const char FLT_CHARS[] = "dDfF";
- static int enable_16bit = 1;
- /* Save for md_assemble to distinguish if this instruction is
- expanded from the pseudo instruction. */
- static bfd_boolean pseudo_opcode = FALSE;
- static struct nds32_relocs_pattern *relocs_list = NULL;
- /* Save instruction relation to inserting relaxation relocation. */
- struct nds32_relocs_pattern
- {
- segT seg;
- fragS *frag;
- frchainS *frchain;
- symbolS *sym;
- fixS* fixP;
- struct nds32_opcode *opcode;
- char *where;
- struct nds32_relocs_pattern *next;
- };
- /* Suffix name and relocation. */
- struct suffix_name
- {
- char *suffix;
- short unsigned int reloc;
- int pic;
- };
- static int vec_size = 0;
- /* If the assembly code is generated by compiler, it is supposed to have
- ".flag verbatim" at beginning of the content. We have
- 'nds32_flag' to parse it and set this field to be non-zero. */
- static int verbatim = 0;
- static struct hash_control *nds32_gprs_hash;
- static struct hash_control *nds32_hint_hash;
- #define TLS_REG "$r27"
- #define GOT_NAME "_GLOBAL_OFFSET_TABLE_"
- /* Generate relocation for relax or not, and the default is true. */
- static int enable_relax_relocs = 1;
- /* The value will be used in RELAX_ENTRY. */
- static int enable_relax_ex9 = 0;
- /* The value will be used in RELAX_ENTRY. */
- static int enable_relax_ifc = 0;
- /* Save option -O for perfomance. */
- static int optimize = 0;
- /* Save option -Os for code size. */
- static int optimize_for_space = 0;
- /* Flag to save label exist. */
- static int label_exist = 0;
- /* Flag to save state in omit_fp region. */
- static int in_omit_fp = 0;
- extern struct nds32_keyword keyword_gpr[];
- /* Tag there is relax relocation having to link. */
- static bfd_boolean relaxing = FALSE;
- static struct hash_control *nds32_relax_info_hash;
- static relax_info_t relax_table[] =
- {
- {
- "jal", /* opcode */
- BR_RANGE_S16M, /* br_range */
- {{0, 0, 0, FALSE}}, /* cond_field */
- {
- {
- INSN_JAL /* jal label */
- }, /* BR_RANGE_S256 */
- {
- INSN_JAL /* jal label */
- }, /* BR_RANGE_S16K */
- {
- INSN_JAL /* jal label */
- }, /* BR_RANGE_S64K */
- {
- INSN_JAL /* jal label */
- }, /* BR_RANGE_S16M */
- {
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JRAL_TA
- }, /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
- {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {4, 4, 4, 4, 12}, /* relax_code_size */
- {4, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, 0, BFD_RELOC_NDS32_HI20},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL4},
- {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "bltzal", /* opcode */
- BR_RANGE_S64K, /* br_range */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BLTZAL /* bltzal $rt, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BLTZAL /* bltzal $rt, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BLTZAL /* bltzal $rt, label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BGEZ, /* bgez $rt, $1 */
- INSN_JAL /* jal label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BGEZ, /* bgez $rt, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JRAL_TA /* jral $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {4, 4, 4, 8, 16}, /* relax_code_size */
- {4, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "bgezal", /* opcode */
- BR_RANGE_S64K, /* br_range */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BGEZAL /* bgezal $rt, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BGEZAL /* bgezal $rt, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BGEZAL /* bgezal $rt, label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BLTZ, /* bltz $rt, $1 */
- INSN_JAL /* jal label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BLTZ, /* bltz $rt, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JRAL_TA /* jral $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {4, 4, 4, 8, 16}, /* relax_code_size */
- {4, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGCALL6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "j", /* opcode */
- BR_RANGE_S16M, /* br_range */
- {{0, 0, 0, FALSE}}, /* cond_field */
- {
- {
- (INSN_J8 << 16) /* j8 label */
- }, /* BR_RANGE_S256 */
- {
- INSN_J /* j label */
- }, /* BR_RANGE_S16K */
- {
- INSN_J /* j label */
- }, /* BR_RANGE_S64K */
- {
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- }, /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
- {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {2, 4, 4, 4, 12}, /* relax_code_size */
- {2, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, 0, BFD_RELOC_NDS32_HI20},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4},
- {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "j8", /* opcode */
- BR_RANGE_S256, /* br_range */
- {{0, 0, 0, FALSE}}, /* cond_field */
- {
- {
- (INSN_J8 << 16) /* j8 label */
- }, /* BR_RANGE_S256 */
- {
- INSN_J /* j label */
- }, /* BR_RANGE_S16K */
- {
- INSN_J /* j label */
- }, /* BR_RANGE_S64K */
- {
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- }, /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
- {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {2, 4, 4, 4, 12}, /* relax_code_size */
- {2, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, 0, BFD_RELOC_NDS32_HI20},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP4},
- {4, 4, NDS32_HINT | NDS32_FIX, BFD_RELOC_NDS32_LO12S0_ORI},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {8, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {8, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "beqz", /* opcode */
- BR_RANGE_S64K, /* br_range */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BEQZ /* beqz $rt, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BEQZ /* beqz $rt, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BEQZ /* beqz $rt, label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BNEZ, /* bnez $rt, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BNEZ, /* bnez $rt, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {4, 4, 4, 8, 16}, /* relax_code_size */
- {4, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "bgez", /* opcode */
- BR_RANGE_S64K, /* br_range */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BGEZ /* bgez $rt, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BGEZ /* bgez $rt, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BGEZ /* bgez $rt, label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BLTZ, /* bltz $rt, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BLTZ, /* bltz $rt, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {4, 4, 4, 8, 16}, /* relax_code_size */
- {4, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "bnez", /* opcode */
- BR_RANGE_S64K, /* br_range */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BNEZ /* bnez $rt, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BNEZ /* bnez $rt, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BNEZ /* bnez $rt, label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BEQZ, /* beqz $rt, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BEQZ, /* beqz $rt, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {4, 4, 4, 8, 16}, /* relax_code_size */
- {4, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 4, NDS32_INSN16 , BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "bgtz", /* opcode */
- BR_RANGE_S64K, /* br_range */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BGTZ /* bgtz $rt, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BGTZ /* bgtz $rt, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BGTZ /* bgtz $rt, label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BLEZ, /* blez $rt, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BLEZ, /* blez $rt, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {4, 4, 4, 8, 16}, /* relax_code_size */
- {4, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "blez", /* opcode */
- BR_RANGE_S64K, /* br_range */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BLEZ /* blez $rt, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BLEZ /* blez $rt, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BLEZ /* blez $rt, label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BGTZ, /* bgtz $rt, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BGTZ, /* bgtz $rt, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {4, 4, 4, 8, 16}, /* relax_code_size */
- {4, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "bltz", /* opcode */
- BR_RANGE_S64K, /* br_range */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BLTZ /* bltz $rt, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BLTZ /* bltz $rt, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BLTZ /* bltz $rt, label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BGEZ, /* bgez $rt, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BGEZ, /* bgez $rt, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {4, 4, 4, 8, 16}, /* relax_code_size */
- {4, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "beq", /* opcode */
- BR_RANGE_S16K, /* br_range */
- {
- {0, 20, 0x1F, FALSE},
- {0, 15, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BEQ /* beq $rt, $ra, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BEQ /* beq $rt, $ra, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BNE, /* bne $rt, $ra, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BNE, /* bne $rt, $ra, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BNE, /* bne $rt, $ra, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 20, 0x1F, FALSE},
- {0, 15, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 20, 0x1F, FALSE},
- {0, 15, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 15, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 15, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 20, 0x1F, FALSE},
- {0, 15, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {4, 4, 8, 8, 16}, /* relax_code_size */
- {4, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {4, 4, NDS32_ABS, BFD_RELOC_NDS32_EMPTY},
- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "bne", /* opcode */
- BR_RANGE_S16K, /* br_range */
- {
- {0, 20, 0x1F, FALSE},
- {0, 15, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BNE /* bne $rt, $ra, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BNE /* bne $rt, $ra, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BEQ, /* beq $rt, $ra, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BEQ, /* beq $rt, $ra, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BEQ, /* beq $rt, $ra, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 20, 0x1F, FALSE},
- {0, 15, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 20, 0x1F, FALSE},
- {0, 15, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 15, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 15, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 20, 0x1F, FALSE},
- {0, 15, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {4, 4, 8, 8, 16}, /* relax_code_size */
- {4, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "beqz38", /* opcode */
- BR_RANGE_S256, /* br_range */
- {
- {0, 8, 0x7, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BEQZ38 << 16 /* beqz $rt, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BEQZ /* beqz $rt, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BEQZ /* beqz $rt, label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BNEZ, /* bnez $rt, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BNEZ, /* bnez $rt, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 8, 0x7, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {2, 4, 4, 8, 16}, /* relax_code_size */
- {2, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "bnez38", /* opcode */
- BR_RANGE_S256, /* br_range */
- {
- {0, 8, 0x7, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BNEZ38 << 16 /* bnez $rt, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BNEZ /* bnez $rt, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BNEZ /* bnez $rt, label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BEQZ, /* beqz $rt, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BEQZ, /* beqz $rt, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 8, 0x7, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {2, 4, 4, 8, 16}, /* relax_code_size */
- {2, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "beqzs8", /* opcode */
- BR_RANGE_S256, /* br_range */
- {{0, 0, 0, FALSE}}, /* cond_field */
- {
- {
- INSN_BEQZS8 << 16 /* beqz $r15, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BEQZ_TA /* bnez $rt, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BEQZ_TA /* bnez $rt, label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BNEZ_TA, /* bnez $r15, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BNEZ_TA, /* bnez $r15, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
- {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {2, 4, 4, 8, 16}, /* relax_code_size */
- {2, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "bnezs8", /* opcode */
- BR_RANGE_S256, /* br_range */
- {{0, 0, 0, FALSE}}, /* cond_field */
- {
- {
- INSN_BNEZS8 << 16 /* bnez $r15, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BNEZ_TA /* bnez $r15, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BNEZ_TA /* bnez $r15, label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BEQZ_TA, /* beqz $r15, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BEQZ_TA, /* beqz $r15, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S256 */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16K */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S64K */
- {{0, 0, 0, FALSE}}, /* BR_RANGE_S16M */
- {{0, 0, 0, FALSE}} /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {2, 4, 4, 8, 16}, /* relax_code_size */
- {2, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_17_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "bnes38", /* opcode */
- BR_RANGE_S256, /* br_range */
- {
- {0, 8, 0x7, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BNES38 << 16 /* bne $rt, $R5, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BNE_R5 /* bne $rt, $R5, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BEQ_R5, /* beq $rt, $R5, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BEQ_R5, /* beq $rt, $R5, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BEQ_R5, /* beq $rt, $R5, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 8, 0x7, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {2, 4, 8, 8, 16}, /* relax_code_size */
- {2, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "beqs38", /* opcode */
- BR_RANGE_S256, /* br_range */
- {
- {0, 8, 0x7, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BEQS38 << 16 /* beq $rt, $R5, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_BEQ_R5 /* beq $rt, $R5, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BNE_R5, /* bne $rt, $R5, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BNE_R5, /* bne $rt, $R5, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BNE_R5, /* bne $rt, $R5, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 8, 0x7, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {2, 4, 8, 8, 16}, /* relax_code_size */
- {2, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 2, NDS32_PCREL, BFD_RELOC_NDS32_9_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP5},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {4, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP6},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {4, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {8, 4, NDS32_FIX | NDS32_HINT, BFD_RELOC_NDS32_LO12S0_ORI},
- {8, 4, NDS32_PTR |NDS32_HINT, BFD_RELOC_NDS32_PTR},
- {12, 4, NDS32_ABS | NDS32_HINT, BFD_RELOC_NDS32_PTR_RESOLVED},
- {12, 4, NDS32_SYM | NDS32_HINT, BFD_RELOC_NDS32_EMPTY},
- {12, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "beqc", /* opcode */
- BR_RANGE_S256, /* br_range */
- {
- {0, 8, 0x7FF, TRUE},
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BEQC /* beqc $rt, imm11s, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_MOVI_TA, /* movi $ta, imm11s */
- INSN_BEQ_TA /* beq $rt, $ta, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BNEC, /* bnec $rt, imm11s, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BNEC, /* bnec $rt, imm11s, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BNEC, /* bnec $rt, imm11s, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 8, 0x7FF, TRUE},
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 0, 0xFFFFF, FALSE},
- {4, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 8, 0x7FF, FALSE},
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 8, 0x7FF, FALSE},
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 8, 0x7FF, FALSE},
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {4, 8, 8, 8, 16}, /* relax_code_size */
- {4, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
- {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- "bnec", /* opcode */
- BR_RANGE_S256, /* br_range */
- {
- {0, 8, 0x7FF, TRUE},
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* cond_field */
- {
- {
- INSN_BNEC /* bnec $rt, imm11s, label */
- }, /* BR_RANGE_S256 */
- {
- INSN_MOVI_TA, /* movi $ta, imm11s */
- INSN_BNE_TA /* bne $rt, $ta, label */
- }, /* BR_RANGE_S16K */
- {
- INSN_BEQC, /* beqc $rt, imm11s, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S64K */
- {
- INSN_BEQC, /* beqc $rt, imm11s, $1 */
- INSN_J /* j label */
- }, /* BR_RANGE_S16M */
- {
- INSN_BEQC, /* beqc $rt, imm11s, $1 */
- INSN_SETHI_TA, /* sethi $ta, label */
- INSN_ORI_TA, /* ori $ta, $ta, label */
- INSN_JR_TA /* jr $ta */
- } /* BR_RANGE_U4G */
- }, /* relax_code_seq */
- {
- {
- {0, 8, 0x7FF, TRUE},
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S256 */
- {
- {0, 0, 0xFFFFF, FALSE},
- {4, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16K */
- {
- {0, 8, 0x7FF, FALSE},
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S64K */
- {
- {0, 8, 0x7FF, FALSE},
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- }, /* BR_RANGE_S16M */
- {
- {0, 8, 0x7FF, FALSE},
- {0, 20, 0x1F, FALSE},
- {0, 0, 0, FALSE}
- } /* BR_RANGE_U4G */
- }, /* relax_code_condition */
- {4, 8, 8, 8, 16}, /* relax_code_size */
- {4, 4, 4, 4, 4}, /* relax_branch_isize */
- {
- {
- {0, 4, NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S256 */
- {
- {0, 4, NDS32_INSN16 | NDS32_HINT, BFD_RELOC_NDS32_INSN16},
- {0, 4, NDS32_PTR | NDS32_HINT, BFD_RELOC_NDS32_LONGJUMP7},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_15_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S64K */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
- {4, 4, NDS32_PCREL, BFD_RELOC_NDS32_25_PCREL},
- {0, 0, 0, 0}
- }, /* BR_RANGE_S16M */
- {
- {0, 4, NDS32_CREATE_LABEL | NDS32_PCREL, BFD_RELOC_NDS32_WORD_9_PCREL},
- {4, 4, 0, BFD_RELOC_NDS32_HI20},
- {8, 4, 0, BFD_RELOC_NDS32_LO12S0_ORI},
- {12, 4, NDS32_INSN16, BFD_RELOC_NDS32_INSN16},
- {0, 0, 0, 0}
- } /* BR_RANGE_U4G */
- } /* relax_fixup */
- },
- {
- NULL, /* opcode */
- 0, /* br_range */
- {{0, 0, 0, FALSE}}, /* cond_field */
- {{0}}, /* relax_code_seq */
- {{{0, 0, 0, FALSE}}}, /* relax_code_condition */
- {0}, /* relax_code_size */
- {0}, /* relax_branch_isize */
- {{{0, 0, 0, 0}}}, /* relax_fixup */
- },
- };
- /* GAS definitions for command-line options. */
- enum options
- {
- OPTION_BIG = OPTION_MD_BASE,
- OPTION_LITTLE,
- OPTION_TURBO,
- OPTION_PIC,
- OPTION_RELAX_FP_AS_GP_OFF,
- OPTION_RELAX_B2BB_ON,
- OPTION_RELAX_ALL_OFF,
- OPTION_OPTIMIZE,
- OPTION_OPTIMIZE_SPACE
- };
- const char *md_shortopts = "m:O:";
- struct option md_longopts[] =
- {
- {"O1", no_argument, NULL, OPTION_OPTIMIZE},
- {"Os", no_argument, NULL, OPTION_OPTIMIZE_SPACE},
- {"big", no_argument, NULL, OPTION_BIG},
- {"little", no_argument, NULL, OPTION_LITTLE},
- {"EB", no_argument, NULL, OPTION_BIG},
- {"EL", no_argument, NULL, OPTION_LITTLE},
- {"meb", no_argument, NULL, OPTION_BIG},
- {"mel", no_argument, NULL, OPTION_LITTLE},
- {"mall-ext", no_argument, NULL, OPTION_TURBO},
- {"mext-all", no_argument, NULL, OPTION_TURBO},
- {"mpic", no_argument, NULL, OPTION_PIC},
- /* Relaxation related options. */
- {"mno-fp-as-gp-relax", no_argument, NULL, OPTION_RELAX_FP_AS_GP_OFF},
- {"mb2bb", no_argument, NULL, OPTION_RELAX_B2BB_ON},
- {"mno-all-relax", no_argument, NULL, OPTION_RELAX_ALL_OFF},
- {NULL, no_argument, NULL, 0}
- };
- size_t md_longopts_size = sizeof (md_longopts);
- struct nds32_parse_option_table
- {
- const char *name; /* Option string. */
- char *help; /* Help description. */
- int (*func) (char *arg); /* How to parse it. */
- };
- /* The value `-1' represents this option has *NOT* been set. */
- #ifdef NDS32_DEFAULT_ARCH_NAME
- static char* nds32_arch_name = NDS32_DEFAULT_ARCH_NAME;
- #else
- static char* nds32_arch_name = "v3";
- #endif
- static int nds32_baseline = -1;
- static int nds32_gpr16 = -1;
- static int nds32_fpu_sp_ext = -1;
- static int nds32_fpu_dp_ext = -1;
- static int nds32_freg = -1;
- static int nds32_abi = -1;
- /* Record ELF flags */
- static int nds32_elf_flags = 0;
- static int nds32_fpu_com = 0;
- static int nds32_parse_arch (char *str);
- static int nds32_parse_baseline (char *str);
- static int nds32_parse_freg (char *str);
- static int nds32_parse_abi (char *str);
- static struct nds32_parse_option_table parse_opts [] =
- {
- {"arch=", N_("<arch name>\t Assemble for architecture <arch name>\n\
- <arch name> could be\n\
- v3, v3j, v3m, v3f, v3s, "\
- "v2, v2j, v2f, v2s"), nds32_parse_arch},
- {"baseline=", N_("<baseline>\t Assemble for baseline <baseline>\n\
- <baseline> could be v2, v3, v3m"),
- nds32_parse_baseline},
- {"fpu-freg=", N_("<freg>\t Specify a FPU configuration\n\
- <freg>\n\
- 0: 8 SP / 4 DP registers\n\
- 1: 16 SP / 8 DP registers\n\
- 2: 32 SP / 16 DP registers\n\
- 3: 32 SP / 32 DP registers"), nds32_parse_freg},
- {"abi=", N_("<abi>\t Specify a abi version\n\
- <abi> could be v1, v2, v2fp, v2fpp"), nds32_parse_abi},
- {NULL, NULL, NULL}
- };
- static int nds32_mac = 1;
- static int nds32_div = 1;
- static int nds32_16bit_ext = 1;
- static int nds32_dx_regs = 1;
- static int nds32_perf_ext = 1;
- static int nds32_perf_ext2 = 1;
- static int nds32_string_ext = 1;
- static int nds32_audio_ext = 1;
- static int nds32_fpu_fma = 0;
- static int nds32_pic = 0;
- static int nds32_relax_fp_as_gp = 1;
- static int nds32_relax_b2bb = 0;
- static int nds32_relax_all = 1;
- struct nds32_set_option_table
- {
- const char *name; /* Option string. */
- char *help; /* Help description. */
- int *var; /* Variable to be set. */
- int value; /* Value to set. */
- };
- /* The option in this group has both Enable/Disable settings.
- Just list on here. */
- static struct nds32_set_option_table toggle_opts [] =
- {
- {"mac", N_("Multiply instructions support"), &nds32_mac, 1},
- {"div", N_("Divide instructions support"), &nds32_div, 1},
- {"16bit-ext", N_("16-bit extension"), &nds32_16bit_ext, 1},
- {"dx-regs", N_("d0/d1 registers"), &nds32_dx_regs, 1},
- {"perf-ext", N_("Performance extension"), &nds32_perf_ext, 1},
- {"perf2-ext", N_("Performance extension 2"), &nds32_perf_ext2, 1},
- {"string-ext", N_("String extension"), &nds32_string_ext, 1},
- {"reduced-regs", N_("Reduced Register configuration (GPR16) option"), &nds32_gpr16, 1},
- {"audio-isa-ext", N_("AUDIO ISA extension"), &nds32_audio_ext, 1},
- {"fpu-sp-ext", N_("FPU SP extension"), &nds32_fpu_sp_ext, 1},
- {"fpu-dp-ext", N_("FPU DP extension"), &nds32_fpu_dp_ext, 1},
- {"fpu-fma", N_("FPU fused-multiply-add instructions"), &nds32_fpu_fma, 1},
- {NULL, NULL, NULL, 0}
- };
- /* GAS declarations. */
- /* This is the callback for nds32-asm.c to parse operands. */
- int
- nds32_asm_parse_operand (struct nds32_asm_desc *pdesc,
- struct nds32_asm_insn *pinsn,
- char **pstr, int64_t *value);
- struct nds32_asm_desc asm_desc;
- /* md_after_parse_args ()
- GAS will call md_after_parse_args whenever it is defined.
- This function checks any conflicting options specified. */
- void
- nds32_after_parse_args (void)
- {
- /* If -march option is not used in command-line, set the value of option
- variable according to NDS32_DEFAULT_ARCH_NAME. */
- nds32_parse_arch (nds32_arch_name);
- }
- /* This function is called when printing usage message (--help). */
- void
- md_show_usage (FILE *stream)
- {
- struct nds32_parse_option_table *coarse_tune;
- struct nds32_set_option_table *fine_tune;
- fprintf (stream, _("\n NDS32-specific assembler options:\n"));
- fprintf (stream, _("\
- -O1, Optimize for performance\n\
- -Os Optimize for space\n"));
- fprintf (stream, _("\
- -EL, -mel or -little Produce little endian output\n\
- -EB, -meb or -big Produce big endian output\n\
- -mpic Generate PIC\n\
- -mno-fp-as-gp-relax Suppress fp-as-gp relaxation for this file\n\
- -mb2bb-relax Back-to-back branch optimization\n\
- -mno-all-relax Suppress all relaxation for this file\n"));
- for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
- {
- if (coarse_tune->help != NULL)
- fprintf (stream, _(" -m%s%s\n"),
- coarse_tune->name, _(coarse_tune->help));
- }
- for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
- {
- if (fine_tune->help != NULL)
- fprintf (stream, _(" -m[no-]%-17sEnable/Disable %s\n"),
- fine_tune->name, _(fine_tune->help));
- }
- fprintf (stream, _("\
- -mall-ext Turn on all extensions and instructions support\n"));
- }
- void
- nds32_frag_init (fragS *fragp)
- {
- fragp->tc_frag_data.flag = 0;
- fragp->tc_frag_data.opcode = NULL;
- fragp->tc_frag_data.fixup = NULL;
- }
- /* This function reads an expression from a C string and returns a pointer past
- the end of the expression. */
- static char *
- parse_expression (char *str, expressionS *exp)
- {
- char *s;
- char *tmp;
- tmp = input_line_pointer; /* Save line pointer. */
- input_line_pointer = str;
- expression (exp);
- s = input_line_pointer;
- input_line_pointer = tmp; /* Restore line pointer. */
- return s; /* Return pointer to where parsing stopped. */
- }
- void
- nds32_start_line_hook (void)
- {
- }
- /*
- * Pseudo opcodes
- */
- typedef void (*nds32_pseudo_opcode_func) (int argc, char *argv[], int pv);
- struct nds32_pseudo_opcode
- {
- const char *opcode;
- int argc;
- nds32_pseudo_opcode_func proc;
- int pseudo_val;
- /* Some instructions are not pseudo opcode, but they might still be
- expanded or changed with other instruction combination for some
- conditions. We also apply this structure to assist such work.
- For example, if the distance of branch target '.L0' is larger than
- imm8s<<1 range,
- the instruction:
- beqzs8 .L0
- will be transformed into:
- bnezs8 .LCB0
- j .L0
- .LCB0:
- However, sometimes we do not want assembler to do such changes
- because compiler knows how to generate corresponding instruction sequence.
- Use this field to indicate that this opcode is also a physical instruction.
- If the flag 'verbatim' is nozero and this opcode
- is a physical instruction, we should not expand it. */
- int physical_op;
- };
- #define PV_DONT_CARE 0
- static struct hash_control *nds32_pseudo_opcode_hash = NULL;
- static int
- builtin_isreg (const char *s, const char *x ATTRIBUTE_UNUSED)
- {
- if (s [0] == '$' && hash_find (nds32_gprs_hash, (s + 1)))
- return 1;
- return 0;
- }
- static int
- builtin_regnum (const char *s, const char *x ATTRIBUTE_UNUSED)
- {
- struct nds32_keyword *k;
- if (*s != '$')
- return -1;
- s++;
- k = hash_find (nds32_gprs_hash, s);
- if (k == NULL)
- return -1;
- return k->value;
- }
- static int
- builtin_addend (const char *s, char *x ATTRIBUTE_UNUSED)
- {
- const char *ptr = s;
- while (*ptr != '+' && *ptr != '-' && *ptr)
- ++ptr;
- if (*ptr == 0)
- return 0;
- else
- return strtol (ptr, NULL, 0);
- }
- static void
- md_assemblef (char *format, ...)
- {
- /* FIXME: hope this is long enough. */
- char line[1024];
- va_list ap;
- unsigned int r;
- va_start (ap, format);
- r = vsnprintf (line, sizeof (line), format, ap);
- md_assemble (line);
- gas_assert (r < sizeof (line));
- }
- /* Some prototypes here, since some op may use another op. */
- static void do_pseudo_li_internal (char *rt, int imm32s);
- static void do_pseudo_move_reg_internal (char *dst, char *src);
- static void
- do_pseudo_b (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- char *arg_label = argv[0];
- relaxing = TRUE;
- /* b label */
- if (nds32_pic && strstr (arg_label, "@PLT"))
- {
- md_assemblef ("sethi $ta,hi20(%s)", arg_label);
- md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
- md_assemble ("add $ta,$ta,$gp");
- md_assemble ("jr $ta");
- }
- else
- {
- md_assemblef ("j %s", arg_label);
- }
- relaxing = FALSE;
- }
- static void
- do_pseudo_bal (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- char *arg_label = argv[0];
- relaxing = TRUE;
- /* bal|call label */
- if (nds32_pic
- && (strstr (arg_label, "@GOT") || strstr (arg_label, "@PLT")))
- {
- md_assemblef ("sethi $ta,hi20(%s)", arg_label);
- md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
- md_assemble ("add $ta,$ta,$gp");
- md_assemble ("jral $ta");
- }
- else
- {
- md_assemblef ("jal %s", arg_label);
- }
- relaxing = FALSE;
- }
- static void
- do_pseudo_bge (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- /* rt5, ra5, label */
- md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
- md_assemblef ("beqz $ta,%s", argv[2]);
- }
- static void
- do_pseudo_bges (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- /* rt5, ra5, label */
- md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
- md_assemblef ("beqz $ta,%s", argv[2]);
- }
- static void
- do_pseudo_bgt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- /* bgt rt5, ra5, label */
- md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
- md_assemblef ("bnez $ta,%s", argv[2]);
- }
- static void
- do_pseudo_bgts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- /* bgt rt5, ra5, label */
- md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
- md_assemblef ("bnez $ta,%s", argv[2]);
- }
- static void
- do_pseudo_ble (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- /* bgt rt5, ra5, label */
- md_assemblef ("slt $ta,%s,%s", argv[1], argv[0]);
- md_assemblef ("beqz $ta,%s", argv[2]);
- }
- static void
- do_pseudo_bles (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- /* bgt rt5, ra5, label */
- md_assemblef ("slts $ta,%s,%s", argv[1], argv[0]);
- md_assemblef ("beqz $ta,%s", argv[2]);
- }
- static void
- do_pseudo_blt (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- /* rt5, ra5, label */
- md_assemblef ("slt $ta,%s,%s", argv[0], argv[1]);
- md_assemblef ("bnez $ta,%s", argv[2]);
- }
- static void
- do_pseudo_blts (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- /* rt5, ra5, label */
- md_assemblef ("slts $ta,%s,%s", argv[0], argv[1]);
- md_assemblef ("bnez $ta,%s", argv[2]);
- }
- static void
- do_pseudo_br (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- md_assemblef ("jr %s", argv[0]);
- }
- static void
- do_pseudo_bral (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- if (argc == 1)
- md_assemblef ("jral $lp,%s", argv[0]);
- else
- md_assemblef ("jral %s,%s", argv[0], argv[1]);
- }
- static void
- do_pseudo_la_internal (const char *arg_reg, char *arg_label,
- const char *line)
- {
- expressionS exp;
- parse_expression (arg_label, &exp);
- if (exp.X_op != O_symbol)
- {
- as_bad (_("la must use with symbol. '%s'"), line);
- return;
- }
- relaxing = TRUE;
- /* rt, label */
- if (!nds32_pic && !strstr(arg_label, "@"))
- {
- md_assemblef ("sethi %s,hi20(%s)", arg_reg, arg_label);
- md_assemblef ("ori %s,%s,lo12(%s)", arg_reg, arg_reg, arg_label);
- }
- else if (strstr (arg_label, "@TPOFF"))
- {
- /* la $rt, sym@TPOFF */
- md_assemblef ("sethi $ta,hi20(%s)", arg_label);
- md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
- md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
- }
- else if (strstr(arg_label, "@GOTTPOFF"))
- {
- /* la $rt, sym@GOTTPOFF*/
- md_assemblef ("sethi $ta,hi20(%s)", arg_label);
- md_assemblef ("lwi $ta,[$ta+lo12(%s)]", arg_label);
- md_assemblef ("add %s,$ta,%s", arg_reg, TLS_REG);
- }
- else if (nds32_pic && ((strstr (arg_label, "@PLT")
- || strstr (arg_label, "@GOTOFF"))))
- {
- md_assemblef ("sethi $ta,hi20(%s)", arg_label);
- md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
- md_assemblef ("add %s,$ta,$gp", arg_reg);
- }
- else if (nds32_pic && strstr (arg_label, "@GOT"))
- {
- long addend = builtin_addend (arg_label, NULL);
- md_assemblef ("sethi $ta,hi20(%s)", arg_label);
- md_assemblef ("ori $ta,$ta,lo12(%s)", arg_label);
- md_assemblef ("lw %s,[$gp+$ta]", arg_reg);
- if (addend != 0)
- {
- if (addend < 0x4000 && addend >= -0x4000)
- {
- md_assemblef ("addi %s,%s,%d", arg_reg, arg_reg, addend);
- }
- else
- {
- do_pseudo_li_internal ("$ta", addend);
- md_assemblef ("add %s,$ta,%s", arg_reg, arg_reg);
- }
- }
- }
- else
- as_bad (_("need PIC qualifier with symbol. '%s'"), line);
- relaxing = FALSE;
- }
- static void
- do_pseudo_la (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- do_pseudo_la_internal (argv[0], argv[1], argv[argc]);
- }
- static void
- do_pseudo_li_internal (char *rt, int imm32s)
- {
- if (enable_16bit && imm32s <= 0xf && imm32s >= -0x10)
- md_assemblef ("movi55 %s,%d", rt, imm32s);
- else if (imm32s <= 0x7ffff && imm32s >= -0x80000)
- md_assemblef ("movi %s,%d", rt, imm32s);
- else if ((imm32s & 0xfff) == 0)
- md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
- else
- {
- md_assemblef ("sethi %s,hi20(%d)", rt, imm32s);
- md_assemblef ("ori %s,%s,lo12(%d)", rt, rt, imm32s);
- }
- }
- static void
- do_pseudo_li (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- /* Validate argv[1] for constant expression. */
- expressionS exp;
- parse_expression (argv[1], &exp);
- if (exp.X_op != O_constant)
- {
- as_bad (_("Operand is not a constant. `%s'"), argv[argc]);
- return;
- }
- do_pseudo_li_internal (argv[0], exp.X_add_number);
- }
- static void
- do_pseudo_ls_bhw (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
- {
- char ls = 'r';
- char size = 'x';
- const char *sign = "";
- /* Prepare arguments for various load/store. */
- sign = (pv & 0x10) ? "s" : "";
- ls = (pv & 0x80000000) ? 's' : 'l';
- switch (pv & 0x3)
- {
- case 0: size = 'b'; break;
- case 1: size = 'h'; break;
- case 2: size = 'w'; break;
- }
- if (ls == 's' || size == 'w')
- sign = "";
- if (builtin_isreg (argv[1], NULL))
- {
- /* lwi */
- md_assemblef ("%c%ci %s,[%s]", ls, size, argv[0], argv[1]);
- }
- else if (!nds32_pic)
- {
- relaxing = TRUE;
- if (strstr (argv[1], "@TPOFF"))
- {
- /* ls.w $rt, sym@TPOFF */
- md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
- md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
- md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
- }
- else if (strstr (argv[1], "@GOTTPOFF"))
- {
- /* ls.w $rt, sym@GOTTPOFF */
- md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
- md_assemblef ("lwi $ta,[$ta+lo12(%s)]", argv[1]);
- md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], TLS_REG);
- }
- else
- {
- /* lwi */
- md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
- md_assemblef ("%c%c%si %s,[$ta+lo12(%s)]", ls, size, sign, argv[0], argv[1]);
- }
- relaxing = FALSE;
- }
- else
- {
- relaxing = TRUE;
- /* PIC code. */
- if (strstr (argv[1], "@GOTOFF"))
- {
- /* lw */
- md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
- md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
- md_assemblef ("%c%c%s %s,[$ta+$gp]", ls, size, sign, argv[0]);
- }
- else if (strstr (argv[1], "@GOT"))
- {
- long addend = builtin_addend (argv[1], NULL);
- /* lw */
- md_assemblef ("sethi $ta,hi20(%s)", argv[1]);
- md_assemblef ("ori $ta,$ta,lo12(%s)", argv[1]);
- md_assemble ("lw $ta,[$gp+$ta]"); /* Load address word. */
- if (addend < 0x10000 && addend >= -0x10000)
- {
- md_assemblef ("%c%c%si %s,[$ta+(%d)]", ls, size, sign, argv[0], addend);
- }
- else
- {
- /* lw */
- do_pseudo_li_internal (argv[0], addend);
- md_assemblef ("%c%c%s %s,[$ta+%s]", ls, size, sign, argv[0], argv[0]);
- }
- }
- else
- {
- as_bad (_("needs @GOT or @GOTOFF. %s"), argv[argc]);
- }
- relaxing = FALSE;
- }
- }
- static void
- do_pseudo_ls_bhwp (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
- {
- char *arg_rt = argv[0];
- char *arg_label = argv[1];
- char *arg_inc = argv[2];
- char ls = 'r';
- char size = 'x';
- const char *sign = "";
- /* Prepare arguments for various load/store. */
- sign = (pv & 0x10) ? "s" : "";
- ls = (pv & 0x80000000) ? 's' : 'l';
- switch (pv & 0x3)
- {
- case 0: size = 'b'; break;
- case 1: size = 'h'; break;
- case 2: size = 'w'; break;
- }
- if (ls == 's' || size == 'w')
- sign = "";
- do_pseudo_la_internal ("$ta", arg_label, argv[argc]);
- md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
- }
- static void
- do_pseudo_ls_bhwpc (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
- {
- char *arg_rt = argv[0];
- char *arg_inc = argv[1];
- char ls = 'r';
- char size = 'x';
- const char *sign = "";
- /* Prepare arguments for various load/store. */
- sign = (pv & 0x10) ? "s" : "";
- ls = (pv & 0x80000000) ? 's' : 'l';
- switch (pv & 0x3)
- {
- case 0: size = 'b'; break;
- case 1: size = 'h'; break;
- case 2: size = 'w'; break;
- }
- if (ls == 's' || size == 'w')
- sign = "";
- md_assemblef ("%c%c%si.bi %s,[$ta],%s", ls, size, sign, arg_rt, arg_inc);
- }
- static void
- do_pseudo_ls_bhwi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv)
- {
- char ls = 'r';
- char size = 'x';
- const char *sign = "";
- /* Prepare arguments for various load/store. */
- sign = (pv & 0x10) ? "s" : "";
- ls = (pv & 0x80000000) ? 's' : 'l';
- switch (pv & 0x3)
- {
- case 0: size = 'b'; break;
- case 1: size = 'h'; break;
- case 2: size = 'w'; break;
- }
- if (ls == 's' || size == 'w')
- sign = "";
- md_assemblef ("%c%c%si.bi %s,%s,%s",
- ls, size, sign, argv[0], argv[1], argv[2]);
- }
- static void
- do_pseudo_move_reg_internal (char *dst, char *src)
- {
- if (enable_16bit)
- md_assemblef ("mov55 %s,%s", dst, src);
- else
- md_assemblef ("ori %s,%s,0", dst, src);
- }
- static void
- do_pseudo_move (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- expressionS exp;
- if (builtin_isreg (argv[1], NULL))
- do_pseudo_move_reg_internal (argv[0], argv[1]);
- else
- {
- parse_expression (argv[1], &exp);
- if (exp.X_op == O_constant)
- /* move $rt, imm -> li $rt, imm */
- do_pseudo_li_internal (argv[0], exp.X_add_number);
- else
- /* l.w $rt, var -> l.w $rt, var */
- do_pseudo_ls_bhw (argc, argv, 2);
- }
- }
- static void
- do_pseudo_neg (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- /* Instead of "subri". */
- md_assemblef ("subri %s,%s,0", argv[0], argv[1]);
- }
- static void
- do_pseudo_not (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- md_assemblef ("nor %s,%s,%s", argv[0], argv[1], argv[1]);
- }
- static void
- do_pseudo_pushpopm (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- /* posh/pop $ra, $rb */
- /* SMW.{b | a}{i | d}{m?} Rb, [Ra], Re, Enable4 */
- int rb, re, ra, en4;
- int i;
- char *opc = "pushpopm";
- if (argc == 3)
- as_bad ("'pushm/popm $ra5, $rb5, $label' is deprecated. "
- "Only 'pushm/popm $ra5' is supported now. %s", argv[argc]);
- else if (argc == 1)
- as_bad ("'pushm/popm $ra5, $rb5'. %s\n", argv[argc]);
- if (strstr (argv[argc], "pop") == argv[argc])
- opc = "lmw.bim";
- else if (strstr (argv[argc], "push") == argv[argc])
- opc = "smw.adm";
- else
- as_fatal ("nds32-as internal error. %s", argv[argc]);
- rb = builtin_regnum (argv[0], NULL);
- re = builtin_regnum (argv[1], NULL);
- if (re < rb)
- {
- as_warn ("$rb should not be smaller than $ra. %s", argv[argc]);
- /* Swap to right order. */
- ra = re;
- re = rb;
- rb = ra;
- }
- /* Build enable4 mask. */
- en4 = 0;
- if (re >= 28 || rb >= 28)
- {
- for (i = (rb >= 28? rb: 28); i <= re; i++)
- en4 |= 1 << (3 - (i - 28));
- }
- /* Adjust $re, $rb. */
- if (rb >= 28)
- rb = re = 31;
- else if (nds32_gpr16 != 1 && re >= 28)
- re = 27;
- /* Reduce register. */
- if (nds32_gpr16 && re > 10 && !(rb == 31 && re == 31))
- {
- if (re >= 15 && strstr(opc, "smw") != NULL)
- md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
- if (rb <= 10)
- md_assemblef ("%s $r%d,[$sp],$r10, 0x0", opc, rb);
- if (re >= 15 && strstr(opc, "lmw") != NULL)
- md_assemblef ("%s $r15,[$sp],$r15,%d", opc, en4);
- }
- else
- md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
- }
- static void
- do_pseudo_pushpop (int argc, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- /* push/pop $ra5, $label=$sp */
- char *argvm[3];
- if (argc == 2)
- as_bad ("'push/pop $ra5, rb5' is deprecated. "
- "Only 'push/pop $ra5' is supported now. %s", argv[argc]);
- argvm[0] = argv[0];
- argvm[1] = argv[0];
- argvm[2] = argv[argc];
- do_pseudo_pushpopm (2, argvm, PV_DONT_CARE);
- }
- static void
- do_pseudo_v3push (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- md_assemblef ("push25 %s,%s", argv[0], argv[1]);
- }
- static void
- do_pseudo_v3pop (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- md_assemblef ("pop25 %s,%s", argv[0], argv[1]);
- }
- /* pv == 0, parsing "push.s" pseudo instruction operands.
- pv != 0, parsing "pop.s" pseudo instruction operands. */
- static void
- do_pseudo_pushpop_stack (int argc, char *argv[], int pv)
- {
- /* push.s Rb,Re,{$fp $gp $lp $sp} ==> smw.adm Rb,[$sp],Re,Eable4 */
- /* pop.s Rb,Re,{$fp $gp $lp $sp} ==> lmw.bim Rb,[$sp],Re,Eable4 */
- int rb, re;
- int en4;
- int last_arg_index;
- char *opc = (pv == 0) ? "smw.adm" : "lmw.bim";
- rb = re = 0;
- if (argc == 1)
- {
- /* argc=1, operands pattern: { $fp $gp $lp $sp } */
- /* Set register number Rb = Re = $sp = $r31. */
- rb = re = 31;
- }
- else if (argc == 2 || argc == 3)
- {
- /* argc=2, operands pattern: Rb, Re */
- /* argc=3, operands pattern: Rb, Re, { $fp $gp $lp $sp } */
- /* Get register number in integer. */
- rb = builtin_regnum (argv[0], NULL);
- re = builtin_regnum (argv[1], NULL);
- /* Rb should be equal/less than Re. */
- if (rb > re)
- as_bad ("The first operand (%s) should be equal to or smaller than "
- "second operand (%s).", argv[0], argv[1]);
- /* forbid using $fp|$gp|$lp|$sp in Rb or Re
- r28 r29 r30 r31 */
- if (rb >= 28)
- as_bad ("Cannot use $fp, $gp, $lp, or $sp at first operand !!");
- if (re >= 28)
- as_bad ("Cannot use $fp, $gp, $lp, or $sp at second operand !!");
- }
- else
- {
- as_bad ("Invalid operands pattern !!");
- }
- /* Build Enable4 mask. */
- /* Using last_arg_index for argc=1|2|3 is safe, because $fp, $gp, $lp,
- and $sp only appear in argc=1 or argc=3 if argc=2, en4 remains 0,
- which is also valid for code generation. */
- en4 = 0;
- last_arg_index = argc - 1;
- if (strstr (argv[last_arg_index], "$fp"))
- en4 |= 8;
- if (strstr (argv[last_arg_index], "$gp"))
- en4 |= 4;
- if (strstr (argv[last_arg_index], "$lp"))
- en4 |= 2;
- if (strstr (argv[last_arg_index], "$sp"))
- en4 |= 1;
- md_assemblef ("%s $r%d,[$sp],$r%d,%d", opc, rb, re, en4);
- }
- static void
- do_pseudo_push_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- char size = 'x';
- /* If users omit push location, use $sp as default value. */
- char location[8] = "$sp"; /* 8 is enough for register name. */
- switch (pv & 0x3)
- {
- case 0: size = 'b'; break;
- case 1: size = 'h'; break;
- case 2: size = 'w'; break;
- case 3: size = 'w'; break;
- }
- if (argc == 2)
- {
- strncpy (location, argv[1], 8);
- location[7] = '\0';
- }
- md_assemblef ("l.%c $ta,%s", size, argv[0]);
- md_assemblef ("smw.adm $ta,[%s],$ta", location);
- if ((pv & 0x3) == 0x3) /* double-word */
- {
- md_assemblef ("l.w $ta,%s+4", argv[0]);
- md_assemblef ("smw.adm $ta,[%s],$ta", location);
- }
- }
- static void
- do_pseudo_pop_bhwd (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- char size = 'x';
- /* If users omit pop location, use $sp as default value. */
- char location[8] = "$sp"; /* 8 is enough for register name. */
- switch (pv & 0x3)
- {
- case 0: size = 'b'; break;
- case 1: size = 'h'; break;
- case 2: size = 'w'; break;
- case 3: size = 'w'; break;
- }
- if (argc == 3)
- {
- strncpy (location, argv[2], 8);
- location[7] = '\0';
- }
- if ((pv & 0x3) == 0x3) /* double-word */
- {
- md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
- md_assemblef ("s.w %s,%s+4", argv[1], argv[0]);
- }
- md_assemblef ("lmw.bim %s,[%s],%s", argv[1], location, argv[1]);
- md_assemblef ("s.%c %s,%s", size, argv[1], argv[0]);
- }
- static void
- do_pseudo_pusha (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- /* If users omit push location, use $sp as default value. */
- char location[8] = "$sp"; /* 8 is enough for register name. */
- if (argc == 2)
- {
- strncpy (location, argv[1], 8);
- location[7] = '\0';
- }
- md_assemblef ("la $ta,%s", argv[0]);
- md_assemblef ("smw.adm $ta,[%s],$ta", location);
- }
- static void
- do_pseudo_pushi (int argc ATTRIBUTE_UNUSED, char *argv[], int pv ATTRIBUTE_UNUSED)
- {
- /* If users omit push location, use $sp as default value. */
- char location[8] = "$sp"; /* 8 is enough for register name. */
- if (argc == 2)
- {
- strncpy (location, argv[1], 8);
- location[7] = '\0';
- }
- md_assemblef ("li $ta,%s", argv[0]);
- md_assemblef ("smw.adm $ta,[%s],$ta", location);
- }
- struct nds32_pseudo_opcode nds32_pseudo_opcode_table[] =
- {
- {"b", 1, do_pseudo_b, 0, 0},
- {"bal", 1, do_pseudo_bal, 0, 0},
- {"bge", 3, do_pseudo_bge, 0, 0},
- {"bges", 3, do_pseudo_bges, 0, 0},
- {"bgt", 3, do_pseudo_bgt, 0, 0},
- {"bgts", 3, do_pseudo_bgts, 0, 0},
- {"ble", 3, do_pseudo_ble, 0, 0},
- {"bles", 3, do_pseudo_bles, 0, 0},
- {"blt", 3, do_pseudo_blt, 0, 0},
- {"blts", 3, do_pseudo_blts, 0, 0},
- {"br", 1, do_pseudo_br, 0, 0},
- {"bral", 1, do_pseudo_bral, 0, 0},
- {"call", 1, do_pseudo_bal, 0, 0},
- {"la", 2, do_pseudo_la, 0, 0},
- {"li", 2, do_pseudo_li, 0, 0},
- {"l.b", 2, do_pseudo_ls_bhw, 0, 0},
- {"l.h", 2, do_pseudo_ls_bhw, 1, 0},
- {"l.w", 2, do_pseudo_ls_bhw, 2, 0},
- {"l.bs", 2, do_pseudo_ls_bhw, 0 | 0x10, 0},
- {"l.hs", 2, do_pseudo_ls_bhw, 1 | 0x10, 0},
- {"s.b", 2, do_pseudo_ls_bhw, 0 | 0x80000000, 0},
- {"s.h", 2, do_pseudo_ls_bhw, 1 | 0x80000000, 0},
- {"s.w", 2, do_pseudo_ls_bhw, 2 | 0x80000000, 0},
- {"l.bp", 3, do_pseudo_ls_bhwp, 0, 0},
- {"l.bpc", 3, do_pseudo_ls_bhwpc, 0, 0},
- {"l.hp", 3, do_pseudo_ls_bhwp, 1, 0},
- {"l.hpc", 3, do_pseudo_ls_bhwpc, 1, 0},
- {"l.wp", 3, do_pseudo_ls_bhwp, 2, 0},
- {"l.wpc", 3, do_pseudo_ls_bhwpc, 2, 0},
- {"l.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x10, 0},
- {"l.bspc", 3, do_pseudo_ls_bhwpc, 0 | 0x10, 0},
- {"l.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x10, 0},
- {"l.hspc", 3, do_pseudo_ls_bhwpc, 1 | 0x10, 0},
- {"s.bp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000, 0},
- {"s.bpc", 3, do_pseudo_ls_bhwpc, 0 | 0x80000000, 0},
- {"s.hp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000, 0},
- {"s.hpc", 3, do_pseudo_ls_bhwpc, 1 | 0x80000000, 0},
- {"s.wp", 3, do_pseudo_ls_bhwp, 2 | 0x80000000, 0},
- {"s.wpc", 3, do_pseudo_ls_bhwpc, 2 | 0x80000000, 0},
- {"s.bsp", 3, do_pseudo_ls_bhwp, 0 | 0x80000000 | 0x10, 0},
- {"s.hsp", 3, do_pseudo_ls_bhwp, 1 | 0x80000000 | 0x10, 0},
- {"lbi.p", 3, do_pseudo_ls_bhwi, 0, 0},
- {"lhi.p", 3, do_pseudo_ls_bhwi, 1, 0},
- {"lwi.p", 3, do_pseudo_ls_bhwi, 2, 0},
- {"sbi.p", 3, do_pseudo_ls_bhwi, 0 | 0x80000000, 0},
- {"shi.p", 3, do_pseudo_ls_bhwi, 1 | 0x80000000, 0},
- {"swi.p", 3, do_pseudo_ls_bhwi, 2 | 0x80000000, 0},
- {"lbsi.p", 3, do_pseudo_ls_bhwi, 0 | 0x10, 0},
- {"lhsi.p", 3, do_pseudo_ls_bhwi, 1 | 0x10, 0},
- {"lwsi.p", 3, do_pseudo_ls_bhwi, 2 | 0x10, 0},
- {"move", 2, do_pseudo_move, 0, 0},
- {"neg", 2, do_pseudo_neg, 0, 0},
- {"not", 2, do_pseudo_not, 0, 0},
- {"pop", 2, do_pseudo_pushpop, 0, 0},
- {"push", 2, do_pseudo_pushpop, 0, 0},
- {"popm", 2, do_pseudo_pushpopm, 0, 0},
- {"pushm", 3, do_pseudo_pushpopm, 0, 0},
- {"v3push", 2, do_pseudo_v3push, 0, 0},
- {"v3pop", 2, do_pseudo_v3pop, 0, 0},
- /* Support pseudo instructions of pushing/poping registers into/from stack
- push.s Rb, Re, { $fp $gp $lp $sp } ==> smw.adm Rb,[$sp],Re,Enable4
- pop.s Rb, Re, { $fp $gp $lp $sp } ==> lmw.bim Rb,[$sp],Re,Enable4 */
- { "push.s", 3, do_pseudo_pushpop_stack, 0, 0 },
- { "pop.s", 3, do_pseudo_pushpop_stack, 1, 0 },
- { "push.b", 2, do_pseudo_push_bhwd, 0, 0 },
- { "push.h", 2, do_pseudo_push_bhwd, 1, 0 },
- { "push.w", 2, do_pseudo_push_bhwd, 2, 0 },
- { "push.d", 2, do_pseudo_push_bhwd, 3, 0 },
- { "pop.b", 3, do_pseudo_pop_bhwd, 0, 0 },
- { "pop.h", 3, do_pseudo_pop_bhwd, 1, 0 },
- { "pop.w", 3, do_pseudo_pop_bhwd, 2, 0 },
- { "pop.d", 3, do_pseudo_pop_bhwd, 3, 0 },
- { "pusha", 2, do_pseudo_pusha, 0, 0 },
- { "pushi", 2, do_pseudo_pushi, 0, 0 },
- {NULL, 0, NULL, 0, 0}
- };
- static void
- nds32_init_nds32_pseudo_opcodes (void)
- {
- struct nds32_pseudo_opcode *opcode = nds32_pseudo_opcode_table;
- nds32_pseudo_opcode_hash = hash_new ();
- for ( ; opcode->opcode; opcode++)
- {
- void *op;
- op = hash_find (nds32_pseudo_opcode_hash, opcode->opcode);
- if (op != NULL)
- {
- as_warn (_("Duplicated pseudo-opcode %s."), opcode->opcode);
- continue;
- }
- hash_insert (nds32_pseudo_opcode_hash, opcode->opcode, opcode);
- }
- }
- static struct nds32_pseudo_opcode *
- nds32_lookup_pseudo_opcode (char *str)
- {
- int i = 0;
- /* Assume pseudo-opcode are less than 16-char in length. */
- char op[16] = {0};
- for (i = 0; i < (int)ARRAY_SIZE (op); i++)
- {
- if (ISSPACE (op[i] = str[i]))
- break;
- }
- if (i >= (int)ARRAY_SIZE (op))
- return NULL;
- op[i] = '\0';
- return hash_find (nds32_pseudo_opcode_hash, op);
- }
- static void
- nds32_pseudo_opcode_wrapper (char *line, struct nds32_pseudo_opcode *opcode)
- {
- int argc = 0;
- char *argv[8] = {NULL};
- char *s;
- char *str = xstrdup (line);
- /* Parse arguments for opcode. */
- s = str + strlen (opcode->opcode);
- if (!s[0])
- goto end;
- /* Dummy comma to ease separate arguments as below. */
- s[0] = ',';
- do
- {
- if (s[0] == ',')
- {
- if (argc >= opcode->argc
- || (argc >= (int)ARRAY_SIZE (argv) - 1))
- as_bad (_("Too many argument. `%s'"), line);
- argv[argc] = s + 1;
- argc ++;
- s[0] = '\0';
- }
- ++s;
- } while (s[0] != '\0');
- end:
- /* Put the origin line for debugging. */
- argv[argc] = line;
- opcode->proc (argc, argv, opcode->pseudo_val);
- free (str);
- }
- /* This function will be invoked from function `nds32_after_parse_args'.
- Thus, if the value of option has been set, keep the value the way it is. */
- static int
- nds32_parse_arch (char *str)
- {
- static const struct nds32_arch
- {
- const char *name;
- int baseline;
- int reduced_reg;
- int fpu_sp_ext;
- int fpu_dp_ext;
- int fpu_freg;
- int abi;
- } archs[] =
- {
- {"v3m", ISA_V3M, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
- {"v3j", ISA_V3, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
- {"v3s", ISA_V3, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
- {"v3f", ISA_V3, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
- {"v3", ISA_V3, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
- {"v2j", ISA_V2, 1, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
- {"v2s", ISA_V2, 0, 1, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
- {"v2f", ISA_V2, 0, 1, 1, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_V2FP_PLUS},
- {"v2", ISA_V2, 0, 0, 0, E_NDS32_FPU_REG_32SP_16DP, E_NDS_ABI_AABI},
- };
- size_t i;
- for (i = 0; i < ARRAY_SIZE (archs); i++)
- {
- if (strcmp (str, archs[i].name) != 0)
- continue;
- /* The value `-1' represents this option has *NOT* been set. */
- nds32_baseline = (-1 != nds32_baseline) ? nds32_baseline : archs[i].baseline;
- nds32_gpr16 = (-1 != nds32_gpr16) ? nds32_gpr16 : archs[i].reduced_reg;
- nds32_fpu_sp_ext = (-1 != nds32_fpu_sp_ext) ? nds32_fpu_sp_ext : archs[i].fpu_sp_ext;
- nds32_fpu_dp_ext = (-1 != nds32_fpu_dp_ext) ? nds32_fpu_dp_ext : archs[i].fpu_dp_ext;
- nds32_freg = (-1 != nds32_freg) ? nds32_freg : archs[i].fpu_freg;
- nds32_abi = (-1 != nds32_abi) ? nds32_abi : archs[i].abi;
- return 1;
- }
- /* Logic here rejects the input arch name. */
- as_bad (_("unknown arch name `%s'\n"), str);
- return 1;
- }
- /* This function parses "baseline" specified. */
- static int
- nds32_parse_baseline (char *str)
- {
- if (strcmp (str, "v3") == 0)
- nds32_baseline = ISA_V3;
- else if (strcmp (str, "v3m") == 0)
- nds32_baseline = ISA_V3M;
- else if (strcmp (str, "v2") == 0)
- nds32_baseline = ISA_V2;
- else
- {
- /* Logic here rejects the input baseline. */
- as_bad (_("unknown baseline `%s'\n"), str);
- return 0;
- }
- return 1;
- }
- /* This function parses "fpu-freg" specified. */
- static int
- nds32_parse_freg (char *str)
- {
- if (strcmp (str, "2") == 0)
- nds32_freg = E_NDS32_FPU_REG_32SP_16DP;
- else if (strcmp (str, "3") == 0)
- nds32_freg = E_NDS32_FPU_REG_32SP_32DP;
- else if (strcmp (str, "1") == 0)
- nds32_freg = E_NDS32_FPU_REG_16SP_8DP;
- else if (strcmp (str, "0") == 0)
- nds32_freg = E_NDS32_FPU_REG_8SP_4DP;
- else
- {
- /* Logic here rejects the input FPU configuration. */
- as_bad (_("unknown FPU configuration `%s'\n"), str);
- return 0;
- }
- return 1;
- }
- /* This function parse "abi=" specified. */
- static int
- nds32_parse_abi (char *str)
- {
- if (strcmp (str, "v2") == 0)
- nds32_abi = E_NDS_ABI_AABI;
- /* Obsolete. */
- else if (strcmp (str, "v2fp") == 0)
- nds32_abi = E_NDS_ABI_V2FP;
- else if (strcmp (str, "v1") == 0)
- nds32_abi = E_NDS_ABI_V1;
- else if (strcmp (str,"v2fpp") == 0)
- nds32_abi = E_NDS_ABI_V2FP_PLUS;
- else
- {
- /* Logic here rejects the input abi version. */
- as_bad (_("unknown ABI version`%s'\n"), str);
- return 0;
- }
- return 1;
- }
- /* This function turn on all extensions and instructions support. */
- static int
- nds32_all_ext (void)
- {
- nds32_mac = 1;
- nds32_div = 1;
- nds32_dx_regs = 1;
- nds32_16bit_ext = 1;
- nds32_perf_ext = 1;
- nds32_perf_ext2 = 1;
- nds32_string_ext = 1;
- nds32_audio_ext = 1;
- nds32_fpu_fma = 1;
- nds32_fpu_sp_ext = 1;
- nds32_fpu_dp_ext = 1;
- return 1;
- }
- /* GAS will call md_parse_option whenever getopt returns an unrecognized code,
- presumably indicating a special code value which appears in md_longopts.
- This function should return non-zero if it handled the option and zero
- otherwise. There is no need to print a message about an option not being
- recognized. This will be handled by the generic code. */
- int
- nds32_parse_option (int c, char *arg)
- {
- struct nds32_parse_option_table *coarse_tune;
- struct nds32_set_option_table *fine_tune;
- char *ptr_arg = NULL;
- switch (c)
- {
- case OPTION_OPTIMIZE:
- optimize = 1;
- optimize_for_space = 0;
- break;
- case OPTION_OPTIMIZE_SPACE:
- optimize = 0;
- optimize_for_space = 1;
- break;
- case OPTION_BIG:
- target_big_endian = 1;
- break;
- case OPTION_LITTLE:
- target_big_endian = 0;
- break;
- case OPTION_TURBO:
- nds32_all_ext ();
- break;
- case OPTION_PIC:
- nds32_pic = 1;
- break;
- case OPTION_RELAX_FP_AS_GP_OFF:
- nds32_relax_fp_as_gp = 0;
- break;
- case OPTION_RELAX_B2BB_ON:
- nds32_relax_b2bb = 1;
- break;
- case OPTION_RELAX_ALL_OFF:
- nds32_relax_all = 0;
- break;
- default:
- /* Determination of which option table to search for to save time. */
- if (!arg)
- return 0;
- ptr_arg = strchr (arg, '=');
- if (ptr_arg)
- {
- /* Find the value after '='. */
- if (ptr_arg != NULL)
- ptr_arg++;
- for (coarse_tune = parse_opts; coarse_tune->name != NULL; coarse_tune++)
- {
- if (strncmp (arg, coarse_tune->name, (ptr_arg - arg)) == 0)
- {
- coarse_tune->func (ptr_arg);
- return 1;
- }
- }
- }
- else
- {
- int disable = 0;
- /* Filter out the Disable option first. */
- if (strncmp (arg, "no-", 3) == 0)
- {
- disable = 1;
- arg += 3;
- }
- for (fine_tune = toggle_opts; fine_tune->name != NULL; fine_tune++)
- {
- if (strcmp (arg, fine_tune->name) == 0)
- {
- if (fine_tune->var != NULL)
- *fine_tune->var = (disable) ? 0 : 1;
- return 1;
- }
- }
- }
- /* Nothing match. */
- return 0;
- }
- return 1;
- }
- /* tc_check_label */
- void
- nds32_check_label (symbolS *label ATTRIBUTE_UNUSED)
- {
- /* The code used to create BB is move to frob_label.
- They should go there. */
- }
- static void
- set_endian_little (int on)
- {
- target_big_endian = !on;
- }
- /* These functions toggles the generation of 16-bit. First encounter signals
- the beginning of not generating 16-bit instructions and next encounter
- signals the restoring back to default behavior. */
- static void
- trigger_16bit (int trigger)
- {
- enable_16bit = trigger;
- }
- static int backup_16bit_mode;
- static void
- restore_16bit (int no_use ATTRIBUTE_UNUSED)
- {
- enable_16bit = backup_16bit_mode;
- }
- static void
- off_16bit (int no_use ATTRIBUTE_UNUSED)
- {
- backup_16bit_mode = enable_16bit;
- enable_16bit = 0;
- }
- /* Built-in segments for small object. */
- typedef struct nds32_seg_entryT
- {
- segT s;
- const char *name;
- flagword flags;
- } nds32_seg_entry;
- nds32_seg_entry nds32_seg_table[] =
- {
- {NULL, ".sdata_f", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
- | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
- {NULL, ".sdata_b", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
- | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
- {NULL, ".sdata_h", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
- | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
- {NULL, ".sdata_w", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
- | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
- {NULL, ".sdata_d", SEC_ALLOC | SEC_LOAD | SEC_RELOC | SEC_DATA
- | SEC_HAS_CONTENTS | SEC_SMALL_DATA},
- {NULL, ".sbss_f", SEC_ALLOC | SEC_SMALL_DATA},
- {NULL, ".sbss_b", SEC_ALLOC | SEC_SMALL_DATA},
- {NULL, ".sbss_h", SEC_ALLOC | SEC_SMALL_DATA},
- {NULL, ".sbss_w", SEC_ALLOC | SEC_SMALL_DATA},
- {NULL, ".sbss_d", SEC_ALLOC | SEC_SMALL_DATA}
- };
- /* Indexes to nds32_seg_table[]. */
- enum NDS32_SECTIONS_ENUM
- {
- SDATA_F_SECTION = 0,
- SDATA_B_SECTION = 1,
- SDATA_H_SECTION = 2,
- SDATA_W_SECTION = 3,
- SDATA_D_SECTION = 4,
- SBSS_F_SECTION = 5,
- SBSS_B_SECTION = 6,
- SBSS_H_SECTION = 7,
- SBSS_W_SECTION = 8,
- SBSS_D_SECTION = 9
- };
- /* The following code is borrowed from v850_seg. Revise this is needed. */
- static void
- do_nds32_seg (int i, subsegT sub)
- {
- nds32_seg_entry *seg = nds32_seg_table + i;
- obj_elf_section_change_hook ();
- if (seg->s != NULL)
- subseg_set (seg->s, sub);
- else
- {
- seg->s = subseg_new (seg->name, sub);
- if (OUTPUT_FLAVOR == bfd_target_elf_flavour)
- {
- bfd_set_section_flags (stdoutput, seg->s, seg->flags);
- if ((seg->flags & SEC_LOAD) == 0)
- seg_info (seg->s)->bss = 1;
- }
- }
- }
- static void
- nds32_seg (int i)
- {
- subsegT sub = get_absolute_expression ();
- do_nds32_seg (i, sub);
- demand_empty_rest_of_line ();
- }
- /* Set if label adjustment is needed. I should not adjust .xbyte in dwarf. */
- static symbolS *nds32_last_label; /* Last label for aligment. */
- /* This code is referred from D30V for adjust label to be with pedning
- aligment. For example,
- LBYTE: .byte 0x12
- LHALF: .half 0x12
- LWORD: .word 0x12
- Without this, the above label will not attatch to incoming data. */
- static void
- nds32_adjust_label (int n)
- {
- /* FIXME: I think adjust lable and alignment is
- the programmer's obligation. Saddly, VLSI team doesn't
- properly use .align for their test cases.
- So I re-implement cons_align and auto adjust labels, again.
- I think d30v's implmentation is simple and good enough. */
- symbolS *label = nds32_last_label;
- nds32_last_label = NULL;
- /* SEC_ALLOC is used to eliminate .debug_ sections.
- SEC_CODE is used to include section for ILM. */
- if (((now_seg->flags & SEC_ALLOC) == 0 && (now_seg->flags & SEC_CODE) == 0)
- || strcmp (now_seg->name, ".eh_frame") == 0
- || strcmp (now_seg->name, ".gcc_except_table") == 0)
- return;
- /* Only frag by alignment when needed.
- Otherwise, it will fail to optimize labels on 4-byte boundary. (bug8454)
- See md_convert_frag () and RELAX_SET_RELAXABLE (frag) for details. */
- if (frag_now_fix () & ((1 << n) -1 ))
- {
- if (subseg_text_p (now_seg))
- frag_align_code (n, 0);
- else
- frag_align (n, 0, 0);
- /* Record the minimum alignment for this segment. */
- record_alignment (now_seg, n - OCTETS_PER_BYTE_POWER);
- }
- if (label != NULL)
- {
- symbolS *sym;
- int label_seen = FALSE;
- struct frag *old_frag;
- valueT old_value, new_value;
- gas_assert (S_GET_SEGMENT (label) == now_seg);
- old_frag = symbol_get_frag (label);
- old_value = S_GET_VALUE (label);
- new_value = (valueT) frag_now_fix ();
- /* Multiple labels may be on the same address. And the last symbol
- may not be a label at all, e.g., register name, external function names,
- so I have to track the last label in tc_frob_label instead of
- just using symbol_lastP. */
- for (sym = symbol_lastP; sym != NULL; sym = symbol_previous (sym))
- {
- if (symbol_get_frag (sym) == old_frag
- && S_GET_VALUE (sym) == old_value)
- {
- /* Warning HERE! */
- label_seen = TRUE;
- symbol_set_frag (sym, frag_now);
- S_SET_VALUE (sym, new_value);
- }
- else if (label_seen && symbol_get_frag (sym) != old_frag)
- break;
- }
- }
- }
- void
- nds32_cons_align (int size ATTRIBUTE_UNUSED)
- {
- /* Do nothing here.
- This is called before `md_flush_pending_output' is called by `cons'.
- There are two things should be done for auto-adjust-label.
- 1. Align data/instructions and adjust label to be attached to them.
- 2. Clear auto-adjust state, so incommng data/instructions will not
- adjust the label.
- For example,
- .byte 0x1
- .L0:
- .word 0x2
- .word 0x3
- in this case, '.word 0x2' will adjust the label, .L0, but '.word 0x3' should not.
- I think `md_flush_pending_output' is a good place to clear the auto-adjust state,
- but it is also called by `cons' before this function.
- To simplify the code, instead of overriding .zero, .fill, .space, etc,
- I think we should just adjust label in `nds32_aligned_X_cons' instead of here. */
- }
- static void
- nds32_aligned_cons (int idx)
- {
- nds32_adjust_label (idx);
- /* Call default handler. */
- cons (1 << idx);
- if (now_seg->flags & SEC_CODE
- && now_seg->flags & SEC_ALLOC && now_seg->flags & SEC_RELOC)
- {
- /* Use BFD_RELOC_NDS32_DATA to avoid EX9 optimization replacing data. */
- expressionS exp;
- exp.X_add_number = 0;
- exp.X_op = O_constant;
- fix_new_exp (frag_now, frag_now_fix () - (1 << idx), 1 << idx,
- &exp, 0, BFD_RELOC_NDS32_DATA);
- }
- }
- /* `.double' directive. */
- static void
- nds32_aligned_float_cons (int type)
- {
- switch (type)
- {
- case 'f':
- case 'F':
- case 's':
- case 'S':
- nds32_adjust_label (2);
- break;
- case 'd':
- case 'D':
- case 'r':
- case 'R':
- nds32_adjust_label (4);
- break;
- default:
- as_bad ("Unrecognized float type, %c\n", (char)type);
- }
- /* Call default handler. */
- float_cons (type);
- }
- static void
- nds32_enable_pic (int ignore ATTRIBUTE_UNUSED)
- {
- /* Another way to do -mpic.
- This is for GCC internal use and should always be first line
- of code, otherwise, the effect is not determined. */
- nds32_pic = 1;
- }
- static void
- nds32_set_abi (int ver)
- {
- nds32_abi = ver;
- }
- /* Relax directive to set relocation R_NDS32_RELAX_ENTRY value. */
- static void
- nds32_relax_relocs (int relax)
- {
- char saved_char;
- char *name;
- int i;
- char *subtype_relax[] =
- {"", "", "ex9", "ifc"};
- name = input_line_pointer;
- while (*input_line_pointer && !ISSPACE (*input_line_pointer))
- input_line_pointer++;
- saved_char = *input_line_pointer;
- *input_line_pointer = 0;
- for (i = 0; i < (int) ARRAY_SIZE (subtype_relax); i++)
- {
- if (strcmp (name, subtype_relax[i]) == 0)
- {
- switch (i)
- {
- case 0:
- case 1:
- enable_relax_relocs = relax & enable_relax_relocs;
- enable_relax_ex9 = relax & enable_relax_ex9;
- enable_relax_ifc = relax & enable_relax_ifc;
- break;
- case 2:
- enable_relax_ex9 = relax;
- break;
- case 3:
- enable_relax_ifc = relax;
- break;
- default:
- break;
- }
- break;
- }
- }
- *input_line_pointer = saved_char;
- ignore_rest_of_line ();
- }
- /* Record which arguments register($r0 ~ $r5) is not used in callee.
- bit[i] for $ri */
- static void
- nds32_set_hint_func_args (int ignore ATTRIBUTE_UNUSED)
- {
- ignore_rest_of_line ();
- }
- /* Insert relocations to mark the begin and end of a fp-omitted function,
- for further relaxation use.
- bit[i] for $ri */
- static void
- nds32_omit_fp_begin (int mode)
- {
- expressionS exp;
- if (nds32_relax_fp_as_gp == 0)
- return;
- exp.X_op = O_symbol;
- exp.X_add_symbol = abs_section_sym;
- if (mode == 1)
- {
- in_omit_fp = 1;
- exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
- fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
- BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
- }
- else
- {
- in_omit_fp = 0;
- exp.X_add_number = R_NDS32_RELAX_REGION_OMIT_FP_FLAG;
- fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
- BFD_RELOC_NDS32_RELAX_REGION_END);
- }
- }
- /* Insert relocations to mark the begin and end of ex9 region,
- for further relaxation use.
- bit[i] for $ri */
- static void
- nds32_no_ex9_begin (int mode)
- {
- expressionS exp;
- exp.X_op = O_symbol;
- exp.X_add_symbol = abs_section_sym;
- if (mode == 1)
- {
- exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG;
- fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
- BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
- }
- else
- {
- exp.X_add_number = R_NDS32_RELAX_REGION_NO_EX9_FLAG;
- fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
- BFD_RELOC_NDS32_RELAX_REGION_END);
- }
- }
- static void
- nds32_loop_begin (int mode)
- {
- /* Insert loop region relocation here. */
- expressionS exp;
- exp.X_op = O_symbol;
- exp.X_add_symbol = abs_section_sym;
- if (mode == 1)
- {
- exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
- fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
- BFD_RELOC_NDS32_RELAX_REGION_BEGIN);
- }
- else
- {
- exp.X_add_number = R_NDS32_RELAX_REGION_INNERMOST_LOOP_FLAG;
- fix_new_exp (frag_now, frag_now_fix (), 0, &exp, 0,
- BFD_RELOC_NDS32_RELAX_REGION_END);
- }
- }
- struct nds32_relocs_group
- {
- struct nds32_relocs_pattern *pattern;
- struct nds32_relocs_group *next;
- };
- static struct nds32_relocs_group *nds32_relax_hint_current = NULL;
- /* Insert a relax hint. */
- static void
- nds32_relax_hint (int mode ATTRIBUTE_UNUSED)
- {
- char *name;
- char saved_char;
- struct nds32_relocs_pattern *relocs = NULL;
- struct nds32_relocs_group *group, *new;
- name = input_line_pointer;
- while (*input_line_pointer && !ISSPACE (*input_line_pointer))
- input_line_pointer++;
- saved_char = *input_line_pointer;
- *input_line_pointer = 0;
- name = strdup (name);
- /* Find relax hint entry for next instruction, and all member will be
- initialized at that time. */
- relocs = hash_find (nds32_hint_hash, name);
- if (relocs == NULL)
- {
- relocs = malloc (sizeof (struct nds32_relocs_pattern));
- hash_insert (nds32_hint_hash, name, relocs);
- }
- else
- {
- while (relocs->next)
- relocs=relocs->next;
- relocs->next = malloc (sizeof (struct nds32_relocs_pattern));
- relocs = relocs->next;
- }
- relocs->next = NULL;
- *input_line_pointer = saved_char;
- ignore_rest_of_line ();
- /* Get the final one of relax hint series. */
- /* It has to build this list because there are maybe more than one
- instructions relative to the same instruction. It to connect to
- next instruction after md_assemble. */
- new = malloc (sizeof (struct nds32_relocs_group));
- new->pattern = relocs;
- new->next = NULL;
- group = nds32_relax_hint_current;
- if (!group)
- nds32_relax_hint_current = new;
- else
- {
- while (group->next != NULL)
- group = group->next;
- group->next = new;
- }
- relaxing = TRUE;
- }
- /* Decide the size of vector entries, only accepts 4 or 16 now. */
- static void
- nds32_vec_size (int ignore ATTRIBUTE_UNUSED)
- {
- expressionS exp;
- expression (&exp);
- if (exp.X_op == O_constant)
- {
- if (exp.X_add_number == 4 || exp.X_add_number == 16)
- {
- if (vec_size == 0)
- vec_size = exp.X_add_number;
- else if (vec_size != exp.X_add_number)
- as_warn (_("Different arguments of .vec_size are found, "
- "previous %d, current %d"),
- (int) vec_size, (int) exp.X_add_number);
- }
- else
- as_warn (_("Argument of .vec_size is expected 4 or 16, actual: %d."),
- (int) exp.X_add_number);
- }
- else
- as_warn (_("Argument of .vec_size is not a constant."));
- }
- /* The behavior of ".flag" directive varies depending on the target.
- In nds32 target, we use it to recognize whether this assembly content is
- generated by compiler. Other features can also be added in this function
- in the future. */
- static void
- nds32_flag (int ignore ATTRIBUTE_UNUSED)
- {
- char *name;
- char saved_char;
- int i;
- char *possible_flags[] = { "verbatim" };
- /* Skip whitespaces. */
- name = input_line_pointer;
- while (*input_line_pointer && !ISSPACE (*input_line_pointer))
- input_line_pointer++;
- saved_char = *input_line_pointer;
- *input_line_pointer = 0;
- for (i = 0; i < (int) ARRAY_SIZE (possible_flags); i++)
- {
- if (strcmp (name, possible_flags[i]) == 0)
- {
- switch (i)
- {
- case 0:
- /* flag: verbatim */
- verbatim = 1;
- break;
- default:
- break;
- }
- /* Already found the flag, no need to continue next loop. */
- break;
- }
- }
- *input_line_pointer = saved_char;
- ignore_rest_of_line ();
- }
- static void
- nds32_n12hc (int ignore ATTRIBUTE_UNUSED)
- {
- /* N1213HC core is used. */
- }
- /* The target specific pseudo-ops which we support. */
- const pseudo_typeS md_pseudo_table[] =
- {
- /* Forced alignment if declared these ways. */
- {"ascii", stringer, 8 + 0},
- {"asciz", stringer, 8 + 1},
- {"double", nds32_aligned_float_cons, 'd'},
- {"dword", nds32_aligned_cons, 3},
- {"float", nds32_aligned_float_cons, 'f'},
- {"half", nds32_aligned_cons, 1},
- {"hword", nds32_aligned_cons, 1},
- {"int", nds32_aligned_cons, 2},
- {"long", nds32_aligned_cons, 2},
- {"octa", nds32_aligned_cons, 4},
- {"quad", nds32_aligned_cons, 3},
- {"qword", nds32_aligned_cons, 4},
- {"short", nds32_aligned_cons, 1},
- {"byte", nds32_aligned_cons, 0},
- {"single", nds32_aligned_float_cons, 'f'},
- {"string", stringer, 8 + 1},
- {"word", nds32_aligned_cons, 2},
- {"little", set_endian_little, 1},
- {"big", set_endian_little, 0},
- {"16bit_on", trigger_16bit, 1},
- {"16bit_off", trigger_16bit, 0},
- {"restore_16bit", restore_16bit, 0},
- {"off_16bit", off_16bit, 0},
- {"sdata_d", nds32_seg, SDATA_D_SECTION},
- {"sdata_w", nds32_seg, SDATA_W_SECTION},
- {"sdata_h", nds32_seg, SDATA_H_SECTION},
- {"sdata_b", nds32_seg, SDATA_B_SECTION},
- {"sdata_f", nds32_seg, SDATA_F_SECTION},
- {"sbss_d", nds32_seg, SBSS_D_SECTION},
- {"sbss_w", nds32_seg, SBSS_W_SECTION},
- {"sbss_h", nds32_seg, SBSS_H_SECTION},
- {"sbss_b", nds32_seg, SBSS_B_SECTION},
- {"sbss_f", nds32_seg, SBSS_F_SECTION},
- {"pic", nds32_enable_pic, 0},
- {"n12_hc", nds32_n12hc, 0},
- {"abi_1", nds32_set_abi, E_NDS_ABI_V1},
- {"abi_2", nds32_set_abi, E_NDS_ABI_AABI},
- /* Obsolete. */
- {"abi_2fp", nds32_set_abi, E_NDS_ABI_V2FP},
- {"abi_2fp_plus", nds32_set_abi, E_NDS_ABI_V2FP_PLUS},
- {"relax", nds32_relax_relocs, 1},
- {"no_relax", nds32_relax_relocs, 0},
- {"hint_func_args", nds32_set_hint_func_args, 0}, /* Abandon?? */
- {"omit_fp_begin", nds32_omit_fp_begin, 1},
- {"omit_fp_end", nds32_omit_fp_begin, 0},
- {"no_ex9_begin", nds32_no_ex9_begin, 1},
- {"no_ex9_end", nds32_no_ex9_begin, 0},
- {"vec_size", nds32_vec_size, 0},
- {"flag", nds32_flag, 0},
- {"innermost_loop_begin", nds32_loop_begin, 1},
- {"innermost_loop_end", nds32_loop_begin, 0},
- {"relax_hint", nds32_relax_hint, 0},
- {NULL, NULL, 0}
- };
- void
- nds32_pre_do_align (int n, char *fill, int len, int max)
- {
- /* Only make a frag if we HAVE to... */
- fragS *fragP;
- if (n != 0 && !need_pass_2)
- {
- if (fill == NULL)
- {
- if (subseg_text_p (now_seg))
- {
- dwarf2_emit_insn (0);
- fragP = frag_now;
- frag_align_code (n, max);
- /* Tag this alignment when there is a lable before it. */
- if (label_exist)
- {
- fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
- label_exist = 0;
- }
- }
- else
- frag_align (n, 0, max);
- }
- else if (len <= 1)
- frag_align (n, *fill, max);
- else
- frag_align_pattern (n, fill, len, max);
- }
- }
- void
- nds32_do_align (int n)
- {
- /* Optimize for space and label exists. */
- expressionS exp;
- /* FIXME:I think this will break debug info sections and except_table. */
- if (!enable_relax_relocs || !subseg_text_p (now_seg))
- return;
- /* Create and attach a BFD_RELOC_NDS32_LABEL fixup
- the size of instruction may not be correct because
- it could be relaxable. */
- exp.X_op = O_symbol;
- exp.X_add_symbol = section_symbol (now_seg);
- exp.X_add_number = n;
- fix_new_exp (frag_now,
- frag_now_fix (), 0, &exp, 0, BFD_RELOC_NDS32_LABEL);
- }
- /* Supported Andes machines. */
- struct nds32_machs
- {
- enum bfd_architecture bfd_mach;
- int mach_flags;
- };
- /* This is the callback for nds32-asm.c to parse operands. */
- int
- nds32_asm_parse_operand (struct nds32_asm_desc *pdesc ATTRIBUTE_UNUSED,
- struct nds32_asm_insn *pinsn,
- char **pstr, int64_t *value)
- {
- char *hold;
- expressionS *pexp = pinsn->info;
- hold = input_line_pointer;
- input_line_pointer = *pstr;
- expression (pexp);
- *pstr = input_line_pointer;
- input_line_pointer = hold;
- switch (pexp->X_op)
- {
- case O_symbol:
- *value = 0;
- return NASM_R_SYMBOL;
- case O_constant:
- *value = pexp->X_add_number;
- return NASM_R_CONST;
- case O_illegal:
- case O_absent:
- case O_register:
- default:
- return NASM_R_ILLEGAL;
- }
- }
- /* GAS will call this function at the start of the assembly, after the command
- line arguments have been parsed and all the machine independent
- initializations have been completed. */
- void
- md_begin (void)
- {
- struct nds32_keyword *k;
- relax_info_t *relax_info;
- bfd_set_arch_mach (stdoutput, TARGET_ARCH, nds32_baseline);
- nds32_init_nds32_pseudo_opcodes ();
- asm_desc.parse_operand = nds32_asm_parse_operand;
- nds32_asm_init (&asm_desc, 0);
- /* Initial general pupose registers hash table. */
- nds32_gprs_hash = hash_new ();
- for (k = keyword_gpr; k->name; k++)
- hash_insert (nds32_gprs_hash, k->name, k);
- /* Initial branch hash table. */
- nds32_relax_info_hash = hash_new ();
- for (relax_info = relax_table; relax_info->opcode; relax_info++)
- hash_insert (nds32_relax_info_hash, relax_info->opcode, relax_info);
- /* Initial relax hint hash table. */
- nds32_hint_hash = hash_new ();
- enable_16bit = nds32_16bit_ext;
- }
- /* HANDLE_ALIGN in write.c. */
- void
- nds32_handle_align (fragS *fragp)
- {
- static const unsigned char nop16[] = { 0x92, 0x00 };
- static const unsigned char nop32[] = { 0x40, 0x00, 0x00, 0x09 };
- int bytes;
- char *p;
- if (fragp->fr_type != rs_align_code)
- return;
- bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
- p = fragp->fr_literal + fragp->fr_fix;
- if (bytes & 1)
- {
- *p++ = 0;
- bytes--;
- }
- if (bytes & 2)
- {
- expressionS exp_t;
- exp_t.X_op = O_symbol;
- exp_t.X_add_symbol = abs_section_sym;
- exp_t.X_add_number = R_NDS32_INSN16_CONVERT_FLAG;
- fix_new_exp (fragp, fragp->fr_fix, 2, &exp_t, 0,
- BFD_RELOC_NDS32_INSN16);
- memcpy (p, nop16, 2);
- p += 2;
- bytes -= 2;
- }
- while (bytes >= 4)
- {
- memcpy (p, nop32, 4);
- p += 4;
- bytes -= 4;
- }
- bytes = fragp->fr_next->fr_address - fragp->fr_address - fragp->fr_fix;
- fragp->fr_fix += bytes;
- }
- /* md_flush_pending_output */
- void
- nds32_flush_pending_output (void)
- {
- nds32_last_label = NULL;
- }
- void
- nds32_frob_label (symbolS *label)
- {
- dwarf2_emit_label (label);
- }
- /* TC_START_LABEL */
- int
- nds32_start_label (int asmdone ATTRIBUTE_UNUSED, int secdone ATTRIBUTE_UNUSED)
- {
- if (optimize && subseg_text_p (now_seg))
- label_exist = 1;
- return 1;
- }
- /* TARGET_FORMAT */
- const char *
- nds32_target_format (void)
- {
- #ifdef TE_LINUX
- if (target_big_endian)
- return "elf32-nds32be-linux";
- else
- return "elf32-nds32le-linux";
- #else
- if (target_big_endian)
- return "elf32-nds32be";
- else
- return "elf32-nds32le";
- #endif
- }
- static enum nds32_br_range
- get_range_type (const struct nds32_field *field)
- {
- gas_assert (field != NULL);
- if (field->bitpos != 0)
- return BR_RANGE_U4G;
- if (field->bitsize == 24 && field->shift == 1)
- return BR_RANGE_S16M;
- else if (field->bitsize == 16 && field->shift == 1)
- return BR_RANGE_S64K;
- else if (field->bitsize == 14 && field->shift == 1)
- return BR_RANGE_S16K;
- else if (field->bitsize == 8 && field->shift == 1)
- return BR_RANGE_S256;
- else
- return BR_RANGE_U4G;
- }
- /* Save pseudo instruction relocation list. */
- static struct nds32_relocs_pattern*
- nds32_elf_save_pseudo_pattern (fixS* fixP, struct nds32_opcode *opcode,
- char *out, symbolS *sym,
- struct nds32_relocs_pattern *reloc_ptr,
- fragS *fragP)
- {
- if (!reloc_ptr)
- reloc_ptr = malloc (sizeof (struct nds32_relocs_pattern));
- reloc_ptr->seg = now_seg;
- reloc_ptr->sym = sym;
- reloc_ptr->frag = fragP;
- reloc_ptr->frchain = frchain_now;
- reloc_ptr->fixP = fixP;
- reloc_ptr->opcode = opcode;
- reloc_ptr->where = out;
- reloc_ptr->next = NULL;
- return reloc_ptr;
- }
- /* Check X_md to transform relocation. */
- static fixS*
- nds32_elf_record_fixup_exp (fragS *fragP, char *str,
- const struct nds32_field *fld,
- expressionS *pexp, char* out,
- struct nds32_asm_insn *insn)
- {
- int reloc = -1;
- expressionS exp;
- fixS *fixP = NULL;
- /* Handle instruction relocation. */
- if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_HI20))
- {
- /* Relocation for hi20 modifier. */
- switch (pexp->X_md)
- {
- case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */
- reloc = BFD_RELOC_NDS32_GOTOFF_HI20;
- break;
- case BFD_RELOC_NDS32_GOT20: /* @GOT */
- reloc = BFD_RELOC_NDS32_GOT_HI20;
- break;
- case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */
- if (!nds32_pic)
- as_bad (_("Invalid PIC expression."));
- else
- reloc = BFD_RELOC_NDS32_PLT_GOTREL_HI20;
- break;
- case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */
- reloc = BFD_RELOC_NDS32_GOTPC_HI20;
- break;
- case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */
- reloc = BFD_RELOC_NDS32_TLS_LE_HI20;
- break;
- case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
- reloc = BFD_RELOC_NDS32_TLS_IE_HI20;
- break;
- default: /* No suffix. */
- reloc = BFD_RELOC_NDS32_HI20;
- break;
- }
- fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
- insn->info, 0 /* pcrel */, reloc);
- }
- else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_LO12))
- {
- /* Relocation for lo12 modifier. */
- if (fld->bitsize == 15 && fld->shift == 0)
- {
- /* [ls]bi || ori */
- switch (pexp->X_md)
- {
- case BFD_RELOC_NDS32_GOTOFF: /* @GOTOFF */
- reloc = BFD_RELOC_NDS32_GOTOFF_LO12;
- break;
- case BFD_RELOC_NDS32_GOT20: /* @GOT */
- reloc = BFD_RELOC_NDS32_GOT_LO12;
- break;
- case BFD_RELOC_NDS32_25_PLTREL: /* @PLT */
- if (!nds32_pic)
- as_bad (_("Invalid PIC expression."));
- else
- reloc = BFD_RELOC_NDS32_PLT_GOTREL_LO12;
- break;
- case BFD_RELOC_NDS32_GOTPC20: /* _GLOBAL_OFFSET_TABLE_ */
- reloc = BFD_RELOC_NDS32_GOTPC_LO12;
- break;
- case BFD_RELOC_NDS32_TPOFF: /* @TPOFF */
- reloc = BFD_RELOC_NDS32_TLS_LE_LO12;
- break;
- default: /* No suffix. */
- reloc = BFD_RELOC_NDS32_LO12S0;
- break;
- }
- }
- else if (fld->bitsize == 15 && fld->shift == 1)
- reloc = BFD_RELOC_NDS32_LO12S1; /* [ls]hi */
- else if (fld->bitsize == 15 && fld->shift == 2)
- {
- /* [ls]wi */
- switch (pexp->X_md)
- {
- case BFD_RELOC_NDS32_GOTTPOFF: /* @GOTTPOFF */
- reloc = BFD_RELOC_NDS32_TLS_IE_LO12S2;
- break;
- default: /* No suffix. */
- reloc = BFD_RELOC_NDS32_LO12S2;
- break;
- }
- }
- else if (fld->bitsize == 15 && fld->shift == 3)
- reloc = BFD_RELOC_NDS32_LO12S3; /* [ls]di */
- else if (fld->bitsize == 12 && fld->shift == 2)
- reloc = R_NDS32_LO12S2_SP_RELA; /* f[ls][sd]i */
- fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
- insn->info, 0 /* pcrel */, reloc);
- }
- else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
- && (insn->attr & NASM_ATTR_PCREL))
- {
- /* Relocation for 32-bit branch instructions. */
- if (fld->bitsize == 24 && fld->shift == 1)
- reloc = BFD_RELOC_NDS32_25_PCREL;
- else if (fld->bitsize == 16 && fld->shift == 1)
- reloc = BFD_RELOC_NDS32_17_PCREL;
- else if (fld->bitsize == 14 && fld->shift == 1)
- reloc = BFD_RELOC_NDS32_15_PCREL;
- else if (fld->bitsize == 8 && fld->shift == 1)
- reloc = BFD_RELOC_NDS32_WORD_9_PCREL;
- else
- abort ();
- fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
- insn->info, 1 /* pcrel */, reloc);
- }
- else if (fld && fld->bitpos == 0 && insn->opcode->isize == 4
- && (insn->attr & NASM_ATTR_GPREL))
- {
- /* Relocation for 32-bit gp-relative instructions. */
- if (fld->bitsize == 19 && fld->shift == 0)
- reloc = BFD_RELOC_NDS32_SDA19S0;
- else if (fld->bitsize == 18 && fld->shift == 1)
- reloc = BFD_RELOC_NDS32_SDA18S1;
- else if (fld->bitsize == 17 && fld->shift == 2)
- reloc = BFD_RELOC_NDS32_SDA17S2;
- else
- abort ();
- fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
- insn->info, 0 /* pcrel */, reloc);
- /* Insert INSN16 for converting fp_as_gp. */
- exp.X_op = O_symbol;
- exp.X_add_symbol = abs_section_sym;
- exp.X_add_number = 0;
- if (in_omit_fp && reloc == BFD_RELOC_NDS32_SDA17S2)
- fix_new_exp (fragP, out - fragP->fr_literal,
- insn->opcode->isize, &exp, 0 /* pcrel */,
- BFD_RELOC_NDS32_INSN16);
- }
- else if (fld && fld->bitpos == 0 && insn->opcode->isize == 2
- && (insn->attr & NASM_ATTR_PCREL))
- {
- /* Relocation for 16-bit branch instructions. */
- if (fld->bitsize == 8 && fld->shift == 1)
- reloc = BFD_RELOC_NDS32_9_PCREL;
- else
- abort ();
- fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
- insn->info, 1 /* pcrel */, reloc);
- }
- else if (fld && fld->bitpos == 0 && (insn->attr & NASM_ATTR_IFC_EXT))
- {
- /* Relocation for ifcall instruction. */
- if (insn->opcode->isize == 2 && fld->bitsize == 9 && fld->shift == 1)
- reloc = BFD_RELOC_NDS32_10IFCU_PCREL;
- else if (insn->opcode->isize == 4 && fld->bitsize == 16
- && fld->shift == 1)
- reloc = BFD_RELOC_NDS32_17IFC_PCREL;
- else
- abort ();
- fixP = fix_new_exp (fragP, out - fragP->fr_literal, insn->opcode->isize,
- insn->info, 1 /* pcrel */, reloc);
- }
- else if (fld)
- as_bad (_("Don't know how to handle this field. %s"), str);
- return fixP;
- }
- /* Build instruction pattern to relax. There are two type group pattern
- including pseudo instruction and relax hint. */
- static void
- nds32_elf_build_relax_relation (fixS *fixP, expressionS *pexp, char* out,
- struct nds32_opcode *opcode, fragS *fragP,
- const struct nds32_field *fld)
- {
- struct nds32_relocs_pattern *reloc_ptr;
- struct nds32_relocs_group *group;
- symbolS *sym = NULL;
- /* The expression may be used uninitialized. */
- if (fld)
- sym = pexp->X_add_symbol;
- if (pseudo_opcode)
- {
- /* Save instruction relation for pseudo instruction expanding pattern. */
- reloc_ptr = nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym,
- NULL, fragP);
- if (!relocs_list)
- relocs_list = reloc_ptr;
- else
- {
- struct nds32_relocs_pattern *temp = relocs_list;
- while (temp->next)
- temp = temp->next;
- temp->next = reloc_ptr;
- }
- }
- else if (nds32_relax_hint_current)
- {
- /* Save instruction relation by relax hint. */
- group = nds32_relax_hint_current;
- while (group)
- {
- nds32_elf_save_pseudo_pattern (fixP, opcode, out, sym,
- group->pattern, fragP);
- group = group->next;
- free (nds32_relax_hint_current);
- nds32_relax_hint_current = group;
- }
- }
- /* Set relaxing false only for relax_hint trigger it. */
- if (!pseudo_opcode)
- relaxing = FALSE;
- }
- #define N32_MEM_EXT(insn) ((N32_OP6_MEM << 25) | insn)
- /* Relax pattern for link time relaxation. */
- static struct nds32_relax_hint_table relax_ls_table[] =
- {
- {
- /* Set address: la -> sethi ori. */
- NDS32_RELAX_HINT_LA, /* main_type */
- 8, /* relax_code_size */
- {
- OP6 (SETHI),
- OP6 (ORI),
- }, /* relax_code_seq */
- {
- {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
- {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16}
- } /* relax_fixup */
- },
- {
- /* Set address: l.w -> sethi ori. */
- NDS32_RELAX_HINT_LS, /* main_type */
- 8, /* relax_code_size */
- {
- OP6 (SETHI),
- OP6 (LBI),
- }, /* relax_code_seq */
- {
- {0, 4, NDS32_HINT | NDS32_ADDEND, BFD_RELOC_NDS32_LOADSTORE},
- {4, 4, NDS32_HINT | NDS32_ABS, BFD_RELOC_NDS32_INSN16}
- } /* relax_fixup */
- },
- {
- 0,
- 0,
- {0},
- {{0, 0 , 0, 0}}
- }
- };
- /* Since sethi loadstore relocation has to using next instruction to determine
- elimination itself or not, we have to return the next instruction range. */
- static int
- nds32_elf_sethi_range (struct nds32_relocs_pattern *pattern)
- {
- int range = 0;
- while (pattern)
- {
- switch (pattern->opcode->value)
- {
- case INSN_LBI:
- case INSN_SBI:
- case INSN_LBSI:
- case N32_MEM_EXT (N32_MEM_LB):
- case N32_MEM_EXT (N32_MEM_LBS):
- case N32_MEM_EXT (N32_MEM_SB):
- range = NDS32_LOADSTORE_BYTE;
- break;
- case INSN_LHI:
- case INSN_SHI:
- case INSN_LHSI:
- case N32_MEM_EXT (N32_MEM_LH):
- case N32_MEM_EXT (N32_MEM_LHS):
- case N32_MEM_EXT (N32_MEM_SH):
- range = NDS32_LOADSTORE_HALF;
- break;
- case INSN_LWI:
- case INSN_SWI:
- case N32_MEM_EXT (N32_MEM_LW):
- case N32_MEM_EXT (N32_MEM_SW):
- range = NDS32_LOADSTORE_WORD;
- break;
- case INSN_FLSI:
- case INSN_FSSI:
- range = NDS32_LOADSTORE_FLOAT_S;
- break;
- case INSN_FLDI:
- case INSN_FSDI:
- range = NDS32_LOADSTORE_FLOAT_D;
- break;
- case INSN_ORI:
- range = NDS32_LOADSTORE_IMM;
- break;
- default:
- range = NDS32_LOADSTORE_NONE;
- break;
- }
- if (range != NDS32_LOADSTORE_NONE)
- break;
- pattern = pattern->next;
- }
- return range;
- }
- /* The args means: instruction size, the 1st instruction is converted to 16 or
- not, optimize option, 16 bit instruction is enable. */
- #define SET_ADDEND(size, convertible, optimize, insn16_on) \
- (((size) & 0xff) | ((convertible) ? 1 << 31 : 0) \
- | ((optimize) ? 1<< 30 : 0) | (insn16_on ? 1 << 29 : 0))
- static void
- nds32_set_elf_flags_by_insn (struct nds32_asm_insn * insn)
- {
- /* Set E_NDS32_HAS_EXT_INST. */
- if (insn->opcode->attr & NASM_ATTR_PERF_EXT)
- {
- if (nds32_perf_ext)
- nds32_elf_flags |= E_NDS32_HAS_EXT_INST;
- else
- as_bad (_("instruction %s requires enabling performance extension"),
- insn->opcode->opcode);
- }
- else if (insn->opcode->attr & NASM_ATTR_PERF2_EXT)
- {
- if (nds32_perf_ext2)
- nds32_elf_flags |= E_NDS32_HAS_EXT2_INST;
- else
- as_bad (_("instruction %s requires enabling performance extension II"),
- insn->opcode->opcode);
- }
- else if (insn->opcode->attr & NASM_ATTR_AUDIO_ISAEXT)
- {
- if (nds32_audio_ext)
- nds32_elf_flags |= E_NDS32_HAS_AUDIO_INST;
- else
- as_bad (_("instruction %s requires enabling AUDIO extension"),
- insn->opcode->opcode);
- }
- else if (insn->opcode->attr & NASM_ATTR_STR_EXT)
- {
- if (nds32_string_ext)
- nds32_elf_flags |= E_NDS32_HAS_STRING_INST;
- else
- as_bad (_("instruction %s requires enabling STRING extension"),
- insn->opcode->opcode);
- }
- else if ((insn->opcode->attr & NASM_ATTR_DIV)
- && (insn->opcode->attr & NASM_ATTR_DXREG))
- {
- if (nds32_div && nds32_dx_regs)
- nds32_elf_flags |= E_NDS32_HAS_DIV_DX_INST;
- else
- as_bad (_("instruction %s requires enabling DIV & DX_REGS extension"),
- insn->opcode->opcode);
- }
- else if (insn->opcode->attr & NASM_ATTR_FPU)
- {
- if (nds32_fpu_sp_ext || nds32_fpu_dp_ext)
- {
- if (!(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
- nds32_fpu_com = 1;
- }
- else
- as_bad (_("instruction %s requires enabling FPU extension"),
- insn->opcode->opcode);
- }
- else if (insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
- {
- if (nds32_fpu_sp_ext)
- nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
- else
- as_bad (_("instruction %s requires enabling FPU_SP extension"),
- insn->opcode->opcode);
- }
- else if ((insn->opcode->attr & NASM_ATTR_FPU_SP_EXT)
- && (insn->opcode->attr & NASM_ATTR_MAC))
- {
- if (nds32_fpu_sp_ext && nds32_mac)
- {
- nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
- nds32_elf_flags |= E_NDS32_HAS_FPU_INST;
- }
- else
- as_bad (_("instruction %s requires enabling FPU_MAC extension"),
- insn->opcode->opcode);
- }
- else if (insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
- {
- if (nds32_fpu_dp_ext)
- nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
- else
- as_bad (_("instruction %s requires enabling FPU_DP extension"),
- insn->opcode->opcode);
- }
- else if ((insn->opcode->attr & NASM_ATTR_FPU_DP_EXT)
- && (insn->opcode->attr & NASM_ATTR_MAC))
- {
- if (nds32_fpu_dp_ext && nds32_mac)
- {
- nds32_elf_flags |= E_NDS32_HAS_FPU_MAC_INST;
- nds32_elf_flags |= E_NDS32_HAS_FPU_DP_INST;
- }
- else
- as_bad (_("instruction %s requires enabling FPU_MAC extension"),
- insn->opcode->opcode);
- }
- /* TODO: FPU_BOTH */
- else if ((insn->opcode->attr & NASM_ATTR_MAC)
- && (insn->opcode->attr & NASM_ATTR_DXREG))
- {
- if (nds32_mac && nds32_dx_regs)
- nds32_elf_flags |= E_NDS32_HAS_MAC_DX_INST;
- else
- as_bad (_("instruction %s requires enabling DX_REGS extension"),
- insn->opcode->opcode);
- }
- /* TODO: for DX_REG set but not for MAC, DIV, AUDIO */
- else if (insn->opcode->attr & NASM_ATTR_IFC_EXT)
- {
- nds32_elf_flags |= E_NDS32_HAS_IFC_INST;
- }
- /* TODO: E_NDS32_HAS_SATURATION_INST */
- }
- /* Flag for analysis relaxation type. */
- enum nds32_insn_type
- {
- N32_RELAX_SETHI = 1,
- N32_RELAX_BR = (1 << 1),
- N32_RELAX_LSI = (1 << 2),
- N32_RELAX_JUMP = (1 << 3),
- N32_RELAX_CALL = (1 << 4),
- N32_RELAX_ORI = (1 << 5),
- N32_RELAX_MEM = (1 << 6),
- N32_RELAX_MOVI = (1 << 7),
- };
- struct nds32_hint_map
- {
- bfd_reloc_code_real_type hi_type;
- char *opc;
- enum nds32_relax_hint_type hint_type;
- enum nds32_br_range range;
- enum nds32_insn_type insn_list;
- };
- /* Table to match instructions with hint and relax pattern. */
- static struct nds32_hint_map hint_map [] =
- {
- {
- /* LONGCALL4. */
- BFD_RELOC_NDS32_HI20,
- "jal",
- NDS32_RELAX_HINT_NONE,
- BR_RANGE_U4G,
- N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL
- },
- {
- /* LONGCALL5. */
- _dummy_first_bfd_reloc_code_real,
- "bgezal",
- NDS32_RELAX_HINT_NONE,
- BR_RANGE_S16M,
- N32_RELAX_BR | N32_RELAX_CALL
- },
- {
- /* LONGCALL6. */
- BFD_RELOC_NDS32_HI20,
- "bgezal",
- NDS32_RELAX_HINT_NONE,
- BR_RANGE_U4G,
- N32_RELAX_BR | N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_CALL
- },
- {
- /* LONGJUMP4. */
- BFD_RELOC_NDS32_HI20,
- "j",
- NDS32_RELAX_HINT_NONE,
- BR_RANGE_U4G,
- N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_JUMP
- },
- {
- /* LONGJUMP5. */
- /* There is two kinds of veriation of LONGJUMP5. One of them
- generate EMPTY relocation for converted INSN16 if needed.
- But we don't distinguish them here. */
- _dummy_first_bfd_reloc_code_real,
- "beq",
- NDS32_RELAX_HINT_NONE,
- BR_RANGE_S16M,
- N32_RELAX_BR | N32_RELAX_JUMP
- },
- {
- /* LONGJUMP6. */
- BFD_RELOC_NDS32_HI20,
- "beq",
- NDS32_RELAX_HINT_NONE,
- BR_RANGE_U4G,
- N32_RELAX_SETHI | N32_RELAX_ORI | N32_RELAX_BR | N32_RELAX_JUMP
- },
- {
- /* LONGJUMP7. */
- _dummy_first_bfd_reloc_code_real,
- "beqc",
- NDS32_RELAX_HINT_NONE,
- BR_RANGE_S16K,
- N32_RELAX_MOVI | N32_RELAX_BR
- },
- {
- /* LOADSTORE ADDRESS. */
- BFD_RELOC_NDS32_HI20,
- NULL,
- NDS32_RELAX_HINT_LA,
- BR_RANGE_U4G,
- N32_RELAX_SETHI | N32_RELAX_ORI
- },
- {
- /* LOADSTORE ADDRESS. */
- BFD_RELOC_NDS32_HI20,
- NULL,
- NDS32_RELAX_HINT_LS,
- BR_RANGE_U4G,
- N32_RELAX_SETHI | N32_RELAX_LSI
- },
- {0, NULL, 0, 0 ,0}
- };
- /* Find the relaxation pattern according to instructions. */
- static bfd_boolean
- nds32_find_reloc_table (struct nds32_relocs_pattern *relocs_pattern,
- struct nds32_relax_hint_table *hint_info)
- {
- unsigned int opcode, seq_size;
- enum nds32_br_range range;
- struct nds32_relocs_pattern *pattern, *hi_pattern = NULL;
- char *opc = NULL;
- relax_info_t *relax_info = NULL;
- nds32_relax_fixup_info_t *fixup_info, *hint_fixup;
- enum nds32_relax_hint_type hint_type = NDS32_RELAX_HINT_NONE;
- struct nds32_relax_hint_table *table_ptr;
- uint32_t *code_seq, *hint_code;
- enum nds32_insn_type relax_type = 0;
- struct nds32_hint_map *map_ptr = hint_map;
- unsigned int i;
- char *check_insn[] =
- { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
- /* TODO: PLT GOT. */
- /* Traverse all pattern instruction and set flag. */
- pattern = relocs_pattern;
- while (pattern)
- {
- if (pattern->opcode->isize == 4)
- {
- /* 4 byte instruction. */
- opcode = N32_OP6 (pattern->opcode->value);
- switch (opcode)
- {
- case N32_OP6_SETHI:
- hi_pattern = pattern;
- relax_type |= N32_RELAX_SETHI;
- break;
- case N32_OP6_MEM:
- relax_type |= N32_RELAX_MEM;
- break;
- case N32_OP6_ORI:
- relax_type |= N32_RELAX_ORI;
- break;
- case N32_OP6_BR1:
- case N32_OP6_BR2:
- case N32_OP6_BR3:
- relax_type |= N32_RELAX_BR;
- break;
- case N32_OP6_MOVI:
- relax_type |= N32_RELAX_MOVI;
- break;
- case N32_OP6_LBI:
- case N32_OP6_SBI:
- case N32_OP6_LBSI:
- case N32_OP6_LHI:
- case N32_OP6_SHI:
- case N32_OP6_LHSI:
- case N32_OP6_LWI:
- case N32_OP6_SWI:
- case N32_OP6_LWC:
- case N32_OP6_SWC:
- relax_type |= N32_RELAX_LSI;
- break;
- case N32_OP6_JREG:
- if (__GF (pattern->opcode->value, 0, 1) == 1)
- relax_type |= N32_RELAX_CALL;
- else
- relax_type |= N32_RELAX_JUMP;
- break;
- case N32_OP6_JI:
- if (__GF (pattern->opcode->value, 24, 1) == 1)
- relax_type |= N32_RELAX_CALL;
- else
- relax_type |= N32_RELAX_JUMP;
- break;
- default:
- as_warn (_("relax hint unrecognized instruction: line %d."),
- pattern->frag->fr_line);
- return FALSE;
- }
- }
- else
- {
- /* 2 byte instruction. Compare by opcode name because the opcode of
- 2byte instruction is not regular. */
- for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++)
- {
- if (strcmp (pattern->opcode->opcode, check_insn[i]) == 0)
- {
- relax_type |= N32_RELAX_BR;
- break;
- }
- }
- if (strcmp (pattern->opcode->opcode, "movi55") == 0)
- relax_type |= N32_RELAX_MOVI;
- }
- pattern = pattern->next;
- }
- /* Analysis instruction flag to choose relaxation table. */
- while (map_ptr->insn_list != 0)
- {
- if (map_ptr->insn_list == relax_type
- && (!hi_pattern
- || (hi_pattern->fixP
- && hi_pattern->fixP->fx_r_type == map_ptr->hi_type)))
- {
- opc = map_ptr->opc;
- hint_type = map_ptr->hint_type;
- range = map_ptr->range;
- break;
- }
- map_ptr++;
- }
- if (map_ptr->insn_list == 0)
- {
- as_warn (_("Can not find match relax hint. line : %d"),
- relocs_pattern->frag->fr_line);
- return FALSE;
- }
- /* Get the match table. */
- if (opc)
- {
- /* Branch relax pattern. */
- relax_info = hash_find (nds32_relax_info_hash, opc);
- if (!relax_info)
- return FALSE;
- fixup_info = relax_info->relax_fixup[range];
- code_seq = relax_info->relax_code_seq[range];
- seq_size = relax_info->relax_code_size[range];
- }
- else if (hint_type)
- {
- /* Load-store relax pattern. */
- table_ptr = relax_ls_table;
- while (table_ptr->main_type != 0)
- {
- if (table_ptr->main_type == hint_type)
- {
- fixup_info = table_ptr->relax_fixup;
- code_seq = table_ptr->relax_code_seq;
- seq_size = table_ptr->relax_code_size;
- break;
- }
- table_ptr++;
- }
- if (table_ptr->main_type == 0)
- return FALSE;
- }
- else
- return FALSE;
- hint_fixup = hint_info->relax_fixup;
- hint_code = hint_info->relax_code_seq;
- hint_info->relax_code_size = seq_size;
- while (fixup_info->size != 0)
- {
- if (fixup_info->ramp & NDS32_HINT)
- {
- memcpy (hint_fixup, fixup_info, sizeof (nds32_relax_fixup_info_t));
- hint_fixup++;
- }
- fixup_info++;
- }
- /* Clear final relocation. */
- memset (hint_fixup, 0, sizeof (nds32_relax_fixup_info_t));
- /* Copy code sequance. */
- memcpy (hint_code, code_seq, seq_size);
- return TRUE;
- }
- /* Because there are a lot of variant of load-store, check
- all these type here. */
- #define CLEAN_REG(insn) ((insn) & 0xff0003ff)
- static bfd_boolean
- nds32_match_hint_insn (struct nds32_opcode *opcode, uint32_t seq)
- {
- char *check_insn[] =
- { "bnes38", "beqs38", "bnez38", "bnezs8", "beqz38", "beqzs8" };
- uint32_t insn = opcode->value;
- unsigned int i;
- insn = CLEAN_REG (opcode->value);
- if (insn == seq)
- return TRUE;
- switch (seq)
- {
- case OP6 (LBI):
- /* In relocation_table, it regards instruction LBI as representation
- of all the NDS32_RELAX_HINT_LS pattern. */
- if (insn == OP6 (LBI) || insn == OP6 (SBI) || insn == OP6 (LBSI)
- || insn == OP6 (LHI) || insn == OP6 (SHI) || insn == OP6 (LHSI)
- || insn == OP6 (LWI) || insn == OP6 (SWI)
- || insn == OP6 (LWC) || insn == OP6 (SWC))
- return TRUE;
- break;
- case OP6 (BR2):
- /* This is for LONGCALL5 and LONGCALL6. */
- if (insn == OP6 (BR2))
- return TRUE;
- break;
- case OP6 (BR1):
- /* This is for LONGJUMP5 and LONGJUMP6. */
- if (opcode->isize == 4
- && (insn == OP6 (BR1) || insn == OP6 (BR2) || insn == OP6 (BR3)))
- return TRUE;
- else if (opcode->isize == 2)
- {
- for (i = 0; i < sizeof (check_insn) / sizeof (check_insn[0]); i++)
- if (strcmp (opcode->opcode, check_insn[i]) == 0)
- return TRUE;
- }
- break;
- case OP6 (MOVI):
- /* This is for LONGJUMP7. */
- if (opcode->isize == 2 && strcmp (opcode->opcode, "movi55") == 0)
- return TRUE;
- break;
- }
- return FALSE;
- }
- /* Append relax relocation for link time relaxing. */
- static void
- nds32_elf_append_relax_relocs (const char *key ATTRIBUTE_UNUSED, void *value)
- {
- struct nds32_relocs_pattern *relocs_pattern =
- (struct nds32_relocs_pattern *) value;
- struct nds32_relocs_pattern *pattern_temp, *pattern_now;
- symbolS *sym, *hi_sym = NULL;
- expressionS exp;
- fragS *fragP;
- segT seg_bak = now_seg;
- frchainS *frchain_bak = frchain_now;
- struct nds32_relax_hint_table hint_info;
- nds32_relax_fixup_info_t *hint_fixup, *fixup_now;
- size_t fixup_size;
- offsetT branch_offset;
- fixS *fixP;
- int range, offset;
- unsigned int ptr_offset, hint_count, relax_code_size, count = 0;
- uint32_t *code_seq, code_insn;
- char *where;
- int pcrel;
- if (!relocs_pattern)
- return;
- if (!nds32_find_reloc_table (relocs_pattern, &hint_info))
- return;
- /* Save symbol for some EMPTY relocation using. */
- pattern_now = relocs_pattern;
- while (pattern_now)
- {
- if (pattern_now->opcode->value == OP6 (SETHI))
- {
- hi_sym = pattern_now->sym;
- break;
- }
- pattern_now = pattern_now->next;
- }
- /* Inserting fix up must specify now_seg or frchain_now. */
- now_seg = relocs_pattern->seg;
- frchain_now = relocs_pattern->frchain;
- fragP = relocs_pattern->frag;
- branch_offset = fragP->fr_offset;
- hint_fixup = hint_info.relax_fixup;
- code_seq = hint_info.relax_code_seq;
- relax_code_size = hint_info.relax_code_size;
- pattern_now = relocs_pattern;
- /* Insert relaxation. */
- exp.X_op = O_symbol;
- while (pattern_now)
- {
- /* Choose the match fixup by instruction. */
- code_insn = CLEAN_REG (*(code_seq + count));
- if (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
- {
- count = 0;
- code_insn = CLEAN_REG (*(code_seq + count));
- while (!nds32_match_hint_insn (pattern_now->opcode, code_insn))
- {
- count++;
- if (count >= relax_code_size / 4)
- {
- as_bad (_("Internal error: Relax hint error. %s: %x"),
- now_seg->name, pattern_now->opcode->value);
- goto restore;
- }
- code_insn = CLEAN_REG (*(code_seq + count));
- }
- }
- fragP = pattern_now->frag;
- sym = pattern_now->sym;
- branch_offset = fragP->fr_offset;
- offset = count * 4;
- where = pattern_now->where;
- /* Find the instruction map fix. */
- fixup_now = hint_fixup;
- while (fixup_now->offset != offset)
- {
- fixup_now++;
- if (fixup_now->size == 0)
- break;
- }
- /* This element is without relaxation relocation. */
- if (fixup_now->size == 0)
- {
- pattern_now = pattern_now->next;
- continue;
- }
- fixup_size = fixup_now->size;
- /* Insert all fixup. */
- while (fixup_size != 0 && fixup_now->offset == offset)
- {
- /* Set the real instruction size in element. */
- fixup_size = pattern_now->opcode->isize;
- pcrel = ((fixup_now->ramp & NDS32_PCREL) != 0) ? 1 : 0;
- if (fixup_now->ramp & NDS32_FIX)
- {
- /* Convert original relocation. */
- pattern_now->fixP->fx_r_type = fixup_now->r_type ;
- fixup_size = 0;
- }
- else if ((fixup_now->ramp & NDS32_PTR) != 0)
- {
- /* This relocation has to point to another instruction. Make
- sure each resolved relocation has to be pointed. */
- pattern_temp = relocs_pattern;
- /* All instruction in relax_table should be 32-bit. */
- hint_count = hint_info.relax_code_size / 4;
- code_insn = CLEAN_REG (*(code_seq + hint_count - 1));
- while (pattern_temp)
- {
- /* Point to every resolved relocation. */
- if (nds32_match_hint_insn (pattern_temp->opcode, code_insn))
- {
- ptr_offset =
- pattern_temp->where - pattern_temp->frag->fr_literal;
- exp.X_add_symbol = symbol_temp_new (now_seg, ptr_offset,
- pattern_temp->frag);
- exp.X_add_number = 0;
- fixP =
- fix_new_exp (fragP, where - fragP->fr_literal,
- fixup_size, &exp, 0, fixup_now->r_type);
- fixP->fx_addnumber = fixP->fx_offset;
- }
- pattern_temp = pattern_temp->next;
- }
- fixup_size = 0;
- }
- else if (fixup_now->ramp & NDS32_ADDEND)
- {
- range = nds32_elf_sethi_range (relocs_pattern);
- if (range == NDS32_LOADSTORE_NONE)
- {
- as_bad (_("Internal error: Range error. %s"), now_seg->name);
- return;
- }
- exp.X_add_symbol = abs_section_sym;
- exp.X_add_number = SET_ADDEND (4, 0, optimize, enable_16bit);
- exp.X_add_number |= ((range & 0x3f) << 8);
- }
- else if ((fixup_now->ramp & NDS32_ABS) != 0)
- {
- /* This is a tag relocation. */
- exp.X_add_symbol = abs_section_sym;
- exp.X_add_number = 0;
- }
- else if ((fixup_now->ramp & NDS32_INSN16) != 0)
- {
- if (!enable_16bit)
- fixup_size = 0;
- /* This is a tag relocation. */
- exp.X_add_symbol = abs_section_sym;
- exp.X_add_number = 0;
- }
- else if ((fixup_now->ramp & NDS32_SYM) != 0)
- {
- /* For EMPTY relocation save the true symbol. */
- exp.X_add_symbol = hi_sym;
- exp.X_add_number = branch_offset;
- }
- else
- {
- exp.X_add_symbol = sym;
- exp.X_add_number = branch_offset;
- }
- if (fixup_size != 0)
- {
- fixP = fix_new_exp (fragP, where - fragP->fr_literal, fixup_size,
- &exp, pcrel, fixup_now->r_type);
- fixP->fx_addnumber = fixP->fx_offset;
- }
- fixup_now++;
- fixup_size = fixup_now->size;
- }
- if (count < relax_code_size / 4)
- count++;
- pattern_now = pattern_now->next;
- }
- restore:
- now_seg = seg_bak;
- frchain_now = frchain_bak;
- }
- /* Check instruction if it can be used for the baseline. */
- static bfd_boolean
- nds32_check_insn_available (struct nds32_asm_insn insn, char *str)
- {
- int attr = insn.attr & ATTR_ALL;
- static int baseline_isa = 0;
- /* No isa setting or all isa can use. */
- if (attr == 0 || attr == ATTR_ALL)
- return TRUE;
- if (baseline_isa == 0)
- {
- /* Map option baseline and instruction attribute. */
- switch (nds32_baseline)
- {
- case ISA_V2:
- baseline_isa = ATTR (ISA_V2);
- break;
- case ISA_V3:
- baseline_isa = ATTR (ISA_V3);
- break;
- case ISA_V3M:
- baseline_isa = ATTR (ISA_V3M);
- break;
- }
- }
- if ((baseline_isa & attr) == 0)
- {
- as_bad (_("Not support instrcution %s in the baseline."), str);
- return FALSE;
- }
- return TRUE;
- }
- /* Stub of machine dependent. */
- void
- md_assemble (char *str)
- {
- struct nds32_asm_insn insn;
- char *out;
- struct nds32_pseudo_opcode *popcode;
- const struct nds32_field *fld = NULL;
- fixS *fixP;
- uint16_t insn_16;
- struct nds32_relocs_pattern *relocs_temp;
- expressionS *pexp;
- fragS *fragP;
- int label = label_exist;
- popcode = nds32_lookup_pseudo_opcode (str);
- /* Note that we need to check 'verbatim' and
- 'opcode->physical_op'. If the assembly content is generated by
- compiler and this opcode is a physical instruction, there is no
- need to perform pseudo instruction expansion/transformation. */
- if (popcode && !(verbatim && popcode->physical_op))
- {
- pseudo_opcode = TRUE;
- nds32_pseudo_opcode_wrapper (str, popcode);
- pseudo_opcode = FALSE;
- nds32_elf_append_relax_relocs (NULL, relocs_list);
- /* Free pseudo list. */
- relocs_temp = relocs_list;
- while (relocs_temp)
- {
- relocs_list = relocs_list->next;
- free (relocs_temp);
- relocs_temp = relocs_list;
- }
- return;
- }
- label_exist = 0;
- insn.info = (expressionS *) alloca (sizeof (expressionS));
- asm_desc.result = NASM_OK;
- nds32_assemble (&asm_desc, &insn, str);
- switch (asm_desc.result)
- {
- case NASM_ERR_UNKNOWN_OP:
- as_bad (_("Unrecognized opcode, %s."), str);
- return;
- case NASM_ERR_SYNTAX:
- as_bad (_("Incorrect syntax, %s."), str);
- return;
- case NASM_ERR_OPERAND:
- as_bad (_("Unrecognized operand/register, %s."), str);
- return;
- case NASM_ERR_OUT_OF_RANGE:
- as_bad (_("Operand out of range, %s."), str);
- return;
- case NASM_ERR_REG_REDUCED:
- as_bad (_("Prohibited register used for reduced-register, %s."), str);
- return;
- case NASM_ERR_JUNK_EOL:
- as_bad (_("Junk at end of line, %s."), str);
- return;
- }
- gas_assert (insn.opcode);
- nds32_set_elf_flags_by_insn (&insn);
- gas_assert (insn.opcode->isize == 4 || insn.opcode->isize == 2);
- if (!nds32_check_insn_available (insn, str))
- return;
- /* Make sure the begining of text being 2-byte align. */
- nds32_adjust_label (1);
- fld = insn.field;
- /* Try to allocate the max size to guarantee relaxable same branch
- instructions in the same fragment. */
- frag_grow (NDS32_MAXCHAR);
- fragP = frag_now;
- if (fld && (insn.attr & NASM_ATTR_BRANCH)
- && (pseudo_opcode || (insn.opcode->value != INSN_JAL
- && insn.opcode->value != INSN_J))
- && (!verbatim || pseudo_opcode))
- {
- /* User assembly code branch relax for it. */
- /* If fld is not NULL, it is a symbol. */
- /* Branch msut relax to proper pattern in user assembly code exclude
- J and JAL. Keep these two in original type for users which wants
- to keep their size be fixed. In general, assembler does not convert
- instruction generated by compiler. But jump instruction may be
- truncated in text virtual model. For workaround, compiler generate
- pseudo jump to fix this issue currently. */
- /* Get branch range type. */
- dwarf2_emit_insn (0);
- enum nds32_br_range range_type;
- pexp = insn.info;
- range_type = get_range_type (fld);
- out = frag_var (rs_machine_dependent, NDS32_MAXCHAR,
- 0, /* VAR is un-used. */
- range_type, /* SUBTYPE is used as range type. */
- pexp->X_add_symbol, pexp->X_add_number, 0);
- fragP->fr_fix += insn.opcode->isize;
- fragP->tc_frag_data.opcode = insn.opcode;
- fragP->tc_frag_data.insn = insn.insn;
- if (insn.opcode->isize == 4)
- bfd_putb32 (insn.insn, out);
- else if (insn.opcode->isize == 2)
- bfd_putb16 (insn.insn, out);
- fragP->tc_frag_data.flag |= NDS32_FRAG_BRANCH;
- return;
- /* md_convert_frag will insert relocations. */
- }
- else if (!relaxing && enable_16bit && (optimize || optimize_for_space)
- && ((!fld && !verbatim && insn.opcode->isize == 4
- && nds32_convert_32_to_16 (stdoutput, insn.insn, &insn_16, NULL))
- || (insn.opcode->isize == 2
- && nds32_convert_16_to_32 (stdoutput, insn.insn, NULL))))
- {
- /* Record this one is relaxable. */
- pexp = insn.info;
- dwarf2_emit_insn (0);
- if (fld)
- {
- out = frag_var (rs_machine_dependent,
- 4, /* Max size is 32-bit instruction. */
- 0, /* VAR is un-used. */
- 0, pexp->X_add_symbol, pexp->X_add_number, 0);
- fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE_BRANCH;
- }
- else
- out = frag_var (rs_machine_dependent,
- 4, /* Max size is 32-bit instruction. */
- 0, /* VAR is un-used. */
- 0, NULL, 0, NULL);
- fragP->tc_frag_data.flag |= NDS32_FRAG_RELAXABLE;
- fragP->tc_frag_data.opcode = insn.opcode;
- fragP->tc_frag_data.insn = insn.insn;
- fragP->fr_fix += 2;
- /* In original, we don't relax the instrucion with label on it,
- but this may cause some redundant nop16. Therefore, tag this
- relaxable instruction and relax it carefully. */
- if (label)
- fragP->tc_frag_data.flag |= NDS32_FRAG_LABEL;
- if (insn.opcode->isize == 4)
- bfd_putb16 (insn_16, out);
- else if (insn.opcode->isize == 2)
- bfd_putb16 (insn.insn, out);
- return;
- }
- else if ((verbatim || !relaxing) && optimize && label)
- {
- /* This instruction is with label. */
- expressionS exp;
- out = frag_var (rs_machine_dependent, insn.opcode->isize,
- 0, 0, NULL, 0, NULL);
- /* If this insturction is branch target, it is not relaxable. */
- fragP->tc_frag_data.flag = NDS32_FRAG_LABEL;
- fragP->tc_frag_data.opcode = insn.opcode;
- fragP->tc_frag_data.insn = insn.insn;
- fragP->fr_fix += insn.opcode->isize;
- if (insn.opcode->isize == 4)
- {
- exp.X_op = O_symbol;
- exp.X_add_symbol = abs_section_sym;
- exp.X_add_number = 0;
- fixP = fix_new_exp (fragP, fragP->fr_fix - 4, 0, &exp,
- 0, BFD_RELOC_NDS32_LABEL);
- if (!verbatim)
- fragP->tc_frag_data.flag = NDS32_FRAG_ALIGN;
- }
- }
- else
- out = frag_more (insn.opcode->isize);
- if (insn.opcode->isize == 4)
- bfd_putb32 (insn.insn, out);
- if (insn.opcode->isize == 2)
- bfd_putb16 (insn.insn, out);
- dwarf2_emit_insn (insn.opcode->isize);
- /* Compiler generating code and user assembly pseudo load-store, insert
- fixup here. */
- pexp = insn.info;
- fixP = nds32_elf_record_fixup_exp (fragP, str, fld, pexp, out, &insn);
- /* Build relaxation pattern when relaxing is enable. */
- if (relaxing)
- nds32_elf_build_relax_relation (fixP, pexp, out, insn.opcode, fragP, fld);
- }
- /* md_macro_start */
- void
- nds32_macro_start (void)
- {
- }
- /* md_macro_info */
- void
- nds32_macro_info (void *info ATTRIBUTE_UNUSED)
- {
- }
- /* md_macro_end */
- void
- nds32_macro_end (void)
- {
- }
- /* GAS will call this function with one argument, an expressionS pointer, for
- any expression that can not be recognized. When the function is called,
- input_line_pointer will point to the start of the expression. */
- void
- md_operand (expressionS *expressionP)
- {
- if (*input_line_pointer == '#')
- {
- input_line_pointer++;
- expression (expressionP);
- }
- }
- /* GAS will call this function for each section at the end of the assembly, to
- permit the CPU back end to adjust the alignment of a section. The function
- must take two arguments, a segT for the section and a valueT for the size of
- the section, and return a valueT for the rounded size. */
- valueT
- md_section_align (segT segment, valueT size)
- {
- int align = bfd_get_section_alignment (stdoutput, segment);
- return ((size + (1 << align) - 1) & (-1 << align));
- }
- /* GAS will call this function when a symbol table lookup fails, before it
- creates a new symbol. Typically this would be used to supply symbols whose
- name or value changes dynamically, possibly in a context sensitive way.
- Predefined symbols with fixed values, such as register names or condition
- codes, are typically entered directly into the symbol table when md_begin
- is called. One argument is passed, a char * for the symbol. */
- symbolS *
- md_undefined_symbol (char *name ATTRIBUTE_UNUSED)
- {
- return NULL;
- }
- static long
- nds32_calc_branch_offset (segT segment, fragS *fragP,
- long stretch ATTRIBUTE_UNUSED,
- relax_info_t *relax_info,
- enum nds32_br_range branch_range_type)
- {
- struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
- symbolS *branch_symbol = fragP->fr_symbol;
- offsetT branch_offset = fragP->fr_offset;
- offsetT branch_target_address;
- offsetT branch_insn_address;
- long offset = 0;
- if ((S_GET_SEGMENT (branch_symbol) != segment)
- || S_IS_WEAK (branch_symbol))
- {
- /* The symbol is not in the SEGMENT. It could be far far away. */
- offset = 0x80000000;
- }
- else
- {
- /* Calculate symbol-to-instruction offset. */
- branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
- /* If the destination symbol is beyond current frag address,
- STRETCH will take effect to symbol's position. */
- if (S_GET_VALUE (branch_symbol) > fragP->fr_address)
- branch_target_address += stretch;
- branch_insn_address = fragP->fr_address + fragP->fr_fix;
- branch_insn_address -= opcode->isize;
- /* Update BRANCH_INSN_ADDRESS to relaxed position. */
- branch_insn_address += (relax_info->relax_code_size[branch_range_type]
- - relax_info->relax_branch_isize[branch_range_type]);
- offset = branch_target_address - branch_insn_address;
- }
- return offset;
- }
- static enum nds32_br_range
- nds32_convert_to_range_type (long offset)
- {
- enum nds32_br_range range_type;
- if (-(0x100) <= offset && offset < 0x100) /* 256 bytes */
- range_type = BR_RANGE_S256;
- else if (-(0x4000) <= offset && offset < 0x4000) /* 16K bytes */
- range_type = BR_RANGE_S16K;
- else if (-(0x10000) <= offset && offset < 0x10000) /* 64K bytes */
- range_type = BR_RANGE_S64K;
- else if (-(0x1000000) <= offset && offset < 0x1000000) /* 16M bytes */
- range_type = BR_RANGE_S16M;
- else /* 4G bytes */
- range_type = BR_RANGE_U4G;
- return range_type;
- }
- /* Set insntruction register mask. */
- static void
- nds32_elf_get_set_cond (relax_info_t *relax_info, int offset, uint32_t *insn,
- uint32_t ori_insn, int range)
- {
- nds32_cond_field_t *cond_fields = relax_info->cond_field;
- nds32_cond_field_t *code_seq_cond = relax_info->relax_code_condition[range];
- uint32_t mask;
- int i = 0;
- /* The instruction has conditions. Collect condition values. */
- while (code_seq_cond[i].bitmask != 0)
- {
- if (offset == code_seq_cond[i].offset)
- {
- mask = (ori_insn >> cond_fields[i].bitpos) & cond_fields[i].bitmask;
- /* Sign extend. */
- if (cond_fields[i].signed_extend)
- mask = (mask ^ ((cond_fields[i].bitmask + 1) >> 1)) -
- ((cond_fields[i].bitmask + 1) >> 1);
- *insn |= (mask & code_seq_cond[i].bitmask) << code_seq_cond[i].bitpos;
- }
- i++;
- }
- }
- static int
- nds32_relax_branch_instructions (segT segment, fragS *fragP,
- long stretch ATTRIBUTE_UNUSED,
- int init)
- {
- enum nds32_br_range branch_range_type;
- struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
- long offset = 0;
- enum nds32_br_range real_range_type;
- int adjust = 0;
- relax_info_t *relax_info;
- int diff = 0;
- int i, j, k;
- int code_seq_size;
- uint32_t *code_seq;
- uint32_t insn;
- int insn_size;
- int code_seq_offset;
- /* Replace with gas_assert (fragP->fr_symbol != NULL); */
- if (fragP->fr_symbol == NULL)
- return adjust;
- /* If frag_var is not enough room, the previos frag is fr_full and with
- opcode. The new one is rs_dependent but without opcode. */
- if (opcode == NULL)
- return adjust;
- relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
- if (relax_info == NULL)
- return adjust;
- if (init)
- branch_range_type = relax_info->br_range;
- else
- branch_range_type = fragP->fr_subtype;
- offset = nds32_calc_branch_offset (segment, fragP, stretch,
- relax_info, branch_range_type);
- real_range_type = nds32_convert_to_range_type (offset);
- /* If actual range is equal to instruction jump range, do nothing. */
- if (real_range_type == branch_range_type)
- return adjust;
- /* Find out proper relaxation code sequence. */
- for (i = BR_RANGE_S256; i < BR_RANGE_NUM; i++)
- {
- if (real_range_type <= (unsigned int) i)
- {
- if (init)
- diff = relax_info->relax_code_size[i] - opcode->isize;
- else
- diff = relax_info->relax_code_size[i]
- - relax_info->relax_code_size[branch_range_type];
- /* If the instruction could be converted to 16-bits,
- minus the difference. */
- code_seq_offset = 0;
- j = 0;
- k = 0;
- code_seq_size = relax_info->relax_code_size[i];
- code_seq = relax_info->relax_code_seq[i];
- while (code_seq_offset < code_seq_size)
- {
- insn = code_seq[j];
- if (insn & 0x80000000) /* 16-bits instruction. */
- {
- insn_size = 2;
- }
- else /* 32-bits instruction. */
- {
- insn_size = 4;
- while (relax_info->relax_fixup[i][k].size !=0
- && relax_info->relax_fixup[i][k].offset < code_seq_offset)
- k++;
- }
- code_seq_offset += insn_size;
- j++;
- }
- /* Update fr_subtype to new NDS32_BR_RANGE. */
- fragP->fr_subtype = i;
- break;
- }
- }
- return diff + adjust;
- }
- /* Adjust relaxable frag till current frag. */
- static int
- nds32_adjust_relaxable_frag (fragS *startP, fragS *fragP)
- {
- int adj;
- if (startP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
- adj = -2;
- else
- adj = 2;
- startP->tc_frag_data.flag ^= NDS32_FRAG_RELAXED;
- while (startP)
- {
- startP = startP->fr_next;
- if (startP)
- {
- startP->fr_address += adj;
- if (startP == fragP)
- break;
- }
- }
- return adj;
- }
- static addressT
- nds32_get_align (addressT address, int align)
- {
- addressT mask, new_address;
- mask = ~((~0) << align);
- new_address = (address + mask) & (~mask);
- return (new_address - address);
- }
- /* Check the prev_frag is legal. */
- static void
- invalid_prev_frag (fragS * fragP, fragS **prev_frag)
- {
- addressT address;
- fragS *frag_start = *prev_frag;
- if (!frag_start)
- return;
- if (frag_start->last_fr_address >= fragP->last_fr_address)
- {
- *prev_frag = NULL;
- return;
- }
- fragS *frag_t = *prev_frag;
- while (frag_t != fragP)
- {
- if (frag_t->fr_type == rs_align
- || frag_t->fr_type == rs_align_code
- || frag_t->fr_type == rs_align_test)
- {
- /* Relax instruction can not walk across lable. */
- if (frag_t->tc_frag_data.flag & NDS32_FRAG_LABEL)
- {
- prev_frag = NULL;
- return;
- }
- /* Relax previos relaxable to align rs_align frag. */
- address = frag_t->fr_address + frag_t->fr_fix;
- addressT offset = nds32_get_align (address, (int) frag_t->fr_offset);
- if (offset & 0x2)
- {
- /* If there is label on the prev_frag, check if it is aligned. */
- if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
- || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
- & 0x2) == 0)
- nds32_adjust_relaxable_frag (*prev_frag, frag_t);
- }
- *prev_frag = NULL;
- return;
- }
- frag_t = frag_t->fr_next;
- }
- if (fragP->tc_frag_data.flag & NDS32_FRAG_ALIGN)
- {
- address = fragP->fr_address;
- addressT offset = nds32_get_align (address, 2);
- if (offset & 0x2)
- {
- /* If there is label on the prev_frag, check if it is aligned. */
- if (!((*prev_frag)->tc_frag_data.flag & NDS32_FRAG_LABEL)
- || (((*prev_frag)->fr_address + (*prev_frag)->fr_fix - 2 )
- & 0x2) == 0)
- nds32_adjust_relaxable_frag (*prev_frag, fragP);
- }
- *prev_frag = NULL;
- return;
- }
- }
- /* md_relax_frag */
- int
- nds32_relax_frag (segT segment, fragS *fragP, long stretch ATTRIBUTE_UNUSED)
- {
- /* Currently, there are two kinds of relaxation in nds32 assembler.
- 1. relax for branch
- 2. relax for 32-bits to 16-bits */
- static fragS *prev_frag = NULL;
- int adjust = 0;
- invalid_prev_frag (fragP, &prev_frag);
- if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
- adjust = nds32_relax_branch_instructions (segment, fragP, stretch, 0);
- if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
- prev_frag = NULL;
- if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE
- && (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED) == 0)
- /* Here is considered relaxed case originally. But it may cause
- unendless loop when relaxing. Once the instruction is relaxed,
- it can not be undo. */
- prev_frag = fragP;
- return adjust;
- }
- /* This function returns an initial guess of the length by which a fragment
- must grow to hold a branch to reach its destination. Also updates
- fr_type/fr_subtype as necessary.
- It is called just before doing relaxation. Any symbol that is now undefined
- will not become defined. The guess for fr_var is ACTUALLY the growth beyond
- fr_fix. Whatever we do to grow fr_fix or fr_var contributes to our returned
- value. Although it may not be explicit in the frag, pretend fr_var starts
- with a 0 value. */
- int
- md_estimate_size_before_relax (fragS *fragP, segT segment)
- {
- /* Currently, there are two kinds of relaxation in nds32 assembler.
- 1. relax for branch
- 2. relax for 32-bits to 16-bits */
- /* Save previos relaxable frag. */
- static fragS *prev_frag = NULL;
- int adjust = 0;
- invalid_prev_frag (fragP, &prev_frag);
- if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
- adjust = nds32_relax_branch_instructions (segment, fragP, 0, 1);
- if (fragP->tc_frag_data.flag & NDS32_FRAG_LABEL)
- prev_frag = NULL;
- if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
- adjust = 2;
- else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE)
- prev_frag = fragP;
- return adjust;
- }
- /* GAS will call this for each rs_machine_dependent fragment. The instruction
- is completed using the data from the relaxation pass. It may also create any
- necessary relocations.
- *FRAGP has been relaxed to its final size, and now needs to have the bytes
- inside it modified to conform to the new size. It is called after relaxation
- is finished.
- fragP->fr_type == rs_machine_dependent.
- fragP->fr_subtype is the subtype of what the address relaxed to. */
- void
- md_convert_frag (bfd *abfd ATTRIBUTE_UNUSED, segT sec, fragS *fragP)
- {
- /* Convert branch relaxation instructions. */
- symbolS *branch_symbol = fragP->fr_symbol;
- offsetT branch_offset = fragP->fr_offset;
- enum nds32_br_range branch_range_type = fragP->fr_subtype;
- struct nds32_opcode *opcode = fragP->tc_frag_data.opcode;
- uint32_t origin_insn = fragP->tc_frag_data.insn;
- relax_info_t *relax_info;
- char *fr_buffer;
- int fr_where;
- int addend ATTRIBUTE_UNUSED;
- offsetT branch_target_address, branch_insn_address;
- expressionS exp;
- fixS *fixP;
- uint32_t *code_seq;
- uint32_t insn;
- int code_size, insn_size, offset, fixup_size;
- int buf_offset, pcrel;
- int i, k;
- uint16_t insn_16;
- nds32_relax_fixup_info_t fixup_info[MAX_RELAX_FIX];
- /* Save the 1st instruction is converted to 16 bit or not. */
- unsigned int branch_size;
- /* Replace with gas_assert (branch_symbol != NULL); */
- if (branch_symbol == NULL && !(fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED))
- return;
- /* If frag_var is not enough room, the previos frag is fr_full and with
- opcode. The new one is rs_dependent but without opcode. */
- if (opcode == NULL)
- return;
- if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXABLE_BRANCH)
- {
- relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
- if (relax_info == NULL)
- return;
- i = BR_RANGE_S256;
- while (i < BR_RANGE_NUM
- && relax_info->relax_code_size[i]
- != (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED ? 4 : 2))
- i++;
- if (i >= BR_RANGE_NUM)
- as_bad ("Internal error: Cannot find relocation of"
- "relaxable branch.");
- exp.X_op = O_symbol;
- exp.X_add_symbol = branch_symbol;
- exp.X_add_number = branch_offset;
- pcrel = ((relax_info->relax_fixup[i][0].ramp & NDS32_PCREL) != 0) ? 1 : 0;
- fr_where = fragP->fr_fix - 2;
- fixP = fix_new_exp (fragP, fr_where, relax_info->relax_fixup[i][0].size,
- &exp, pcrel, relax_info->relax_fixup[i][0].r_type);
- fixP->fx_addnumber = fixP->fx_offset;
- if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
- {
- insn_16 = fragP->tc_frag_data.insn;
- nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
- fr_buffer = fragP->fr_literal + fr_where;
- fragP->fr_fix += 2;
- exp.X_op = O_symbol;
- exp.X_add_symbol = abs_section_sym;
- exp.X_add_number = 0;
- fix_new_exp (fragP, fr_where, 4,
- &exp, 0, BFD_RELOC_NDS32_INSN16);
- number_to_chars_bigendian (fr_buffer, insn, 4);
- }
- }
- else if (fragP->tc_frag_data.flag & NDS32_FRAG_RELAXED)
- {
- if (fragP->tc_frag_data.opcode->isize == 2)
- {
- insn_16 = fragP->tc_frag_data.insn;
- nds32_convert_16_to_32 (stdoutput, insn_16, &insn);
- }
- else
- insn = fragP->tc_frag_data.insn;
- fragP->fr_fix += 2;
- fr_where = fragP->fr_fix - 4;
- fr_buffer = fragP->fr_literal + fr_where;
- exp.X_op = O_symbol;
- exp.X_add_symbol = abs_section_sym;
- exp.X_add_number = 0;
- fix_new_exp (fragP, fr_where, 4, &exp, 0,
- BFD_RELOC_NDS32_INSN16);
- number_to_chars_bigendian (fr_buffer, insn, 4);
- }
- else if (fragP->tc_frag_data.flag & NDS32_FRAG_BRANCH)
- {
- /* Branch instruction adjust and append relocations. */
- relax_info = hash_find (nds32_relax_info_hash, opcode->opcode);
- if (relax_info == NULL)
- return;
- fr_where = fragP->fr_fix - opcode->isize;
- fr_buffer = fragP->fr_literal + fr_where;
- if ((S_GET_SEGMENT (branch_symbol) != sec)
- || S_IS_WEAK (branch_symbol))
- {
- if (fragP->fr_offset & 3)
- as_warn (_("Addend to unresolved symbol is not on word boundary."));
- addend = 0;
- }
- else
- {
- /* Calculate symbol-to-instruction offset. */
- branch_target_address = S_GET_VALUE (branch_symbol) + branch_offset;
- branch_insn_address = fragP->fr_address + fr_where;
- addend = (branch_target_address - branch_insn_address) >> 1;
- }
- code_size = relax_info->relax_code_size[branch_range_type];
- code_seq = relax_info->relax_code_seq[branch_range_type];
- memcpy (fixup_info, relax_info->relax_fixup[branch_range_type],
- sizeof (fixup_info));
- /* Fill in frag. */
- i = 0;
- k = 0;
- offset = 0; /* code_seq offset */
- buf_offset = 0; /* fr_buffer offset */
- while (offset < code_size)
- {
- insn = code_seq[i];
- if (insn & 0x80000000) /* 16-bits instruction. */
- {
- insn = (insn >> 16) & 0xFFFF;
- insn_size = 2;
- }
- else /* 32-bits instruction. */
- {
- insn_size = 4;
- }
- nds32_elf_get_set_cond (relax_info, offset, &insn,
- origin_insn, branch_range_type);
- /* Try to convert to 16-bits instruction. Currently, only the first
- insntruction in pattern can be converted. EX: bnez sethi ori jr,
- only bnez can be converted to 16 bit and ori can't. */
- while (fixup_info[k].size != 0
- && relax_info->relax_fixup[branch_range_type][k].offset < offset)
- k++;
- number_to_chars_bigendian (fr_buffer + buf_offset, insn, insn_size);
- buf_offset += insn_size;
- offset += insn_size;
- i++;
- }
- /* Set up fixup. */
- exp.X_op = O_symbol;
- for (i = 0; fixup_info[i].size != 0; i++)
- {
- fixup_size = fixup_info[i].size;
- pcrel = ((fixup_info[i].ramp & NDS32_PCREL) != 0) ? 1 : 0;
- if ((fixup_info[i].ramp & NDS32_CREATE_LABEL) != 0)
- {
- /* This is a reverse branch. */
- exp.X_add_symbol = symbol_temp_new (sec, 0, fragP->fr_next);
- exp.X_add_number = 0;
- }
- else if ((fixup_info[i].ramp & NDS32_PTR) != 0)
- {
- /* This relocation has to point to another instruction. */
- branch_size = fr_where + code_size - 4;
- exp.X_add_symbol = symbol_temp_new (sec, branch_size, fragP);
- exp.X_add_number = 0;
- }
- else if ((fixup_info[i].ramp & NDS32_ABS) != 0)
- {
- /* This is a tag relocation. */
- exp.X_add_symbol = abs_section_sym;
- exp.X_add_number = 0;
- }
- else if ((fixup_info[i].ramp & NDS32_INSN16) != 0)
- {
- if (!enable_16bit)
- continue;
- /* This is a tag relocation. */
- exp.X_add_symbol = abs_section_sym;
- exp.X_add_number = 0;
- }
- else
- {
- exp.X_add_symbol = branch_symbol;
- exp.X_add_number = branch_offset;
- }
- if (fixup_info[i].r_type != 0)
- {
- fixP = fix_new_exp (fragP, fr_where + fixup_info[i].offset,
- fixup_size, &exp, pcrel,
- fixup_info[i].r_type);
- fixP->fx_addnumber = fixP->fx_offset;
- }
- }
- fragP->fr_fix = fr_where + buf_offset;
- }
- }
- /* tc_frob_file_before_fix */
- void
- nds32_frob_file_before_fix (void)
- {
- }
- static bfd_boolean
- nds32_relaxable_section (asection *sec)
- {
- return ((sec->flags & SEC_DEBUGGING) == 0
- && strcmp (sec->name, ".eh_frame") != 0);
- }
- /* TC_FORCE_RELOCATION */
- int
- nds32_force_relocation (fixS * fix)
- {
- switch (fix->fx_r_type)
- {
- case BFD_RELOC_NDS32_INSN16:
- case BFD_RELOC_NDS32_LABEL:
- case BFD_RELOC_NDS32_LONGCALL1:
- case BFD_RELOC_NDS32_LONGCALL2:
- case BFD_RELOC_NDS32_LONGCALL3:
- case BFD_RELOC_NDS32_LONGJUMP1:
- case BFD_RELOC_NDS32_LONGJUMP2:
- case BFD_RELOC_NDS32_LONGJUMP3:
- case BFD_RELOC_NDS32_LOADSTORE:
- case BFD_RELOC_NDS32_9_FIXED:
- case BFD_RELOC_NDS32_15_FIXED:
- case BFD_RELOC_NDS32_17_FIXED:
- case BFD_RELOC_NDS32_25_FIXED:
- case BFD_RELOC_NDS32_9_PCREL:
- case BFD_RELOC_NDS32_15_PCREL:
- case BFD_RELOC_NDS32_17_PCREL:
- case BFD_RELOC_NDS32_WORD_9_PCREL:
- case BFD_RELOC_NDS32_10_UPCREL:
- case BFD_RELOC_NDS32_25_PCREL:
- case BFD_RELOC_NDS32_MINUEND:
- case BFD_RELOC_NDS32_SUBTRAHEND:
- return 1;
- case BFD_RELOC_8:
- case BFD_RELOC_16:
- case BFD_RELOC_32:
- case BFD_RELOC_NDS32_DIFF_ULEB128:
- /* Linker should handle difference between two symbol. */
- return fix->fx_subsy != NULL
- && nds32_relaxable_section (S_GET_SEGMENT (fix->fx_addsy));
- case BFD_RELOC_64:
- if (fix->fx_subsy)
- as_bad ("Double word for difference between two symbols "
- "is not supported across relaxation.");
- default:
- ;
- }
- if (generic_force_reloc (fix))
- return 1;
- return fix->fx_pcrel;
- }
- /* TC_VALIDATE_FIX_SUB */
- int
- nds32_validate_fix_sub (fixS *fix, segT add_symbol_segment)
- {
- segT sub_symbol_segment;
- /* This code is referred from Xtensa. Check their implementation for
- details. */
- /* Make sure both symbols are in the same segment, and that segment is
- "normal" and relaxable. */
- sub_symbol_segment = S_GET_SEGMENT (fix->fx_subsy);
- return (sub_symbol_segment == add_symbol_segment
- && add_symbol_segment != undefined_section);
- }
- void
- md_number_to_chars (char *buf, valueT val, int n)
- {
- if (target_big_endian)
- number_to_chars_bigendian (buf, val, n);
- else
- number_to_chars_littleendian (buf, val, n);
- }
- /* Equal to MAX_PRECISION in atof-ieee.c. */
- #define MAX_LITTLENUMS 6
- /* This function is called to convert an ASCII string into a floating point
- value in format used by the CPU. */
- char *
- md_atof (int type, char *litP, int *sizeP)
- {
- int i;
- int prec;
- LITTLENUM_TYPE words[MAX_LITTLENUMS];
- char *t;
- switch (type)
- {
- case 'f':
- case 'F':
- case 's':
- case 'S':
- prec = 2;
- break;
- case 'd':
- case 'D':
- case 'r':
- case 'R':
- prec = 4;
- break;
- default:
- *sizeP = 0;
- return _("Bad call to md_atof()");
- }
- t = atof_ieee (input_line_pointer, type, words);
- if (t)
- input_line_pointer = t;
- *sizeP = prec * sizeof (LITTLENUM_TYPE);
- if (target_big_endian)
- {
- for (i = 0; i < prec; i++)
- {
- md_number_to_chars (litP, (valueT) words[i],
- sizeof (LITTLENUM_TYPE));
- litP += sizeof (LITTLENUM_TYPE);
- }
- }
- else
- {
- for (i = prec - 1; i >= 0; i--)
- {
- md_number_to_chars (litP, (valueT) words[i],
- sizeof (LITTLENUM_TYPE));
- litP += sizeof (LITTLENUM_TYPE);
- }
- }
- return 0;
- }
- /* md_elf_section_change_hook */
- void
- nds32_elf_section_change_hook (void)
- {
- }
- /* md_cleanup */
- void
- nds32_cleanup (void)
- {
- }
- /* This function is used to scan leb128 subtraction expressions,
- and insert fixups for them.
- e.g., .leb128 .L1 - .L0
- These expressions are heavily used in debug information or
- exception tables. Because relaxation will change code size,
- we must resolve them in link time. */
- static void
- nds32_insert_leb128_fixes (bfd *abfd ATTRIBUTE_UNUSED,
- asection *sec, void *xxx ATTRIBUTE_UNUSED)
- {
- segment_info_type *seginfo = seg_info (sec);
- struct frag *fragP;
- subseg_set (sec, 0);
- for (fragP = seginfo->frchainP->frch_root;
- fragP; fragP = fragP->fr_next)
- {
- expressionS *exp;
- /* Only unsigned leb128 can be handle. */
- if (fragP->fr_type != rs_leb128 || fragP->fr_subtype != 0
- || fragP->fr_symbol == NULL)
- continue;
- exp = symbol_get_value_expression (fragP->fr_symbol);
- if (exp->X_op != O_subtract)
- continue;
- fix_new_exp (fragP, fragP->fr_fix, 0,
- exp, 0, BFD_RELOC_NDS32_DIFF_ULEB128);
- }
- }
- static void
- nds32_insert_relax_entry (bfd *abfd ATTRIBUTE_UNUSED, asection *sec,
- void *xxx ATTRIBUTE_UNUSED)
- {
- segment_info_type *seginfo;
- fragS *fragP;
- fixS *fixP;
- expressionS exp;
- fixS *fixp;
- seginfo = seg_info (sec);
- if (!seginfo || !symbol_rootP || !subseg_text_p (sec) || sec->size == 0)
- return;
- /* If there is no relocation and relax is disabled, it is not necessary to
- insert R_NDS32_RELAX_ENTRY for linker do EX9 or IFC optimization. */
- for (fixp = seginfo->fix_root; fixp; fixp = fixp->fx_next)
- if (!fixp->fx_done)
- break;
- if (!fixp && !enable_relax_ex9 && !verbatim)
- return;
- subseg_change (sec, 0);
- /* Set RELAX_ENTRY flags for linker. */
- fragP = seginfo->frchainP->frch_root;
- exp.X_op = O_symbol;
- exp.X_add_symbol = section_symbol (sec);
- exp.X_add_number = 0;
- if (!enable_relax_relocs)
- exp.X_add_number |= R_NDS32_RELAX_ENTRY_DISABLE_RELAX_FLAG;
- else
- {
- /* These flags are only enabled when global relax is enabled.
- Maybe we can check DISABLE_RELAX_FLAG at linke-time,
- so we set them anyway. */
- if (enable_relax_ex9)
- exp.X_add_number |= R_NDS32_RELAX_ENTRY_EX9_FLAG;
- if (enable_relax_ifc)
- exp.X_add_number |= R_NDS32_RELAX_ENTRY_IFC_FLAG;
- if (verbatim)
- exp.X_add_number |= R_NDS32_RELAX_ENTRY_VERBATIM_FLAG;
- }
- if (optimize)
- exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FLAG;
- if (optimize_for_space)
- exp.X_add_number |= R_NDS32_RELAX_ENTRY_OPTIMIZE_FOR_SPACE_FLAG;
- fixP = fix_new_exp (fragP, 0, 0, &exp, 0, BFD_RELOC_NDS32_RELAX_ENTRY);
- fixP->fx_no_overflow = 1;
- }
- /* Analysis relax hint and insert suitable relocation pattern. */
- static void
- nds32_elf_analysis_relax_hint (void)
- {
- hash_traverse (nds32_hint_hash, nds32_elf_append_relax_relocs);
- }
- static void
- nds32_elf_insert_final_frag (void)
- {
- struct frchain *frchainP;
- asection *s;
- fragS *fragP;
- if (!optimize)
- return;
- for (s = stdoutput->sections; s; s = s->next)
- {
- segment_info_type *seginfo = seg_info (s);
- if (!seginfo)
- continue;
- for (frchainP = seginfo->frchainP; frchainP != NULL;
- frchainP = frchainP->frch_next)
- {
- subseg_set (s, frchainP->frch_subseg);
- if (subseg_text_p (now_seg))
- {
- fragP = frag_now;
- frag_var (rs_machine_dependent, 2, /* Max size. */
- 0, /* VAR is un-used. */ 0, NULL, 0, NULL);
- fragP->tc_frag_data.flag |= NDS32_FRAG_FINAL;
- }
- }
- }
- }
- void
- md_end (void)
- {
- nds32_elf_insert_final_frag ();
- nds32_elf_analysis_relax_hint ();
- bfd_map_over_sections (stdoutput, nds32_insert_leb128_fixes, NULL);
- }
- /* Implement md_allow_local_subtract. */
- bfd_boolean
- nds32_allow_local_subtract (expressionS *expr_l ATTRIBUTE_UNUSED,
- expressionS *expr_r ATTRIBUTE_UNUSED,
- segT sec ATTRIBUTE_UNUSED)
- {
- /* Don't allow any subtraction, because relax may change the code. */
- return FALSE;
- }
- /* Sort relocation by address.
- We didn't use qsort () in stdlib, because quick-sort is not a stable
- sorting algorithm. Relocations at the same address (r_offset) must keep
- their relative order. For example, RELAX_ENTRY must be the very first
- relocation entry.
- Currently, this function implements insertion-sort. */
- static int
- compar_relent (const void *lhs, const void *rhs)
- {
- const arelent **l = (const arelent **) lhs;
- const arelent **r = (const arelent **) rhs;
- if ((*l)->address > (*r)->address)
- return 1;
- else if ((*l)->address == (*r)->address)
- return 0;
- else
- return -1;
- }
- /* SET_SECTION_RELOCS ()
- Although this macro is originally used to set a relocation for each section,
- we use it to sort relocations in the same section by the address of the
- relocation. */
- void
- nds32_set_section_relocs (asection *sec, arelent ** relocs ATTRIBUTE_UNUSED,
- unsigned int n ATTRIBUTE_UNUSED)
- {
- bfd *abfd ATTRIBUTE_UNUSED = sec->owner;
- if (bfd_get_section_flags (abfd, sec) & (flagword) SEC_RELOC)
- nds32_insertion_sort (sec->orelocation, sec->reloc_count,
- sizeof (arelent**), compar_relent);
- }
- long
- nds32_pcrel_from_section (fixS *fixP, segT sec ATTRIBUTE_UNUSED)
- {
- if (fixP->fx_addsy == NULL || !S_IS_DEFINED (fixP->fx_addsy)
- || S_IS_EXTERNAL (fixP->fx_addsy) || S_IS_WEAK (fixP->fx_addsy))
- {
- /* Let linker resolve undefined symbols. */
- return 0;
- }
- return fixP->fx_frag->fr_address + fixP->fx_where;
- }
- /* md_post_relax_hook ()
- Insert relax entry relocation into sections. */
- void
- nds32_post_relax_hook (void)
- {
- bfd_map_over_sections (stdoutput, nds32_insert_relax_entry, NULL);
- }
- /* tc_fix_adjustable ()
- Return whether this symbol (fixup) can be replaced with
- section symbols. */
- bfd_boolean
- nds32_fix_adjustable (fixS *fixP)
- {
- switch (fixP->fx_r_type)
- {
- case BFD_RELOC_NDS32_WORD_9_PCREL:
- case BFD_RELOC_NDS32_9_PCREL:
- case BFD_RELOC_NDS32_15_PCREL:
- case BFD_RELOC_NDS32_17_PCREL:
- case BFD_RELOC_NDS32_25_PCREL:
- case BFD_RELOC_NDS32_HI20:
- case BFD_RELOC_NDS32_LO12S0:
- case BFD_RELOC_8:
- case BFD_RELOC_16:
- case BFD_RELOC_32:
- case BFD_RELOC_NDS32_PTR:
- case BFD_RELOC_NDS32_LONGCALL4:
- case BFD_RELOC_NDS32_LONGCALL5:
- case BFD_RELOC_NDS32_LONGCALL6:
- case BFD_RELOC_NDS32_LONGJUMP4:
- case BFD_RELOC_NDS32_LONGJUMP5:
- case BFD_RELOC_NDS32_LONGJUMP6:
- case BFD_RELOC_NDS32_LONGJUMP7:
- return 1;
- default:
- return 0;
- }
- }
- /* elf_tc_final_processing */
- void
- elf_nds32_final_processing (void)
- {
- /* An FPU_COM instruction is found without previous non-FPU_COM
- instruction. */
- if (nds32_fpu_com
- && !(nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST)))
- {
- /* Since only FPU_COM instructions are used and no other FPU instructions
- are used. The nds32_elf_flags will be decided by the enabled options
- by command line or default configuration. */
- if (nds32_fpu_dp_ext || nds32_fpu_sp_ext)
- {
- nds32_elf_flags |= nds32_fpu_dp_ext ? E_NDS32_HAS_FPU_DP_INST : 0;
- nds32_elf_flags |= nds32_fpu_sp_ext ? E_NDS32_HAS_FPU_INST : 0;
- }
- else
- {
- /* Should never here. */
- as_bad (_("Used FPU instructions requires enabling FPU extension"));
- }
- }
- if (nds32_elf_flags & (E_NDS32_HAS_FPU_INST | E_NDS32_HAS_FPU_DP_INST))
- {
- /* Single/double FPU has been used, set FPU register config. */
- /* We did not check the actual number of register used. We may
- want to do it while assemble. */
- nds32_elf_flags &= ~E_NDS32_FPU_REG_CONF;
- nds32_elf_flags |= (nds32_freg << E_NDS32_FPU_REG_CONF_SHIFT);
- }
- if (nds32_pic)
- nds32_elf_flags |= E_NDS32_HAS_PIC;
- if (nds32_gpr16)
- nds32_elf_flags |= E_NDS32_HAS_REDUCED_REGS;
- nds32_elf_flags |= (E_NDS32_ELF_VER_1_4 | nds32_abi);
- elf_elfheader (stdoutput)->e_flags |= nds32_elf_flags;
- }
- /* Implement md_apply_fix. Apply the fix-up or tranform the fix-up for
- later relocation generation. */
- void
- nds32_apply_fix (fixS *fixP, valueT *valP, segT seg ATTRIBUTE_UNUSED)
- {
- char *where = fixP->fx_frag->fr_literal + fixP->fx_where;
- bfd_vma value = *valP;
- if (fixP->fx_r_type < BFD_RELOC_UNUSED
- && fixP->fx_r_type > BFD_RELOC_NONE
- && fixP->fx_r_type != BFD_RELOC_NDS32_DIFF_ULEB128)
- {
- /* In our old nds32 binutils, it must convert relocations which is
- generated by CGEN. However, it does not have to consider this anymore.
- In current, it only deal with data relocations which enum
- is smaller than BFD_RELOC_NONE and BFD_RELOC_NDS32_DIFF_ULEB128.
- It is believed that we can construct a better mechanism to
- deal with the whole relocation issue in nds32 target
- without using CGEN. */
- fixP->fx_addnumber = value;
- fixP->tc_fix_data = NULL;
- /* Tranform specific relocations here for later relocation generation.
- Tag data here for ex9 relaxtion and tag tls data for linker. */
- switch (fixP->fx_r_type)
- {
- case BFD_RELOC_NDS32_DATA:
- if (!enable_relax_ex9)
- fixP->fx_done = 1;
- break;
- case BFD_RELOC_NDS32_TPOFF:
- case BFD_RELOC_NDS32_TLS_LE_HI20:
- case BFD_RELOC_NDS32_TLS_LE_LO12:
- case BFD_RELOC_NDS32_TLS_LE_ADD:
- case BFD_RELOC_NDS32_TLS_LE_LS:
- case BFD_RELOC_NDS32_GOTTPOFF:
- case BFD_RELOC_NDS32_TLS_IE_HI20:
- case BFD_RELOC_NDS32_TLS_IE_LO12S2:
- S_SET_THREAD_LOCAL (fixP->fx_addsy);
- break;
- default:
- break;
- }
- return;
- }
- if (fixP->fx_addsy == (symbolS *) NULL)
- fixP->fx_done = 1;
- if (fixP->fx_subsy != (symbolS *) NULL)
- {
- /* HOW DIFF RELOCATION WORKS.
- First of all, this relocation is used to calculate the distance
- between two symbols in the SAME section. It is used for jump-
- table, debug information, exception table, et al. Therefore,
- it is a unsigned positive value. It is NOT used for general-
- purpose arithmetic.
- Consider this example, the distance between .LEND and .LBEGIN
- is stored at the address of foo.
- ---- >8 ---- >8 ---- >8 ---- >8 ----
- .data
- foo:
- .word .LBEGIN - .LEND
- .text
- [before]
- .LBEGIN
- \
- [between] distance
- /
- .LEND
- [after]
- ---- 8< ---- 8< ---- 8< ---- 8< ----
- We use a single relocation entry for this expression.
- * The initial distance value is stored direcly in that location
- specified by r_offset (i.e., foo in this example.)
- * The begin of the region, i.e., .LBEGIN, is specified by
- r_info/R_SYM and r_addend, e.g., .text + 0x32.
- * The end of region, i.e., .LEND, is represented by
- .LBEGIN + distance instead of .LEND, so we only need
- a single relocation entry instead of two.
- When an instruction is relaxed, we adjust the relocation entry
- depending on where the instruction locates. There are three
- cases, before, after and between the region.
- * between: Distance value is read from r_offset, adjusted and
- written back into r_offset.
- * before: Only r_addend is adjust.
- * after: We don't care about it.
- Hereby, there are some limitation.
- `(.LEND - 1) - .LBEGIN' and `(.LEND - .LBEGIN) - 1'
- are semantically different, and we cannot handle latter case
- when relaxation.
- The latter expression means subtracting 1 from the distance
- between .LEND and .LBEGIN. And the former expression means
- the distance between (.LEND - 1) and .LBEGIN.
- The nuance affects whether to adjust distance value when relax
- an instruction. In another words, whether the instruction
- locates in the region. Because we use a single relocation entry,
- there is no field left for .LEND and the subtrahend.
- Since GCC-4.5, GCC may produce debug information in such expression
- .long .L1-1-.L0
- in order to describe register clobbering during an function-call.
- .L0:
- call foo
- .L1:
- Check http://gcc.gnu.org/ml/gcc-patches/2009-06/msg01317.html
- for details. */
- value -= S_GET_VALUE (fixP->fx_subsy);
- *valP = value;
- fixP->fx_subsy = NULL;
- fixP->fx_offset -= value;
- switch (fixP->fx_r_type)
- {
- case BFD_RELOC_8:
- fixP->fx_r_type = BFD_RELOC_NDS32_DIFF8;
- md_number_to_chars (where, value, 1);
- break;
- case BFD_RELOC_16:
- fixP->fx_r_type = BFD_RELOC_NDS32_DIFF16;
- md_number_to_chars (where, value, 2);
- break;
- case BFD_RELOC_32:
- fixP->fx_r_type = BFD_RELOC_NDS32_DIFF32;
- md_number_to_chars (where, value, 4);
- break;
- case BFD_RELOC_NDS32_DIFF_ULEB128:
- /* cvt_frag_to_fill () has called output_leb128 () for us. */
- break;
- default:
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("expression too complex"));
- return;
- }
- }
- else if (fixP->fx_done)
- {
- /* We're finished with this fixup. Install it because
- bfd_install_relocation won't be called to do it. */
- switch (fixP->fx_r_type)
- {
- case BFD_RELOC_8:
- md_number_to_chars (where, value, 1);
- break;
- case BFD_RELOC_16:
- md_number_to_chars (where, value, 2);
- break;
- case BFD_RELOC_32:
- md_number_to_chars (where, value, 4);
- break;
- case BFD_RELOC_64:
- md_number_to_chars (where, value, 8);
- default:
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("Internal error: Unknown fixup type %d (`%s')"),
- fixP->fx_r_type,
- bfd_get_reloc_code_name (fixP->fx_r_type));
- break;
- }
- }
- }
- /* Implement tc_gen_reloc. Generate ELF relocation for a fix-up. */
- arelent *
- tc_gen_reloc (asection *section ATTRIBUTE_UNUSED, fixS *fixP)
- {
- arelent *reloc;
- bfd_reloc_code_real_type code;
- reloc = (arelent *) xmalloc (sizeof (arelent));
- reloc->sym_ptr_ptr = (asymbol **) xmalloc (sizeof (asymbol *));
- *reloc->sym_ptr_ptr = symbol_get_bfdsym (fixP->fx_addsy);
- reloc->address = fixP->fx_frag->fr_address + fixP->fx_where;
- code = fixP->fx_r_type;
- reloc->howto = bfd_reloc_type_lookup (stdoutput, code);
- if (reloc->howto == (reloc_howto_type *) NULL)
- {
- as_bad_where (fixP->fx_file, fixP->fx_line,
- _("internal error: can't export reloc type %d (`%s')"),
- fixP->fx_r_type, bfd_get_reloc_code_name (code));
- return NULL;
- }
- /* Add relocation handling here. */
- switch (fixP->fx_r_type)
- {
- default:
- /* In general, addend of a relocation is the offset to the
- associated symbol. */
- reloc->addend = fixP->fx_offset;
- break;
- case BFD_RELOC_NDS32_DATA:
- /* Prevent linker from optimizing data in text sections.
- For example, jump table. */
- reloc->addend = fixP->fx_size;
- break;
- }
- return reloc;
- }
- struct suffix_name suffix_table[] =
- {
- {"GOTOFF", BFD_RELOC_NDS32_GOTOFF, 1},
- {"GOT", BFD_RELOC_NDS32_GOT20, 1},
- {"TPOFF", BFD_RELOC_NDS32_TPOFF, 0},
- {"PLT", BFD_RELOC_NDS32_25_PLTREL, 1},
- {"GOTTPOFF", BFD_RELOC_NDS32_GOTTPOFF, 0}
- };
- /* Implement md_parse_name. */
- int
- nds32_parse_name (char const *name, expressionS *exprP,
- enum expr_mode mode ATTRIBUTE_UNUSED,
- char *nextcharP ATTRIBUTE_UNUSED)
- {
- segT segment;
- exprP->X_op_symbol = NULL;
- exprP->X_md = BFD_RELOC_UNUSED;
- exprP->X_add_symbol = symbol_find_or_make (name);
- exprP->X_op = O_symbol;
- exprP->X_add_number = 0;
- /* Check the specail name if a symbol. */
- segment = S_GET_SEGMENT (exprP->X_add_symbol);
- if (segment != undefined_section)
- return 0;
- if (strcmp (name, GOT_NAME) == 0 && *nextcharP != '@')
- {
- /* Set for _GOT_OFFSET_TABLE_. */
- exprP->X_md = BFD_RELOC_NDS32_GOTPC20;
- }
- else if (*nextcharP == '@')
- {
- size_t i;
- char *next;
- for (i = 0; i < ARRAY_SIZE (suffix_table); i++)
- {
- next = input_line_pointer + 1 + strlen(suffix_table[i].suffix);
- if (strncasecmp (input_line_pointer + 1, suffix_table[i].suffix,
- strlen (suffix_table[i].suffix)) == 0
- && !is_part_of_name (*next))
- {
- if (!nds32_pic && suffix_table[i].pic)
- as_bad (_("need PIC qualifier with symbol."));
- exprP->X_md = suffix_table[i].reloc;
- *input_line_pointer = *nextcharP;
- input_line_pointer = next;
- *nextcharP = *input_line_pointer;
- *input_line_pointer = '\0';
- break;
- }
- }
- }
- return 1;
- }
- /* Implement tc_regname_to_dw2regnum. */
- int
- tc_nds32_regname_to_dw2regnum (char *regname)
- {
- struct nds32_keyword *sym = hash_find (nds32_gprs_hash, regname);
- if (!sym)
- return -1;
- return sym->value;
- }
- void
- tc_nds32_frame_initial_instructions (void)
- {
- /* CIE */
- /* Default cfa is register-31/sp. */
- cfi_add_CFA_def_cfa (31, 0);
- }
|