12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368936993709371937293739374937593769377937893799380938193829383938493859386938793889389939093919392939393949395939693979398939994009401940294039404940594069407940894099410941194129413941494159416941794189419942094219422942394249425942694279428942994309431943294339434943594369437943894399440944194429443944494459446944794489449945094519452945394549455945694579458945994609461946294639464946594669467946894699470947194729473947494759476947794789479948094819482948394849485948694879488948994909491949294939494949594969497949894999500950195029503950495059506950795089509951095119512951395149515951695179518951995209521952295239524952595269527952895299530953195329533953495359536953795389539954095419542954395449545954695479548954995509551955295539554955595569557955895599560956195629563956495659566956795689569957095719572957395749575957695779578957995809581958295839584958595869587958895899590959195929593959495959596959795989599960096019602960396049605960696079608960996109611961296139614961596169617961896199620962196229623962496259626962796289629963096319632963396349635963696379638963996409641964296439644964596469647964896499650965196529653965496559656965796589659966096619662966396649665966696679668966996709671967296739674967596769677967896799680968196829683968496859686968796889689969096919692969396949695969696979698969997009701970297039704970597069707970897099710971197129713971497159716971797189719972097219722972397249725972697279728972997309731973297339734973597369737973897399740974197429743974497459746974797489749975097519752975397549755975697579758975997609761976297639764976597669767976897699770977197729773977497759776977797789779978097819782978397849785978697879788978997909791979297939794979597969797979897999800980198029803980498059806980798089809981098119812981398149815981698179818981998209821982298239824982598269827982898299830983198329833983498359836983798389839984098419842984398449845984698479848984998509851985298539854985598569857985898599860986198629863986498659866986798689869987098719872987398749875987698779878987998809881988298839884988598869887988898899890989198929893989498959896989798989899990099019902990399049905990699079908990999109911991299139914991599169917991899199920992199229923992499259926992799289929993099319932993399349935993699379938993999409941994299439944994599469947994899499950995199529953995499559956995799589959996099619962996399649965996699679968996999709971997299739974997599769977997899799980998199829983998499859986998799889989999099919992999399949995999699979998999910000100011000210003100041000510006100071000810009100101001110012100131001410015100161001710018100191002010021100221002310024100251002610027100281002910030100311003210033100341003510036100371003810039100401004110042100431004410045100461004710048100491005010051100521005310054100551005610057100581005910060100611006210063100641006510066100671006810069100701007110072100731007410075100761007710078100791008010081100821008310084100851008610087100881008910090100911009210093100941009510096100971009810099101001010110102101031010410105101061010710108101091011010111101121011310114101151011610117101181011910120101211012210123101241012510126101271012810129101301013110132101331013410135101361013710138101391014010141101421014310144101451014610147101481014910150101511015210153101541015510156101571015810159101601016110162101631016410165101661016710168101691017010171101721017310174101751017610177101781017910180101811018210183101841018510186101871018810189101901019110192101931019410195101961019710198101991020010201102021020310204102051020610207102081020910210102111021210213102141021510216102171021810219102201022110222102231022410225102261022710228102291023010231102321023310234102351023610237102381023910240102411024210243102441024510246102471024810249102501025110252102531025410255102561025710258102591026010261102621026310264102651026610267102681026910270102711027210273102741027510276102771027810279102801028110282102831028410285102861028710288102891029010291102921029310294102951029610297102981029910300103011030210303103041030510306103071030810309103101031110312103131031410315103161031710318103191032010321103221032310324103251032610327103281032910330103311033210333103341033510336103371033810339103401034110342103431034410345103461034710348103491035010351103521035310354103551035610357103581035910360103611036210363103641036510366103671036810369103701037110372103731037410375103761037710378103791038010381103821038310384103851038610387103881038910390103911039210393103941039510396103971039810399104001040110402104031040410405104061040710408104091041010411104121041310414104151041610417104181041910420104211042210423104241042510426104271042810429104301043110432104331043410435104361043710438104391044010441104421044310444104451044610447104481044910450104511045210453104541045510456104571045810459104601046110462104631046410465104661046710468104691047010471104721047310474104751047610477104781047910480104811048210483104841048510486104871048810489104901049110492104931049410495104961049710498104991050010501105021050310504105051050610507105081050910510105111051210513105141051510516105171051810519105201052110522105231052410525105261052710528105291053010531105321053310534105351053610537105381053910540105411054210543105441054510546105471054810549105501055110552105531055410555105561055710558105591056010561105621056310564105651056610567105681056910570105711057210573105741057510576105771057810579105801058110582105831058410585105861058710588105891059010591105921059310594105951059610597105981059910600106011060210603106041060510606106071060810609106101061110612106131061410615106161061710618106191062010621106221062310624106251062610627106281062910630106311063210633106341063510636106371063810639106401064110642106431064410645106461064710648106491065010651106521065310654106551065610657106581065910660106611066210663106641066510666106671066810669106701067110672106731067410675106761067710678106791068010681106821068310684106851068610687106881068910690106911069210693106941069510696106971069810699107001070110702107031070410705107061070710708107091071010711107121071310714107151071610717107181071910720107211072210723107241072510726107271072810729107301073110732107331073410735107361073710738107391074010741107421074310744107451074610747107481074910750107511075210753107541075510756107571075810759107601076110762107631076410765107661076710768107691077010771107721077310774107751077610777107781077910780107811078210783107841078510786107871078810789107901079110792107931079410795107961079710798107991080010801108021080310804108051080610807108081080910810108111081210813108141081510816108171081810819108201082110822108231082410825108261082710828108291083010831108321083310834108351083610837108381083910840108411084210843108441084510846108471084810849108501085110852108531085410855108561085710858108591086010861108621086310864108651086610867108681086910870108711087210873108741087510876108771087810879108801088110882108831088410885108861088710888108891089010891108921089310894108951089610897108981089910900109011090210903109041090510906109071090810909109101091110912109131091410915109161091710918109191092010921109221092310924109251092610927109281092910930109311093210933109341093510936109371093810939109401094110942109431094410945109461094710948109491095010951109521095310954109551095610957109581095910960109611096210963109641096510966109671096810969109701097110972109731097410975109761097710978109791098010981109821098310984109851098610987109881098910990109911099210993109941099510996109971099810999110001100111002110031100411005110061100711008110091101011011110121101311014110151101611017110181101911020110211102211023110241102511026110271102811029110301103111032110331103411035110361103711038110391104011041110421104311044110451104611047110481104911050110511105211053110541105511056110571105811059110601106111062110631106411065110661106711068110691107011071110721107311074110751107611077110781107911080110811108211083110841108511086110871108811089110901109111092110931109411095110961109711098110991110011101111021110311104111051110611107111081110911110111111111211113111141111511116111171111811119111201112111122111231112411125111261112711128111291113011131111321113311134111351113611137111381113911140111411114211143111441114511146111471114811149111501115111152111531115411155111561115711158111591116011161111621116311164111651116611167111681116911170111711117211173111741117511176111771117811179111801118111182111831118411185111861118711188111891119011191111921119311194111951119611197111981119911200112011120211203112041120511206112071120811209112101121111212112131121411215112161121711218112191122011221112221122311224112251122611227112281122911230112311123211233112341123511236112371123811239112401124111242112431124411245112461124711248112491125011251112521125311254112551125611257112581125911260112611126211263112641126511266112671126811269112701127111272112731127411275112761127711278112791128011281112821128311284112851128611287112881128911290112911129211293112941129511296112971129811299113001130111302113031130411305113061130711308113091131011311113121131311314113151131611317113181131911320113211132211323113241132511326113271132811329113301133111332113331133411335113361133711338113391134011341113421134311344113451134611347113481134911350113511135211353113541135511356113571135811359113601136111362113631136411365113661136711368113691137011371113721137311374113751137611377113781137911380113811138211383113841138511386113871138811389113901139111392113931139411395113961139711398113991140011401114021140311404114051140611407114081140911410114111141211413114141141511416114171141811419114201142111422114231142411425114261142711428114291143011431114321143311434114351143611437114381143911440114411144211443114441144511446114471144811449114501145111452114531145411455114561145711458114591146011461114621146311464114651146611467114681146911470114711147211473114741147511476114771147811479114801148111482114831148411485114861148711488114891149011491114921149311494114951149611497114981149911500115011150211503115041150511506115071150811509115101151111512115131151411515115161151711518115191152011521115221152311524115251152611527115281152911530115311153211533115341153511536115371153811539115401154111542115431154411545115461154711548115491155011551115521155311554115551155611557115581155911560115611156211563115641156511566115671156811569115701157111572115731157411575115761157711578115791158011581115821158311584115851158611587115881158911590115911159211593115941159511596115971159811599116001160111602116031160411605116061160711608116091161011611116121161311614116151161611617116181161911620116211162211623116241162511626116271162811629116301163111632116331163411635116361163711638116391164011641116421164311644116451164611647116481164911650116511165211653116541165511656116571165811659116601166111662116631166411665116661166711668116691167011671116721167311674116751167611677116781167911680116811168211683116841168511686116871168811689116901169111692116931169411695116961169711698116991170011701117021170311704117051170611707117081170911710117111171211713117141171511716117171171811719117201172111722117231172411725117261172711728117291173011731117321173311734117351173611737117381173911740117411174211743117441174511746117471174811749117501175111752117531175411755117561175711758117591176011761117621176311764117651176611767117681176911770117711177211773117741177511776117771177811779117801178111782117831178411785117861178711788117891179011791117921179311794117951179611797117981179911800118011180211803118041180511806118071180811809118101181111812118131181411815118161181711818118191182011821118221182311824118251182611827118281182911830118311183211833118341183511836118371183811839118401184111842118431184411845118461184711848118491185011851118521185311854118551185611857118581185911860118611186211863118641186511866118671186811869118701187111872118731187411875118761187711878118791188011881118821188311884118851188611887118881188911890118911189211893118941189511896118971189811899119001190111902119031190411905119061190711908119091191011911119121191311914119151191611917119181191911920119211192211923119241192511926119271192811929119301193111932119331193411935119361193711938119391194011941119421194311944119451194611947119481194911950119511195211953119541195511956119571195811959119601196111962119631196411965119661196711968119691197011971119721197311974119751197611977119781197911980119811198211983119841198511986119871198811989119901199111992119931199411995119961199711998119991200012001120021200312004120051200612007120081200912010120111201212013120141201512016120171201812019120201202112022120231202412025120261202712028120291203012031120321203312034120351203612037120381203912040120411204212043120441204512046120471204812049120501205112052120531205412055120561205712058120591206012061120621206312064120651206612067120681206912070120711207212073120741207512076120771207812079120801208112082120831208412085120861208712088120891209012091120921209312094120951209612097120981209912100121011210212103121041210512106121071210812109121101211112112121131211412115121161211712118121191212012121121221212312124121251212612127121281212912130121311213212133121341213512136121371213812139121401214112142121431214412145121461214712148121491215012151121521215312154121551215612157121581215912160121611216212163121641216512166121671216812169121701217112172121731217412175121761217712178121791218012181121821218312184121851218612187121881218912190121911219212193121941219512196121971219812199122001220112202122031220412205122061220712208122091221012211122121221312214122151221612217122181221912220122211222212223122241222512226122271222812229122301223112232122331223412235122361223712238122391224012241122421224312244122451224612247122481224912250122511225212253122541225512256122571225812259122601226112262122631226412265122661226712268122691227012271122721227312274122751227612277122781227912280122811228212283122841228512286122871228812289122901229112292122931229412295122961229712298122991230012301123021230312304123051230612307123081230912310123111231212313123141231512316123171231812319123201232112322123231232412325123261232712328123291233012331123321233312334123351233612337123381233912340123411234212343123441234512346123471234812349123501235112352123531235412355123561235712358123591236012361123621236312364123651236612367123681236912370123711237212373123741237512376123771237812379123801238112382123831238412385123861238712388123891239012391123921239312394123951239612397123981239912400124011240212403124041240512406124071240812409124101241112412124131241412415124161241712418124191242012421124221242312424124251242612427124281242912430124311243212433124341243512436124371243812439124401244112442124431244412445124461244712448124491245012451124521245312454124551245612457124581245912460124611246212463124641246512466124671246812469124701247112472124731247412475124761247712478124791248012481124821248312484124851248612487124881248912490124911249212493124941249512496124971249812499125001250112502125031250412505125061250712508125091251012511125121251312514125151251612517125181251912520125211252212523125241252512526125271252812529125301253112532125331253412535125361253712538125391254012541125421254312544125451254612547125481254912550125511255212553125541255512556125571255812559125601256112562125631256412565125661256712568125691257012571125721257312574125751257612577125781257912580125811258212583125841258512586125871258812589125901259112592125931259412595125961259712598125991260012601126021260312604126051260612607126081260912610126111261212613126141261512616126171261812619126201262112622126231262412625126261262712628126291263012631126321263312634126351263612637126381263912640126411264212643126441264512646126471264812649126501265112652126531265412655126561265712658126591266012661126621266312664126651266612667126681266912670126711267212673126741267512676126771267812679126801268112682126831268412685126861268712688126891269012691126921269312694126951269612697126981269912700127011270212703127041270512706127071270812709127101271112712127131271412715127161271712718127191272012721127221272312724127251272612727127281272912730127311273212733127341273512736127371273812739127401274112742127431274412745127461274712748127491275012751127521275312754127551275612757127581275912760127611276212763127641276512766127671276812769127701277112772127731277412775127761277712778127791278012781127821278312784127851278612787127881278912790127911279212793127941279512796127971279812799128001280112802128031280412805128061280712808128091281012811128121281312814128151281612817128181281912820128211282212823128241282512826128271282812829128301283112832128331283412835128361283712838128391284012841128421284312844128451284612847128481284912850128511285212853128541285512856128571285812859128601286112862128631286412865128661286712868128691287012871128721287312874128751287612877128781287912880128811288212883128841288512886128871288812889128901289112892128931289412895128961289712898128991290012901129021290312904129051290612907129081290912910129111291212913129141291512916129171291812919129201292112922129231292412925129261292712928129291293012931129321293312934129351293612937129381293912940129411294212943129441294512946129471294812949129501295112952129531295412955129561295712958129591296012961129621296312964129651296612967129681296912970129711297212973129741297512976129771297812979129801298112982129831298412985129861298712988129891299012991129921299312994129951299612997129981299913000130011300213003130041300513006130071300813009130101301113012130131301413015130161301713018130191302013021130221302313024130251302613027130281302913030130311303213033130341303513036130371303813039130401304113042130431304413045130461304713048130491305013051130521305313054130551305613057130581305913060130611306213063130641306513066130671306813069130701307113072130731307413075130761307713078130791308013081130821308313084130851308613087130881308913090130911309213093130941309513096130971309813099131001310113102131031310413105131061310713108131091311013111131121311313114131151311613117131181311913120131211312213123131241312513126131271312813129131301313113132131331313413135131361313713138131391314013141131421314313144131451314613147131481314913150131511315213153131541315513156131571315813159131601316113162131631316413165131661316713168131691317013171131721317313174131751317613177131781317913180131811318213183131841318513186131871318813189131901319113192131931319413195131961319713198131991320013201132021320313204132051320613207132081320913210132111321213213132141321513216132171321813219132201322113222132231322413225132261322713228132291323013231132321323313234132351323613237132381323913240132411324213243132441324513246132471324813249132501325113252132531325413255132561325713258132591326013261132621326313264132651326613267132681326913270132711327213273132741327513276132771327813279132801328113282132831328413285132861328713288132891329013291132921329313294132951329613297132981329913300133011330213303133041330513306133071330813309133101331113312133131331413315133161331713318133191332013321133221332313324133251332613327133281332913330133311333213333133341333513336133371333813339133401334113342133431334413345133461334713348133491335013351133521335313354133551335613357133581335913360133611336213363133641336513366133671336813369133701337113372133731337413375133761337713378133791338013381133821338313384133851338613387133881338913390133911339213393133941339513396133971339813399134001340113402134031340413405134061340713408134091341013411134121341313414134151341613417134181341913420134211342213423134241342513426134271342813429134301343113432134331343413435134361343713438134391344013441134421344313444134451344613447134481344913450134511345213453134541345513456134571345813459134601346113462134631346413465134661346713468134691347013471134721347313474134751347613477134781347913480134811348213483134841348513486134871348813489134901349113492134931349413495134961349713498134991350013501135021350313504135051350613507135081350913510135111351213513135141351513516135171351813519135201352113522135231352413525135261352713528135291353013531135321353313534135351353613537135381353913540135411354213543135441354513546135471354813549135501355113552135531355413555135561355713558135591356013561135621356313564135651356613567135681356913570135711357213573135741357513576135771357813579135801358113582135831358413585135861358713588135891359013591135921359313594135951359613597135981359913600136011360213603136041360513606136071360813609136101361113612136131361413615136161361713618136191362013621136221362313624136251362613627136281362913630136311363213633136341363513636136371363813639136401364113642136431364413645136461364713648136491365013651136521365313654136551365613657136581365913660136611366213663136641366513666136671366813669136701367113672136731367413675136761367713678136791368013681136821368313684136851368613687136881368913690136911369213693136941369513696136971369813699137001370113702137031370413705137061370713708137091371013711137121371313714137151371613717137181371913720137211372213723137241372513726137271372813729137301373113732137331373413735137361373713738137391374013741137421374313744137451374613747137481374913750137511375213753137541375513756137571375813759137601376113762137631376413765137661376713768137691377013771137721377313774137751377613777137781377913780137811378213783137841378513786137871378813789137901379113792137931379413795137961379713798137991380013801138021380313804138051380613807138081380913810138111381213813138141381513816138171381813819138201382113822138231382413825138261382713828138291383013831138321383313834138351383613837138381383913840138411384213843138441384513846138471384813849138501385113852138531385413855138561385713858138591386013861138621386313864138651386613867138681386913870138711387213873138741387513876138771387813879138801388113882138831388413885138861388713888138891389013891138921389313894138951389613897138981389913900139011390213903139041390513906139071390813909139101391113912139131391413915139161391713918139191392013921139221392313924139251392613927139281392913930139311393213933139341393513936139371393813939139401394113942139431394413945139461394713948139491395013951139521395313954139551395613957139581395913960139611396213963139641396513966139671396813969139701397113972139731397413975139761397713978139791398013981139821398313984139851398613987139881398913990139911399213993139941399513996139971399813999140001400114002140031400414005140061400714008140091401014011140121401314014140151401614017140181401914020140211402214023140241402514026140271402814029140301403114032140331403414035140361403714038140391404014041140421404314044140451404614047140481404914050140511405214053140541405514056140571405814059140601406114062140631406414065140661406714068140691407014071140721407314074140751407614077140781407914080140811408214083140841408514086140871408814089140901409114092140931409414095140961409714098140991410014101141021410314104141051410614107141081410914110141111411214113141141411514116141171411814119141201412114122141231412414125141261412714128141291413014131141321413314134141351413614137141381413914140141411414214143141441414514146141471414814149141501415114152141531415414155141561415714158141591416014161141621416314164141651416614167141681416914170141711417214173141741417514176141771417814179141801418114182141831418414185141861418714188141891419014191141921419314194141951419614197141981419914200142011420214203142041420514206142071420814209142101421114212142131421414215142161421714218142191422014221142221422314224142251422614227142281422914230142311423214233142341423514236142371423814239142401424114242142431424414245142461424714248142491425014251142521425314254142551425614257142581425914260142611426214263142641426514266142671426814269142701427114272142731427414275142761427714278142791428014281142821428314284142851428614287142881428914290142911429214293142941429514296142971429814299143001430114302143031430414305143061430714308143091431014311143121431314314143151431614317143181431914320143211432214323143241432514326143271432814329143301433114332143331433414335143361433714338143391434014341143421434314344143451434614347143481434914350143511435214353143541435514356143571435814359143601436114362143631436414365143661436714368143691437014371143721437314374143751437614377 |
- diff --git a/config.sub b/config.sub
- index d2e3557..2297c30 100755
- --- a/config.sub
- +++ b/config.sub
- @@ -276,6 +276,15 @@ case $basic_machine in
- basic_machine=$basic_machine-unknown
- os=-none
- ;;
- + # JBG
- + nios2 | nios2-* | nios2el | nios2el-*)
- + basic_machine=nios2-altera
- + os=-none_el
- + ;;
- + nios2eb | nios2eb-*)
- + basic_machine=nios2-altera
- + os=-none_eb
- + ;;
- m88110 | m680[12346]0 | m683?2 | m68360 | m5200 | v70 | w65 | z8k)
- ;;
-
- diff --git a/gcc/combine.c b/gcc/combine.c
- index 8f43c23..02648b1 100644
- --- a/gcc/combine.c
- +++ b/gcc/combine.c
- @@ -4381,6 +4381,14 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int last,
- mode);
- }
-
- +#ifndef __nios2__
- +/* This screws up Nios II in this test case:
- +
- +if (x & 1)
- + return 2;
- +else
- + return 3;
- +*/
- else if (STORE_FLAG_VALUE == 1
- && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
- && op1 == const0_rtx
- @@ -4392,6 +4400,7 @@ combine_simplify_rtx (rtx x, enum machine_mode op0_mode, int last,
- gen_lowpart_for_combine (mode, op0),
- const1_rtx);
- }
- +#endif
-
- else if (STORE_FLAG_VALUE == 1
- && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
- diff --git a/gcc/config.gcc b/gcc/config.gcc
- index d22f34b..4ecb6e9 100644
- --- a/gcc/config.gcc
- +++ b/gcc/config.gcc
- @@ -1337,6 +1337,17 @@ m32rle-*-linux*)
- thread_file='posix'
- fi
- ;;
- +# JBG
- +nios2-*-elf*_eb)
- + tm_file="elfos.h nios2/big.h ${tm_file}"
- + ;;
- +nios2-*-elf*)
- + tm_file="elfos.h ${tm_file}"
- + ;;
- +nios2-*-uclibc*) # Altera Nios2 running uClinux with uClibc
- + tm_file="elfos.h ${tm_file} nios2/nios2-uclibc.h"
- + tmake_file=nios2/t-nios2-uclibc
- + ;;
- # m68hc11 and m68hc12 share the same machine description.
- m68hc11-*-*|m6811-*-*)
- tm_file="dbxelf.h elfos.h m68hc11/m68hc11.h"
- diff --git a/gcc/config/nios2/big.h b/gcc/config/nios2/big.h
- new file mode 100644
- index 0000000..b7b1731
- --- /dev/null
- +++ b/gcc/config/nios2/big.h
- @@ -0,0 +1,23 @@
- +/*
- + big.h - Additional definitions for nios2 targets that default to big-endian
- +
- + Copyright (C) 2006 Altera
- +
- +This file is part of GNU CC.
- +
- +GNU CC 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 2, or (at your option)
- +any later version.
- +
- +GNU CC 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 GNU CC; see the file COPYING. If not, write to
- +the Free Software Foundation, 59 Temple Place - Suite 330,
- +Boston, MA 02111-1307, USA. */
- +
- +#define TARGET_ENDIAN_DEFAULT BIG_ENDIAN_FLAG
- diff --git a/gcc/config/nios2/crti.asm b/gcc/config/nios2/crti.asm
- new file mode 100644
- index 0000000..1fcfeb2
- --- /dev/null
- +++ b/gcc/config/nios2/crti.asm
- @@ -0,0 +1,88 @@
- +/*
- + Copyright (C) 2003
- + by Jonah Graham (jgraham@altera.com)
- +
- +This file 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 2, or (at your option) any
- +later version.
- +
- +In addition to the permissions in the GNU General Public License, the
- +Free Software Foundation gives you unlimited permission to link the
- +compiled version of this file with other programs, and to distribute
- +those programs without any restriction coming from the use of this
- +file. (The General Public License restrictions do apply in other
- +respects; for example, they cover modification of the file, and
- +distribution when not linked into another program.)
- +
- +This file 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 this program; see the file COPYING. If not, write to
- +the Free Software Foundation, 59 Temple Place - Suite 330,
- +Boston, MA 02111-1307, USA.
- +
- + As a special exception, if you link this library with files
- + compiled with GCC to produce an executable, this does not cause
- + the resulting executable to be covered by the GNU General Public License.
- + This exception does not however invalidate any other reasons why
- + the executable file might be covered by the GNU General Public License.
- +
- +
- +This file just make a stack frame for the contents of the .fini and
- +.init sections. Users may put any desired instructions in those
- +sections.
- +
- +
- +While technically any code can be put in the init and fini sections
- +most stuff will not work other than stuff which obeys the call frame
- +and ABI. All the call-preserved registers are saved, the call clobbered
- +registers should have been saved by the code calling init and fini.
- +
- +See crtstuff.c for an example of code that inserts itself in the
- +init and fini sections.
- +
- +See crt0.s for the code that calls init and fini.
- +*/
- +
- + .file "crti.asm"
- +
- + .section ".init"
- + .align 2
- + .global _init
- +_init:
- + addi sp, sp, -48
- + stw ra, 44(sp)
- + stw r23, 40(sp)
- + stw r22, 36(sp)
- + stw r21, 32(sp)
- + stw r20, 28(sp)
- + stw r19, 24(sp)
- + stw r18, 20(sp)
- + stw r17, 16(sp)
- + stw r16, 12(sp)
- + stw fp, 8(sp)
- + mov fp, sp
- +
- +
- + .section ".fini"
- + .align 2
- + .global _fini
- +_fini:
- + addi sp, sp, -48
- + stw ra, 44(sp)
- + stw r23, 40(sp)
- + stw r22, 36(sp)
- + stw r21, 32(sp)
- + stw r20, 28(sp)
- + stw r19, 24(sp)
- + stw r18, 20(sp)
- + stw r17, 16(sp)
- + stw r16, 12(sp)
- + stw fp, 8(sp)
- + mov fp, sp
- +
- +
- diff --git a/gcc/config/nios2/crtn.asm b/gcc/config/nios2/crtn.asm
- new file mode 100644
- index 0000000..e337480
- --- /dev/null
- +++ b/gcc/config/nios2/crtn.asm
- @@ -0,0 +1,70 @@
- +/*
- + Copyright (C) 2003
- + by Jonah Graham (jgraham@altera.com)
- +
- +This file 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 2, or (at your option) any
- +later version.
- +
- +In addition to the permissions in the GNU General Public License, the
- +Free Software Foundation gives you unlimited permission to link the
- +compiled version of this file with other programs, and to distribute
- +those programs without any restriction coming from the use of this
- +file. (The General Public License restrictions do apply in other
- +respects; for example, they cover modification of the file, and
- +distribution when not linked into another program.)
- +
- +This file 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 this program; see the file COPYING. If not, write to
- +the Free Software Foundation, 59 Temple Place - Suite 330,
- +Boston, MA 02111-1307, USA.
- +
- + As a special exception, if you link this library with files
- + compiled with GCC to produce an executable, this does not cause
- + the resulting executable to be covered by the GNU General Public License.
- + This exception does not however invalidate any other reasons why
- + the executable file might be covered by the GNU General Public License.
- +
- +
- +This file just makes sure that the .fini and .init sections do in
- +fact return. Users may put any desired instructions in those sections.
- +This file is the last thing linked into any executable.
- +*/
- + .file "crtn.asm"
- +
- +
- +
- + .section ".init"
- + ldw ra, 44(sp)
- + ldw r23, 40(sp)
- + ldw r22, 36(sp)
- + ldw r21, 32(sp)
- + ldw r20, 28(sp)
- + ldw r19, 24(sp)
- + ldw r18, 20(sp)
- + ldw r17, 16(sp)
- + ldw r16, 12(sp)
- + ldw fp, 8(sp)
- + addi sp, sp, -48
- + ret
- +
- + .section ".fini"
- + ldw ra, 44(sp)
- + ldw r23, 40(sp)
- + ldw r22, 36(sp)
- + ldw r21, 32(sp)
- + ldw r20, 28(sp)
- + ldw r19, 24(sp)
- + ldw r18, 20(sp)
- + ldw r17, 16(sp)
- + ldw r16, 12(sp)
- + ldw fp, 8(sp)
- + addi sp, sp, -48
- + ret
- +
- diff --git a/gcc/config/nios2/lib2-divmod-hi.c b/gcc/config/nios2/lib2-divmod-hi.c
- new file mode 100644
- index 0000000..10bd6e4
- --- /dev/null
- +++ b/gcc/config/nios2/lib2-divmod-hi.c
- @@ -0,0 +1,123 @@
- +
- +/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
- + supposedly valid even though this is a "target" file. */
- +#include "auto-host.h"
- +
- +
- +#include "tconfig.h"
- +#include "tsystem.h"
- +#include "coretypes.h"
- +#include "tm.h"
- +
- +
- +/* Don't use `fancy_abort' here even if config.h says to use it. */
- +#ifdef abort
- +#undef abort
- +#endif
- +
- +
- +#ifdef HAVE_GAS_HIDDEN
- +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
- +#else
- +#define ATTRIBUTE_HIDDEN
- +#endif
- +
- +#include "libgcc2.h"
- +
- +extern HItype __modhi3 (HItype, HItype);
- +extern HItype __divhi3 (HItype, HItype);
- +extern HItype __umodhi3 (HItype, HItype);
- +extern HItype __udivhi3 (HItype, HItype);
- +
- +static UHItype udivmodhi4(UHItype, UHItype, word_type);
- +
- +static UHItype
- +udivmodhi4(UHItype num, UHItype den, word_type modwanted)
- +{
- + UHItype bit = 1;
- + UHItype res = 0;
- +
- + while (den < num && bit && !(den & (1L<<15)))
- + {
- + den <<=1;
- + bit <<=1;
- + }
- + while (bit)
- + {
- + if (num >= den)
- + {
- + num -= den;
- + res |= bit;
- + }
- + bit >>=1;
- + den >>=1;
- + }
- + if (modwanted) return num;
- + return res;
- +}
- +
- +
- +HItype
- +__divhi3 (HItype a, HItype b)
- +{
- + word_type neg = 0;
- + HItype res;
- +
- + if (a < 0)
- + {
- + a = -a;
- + neg = !neg;
- + }
- +
- + if (b < 0)
- + {
- + b = -b;
- + neg = !neg;
- + }
- +
- + res = udivmodhi4 (a, b, 0);
- +
- + if (neg)
- + res = -res;
- +
- + return res;
- +}
- +
- +
- +HItype
- +__modhi3 (HItype a, HItype b)
- +{
- + word_type neg = 0;
- + HItype res;
- +
- + if (a < 0)
- + {
- + a = -a;
- + neg = 1;
- + }
- +
- + if (b < 0)
- + b = -b;
- +
- + res = udivmodhi4 (a, b, 1);
- +
- + if (neg)
- + res = -res;
- +
- + return res;
- +}
- +
- +
- +HItype
- +__udivhi3 (HItype a, HItype b)
- +{
- + return udivmodhi4 (a, b, 0);
- +}
- +
- +
- +HItype
- +__umodhi3 (HItype a, HItype b)
- +{
- + return udivmodhi4 (a, b, 1);
- +}
- +
- diff --git a/gcc/config/nios2/lib2-divmod.c b/gcc/config/nios2/lib2-divmod.c
- new file mode 100644
- index 0000000..00e730d
- --- /dev/null
- +++ b/gcc/config/nios2/lib2-divmod.c
- @@ -0,0 +1,126 @@
- +
- +/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
- + supposedly valid even though this is a "target" file. */
- +#include "auto-host.h"
- +
- +
- +#include "tconfig.h"
- +#include "tsystem.h"
- +#include "coretypes.h"
- +#include "tm.h"
- +
- +
- +/* Don't use `fancy_abort' here even if config.h says to use it. */
- +#ifdef abort
- +#undef abort
- +#endif
- +
- +
- +#ifdef HAVE_GAS_HIDDEN
- +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
- +#else
- +#define ATTRIBUTE_HIDDEN
- +#endif
- +
- +#include "libgcc2.h"
- +
- +extern SItype __modsi3 (SItype, SItype);
- +extern SItype __divsi3 (SItype, SItype);
- +extern SItype __umodsi3 (SItype, SItype);
- +extern SItype __udivsi3 (SItype, SItype);
- +
- +static USItype udivmodsi4(USItype, USItype, word_type);
- +
- +/* 16-bit SI divide and modulo as used in NIOS */
- +
- +
- +static USItype
- +udivmodsi4(USItype num, USItype den, word_type modwanted)
- +{
- + USItype bit = 1;
- + USItype res = 0;
- +
- + while (den < num && bit && !(den & (1L<<31)))
- + {
- + den <<=1;
- + bit <<=1;
- + }
- + while (bit)
- + {
- + if (num >= den)
- + {
- + num -= den;
- + res |= bit;
- + }
- + bit >>=1;
- + den >>=1;
- + }
- + if (modwanted) return num;
- + return res;
- +}
- +
- +
- +SItype
- +__divsi3 (SItype a, SItype b)
- +{
- + word_type neg = 0;
- + SItype res;
- +
- + if (a < 0)
- + {
- + a = -a;
- + neg = !neg;
- + }
- +
- + if (b < 0)
- + {
- + b = -b;
- + neg = !neg;
- + }
- +
- + res = udivmodsi4 (a, b, 0);
- +
- + if (neg)
- + res = -res;
- +
- + return res;
- +}
- +
- +
- +SItype
- +__modsi3 (SItype a, SItype b)
- +{
- + word_type neg = 0;
- + SItype res;
- +
- + if (a < 0)
- + {
- + a = -a;
- + neg = 1;
- + }
- +
- + if (b < 0)
- + b = -b;
- +
- + res = udivmodsi4 (a, b, 1);
- +
- + if (neg)
- + res = -res;
- +
- + return res;
- +}
- +
- +
- +SItype
- +__udivsi3 (SItype a, SItype b)
- +{
- + return udivmodsi4 (a, b, 0);
- +}
- +
- +
- +SItype
- +__umodsi3 (SItype a, SItype b)
- +{
- + return udivmodsi4 (a, b, 1);
- +}
- +
- diff --git a/gcc/config/nios2/lib2-divtable.c b/gcc/config/nios2/lib2-divtable.c
- new file mode 100644
- index 0000000..48a7bd7
- --- /dev/null
- +++ b/gcc/config/nios2/lib2-divtable.c
- @@ -0,0 +1,46 @@
- +
- +/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
- + supposedly valid even though this is a "target" file. */
- +#include "auto-host.h"
- +
- +
- +#include "tconfig.h"
- +#include "tsystem.h"
- +#include "coretypes.h"
- +#include "tm.h"
- +
- +
- +/* Don't use `fancy_abort' here even if config.h says to use it. */
- +#ifdef abort
- +#undef abort
- +#endif
- +
- +
- +#ifdef HAVE_GAS_HIDDEN
- +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
- +#else
- +#define ATTRIBUTE_HIDDEN
- +#endif
- +
- +#include "libgcc2.h"
- +
- +UQItype __divsi3_table[] =
- +{
- + 0, 0/1, 0/2, 0/3, 0/4, 0/5, 0/6, 0/7, 0/8, 0/9, 0/10, 0/11, 0/12, 0/13, 0/14, 0/15,
- + 0, 1/1, 1/2, 1/3, 1/4, 1/5, 1/6, 1/7, 1/8, 1/9, 1/10, 1/11, 1/12, 1/13, 1/14, 1/15,
- + 0, 2/1, 2/2, 2/3, 2/4, 2/5, 2/6, 2/7, 2/8, 2/9, 2/10, 2/11, 2/12, 2/13, 2/14, 2/15,
- + 0, 3/1, 3/2, 3/3, 3/4, 3/5, 3/6, 3/7, 3/8, 3/9, 3/10, 3/11, 3/12, 3/13, 3/14, 3/15,
- + 0, 4/1, 4/2, 4/3, 4/4, 4/5, 4/6, 4/7, 4/8, 4/9, 4/10, 4/11, 4/12, 4/13, 4/14, 4/15,
- + 0, 5/1, 5/2, 5/3, 5/4, 5/5, 5/6, 5/7, 5/8, 5/9, 5/10, 5/11, 5/12, 5/13, 5/14, 5/15,
- + 0, 6/1, 6/2, 6/3, 6/4, 6/5, 6/6, 6/7, 6/8, 6/9, 6/10, 6/11, 6/12, 6/13, 6/14, 6/15,
- + 0, 7/1, 7/2, 7/3, 7/4, 7/5, 7/6, 7/7, 7/8, 7/9, 7/10, 7/11, 7/12, 7/13, 7/14, 7/15,
- + 0, 8/1, 8/2, 8/3, 8/4, 8/5, 8/6, 8/7, 8/8, 8/9, 8/10, 8/11, 8/12, 8/13, 8/14, 8/15,
- + 0, 9/1, 9/2, 9/3, 9/4, 9/5, 9/6, 9/7, 9/8, 9/9, 9/10, 9/11, 9/12, 9/13, 9/14, 9/15,
- + 0, 10/1, 10/2, 10/3, 10/4, 10/5, 10/6, 10/7, 10/8, 10/9, 10/10, 10/11, 10/12, 10/13, 10/14, 10/15,
- + 0, 11/1, 11/2, 11/3, 11/4, 11/5, 11/6, 11/7, 11/8, 11/9, 11/10, 11/11, 11/12, 11/13, 11/14, 11/15,
- + 0, 12/1, 12/2, 12/3, 12/4, 12/5, 12/6, 12/7, 12/8, 12/9, 12/10, 12/11, 12/12, 12/13, 12/14, 12/15,
- + 0, 13/1, 13/2, 13/3, 13/4, 13/5, 13/6, 13/7, 13/8, 13/9, 13/10, 13/11, 13/12, 13/13, 13/14, 13/15,
- + 0, 14/1, 14/2, 14/3, 14/4, 14/5, 14/6, 14/7, 14/8, 14/9, 14/10, 14/11, 14/12, 14/13, 14/14, 14/15,
- + 0, 15/1, 15/2, 15/3, 15/4, 15/5, 15/6, 15/7, 15/8, 15/9, 15/10, 15/11, 15/12, 15/13, 15/14, 15/15,
- +};
- +
- diff --git a/gcc/config/nios2/lib2-mul.c b/gcc/config/nios2/lib2-mul.c
- new file mode 100644
- index 0000000..8511b33
- --- /dev/null
- +++ b/gcc/config/nios2/lib2-mul.c
- @@ -0,0 +1,103 @@
- +/* while we are debugging (ie compile outside of gcc build)
- + disable gcc specific headers */
- +#ifndef DEBUG_MULSI3
- +
- +
- +/* We include auto-host.h here to get HAVE_GAS_HIDDEN. This is
- + supposedly valid even though this is a "target" file. */
- +#include "auto-host.h"
- +
- +
- +#include "tconfig.h"
- +#include "tsystem.h"
- +#include "coretypes.h"
- +#include "tm.h"
- +
- +
- +/* Don't use `fancy_abort' here even if config.h says to use it. */
- +#ifdef abort
- +#undef abort
- +#endif
- +
- +
- +#ifdef HAVE_GAS_HIDDEN
- +#define ATTRIBUTE_HIDDEN __attribute__ ((__visibility__ ("hidden")))
- +#else
- +#define ATTRIBUTE_HIDDEN
- +#endif
- +
- +#include "libgcc2.h"
- +
- +#else
- +#define SItype int
- +#define USItype unsigned int
- +#endif
- +
- +
- +extern SItype __mulsi3 (SItype, SItype);
- +
- +SItype
- +__mulsi3 (SItype a, SItype b)
- +{
- + SItype res = 0;
- + USItype cnt = a;
- +
- + while (cnt)
- + {
- + if (cnt & 1)
- + {
- + res += b;
- + }
- + b <<= 1;
- + cnt >>= 1;
- + }
- +
- + return res;
- +}
- +/*
- +TODO: Choose best alternative implementation.
- +
- +SItype
- +__divsi3 (SItype a, SItype b)
- +{
- + SItype res = 0;
- + USItype cnt = 0;
- +
- + while (cnt < 32)
- + {
- + if (a & (1L << cnt))
- + {
- + res += b;
- + }
- + b <<= 1;
- + cnt++;
- + }
- +
- + return res;
- +}
- +*/
- +
- +
- +#ifdef DEBUG_MULSI3
- +
- +int
- +main ()
- +{
- + int i, j;
- + int error = 0;
- +
- + for (i = -1000; i < 1000; i++)
- + for (j = -1000; j < 1000; j++)
- + {
- + int expect = i * j;
- + int actual = A__divsi3 (i, j);
- + if (expect != actual)
- + {
- + printf ("error: %d * %d = %d not %d\n", i, j, expect, actual);
- + error = 1;
- + }
- + }
- +
- + return error;
- +}
- +#endif
- diff --git a/gcc/config/nios2/nios2-dp-bit.c b/gcc/config/nios2/nios2-dp-bit.c
- new file mode 100644
- index 0000000..4d63748
- --- /dev/null
- +++ b/gcc/config/nios2/nios2-dp-bit.c
- @@ -0,0 +1,1655 @@
- +
- +#ifndef __nios2_big_endian__
- +#define FLOAT_BIT_ORDER_MISMATCH
- +#endif
- +/* This is a software floating point library which can be used
- + for targets without hardware floating point.
- + Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
- + Free Software Foundation, Inc.
- +
- +This file 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 2, or (at your option) any
- +later version.
- +
- +In addition to the permissions in the GNU General Public License, the
- +Free Software Foundation gives you unlimited permission to link the
- +compiled version of this file with other programs, and to distribute
- +those programs without any restriction coming from the use of this
- +file. (The General Public License restrictions do apply in other
- +respects; for example, they cover modification of the file, and
- +distribution when not linked into another program.)
- +
- +This file 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 this program; see the file COPYING. If not, write to
- +the Free Software Foundation, 59 Temple Place - Suite 330,
- +Boston, MA 02111-1307, USA. */
- +
- +/* As a special exception, if you link this library with other files,
- + some of which are compiled with GCC, to produce an executable,
- + this library does not by itself cause the resulting executable
- + to be covered by the GNU General Public License.
- + This exception does not however invalidate any other reasons why
- + the executable file might be covered by the GNU General Public License. */
- +
- +/* This implements IEEE 754 format arithmetic, but does not provide a
- + mechanism for setting the rounding mode, or for generating or handling
- + exceptions.
- +
- + The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
- + Wilson, all of Cygnus Support. */
- +
- +/* The intended way to use this file is to make two copies, add `#define FLOAT'
- + to one copy, then compile both copies and add them to libgcc.a. */
- +
- +#include "tconfig.h"
- +#include "coretypes.h"
- +#include "tm.h"
- +#include "config/fp-bit.h"
- +
- +/* The following macros can be defined to change the behavior of this file:
- + FLOAT: Implement a `float', aka SFmode, fp library. If this is not
- + defined, then this file implements a `double', aka DFmode, fp library.
- + FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e.
- + don't include float->double conversion which requires the double library.
- + This is useful only for machines which can't support doubles, e.g. some
- + 8-bit processors.
- + CMPtype: Specify the type that floating point compares should return.
- + This defaults to SItype, aka int.
- + US_SOFTWARE_GOFAST: This makes all entry points use the same names as the
- + US Software goFast library.
- + _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding
- + two integers to the FLO_union_type.
- + NO_DENORMALS: Disable handling of denormals.
- + NO_NANS: Disable nan and infinity handling
- + SMALL_MACHINE: Useful when operations on QIs and HIs are faster
- + than on an SI */
- +
- +/* We don't currently support extended floats (long doubles) on machines
- + without hardware to deal with them.
- +
- + These stubs are just to keep the linker from complaining about unresolved
- + references which can be pulled in from libio & libstdc++, even if the
- + user isn't using long doubles. However, they may generate an unresolved
- + external to abort if abort is not used by the function, and the stubs
- + are referenced from within libc, since libgcc goes before and after the
- + system library. */
- +
- +#ifdef DECLARE_LIBRARY_RENAMES
- + DECLARE_LIBRARY_RENAMES
- +#endif
- +
- +#ifdef EXTENDED_FLOAT_STUBS
- +extern void abort (void);
- +void __extendsfxf2 (void) { abort(); }
- +void __extenddfxf2 (void) { abort(); }
- +void __truncxfdf2 (void) { abort(); }
- +void __truncxfsf2 (void) { abort(); }
- +void __fixxfsi (void) { abort(); }
- +void __floatsixf (void) { abort(); }
- +void __addxf3 (void) { abort(); }
- +void __subxf3 (void) { abort(); }
- +void __mulxf3 (void) { abort(); }
- +void __divxf3 (void) { abort(); }
- +void __negxf2 (void) { abort(); }
- +void __eqxf2 (void) { abort(); }
- +void __nexf2 (void) { abort(); }
- +void __gtxf2 (void) { abort(); }
- +void __gexf2 (void) { abort(); }
- +void __lexf2 (void) { abort(); }
- +void __ltxf2 (void) { abort(); }
- +
- +void __extendsftf2 (void) { abort(); }
- +void __extenddftf2 (void) { abort(); }
- +void __trunctfdf2 (void) { abort(); }
- +void __trunctfsf2 (void) { abort(); }
- +void __fixtfsi (void) { abort(); }
- +void __floatsitf (void) { abort(); }
- +void __addtf3 (void) { abort(); }
- +void __subtf3 (void) { abort(); }
- +void __multf3 (void) { abort(); }
- +void __divtf3 (void) { abort(); }
- +void __negtf2 (void) { abort(); }
- +void __eqtf2 (void) { abort(); }
- +void __netf2 (void) { abort(); }
- +void __gttf2 (void) { abort(); }
- +void __getf2 (void) { abort(); }
- +void __letf2 (void) { abort(); }
- +void __lttf2 (void) { abort(); }
- +#else /* !EXTENDED_FLOAT_STUBS, rest of file */
- +
- +/* IEEE "special" number predicates */
- +
- +#ifdef NO_NANS
- +
- +#define nan() 0
- +#define isnan(x) 0
- +#define isinf(x) 0
- +#else
- +
- +#if defined L_thenan_sf
- +const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
- +#elif defined L_thenan_df
- +const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} };
- +#elif defined L_thenan_tf
- +const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
- +#elif defined TFLOAT
- +extern const fp_number_type __thenan_tf;
- +#elif defined FLOAT
- +extern const fp_number_type __thenan_sf;
- +#else
- +extern const fp_number_type __thenan_df;
- +#endif
- +
- +INLINE
- +static fp_number_type *
- +nan (void)
- +{
- + /* Discard the const qualifier... */
- +#ifdef TFLOAT
- + return (fp_number_type *) (& __thenan_tf);
- +#elif defined FLOAT
- + return (fp_number_type *) (& __thenan_sf);
- +#else
- + return (fp_number_type *) (& __thenan_df);
- +#endif
- +}
- +
- +INLINE
- +static int
- +isnan ( fp_number_type * x)
- +{
- + return x->class == CLASS_SNAN || x->class == CLASS_QNAN;
- +}
- +
- +INLINE
- +static int
- +isinf ( fp_number_type * x)
- +{
- + return x->class == CLASS_INFINITY;
- +}
- +
- +#endif /* NO_NANS */
- +
- +INLINE
- +static int
- +iszero ( fp_number_type * x)
- +{
- + return x->class == CLASS_ZERO;
- +}
- +
- +INLINE
- +static void
- +flip_sign ( fp_number_type * x)
- +{
- + x->sign = !x->sign;
- +}
- +
- +extern FLO_type pack_d ( fp_number_type * );
- +
- +#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
- +FLO_type
- +pack_d ( fp_number_type * src)
- +{
- + FLO_union_type dst;
- + fractype fraction = src->fraction.ll; /* wasn't unsigned before? */
- + int sign = src->sign;
- + int exp = 0;
- +
- + if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
- + {
- + /* We can't represent these values accurately. By using the
- + largest possible magnitude, we guarantee that the conversion
- + of infinity is at least as big as any finite number. */
- + exp = EXPMAX;
- + fraction = ((fractype) 1 << FRACBITS) - 1;
- + }
- + else if (isnan (src))
- + {
- + exp = EXPMAX;
- + if (src->class == CLASS_QNAN || 1)
- + {
- +#ifdef QUIET_NAN_NEGATED
- + fraction |= QUIET_NAN - 1;
- +#else
- + fraction |= QUIET_NAN;
- +#endif
- + }
- + }
- + else if (isinf (src))
- + {
- + exp = EXPMAX;
- + fraction = 0;
- + }
- + else if (iszero (src))
- + {
- + exp = 0;
- + fraction = 0;
- + }
- + else if (fraction == 0)
- + {
- + exp = 0;
- + }
- + else
- + {
- + if (src->normal_exp < NORMAL_EXPMIN)
- + {
- +#ifdef NO_DENORMALS
- + /* Go straight to a zero representation if denormals are not
- + supported. The denormal handling would be harmless but
- + isn't unnecessary. */
- + exp = 0;
- + fraction = 0;
- +#else /* NO_DENORMALS */
- + /* This number's exponent is too low to fit into the bits
- + available in the number, so we'll store 0 in the exponent and
- + shift the fraction to the right to make up for it. */
- +
- + int shift = NORMAL_EXPMIN - src->normal_exp;
- +
- + exp = 0;
- +
- + if (shift > FRAC_NBITS - NGARDS)
- + {
- + /* No point shifting, since it's more that 64 out. */
- + fraction = 0;
- + }
- + else
- + {
- + int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0;
- + fraction = (fraction >> shift) | lowbit;
- + }
- + if ((fraction & GARDMASK) == GARDMSB)
- + {
- + if ((fraction & (1 << NGARDS)))
- + fraction += GARDROUND + 1;
- + }
- + else
- + {
- + /* Add to the guards to round up. */
- + fraction += GARDROUND;
- + }
- + /* Perhaps the rounding means we now need to change the
- + exponent, because the fraction is no longer denormal. */
- + if (fraction >= IMPLICIT_1)
- + {
- + exp += 1;
- + }
- + fraction >>= NGARDS;
- +#endif /* NO_DENORMALS */
- + }
- + else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
- + && src->normal_exp > EXPBIAS)
- + {
- + exp = EXPMAX;
- + fraction = 0;
- + }
- + else
- + {
- + exp = src->normal_exp + EXPBIAS;
- + if (!ROUND_TOWARDS_ZERO)
- + {
- + /* IF the gard bits are the all zero, but the first, then we're
- + half way between two numbers, choose the one which makes the
- + lsb of the answer 0. */
- + if ((fraction & GARDMASK) == GARDMSB)
- + {
- + if (fraction & (1 << NGARDS))
- + fraction += GARDROUND + 1;
- + }
- + else
- + {
- + /* Add a one to the guards to round up */
- + fraction += GARDROUND;
- + }
- + if (fraction >= IMPLICIT_2)
- + {
- + fraction >>= 1;
- + exp += 1;
- + }
- + }
- + fraction >>= NGARDS;
- +
- + if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
- + {
- + /* Saturate on overflow. */
- + exp = EXPMAX;
- + fraction = ((fractype) 1 << FRACBITS) - 1;
- + }
- + }
- + }
- +
- + /* We previously used bitfields to store the number, but this doesn't
- + handle little/big endian systems conveniently, so use shifts and
- + masks */
- +#ifdef FLOAT_BIT_ORDER_MISMATCH
- + dst.bits.fraction = fraction;
- + dst.bits.exp = exp;
- + dst.bits.sign = sign;
- +#else
- +# if defined TFLOAT && defined HALFFRACBITS
- + {
- + halffractype high, low, unity;
- + int lowsign, lowexp;
- +
- + unity = (halffractype) 1 << HALFFRACBITS;
- +
- + /* Set HIGH to the high double's significand, masking out the implicit 1.
- + Set LOW to the low double's full significand. */
- + high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1);
- + low = fraction & (unity * 2 - 1);
- +
- + /* Get the initial sign and exponent of the low double. */
- + lowexp = exp - HALFFRACBITS - 1;
- + lowsign = sign;
- +
- + /* HIGH should be rounded like a normal double, making |LOW| <=
- + 0.5 ULP of HIGH. Assume round-to-nearest. */
- + if (exp < EXPMAX)
- + if (low > unity || (low == unity && (high & 1) == 1))
- + {
- + /* Round HIGH up and adjust LOW to match. */
- + high++;
- + if (high == unity)
- + {
- + /* May make it infinite, but that's OK. */
- + high = 0;
- + exp++;
- + }
- + low = unity * 2 - low;
- + lowsign ^= 1;
- + }
- +
- + high |= (halffractype) exp << HALFFRACBITS;
- + high |= (halffractype) sign << (HALFFRACBITS + EXPBITS);
- +
- + if (exp == EXPMAX || exp == 0 || low == 0)
- + low = 0;
- + else
- + {
- + while (lowexp > 0 && low < unity)
- + {
- + low <<= 1;
- + lowexp--;
- + }
- +
- + if (lowexp <= 0)
- + {
- + halffractype roundmsb, round;
- + int shift;
- +
- + shift = 1 - lowexp;
- + roundmsb = (1 << (shift - 1));
- + round = low & ((roundmsb << 1) - 1);
- +
- + low >>= shift;
- + lowexp = 0;
- +
- + if (round > roundmsb || (round == roundmsb && (low & 1) == 1))
- + {
- + low++;
- + if (low == unity)
- + /* LOW rounds up to the smallest normal number. */
- + lowexp++;
- + }
- + }
- +
- + low &= unity - 1;
- + low |= (halffractype) lowexp << HALFFRACBITS;
- + low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS);
- + }
- + dst.value_raw = ((fractype) high << HALFSHIFT) | low;
- + }
- +# else
- + dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
- + dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS;
- + dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS);
- +# endif
- +#endif
- +
- +#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
- +#ifdef TFLOAT
- + {
- + qrtrfractype tmp1 = dst.words[0];
- + qrtrfractype tmp2 = dst.words[1];
- + dst.words[0] = dst.words[3];
- + dst.words[1] = dst.words[2];
- + dst.words[2] = tmp2;
- + dst.words[3] = tmp1;
- + }
- +#else
- + {
- + halffractype tmp = dst.words[0];
- + dst.words[0] = dst.words[1];
- + dst.words[1] = tmp;
- + }
- +#endif
- +#endif
- +
- + return dst.value;
- +}
- +#endif
- +
- +#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
- +void
- +unpack_d (FLO_union_type * src, fp_number_type * dst)
- +{
- + /* We previously used bitfields to store the number, but this doesn't
- + handle little/big endian systems conveniently, so use shifts and
- + masks */
- + fractype fraction;
- + int exp;
- + int sign;
- +
- +#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
- + FLO_union_type swapped;
- +
- +#ifdef TFLOAT
- + swapped.words[0] = src->words[3];
- + swapped.words[1] = src->words[2];
- + swapped.words[2] = src->words[1];
- + swapped.words[3] = src->words[0];
- +#else
- + swapped.words[0] = src->words[1];
- + swapped.words[1] = src->words[0];
- +#endif
- + src = &swapped;
- +#endif
- +
- +#ifdef FLOAT_BIT_ORDER_MISMATCH
- + fraction = src->bits.fraction;
- + exp = src->bits.exp;
- + sign = src->bits.sign;
- +#else
- +# if defined TFLOAT && defined HALFFRACBITS
- + {
- + halffractype high, low;
- +
- + high = src->value_raw >> HALFSHIFT;
- + low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1);
- +
- + fraction = high & ((((fractype)1) << HALFFRACBITS) - 1);
- + fraction <<= FRACBITS - HALFFRACBITS;
- + exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
- + sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1;
- +
- + if (exp != EXPMAX && exp != 0 && low != 0)
- + {
- + int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
- + int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1;
- + int shift;
- + fractype xlow;
- +
- + xlow = low & ((((fractype)1) << HALFFRACBITS) - 1);
- + if (lowexp)
- + xlow |= (((halffractype)1) << HALFFRACBITS);
- + else
- + lowexp = 1;
- + shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp);
- + if (shift > 0)
- + xlow <<= shift;
- + else if (shift < 0)
- + xlow >>= -shift;
- + if (sign == lowsign)
- + fraction += xlow;
- + else if (fraction >= xlow)
- + fraction -= xlow;
- + else
- + {
- + /* The high part is a power of two but the full number is lower.
- + This code will leave the implicit 1 in FRACTION, but we'd
- + have added that below anyway. */
- + fraction = (((fractype) 1 << FRACBITS) - xlow) << 1;
- + exp--;
- + }
- + }
- + }
- +# else
- + fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1);
- + exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1);
- + sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1;
- +# endif
- +#endif
- +
- + dst->sign = sign;
- + if (exp == 0)
- + {
- + /* Hmm. Looks like 0 */
- + if (fraction == 0
- +#ifdef NO_DENORMALS
- + || 1
- +#endif
- + )
- + {
- + /* tastes like zero */
- + dst->class = CLASS_ZERO;
- + }
- + else
- + {
- + /* Zero exponent with nonzero fraction - it's denormalized,
- + so there isn't a leading implicit one - we'll shift it so
- + it gets one. */
- + dst->normal_exp = exp - EXPBIAS + 1;
- + fraction <<= NGARDS;
- +
- + dst->class = CLASS_NUMBER;
- +#if 1
- + while (fraction < IMPLICIT_1)
- + {
- + fraction <<= 1;
- + dst->normal_exp--;
- + }
- +#endif
- + dst->fraction.ll = fraction;
- + }
- + }
- + else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
- + {
- + /* Huge exponent*/
- + if (fraction == 0)
- + {
- + /* Attached to a zero fraction - means infinity */
- + dst->class = CLASS_INFINITY;
- + }
- + else
- + {
- + /* Nonzero fraction, means nan */
- +#ifdef QUIET_NAN_NEGATED
- + if ((fraction & QUIET_NAN) == 0)
- +#else
- + if (fraction & QUIET_NAN)
- +#endif
- + {
- + dst->class = CLASS_QNAN;
- + }
- + else
- + {
- + dst->class = CLASS_SNAN;
- + }
- + /* Keep the fraction part as the nan number */
- + dst->fraction.ll = fraction;
- + }
- + }
- + else
- + {
- + /* Nothing strange about this number */
- + dst->normal_exp = exp - EXPBIAS;
- + dst->class = CLASS_NUMBER;
- + dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
- + }
- +}
- +#endif /* L_unpack_df || L_unpack_sf */
- +
- +#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
- +static fp_number_type *
- +_fpadd_parts (fp_number_type * a,
- + fp_number_type * b,
- + fp_number_type * tmp)
- +{
- + intfrac tfraction;
- +
- + /* Put commonly used fields in local variables. */
- + int a_normal_exp;
- + int b_normal_exp;
- + fractype a_fraction;
- + fractype b_fraction;
- +
- + if (isnan (a))
- + {
- + return a;
- + }
- + if (isnan (b))
- + {
- + return b;
- + }
- + if (isinf (a))
- + {
- + /* Adding infinities with opposite signs yields a NaN. */
- + if (isinf (b) && a->sign != b->sign)
- + return nan ();
- + return a;
- + }
- + if (isinf (b))
- + {
- + return b;
- + }
- + if (iszero (b))
- + {
- + if (iszero (a))
- + {
- + *tmp = *a;
- + tmp->sign = a->sign & b->sign;
- + return tmp;
- + }
- + return a;
- + }
- + if (iszero (a))
- + {
- + return b;
- + }
- +
- + /* Got two numbers. shift the smaller and increment the exponent till
- + they're the same */
- + {
- + int diff;
- +
- + a_normal_exp = a->normal_exp;
- + b_normal_exp = b->normal_exp;
- + a_fraction = a->fraction.ll;
- + b_fraction = b->fraction.ll;
- +
- + diff = a_normal_exp - b_normal_exp;
- +
- + if (diff < 0)
- + diff = -diff;
- + if (diff < FRAC_NBITS)
- + {
- + /* ??? This does shifts one bit at a time. Optimize. */
- + while (a_normal_exp > b_normal_exp)
- + {
- + b_normal_exp++;
- + LSHIFT (b_fraction);
- + }
- + while (b_normal_exp > a_normal_exp)
- + {
- + a_normal_exp++;
- + LSHIFT (a_fraction);
- + }
- + }
- + else
- + {
- + /* Somethings's up.. choose the biggest */
- + if (a_normal_exp > b_normal_exp)
- + {
- + b_normal_exp = a_normal_exp;
- + b_fraction = 0;
- + }
- + else
- + {
- + a_normal_exp = b_normal_exp;
- + a_fraction = 0;
- + }
- + }
- + }
- +
- + if (a->sign != b->sign)
- + {
- + if (a->sign)
- + {
- + tfraction = -a_fraction + b_fraction;
- + }
- + else
- + {
- + tfraction = a_fraction - b_fraction;
- + }
- + if (tfraction >= 0)
- + {
- + tmp->sign = 0;
- + tmp->normal_exp = a_normal_exp;
- + tmp->fraction.ll = tfraction;
- + }
- + else
- + {
- + tmp->sign = 1;
- + tmp->normal_exp = a_normal_exp;
- + tmp->fraction.ll = -tfraction;
- + }
- + /* and renormalize it */
- +
- + while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll)
- + {
- + tmp->fraction.ll <<= 1;
- + tmp->normal_exp--;
- + }
- + }
- + else
- + {
- + tmp->sign = a->sign;
- + tmp->normal_exp = a_normal_exp;
- + tmp->fraction.ll = a_fraction + b_fraction;
- + }
- + tmp->class = CLASS_NUMBER;
- + /* Now the fraction is added, we have to shift down to renormalize the
- + number */
- +
- + if (tmp->fraction.ll >= IMPLICIT_2)
- + {
- + LSHIFT (tmp->fraction.ll);
- + tmp->normal_exp++;
- + }
- + return tmp;
- +
- +}
- +
- +FLO_type
- +add (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + fp_number_type tmp;
- + fp_number_type *res;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + res = _fpadd_parts (&a, &b, &tmp);
- +
- + return pack_d (res);
- +}
- +
- +FLO_type
- +sub (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + fp_number_type tmp;
- + fp_number_type *res;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + b.sign ^= 1;
- +
- + res = _fpadd_parts (&a, &b, &tmp);
- +
- + return pack_d (res);
- +}
- +#endif /* L_addsub_sf || L_addsub_df */
- +
- +#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
- +static inline __attribute__ ((__always_inline__)) fp_number_type *
- +_fpmul_parts ( fp_number_type * a,
- + fp_number_type * b,
- + fp_number_type * tmp)
- +{
- + fractype low = 0;
- + fractype high = 0;
- +
- + if (isnan (a))
- + {
- + a->sign = a->sign != b->sign;
- + return a;
- + }
- + if (isnan (b))
- + {
- + b->sign = a->sign != b->sign;
- + return b;
- + }
- + if (isinf (a))
- + {
- + if (iszero (b))
- + return nan ();
- + a->sign = a->sign != b->sign;
- + return a;
- + }
- + if (isinf (b))
- + {
- + if (iszero (a))
- + {
- + return nan ();
- + }
- + b->sign = a->sign != b->sign;
- + return b;
- + }
- + if (iszero (a))
- + {
- + a->sign = a->sign != b->sign;
- + return a;
- + }
- + if (iszero (b))
- + {
- + b->sign = a->sign != b->sign;
- + return b;
- + }
- +
- + /* Calculate the mantissa by multiplying both numbers to get a
- + twice-as-wide number. */
- + {
- +#if defined(NO_DI_MODE) || defined(TFLOAT)
- + {
- + fractype x = a->fraction.ll;
- + fractype ylow = b->fraction.ll;
- + fractype yhigh = 0;
- + int bit;
- +
- + /* ??? This does multiplies one bit at a time. Optimize. */
- + for (bit = 0; bit < FRAC_NBITS; bit++)
- + {
- + int carry;
- +
- + if (x & 1)
- + {
- + carry = (low += ylow) < ylow;
- + high += yhigh + carry;
- + }
- + yhigh <<= 1;
- + if (ylow & FRACHIGH)
- + {
- + yhigh |= 1;
- + }
- + ylow <<= 1;
- + x >>= 1;
- + }
- + }
- +#elif defined(FLOAT)
- + /* Multiplying two USIs to get a UDI, we're safe. */
- + {
- + UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll;
- +
- + high = answer >> BITS_PER_SI;
- + low = answer;
- + }
- +#else
- + /* fractype is DImode, but we need the result to be twice as wide.
- + Assuming a widening multiply from DImode to TImode is not
- + available, build one by hand. */
- + {
- + USItype nl = a->fraction.ll;
- + USItype nh = a->fraction.ll >> BITS_PER_SI;
- + USItype ml = b->fraction.ll;
- + USItype mh = b->fraction.ll >> BITS_PER_SI;
- + UDItype pp_ll = (UDItype) ml * nl;
- + UDItype pp_hl = (UDItype) mh * nl;
- + UDItype pp_lh = (UDItype) ml * nh;
- + UDItype pp_hh = (UDItype) mh * nh;
- + UDItype res2 = 0;
- + UDItype res0 = 0;
- + UDItype ps_hh__ = pp_hl + pp_lh;
- + if (ps_hh__ < pp_hl)
- + res2 += (UDItype)1 << BITS_PER_SI;
- + pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI;
- + res0 = pp_ll + pp_hl;
- + if (res0 < pp_ll)
- + res2++;
- + res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh;
- + high = res2;
- + low = res0;
- + }
- +#endif
- + }
- +
- + tmp->normal_exp = a->normal_exp + b->normal_exp
- + + FRAC_NBITS - (FRACBITS + NGARDS);
- + tmp->sign = a->sign != b->sign;
- + while (high >= IMPLICIT_2)
- + {
- + tmp->normal_exp++;
- + if (high & 1)
- + {
- + low >>= 1;
- + low |= FRACHIGH;
- + }
- + high >>= 1;
- + }
- + while (high < IMPLICIT_1)
- + {
- + tmp->normal_exp--;
- +
- + high <<= 1;
- + if (low & FRACHIGH)
- + high |= 1;
- + low <<= 1;
- + }
- + /* rounding is tricky. if we only round if it won't make us round later. */
- +#if 0
- + if (low & FRACHIGH2)
- + {
- + if (((high & GARDMASK) != GARDMSB)
- + && (((high + 1) & GARDMASK) == GARDMSB))
- + {
- + /* don't round, it gets done again later. */
- + }
- + else
- + {
- + high++;
- + }
- + }
- +#endif
- + if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
- + {
- + if (high & (1 << NGARDS))
- + {
- + /* half way, so round to even */
- + high += GARDROUND + 1;
- + }
- + else if (low)
- + {
- + /* but we really weren't half way */
- + high += GARDROUND + 1;
- + }
- + }
- + tmp->fraction.ll = high;
- + tmp->class = CLASS_NUMBER;
- + return tmp;
- +}
- +
- +FLO_type
- +multiply (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + fp_number_type tmp;
- + fp_number_type *res;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + res = _fpmul_parts (&a, &b, &tmp);
- +
- + return pack_d (res);
- +}
- +#endif /* L_mul_sf || L_mul_df */
- +
- +#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
- +static inline __attribute__ ((__always_inline__)) fp_number_type *
- +_fpdiv_parts (fp_number_type * a,
- + fp_number_type * b)
- +{
- + fractype bit;
- + fractype numerator;
- + fractype denominator;
- + fractype quotient;
- +
- + if (isnan (a))
- + {
- + return a;
- + }
- + if (isnan (b))
- + {
- + return b;
- + }
- +
- + a->sign = a->sign ^ b->sign;
- +
- + if (isinf (a) || iszero (a))
- + {
- + if (a->class == b->class)
- + return nan ();
- + return a;
- + }
- +
- + if (isinf (b))
- + {
- + a->fraction.ll = 0;
- + a->normal_exp = 0;
- + return a;
- + }
- + if (iszero (b))
- + {
- + a->class = CLASS_INFINITY;
- + return a;
- + }
- +
- + /* Calculate the mantissa by multiplying both 64bit numbers to get a
- + 128 bit number */
- + {
- + /* quotient =
- + ( numerator / denominator) * 2^(numerator exponent - denominator exponent)
- + */
- +
- + a->normal_exp = a->normal_exp - b->normal_exp;
- + numerator = a->fraction.ll;
- + denominator = b->fraction.ll;
- +
- + if (numerator < denominator)
- + {
- + /* Fraction will be less than 1.0 */
- + numerator *= 2;
- + a->normal_exp--;
- + }
- + bit = IMPLICIT_1;
- + quotient = 0;
- + /* ??? Does divide one bit at a time. Optimize. */
- + while (bit)
- + {
- + if (numerator >= denominator)
- + {
- + quotient |= bit;
- + numerator -= denominator;
- + }
- + bit >>= 1;
- + numerator *= 2;
- + }
- +
- + if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
- + {
- + if (quotient & (1 << NGARDS))
- + {
- + /* half way, so round to even */
- + quotient += GARDROUND + 1;
- + }
- + else if (numerator)
- + {
- + /* but we really weren't half way, more bits exist */
- + quotient += GARDROUND + 1;
- + }
- + }
- +
- + a->fraction.ll = quotient;
- + return (a);
- + }
- +}
- +
- +FLO_type
- +divide (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + fp_number_type *res;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + res = _fpdiv_parts (&a, &b);
- +
- + return pack_d (res);
- +}
- +#endif /* L_div_sf || L_div_df */
- +
- +#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
- + || defined(L_fpcmp_parts_tf)
- +/* according to the demo, fpcmp returns a comparison with 0... thus
- + a<b -> -1
- + a==b -> 0
- + a>b -> +1
- + */
- +
- +int
- +__fpcmp_parts (fp_number_type * a, fp_number_type * b)
- +{
- +#if 0
- + /* either nan -> unordered. Must be checked outside of this routine. */
- + if (isnan (a) && isnan (b))
- + {
- + return 1; /* still unordered! */
- + }
- +#endif
- +
- + if (isnan (a) || isnan (b))
- + {
- + return 1; /* how to indicate unordered compare? */
- + }
- + if (isinf (a) && isinf (b))
- + {
- + /* +inf > -inf, but +inf != +inf */
- + /* b \a| +inf(0)| -inf(1)
- + ______\+--------+--------
- + +inf(0)| a==b(0)| a<b(-1)
- + -------+--------+--------
- + -inf(1)| a>b(1) | a==b(0)
- + -------+--------+--------
- + So since unordered must be nonzero, just line up the columns...
- + */
- + return b->sign - a->sign;
- + }
- + /* but not both... */
- + if (isinf (a))
- + {
- + return a->sign ? -1 : 1;
- + }
- + if (isinf (b))
- + {
- + return b->sign ? 1 : -1;
- + }
- + if (iszero (a) && iszero (b))
- + {
- + return 0;
- + }
- + if (iszero (a))
- + {
- + return b->sign ? 1 : -1;
- + }
- + if (iszero (b))
- + {
- + return a->sign ? -1 : 1;
- + }
- + /* now both are "normal". */
- + if (a->sign != b->sign)
- + {
- + /* opposite signs */
- + return a->sign ? -1 : 1;
- + }
- + /* same sign; exponents? */
- + if (a->normal_exp > b->normal_exp)
- + {
- + return a->sign ? -1 : 1;
- + }
- + if (a->normal_exp < b->normal_exp)
- + {
- + return a->sign ? 1 : -1;
- + }
- + /* same exponents; check size. */
- + if (a->fraction.ll > b->fraction.ll)
- + {
- + return a->sign ? -1 : 1;
- + }
- + if (a->fraction.ll < b->fraction.ll)
- + {
- + return a->sign ? 1 : -1;
- + }
- + /* after all that, they're equal. */
- + return 0;
- +}
- +#endif
- +
- +#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
- +CMPtype
- +compare (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + return __fpcmp_parts (&a, &b);
- +}
- +#endif /* L_compare_sf || L_compare_df */
- +
- +#ifndef US_SOFTWARE_GOFAST
- +
- +/* These should be optimized for their specific tasks someday. */
- +
- +#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
- +CMPtype
- +_eq_f2 (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + if (isnan (&a) || isnan (&b))
- + return 1; /* false, truth == 0 */
- +
- + return __fpcmp_parts (&a, &b) ;
- +}
- +#endif /* L_eq_sf || L_eq_df */
- +
- +#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
- +CMPtype
- +_ne_f2 (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + if (isnan (&a) || isnan (&b))
- + return 1; /* true, truth != 0 */
- +
- + return __fpcmp_parts (&a, &b) ;
- +}
- +#endif /* L_ne_sf || L_ne_df */
- +
- +#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
- +CMPtype
- +_gt_f2 (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + if (isnan (&a) || isnan (&b))
- + return -1; /* false, truth > 0 */
- +
- + return __fpcmp_parts (&a, &b);
- +}
- +#endif /* L_gt_sf || L_gt_df */
- +
- +#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
- +CMPtype
- +_ge_f2 (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + if (isnan (&a) || isnan (&b))
- + return -1; /* false, truth >= 0 */
- + return __fpcmp_parts (&a, &b) ;
- +}
- +#endif /* L_ge_sf || L_ge_df */
- +
- +#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
- +CMPtype
- +_lt_f2 (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + if (isnan (&a) || isnan (&b))
- + return 1; /* false, truth < 0 */
- +
- + return __fpcmp_parts (&a, &b);
- +}
- +#endif /* L_lt_sf || L_lt_df */
- +
- +#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
- +CMPtype
- +_le_f2 (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + if (isnan (&a) || isnan (&b))
- + return 1; /* false, truth <= 0 */
- +
- + return __fpcmp_parts (&a, &b) ;
- +}
- +#endif /* L_le_sf || L_le_df */
- +
- +#endif /* ! US_SOFTWARE_GOFAST */
- +
- +#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
- +CMPtype
- +_unord_f2 (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + return (isnan (&a) || isnan (&b));
- +}
- +#endif /* L_unord_sf || L_unord_df */
- +
- +#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
- +FLO_type
- +si_to_float (SItype arg_a)
- +{
- + fp_number_type in;
- +
- + in.class = CLASS_NUMBER;
- + in.sign = arg_a < 0;
- + if (!arg_a)
- + {
- + in.class = CLASS_ZERO;
- + }
- + else
- + {
- + in.normal_exp = FRACBITS + NGARDS;
- + if (in.sign)
- + {
- + /* Special case for minint, since there is no +ve integer
- + representation for it */
- + if (arg_a == (- MAX_SI_INT - 1))
- + {
- + return (FLO_type)(- MAX_SI_INT - 1);
- + }
- + in.fraction.ll = (-arg_a);
- + }
- + else
- + in.fraction.ll = arg_a;
- +
- + while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
- + {
- + in.fraction.ll <<= 1;
- + in.normal_exp -= 1;
- + }
- + }
- + return pack_d (&in);
- +}
- +#endif /* L_si_to_sf || L_si_to_df */
- +
- +#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
- +FLO_type
- +usi_to_float (USItype arg_a)
- +{
- + fp_number_type in;
- +
- + in.sign = 0;
- + if (!arg_a)
- + {
- + in.class = CLASS_ZERO;
- + }
- + else
- + {
- + in.class = CLASS_NUMBER;
- + in.normal_exp = FRACBITS + NGARDS;
- + in.fraction.ll = arg_a;
- +
- + while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS)))
- + {
- + in.fraction.ll >>= 1;
- + in.normal_exp += 1;
- + }
- + while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
- + {
- + in.fraction.ll <<= 1;
- + in.normal_exp -= 1;
- + }
- + }
- + return pack_d (&in);
- +}
- +#endif
- +
- +#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
- +SItype
- +float_to_si (FLO_type arg_a)
- +{
- + fp_number_type a;
- + SItype tmp;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &a);
- +
- + if (iszero (&a))
- + return 0;
- + if (isnan (&a))
- + return 0;
- + /* get reasonable MAX_SI_INT... */
- + if (isinf (&a))
- + return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
- + /* it is a number, but a small one */
- + if (a.normal_exp < 0)
- + return 0;
- + if (a.normal_exp > BITS_PER_SI - 2)
- + return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
- + tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
- + return a.sign ? (-tmp) : (tmp);
- +}
- +#endif /* L_sf_to_si || L_df_to_si */
- +
- +#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
- +#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi)
- +/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
- + we also define them for GOFAST because the ones in libgcc2.c have the
- + wrong names and I'd rather define these here and keep GOFAST CYG-LOC's
- + out of libgcc2.c. We can't define these here if not GOFAST because then
- + there'd be duplicate copies. */
- +
- +USItype
- +float_to_usi (FLO_type arg_a)
- +{
- + fp_number_type a;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &a);
- +
- + if (iszero (&a))
- + return 0;
- + if (isnan (&a))
- + return 0;
- + /* it is a negative number */
- + if (a.sign)
- + return 0;
- + /* get reasonable MAX_USI_INT... */
- + if (isinf (&a))
- + return MAX_USI_INT;
- + /* it is a number, but a small one */
- + if (a.normal_exp < 0)
- + return 0;
- + if (a.normal_exp > BITS_PER_SI - 1)
- + return MAX_USI_INT;
- + else if (a.normal_exp > (FRACBITS + NGARDS))
- + return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS));
- + else
- + return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
- +}
- +#endif /* US_SOFTWARE_GOFAST */
- +#endif /* L_sf_to_usi || L_df_to_usi */
- +
- +#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
- +FLO_type
- +negate (FLO_type arg_a)
- +{
- + fp_number_type a;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &a);
- +
- + flip_sign (&a);
- + return pack_d (&a);
- +}
- +#endif /* L_negate_sf || L_negate_df */
- +
- +#ifdef FLOAT
- +
- +#if defined(L_make_sf)
- +SFtype
- +__make_fp(fp_class_type class,
- + unsigned int sign,
- + int exp,
- + USItype frac)
- +{
- + fp_number_type in;
- +
- + in.class = class;
- + in.sign = sign;
- + in.normal_exp = exp;
- + in.fraction.ll = frac;
- + return pack_d (&in);
- +}
- +#endif /* L_make_sf */
- +
- +#ifndef FLOAT_ONLY
- +
- +/* This enables one to build an fp library that supports float but not double.
- + Otherwise, we would get an undefined reference to __make_dp.
- + This is needed for some 8-bit ports that can't handle well values that
- + are 8-bytes in size, so we just don't support double for them at all. */
- +
- +#if defined(L_sf_to_df)
- +DFtype
- +sf_to_df (SFtype arg_a)
- +{
- + fp_number_type in;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &in);
- +
- + return __make_dp (in.class, in.sign, in.normal_exp,
- + ((UDItype) in.fraction.ll) << F_D_BITOFF);
- +}
- +#endif /* L_sf_to_df */
- +
- +#if defined(L_sf_to_tf) && defined(TMODES)
- +TFtype
- +sf_to_tf (SFtype arg_a)
- +{
- + fp_number_type in;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &in);
- +
- + return __make_tp (in.class, in.sign, in.normal_exp,
- + ((UTItype) in.fraction.ll) << F_T_BITOFF);
- +}
- +#endif /* L_sf_to_df */
- +
- +#endif /* ! FLOAT_ONLY */
- +#endif /* FLOAT */
- +
- +#ifndef FLOAT
- +
- +extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);
- +
- +#if defined(L_make_df)
- +DFtype
- +__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac)
- +{
- + fp_number_type in;
- +
- + in.class = class;
- + in.sign = sign;
- + in.normal_exp = exp;
- + in.fraction.ll = frac;
- + return pack_d (&in);
- +}
- +#endif /* L_make_df */
- +
- +#if defined(L_df_to_sf)
- +SFtype
- +df_to_sf (DFtype arg_a)
- +{
- + fp_number_type in;
- + USItype sffrac;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &in);
- +
- + sffrac = in.fraction.ll >> F_D_BITOFF;
- +
- + /* We set the lowest guard bit in SFFRAC if we discarded any non
- + zero bits. */
- + if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0)
- + sffrac |= 1;
- +
- + return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
- +}
- +#endif /* L_df_to_sf */
- +
- +#if defined(L_df_to_tf) && defined(TMODES) \
- + && !defined(FLOAT) && !defined(TFLOAT)
- +TFtype
- +df_to_tf (DFtype arg_a)
- +{
- + fp_number_type in;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &in);
- +
- + return __make_tp (in.class, in.sign, in.normal_exp,
- + ((UTItype) in.fraction.ll) << D_T_BITOFF);
- +}
- +#endif /* L_sf_to_df */
- +
- +#ifdef TFLOAT
- +#if defined(L_make_tf)
- +TFtype
- +__make_tp(fp_class_type class,
- + unsigned int sign,
- + int exp,
- + UTItype frac)
- +{
- + fp_number_type in;
- +
- + in.class = class;
- + in.sign = sign;
- + in.normal_exp = exp;
- + in.fraction.ll = frac;
- + return pack_d (&in);
- +}
- +#endif /* L_make_tf */
- +
- +#if defined(L_tf_to_df)
- +DFtype
- +tf_to_df (TFtype arg_a)
- +{
- + fp_number_type in;
- + UDItype sffrac;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &in);
- +
- + sffrac = in.fraction.ll >> D_T_BITOFF;
- +
- + /* We set the lowest guard bit in SFFRAC if we discarded any non
- + zero bits. */
- + if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0)
- + sffrac |= 1;
- +
- + return __make_dp (in.class, in.sign, in.normal_exp, sffrac);
- +}
- +#endif /* L_tf_to_df */
- +
- +#if defined(L_tf_to_sf)
- +SFtype
- +tf_to_sf (TFtype arg_a)
- +{
- + fp_number_type in;
- + USItype sffrac;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &in);
- +
- + sffrac = in.fraction.ll >> F_T_BITOFF;
- +
- + /* We set the lowest guard bit in SFFRAC if we discarded any non
- + zero bits. */
- + if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0)
- + sffrac |= 1;
- +
- + return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
- +}
- +#endif /* L_tf_to_sf */
- +#endif /* TFLOAT */
- +
- +#endif /* ! FLOAT */
- +#endif /* !EXTENDED_FLOAT_STUBS */
- diff --git a/gcc/config/nios2/nios2-fp-bit.c b/gcc/config/nios2/nios2-fp-bit.c
- new file mode 100644
- index 0000000..839ffcc
- --- /dev/null
- +++ b/gcc/config/nios2/nios2-fp-bit.c
- @@ -0,0 +1,1655 @@
- +#define FLOAT
- +#ifndef __nios2_big_endian__
- +#define FLOAT_BIT_ORDER_MISMATCH
- +#endif
- +/* This is a software floating point library which can be used
- + for targets without hardware floating point.
- + Copyright (C) 1994, 1995, 1996, 1997, 1998, 2000, 2001, 2002, 2003, 2004
- + Free Software Foundation, Inc.
- +
- +This file 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 2, or (at your option) any
- +later version.
- +
- +In addition to the permissions in the GNU General Public License, the
- +Free Software Foundation gives you unlimited permission to link the
- +compiled version of this file with other programs, and to distribute
- +those programs without any restriction coming from the use of this
- +file. (The General Public License restrictions do apply in other
- +respects; for example, they cover modification of the file, and
- +distribution when not linked into another program.)
- +
- +This file 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 this program; see the file COPYING. If not, write to
- +the Free Software Foundation, 59 Temple Place - Suite 330,
- +Boston, MA 02111-1307, USA. */
- +
- +/* As a special exception, if you link this library with other files,
- + some of which are compiled with GCC, to produce an executable,
- + this library does not by itself cause the resulting executable
- + to be covered by the GNU General Public License.
- + This exception does not however invalidate any other reasons why
- + the executable file might be covered by the GNU General Public License. */
- +
- +/* This implements IEEE 754 format arithmetic, but does not provide a
- + mechanism for setting the rounding mode, or for generating or handling
- + exceptions.
- +
- + The original code by Steve Chamberlain, hacked by Mark Eichin and Jim
- + Wilson, all of Cygnus Support. */
- +
- +/* The intended way to use this file is to make two copies, add `#define FLOAT'
- + to one copy, then compile both copies and add them to libgcc.a. */
- +
- +#include "tconfig.h"
- +#include "coretypes.h"
- +#include "tm.h"
- +#include "config/fp-bit.h"
- +
- +/* The following macros can be defined to change the behavior of this file:
- + FLOAT: Implement a `float', aka SFmode, fp library. If this is not
- + defined, then this file implements a `double', aka DFmode, fp library.
- + FLOAT_ONLY: Used with FLOAT, to implement a `float' only library, i.e.
- + don't include float->double conversion which requires the double library.
- + This is useful only for machines which can't support doubles, e.g. some
- + 8-bit processors.
- + CMPtype: Specify the type that floating point compares should return.
- + This defaults to SItype, aka int.
- + US_SOFTWARE_GOFAST: This makes all entry points use the same names as the
- + US Software goFast library.
- + _DEBUG_BITFLOAT: This makes debugging the code a little easier, by adding
- + two integers to the FLO_union_type.
- + NO_DENORMALS: Disable handling of denormals.
- + NO_NANS: Disable nan and infinity handling
- + SMALL_MACHINE: Useful when operations on QIs and HIs are faster
- + than on an SI */
- +
- +/* We don't currently support extended floats (long doubles) on machines
- + without hardware to deal with them.
- +
- + These stubs are just to keep the linker from complaining about unresolved
- + references which can be pulled in from libio & libstdc++, even if the
- + user isn't using long doubles. However, they may generate an unresolved
- + external to abort if abort is not used by the function, and the stubs
- + are referenced from within libc, since libgcc goes before and after the
- + system library. */
- +
- +#ifdef DECLARE_LIBRARY_RENAMES
- + DECLARE_LIBRARY_RENAMES
- +#endif
- +
- +#ifdef EXTENDED_FLOAT_STUBS
- +extern void abort (void);
- +void __extendsfxf2 (void) { abort(); }
- +void __extenddfxf2 (void) { abort(); }
- +void __truncxfdf2 (void) { abort(); }
- +void __truncxfsf2 (void) { abort(); }
- +void __fixxfsi (void) { abort(); }
- +void __floatsixf (void) { abort(); }
- +void __addxf3 (void) { abort(); }
- +void __subxf3 (void) { abort(); }
- +void __mulxf3 (void) { abort(); }
- +void __divxf3 (void) { abort(); }
- +void __negxf2 (void) { abort(); }
- +void __eqxf2 (void) { abort(); }
- +void __nexf2 (void) { abort(); }
- +void __gtxf2 (void) { abort(); }
- +void __gexf2 (void) { abort(); }
- +void __lexf2 (void) { abort(); }
- +void __ltxf2 (void) { abort(); }
- +
- +void __extendsftf2 (void) { abort(); }
- +void __extenddftf2 (void) { abort(); }
- +void __trunctfdf2 (void) { abort(); }
- +void __trunctfsf2 (void) { abort(); }
- +void __fixtfsi (void) { abort(); }
- +void __floatsitf (void) { abort(); }
- +void __addtf3 (void) { abort(); }
- +void __subtf3 (void) { abort(); }
- +void __multf3 (void) { abort(); }
- +void __divtf3 (void) { abort(); }
- +void __negtf2 (void) { abort(); }
- +void __eqtf2 (void) { abort(); }
- +void __netf2 (void) { abort(); }
- +void __gttf2 (void) { abort(); }
- +void __getf2 (void) { abort(); }
- +void __letf2 (void) { abort(); }
- +void __lttf2 (void) { abort(); }
- +#else /* !EXTENDED_FLOAT_STUBS, rest of file */
- +
- +/* IEEE "special" number predicates */
- +
- +#ifdef NO_NANS
- +
- +#define nan() 0
- +#define isnan(x) 0
- +#define isinf(x) 0
- +#else
- +
- +#if defined L_thenan_sf
- +const fp_number_type __thenan_sf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
- +#elif defined L_thenan_df
- +const fp_number_type __thenan_df = { CLASS_SNAN, 0, 0, {(fractype) 0} };
- +#elif defined L_thenan_tf
- +const fp_number_type __thenan_tf = { CLASS_SNAN, 0, 0, {(fractype) 0} };
- +#elif defined TFLOAT
- +extern const fp_number_type __thenan_tf;
- +#elif defined FLOAT
- +extern const fp_number_type __thenan_sf;
- +#else
- +extern const fp_number_type __thenan_df;
- +#endif
- +
- +INLINE
- +static fp_number_type *
- +nan (void)
- +{
- + /* Discard the const qualifier... */
- +#ifdef TFLOAT
- + return (fp_number_type *) (& __thenan_tf);
- +#elif defined FLOAT
- + return (fp_number_type *) (& __thenan_sf);
- +#else
- + return (fp_number_type *) (& __thenan_df);
- +#endif
- +}
- +
- +INLINE
- +static int
- +isnan ( fp_number_type * x)
- +{
- + return x->class == CLASS_SNAN || x->class == CLASS_QNAN;
- +}
- +
- +INLINE
- +static int
- +isinf ( fp_number_type * x)
- +{
- + return x->class == CLASS_INFINITY;
- +}
- +
- +#endif /* NO_NANS */
- +
- +INLINE
- +static int
- +iszero ( fp_number_type * x)
- +{
- + return x->class == CLASS_ZERO;
- +}
- +
- +INLINE
- +static void
- +flip_sign ( fp_number_type * x)
- +{
- + x->sign = !x->sign;
- +}
- +
- +extern FLO_type pack_d ( fp_number_type * );
- +
- +#if defined(L_pack_df) || defined(L_pack_sf) || defined(L_pack_tf)
- +FLO_type
- +pack_d ( fp_number_type * src)
- +{
- + FLO_union_type dst;
- + fractype fraction = src->fraction.ll; /* wasn't unsigned before? */
- + int sign = src->sign;
- + int exp = 0;
- +
- + if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && (isnan (src) || isinf (src)))
- + {
- + /* We can't represent these values accurately. By using the
- + largest possible magnitude, we guarantee that the conversion
- + of infinity is at least as big as any finite number. */
- + exp = EXPMAX;
- + fraction = ((fractype) 1 << FRACBITS) - 1;
- + }
- + else if (isnan (src))
- + {
- + exp = EXPMAX;
- + if (src->class == CLASS_QNAN || 1)
- + {
- +#ifdef QUIET_NAN_NEGATED
- + fraction |= QUIET_NAN - 1;
- +#else
- + fraction |= QUIET_NAN;
- +#endif
- + }
- + }
- + else if (isinf (src))
- + {
- + exp = EXPMAX;
- + fraction = 0;
- + }
- + else if (iszero (src))
- + {
- + exp = 0;
- + fraction = 0;
- + }
- + else if (fraction == 0)
- + {
- + exp = 0;
- + }
- + else
- + {
- + if (src->normal_exp < NORMAL_EXPMIN)
- + {
- +#ifdef NO_DENORMALS
- + /* Go straight to a zero representation if denormals are not
- + supported. The denormal handling would be harmless but
- + isn't unnecessary. */
- + exp = 0;
- + fraction = 0;
- +#else /* NO_DENORMALS */
- + /* This number's exponent is too low to fit into the bits
- + available in the number, so we'll store 0 in the exponent and
- + shift the fraction to the right to make up for it. */
- +
- + int shift = NORMAL_EXPMIN - src->normal_exp;
- +
- + exp = 0;
- +
- + if (shift > FRAC_NBITS - NGARDS)
- + {
- + /* No point shifting, since it's more that 64 out. */
- + fraction = 0;
- + }
- + else
- + {
- + int lowbit = (fraction & (((fractype)1 << shift) - 1)) ? 1 : 0;
- + fraction = (fraction >> shift) | lowbit;
- + }
- + if ((fraction & GARDMASK) == GARDMSB)
- + {
- + if ((fraction & (1 << NGARDS)))
- + fraction += GARDROUND + 1;
- + }
- + else
- + {
- + /* Add to the guards to round up. */
- + fraction += GARDROUND;
- + }
- + /* Perhaps the rounding means we now need to change the
- + exponent, because the fraction is no longer denormal. */
- + if (fraction >= IMPLICIT_1)
- + {
- + exp += 1;
- + }
- + fraction >>= NGARDS;
- +#endif /* NO_DENORMALS */
- + }
- + else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS)
- + && src->normal_exp > EXPBIAS)
- + {
- + exp = EXPMAX;
- + fraction = 0;
- + }
- + else
- + {
- + exp = src->normal_exp + EXPBIAS;
- + if (!ROUND_TOWARDS_ZERO)
- + {
- + /* IF the gard bits are the all zero, but the first, then we're
- + half way between two numbers, choose the one which makes the
- + lsb of the answer 0. */
- + if ((fraction & GARDMASK) == GARDMSB)
- + {
- + if (fraction & (1 << NGARDS))
- + fraction += GARDROUND + 1;
- + }
- + else
- + {
- + /* Add a one to the guards to round up */
- + fraction += GARDROUND;
- + }
- + if (fraction >= IMPLICIT_2)
- + {
- + fraction >>= 1;
- + exp += 1;
- + }
- + }
- + fraction >>= NGARDS;
- +
- + if (LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp > EXPMAX)
- + {
- + /* Saturate on overflow. */
- + exp = EXPMAX;
- + fraction = ((fractype) 1 << FRACBITS) - 1;
- + }
- + }
- + }
- +
- + /* We previously used bitfields to store the number, but this doesn't
- + handle little/big endian systems conveniently, so use shifts and
- + masks */
- +#ifdef FLOAT_BIT_ORDER_MISMATCH
- + dst.bits.fraction = fraction;
- + dst.bits.exp = exp;
- + dst.bits.sign = sign;
- +#else
- +# if defined TFLOAT && defined HALFFRACBITS
- + {
- + halffractype high, low, unity;
- + int lowsign, lowexp;
- +
- + unity = (halffractype) 1 << HALFFRACBITS;
- +
- + /* Set HIGH to the high double's significand, masking out the implicit 1.
- + Set LOW to the low double's full significand. */
- + high = (fraction >> (FRACBITS - HALFFRACBITS)) & (unity - 1);
- + low = fraction & (unity * 2 - 1);
- +
- + /* Get the initial sign and exponent of the low double. */
- + lowexp = exp - HALFFRACBITS - 1;
- + lowsign = sign;
- +
- + /* HIGH should be rounded like a normal double, making |LOW| <=
- + 0.5 ULP of HIGH. Assume round-to-nearest. */
- + if (exp < EXPMAX)
- + if (low > unity || (low == unity && (high & 1) == 1))
- + {
- + /* Round HIGH up and adjust LOW to match. */
- + high++;
- + if (high == unity)
- + {
- + /* May make it infinite, but that's OK. */
- + high = 0;
- + exp++;
- + }
- + low = unity * 2 - low;
- + lowsign ^= 1;
- + }
- +
- + high |= (halffractype) exp << HALFFRACBITS;
- + high |= (halffractype) sign << (HALFFRACBITS + EXPBITS);
- +
- + if (exp == EXPMAX || exp == 0 || low == 0)
- + low = 0;
- + else
- + {
- + while (lowexp > 0 && low < unity)
- + {
- + low <<= 1;
- + lowexp--;
- + }
- +
- + if (lowexp <= 0)
- + {
- + halffractype roundmsb, round;
- + int shift;
- +
- + shift = 1 - lowexp;
- + roundmsb = (1 << (shift - 1));
- + round = low & ((roundmsb << 1) - 1);
- +
- + low >>= shift;
- + lowexp = 0;
- +
- + if (round > roundmsb || (round == roundmsb && (low & 1) == 1))
- + {
- + low++;
- + if (low == unity)
- + /* LOW rounds up to the smallest normal number. */
- + lowexp++;
- + }
- + }
- +
- + low &= unity - 1;
- + low |= (halffractype) lowexp << HALFFRACBITS;
- + low |= (halffractype) lowsign << (HALFFRACBITS + EXPBITS);
- + }
- + dst.value_raw = ((fractype) high << HALFSHIFT) | low;
- + }
- +# else
- + dst.value_raw = fraction & ((((fractype)1) << FRACBITS) - (fractype)1);
- + dst.value_raw |= ((fractype) (exp & ((1 << EXPBITS) - 1))) << FRACBITS;
- + dst.value_raw |= ((fractype) (sign & 1)) << (FRACBITS | EXPBITS);
- +# endif
- +#endif
- +
- +#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
- +#ifdef TFLOAT
- + {
- + qrtrfractype tmp1 = dst.words[0];
- + qrtrfractype tmp2 = dst.words[1];
- + dst.words[0] = dst.words[3];
- + dst.words[1] = dst.words[2];
- + dst.words[2] = tmp2;
- + dst.words[3] = tmp1;
- + }
- +#else
- + {
- + halffractype tmp = dst.words[0];
- + dst.words[0] = dst.words[1];
- + dst.words[1] = tmp;
- + }
- +#endif
- +#endif
- +
- + return dst.value;
- +}
- +#endif
- +
- +#if defined(L_unpack_df) || defined(L_unpack_sf) || defined(L_unpack_tf)
- +void
- +unpack_d (FLO_union_type * src, fp_number_type * dst)
- +{
- + /* We previously used bitfields to store the number, but this doesn't
- + handle little/big endian systems conveniently, so use shifts and
- + masks */
- + fractype fraction;
- + int exp;
- + int sign;
- +
- +#if defined(FLOAT_WORD_ORDER_MISMATCH) && !defined(FLOAT)
- + FLO_union_type swapped;
- +
- +#ifdef TFLOAT
- + swapped.words[0] = src->words[3];
- + swapped.words[1] = src->words[2];
- + swapped.words[2] = src->words[1];
- + swapped.words[3] = src->words[0];
- +#else
- + swapped.words[0] = src->words[1];
- + swapped.words[1] = src->words[0];
- +#endif
- + src = &swapped;
- +#endif
- +
- +#ifdef FLOAT_BIT_ORDER_MISMATCH
- + fraction = src->bits.fraction;
- + exp = src->bits.exp;
- + sign = src->bits.sign;
- +#else
- +# if defined TFLOAT && defined HALFFRACBITS
- + {
- + halffractype high, low;
- +
- + high = src->value_raw >> HALFSHIFT;
- + low = src->value_raw & (((fractype)1 << HALFSHIFT) - 1);
- +
- + fraction = high & ((((fractype)1) << HALFFRACBITS) - 1);
- + fraction <<= FRACBITS - HALFFRACBITS;
- + exp = ((int)(high >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
- + sign = ((int)(high >> (((HALFFRACBITS + EXPBITS))))) & 1;
- +
- + if (exp != EXPMAX && exp != 0 && low != 0)
- + {
- + int lowexp = ((int)(low >> HALFFRACBITS)) & ((1 << EXPBITS) - 1);
- + int lowsign = ((int)(low >> (((HALFFRACBITS + EXPBITS))))) & 1;
- + int shift;
- + fractype xlow;
- +
- + xlow = low & ((((fractype)1) << HALFFRACBITS) - 1);
- + if (lowexp)
- + xlow |= (((halffractype)1) << HALFFRACBITS);
- + else
- + lowexp = 1;
- + shift = (FRACBITS - HALFFRACBITS) - (exp - lowexp);
- + if (shift > 0)
- + xlow <<= shift;
- + else if (shift < 0)
- + xlow >>= -shift;
- + if (sign == lowsign)
- + fraction += xlow;
- + else if (fraction >= xlow)
- + fraction -= xlow;
- + else
- + {
- + /* The high part is a power of two but the full number is lower.
- + This code will leave the implicit 1 in FRACTION, but we'd
- + have added that below anyway. */
- + fraction = (((fractype) 1 << FRACBITS) - xlow) << 1;
- + exp--;
- + }
- + }
- + }
- +# else
- + fraction = src->value_raw & ((((fractype)1) << FRACBITS) - 1);
- + exp = ((int)(src->value_raw >> FRACBITS)) & ((1 << EXPBITS) - 1);
- + sign = ((int)(src->value_raw >> (FRACBITS + EXPBITS))) & 1;
- +# endif
- +#endif
- +
- + dst->sign = sign;
- + if (exp == 0)
- + {
- + /* Hmm. Looks like 0 */
- + if (fraction == 0
- +#ifdef NO_DENORMALS
- + || 1
- +#endif
- + )
- + {
- + /* tastes like zero */
- + dst->class = CLASS_ZERO;
- + }
- + else
- + {
- + /* Zero exponent with nonzero fraction - it's denormalized,
- + so there isn't a leading implicit one - we'll shift it so
- + it gets one. */
- + dst->normal_exp = exp - EXPBIAS + 1;
- + fraction <<= NGARDS;
- +
- + dst->class = CLASS_NUMBER;
- +#if 1
- + while (fraction < IMPLICIT_1)
- + {
- + fraction <<= 1;
- + dst->normal_exp--;
- + }
- +#endif
- + dst->fraction.ll = fraction;
- + }
- + }
- + else if (!LARGEST_EXPONENT_IS_NORMAL (FRAC_NBITS) && exp == EXPMAX)
- + {
- + /* Huge exponent*/
- + if (fraction == 0)
- + {
- + /* Attached to a zero fraction - means infinity */
- + dst->class = CLASS_INFINITY;
- + }
- + else
- + {
- + /* Nonzero fraction, means nan */
- +#ifdef QUIET_NAN_NEGATED
- + if ((fraction & QUIET_NAN) == 0)
- +#else
- + if (fraction & QUIET_NAN)
- +#endif
- + {
- + dst->class = CLASS_QNAN;
- + }
- + else
- + {
- + dst->class = CLASS_SNAN;
- + }
- + /* Keep the fraction part as the nan number */
- + dst->fraction.ll = fraction;
- + }
- + }
- + else
- + {
- + /* Nothing strange about this number */
- + dst->normal_exp = exp - EXPBIAS;
- + dst->class = CLASS_NUMBER;
- + dst->fraction.ll = (fraction << NGARDS) | IMPLICIT_1;
- + }
- +}
- +#endif /* L_unpack_df || L_unpack_sf */
- +
- +#if defined(L_addsub_sf) || defined(L_addsub_df) || defined(L_addsub_tf)
- +static fp_number_type *
- +_fpadd_parts (fp_number_type * a,
- + fp_number_type * b,
- + fp_number_type * tmp)
- +{
- + intfrac tfraction;
- +
- + /* Put commonly used fields in local variables. */
- + int a_normal_exp;
- + int b_normal_exp;
- + fractype a_fraction;
- + fractype b_fraction;
- +
- + if (isnan (a))
- + {
- + return a;
- + }
- + if (isnan (b))
- + {
- + return b;
- + }
- + if (isinf (a))
- + {
- + /* Adding infinities with opposite signs yields a NaN. */
- + if (isinf (b) && a->sign != b->sign)
- + return nan ();
- + return a;
- + }
- + if (isinf (b))
- + {
- + return b;
- + }
- + if (iszero (b))
- + {
- + if (iszero (a))
- + {
- + *tmp = *a;
- + tmp->sign = a->sign & b->sign;
- + return tmp;
- + }
- + return a;
- + }
- + if (iszero (a))
- + {
- + return b;
- + }
- +
- + /* Got two numbers. shift the smaller and increment the exponent till
- + they're the same */
- + {
- + int diff;
- +
- + a_normal_exp = a->normal_exp;
- + b_normal_exp = b->normal_exp;
- + a_fraction = a->fraction.ll;
- + b_fraction = b->fraction.ll;
- +
- + diff = a_normal_exp - b_normal_exp;
- +
- + if (diff < 0)
- + diff = -diff;
- + if (diff < FRAC_NBITS)
- + {
- + /* ??? This does shifts one bit at a time. Optimize. */
- + while (a_normal_exp > b_normal_exp)
- + {
- + b_normal_exp++;
- + LSHIFT (b_fraction);
- + }
- + while (b_normal_exp > a_normal_exp)
- + {
- + a_normal_exp++;
- + LSHIFT (a_fraction);
- + }
- + }
- + else
- + {
- + /* Somethings's up.. choose the biggest */
- + if (a_normal_exp > b_normal_exp)
- + {
- + b_normal_exp = a_normal_exp;
- + b_fraction = 0;
- + }
- + else
- + {
- + a_normal_exp = b_normal_exp;
- + a_fraction = 0;
- + }
- + }
- + }
- +
- + if (a->sign != b->sign)
- + {
- + if (a->sign)
- + {
- + tfraction = -a_fraction + b_fraction;
- + }
- + else
- + {
- + tfraction = a_fraction - b_fraction;
- + }
- + if (tfraction >= 0)
- + {
- + tmp->sign = 0;
- + tmp->normal_exp = a_normal_exp;
- + tmp->fraction.ll = tfraction;
- + }
- + else
- + {
- + tmp->sign = 1;
- + tmp->normal_exp = a_normal_exp;
- + tmp->fraction.ll = -tfraction;
- + }
- + /* and renormalize it */
- +
- + while (tmp->fraction.ll < IMPLICIT_1 && tmp->fraction.ll)
- + {
- + tmp->fraction.ll <<= 1;
- + tmp->normal_exp--;
- + }
- + }
- + else
- + {
- + tmp->sign = a->sign;
- + tmp->normal_exp = a_normal_exp;
- + tmp->fraction.ll = a_fraction + b_fraction;
- + }
- + tmp->class = CLASS_NUMBER;
- + /* Now the fraction is added, we have to shift down to renormalize the
- + number */
- +
- + if (tmp->fraction.ll >= IMPLICIT_2)
- + {
- + LSHIFT (tmp->fraction.ll);
- + tmp->normal_exp++;
- + }
- + return tmp;
- +
- +}
- +
- +FLO_type
- +add (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + fp_number_type tmp;
- + fp_number_type *res;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + res = _fpadd_parts (&a, &b, &tmp);
- +
- + return pack_d (res);
- +}
- +
- +FLO_type
- +sub (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + fp_number_type tmp;
- + fp_number_type *res;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + b.sign ^= 1;
- +
- + res = _fpadd_parts (&a, &b, &tmp);
- +
- + return pack_d (res);
- +}
- +#endif /* L_addsub_sf || L_addsub_df */
- +
- +#if defined(L_mul_sf) || defined(L_mul_df) || defined(L_mul_tf)
- +static inline __attribute__ ((__always_inline__)) fp_number_type *
- +_fpmul_parts ( fp_number_type * a,
- + fp_number_type * b,
- + fp_number_type * tmp)
- +{
- + fractype low = 0;
- + fractype high = 0;
- +
- + if (isnan (a))
- + {
- + a->sign = a->sign != b->sign;
- + return a;
- + }
- + if (isnan (b))
- + {
- + b->sign = a->sign != b->sign;
- + return b;
- + }
- + if (isinf (a))
- + {
- + if (iszero (b))
- + return nan ();
- + a->sign = a->sign != b->sign;
- + return a;
- + }
- + if (isinf (b))
- + {
- + if (iszero (a))
- + {
- + return nan ();
- + }
- + b->sign = a->sign != b->sign;
- + return b;
- + }
- + if (iszero (a))
- + {
- + a->sign = a->sign != b->sign;
- + return a;
- + }
- + if (iszero (b))
- + {
- + b->sign = a->sign != b->sign;
- + return b;
- + }
- +
- + /* Calculate the mantissa by multiplying both numbers to get a
- + twice-as-wide number. */
- + {
- +#if defined(NO_DI_MODE) || defined(TFLOAT)
- + {
- + fractype x = a->fraction.ll;
- + fractype ylow = b->fraction.ll;
- + fractype yhigh = 0;
- + int bit;
- +
- + /* ??? This does multiplies one bit at a time. Optimize. */
- + for (bit = 0; bit < FRAC_NBITS; bit++)
- + {
- + int carry;
- +
- + if (x & 1)
- + {
- + carry = (low += ylow) < ylow;
- + high += yhigh + carry;
- + }
- + yhigh <<= 1;
- + if (ylow & FRACHIGH)
- + {
- + yhigh |= 1;
- + }
- + ylow <<= 1;
- + x >>= 1;
- + }
- + }
- +#elif defined(FLOAT)
- + /* Multiplying two USIs to get a UDI, we're safe. */
- + {
- + UDItype answer = (UDItype)a->fraction.ll * (UDItype)b->fraction.ll;
- +
- + high = answer >> BITS_PER_SI;
- + low = answer;
- + }
- +#else
- + /* fractype is DImode, but we need the result to be twice as wide.
- + Assuming a widening multiply from DImode to TImode is not
- + available, build one by hand. */
- + {
- + USItype nl = a->fraction.ll;
- + USItype nh = a->fraction.ll >> BITS_PER_SI;
- + USItype ml = b->fraction.ll;
- + USItype mh = b->fraction.ll >> BITS_PER_SI;
- + UDItype pp_ll = (UDItype) ml * nl;
- + UDItype pp_hl = (UDItype) mh * nl;
- + UDItype pp_lh = (UDItype) ml * nh;
- + UDItype pp_hh = (UDItype) mh * nh;
- + UDItype res2 = 0;
- + UDItype res0 = 0;
- + UDItype ps_hh__ = pp_hl + pp_lh;
- + if (ps_hh__ < pp_hl)
- + res2 += (UDItype)1 << BITS_PER_SI;
- + pp_hl = (UDItype)(USItype)ps_hh__ << BITS_PER_SI;
- + res0 = pp_ll + pp_hl;
- + if (res0 < pp_ll)
- + res2++;
- + res2 += (ps_hh__ >> BITS_PER_SI) + pp_hh;
- + high = res2;
- + low = res0;
- + }
- +#endif
- + }
- +
- + tmp->normal_exp = a->normal_exp + b->normal_exp
- + + FRAC_NBITS - (FRACBITS + NGARDS);
- + tmp->sign = a->sign != b->sign;
- + while (high >= IMPLICIT_2)
- + {
- + tmp->normal_exp++;
- + if (high & 1)
- + {
- + low >>= 1;
- + low |= FRACHIGH;
- + }
- + high >>= 1;
- + }
- + while (high < IMPLICIT_1)
- + {
- + tmp->normal_exp--;
- +
- + high <<= 1;
- + if (low & FRACHIGH)
- + high |= 1;
- + low <<= 1;
- + }
- + /* rounding is tricky. if we only round if it won't make us round later. */
- +#if 0
- + if (low & FRACHIGH2)
- + {
- + if (((high & GARDMASK) != GARDMSB)
- + && (((high + 1) & GARDMASK) == GARDMSB))
- + {
- + /* don't round, it gets done again later. */
- + }
- + else
- + {
- + high++;
- + }
- + }
- +#endif
- + if (!ROUND_TOWARDS_ZERO && (high & GARDMASK) == GARDMSB)
- + {
- + if (high & (1 << NGARDS))
- + {
- + /* half way, so round to even */
- + high += GARDROUND + 1;
- + }
- + else if (low)
- + {
- + /* but we really weren't half way */
- + high += GARDROUND + 1;
- + }
- + }
- + tmp->fraction.ll = high;
- + tmp->class = CLASS_NUMBER;
- + return tmp;
- +}
- +
- +FLO_type
- +multiply (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + fp_number_type tmp;
- + fp_number_type *res;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + res = _fpmul_parts (&a, &b, &tmp);
- +
- + return pack_d (res);
- +}
- +#endif /* L_mul_sf || L_mul_df */
- +
- +#if defined(L_div_sf) || defined(L_div_df) || defined(L_div_tf)
- +static inline __attribute__ ((__always_inline__)) fp_number_type *
- +_fpdiv_parts (fp_number_type * a,
- + fp_number_type * b)
- +{
- + fractype bit;
- + fractype numerator;
- + fractype denominator;
- + fractype quotient;
- +
- + if (isnan (a))
- + {
- + return a;
- + }
- + if (isnan (b))
- + {
- + return b;
- + }
- +
- + a->sign = a->sign ^ b->sign;
- +
- + if (isinf (a) || iszero (a))
- + {
- + if (a->class == b->class)
- + return nan ();
- + return a;
- + }
- +
- + if (isinf (b))
- + {
- + a->fraction.ll = 0;
- + a->normal_exp = 0;
- + return a;
- + }
- + if (iszero (b))
- + {
- + a->class = CLASS_INFINITY;
- + return a;
- + }
- +
- + /* Calculate the mantissa by multiplying both 64bit numbers to get a
- + 128 bit number */
- + {
- + /* quotient =
- + ( numerator / denominator) * 2^(numerator exponent - denominator exponent)
- + */
- +
- + a->normal_exp = a->normal_exp - b->normal_exp;
- + numerator = a->fraction.ll;
- + denominator = b->fraction.ll;
- +
- + if (numerator < denominator)
- + {
- + /* Fraction will be less than 1.0 */
- + numerator *= 2;
- + a->normal_exp--;
- + }
- + bit = IMPLICIT_1;
- + quotient = 0;
- + /* ??? Does divide one bit at a time. Optimize. */
- + while (bit)
- + {
- + if (numerator >= denominator)
- + {
- + quotient |= bit;
- + numerator -= denominator;
- + }
- + bit >>= 1;
- + numerator *= 2;
- + }
- +
- + if (!ROUND_TOWARDS_ZERO && (quotient & GARDMASK) == GARDMSB)
- + {
- + if (quotient & (1 << NGARDS))
- + {
- + /* half way, so round to even */
- + quotient += GARDROUND + 1;
- + }
- + else if (numerator)
- + {
- + /* but we really weren't half way, more bits exist */
- + quotient += GARDROUND + 1;
- + }
- + }
- +
- + a->fraction.ll = quotient;
- + return (a);
- + }
- +}
- +
- +FLO_type
- +divide (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + fp_number_type *res;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + res = _fpdiv_parts (&a, &b);
- +
- + return pack_d (res);
- +}
- +#endif /* L_div_sf || L_div_df */
- +
- +#if defined(L_fpcmp_parts_sf) || defined(L_fpcmp_parts_df) \
- + || defined(L_fpcmp_parts_tf)
- +/* according to the demo, fpcmp returns a comparison with 0... thus
- + a<b -> -1
- + a==b -> 0
- + a>b -> +1
- + */
- +
- +int
- +__fpcmp_parts (fp_number_type * a, fp_number_type * b)
- +{
- +#if 0
- + /* either nan -> unordered. Must be checked outside of this routine. */
- + if (isnan (a) && isnan (b))
- + {
- + return 1; /* still unordered! */
- + }
- +#endif
- +
- + if (isnan (a) || isnan (b))
- + {
- + return 1; /* how to indicate unordered compare? */
- + }
- + if (isinf (a) && isinf (b))
- + {
- + /* +inf > -inf, but +inf != +inf */
- + /* b \a| +inf(0)| -inf(1)
- + ______\+--------+--------
- + +inf(0)| a==b(0)| a<b(-1)
- + -------+--------+--------
- + -inf(1)| a>b(1) | a==b(0)
- + -------+--------+--------
- + So since unordered must be nonzero, just line up the columns...
- + */
- + return b->sign - a->sign;
- + }
- + /* but not both... */
- + if (isinf (a))
- + {
- + return a->sign ? -1 : 1;
- + }
- + if (isinf (b))
- + {
- + return b->sign ? 1 : -1;
- + }
- + if (iszero (a) && iszero (b))
- + {
- + return 0;
- + }
- + if (iszero (a))
- + {
- + return b->sign ? 1 : -1;
- + }
- + if (iszero (b))
- + {
- + return a->sign ? -1 : 1;
- + }
- + /* now both are "normal". */
- + if (a->sign != b->sign)
- + {
- + /* opposite signs */
- + return a->sign ? -1 : 1;
- + }
- + /* same sign; exponents? */
- + if (a->normal_exp > b->normal_exp)
- + {
- + return a->sign ? -1 : 1;
- + }
- + if (a->normal_exp < b->normal_exp)
- + {
- + return a->sign ? 1 : -1;
- + }
- + /* same exponents; check size. */
- + if (a->fraction.ll > b->fraction.ll)
- + {
- + return a->sign ? -1 : 1;
- + }
- + if (a->fraction.ll < b->fraction.ll)
- + {
- + return a->sign ? 1 : -1;
- + }
- + /* after all that, they're equal. */
- + return 0;
- +}
- +#endif
- +
- +#if defined(L_compare_sf) || defined(L_compare_df) || defined(L_compoare_tf)
- +CMPtype
- +compare (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + return __fpcmp_parts (&a, &b);
- +}
- +#endif /* L_compare_sf || L_compare_df */
- +
- +#ifndef US_SOFTWARE_GOFAST
- +
- +/* These should be optimized for their specific tasks someday. */
- +
- +#if defined(L_eq_sf) || defined(L_eq_df) || defined(L_eq_tf)
- +CMPtype
- +_eq_f2 (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + if (isnan (&a) || isnan (&b))
- + return 1; /* false, truth == 0 */
- +
- + return __fpcmp_parts (&a, &b) ;
- +}
- +#endif /* L_eq_sf || L_eq_df */
- +
- +#if defined(L_ne_sf) || defined(L_ne_df) || defined(L_ne_tf)
- +CMPtype
- +_ne_f2 (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + if (isnan (&a) || isnan (&b))
- + return 1; /* true, truth != 0 */
- +
- + return __fpcmp_parts (&a, &b) ;
- +}
- +#endif /* L_ne_sf || L_ne_df */
- +
- +#if defined(L_gt_sf) || defined(L_gt_df) || defined(L_gt_tf)
- +CMPtype
- +_gt_f2 (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + if (isnan (&a) || isnan (&b))
- + return -1; /* false, truth > 0 */
- +
- + return __fpcmp_parts (&a, &b);
- +}
- +#endif /* L_gt_sf || L_gt_df */
- +
- +#if defined(L_ge_sf) || defined(L_ge_df) || defined(L_ge_tf)
- +CMPtype
- +_ge_f2 (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + if (isnan (&a) || isnan (&b))
- + return -1; /* false, truth >= 0 */
- + return __fpcmp_parts (&a, &b) ;
- +}
- +#endif /* L_ge_sf || L_ge_df */
- +
- +#if defined(L_lt_sf) || defined(L_lt_df) || defined(L_lt_tf)
- +CMPtype
- +_lt_f2 (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + if (isnan (&a) || isnan (&b))
- + return 1; /* false, truth < 0 */
- +
- + return __fpcmp_parts (&a, &b);
- +}
- +#endif /* L_lt_sf || L_lt_df */
- +
- +#if defined(L_le_sf) || defined(L_le_df) || defined(L_le_tf)
- +CMPtype
- +_le_f2 (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + if (isnan (&a) || isnan (&b))
- + return 1; /* false, truth <= 0 */
- +
- + return __fpcmp_parts (&a, &b) ;
- +}
- +#endif /* L_le_sf || L_le_df */
- +
- +#endif /* ! US_SOFTWARE_GOFAST */
- +
- +#if defined(L_unord_sf) || defined(L_unord_df) || defined(L_unord_tf)
- +CMPtype
- +_unord_f2 (FLO_type arg_a, FLO_type arg_b)
- +{
- + fp_number_type a;
- + fp_number_type b;
- + FLO_union_type au, bu;
- +
- + au.value = arg_a;
- + bu.value = arg_b;
- +
- + unpack_d (&au, &a);
- + unpack_d (&bu, &b);
- +
- + return (isnan (&a) || isnan (&b));
- +}
- +#endif /* L_unord_sf || L_unord_df */
- +
- +#if defined(L_si_to_sf) || defined(L_si_to_df) || defined(L_si_to_tf)
- +FLO_type
- +si_to_float (SItype arg_a)
- +{
- + fp_number_type in;
- +
- + in.class = CLASS_NUMBER;
- + in.sign = arg_a < 0;
- + if (!arg_a)
- + {
- + in.class = CLASS_ZERO;
- + }
- + else
- + {
- + in.normal_exp = FRACBITS + NGARDS;
- + if (in.sign)
- + {
- + /* Special case for minint, since there is no +ve integer
- + representation for it */
- + if (arg_a == (- MAX_SI_INT - 1))
- + {
- + return (FLO_type)(- MAX_SI_INT - 1);
- + }
- + in.fraction.ll = (-arg_a);
- + }
- + else
- + in.fraction.ll = arg_a;
- +
- + while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
- + {
- + in.fraction.ll <<= 1;
- + in.normal_exp -= 1;
- + }
- + }
- + return pack_d (&in);
- +}
- +#endif /* L_si_to_sf || L_si_to_df */
- +
- +#if defined(L_usi_to_sf) || defined(L_usi_to_df) || defined(L_usi_to_tf)
- +FLO_type
- +usi_to_float (USItype arg_a)
- +{
- + fp_number_type in;
- +
- + in.sign = 0;
- + if (!arg_a)
- + {
- + in.class = CLASS_ZERO;
- + }
- + else
- + {
- + in.class = CLASS_NUMBER;
- + in.normal_exp = FRACBITS + NGARDS;
- + in.fraction.ll = arg_a;
- +
- + while (in.fraction.ll > ((fractype)1 << (FRACBITS + NGARDS)))
- + {
- + in.fraction.ll >>= 1;
- + in.normal_exp += 1;
- + }
- + while (in.fraction.ll < ((fractype)1 << (FRACBITS + NGARDS)))
- + {
- + in.fraction.ll <<= 1;
- + in.normal_exp -= 1;
- + }
- + }
- + return pack_d (&in);
- +}
- +#endif
- +
- +#if defined(L_sf_to_si) || defined(L_df_to_si) || defined(L_tf_to_si)
- +SItype
- +float_to_si (FLO_type arg_a)
- +{
- + fp_number_type a;
- + SItype tmp;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &a);
- +
- + if (iszero (&a))
- + return 0;
- + if (isnan (&a))
- + return 0;
- + /* get reasonable MAX_SI_INT... */
- + if (isinf (&a))
- + return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
- + /* it is a number, but a small one */
- + if (a.normal_exp < 0)
- + return 0;
- + if (a.normal_exp > BITS_PER_SI - 2)
- + return a.sign ? (-MAX_SI_INT)-1 : MAX_SI_INT;
- + tmp = a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
- + return a.sign ? (-tmp) : (tmp);
- +}
- +#endif /* L_sf_to_si || L_df_to_si */
- +
- +#if defined(L_sf_to_usi) || defined(L_df_to_usi) || defined(L_tf_to_usi)
- +#if defined US_SOFTWARE_GOFAST || defined(L_tf_to_usi)
- +/* While libgcc2.c defines its own __fixunssfsi and __fixunsdfsi routines,
- + we also define them for GOFAST because the ones in libgcc2.c have the
- + wrong names and I'd rather define these here and keep GOFAST CYG-LOC's
- + out of libgcc2.c. We can't define these here if not GOFAST because then
- + there'd be duplicate copies. */
- +
- +USItype
- +float_to_usi (FLO_type arg_a)
- +{
- + fp_number_type a;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &a);
- +
- + if (iszero (&a))
- + return 0;
- + if (isnan (&a))
- + return 0;
- + /* it is a negative number */
- + if (a.sign)
- + return 0;
- + /* get reasonable MAX_USI_INT... */
- + if (isinf (&a))
- + return MAX_USI_INT;
- + /* it is a number, but a small one */
- + if (a.normal_exp < 0)
- + return 0;
- + if (a.normal_exp > BITS_PER_SI - 1)
- + return MAX_USI_INT;
- + else if (a.normal_exp > (FRACBITS + NGARDS))
- + return a.fraction.ll << (a.normal_exp - (FRACBITS + NGARDS));
- + else
- + return a.fraction.ll >> ((FRACBITS + NGARDS) - a.normal_exp);
- +}
- +#endif /* US_SOFTWARE_GOFAST */
- +#endif /* L_sf_to_usi || L_df_to_usi */
- +
- +#if defined(L_negate_sf) || defined(L_negate_df) || defined(L_negate_tf)
- +FLO_type
- +negate (FLO_type arg_a)
- +{
- + fp_number_type a;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &a);
- +
- + flip_sign (&a);
- + return pack_d (&a);
- +}
- +#endif /* L_negate_sf || L_negate_df */
- +
- +#ifdef FLOAT
- +
- +#if defined(L_make_sf)
- +SFtype
- +__make_fp(fp_class_type class,
- + unsigned int sign,
- + int exp,
- + USItype frac)
- +{
- + fp_number_type in;
- +
- + in.class = class;
- + in.sign = sign;
- + in.normal_exp = exp;
- + in.fraction.ll = frac;
- + return pack_d (&in);
- +}
- +#endif /* L_make_sf */
- +
- +#ifndef FLOAT_ONLY
- +
- +/* This enables one to build an fp library that supports float but not double.
- + Otherwise, we would get an undefined reference to __make_dp.
- + This is needed for some 8-bit ports that can't handle well values that
- + are 8-bytes in size, so we just don't support double for them at all. */
- +
- +#if defined(L_sf_to_df)
- +DFtype
- +sf_to_df (SFtype arg_a)
- +{
- + fp_number_type in;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &in);
- +
- + return __make_dp (in.class, in.sign, in.normal_exp,
- + ((UDItype) in.fraction.ll) << F_D_BITOFF);
- +}
- +#endif /* L_sf_to_df */
- +
- +#if defined(L_sf_to_tf) && defined(TMODES)
- +TFtype
- +sf_to_tf (SFtype arg_a)
- +{
- + fp_number_type in;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &in);
- +
- + return __make_tp (in.class, in.sign, in.normal_exp,
- + ((UTItype) in.fraction.ll) << F_T_BITOFF);
- +}
- +#endif /* L_sf_to_df */
- +
- +#endif /* ! FLOAT_ONLY */
- +#endif /* FLOAT */
- +
- +#ifndef FLOAT
- +
- +extern SFtype __make_fp (fp_class_type, unsigned int, int, USItype);
- +
- +#if defined(L_make_df)
- +DFtype
- +__make_dp (fp_class_type class, unsigned int sign, int exp, UDItype frac)
- +{
- + fp_number_type in;
- +
- + in.class = class;
- + in.sign = sign;
- + in.normal_exp = exp;
- + in.fraction.ll = frac;
- + return pack_d (&in);
- +}
- +#endif /* L_make_df */
- +
- +#if defined(L_df_to_sf)
- +SFtype
- +df_to_sf (DFtype arg_a)
- +{
- + fp_number_type in;
- + USItype sffrac;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &in);
- +
- + sffrac = in.fraction.ll >> F_D_BITOFF;
- +
- + /* We set the lowest guard bit in SFFRAC if we discarded any non
- + zero bits. */
- + if ((in.fraction.ll & (((USItype) 1 << F_D_BITOFF) - 1)) != 0)
- + sffrac |= 1;
- +
- + return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
- +}
- +#endif /* L_df_to_sf */
- +
- +#if defined(L_df_to_tf) && defined(TMODES) \
- + && !defined(FLOAT) && !defined(TFLOAT)
- +TFtype
- +df_to_tf (DFtype arg_a)
- +{
- + fp_number_type in;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &in);
- +
- + return __make_tp (in.class, in.sign, in.normal_exp,
- + ((UTItype) in.fraction.ll) << D_T_BITOFF);
- +}
- +#endif /* L_sf_to_df */
- +
- +#ifdef TFLOAT
- +#if defined(L_make_tf)
- +TFtype
- +__make_tp(fp_class_type class,
- + unsigned int sign,
- + int exp,
- + UTItype frac)
- +{
- + fp_number_type in;
- +
- + in.class = class;
- + in.sign = sign;
- + in.normal_exp = exp;
- + in.fraction.ll = frac;
- + return pack_d (&in);
- +}
- +#endif /* L_make_tf */
- +
- +#if defined(L_tf_to_df)
- +DFtype
- +tf_to_df (TFtype arg_a)
- +{
- + fp_number_type in;
- + UDItype sffrac;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &in);
- +
- + sffrac = in.fraction.ll >> D_T_BITOFF;
- +
- + /* We set the lowest guard bit in SFFRAC if we discarded any non
- + zero bits. */
- + if ((in.fraction.ll & (((UTItype) 1 << D_T_BITOFF) - 1)) != 0)
- + sffrac |= 1;
- +
- + return __make_dp (in.class, in.sign, in.normal_exp, sffrac);
- +}
- +#endif /* L_tf_to_df */
- +
- +#if defined(L_tf_to_sf)
- +SFtype
- +tf_to_sf (TFtype arg_a)
- +{
- + fp_number_type in;
- + USItype sffrac;
- + FLO_union_type au;
- +
- + au.value = arg_a;
- + unpack_d (&au, &in);
- +
- + sffrac = in.fraction.ll >> F_T_BITOFF;
- +
- + /* We set the lowest guard bit in SFFRAC if we discarded any non
- + zero bits. */
- + if ((in.fraction.ll & (((UTItype) 1 << F_T_BITOFF) - 1)) != 0)
- + sffrac |= 1;
- +
- + return __make_fp (in.class, in.sign, in.normal_exp, sffrac);
- +}
- +#endif /* L_tf_to_sf */
- +#endif /* TFLOAT */
- +
- +#endif /* ! FLOAT */
- +#endif /* !EXTENDED_FLOAT_STUBS */
- diff --git a/gcc/config/nios2/nios2-protos.h b/gcc/config/nios2/nios2-protos.h
- new file mode 100644
- index 0000000..dc75c4f
- --- /dev/null
- +++ b/gcc/config/nios2/nios2-protos.h
- @@ -0,0 +1,78 @@
- +/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
- + Copyright (C) 2003 Altera
- + Contributed by Jonah Graham (jgraham@altera.com).
- +
- +This file is part of GNU CC.
- +
- +GNU CC 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 2, or (at your option)
- +any later version.
- +
- +GNU CC 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 GNU CC; see the file COPYING. If not, write to
- +the Free Software Foundation, 59 Temple Place - Suite 330,
- +Boston, MA 02111-1307, USA. */
- +
- +extern void dump_frame_size (FILE *);
- +extern HOST_WIDE_INT compute_frame_size (void);
- +extern int nios2_initial_elimination_offset (int, int);
- +extern void override_options (void);
- +extern void optimization_options (int, int);
- +extern int nios2_can_use_return_insn (void);
- +extern void expand_prologue (void);
- +extern void expand_epilogue (bool);
- +extern void function_profiler (FILE *, int);
- +extern enum reg_class reg_class_from_constraint (char, const char *);
- +extern void nios2_register_target_pragmas (void);
- +
- +#ifdef RTX_CODE
- +extern int nios2_legitimate_address (rtx, enum machine_mode, int);
- +extern void nios2_print_operand (FILE *, rtx, int);
- +extern void nios2_print_operand_address (FILE *, rtx);
- +
- +extern int nios2_emit_move_sequence (rtx *, enum machine_mode);
- +extern int nios2_emit_expensive_div (rtx *, enum machine_mode);
- +
- +extern void gen_int_relational (enum rtx_code, rtx, rtx, rtx, rtx);
- +extern void gen_conditional_move (rtx *, enum machine_mode);
- +extern const char *asm_output_opcode (FILE *, const char *);
- +
- +/* predicates */
- +extern int arith_operand (rtx, enum machine_mode);
- +extern int uns_arith_operand (rtx, enum machine_mode);
- +extern int logical_operand (rtx, enum machine_mode);
- +extern int shift_operand (rtx, enum machine_mode);
- +extern int reg_or_0_operand (rtx, enum machine_mode);
- +extern int equality_op (rtx, enum machine_mode);
- +extern int custom_insn_opcode (rtx, enum machine_mode);
- +extern int rdwrctl_operand (rtx, enum machine_mode);
- +
- +/* custom fpu instruction output */
- +extern const char *nios2_output_fpu_insn_cmps (rtx, enum rtx_code);
- +extern const char *nios2_output_fpu_insn_cmpd (rtx, enum rtx_code);
- +
- +# ifdef HAVE_MACHINE_MODES
- +# if defined TREE_CODE
- +extern rtx function_arg (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
- +extern int nios2_must_pass_in_stack (enum machine_mode, tree);
- +extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
- +extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
- +extern int nios2_function_arg_padding (enum machine_mode, tree);
- +extern int nios2_block_reg_padding (enum machine_mode, tree, int);
- +extern void init_cumulative_args (CUMULATIVE_ARGS *, tree, rtx, tree, int);
- +extern int nios2_setup_incoming_varargs (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
- +
- +# endif /* TREE_CODE */
- +# endif /* HAVE_MACHINE_MODES */
- +#endif
- +
- +#ifdef TREE_CODE
- +extern int nios2_return_in_memory (tree);
- +
- +#endif /* TREE_CODE */
- diff --git a/gcc/config/nios2/nios2-uclibc.h b/gcc/config/nios2/nios2-uclibc.h
- new file mode 100644
- index 0000000..af98cdd
- --- /dev/null
- +++ b/gcc/config/nios2/nios2-uclibc.h
- @@ -0,0 +1,75 @@
- +#ifdef USE_UCLIBC
- +
- +#undef TARGET_SWITCHES
- +#define TARGET_SWITCHES \
- +{ \
- + { "hw-div", HAS_DIV_FLAG, \
- + N_("Enable DIV, DIVU") }, \
- + { "no-hw-div", -HAS_DIV_FLAG, \
- + N_("Disable DIV, DIVU (default)") }, \
- + { "hw-mul", HAS_MUL_FLAG, \
- + N_("Enable MUL instructions (default)") }, \
- + { "hw-mulx", HAS_MULX_FLAG, \
- + N_("Enable MULX instructions, assume fast shifter") }, \
- + { "no-hw-mul", -HAS_MUL_FLAG, \
- + N_("Disable MUL instructions") }, \
- + { "no-hw-mulx", -HAS_MULX_FLAG, \
- + N_("Disable MULX instructions, assume slow shifter (default and implied by -mno-hw-mul)") }, \
- + { "fast-sw-div", FAST_SW_DIV_FLAG, \
- + N_("Use table based fast divide (default at -O3)") }, \
- + { "no-fast-sw-div", -FAST_SW_DIV_FLAG, \
- + N_("Don't use table based fast divide ever") }, \
- + { "inline-memcpy", INLINE_MEMCPY_FLAG, \
- + N_("Inline small memcpy (default when optimizing)") }, \
- + { "no-inline-memcpy", -INLINE_MEMCPY_FLAG, \
- + N_("Don't Inline small memcpy") }, \
- + { "cache-volatile", CACHE_VOLATILE_FLAG, \
- + N_("Volatile accesses use non-io variants of instructions (default)") }, \
- + { "no-cache-volatile", -CACHE_VOLATILE_FLAG, \
- + N_("Volatile accesses use io variants of instructions") }, \
- + { "bypass-cache", BYPASS_CACHE_FLAG, \
- + N_("All ld/st instructins use io variants") }, \
- + { "no-bypass-cache", -BYPASS_CACHE_FLAG, \
- + N_("All ld/st instructins do not use io variants (default)") }, \
- + { "smallc", 0, \
- + N_("Link with a limited version of the C library") }, \
- + { "stack-check", STACK_CHECK_FLAG, \
- + N_("Enable stack limit checking.") }, \
- + { "no-stack-check", -STACK_CHECK_FLAG, \
- + N_("Disable stack limit checking (default).") }, \
- + { "reverse-bitfields", REVERSE_BITFIELDS_FLAG, \
- + N_("Reverse the order of bitfields in a struct.") }, \
- + { "no-reverse-bitfields", -REVERSE_BITFIELDS_FLAG, \
- + N_("Use the normal order of bitfields in a struct (default).") }, \
- + { "eb", BIG_ENDIAN_FLAG, \
- + N_("Use big-endian byte order") }, \
- + { "el", -BIG_ENDIAN_FLAG, \
- + N_("Use little-endian byte order") }, \
- + { "", TARGET_DEFAULT, 0 } \
- +}
- +
- +/* The GNU C++ standard library requires that these macros be defined. */
- +#undef CPLUSPLUS_CPP_SPEC
- +#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
- +
- +#undef LIB_SPEC
- +#define LIB_SPEC \
- +"--start-group %{msmallc: -lsmallc} %{!msmallc: -lc} -lgcc \
- + %{msys-lib=*: -l%*} \
- + %{!msys-lib=*: -lc} \
- + --end-group \
- + %{msys-lib=: %eYou need a library name for -msys-lib=} \
- +"
- +
- +#undef STARTFILE_SPEC
- +#define STARTFILE_SPEC \
- +"%{msys-crt0=*: %*} %{!msys-crt0=*: crt1%O%s} \
- + %{msys-crt0=: %eYou need a C startup file for -msys-crt0=} \
- + crti%O%s crtbegin%O%s \
- +"
- +
- +#undef ENDFILE_SPEC
- +#define ENDFILE_SPEC \
- + " crtend%O%s crtn%O%s"
- +
- +#endif /* USE_UCLIBC */
- diff --git a/gcc/config/nios2/nios2.c b/gcc/config/nios2/nios2.c
- new file mode 100644
- index 0000000..8723a86
- --- /dev/null
- +++ b/gcc/config/nios2/nios2.c
- @@ -0,0 +1,4694 @@
- +/* Subroutines for assembler code output for Altera NIOS 2G NIOS2 version.
- + Copyright (C) 2005 Altera
- + Contributed by Jonah Graham (jgraham@altera.com) and Will Reece (wreece@altera.com).
- +
- +This file is part of GNU CC.
- +
- +GNU CC 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 2, or (at your option)
- +any later version.
- +
- +GNU CC 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 GNU CC; see the file COPYING. If not, write to
- +the Free Software Foundation, 59 Temple Place - Suite 330,
- +Boston, MA 02111-1307, USA. */
- +
- +
- +#include <stdio.h>
- +#include "config.h"
- +#include "system.h"
- +#include "coretypes.h"
- +#include "tm.h"
- +#include "rtl.h"
- +#include "tree.h"
- +#include "tm_p.h"
- +#include "regs.h"
- +#include "hard-reg-set.h"
- +#include "real.h"
- +#include "insn-config.h"
- +#include "conditions.h"
- +#include "output.h"
- +#include "insn-attr.h"
- +#include "flags.h"
- +#include "recog.h"
- +#include "expr.h"
- +#include "toplev.h"
- +#include "basic-block.h"
- +#include "function.h"
- +#include "ggc.h"
- +#include "reload.h"
- +#include "debug.h"
- +#include "optabs.h"
- +#include "target.h"
- +#include "target-def.h"
- +#include "c-pragma.h" /* for c_register_pragma */
- +#include "cpplib.h" /* for CPP_NUMBER */
- +
- +/* local prototypes */
- +static bool nios2_rtx_costs (rtx, int, int, int *);
- +
- +static void nios2_asm_function_prologue (FILE *, HOST_WIDE_INT);
- +static int nios2_use_dfa_pipeline_interface (void);
- +static int nios2_issue_rate (void);
- +static struct machine_function *nios2_init_machine_status (void);
- +static bool nios2_in_small_data_p (tree);
- +static rtx save_reg (int, HOST_WIDE_INT, rtx);
- +static rtx restore_reg (int, HOST_WIDE_INT);
- +static unsigned int nios2_section_type_flags (tree, const char *, int);
- +
- +/* 0 --> no #pragma seen
- + 1 --> in scope of #pragma reverse_bitfields
- + -1 --> in scope of #pragma no_reverse_bitfields */
- +static int nios2_pragma_reverse_bitfields_flag = 0;
- +static void nios2_pragma_reverse_bitfields (struct cpp_reader *);
- +static void nios2_pragma_no_reverse_bitfields (struct cpp_reader *);
- +static tree nios2_handle_struct_attribute (tree *, tree, tree, int, bool *);
- +static void nios2_insert_attributes (tree, tree *);
- +static bool nios2_reverse_bitfield_layout_p (tree record_type);
- +static void nios2_init_builtins (void);
- +static rtx nios2_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
- +static bool nios2_function_ok_for_sibcall (tree, tree);
- +static void nios2_encode_section_info (tree, rtx, int);
- +
- +/* Initialize the GCC target structure. */
- +#undef TARGET_ASM_FUNCTION_PROLOGUE
- +#define TARGET_ASM_FUNCTION_PROLOGUE nios2_asm_function_prologue
- +
- +#undef TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE
- +#define TARGET_SCHED_USE_DFA_PIPELINE_INTERFACE \
- + nios2_use_dfa_pipeline_interface
- +#undef TARGET_SCHED_ISSUE_RATE
- +#define TARGET_SCHED_ISSUE_RATE nios2_issue_rate
- +#undef TARGET_IN_SMALL_DATA_P
- +#define TARGET_IN_SMALL_DATA_P nios2_in_small_data_p
- +#undef TARGET_ENCODE_SECTION_INFO
- +#define TARGET_ENCODE_SECTION_INFO nios2_encode_section_info
- +#undef TARGET_SECTION_TYPE_FLAGS
- +#define TARGET_SECTION_TYPE_FLAGS nios2_section_type_flags
- +
- +#undef TARGET_REVERSE_BITFIELD_LAYOUT_P
- +#define TARGET_REVERSE_BITFIELD_LAYOUT_P nios2_reverse_bitfield_layout_p
- +
- +#undef TARGET_INIT_BUILTINS
- +#define TARGET_INIT_BUILTINS nios2_init_builtins
- +#undef TARGET_EXPAND_BUILTIN
- +#define TARGET_EXPAND_BUILTIN nios2_expand_builtin
- +
- +#undef TARGET_FUNCTION_OK_FOR_SIBCALL
- +#define TARGET_FUNCTION_OK_FOR_SIBCALL nios2_function_ok_for_sibcall
- +
- +#undef TARGET_RTX_COSTS
- +#define TARGET_RTX_COSTS nios2_rtx_costs
- +
- +const struct attribute_spec nios2_attribute_table[] =
- +{
- + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
- + { "reverse_bitfields", 0, 0, false, false, false, nios2_handle_struct_attribute },
- + { "no_reverse_bitfields", 0, 0, false, false, false, nios2_handle_struct_attribute },
- + { "pragma_reverse_bitfields", 0, 0, false, false, false, NULL },
- + { "pragma_no_reverse_bitfields", 0, 0, false, false, false, NULL },
- + { NULL, 0, 0, false, false, false, NULL }
- +};
- +
- +#undef TARGET_ATTRIBUTE_TABLE
- +#define TARGET_ATTRIBUTE_TABLE nios2_attribute_table
- +
- +#undef TARGET_INSERT_ATTRIBUTES
- +#define TARGET_INSERT_ATTRIBUTES nios2_insert_attributes
- +
- +/* ??? Might want to redefine TARGET_RETURN_IN_MSB here to handle
- + big-endian case; depends on what ABI we choose. */
- +
- +struct gcc_target targetm = TARGET_INITIALIZER;
- +
- +
- +
- +/* Threshold for data being put into the small data/bss area, instead
- + of the normal data area (references to the small data/bss area take
- + 1 instruction, and use the global pointer, references to the normal
- + data area takes 2 instructions). */
- +unsigned HOST_WIDE_INT nios2_section_threshold = NIOS2_DEFAULT_GVALUE;
- +
- +
- +/* Structure to be filled in by compute_frame_size with register
- + save masks, and offsets for the current function. */
- +
- +struct nios2_frame_info
- +GTY (())
- +{
- + long total_size; /* # bytes that the entire frame takes up */
- + long var_size; /* # bytes that variables take up */
- + long args_size; /* # bytes that outgoing arguments take up */
- + int save_reg_size; /* # bytes needed to store gp regs */
- + int save_reg_rounded; /* # bytes needed to store gp regs */
- + long save_regs_offset; /* offset from new sp to store gp registers */
- + int initialized; /* != 0 if frame size already calculated */
- + int num_regs; /* number of gp registers saved */
- +};
- +
- +struct machine_function
- +GTY (())
- +{
- +
- + /* Current frame information, calculated by compute_frame_size. */
- + struct nios2_frame_info frame;
- +};
- +
- +
- +/***************************************
- + * Register Classes
- + ***************************************/
- +
- +enum reg_class
- +reg_class_from_constraint (char chr, const char *str)
- +{
- + if (chr == 'D' && ISDIGIT (str[1]) && ISDIGIT (str[2]))
- + {
- + int regno;
- + int ones = str[2] - '0';
- + int tens = str[1] - '0';
- +
- + regno = ones + (10 * tens);
- + if (regno < 0 || regno > 31)
- + return NO_REGS;
- +
- + return D00_REG + regno;
- + }
- +
- + return NO_REGS;
- +}
- +
- +
- +/***************************************
- + * Stack Layout and Calling Conventions
- + ***************************************/
- +
- +
- +#define TOO_BIG_OFFSET(X) ((X) > ((1 << 15) - 1))
- +#define TEMP_REG_NUM 8
- +
- +static void
- +nios2_asm_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
- +{
- + if (flag_verbose_asm || flag_debug_asm)
- + {
- + compute_frame_size ();
- + dump_frame_size (file);
- + }
- +}
- +
- +static rtx
- +save_reg (int regno, HOST_WIDE_INT offset, rtx cfa_store_reg)
- +{
- + rtx insn, stack_slot;
- +
- + stack_slot = gen_rtx_PLUS (SImode,
- + cfa_store_reg,
- + GEN_INT (offset));
- +
- + insn = emit_insn (gen_rtx_SET (SImode,
- + gen_rtx_MEM (SImode, stack_slot),
- + gen_rtx_REG (SImode, regno)));
- +
- + RTX_FRAME_RELATED_P (insn) = 1;
- +
- + return insn;
- +}
- +
- +static rtx
- +restore_reg (int regno, HOST_WIDE_INT offset)
- +{
- + rtx insn, stack_slot;
- +
- + if (TOO_BIG_OFFSET (offset))
- + {
- + stack_slot = gen_rtx_REG (SImode, TEMP_REG_NUM);
- + insn = emit_insn (gen_rtx_SET (SImode,
- + stack_slot,
- + GEN_INT (offset)));
- +
- + insn = emit_insn (gen_rtx_SET (SImode,
- + stack_slot,
- + gen_rtx_PLUS (SImode,
- + stack_slot,
- + stack_pointer_rtx)));
- + }
- + else
- + {
- + stack_slot = gen_rtx_PLUS (SImode,
- + stack_pointer_rtx,
- + GEN_INT (offset));
- + }
- +
- + stack_slot = gen_rtx_MEM (SImode, stack_slot);
- +
- + insn = emit_move_insn (gen_rtx_REG (SImode, regno), stack_slot);
- +
- + return insn;
- +}
- +
- +
- +/* There are two possible paths for prologue expansion,
- +- the first is if the total frame size is < 2^15-1. In that
- +case all the immediates will fit into the 16-bit immediate
- +fields.
- +- the second is when the frame size is too big, in that
- +case an additional temporary register is used, first
- +as a cfa_temp to offset the sp, second as the cfa_store
- +register.
- +
- +See the comment above dwarf2out_frame_debug_expr in
- +dwarf2out.c for more explanation of the "rules."
- +
- +
- +Case 1:
- +Rule # Example Insn Effect
- +2 addi sp, sp, -total_frame_size cfa.reg=sp, cfa.offset=total_frame_size
- + cfa_store.reg=sp, cfa_store.offset=total_frame_size
- +12 stw ra, offset(sp)
- +12 stw r16, offset(sp)
- +1 mov fp, sp
- +
- +Case 2:
- +Rule # Example Insn Effect
- +6 movi r8, total_frame_size cfa_temp.reg=r8, cfa_temp.offset=total_frame_size
- +2 sub sp, sp, r8 cfa.reg=sp, cfa.offset=total_frame_size
- + cfa_store.reg=sp, cfa_store.offset=total_frame_size
- +5 add r8, r8, sp cfa_store.reg=r8, cfa_store.offset=0
- +12 stw ra, offset(r8)
- +12 stw r16, offset(r8)
- +1 mov fp, sp
- +
- +*/
- +
- +void
- +expand_prologue ()
- +{
- + int i;
- + HOST_WIDE_INT total_frame_size;
- + int cfa_store_offset = 0;
- + rtx insn;
- + rtx cfa_store_reg = 0;
- +
- + total_frame_size = compute_frame_size ();
- +
- + if (total_frame_size)
- + {
- +
- + if (TOO_BIG_OFFSET (total_frame_size))
- + {
- + /* cfa_temp and cfa_store_reg are the same register,
- + cfa_store_reg overwrites cfa_temp */
- + cfa_store_reg = gen_rtx_REG (SImode, TEMP_REG_NUM);
- + insn = emit_insn (gen_rtx_SET (SImode,
- + cfa_store_reg,
- + GEN_INT (total_frame_size)));
- +
- + RTX_FRAME_RELATED_P (insn) = 1;
- +
- +
- + insn = gen_rtx_SET (SImode,
- + stack_pointer_rtx,
- + gen_rtx_MINUS (SImode,
- + stack_pointer_rtx,
- + cfa_store_reg));
- +
- + insn = emit_insn (insn);
- + RTX_FRAME_RELATED_P (insn) = 1;
- +
- +
- + /* if there are no registers to save, I don't need to
- + create a cfa_store */
- + if (cfun->machine->frame.save_reg_size)
- + {
- + insn = gen_rtx_SET (SImode,
- + cfa_store_reg,
- + gen_rtx_PLUS (SImode,
- + cfa_store_reg,
- + stack_pointer_rtx));
- +
- + insn = emit_insn (insn);
- + RTX_FRAME_RELATED_P (insn) = 1;
- + }
- +
- + cfa_store_offset
- + = total_frame_size
- + - (cfun->machine->frame.save_regs_offset
- + + cfun->machine->frame.save_reg_rounded);
- + }
- + else
- + {
- + insn = gen_rtx_SET (SImode,
- + stack_pointer_rtx,
- + gen_rtx_PLUS (SImode,
- + stack_pointer_rtx,
- + GEN_INT (-total_frame_size)));
- + insn = emit_insn (insn);
- + RTX_FRAME_RELATED_P (insn) = 1;
- +
- + cfa_store_reg = stack_pointer_rtx;
- + cfa_store_offset
- + = cfun->machine->frame.save_regs_offset
- + + cfun->machine->frame.save_reg_rounded;
- + }
- +
- + if (current_function_limit_stack)
- + {
- + emit_insn (gen_stack_overflow_detect_and_trap ());
- + }
- + }
- +
- + if (MUST_SAVE_REGISTER (RA_REGNO))
- + {
- + cfa_store_offset -= 4;
- + save_reg (RA_REGNO, cfa_store_offset, cfa_store_reg);
- + }
- + if (MUST_SAVE_REGISTER (FP_REGNO))
- + {
- + cfa_store_offset -= 4;
- + save_reg (FP_REGNO, cfa_store_offset, cfa_store_reg);
- + }
- +
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + {
- + if (MUST_SAVE_REGISTER (i) && i != FP_REGNO && i != RA_REGNO)
- + {
- + cfa_store_offset -= 4;
- + save_reg (i, cfa_store_offset, cfa_store_reg);
- + }
- + }
- +
- + if (frame_pointer_needed)
- + {
- + insn = emit_insn (gen_rtx_SET (SImode,
- + gen_rtx_REG (SImode, FP_REGNO),
- + gen_rtx_REG (SImode, SP_REGNO)));
- +
- + RTX_FRAME_RELATED_P (insn) = 1;
- + }
- +
- + /* If we are profiling, make sure no instructions are scheduled before
- + the call to mcount. */
- + if (current_function_profile)
- + emit_insn (gen_blockage ());
- +}
- +
- +void
- +expand_epilogue (bool sibcall_p)
- +{
- + rtx insn;
- + int i;
- + HOST_WIDE_INT total_frame_size;
- + int register_store_offset;
- +
- + total_frame_size = compute_frame_size ();
- +
- + if (!sibcall_p && nios2_can_use_return_insn ())
- + {
- + insn = emit_jump_insn (gen_return ());
- + return;
- + }
- +
- + emit_insn (gen_blockage ());
- +
- + register_store_offset =
- + cfun->machine->frame.save_regs_offset +
- + cfun->machine->frame.save_reg_rounded;
- +
- + if (MUST_SAVE_REGISTER (RA_REGNO))
- + {
- + register_store_offset -= 4;
- + restore_reg (RA_REGNO, register_store_offset);
- + }
- +
- + if (MUST_SAVE_REGISTER (FP_REGNO))
- + {
- + register_store_offset -= 4;
- + restore_reg (FP_REGNO, register_store_offset);
- + }
- +
- + for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
- + {
- + if (MUST_SAVE_REGISTER (i) && i != FP_REGNO && i != RA_REGNO)
- + {
- + register_store_offset -= 4;
- + restore_reg (i, register_store_offset);
- + }
- + }
- +
- + if (total_frame_size)
- + {
- + rtx sp_adjust;
- +
- + if (TOO_BIG_OFFSET (total_frame_size))
- + {
- + sp_adjust = gen_rtx_REG (SImode, TEMP_REG_NUM);
- + insn = emit_insn (gen_rtx_SET (SImode,
- + sp_adjust,
- + GEN_INT (total_frame_size)));
- +
- + }
- + else
- + {
- + sp_adjust = GEN_INT (total_frame_size);
- + }
- +
- + insn = gen_rtx_SET (SImode,
- + stack_pointer_rtx,
- + gen_rtx_PLUS (SImode,
- + stack_pointer_rtx,
- + sp_adjust));
- + insn = emit_insn (insn);
- + }
- +
- +
- + if (!sibcall_p)
- + {
- + insn = emit_jump_insn (gen_return_from_epilogue (gen_rtx (REG, Pmode,
- + RA_REGNO)));
- + }
- +}
- +
- +
- +bool
- +nios2_function_ok_for_sibcall (tree a ATTRIBUTE_UNUSED, tree b ATTRIBUTE_UNUSED)
- +{
- + return true;
- +}
- +
- +
- +
- +
- +
- +/* ----------------------- *
- + * Profiling
- + * ----------------------- */
- +
- +void
- +function_profiler (FILE *file, int labelno ATTRIBUTE_UNUSED)
- +{
- + fprintf (file, "\tmov\tr8, ra\n");
- + fprintf (file, "\tcall\tmcount\n");
- + fprintf (file, "\tmov\tra, r8\n");
- +}
- +
- +
- +/***************************************
- + * Stack Layout
- + ***************************************/
- +
- +
- +void
- +dump_frame_size (FILE *file)
- +{
- + fprintf (file, "\t%s Current Frame Info\n", ASM_COMMENT_START);
- +
- + fprintf (file, "\t%s total_size = %ld\n", ASM_COMMENT_START,
- + cfun->machine->frame.total_size);
- + fprintf (file, "\t%s var_size = %ld\n", ASM_COMMENT_START,
- + cfun->machine->frame.var_size);
- + fprintf (file, "\t%s args_size = %ld\n", ASM_COMMENT_START,
- + cfun->machine->frame.args_size);
- + fprintf (file, "\t%s save_reg_size = %d\n", ASM_COMMENT_START,
- + cfun->machine->frame.save_reg_size);
- + fprintf (file, "\t%s save_reg_rounded = %d\n", ASM_COMMENT_START,
- + cfun->machine->frame.save_reg_rounded);
- + fprintf (file, "\t%s initialized = %d\n", ASM_COMMENT_START,
- + cfun->machine->frame.initialized);
- + fprintf (file, "\t%s num_regs = %d\n", ASM_COMMENT_START,
- + cfun->machine->frame.num_regs);
- + fprintf (file, "\t%s save_regs_offset = %ld\n", ASM_COMMENT_START,
- + cfun->machine->frame.save_regs_offset);
- + fprintf (file, "\t%s current_function_is_leaf = %d\n", ASM_COMMENT_START,
- + current_function_is_leaf);
- + fprintf (file, "\t%s frame_pointer_needed = %d\n", ASM_COMMENT_START,
- + frame_pointer_needed);
- + fprintf (file, "\t%s pretend_args_size = %d\n", ASM_COMMENT_START,
- + current_function_pretend_args_size);
- +
- +}
- +
- +
- +/* Return the bytes needed to compute the frame pointer from the current
- + stack pointer.
- +*/
- +
- +HOST_WIDE_INT
- +compute_frame_size ()
- +{
- + unsigned int regno;
- + HOST_WIDE_INT var_size; /* # of var. bytes allocated */
- + HOST_WIDE_INT total_size; /* # bytes that the entire frame takes up */
- + HOST_WIDE_INT save_reg_size; /* # bytes needed to store callee save regs */
- + HOST_WIDE_INT save_reg_rounded;
- + /* # bytes needed to store callee save regs (rounded) */
- + HOST_WIDE_INT out_args_size; /* # bytes needed for outgoing args */
- +
- + save_reg_size = 0;
- + var_size = STACK_ALIGN (get_frame_size ());
- + out_args_size = STACK_ALIGN (current_function_outgoing_args_size);
- +
- + total_size = var_size + out_args_size;
- +
- + /* Calculate space needed for gp registers. */
- + for (regno = 0; regno <= FIRST_PSEUDO_REGISTER; regno++)
- + {
- + if (MUST_SAVE_REGISTER (regno))
- + {
- + save_reg_size += 4;
- + }
- + }
- +
- + save_reg_rounded = STACK_ALIGN (save_reg_size);
- + total_size += save_reg_rounded;
- +
- + total_size += STACK_ALIGN (current_function_pretend_args_size);
- +
- + /* Save other computed information. */
- + cfun->machine->frame.total_size = total_size;
- + cfun->machine->frame.var_size = var_size;
- + cfun->machine->frame.args_size = current_function_outgoing_args_size;
- + cfun->machine->frame.save_reg_size = save_reg_size;
- + cfun->machine->frame.save_reg_rounded = save_reg_rounded;
- + cfun->machine->frame.initialized = reload_completed;
- + cfun->machine->frame.num_regs = save_reg_size / UNITS_PER_WORD;
- +
- + cfun->machine->frame.save_regs_offset
- + = save_reg_rounded ? current_function_outgoing_args_size + var_size : 0;
- +
- + return total_size;
- +}
- +
- +
- +int
- +nios2_initial_elimination_offset (int from, int to ATTRIBUTE_UNUSED)
- +{
- + int offset;
- +
- + /* Set OFFSET to the offset from the stack pointer. */
- + switch (from)
- + {
- + case FRAME_POINTER_REGNUM:
- + offset = 0;
- + break;
- +
- + case ARG_POINTER_REGNUM:
- + compute_frame_size ();
- + offset = cfun->machine->frame.total_size;
- + offset -= current_function_pretend_args_size;
- + break;
- +
- + case RETURN_ADDRESS_POINTER_REGNUM:
- + compute_frame_size ();
- + /* since the return address is always the first of the
- + saved registers, return the offset to the beginning
- + of the saved registers block */
- + offset = cfun->machine->frame.save_regs_offset;
- + break;
- +
- + default:
- + abort ();
- + }
- +
- + return offset;
- +}
- +
- +/* Return nonzero if this function is known to have a null epilogue.
- + This allows the optimizer to omit jumps to jumps if no stack
- + was created. */
- +int
- +nios2_can_use_return_insn ()
- +{
- + if (!reload_completed)
- + return 0;
- +
- + if (regs_ever_live[RA_REGNO] || current_function_profile)
- + return 0;
- +
- + if (cfun->machine->frame.initialized)
- + return cfun->machine->frame.total_size == 0;
- +
- + return compute_frame_size () == 0;
- +}
- +
- +
- +
- +
- +
- +/***************************************
- + *
- + ***************************************/
- +
- +/*
- + * Try to take a bit of tedium out of the __builtin_custom_<blah>
- + * builtin functions, too.
- + */
- +
- +#define NIOS2_FOR_ALL_CUSTOM_BUILTINS \
- + NIOS2_DO_BUILTIN (N, n, n ) \
- + NIOS2_DO_BUILTIN (NI, ni, nX ) \
- + NIOS2_DO_BUILTIN (NF, nf, nX ) \
- + NIOS2_DO_BUILTIN (NP, np, nX ) \
- + NIOS2_DO_BUILTIN (NII, nii, nXX ) \
- + NIOS2_DO_BUILTIN (NIF, nif, nXX ) \
- + NIOS2_DO_BUILTIN (NIP, nip, nXX ) \
- + NIOS2_DO_BUILTIN (NFI, nfi, nXX ) \
- + NIOS2_DO_BUILTIN (NFF, nff, nXX ) \
- + NIOS2_DO_BUILTIN (NFP, nfp, nXX ) \
- + NIOS2_DO_BUILTIN (NPI, npi, nXX ) \
- + NIOS2_DO_BUILTIN (NPF, npf, nXX ) \
- + NIOS2_DO_BUILTIN (NPP, npp, nXX ) \
- + NIOS2_DO_BUILTIN (IN, in, Xn ) \
- + NIOS2_DO_BUILTIN (INI, ini, XnX ) \
- + NIOS2_DO_BUILTIN (INF, inf, XnX ) \
- + NIOS2_DO_BUILTIN (INP, inp, XnX ) \
- + NIOS2_DO_BUILTIN (INII, inii, XnXX ) \
- + NIOS2_DO_BUILTIN (INIF, inif, XnXX ) \
- + NIOS2_DO_BUILTIN (INIP, inip, XnXX ) \
- + NIOS2_DO_BUILTIN (INFI, infi, XnXX ) \
- + NIOS2_DO_BUILTIN (INFF, inff, XnXX ) \
- + NIOS2_DO_BUILTIN (INFP, infp, XnXX ) \
- + NIOS2_DO_BUILTIN (INPI, inpi, XnXX ) \
- + NIOS2_DO_BUILTIN (INPF, inpf, XnXX ) \
- + NIOS2_DO_BUILTIN (INPP, inpp, XnXX ) \
- + NIOS2_DO_BUILTIN (FN, fn, Xn ) \
- + NIOS2_DO_BUILTIN (FNI, fni, XnX ) \
- + NIOS2_DO_BUILTIN (FNF, fnf, XnX ) \
- + NIOS2_DO_BUILTIN (FNP, fnp, XnX ) \
- + NIOS2_DO_BUILTIN (FNII, fnii, XnXX ) \
- + NIOS2_DO_BUILTIN (FNIF, fnif, XnXX ) \
- + NIOS2_DO_BUILTIN (FNIP, fnip, XnXX ) \
- + NIOS2_DO_BUILTIN (FNFI, fnfi, XnXX ) \
- + NIOS2_DO_BUILTIN (FNFF, fnff, XnXX ) \
- + NIOS2_DO_BUILTIN (FNFP, fnfp, XnXX ) \
- + NIOS2_DO_BUILTIN (FNPI, fnpi, XnXX ) \
- + NIOS2_DO_BUILTIN (FNPF, fnpf, XnXX ) \
- + NIOS2_DO_BUILTIN (FNPP, fnpp, XnXX ) \
- + NIOS2_DO_BUILTIN (PN, pn, Xn ) \
- + NIOS2_DO_BUILTIN (PNI, pni, XnX ) \
- + NIOS2_DO_BUILTIN (PNF, pnf, XnX ) \
- + NIOS2_DO_BUILTIN (PNP, pnp, XnX ) \
- + NIOS2_DO_BUILTIN (PNII, pnii, XnXX ) \
- + NIOS2_DO_BUILTIN (PNIF, pnif, XnXX ) \
- + NIOS2_DO_BUILTIN (PNIP, pnip, XnXX ) \
- + NIOS2_DO_BUILTIN (PNFI, pnfi, XnXX ) \
- + NIOS2_DO_BUILTIN (PNFF, pnff, XnXX ) \
- + NIOS2_DO_BUILTIN (PNFP, pnfp, XnXX ) \
- + NIOS2_DO_BUILTIN (PNPI, pnpi, XnXX ) \
- + NIOS2_DO_BUILTIN (PNPF, pnpf, XnXX ) \
- + NIOS2_DO_BUILTIN (PNPP, pnpp, XnXX )
- +
- +const char *nios2_sys_nosys_string; /* for -msys=nosys */
- +const char *nios2_sys_lib_string; /* for -msys-lib= */
- +const char *nios2_sys_crt0_string; /* for -msys-crt0= */
- +
- +#undef NIOS2_FPU_INSN
- +#define NIOS2_FPU_INSN(opt, insn, args) \
- +static const char *NIOS2_CONCAT (nios2_output_fpu_insn_, insn) (rtx); \
- +static void NIOS2_CONCAT (nios2_pragma_, insn) (struct cpp_reader *); \
- +static void NIOS2_CONCAT (nios2_pragma_no_, insn) (struct cpp_reader *);
- +NIOS2_FOR_ALL_FPU_INSNS
- +
- +nios2_fpu_info nios2_fpu_insns[nios2_fpu_max_insn] = {
- +#undef NIOS2_FPU_INSN
- +#define NIOS2_FPU_INSN(opt, insn, args) \
- + { NIOS2_STRINGIFY (opt), \
- + NIOS2_STRINGIFY (insn), \
- + NIOS2_STRINGIFY (args), \
- + 0, \
- + -1, \
- + NIOS2_CONCAT (nios2_output_fpu_insn_, insn), \
- + "custom_" NIOS2_STRINGIFY (opt), \
- + NIOS2_CONCAT (nios2_pragma_, insn), \
- + "no_custom_" NIOS2_STRINGIFY (opt), \
- + NIOS2_CONCAT (nios2_pragma_no_, insn), \
- + 0, \
- + 0, \
- + 0, \
- + 0, \
- + 0 },
- + NIOS2_FOR_ALL_FPU_INSNS
- +};
- +
- +const char *nios2_custom_fpu_cfg_string;
- +
- +static const char *builtin_custom_seen[256];
- +
- +static void
- +nios2_custom_switch (const char *parameter, int *value, const char *opt)
- +{
- + /*
- + * We only document values from 0-255, but we secretly allow -1 so
- + * that the -mno-custom-<opt> switches work.
- + */
- + if (parameter && *parameter)
- + {
- + char *endptr;
- + long v = strtol (parameter, &endptr, 0);
- + if (*endptr)
- + {
- + error ("switch `-mcustom-%s' value `%s' must be a number between 0 and 255",
- + opt, parameter);
- + }
- + if (v < -1 || v > 255)
- + {
- + error ("switch `-mcustom-%s' value %ld must be between 0 and 255",
- + opt, v);
- + }
- + *value = (int)v;
- + }
- +}
- +
- +static void
- +nios2_custom_check_insns (int is_pragma)
- +{
- + int i;
- + int has_double = 0;
- + int errors = 0;
- + const char *ns[256];
- + int ps[256];
- +
- + for (i = 0; i < nios2_fpu_max_insn; i++)
- + {
- + if (nios2_fpu_insns[i].is_double && nios2_fpu_insns[i].N >= 0)
- + {
- + has_double = 1;
- + }
- + }
- +
- + if (has_double)
- + {
- + for (i = 0; i < nios2_fpu_max_insn; i++)
- + {
- + if (nios2_fpu_insns[i].needed_by_double
- + && nios2_fpu_insns[i].N < 0)
- + {
- + if (is_pragma)
- + {
- + error ("either switch `-mcustom-%s' or `#pragma custom_%s' is required for double precision floating point",
- + nios2_fpu_insns[i].option,
- + nios2_fpu_insns[i].option);
- + }
- + else
- + {
- + error ("switch `-mcustom-%s' is required for double precision floating point",
- + nios2_fpu_insns[i].option);
- + }
- + errors = 1;
- + }
- + }
- + }
- +
- + /*
- + * Warn if the user has certain exotic operations that won't get used
- + * without -funsafe-math-optimizations, See expand_builtin () in
- + * bulitins.c.
- + */
- + if (!flag_unsafe_math_optimizations)
- + {
- + for (i = 0; i < nios2_fpu_max_insn; i++)
- + {
- + if (nios2_fpu_insns[i].needs_unsafe && nios2_fpu_insns[i].N >= 0)
- + {
- + warning ("%s%s' has no effect unless -funsafe-math-optimizations is specified",
- + is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
- + nios2_fpu_insns[i].option);
- + /* Just one warning per function per compilation unit, please. */
- + nios2_fpu_insns[i].needs_unsafe = 0;
- + }
- + }
- + }
- +
- + /*
- + * Warn if the user is trying to use -mcustom-fmins et. al, that won't
- + * get used without -ffinite-math-only. See fold in fold () in
- + * fold-const.c
- + */
- + if (!flag_finite_math_only)
- + {
- + for (i = 0; i < nios2_fpu_max_insn; i++)
- + {
- + if (nios2_fpu_insns[i].needs_finite && nios2_fpu_insns[i].N >= 0)
- + {
- + warning ("%s%s' has no effect unless -ffinite-math-only is specified",
- + is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
- + nios2_fpu_insns[i].option);
- + /* Just one warning per function per compilation unit, please. */
- + nios2_fpu_insns[i].needs_finite = 0;
- + }
- + }
- + }
- +
- + /*
- + * Warn the user about double precision divide braindamage until we
- + * can fix it properly. See the RDIV_EXPR case of expand_expr_real in
- + * expr.c.
- + */
- + {
- + static int warned = 0;
- + if (flag_unsafe_math_optimizations
- + && !optimize_size
- + && nios2_fpu_insns[nios2_fpu_divdf3].N >= 0
- + && !warned)
- + {
- + warning ("%s%s' behaves poorly without -Os",
- + is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
- + nios2_fpu_insns[nios2_fpu_divdf3].option);
- + warned = 1;
- + }
- + }
- +
- + /*
- + * The following bit of voodoo is lifted from the generated file
- + * insn-opinit.c: to allow #pragmas to work properly, we have to tweak
- + * the optab_table manually -- it only gets initialized once after the
- + * switches are handled and before any #pragmas are seen.
- + */
- + if (is_pragma)
- + {
- + /* Only do this if the optabs have already been defined, not
- + when we're handling command line switches. */
- + addv_optab->handlers[SFmode].insn_code =
- + add_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + addv_optab->handlers[DFmode].insn_code =
- + add_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + subv_optab->handlers[SFmode].insn_code =
- + sub_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + subv_optab->handlers[DFmode].insn_code =
- + sub_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + smulv_optab->handlers[SFmode].insn_code =
- + smul_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + smulv_optab->handlers[DFmode].insn_code =
- + smul_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + sdiv_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + sdiv_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + negv_optab->handlers[SFmode].insn_code =
- + neg_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + negv_optab->handlers[DFmode].insn_code =
- + neg_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + smin_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + smin_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + smax_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + smax_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + absv_optab->handlers[SFmode].insn_code =
- + abs_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + absv_optab->handlers[DFmode].insn_code =
- + abs_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + sqrt_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + sqrt_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + cos_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + cos_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + sin_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + sin_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + tan_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + tan_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + atan_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + atan_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + exp_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + exp_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + log_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + log_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- + sfloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_nothing;
- + sfloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_nothing;
- + ufloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_nothing;
- + ufloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_nothing;
- + sfix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_nothing;
- + sfix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_nothing;
- + ufix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_nothing;
- + ufix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_nothing;
- + sext_optab->handlers[DFmode][SFmode].insn_code = CODE_FOR_nothing;
- + trunc_optab->handlers[SFmode][DFmode].insn_code = CODE_FOR_nothing;
- + cmp_optab->handlers[SFmode].insn_code = CODE_FOR_nothing;
- + cmp_optab->handlers[DFmode].insn_code = CODE_FOR_nothing;
- +
- + if (HAVE_addsf3)
- + addv_optab->handlers[SFmode].insn_code =
- + add_optab->handlers[SFmode].insn_code = CODE_FOR_addsf3;
- + if (HAVE_adddf3)
- + addv_optab->handlers[DFmode].insn_code =
- + add_optab->handlers[DFmode].insn_code = CODE_FOR_adddf3;
- + if (HAVE_subsf3)
- + subv_optab->handlers[SFmode].insn_code =
- + sub_optab->handlers[SFmode].insn_code = CODE_FOR_subsf3;
- + if (HAVE_subdf3)
- + subv_optab->handlers[DFmode].insn_code =
- + sub_optab->handlers[DFmode].insn_code = CODE_FOR_subdf3;
- + if (HAVE_mulsf3)
- + smulv_optab->handlers[SFmode].insn_code =
- + smul_optab->handlers[SFmode].insn_code = CODE_FOR_mulsf3;
- + if (HAVE_muldf3)
- + smulv_optab->handlers[DFmode].insn_code =
- + smul_optab->handlers[DFmode].insn_code = CODE_FOR_muldf3;
- + if (HAVE_divsf3)
- + sdiv_optab->handlers[SFmode].insn_code = CODE_FOR_divsf3;
- + if (HAVE_divdf3)
- + sdiv_optab->handlers[DFmode].insn_code = CODE_FOR_divdf3;
- + if (HAVE_negsf2)
- + negv_optab->handlers[SFmode].insn_code =
- + neg_optab->handlers[SFmode].insn_code = CODE_FOR_negsf2;
- + if (HAVE_negdf2)
- + negv_optab->handlers[DFmode].insn_code =
- + neg_optab->handlers[DFmode].insn_code = CODE_FOR_negdf2;
- + if (HAVE_minsf3)
- + smin_optab->handlers[SFmode].insn_code = CODE_FOR_minsf3;
- + if (HAVE_mindf3)
- + smin_optab->handlers[DFmode].insn_code = CODE_FOR_mindf3;
- + if (HAVE_maxsf3)
- + smax_optab->handlers[SFmode].insn_code = CODE_FOR_maxsf3;
- + if (HAVE_maxdf3)
- + smax_optab->handlers[DFmode].insn_code = CODE_FOR_maxdf3;
- + if (HAVE_abssf2)
- + absv_optab->handlers[SFmode].insn_code =
- + abs_optab->handlers[SFmode].insn_code = CODE_FOR_abssf2;
- + if (HAVE_absdf2)
- + absv_optab->handlers[DFmode].insn_code =
- + abs_optab->handlers[DFmode].insn_code = CODE_FOR_absdf2;
- + if (HAVE_sqrtsf2)
- + sqrt_optab->handlers[SFmode].insn_code = CODE_FOR_sqrtsf2;
- + if (HAVE_sqrtdf2)
- + sqrt_optab->handlers[DFmode].insn_code = CODE_FOR_sqrtdf2;
- + if (HAVE_cossf2)
- + cos_optab->handlers[SFmode].insn_code = CODE_FOR_cossf2;
- + if (HAVE_cosdf2)
- + cos_optab->handlers[DFmode].insn_code = CODE_FOR_cosdf2;
- + if (HAVE_sinsf2)
- + sin_optab->handlers[SFmode].insn_code = CODE_FOR_sinsf2;
- + if (HAVE_sindf2)
- + sin_optab->handlers[DFmode].insn_code = CODE_FOR_sindf2;
- + if (HAVE_tansf2)
- + tan_optab->handlers[SFmode].insn_code = CODE_FOR_tansf2;
- + if (HAVE_tandf2)
- + tan_optab->handlers[DFmode].insn_code = CODE_FOR_tandf2;
- + if (HAVE_atansf2)
- + atan_optab->handlers[SFmode].insn_code = CODE_FOR_atansf2;
- + if (HAVE_atandf2)
- + atan_optab->handlers[DFmode].insn_code = CODE_FOR_atandf2;
- + if (HAVE_expsf2)
- + exp_optab->handlers[SFmode].insn_code = CODE_FOR_expsf2;
- + if (HAVE_expdf2)
- + exp_optab->handlers[DFmode].insn_code = CODE_FOR_expdf2;
- + if (HAVE_logsf2)
- + log_optab->handlers[SFmode].insn_code = CODE_FOR_logsf2;
- + if (HAVE_logdf2)
- + log_optab->handlers[DFmode].insn_code = CODE_FOR_logdf2;
- + if (HAVE_floatsisf2)
- + sfloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_floatsisf2;
- + if (HAVE_floatsidf2)
- + sfloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_floatsidf2;
- + if (HAVE_floatunssisf2)
- + ufloat_optab->handlers[SFmode][SImode].insn_code = CODE_FOR_floatunssisf2;
- + if (HAVE_floatunssidf2)
- + ufloat_optab->handlers[DFmode][SImode].insn_code = CODE_FOR_floatunssidf2;
- + if (HAVE_fixsfsi2)
- + sfix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_fixsfsi2;
- + if (HAVE_fixdfsi2)
- + sfix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_fixdfsi2;
- + if (HAVE_fixunssfsi2)
- + ufix_optab->handlers[SImode][SFmode].insn_code = CODE_FOR_fixunssfsi2;
- + if (HAVE_fixunsdfsi2)
- + ufix_optab->handlers[SImode][DFmode].insn_code = CODE_FOR_fixunsdfsi2;
- + if (HAVE_extendsfdf2)
- + sext_optab->handlers[DFmode][SFmode].insn_code = CODE_FOR_extendsfdf2;
- + if (HAVE_truncdfsf2)
- + trunc_optab->handlers[SFmode][DFmode].insn_code = CODE_FOR_truncdfsf2;
- + if (HAVE_cmpsf)
- + cmp_optab->handlers[SFmode].insn_code = CODE_FOR_cmpsf;
- + if (HAVE_cmpdf)
- + cmp_optab->handlers[DFmode].insn_code = CODE_FOR_cmpdf;
- + }
- +
- + /* Check for duplicate values of N */
- + for (i = 0; i < 256; i++)
- + {
- + ns[i] = 0;
- + ps[i] = 0;
- + }
- +
- + for (i = 0; i < nios2_fpu_max_insn; i++)
- + {
- + int N = nios2_fpu_insns[i].N;
- + if (N >= 0)
- + {
- + if (ns[N])
- + {
- + error ("%s%s' conflicts with %s%s'",
- + is_pragma ? "`#pragma custom_" : "switch `-mcustom-",
- + nios2_fpu_insns[i].option,
- + ps[N] ? "`#pragma custom_" : "switch `-mcustom-",
- + ns[N]);
- + errors = 1;
- + }
- + else if (builtin_custom_seen[N])
- + {
- + error ("call to `%s' conflicts with %s%s'",
- + builtin_custom_seen[N],
- + (nios2_fpu_insns[i].pragma_seen
- + ? "`#pragma custom_" : "switch `-mcustom-"),
- + nios2_fpu_insns[i].option);
- + errors = 1;
- + }
- + else
- + {
- + ns[N] = nios2_fpu_insns[i].option;
- + ps[N] = nios2_fpu_insns[i].pragma_seen;
- + }
- + }
- + }
- +
- + if (errors)
- + {
- + fatal_error ("conflicting use of -mcustom switches, #pragmas, and/or __builtin_custom_ functions");
- + }
- +}
- +
- +static void
- +nios2_handle_custom_fpu_cfg (const char *cfg, int is_pragma)
- +{
- +#undef NIOS2_FPU_INSN
- +#define NIOS2_FPU_INSN(opt, insn, args) \
- + int opt = nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].N;
- +NIOS2_FOR_ALL_FPU_INSNS
- +
- + /*
- + * ??? These are just some sample possibilities. We'll change these
- + * at the last minute to match the capabilities of the actual fpu.
- + */
- + if (!strcasecmp (cfg, "60-1"))
- + {
- + fmuls = 252;
- + fadds = 253;
- + fsubs = 254;
- + flag_single_precision_constant = 1;
- + }
- + else if (!strcasecmp (cfg, "60-2"))
- + {
- + fmuls = 252;
- + fadds = 253;
- + fsubs = 254;
- + fdivs = 255;
- + flag_single_precision_constant = 1;
- + }
- + else if (!strcasecmp (cfg, "72-3"))
- + {
- + floatus = 243;
- + fixsi = 244;
- + floatis = 245;
- + fcmpgts = 246;
- + fcmples = 249;
- + fcmpeqs = 250;
- + fcmpnes = 251;
- + fmuls = 252;
- + fadds = 253;
- + fsubs = 254;
- + fdivs = 255;
- + flag_single_precision_constant = 1;
- + }
- + else
- + {
- + warning ("ignoring unrecognized %sfpu-cfg' value `%s'",
- + is_pragma ? "`#pragma custom_" : "switch -mcustom-", cfg);
- + }
- +
- +#undef NIOS2_FPU_INSN
- +#define NIOS2_FPU_INSN(opt, insn, args) \
- + nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].N = opt;
- +NIOS2_FOR_ALL_FPU_INSNS
- +
- + /* Guard against errors in the standard configurations. */
- + nios2_custom_check_insns (is_pragma);
- +}
- +
- +void
- +override_options ()
- +{
- + int i;
- +
- + /* Function to allocate machine-dependent function status. */
- + init_machine_status = &nios2_init_machine_status;
- +
- + nios2_section_threshold
- + = g_switch_set ? g_switch_value : NIOS2_DEFAULT_GVALUE;
- +
- + if (nios2_sys_nosys_string && *nios2_sys_nosys_string)
- + {
- + error ("invalid option '-msys=nosys%s'", nios2_sys_nosys_string);
- + }
- +
- + /* If we don't have mul, we don't have mulx either! */
- + if (!TARGET_HAS_MUL && TARGET_HAS_MULX)
- + {
- + target_flags &= ~HAS_MULX_FLAG;
- + }
- +
- + /* Set up for stack limit checking */
- + if (TARGET_STACK_CHECK)
- + {
- + stack_limit_rtx = gen_rtx_REG(SImode, ET_REGNO);
- + }
- +
- + for (i = 0; i < nios2_fpu_max_insn; i++)
- + {
- + nios2_fpu_insns[i].is_double = (nios2_fpu_insns[i].args[0] == 'd'
- + || nios2_fpu_insns[i].args[0] == 'd'
- + || nios2_fpu_insns[i].args[0] == 'd');
- + nios2_fpu_insns[i].needed_by_double = (i == nios2_fpu_nios2_fwrx
- + || i == nios2_fpu_nios2_fwry
- + || i == nios2_fpu_nios2_frdxlo
- + || i == nios2_fpu_nios2_frdxhi
- + || i == nios2_fpu_nios2_frdy);
- + nios2_fpu_insns[i].needs_unsafe = (i == nios2_fpu_cossf2
- + || i == nios2_fpu_cosdf2
- + || i == nios2_fpu_sinsf2
- + || i == nios2_fpu_sindf2
- + || i == nios2_fpu_tansf2
- + || i == nios2_fpu_tandf2
- + || i == nios2_fpu_atansf2
- + || i == nios2_fpu_atandf2
- + || i == nios2_fpu_expsf2
- + || i == nios2_fpu_expdf2
- + || i == nios2_fpu_logsf2
- + || i == nios2_fpu_logdf2);
- + nios2_fpu_insns[i].needs_finite = (i == nios2_fpu_minsf3
- + || i == nios2_fpu_maxsf3
- + || i == nios2_fpu_mindf3
- + || i == nios2_fpu_maxdf3);
- + }
- +
- + /*
- + * We haven't seen any __builtin_custom functions yet.
- + */
- + for (i = 0; i < 256; i++)
- + {
- + builtin_custom_seen[i] = 0;
- + }
- +
- + /*
- + * Set up default handling for floating point custom instructions.
- + *
- + * Putting things in this order means that the -mcustom-fpu-cfg=
- + * switch will always be overridden by individual -mcustom-fadds=
- + * switches, regardless of the order in which they were specified
- + * on the command line. ??? Remember to document this.
- + */
- + if (nios2_custom_fpu_cfg_string && *nios2_custom_fpu_cfg_string)
- + {
- + nios2_handle_custom_fpu_cfg (nios2_custom_fpu_cfg_string, 0);
- + }
- +
- + for (i = 0; i < nios2_fpu_max_insn; i++)
- + {
- + nios2_custom_switch (nios2_fpu_insns[i].value,
- + &nios2_fpu_insns[i].N,
- + nios2_fpu_insns[i].option);
- + }
- +
- + nios2_custom_check_insns (0);
- +}
- +
- +void
- +optimization_options (int level, int size)
- +{
- + if (level || size)
- + {
- + target_flags |= INLINE_MEMCPY_FLAG;
- + }
- +
- + if (level >= 3 && !size)
- + {
- + target_flags |= FAST_SW_DIV_FLAG;
- + }
- +}
- +
- +/* Allocate a chunk of memory for per-function machine-dependent data. */
- +static struct machine_function *
- +nios2_init_machine_status ()
- +{
- + return ((struct machine_function *)
- + ggc_alloc_cleared (sizeof (struct machine_function)));
- +}
- +
- +
- +
- +/*****************
- + * Describing Relative Costs of Operations
- + *****************/
- +
- +/* Compute a (partial) cost for rtx X. Return true if the complete
- + cost has been computed, and false if subexpressions should be
- + scanned. In either case, *TOTAL contains the cost result. */
- +
- +
- +
- +static bool
- +nios2_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED, int *total)
- +{
- + switch (code)
- + {
- + case CONST_INT:
- + if (INTVAL (x) == 0)
- + {
- + *total = COSTS_N_INSNS (0);
- + return true;
- + }
- + else if (SMALL_INT (INTVAL (x))
- + || SMALL_INT_UNSIGNED (INTVAL (x))
- + || UPPER16_INT (INTVAL (x)))
- + {
- + *total = COSTS_N_INSNS (2);
- + return true;
- + }
- + else
- + {
- + *total = COSTS_N_INSNS (4);
- + return true;
- + }
- +
- + case LABEL_REF:
- + case SYMBOL_REF:
- + /* ??? gp relative stuff will fit in here */
- + /* fall through */
- + case CONST:
- + case CONST_DOUBLE:
- + {
- + *total = COSTS_N_INSNS (4);
- + return true;
- + }
- +
- + case MULT:
- + {
- + *total = COSTS_N_INSNS (1);
- + return false;
- + }
- + case SIGN_EXTEND:
- + {
- + *total = COSTS_N_INSNS (3);
- + return false;
- + }
- + case ZERO_EXTEND:
- + {
- + *total = COSTS_N_INSNS (1);
- + return false;
- + }
- +
- + default:
- + return false;
- + }
- +}
- +
- +
- +/***************************************
- + * INSTRUCTION SUPPORT
- + *
- + * These functions are used within the Machine Description to
- + * handle common or complicated output and expansions from
- + * instructions.
- + ***************************************/
- +
- +int
- +nios2_emit_move_sequence (rtx *operands, enum machine_mode mode)
- +{
- + rtx to = operands[0];
- + rtx from = operands[1];
- +
- + if (!register_operand (to, mode) && !reg_or_0_operand (from, mode))
- + {
- + if (no_new_pseudos)
- + internal_error ("Trying to force_reg no_new_pseudos == 1");
- + from = copy_to_mode_reg (mode, from);
- + }
- +
- + operands[0] = to;
- + operands[1] = from;
- + return 0;
- +}
- +
- +/* Divide Support */
- +
- +/*
- + If -O3 is used, we want to output a table lookup for
- + divides between small numbers (both num and den >= 0
- + and < 0x10). The overhead of this method in the worse
- + case is 40 bytes in the text section (10 insns) and
- + 256 bytes in the data section. Additional divides do
- + not incur additional penalties in the data section.
- +
- + Code speed is improved for small divides by about 5x
- + when using this method in the worse case (~9 cycles
- + vs ~45). And in the worse case divides not within the
- + table are penalized by about 10% (~5 cycles vs ~45).
- + However in the typical case the penalty is not as bad
- + because doing the long divide in only 45 cycles is
- + quite optimistic.
- +
- + ??? It would be nice to have some benchmarks other
- + than Dhrystone to back this up.
- +
- + This bit of expansion is to create this instruction
- + sequence as rtl.
- + or $8, $4, $5
- + slli $9, $4, 4
- + cmpgeui $3, $8, 16
- + beq $3, $0, .L3
- + or $10, $9, $5
- + add $12, $11, divide_table
- + ldbu $2, 0($12)
- + br .L1
- +.L3:
- + call slow_div
- +.L1:
- +# continue here with result in $2
- +
- + ??? Ideally I would like the emit libcall block to contain
- + all of this code, but I don't know how to do that. What it
- + means is that if the divide can be eliminated, it may not
- + completely disappear.
- +
- + ??? The __divsi3_table label should ideally be moved out
- + of this block and into a global. If it is placed into the
- + sdata section we can save even more cycles by doing things
- + gp relative.
- +*/
- +int
- +nios2_emit_expensive_div (rtx *operands, enum machine_mode mode)
- +{
- + rtx or_result, shift_left_result;
- + rtx lookup_value;
- + rtx lab1, lab3;
- + rtx insns;
- + rtx libfunc;
- + rtx final_result;
- + rtx tmp;
- +
- + /* it may look a little generic, but only SImode
- + is supported for now */
- + if (mode != SImode)
- + abort ();
- +
- + libfunc = sdiv_optab->handlers[(int) SImode].libfunc;
- +
- +
- +
- + lab1 = gen_label_rtx ();
- + lab3 = gen_label_rtx ();
- +
- + or_result = expand_simple_binop (SImode, IOR,
- + operands[1], operands[2],
- + 0, 0, OPTAB_LIB_WIDEN);
- +
- + emit_cmp_and_jump_insns (or_result, GEN_INT (15), GTU, 0,
- + GET_MODE (or_result), 0, lab3);
- + JUMP_LABEL (get_last_insn ()) = lab3;
- +
- + shift_left_result = expand_simple_binop (SImode, ASHIFT,
- + operands[1], GEN_INT (4),
- + 0, 0, OPTAB_LIB_WIDEN);
- +
- + lookup_value = expand_simple_binop (SImode, IOR,
- + shift_left_result, operands[2],
- + 0, 0, OPTAB_LIB_WIDEN);
- +
- + convert_move (operands[0],
- + gen_rtx (MEM, QImode,
- + gen_rtx (PLUS, SImode,
- + lookup_value,
- + gen_rtx_SYMBOL_REF (SImode, "__divsi3_table"))),
- + 1);
- +
- +
- + tmp = emit_jump_insn (gen_jump (lab1));
- + JUMP_LABEL (tmp) = lab1;
- + emit_barrier ();
- +
- + emit_label (lab3);
- + LABEL_NUSES (lab3) = 1;
- +
- + start_sequence ();
- + final_result = emit_library_call_value (libfunc, NULL_RTX,
- + LCT_CONST, SImode, 2,
- + operands[1], SImode,
- + operands[2], SImode);
- +
- +
- + insns = get_insns ();
- + end_sequence ();
- + emit_libcall_block (insns, operands[0], final_result,
- + gen_rtx (DIV, SImode, operands[1], operands[2]));
- +
- + emit_label (lab1);
- + LABEL_NUSES (lab1) = 1;
- + return 1;
- +}
- +
- +/* Branches/Compares */
- +
- +/* the way of handling branches/compares
- + in gcc is heavily borrowed from MIPS */
- +
- +enum internal_test
- +{
- + ITEST_EQ,
- + ITEST_NE,
- + ITEST_GT,
- + ITEST_GE,
- + ITEST_LT,
- + ITEST_LE,
- + ITEST_GTU,
- + ITEST_GEU,
- + ITEST_LTU,
- + ITEST_LEU,
- + ITEST_MAX
- +};
- +
- +static enum internal_test map_test_to_internal_test (enum rtx_code);
- +
- +/* Cached operands, and operator to compare for use in set/branch/trap
- + on condition codes. */
- +rtx branch_cmp[2];
- +enum cmp_type branch_type;
- +
- +/* Make normal rtx_code into something we can index from an array */
- +
- +static enum internal_test
- +map_test_to_internal_test (enum rtx_code test_code)
- +{
- + enum internal_test test = ITEST_MAX;
- +
- + switch (test_code)
- + {
- + case EQ:
- + test = ITEST_EQ;
- + break;
- + case NE:
- + test = ITEST_NE;
- + break;
- + case GT:
- + test = ITEST_GT;
- + break;
- + case GE:
- + test = ITEST_GE;
- + break;
- + case LT:
- + test = ITEST_LT;
- + break;
- + case LE:
- + test = ITEST_LE;
- + break;
- + case GTU:
- + test = ITEST_GTU;
- + break;
- + case GEU:
- + test = ITEST_GEU;
- + break;
- + case LTU:
- + test = ITEST_LTU;
- + break;
- + case LEU:
- + test = ITEST_LEU;
- + break;
- + default:
- + break;
- + }
- +
- + return test;
- +}
- +
- +bool have_nios2_fpu_cmp_insn( enum rtx_code cond_t, enum cmp_type cmp_t );
- +enum rtx_code get_reverse_cond(enum rtx_code cond_t);
- +
- +bool
- +have_nios2_fpu_cmp_insn( enum rtx_code cond_t, enum cmp_type cmp_t )
- +{
- + if (cmp_t == CMP_SF)
- + {
- + switch (cond_t) {
- + case EQ:
- + return (nios2_fpu_insns[nios2_fpu_nios2_seqsf].N >= 0);
- + case NE:
- + return (nios2_fpu_insns[nios2_fpu_nios2_snesf].N >= 0);
- + case GT:
- + return (nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N >= 0);
- + case GE:
- + return (nios2_fpu_insns[nios2_fpu_nios2_sgesf].N >= 0);
- + case LT:
- + return (nios2_fpu_insns[nios2_fpu_nios2_sltsf].N >= 0);
- + case LE:
- + return (nios2_fpu_insns[nios2_fpu_nios2_slesf].N >= 0);
- + default:
- + break;
- + }
- + }
- + else if (cmp_t == CMP_DF)
- + {
- + switch (cond_t) {
- + case EQ:
- + return (nios2_fpu_insns[nios2_fpu_nios2_seqdf].N >= 0);
- + case NE:
- + return (nios2_fpu_insns[nios2_fpu_nios2_snedf].N >= 0);
- + case GT:
- + return (nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N >= 0);
- + case GE:
- + return (nios2_fpu_insns[nios2_fpu_nios2_sgedf].N >= 0);
- + case LT:
- + return (nios2_fpu_insns[nios2_fpu_nios2_sltdf].N >= 0);
- + case LE:
- + return (nios2_fpu_insns[nios2_fpu_nios2_sledf].N >= 0);
- + default:
- + break;
- + }
- + }
- +
- + return false;
- +}
- +
- +/* Note that get_reverse_cond() is not the same as get_inverse_cond()
- + get_reverse_cond() means that if the operand order is reversed,
- + what is the operand that is needed to generate the same condition?
- +*/
- +enum rtx_code
- +get_reverse_cond(enum rtx_code cond_t)
- +{
- + switch (cond_t)
- + {
- + case GT: return LT;
- + case GE: return LE;
- + case LT: return GT;
- + case LE: return GE;
- + case GTU: return LTU;
- + case GEU: return LEU;
- + case LTU: return GTU;
- + case LEU: return GEU;
- + default: break;
- + }
- +
- + return cond_t;
- +}
- +
- +
- +/* Generate the code to compare (and possibly branch) two integer values
- + TEST_CODE is the comparison code we are trying to emulate
- + (or implement directly)
- + RESULT is where to store the result of the comparison,
- + or null to emit a branch
- + CMP0 CMP1 are the two comparison operands
- + DESTINATION is the destination of the branch, or null to only compare
- + */
- +
- +void
- +gen_int_relational (enum rtx_code test_code, /* relational test (EQ, etc) */
- + rtx result, /* result to store comp. or 0 if branch */
- + rtx cmp0, /* first operand to compare */
- + rtx cmp1, /* second operand to compare */
- + rtx destination) /* destination of the branch, or 0 if compare */
- +{
- + struct cmp_info
- + {
- + /* for register (or 0) compares */
- + enum rtx_code test_code_reg; /* code to use in instruction (LT vs. LTU) */
- + int reverse_regs; /* reverse registers in test */
- +
- + /* for immediate compares */
- + enum rtx_code test_code_const;
- + /* code to use in instruction (LT vs. LTU) */
- + int const_low; /* low bound of constant we can accept */
- + int const_high; /* high bound of constant we can accept */
- + int const_add; /* constant to add */
- +
- + /* generic info */
- + int unsignedp; /* != 0 for unsigned comparisons. */
- + };
- +
- + static const struct cmp_info info[(int) ITEST_MAX] = {
- +
- + {EQ, 0, EQ, -32768, 32767, 0, 0}, /* EQ */
- + {NE, 0, NE, -32768, 32767, 0, 0}, /* NE */
- +
- + {LT, 1, GE, -32769, 32766, 1, 0}, /* GT */
- + {GE, 0, GE, -32768, 32767, 0, 0}, /* GE */
- + {LT, 0, LT, -32768, 32767, 0, 0}, /* LT */
- + {GE, 1, LT, -32769, 32766, 1, 0}, /* LE */
- +
- + {LTU, 1, GEU, 0, 65534, 1, 0}, /* GTU */
- + {GEU, 0, GEU, 0, 65535, 0, 0}, /* GEU */
- + {LTU, 0, LTU, 0, 65535, 0, 0}, /* LTU */
- + {GEU, 1, LTU, 0, 65534, 1, 0}, /* LEU */
- + };
- +
- + enum internal_test test;
- + enum machine_mode mode;
- + const struct cmp_info *p_info;
- + int branch_p;
- +
- +
- + test = map_test_to_internal_test (test_code);
- + if (test == ITEST_MAX)
- + abort ();
- +
- + p_info = &info[(int) test];
- +
- + mode = GET_MODE (cmp0);
- + if (mode == VOIDmode)
- + mode = GET_MODE (cmp1);
- +
- + branch_p = (destination != 0);
- +
- + /* Handle floating point comparison directly. */
- + if (branch_type == CMP_SF || branch_type == CMP_DF)
- + {
- +
- + bool reverse_operands = false;
- +
- + enum machine_mode float_mode = (branch_type == CMP_SF) ? SFmode : DFmode;
- +
- + if (!register_operand (cmp0, float_mode)
- + || !register_operand (cmp1, float_mode))
- + {
- + abort ();
- + }
- +
- + if (branch_p)
- + {
- + test_code = p_info->test_code_reg;
- + reverse_operands = (p_info->reverse_regs);
- + }
- +
- + if ( !have_nios2_fpu_cmp_insn(test_code, branch_type) &&
- + have_nios2_fpu_cmp_insn(get_reverse_cond(test_code), branch_type) )
- + {
- + test_code = get_reverse_cond(test_code);
- + reverse_operands = !reverse_operands;
- + }
- +
- + if (reverse_operands)
- + {
- + rtx temp = cmp0;
- + cmp0 = cmp1;
- + cmp1 = temp;
- + }
- +
- + if (branch_p)
- + {
- + rtx cond = gen_rtx (test_code, SImode, cmp0, cmp1);
- + rtx label = gen_rtx_LABEL_REF (VOIDmode, destination);
- + rtx insn = gen_rtx_SET (VOIDmode, pc_rtx,
- + gen_rtx_IF_THEN_ELSE (VOIDmode,
- + cond, label, pc_rtx));
- + emit_jump_insn (insn);
- + }
- + else
- + {
- + emit_move_insn (result, gen_rtx (test_code, SImode, cmp0, cmp1));
- + }
- + return;
- + }
- +
- + /* We can't, under any circumstances, have const_ints in cmp0
- + ??? Actually we could have const0 */
- + if (GET_CODE (cmp0) == CONST_INT)
- + cmp0 = force_reg (mode, cmp0);
- +
- + /* if the comparison is against an int not in legal range
- + move it into a register */
- + if (GET_CODE (cmp1) == CONST_INT)
- + {
- + HOST_WIDE_INT value = INTVAL (cmp1);
- +
- + if (value < p_info->const_low || value > p_info->const_high)
- + cmp1 = force_reg (mode, cmp1);
- + }
- +
- + /* Comparison to constants, may involve adding 1 to change a GT into GE.
- + Comparison between two registers, may involve switching operands. */
- + if (GET_CODE (cmp1) == CONST_INT)
- + {
- + if (p_info->const_add != 0)
- + {
- + HOST_WIDE_INT new = INTVAL (cmp1) + p_info->const_add;
- +
- + /* If modification of cmp1 caused overflow,
- + we would get the wrong answer if we follow the usual path;
- + thus, x > 0xffffffffU would turn into x > 0U. */
- + if ((p_info->unsignedp
- + ? (unsigned HOST_WIDE_INT) new >
- + (unsigned HOST_WIDE_INT) INTVAL (cmp1)
- + : new > INTVAL (cmp1)) != (p_info->const_add > 0))
- + {
- + /* ??? This case can never happen with the current numbers,
- + but I am paranoid and would rather an abort than
- + a bug I will never find */
- + abort ();
- + }
- + else
- + cmp1 = GEN_INT (new);
- + }
- + }
- +
- + else if (p_info->reverse_regs)
- + {
- + rtx temp = cmp0;
- + cmp0 = cmp1;
- + cmp1 = temp;
- + }
- +
- +
- +
- + if (branch_p)
- + {
- + if (register_operand (cmp0, mode) && register_operand (cmp1, mode))
- + {
- + rtx insn;
- + rtx cond = gen_rtx (p_info->test_code_reg, mode, cmp0, cmp1);
- + rtx label = gen_rtx_LABEL_REF (VOIDmode, destination);
- +
- + insn = gen_rtx_SET (VOIDmode, pc_rtx,
- + gen_rtx_IF_THEN_ELSE (VOIDmode,
- + cond, label, pc_rtx));
- + emit_jump_insn (insn);
- + }
- + else
- + {
- + rtx cond, label;
- +
- + result = gen_reg_rtx (mode);
- +
- + emit_move_insn (result,
- + gen_rtx (p_info->test_code_const, mode, cmp0,
- + cmp1));
- +
- + cond = gen_rtx (NE, mode, result, const0_rtx);
- + label = gen_rtx_LABEL_REF (VOIDmode, destination);
- +
- + emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
- + gen_rtx_IF_THEN_ELSE (VOIDmode,
- + cond,
- + label, pc_rtx)));
- + }
- + }
- + else
- + {
- + if (register_operand (cmp0, mode) && register_operand (cmp1, mode))
- + {
- + emit_move_insn (result,
- + gen_rtx (p_info->test_code_reg, mode, cmp0, cmp1));
- + }
- + else
- + {
- + emit_move_insn (result,
- + gen_rtx (p_info->test_code_const, mode, cmp0,
- + cmp1));
- + }
- + }
- +
- +}
- +
- +
- +/* ??? For now conditional moves are only supported
- + when the mode of the operands being compared are
- + the same as the ones being moved */
- +
- +void
- +gen_conditional_move (rtx *operands, enum machine_mode mode)
- +{
- + rtx insn, cond;
- + rtx cmp_reg = gen_reg_rtx (mode);
- + enum rtx_code cmp_code = GET_CODE (operands[1]);
- + enum rtx_code move_code = EQ;
- +
- + /* emit a comparison if it is not "simple".
- + Simple comparisons are X eq 0 and X ne 0 */
- + if ((cmp_code == EQ || cmp_code == NE) && branch_cmp[1] == const0_rtx)
- + {
- + cmp_reg = branch_cmp[0];
- + move_code = cmp_code;
- + }
- + else if ((cmp_code == EQ || cmp_code == NE) && branch_cmp[0] == const0_rtx)
- + {
- + cmp_reg = branch_cmp[1];
- + move_code = cmp_code == EQ ? NE : EQ;
- + }
- + else
- + gen_int_relational (cmp_code, cmp_reg, branch_cmp[0], branch_cmp[1],
- + NULL_RTX);
- +
- + cond = gen_rtx (move_code, VOIDmode, cmp_reg, CONST0_RTX (mode));
- + insn = gen_rtx_SET (mode, operands[0],
- + gen_rtx_IF_THEN_ELSE (mode,
- + cond, operands[2], operands[3]));
- + emit_insn (insn);
- +}
- +
- +/*******************
- + * Addressing Modes
- + *******************/
- +
- +int
- +nios2_legitimate_address (rtx operand, enum machine_mode mode ATTRIBUTE_UNUSED,
- + int strict)
- +{
- + int ret_val = 0;
- +
- + switch (GET_CODE (operand))
- + {
- + /* direct. */
- + case SYMBOL_REF:
- + if (SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (operand))
- + {
- + ret_val = 1;
- + break;
- + }
- + /* else, fall through */
- + case LABEL_REF:
- + case CONST_INT:
- + case CONST:
- + case CONST_DOUBLE:
- + /* ??? In here I need to add gp addressing */
- + ret_val = 0;
- +
- + break;
- +
- + /* Register indirect. */
- + case REG:
- + ret_val = REG_OK_FOR_BASE_P2 (operand, strict);
- + break;
- +
- + /* Register indirect with displacement */
- + case PLUS:
- + {
- + rtx op0 = XEXP (operand, 0);
- + rtx op1 = XEXP (operand, 1);
- +
- + if (REG_P (op0) && REG_P (op1))
- + ret_val = 0;
- + else if (REG_P (op0) && GET_CODE (op1) == CONST_INT)
- + ret_val = REG_OK_FOR_BASE_P2 (op0, strict)
- + && SMALL_INT (INTVAL (op1));
- + else if (REG_P (op1) && GET_CODE (op0) == CONST_INT)
- + ret_val = REG_OK_FOR_BASE_P2 (op1, strict)
- + && SMALL_INT (INTVAL (op0));
- + else
- + ret_val = 0;
- + }
- + break;
- +
- + default:
- + ret_val = 0;
- + break;
- + }
- +
- + return ret_val;
- +}
- +
- +/* Return true if EXP should be placed in the small data section. */
- +
- +static bool
- +nios2_in_small_data_p (tree exp)
- +{
- + /* We want to merge strings, so we never consider them small data. */
- + if (TREE_CODE (exp) == STRING_CST)
- + return false;
- +
- + if (TREE_CODE (exp) == VAR_DECL && DECL_SECTION_NAME (exp))
- + {
- + const char *section = TREE_STRING_POINTER (DECL_SECTION_NAME (exp));
- + /* ??? these string names need moving into
- + an array in some header file */
- + if (nios2_section_threshold > 0
- + && (strcmp (section, ".sbss") == 0
- + || strncmp (section, ".sbss.", 6) == 0
- + || strcmp (section, ".sdata") == 0
- + || strncmp (section, ".sdata.", 7) == 0))
- + return true;
- + }
- + else if (TREE_CODE (exp) == VAR_DECL)
- + {
- + HOST_WIDE_INT size = int_size_in_bytes (TREE_TYPE (exp));
- +
- + /* If this is an incomplete type with size 0, then we can't put it
- + in sdata because it might be too big when completed. */
- + if (size > 0 && (unsigned HOST_WIDE_INT)size <= nios2_section_threshold)
- + return true;
- + }
- +
- + return false;
- +}
- +
- +static void
- +nios2_encode_section_info (tree decl, rtx rtl, int first)
- +{
- +
- + rtx symbol;
- + int flags;
- +
- + default_encode_section_info (decl, rtl, first);
- +
- + /* Careful not to prod global register variables. */
- + if (GET_CODE (rtl) != MEM)
- + return;
- + symbol = XEXP (rtl, 0);
- + if (GET_CODE (symbol) != SYMBOL_REF)
- + return;
- +
- + flags = SYMBOL_REF_FLAGS (symbol);
- +
- + /* We don't want weak variables to be addressed with gp in case they end up with
- + value 0 which is not within 2^15 of $gp */
- + if (DECL_P (decl) && DECL_WEAK (decl))
- + flags |= SYMBOL_FLAG_WEAK_DECL;
- +
- + SYMBOL_REF_FLAGS (symbol) = flags;
- +}
- +
- +
- +static unsigned int
- +nios2_section_type_flags (tree decl, const char *name, int reloc)
- +{
- + unsigned int flags;
- +
- + flags = default_section_type_flags (decl, name, reloc);
- +
- + /* ??? these string names need moving into an array in some header file */
- + if (strcmp (name, ".sbss") == 0
- + || strncmp (name, ".sbss.", 6) == 0
- + || strcmp (name, ".sdata") == 0
- + || strncmp (name, ".sdata.", 7) == 0)
- + flags |= SECTION_SMALL;
- +
- + return flags;
- +}
- +
- +/* Handle a #pragma reverse_bitfields */
- +static void
- +nios2_pragma_reverse_bitfields (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
- +{
- + nios2_pragma_reverse_bitfields_flag = 1; /* Reverse */
- +}
- +
- +/* Handle a #pragma no_reverse_bitfields */
- +static void
- +nios2_pragma_no_reverse_bitfields (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
- +{
- + nios2_pragma_reverse_bitfields_flag = -1; /* Forward */
- +}
- +
- +/* Handle the various #pragma custom_<switch>s */
- +static void
- +nios2_pragma_fpu (int *value, const char *opt, int *seen)
- +{
- + tree t;
- + if (c_lex (&t) != CPP_NUMBER)
- + {
- + error ("`#pragma custom_%s' value must be a number between 0 and 255",
- + opt);
- + return;
- + }
- +
- + if (TREE_INT_CST_HIGH (t) == 0
- + && TREE_INT_CST_LOW (t) <= 255)
- + {
- + *value = (int)TREE_INT_CST_LOW (t);
- + *seen = 1;
- + }
- + else
- + {
- + error ("`#pragma custom_%s' value must be between 0 and 255", opt);
- + }
- + nios2_custom_check_insns (1);
- +}
- +
- +/* Handle the various #pragma no_custom_<switch>s */
- +static void
- +nios2_pragma_no_fpu (int *value, const char *opt ATTRIBUTE_UNUSED)
- +{
- + *value = -1;
- + nios2_custom_check_insns (1);
- +}
- +
- +#undef NIOS2_FPU_INSN
- +#define NIOS2_FPU_INSN(opt, insn, args) \
- +static void \
- +NIOS2_CONCAT (nios2_pragma_, insn) \
- + (struct cpp_reader *pfile ATTRIBUTE_UNUSED) \
- +{ \
- + nios2_fpu_info *inf = &(nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)]); \
- + nios2_pragma_fpu (&(inf->N), inf->option, &(inf->pragma_seen)); \
- +} \
- +static void \
- +NIOS2_CONCAT (nios2_pragma_no_, insn) \
- + (struct cpp_reader *pfile ATTRIBUTE_UNUSED) \
- +{ \
- + nios2_fpu_info *inf = &(nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)]); \
- + nios2_pragma_no_fpu (&(inf->N), inf->option); \
- +}
- +NIOS2_FOR_ALL_FPU_INSNS
- +
- +static void
- +nios2_pragma_handle_custom_fpu_cfg (struct cpp_reader *pfile ATTRIBUTE_UNUSED)
- +{
- + tree t;
- + if (c_lex (&t) != CPP_STRING)
- + {
- + error ("`#pragma custom_fpu_cfg' value must be a string");
- + return;
- + }
- +
- + if (TREE_STRING_LENGTH (t) > 0)
- + {
- + nios2_handle_custom_fpu_cfg (TREE_STRING_POINTER (t), 1);
- + }
- +}
- +
- +void
- +nios2_register_target_pragmas ()
- +{
- + int i;
- +
- + c_register_pragma (0, "reverse_bitfields",
- + nios2_pragma_reverse_bitfields);
- + c_register_pragma (0, "no_reverse_bitfields",
- + nios2_pragma_no_reverse_bitfields);
- +
- + for (i = 0; i < nios2_fpu_max_insn; i++)
- + {
- + nios2_fpu_info *inf = &(nios2_fpu_insns[i]);
- + c_register_pragma (0, inf->pname, inf->pragma);
- + c_register_pragma (0, inf->nopname, inf->nopragma);
- + }
- +
- + c_register_pragma (0, "custom_fpu_cfg",
- + nios2_pragma_handle_custom_fpu_cfg);
- +}
- +
- +/* Handle a "reverse_bitfields" or "no_reverse_bitfields" attribute.
- + ??? What do these attributes mean on a union? */
- +static tree
- +nios2_handle_struct_attribute (tree *node, tree name,
- + tree args ATTRIBUTE_UNUSED,
- + int flags ATTRIBUTE_UNUSED,
- + bool *no_add_attrs)
- +{
- + tree *type = NULL;
- + if (DECL_P (*node))
- + {
- + if (TREE_CODE (*node) == TYPE_DECL)
- + {
- + type = &TREE_TYPE (*node);
- + }
- + }
- + else
- + {
- + type = node;
- + }
- +
- + if (!(type && (TREE_CODE (*type) == RECORD_TYPE
- + || TREE_CODE (*type) == UNION_TYPE)))
- + {
- + warning ("`%s' attribute ignored", IDENTIFIER_POINTER (name));
- + *no_add_attrs = true;
- + }
- +
- + else if ((is_attribute_p ("reverse_bitfields", name)
- + && lookup_attribute ("no_reverse_bitfields",
- + TYPE_ATTRIBUTES (*type)))
- + || ((is_attribute_p ("no_reverse_bitfields", name)
- + && lookup_attribute ("reverse_bitfields",
- + TYPE_ATTRIBUTES (*type)))))
- + {
- + warning ("`%s' incompatible attribute ignored",
- + IDENTIFIER_POINTER (name));
- + *no_add_attrs = true;
- + }
- +
- + return NULL_TREE;
- +}
- +
- +/*
- + Add __attribute__ ((pragma_reverse_bitfields)) when in the scope of a
- + #pragma reverse_bitfields, or __attribute__
- + ((pragma_no_reverse_bitfields)) when in the scope of a #pragma
- + no_reverse_bitfields. This gets called before
- + nios2_handle_struct_attribute above, so we can't just reuse the same
- + attributes.
- +*/
- +static void
- +nios2_insert_attributes (tree node, tree *attr_ptr)
- +{
- + tree type = NULL;
- + if (DECL_P (node))
- + {
- + if (TREE_CODE (node) == TYPE_DECL)
- + {
- + type = TREE_TYPE (node);
- + }
- + }
- + else
- + {
- + type = node;
- + }
- +
- + if (!type
- + || (TREE_CODE (type) != RECORD_TYPE
- + && TREE_CODE (type) != UNION_TYPE))
- + {
- + /* We can ignore things other than structs & unions */
- + return;
- + }
- +
- + if (lookup_attribute ("reverse_bitfields", TYPE_ATTRIBUTES (type))
- + || lookup_attribute ("no_reverse_bitfields", TYPE_ATTRIBUTES (type)))
- + {
- + /* If an attribute is already set, it silently overrides the
- + current #pragma, if any */
- + return;
- + }
- +
- + if (nios2_pragma_reverse_bitfields_flag)
- + {
- + const char *id = (nios2_pragma_reverse_bitfields_flag == 1 ?
- + "pragma_reverse_bitfields" :
- + "pragma_no_reverse_bitfields");
- + /* No attribute set, and we are in the scope of a #pragma */
- + *attr_ptr = tree_cons (get_identifier (id), NULL, *attr_ptr);
- + }
- +}
- +
- +
- +/*
- + * The attributes take precedence over the pragmas, which in turn take
- + * precedence over the compile-time switches.
- + */
- +static bool
- +nios2_reverse_bitfield_layout_p (tree record_type)
- +{
- + return ((TARGET_REVERSE_BITFIELDS
- + && !lookup_attribute ("pragma_no_reverse_bitfields",
- + TYPE_ATTRIBUTES (record_type))
- + && !lookup_attribute ("no_reverse_bitfields",
- + TYPE_ATTRIBUTES (record_type)))
- + || (lookup_attribute ("pragma_reverse_bitfields",
- + TYPE_ATTRIBUTES (record_type))
- + && !lookup_attribute ("no_reverse_bitfields",
- + TYPE_ATTRIBUTES (record_type)))
- + || lookup_attribute ("reverse_bitfields",
- + TYPE_ATTRIBUTES (record_type)));
- +}
- +
- +
- +/*****************************************
- + * Defining the Output Assembler Language
- + *****************************************/
- +
- +/* -------------- *
- + * Output of Data
- + * -------------- */
- +
- +
- +/* -------------------------------- *
- + * Output of Assembler Instructions
- + * -------------------------------- */
- +
- +
- +/* print the operand OP to file stream
- + FILE modified by LETTER. LETTER
- + can be one of:
- + i: print "i" if OP is an immediate, except 0
- + o: print "io" if OP is volatile
- +
- + z: for const0_rtx print $0 instead of 0
- + H: for %hiadj
- + L: for %lo
- + U: for upper half of 32 bit value
- + D: for the upper 32-bits of a 64-bit double value
- + */
- +
- +void
- +nios2_print_operand (FILE *file, rtx op, int letter)
- +{
- +
- + switch (letter)
- + {
- + case 'i':
- + if (CONSTANT_P (op) && (op != const0_rtx))
- + fprintf (file, "i");
- + return;
- +
- + case 'o':
- + if (GET_CODE (op) == MEM
- + && ((MEM_VOLATILE_P (op) && !TARGET_CACHE_VOLATILE)
- + || TARGET_BYPASS_CACHE))
- + fprintf (file, "io");
- + return;
- +
- + default:
- + break;
- + }
- +
- + if (comparison_operator (op, VOIDmode))
- + {
- + if (letter == 0)
- + {
- + fprintf (file, "%s", GET_RTX_NAME (GET_CODE (op)));
- + return;
- + }
- + }
- +
- +
- + switch (GET_CODE (op))
- + {
- + case REG:
- + if (letter == 0 || letter == 'z')
- + {
- + fprintf (file, "%s", reg_names[REGNO (op)]);
- + return;
- + }
- + else if (letter == 'D')
- + {
- + fprintf (file, "%s", reg_names[REGNO (op)+1]);
- + return;
- + }
- + break;
- +
- + case CONST_INT:
- + if (INTVAL (op) == 0 && letter == 'z')
- + {
- + fprintf (file, "zero");
- + return;
- + }
- + else if (letter == 'U')
- + {
- + HOST_WIDE_INT val = INTVAL (op);
- + rtx new_op;
- + val = (val / 65536) & 0xFFFF;
- + new_op = GEN_INT (val);
- + output_addr_const (file, new_op);
- + return;
- + }
- +
- + /* else, fall through */
- + case CONST:
- + case LABEL_REF:
- + case SYMBOL_REF:
- + case CONST_DOUBLE:
- + if (letter == 0 || letter == 'z')
- + {
- + output_addr_const (file, op);
- + return;
- + }
- + else if (letter == 'H')
- + {
- + fprintf (file, "%%hiadj(");
- + output_addr_const (file, op);
- + fprintf (file, ")");
- + return;
- + }
- + else if (letter == 'L')
- + {
- + fprintf (file, "%%lo(");
- + output_addr_const (file, op);
- + fprintf (file, ")");
- + return;
- + }
- + break;
- +
- +
- + case SUBREG:
- + case MEM:
- + if (letter == 0)
- + {
- + output_address (op);
- + return;
- + }
- + break;
- +
- + case CODE_LABEL:
- + if (letter == 0)
- + {
- + output_addr_const (file, op);
- + return;
- + }
- + break;
- +
- + default:
- + break;
- + }
- +
- + fprintf (stderr, "Missing way to print (%c) ", letter);
- + debug_rtx (op);
- + abort ();
- +}
- +
- +static int gprel_constant (rtx);
- +
- +static int
- +gprel_constant (rtx op)
- +{
- + if (GET_CODE (op) == SYMBOL_REF
- + && SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (op))
- + {
- + return 1;
- + }
- + else if (GET_CODE (op) == CONST
- + && GET_CODE (XEXP (op, 0)) == PLUS)
- + {
- + return gprel_constant (XEXP (XEXP (op, 0), 0));
- + }
- + else
- + {
- + return 0;
- + }
- +}
- +
- +void
- +nios2_print_operand_address (FILE *file, rtx op)
- +{
- + switch (GET_CODE (op))
- + {
- + case CONST:
- + case CONST_INT:
- + case LABEL_REF:
- + case CONST_DOUBLE:
- + case SYMBOL_REF:
- + if (gprel_constant (op))
- + {
- + fprintf (file, "%%gprel(");
- + output_addr_const (file, op);
- + fprintf (file, ")(%s)", reg_names[GP_REGNO]);
- + return;
- + }
- +
- + break;
- +
- + case PLUS:
- + {
- + rtx op0 = XEXP (op, 0);
- + rtx op1 = XEXP (op, 1);
- +
- + if (REG_P (op0) && CONSTANT_P (op1))
- + {
- + output_addr_const (file, op1);
- + fprintf (file, "(%s)", reg_names[REGNO (op0)]);
- + return;
- + }
- + else if (REG_P (op1) && CONSTANT_P (op0))
- + {
- + output_addr_const (file, op0);
- + fprintf (file, "(%s)", reg_names[REGNO (op1)]);
- + return;
- + }
- + }
- + break;
- +
- + case REG:
- + fprintf (file, "0(%s)", reg_names[REGNO (op)]);
- + return;
- +
- + case MEM:
- + {
- + rtx base = XEXP (op, 0);
- + PRINT_OPERAND_ADDRESS (file, base);
- + return;
- + }
- + default:
- + break;
- + }
- +
- + fprintf (stderr, "Missing way to print address\n");
- + debug_rtx (op);
- + abort ();
- +}
- +
- +
- +
- +
- +
- +/****************************
- + * Predicates
- + ****************************/
- +
- +int
- +arith_operand (rtx op, enum machine_mode mode)
- +{
- + if (GET_CODE (op) == CONST_INT && SMALL_INT (INTVAL (op)))
- + return 1;
- +
- + return register_operand (op, mode);
- +}
- +
- +int
- +uns_arith_operand (rtx op, enum machine_mode mode)
- +{
- + if (GET_CODE (op) == CONST_INT && SMALL_INT_UNSIGNED (INTVAL (op)))
- + return 1;
- +
- + return register_operand (op, mode);
- +}
- +
- +int
- +logical_operand (rtx op, enum machine_mode mode)
- +{
- + if (GET_CODE (op) == CONST_INT
- + && (SMALL_INT_UNSIGNED (INTVAL (op)) || UPPER16_INT (INTVAL (op))))
- + return 1;
- +
- + return register_operand (op, mode);
- +}
- +
- +int
- +shift_operand (rtx op, enum machine_mode mode)
- +{
- + if (GET_CODE (op) == CONST_INT && SHIFT_INT (INTVAL (op)))
- + return 1;
- +
- + return register_operand (op, mode);
- +}
- +
- +int
- +rdwrctl_operand (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
- +{
- + return GET_CODE (op) == CONST_INT && RDWRCTL_INT (INTVAL (op));
- +}
- +
- +/* Return truth value of whether OP is a register or the constant 0. */
- +
- +int
- +reg_or_0_operand (rtx op, enum machine_mode mode)
- +{
- + switch (GET_CODE (op))
- + {
- + case CONST_INT:
- + return INTVAL (op) == 0;
- +
- + case CONST_DOUBLE:
- + return op == CONST0_RTX (mode);
- +
- + default:
- + break;
- + }
- +
- + return register_operand (op, mode);
- +}
- +
- +
- +int
- +equality_op (rtx op, enum machine_mode mode)
- +{
- + if (mode != GET_MODE (op))
- + return 0;
- +
- + return GET_CODE (op) == EQ || GET_CODE (op) == NE;
- +}
- +
- +int
- +custom_insn_opcode (rtx op, enum machine_mode mode ATTRIBUTE_UNUSED)
- +{
- + return GET_CODE (op) == CONST_INT && CUSTOM_INSN_OPCODE (INTVAL (op));
- +}
- +
- +
- +
- +
- +/*****************************************************************************
- +**
- +** custom fpu instruction output
- +**
- +*****************************************************************************/
- +
- +static const char *nios2_custom_fpu_insn_zdz (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_zsz (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_szz (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_sss (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_ssz (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_iss (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_ddd (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_ddz (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_idd (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_siz (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_suz (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_diz (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_duz (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_isz (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_usz (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_idz (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_udz (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_dsz (rtx, int, const char *);
- +static const char *nios2_custom_fpu_insn_sdz (rtx, int, const char *);
- +
- +static const char *
- +nios2_custom_fpu_insn_zdz (rtx insn, int N, const char *opt)
- +{
- + static char buf[1024];
- +
- + if (N < 0)
- + {
- + fatal_insn ("attempt to use disabled fpu instruction", insn);
- + }
- + if (snprintf (buf, sizeof (buf),
- + "custom\t%d, zero, %%0, %%D0 # %s %%0",
- + N, opt) >= (int)sizeof (buf))
- + {
- + fatal_insn ("buffer overflow", insn);
- + }
- + return buf;
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_zsz (rtx insn, int N, const char *opt)
- +{
- + static char buf[1024];
- +
- + if (N < 0)
- + {
- + fatal_insn ("attempt to use disabled fpu instruction", insn);
- + }
- + if (snprintf (buf, sizeof (buf),
- + "custom\t%d, zero, %%0, zero # %s %%0",
- + N, opt) >= (int)sizeof (buf))
- + {
- + fatal_insn ("buffer overflow", insn);
- + }
- + return buf;
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_szz (rtx insn, int N, const char *opt)
- +{
- + static char buf[1024];
- +
- + if (N < 0)
- + {
- + fatal_insn ("attempt to use disabled fpu instruction", insn);
- + }
- + if (snprintf (buf, sizeof (buf),
- + "custom\t%d, %%0, zero, zero # %s %%0",
- + N, opt) >= (int)sizeof (buf))
- + {
- + fatal_insn ("buffer overflow", insn);
- + }
- + return buf;
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_sss (rtx insn, int N, const char *opt)
- +{
- + static char buf[1024];
- +
- + if (N < 0)
- + {
- + fatal_insn ("attempt to use disabled fpu instruction", insn);
- + }
- + if (snprintf (buf, sizeof (buf),
- + "custom\t%d, %%0, %%1, %%2 # %s %%0, %%1, %%2",
- + N, opt) >= (int)sizeof (buf))
- + {
- + fatal_insn ("buffer overflow", insn);
- + }
- + return buf;
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_ssz (rtx insn, int N, const char *opt)
- +{
- + static char buf[1024];
- +
- + if (N < 0)
- + {
- + fatal_insn ("attempt to use disabled fpu instruction", insn);
- + }
- + if (snprintf (buf, sizeof (buf),
- + "custom\t%d, %%0, %%1, zero # %s %%0, %%1",
- + N, opt) >= (int)sizeof (buf))
- + {
- + fatal_insn ("buffer overflow", insn);
- + }
- + return buf;
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_iss (rtx insn, int N, const char *opt)
- +{
- + return nios2_custom_fpu_insn_sss (insn, N, opt);
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_ddd (rtx insn, int N, const char *opt)
- +{
- + static char buf[1024];
- +
- + if (N < 0
- + || nios2_fpu_insns[nios2_fpu_nios2_frdy].N < 0
- + || nios2_fpu_insns[nios2_fpu_nios2_fwrx].N < 0)
- + {
- + fatal_insn ("attempt to use disabled fpu instruction", insn);
- + }
- + if (snprintf (buf, sizeof (buf),
- + "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t"
- + "custom\t%d, %%D0, %%2, %%D2 # %s %%0, %%1, %%2\n\t"
- + "custom\t%d, %%0, zero, zero # frdy %%0",
- + nios2_fpu_insns[nios2_fpu_nios2_fwrx].N,
- + N, opt,
- + nios2_fpu_insns[nios2_fpu_nios2_frdy].N) >= (int)sizeof (buf))
- + {
- + fatal_insn ("buffer overflow", insn);
- + }
- + return buf;
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_ddz (rtx insn, int N, const char *opt)
- +{
- + static char buf[1024];
- +
- + if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_frdy].N < 0)
- + {
- + fatal_insn ("attempt to use disabled fpu instruction", insn);
- + }
- + if (snprintf (buf, sizeof (buf),
- + "custom\t%d, %%D0, %%1, %%D1 # %s %%0, %%1\n\t"
- + "custom\t%d, %%0, zero, zero # frdy %%0",
- + N, opt,
- + nios2_fpu_insns[nios2_fpu_nios2_frdy].N) >= (int)sizeof (buf))
- + {
- + fatal_insn ("buffer overflow", insn);
- + }
- + return buf;
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_idd (rtx insn, int N, const char *opt)
- +{
- + static char buf[1024];
- +
- + if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_fwrx].N < 0)
- + {
- + fatal_insn ("attempt to use disabled fpu instruction", insn);
- + }
- + if (snprintf (buf, sizeof (buf),
- + "custom\t%d, zero, %%1, %%D1 # fwrx %%1\n\t"
- + "custom\t%d, %%0, %%2, %%D2 # %s %%0, %%1, %%2",
- + nios2_fpu_insns[nios2_fpu_nios2_fwrx].N,
- + N, opt) >= (int)sizeof (buf))
- + {
- + fatal_insn ("buffer overflow", insn);
- + }
- + return buf;
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_siz (rtx insn, int N, const char *opt)
- +{
- + return nios2_custom_fpu_insn_ssz (insn, N, opt);
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_suz (rtx insn, int N, const char *opt)
- +{
- + return nios2_custom_fpu_insn_ssz (insn, N, opt);
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_diz (rtx insn, int N, const char *opt)
- +{
- + return nios2_custom_fpu_insn_dsz (insn, N, opt);
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_duz (rtx insn, int N, const char *opt)
- +{
- + return nios2_custom_fpu_insn_dsz (insn, N, opt);
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_isz (rtx insn, int N, const char *opt)
- +{
- + return nios2_custom_fpu_insn_ssz (insn, N, opt);
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_usz (rtx insn, int N, const char *opt)
- +{
- + return nios2_custom_fpu_insn_ssz (insn, N, opt);
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_idz (rtx insn, int N, const char *opt)
- +{
- + return nios2_custom_fpu_insn_sdz (insn, N, opt);
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_udz (rtx insn, int N, const char *opt)
- +{
- + return nios2_custom_fpu_insn_sdz (insn, N, opt);
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_dsz (rtx insn, int N, const char *opt)
- +{
- + static char buf[1024];
- +
- + if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_frdy].N < 0)
- + {
- + fatal_insn ("attempt to use disabled fpu instruction", insn);
- + }
- + if (snprintf (buf, sizeof (buf),
- + "custom\t%d, %%D0, %%1, zero # %s %%0, %%1\n\t"
- + "custom\t%d, %%0, zero, zero # frdy %%0",
- + N, opt,
- + nios2_fpu_insns[nios2_fpu_nios2_frdy].N) >= (int)sizeof (buf))
- + {
- + fatal_insn ("buffer overflow", insn);
- + }
- + return buf;
- +}
- +
- +static const char *
- +nios2_custom_fpu_insn_sdz (rtx insn, int N, const char *opt)
- +{
- + static char buf[1024];
- +
- + if (N < 0)
- + {
- + fatal_insn ("attempt to use disabled fpu instruction", insn);
- + }
- + if (snprintf (buf, sizeof (buf),
- + "custom\t%d, %%0, %%1, %%D1 # %s %%0, %%1",
- + N, opt) >= (int)sizeof (buf))
- + {
- + fatal_insn ("buffer overflow", insn);
- + }
- + return buf;
- +}
- +
- +#undef NIOS2_FPU_INSN
- +#define NIOS2_FPU_INSN(opt, insn, args) \
- +static const char * \
- +NIOS2_CONCAT (nios2_output_fpu_insn_, insn) (rtx i) \
- +{ \
- + return NIOS2_CONCAT (nios2_custom_fpu_insn_, args) \
- + (i, \
- + nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].N, \
- + nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].option); \
- +}
- +NIOS2_FOR_ALL_FPU_INSNS
- +
- +
- +
- +const char *
- +nios2_output_fpu_insn_cmps (rtx insn, enum rtx_code cond)
- +{
- + static char buf[1024];
- + int N;
- + const char *opt;
- +
- + int operandL = 2;
- + int operandR = 3;
- +
- + if ( !have_nios2_fpu_cmp_insn(cond, CMP_SF) &&
- + have_nios2_fpu_cmp_insn(get_reverse_cond(cond), CMP_SF) ) {
- +
- + int temp = operandL;
- + operandL = operandR;
- + operandR = temp;
- +
- + cond = get_reverse_cond(cond);
- + }
- +
- + switch (cond)
- + {
- + case EQ:
- + N = nios2_fpu_insns[nios2_fpu_nios2_seqsf].N;
- + opt = "fcmpeqs";
- + break;
- + case NE:
- + N = nios2_fpu_insns[nios2_fpu_nios2_snesf].N;
- + opt = "fcmpnes";
- + break;
- + case GT:
- + N = nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N;
- + opt = "fcmpgts";
- + break;
- + case GE:
- + N = nios2_fpu_insns[nios2_fpu_nios2_sgesf].N;
- + opt = "fcmpges";
- + break;
- + case LT:
- + N = nios2_fpu_insns[nios2_fpu_nios2_sltsf].N;
- + opt = "fcmplts";
- + break;
- + case LE:
- + N = nios2_fpu_insns[nios2_fpu_nios2_slesf].N;
- + opt = "fcmples"; break;
- + default:
- + fatal_insn ("bad single compare", insn);
- + }
- +
- + if (N < 0)
- + {
- + fatal_insn ("attempt to use disabled fpu instruction", insn);
- + }
- +
- + /*
- + * ??? This raises the whole vexing issue of how to handle
- + * out-of-range branches. Punt for now, seeing as how nios2-elf-as
- + * doesn't even _try_ to handle out-of-range branches yet!
- + */
- + if (snprintf (buf, sizeof (buf),
- + ".set\tnoat\n\t"
- + "custom\t%d, at, %%%d, %%%d # %s at, %%%d, %%%d\n\t"
- + "bne\tat, zero, %%l1\n\t"
- + ".set\tat",
- + N, operandL, operandR, opt, operandL, operandR) >= (int)sizeof (buf))
- + {
- + fatal_insn ("buffer overflow", insn);
- + }
- + return buf;
- +}
- +
- +const char *
- +nios2_output_fpu_insn_cmpd (rtx insn, enum rtx_code cond)
- +{
- + static char buf[1024];
- + int N;
- + const char *opt;
- +
- + int operandL = 2;
- + int operandR = 3;
- +
- + if ( !have_nios2_fpu_cmp_insn(cond, CMP_DF) &&
- + have_nios2_fpu_cmp_insn(get_reverse_cond(cond), CMP_DF) ) {
- +
- + int temp = operandL;
- + operandL = operandR;
- + operandR = temp;
- +
- + cond = get_reverse_cond(cond);
- + }
- +
- + switch (cond)
- + {
- + case EQ:
- + N = nios2_fpu_insns[nios2_fpu_nios2_seqdf].N;
- + opt = "fcmpeqd";
- + break;
- + case NE:
- + N = nios2_fpu_insns[nios2_fpu_nios2_snedf].N;
- + opt = "fcmpned";
- + break;
- + case GT:
- + N = nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N;
- + opt = "fcmpgtd";
- + break;
- + case GE:
- + N = nios2_fpu_insns[nios2_fpu_nios2_sgedf].N;
- + opt = "fcmpged";
- + break;
- + case LT:
- + N = nios2_fpu_insns[nios2_fpu_nios2_sltdf].N;
- + opt = "fcmpltd";
- + break;
- + case LE:
- + N = nios2_fpu_insns[nios2_fpu_nios2_sledf].N;
- + opt = "fcmpled";
- + break;
- + default:
- + fatal_insn ("bad double compare", insn);
- + }
- +
- + if (N < 0 || nios2_fpu_insns[nios2_fpu_nios2_fwrx].N < 0)
- + {
- + fatal_insn ("attempt to use disabled fpu instruction", insn);
- + }
- + if (snprintf (buf, sizeof (buf),
- + ".set\tnoat\n\t"
- + "custom\t%d, zero, %%%d, %%D%d # fwrx %%%d\n\t"
- + "custom\t%d, at, %%%d, %%D%d # %s at, %%%d, %%%d\n\t"
- + "bne\tat, zero, %%l1\n\t"
- + ".set\tat",
- + nios2_fpu_insns[nios2_fpu_nios2_fwrx].N, operandL, operandL, operandL,
- + N, operandR, operandR, operandL, operandR, opt) >= (int)sizeof (buf))
- + {
- + fatal_insn ("buffer overflow", insn);
- + }
- + return buf;
- +}
- +
- +
- +
- +
- +/*****************************************************************************
- +**
- +** instruction scheduler
- +**
- +*****************************************************************************/
- +static int
- +nios2_use_dfa_pipeline_interface ()
- +{
- + return 1;
- +}
- +
- +
- +static int
- +nios2_issue_rate ()
- +{
- +#ifdef MAX_DFA_ISSUE_RATE
- + return MAX_DFA_ISSUE_RATE;
- +#else
- + return 1;
- +#endif
- +}
- +
- +
- +const char *
- +asm_output_opcode (FILE *file ATTRIBUTE_UNUSED,
- + const char *ptr ATTRIBUTE_UNUSED)
- +{
- + const char *p;
- +
- + p = ptr;
- + return ptr;
- +}
- +
- +
- +
- +/*****************************************************************************
- +**
- +** function arguments
- +**
- +*****************************************************************************/
- +
- +void
- +init_cumulative_args (CUMULATIVE_ARGS *cum,
- + tree fntype ATTRIBUTE_UNUSED,
- + rtx libname ATTRIBUTE_UNUSED,
- + tree fndecl ATTRIBUTE_UNUSED,
- + int n_named_args ATTRIBUTE_UNUSED)
- +{
- + cum->regs_used = 0;
- +}
- +
- +
- +/* Define where to put the arguments to a function. Value is zero to
- + push the argument on the stack, or a hard register in which to
- + store the argument.
- +
- + MODE is the argument's machine mode.
- + TYPE is the data type of the argument (as a tree).
- + This is null for libcalls where that information may
- + not be available.
- + CUM is a variable of type CUMULATIVE_ARGS which gives info about
- + the preceding args and about the function being called.
- + NAMED is nonzero if this argument is a named parameter
- + (otherwise it is an extra parameter matching an ellipsis). */
- +rtx
- +function_arg (const CUMULATIVE_ARGS *cum, enum machine_mode mode,
- + tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
- +{
- + rtx return_rtx = NULL_RTX;
- +
- + if (cum->regs_used < NUM_ARG_REGS)
- + {
- + return_rtx = gen_rtx_REG (mode, FIRST_ARG_REGNO + cum->regs_used);
- + }
- +
- + return return_rtx;
- +}
- +
- +/*
- + * This is just default_must_pass_in_stack from calls.c sans the final
- + * test for padding which isn't needed: we define BLOCK_REG_PADDING
- + * instead.
- + */
- +int
- +nios2_must_pass_in_stack (enum machine_mode mode, tree type)
- +{
- + if (!type)
- + return false;
- +
- + /* If the type has variable size... */
- + if (TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST)
- + return true;
- +
- + /* If the type is marked as addressable (it is required
- + to be constructed into the stack)... */
- + if (TREE_ADDRESSABLE (type))
- + return true;
- +
- + return false;
- +}
- +
- +int
- +function_arg_partial_nregs (const CUMULATIVE_ARGS *cum,
- + enum machine_mode mode, tree type,
- + int named ATTRIBUTE_UNUSED)
- +{
- + HOST_WIDE_INT param_size;
- +
- + if (mode == BLKmode)
- + {
- + param_size = int_size_in_bytes (type);
- + if (param_size < 0)
- + internal_error
- + ("Do not know how to handle large structs or variable length types");
- + }
- + else
- + {
- + param_size = GET_MODE_SIZE (mode);
- + }
- +
- + /* convert to words (round up) */
- + param_size = (3 + param_size) / 4;
- +
- + if (cum->regs_used < NUM_ARG_REGS
- + && cum->regs_used + param_size > NUM_ARG_REGS)
- + {
- + return NUM_ARG_REGS - cum->regs_used;
- + }
- + else
- + {
- + return 0;
- + }
- +}
- +
- +
- +/* Update the data in CUM to advance over an argument
- + of mode MODE and data type TYPE.
- + (TYPE is null for libcalls where that information may not be available.) */
- +
- +void
- +function_arg_advance (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- + tree type ATTRIBUTE_UNUSED, int named ATTRIBUTE_UNUSED)
- +{
- + HOST_WIDE_INT param_size;
- +
- + if (mode == BLKmode)
- + {
- + param_size = int_size_in_bytes (type);
- + if (param_size < 0)
- + internal_error
- + ("Do not know how to handle large structs or variable length types");
- + }
- + else
- + {
- + param_size = GET_MODE_SIZE (mode);
- + }
- +
- + /* convert to words (round up) */
- + param_size = (3 + param_size) / 4;
- +
- + if (cum->regs_used + param_size > NUM_ARG_REGS)
- + {
- + cum->regs_used = NUM_ARG_REGS;
- + }
- + else
- + {
- + cum->regs_used += param_size;
- + }
- +
- + return;
- +}
- +
- +int
- +nios2_function_arg_padding_upward (enum machine_mode mode, tree type)
- +{
- + /* On little-endian targets, the first byte of every stack argument
- + is passed in the first byte of the stack slot. */
- + if (!BYTES_BIG_ENDIAN)
- + return 1;
- +
- + /* Otherwise, integral types are padded downward: the last byte of a
- + stack argument is passed in the last byte of the stack slot. */
- + if (type != 0
- + ? INTEGRAL_TYPE_P (type) || POINTER_TYPE_P (type)
- + : GET_MODE_CLASS (mode) == MODE_INT)
- + return 0;
- +
- + /* Arguments smaller than a stack slot are padded downward. */
- + if (mode != BLKmode)
- + return (GET_MODE_BITSIZE (mode) >= PARM_BOUNDARY) ? 1 : 0;
- + else
- + return ((int_size_in_bytes (type) >= (PARM_BOUNDARY / BITS_PER_UNIT))
- + ? 1 : 0);
- +}
- +
- +int
- +nios2_block_reg_padding_upward (enum machine_mode mode, tree type,
- + int first ATTRIBUTE_UNUSED)
- +{
- + /* ??? Do we need to treat floating point specially, ala MIPS? */
- + return nios2_function_arg_padding_upward (mode, type);
- +}
- +
- +int
- +nios2_return_in_memory (tree type)
- +{
- + int res = ((int_size_in_bytes (type) > (2 * UNITS_PER_WORD))
- + || (int_size_in_bytes (type) == -1));
- +
- + return res;
- +}
- +
- +/* ??? It may be possible to eliminate the copyback and implement
- + my own va_arg type, but that is more work for now. */
- +int
- +nios2_setup_incoming_varargs (const CUMULATIVE_ARGS *cum,
- + enum machine_mode mode, tree type,
- + int no_rtl)
- +{
- + CUMULATIVE_ARGS local_cum;
- + int regs_to_push;
- +
- + local_cum = *cum;
- + FUNCTION_ARG_ADVANCE (local_cum, mode, type, 1);
- +
- + regs_to_push = NUM_ARG_REGS - local_cum.regs_used;
- +
- + if (!no_rtl)
- + {
- + if (regs_to_push > 0)
- + {
- + rtx ptr, mem;
- +
- + ptr = virtual_incoming_args_rtx;
- + mem = gen_rtx_MEM (BLKmode, ptr);
- +
- + /* va_arg is an array access in this case, which causes
- + it to get MEM_IN_STRUCT_P set. We must set it here
- + so that the insn scheduler won't assume that these
- + stores can't possibly overlap with the va_arg loads. */
- + MEM_SET_IN_STRUCT_P (mem, 1);
- +
- + emit_insn (gen_blockage ());
- + move_block_from_reg (local_cum.regs_used + FIRST_ARG_REGNO, mem,
- + regs_to_push);
- + emit_insn (gen_blockage ());
- + }
- + }
- +
- + return regs_to_push * UNITS_PER_WORD;
- +
- +}
- +
- +
- +
- +/*****************************************************************************
- +**
- +** builtins
- +**
- +** This method for handling builtins is from CSP where _many_ more types of
- +** expanders have already been written. Check there first before writing
- +** new ones.
- +**
- +*****************************************************************************/
- +
- +enum nios2_builtins
- +{
- + NIOS2_BUILTIN_LDBIO,
- + NIOS2_BUILTIN_LDBUIO,
- + NIOS2_BUILTIN_LDHIO,
- + NIOS2_BUILTIN_LDHUIO,
- + NIOS2_BUILTIN_LDWIO,
- + NIOS2_BUILTIN_STBIO,
- + NIOS2_BUILTIN_STHIO,
- + NIOS2_BUILTIN_STWIO,
- + NIOS2_BUILTIN_SYNC,
- + NIOS2_BUILTIN_RDCTL,
- + NIOS2_BUILTIN_WRCTL,
- +
- +#undef NIOS2_DO_BUILTIN
- +#define NIOS2_DO_BUILTIN(upper, lower, handler) \
- + NIOS2_CONCAT (NIOS2_BUILTIN_CUSTOM_, upper),
- +NIOS2_FOR_ALL_CUSTOM_BUILTINS
- +
- + NIOS2_FIRST_FPU_INSN,
- +
- +#undef NIOS2_FPU_INSN
- +#define NIOS2_FPU_INSN(opt, insn, args) \
- + NIOS2_CONCAT (NIOS2_BUILTIN_FPU_, opt),
- +NIOS2_FOR_ALL_FPU_INSNS
- +
- + NIOS2_LAST_FPU_INSN,
- +
- + LIM_NIOS2_BUILTINS
- +};
- +
- +struct builtin_description
- +{
- + const enum insn_code icode;
- + const char *const name;
- + const enum nios2_builtins code;
- + const tree *type;
- + rtx (* expander) (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +};
- +
- +static rtx nios2_expand_STXIO (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_LDXIO (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_sync (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_rdctl (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_wrctl (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +
- +static rtx nios2_expand_custom_n (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_Xn (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_nX (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_XnX (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_nXX (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_XnXX (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +
- +static rtx nios2_expand_custom_zdz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_zsz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_szz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_sss (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_ssz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_iss (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_ddd (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_ddz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_idd (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_siz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_suz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_diz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_duz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_isz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_usz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_idz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_udz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_dsz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +static rtx nios2_expand_custom_sdz (const struct builtin_description *,
- + tree, rtx, rtx, enum machine_mode, int);
- +
- +static tree endlink;
- +
- +/* int fn (volatile const void *)
- + */
- +static tree int_ftype_volatile_const_void_p;
- +
- +/* int fn (int)
- + */
- +static tree int_ftype_int;
- +
- +/* void fn (int, int)
- + */
- +static tree void_ftype_int_int;
- +
- +/* void fn (volatile void *, int)
- + */
- +static tree void_ftype_volatile_void_p_int;
- +
- +/* void fn (void)
- + */
- +static tree void_ftype_void;
- +
- +#undef NIOS2_DO_BUILTIN
- +#define NIOS2_DO_BUILTIN(upper, lower, handler) \
- + static tree NIOS2_CONCAT (custom_, lower);
- +NIOS2_FOR_ALL_CUSTOM_BUILTINS
- +
- +static tree custom_zdz;
- +static tree custom_zsz;
- +static tree custom_szz;
- +static tree custom_sss;
- +static tree custom_ssz;
- +static tree custom_iss;
- +static tree custom_ddd;
- +static tree custom_ddz;
- +static tree custom_idd;
- +static tree custom_siz;
- +static tree custom_suz;
- +static tree custom_diz;
- +static tree custom_duz;
- +static tree custom_isz;
- +static tree custom_usz;
- +static tree custom_idz;
- +static tree custom_udz;
- +static tree custom_dsz;
- +static tree custom_sdz;
- +
- +static const struct builtin_description bdesc[] = {
- + {CODE_FOR_ldbio, "__builtin_ldbio", NIOS2_BUILTIN_LDBIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
- + {CODE_FOR_ldbuio, "__builtin_ldbuio", NIOS2_BUILTIN_LDBUIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
- + {CODE_FOR_ldhio, "__builtin_ldhio", NIOS2_BUILTIN_LDHIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
- + {CODE_FOR_ldhuio, "__builtin_ldhuio", NIOS2_BUILTIN_LDHUIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
- + {CODE_FOR_ldwio, "__builtin_ldwio", NIOS2_BUILTIN_LDWIO, &int_ftype_volatile_const_void_p, nios2_expand_LDXIO},
- +
- + {CODE_FOR_stbio, "__builtin_stbio", NIOS2_BUILTIN_STBIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
- + {CODE_FOR_sthio, "__builtin_sthio", NIOS2_BUILTIN_STHIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
- + {CODE_FOR_stwio, "__builtin_stwio", NIOS2_BUILTIN_STWIO, &void_ftype_volatile_void_p_int, nios2_expand_STXIO},
- +
- + {CODE_FOR_sync, "__builtin_sync", NIOS2_BUILTIN_SYNC, &void_ftype_void, nios2_expand_sync},
- + {CODE_FOR_rdctl, "__builtin_rdctl", NIOS2_BUILTIN_RDCTL, &int_ftype_int, nios2_expand_rdctl},
- + {CODE_FOR_wrctl, "__builtin_wrctl", NIOS2_BUILTIN_WRCTL, &void_ftype_int_int, nios2_expand_wrctl},
- +
- +#undef NIOS2_DO_BUILTIN
- +#define NIOS2_DO_BUILTIN(upper, lower, handler) \
- + {NIOS2_CONCAT (CODE_FOR_custom_, lower), \
- + "__builtin_custom_" NIOS2_STRINGIFY (lower), \
- + NIOS2_CONCAT (NIOS2_BUILTIN_CUSTOM_, upper), \
- + &NIOS2_CONCAT (custom_, lower), \
- + NIOS2_CONCAT (nios2_expand_custom_, handler)},
- +NIOS2_FOR_ALL_CUSTOM_BUILTINS
- +
- +#undef NIOS2_FPU_INSN
- +#define NIOS2_FPU_INSN(opt, insn, args) \
- + {NIOS2_CONCAT (CODE_FOR_, insn), \
- + "__builtin_custom_" NIOS2_STRINGIFY (opt), \
- + NIOS2_CONCAT (NIOS2_BUILTIN_FPU_, opt), \
- + &NIOS2_CONCAT (custom_, args), \
- + NIOS2_CONCAT (nios2_expand_custom_, args)},
- +NIOS2_FOR_ALL_FPU_INSNS
- +
- + {0, 0, 0, 0, 0},
- +};
- +
- +/* This does not have a closing bracket on purpose (see use) */
- +#define def_param(TYPE) \
- + tree_cons (NULL_TREE, TYPE,
- +
- +static void
- +nios2_init_builtins ()
- +{
- + const struct builtin_description *d;
- +
- +
- + endlink = void_list_node;
- +
- + /* Special indenting here because one of the brackets is in def_param */
- + /* *INDENT-OFF* */
- +
- + /* int fn (volatile const void *)
- + */
- + int_ftype_volatile_const_void_p
- + = build_function_type (integer_type_node,
- + def_param (build_qualified_type (ptr_type_node,
- + TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE))
- + endlink));
- +
- +
- + /* void fn (volatile void *, int)
- + */
- + void_ftype_volatile_void_p_int
- + = build_function_type (void_type_node,
- + def_param (build_qualified_type (ptr_type_node,
- + TYPE_QUAL_VOLATILE))
- + def_param (integer_type_node)
- + endlink)));
- +
- + /* void fn (void)
- + */
- + void_ftype_void
- + = build_function_type (void_type_node,
- + endlink);
- +
- + /* int fn (int)
- + */
- + int_ftype_int
- + = build_function_type (integer_type_node,
- + def_param (integer_type_node)
- + endlink));
- +
- + /* void fn (int, int)
- + */
- + void_ftype_int_int
- + = build_function_type (void_type_node,
- + def_param (integer_type_node)
- + def_param (integer_type_node)
- + endlink)));
- +
- +
- +#define CUSTOM_NUM def_param (integer_type_node)
- +
- + custom_n
- + = build_function_type (void_type_node,
- + CUSTOM_NUM
- + endlink));
- + custom_ni
- + = build_function_type (void_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + endlink)));
- + custom_nf
- + = build_function_type (void_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + endlink)));
- + custom_np
- + = build_function_type (void_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + endlink)));
- + custom_nii
- + = build_function_type (void_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + def_param (integer_type_node)
- + endlink))));
- + custom_nif
- + = build_function_type (void_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + def_param (float_type_node)
- + endlink))));
- + custom_nip
- + = build_function_type (void_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + def_param (ptr_type_node)
- + endlink))));
- + custom_nfi
- + = build_function_type (void_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + def_param (integer_type_node)
- + endlink))));
- + custom_nff
- + = build_function_type (void_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + def_param (float_type_node)
- + endlink))));
- + custom_nfp
- + = build_function_type (void_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + def_param (ptr_type_node)
- + endlink))));
- + custom_npi
- + = build_function_type (void_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + def_param (integer_type_node)
- + endlink))));
- + custom_npf
- + = build_function_type (void_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + def_param (float_type_node)
- + endlink))));
- + custom_npp
- + = build_function_type (void_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + def_param (ptr_type_node)
- + endlink))));
- +
- + custom_in
- + = build_function_type (integer_type_node,
- + CUSTOM_NUM
- + endlink));
- + custom_ini
- + = build_function_type (integer_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + endlink)));
- + custom_inf
- + = build_function_type (integer_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + endlink)));
- + custom_inp
- + = build_function_type (integer_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + endlink)));
- + custom_inii
- + = build_function_type (integer_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + def_param (integer_type_node)
- + endlink))));
- + custom_inif
- + = build_function_type (integer_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + def_param (float_type_node)
- + endlink))));
- + custom_inip
- + = build_function_type (integer_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + def_param (ptr_type_node)
- + endlink))));
- + custom_infi
- + = build_function_type (integer_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + def_param (integer_type_node)
- + endlink))));
- + custom_inff
- + = build_function_type (integer_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + def_param (float_type_node)
- + endlink))));
- + custom_infp
- + = build_function_type (integer_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + def_param (ptr_type_node)
- + endlink))));
- + custom_inpi
- + = build_function_type (integer_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + def_param (integer_type_node)
- + endlink))));
- + custom_inpf
- + = build_function_type (integer_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + def_param (float_type_node)
- + endlink))));
- + custom_inpp
- + = build_function_type (integer_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + def_param (ptr_type_node)
- + endlink))));
- +
- + custom_fn
- + = build_function_type (float_type_node,
- + CUSTOM_NUM
- + endlink));
- + custom_fni
- + = build_function_type (float_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + endlink)));
- + custom_fnf
- + = build_function_type (float_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + endlink)));
- + custom_fnp
- + = build_function_type (float_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + endlink)));
- + custom_fnii
- + = build_function_type (float_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + def_param (integer_type_node)
- + endlink))));
- + custom_fnif
- + = build_function_type (float_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + def_param (float_type_node)
- + endlink))));
- + custom_fnip
- + = build_function_type (float_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + def_param (ptr_type_node)
- + endlink))));
- + custom_fnfi
- + = build_function_type (float_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + def_param (integer_type_node)
- + endlink))));
- + custom_fnff
- + = build_function_type (float_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + def_param (float_type_node)
- + endlink))));
- + custom_fnfp
- + = build_function_type (float_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + def_param (ptr_type_node)
- + endlink))));
- + custom_fnpi
- + = build_function_type (float_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + def_param (integer_type_node)
- + endlink))));
- + custom_fnpf
- + = build_function_type (float_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + def_param (float_type_node)
- + endlink))));
- + custom_fnpp
- + = build_function_type (float_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + def_param (ptr_type_node)
- + endlink))));
- +
- +
- + custom_pn
- + = build_function_type (ptr_type_node,
- + CUSTOM_NUM
- + endlink));
- + custom_pni
- + = build_function_type (ptr_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + endlink)));
- + custom_pnf
- + = build_function_type (ptr_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + endlink)));
- + custom_pnp
- + = build_function_type (ptr_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + endlink)));
- + custom_pnii
- + = build_function_type (ptr_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + def_param (integer_type_node)
- + endlink))));
- + custom_pnif
- + = build_function_type (ptr_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + def_param (float_type_node)
- + endlink))));
- + custom_pnip
- + = build_function_type (ptr_type_node,
- + CUSTOM_NUM
- + def_param (integer_type_node)
- + def_param (ptr_type_node)
- + endlink))));
- + custom_pnfi
- + = build_function_type (ptr_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + def_param (integer_type_node)
- + endlink))));
- + custom_pnff
- + = build_function_type (ptr_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + def_param (float_type_node)
- + endlink))));
- + custom_pnfp
- + = build_function_type (ptr_type_node,
- + CUSTOM_NUM
- + def_param (float_type_node)
- + def_param (ptr_type_node)
- + endlink))));
- + custom_pnpi
- + = build_function_type (ptr_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + def_param (integer_type_node)
- + endlink))));
- + custom_pnpf
- + = build_function_type (ptr_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + def_param (float_type_node)
- + endlink))));
- + custom_pnpp
- + = build_function_type (ptr_type_node,
- + CUSTOM_NUM
- + def_param (ptr_type_node)
- + def_param (ptr_type_node)
- + endlink))));
- +
- + custom_zdz
- + = build_function_type (void_type_node,
- + def_param (double_type_node)
- + endlink));
- +
- + custom_zsz
- + = build_function_type (void_type_node,
- + def_param (float_type_node)
- + endlink));
- +
- + custom_szz
- + = build_function_type (float_type_node,
- + def_param (void_type_node)
- + endlink));
- +
- + custom_sss
- + = build_function_type (float_type_node,
- + def_param (float_type_node)
- + def_param (float_type_node)
- + endlink)));
- +
- + custom_ssz
- + = build_function_type (float_type_node,
- + def_param (float_type_node)
- + endlink));
- +
- + custom_iss
- + = build_function_type (integer_type_node,
- + def_param (float_type_node)
- + def_param (float_type_node)
- + endlink)));
- +
- + custom_ddd
- + = build_function_type (double_type_node,
- + def_param (double_type_node)
- + def_param (double_type_node)
- + endlink)));
- +
- + custom_ddz
- + = build_function_type (double_type_node,
- + def_param (double_type_node)
- + endlink));
- +
- + custom_idd
- + = build_function_type (integer_type_node,
- + def_param (double_type_node)
- + def_param (double_type_node)
- + endlink)));
- +
- + custom_siz
- + = build_function_type (float_type_node,
- + def_param (integer_type_node)
- + endlink));
- +
- + custom_suz
- + = build_function_type (float_type_node,
- + def_param (unsigned_type_node)
- + endlink));
- +
- + custom_diz
- + = build_function_type (double_type_node,
- + def_param (integer_type_node)
- + endlink));
- +
- + custom_duz
- + = build_function_type (double_type_node,
- + def_param (unsigned_type_node)
- + endlink));
- +
- + custom_isz
- + = build_function_type (integer_type_node,
- + def_param (float_type_node)
- + endlink));
- +
- + custom_usz
- + = build_function_type (unsigned_type_node,
- + def_param (float_type_node)
- + endlink));
- +
- + custom_idz
- + = build_function_type (integer_type_node,
- + def_param (double_type_node)
- + endlink));
- +
- + custom_udz
- + = build_function_type (unsigned_type_node,
- + def_param (double_type_node)
- + endlink));
- +
- + custom_dsz
- + = build_function_type (double_type_node,
- + def_param (float_type_node)
- + endlink));
- +
- + custom_sdz
- + = build_function_type (float_type_node,
- + def_param (double_type_node)
- + endlink));
- +
- + /* *INDENT-ON* */
- +
- +
- + for (d = bdesc; d->name; d++)
- + {
- + builtin_function (d->name, *d->type, d->code,
- + BUILT_IN_MD, NULL, NULL);
- + }
- +}
- +
- +/* Expand an expression EXP that calls a built-in function,
- + with result going to TARGET if that's convenient
- + (and in mode MODE if that's convenient).
- + SUBTARGET may be used as the target for computing one of EXP's operands.
- + IGNORE is nonzero if the value is to be ignored. */
- +
- +static rtx
- +nios2_expand_builtin (tree exp, rtx target, rtx subtarget,
- + enum machine_mode mode, int ignore)
- +{
- + const struct builtin_description *d;
- + tree fndecl = TREE_OPERAND (TREE_OPERAND (exp, 0), 0);
- + unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
- +
- + for (d = bdesc; d->name; d++)
- + if (d->code == fcode)
- + {
- + if (d->code > NIOS2_FIRST_FPU_INSN && d->code < NIOS2_LAST_FPU_INSN)
- + {
- + nios2_fpu_info *inf = &nios2_fpu_insns[d->code - (NIOS2_FIRST_FPU_INSN + 1)];
- + const struct insn_data *idata = &insn_data[d->icode];
- + if (inf->N < 0)
- + {
- + fatal_error ("Cannot call `%s' without specifying switch `-mcustom-%s'",
- + d->name,
- + inf->option);
- + }
- + if (inf->args[0] != 'z'
- + && (!target
- + || !(idata->operand[0].predicate) (target,
- + idata->operand[0].mode)))
- + target = gen_reg_rtx (idata->operand[0].mode);
- + }
- + return (d->expander) (d, exp, target, subtarget, mode, ignore);
- + }
- +
- + /* we should have seen one of the functins we registered */
- + abort ();
- +}
- +
- +static rtx nios2_create_target (const struct builtin_description *, rtx);
- +
- +
- +static rtx
- +nios2_create_target (const struct builtin_description *d, rtx target)
- +{
- + if (!target
- + || !(*insn_data[d->icode].operand[0].predicate) (target,
- + insn_data[d->icode].operand[0].mode))
- + {
- + target = gen_reg_rtx (insn_data[d->icode].operand[0].mode);
- + }
- +
- + return target;
- +}
- +
- +
- +static rtx nios2_extract_opcode (const struct builtin_description *, int, tree);
- +static rtx nios2_extract_operand (const struct builtin_description *, int, int, tree);
- +
- +static rtx
- +nios2_extract_opcode (const struct builtin_description *d, int op, tree arglist)
- +{
- + enum machine_mode mode = insn_data[d->icode].operand[op].mode;
- + tree arg = TREE_VALUE (arglist);
- + rtx opcode = expand_expr (arg, NULL_RTX, mode, 0);
- + opcode = protect_from_queue (opcode, 0);
- +
- + if (!(*insn_data[d->icode].operand[op].predicate) (opcode, mode))
- + error ("Custom instruction opcode must be compile time constant in the range 0-255 for %s", d->name);
- +
- + builtin_custom_seen[INTVAL (opcode)] = d->name;
- + nios2_custom_check_insns (0);
- + return opcode;
- +}
- +
- +static rtx
- +nios2_extract_operand (const struct builtin_description *d, int op, int argnum, tree arglist)
- +{
- + enum machine_mode mode = insn_data[d->icode].operand[op].mode;
- + tree arg = TREE_VALUE (arglist);
- + rtx operand = expand_expr (arg, NULL_RTX, mode, 0);
- + operand = protect_from_queue (operand, 0);
- +
- + if (!(*insn_data[d->icode].operand[op].predicate) (operand, mode))
- + operand = copy_to_mode_reg (mode, operand);
- +
- + /* ??? Better errors would be nice */
- + if (!(*insn_data[d->icode].operand[op].predicate) (operand, mode))
- + error ("Invalid argument %d to %s", argnum, d->name);
- +
- + return operand;
- +}
- +
- +
- +static rtx
- +nios2_expand_custom_n (const struct builtin_description *d, tree exp,
- + rtx target ATTRIBUTE_UNUSED, rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat;
- + rtx opcode;
- +
- + /* custom_n should have exactly one operand */
- + if (insn_data[d->icode].n_operands != 1)
- + abort ();
- +
- + opcode = nios2_extract_opcode (d, 0, arglist);
- +
- + pat = GEN_FCN (d->icode) (opcode);
- + if (!pat)
- + return 0;
- + emit_insn (pat);
- + return 0;
- +}
- +
- +static rtx
- +nios2_expand_custom_Xn (const struct builtin_description *d, tree exp,
- + rtx target, rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat;
- + rtx opcode;
- +
- + /* custom_Xn should have exactly two operands */
- + if (insn_data[d->icode].n_operands != 2)
- + abort ();
- +
- + target = nios2_create_target (d, target);
- + opcode = nios2_extract_opcode (d, 1, arglist);
- +
- + pat = GEN_FCN (d->icode) (target, opcode);
- + if (!pat)
- + return 0;
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_nX (const struct builtin_description *d, tree exp,
- + rtx target ATTRIBUTE_UNUSED, rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED, int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat;
- + rtx opcode;
- + rtx operands[1];
- + int i;
- +
- +
- + /* custom_nX should have exactly two operands */
- + if (insn_data[d->icode].n_operands != 2)
- + abort ();
- +
- + opcode = nios2_extract_opcode (d, 0, arglist);
- + for (i = 0; i < 1; i++)
- + {
- + arglist = TREE_CHAIN (arglist);
- + operands[i] = nios2_extract_operand (d, i + 1, i + 1, arglist);
- + }
- +
- + pat = GEN_FCN (d->icode) (opcode, operands[0]);
- + if (!pat)
- + return 0;
- + emit_insn (pat);
- + return 0;
- +}
- +
- +static rtx
- +nios2_expand_custom_XnX (const struct builtin_description *d, tree exp, rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat;
- + rtx opcode;
- + rtx operands[1];
- + int i;
- +
- + /* custom_Xn should have exactly three operands */
- + if (insn_data[d->icode].n_operands != 3)
- + abort ();
- +
- + target = nios2_create_target (d, target);
- + opcode = nios2_extract_opcode (d, 1, arglist);
- +
- + for (i = 0; i < 1; i++)
- + {
- + arglist = TREE_CHAIN (arglist);
- + operands[i] = nios2_extract_operand (d, i + 2, i + 1, arglist);
- + }
- +
- + pat = GEN_FCN (d->icode) (target, opcode, operands[0]);
- +
- + if (!pat)
- + return 0;
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_nXX (const struct builtin_description *d, tree exp, rtx target ATTRIBUTE_UNUSED,
- + rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat;
- + rtx opcode;
- + rtx operands[2];
- + int i;
- +
- +
- + /* custom_nX should have exactly three operands */
- + if (insn_data[d->icode].n_operands != 3)
- + abort ();
- +
- + opcode = nios2_extract_opcode (d, 0, arglist);
- + for (i = 0; i < 2; i++)
- + {
- + arglist = TREE_CHAIN (arglist);
- + operands[i] = nios2_extract_operand (d, i + 1, i + 1, arglist);
- + }
- +
- + pat = GEN_FCN (d->icode) (opcode, operands[0], operands[1]);
- + if (!pat)
- + return 0;
- + emit_insn (pat);
- + return 0;
- +}
- +
- +static rtx
- +nios2_expand_custom_XnXX (const struct builtin_description *d, tree exp, rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat;
- + rtx opcode;
- + rtx operands[2];
- + int i;
- +
- +
- + /* custom_XnX should have exactly four operands */
- + if (insn_data[d->icode].n_operands != 4)
- + abort ();
- +
- + target = nios2_create_target (d, target);
- + opcode = nios2_extract_opcode (d, 1, arglist);
- + for (i = 0; i < 2; i++)
- + {
- + arglist = TREE_CHAIN (arglist);
- + operands[i] = nios2_extract_operand (d, i + 2, i + 1, arglist);
- + }
- +
- + pat = GEN_FCN (d->icode) (target, opcode, operands[0], operands[1]);
- +
- + if (!pat)
- + return 0;
- + emit_insn (pat);
- + return target;
- +}
- +
- +
- +
- +static rtx
- +nios2_expand_STXIO (const struct builtin_description *d, tree exp, rtx target ATTRIBUTE_UNUSED,
- + rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat;
- + rtx store_dest, store_val;
- + enum insn_code icode = d->icode;
- +
- + /* stores should have exactly two operands */
- + if (insn_data[icode].n_operands != 2)
- + abort ();
- +
- + /* process the destination of the store */
- + {
- + enum machine_mode mode = insn_data[icode].operand[0].mode;
- + tree arg = TREE_VALUE (arglist);
- + store_dest = expand_expr (arg, NULL_RTX, VOIDmode, 0);
- + store_dest = protect_from_queue (store_dest, 0);
- +
- + store_dest = gen_rtx_MEM (mode, copy_to_mode_reg (Pmode, store_dest));
- +
- + /* ??? Better errors would be nice */
- + if (!(*insn_data[icode].operand[0].predicate) (store_dest, mode))
- + error ("Invalid argument 1 to %s", d->name);
- + }
- +
- +
- + /* process the value to store */
- + {
- + enum machine_mode mode = insn_data[icode].operand[1].mode;
- + tree arg = TREE_VALUE (TREE_CHAIN (arglist));
- + store_val = expand_expr (arg, NULL_RTX, mode, 0);
- + store_val = protect_from_queue (store_val, 0);
- +
- + if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
- + store_val = copy_to_mode_reg (mode, store_val);
- +
- + /* ??? Better errors would be nice */
- + if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
- + error ("Invalid argument 2 to %s", d->name);
- + }
- +
- + pat = GEN_FCN (d->icode) (store_dest, store_val);
- + if (!pat)
- + return 0;
- + emit_insn (pat);
- + return 0;
- +}
- +
- +
- +static rtx
- +nios2_expand_LDXIO (const struct builtin_description * d, tree exp, rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED, enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat;
- + rtx ld_src;
- + enum insn_code icode = d->icode;
- +
- + /* loads should have exactly two operands */
- + if (insn_data[icode].n_operands != 2)
- + abort ();
- +
- + target = nios2_create_target (d, target);
- +
- + {
- + enum machine_mode mode = insn_data[icode].operand[1].mode;
- + tree arg = TREE_VALUE (arglist);
- + ld_src = expand_expr (arg, NULL_RTX, VOIDmode, 0);
- + ld_src = protect_from_queue (ld_src, 0);
- +
- + ld_src = gen_rtx_MEM (mode, copy_to_mode_reg (Pmode, ld_src));
- +
- + /* ??? Better errors would be nice */
- + if (!(*insn_data[icode].operand[1].predicate) (ld_src, mode))
- + {
- + error ("Invalid argument 1 to %s", d->name);
- + }
- + }
- +
- + pat = GEN_FCN (d->icode) (target, ld_src);
- + if (!pat)
- + return 0;
- + emit_insn (pat);
- + return target;
- +}
- +
- +
- +static rtx
- +nios2_expand_sync (const struct builtin_description * d ATTRIBUTE_UNUSED,
- + tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + emit_insn (gen_sync ());
- + return 0;
- +}
- +
- +static rtx
- +nios2_expand_rdctl (const struct builtin_description * d ATTRIBUTE_UNUSED,
- + tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat;
- + rtx rdctl_reg;
- + enum insn_code icode = d->icode;
- +
- + /* rdctl should have exactly two operands */
- + if (insn_data[icode].n_operands != 2)
- + abort ();
- +
- + target = nios2_create_target (d, target);
- +
- + {
- + enum machine_mode mode = insn_data[icode].operand[1].mode;
- + tree arg = TREE_VALUE (arglist);
- + rdctl_reg = expand_expr (arg, NULL_RTX, VOIDmode, 0);
- + rdctl_reg = protect_from_queue (rdctl_reg, 0);
- +
- + if (!(*insn_data[icode].operand[1].predicate) (rdctl_reg, mode))
- + {
- + error ("Control register number must be in range 0-31 for %s", d->name);
- + }
- + }
- +
- + pat = GEN_FCN (d->icode) (target, rdctl_reg);
- + if (!pat)
- + return 0;
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_wrctl (const struct builtin_description * d ATTRIBUTE_UNUSED,
- + tree exp ATTRIBUTE_UNUSED, rtx target ATTRIBUTE_UNUSED,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat;
- + rtx wrctl_reg, store_val;
- + enum insn_code icode = d->icode;
- +
- + /* stores should have exactly two operands */
- + if (insn_data[icode].n_operands != 2)
- + abort ();
- +
- + /* process the destination of the store */
- + {
- + enum machine_mode mode = insn_data[icode].operand[0].mode;
- + tree arg = TREE_VALUE (arglist);
- + wrctl_reg = expand_expr (arg, NULL_RTX, VOIDmode, 0);
- + wrctl_reg = protect_from_queue (wrctl_reg, 0);
- +
- + if (!(*insn_data[icode].operand[0].predicate) (wrctl_reg, mode))
- + error ("Control register number must be in range 0-31 for %s", d->name);
- + }
- +
- +
- + /* process the value to store */
- + {
- + enum machine_mode mode = insn_data[icode].operand[1].mode;
- + tree arg = TREE_VALUE (TREE_CHAIN (arglist));
- + store_val = expand_expr (arg, NULL_RTX, mode, 0);
- + store_val = protect_from_queue (store_val, 0);
- +
- + if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
- + store_val = copy_to_mode_reg (mode, store_val);
- +
- + /* ??? Better errors would be nice */
- + if (!(*insn_data[icode].operand[1].predicate) (store_val, mode))
- + error ("Invalid argument 2 to %s", d->name);
- + }
- +
- + pat = GEN_FCN (d->icode) (wrctl_reg, store_val);
- + if (!pat)
- + return 0;
- + emit_insn (pat);
- + return 0;
- +}
- +
- +static rtx
- +nios2_extract_double (const struct insn_data *idata, tree arglist, int index)
- +{
- + rtx arg;
- +
- + while (index--)
- + {
- + arglist = TREE_CHAIN (arglist);
- + }
- + arg = expand_expr (TREE_VALUE (arglist), NULL_RTX, DFmode, 0);
- + arg = protect_from_queue (arg, 0);
- + if (!(*(idata->operand[index+1].predicate)) (arg, DFmode))
- + {
- + arg = copy_to_mode_reg (DFmode, arg);
- + }
- + return arg;
- +}
- +
- +static rtx
- +nios2_extract_float (const struct insn_data *idata, tree arglist, int index)
- +{
- + rtx arg;
- +
- + while (index--)
- + {
- + arglist = TREE_CHAIN (arglist);
- + }
- + arg = expand_expr (TREE_VALUE (arglist), NULL_RTX, SFmode, 0);
- + arg = protect_from_queue (arg, 0);
- + if (!(*(idata->operand[index+1].predicate)) (arg, SFmode))
- + {
- + arg = copy_to_mode_reg (SFmode, arg);
- + }
- + return arg;
- +}
- +
- +static rtx
- +nios2_extract_integer (const struct insn_data *idata, tree arglist, int index)
- +{
- + rtx arg;
- +
- + while (index--)
- + {
- + arglist = TREE_CHAIN (arglist);
- + }
- + arg = expand_expr (TREE_VALUE (arglist), NULL_RTX, SImode, 0);
- + arg = protect_from_queue (arg, 0);
- + if (!(*(idata->operand[index+1].predicate)) (arg, SImode))
- + {
- + arg = copy_to_mode_reg (SImode, arg);
- + }
- + return protect_from_queue (arg, 0);
- +}
- +
- +static rtx
- +nios2_expand_custom_zdz (const struct builtin_description *d,
- + tree exp,
- + rtx target ATTRIBUTE_UNUSED,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (nios2_extract_double (&insn_data[d->icode],
- + arglist, 0));
- + if (pat)
- + emit_insn (pat);
- + return 0;
- +}
- +
- +static rtx
- +nios2_expand_custom_zsz (const struct builtin_description *d,
- + tree exp,
- + rtx target ATTRIBUTE_UNUSED,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (nios2_extract_float (&insn_data[d->icode],
- + arglist, 0));
- + if (pat)
- + emit_insn (pat);
- + return 0;
- +}
- +
- +static rtx
- +nios2_expand_custom_szz (const struct builtin_description *d,
- + tree exp ATTRIBUTE_UNUSED,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + rtx pat = GEN_FCN (d->icode) (target);
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_sss (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_float (&insn_data[d->icode],
- + arglist, 0),
- + nios2_extract_float (&insn_data[d->icode],
- + arglist, 1));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_ssz (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_float (&insn_data[d->icode],
- + arglist, 0));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_iss (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_float (&insn_data[d->icode],
- + arglist, 0),
- + nios2_extract_float (&insn_data[d->icode],
- + arglist, 1));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_ddd (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_double (&insn_data[d->icode],
- + arglist, 0),
- + nios2_extract_double (&insn_data[d->icode],
- + arglist, 1));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_ddz (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_double (&insn_data[d->icode],
- + arglist, 0));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_idd (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_double (&insn_data[d->icode],
- + arglist, 0),
- + nios2_extract_double (&insn_data[d->icode],
- + arglist, 1));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_siz (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_integer (&insn_data[d->icode],
- + arglist, 0));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_suz (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_integer (&insn_data[d->icode],
- + arglist, 0));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_diz (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_integer (&insn_data[d->icode],
- + arglist, 0));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_duz (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_integer (&insn_data[d->icode],
- + arglist, 0));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_isz (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_float (&insn_data[d->icode],
- + arglist, 0));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_usz (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_float (&insn_data[d->icode],
- + arglist, 0));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_idz (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_double (&insn_data[d->icode],
- + arglist, 0));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_udz (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_double (&insn_data[d->icode],
- + arglist, 0));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_dsz (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_float (&insn_data[d->icode],
- + arglist, 0));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +static rtx
- +nios2_expand_custom_sdz (const struct builtin_description *d,
- + tree exp,
- + rtx target,
- + rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree arglist = TREE_OPERAND (exp, 1);
- + rtx pat = GEN_FCN (d->icode) (target,
- + nios2_extract_double (&insn_data[d->icode],
- + arglist, 0));
- + if (pat)
- + emit_insn (pat);
- + return target;
- +}
- +
- +#include "gt-nios2.h"
- +
- diff --git a/gcc/config/nios2/nios2.h b/gcc/config/nios2/nios2.h
- new file mode 100644
- index 0000000..500ccf0
- --- /dev/null
- +++ b/gcc/config/nios2/nios2.h
- @@ -0,0 +1,1130 @@
- +/* Definitions of target machine for Altera NIOS 2G NIOS2 version.
- + Copyright (C) 2005 Altera
- + Contributed by Jonah Graham (jgraham@altera.com) and Will Reece (wreece@altera.com).
- +
- +This file is part of GNU CC.
- +
- +GNU CC 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 2, or (at your option)
- +any later version.
- +
- +GNU CC 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 GNU CC; see the file COPYING. If not, write to
- +the Free Software Foundation, 59 Temple Place - Suite 330,
- +Boston, MA 02111-1307, USA. */
- +
- +
- +
- +#define TARGET_CPU_CPP_BUILTINS() \
- + do \
- + { \
- + builtin_define_std ("NIOS2"); \
- + builtin_define_std ("nios2"); \
- + if (TARGET_BIG_ENDIAN) \
- + builtin_define_std ("nios2_big_endian"); \
- + else \
- + builtin_define_std ("nios2_little_endian"); \
- + } \
- + while (0)
- +#define TARGET_VERSION fprintf (stderr, " (Altera Nios II)")
- +
- +
- +
- +
- +
- +/*********************************
- + * Run-time Target Specification
- + *********************************/
- +
- +#define HAS_DIV_FLAG 0x0001
- +#define HAS_MUL_FLAG 0x0002
- +#define HAS_MULX_FLAG 0x0004
- +#define FAST_SW_DIV_FLAG 0x0008
- +#define INLINE_MEMCPY_FLAG 0x00010
- +#define CACHE_VOLATILE_FLAG 0x0020
- +#define BYPASS_CACHE_FLAG 0x0040
- +#define STACK_CHECK_FLAG 0x0080
- +#define REVERSE_BITFIELDS_FLAG 0x0100
- +/* Reserve 0x0200 for REVERSE_ENDIAN_FLAG */
- +#define BIG_ENDIAN_FLAG 0x0400
- +
- +extern int target_flags;
- +#define TARGET_HAS_DIV (target_flags & HAS_DIV_FLAG)
- +#define TARGET_HAS_MUL (target_flags & HAS_MUL_FLAG)
- +#define TARGET_HAS_MULX (target_flags & HAS_MULX_FLAG)
- +#define TARGET_FAST_SW_DIV (target_flags & FAST_SW_DIV_FLAG)
- +#define TARGET_INLINE_MEMCPY (target_flags & INLINE_MEMCPY_FLAG)
- +#define TARGET_CACHE_VOLATILE (target_flags & CACHE_VOLATILE_FLAG)
- +#define TARGET_BYPASS_CACHE (target_flags & BYPASS_CACHE_FLAG)
- +#define TARGET_STACK_CHECK (target_flags & STACK_CHECK_FLAG)
- +#define TARGET_REVERSE_BITFIELDS (target_flags & REVERSE_BITFIELDS_FLAG)
- +#define TARGET_BIG_ENDIAN (target_flags & BIG_ENDIAN_FLAG)
- +
- +#define TARGET_SWITCHES \
- +{ \
- + { "hw-div", HAS_DIV_FLAG, \
- + N_("Enable DIV, DIVU") }, \
- + { "no-hw-div", -HAS_DIV_FLAG, \
- + N_("Disable DIV, DIVU (default)") }, \
- + { "hw-mul", HAS_MUL_FLAG, \
- + N_("Enable MUL instructions (default)") }, \
- + { "hw-mulx", HAS_MULX_FLAG, \
- + N_("Enable MULX instructions, assume fast shifter") }, \
- + { "no-hw-mul", -HAS_MUL_FLAG, \
- + N_("Disable MUL instructions") }, \
- + { "no-hw-mulx", -HAS_MULX_FLAG, \
- + N_("Disable MULX instructions, assume slow shifter (default and implied by -mno-hw-mul)") }, \
- + { "fast-sw-div", FAST_SW_DIV_FLAG, \
- + N_("Use table based fast divide (default at -O3)") }, \
- + { "no-fast-sw-div", -FAST_SW_DIV_FLAG, \
- + N_("Don't use table based fast divide ever") }, \
- + { "inline-memcpy", INLINE_MEMCPY_FLAG, \
- + N_("Inline small memcpy (default when optimizing)") }, \
- + { "no-inline-memcpy", -INLINE_MEMCPY_FLAG, \
- + N_("Don't Inline small memcpy") }, \
- + { "cache-volatile", CACHE_VOLATILE_FLAG, \
- + N_("Volatile accesses use non-io variants of instructions (default)") }, \
- + { "no-cache-volatile", -CACHE_VOLATILE_FLAG, \
- + N_("Volatile accesses use io variants of instructions") }, \
- + { "bypass-cache", BYPASS_CACHE_FLAG, \
- + N_("All ld/st instructins use io variants") }, \
- + { "no-bypass-cache", -BYPASS_CACHE_FLAG, \
- + N_("All ld/st instructins do not use io variants (default)") }, \
- + { "smallc", 0, \
- + N_("Link with a limited version of the C library") }, \
- + { "ctors-in-init", 0, \
- + "" /* undocumented: N_("Link with static constructors and destructors in init") */ }, \
- + { "stack-check", STACK_CHECK_FLAG, \
- + N_("Enable stack limit checking.") }, \
- + { "no-stack-check", -STACK_CHECK_FLAG, \
- + N_("Disable stack limit checking (default).") }, \
- + { "reverse-bitfields", REVERSE_BITFIELDS_FLAG, \
- + N_("Reverse the order of bitfields in a struct.") }, \
- + { "no-reverse-bitfields", -REVERSE_BITFIELDS_FLAG, \
- + N_("Use the normal order of bitfields in a struct (default).") }, \
- + { "eb", BIG_ENDIAN_FLAG, \
- + N_("Use big-endian byte order") }, \
- + { "el", -BIG_ENDIAN_FLAG, \
- + N_("Use little-endian byte order") }, \
- + { "", TARGET_DEFAULT, 0 } \
- +}
- +
- +extern const char *nios2_sys_nosys_string; /* for -msys=nosys */
- +extern const char *nios2_sys_lib_string; /* for -msys-lib= */
- +extern const char *nios2_sys_crt0_string; /* for -msys-crt0= */
- +
- +/*
- + * There's a lot of error-prone tedium with all the different
- + * custom floating point instructions. Try to automate it a bit
- + * to make it easier to deal with.
- + */
- +#define NIOS2_STRINGIFY_INNER(x) #x
- +#define NIOS2_STRINGIFY(x) NIOS2_STRINGIFY_INNER(x)
- +#define NIOS2_CONCAT_INNER(x, y) x ## y
- +#define NIOS2_CONCAT(x, y) NIOS2_CONCAT_INNER (x, y)
- +
- +#define NIOS2_FOR_ALL_FPU_INSNS \
- + NIOS2_FPU_INSN (fwrx, nios2_fwrx, zdz) \
- + NIOS2_FPU_INSN (fwry, nios2_fwry, zsz) \
- + NIOS2_FPU_INSN (frdxlo, nios2_frdxlo, szz) \
- + NIOS2_FPU_INSN (frdxhi, nios2_frdxhi, szz) \
- + NIOS2_FPU_INSN (frdy, nios2_frdy, szz) \
- +\
- + NIOS2_FPU_INSN (fadds, addsf3, sss) \
- + NIOS2_FPU_INSN (fsubs, subsf3, sss) \
- + NIOS2_FPU_INSN (fmuls, mulsf3, sss) \
- + NIOS2_FPU_INSN (fdivs, divsf3, sss) \
- + NIOS2_FPU_INSN (fmins, minsf3, sss) \
- + NIOS2_FPU_INSN (fmaxs, maxsf3, sss) \
- + NIOS2_FPU_INSN (fnegs, negsf2, ssz) \
- + NIOS2_FPU_INSN (fabss, abssf2, ssz) \
- + NIOS2_FPU_INSN (fsqrts, sqrtsf2, ssz) \
- + NIOS2_FPU_INSN (fcoss, cossf2, ssz) \
- + NIOS2_FPU_INSN (fsins, sinsf2, ssz) \
- + NIOS2_FPU_INSN (ftans, tansf2, ssz) \
- + NIOS2_FPU_INSN (fatans, atansf2, ssz) \
- + NIOS2_FPU_INSN (fexps, expsf2, ssz) \
- + NIOS2_FPU_INSN (flogs, logsf2, ssz) \
- + NIOS2_FPU_INSN (fcmplts, nios2_sltsf, iss) \
- + NIOS2_FPU_INSN (fcmples, nios2_slesf, iss) \
- + NIOS2_FPU_INSN (fcmpgts, nios2_sgtsf, iss) \
- + NIOS2_FPU_INSN (fcmpges, nios2_sgesf, iss) \
- + NIOS2_FPU_INSN (fcmpeqs, nios2_seqsf, iss) \
- + NIOS2_FPU_INSN (fcmpnes, nios2_snesf, iss) \
- +\
- + NIOS2_FPU_INSN (faddd, adddf3, ddd) \
- + NIOS2_FPU_INSN (fsubd, subdf3, ddd) \
- + NIOS2_FPU_INSN (fmuld, muldf3, ddd) \
- + NIOS2_FPU_INSN (fdivd, divdf3, ddd) \
- + NIOS2_FPU_INSN (fmind, mindf3, ddd) \
- + NIOS2_FPU_INSN (fmaxd, maxdf3, ddd) \
- + NIOS2_FPU_INSN (fnegd, negdf2, ddz) \
- + NIOS2_FPU_INSN (fabsd, absdf2, ddz) \
- + NIOS2_FPU_INSN (fsqrtd, sqrtdf2, ddz) \
- + NIOS2_FPU_INSN (fcosd, cosdf2, ddz) \
- + NIOS2_FPU_INSN (fsind, sindf2, ddz) \
- + NIOS2_FPU_INSN (ftand, tandf2, ddz) \
- + NIOS2_FPU_INSN (fatand, atandf2, ddz) \
- + NIOS2_FPU_INSN (fexpd, expdf2, ddz) \
- + NIOS2_FPU_INSN (flogd, logdf2, ddz) \
- + NIOS2_FPU_INSN (fcmpltd, nios2_sltdf, idd) \
- + NIOS2_FPU_INSN (fcmpled, nios2_sledf, idd) \
- + NIOS2_FPU_INSN (fcmpgtd, nios2_sgtdf, idd) \
- + NIOS2_FPU_INSN (fcmpged, nios2_sgedf, idd) \
- + NIOS2_FPU_INSN (fcmpeqd, nios2_seqdf, idd) \
- + NIOS2_FPU_INSN (fcmpned, nios2_snedf, idd) \
- +\
- + NIOS2_FPU_INSN (floatis, floatsisf2, siz) \
- + NIOS2_FPU_INSN (floatus, floatunssisf2, suz) \
- + NIOS2_FPU_INSN (floatid, floatsidf2, diz) \
- + NIOS2_FPU_INSN (floatud, floatunssidf2, duz) \
- + NIOS2_FPU_INSN (fixsi, fixsfsi2, isz) \
- + NIOS2_FPU_INSN (fixsu, fixunssfsi2, usz) \
- + NIOS2_FPU_INSN (fixdi, fixdfsi2, idz) \
- + NIOS2_FPU_INSN (fixdu, fixunsdfsi2, udz) \
- + NIOS2_FPU_INSN (fextsd, extendsfdf2, dsz) \
- + NIOS2_FPU_INSN (ftruncds, truncdfsf2, sdz)
- +
- +enum
- +{
- +#define NIOS2_FPU_INSN(opt, insn, args) \
- + NIOS2_CONCAT (nios2_fpu_, insn),
- +NIOS2_FOR_ALL_FPU_INSNS
- + nios2_fpu_max_insn
- +};
- +
- +struct cpp_reader;
- +typedef const char * (*nios2_outputfn) (rtx);
- +typedef void (*nios2_pragmafn) (struct cpp_reader *);
- +
- +typedef struct
- +{
- + const char *option; /* name of switch, e.g. fadds */
- + const char *insnnm; /* name of gcc insn, e.g. addsf3 */
- + const char *args; /* args to gcc insn, e.g. sss */
- + const char *value; /* value of switch as a string */
- + int N; /* value of switch as an integer, -1 = not used */
- + nios2_outputfn output; /* output function for use in .md file */
- + const char *pname; /* name of corresponding #pragma custom- */
- + nios2_pragmafn pragma; /* pragma function for register_target_pragmas */
- + const char *nopname; /* name of corresponding #pragma no-custom- */
- + nios2_pragmafn nopragma; /* pragma function for register_target_pragmas */
- + int is_double; /* does this insn have any double operands */
- + int needed_by_double; /* is this insn needed if doubles are used? */
- + int needs_unsafe; /* does this insn require
- + -funsafe-math-optimizations to work? */
- + int needs_finite; /* does this insn require
- + -ffinite-math-only to work? */
- + int pragma_seen; /* have we seen the corresponding #pragma? */
- +} nios2_fpu_info;
- +
- +extern nios2_fpu_info nios2_fpu_insns[nios2_fpu_max_insn];
- +extern const char *nios2_custom_fpu_cfg_string;
- +
- +#undef NIOS2_FPU_INSN
- +#define NIOS2_FPU_INSN(opt, insn, args) \
- + { \
- + "custom-" NIOS2_STRINGIFY (opt) "=", \
- + &(nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].value), \
- + N_("Integer id (N) of " NIOS2_STRINGIFY (opt) " custom instruction"), \
- + 0 \
- + }, \
- + { \
- + "no-custom-" NIOS2_STRINGIFY (opt), \
- + &(nios2_fpu_insns[NIOS2_CONCAT (nios2_fpu_, insn)].value), \
- + N_("Do not use the " NIOS2_STRINGIFY (opt) " custom instruction"), \
- + "-1" \
- + },
- +
- +#define TARGET_OPTIONS \
- +{ \
- + { "sys=nosys", &nios2_sys_nosys_string, \
- + N_("Use stub versions of OS library calls (default)"), 0}, \
- + { "sys-lib=", &nios2_sys_lib_string, \
- + N_("Name of System Library to link against. (Converted to a -l option)"), 0}, \
- + { "sys-crt0=", &nios2_sys_crt0_string, \
- + N_("Name of the startfile. (default is a crt0 for the ISS only)"), 0}, \
- + NIOS2_FOR_ALL_FPU_INSNS \
- + { "custom-fpu-cfg=", &nios2_custom_fpu_cfg_string, \
- + N_("Floating point custom instruction configuration name"), 0 }, \
- +}
- +
- +/* We're little endian, unless otherwise specified by including big.h */
- +#ifndef TARGET_ENDIAN_DEFAULT
- +# define TARGET_ENDIAN_DEFAULT 0
- +#endif
- +
- +/* Default target_flags if no switches specified. */
- +#ifndef TARGET_DEFAULT
- +# define TARGET_DEFAULT (HAS_MUL_FLAG | CACHE_VOLATILE_FLAG | TARGET_ENDIAN_DEFAULT)
- +#endif
- +
- +/* Switch Recognition by gcc.c. Add -G xx support */
- +#undef SWITCH_TAKES_ARG
- +#define SWITCH_TAKES_ARG(CHAR) \
- + (DEFAULT_SWITCH_TAKES_ARG (CHAR) || (CHAR) == 'G')
- +
- +#define OVERRIDE_OPTIONS override_options ()
- +#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) optimization_options (LEVEL, SIZE)
- +#define CAN_DEBUG_WITHOUT_FP
- +
- +#define CC1_SPEC "\
- +%{G*} %{EB:-meb} %{EL:-mel} %{EB:%{EL:%emay not use both -EB and -EL}}"
- +
- +#if TARGET_ENDIAN_DEFAULT == 0
- +# define ASM_SPEC "\
- +%{!EB:%{!meb:-EL}} %{EB|meb:-EB}"
- +# define LINK_SPEC "\
- +%{!EB:%{!meb:-EL}} %{EB|meb:-EB}"
- +# define MULTILIB_DEFAULTS { "EL" }
- +#else
- +# define ASM_SPEC "\
- +%{!EL:%{!mel:-EB}} %{EL|mel:-EL}"
- +# define LINK_SPEC "\
- +%{!EL:%{!mel:-EB}} %{EL|mel:-EL}"
- +# define MULTILIB_DEFAULTS { "EB" }
- +#endif
- +
- +#undef LIB_SPEC
- +#define LIB_SPEC \
- +"--start-group %{msmallc: -lsmallc} %{!msmallc: -lc} -lgcc \
- + %{msys-lib=*: -l%*} \
- + %{!msys-lib=*: -lnosys -lstack} \
- + --end-group \
- + %{msys-lib=: %eYou need a library name for -msys-lib=} \
- +"
- +
- +
- +#undef STARTFILE_SPEC
- +#define STARTFILE_SPEC \
- +"%{msys-crt0=*: %*} %{!msys-crt0=*: crt0%O%s} \
- + %{msys-crt0=: %eYou need a C startup file for -msys-crt0=} \
- + %{mctors-in-init: crti%O%s crtbegin%O%s} \
- +"
- +
- +#undef ENDFILE_SPEC
- +#define ENDFILE_SPEC \
- + "%{mctors-in-init: crtend%O%s crtn%O%s}"
- +
- +
- +/***********************
- + * Storage Layout
- + ***********************/
- +
- +#define DEFAULT_SIGNED_CHAR 1
- +#define BITS_BIG_ENDIAN 0
- +#define BYTES_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
- +#define WORDS_BIG_ENDIAN (TARGET_BIG_ENDIAN != 0)
- +#if defined(__nios2_big_endian__)
- +#define LIBGCC2_WORDS_BIG_ENDIAN 1
- +#else
- +#define LIBGCC2_WORDS_BIG_ENDIAN 0
- +#endif
- +#define BITS_PER_UNIT 8
- +#define BITS_PER_WORD 32
- +#define UNITS_PER_WORD 4
- +#define POINTER_SIZE 32
- +#define BIGGEST_ALIGNMENT 32
- +#define STRICT_ALIGNMENT 1
- +#define FUNCTION_BOUNDARY 32
- +#define PARM_BOUNDARY 32
- +#define STACK_BOUNDARY 32
- +#define PREFERRED_STACK_BOUNDARY 32
- +#define MAX_FIXED_MODE_SIZE 64
- +
- +#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- + ((TREE_CODE (EXP) == STRING_CST) \
- + && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
- +
- +
- +/**********************
- + * Layout of Source Language Data Types
- + **********************/
- +
- +#define INT_TYPE_SIZE 32
- +#define SHORT_TYPE_SIZE 16
- +#define LONG_TYPE_SIZE 32
- +#define LONG_LONG_TYPE_SIZE 64
- +#define FLOAT_TYPE_SIZE 32
- +#define DOUBLE_TYPE_SIZE 64
- +#define LONG_DOUBLE_TYPE_SIZE DOUBLE_TYPE_SIZE
- +
- +
- +/*************************
- + * Condition Code Status
- + ************************/
- +
- +/* comparison type */
- +/* ??? Currently CMP_DI is unused. CMP_SF and CMP_DF are only used if
- + the corresponding -mcustom-<opcode> switches are present. */
- +enum cmp_type {
- + CMP_SI, /* compare four byte integers */
- + CMP_DI, /* compare eight byte integers */
- + CMP_SF, /* compare single precision floats */
- + CMP_DF, /* compare double precision floats */
- + CMP_MAX /* max comparison type */
- +};
- +
- +extern GTY(()) rtx branch_cmp[2]; /* operands for compare */
- +extern enum cmp_type branch_type; /* what type of branch to use */
- +
- +/**********************
- + * Register Usage
- + **********************/
- +
- +/* ---------------------------------- *
- + * Basic Characteristics of Registers
- + * ---------------------------------- */
- +
- +/*
- +Register Number
- + Register Name
- + Alternate Name
- + Purpose
- +0 r0 zero always zero
- +1 r1 at Assembler Temporary
- +2-3 r2-r3 Return Location
- +4-7 r4-r7 Register Arguments
- +8-15 r8-r15 Caller Saved Registers
- +16-22 r16-r22 Callee Saved Registers
- +23 r23 sc Static Chain (Callee Saved)
- + ??? Does $sc want to be caller or callee
- + saved. If caller, 15, else 23.
- +24 r24 et Exception Temporary
- +25 r25 bt Breakpoint Temporary
- +26 r26 gp Global Pointer
- +27 r27 sp Stack Pointer
- +28 r28 fp Frame Pointer
- +29 r29 ea Exception Return Address
- +30 r30 ba Breakpoint Return Address
- +31 r31 ra Return Address
- +
- +32 ctl0 status
- +33 ctl1 estatus STATUS saved by exception ?
- +34 ctl2 bstatus STATUS saved by break ?
- +35 ctl3 ipri Interrupt Priority Mask ?
- +36 ctl4 ecause Exception Cause ?
- +
- +37 pc Not an actual register
- +
- +38 rap Return address pointer, this does not
- + actually exist and will be eliminated
- +
- +39 fake_fp Fake Frame Pointer which will always be eliminated.
- +40 fake_ap Fake Argument Pointer which will always be eliminated.
- +
- +41 First Pseudo Register
- +
- +
- +The definitions for all the hard register numbers
- +are located in nios2.md.
- +*/
- +
- +#define FIRST_PSEUDO_REGISTER 41
- +#define NUM_ARG_REGS (LAST_ARG_REGNO - FIRST_ARG_REGNO + 1)
- +
- +
- +
- +/* also see CONDITIONAL_REGISTER_USAGE */
- +#define FIXED_REGISTERS \
- + { \
- +/* +0 1 2 3 4 5 6 7 8 9 */ \
- +/* 0 */ 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, \
- +/* 10 */ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, \
- +/* 20 */ 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, \
- +/* 30 */ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, \
- +/* 40 */ 1 \
- + }
- +
- +/* call used is the same as caller saved
- + + fixed regs + args + ret vals */
- +#define CALL_USED_REGISTERS \
- + { \
- +/* +0 1 2 3 4 5 6 7 8 9 */ \
- +/* 0 */ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, \
- +/* 10 */ 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, \
- +/* 20 */ 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, \
- +/* 30 */ 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, \
- +/* 40 */ 1 \
- + }
- +
- +#define HARD_REGNO_NREGS(REGNO, MODE) \
- + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
- + / UNITS_PER_WORD)
- +
- +/* --------------------------- *
- + * How Values Fit in Registers
- + * --------------------------- */
- +
- +#define HARD_REGNO_MODE_OK(REGNO, MODE) 1
- +
- +#define MODES_TIEABLE_P(MODE1, MODE2) 1
- +
- +
- +/*************************
- + * Register Classes
- + *************************/
- +
- +enum reg_class
- +{
- + NO_REGS,
- + D00_REG,
- + D01_REG,
- + D02_REG,
- + D03_REG,
- + D04_REG,
- + D05_REG,
- + D06_REG,
- + D07_REG,
- + D08_REG,
- + D09_REG,
- + D10_REG,
- + D11_REG,
- + D12_REG,
- + D13_REG,
- + D14_REG,
- + D15_REG,
- + D16_REG,
- + D17_REG,
- + D18_REG,
- + D19_REG,
- + D20_REG,
- + D21_REG,
- + D22_REG,
- + D23_REG,
- + D24_REG,
- + D25_REG,
- + D26_REG,
- + D27_REG,
- + D28_REG,
- + D29_REG,
- + D30_REG,
- + D31_REG,
- + GP_REGS,
- + ALL_REGS,
- + LIM_REG_CLASSES
- +};
- +
- +#define N_REG_CLASSES (int) LIM_REG_CLASSES
- +
- +#define REG_CLASS_NAMES \
- + {"NO_REGS", \
- + "D00_REG", \
- + "D01_REG", \
- + "D02_REG", \
- + "D03_REG", \
- + "D04_REG", \
- + "D05_REG", \
- + "D06_REG", \
- + "D07_REG", \
- + "D08_REG", \
- + "D09_REG", \
- + "D10_REG", \
- + "D11_REG", \
- + "D12_REG", \
- + "D13_REG", \
- + "D14_REG", \
- + "D15_REG", \
- + "D16_REG", \
- + "D17_REG", \
- + "D18_REG", \
- + "D19_REG", \
- + "D20_REG", \
- + "D21_REG", \
- + "D22_REG", \
- + "D23_REG", \
- + "D24_REG", \
- + "D25_REG", \
- + "D26_REG", \
- + "D27_REG", \
- + "D28_REG", \
- + "D29_REG", \
- + "D30_REG", \
- + "D31_REG", \
- + "GP_REGS", \
- + "ALL_REGS"}
- +
- +#define GENERAL_REGS ALL_REGS
- +
- +#define REG_CLASS_CONTENTS \
- +/* NO_REGS */ {{ 0, 0}, \
- +/* D00_REG */ { 1 << 0, 0}, \
- +/* D01_REG */ { 1 << 1, 0}, \
- +/* D02_REG */ { 1 << 2, 0}, \
- +/* D03_REG */ { 1 << 3, 0}, \
- +/* D04_REG */ { 1 << 4, 0}, \
- +/* D05_REG */ { 1 << 5, 0}, \
- +/* D06_REG */ { 1 << 6, 0}, \
- +/* D07_REG */ { 1 << 7, 0}, \
- +/* D08_REG */ { 1 << 8, 0}, \
- +/* D09_REG */ { 1 << 9, 0}, \
- +/* D10_REG */ { 1 << 10, 0}, \
- +/* D11_REG */ { 1 << 11, 0}, \
- +/* D12_REG */ { 1 << 12, 0}, \
- +/* D13_REG */ { 1 << 13, 0}, \
- +/* D14_REG */ { 1 << 14, 0}, \
- +/* D15_REG */ { 1 << 15, 0}, \
- +/* D16_REG */ { 1 << 16, 0}, \
- +/* D17_REG */ { 1 << 17, 0}, \
- +/* D18_REG */ { 1 << 18, 0}, \
- +/* D19_REG */ { 1 << 19, 0}, \
- +/* D20_REG */ { 1 << 20, 0}, \
- +/* D21_REG */ { 1 << 21, 0}, \
- +/* D22_REG */ { 1 << 22, 0}, \
- +/* D23_REG */ { 1 << 23, 0}, \
- +/* D24_REG */ { 1 << 24, 0}, \
- +/* D25_REG */ { 1 << 25, 0}, \
- +/* D26_REG */ { 1 << 26, 0}, \
- +/* D27_REG */ { 1 << 27, 0}, \
- +/* D28_REG */ { 1 << 28, 0}, \
- +/* D29_REG */ { 1 << 29, 0}, \
- +/* D30_REG */ { 1 << 30, 0}, \
- +/* D31_REG */ { 1 << 31, 0}, \
- +/* GP_REGS */ {~0, 0}, \
- +/* ALL_REGS */ {~0,~0}} \
- +
- +#define REGNO_REG_CLASS(REGNO) ((REGNO) <= 31 ? GP_REGS : ALL_REGS)
- +
- +#define BASE_REG_CLASS ALL_REGS
- +#define INDEX_REG_CLASS ALL_REGS
- +
- +/* 'r', is handled automatically */
- +#define REG_CLASS_FROM_CONSTRAINT(CHAR, STR) \
- + reg_class_from_constraint ((CHAR), (STR))
- +
- +
- +#define REGNO_OK_FOR_BASE_P2(REGNO, STRICT) \
- + ((STRICT) \
- + ? (REGNO) < FIRST_PSEUDO_REGISTER \
- + : (REGNO) < FIRST_PSEUDO_REGISTER || (reg_renumber && reg_renumber[REGNO] < FIRST_PSEUDO_REGISTER))
- +
- +#define REGNO_OK_FOR_INDEX_P2(REGNO, STRICT) \
- + (REGNO_OK_FOR_BASE_P2 (REGNO, STRICT))
- +
- +#define REGNO_OK_FOR_BASE_P(REGNO) \
- + (REGNO_OK_FOR_BASE_P2 (REGNO, 1))
- +
- +#define REGNO_OK_FOR_INDEX_P(REGNO) \
- + (REGNO_OK_FOR_INDEX_P2 (REGNO, 1))
- +
- +#define REG_OK_FOR_BASE_P2(X, STRICT) \
- + (STRICT \
- + ? REGNO_OK_FOR_BASE_P2 (REGNO (X), 1) \
- + : REGNO_OK_FOR_BASE_P2 (REGNO (X), 1) || REGNO(X) >= FIRST_PSEUDO_REGISTER)
- +
- +#define REG_OK_FOR_INDEX_P2(X, STRICT) \
- + (STRICT \
- + ? REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1) \
- + : REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1) || REGNO(X) >= FIRST_PSEUDO_REGISTER)
- +
- +#define CLASS_MAX_NREGS(CLASS, MODE) \
- + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) \
- + / UNITS_PER_WORD)
- +
- +
- +#define SMALL_INT(X) ((unsigned HOST_WIDE_INT) ((X) + 0x8000) < 0x10000)
- +#define SMALL_INT_UNSIGNED(X) ((unsigned HOST_WIDE_INT) (X) < 0x10000)
- +#define UPPER16_INT(X) (((X) & 0xffff) == 0)
- +#define SHIFT_INT(X) ((X) >= 0 && (X) <= 31)
- +#define RDWRCTL_INT(X) ((X) >= 0 && (X) <= 31)
- +#define CUSTOM_INSN_OPCODE(X) ((X) >= 0 && (X) <= 255)
- +
- +#define CONST_OK_FOR_LETTER_P(VALUE, C) \
- + ( \
- + (C) == 'I' ? SMALL_INT (VALUE) : \
- + (C) == 'J' ? SMALL_INT_UNSIGNED (VALUE) : \
- + (C) == 'K' ? UPPER16_INT (VALUE) : \
- + (C) == 'L' ? SHIFT_INT (VALUE) : \
- + (C) == 'M' ? (VALUE) == 0 : \
- + (C) == 'N' ? CUSTOM_INSN_OPCODE (VALUE) : \
- + (C) == 'O' ? RDWRCTL_INT (VALUE) : \
- + 0)
- +
- +#define CONST_DOUBLE_OK_FOR_LETTER_P(VALUE, C) 0
- +
- +#define PREFERRED_RELOAD_CLASS(X, CLASS) \
- + ((CLASS) == NO_REGS ? GENERAL_REGS : (CLASS))
- +
- +#define CONSTRAINT_LEN(C, STR) \
- + ((C) == 'D' ? 3 : DEFAULT_CONSTRAINT_LEN ((C), (STR)))
- +
- +/* 'S' matches immediates which are in small data
- + and therefore can be added to gp to create a
- + 32-bit value. */
- +#define EXTRA_CONSTRAINT(VALUE, C) \
- + ((C) == 'S' \
- + && (GET_CODE (VALUE) == SYMBOL_REF) \
- + && SYMBOL_REF_IN_NIOS2_SMALL_DATA_P (VALUE))
- +
- +
- +
- +
- +/* Say that the epilogue uses the return address register. Note that
- + in the case of sibcalls, the values "used by the epilogue" are
- + considered live at the start of the called function. */
- +#define EPILOGUE_USES(REGNO) ((REGNO) == RA_REGNO)
- +
- +
- +#define DEFAULT_MAIN_RETURN c_expand_return (integer_zero_node)
- +
- +/**********************************
- + * Trampolines for Nested Functions
- + ***********************************/
- +
- +#define TRAMPOLINE_TEMPLATE(FILE) \
- + error ("trampolines not yet implemented")
- +#define TRAMPOLINE_SIZE 20
- +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
- + error ("trampolines not yet implemented")
- +
- +/***************************
- + * Stack Layout and Calling Conventions
- + ***************************/
- +
- +/* ------------------ *
- + * Basic Stack Layout
- + * ------------------ */
- +
- +/* The downward variants are used by the compiler,
- + the upward ones serve as documentation */
- +#define STACK_GROWS_DOWNWARD
- +#define FRAME_GROWS_UPWARD
- +#define ARGS_GROW_UPWARD
- +
- +#define STARTING_FRAME_OFFSET current_function_outgoing_args_size
- +#define FIRST_PARM_OFFSET(FUNDECL) 0
- +
- +/* Before the prologue, RA lives in r31. */
- +#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (VOIDmode, RA_REGNO)
- +
- +/* -------------------------------------- *
- + * Registers That Address the Stack Frame
- + * -------------------------------------- */
- +
- +#define STACK_POINTER_REGNUM SP_REGNO
- +#define STATIC_CHAIN_REGNUM SC_REGNO
- +#define PC_REGNUM PC_REGNO
- +#define DWARF_FRAME_RETURN_COLUMN RA_REGNO
- +
- +/* Base register for access to local variables of the function. We
- + pretend that the frame pointer is a non-existent hard register, and
- + then eliminate it to HARD_FRAME_POINTER_REGNUM. */
- +#define FRAME_POINTER_REGNUM FAKE_FP_REGNO
- +
- +#define HARD_FRAME_POINTER_REGNUM FP_REGNO
- +#define RETURN_ADDRESS_POINTER_REGNUM RAP_REGNO
- +/* the argumnet pointer needs to always be eliminated
- + so it is set to a fake hard register. */
- +#define ARG_POINTER_REGNUM FAKE_AP_REGNO
- +
- +/* ----------------------------------------- *
- + * Eliminating Frame Pointer and Arg Pointer
- + * ----------------------------------------- */
- +
- +#define FRAME_POINTER_REQUIRED 0
- +
- +#define ELIMINABLE_REGS \
- +{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- + { ARG_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
- + { RETURN_ADDRESS_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- + { RETURN_ADDRESS_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}, \
- + { FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- + { FRAME_POINTER_REGNUM, HARD_FRAME_POINTER_REGNUM}}
- +
- +#define CAN_ELIMINATE(FROM, TO) 1
- +
- +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
- + (OFFSET) = nios2_initial_elimination_offset ((FROM), (TO))
- +
- +#define MUST_SAVE_REGISTER(regno) \
- + ((regs_ever_live[regno] && !call_used_regs[regno]) \
- + || (regno == HARD_FRAME_POINTER_REGNUM && frame_pointer_needed) \
- + || (regno == RA_REGNO && regs_ever_live[RA_REGNO]))
- +
- +/* Treat LOC as a byte offset from the stack pointer and round it up
- + to the next fully-aligned offset. */
- +#define STACK_ALIGN(LOC) \
- + (((LOC) + ((PREFERRED_STACK_BOUNDARY / 8) - 1)) & ~((PREFERRED_STACK_BOUNDARY / 8) - 1))
- +
- +
- +/* ------------------------------ *
- + * Passing Arguments in Registers
- + * ------------------------------ */
- +
- +/* see nios2.c */
- +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- + (function_arg (&CUM, MODE, TYPE, NAMED))
- +
- +#define MUST_PASS_IN_STACK(MODE, TYPE) \
- + nios2_must_pass_in_stack ((MODE), (TYPE))
- +
- +#define FUNCTION_ARG_PARTIAL_NREGS(CUM, MODE, TYPE, NAMED) \
- + (function_arg_partial_nregs (&CUM, MODE, TYPE, NAMED))
- +
- +#define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) 0
- +
- +#define FUNCTION_ARG_CALLEE_COPIES(CUM, MODE, TYPE, NAMED) 0
- +
- +typedef struct nios2_args
- +{
- + int regs_used;
- +} CUMULATIVE_ARGS;
- +
- +/* This is to initialize the above unused CUM data type */
- +#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS) \
- + (init_cumulative_args (&CUM, FNTYPE, LIBNAME, FNDECL, N_NAMED_ARGS))
- +
- +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- + (function_arg_advance (&CUM, MODE, TYPE, NAMED))
- +
- +#define FUNCTION_ARG_PADDING(MODE, TYPE) \
- + (nios2_function_arg_padding_upward ((MODE), (TYPE)) ? upward : downward)
- +
- +#define PAD_VARARGS_DOWN \
- + (FUNCTION_ARG_PADDING (TYPE_MODE (type), type) == downward)
- +
- +#define BLOCK_REG_PADDING(MODE, TYPE, FIRST) \
- + (nios2_block_reg_padding_upward ((MODE), (TYPE), (FIRST)) ? upward : downward)
- +
- +#define FUNCTION_ARG_REGNO_P(REGNO) \
- + ((REGNO) >= FIRST_ARG_REGNO && (REGNO) <= LAST_ARG_REGNO)
- +
- +#define SETUP_INCOMING_VARARGS(CUM,MODE,TYPE,PRETEND_SIZE,NO_RTL) \
- + { \
- + int pret_size = nios2_setup_incoming_varargs (&(CUM), (MODE), \
- + (TYPE), (NO_RTL)); \
- + if (pret_size) \
- + (PRETEND_SIZE) = pret_size; \
- + }
- +
- +/* ----------------------------- *
- + * Generating Code for Profiling
- + * ----------------------------- */
- +
- +
- +#define PROFILE_BEFORE_PROLOGUE
- +#define NO_PROFILE_COUNTERS 1
- +#define FUNCTION_PROFILER(FILE, LABELNO) \
- + function_profiler ((FILE), (LABELNO))
- +
- +/* --------------------------------------- *
- + * Passing Function Arguments on the Stack
- + * --------------------------------------- */
- +
- +#define PROMOTE_PROTOTYPES 1
- +
- +#define PUSH_ARGS 0
- +#define ACCUMULATE_OUTGOING_ARGS 1
- +
- +#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACKSIZE) 0
- +
- +/* --------------------------------------- *
- + * How Scalar Function Values Are Returned
- + * --------------------------------------- */
- +
- +#define FUNCTION_VALUE(VALTYPE, FUNC) \
- + gen_rtx(REG, TYPE_MODE(VALTYPE), FIRST_RETVAL_REGNO)
- +
- +#define LIBCALL_VALUE(MODE) \
- + gen_rtx(REG, MODE, FIRST_RETVAL_REGNO)
- +
- +#define FUNCTION_VALUE_REGNO_P(REGNO) ((REGNO) == FIRST_RETVAL_REGNO)
- +
- +/* ----------------------------- *
- + * How Large Values Are Returned
- + * ----------------------------- */
- +
- +
- +#define RETURN_IN_MEMORY(TYPE) \
- + nios2_return_in_memory (TYPE)
- +
- +
- +#define STRUCT_VALUE 0
- +
- +#define DEFAULT_PCC_STRUCT_RETURN 0
- +
- +/*******************
- + * Addressing Modes
- + *******************/
- +
- +
- +#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN)
- +
- +#define CONSTANT_ADDRESS_P(X) (CONSTANT_P (X))
- +
- +#define MAX_REGS_PER_ADDRESS 1
- +
- +/* Go to ADDR if X is a valid address. */
- +#ifndef REG_OK_STRICT
- +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
- + { \
- + if (nios2_legitimate_address ((X), (MODE), 0)) \
- + goto ADDR; \
- + }
- +#else
- +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
- + { \
- + if (nios2_legitimate_address ((X), (MODE), 1)) \
- + goto ADDR; \
- + }
- +#endif
- +
- +#ifndef REG_OK_STRICT
- +#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P2 (REGNO (X), 0)
- +#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P2 (REGNO (X), 0)
- +#else
- +#define REG_OK_FOR_BASE_P(X) REGNO_OK_FOR_BASE_P2 (REGNO (X), 1)
- +#define REG_OK_FOR_INDEX_P(X) REGNO_OK_FOR_INDEX_P2 (REGNO (X), 1)
- +#endif
- +
- +#define LEGITIMATE_CONSTANT_P(X) 1
- +
- +/* Nios II has no mode dependent addresses. */
- +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL)
- +
- +/* Set if this has a weak declaration */
- +#define SYMBOL_FLAG_WEAK_DECL (1 << SYMBOL_FLAG_MACH_DEP_SHIFT)
- +#define SYMBOL_REF_WEAK_DECL_P(RTX) \
- + ((SYMBOL_REF_FLAGS (RTX) & SYMBOL_FLAG_WEAK_DECL) != 0)
- +
- +
- +/* true if a symbol is both small and not weak. In this case, gp
- + relative access can be used */
- +#define SYMBOL_REF_IN_NIOS2_SMALL_DATA_P(RTX) \
- + (SYMBOL_REF_SMALL_P(RTX) && !SYMBOL_REF_WEAK_DECL_P(RTX))
- +
- +/*****************
- + * Describing Relative Costs of Operations
- + *****************/
- +
- +#define SLOW_BYTE_ACCESS 1
- +
- +/* It is as good to call a constant function address as to call an address
- + kept in a register.
- + ??? Not true anymore really. Now that call cannot address full range
- + of memory callr may need to be used */
- +
- +#define NO_FUNCTION_CSE
- +#define NO_RECURSIVE_FUNCTION_CSE
- +
- +
- +
- +/*****************************************
- + * Defining the Output Assembler Language
- + *****************************************/
- +
- +/* ------------------------------------------ *
- + * The Overall Framework of an Assembler File
- + * ------------------------------------------ */
- +
- +#define ASM_APP_ON "#APP\n"
- +#define ASM_APP_OFF "#NO_APP\n"
- +
- +#define ASM_COMMENT_START "# "
- +
- +/* ------------------------------- *
- + * Output and Generation of Labels
- + * ------------------------------- */
- +
- +#define GLOBAL_ASM_OP "\t.global\t"
- +
- +
- +/* -------------- *
- + * Output of Data
- + * -------------- */
- +
- +#define DWARF2_UNWIND_INFO 0
- +
- +
- +/* -------------------------------- *
- + * Assembler Commands for Alignment
- + * -------------------------------- */
- +
- +#define ASM_OUTPUT_ALIGN(FILE, LOG) \
- + do { \
- + fprintf ((FILE), "%s%d\n", ALIGN_ASM_OP, (LOG)); \
- + } while (0)
- +
- +
- +/* -------------------------------- *
- + * Output of Assembler Instructions
- + * -------------------------------- */
- +
- +#define REGISTER_NAMES \
- +{ \
- + "zero", \
- + "at", \
- + "r2", \
- + "r3", \
- + "r4", \
- + "r5", \
- + "r6", \
- + "r7", \
- + "r8", \
- + "r9", \
- + "r10", \
- + "r11", \
- + "r12", \
- + "r13", \
- + "r14", \
- + "r15", \
- + "r16", \
- + "r17", \
- + "r18", \
- + "r19", \
- + "r20", \
- + "r21", \
- + "r22", \
- + "r23", \
- + "et", \
- + "bt", \
- + "gp", \
- + "sp", \
- + "fp", \
- + "ta", \
- + "ba", \
- + "ra", \
- + "status", \
- + "estatus", \
- + "bstatus", \
- + "ipri", \
- + "ecause", \
- + "pc", \
- + "rap", \
- + "fake_fp", \
- + "fake_ap", \
- +}
- +
- +#define ADDITIONAL_REGISTER_NAMES \
- +{ \
- + {"r0", 0}, \
- + {"r1", 1}, \
- + {"r24", 24}, \
- + {"r25", 25}, \
- + {"r26", 26}, \
- + {"r27", 27}, \
- + {"r28", 28}, \
- + {"r29", 29}, \
- + {"r30", 30}, \
- + {"r31", 31} \
- +}
- +
- +
- +#define ASM_OUTPUT_OPCODE(STREAM, PTR)\
- + (PTR) = asm_output_opcode (STREAM, PTR)
- +
- +#define PRINT_OPERAND(STREAM, X, CODE) \
- + nios2_print_operand (STREAM, X, CODE)
- +
- +#define PRINT_OPERAND_ADDRESS(STREAM, X) \
- + nios2_print_operand_address (STREAM, X)
- +
- +#define ASM_OUTPUT_ADDR_VEC_ELT(FILE, VALUE) \
- +do { fputs (integer_asm_op (POINTER_SIZE / BITS_PER_UNIT, TRUE), FILE); \
- + fprintf (FILE, ".L%u\n", (unsigned) (VALUE)); \
- + } while (0)
- +
- +
- +/* ------------ *
- + * Label Output
- + * ------------ */
- +
- +
- +/* ---------------------------------------------------- *
- + * Dividing the Output into Sections (Texts, Data, ...)
- + * ---------------------------------------------------- */
- +
- +/* Output before read-only data. */
- +#define TEXT_SECTION_ASM_OP ("\t.section\t.text")
- +
- +/* Output before writable data. */
- +#define DATA_SECTION_ASM_OP ("\t.section\t.data")
- +
- +
- +/* Default the definition of "small data" to 8 bytes. */
- +/* ??? How come I can't use HOST_WIDE_INT here? */
- +extern unsigned long nios2_section_threshold;
- +#define NIOS2_DEFAULT_GVALUE 8
- +
- +
- +
- +/* This says how to output assembler code to declare an
- + uninitialized external linkage data object. Under SVR4,
- + the linker seems to want the alignment of data objects
- + to depend on their types. We do exactly that here. */
- +
- +#undef COMMON_ASM_OP
- +#define COMMON_ASM_OP "\t.comm\t"
- +
- +#undef ASM_OUTPUT_ALIGNED_COMMON
- +#define ASM_OUTPUT_ALIGNED_COMMON(FILE, NAME, SIZE, ALIGN) \
- +do \
- +{ \
- + if ((SIZE) <= nios2_section_threshold) \
- + { \
- + named_section (0, ".sbss", 0); \
- + (*targetm.asm_out.globalize_label) (FILE, NAME); \
- + ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
- + if (!flag_inhibit_size_directive) \
- + ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE); \
- + ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT)); \
- + ASM_OUTPUT_LABEL(FILE, NAME); \
- + ASM_OUTPUT_SKIP((FILE), (SIZE) ? (SIZE) : 1); \
- + } \
- + else \
- + { \
- + fprintf ((FILE), "%s", COMMON_ASM_OP); \
- + assemble_name ((FILE), (NAME)); \
- + fprintf ((FILE), ","HOST_WIDE_INT_PRINT_UNSIGNED",%u\n", (SIZE), (ALIGN) / BITS_PER_UNIT); \
- + } \
- +} \
- +while (0)
- +
- +
- +/* This says how to output assembler code to declare an
- + uninitialized internal linkage data object. Under SVR4,
- + the linker seems to want the alignment of data objects
- + to depend on their types. We do exactly that here. */
- +
- +#undef ASM_OUTPUT_ALIGNED_LOCAL
- +#define ASM_OUTPUT_ALIGNED_LOCAL(FILE, NAME, SIZE, ALIGN) \
- +do { \
- + if ((SIZE) <= nios2_section_threshold) \
- + named_section (0, ".sbss", 0); \
- + else \
- + named_section (0, ".bss", 0); \
- + ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "object"); \
- + if (!flag_inhibit_size_directive) \
- + ASM_OUTPUT_SIZE_DIRECTIVE (FILE, NAME, SIZE); \
- + ASM_OUTPUT_ALIGN ((FILE), exact_log2((ALIGN) / BITS_PER_UNIT)); \
- + ASM_OUTPUT_LABEL(FILE, NAME); \
- + ASM_OUTPUT_SKIP((FILE), (SIZE) ? (SIZE) : 1); \
- +} while (0)
- +
- +
- +
- +/***************************
- + * Miscellaneous Parameters
- + ***************************/
- +
- +#define MOVE_MAX 4
- +
- +#define STORE_FLAG_VALUE 1
- +#define Pmode SImode
- +#define FUNCTION_MODE QImode
- +
- +#define REGISTER_TARGET_PRAGMAS() nios2_register_target_pragmas ();
- +
- +#define CASE_VECTOR_MODE Pmode
- +
- +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
- +
- +#define LOAD_EXTEND_OP(MODE) (ZERO_EXTEND)
- +
- +#define WORD_REGISTER_OPERATIONS
- diff --git a/gcc/config/nios2/nios2.md b/gcc/config/nios2/nios2.md
- new file mode 100644
- index 0000000..6183247
- --- /dev/null
- +++ b/gcc/config/nios2/nios2.md
- @@ -0,0 +1,2867 @@
- +;; Machine Description for Altera NIOS 2G NIOS2 version.
- +;; Copyright (C) 2005 Altera
- +;; Contributed by Jonah Graham (jgraham@altera.com) and Will Reece (wreece@altera.com).
- +;;
- +;; This file is part of GNU CC.
- +;;
- +;; GNU CC 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 2, or (at your option)
- +;; any later version.
- +;;
- +;; GNU CC 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 GNU CC; see the file COPYING. If not, write to
- +;; the Free Software Foundation, 59 Temple Place - Suite 330,
- +;; Boston, MA 02111-1307, USA. */
- +
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* constraint strings
- +;*
- +;*****************************************************************************
- +;
- +; We use the following constraint letters for constants
- +;
- +; I: -32768 to -32767
- +; J: 0 to 65535
- +; K: $nnnn0000 for some nnnn
- +; L: 0 to 31 (for shift counts)
- +; M: 0
- +; N: 0 to 255 (for custom instruction numbers)
- +; O: 0 to 31 (for control register numbers)
- +;
- +; We use the following built-in register classes:
- +;
- +; r: general purpose register (r0..r31)
- +; m: memory operand
- +;
- +; Plus, we define the following constraint strings:
- +;
- +; S: symbol that is in the "small data" area
- +; Dnn: Dnn_REG (just rnn)
- +;
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* constants
- +;*
- +;*****************************************************************************
- +(define_constants [
- + (ET_REGNO 24)
- + (GP_REGNO 26)
- + (SP_REGNO 27)
- + (FP_REGNO 28)
- + (RA_REGNO 31)
- + (RAP_REGNO 38)
- + (FIRST_RETVAL_REGNO 2)
- + (LAST_RETVAL_REGNO 3)
- + (FIRST_ARG_REGNO 4)
- + (LAST_ARG_REGNO 7)
- + (SC_REGNO 23)
- + (PC_REGNO 37)
- + (FAKE_FP_REGNO 39)
- + (FAKE_AP_REGNO 40)
- +
- +
- + (UNSPEC_BLOCKAGE 0)
- + (UNSPEC_LDBIO 1)
- + (UNSPEC_LDBUIO 2)
- + (UNSPEC_LDHIO 3)
- + (UNSPEC_LDHUIO 4)
- + (UNSPEC_LDWIO 5)
- + (UNSPEC_STBIO 6)
- + (UNSPEC_STHIO 7)
- + (UNSPEC_STWIO 8)
- + (UNSPEC_SYNC 9)
- + (UNSPEC_WRCTL 10)
- + (UNSPEC_RDCTL 11)
- + (UNSPEC_TRAP 12)
- + (UNSPEC_STACK_OVERFLOW_DETECT_AND_TRAP 13)
- + (UNSPEC_FCOSS 14)
- + (UNSPEC_FCOSD 15)
- + (UNSPEC_FSINS 16)
- + (UNSPEC_FSIND 17)
- + (UNSPEC_FTANS 18)
- + (UNSPEC_FTAND 19)
- + (UNSPEC_FATANS 20)
- + (UNSPEC_FATAND 21)
- + (UNSPEC_FEXPS 22)
- + (UNSPEC_FEXPD 23)
- + (UNSPEC_FLOGS 24)
- + (UNSPEC_FLOGD 25)
- + (UNSPEC_FWRX 26)
- + (UNSPEC_FWRY 27)
- + (UNSPEC_FRDXLO 28)
- + (UNSPEC_FRDXHI 29)
- + (UNSPEC_FRDY 30)
- + ;; Note that values 100..151 are used by custom instructions, see below.
- +])
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* instruction scheduler
- +;*
- +;*****************************************************************************
- +
- +; No schedule info is currently available, using an assumption that no
- +; instruction can use the results of the previous instruction without
- +; incuring a stall.
- +
- +; length of an instruction (in bytes)
- +(define_attr "length" "" (const_int 4))
- +(define_attr "type" "unknown,complex,control,alu,cond_alu,st,ld,shift,mul,div,custom" (const_string "complex"))
- +
- +(define_asm_attributes
- + [(set_attr "length" "4")
- + (set_attr "type" "complex")])
- +
- +(define_automaton "nios2")
- +(automata_option "v")
- +;(automata_option "no-minimization")
- +(automata_option "ndfa")
- +
- +; The nios2 pipeline is fairly straightforward for the fast model.
- +; Every alu operation is pipelined so that an instruction can
- +; be issued every cycle. However, there are still potential
- +; stalls which this description tries to deal with.
- +
- +(define_cpu_unit "cpu" "nios2")
- +
- +(define_insn_reservation "complex" 1
- + (eq_attr "type" "complex")
- + "cpu")
- +
- +(define_insn_reservation "control" 1
- + (eq_attr "type" "control")
- + "cpu")
- +
- +(define_insn_reservation "alu" 1
- + (eq_attr "type" "alu")
- + "cpu")
- +
- +(define_insn_reservation "cond_alu" 1
- + (eq_attr "type" "cond_alu")
- + "cpu")
- +
- +(define_insn_reservation "st" 1
- + (eq_attr "type" "st")
- + "cpu")
- +
- +(define_insn_reservation "custom" 1
- + (eq_attr "type" "custom")
- + "cpu")
- +
- +; shifts, muls and lds have three cycle latency
- +(define_insn_reservation "ld" 3
- + (eq_attr "type" "ld")
- + "cpu")
- +
- +(define_insn_reservation "shift" 3
- + (eq_attr "type" "shift")
- + "cpu")
- +
- +(define_insn_reservation "mul" 3
- + (eq_attr "type" "mul")
- + "cpu")
- +
- +(define_insn_reservation "div" 1
- + (eq_attr "type" "div")
- + "cpu")
- +
- +
- +;*****************************************************************************
- +;*
- +;* MOV Instructions
- +;*
- +;*****************************************************************************
- +
- +(define_expand "movqi"
- + [(set (match_operand:QI 0 "nonimmediate_operand" "")
- + (match_operand:QI 1 "general_operand" ""))]
- + ""
- +{
- + if (nios2_emit_move_sequence (operands, QImode))
- + DONE;
- +})
- +
- +(define_insn "movqi_internal"
- + [(set (match_operand:QI 0 "nonimmediate_operand" "=m, r,r, r")
- + (match_operand:QI 1 "general_operand" "rM,m,rM,I"))]
- + "(register_operand (operands[0], QImode)
- + || reg_or_0_operand (operands[1], QImode))"
- + "@
- + stb%o0\\t%z1, %0
- + ldbu%o1\\t%0, %1
- + mov\\t%0, %z1
- + movi\\t%0, %1"
- + [(set_attr "type" "st,ld,alu,alu")])
- +
- +(define_insn "ldbio"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(const_int 0)] UNSPEC_LDBIO))
- + (use (match_operand:SI 1 "memory_operand" "m"))]
- + ""
- + "ldbio\\t%0, %1"
- + [(set_attr "type" "ld")])
- +
- +(define_insn "ldbuio"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(const_int 0)] UNSPEC_LDBUIO))
- + (use (match_operand:SI 1 "memory_operand" "m"))]
- + ""
- + "ldbuio\\t%0, %1"
- + [(set_attr "type" "ld")])
- +
- +(define_insn "stbio"
- + [(set (match_operand:SI 0 "memory_operand" "=m")
- + (match_operand:SI 1 "reg_or_0_operand" "rM"))
- + (unspec_volatile:SI [(const_int 0)] UNSPEC_STBIO)]
- + ""
- + "stbio\\t%z1, %0"
- + [(set_attr "type" "st")])
- +
- +
- +(define_expand "movhi"
- + [(set (match_operand:HI 0 "nonimmediate_operand" "")
- + (match_operand:HI 1 "general_operand" ""))]
- + ""
- +{
- + if (nios2_emit_move_sequence (operands, HImode))
- + DONE;
- +})
- +
- +(define_insn "movhi_internal"
- + [(set (match_operand:HI 0 "nonimmediate_operand" "=m, r,r, r,r")
- + (match_operand:HI 1 "general_operand" "rM,m,rM,I,J"))]
- + "(register_operand (operands[0], HImode)
- + || reg_or_0_operand (operands[1], HImode))"
- + "@
- + sth%o0\\t%z1, %0
- + ldhu%o1\\t%0, %1
- + mov\\t%0, %z1
- + movi\\t%0, %1
- + movui\\t%0, %1"
- + [(set_attr "type" "st,ld,alu,alu,alu")])
- +
- +(define_insn "ldhio"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(const_int 0)] UNSPEC_LDHIO))
- + (use (match_operand:SI 1 "memory_operand" "m"))]
- + ""
- + "ldhio\\t%0, %1"
- + [(set_attr "type" "ld")])
- +
- +(define_insn "ldhuio"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(const_int 0)] UNSPEC_LDHUIO))
- + (use (match_operand:SI 1 "memory_operand" "m"))]
- + ""
- + "ldhuio\\t%0, %1"
- + [(set_attr "type" "ld")])
- +
- +(define_insn "sthio"
- + [(set (match_operand:SI 0 "memory_operand" "=m")
- + (match_operand:SI 1 "reg_or_0_operand" "rM"))
- + (unspec_volatile:SI [(const_int 0)] UNSPEC_STHIO)]
- + ""
- + "sthio\\t%z1, %0"
- + [(set_attr "type" "st")])
- +
- +(define_expand "movsi"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "")
- + (match_operand:SI 1 "general_operand" ""))]
- + ""
- +{
- + if (nios2_emit_move_sequence (operands, SImode))
- + DONE;
- +})
- +
- +(define_insn "movsi_internal"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=m, r,r, r,r,r,r")
- + (match_operand:SI 1 "general_operand" "rM,m,rM,I,J,S,i"))]
- + "(register_operand (operands[0], SImode)
- + || reg_or_0_operand (operands[1], SImode))"
- + "@
- + stw%o0\\t%z1, %0
- + ldw%o1\\t%0, %1
- + mov\\t%0, %z1
- + movi\\t%0, %1
- + movui\\t%0, %1
- + addi\\t%0, gp, %%gprel(%1)
- + movhi\\t%0, %H1\;addi\\t%0, %0, %L1"
- + [(set_attr "type" "st,ld,alu,alu,alu,alu,alu")])
- +
- +(define_insn "ldwio"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(const_int 0)] UNSPEC_LDWIO))
- + (use (match_operand:SI 1 "memory_operand" "m"))]
- + ""
- + "ldwio\\t%0, %1"
- + [(set_attr "type" "ld")])
- +
- +(define_insn "stwio"
- + [(set (match_operand:SI 0 "memory_operand" "=m")
- + (match_operand:SI 1 "reg_or_0_operand" "rM"))
- + (unspec_volatile:SI [(const_int 0)] UNSPEC_STWIO)]
- + ""
- + "stwio\\t%z1, %0"
- + [(set_attr "type" "st")])
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* zero extension
- +;*
- +;*****************************************************************************
- +
- +
- +(define_insn "zero_extendhisi2"
- + [(set (match_operand:SI 0 "register_operand" "=r,r")
- + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
- + ""
- + "@
- + andi\\t%0, %1, 0xffff
- + ldhu%o1\\t%0, %1"
- + [(set_attr "type" "alu,ld")])
- +
- +(define_insn "zero_extendqihi2"
- + [(set (match_operand:HI 0 "register_operand" "=r,r")
- + (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
- + ""
- + "@
- + andi\\t%0, %1, 0xff
- + ldbu%o1\\t%0, %1"
- + [(set_attr "type" "alu,ld")])
- +
- +(define_insn "zero_extendqisi2"
- + [(set (match_operand:SI 0 "register_operand" "=r,r")
- + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "r,m")))]
- + ""
- + "@
- + andi\\t%0, %1, 0xff
- + ldbu%o1\\t%0, %1"
- + [(set_attr "type" "alu,ld")])
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* sign extension
- +;*
- +;*****************************************************************************
- +(define_expand "extendhisi2"
- + [(set (match_operand:SI 0 "register_operand" "")
- + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
- + ""
- +{
- +})
- +
- +(define_insn "*extendhisi2"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (sign_extend:SI (match_operand:HI 1 "register_operand" "r")))]
- + ""
- + "#")
- +
- +(define_split
- + [(set (match_operand:SI 0 "register_operand" "")
- + (sign_extend:SI (match_operand:HI 1 "register_operand" "")))]
- + "reload_completed"
- + [(set (match_dup 0)
- + (and:SI (match_dup 1) (const_int 65535)))
- + (set (match_dup 0)
- + (xor:SI (match_dup 0) (const_int 32768)))
- + (set (match_dup 0)
- + (plus:SI (match_dup 0) (const_int -32768)))]
- + "operands[1] = gen_lowpart (SImode, operands[1]);")
- +
- +(define_insn "extendhisi2_internal"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (sign_extend:SI (match_operand:HI 1 "memory_operand" "m")))]
- + ""
- + "ldh%o1\\t%0, %1"
- + [(set_attr "type" "ld")])
- +
- +
- +(define_expand "extendqihi2"
- + [(set (match_operand:HI 0 "register_operand" "")
- + (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))]
- + ""
- +{
- +})
- +
- +(define_insn "*extendqihi2"
- + [(set (match_operand:HI 0 "register_operand" "=r")
- + (sign_extend:HI (match_operand:QI 1 "register_operand" "r")))]
- + ""
- + "#")
- +
- +(define_split
- + [(set (match_operand:HI 0 "register_operand" "")
- + (sign_extend:HI (match_operand:QI 1 "register_operand" "")))]
- + "reload_completed"
- + [(set (match_dup 0)
- + (and:SI (match_dup 1) (const_int 255)))
- + (set (match_dup 0)
- + (xor:SI (match_dup 0) (const_int 128)))
- + (set (match_dup 0)
- + (plus:SI (match_dup 0) (const_int -128)))]
- + "operands[0] = gen_lowpart (SImode, operands[0]);
- + operands[1] = gen_lowpart (SImode, operands[1]);")
- +
- +
- +
- +(define_insn "extendqihi2_internal"
- + [(set (match_operand:HI 0 "register_operand" "=r")
- + (sign_extend:HI (match_operand:QI 1 "memory_operand" "m")))]
- + ""
- + "ldb%o1\\t%0, %1"
- + [(set_attr "type" "ld")])
- +
- +
- +(define_expand "extendqisi2"
- + [(set (match_operand:SI 0 "register_operand" "")
- + (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
- + ""
- +{
- +})
- +
- +(define_insn "*extendqisi2"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (sign_extend:SI (match_operand:QI 1 "register_operand" "r")))]
- + ""
- + "#")
- +
- +(define_split
- + [(set (match_operand:SI 0 "register_operand" "")
- + (sign_extend:SI (match_operand:QI 1 "register_operand" "")))]
- + "reload_completed"
- + [(set (match_dup 0)
- + (and:SI (match_dup 1) (const_int 255)))
- + (set (match_dup 0)
- + (xor:SI (match_dup 0) (const_int 128)))
- + (set (match_dup 0)
- + (plus:SI (match_dup 0) (const_int -128)))]
- + "operands[1] = gen_lowpart (SImode, operands[1]);")
- +
- +(define_insn "extendqisi2_insn"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (sign_extend:SI (match_operand:QI 1 "memory_operand" "m")))]
- + ""
- + "ldb%o1\\t%0, %1"
- + [(set_attr "type" "ld")])
- +
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* Arithmetic Operations
- +;*
- +;*****************************************************************************
- +
- +(define_insn "addsi3"
- + [(set (match_operand:SI 0 "register_operand" "=r,r")
- + (plus:SI (match_operand:SI 1 "register_operand" "%r,r")
- + (match_operand:SI 2 "arith_operand" "r,I")))]
- + ""
- + "add%i2\\t%0, %1, %z2"
- + [(set_attr "type" "alu")])
- +
- +(define_insn "addsf3"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (plus:SF (match_operand:SF 1 "register_operand" "%r")
- + (match_operand:SF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_addsf3].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_addsf3].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "adddf3"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (plus:DF (match_operand:DF 1 "register_operand" "%r")
- + (match_operand:DF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_adddf3].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_adddf3].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "subsi3"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (minus:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
- + (match_operand:SI 2 "register_operand" "r")))]
- + ""
- + "sub\\t%0, %z1, %2"
- + [(set_attr "type" "alu")])
- +
- +(define_insn "subsf3"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (minus:SF (match_operand:SF 1 "register_operand" "r")
- + (match_operand:SF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_subsf3].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_subsf3].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "subdf3"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (minus:DF (match_operand:DF 1 "register_operand" "r")
- + (match_operand:DF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_subdf3].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_subdf3].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "mulsi3"
- + [(set (match_operand:SI 0 "register_operand" "=r,r")
- + (mult:SI (match_operand:SI 1 "register_operand" "r,r")
- + (match_operand:SI 2 "arith_operand" "r,I")))]
- + "TARGET_HAS_MUL"
- + "mul%i2\\t%0, %1, %z2"
- + [(set_attr "type" "mul")])
- +
- +(define_insn "mulsf3"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (mult:SF (match_operand:SF 1 "register_operand" "%r")
- + (match_operand:SF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_mulsf3].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_mulsf3].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "muldf3"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (mult:DF (match_operand:DF 1 "register_operand" "%r")
- + (match_operand:DF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_muldf3].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_muldf3].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_expand "divsi3"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (div:SI (match_operand:SI 1 "register_operand" "r")
- + (match_operand:SI 2 "register_operand" "r")))]
- + ""
- +{
- + if (!TARGET_HAS_DIV)
- + {
- + if (!TARGET_FAST_SW_DIV)
- + FAIL;
- + else
- + {
- + if (nios2_emit_expensive_div (operands, SImode))
- + DONE;
- + }
- + }
- +})
- +
- +(define_insn "divsi3_insn"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (div:SI (match_operand:SI 1 "register_operand" "r")
- + (match_operand:SI 2 "register_operand" "r")))]
- + "TARGET_HAS_DIV"
- + "div\\t%0, %1, %2"
- + [(set_attr "type" "div")])
- +
- +(define_insn "divsf3"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (div:SF (match_operand:SF 1 "register_operand" "r")
- + (match_operand:SF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_divsf3].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_divsf3].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "divdf3"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (div:DF (match_operand:DF 1 "register_operand" "r")
- + (match_operand:DF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_divdf3].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_divdf3].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "udivsi3"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (udiv:SI (match_operand:SI 1 "register_operand" "r")
- + (match_operand:SI 2 "register_operand" "r")))]
- + "TARGET_HAS_DIV"
- + "divu\\t%0, %1, %2"
- + [(set_attr "type" "div")])
- +
- +(define_insn "smulsi3_highpart"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (truncate:SI
- + (lshiftrt:DI
- + (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "r"))
- + (sign_extend:DI (match_operand:SI 2 "register_operand" "r")))
- + (const_int 32))))]
- + "TARGET_HAS_MULX"
- + "mulxss\\t%0, %1, %2"
- + [(set_attr "type" "mul")])
- +
- +(define_insn "umulsi3_highpart"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (truncate:SI
- + (lshiftrt:DI
- + (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "r"))
- + (zero_extend:DI (match_operand:SI 2 "register_operand" "r")))
- + (const_int 32))))]
- + "TARGET_HAS_MULX"
- + "mulxuu\\t%0, %1, %2"
- + [(set_attr "type" "mul")])
- +
- +
- +(define_expand "mulsidi3_little_endian"
- + [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
- + (mult:SI (match_operand:SI 1 "register_operand" "")
- + (match_operand:SI 2 "register_operand" "")))
- + (set (subreg:SI (match_dup 0) 4)
- + (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
- + (sign_extend:DI (match_dup 2)))
- + (const_int 32))))]
- + "TARGET_HAS_MULX && !WORDS_BIG_ENDIAN"
- + "")
- +
- +(define_expand "mulsidi3_big_endian"
- + [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 4)
- + (mult:SI (match_operand:SI 1 "register_operand" "")
- + (match_operand:SI 2 "register_operand" "")))
- + (set (subreg:SI (match_dup 0) 0)
- + (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1))
- + (sign_extend:DI (match_dup 2)))
- + (const_int 32))))]
- + "TARGET_HAS_MULX && WORDS_BIG_ENDIAN"
- + "")
- +
- +(define_expand "mulsidi3"
- + [(match_operand:DI 0 "register_operand" "")
- + (match_operand:SI 1 "register_operand" "")
- + (match_operand:SI 2 "register_operand" "")]
- + "TARGET_HAS_MULX"
- + {
- + if (WORDS_BIG_ENDIAN)
- + {
- + emit_insn (gen_mulsidi3_big_endian (operands[0],
- + operands[1],
- + operands[2]));
- + }
- + else
- + {
- + emit_insn (gen_mulsidi3_little_endian (operands[0],
- + operands[1],
- + operands[2]));
- + }
- + DONE;
- + })
- +
- +(define_expand "umulsidi3_little_endian"
- + [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 0)
- + (mult:SI (match_operand:SI 1 "register_operand" "")
- + (match_operand:SI 2 "register_operand" "")))
- + (set (subreg:SI (match_dup 0) 4)
- + (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
- + (zero_extend:DI (match_dup 2)))
- + (const_int 32))))]
- + "TARGET_HAS_MULX && !WORDS_BIG_ENDIAN"
- + "")
- +
- +(define_expand "umulsidi3_big_endian"
- + [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 4)
- + (mult:SI (match_operand:SI 1 "register_operand" "")
- + (match_operand:SI 2 "register_operand" "")))
- + (set (subreg:SI (match_dup 0) 0)
- + (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1))
- + (zero_extend:DI (match_dup 2)))
- + (const_int 32))))]
- + "TARGET_HAS_MULX && WORDS_BIG_ENDIAN"
- + "")
- +
- +(define_expand "umulsidi3"
- + [(match_operand:DI 0 "register_operand" "")
- + (match_operand:SI 1 "register_operand" "")
- + (match_operand:SI 2 "register_operand" "")]
- + "TARGET_HAS_MULX"
- + {
- + if (WORDS_BIG_ENDIAN)
- + {
- + emit_insn (gen_umulsidi3_big_endian (operands[0],
- + operands[1],
- + operands[2]));
- + }
- + else
- + {
- + emit_insn (gen_umulsidi3_little_endian (operands[0],
- + operands[1],
- + operands[2]));
- + }
- + DONE;
- + })
- +
- +
- +;*****************************************************************************
- +;*
- +;* Negate and ones complement
- +;*
- +;*****************************************************************************
- +
- +(define_insn "negsi2"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (neg:SI (match_operand:SI 1 "register_operand" "r")))]
- + ""
- +{
- + operands[2] = const0_rtx;
- + return "sub\\t%0, %z2, %1";
- +}
- + [(set_attr "type" "alu")])
- +
- +(define_insn "negsf2"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (neg:SF (match_operand:SF 1 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_negsf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_negsf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "negdf2"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (neg:DF (match_operand:DF 1 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_negdf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_negdf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "one_cmplsi2"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (not:SI (match_operand:SI 1 "register_operand" "r")))]
- + ""
- +{
- + operands[2] = const0_rtx;
- + return "nor\\t%0, %z2, %1";
- +}
- + [(set_attr "type" "alu")])
- +
- +
- +;*****************************************************************************
- +;*
- +;* Miscellaneous floating point
- +;*
- +;*****************************************************************************
- +(define_insn "nios2_fwrx"
- + [(unspec_volatile [(match_operand:DF 0 "register_operand" "r")] UNSPEC_FWRX)]
- + "nios2_fpu_insns[nios2_fpu_nios2_fwrx].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_fwrx].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "nios2_fwry"
- + [(unspec_volatile [(match_operand:SF 0 "register_operand" "r")] UNSPEC_FWRY)]
- + "nios2_fpu_insns[nios2_fpu_nios2_fwry].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_fwry].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "nios2_frdxlo"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(const_int 0)] UNSPEC_FRDXLO))]
- + "nios2_fpu_insns[nios2_fpu_nios2_frdxlo].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_frdxlo].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "nios2_frdxhi"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(const_int 0)] UNSPEC_FRDXHI))]
- + "nios2_fpu_insns[nios2_fpu_nios2_frdxhi].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_frdxhi].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "nios2_frdy"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(const_int 0)] UNSPEC_FRDY))]
- + "nios2_fpu_insns[nios2_fpu_nios2_frdy].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_frdy].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "minsf3"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (if_then_else:SF (lt:SF (match_operand:SF 1 "register_operand" "%r")
- + (match_operand:SF 2 "register_operand" "r"))
- + (match_dup 1)
- + (match_dup 2)))]
- + "nios2_fpu_insns[nios2_fpu_minsf3].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_minsf3].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "mindf3"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (if_then_else:DF (lt:DF (match_operand:DF 1 "register_operand" "%r")
- + (match_operand:DF 2 "register_operand" "r"))
- + (match_dup 1)
- + (match_dup 2)))]
- + "nios2_fpu_insns[nios2_fpu_mindf3].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_mindf3].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "maxsf3"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (if_then_else:SF (lt:SF (match_operand:SF 1 "register_operand" "%r")
- + (match_operand:SF 2 "register_operand" "r"))
- + (match_dup 2)
- + (match_dup 1)))]
- + "nios2_fpu_insns[nios2_fpu_maxsf3].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_maxsf3].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "maxdf3"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (if_then_else:DF (lt:DF (match_operand:DF 1 "register_operand" "%r")
- + (match_operand:DF 2 "register_operand" "r"))
- + (match_dup 2)
- + (match_dup 1)))]
- + "nios2_fpu_insns[nios2_fpu_maxdf3].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_maxdf3].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "abssf2"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (abs:SF (match_operand:SF 1 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_abssf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_abssf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "absdf2"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (abs:DF (match_operand:DF 1 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_absdf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_absdf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "sqrtsf2"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (sqrt:SF (match_operand:SF 1 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_sqrtsf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_sqrtsf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "sqrtdf2"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (sqrt:DF (match_operand:DF 1 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_sqrtdf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_sqrtdf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "cossf2"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FCOSS))]
- + "nios2_fpu_insns[nios2_fpu_cossf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_cossf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "cosdf2"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FCOSD))]
- + "nios2_fpu_insns[nios2_fpu_cosdf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_cosdf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "sinsf2"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FSINS))]
- + "nios2_fpu_insns[nios2_fpu_sinsf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_sinsf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "sindf2"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FSIND))]
- + "nios2_fpu_insns[nios2_fpu_sindf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_sindf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "tansf2"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FTANS))]
- + "nios2_fpu_insns[nios2_fpu_tansf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_tansf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "tandf2"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FTAND))]
- + "nios2_fpu_insns[nios2_fpu_tandf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_tandf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "atansf2"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FATANS))]
- + "nios2_fpu_insns[nios2_fpu_atansf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_atansf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "atandf2"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FATAND))]
- + "nios2_fpu_insns[nios2_fpu_atandf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_atandf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "expsf2"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FEXPS))]
- + "nios2_fpu_insns[nios2_fpu_expsf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_expsf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "expdf2"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FEXPD))]
- + "nios2_fpu_insns[nios2_fpu_expdf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_expdf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "logsf2"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec:SF [(match_operand:SF 1 "register_operand" "r")] UNSPEC_FLOGS))]
- + "nios2_fpu_insns[nios2_fpu_logsf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_logsf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "logdf2"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (unspec:DF [(match_operand:DF 1 "register_operand" "r")] UNSPEC_FLOGD))]
- + "nios2_fpu_insns[nios2_fpu_logdf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_logdf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +;*****************************************************************************
- +;*
- +;* Logical Operantions
- +;*
- +;*****************************************************************************
- +
- +(define_insn "andsi3"
- + [(set (match_operand:SI 0 "register_operand" "=r, r,r")
- + (and:SI (match_operand:SI 1 "register_operand" "%r, r,r")
- + (match_operand:SI 2 "logical_operand" "rM,J,K")))]
- + ""
- + "@
- + and\\t%0, %1, %z2
- + and%i2\\t%0, %1, %2
- + andh%i2\\t%0, %1, %U2"
- + [(set_attr "type" "alu")])
- +
- +(define_insn "iorsi3"
- + [(set (match_operand:SI 0 "register_operand" "=r, r,r")
- + (ior:SI (match_operand:SI 1 "register_operand" "%r, r,r")
- + (match_operand:SI 2 "logical_operand" "rM,J,K")))]
- + ""
- + "@
- + or\\t%0, %1, %z2
- + or%i2\\t%0, %1, %2
- + orh%i2\\t%0, %1, %U2"
- + [(set_attr "type" "alu")])
- +
- +(define_insn "*norsi3"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (and:SI (not:SI (match_operand:SI 1 "register_operand" "%r"))
- + (not:SI (match_operand:SI 2 "reg_or_0_operand" "rM"))))]
- + ""
- + "nor\\t%0, %1, %z2"
- + [(set_attr "type" "alu")])
- +
- +(define_insn "xorsi3"
- + [(set (match_operand:SI 0 "register_operand" "=r, r,r")
- + (xor:SI (match_operand:SI 1 "register_operand" "%r, r,r")
- + (match_operand:SI 2 "logical_operand" "rM,J,K")))]
- + ""
- + "@
- + xor\\t%0, %1, %z2
- + xor%i2\\t%0, %1, %2
- + xorh%i2\\t%0, %1, %U2"
- + [(set_attr "type" "alu")])
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* Shifts
- +;*
- +;*****************************************************************************
- +
- +(define_insn "ashlsi3"
- + [(set (match_operand:SI 0 "register_operand" "=r,r")
- + (ashift:SI (match_operand:SI 1 "register_operand" "r,r")
- + (match_operand:SI 2 "shift_operand" "r,L")))]
- + ""
- +
- +{
- + if( GET_CODE ( operands[2] ) == CONST_INT && INTVAL( operands[2] ) == 1 )
- + return "add\t%0,%1,%1";
- + return "sll%i2\t%0,%1,%z2";
- +}
- + [(set_attr "type" "shift")])
- +
- +(define_insn "ashrsi3"
- + [(set (match_operand:SI 0 "register_operand" "=r,r")
- + (ashiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
- + (match_operand:SI 2 "shift_operand" "r,L")))]
- + ""
- + "sra%i2\\t%0, %1, %z2"
- + [(set_attr "type" "shift")])
- +
- +(define_insn "lshrsi3"
- + [(set (match_operand:SI 0 "register_operand" "=r,r")
- + (lshiftrt:SI (match_operand:SI 1 "register_operand" "r,r")
- + (match_operand:SI 2 "shift_operand" "r,L")))]
- + ""
- + "srl%i2\\t%0, %1, %z2"
- + [(set_attr "type" "shift")])
- +
- +(define_insn "rotlsi3"
- + [(set (match_operand:SI 0 "register_operand" "=r,r")
- + (rotate:SI (match_operand:SI 1 "register_operand" "r,r")
- + (match_operand:SI 2 "shift_operand" "r,L")))]
- + ""
- + "rol%i2\\t%0, %1, %z2"
- + [(set_attr "type" "shift")])
- +
- +(define_insn "rotrsi3"
- + [(set (match_operand:SI 0 "register_operand" "=r,r")
- + (rotatert:SI (match_operand:SI 1 "register_operand" "r,r")
- + (match_operand:SI 2 "register_operand" "r,r")))]
- + ""
- + "ror\\t%0, %1, %2"
- + [(set_attr "type" "shift")])
- +
- +(define_insn "*shift_mul_constants"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (ashift:SI (mult:SI (match_operand:SI 1 "register_operand" "r")
- + (match_operand:SI 2 "const_int_operand" "I"))
- + (match_operand:SI 3 "const_int_operand" "I")))]
- + "TARGET_HAS_MUL && SMALL_INT (INTVAL (operands[2]) << INTVAL (operands[3]))"
- +{
- + HOST_WIDE_INT mul = INTVAL (operands[2]) << INTVAL (operands[3]);
- + rtx ops[3];
- +
- + ops[0] = operands[0];
- + ops[1] = operands[1];
- + ops[2] = GEN_INT (mul);
- +
- + output_asm_insn ("muli\t%0, %1, %2", ops);
- + return "";
- +}
- + [(set_attr "type" "mul")])
- +
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* Converting between floating point and fixed point
- +;*
- +;*****************************************************************************
- +(define_insn "floatsisf2"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (float:SF (match_operand:SI 1 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_floatsisf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_floatsisf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "floatsidf2"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (float:DF (match_operand:SI 1 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_floatsidf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_floatsidf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "floatunssisf2"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unsigned_float:SF (match_operand:SI 1 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_floatunssisf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_floatunssisf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "floatunssidf2"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (unsigned_float:DF (match_operand:SI 1 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_floatunssidf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_floatunssidf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "fixsfsi2"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (fix:SI (match_operand:SF 1 "general_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_fixsfsi2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_fixsfsi2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "fixdfsi2"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (fix:SI (match_operand:DF 1 "general_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_fixdfsi2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_fixdfsi2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "fixunssfsi2"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unsigned_fix:SI (match_operand:SF 1 "general_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_fixunssfsi2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_fixunssfsi2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "fixunsdfsi2"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unsigned_fix:SI (match_operand:DF 1 "general_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_fixunsdfsi2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_fixunsdfsi2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "extendsfdf2"
- + [(set (match_operand:DF 0 "register_operand" "=r")
- + (float_extend:DF (match_operand:SF 1 "general_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_extendsfdf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_extendsfdf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +(define_insn "truncdfsf2"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (float_truncate:SF (match_operand:DF 1 "general_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_truncdfsf2].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_truncdfsf2].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +
- +
- +
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* Prologue, Epilogue and Return
- +;*
- +;*****************************************************************************
- +
- +(define_expand "prologue"
- + [(const_int 1)]
- + ""
- +{
- + expand_prologue ();
- + DONE;
- +})
- +
- +(define_expand "epilogue"
- + [(return)]
- + ""
- +{
- + expand_epilogue (false);
- + DONE;
- +})
- +
- +(define_expand "sibcall_epilogue"
- + [(return)]
- + ""
- +{
- + expand_epilogue (true);
- + DONE;
- +})
- +
- +(define_insn "return"
- + [(return)]
- + "reload_completed && nios2_can_use_return_insn ()"
- + "ret\\t"
- +)
- +
- +(define_insn "return_from_epilogue"
- + [(use (match_operand 0 "pmode_register_operand" ""))
- + (return)]
- + "reload_completed"
- + "ret\\t"
- +)
- +
- +;; Block any insns from being moved before this point, since the
- +;; profiling call to mcount can use various registers that aren't
- +;; saved or used to pass arguments.
- +
- +(define_insn "blockage"
- + [(unspec_volatile [(const_int 0)] UNSPEC_BLOCKAGE)]
- + ""
- + ""
- + [(set_attr "type" "unknown")
- + (set_attr "length" "0")])
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* Jumps and Calls
- +;*
- +;*****************************************************************************
- +
- +(define_insn "indirect_jump"
- + [(set (pc) (match_operand:SI 0 "register_operand" "r"))]
- + ""
- + "jmp\\t%0"
- + [(set_attr "type" "control")])
- +
- +(define_insn "jump"
- + [(set (pc)
- + (label_ref (match_operand 0 "" "")))]
- + ""
- + "br\\t%0"
- + [(set_attr "type" "control")])
- +
- +
- +(define_insn "indirect_call"
- + [(call (mem:QI (match_operand:SI 0 "register_operand" "r"))
- + (match_operand 1 "" ""))
- + (clobber (reg:SI RA_REGNO))]
- + ""
- + "callr\\t%0"
- + [(set_attr "type" "control")])
- +
- +(define_insn "indirect_call_value"
- + [(set (match_operand 0 "" "")
- + (call (mem:QI (match_operand:SI 1 "register_operand" "r"))
- + (match_operand 2 "" "")))
- + (clobber (reg:SI RA_REGNO))]
- + ""
- + "callr\\t%1"
- +)
- +
- +(define_expand "call"
- + [(parallel [(call (match_operand 0 "" "")
- + (match_operand 1 "" ""))
- + (clobber (reg:SI RA_REGNO))])]
- + ""
- + "")
- +
- +(define_expand "call_value"
- + [(parallel [(set (match_operand 0 "" "")
- + (call (match_operand 1 "" "")
- + (match_operand 2 "" "")))
- + (clobber (reg:SI RA_REGNO))])]
- + ""
- + "")
- +
- +(define_insn "*call"
- + [(call (mem:QI (match_operand:SI 0 "immediate_operand" "i"))
- + (match_operand 1 "" ""))
- + (clobber (match_operand:SI 2 "register_operand" "=r"))]
- + ""
- + "call\\t%0"
- + [(set_attr "type" "control")])
- +
- +(define_insn "*call_value"
- + [(set (match_operand 0 "" "")
- + (call (mem:QI (match_operand:SI 1 "immediate_operand" "i"))
- + (match_operand 2 "" "")))
- + (clobber (match_operand:SI 3 "register_operand" "=r"))]
- + ""
- + "call\\t%1"
- + [(set_attr "type" "control")])
- +
- +(define_expand "sibcall"
- + [(parallel [(call (match_operand 0 "" "")
- + (match_operand 1 "" ""))
- + (return)
- + (use (match_operand 2 "" ""))])]
- + ""
- + {
- + XEXP (operands[0], 0) = copy_to_mode_reg (SImode, XEXP (operands[0], 0));
- +
- + if (operands[2] == NULL_RTX)
- + operands[2] = const0_rtx;
- + }
- +)
- +
- +(define_expand "sibcall_value"
- + [(parallel [(set (match_operand 0 "" "")
- + (call (match_operand 1 "" "")
- + (match_operand 2 "" "")))
- + (return)
- + (use (match_operand 3 "" ""))])]
- + ""
- + {
- + XEXP (operands[1], 0) = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
- +
- + if (operands[3] == NULL_RTX)
- + operands[3] = const0_rtx;
- + }
- +)
- +
- +(define_insn "sibcall_insn"
- + [(call (mem:QI (match_operand:SI 0 "register_operand" "D08"))
- + (match_operand 1 "" ""))
- + (return)
- + (use (match_operand 2 "" ""))]
- + ""
- + "jmp\\t%0"
- +)
- +
- +(define_insn "sibcall_value_insn"
- + [(set (match_operand 0 "register_operand" "")
- + (call (mem:QI (match_operand:SI 1 "register_operand" "D08"))
- + (match_operand 2 "" "")))
- + (return)
- + (use (match_operand 3 "" ""))]
- + ""
- + "jmp\\t%1"
- +)
- +
- +
- +
- +
- +(define_expand "tablejump"
- + [(parallel [(set (pc) (match_operand 0 "register_operand" "r"))
- + (use (label_ref (match_operand 1 "" "")))])]
- + ""
- + ""
- +)
- +
- +(define_insn "*tablejump"
- + [(set (pc)
- + (match_operand:SI 0 "register_operand" "r"))
- + (use (label_ref (match_operand 1 "" "")))]
- + ""
- + "jmp\\t%0"
- + [(set_attr "type" "control")])
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* Comparisons
- +;*
- +;*****************************************************************************
- +;; Flow here is rather complex (based on MIPS):
- +;;
- +;; 1) The cmp{si,di,sf,df} routine is called. It deposits the
- +;; arguments into the branch_cmp array, and the type into
- +;; branch_type. No RTL is generated.
- +;;
- +;; 2) The appropriate branch define_expand is called, which then
- +;; creates the appropriate RTL for the comparison and branch.
- +;; Different CC modes are used, based on what type of branch is
- +;; done, so that we can constrain things appropriately. There
- +;; are assumptions in the rest of GCC that break if we fold the
- +;; operands into the branchs for integer operations, and use cc0
- +;; for floating point, so we use the fp status register instead.
- +;; If needed, an appropriate temporary is created to hold the
- +;; of the integer compare.
- +
- +(define_expand "cmpsi"
- + [(set (cc0)
- + (compare:CC (match_operand:SI 0 "register_operand" "")
- + (match_operand:SI 1 "arith_operand" "")))]
- + ""
- +{
- + branch_cmp[0] = operands[0];
- + branch_cmp[1] = operands[1];
- + branch_type = CMP_SI;
- + DONE;
- +})
- +
- +(define_expand "tstsi"
- + [(set (cc0)
- + (match_operand:SI 0 "register_operand" ""))]
- + ""
- +{
- + branch_cmp[0] = operands[0];
- + branch_cmp[1] = const0_rtx;
- + branch_type = CMP_SI;
- + DONE;
- +})
- +
- +(define_expand "cmpsf"
- + [(set (cc0)
- + (compare:CC (match_operand:SF 0 "register_operand" "")
- + (match_operand:SF 1 "register_operand" "")))]
- + "(nios2_fpu_insns[nios2_fpu_nios2_sltsf].N >= 0
- + || nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N >= 0)
- + && (nios2_fpu_insns[nios2_fpu_nios2_sgesf].N >= 0
- + || nios2_fpu_insns[nios2_fpu_nios2_slesf].N >= 0)
- + && nios2_fpu_insns[nios2_fpu_nios2_seqsf].N >= 0
- + && nios2_fpu_insns[nios2_fpu_nios2_snesf].N >= 0"
- +{
- + branch_cmp[0] = operands[0];
- + branch_cmp[1] = operands[1];
- + branch_type = CMP_SF;
- + DONE;
- +})
- +
- +(define_expand "cmpdf"
- + [(set (cc0)
- + (compare:CC (match_operand:DF 0 "register_operand" "")
- + (match_operand:DF 1 "register_operand" "")))]
- + "(nios2_fpu_insns[nios2_fpu_nios2_sltdf].N >= 0
- + || nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N >= 0)
- + && (nios2_fpu_insns[nios2_fpu_nios2_sgedf].N >= 0
- + || nios2_fpu_insns[nios2_fpu_nios2_sledf].N >= 0)
- + && nios2_fpu_insns[nios2_fpu_nios2_seqdf].N >= 0
- + && nios2_fpu_insns[nios2_fpu_nios2_snedf].N >= 0"
- +{
- + branch_cmp[0] = operands[0];
- + branch_cmp[1] = operands[1];
- + branch_type = CMP_DF;
- + DONE;
- +})
- +
- +
- +;*****************************************************************************
- +;*
- +;* setting a register from a comparison
- +;*
- +;*****************************************************************************
- +
- +(define_expand "seq"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (eq:SI (match_dup 1)
- + (match_dup 2)))]
- + ""
- +{
- + if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
- + FAIL;
- +
- + /* set up operands from compare. */
- + operands[1] = branch_cmp[0];
- + operands[2] = branch_cmp[1];
- +
- + gen_int_relational (EQ, operands[0], operands[1], operands[2], NULL_RTX);
- + DONE;
- +})
- +
- +
- +(define_insn "*seq"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (eq:SI (match_operand:SI 1 "reg_or_0_operand" "%rM")
- + (match_operand:SI 2 "arith_operand" "rI")))]
- + ""
- + "cmpeq%i2\\t%0, %z1, %z2"
- + [(set_attr "type" "alu")])
- +
- +
- +(define_insn "nios2_seqsf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (eq:SI (match_operand:SF 1 "register_operand" "%r")
- + (match_operand:SF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_nios2_seqsf].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_seqsf].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +(define_insn "nios2_seqdf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (eq:SI (match_operand:DF 1 "register_operand" "%r")
- + (match_operand:DF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_nios2_seqdf].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_seqdf].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +(define_expand "sne"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (ne:SI (match_dup 1)
- + (match_dup 2)))]
- + ""
- +{
- + if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
- + FAIL;
- +
- + /* set up operands from compare. */
- + operands[1] = branch_cmp[0];
- + operands[2] = branch_cmp[1];
- +
- + gen_int_relational (NE, operands[0], operands[1], operands[2], NULL_RTX);
- + DONE;
- +})
- +
- +
- +(define_insn "*sne"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (ne:SI (match_operand:SI 1 "reg_or_0_operand" "%rM")
- + (match_operand:SI 2 "arith_operand" "rI")))]
- + ""
- + "cmpne%i2\\t%0, %z1, %z2"
- + [(set_attr "type" "alu")])
- +
- +
- +(define_insn "nios2_snesf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (ne:SI (match_operand:SF 1 "register_operand" "%r")
- + (match_operand:SF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_nios2_snesf].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_snesf].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +(define_insn "nios2_snedf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (ne:SI (match_operand:DF 1 "register_operand" "%r")
- + (match_operand:DF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_nios2_snedf].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_snedf].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +(define_expand "sgt"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (gt:SI (match_dup 1)
- + (match_dup 2)))]
- + ""
- +{
- + if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
- + FAIL;
- +
- + /* set up operands from compare. */
- + operands[1] = branch_cmp[0];
- + operands[2] = branch_cmp[1];
- +
- + gen_int_relational (GT, operands[0], operands[1], operands[2], NULL_RTX);
- + DONE;
- +})
- +
- +
- +(define_insn "*sgt"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (gt:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
- + (match_operand:SI 2 "reg_or_0_operand" "rM")))]
- + ""
- + "cmplt\\t%0, %z2, %z1"
- + [(set_attr "type" "alu")])
- +
- +
- +(define_insn "nios2_sgtsf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (gt:SI (match_operand:SF 1 "register_operand" "r")
- + (match_operand:SF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_nios2_sgtsf].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_sgtsf].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +(define_insn "nios2_sgtdf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (gt:SI (match_operand:DF 1 "register_operand" "r")
- + (match_operand:DF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_nios2_sgtdf].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_sgtdf].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +(define_expand "sge"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (ge:SI (match_dup 1)
- + (match_dup 2)))]
- + ""
- +{
- + if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
- + FAIL;
- +
- + /* set up operands from compare. */
- + operands[1] = branch_cmp[0];
- + operands[2] = branch_cmp[1];
- +
- + gen_int_relational (GE, operands[0], operands[1], operands[2], NULL_RTX);
- + DONE;
- +})
- +
- +
- +(define_insn "*sge"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (ge:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
- + (match_operand:SI 2 "arith_operand" "rI")))]
- + ""
- + "cmpge%i2\\t%0, %z1, %z2"
- + [(set_attr "type" "alu")])
- +
- +
- +(define_insn "nios2_sgesf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (ge:SI (match_operand:SF 1 "register_operand" "r")
- + (match_operand:SF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_nios2_sgesf].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_sgesf].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +(define_insn "nios2_sgedf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (ge:SI (match_operand:DF 1 "register_operand" "r")
- + (match_operand:DF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_nios2_sgedf].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_sgedf].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +(define_expand "sle"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (le:SI (match_dup 1)
- + (match_dup 2)))]
- + ""
- +{
- + if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
- + FAIL;
- +
- + /* set up operands from compare. */
- + operands[1] = branch_cmp[0];
- + operands[2] = branch_cmp[1];
- +
- + gen_int_relational (LE, operands[0], operands[1], operands[2], NULL_RTX);
- + DONE;
- +})
- +
- +
- +(define_insn "*sle"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (le:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
- + (match_operand:SI 2 "reg_or_0_operand" "rM")))]
- + ""
- + "cmpge\\t%0, %z2, %z1"
- + [(set_attr "type" "alu")])
- +
- +
- +(define_insn "nios2_slesf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (le:SI (match_operand:SF 1 "register_operand" "r")
- + (match_operand:SF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_nios2_slesf].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_slesf].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +(define_insn "nios2_sledf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (le:SI (match_operand:DF 1 "register_operand" "r")
- + (match_operand:DF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_nios2_sledf].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_sledf].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +(define_expand "slt"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (lt:SI (match_dup 1)
- + (match_dup 2)))]
- + ""
- +{
- + if (branch_type != CMP_SI && branch_type != CMP_SF && branch_type != CMP_DF)
- + FAIL;
- +
- + /* set up operands from compare. */
- + operands[1] = branch_cmp[0];
- + operands[2] = branch_cmp[1];
- +
- + gen_int_relational (LT, operands[0], operands[1], operands[2], NULL_RTX);
- + DONE;
- +})
- +
- +
- +(define_insn "*slt"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (lt:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
- + (match_operand:SI 2 "arith_operand" "rI")))]
- + ""
- + "cmplt%i2\\t%0, %z1, %z2"
- + [(set_attr "type" "alu")])
- +
- +
- +(define_insn "nios2_sltsf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (lt:SI (match_operand:SF 1 "register_operand" "r")
- + (match_operand:SF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_nios2_sltsf].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_sltsf].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +(define_insn "nios2_sltdf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (lt:SI (match_operand:DF 1 "register_operand" "r")
- + (match_operand:DF 2 "register_operand" "r")))]
- + "nios2_fpu_insns[nios2_fpu_nios2_sltdf].N >= 0"
- + {
- + return (*nios2_fpu_insns[nios2_fpu_nios2_sltdf].output) (insn);
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +(define_expand "sgtu"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (gtu:SI (match_dup 1)
- + (match_dup 2)))]
- + ""
- +{
- + if (branch_type != CMP_SI)
- + FAIL;
- +
- + /* set up operands from compare. */
- + operands[1] = branch_cmp[0];
- + operands[2] = branch_cmp[1];
- +
- + gen_int_relational (GTU, operands[0], operands[1], operands[2], NULL_RTX);
- + DONE;
- +})
- +
- +
- +(define_insn "*sgtu"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (gtu:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
- + (match_operand:SI 2 "reg_or_0_operand" "rM")))]
- + ""
- + "cmpltu\\t%0, %z2, %z1"
- + [(set_attr "type" "alu")])
- +
- +
- +(define_expand "sgeu"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (geu:SI (match_dup 1)
- + (match_dup 2)))]
- + ""
- +{
- + if (branch_type != CMP_SI)
- + FAIL;
- +
- + /* set up operands from compare. */
- + operands[1] = branch_cmp[0];
- + operands[2] = branch_cmp[1];
- +
- + gen_int_relational (GEU, operands[0], operands[1], operands[2], NULL_RTX);
- + DONE;
- +})
- +
- +
- +(define_insn "*sgeu"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (geu:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
- + (match_operand:SI 2 "uns_arith_operand" "rJ")))]
- + ""
- + "cmpgeu%i2\\t%0, %z1, %z2"
- + [(set_attr "type" "alu")])
- +
- +(define_expand "sleu"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (leu:SI (match_dup 1)
- + (match_dup 2)))]
- + ""
- +{
- + if (branch_type != CMP_SI)
- + FAIL;
- +
- + /* set up operands from compare. */
- + operands[1] = branch_cmp[0];
- + operands[2] = branch_cmp[1];
- +
- + gen_int_relational (LEU, operands[0], operands[1], operands[2], NULL_RTX);
- + DONE;
- +})
- +
- +
- +(define_insn "*sleu"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (leu:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
- + (match_operand:SI 2 "reg_or_0_operand" "rM")))]
- + ""
- + "cmpgeu\\t%0, %z2, %z1"
- + [(set_attr "type" "alu")])
- +
- +
- +(define_expand "sltu"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (ltu:SI (match_dup 1)
- + (match_dup 2)))]
- + ""
- +{
- + if (branch_type != CMP_SI)
- + FAIL;
- +
- + /* set up operands from compare. */
- + operands[1] = branch_cmp[0];
- + operands[2] = branch_cmp[1];
- +
- + gen_int_relational (LTU, operands[0], operands[1], operands[2], NULL_RTX);
- + DONE;
- +})
- +
- +
- +(define_insn "*sltu"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (ltu:SI (match_operand:SI 1 "reg_or_0_operand" "rM")
- + (match_operand:SI 2 "uns_arith_operand" "rJ")))]
- + ""
- + "cmpltu%i2\\t%0, %z1, %z2"
- + [(set_attr "type" "alu")])
- +
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* branches
- +;*
- +;*****************************************************************************
- +
- +(define_insn "*cbranch"
- + [(set (pc)
- + (if_then_else
- + (match_operator:SI 0 "comparison_operator"
- + [(match_operand:SI 2 "reg_or_0_operand" "rM")
- + (match_operand:SI 3 "reg_or_0_operand" "rM")])
- + (label_ref (match_operand 1 "" ""))
- + (pc)))]
- + ""
- + "b%0\\t%z2, %z3, %l1"
- + [(set_attr "type" "control")])
- +
- +
- +(define_insn "nios2_cbranch_sf"
- + [(set (pc)
- + (if_then_else
- + (match_operator:SI 0 "comparison_operator"
- + [(match_operand:SF 2 "register_operand" "r")
- + (match_operand:SF 3 "register_operand" "r")])
- + (label_ref (match_operand 1 "" ""))
- + (pc)))]
- + ""
- + {
- + return nios2_output_fpu_insn_cmps (insn, GET_CODE (operands[0]));
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +(define_insn "nios2_cbranch_df"
- + [(set (pc)
- + (if_then_else
- + (match_operator:SI 0 "comparison_operator"
- + [(match_operand:DF 2 "register_operand" "r")
- + (match_operand:DF 3 "register_operand" "r")])
- + (label_ref (match_operand 1 "" ""))
- + (pc)))]
- + ""
- + {
- + return nios2_output_fpu_insn_cmpd (insn, GET_CODE (operands[0]));
- + }
- + [(set_attr "type" "custom")])
- +
- +
- +(define_expand "beq"
- + [(set (pc)
- + (if_then_else (eq:CC (cc0)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- +{
- + gen_int_relational (EQ, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
- + DONE;
- +})
- +
- +
- +(define_expand "bne"
- + [(set (pc)
- + (if_then_else (ne:CC (cc0)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- +{
- + gen_int_relational (NE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
- + DONE;
- +})
- +
- +
- +(define_expand "bgt"
- + [(set (pc)
- + (if_then_else (gt:CC (cc0)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- +{
- + gen_int_relational (GT, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
- + DONE;
- +})
- +
- +(define_expand "bge"
- + [(set (pc)
- + (if_then_else (ge:CC (cc0)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- +{
- + gen_int_relational (GE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
- + DONE;
- +})
- +
- +(define_expand "ble"
- + [(set (pc)
- + (if_then_else (le:CC (cc0)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- +{
- + gen_int_relational (LE, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
- + DONE;
- +})
- +
- +(define_expand "blt"
- + [(set (pc)
- + (if_then_else (lt:CC (cc0)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- +{
- + gen_int_relational (LT, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
- + DONE;
- +})
- +
- +
- +(define_expand "bgtu"
- + [(set (pc)
- + (if_then_else (gtu:CC (cc0)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- +{
- + gen_int_relational (GTU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
- + DONE;
- +})
- +
- +(define_expand "bgeu"
- + [(set (pc)
- + (if_then_else (geu:CC (cc0)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- +{
- + gen_int_relational (GEU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
- + DONE;
- +})
- +
- +(define_expand "bleu"
- + [(set (pc)
- + (if_then_else (leu:CC (cc0)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- +{
- + gen_int_relational (LEU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
- + DONE;
- +})
- +
- +(define_expand "bltu"
- + [(set (pc)
- + (if_then_else (ltu:CC (cc0)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- +{
- + gen_int_relational (LTU, NULL_RTX, branch_cmp[0], branch_cmp[1], operands[0]);
- + DONE;
- +})
- +
- +
- +;*****************************************************************************
- +;*
- +;* String and Block Operations
- +;*
- +;*****************************************************************************
- +
- +; ??? This is all really a hack to get Dhrystone to work as fast as possible
- +; things to be fixed:
- +; * let the compiler core handle all of this, for that to work the extra
- +; aliasing needs to be addressed.
- +; * we use three temporary registers for loading and storing to ensure no
- +; ld use stalls, this is excessive, because after the first ld/st only
- +; two are needed. Only two would be needed all the way through if
- +; we could schedule with other code. Consider:
- +; 1 ld $1, 0($src)
- +; 2 ld $2, 4($src)
- +; 3 ld $3, 8($src)
- +; 4 st $1, 0($dest)
- +; 5 ld $1, 12($src)
- +; 6 st $2, 4($src)
- +; 7 etc.
- +; The first store has to wait until 4. If it does not there will be one
- +; cycle of stalling. However, if any other instruction could be placed
- +; between 1 and 4, $3 would not be needed.
- +; * In small we probably don't want to ever do this ourself because there
- +; is no ld use stall.
- +
- +(define_expand "movstrsi"
- + [(parallel [(set (match_operand:BLK 0 "general_operand" "")
- + (match_operand:BLK 1 "general_operand" ""))
- + (use (match_operand:SI 2 "const_int_operand" ""))
- + (use (match_operand:SI 3 "const_int_operand" ""))
- + (clobber (match_scratch:SI 4 "=&r"))
- + (clobber (match_scratch:SI 5 "=&r"))
- + (clobber (match_scratch:SI 6 "=&r"))])]
- + "TARGET_INLINE_MEMCPY"
- +{
- + rtx ld_addr_reg, st_addr_reg;
- +
- + /* If the predicate for op2 fails in expr.c:emit_block_move_via_movstr
- + it trys to copy to a register, but does not re-try the predicate.
- + ??? Intead of fixing expr.c, I fix it here. */
- + if (!const_int_operand (operands[2], SImode))
- + FAIL;
- +
- + /* ??? there are some magic numbers which need to be sorted out here.
- + the basis for them is not increasing code size hugely or going
- + out of range of offset addressing */
- + if (INTVAL (operands[3]) < 4)
- + FAIL;
- + if (!optimize
- + || (optimize_size && INTVAL (operands[2]) > 12)
- + || (optimize < 3 && INTVAL (operands[2]) > 100)
- + || INTVAL (operands[2]) > 200)
- + FAIL;
- +
- + st_addr_reg
- + = replace_equiv_address (operands[0],
- + copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
- + ld_addr_reg
- + = replace_equiv_address (operands[1],
- + copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
- + emit_insn (gen_movstrsi_internal (st_addr_reg, ld_addr_reg,
- + operands[2], operands[3]));
- +
- + DONE;
- +})
- +
- +
- +(define_insn "movstrsi_internal"
- + [(set (match_operand:BLK 0 "memory_operand" "=o")
- + (match_operand:BLK 1 "memory_operand" "o"))
- + (use (match_operand:SI 2 "const_int_operand" "i"))
- + (use (match_operand:SI 3 "const_int_operand" "i"))
- + (clobber (match_scratch:SI 4 "=&r"))
- + (clobber (match_scratch:SI 5 "=&r"))
- + (clobber (match_scratch:SI 6 "=&r"))]
- + "TARGET_INLINE_MEMCPY"
- +{
- + int ld_offset = INTVAL (operands[2]);
- + int ld_len = INTVAL (operands[2]);
- + int ld_reg = 0;
- + rtx ld_addr_reg = XEXP (operands[1], 0);
- + int st_offset = INTVAL (operands[2]);
- + int st_len = INTVAL (operands[2]);
- + int st_reg = 0;
- + rtx st_addr_reg = XEXP (operands[0], 0);
- + int delay_count = 0;
- +
- + /* ops[0] is the address used by the insn
- + ops[1] is the register being loaded or stored */
- + rtx ops[2];
- +
- + if (INTVAL (operands[3]) < 4)
- + abort ();
- +
- + while (ld_offset >= 4)
- + {
- + /* if the load use delay has been met, I can start
- + storing */
- + if (delay_count >= 3)
- + {
- + ops[0] = gen_rtx (MEM, SImode,
- + plus_constant (st_addr_reg, st_len - st_offset));
- + ops[1] = operands[st_reg + 4];
- + output_asm_insn ("stw\t%1, %0", ops);
- +
- + st_reg = (st_reg + 1) % 3;
- + st_offset -= 4;
- + }
- +
- + ops[0] = gen_rtx (MEM, SImode,
- + plus_constant (ld_addr_reg, ld_len - ld_offset));
- + ops[1] = operands[ld_reg + 4];
- + output_asm_insn ("ldw\t%1, %0", ops);
- +
- + ld_reg = (ld_reg + 1) % 3;
- + ld_offset -= 4;
- + delay_count++;
- + }
- +
- + if (ld_offset >= 2)
- + {
- + /* if the load use delay has been met, I can start
- + storing */
- + if (delay_count >= 3)
- + {
- + ops[0] = gen_rtx (MEM, SImode,
- + plus_constant (st_addr_reg, st_len - st_offset));
- + ops[1] = operands[st_reg + 4];
- + output_asm_insn ("stw\t%1, %0", ops);
- +
- + st_reg = (st_reg + 1) % 3;
- + st_offset -= 4;
- + }
- +
- + ops[0] = gen_rtx (MEM, HImode,
- + plus_constant (ld_addr_reg, ld_len - ld_offset));
- + ops[1] = operands[ld_reg + 4];
- + output_asm_insn ("ldh\t%1, %0", ops);
- +
- + ld_reg = (ld_reg + 1) % 3;
- + ld_offset -= 2;
- + delay_count++;
- + }
- +
- + if (ld_offset >= 1)
- + {
- + /* if the load use delay has been met, I can start
- + storing */
- + if (delay_count >= 3)
- + {
- + ops[0] = gen_rtx (MEM, SImode,
- + plus_constant (st_addr_reg, st_len - st_offset));
- + ops[1] = operands[st_reg + 4];
- + output_asm_insn ("stw\t%1, %0", ops);
- +
- + st_reg = (st_reg + 1) % 3;
- + st_offset -= 4;
- + }
- +
- + ops[0] = gen_rtx (MEM, QImode,
- + plus_constant (ld_addr_reg, ld_len - ld_offset));
- + ops[1] = operands[ld_reg + 4];
- + output_asm_insn ("ldb\t%1, %0", ops);
- +
- + ld_reg = (ld_reg + 1) % 3;
- + ld_offset -= 1;
- + delay_count++;
- + }
- +
- + while (st_offset >= 4)
- + {
- + ops[0] = gen_rtx (MEM, SImode,
- + plus_constant (st_addr_reg, st_len - st_offset));
- + ops[1] = operands[st_reg + 4];
- + output_asm_insn ("stw\t%1, %0", ops);
- +
- + st_reg = (st_reg + 1) % 3;
- + st_offset -= 4;
- + }
- +
- + while (st_offset >= 2)
- + {
- + ops[0] = gen_rtx (MEM, HImode,
- + plus_constant (st_addr_reg, st_len - st_offset));
- + ops[1] = operands[st_reg + 4];
- + output_asm_insn ("sth\t%1, %0", ops);
- +
- + st_reg = (st_reg + 1) % 3;
- + st_offset -= 2;
- + }
- +
- + while (st_offset >= 1)
- + {
- + ops[0] = gen_rtx (MEM, QImode,
- + plus_constant (st_addr_reg, st_len - st_offset));
- + ops[1] = operands[st_reg + 4];
- + output_asm_insn ("stb\t%1, %0", ops);
- +
- + st_reg = (st_reg + 1) % 3;
- + st_offset -= 1;
- + }
- +
- + return "";
- +}
- +; ??? lengths are not being used yet, but I will probably forget
- +; to update this once I am using lengths, so set it to something
- +; definetely big enough to cover it. 400 allows for 200 bytes
- +; of motion.
- + [(set_attr "length" "400")])
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* Custom instructions
- +;*
- +;*****************************************************************************
- +
- +(define_constants [
- + (CUSTOM_N 100)
- + (CUSTOM_NI 101)
- + (CUSTOM_NF 102)
- + (CUSTOM_NP 103)
- + (CUSTOM_NII 104)
- + (CUSTOM_NIF 105)
- + (CUSTOM_NIP 106)
- + (CUSTOM_NFI 107)
- + (CUSTOM_NFF 108)
- + (CUSTOM_NFP 109)
- + (CUSTOM_NPI 110)
- + (CUSTOM_NPF 111)
- + (CUSTOM_NPP 112)
- + (CUSTOM_IN 113)
- + (CUSTOM_INI 114)
- + (CUSTOM_INF 115)
- + (CUSTOM_INP 116)
- + (CUSTOM_INII 117)
- + (CUSTOM_INIF 118)
- + (CUSTOM_INIP 119)
- + (CUSTOM_INFI 120)
- + (CUSTOM_INFF 121)
- + (CUSTOM_INFP 122)
- + (CUSTOM_INPI 123)
- + (CUSTOM_INPF 124)
- + (CUSTOM_INPP 125)
- + (CUSTOM_FN 126)
- + (CUSTOM_FNI 127)
- + (CUSTOM_FNF 128)
- + (CUSTOM_FNP 129)
- + (CUSTOM_FNII 130)
- + (CUSTOM_FNIF 131)
- + (CUSTOM_FNIP 132)
- + (CUSTOM_FNFI 133)
- + (CUSTOM_FNFF 134)
- + (CUSTOM_FNFP 135)
- + (CUSTOM_FNPI 136)
- + (CUSTOM_FNPF 137)
- + (CUSTOM_FNPP 138)
- + (CUSTOM_PN 139)
- + (CUSTOM_PNI 140)
- + (CUSTOM_PNF 141)
- + (CUSTOM_PNP 142)
- + (CUSTOM_PNII 143)
- + (CUSTOM_PNIF 144)
- + (CUSTOM_PNIP 145)
- + (CUSTOM_PNFI 146)
- + (CUSTOM_PNFF 147)
- + (CUSTOM_PNFP 148)
- + (CUSTOM_PNPI 149)
- + (CUSTOM_PNPF 150)
- + (CUSTOM_PNPP 151)
- +])
- +
- +
- +(define_insn "custom_n"
- + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")] CUSTOM_N)]
- + ""
- + "custom\\t%0, zero, zero, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_ni"
- + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
- + (match_operand:SI 1 "register_operand" "r")] CUSTOM_NI)]
- + ""
- + "custom\\t%0, zero, %1, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_nf"
- + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
- + (match_operand:SF 1 "register_operand" "r")] CUSTOM_NF)]
- + ""
- + "custom\\t%0, zero, %1, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_np"
- + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
- + (match_operand:SI 1 "register_operand" "r")] CUSTOM_NP)]
- + ""
- + "custom\\t%0, zero, %1, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_nii"
- + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
- + (match_operand:SI 1 "register_operand" "r")
- + (match_operand:SI 2 "register_operand" "r")] CUSTOM_NII)]
- + ""
- + "custom\\t%0, zero, %1, %2"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_nif"
- + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
- + (match_operand:SI 1 "register_operand" "r")
- + (match_operand:SF 2 "register_operand" "r")] CUSTOM_NIF)]
- + ""
- + "custom\\t%0, zero, %1, %2"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_nip"
- + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
- + (match_operand:SI 1 "register_operand" "r")
- + (match_operand:SI 2 "register_operand" "r")] CUSTOM_NIP)]
- + ""
- + "custom\\t%0, zero, %1, %2"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_nfi"
- + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
- + (match_operand:SF 1 "register_operand" "r")
- + (match_operand:SI 2 "register_operand" "r")] CUSTOM_NFI)]
- + ""
- + "custom\\t%0, zero, %1, %2"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_nff"
- + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
- + (match_operand:SF 1 "register_operand" "r")
- + (match_operand:SF 2 "register_operand" "r")] CUSTOM_NFF)]
- + ""
- + "custom\\t%0, zero, %1, %2"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_nfp"
- + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
- + (match_operand:SF 1 "register_operand" "r")
- + (match_operand:SI 2 "register_operand" "r")] CUSTOM_NFP)]
- + ""
- + "custom\\t%0, zero, %1, %2"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_npi"
- + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
- + (match_operand:SI 1 "register_operand" "r")
- + (match_operand:SI 2 "register_operand" "r")] CUSTOM_NPI)]
- + ""
- + "custom\\t%0, zero, %1, %2"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_npf"
- + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
- + (match_operand:SI 1 "register_operand" "r")
- + (match_operand:SF 2 "register_operand" "r")] CUSTOM_NPF)]
- + ""
- + "custom\\t%0, zero, %1, %2"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_npp"
- + [(unspec_volatile [(match_operand:SI 0 "custom_insn_opcode" "N")
- + (match_operand:SI 1 "register_operand" "r")
- + (match_operand:SI 2 "register_operand" "r")] CUSTOM_NPP)]
- + ""
- + "custom\\t%0, zero, %1, %2"
- + [(set_attr "type" "custom")])
- +
- +
- +
- +(define_insn "custom_in"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_IN))]
- + ""
- + "custom\\t%1, %0, zero, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_ini"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")] CUSTOM_INI))]
- + ""
- + "custom\\t%1, %0, %2, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_inf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SF 2 "register_operand" "r")] CUSTOM_INF))]
- + ""
- + "custom\\t%1, %0, %2, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_inp"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")] CUSTOM_INP))]
- + ""
- + "custom\\t%1, %0, %2, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_inii"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_INII))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_inif"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SF 3 "register_operand" "r")] CUSTOM_INIF))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_inip"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_INIP))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_infi"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SF 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_INFI))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_inff"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SF 2 "register_operand" "r")
- + (match_operand:SF 3 "register_operand" "r")] CUSTOM_INFF))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_infp"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SF 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_INFP))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_inpi"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_INPI))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_inpf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SF 3 "register_operand" "r")] CUSTOM_INPF))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_inpp"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_INPP))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +
- +
- +
- +
- +(define_insn "custom_fn"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_FN))]
- + ""
- + "custom\\t%1, %0, zero, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_fni"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")] CUSTOM_FNI))]
- + ""
- + "custom\\t%1, %0, %2, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_fnf"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SF 2 "register_operand" "r")] CUSTOM_FNF))]
- + ""
- + "custom\\t%1, %0, %2, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_fnp"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")] CUSTOM_FNP))]
- + ""
- + "custom\\t%1, %0, %2, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_fnii"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNII))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_fnif"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SF 3 "register_operand" "r")] CUSTOM_FNIF))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_fnip"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNIP))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_fnfi"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SF 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNFI))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_fnff"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SF 2 "register_operand" "r")
- + (match_operand:SF 3 "register_operand" "r")] CUSTOM_FNFF))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_fnfp"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SF 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNFP))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_fnpi"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNPI))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_fnpf"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SF 3 "register_operand" "r")] CUSTOM_FNPF))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_fnpp"
- + [(set (match_operand:SF 0 "register_operand" "=r")
- + (unspec_volatile:SF [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_FNPP))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +
- +
- +(define_insn "custom_pn"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")] CUSTOM_PN))]
- + ""
- + "custom\\t%1, %0, zero, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_pni"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")] CUSTOM_PNI))]
- + ""
- + "custom\\t%1, %0, %2, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_pnf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SF 2 "register_operand" "r")] CUSTOM_PNF))]
- + ""
- + "custom\\t%1, %0, %2, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_pnp"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")] CUSTOM_PNP))]
- + ""
- + "custom\\t%1, %0, %2, zero"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_pnii"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNII))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_pnif"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SF 3 "register_operand" "r")] CUSTOM_PNIF))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_pnip"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNIP))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_pnfi"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SF 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNFI))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_pnff"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SF 2 "register_operand" "r")
- + (match_operand:SF 3 "register_operand" "r")] CUSTOM_PNFF))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_pnfp"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SF 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNFP))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_pnpi"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNPI))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_pnpf"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SF 3 "register_operand" "r")] CUSTOM_PNPF))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +(define_insn "custom_pnpp"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "custom_insn_opcode" "N")
- + (match_operand:SI 2 "register_operand" "r")
- + (match_operand:SI 3 "register_operand" "r")] CUSTOM_PNPP))]
- + ""
- + "custom\\t%1, %0, %2, %3"
- + [(set_attr "type" "custom")])
- +
- +
- +
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* Misc
- +;*
- +;*****************************************************************************
- +
- +(define_insn "nop"
- + [(const_int 0)]
- + ""
- + "nop\\t"
- + [(set_attr "type" "alu")])
- +
- +(define_insn "sync"
- + [(unspec_volatile [(const_int 0)] UNSPEC_SYNC)]
- + ""
- + "sync\\t"
- + [(set_attr "type" "control")])
- +
- +
- +(define_insn "rdctl"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (unspec_volatile:SI [(match_operand:SI 1 "rdwrctl_operand" "O")] UNSPEC_RDCTL))]
- + ""
- + "rdctl\\t%0, ctl%1"
- + [(set_attr "type" "control")])
- +
- +(define_insn "wrctl"
- + [(unspec_volatile:SI [(match_operand:SI 0 "rdwrctl_operand" "O")
- + (match_operand:SI 1 "reg_or_0_operand" "rM")] UNSPEC_WRCTL)]
- + ""
- + "wrctl\\tctl%0, %z1"
- + [(set_attr "type" "control")])
- +
- +;Used to signal a stack overflow
- +(define_insn "trap"
- + [(unspec_volatile [(const_int 0)] UNSPEC_TRAP)]
- + ""
- + "break\\t3"
- + [(set_attr "type" "control")])
- +
- +(define_insn "stack_overflow_detect_and_trap"
- + [(unspec_volatile [(const_int 0)] UNSPEC_STACK_OVERFLOW_DETECT_AND_TRAP)]
- + ""
- + "bgeu\\tsp, et, 1f\;break\\t3\;1:"
- + [(set_attr "type" "control")])
- +
- +
- +;*****************************************************************************
- +;*
- +;* Peepholes
- +;*
- +;*****************************************************************************
- +
- +
- +;; Local Variables:
- +;; mode: lisp
- +;; End:
- diff --git a/gcc/config/nios2/t-nios2 b/gcc/config/nios2/t-nios2
- new file mode 100644
- index 0000000..b92f80a
- --- /dev/null
- +++ b/gcc/config/nios2/t-nios2
- @@ -0,0 +1,175 @@
- +##
- +## Compiler flags to use when compiling libgcc2.c.
- +##
- +## LIB2FUNCS_EXTRA
- +## A list of source file names to be compiled or assembled and inserted into libgcc.a.
- +
- +LIB2FUNCS_EXTRA=$(srcdir)/config/nios2/lib2-divmod.c \
- + $(srcdir)/config/nios2/lib2-divmod-hi.c \
- + $(srcdir)/config/nios2/lib2-divtable.c \
- + $(srcdir)/config/nios2/lib2-mul.c
- +
- +##
- +## Floating Point Emulation
- +## To have GCC include software floating point libraries in libgcc.a define FPBIT
- +## and DPBIT along with a few rules as follows:
- +##
- +## # We want fine grained libraries, so use the new code
- +## # to build the floating point emulation libraries.
- +FPBIT=$(srcdir)/config/nios2/nios2-fp-bit.c
- +DPBIT=$(srcdir)/config/nios2/nios2-dp-bit.c
- +
- +TARGET_LIBGCC2_CFLAGS = -O2
- +
- +# FLOAT_ONLY - no doubles
- +# SMALL_MACHINE - QI/HI is faster than SI
- +# Actually SMALL_MACHINE uses chars and shorts instead of ints
- +# since ints (16-bit ones as they are today) are at least as fast
- +# as chars and shorts, don't define SMALL_MACHINE
- +# CMPtype - type returned by FP compare, i.e. INT (hard coded in fp-bit - see code )
- +
- +$(FPBIT): $(srcdir)/config/fp-bit.c Makefile
- + echo '#define FLOAT' > ${FPBIT}
- + echo '#ifndef __nios2_big_endian__' >> ${FPBIT}
- + echo '#define FLOAT_BIT_ORDER_MISMATCH' >> ${FPBIT}
- + echo '#endif' >> ${FPBIT}
- + cat $(srcdir)/config/fp-bit.c >> ${FPBIT}
- +
- +$(DPBIT): $(srcdir)/config/fp-bit.c Makefile
- + echo '' > ${DPBIT}
- + echo '#ifndef __nios2_big_endian__' >> ${DPBIT}
- + echo '#define FLOAT_BIT_ORDER_MISMATCH' >> ${DPBIT}
- + echo '#endif' >> ${DPBIT}
- + cat $(srcdir)/config/fp-bit.c >> ${DPBIT}
- +
- +EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crti.o crtn.o
- +
- +# Assemble startup files.
- +$(T)crti.o: $(srcdir)/config/nios2/crti.asm $(GCC_PASSES)
- + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- + -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/nios2/crti.asm
- +
- +$(T)crtn.o: $(srcdir)/config/nios2/crtn.asm $(GCC_PASSES)
- + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- + -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/nios2/crtn.asm
- +
- +
- +## You may need to provide additional #defines at the beginning of
- +## fp-bit.c and dp-bit.c to control target endianness and other options
- +##
- +## CRTSTUFF_T_CFLAGS
- +## Special flags used when compiling crtstuff.c. See Initialization.
- +##
- +## CRTSTUFF_T_CFLAGS_S
- +## Special flags used when compiling crtstuff.c for shared linking. Used
- +## if you use crtbeginS.o and crtendS.o in EXTRA-PARTS. See Initialization.
- +##
- +## MULTILIB_OPTIONS
- +## For some targets, invoking GCC in different ways produces objects that
- +## can not be linked together. For example, for some targets GCC produces
- +## both big and little endian code. For these targets, you must arrange
- +## for multiple versions of libgcc.a to be compiled, one for each set of
- +## incompatible options. When GCC invokes the linker, it arranges to link
- +## in the right version of libgcc.a, based on the command line options
- +## used.
- +## The MULTILIB_OPTIONS macro lists the set of options for which special
- +## versions of libgcc.a must be built. Write options that are mutually
- +## incompatible side by side, separated by a slash. Write options that may
- +## be used together separated by a space. The build procedure will build
- +## all combinations of compatible options.
- +##
- +## For example, if you set MULTILIB_OPTIONS to m68000/m68020 msoft-float,
- +## Makefile will build special versions of libgcc.a using the following
- +## sets of options: -m68000, -m68020, -msoft-float, -m68000 -msoft-float,
- +## and -m68020 -msoft-float.
- +
- +
- +## The BUILD_BE_MULTILIB and BUILD_PG_MULTILIB variables allow the
- +## makefile user to enable/disable the generation of the precompiled
- +## big endian and profiling libraries. By default, the big endian
- +## libraries are not created on a windows build and the profiling
- +## libraries are not created on a Solaris build. All other library
- +## combinations are created by default.
- +
- +# Uncomment to temporarily avoid building big endian and profiling libraries during a Windows build.
- +#ifeq ($(DEV_HOST_OS), win32)
- +#BUILD_BE_MULTILIB ?= 0
- +#BUILD_PG_MULTILIB ?= 0
- +#endif
- +
- +#By default, avoid building the profiling libraries during a Solaris build.
- +ifeq ($(DEV_HOST_OS), solaris)
- +BUILD_PG_MULTILIB ?= 0
- +endif
- +
- +BUILD_BE_MULTILIB ?= 1
- +BUILD_PG_MULTILIB ?= 1
- +BUILD_MULTILIB ?= 1
- +
- +ifeq ($(BUILD_MULTILIB), 1)
- +
- +MULTILIB_OPTIONS = mno-hw-mul mhw-mulx mstack-check mcustom-fpu-cfg=60-1 mcustom-fpu-cfg=60-2
- +
- +#Add the profiling flag to the multilib variable if required
- +ifeq ($(BUILD_PG_MULTILIB), 1)
- +MULTILIB_OPTIONS += pg
- +endif
- +
- +#Add the big endian flag to the multilib variable if required
- +ifeq ($(BUILD_BE_MULTILIB), 1)
- +MULTILIB_OPTIONS += EB/EL
- +endif
- +
- +endif
- +
- +## MULTILIB_DIRNAMES
- +## If MULTILIB_OPTIONS is used, this variable specifies the directory names
- +## that should be used to hold the various libraries. Write one element in
- +## MULTILIB_DIRNAMES for each element in MULTILIB_OPTIONS. If
- +## MULTILIB_DIRNAMES is not used, the default value will be
- +## MULTILIB_OPTIONS, with all slashes treated as spaces.
- +## For example, if MULTILIB_OPTIONS is set to m68000/m68020 msoft-float,
- +## then the default value of MULTILIB_DIRNAMES is m68000 m68020
- +## msoft-float. You may specify a different value if you desire a
- +## different set of directory names.
- +
- +# MULTILIB_DIRNAMES =
- +
- +## MULTILIB_MATCHES
- +## Sometimes the same option may be written in two different ways. If an
- +## option is listed in MULTILIB_OPTIONS, GCC needs to know about any
- +## synonyms. In that case, set MULTILIB_MATCHES to a list of items of the
- +## form option=option to describe all relevant synonyms. For example,
- +## m68000=mc68000 m68020=mc68020.
- +
- +ifeq ($(BUILD_MULTILIB), 1)
- +ifeq ($(BUILD_BE_MULTILIB), 1)
- +MULTILIB_MATCHES = EL=mel EB=meb
- +endif
- +endif
- +
- +##
- +## MULTILIB_EXCEPTIONS
- +## Sometimes when there are multiple sets of MULTILIB_OPTIONS being
- +## specified, there are combinations that should not be built. In that
- +## case, set MULTILIB_EXCEPTIONS to be all of the switch exceptions in
- +## shell case syntax that should not be built.
- +## For example, in the PowerPC embedded ABI support, it is not desirable to
- +## build libraries compiled with the -mcall-aix option and either of the
- +## -fleading-underscore or -mlittle options at the same time. Therefore
- +## MULTILIB_EXCEPTIONS is set to
- +##
- +## *mcall-aix/*fleading-underscore* *mlittle/*mcall-aix*
- +##
- +
- +ifeq ($(BUILD_MULTILIB), 1)
- +MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx* *mcustom-fpu-cfg=60-1/*mcustom-fpu-cfg=60-2*
- +endif
- +
- +##
- +## MULTILIB_EXTRA_OPTS Sometimes it is desirable that when building
- +## multiple versions of libgcc.a certain options should always be passed on
- +## to the compiler. In that case, set MULTILIB_EXTRA_OPTS to be the list
- +## of options to be used for all builds.
- +##
- +
- diff --git a/gcc/config/nios2/t-nios2-uclibc b/gcc/config/nios2/t-nios2-uclibc
- new file mode 100644
- index 0000000..9a303db
- --- /dev/null
- +++ b/gcc/config/nios2/t-nios2-uclibc
- @@ -0,0 +1,152 @@
- +##
- +## Compiler flags to use when compiling libgcc2.c.
- +##
- +## LIB2FUNCS_EXTRA
- +## A list of source file names to be compiled or assembled and inserted into libgcc.a.
- +
- +LIB2FUNCS_EXTRA=$(srcdir)/config/nios2/lib2-divmod.c \
- + $(srcdir)/config/nios2/lib2-divmod-hi.c \
- + $(srcdir)/config/nios2/lib2-divtable.c \
- + $(srcdir)/config/nios2/lib2-mul.c
- +
- +##
- +## Floating Point Emulation
- +## To have GCC include software floating point libraries in libgcc.a define FPBIT
- +## and DPBIT along with a few rules as follows:
- +##
- +## # We want fine grained libraries, so use the new code
- +## # to build the floating point emulation libraries.
- +FPBIT=$(srcdir)/config/nios2/nios2-fp-bit.c
- +DPBIT=$(srcdir)/config/nios2/nios2-dp-bit.c
- +
- +TARGET_LIBGCC2_CFLAGS = -O2
- +
- +# FLOAT_ONLY - no doubles
- +# SMALL_MACHINE - QI/HI is faster than SI
- +# Actually SMALL_MACHINE uses chars and shorts instead of ints
- +# since ints (16-bit ones as they are today) are at least as fast
- +# as chars and shorts, don't define SMALL_MACHINE
- +# CMPtype - type returned by FP compare, i.e. INT (hard coded in fp-bit - see code )
- +
- +$(FPBIT): $(srcdir)/config/fp-bit.c Makefile
- + echo '#define FLOAT' > ${FPBIT}
- + echo '#ifndef __nios2_big_endian__' >> ${FPBIT}
- + echo '#define FLOAT_BIT_ORDER_MISMATCH' >> ${FPBIT}
- + echo '#endif' >> ${FPBIT}
- + cat $(srcdir)/config/fp-bit.c >> ${FPBIT}
- +
- +$(DPBIT): $(srcdir)/config/fp-bit.c Makefile
- + echo '' > ${DPBIT}
- + echo '#ifndef __nios2_big_endian__' >> ${DPBIT}
- + echo '#define FLOAT_BIT_ORDER_MISMATCH' >> ${DPBIT}
- + echo '#endif' >> ${DPBIT}
- + cat $(srcdir)/config/fp-bit.c >> ${DPBIT}
- +
- +EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o
- +
- +## You may need to provide additional #defines at the beginning of
- +## fp-bit.c and dp-bit.c to control target endianness and other options
- +##
- +## CRTSTUFF_T_CFLAGS
- +## Special flags used when compiling crtstuff.c. See Initialization.
- +##
- +## CRTSTUFF_T_CFLAGS_S
- +## Special flags used when compiling crtstuff.c for shared linking. Used
- +## if you use crtbeginS.o and crtendS.o in EXTRA-PARTS. See Initialization.
- +##
- +## MULTILIB_OPTIONS
- +## For some targets, invoking GCC in different ways produces objects that
- +## can not be linked together. For example, for some targets GCC produces
- +## both big and little endian code. For these targets, you must arrange
- +## for multiple versions of libgcc.a to be compiled, one for each set of
- +## incompatible options. When GCC invokes the linker, it arranges to link
- +## in the right version of libgcc.a, based on the command line options
- +## used.
- +## The MULTILIB_OPTIONS macro lists the set of options for which special
- +## versions of libgcc.a must be built. Write options that are mutually
- +## incompatible side by side, separated by a slash. Write options that may
- +## be used together separated by a space. The build procedure will build
- +## all combinations of compatible options.
- +##
- +## For example, if you set MULTILIB_OPTIONS to m68000/m68020 msoft-float,
- +## Makefile will build special versions of libgcc.a using the following
- +## sets of options: -m68000, -m68020, -msoft-float, -m68000 -msoft-float,
- +## and -m68020 -msoft-float.
- +
- +
- +## The BUILD_BE_MULTILIB and BUILD_PG_MULTILIB variables allow the
- +## makefile user to enable/disable the generation of the precompiled
- +## big endian and profiling libraries.
- +
- +# By default, avoid building big endian and profiling libraries
- +BUILD_BE_MULTILIB ?= 0
- +BUILD_PG_MULTILIB ?= 0
- +BUILD_MULTILIB ?= 1
- +
- +ifeq ($(BUILD_MULTILIB), 1)
- +
- +MULTILIB_OPTIONS = mno-hw-mul mhw-mulx mstack-check mcustom-fpu-cfg=60-1 mcustom-fpu-cfg=60-2
- +
- +#Add the profiling flag to the multilib variable if required
- +ifeq ($(BUILD_PG_MULTILIB), 1)
- +MULTILIB_OPTIONS += pg
- +endif
- +
- +#Add the big endian flag to the multilib variable if required
- +ifeq ($(BUILD_BE_MULTILIB), 1)
- +MULTILIB_OPTIONS += EB/EL
- +endif
- +
- +endif
- +
- +## MULTILIB_DIRNAMES
- +## If MULTILIB_OPTIONS is used, this variable specifies the directory names
- +## that should be used to hold the various libraries. Write one element in
- +## MULTILIB_DIRNAMES for each element in MULTILIB_OPTIONS. If
- +## MULTILIB_DIRNAMES is not used, the default value will be
- +## MULTILIB_OPTIONS, with all slashes treated as spaces.
- +## For example, if MULTILIB_OPTIONS is set to m68000/m68020 msoft-float,
- +## then the default value of MULTILIB_DIRNAMES is m68000 m68020
- +## msoft-float. You may specify a different value if you desire a
- +## different set of directory names.
- +
- +# MULTILIB_DIRNAMES =
- +
- +## MULTILIB_MATCHES
- +## Sometimes the same option may be written in two different ways. If an
- +## option is listed in MULTILIB_OPTIONS, GCC needs to know about any
- +## synonyms. In that case, set MULTILIB_MATCHES to a list of items of the
- +## form option=option to describe all relevant synonyms. For example,
- +## m68000=mc68000 m68020=mc68020.
- +
- +ifeq ($(BUILD_MULTILIB), 1)
- +ifeq ($(BUILD_BE_MULTILIB), 1)
- +MULTILIB_MATCHES = EL=mel EB=meb
- +endif
- +endif
- +
- +##
- +## MULTILIB_EXCEPTIONS
- +## Sometimes when there are multiple sets of MULTILIB_OPTIONS being
- +## specified, there are combinations that should not be built. In that
- +## case, set MULTILIB_EXCEPTIONS to be all of the switch exceptions in
- +## shell case syntax that should not be built.
- +## For example, in the PowerPC embedded ABI support, it is not desirable to
- +## build libraries compiled with the -mcall-aix option and either of the
- +## -fleading-underscore or -mlittle options at the same time. Therefore
- +## MULTILIB_EXCEPTIONS is set to
- +##
- +## *mcall-aix/*fleading-underscore* *mlittle/*mcall-aix*
- +##
- +
- +ifeq ($(BUILD_MULTILIB), 1)
- +MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx* *mcustom-fpu-cfg=60-1/*mcustom-fpu-cfg=60-2*
- +endif
- +
- +##
- +## MULTILIB_EXTRA_OPTS Sometimes it is desirable that when building
- +## multiple versions of libgcc.a certain options should always be passed on
- +## to the compiler. In that case, set MULTILIB_EXTRA_OPTS to be the list
- +## of options to be used for all builds.
- +##
- +
- diff --git a/gcc/cse.c b/gcc/cse.c
- index 72af39a..b36310c 100644
- --- a/gcc/cse.c
- +++ b/gcc/cse.c
- @@ -3134,6 +3134,10 @@ find_comparison_args (enum rtx_code code, rtx *parg1, rtx *parg2,
- #ifdef FLOAT_STORE_FLAG_VALUE
- REAL_VALUE_TYPE fsfv;
- #endif
- +#ifdef __nios2__
- + if (p->is_const)
- + break;
- +#endif
-
- /* If the entry isn't valid, skip it. */
- if (! exp_equiv_p (p->exp, p->exp, 1, 0))
- diff --git a/gcc/doc/extend.texi b/gcc/doc/extend.texi
- index 4638645..cdb248d 100644
- --- a/gcc/doc/extend.texi
- +++ b/gcc/doc/extend.texi
- @@ -2488,6 +2488,33 @@ contents of that register. The @code{short_call} attribute always places
- the offset to the function from the call site into the @samp{BL}
- instruction directly.
-
- +@item reverse_bitfields/no_reverse_bitfields
- +@cindex reverse_bitfields on Altera Nios II
- +This attribute specifies the order of bitfield allocation within a
- +particular struct on Altera's Nios II processor. This overrides both
- +the @option{-mno-reverse-bitfields} and @option{-mreverse-bitfields}
- +switches, as well as any @code{#pragma} that might be present. It is
- +ignored except when present on a struct.
- +
- +@smallexample
- +struct inner
- +@{
- + unsigned int a:1;
- + unsigned int b:31;
- +@} __attribute__ ((reverse_bitfields));
- +
- +union outer
- +@{
- + struct inner inner;
- + unsigned int val;
- +@};
- +
- +@end smallexample
- +
- +will cause a to be allocated overlapping the most significant bit of
- +val, regardless of any @code{#pragma} or compiler switch. See the
- +@option{-mreverse-bitfields} switch for more examples.
- +
- @item function_vector
- @cindex calling functions through the function vector on the H8/300 processors
- Use this attribute on the H8/300, H8/300H, and H8S to indicate that the specified
- @@ -5638,12 +5665,118 @@ to those machines. Generally these generate calls to specific machine
- instructions, but allow the compiler to schedule those calls.
-
- @menu
- +* Altera Nios II Built-in Functions::
- * Alpha Built-in Functions::
- * ARM Built-in Functions::
- * X86 Built-in Functions::
- * PowerPC AltiVec Built-in Functions::
- @end menu
-
- +@node Altera Nios II Built-in Functions
- +@subsection Altera Nios II Built-in Functions
- +
- +These built-in functions are available for the Altera Nios II
- +family of processors.
- +
- +The following built-in functions are always available. They
- +all generate the machine instruction that is part of the name.
- +
- +@example
- +int __builtin_ldbio (volatile const void *)
- +int __builtin_ldbuio (volatile const void *)
- +int __builtin_ldhio (volatile const void *)
- +int __builtin_ldhuio (volatile const void *)
- +int __builtin_ldwio (volatile const void *)
- +void __builtin_stbio (volatile void *, int)
- +void __builtin_sthio (volatile void *, int)
- +void __builtin_stwio (volatile void *, int)
- +void __builtin_sync (void)
- +int __builtin_rdctl (int)
- +void __builtin_wrctl (int, int)
- +@end example
- +
- +The following built-in functions are always available. They
- +all generate a Nios II Custom Instruction. The name of the
- +function represents the types that the function takes and
- +returns. The letter before the @code{n} is the return type
- +or void if absent. The @code{n} represnts the first parameter
- +to all the custom instructions, the custom instruction number.
- +The two letters after the @code{n} represent the up to two
- +parameters to the function.
- +
- +The letters reprsent the following data types:
- +@table @code
- +@item <no letter>
- +@code{void} for return type and no parameter for parameter types.
- +
- +@item i
- +@code{int} for return type and parameter type
- +
- +@item f
- +@code{float} for return type and parameter type
- +
- +@item p
- +@code{void *} for return type and parameter type
- +
- +@end table
- +
- +And the function names are:
- +@example
- +void __builtin_custom_n (void)
- +void __builtin_custom_ni (int)
- +void __builtin_custom_nf (float)
- +void __builtin_custom_np (void *)
- +void __builtin_custom_nii (int, int)
- +void __builtin_custom_nif (int, float)
- +void __builtin_custom_nip (int, void *)
- +void __builtin_custom_nfi (float, int)
- +void __builtin_custom_nff (float, float)
- +void __builtin_custom_nfp (float, void *)
- +void __builtin_custom_npi (void *, int)
- +void __builtin_custom_npf (void *, float)
- +void __builtin_custom_npp (void *, void *)
- +int __builtin_custom_in (void)
- +int __builtin_custom_ini (int)
- +int __builtin_custom_inf (float)
- +int __builtin_custom_inp (void *)
- +int __builtin_custom_inii (int, int)
- +int __builtin_custom_inif (int, float)
- +int __builtin_custom_inip (int, void *)
- +int __builtin_custom_infi (float, int)
- +int __builtin_custom_inff (float, float)
- +int __builtin_custom_infp (float, void *)
- +int __builtin_custom_inpi (void *, int)
- +int __builtin_custom_inpf (void *, float)
- +int __builtin_custom_inpp (void *, void *)
- +float __builtin_custom_fn (void)
- +float __builtin_custom_fni (int)
- +float __builtin_custom_fnf (float)
- +float __builtin_custom_fnp (void *)
- +float __builtin_custom_fnii (int, int)
- +float __builtin_custom_fnif (int, float)
- +float __builtin_custom_fnip (int, void *)
- +float __builtin_custom_fnfi (float, int)
- +float __builtin_custom_fnff (float, float)
- +float __builtin_custom_fnfp (float, void *)
- +float __builtin_custom_fnpi (void *, int)
- +float __builtin_custom_fnpf (void *, float)
- +float __builtin_custom_fnpp (void *, void *)
- +void * __builtin_custom_pn (void)
- +void * __builtin_custom_pni (int)
- +void * __builtin_custom_pnf (float)
- +void * __builtin_custom_pnp (void *)
- +void * __builtin_custom_pnii (int, int)
- +void * __builtin_custom_pnif (int, float)
- +void * __builtin_custom_pnip (int, void *)
- +void * __builtin_custom_pnfi (float, int)
- +void * __builtin_custom_pnff (float, float)
- +void * __builtin_custom_pnfp (float, void *)
- +void * __builtin_custom_pnpi (void *, int)
- +void * __builtin_custom_pnpf (void *, float)
- +void * __builtin_custom_pnpp (void *, void *)
- +@end example
- +
- +
- @node Alpha Built-in Functions
- @subsection Alpha Built-in Functions
-
- @@ -8022,6 +8155,7 @@ we do not recommend the use of pragmas; @xref{Function Attributes},
- for further explanation.
-
- @menu
- +* Altera Nios II Pragmas::
- * ARM Pragmas::
- * RS/6000 and PowerPC Pragmas::
- * Darwin Pragmas::
- @@ -8029,6 +8163,29 @@ for further explanation.
- * Tru64 Pragmas::
- @end menu
-
- +@node Altera Nios II Pragmas
- +@subsection Altera Nios II Pragmas
- +
- +The Altera Nios II target defines two pragmas to control the placement
- +of bitfields within a struct.
- +
- +@table @code
- +@item reverse_bitfields
- +@cindex pragma, reverse_bitfields
- +Cause all subsequent structs to behave as though the -mreverse-bitfields
- +compiler switch had been given. Can be overridden by the
- +@code{no_reverse_bitfields} attribute or a subsequent
- +@code{#pragma no_reverse_bitfields}.
- +
- +@item no_reverse_bitfields
- +@cindex pragma, no_reverse_bitfields
- +Cause all subsequent structs to behave as though the -mno-reverse-bitfields
- +compiler switch had been given. Can be overridden by the
- +@code{reverse_bitfields} attribute or a subsequent
- +@code{#pragma reverse_bitfields}.
- +
- +@end table
- +
- @node ARM Pragmas
- @subsection ARM Pragmas
-
- diff --git a/gcc/doc/invoke.texi b/gcc/doc/invoke.texi
- index e683d0c..b34200f 100644
- --- a/gcc/doc/invoke.texi
- +++ b/gcc/doc/invoke.texi
- @@ -337,6 +337,16 @@ in the following sections.
- @item Machine Dependent Options
- @xref{Submodel Options,,Hardware Models and Configurations}.
-
- +@emph{Altera Nios II Options}
- +@gccoptlist{-msmallc -mno-bypass-cache -mbypass-cache @gol
- +-mno-cache-volatile -mcache-volatile -mno-inline-memcpy @gol
- +-minline-memcpy -mno-fast-sw-div -mfast-sw-div @gol
- +-mhw-mul -mno-hw-mul -mhw-mulx -mno-hw-mulx @gol
- +-mno-hw-div -mhw-div @gol
- +-mno-stack-check -mstack-check @gol
- +-msys-crt0= -msys-lib= -msys=nosys @gol
- +-mreverse-bitfields -mno-reverse-bitfields}
- +
- @emph{M680x0 Options}
- @gccoptlist{-m68000 -m68020 -m68020-40 -m68020-60 -m68030 -m68040 @gol
- -m68060 -mcpu32 -m5200 -m68881 -mbitfield -mc68000 -mc68020 @gol
- @@ -5839,6 +5849,7 @@ machine description. The default for the options is also defined by
- that macro, which enables you to change the defaults.
-
- @menu
- +* Altera Nios II Options::
- * M680x0 Options::
- * M68hc1x Options::
- * VAX Options::
- @@ -5874,6 +5885,290 @@ that macro, which enables you to change the defaults.
- * FRV Options::
- @end menu
-
- +
- +@node Altera Nios II Options
- +@subsection Altera Nios II Options
- +@cindex Altera Nios II options
- +
- +These are the @samp{-m} options defined for the Altera Nios II
- +processor.
- +
- +@table @gcctabopt
- +
- +@item -msmallc
- +@opindex msmallc
- +Link with a limited version of the C library, -lsmallc. For more
- +information see the C Library Documentation.
- +
- +
- +@item -mbypass-cache
- +@itemx -mno-bypass-cache
- +@opindex mno-bypass-cache
- +@opindex mbypass-cache
- +Force all load and store instructions to always bypass cache by
- +using io variants of the instructions. The default is to not
- +bypass the cache.
- +
- +@item -mno-cache-volatile
- +@itemx -mcache-volatile
- +@opindex mcache-volatile
- +@opindex mno-cache-volatile
- +Volatile memory access bypass the cache using the io variants of
- +the ld and st instructions. The default is to cache volatile
- +accesses.
- +
- +-mno-cache-volatile is deprecated and will be deleted in a
- +future GCC release.
- +
- +
- +@item -mno-inline-memcpy
- +@itemx -minline-memcpy
- +@opindex mno-inline-memcpy
- +@opindex minline-memcpy
- +Do not inline memcpy. The default is to inline when -O is on.
- +
- +
- +@item -mno-fast-sw-div
- +@itemx -mfast-sw-div
- +@opindex mno-fast-sw-div
- +@opindex mfast-sw-div
- +Do no use table based fast divide for small numbers. The default
- +is to use the fast divide at -O3 and above.
- +
- +
- +@item -mno-hw-mul
- +@itemx -mhw-mul
- +@itemx -mno-hw-mulx
- +@itemx -mhw-mulx
- +@itemx -mno-hw-div
- +@itemx -mhw-div
- +@opindex mno-hw-mul
- +@opindex mhw-mul
- +@opindex mno-hw-mulx
- +@opindex mhw-mulx
- +@opindex mno-hw-div
- +@opindex mhw-div
- +Enable or disable emitting @code{mul}, @code{mulx} and @code{div} family of
- +instructions by the compiler. The default is to emit @code{mul}
- +and not emit @code{div} and @code{mulx}.
- +
- +The different combinations of @code{mul} and @code{mulx} instructions
- +generate a different multilib options.
- +
- +@item -mno-stack-check
- +@itemx -mstack-check
- +@opindex no-stack-check
- +@opindex stack-check
- +Enables or disables the checking for sufficient memory when
- +items are pushed onto the stack. A checked and non-checked
- +version of each of the multilibs is provided.
- +
- +@item -msys-crt0=@var{startfile}
- +@opindex msys-crt0
- +@var{startfile} is the file name of the startfile (crt0) to use
- +when linking. The default is crt0.o that comes with libgloss
- +and is only suitable for use with the instruction set
- +simulator.
- +
- +@item -msys-lib=@var{systemlib}
- +@itemx -msys-lib=nosys
- +@opindex msys-lib
- +@var{systemlib} is the library name of the library which provides
- +the system calls required by the C library, e.g. @code{read}, @code{write}
- +etc. The default is to use nosys, this library provides
- +stub implementations of the calls and is part of libgloss.
- +
- +@item -mno-reverse-bitfields
- +@itemx -mreverse-bitfields
- +@opindex mno-reverse-bitfields
- +@opindex mreverse-bitfields
- +When enabled, bitfields within a struct are allocated in reverse order.
- +This is useful with legacy code that depends on the (inherently
- +non-portable) ordering of bitfields via a union. Given:
- +
- +@smallexample
- +struct inner
- +@{
- + unsigned int a:1;
- + unsigned int b:31;
- +@};
- +
- +union outer
- +@{
- + struct inner inner;
- + unsigned int val;
- +@};
- +
- +unsigned int f()
- +@{
- + union outer o;
- + o.inner.a = 1;
- + o.inner.b = 0;
- + return o.val;
- +@}
- +@end smallexample
- +
- +a call to @code{f} will return 1 when compiled with
- +@option{-mno-reverse-bitfields} (the default), or 2147483648 when
- +compiled with @option{-mreverse-bitfields}.
- +
- +For structures that are a multiple of 32 bits wide, the reversal is
- +done 32 bits at a time. For structures that are an odd multiple of 16
- +bits wide, the reversal is done 16 bits at a time. For structures
- +that are an odd multiple of 8 bits wide, the reversal is done 8 bits
- +at a time. The size of a structure (as measured by the @code{sizeof}
- +operator) never changes between @option{-mno-reverse-bitfields} and
- +@option{-mreverse-bitfields}. Nonetheless, there can be some
- +confusing corner cases with structs where the compiler has to add
- +additional padding to meet alignment restrictions. Consider:
- +
- +@smallexample
- +struct inner
- +@{
- + unsigned int a:1;
- + unsigned int b:15;
- +@};
- +
- +union outer
- +@{
- + struct inner inner;
- + unsigned int val;
- +@};
- +
- +unsigned int f()
- +@{
- + union outer o;
- + o.val = 0;
- + o.inner.b = 1;
- + return o.val;
- +@}
- +@end smallexample
- +
- +a call to @code{f} will return 2 when compiled with
- +@option{-mno-reverse-bitfields} (the default), or 65536 when compiled
- +with @option{-mreverse-bitfields}. This is because @code{sizeof
- +(inner)} is 4 in both cases. In the @option{-mno-reverse-bitfields}
- +case, the compiler pads the struct at the end to be 4 bytes long,
- +effectively doing:
- +
- +@smallexample
- +struct inner
- +@{
- + unsigned int a:1;
- + unsigned int b:15;
- + unsigned int padding:16;
- +@};
- +@end smallexample
- +
- +In the @option{-mreverse-bitfields} case, the hidden padding is
- +reversed along with everything else, yielding the equivalent of:
- +
- +@smallexample
- +struct inner
- +@{
- + unsigned int padding:16;
- + unsigned int b:15;
- + unsigned int a:1;
- +@};
- +@end smallexample
- +
- +Of course, if we would rather that @code{sizeof (inner)} was 2, we could
- +write the struct as:
- +
- +@smallexample
- +struct inner
- +@{
- + unsigned short a:1;
- + unsigned short b:15;
- +@};
- +@end smallexample
- +
- +and the padding would go away.
- +
- +In some cases, especially when using the @code{__packed__} attribute,
- +there is no well-defined bit reversal that is possible: the compiler
- +will issue an error message in this case. Consider:
- +
- +@smallexample
- +struct invalid
- +@{
- + unsigned int f1:1;
- + unsigned int f2:15;
- + unsigned int f3:4;
- + unsigned int f4:4;
- +@} __attribute__ ((__packed__));
- +@end smallexample
- +
- +Since @code{sizeof (invalid)} is 3, we are forced to try reversing
- +individual bytes in the struct. But f2 is more than a byte wide, so
- +we can't reverse it and still have it be contiguous. Similar cases
- +occur when dealing with arrays or other large contiguous objects:
- +
- +@smallexample
- +struct invalid2
- +@{
- + unsigned char f1[5];
- + unsigned char f2[3];
- +@};
- +@end smallexample
- +
- +You'll have to rewrite the affected structs to say exactly what you
- +mean in odd cases like that.
- +
- +Finally, note that individual fields are sized as a whole. The structs
- +
- +@smallexample
- +struct array1
- +@{
- + unsigned char f1[3];
- + unsigned char f2;
- +@}
- +@end smallexample
- +
- +and:
- +
- +@smallexample
- +struct array2
- +@{
- + unsigned char f1a;
- + unsigned char f1b;
- + unsigned char f1c;
- + unsigned char f2;
- +@}
- +@end smallexample
- +
- +are not equivalent. When compiled with @option{-mreverse-bitfields},
- +they behave the same as:
- +
- +@smallexample
- +struct array1r
- +@{
- + unsigned char f2;
- + unsigned char f1[3];
- +@}
- +@end smallexample
- +
- +and:
- +
- +@smallexample
- +struct array2r
- +@{
- + unsigned char f2;
- + unsigned char f1c;
- + unsigned char f1b;
- + unsigned char f1a;
- +@}
- +@end smallexample
- +
- +would, respectively, when compiled with
- +@option{-mno-reverse-bitfields}. In particular, f1 is treated as a
- +single contiguous 24-bit object for purposes of reversal, while f1a,
- +f1b, and f1c are treated as individual 8-bit objects that need not
- +(and do not) remain contiguous. Use caution.
- +
- +@end table
- +
- +
- @node M680x0 Options
- @subsection M680x0 Options
- @cindex M680x0 options
- diff --git a/gcc/doc/md.texi b/gcc/doc/md.texi
- index b73f325..4a134b2 100644
- --- a/gcc/doc/md.texi
- +++ b/gcc/doc/md.texi
- @@ -1337,6 +1337,58 @@ However, here is a summary of the machine-dependent constraints
- available on some particular machines.
-
- @table @emph
- +
- +@item Altera Nios II family---@file{nios2.h}
- +@table @code
- +
- +@item I
- +Integer that is valid as an immediate operand in an
- +instruction taking a signed 16-bit number. Range
- +@minus{}32768 to 32767.
- +
- +@item J
- +Integer that is valid as an immediate operand in an
- +instruction taking an unsigned 16-bit number. Range
- +0 to 65535.
- +
- +@item K
- +Integer that is valid as an immediate operand in an
- +instruction taking only the upper 16-bits of a
- +32-bit number. Range 32-bit numbers with the lower
- +16-bits being 0.
- +
- +@item L
- +Integer that is valid as an immediate operand for a
- +shift instruction. Range 0 to 31.
- +
- +
- +@item M
- +Integer that is valid as an immediate operand for
- +only the value 0. Can be used in conjunction with
- +the format modifier @code{z} to use @code{r0}
- +instead of @code{0} in the assembly output.
- +
- +@item N
- +Integer that is valid as an immediate operand for
- +a custom instruction opcode. Range 0 to 255.
- +
- +@item S
- +Matches immediates which are addresses in the small
- +data section and therefore can be added to @code{gp}
- +as a 16-bit immediate to re-create their 32-bit value.
- +
- +@item D@var{nn}
- +For a given two digit @var{nn} constrains the operand
- +to the corresponding register. Example: D02 forces the
- +operand into register r2. The side effect of using this
- +operand constraint is that reload may not be able to
- +meet the constraint. If reload fails, an error message
- +about failing to find any register to spill in the
- +D@var{nn}_REG register class will be emitted.
- +
- +@end table
- +
- +
- @item ARM family---@file{arm.h}
- @table @code
- @item f
- diff --git a/gcc/stor-layout.c b/gcc/stor-layout.c
- index 4527fe4..e7cc581 100644
- --- a/gcc/stor-layout.c
- +++ b/gcc/stor-layout.c
- @@ -1435,6 +1435,355 @@ finalize_type_size (tree type)
- }
- }
-
- +static void
- +reverse_bitfield_layout (record_layout_info rli)
- +{
- + tree field;
- + tree rev_size;
- + unsigned int rev_size_int;
- +
- + /*
- + * The size of the words we'll be reversing. Normally, we reverse
- + * entire SImode words. However, if the entire struct's size isn't an
- + * exact multiple of the size of SImode, we can reverse HImode or even
- + * QImode pieces. In the examples below, assume SImode/int is 32
- + * bits, HImode/short is 16 bits, and QImode/char is 8 bits.
- + * Consider:
- + *
- + * struct s1
- + * {
- + * int f1:1;
- + * int f2:31;
- + * };
- + *
- + * struct s2
- + * {
- + * int f1:1;
- + * int f2:15;
- + * } __attribute__ ((__packed__));
- + *
- + * struct s3
- + * {
- + * short f1:1;
- + * short f2:15;
- + * };
- + *
- + * struct s4
- + * {
- + * int f1:1;
- + * int f2:15;
- + * };
- + *
- + * struct s5
- + * {
- + * int f1:8;
- + * int f2:8;
- + * int f3:4;
- + * int f4:4;
- + * } __attribute__ ((__packed__));
- + *
- + * struct s6
- + * {
- + * int f1:1;
- + * int f2:15;
- + * int f3:4;
- + * int f4:4;
- + * int f5:8;
- + * };
- + *
- + * struct s7
- + * {
- + * int f1:1;
- + * int f2:15;
- + * int f3:4;
- + * int f4:4;
- + * } __attribute__ ((__packed__));
- + *
- + * struct s8
- + * {
- + * char f1;
- + * short f2;
- + * char f3;
- + * };
- + *
- + * struct s9
- + * {
- + * char f1;
- + * short f2;
- + * char f3;
- + * } __attribute__ ((__packed__));
- + *
- + * struct s10
- + * {
- + * char f1;
- + * short f2;
- + * char f3;
- + * short f4;
- + * };
- + *
- + * struct s11
- + * {
- + * char f1[5];
- + * int f2;
- + * };
- + *
- + * struct s12
- + * {
- + * char f1[5];
- + * char f2[3];
- + * int f3;
- + * };
- + *
- + * struct s13
- + * {
- + * char f1[3];
- + * int f2;
- + * };
- + *
- + * struct s14
- + * {
- + * char f1a;
- + * char f1b;
- + * char f1c;
- + * int f2;
- + * };
- + *
- + * Then we have:
- + *
- + * sizeof (struct s1) == 4
- + * sizeof (struct s2) == 2
- + * sizeof (struct s3) == 2
- + * sizeof (struct s4) == 4
- + * sizeof (struct s5) == 3
- + * sizeof (struct s6) == 4
- + * sizeof (struct s7) == 3
- + * sizeof (struct s8) == 6
- + * sizeof (struct s9) == 4
- + * sizeof (struct s10) == 8
- + * sizeof (struct s11) == 12
- + * sizeof (struct s12) == 12
- + *
- + * We want the equivalent reversed bitfield structs to be:
- + *
- + * struct s1r
- + * {
- + * int f2:31;
- + * int f1:1;
- + * };
- + *
- + * struct s2r
- + * {
- + * int f2:15;
- + * int f1:1;
- + * } __attribute__ ((__packed__));
- + *
- + * struct s3r
- + * {
- + * short f2:15;
- + * short f1:1;
- + * };
- + *
- + * struct s4r
- + * {
- + * int unnamed:16;
- + * int f2:15;
- + * int f1:1;
- + * };
- + *
- + * struct s5r
- + * {
- + * int f1:8;
- + * int f2:8;
- + * int f4:4;
- + * int f3:4;
- + * } __attribute__ ((__packed__));
- + *
- + * struct s6r
- + * {
- + * int f5:8;
- + * int f4:4;
- + * int f3:4;
- + * int f2:15;
- + * int f1:1;
- + * };
- + *
- + * struct s7r
- + * {
- + * #error cannot reverse bitfield
- + * } __attribute__ ((__packed__));
- + *
- + * struct s8r
- + * {
- + * char unnamed1;
- + * char f1;
- + * short f2;
- + * char unnamed2;
- + * char f3;
- + * };
- + *
- + * struct s9r
- + * {
- + * char f3;
- + * short f2;
- + * char f1;
- + * } __attribute__ ((__packed__));
- + *
- + * struct s10r
- + * {
- + * short f2;
- + * char unnamed1;
- + * char f1;
- + * short f4;
- + * char unnamed2;
- + * char f3;
- + * };
- + *
- + * struct s11r
- + * {
- + * char f1[5];
- + * int f2;
- + * };
- + *
- + * struct s12r
- + * {
- + * #error cannot reverse bitfield
- + * };
- + *
- + * struct s13r
- + * {
- + * char unnamed;
- + * char f1[3];
- + * int f2;
- + * };
- + *
- + * struct s14r
- + * {
- + * char unnamed;
- + * char f1c;
- + * char f1b;
- + * char f1a;
- + * int f2;
- + * };
- + *
- + * Note that the s4, s8, s10, s13, and s14 cases produce somewhat
- + * suprising results: the normally hidden padding bytes the compiler
- + * adds are also reversed. Further note that s13 and s14 are not
- + * equivalent: the f1 field in s13 is 24-bits wide, and is reversed
- + * accordingly, while the three fields f1a, f1b, and f1c in s14 are
- + * reversed as individual bytes.
- + *
- + * The s7 and s12 cases produce an error: we can't reverse a bitfield
- + * that is larger than word size we're reversing. The error is
- + * suppressed in the s11 case since the field in question and the
- + * field that follows are both word aligned.
- + */
- +
- + /*
- + * First, figure out what size words to reverse. We look at the total
- + * number of bits currently in use by the struct, rounded up to the
- + * next multiple of rli->record_align, to decide.
- + */
- + {
- + int bits_in_use = TREE_INT_CST_LOW (round_up (rli_size_so_far (rli),
- + rli->record_align));
- + unsigned int size;
- + for (size = GET_MODE_BITSIZE (SImode);
- + size >= GET_MODE_BITSIZE (QImode);
- + size /= 2)
- + {
- + if (bits_in_use % size == 0)
- + {
- + break;
- + }
- + }
- + if (size < GET_MODE_BITSIZE (QImode))
- + {
- + /*
- + * rli->record_align should never be less than QImode, even
- + * for packed structs.
- + */
- + abort ();
- + }
- + rev_size = size_int_type (size, bitsizetype);
- + rev_size_int = size;
- + }
- +
- + /*
- + * Then, iterate over the fields, reversing them as we go.
- + */
- + for (field = TYPE_FIELDS (rli->t); field; field = TREE_CHAIN (field))
- + {
- + tree type = TREE_TYPE (field);
- + if (TREE_CODE (field) != FIELD_DECL)
- + {
- + continue;
- + }
- + if (TREE_CODE (field) == ERROR_MARK || TREE_CODE (type) == ERROR_MARK)
- + {
- + return;
- + }
- + {
- + tree offset = DECL_FIELD_OFFSET (field);
- + tree offset_type = TREE_TYPE (offset);
- + tree bit_offset = DECL_FIELD_BIT_OFFSET (field);
- + tree bit_offset_type = TREE_TYPE (bit_offset);
- + tree bit = bit_from_pos (offset, bit_offset);
- + tree true_size = DECL_SIZE (field);
- + pos_from_bit (&offset, &bit_offset, rev_size_int, bit);
- + bit_offset = size_binop (MINUS_EXPR,
- + size_binop (MINUS_EXPR, rev_size, true_size),
- + bit_offset);
- + if (TREE_INT_CST_HIGH (bit_offset) != 0)
- + {
- + /*
- + * This happens when a field spans a rev_size boundary (see
- + * example s7 above): rather than try to come up with some
- + * well-defined, but non-intuitive definition for this case,
- + * just issue an error. It can also happen for large fields,
- + * e.g. arrays or other structs: if these large fields were
- + * already aligned, leave them be; otherwise issue the error
- + * in this case as well.
- + */
- + if ((TREE_INT_CST_HIGH (true_size) != 0
- + || TREE_INT_CST_LOW (true_size) > rev_size_int)
- + && TREE_INT_CST_HIGH (DECL_FIELD_BIT_OFFSET (field)) == 0
- + && TREE_INT_CST_LOW (DECL_FIELD_BIT_OFFSET (field)) == 0)
- + {
- + tree next_field = TREE_CHAIN (field);
- + if (!next_field)
- + {
- + /* No following field, so we're ok. */
- + continue;
- + }
- + else
- + {
- + tree next_offset = DECL_FIELD_OFFSET (next_field);
- + tree next_bit_offset = DECL_FIELD_BIT_OFFSET (next_field);
- + tree next_bit = bit_from_pos (next_offset, next_bit_offset);
- + pos_from_bit (&next_offset, &next_bit_offset, rev_size_int,
- + next_bit);
- + if (TREE_INT_CST_HIGH (next_bit_offset) == 0
- + && TREE_INT_CST_LOW (next_bit_offset) == 0)
- + {
- + /* Following field is aligned wrt rev_size_int boundary,
- + so we're ok. */
- + continue;
- + }
- + }
- + }
- + error ("unable to reverse bitfields in structure");
- + return;
- + }
- + bit = bit_from_pos (offset, bit_offset);
- + pos_from_bit (&offset, &bit_offset, rli->offset_align, bit);
- + TREE_TYPE (offset) = offset_type;
- + DECL_FIELD_OFFSET (field) = offset;
- + TREE_TYPE (bit_offset) = bit_offset_type;
- + DECL_FIELD_BIT_OFFSET (field) = bit_offset;
- + }
- + }
- +}
- +
- /* Do all of the work required to layout the type indicated by RLI,
- once the fields have been laid out. This function will call `free'
- for RLI, unless FREE_P is false. Passing a value other than false
- @@ -1444,6 +1793,12 @@ finalize_type_size (tree type)
- void
- finish_record_layout (record_layout_info rli, int free_p)
- {
- + /* Optionally reverse the placement of bitfields within the record */
- + if ((* targetm.reverse_bitfield_layout_p) (rli->t))
- + {
- + reverse_bitfield_layout (rli);
- + }
- +
- /* Compute the final size. */
- finalize_record_size (rli);
-
- diff --git a/gcc/target-def.h b/gcc/target-def.h
- index 32d00ae..bdea4d4 100644
- --- a/gcc/target-def.h
- +++ b/gcc/target-def.h
- @@ -300,6 +300,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- #define TARGET_INSERT_ATTRIBUTES hook_void_tree_treeptr
- #define TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P hook_bool_tree_false
- #define TARGET_MS_BITFIELD_LAYOUT_P hook_bool_tree_false
- +#define TARGET_REVERSE_BITFIELD_LAYOUT_P hook_bool_tree_false
- #define TARGET_RTX_COSTS hook_bool_rtx_int_int_intp_false
- #define TARGET_MANGLE_FUNDAMENTAL_TYPE hook_constcharptr_tree_null
-
- @@ -368,6 +369,7 @@ Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
- TARGET_INSERT_ATTRIBUTES, \
- TARGET_FUNCTION_ATTRIBUTE_INLINABLE_P, \
- TARGET_MS_BITFIELD_LAYOUT_P, \
- + TARGET_REVERSE_BITFIELD_LAYOUT_P, \
- TARGET_INIT_BUILTINS, \
- TARGET_EXPAND_BUILTIN, \
- TARGET_MANGLE_FUNDAMENTAL_TYPE, \
- diff --git a/gcc/target.h b/gcc/target.h
- index 59788f9..97bde5f 100644
- --- a/gcc/target.h
- +++ b/gcc/target.h
- @@ -295,6 +295,10 @@ struct gcc_target
- Microsoft Visual C++ bitfield layout rules. */
- bool (* ms_bitfield_layout_p) (tree record_type);
-
- + /* Return true if bitfields in RECORD_TYPE should be allocated
- + within their base type's bytes starting at the opposite end. */
- + bool (* reverse_bitfield_layout_p) (tree record_type);
- +
- /* Set up target-specific built-in functions. */
- void (* init_builtins) (void);
-
- diff --git a/gcc/varasm.c b/gcc/varasm.c
- index 33307e5..d4ed0fc 100644
- --- a/gcc/varasm.c
- +++ b/gcc/varasm.c
- @@ -3912,6 +3912,107 @@ array_size_for_constructor (tree val)
- return tree_low_cst (i, 1);
- }
-
- +struct reorder_bitfields_key
- +{
- + tree field;
- + tree value;
- +};
- +
- +static int
- +reorder_bitfields_compare (const void *x1, const void *x2)
- +{
- + const struct reorder_bitfields_key *key1 = x1;
- + const struct reorder_bitfields_key *key2 = x2;
- + int pos1 = int_bit_position (key1->field);
- + int pos2 = int_bit_position (key2->field);
- +
- + if (pos1 < pos2)
- + {
- + return -1;
- + }
- + else if (pos1 > pos2)
- + {
- + return 1;
- + }
- + else
- + {
- + /*
- + * No two fields should ever have the same bit_position, so
- + * something is horribly wrong.
- + */
- + abort ();
- + }
- +}
- +
- +static void
- +reorder_bitfields (tree *first_field, tree *first_value)
- +{
- + struct reorder_bitfields_key *keys;
- + size_t field_count;
- + tree field;
- + tree value;
- + size_t i;
- +
- + /*
- + * Find out how many fields are in this record, and allocate an array
- + * of keys to hold them all.
- + */
- + field_count = 0;
- + for (field = *first_field; field; field = TREE_CHAIN (field))
- + {
- + field_count++;
- + }
- + if (field_count < 2)
- + {
- + return;
- + }
- + keys = xmalloc (sizeof (struct reorder_bitfields_key) * field_count);
- +
- + /*
- + * Make copies of the existing fields and values (using signed integer
- + * zeros for missing values) in the array of keys.
- + */
- + field = *first_field;
- + value = *first_value;
- + for (i = 0; i < field_count; i++)
- + {
- + keys[i].field = copy_node (field);
- + field = TREE_CHAIN (field);
- + if (value)
- + {
- + keys[i].value = copy_node (value);
- + TREE_PURPOSE (keys[i].value) = keys[i].field;
- + value = TREE_CHAIN (value);
- + }
- + else
- + {
- + keys[i].value = tree_cons (keys[i].field, ssize_int (0), 0);
- + }
- + }
- +
- + /*
- + * Sort the array based on position of the fields in the record.
- + */
- + qsort (keys, field_count, sizeof (struct reorder_bitfields_key),
- + reorder_bitfields_compare);
- +
- + /*
- + * Build new lists out of the sorted array.
- + */
- + for (i = 0; i < field_count - 1; i++)
- + {
- + TREE_CHAIN (keys[i].field) = keys[i+1].field;
- + TREE_CHAIN (keys[i].value) = keys[i+1].value;
- + }
- + *first_field = keys[0].field;
- + *first_value = keys[0].value;
- +
- + /*
- + * Get rid of our array of keys and we're done.
- + */
- + free (keys);
- +}
- +
- /* Subroutine of output_constant, used for CONSTRUCTORs (aggregate constants).
- Generate at least SIZE bytes, padding if necessary. */
-
- @@ -3928,12 +4029,29 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
- /* Nonzero means BYTE contains part of a byte, to be output. */
- int byte_buffer_in_use = 0;
- int byte = 0;
- + tree first_link = CONSTRUCTOR_ELTS (exp);
-
- if (HOST_BITS_PER_WIDE_INT < BITS_PER_UNIT)
- abort ();
-
- if (TREE_CODE (type) == RECORD_TYPE)
- + {
- + if ((*targetm.reverse_bitfield_layout_p) (type))
- + {
- + /*
- + * If we're reversing bitfields, we have to reverse the order in
- + * which constructors containing bitfields are output. The
- + * easiest way to do that is to reorder the constructor elements
- + * and fields to be in memory-order.
- + */
- field = TYPE_FIELDS (type);
- + reorder_bitfields (&field, &first_link);
- + }
- + else
- + {
- + field = TYPE_FIELDS (type);
- + }
- + }
-
- if (TREE_CODE (type) == ARRAY_TYPE
- && TYPE_DOMAIN (type) != 0)
- @@ -3948,7 +4066,7 @@ output_constructor (tree exp, unsigned HOST_WIDE_INT size,
- There is always a maximum of one element in the chain LINK for unions
- (even if the initializer in a source program incorrectly contains
- more one). */
- - for (link = CONSTRUCTOR_ELTS (exp);
- + for (link = first_link;
- link;
- link = TREE_CHAIN (link),
- field = field ? TREE_CHAIN (field) : 0)
|