1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381738273837384738573867387738873897390739173927393739473957396739773987399740074017402740374047405740674077408740974107411741274137414741574167417741874197420742174227423742474257426742774287429743074317432743374347435743674377438743974407441744274437444744574467447744874497450745174527453745474557456745774587459746074617462746374647465746674677468746974707471747274737474747574767477747874797480748174827483748474857486748774887489749074917492749374947495749674977498749975007501750275037504750575067507750875097510751175127513751475157516751775187519752075217522752375247525752675277528752975307531753275337534753575367537753875397540754175427543754475457546754775487549755075517552755375547555755675577558755975607561756275637564756575667567756875697570757175727573757475757576757775787579758075817582758375847585758675877588758975907591759275937594759575967597759875997600760176027603760476057606760776087609761076117612761376147615761676177618761976207621762276237624762576267627762876297630763176327633763476357636763776387639764076417642764376447645764676477648764976507651765276537654765576567657765876597660766176627663766476657666766776687669767076717672767376747675767676777678767976807681768276837684768576867687768876897690769176927693769476957696769776987699770077017702770377047705770677077708770977107711771277137714771577167717771877197720772177227723772477257726772777287729773077317732773377347735773677377738773977407741774277437744774577467747774877497750775177527753775477557756775777587759776077617762776377647765776677677768776977707771777277737774777577767777777877797780778177827783778477857786778777887789779077917792779377947795779677977798779978007801780278037804780578067807780878097810781178127813781478157816781778187819782078217822782378247825782678277828782978307831783278337834783578367837783878397840784178427843784478457846784778487849785078517852785378547855785678577858785978607861786278637864786578667867786878697870787178727873787478757876787778787879788078817882788378847885788678877888788978907891789278937894789578967897789878997900790179027903790479057906790779087909791079117912791379147915791679177918791979207921792279237924792579267927792879297930793179327933793479357936793779387939794079417942794379447945794679477948794979507951795279537954795579567957795879597960796179627963796479657966796779687969797079717972797379747975797679777978797979807981798279837984798579867987798879897990799179927993799479957996799779987999800080018002800380048005800680078008800980108011801280138014801580168017801880198020802180228023802480258026802780288029803080318032803380348035803680378038803980408041804280438044804580468047804880498050805180528053805480558056805780588059806080618062806380648065806680678068806980708071807280738074807580768077807880798080808180828083808480858086808780888089809080918092809380948095809680978098809981008101810281038104810581068107810881098110811181128113811481158116811781188119812081218122812381248125812681278128812981308131813281338134813581368137813881398140814181428143814481458146814781488149815081518152815381548155815681578158815981608161816281638164816581668167816881698170817181728173817481758176817781788179818081818182818381848185818681878188818981908191819281938194819581968197819881998200820182028203820482058206820782088209821082118212821382148215821682178218821982208221822282238224822582268227822882298230823182328233823482358236823782388239824082418242824382448245824682478248824982508251825282538254825582568257825882598260826182628263826482658266826782688269827082718272827382748275827682778278827982808281828282838284828582868287828882898290829182928293829482958296829782988299830083018302830383048305830683078308830983108311831283138314831583168317831883198320832183228323832483258326832783288329833083318332833383348335833683378338833983408341834283438344834583468347834883498350835183528353835483558356835783588359836083618362836383648365836683678368836983708371837283738374837583768377837883798380838183828383838483858386838783888389839083918392839383948395839683978398839984008401840284038404840584068407840884098410841184128413841484158416841784188419842084218422842384248425842684278428842984308431843284338434843584368437843884398440844184428443844484458446844784488449845084518452845384548455845684578458845984608461846284638464846584668467846884698470847184728473847484758476847784788479848084818482848384848485848684878488848984908491849284938494849584968497849884998500850185028503850485058506850785088509851085118512851385148515851685178518851985208521852285238524852585268527852885298530853185328533853485358536853785388539854085418542854385448545854685478548854985508551855285538554855585568557855885598560856185628563856485658566856785688569857085718572857385748575857685778578857985808581858285838584858585868587858885898590859185928593859485958596859785988599860086018602860386048605860686078608860986108611861286138614861586168617861886198620862186228623862486258626862786288629863086318632863386348635863686378638863986408641864286438644864586468647864886498650865186528653865486558656865786588659866086618662866386648665866686678668866986708671867286738674867586768677867886798680868186828683868486858686868786888689869086918692869386948695869686978698869987008701870287038704870587068707870887098710871187128713871487158716871787188719872087218722872387248725872687278728872987308731873287338734873587368737873887398740874187428743874487458746874787488749875087518752875387548755875687578758875987608761876287638764876587668767876887698770877187728773877487758776877787788779878087818782878387848785878687878788878987908791879287938794879587968797879887998800880188028803880488058806880788088809881088118812881388148815881688178818881988208821882288238824882588268827882888298830883188328833883488358836883788388839884088418842884388448845884688478848884988508851885288538854885588568857885888598860886188628863886488658866886788688869887088718872887388748875887688778878887988808881888288838884888588868887888888898890889188928893889488958896889788988899890089018902890389048905890689078908890989108911891289138914891589168917891889198920892189228923892489258926892789288929893089318932893389348935893689378938893989408941894289438944894589468947894889498950895189528953895489558956895789588959896089618962896389648965896689678968896989708971897289738974897589768977897889798980898189828983898489858986898789888989899089918992899389948995899689978998899990009001900290039004900590069007900890099010901190129013901490159016901790189019902090219022902390249025902690279028902990309031903290339034903590369037903890399040904190429043904490459046904790489049905090519052905390549055905690579058905990609061906290639064906590669067906890699070907190729073907490759076907790789079908090819082908390849085908690879088908990909091909290939094909590969097909890999100910191029103910491059106910791089109911091119112911391149115911691179118911991209121912291239124912591269127912891299130913191329133913491359136913791389139914091419142914391449145914691479148914991509151915291539154915591569157915891599160916191629163916491659166916791689169917091719172917391749175917691779178917991809181918291839184918591869187918891899190919191929193919491959196919791989199920092019202920392049205920692079208920992109211921292139214921592169217921892199220922192229223922492259226922792289229923092319232923392349235923692379238923992409241924292439244924592469247924892499250925192529253925492559256925792589259926092619262926392649265926692679268926992709271927292739274927592769277927892799280928192829283928492859286928792889289929092919292929392949295929692979298929993009301930293039304930593069307930893099310931193129313931493159316931793189319932093219322932393249325932693279328932993309331933293339334933593369337933893399340934193429343934493459346934793489349935093519352935393549355935693579358935993609361936293639364936593669367936893699370937193729373937493759376937793789379938093819382938393849385938693879388938993909391939293939394939593969397939893999400940194029403940494059406940794089409941094119412941394149415941694179418941994209421942294239424942594269427942894299430943194329433943494359436943794389439944094419442944394449445944694479448944994509451945294539454945594569457945894599460946194629463946494659466946794689469947094719472947394749475947694779478947994809481948294839484948594869487948894899490949194929493949494959496949794989499950095019502950395049505950695079508950995109511951295139514951595169517951895199520952195229523952495259526952795289529953095319532953395349535953695379538953995409541954295439544954595469547954895499550955195529553955495559556955795589559956095619562956395649565956695679568956995709571957295739574957595769577957895799580958195829583958495859586958795889589959095919592959395949595959695979598959996009601960296039604960596069607960896099610961196129613961496159616961796189619962096219622962396249625962696279628962996309631963296339634963596369637963896399640964196429643964496459646964796489649965096519652965396549655965696579658965996609661966296639664966596669667966896699670967196729673967496759676967796789679968096819682968396849685968696879688968996909691969296939694969596969697969896999700970197029703970497059706970797089709971097119712971397149715971697179718971997209721972297239724972597269727972897299730973197329733973497359736973797389739974097419742974397449745974697479748974997509751975297539754975597569757975897599760976197629763976497659766976797689769977097719772977397749775977697779778977997809781978297839784978597869787978897899790979197929793979497959796979797989799980098019802980398049805980698079808980998109811981298139814981598169817981898199820982198229823982498259826982798289829983098319832983398349835983698379838983998409841984298439844984598469847984898499850985198529853985498559856985798589859986098619862986398649865986698679868986998709871987298739874987598769877987898799880988198829883988498859886988798889889989098919892989398949895989698979898989999009901990299039904990599069907990899099910991199129913991499159916991799189919992099219922992399249925992699279928992999309931993299339934993599369937993899399940994199429943994499459946994799489949995099519952995399549955995699579958995999609961996299639964996599669967996899699970997199729973997499759976997799789979998099819982998399849985998699879988998999909991999299939994999599969997999899991000010001100021000310004100051000610007100081000910010100111001210013100141001510016100171001810019100201002110022100231002410025100261002710028100291003010031100321003310034100351003610037100381003910040100411004210043100441004510046100471004810049100501005110052100531005410055100561005710058100591006010061100621006310064100651006610067100681006910070100711007210073100741007510076100771007810079100801008110082100831008410085100861008710088100891009010091100921009310094100951009610097100981009910100101011010210103101041010510106101071010810109101101011110112101131011410115101161011710118101191012010121101221012310124101251012610127101281012910130101311013210133101341013510136101371013810139101401014110142101431014410145101461014710148101491015010151101521015310154101551015610157101581015910160101611016210163101641016510166101671016810169101701017110172101731017410175101761017710178101791018010181101821018310184101851018610187101881018910190101911019210193101941019510196101971019810199102001020110202102031020410205102061020710208102091021010211 |
- --- gcc-3.4.3/gcc/Makefile.in
- +++ gcc-3.4.3-nios2/gcc/Makefile.in
- @@ -3085,7 +3085,7 @@ install-mkheaders: stmp-int-hdrs $(STMP_
- $(INSTALL_DATA) $(srcdir)/README-fixinc \
- $(DESTDIR)$(itoolsdatadir)/include/README ; \
- $(INSTALL_SCRIPT) fixinc.sh $(DESTDIR)$(itoolsdir)/fixinc.sh ; \
- - $(INSTALL_PROGRAM) fixinc/fixincl $(DESTDIR)$(itoolsdir)/fixincl ; \
- + $(INSTALL_PROGRAM) fixinc/fixincl$(build_exeext) $(DESTDIR)$(itoolsdir)/fixincl$(build_exeext) ; \
- $(INSTALL_DATA) $(srcdir)/gsyslimits.h \
- $(DESTDIR)$(itoolsdatadir)/gsyslimits.h ; \
- else :; fi
- --- gcc-3.4.3/gcc/combine.c
- +++ gcc-3.4.3-nios2/gcc/combine.c
- @@ -4380,6 +4380,14 @@ combine_simplify_rtx (rtx x, enum machin
- 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
- @@ -4391,6 +4399,7 @@ combine_simplify_rtx (rtx x, enum machin
- gen_lowpart_for_combine (mode, op0),
- const1_rtx);
- }
- +#endif
-
- else if (STORE_FLAG_VALUE == 1
- && new_code == EQ && GET_MODE_CLASS (mode) == MODE_INT
- --- gcc-3.4.3/gcc/config/nios2/crti.asm
- +++ gcc-3.4.3-nios2/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
- +
- +
- --- gcc-3.4.3/gcc/config/nios2/crtn.asm
- +++ gcc-3.4.3-nios2/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
- +
- --- gcc-3.4.3/gcc/config/nios2/lib2-divmod-hi.c
- +++ gcc-3.4.3-nios2/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);
- +}
- +
- --- gcc-3.4.3/gcc/config/nios2/lib2-divmod.c
- +++ gcc-3.4.3-nios2/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);
- +}
- +
- --- gcc-3.4.3/gcc/config/nios2/lib2-divtable.c
- +++ gcc-3.4.3-nios2/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,
- +};
- +
- --- gcc-3.4.3/gcc/config/nios2/lib2-mul.c
- +++ gcc-3.4.3-nios2/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
- --- gcc-3.4.3/gcc/config/nios2/nios2-dp-bit.c
- +++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-dp-bit.c
- @@ -0,0 +1,1652 @@
- +
- +/* 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 */
- --- gcc-3.4.3/gcc/config/nios2/nios2-fp-bit.c
- +++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-fp-bit.c
- @@ -0,0 +1,1652 @@
- +#define FLOAT
- +/* 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 */
- --- gcc-3.4.3/gcc/config/nios2/nios2-protos.h
- +++ gcc-3.4.3-nios2/gcc/config/nios2/nios2-protos.h
- @@ -0,0 +1,70 @@
- +/* 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);
- +
- +
- +#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);
- +
- +# ifdef HAVE_MACHINE_MODES
- +# if defined TREE_CODE
- +extern void function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
- +extern rtx function_arg (const CUMULATIVE_ARGS *, enum machine_mode, tree, int);
- +extern int function_arg_partial_nregs (const CUMULATIVE_ARGS *, 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 */
- --- gcc-3.4.3/gcc/config/nios2/nios2.c
- +++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.c
- @@ -0,0 +1,2853 @@
- +/* 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. */
- +
- +
- +#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"
- +
- +/* 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);
- +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_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
- +
- +
- +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;
- +};
- +
- +
- +/***************************************
- + * Section encodings
- + ***************************************/
- +
- +
- +
- +
- +
- +/***************************************
- + * 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;
- + 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 (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)
- +{
- + fprintf (file, "\t%s mcount begin, label: .LP%d\n",
- + ASM_COMMENT_START, labelno);
- + fprintf (file, "\tnextpc\tr8\n");
- + fprintf (file, "\tmov\tr9, ra\n");
- + fprintf (file, "\tmovhi\tr10, %%hiadj(.LP%d)\n", labelno);
- + fprintf (file, "\taddi\tr10, r10, %%lo(.LP%d)\n", labelno);
- + fprintf (file, "\tcall\tmcount\n");
- + fprintf (file, "\tmov\tra, r9\n");
- + fprintf (file, "\t%s mcount end\n", ASM_COMMENT_START);
- +}
- +
- +
- +/***************************************
- + * 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;
- +}
- +
- +
- +
- +
- +
- +/***************************************
- + *
- + ***************************************/
- +
- +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= */
- +
- +void
- +override_options ()
- +{
- + /* 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;
- + }
- +
- +}
- +
- +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;
- +}
- +
- +/* 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);
- +
- + /* 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) && CONSTANT_P (op1))
- + ret_val = REG_OK_FOR_BASE_P2 (op0, strict)
- + && SMALL_INT (INTVAL (op1));
- + else if (REG_P (op1) && CONSTANT_P (op0))
- + 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 && 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;
- +}
- +
- +
- +
- +
- +/*****************************************
- + * 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
- + */
- +
- +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;
- + }
- +
- + 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;
- + }
- +
- +
- + case SUBREG:
- + case MEM:
- + if (letter == 0)
- + {
- + output_address (op);
- + return;
- + }
- +
- + case CODE_LABEL:
- + if (letter == 0)
- + {
- + output_addr_const (file, op);
- + return;
- + }
- +
- + 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));
- +}
- +
- +
- +
- +
- +
- +
- +
- +/*****************************************************************************
- +**
- +** 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;
- +}
- +
- +
- +/* 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;
- +}
- +
- +/* 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;
- +}
- +
- +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;
- + }
- +}
- +
- +
- +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,
- +
- + NIOS2_BUILTIN_CUSTOM_N,
- + NIOS2_BUILTIN_CUSTOM_NI,
- + NIOS2_BUILTIN_CUSTOM_NF,
- + NIOS2_BUILTIN_CUSTOM_NP,
- + NIOS2_BUILTIN_CUSTOM_NII,
- + NIOS2_BUILTIN_CUSTOM_NIF,
- + NIOS2_BUILTIN_CUSTOM_NIP,
- + NIOS2_BUILTIN_CUSTOM_NFI,
- + NIOS2_BUILTIN_CUSTOM_NFF,
- + NIOS2_BUILTIN_CUSTOM_NFP,
- + NIOS2_BUILTIN_CUSTOM_NPI,
- + NIOS2_BUILTIN_CUSTOM_NPF,
- + NIOS2_BUILTIN_CUSTOM_NPP,
- + NIOS2_BUILTIN_CUSTOM_IN,
- + NIOS2_BUILTIN_CUSTOM_INI,
- + NIOS2_BUILTIN_CUSTOM_INF,
- + NIOS2_BUILTIN_CUSTOM_INP,
- + NIOS2_BUILTIN_CUSTOM_INII,
- + NIOS2_BUILTIN_CUSTOM_INIF,
- + NIOS2_BUILTIN_CUSTOM_INIP,
- + NIOS2_BUILTIN_CUSTOM_INFI,
- + NIOS2_BUILTIN_CUSTOM_INFF,
- + NIOS2_BUILTIN_CUSTOM_INFP,
- + NIOS2_BUILTIN_CUSTOM_INPI,
- + NIOS2_BUILTIN_CUSTOM_INPF,
- + NIOS2_BUILTIN_CUSTOM_INPP,
- + NIOS2_BUILTIN_CUSTOM_FN,
- + NIOS2_BUILTIN_CUSTOM_FNI,
- + NIOS2_BUILTIN_CUSTOM_FNF,
- + NIOS2_BUILTIN_CUSTOM_FNP,
- + NIOS2_BUILTIN_CUSTOM_FNII,
- + NIOS2_BUILTIN_CUSTOM_FNIF,
- + NIOS2_BUILTIN_CUSTOM_FNIP,
- + NIOS2_BUILTIN_CUSTOM_FNFI,
- + NIOS2_BUILTIN_CUSTOM_FNFF,
- + NIOS2_BUILTIN_CUSTOM_FNFP,
- + NIOS2_BUILTIN_CUSTOM_FNPI,
- + NIOS2_BUILTIN_CUSTOM_FNPF,
- + NIOS2_BUILTIN_CUSTOM_FNPP,
- + NIOS2_BUILTIN_CUSTOM_PN,
- + NIOS2_BUILTIN_CUSTOM_PNI,
- + NIOS2_BUILTIN_CUSTOM_PNF,
- + NIOS2_BUILTIN_CUSTOM_PNP,
- + NIOS2_BUILTIN_CUSTOM_PNII,
- + NIOS2_BUILTIN_CUSTOM_PNIF,
- + NIOS2_BUILTIN_CUSTOM_PNIP,
- + NIOS2_BUILTIN_CUSTOM_PNFI,
- + NIOS2_BUILTIN_CUSTOM_PNFF,
- + NIOS2_BUILTIN_CUSTOM_PNFP,
- + NIOS2_BUILTIN_CUSTOM_PNPI,
- + NIOS2_BUILTIN_CUSTOM_PNPF,
- + NIOS2_BUILTIN_CUSTOM_PNPP,
- +
- +
- + 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) PARAMS ((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 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;
- +
- +static tree custom_n;
- +static tree custom_ni;
- +static tree custom_nf;
- +static tree custom_np;
- +static tree custom_nii;
- +static tree custom_nif;
- +static tree custom_nip;
- +static tree custom_nfi;
- +static tree custom_nff;
- +static tree custom_nfp;
- +static tree custom_npi;
- +static tree custom_npf;
- +static tree custom_npp;
- +static tree custom_in;
- +static tree custom_ini;
- +static tree custom_inf;
- +static tree custom_inp;
- +static tree custom_inii;
- +static tree custom_inif;
- +static tree custom_inip;
- +static tree custom_infi;
- +static tree custom_inff;
- +static tree custom_infp;
- +static tree custom_inpi;
- +static tree custom_inpf;
- +static tree custom_inpp;
- +static tree custom_fn;
- +static tree custom_fni;
- +static tree custom_fnf;
- +static tree custom_fnp;
- +static tree custom_fnii;
- +static tree custom_fnif;
- +static tree custom_fnip;
- +static tree custom_fnfi;
- +static tree custom_fnff;
- +static tree custom_fnfp;
- +static tree custom_fnpi;
- +static tree custom_fnpf;
- +static tree custom_fnpp;
- +static tree custom_pn;
- +static tree custom_pni;
- +static tree custom_pnf;
- +static tree custom_pnp;
- +static tree custom_pnii;
- +static tree custom_pnif;
- +static tree custom_pnip;
- +static tree custom_pnfi;
- +static tree custom_pnff;
- +static tree custom_pnfp;
- +static tree custom_pnpi;
- +static tree custom_pnpf;
- +static tree custom_pnpp;
- +
- +
- +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},
- +
- + {CODE_FOR_custom_n, "__builtin_custom_n", NIOS2_BUILTIN_CUSTOM_N, &custom_n, nios2_expand_custom_n},
- + {CODE_FOR_custom_ni, "__builtin_custom_ni", NIOS2_BUILTIN_CUSTOM_NI, &custom_ni, nios2_expand_custom_nX},
- + {CODE_FOR_custom_nf, "__builtin_custom_nf", NIOS2_BUILTIN_CUSTOM_NF, &custom_nf, nios2_expand_custom_nX},
- + {CODE_FOR_custom_np, "__builtin_custom_np", NIOS2_BUILTIN_CUSTOM_NP, &custom_np, nios2_expand_custom_nX},
- + {CODE_FOR_custom_nii, "__builtin_custom_nii", NIOS2_BUILTIN_CUSTOM_NII, &custom_nii, nios2_expand_custom_nXX},
- + {CODE_FOR_custom_nif, "__builtin_custom_nif", NIOS2_BUILTIN_CUSTOM_NIF, &custom_nif, nios2_expand_custom_nXX},
- + {CODE_FOR_custom_nip, "__builtin_custom_nip", NIOS2_BUILTIN_CUSTOM_NIP, &custom_nip, nios2_expand_custom_nXX},
- + {CODE_FOR_custom_nfi, "__builtin_custom_nfi", NIOS2_BUILTIN_CUSTOM_NFI, &custom_nfi, nios2_expand_custom_nXX},
- + {CODE_FOR_custom_nff, "__builtin_custom_nff", NIOS2_BUILTIN_CUSTOM_NFF, &custom_nff, nios2_expand_custom_nXX},
- + {CODE_FOR_custom_nfp, "__builtin_custom_nfp", NIOS2_BUILTIN_CUSTOM_NFP, &custom_nfp, nios2_expand_custom_nXX},
- + {CODE_FOR_custom_npi, "__builtin_custom_npi", NIOS2_BUILTIN_CUSTOM_NPI, &custom_npi, nios2_expand_custom_nXX},
- + {CODE_FOR_custom_npf, "__builtin_custom_npf", NIOS2_BUILTIN_CUSTOM_NPF, &custom_npf, nios2_expand_custom_nXX},
- + {CODE_FOR_custom_npp, "__builtin_custom_npp", NIOS2_BUILTIN_CUSTOM_NPP, &custom_npp, nios2_expand_custom_nXX},
- + {CODE_FOR_custom_in, "__builtin_custom_in", NIOS2_BUILTIN_CUSTOM_IN, &custom_in, nios2_expand_custom_Xn},
- + {CODE_FOR_custom_ini, "__builtin_custom_ini", NIOS2_BUILTIN_CUSTOM_INI, &custom_ini, nios2_expand_custom_XnX},
- + {CODE_FOR_custom_inf, "__builtin_custom_inf", NIOS2_BUILTIN_CUSTOM_INF, &custom_inf, nios2_expand_custom_XnX},
- + {CODE_FOR_custom_inp, "__builtin_custom_inp", NIOS2_BUILTIN_CUSTOM_INP, &custom_inp, nios2_expand_custom_XnX},
- + {CODE_FOR_custom_inii, "__builtin_custom_inii", NIOS2_BUILTIN_CUSTOM_INII, &custom_inii, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_inif, "__builtin_custom_inif", NIOS2_BUILTIN_CUSTOM_INIF, &custom_inif, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_inip, "__builtin_custom_inip", NIOS2_BUILTIN_CUSTOM_INIP, &custom_inip, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_infi, "__builtin_custom_infi", NIOS2_BUILTIN_CUSTOM_INFI, &custom_infi, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_inff, "__builtin_custom_inff", NIOS2_BUILTIN_CUSTOM_INFF, &custom_inff, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_infp, "__builtin_custom_infp", NIOS2_BUILTIN_CUSTOM_INFP, &custom_infp, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_inpi, "__builtin_custom_inpi", NIOS2_BUILTIN_CUSTOM_INPI, &custom_inpi, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_inpf, "__builtin_custom_inpf", NIOS2_BUILTIN_CUSTOM_INPF, &custom_inpf, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_inpp, "__builtin_custom_inpp", NIOS2_BUILTIN_CUSTOM_INPP, &custom_inpp, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_fn, "__builtin_custom_fn", NIOS2_BUILTIN_CUSTOM_FN, &custom_fn, nios2_expand_custom_Xn},
- + {CODE_FOR_custom_fni, "__builtin_custom_fni", NIOS2_BUILTIN_CUSTOM_FNI, &custom_fni, nios2_expand_custom_XnX},
- + {CODE_FOR_custom_fnf, "__builtin_custom_fnf", NIOS2_BUILTIN_CUSTOM_FNF, &custom_fnf, nios2_expand_custom_XnX},
- + {CODE_FOR_custom_fnp, "__builtin_custom_fnp", NIOS2_BUILTIN_CUSTOM_FNP, &custom_fnp, nios2_expand_custom_XnX},
- + {CODE_FOR_custom_fnii, "__builtin_custom_fnii", NIOS2_BUILTIN_CUSTOM_FNII, &custom_fnii, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_fnif, "__builtin_custom_fnif", NIOS2_BUILTIN_CUSTOM_FNIF, &custom_fnif, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_fnip, "__builtin_custom_fnip", NIOS2_BUILTIN_CUSTOM_FNIP, &custom_fnip, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_fnfi, "__builtin_custom_fnfi", NIOS2_BUILTIN_CUSTOM_FNFI, &custom_fnfi, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_fnff, "__builtin_custom_fnff", NIOS2_BUILTIN_CUSTOM_FNFF, &custom_fnff, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_fnfp, "__builtin_custom_fnfp", NIOS2_BUILTIN_CUSTOM_FNFP, &custom_fnfp, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_fnpi, "__builtin_custom_fnpi", NIOS2_BUILTIN_CUSTOM_FNPI, &custom_fnpi, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_fnpf, "__builtin_custom_fnpf", NIOS2_BUILTIN_CUSTOM_FNPF, &custom_fnpf, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_fnpp, "__builtin_custom_fnpp", NIOS2_BUILTIN_CUSTOM_FNPP, &custom_fnpp, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_pn, "__builtin_custom_pn", NIOS2_BUILTIN_CUSTOM_PN, &custom_pn, nios2_expand_custom_Xn},
- + {CODE_FOR_custom_pni, "__builtin_custom_pni", NIOS2_BUILTIN_CUSTOM_PNI, &custom_pni, nios2_expand_custom_XnX},
- + {CODE_FOR_custom_pnf, "__builtin_custom_pnf", NIOS2_BUILTIN_CUSTOM_PNF, &custom_pnf, nios2_expand_custom_XnX},
- + {CODE_FOR_custom_pnp, "__builtin_custom_pnp", NIOS2_BUILTIN_CUSTOM_PNP, &custom_pnp, nios2_expand_custom_XnX},
- + {CODE_FOR_custom_pnii, "__builtin_custom_pnii", NIOS2_BUILTIN_CUSTOM_PNII, &custom_pnii, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_pnif, "__builtin_custom_pnif", NIOS2_BUILTIN_CUSTOM_PNIF, &custom_pnif, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_pnip, "__builtin_custom_pnip", NIOS2_BUILTIN_CUSTOM_PNIP, &custom_pnip, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_pnfi, "__builtin_custom_pnfi", NIOS2_BUILTIN_CUSTOM_PNFI, &custom_pnfi, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_pnff, "__builtin_custom_pnff", NIOS2_BUILTIN_CUSTOM_PNFF, &custom_pnff, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_pnfp, "__builtin_custom_pnfp", NIOS2_BUILTIN_CUSTOM_PNFP, &custom_pnfp, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_pnpi, "__builtin_custom_pnpi", NIOS2_BUILTIN_CUSTOM_PNPI, &custom_pnpi, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_pnpf, "__builtin_custom_pnpf", NIOS2_BUILTIN_CUSTOM_PNPF, &custom_pnpf, nios2_expand_custom_XnXX},
- + {CODE_FOR_custom_pnpp, "__builtin_custom_pnpp", NIOS2_BUILTIN_CUSTOM_PNPP, &custom_pnpp, nios2_expand_custom_XnXX},
- +
- +
- + {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))));
- +
- +
- +
- + /* *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)
- + 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);
- +
- + 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;
- +}
- +
- +
- +#include "gt-nios2.h"
- +
- --- gcc-3.4.3/gcc/config/nios2/nios2.h
- +++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.h
- @@ -0,0 +1,824 @@
- +/* Definitions of target machine 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. */
- +
- +
- +
- +#define TARGET_CPU_CPP_BUILTINS() \
- + do \
- + { \
- + builtin_define_std ("NIOS2"); \
- + builtin_define_std ("nios2"); \
- + builtin_define ("_GNU_SOURCE"); \
- + } \
- + 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
- +
- +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_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") */ }, \
- + { "", 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= */
- +
- +#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}, \
- +}
- +
- +
- +/* Default target_flags if no switches specified. */
- +#ifndef TARGET_DEFAULT
- +# define TARGET_DEFAULT (HAS_MUL_FLAG | CACHE_VOLATILE_FLAG)
- +#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*}"
- +
- +#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=} \
- + %{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 0
- +#define WORDS_BIG_ENDIAN 0
- +#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 only CMP_SI is used */
- +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 Exception Temporary
- +25 r25 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,
- + ALL_REGS,
- + LIM_REG_CLASSES
- +};
- +
- +#define N_REG_CLASSES (int) LIM_REG_CLASSES
- +
- +#define REG_CLASS_NAMES \
- + {"NO_REGS", \
- + "ALL_REGS"}
- +
- +#define GENERAL_REGS ALL_REGS
- +
- +#define REG_CLASS_CONTENTS \
- +/* NO_REGS */ {{ 0, 0}, \
- +/* ALL_REGS */ {~0,~0}} \
- +
- +#define REGNO_REG_CLASS(REGNO) ALL_REGS
- +
- +#define BASE_REG_CLASS ALL_REGS
- +#define INDEX_REG_CLASS ALL_REGS
- +
- +/* only one reg class, 'r', is handled automatically */
- +#define REG_CLASS_FROM_LETTER(CHAR) NO_REGS
- +
- +#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))
- +
- +/* '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 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_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 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", \
- + "r24", \
- + "r25", \
- + "gp", \
- + "sp", \
- + "fp", \
- + "ta", \
- + "ba", \
- + "ra", \
- + "status", \
- + "estatus", \
- + "bstatus", \
- + "ipri", \
- + "ecause", \
- + "pc", \
- + "rap", \
- + "fake_fp", \
- + "fake_ap", \
- +}
- +
- +#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 Pmode SImode
- +#define FUNCTION_MODE QImode
- +
- +#define CASE_VECTOR_MODE Pmode
- +
- +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
- +
- +#define LOAD_EXTEND_OP(MODE) (ZERO_EXTEND)
- +
- +#define WORD_REGISTER_OPERATIONS
- --- gcc-3.4.3/gcc/config/nios2/nios2.md
- +++ gcc-3.4.3-nios2/gcc/config/nios2/nios2.md
- @@ -0,0 +1,2078 @@
- +;; Machine Description 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. */
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* constants
- +;*
- +;*****************************************************************************
- +(define_constants [
- + (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)
- +
- +])
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* 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)
- + || register_operand (operands[1], QImode)
- + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
- + "@
- + 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 "register_operand" "r"))
- + (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)
- + || register_operand (operands[1], HImode)
- + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
- + "@
- + 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 "register_operand" "r"))
- + (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)
- + || register_operand (operands[1], SImode)
- + || (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == 0))"
- + "@
- + 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 "register_operand" "r"))
- + (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" "")))]
- + ""
- +{
- + if (optimize && GET_CODE (operands[1]) == MEM)
- + operands[1] = force_not_mem (operands[1]);
- +
- + if (GET_CODE (operands[1]) != MEM)
- + {
- + rtx op1 = gen_lowpart (SImode, operands[1]);
- + rtx temp = gen_reg_rtx (SImode);
- + rtx shift = GEN_INT (16);
- +
- + emit_insn (gen_ashlsi3 (temp, op1, shift));
- + emit_insn (gen_ashrsi3 (operands[0], temp, shift));
- + DONE;
- + }
- +})
- +
- +(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" "")))]
- + ""
- +{
- + if (optimize && GET_CODE (operands[1]) == MEM)
- + operands[1] = force_not_mem (operands[1]);
- +
- + if (GET_CODE (operands[1]) != MEM)
- + {
- + rtx op0 = gen_lowpart (SImode, operands[0]);
- + rtx op1 = gen_lowpart (SImode, operands[1]);
- + rtx temp = gen_reg_rtx (SImode);
- + rtx shift = GEN_INT (24);
- +
- + emit_insn (gen_ashlsi3 (temp, op1, shift));
- + emit_insn (gen_ashrsi3 (op0, temp, shift));
- + DONE;
- + }
- +})
- +
- +(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" "")))]
- + ""
- +{
- + if (optimize && GET_CODE (operands[1]) == MEM)
- + operands[1] = force_not_mem (operands[1]);
- +
- + if (GET_CODE (operands[1]) != MEM)
- + {
- + rtx op1 = gen_lowpart (SImode, operands[1]);
- + rtx temp = gen_reg_rtx (SImode);
- + rtx shift = GEN_INT (24);
- +
- + emit_insn (gen_ashlsi3 (temp, op1, shift));
- + emit_insn (gen_ashrsi3 (operands[0], temp, shift));
- + DONE;
- + }
- +})
- +
- +(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 "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 "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_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 "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"
- + [(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"
- + "")
- +
- +(define_expand "umulsidi3"
- + [(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"
- + "")
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* 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 "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")])
- +
- +
- +
- +; 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")))]
- + ""
- + "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")])
- +
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* 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" "r"))
- + (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" "r"))
- + (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;
- +})
- +
- +
- +;*****************************************************************************
- +;*
- +;* 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)
- + 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_expand "sne"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (ne: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 (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_expand "sgt"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (gt: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 (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_expand "sge"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (ge: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 (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_expand "sle"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (le: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 (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_expand "slt"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (lt: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 (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_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_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 "register_operand" "r")] UNSPEC_WRCTL)]
- + ""
- + "wrctl\\tctl%0, %1"
- + [(set_attr "type" "control")])
- +
- +
- +
- +;*****************************************************************************
- +;*
- +;* Peepholes
- +;*
- +;*****************************************************************************
- +
- +
- --- gcc-3.4.3/gcc/config/nios2/t-nios2
- +++ gcc-3.4.3-nios2/gcc/config/nios2/t-nios2
- @@ -0,0 +1,123 @@
- +##
- +## 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}
- + cat $(srcdir)/config/fp-bit.c >> ${FPBIT}
- +
- +$(DPBIT): $(srcdir)/config/fp-bit.c Makefile
- + echo '' > ${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.
- +
- +MULTILIB_OPTIONS = mno-hw-mul mhw-mulx
- +
- +## 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.
- +##
- +## 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*
- +##
- +
- +MULTILIB_EXCEPTIONS = *mno-hw-mul/*mhw-mulx*
- +
- +##
- +## 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.
- +##
- +
- --- gcc-3.4.3/gcc/config.gcc
- +++ gcc-3.4.3-nios2/gcc/config.gcc
- @@ -1321,6 +1321,10 @@ m32rle-*-linux*)
- thread_file='posix'
- fi
- ;;
- +# JBG
- +nios2-*-* | nios2-*-*)
- + tm_file="elfos.h ${tm_file}"
- + ;;
- # m68hc11 and m68hc12 share the same machine description.
- m68hc11-*-*|m6811-*-*)
- tm_file="dbxelf.h elfos.h m68hc11/m68hc11.h"
- --- gcc-3.4.3/gcc/cse.c
- +++ gcc-3.4.3-nios2/gcc/cse.c
- @@ -3134,6 +3134,10 @@ find_comparison_args (enum rtx_code code
- #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))
- --- gcc-3.4.3/gcc/doc/extend.texi
- +++ gcc-3.4.3-nios2/gcc/doc/extend.texi
- @@ -5636,12 +5636,118 @@ to those machines. Generally these gene
- 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
-
- --- gcc-3.4.3/gcc/doc/invoke.texi
- +++ gcc-3.4.3-nios2/gcc/doc/invoke.texi
- @@ -337,6 +337,14 @@ 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
- +-msys-crt0= -msys-lib= -msys=nosys }
- +
- @emph{M680x0 Options}
- @gccoptlist{-m68000 -m68020 -m68020-40 -m68020-60 -m68030 -m68040 @gol
- -m68060 -mcpu32 -m5200 -m68881 -mbitfield -mc68000 -mc68020 @gol
- @@ -5836,6 +5844,7 @@ machine description. The default for th
- that macro, which enables you to change the defaults.
-
- @menu
- +* Altera Nios II Options::
- * M680x0 Options::
- * M68hc1x Options::
- * VAX Options::
- @@ -5871,6 +5880,103 @@ that macro, which enables you to change
- * 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 -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.
- +
- +@end table
- +
- +
- @node M680x0 Options
- @subsection M680x0 Options
- @cindex M680x0 options
- --- gcc-3.4.3/gcc/doc/md.texi
- +++ gcc-3.4.3-nios2/gcc/doc/md.texi
- @@ -1335,6 +1335,49 @@ However, here is a summary of the machin
- 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.
- +
- +@end table
- +
- +
- @item ARM family---@file{arm.h}
- @table @code
- @item f
|