spu.c 202 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137513851395140514151425143514451455146514751485149515051515152515351545155515651575158515951605161516251635164516551665167516851695170517151725173517451755176517751785179518051815182518351845185518651875188518951905191519251935194519551965197519851995200520152025203520452055206520752085209521052115212521352145215521652175218521952205221522252235224522552265227522852295230523152325233523452355236523752385239524052415242524352445245524652475248524952505251525252535254525552565257525852595260526152625263526452655266526752685269527052715272527352745275527652775278527952805281528252835284528552865287528852895290529152925293529452955296529752985299530053015302530353045305530653075308530953105311531253135314531553165317531853195320532153225323532453255326532753285329533053315332533353345335533653375338533953405341534253435344534553465347534853495350535153525353535453555356535753585359536053615362536353645365536653675368536953705371537253735374537553765377537853795380538153825383538453855386538753885389539053915392539353945395539653975398539954005401540254035404540554065407540854095410541154125413541454155416541754185419542054215422542354245425542654275428542954305431543254335434543554365437543854395440544154425443544454455446544754485449545054515452545354545455545654575458545954605461546254635464546554665467546854695470547154725473547454755476547754785479548054815482548354845485548654875488548954905491549254935494549554965497549854995500550155025503550455055506550755085509551055115512551355145515551655175518551955205521552255235524552555265527552855295530553155325533553455355536553755385539554055415542554355445545554655475548554955505551555255535554555555565557555855595560556155625563556455655566556755685569557055715572557355745575557655775578557955805581558255835584558555865587558855895590559155925593559455955596559755985599560056015602560356045605560656075608560956105611561256135614561556165617561856195620562156225623562456255626562756285629563056315632563356345635563656375638563956405641564256435644564556465647564856495650565156525653565456555656565756585659566056615662566356645665566656675668566956705671567256735674567556765677567856795680568156825683568456855686568756885689569056915692569356945695569656975698569957005701570257035704570557065707570857095710571157125713571457155716571757185719572057215722572357245725572657275728572957305731573257335734573557365737573857395740574157425743574457455746574757485749575057515752575357545755575657575758575957605761576257635764576557665767576857695770577157725773577457755776577757785779578057815782578357845785578657875788578957905791579257935794579557965797579857995800580158025803580458055806580758085809581058115812581358145815581658175818581958205821582258235824582558265827582858295830583158325833583458355836583758385839584058415842584358445845584658475848584958505851585258535854585558565857585858595860586158625863586458655866586758685869587058715872587358745875587658775878587958805881588258835884588558865887588858895890589158925893589458955896589758985899590059015902590359045905590659075908590959105911591259135914591559165917591859195920592159225923592459255926592759285929593059315932593359345935593659375938593959405941594259435944594559465947594859495950595159525953595459555956595759585959596059615962596359645965596659675968596959705971597259735974597559765977597859795980598159825983598459855986598759885989599059915992599359945995599659975998599960006001600260036004600560066007600860096010601160126013601460156016601760186019602060216022602360246025602660276028602960306031603260336034603560366037603860396040604160426043604460456046604760486049605060516052605360546055605660576058605960606061606260636064606560666067606860696070607160726073607460756076607760786079608060816082608360846085608660876088608960906091609260936094609560966097609860996100610161026103610461056106610761086109611061116112611361146115611661176118611961206121612261236124612561266127612861296130613161326133613461356136613761386139614061416142614361446145614661476148614961506151615261536154615561566157615861596160616161626163616461656166616761686169617061716172617361746175617661776178617961806181618261836184618561866187618861896190619161926193619461956196619761986199620062016202620362046205620662076208620962106211621262136214621562166217621862196220622162226223622462256226622762286229623062316232623362346235623662376238623962406241624262436244624562466247624862496250625162526253625462556256625762586259626062616262626362646265626662676268626962706271627262736274627562766277627862796280628162826283628462856286628762886289629062916292629362946295629662976298629963006301630263036304630563066307630863096310631163126313631463156316631763186319632063216322632363246325632663276328632963306331633263336334633563366337633863396340634163426343634463456346634763486349635063516352635363546355635663576358635963606361636263636364636563666367636863696370637163726373637463756376637763786379638063816382638363846385638663876388638963906391639263936394639563966397639863996400640164026403640464056406640764086409641064116412641364146415641664176418641964206421642264236424642564266427642864296430643164326433643464356436643764386439644064416442644364446445644664476448644964506451645264536454645564566457645864596460646164626463646464656466646764686469647064716472647364746475647664776478647964806481648264836484648564866487648864896490649164926493649464956496649764986499650065016502650365046505650665076508650965106511651265136514651565166517651865196520652165226523652465256526652765286529653065316532653365346535653665376538653965406541654265436544654565466547654865496550655165526553655465556556655765586559656065616562656365646565656665676568656965706571657265736574657565766577657865796580658165826583658465856586658765886589659065916592659365946595659665976598659966006601660266036604660566066607660866096610661166126613661466156616661766186619662066216622662366246625662666276628662966306631663266336634663566366637663866396640664166426643664466456646664766486649665066516652665366546655665666576658665966606661666266636664666566666667666866696670667166726673667466756676667766786679668066816682668366846685668666876688668966906691669266936694669566966697669866996700670167026703670467056706670767086709671067116712671367146715671667176718671967206721672267236724672567266727672867296730673167326733673467356736673767386739674067416742674367446745674667476748674967506751675267536754675567566757675867596760676167626763676467656766676767686769677067716772677367746775677667776778677967806781678267836784678567866787678867896790679167926793679467956796679767986799680068016802680368046805680668076808680968106811681268136814681568166817681868196820682168226823682468256826682768286829683068316832683368346835683668376838683968406841684268436844684568466847684868496850685168526853685468556856685768586859686068616862686368646865686668676868686968706871687268736874687568766877687868796880688168826883688468856886688768886889689068916892689368946895689668976898689969006901690269036904690569066907690869096910691169126913691469156916691769186919692069216922692369246925692669276928692969306931693269336934693569366937693869396940694169426943694469456946694769486949695069516952695369546955695669576958695969606961696269636964696569666967696869696970697169726973697469756976697769786979698069816982698369846985698669876988698969906991699269936994699569966997699869997000700170027003700470057006700770087009701070117012701370147015701670177018701970207021702270237024702570267027702870297030703170327033703470357036703770387039704070417042704370447045704670477048704970507051705270537054705570567057705870597060706170627063706470657066706770687069707070717072707370747075707670777078707970807081708270837084708570867087708870897090709170927093709470957096709770987099710071017102710371047105710671077108710971107111711271137114711571167117711871197120712171227123712471257126712771287129713071317132713371347135713671377138713971407141714271437144714571467147714871497150715171527153715471557156715771587159716071617162716371647165716671677168716971707171717271737174717571767177717871797180718171827183718471857186718771887189719071917192719371947195719671977198719972007201720272037204720572067207720872097210721172127213721472157216721772187219722072217222722372247225722672277228722972307231723272337234723572367237723872397240724172427243724472457246724772487249725072517252725372547255725672577258725972607261726272637264726572667267726872697270727172727273727472757276727772787279728072817282728372847285728672877288728972907291729272937294729572967297729872997300730173027303730473057306730773087309731073117312731373147315731673177318731973207321732273237324732573267327732873297330733173327333733473357336733773387339734073417342734373447345734673477348734973507351735273537354735573567357735873597360736173627363736473657366736773687369737073717372737373747375737673777378737973807381
  1. /* Copyright (C) 2006-2015 Free Software Foundation, Inc.
  2. This file is free software; you can redistribute it and/or modify it under
  3. the terms of the GNU General Public License as published by the Free
  4. Software Foundation; either version 3 of the License, or (at your option)
  5. any later version.
  6. This file is distributed in the hope that it will be useful, but WITHOUT
  7. ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  8. FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
  9. for more details.
  10. You should have received a copy of the GNU General Public License
  11. along with GCC; see the file COPYING3. If not see
  12. <http://www.gnu.org/licenses/>. */
  13. #include "config.h"
  14. #include "system.h"
  15. #include "coretypes.h"
  16. #include "tm.h"
  17. #include "rtl.h"
  18. #include "regs.h"
  19. #include "hard-reg-set.h"
  20. #include "insn-config.h"
  21. #include "conditions.h"
  22. #include "insn-attr.h"
  23. #include "flags.h"
  24. #include "recog.h"
  25. #include "obstack.h"
  26. #include "hash-set.h"
  27. #include "machmode.h"
  28. #include "vec.h"
  29. #include "double-int.h"
  30. #include "input.h"
  31. #include "alias.h"
  32. #include "symtab.h"
  33. #include "wide-int.h"
  34. #include "inchash.h"
  35. #include "tree.h"
  36. #include "fold-const.h"
  37. #include "stringpool.h"
  38. #include "stor-layout.h"
  39. #include "calls.h"
  40. #include "varasm.h"
  41. #include "hashtab.h"
  42. #include "function.h"
  43. #include "statistics.h"
  44. #include "real.h"
  45. #include "fixed-value.h"
  46. #include "expmed.h"
  47. #include "dojump.h"
  48. #include "explow.h"
  49. #include "emit-rtl.h"
  50. #include "stmt.h"
  51. #include "expr.h"
  52. #include "insn-codes.h"
  53. #include "optabs.h"
  54. #include "except.h"
  55. #include "output.h"
  56. #include "predict.h"
  57. #include "dominance.h"
  58. #include "cfg.h"
  59. #include "cfgrtl.h"
  60. #include "cfganal.h"
  61. #include "lcm.h"
  62. #include "cfgbuild.h"
  63. #include "cfgcleanup.h"
  64. #include "basic-block.h"
  65. #include "diagnostic-core.h"
  66. #include "ggc.h"
  67. #include "tm_p.h"
  68. #include "target.h"
  69. #include "target-def.h"
  70. #include "langhooks.h"
  71. #include "reload.h"
  72. #include "sched-int.h"
  73. #include "params.h"
  74. #include "hash-table.h"
  75. #include "tree-ssa-alias.h"
  76. #include "internal-fn.h"
  77. #include "gimple-fold.h"
  78. #include "tree-eh.h"
  79. #include "gimple-expr.h"
  80. #include "is-a.h"
  81. #include "gimple.h"
  82. #include "gimplify.h"
  83. #include "tm-constrs.h"
  84. #include "sbitmap.h"
  85. #include "df.h"
  86. #include "ddg.h"
  87. #include "timevar.h"
  88. #include "dumpfile.h"
  89. #include "cfgloop.h"
  90. #include "builtins.h"
  91. #include "rtl-iter.h"
  92. /* Builtin types, data and prototypes. */
  93. enum spu_builtin_type_index
  94. {
  95. SPU_BTI_END_OF_PARAMS,
  96. /* We create new type nodes for these. */
  97. SPU_BTI_V16QI,
  98. SPU_BTI_V8HI,
  99. SPU_BTI_V4SI,
  100. SPU_BTI_V2DI,
  101. SPU_BTI_V4SF,
  102. SPU_BTI_V2DF,
  103. SPU_BTI_UV16QI,
  104. SPU_BTI_UV8HI,
  105. SPU_BTI_UV4SI,
  106. SPU_BTI_UV2DI,
  107. /* A 16-byte type. (Implemented with V16QI_type_node) */
  108. SPU_BTI_QUADWORD,
  109. /* These all correspond to intSI_type_node */
  110. SPU_BTI_7,
  111. SPU_BTI_S7,
  112. SPU_BTI_U7,
  113. SPU_BTI_S10,
  114. SPU_BTI_S10_4,
  115. SPU_BTI_U14,
  116. SPU_BTI_16,
  117. SPU_BTI_S16,
  118. SPU_BTI_S16_2,
  119. SPU_BTI_U16,
  120. SPU_BTI_U16_2,
  121. SPU_BTI_U18,
  122. /* These correspond to the standard types */
  123. SPU_BTI_INTQI,
  124. SPU_BTI_INTHI,
  125. SPU_BTI_INTSI,
  126. SPU_BTI_INTDI,
  127. SPU_BTI_UINTQI,
  128. SPU_BTI_UINTHI,
  129. SPU_BTI_UINTSI,
  130. SPU_BTI_UINTDI,
  131. SPU_BTI_FLOAT,
  132. SPU_BTI_DOUBLE,
  133. SPU_BTI_VOID,
  134. SPU_BTI_PTR,
  135. SPU_BTI_MAX
  136. };
  137. #define V16QI_type_node (spu_builtin_types[SPU_BTI_V16QI])
  138. #define V8HI_type_node (spu_builtin_types[SPU_BTI_V8HI])
  139. #define V4SI_type_node (spu_builtin_types[SPU_BTI_V4SI])
  140. #define V2DI_type_node (spu_builtin_types[SPU_BTI_V2DI])
  141. #define V4SF_type_node (spu_builtin_types[SPU_BTI_V4SF])
  142. #define V2DF_type_node (spu_builtin_types[SPU_BTI_V2DF])
  143. #define unsigned_V16QI_type_node (spu_builtin_types[SPU_BTI_UV16QI])
  144. #define unsigned_V8HI_type_node (spu_builtin_types[SPU_BTI_UV8HI])
  145. #define unsigned_V4SI_type_node (spu_builtin_types[SPU_BTI_UV4SI])
  146. #define unsigned_V2DI_type_node (spu_builtin_types[SPU_BTI_UV2DI])
  147. static GTY(()) tree spu_builtin_types[SPU_BTI_MAX];
  148. struct spu_builtin_range
  149. {
  150. int low, high;
  151. };
  152. static struct spu_builtin_range spu_builtin_range[] = {
  153. {-0x40ll, 0x7fll}, /* SPU_BTI_7 */
  154. {-0x40ll, 0x3fll}, /* SPU_BTI_S7 */
  155. {0ll, 0x7fll}, /* SPU_BTI_U7 */
  156. {-0x200ll, 0x1ffll}, /* SPU_BTI_S10 */
  157. {-0x2000ll, 0x1fffll}, /* SPU_BTI_S10_4 */
  158. {0ll, 0x3fffll}, /* SPU_BTI_U14 */
  159. {-0x8000ll, 0xffffll}, /* SPU_BTI_16 */
  160. {-0x8000ll, 0x7fffll}, /* SPU_BTI_S16 */
  161. {-0x20000ll, 0x1ffffll}, /* SPU_BTI_S16_2 */
  162. {0ll, 0xffffll}, /* SPU_BTI_U16 */
  163. {0ll, 0x3ffffll}, /* SPU_BTI_U16_2 */
  164. {0ll, 0x3ffffll}, /* SPU_BTI_U18 */
  165. };
  166. /* Target specific attribute specifications. */
  167. char regs_ever_allocated[FIRST_PSEUDO_REGISTER];
  168. /* Prototypes and external defs. */
  169. static int get_pipe (rtx_insn *insn);
  170. static int spu_naked_function_p (tree func);
  171. static int mem_is_padded_component_ref (rtx x);
  172. static void fix_range (const char *);
  173. static rtx spu_expand_load (rtx, rtx, rtx, int);
  174. /* Which instruction set architecture to use. */
  175. int spu_arch;
  176. /* Which cpu are we tuning for. */
  177. int spu_tune;
  178. /* The hardware requires 8 insns between a hint and the branch it
  179. effects. This variable describes how many rtl instructions the
  180. compiler needs to see before inserting a hint, and then the compiler
  181. will insert enough nops to make it at least 8 insns. The default is
  182. for the compiler to allow up to 2 nops be emitted. The nops are
  183. inserted in pairs, so we round down. */
  184. int spu_hint_dist = (8*4) - (2*4);
  185. enum spu_immediate {
  186. SPU_NONE,
  187. SPU_IL,
  188. SPU_ILA,
  189. SPU_ILH,
  190. SPU_ILHU,
  191. SPU_ORI,
  192. SPU_ORHI,
  193. SPU_ORBI,
  194. SPU_IOHL
  195. };
  196. enum immediate_class
  197. {
  198. IC_POOL, /* constant pool */
  199. IC_IL1, /* one il* instruction */
  200. IC_IL2, /* both ilhu and iohl instructions */
  201. IC_IL1s, /* one il* instruction */
  202. IC_IL2s, /* both ilhu and iohl instructions */
  203. IC_FSMBI, /* the fsmbi instruction */
  204. IC_CPAT, /* one of the c*d instructions */
  205. IC_FSMBI2 /* fsmbi plus 1 other instruction */
  206. };
  207. static enum spu_immediate which_immediate_load (HOST_WIDE_INT val);
  208. static enum spu_immediate which_logical_immediate (HOST_WIDE_INT val);
  209. static int cpat_info(unsigned char *arr, int size, int *prun, int *pstart);
  210. static enum immediate_class classify_immediate (rtx op,
  211. machine_mode mode);
  212. /* Pointer mode for __ea references. */
  213. #define EAmode (spu_ea_model != 32 ? DImode : SImode)
  214. /* Define the structure for the machine field in struct function. */
  215. struct GTY(()) machine_function
  216. {
  217. /* Register to use for PIC accesses. */
  218. rtx pic_reg;
  219. };
  220. /* How to allocate a 'struct machine_function'. */
  221. static struct machine_function *
  222. spu_init_machine_status (void)
  223. {
  224. return ggc_cleared_alloc<machine_function> ();
  225. }
  226. /* Implement TARGET_OPTION_OVERRIDE. */
  227. static void
  228. spu_option_override (void)
  229. {
  230. /* Set up function hooks. */
  231. init_machine_status = spu_init_machine_status;
  232. /* Small loops will be unpeeled at -O3. For SPU it is more important
  233. to keep code small by default. */
  234. if (!flag_unroll_loops && !flag_peel_loops)
  235. maybe_set_param_value (PARAM_MAX_COMPLETELY_PEEL_TIMES, 4,
  236. global_options.x_param_values,
  237. global_options_set.x_param_values);
  238. flag_omit_frame_pointer = 1;
  239. /* Functions must be 8 byte aligned so we correctly handle dual issue */
  240. if (align_functions < 8)
  241. align_functions = 8;
  242. spu_hint_dist = 8*4 - spu_max_nops*4;
  243. if (spu_hint_dist < 0)
  244. spu_hint_dist = 0;
  245. if (spu_fixed_range_string)
  246. fix_range (spu_fixed_range_string);
  247. /* Determine processor architectural level. */
  248. if (spu_arch_string)
  249. {
  250. if (strcmp (&spu_arch_string[0], "cell") == 0)
  251. spu_arch = PROCESSOR_CELL;
  252. else if (strcmp (&spu_arch_string[0], "celledp") == 0)
  253. spu_arch = PROCESSOR_CELLEDP;
  254. else
  255. error ("bad value (%s) for -march= switch", spu_arch_string);
  256. }
  257. /* Determine processor to tune for. */
  258. if (spu_tune_string)
  259. {
  260. if (strcmp (&spu_tune_string[0], "cell") == 0)
  261. spu_tune = PROCESSOR_CELL;
  262. else if (strcmp (&spu_tune_string[0], "celledp") == 0)
  263. spu_tune = PROCESSOR_CELLEDP;
  264. else
  265. error ("bad value (%s) for -mtune= switch", spu_tune_string);
  266. }
  267. /* Change defaults according to the processor architecture. */
  268. if (spu_arch == PROCESSOR_CELLEDP)
  269. {
  270. /* If no command line option has been otherwise specified, change
  271. the default to -mno-safe-hints on celledp -- only the original
  272. Cell/B.E. processors require this workaround. */
  273. if (!(target_flags_explicit & MASK_SAFE_HINTS))
  274. target_flags &= ~MASK_SAFE_HINTS;
  275. }
  276. REAL_MODE_FORMAT (SFmode) = &spu_single_format;
  277. }
  278. /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
  279. struct attribute_spec.handler. */
  280. /* True if MODE is valid for the target. By "valid", we mean able to
  281. be manipulated in non-trivial ways. In particular, this means all
  282. the arithmetic is supported. */
  283. static bool
  284. spu_scalar_mode_supported_p (machine_mode mode)
  285. {
  286. switch (mode)
  287. {
  288. case QImode:
  289. case HImode:
  290. case SImode:
  291. case SFmode:
  292. case DImode:
  293. case TImode:
  294. case DFmode:
  295. return true;
  296. default:
  297. return false;
  298. }
  299. }
  300. /* Similarly for vector modes. "Supported" here is less strict. At
  301. least some operations are supported; need to check optabs or builtins
  302. for further details. */
  303. static bool
  304. spu_vector_mode_supported_p (machine_mode mode)
  305. {
  306. switch (mode)
  307. {
  308. case V16QImode:
  309. case V8HImode:
  310. case V4SImode:
  311. case V2DImode:
  312. case V4SFmode:
  313. case V2DFmode:
  314. return true;
  315. default:
  316. return false;
  317. }
  318. }
  319. /* GCC assumes that in a paradoxical SUBREG the inner mode occupies the
  320. least significant bytes of the outer mode. This function returns
  321. TRUE for the SUBREG's where this is correct. */
  322. int
  323. valid_subreg (rtx op)
  324. {
  325. machine_mode om = GET_MODE (op);
  326. machine_mode im = GET_MODE (SUBREG_REG (op));
  327. return om != VOIDmode && im != VOIDmode
  328. && (GET_MODE_SIZE (im) == GET_MODE_SIZE (om)
  329. || (GET_MODE_SIZE (im) <= 4 && GET_MODE_SIZE (om) <= 4)
  330. || (GET_MODE_SIZE (im) >= 16 && GET_MODE_SIZE (om) >= 16));
  331. }
  332. /* When insv and ext[sz]v ar passed a TI SUBREG, we want to strip it off
  333. and adjust the start offset. */
  334. static rtx
  335. adjust_operand (rtx op, HOST_WIDE_INT * start)
  336. {
  337. machine_mode mode;
  338. int op_size;
  339. /* Strip any paradoxical SUBREG. */
  340. if (GET_CODE (op) == SUBREG
  341. && (GET_MODE_BITSIZE (GET_MODE (op))
  342. > GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op)))))
  343. {
  344. if (start)
  345. *start -=
  346. GET_MODE_BITSIZE (GET_MODE (op)) -
  347. GET_MODE_BITSIZE (GET_MODE (SUBREG_REG (op)));
  348. op = SUBREG_REG (op);
  349. }
  350. /* If it is smaller than SI, assure a SUBREG */
  351. op_size = GET_MODE_BITSIZE (GET_MODE (op));
  352. if (op_size < 32)
  353. {
  354. if (start)
  355. *start += 32 - op_size;
  356. op_size = 32;
  357. }
  358. /* If it is not a MODE_INT (and/or it is smaller than SI) add a SUBREG. */
  359. mode = mode_for_size (op_size, MODE_INT, 0);
  360. if (mode != GET_MODE (op))
  361. op = gen_rtx_SUBREG (mode, op, 0);
  362. return op;
  363. }
  364. void
  365. spu_expand_extv (rtx ops[], int unsignedp)
  366. {
  367. rtx dst = ops[0], src = ops[1];
  368. HOST_WIDE_INT width = INTVAL (ops[2]);
  369. HOST_WIDE_INT start = INTVAL (ops[3]);
  370. HOST_WIDE_INT align_mask;
  371. rtx s0, s1, mask, r0;
  372. gcc_assert (REG_P (dst) && GET_MODE (dst) == TImode);
  373. if (MEM_P (src))
  374. {
  375. /* First, determine if we need 1 TImode load or 2. We need only 1
  376. if the bits being extracted do not cross the alignment boundary
  377. as determined by the MEM and its address. */
  378. align_mask = -MEM_ALIGN (src);
  379. if ((start & align_mask) == ((start + width - 1) & align_mask))
  380. {
  381. /* Alignment is sufficient for 1 load. */
  382. s0 = gen_reg_rtx (TImode);
  383. r0 = spu_expand_load (s0, 0, src, start / 8);
  384. start &= 7;
  385. if (r0)
  386. emit_insn (gen_rotqby_ti (s0, s0, r0));
  387. }
  388. else
  389. {
  390. /* Need 2 loads. */
  391. s0 = gen_reg_rtx (TImode);
  392. s1 = gen_reg_rtx (TImode);
  393. r0 = spu_expand_load (s0, s1, src, start / 8);
  394. start &= 7;
  395. gcc_assert (start + width <= 128);
  396. if (r0)
  397. {
  398. rtx r1 = gen_reg_rtx (SImode);
  399. mask = gen_reg_rtx (TImode);
  400. emit_move_insn (mask, GEN_INT (-1));
  401. emit_insn (gen_rotqby_ti (s0, s0, r0));
  402. emit_insn (gen_rotqby_ti (s1, s1, r0));
  403. if (GET_CODE (r0) == CONST_INT)
  404. r1 = GEN_INT (INTVAL (r0) & 15);
  405. else
  406. emit_insn (gen_andsi3 (r1, r0, GEN_INT (15)));
  407. emit_insn (gen_shlqby_ti (mask, mask, r1));
  408. emit_insn (gen_selb (s0, s1, s0, mask));
  409. }
  410. }
  411. }
  412. else if (GET_CODE (src) == SUBREG)
  413. {
  414. rtx r = SUBREG_REG (src);
  415. gcc_assert (REG_P (r) && SCALAR_INT_MODE_P (GET_MODE (r)));
  416. s0 = gen_reg_rtx (TImode);
  417. if (GET_MODE_SIZE (GET_MODE (r)) < GET_MODE_SIZE (TImode))
  418. emit_insn (gen_rtx_SET (VOIDmode, s0, gen_rtx_ZERO_EXTEND (TImode, r)));
  419. else
  420. emit_move_insn (s0, src);
  421. }
  422. else
  423. {
  424. gcc_assert (REG_P (src) && GET_MODE (src) == TImode);
  425. s0 = gen_reg_rtx (TImode);
  426. emit_move_insn (s0, src);
  427. }
  428. /* Now s0 is TImode and contains the bits to extract at start. */
  429. if (start)
  430. emit_insn (gen_rotlti3 (s0, s0, GEN_INT (start)));
  431. if (128 - width)
  432. s0 = expand_shift (RSHIFT_EXPR, TImode, s0, 128 - width, s0, unsignedp);
  433. emit_move_insn (dst, s0);
  434. }
  435. void
  436. spu_expand_insv (rtx ops[])
  437. {
  438. HOST_WIDE_INT width = INTVAL (ops[1]);
  439. HOST_WIDE_INT start = INTVAL (ops[2]);
  440. HOST_WIDE_INT maskbits;
  441. machine_mode dst_mode;
  442. rtx dst = ops[0], src = ops[3];
  443. int dst_size;
  444. rtx mask;
  445. rtx shift_reg;
  446. int shift;
  447. if (GET_CODE (ops[0]) == MEM)
  448. dst = gen_reg_rtx (TImode);
  449. else
  450. dst = adjust_operand (dst, &start);
  451. dst_mode = GET_MODE (dst);
  452. dst_size = GET_MODE_BITSIZE (GET_MODE (dst));
  453. if (CONSTANT_P (src))
  454. {
  455. machine_mode m =
  456. (width <= 32 ? SImode : width <= 64 ? DImode : TImode);
  457. src = force_reg (m, convert_to_mode (m, src, 0));
  458. }
  459. src = adjust_operand (src, 0);
  460. mask = gen_reg_rtx (dst_mode);
  461. shift_reg = gen_reg_rtx (dst_mode);
  462. shift = dst_size - start - width;
  463. /* It's not safe to use subreg here because the compiler assumes
  464. that the SUBREG_REG is right justified in the SUBREG. */
  465. convert_move (shift_reg, src, 1);
  466. if (shift > 0)
  467. {
  468. switch (dst_mode)
  469. {
  470. case SImode:
  471. emit_insn (gen_ashlsi3 (shift_reg, shift_reg, GEN_INT (shift)));
  472. break;
  473. case DImode:
  474. emit_insn (gen_ashldi3 (shift_reg, shift_reg, GEN_INT (shift)));
  475. break;
  476. case TImode:
  477. emit_insn (gen_ashlti3 (shift_reg, shift_reg, GEN_INT (shift)));
  478. break;
  479. default:
  480. abort ();
  481. }
  482. }
  483. else if (shift < 0)
  484. abort ();
  485. switch (dst_size)
  486. {
  487. case 32:
  488. maskbits = (-1ll << (32 - width - start));
  489. if (start)
  490. maskbits += (1ll << (32 - start));
  491. emit_move_insn (mask, GEN_INT (maskbits));
  492. break;
  493. case 64:
  494. maskbits = (-1ll << (64 - width - start));
  495. if (start)
  496. maskbits += (1ll << (64 - start));
  497. emit_move_insn (mask, GEN_INT (maskbits));
  498. break;
  499. case 128:
  500. {
  501. unsigned char arr[16];
  502. int i = start / 8;
  503. memset (arr, 0, sizeof (arr));
  504. arr[i] = 0xff >> (start & 7);
  505. for (i++; i <= (start + width - 1) / 8; i++)
  506. arr[i] = 0xff;
  507. arr[i - 1] &= 0xff << (7 - ((start + width - 1) & 7));
  508. emit_move_insn (mask, array_to_constant (TImode, arr));
  509. }
  510. break;
  511. default:
  512. abort ();
  513. }
  514. if (GET_CODE (ops[0]) == MEM)
  515. {
  516. rtx low = gen_reg_rtx (SImode);
  517. rtx rotl = gen_reg_rtx (SImode);
  518. rtx mask0 = gen_reg_rtx (TImode);
  519. rtx addr;
  520. rtx addr0;
  521. rtx addr1;
  522. rtx mem;
  523. addr = force_reg (Pmode, XEXP (ops[0], 0));
  524. addr0 = gen_rtx_AND (Pmode, addr, GEN_INT (-16));
  525. emit_insn (gen_andsi3 (low, addr, GEN_INT (15)));
  526. emit_insn (gen_negsi2 (rotl, low));
  527. emit_insn (gen_rotqby_ti (shift_reg, shift_reg, rotl));
  528. emit_insn (gen_rotqmby_ti (mask0, mask, rotl));
  529. mem = change_address (ops[0], TImode, addr0);
  530. set_mem_alias_set (mem, 0);
  531. emit_move_insn (dst, mem);
  532. emit_insn (gen_selb (dst, dst, shift_reg, mask0));
  533. if (start + width > MEM_ALIGN (ops[0]))
  534. {
  535. rtx shl = gen_reg_rtx (SImode);
  536. rtx mask1 = gen_reg_rtx (TImode);
  537. rtx dst1 = gen_reg_rtx (TImode);
  538. rtx mem1;
  539. addr1 = plus_constant (Pmode, addr, 16);
  540. addr1 = gen_rtx_AND (Pmode, addr1, GEN_INT (-16));
  541. emit_insn (gen_subsi3 (shl, GEN_INT (16), low));
  542. emit_insn (gen_shlqby_ti (mask1, mask, shl));
  543. mem1 = change_address (ops[0], TImode, addr1);
  544. set_mem_alias_set (mem1, 0);
  545. emit_move_insn (dst1, mem1);
  546. emit_insn (gen_selb (dst1, dst1, shift_reg, mask1));
  547. emit_move_insn (mem1, dst1);
  548. }
  549. emit_move_insn (mem, dst);
  550. }
  551. else
  552. emit_insn (gen_selb (dst, copy_rtx (dst), shift_reg, mask));
  553. }
  554. int
  555. spu_expand_block_move (rtx ops[])
  556. {
  557. HOST_WIDE_INT bytes, align, offset;
  558. rtx src, dst, sreg, dreg, target;
  559. int i;
  560. if (GET_CODE (ops[2]) != CONST_INT
  561. || GET_CODE (ops[3]) != CONST_INT
  562. || INTVAL (ops[2]) > (HOST_WIDE_INT) (MOVE_RATIO (optimize_insn_for_speed_p ()) * 8))
  563. return 0;
  564. bytes = INTVAL (ops[2]);
  565. align = INTVAL (ops[3]);
  566. if (bytes <= 0)
  567. return 1;
  568. dst = ops[0];
  569. src = ops[1];
  570. if (align == 16)
  571. {
  572. for (offset = 0; offset + 16 <= bytes; offset += 16)
  573. {
  574. dst = adjust_address (ops[0], V16QImode, offset);
  575. src = adjust_address (ops[1], V16QImode, offset);
  576. emit_move_insn (dst, src);
  577. }
  578. if (offset < bytes)
  579. {
  580. rtx mask;
  581. unsigned char arr[16] = { 0 };
  582. for (i = 0; i < bytes - offset; i++)
  583. arr[i] = 0xff;
  584. dst = adjust_address (ops[0], V16QImode, offset);
  585. src = adjust_address (ops[1], V16QImode, offset);
  586. mask = gen_reg_rtx (V16QImode);
  587. sreg = gen_reg_rtx (V16QImode);
  588. dreg = gen_reg_rtx (V16QImode);
  589. target = gen_reg_rtx (V16QImode);
  590. emit_move_insn (mask, array_to_constant (V16QImode, arr));
  591. emit_move_insn (dreg, dst);
  592. emit_move_insn (sreg, src);
  593. emit_insn (gen_selb (target, dreg, sreg, mask));
  594. emit_move_insn (dst, target);
  595. }
  596. return 1;
  597. }
  598. return 0;
  599. }
  600. enum spu_comp_code
  601. { SPU_EQ, SPU_GT, SPU_GTU };
  602. int spu_comp_icode[12][3] = {
  603. {CODE_FOR_ceq_qi, CODE_FOR_cgt_qi, CODE_FOR_clgt_qi},
  604. {CODE_FOR_ceq_hi, CODE_FOR_cgt_hi, CODE_FOR_clgt_hi},
  605. {CODE_FOR_ceq_si, CODE_FOR_cgt_si, CODE_FOR_clgt_si},
  606. {CODE_FOR_ceq_di, CODE_FOR_cgt_di, CODE_FOR_clgt_di},
  607. {CODE_FOR_ceq_ti, CODE_FOR_cgt_ti, CODE_FOR_clgt_ti},
  608. {CODE_FOR_ceq_sf, CODE_FOR_cgt_sf, 0},
  609. {CODE_FOR_ceq_df, CODE_FOR_cgt_df, 0},
  610. {CODE_FOR_ceq_v16qi, CODE_FOR_cgt_v16qi, CODE_FOR_clgt_v16qi},
  611. {CODE_FOR_ceq_v8hi, CODE_FOR_cgt_v8hi, CODE_FOR_clgt_v8hi},
  612. {CODE_FOR_ceq_v4si, CODE_FOR_cgt_v4si, CODE_FOR_clgt_v4si},
  613. {CODE_FOR_ceq_v4sf, CODE_FOR_cgt_v4sf, 0},
  614. {CODE_FOR_ceq_v2df, CODE_FOR_cgt_v2df, 0},
  615. };
  616. /* Generate a compare for CODE. Return a brand-new rtx that represents
  617. the result of the compare. GCC can figure this out too if we don't
  618. provide all variations of compares, but GCC always wants to use
  619. WORD_MODE, we can generate better code in most cases if we do it
  620. ourselves. */
  621. void
  622. spu_emit_branch_or_set (int is_set, rtx cmp, rtx operands[])
  623. {
  624. int reverse_compare = 0;
  625. int reverse_test = 0;
  626. rtx compare_result, eq_result;
  627. rtx comp_rtx, eq_rtx;
  628. machine_mode comp_mode;
  629. machine_mode op_mode;
  630. enum spu_comp_code scode, eq_code;
  631. enum insn_code ior_code;
  632. enum rtx_code code = GET_CODE (cmp);
  633. rtx op0 = XEXP (cmp, 0);
  634. rtx op1 = XEXP (cmp, 1);
  635. int index;
  636. int eq_test = 0;
  637. /* When op1 is a CONST_INT change (X >= C) to (X > C-1),
  638. and so on, to keep the constant in operand 1. */
  639. if (GET_CODE (op1) == CONST_INT)
  640. {
  641. HOST_WIDE_INT val = INTVAL (op1) - 1;
  642. if (trunc_int_for_mode (val, GET_MODE (op0)) == val)
  643. switch (code)
  644. {
  645. case GE:
  646. op1 = GEN_INT (val);
  647. code = GT;
  648. break;
  649. case LT:
  650. op1 = GEN_INT (val);
  651. code = LE;
  652. break;
  653. case GEU:
  654. op1 = GEN_INT (val);
  655. code = GTU;
  656. break;
  657. case LTU:
  658. op1 = GEN_INT (val);
  659. code = LEU;
  660. break;
  661. default:
  662. break;
  663. }
  664. }
  665. /* However, if we generate an integer result, performing a reverse test
  666. would require an extra negation, so avoid that where possible. */
  667. if (GET_CODE (op1) == CONST_INT && is_set == 1)
  668. {
  669. HOST_WIDE_INT val = INTVAL (op1) + 1;
  670. if (trunc_int_for_mode (val, GET_MODE (op0)) == val)
  671. switch (code)
  672. {
  673. case LE:
  674. op1 = GEN_INT (val);
  675. code = LT;
  676. break;
  677. case LEU:
  678. op1 = GEN_INT (val);
  679. code = LTU;
  680. break;
  681. default:
  682. break;
  683. }
  684. }
  685. comp_mode = SImode;
  686. op_mode = GET_MODE (op0);
  687. switch (code)
  688. {
  689. case GE:
  690. scode = SPU_GT;
  691. if (HONOR_NANS (op_mode))
  692. {
  693. reverse_compare = 0;
  694. reverse_test = 0;
  695. eq_test = 1;
  696. eq_code = SPU_EQ;
  697. }
  698. else
  699. {
  700. reverse_compare = 1;
  701. reverse_test = 1;
  702. }
  703. break;
  704. case LE:
  705. scode = SPU_GT;
  706. if (HONOR_NANS (op_mode))
  707. {
  708. reverse_compare = 1;
  709. reverse_test = 0;
  710. eq_test = 1;
  711. eq_code = SPU_EQ;
  712. }
  713. else
  714. {
  715. reverse_compare = 0;
  716. reverse_test = 1;
  717. }
  718. break;
  719. case LT:
  720. reverse_compare = 1;
  721. reverse_test = 0;
  722. scode = SPU_GT;
  723. break;
  724. case GEU:
  725. reverse_compare = 1;
  726. reverse_test = 1;
  727. scode = SPU_GTU;
  728. break;
  729. case LEU:
  730. reverse_compare = 0;
  731. reverse_test = 1;
  732. scode = SPU_GTU;
  733. break;
  734. case LTU:
  735. reverse_compare = 1;
  736. reverse_test = 0;
  737. scode = SPU_GTU;
  738. break;
  739. case NE:
  740. reverse_compare = 0;
  741. reverse_test = 1;
  742. scode = SPU_EQ;
  743. break;
  744. case EQ:
  745. scode = SPU_EQ;
  746. break;
  747. case GT:
  748. scode = SPU_GT;
  749. break;
  750. case GTU:
  751. scode = SPU_GTU;
  752. break;
  753. default:
  754. scode = SPU_EQ;
  755. break;
  756. }
  757. switch (op_mode)
  758. {
  759. case QImode:
  760. index = 0;
  761. comp_mode = QImode;
  762. break;
  763. case HImode:
  764. index = 1;
  765. comp_mode = HImode;
  766. break;
  767. case SImode:
  768. index = 2;
  769. break;
  770. case DImode:
  771. index = 3;
  772. break;
  773. case TImode:
  774. index = 4;
  775. break;
  776. case SFmode:
  777. index = 5;
  778. break;
  779. case DFmode:
  780. index = 6;
  781. break;
  782. case V16QImode:
  783. index = 7;
  784. comp_mode = op_mode;
  785. break;
  786. case V8HImode:
  787. index = 8;
  788. comp_mode = op_mode;
  789. break;
  790. case V4SImode:
  791. index = 9;
  792. comp_mode = op_mode;
  793. break;
  794. case V4SFmode:
  795. index = 10;
  796. comp_mode = V4SImode;
  797. break;
  798. case V2DFmode:
  799. index = 11;
  800. comp_mode = V2DImode;
  801. break;
  802. case V2DImode:
  803. default:
  804. abort ();
  805. }
  806. if (GET_MODE (op1) == DFmode
  807. && (scode != SPU_GT && scode != SPU_EQ))
  808. abort ();
  809. if (is_set == 0 && op1 == const0_rtx
  810. && (GET_MODE (op0) == SImode
  811. || GET_MODE (op0) == HImode
  812. || GET_MODE (op0) == QImode) && scode == SPU_EQ)
  813. {
  814. /* Don't need to set a register with the result when we are
  815. comparing against zero and branching. */
  816. reverse_test = !reverse_test;
  817. compare_result = op0;
  818. }
  819. else
  820. {
  821. compare_result = gen_reg_rtx (comp_mode);
  822. if (reverse_compare)
  823. {
  824. rtx t = op1;
  825. op1 = op0;
  826. op0 = t;
  827. }
  828. if (spu_comp_icode[index][scode] == 0)
  829. abort ();
  830. if (!(*insn_data[spu_comp_icode[index][scode]].operand[1].predicate)
  831. (op0, op_mode))
  832. op0 = force_reg (op_mode, op0);
  833. if (!(*insn_data[spu_comp_icode[index][scode]].operand[2].predicate)
  834. (op1, op_mode))
  835. op1 = force_reg (op_mode, op1);
  836. comp_rtx = GEN_FCN (spu_comp_icode[index][scode]) (compare_result,
  837. op0, op1);
  838. if (comp_rtx == 0)
  839. abort ();
  840. emit_insn (comp_rtx);
  841. if (eq_test)
  842. {
  843. eq_result = gen_reg_rtx (comp_mode);
  844. eq_rtx = GEN_FCN (spu_comp_icode[index][eq_code]) (eq_result,
  845. op0, op1);
  846. if (eq_rtx == 0)
  847. abort ();
  848. emit_insn (eq_rtx);
  849. ior_code = optab_handler (ior_optab, comp_mode);
  850. gcc_assert (ior_code != CODE_FOR_nothing);
  851. emit_insn (GEN_FCN (ior_code)
  852. (compare_result, compare_result, eq_result));
  853. }
  854. }
  855. if (is_set == 0)
  856. {
  857. rtx bcomp;
  858. rtx loc_ref;
  859. /* We don't have branch on QI compare insns, so we convert the
  860. QI compare result to a HI result. */
  861. if (comp_mode == QImode)
  862. {
  863. rtx old_res = compare_result;
  864. compare_result = gen_reg_rtx (HImode);
  865. comp_mode = HImode;
  866. emit_insn (gen_extendqihi2 (compare_result, old_res));
  867. }
  868. if (reverse_test)
  869. bcomp = gen_rtx_EQ (comp_mode, compare_result, const0_rtx);
  870. else
  871. bcomp = gen_rtx_NE (comp_mode, compare_result, const0_rtx);
  872. loc_ref = gen_rtx_LABEL_REF (VOIDmode, operands[3]);
  873. emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
  874. gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
  875. loc_ref, pc_rtx)));
  876. }
  877. else if (is_set == 2)
  878. {
  879. rtx target = operands[0];
  880. int compare_size = GET_MODE_BITSIZE (comp_mode);
  881. int target_size = GET_MODE_BITSIZE (GET_MODE (target));
  882. machine_mode mode = mode_for_size (target_size, MODE_INT, 0);
  883. rtx select_mask;
  884. rtx op_t = operands[2];
  885. rtx op_f = operands[3];
  886. /* The result of the comparison can be SI, HI or QI mode. Create a
  887. mask based on that result. */
  888. if (target_size > compare_size)
  889. {
  890. select_mask = gen_reg_rtx (mode);
  891. emit_insn (gen_extend_compare (select_mask, compare_result));
  892. }
  893. else if (target_size < compare_size)
  894. select_mask =
  895. gen_rtx_SUBREG (mode, compare_result,
  896. (compare_size - target_size) / BITS_PER_UNIT);
  897. else if (comp_mode != mode)
  898. select_mask = gen_rtx_SUBREG (mode, compare_result, 0);
  899. else
  900. select_mask = compare_result;
  901. if (GET_MODE (target) != GET_MODE (op_t)
  902. || GET_MODE (target) != GET_MODE (op_f))
  903. abort ();
  904. if (reverse_test)
  905. emit_insn (gen_selb (target, op_t, op_f, select_mask));
  906. else
  907. emit_insn (gen_selb (target, op_f, op_t, select_mask));
  908. }
  909. else
  910. {
  911. rtx target = operands[0];
  912. if (reverse_test)
  913. emit_insn (gen_rtx_SET (VOIDmode, compare_result,
  914. gen_rtx_NOT (comp_mode, compare_result)));
  915. if (GET_MODE (target) == SImode && GET_MODE (compare_result) == HImode)
  916. emit_insn (gen_extendhisi2 (target, compare_result));
  917. else if (GET_MODE (target) == SImode
  918. && GET_MODE (compare_result) == QImode)
  919. emit_insn (gen_extend_compare (target, compare_result));
  920. else
  921. emit_move_insn (target, compare_result);
  922. }
  923. }
  924. HOST_WIDE_INT
  925. const_double_to_hwint (rtx x)
  926. {
  927. HOST_WIDE_INT val;
  928. REAL_VALUE_TYPE rv;
  929. if (GET_MODE (x) == SFmode)
  930. {
  931. REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
  932. REAL_VALUE_TO_TARGET_SINGLE (rv, val);
  933. }
  934. else if (GET_MODE (x) == DFmode)
  935. {
  936. long l[2];
  937. REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
  938. REAL_VALUE_TO_TARGET_DOUBLE (rv, l);
  939. val = l[0];
  940. val = (val << 32) | (l[1] & 0xffffffff);
  941. }
  942. else
  943. abort ();
  944. return val;
  945. }
  946. rtx
  947. hwint_to_const_double (machine_mode mode, HOST_WIDE_INT v)
  948. {
  949. long tv[2];
  950. REAL_VALUE_TYPE rv;
  951. gcc_assert (mode == SFmode || mode == DFmode);
  952. if (mode == SFmode)
  953. tv[0] = (v << 32) >> 32;
  954. else if (mode == DFmode)
  955. {
  956. tv[1] = (v << 32) >> 32;
  957. tv[0] = v >> 32;
  958. }
  959. real_from_target (&rv, tv, mode);
  960. return CONST_DOUBLE_FROM_REAL_VALUE (rv, mode);
  961. }
  962. void
  963. print_operand_address (FILE * file, register rtx addr)
  964. {
  965. rtx reg;
  966. rtx offset;
  967. if (GET_CODE (addr) == AND
  968. && GET_CODE (XEXP (addr, 1)) == CONST_INT
  969. && INTVAL (XEXP (addr, 1)) == -16)
  970. addr = XEXP (addr, 0);
  971. switch (GET_CODE (addr))
  972. {
  973. case REG:
  974. fprintf (file, "0(%s)", reg_names[REGNO (addr)]);
  975. break;
  976. case PLUS:
  977. reg = XEXP (addr, 0);
  978. offset = XEXP (addr, 1);
  979. if (GET_CODE (offset) == REG)
  980. {
  981. fprintf (file, "%s,%s", reg_names[REGNO (reg)],
  982. reg_names[REGNO (offset)]);
  983. }
  984. else if (GET_CODE (offset) == CONST_INT)
  985. {
  986. fprintf (file, HOST_WIDE_INT_PRINT_DEC "(%s)",
  987. INTVAL (offset), reg_names[REGNO (reg)]);
  988. }
  989. else
  990. abort ();
  991. break;
  992. case CONST:
  993. case LABEL_REF:
  994. case SYMBOL_REF:
  995. case CONST_INT:
  996. output_addr_const (file, addr);
  997. break;
  998. default:
  999. debug_rtx (addr);
  1000. abort ();
  1001. }
  1002. }
  1003. void
  1004. print_operand (FILE * file, rtx x, int code)
  1005. {
  1006. machine_mode mode = GET_MODE (x);
  1007. HOST_WIDE_INT val;
  1008. unsigned char arr[16];
  1009. int xcode = GET_CODE (x);
  1010. int i, info;
  1011. if (GET_MODE (x) == VOIDmode)
  1012. switch (code)
  1013. {
  1014. case 'L': /* 128 bits, signed */
  1015. case 'm': /* 128 bits, signed */
  1016. case 'T': /* 128 bits, signed */
  1017. case 't': /* 128 bits, signed */
  1018. mode = TImode;
  1019. break;
  1020. case 'K': /* 64 bits, signed */
  1021. case 'k': /* 64 bits, signed */
  1022. case 'D': /* 64 bits, signed */
  1023. case 'd': /* 64 bits, signed */
  1024. mode = DImode;
  1025. break;
  1026. case 'J': /* 32 bits, signed */
  1027. case 'j': /* 32 bits, signed */
  1028. case 's': /* 32 bits, signed */
  1029. case 'S': /* 32 bits, signed */
  1030. mode = SImode;
  1031. break;
  1032. }
  1033. switch (code)
  1034. {
  1035. case 'j': /* 32 bits, signed */
  1036. case 'k': /* 64 bits, signed */
  1037. case 'm': /* 128 bits, signed */
  1038. if (xcode == CONST_INT
  1039. || xcode == CONST_DOUBLE || xcode == CONST_VECTOR)
  1040. {
  1041. gcc_assert (logical_immediate_p (x, mode));
  1042. constant_to_array (mode, x, arr);
  1043. val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
  1044. val = trunc_int_for_mode (val, SImode);
  1045. switch (which_logical_immediate (val))
  1046. {
  1047. case SPU_ORI:
  1048. break;
  1049. case SPU_ORHI:
  1050. fprintf (file, "h");
  1051. break;
  1052. case SPU_ORBI:
  1053. fprintf (file, "b");
  1054. break;
  1055. default:
  1056. gcc_unreachable();
  1057. }
  1058. }
  1059. else
  1060. gcc_unreachable();
  1061. return;
  1062. case 'J': /* 32 bits, signed */
  1063. case 'K': /* 64 bits, signed */
  1064. case 'L': /* 128 bits, signed */
  1065. if (xcode == CONST_INT
  1066. || xcode == CONST_DOUBLE || xcode == CONST_VECTOR)
  1067. {
  1068. gcc_assert (logical_immediate_p (x, mode)
  1069. || iohl_immediate_p (x, mode));
  1070. constant_to_array (mode, x, arr);
  1071. val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
  1072. val = trunc_int_for_mode (val, SImode);
  1073. switch (which_logical_immediate (val))
  1074. {
  1075. case SPU_ORI:
  1076. case SPU_IOHL:
  1077. break;
  1078. case SPU_ORHI:
  1079. val = trunc_int_for_mode (val, HImode);
  1080. break;
  1081. case SPU_ORBI:
  1082. val = trunc_int_for_mode (val, QImode);
  1083. break;
  1084. default:
  1085. gcc_unreachable();
  1086. }
  1087. fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
  1088. }
  1089. else
  1090. gcc_unreachable();
  1091. return;
  1092. case 't': /* 128 bits, signed */
  1093. case 'd': /* 64 bits, signed */
  1094. case 's': /* 32 bits, signed */
  1095. if (CONSTANT_P (x))
  1096. {
  1097. enum immediate_class c = classify_immediate (x, mode);
  1098. switch (c)
  1099. {
  1100. case IC_IL1:
  1101. constant_to_array (mode, x, arr);
  1102. val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
  1103. val = trunc_int_for_mode (val, SImode);
  1104. switch (which_immediate_load (val))
  1105. {
  1106. case SPU_IL:
  1107. break;
  1108. case SPU_ILA:
  1109. fprintf (file, "a");
  1110. break;
  1111. case SPU_ILH:
  1112. fprintf (file, "h");
  1113. break;
  1114. case SPU_ILHU:
  1115. fprintf (file, "hu");
  1116. break;
  1117. default:
  1118. gcc_unreachable ();
  1119. }
  1120. break;
  1121. case IC_CPAT:
  1122. constant_to_array (mode, x, arr);
  1123. cpat_info (arr, GET_MODE_SIZE (mode), &info, 0);
  1124. if (info == 1)
  1125. fprintf (file, "b");
  1126. else if (info == 2)
  1127. fprintf (file, "h");
  1128. else if (info == 4)
  1129. fprintf (file, "w");
  1130. else if (info == 8)
  1131. fprintf (file, "d");
  1132. break;
  1133. case IC_IL1s:
  1134. if (xcode == CONST_VECTOR)
  1135. {
  1136. x = CONST_VECTOR_ELT (x, 0);
  1137. xcode = GET_CODE (x);
  1138. }
  1139. if (xcode == SYMBOL_REF || xcode == LABEL_REF || xcode == CONST)
  1140. fprintf (file, "a");
  1141. else if (xcode == HIGH)
  1142. fprintf (file, "hu");
  1143. break;
  1144. case IC_FSMBI:
  1145. case IC_FSMBI2:
  1146. case IC_IL2:
  1147. case IC_IL2s:
  1148. case IC_POOL:
  1149. abort ();
  1150. }
  1151. }
  1152. else
  1153. gcc_unreachable ();
  1154. return;
  1155. case 'T': /* 128 bits, signed */
  1156. case 'D': /* 64 bits, signed */
  1157. case 'S': /* 32 bits, signed */
  1158. if (CONSTANT_P (x))
  1159. {
  1160. enum immediate_class c = classify_immediate (x, mode);
  1161. switch (c)
  1162. {
  1163. case IC_IL1:
  1164. constant_to_array (mode, x, arr);
  1165. val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
  1166. val = trunc_int_for_mode (val, SImode);
  1167. switch (which_immediate_load (val))
  1168. {
  1169. case SPU_IL:
  1170. case SPU_ILA:
  1171. break;
  1172. case SPU_ILH:
  1173. case SPU_ILHU:
  1174. val = trunc_int_for_mode (((arr[0] << 8) | arr[1]), HImode);
  1175. break;
  1176. default:
  1177. gcc_unreachable ();
  1178. }
  1179. fprintf (file, HOST_WIDE_INT_PRINT_DEC, val);
  1180. break;
  1181. case IC_FSMBI:
  1182. constant_to_array (mode, x, arr);
  1183. val = 0;
  1184. for (i = 0; i < 16; i++)
  1185. {
  1186. val <<= 1;
  1187. val |= arr[i] & 1;
  1188. }
  1189. print_operand (file, GEN_INT (val), 0);
  1190. break;
  1191. case IC_CPAT:
  1192. constant_to_array (mode, x, arr);
  1193. cpat_info (arr, GET_MODE_SIZE (mode), 0, &info);
  1194. fprintf (file, HOST_WIDE_INT_PRINT_DEC, (HOST_WIDE_INT)info);
  1195. break;
  1196. case IC_IL1s:
  1197. if (xcode == HIGH)
  1198. x = XEXP (x, 0);
  1199. if (GET_CODE (x) == CONST_VECTOR)
  1200. x = CONST_VECTOR_ELT (x, 0);
  1201. output_addr_const (file, x);
  1202. if (xcode == HIGH)
  1203. fprintf (file, "@h");
  1204. break;
  1205. case IC_IL2:
  1206. case IC_IL2s:
  1207. case IC_FSMBI2:
  1208. case IC_POOL:
  1209. abort ();
  1210. }
  1211. }
  1212. else
  1213. gcc_unreachable ();
  1214. return;
  1215. case 'C':
  1216. if (xcode == CONST_INT)
  1217. {
  1218. /* Only 4 least significant bits are relevant for generate
  1219. control word instructions. */
  1220. fprintf (file, HOST_WIDE_INT_PRINT_DEC, INTVAL (x) & 15);
  1221. return;
  1222. }
  1223. break;
  1224. case 'M': /* print code for c*d */
  1225. if (GET_CODE (x) == CONST_INT)
  1226. switch (INTVAL (x))
  1227. {
  1228. case 1:
  1229. fprintf (file, "b");
  1230. break;
  1231. case 2:
  1232. fprintf (file, "h");
  1233. break;
  1234. case 4:
  1235. fprintf (file, "w");
  1236. break;
  1237. case 8:
  1238. fprintf (file, "d");
  1239. break;
  1240. default:
  1241. gcc_unreachable();
  1242. }
  1243. else
  1244. gcc_unreachable();
  1245. return;
  1246. case 'N': /* Negate the operand */
  1247. if (xcode == CONST_INT)
  1248. fprintf (file, HOST_WIDE_INT_PRINT_DEC, -INTVAL (x));
  1249. else if (xcode == CONST_VECTOR)
  1250. fprintf (file, HOST_WIDE_INT_PRINT_DEC,
  1251. -INTVAL (CONST_VECTOR_ELT (x, 0)));
  1252. return;
  1253. case 'I': /* enable/disable interrupts */
  1254. if (xcode == CONST_INT)
  1255. fprintf (file, "%s", INTVAL (x) == 0 ? "d" : "e");
  1256. return;
  1257. case 'b': /* branch modifiers */
  1258. if (xcode == REG)
  1259. fprintf (file, "%s", GET_MODE (x) == HImode ? "h" : "");
  1260. else if (COMPARISON_P (x))
  1261. fprintf (file, "%s", xcode == NE ? "n" : "");
  1262. return;
  1263. case 'i': /* indirect call */
  1264. if (xcode == MEM)
  1265. {
  1266. if (GET_CODE (XEXP (x, 0)) == REG)
  1267. /* Used in indirect function calls. */
  1268. fprintf (file, "%s", reg_names[REGNO (XEXP (x, 0))]);
  1269. else
  1270. output_address (XEXP (x, 0));
  1271. }
  1272. return;
  1273. case 'p': /* load/store */
  1274. if (xcode == MEM)
  1275. {
  1276. x = XEXP (x, 0);
  1277. xcode = GET_CODE (x);
  1278. }
  1279. if (xcode == AND)
  1280. {
  1281. x = XEXP (x, 0);
  1282. xcode = GET_CODE (x);
  1283. }
  1284. if (xcode == REG)
  1285. fprintf (file, "d");
  1286. else if (xcode == CONST_INT)
  1287. fprintf (file, "a");
  1288. else if (xcode == CONST || xcode == SYMBOL_REF || xcode == LABEL_REF)
  1289. fprintf (file, "r");
  1290. else if (xcode == PLUS || xcode == LO_SUM)
  1291. {
  1292. if (GET_CODE (XEXP (x, 1)) == REG)
  1293. fprintf (file, "x");
  1294. else
  1295. fprintf (file, "d");
  1296. }
  1297. return;
  1298. case 'e':
  1299. val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
  1300. val &= 0x7;
  1301. output_addr_const (file, GEN_INT (val));
  1302. return;
  1303. case 'f':
  1304. val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
  1305. val &= 0x1f;
  1306. output_addr_const (file, GEN_INT (val));
  1307. return;
  1308. case 'g':
  1309. val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
  1310. val &= 0x3f;
  1311. output_addr_const (file, GEN_INT (val));
  1312. return;
  1313. case 'h':
  1314. val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
  1315. val = (val >> 3) & 0x1f;
  1316. output_addr_const (file, GEN_INT (val));
  1317. return;
  1318. case 'E':
  1319. val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
  1320. val = -val;
  1321. val &= 0x7;
  1322. output_addr_const (file, GEN_INT (val));
  1323. return;
  1324. case 'F':
  1325. val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
  1326. val = -val;
  1327. val &= 0x1f;
  1328. output_addr_const (file, GEN_INT (val));
  1329. return;
  1330. case 'G':
  1331. val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
  1332. val = -val;
  1333. val &= 0x3f;
  1334. output_addr_const (file, GEN_INT (val));
  1335. return;
  1336. case 'H':
  1337. val = xcode == CONST_INT ? INTVAL (x) : INTVAL (CONST_VECTOR_ELT (x, 0));
  1338. val = -(val & -8ll);
  1339. val = (val >> 3) & 0x1f;
  1340. output_addr_const (file, GEN_INT (val));
  1341. return;
  1342. case 'v':
  1343. case 'w':
  1344. constant_to_array (mode, x, arr);
  1345. val = (((arr[0] << 1) + (arr[1] >> 7)) & 0xff) - 127;
  1346. output_addr_const (file, GEN_INT (code == 'w' ? -val : val));
  1347. return;
  1348. case 0:
  1349. if (xcode == REG)
  1350. fprintf (file, "%s", reg_names[REGNO (x)]);
  1351. else if (xcode == MEM)
  1352. output_address (XEXP (x, 0));
  1353. else if (xcode == CONST_VECTOR)
  1354. print_operand (file, CONST_VECTOR_ELT (x, 0), 0);
  1355. else
  1356. output_addr_const (file, x);
  1357. return;
  1358. /* unused letters
  1359. o qr u yz
  1360. AB OPQR UVWXYZ */
  1361. default:
  1362. output_operand_lossage ("invalid %%xn code");
  1363. }
  1364. gcc_unreachable ();
  1365. }
  1366. /* For PIC mode we've reserved PIC_OFFSET_TABLE_REGNUM, which is a
  1367. caller saved register. For leaf functions it is more efficient to
  1368. use a volatile register because we won't need to save and restore the
  1369. pic register. This routine is only valid after register allocation
  1370. is completed, so we can pick an unused register. */
  1371. static rtx
  1372. get_pic_reg (void)
  1373. {
  1374. if (!reload_completed && !reload_in_progress)
  1375. abort ();
  1376. /* If we've already made the decision, we need to keep with it. Once we've
  1377. decided to use LAST_ARG_REGNUM, future calls to df_regs_ever_live_p may
  1378. return true since the register is now live; this should not cause us to
  1379. "switch back" to using pic_offset_table_rtx. */
  1380. if (!cfun->machine->pic_reg)
  1381. {
  1382. if (crtl->is_leaf && !df_regs_ever_live_p (LAST_ARG_REGNUM))
  1383. cfun->machine->pic_reg = gen_rtx_REG (SImode, LAST_ARG_REGNUM);
  1384. else
  1385. cfun->machine->pic_reg = pic_offset_table_rtx;
  1386. }
  1387. return cfun->machine->pic_reg;
  1388. }
  1389. /* Split constant addresses to handle cases that are too large.
  1390. Add in the pic register when in PIC mode.
  1391. Split immediates that require more than 1 instruction. */
  1392. int
  1393. spu_split_immediate (rtx * ops)
  1394. {
  1395. machine_mode mode = GET_MODE (ops[0]);
  1396. enum immediate_class c = classify_immediate (ops[1], mode);
  1397. switch (c)
  1398. {
  1399. case IC_IL2:
  1400. {
  1401. unsigned char arrhi[16];
  1402. unsigned char arrlo[16];
  1403. rtx to, temp, hi, lo;
  1404. int i;
  1405. machine_mode imode = mode;
  1406. /* We need to do reals as ints because the constant used in the
  1407. IOR might not be a legitimate real constant. */
  1408. imode = int_mode_for_mode (mode);
  1409. constant_to_array (mode, ops[1], arrhi);
  1410. if (imode != mode)
  1411. to = simplify_gen_subreg (imode, ops[0], mode, 0);
  1412. else
  1413. to = ops[0];
  1414. temp = !can_create_pseudo_p () ? to : gen_reg_rtx (imode);
  1415. for (i = 0; i < 16; i += 4)
  1416. {
  1417. arrlo[i + 2] = arrhi[i + 2];
  1418. arrlo[i + 3] = arrhi[i + 3];
  1419. arrlo[i + 0] = arrlo[i + 1] = 0;
  1420. arrhi[i + 2] = arrhi[i + 3] = 0;
  1421. }
  1422. hi = array_to_constant (imode, arrhi);
  1423. lo = array_to_constant (imode, arrlo);
  1424. emit_move_insn (temp, hi);
  1425. emit_insn (gen_rtx_SET
  1426. (VOIDmode, to, gen_rtx_IOR (imode, temp, lo)));
  1427. return 1;
  1428. }
  1429. case IC_FSMBI2:
  1430. {
  1431. unsigned char arr_fsmbi[16];
  1432. unsigned char arr_andbi[16];
  1433. rtx to, reg_fsmbi, reg_and;
  1434. int i;
  1435. machine_mode imode = mode;
  1436. /* We need to do reals as ints because the constant used in the
  1437. * AND might not be a legitimate real constant. */
  1438. imode = int_mode_for_mode (mode);
  1439. constant_to_array (mode, ops[1], arr_fsmbi);
  1440. if (imode != mode)
  1441. to = simplify_gen_subreg(imode, ops[0], GET_MODE (ops[0]), 0);
  1442. else
  1443. to = ops[0];
  1444. for (i = 0; i < 16; i++)
  1445. if (arr_fsmbi[i] != 0)
  1446. {
  1447. arr_andbi[0] = arr_fsmbi[i];
  1448. arr_fsmbi[i] = 0xff;
  1449. }
  1450. for (i = 1; i < 16; i++)
  1451. arr_andbi[i] = arr_andbi[0];
  1452. reg_fsmbi = array_to_constant (imode, arr_fsmbi);
  1453. reg_and = array_to_constant (imode, arr_andbi);
  1454. emit_move_insn (to, reg_fsmbi);
  1455. emit_insn (gen_rtx_SET
  1456. (VOIDmode, to, gen_rtx_AND (imode, to, reg_and)));
  1457. return 1;
  1458. }
  1459. case IC_POOL:
  1460. if (reload_in_progress || reload_completed)
  1461. {
  1462. rtx mem = force_const_mem (mode, ops[1]);
  1463. if (TARGET_LARGE_MEM)
  1464. {
  1465. rtx addr = gen_rtx_REG (Pmode, REGNO (ops[0]));
  1466. emit_move_insn (addr, XEXP (mem, 0));
  1467. mem = replace_equiv_address (mem, addr);
  1468. }
  1469. emit_move_insn (ops[0], mem);
  1470. return 1;
  1471. }
  1472. break;
  1473. case IC_IL1s:
  1474. case IC_IL2s:
  1475. if (reload_completed && GET_CODE (ops[1]) != HIGH)
  1476. {
  1477. if (c == IC_IL2s)
  1478. {
  1479. emit_move_insn (ops[0], gen_rtx_HIGH (mode, ops[1]));
  1480. emit_move_insn (ops[0], gen_rtx_LO_SUM (mode, ops[0], ops[1]));
  1481. }
  1482. else if (flag_pic)
  1483. emit_insn (gen_pic (ops[0], ops[1]));
  1484. if (flag_pic)
  1485. {
  1486. rtx pic_reg = get_pic_reg ();
  1487. emit_insn (gen_addsi3 (ops[0], ops[0], pic_reg));
  1488. }
  1489. return flag_pic || c == IC_IL2s;
  1490. }
  1491. break;
  1492. case IC_IL1:
  1493. case IC_FSMBI:
  1494. case IC_CPAT:
  1495. break;
  1496. }
  1497. return 0;
  1498. }
  1499. /* SAVING is TRUE when we are generating the actual load and store
  1500. instructions for REGNO. When determining the size of the stack
  1501. needed for saving register we must allocate enough space for the
  1502. worst case, because we don't always have the information early enough
  1503. to not allocate it. But we can at least eliminate the actual loads
  1504. and stores during the prologue/epilogue. */
  1505. static int
  1506. need_to_save_reg (int regno, int saving)
  1507. {
  1508. if (df_regs_ever_live_p (regno) && !call_used_regs[regno])
  1509. return 1;
  1510. if (flag_pic
  1511. && regno == PIC_OFFSET_TABLE_REGNUM
  1512. && (!saving || cfun->machine->pic_reg == pic_offset_table_rtx))
  1513. return 1;
  1514. return 0;
  1515. }
  1516. /* This function is only correct starting with local register
  1517. allocation */
  1518. int
  1519. spu_saved_regs_size (void)
  1520. {
  1521. int reg_save_size = 0;
  1522. int regno;
  1523. for (regno = FIRST_PSEUDO_REGISTER - 1; regno >= 0; --regno)
  1524. if (need_to_save_reg (regno, 0))
  1525. reg_save_size += 0x10;
  1526. return reg_save_size;
  1527. }
  1528. static rtx_insn *
  1529. frame_emit_store (int regno, rtx addr, HOST_WIDE_INT offset)
  1530. {
  1531. rtx reg = gen_rtx_REG (V4SImode, regno);
  1532. rtx mem =
  1533. gen_frame_mem (V4SImode, gen_rtx_PLUS (Pmode, addr, GEN_INT (offset)));
  1534. return emit_insn (gen_movv4si (mem, reg));
  1535. }
  1536. static rtx_insn *
  1537. frame_emit_load (int regno, rtx addr, HOST_WIDE_INT offset)
  1538. {
  1539. rtx reg = gen_rtx_REG (V4SImode, regno);
  1540. rtx mem =
  1541. gen_frame_mem (V4SImode, gen_rtx_PLUS (Pmode, addr, GEN_INT (offset)));
  1542. return emit_insn (gen_movv4si (reg, mem));
  1543. }
  1544. /* This happens after reload, so we need to expand it. */
  1545. static rtx_insn *
  1546. frame_emit_add_imm (rtx dst, rtx src, HOST_WIDE_INT imm, rtx scratch)
  1547. {
  1548. rtx_insn *insn;
  1549. if (satisfies_constraint_K (GEN_INT (imm)))
  1550. {
  1551. insn = emit_insn (gen_addsi3 (dst, src, GEN_INT (imm)));
  1552. }
  1553. else
  1554. {
  1555. emit_insn (gen_movsi (scratch, gen_int_mode (imm, SImode)));
  1556. insn = emit_insn (gen_addsi3 (dst, src, scratch));
  1557. if (REGNO (src) == REGNO (scratch))
  1558. abort ();
  1559. }
  1560. return insn;
  1561. }
  1562. /* Return nonzero if this function is known to have a null epilogue. */
  1563. int
  1564. direct_return (void)
  1565. {
  1566. if (reload_completed)
  1567. {
  1568. if (cfun->static_chain_decl == 0
  1569. && (spu_saved_regs_size ()
  1570. + get_frame_size ()
  1571. + crtl->outgoing_args_size
  1572. + crtl->args.pretend_args_size == 0)
  1573. && crtl->is_leaf)
  1574. return 1;
  1575. }
  1576. return 0;
  1577. }
  1578. /*
  1579. The stack frame looks like this:
  1580. +-------------+
  1581. | incoming |
  1582. | args |
  1583. AP -> +-------------+
  1584. | $lr save |
  1585. +-------------+
  1586. prev SP | back chain |
  1587. +-------------+
  1588. | var args |
  1589. | reg save | crtl->args.pretend_args_size bytes
  1590. +-------------+
  1591. | ... |
  1592. | saved regs | spu_saved_regs_size() bytes
  1593. FP -> +-------------+
  1594. | ... |
  1595. | vars | get_frame_size() bytes
  1596. HFP -> +-------------+
  1597. | ... |
  1598. | outgoing |
  1599. | args | crtl->outgoing_args_size bytes
  1600. +-------------+
  1601. | $lr of next |
  1602. | frame |
  1603. +-------------+
  1604. | back chain |
  1605. SP -> +-------------+
  1606. */
  1607. void
  1608. spu_expand_prologue (void)
  1609. {
  1610. HOST_WIDE_INT size = get_frame_size (), offset, regno;
  1611. HOST_WIDE_INT total_size;
  1612. HOST_WIDE_INT saved_regs_size;
  1613. rtx sp_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
  1614. rtx scratch_reg_0, scratch_reg_1;
  1615. rtx_insn *insn;
  1616. rtx real;
  1617. if (flag_pic && optimize == 0 && !cfun->machine->pic_reg)
  1618. cfun->machine->pic_reg = pic_offset_table_rtx;
  1619. if (spu_naked_function_p (current_function_decl))
  1620. return;
  1621. scratch_reg_0 = gen_rtx_REG (SImode, LAST_ARG_REGNUM + 1);
  1622. scratch_reg_1 = gen_rtx_REG (SImode, LAST_ARG_REGNUM + 2);
  1623. saved_regs_size = spu_saved_regs_size ();
  1624. total_size = size + saved_regs_size
  1625. + crtl->outgoing_args_size
  1626. + crtl->args.pretend_args_size;
  1627. if (!crtl->is_leaf
  1628. || cfun->calls_alloca || total_size > 0)
  1629. total_size += STACK_POINTER_OFFSET;
  1630. /* Save this first because code after this might use the link
  1631. register as a scratch register. */
  1632. if (!crtl->is_leaf)
  1633. {
  1634. insn = frame_emit_store (LINK_REGISTER_REGNUM, sp_reg, 16);
  1635. RTX_FRAME_RELATED_P (insn) = 1;
  1636. }
  1637. if (total_size > 0)
  1638. {
  1639. offset = -crtl->args.pretend_args_size;
  1640. for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
  1641. if (need_to_save_reg (regno, 1))
  1642. {
  1643. offset -= 16;
  1644. insn = frame_emit_store (regno, sp_reg, offset);
  1645. RTX_FRAME_RELATED_P (insn) = 1;
  1646. }
  1647. }
  1648. if (flag_pic && cfun->machine->pic_reg)
  1649. {
  1650. rtx pic_reg = cfun->machine->pic_reg;
  1651. insn = emit_insn (gen_load_pic_offset (pic_reg, scratch_reg_0));
  1652. insn = emit_insn (gen_subsi3 (pic_reg, pic_reg, scratch_reg_0));
  1653. }
  1654. if (total_size > 0)
  1655. {
  1656. if (flag_stack_check)
  1657. {
  1658. /* We compare against total_size-1 because
  1659. ($sp >= total_size) <=> ($sp > total_size-1) */
  1660. rtx scratch_v4si = gen_rtx_REG (V4SImode, REGNO (scratch_reg_0));
  1661. rtx sp_v4si = gen_rtx_REG (V4SImode, STACK_POINTER_REGNUM);
  1662. rtx size_v4si = spu_const (V4SImode, total_size - 1);
  1663. if (!satisfies_constraint_K (GEN_INT (total_size - 1)))
  1664. {
  1665. emit_move_insn (scratch_v4si, size_v4si);
  1666. size_v4si = scratch_v4si;
  1667. }
  1668. emit_insn (gen_cgt_v4si (scratch_v4si, sp_v4si, size_v4si));
  1669. emit_insn (gen_vec_extractv4si
  1670. (scratch_reg_0, scratch_v4si, GEN_INT (1)));
  1671. emit_insn (gen_spu_heq (scratch_reg_0, GEN_INT (0)));
  1672. }
  1673. /* Adjust the stack pointer, and make sure scratch_reg_0 contains
  1674. the value of the previous $sp because we save it as the back
  1675. chain. */
  1676. if (total_size <= 2000)
  1677. {
  1678. /* In this case we save the back chain first. */
  1679. insn = frame_emit_store (STACK_POINTER_REGNUM, sp_reg, -total_size);
  1680. insn =
  1681. frame_emit_add_imm (sp_reg, sp_reg, -total_size, scratch_reg_0);
  1682. }
  1683. else
  1684. {
  1685. insn = emit_move_insn (scratch_reg_0, sp_reg);
  1686. insn =
  1687. frame_emit_add_imm (sp_reg, sp_reg, -total_size, scratch_reg_1);
  1688. }
  1689. RTX_FRAME_RELATED_P (insn) = 1;
  1690. real = gen_addsi3 (sp_reg, sp_reg, GEN_INT (-total_size));
  1691. add_reg_note (insn, REG_FRAME_RELATED_EXPR, real);
  1692. if (total_size > 2000)
  1693. {
  1694. /* Save the back chain ptr */
  1695. insn = frame_emit_store (REGNO (scratch_reg_0), sp_reg, 0);
  1696. }
  1697. if (frame_pointer_needed)
  1698. {
  1699. rtx fp_reg = gen_rtx_REG (Pmode, HARD_FRAME_POINTER_REGNUM);
  1700. HOST_WIDE_INT fp_offset = STACK_POINTER_OFFSET
  1701. + crtl->outgoing_args_size;
  1702. /* Set the new frame_pointer */
  1703. insn = frame_emit_add_imm (fp_reg, sp_reg, fp_offset, scratch_reg_0);
  1704. RTX_FRAME_RELATED_P (insn) = 1;
  1705. real = gen_addsi3 (fp_reg, sp_reg, GEN_INT (fp_offset));
  1706. add_reg_note (insn, REG_FRAME_RELATED_EXPR, real);
  1707. REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = STACK_BOUNDARY;
  1708. }
  1709. }
  1710. if (flag_stack_usage_info)
  1711. current_function_static_stack_size = total_size;
  1712. }
  1713. void
  1714. spu_expand_epilogue (bool sibcall_p)
  1715. {
  1716. int size = get_frame_size (), offset, regno;
  1717. HOST_WIDE_INT saved_regs_size, total_size;
  1718. rtx sp_reg = gen_rtx_REG (Pmode, STACK_POINTER_REGNUM);
  1719. rtx scratch_reg_0;
  1720. if (spu_naked_function_p (current_function_decl))
  1721. return;
  1722. scratch_reg_0 = gen_rtx_REG (SImode, LAST_ARG_REGNUM + 1);
  1723. saved_regs_size = spu_saved_regs_size ();
  1724. total_size = size + saved_regs_size
  1725. + crtl->outgoing_args_size
  1726. + crtl->args.pretend_args_size;
  1727. if (!crtl->is_leaf
  1728. || cfun->calls_alloca || total_size > 0)
  1729. total_size += STACK_POINTER_OFFSET;
  1730. if (total_size > 0)
  1731. {
  1732. if (cfun->calls_alloca)
  1733. frame_emit_load (STACK_POINTER_REGNUM, sp_reg, 0);
  1734. else
  1735. frame_emit_add_imm (sp_reg, sp_reg, total_size, scratch_reg_0);
  1736. if (saved_regs_size > 0)
  1737. {
  1738. offset = -crtl->args.pretend_args_size;
  1739. for (regno = 0; regno < FIRST_PSEUDO_REGISTER; ++regno)
  1740. if (need_to_save_reg (regno, 1))
  1741. {
  1742. offset -= 0x10;
  1743. frame_emit_load (regno, sp_reg, offset);
  1744. }
  1745. }
  1746. }
  1747. if (!crtl->is_leaf)
  1748. frame_emit_load (LINK_REGISTER_REGNUM, sp_reg, 16);
  1749. if (!sibcall_p)
  1750. {
  1751. emit_use (gen_rtx_REG (SImode, LINK_REGISTER_REGNUM));
  1752. emit_jump_insn (gen__return ());
  1753. }
  1754. }
  1755. rtx
  1756. spu_return_addr (int count, rtx frame ATTRIBUTE_UNUSED)
  1757. {
  1758. if (count != 0)
  1759. return 0;
  1760. /* This is inefficient because it ends up copying to a save-register
  1761. which then gets saved even though $lr has already been saved. But
  1762. it does generate better code for leaf functions and we don't need
  1763. to use RETURN_ADDRESS_POINTER_REGNUM to get it working. It's only
  1764. used for __builtin_return_address anyway, so maybe we don't care if
  1765. it's inefficient. */
  1766. return get_hard_reg_initial_val (Pmode, LINK_REGISTER_REGNUM);
  1767. }
  1768. /* Given VAL, generate a constant appropriate for MODE.
  1769. If MODE is a vector mode, every element will be VAL.
  1770. For TImode, VAL will be zero extended to 128 bits. */
  1771. rtx
  1772. spu_const (machine_mode mode, HOST_WIDE_INT val)
  1773. {
  1774. rtx inner;
  1775. rtvec v;
  1776. int units, i;
  1777. gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
  1778. || GET_MODE_CLASS (mode) == MODE_FLOAT
  1779. || GET_MODE_CLASS (mode) == MODE_VECTOR_INT
  1780. || GET_MODE_CLASS (mode) == MODE_VECTOR_FLOAT);
  1781. if (GET_MODE_CLASS (mode) == MODE_INT)
  1782. return immed_double_const (val, 0, mode);
  1783. /* val is the bit representation of the float */
  1784. if (GET_MODE_CLASS (mode) == MODE_FLOAT)
  1785. return hwint_to_const_double (mode, val);
  1786. if (GET_MODE_CLASS (mode) == MODE_VECTOR_INT)
  1787. inner = immed_double_const (val, 0, GET_MODE_INNER (mode));
  1788. else
  1789. inner = hwint_to_const_double (GET_MODE_INNER (mode), val);
  1790. units = GET_MODE_NUNITS (mode);
  1791. v = rtvec_alloc (units);
  1792. for (i = 0; i < units; ++i)
  1793. RTVEC_ELT (v, i) = inner;
  1794. return gen_rtx_CONST_VECTOR (mode, v);
  1795. }
  1796. /* Create a MODE vector constant from 4 ints. */
  1797. rtx
  1798. spu_const_from_ints(machine_mode mode, int a, int b, int c, int d)
  1799. {
  1800. unsigned char arr[16];
  1801. arr[0] = (a >> 24) & 0xff;
  1802. arr[1] = (a >> 16) & 0xff;
  1803. arr[2] = (a >> 8) & 0xff;
  1804. arr[3] = (a >> 0) & 0xff;
  1805. arr[4] = (b >> 24) & 0xff;
  1806. arr[5] = (b >> 16) & 0xff;
  1807. arr[6] = (b >> 8) & 0xff;
  1808. arr[7] = (b >> 0) & 0xff;
  1809. arr[8] = (c >> 24) & 0xff;
  1810. arr[9] = (c >> 16) & 0xff;
  1811. arr[10] = (c >> 8) & 0xff;
  1812. arr[11] = (c >> 0) & 0xff;
  1813. arr[12] = (d >> 24) & 0xff;
  1814. arr[13] = (d >> 16) & 0xff;
  1815. arr[14] = (d >> 8) & 0xff;
  1816. arr[15] = (d >> 0) & 0xff;
  1817. return array_to_constant(mode, arr);
  1818. }
  1819. /* branch hint stuff */
  1820. /* An array of these is used to propagate hints to predecessor blocks. */
  1821. struct spu_bb_info
  1822. {
  1823. rtx_insn *prop_jump; /* propagated from another block */
  1824. int bb_index; /* the original block. */
  1825. };
  1826. static struct spu_bb_info *spu_bb_info;
  1827. #define STOP_HINT_P(INSN) \
  1828. (CALL_P(INSN) \
  1829. || INSN_CODE(INSN) == CODE_FOR_divmodsi4 \
  1830. || INSN_CODE(INSN) == CODE_FOR_udivmodsi4)
  1831. /* 1 when RTX is a hinted branch or its target. We keep track of
  1832. what has been hinted so the safe-hint code can test it easily. */
  1833. #define HINTED_P(RTX) \
  1834. (RTL_FLAG_CHECK3("HINTED_P", (RTX), CODE_LABEL, JUMP_INSN, CALL_INSN)->unchanging)
  1835. /* 1 when RTX is an insn that must be scheduled on an even boundary. */
  1836. #define SCHED_ON_EVEN_P(RTX) \
  1837. (RTL_FLAG_CHECK2("SCHED_ON_EVEN_P", (RTX), JUMP_INSN, CALL_INSN)->in_struct)
  1838. /* Emit a nop for INSN such that the two will dual issue. This assumes
  1839. INSN is 8-byte aligned. When INSN is inline asm we emit an lnop.
  1840. We check for TImode to handle a MULTI1 insn which has dual issued its
  1841. first instruction. get_pipe returns -1 for MULTI0 or inline asm. */
  1842. static void
  1843. emit_nop_for_insn (rtx_insn *insn)
  1844. {
  1845. int p;
  1846. rtx_insn *new_insn;
  1847. /* We need to handle JUMP_TABLE_DATA separately. */
  1848. if (JUMP_TABLE_DATA_P (insn))
  1849. {
  1850. new_insn = emit_insn_after (gen_lnop(), insn);
  1851. recog_memoized (new_insn);
  1852. INSN_LOCATION (new_insn) = UNKNOWN_LOCATION;
  1853. return;
  1854. }
  1855. p = get_pipe (insn);
  1856. if ((CALL_P (insn) || JUMP_P (insn)) && SCHED_ON_EVEN_P (insn))
  1857. new_insn = emit_insn_after (gen_lnop (), insn);
  1858. else if (p == 1 && GET_MODE (insn) == TImode)
  1859. {
  1860. new_insn = emit_insn_before (gen_nopn (GEN_INT (127)), insn);
  1861. PUT_MODE (new_insn, TImode);
  1862. PUT_MODE (insn, VOIDmode);
  1863. }
  1864. else
  1865. new_insn = emit_insn_after (gen_lnop (), insn);
  1866. recog_memoized (new_insn);
  1867. INSN_LOCATION (new_insn) = INSN_LOCATION (insn);
  1868. }
  1869. /* Insert nops in basic blocks to meet dual issue alignment
  1870. requirements. Also make sure hbrp and hint instructions are at least
  1871. one cycle apart, possibly inserting a nop. */
  1872. static void
  1873. pad_bb(void)
  1874. {
  1875. rtx_insn *insn, *next_insn, *prev_insn, *hbr_insn = 0;
  1876. int length;
  1877. int addr;
  1878. /* This sets up INSN_ADDRESSES. */
  1879. shorten_branches (get_insns ());
  1880. /* Keep track of length added by nops. */
  1881. length = 0;
  1882. prev_insn = 0;
  1883. insn = get_insns ();
  1884. if (!active_insn_p (insn))
  1885. insn = next_active_insn (insn);
  1886. for (; insn; insn = next_insn)
  1887. {
  1888. next_insn = next_active_insn (insn);
  1889. if (INSN_CODE (insn) == CODE_FOR_iprefetch
  1890. || INSN_CODE (insn) == CODE_FOR_hbr)
  1891. {
  1892. if (hbr_insn)
  1893. {
  1894. int a0 = INSN_ADDRESSES (INSN_UID (hbr_insn));
  1895. int a1 = INSN_ADDRESSES (INSN_UID (insn));
  1896. if ((a1 - a0 == 8 && GET_MODE (insn) != TImode)
  1897. || (a1 - a0 == 4))
  1898. {
  1899. prev_insn = emit_insn_before (gen_lnop (), insn);
  1900. PUT_MODE (prev_insn, GET_MODE (insn));
  1901. PUT_MODE (insn, TImode);
  1902. INSN_LOCATION (prev_insn) = INSN_LOCATION (insn);
  1903. length += 4;
  1904. }
  1905. }
  1906. hbr_insn = insn;
  1907. }
  1908. if (INSN_CODE (insn) == CODE_FOR_blockage && next_insn)
  1909. {
  1910. if (GET_MODE (insn) == TImode)
  1911. PUT_MODE (next_insn, TImode);
  1912. insn = next_insn;
  1913. next_insn = next_active_insn (insn);
  1914. }
  1915. addr = INSN_ADDRESSES (INSN_UID (insn));
  1916. if ((CALL_P (insn) || JUMP_P (insn)) && SCHED_ON_EVEN_P (insn))
  1917. {
  1918. if (((addr + length) & 7) != 0)
  1919. {
  1920. emit_nop_for_insn (prev_insn);
  1921. length += 4;
  1922. }
  1923. }
  1924. else if (GET_MODE (insn) == TImode
  1925. && ((next_insn && GET_MODE (next_insn) != TImode)
  1926. || get_attr_type (insn) == TYPE_MULTI0)
  1927. && ((addr + length) & 7) != 0)
  1928. {
  1929. /* prev_insn will always be set because the first insn is
  1930. always 8-byte aligned. */
  1931. emit_nop_for_insn (prev_insn);
  1932. length += 4;
  1933. }
  1934. prev_insn = insn;
  1935. }
  1936. }
  1937. /* Routines for branch hints. */
  1938. static void
  1939. spu_emit_branch_hint (rtx_insn *before, rtx_insn *branch, rtx target,
  1940. int distance, sbitmap blocks)
  1941. {
  1942. rtx branch_label = 0;
  1943. rtx_insn *hint;
  1944. rtx_insn *insn;
  1945. rtx_jump_table_data *table;
  1946. if (before == 0 || branch == 0 || target == 0)
  1947. return;
  1948. /* While scheduling we require hints to be no further than 600, so
  1949. we need to enforce that here too */
  1950. if (distance > 600)
  1951. return;
  1952. /* If we have a Basic block note, emit it after the basic block note. */
  1953. if (NOTE_INSN_BASIC_BLOCK_P (before))
  1954. before = NEXT_INSN (before);
  1955. branch_label = gen_label_rtx ();
  1956. LABEL_NUSES (branch_label)++;
  1957. LABEL_PRESERVE_P (branch_label) = 1;
  1958. insn = emit_label_before (branch_label, branch);
  1959. branch_label = gen_rtx_LABEL_REF (VOIDmode, branch_label);
  1960. bitmap_set_bit (blocks, BLOCK_FOR_INSN (branch)->index);
  1961. hint = emit_insn_before (gen_hbr (branch_label, target), before);
  1962. recog_memoized (hint);
  1963. INSN_LOCATION (hint) = INSN_LOCATION (branch);
  1964. HINTED_P (branch) = 1;
  1965. if (GET_CODE (target) == LABEL_REF)
  1966. HINTED_P (XEXP (target, 0)) = 1;
  1967. else if (tablejump_p (branch, 0, &table))
  1968. {
  1969. rtvec vec;
  1970. int j;
  1971. if (GET_CODE (PATTERN (table)) == ADDR_VEC)
  1972. vec = XVEC (PATTERN (table), 0);
  1973. else
  1974. vec = XVEC (PATTERN (table), 1);
  1975. for (j = GET_NUM_ELEM (vec) - 1; j >= 0; --j)
  1976. HINTED_P (XEXP (RTVEC_ELT (vec, j), 0)) = 1;
  1977. }
  1978. if (distance >= 588)
  1979. {
  1980. /* Make sure the hint isn't scheduled any earlier than this point,
  1981. which could make it too far for the branch offest to fit */
  1982. insn = emit_insn_before (gen_blockage (), hint);
  1983. recog_memoized (insn);
  1984. INSN_LOCATION (insn) = INSN_LOCATION (hint);
  1985. }
  1986. else if (distance <= 8 * 4)
  1987. {
  1988. /* To guarantee at least 8 insns between the hint and branch we
  1989. insert nops. */
  1990. int d;
  1991. for (d = distance; d < 8 * 4; d += 4)
  1992. {
  1993. insn =
  1994. emit_insn_after (gen_nopn_nv (gen_rtx_REG (SImode, 127)), hint);
  1995. recog_memoized (insn);
  1996. INSN_LOCATION (insn) = INSN_LOCATION (hint);
  1997. }
  1998. /* Make sure any nops inserted aren't scheduled before the hint. */
  1999. insn = emit_insn_after (gen_blockage (), hint);
  2000. recog_memoized (insn);
  2001. INSN_LOCATION (insn) = INSN_LOCATION (hint);
  2002. /* Make sure any nops inserted aren't scheduled after the call. */
  2003. if (CALL_P (branch) && distance < 8 * 4)
  2004. {
  2005. insn = emit_insn_before (gen_blockage (), branch);
  2006. recog_memoized (insn);
  2007. INSN_LOCATION (insn) = INSN_LOCATION (branch);
  2008. }
  2009. }
  2010. }
  2011. /* Returns 0 if we don't want a hint for this branch. Otherwise return
  2012. the rtx for the branch target. */
  2013. static rtx
  2014. get_branch_target (rtx_insn *branch)
  2015. {
  2016. if (JUMP_P (branch))
  2017. {
  2018. rtx set, src;
  2019. /* Return statements */
  2020. if (GET_CODE (PATTERN (branch)) == RETURN)
  2021. return gen_rtx_REG (SImode, LINK_REGISTER_REGNUM);
  2022. /* ASM GOTOs. */
  2023. if (extract_asm_operands (PATTERN (branch)) != NULL)
  2024. return NULL;
  2025. set = single_set (branch);
  2026. src = SET_SRC (set);
  2027. if (GET_CODE (SET_DEST (set)) != PC)
  2028. abort ();
  2029. if (GET_CODE (src) == IF_THEN_ELSE)
  2030. {
  2031. rtx lab = 0;
  2032. rtx note = find_reg_note (branch, REG_BR_PROB, 0);
  2033. if (note)
  2034. {
  2035. /* If the more probable case is not a fall through, then
  2036. try a branch hint. */
  2037. int prob = XINT (note, 0);
  2038. if (prob > (REG_BR_PROB_BASE * 6 / 10)
  2039. && GET_CODE (XEXP (src, 1)) != PC)
  2040. lab = XEXP (src, 1);
  2041. else if (prob < (REG_BR_PROB_BASE * 4 / 10)
  2042. && GET_CODE (XEXP (src, 2)) != PC)
  2043. lab = XEXP (src, 2);
  2044. }
  2045. if (lab)
  2046. {
  2047. if (GET_CODE (lab) == RETURN)
  2048. return gen_rtx_REG (SImode, LINK_REGISTER_REGNUM);
  2049. return lab;
  2050. }
  2051. return 0;
  2052. }
  2053. return src;
  2054. }
  2055. else if (CALL_P (branch))
  2056. {
  2057. rtx call;
  2058. /* All of our call patterns are in a PARALLEL and the CALL is
  2059. the first pattern in the PARALLEL. */
  2060. if (GET_CODE (PATTERN (branch)) != PARALLEL)
  2061. abort ();
  2062. call = XVECEXP (PATTERN (branch), 0, 0);
  2063. if (GET_CODE (call) == SET)
  2064. call = SET_SRC (call);
  2065. if (GET_CODE (call) != CALL)
  2066. abort ();
  2067. return XEXP (XEXP (call, 0), 0);
  2068. }
  2069. return 0;
  2070. }
  2071. /* The special $hbr register is used to prevent the insn scheduler from
  2072. moving hbr insns across instructions which invalidate them. It
  2073. should only be used in a clobber, and this function searches for
  2074. insns which clobber it. */
  2075. static bool
  2076. insn_clobbers_hbr (rtx_insn *insn)
  2077. {
  2078. if (INSN_P (insn)
  2079. && GET_CODE (PATTERN (insn)) == PARALLEL)
  2080. {
  2081. rtx parallel = PATTERN (insn);
  2082. rtx clobber;
  2083. int j;
  2084. for (j = XVECLEN (parallel, 0) - 1; j >= 0; j--)
  2085. {
  2086. clobber = XVECEXP (parallel, 0, j);
  2087. if (GET_CODE (clobber) == CLOBBER
  2088. && GET_CODE (XEXP (clobber, 0)) == REG
  2089. && REGNO (XEXP (clobber, 0)) == HBR_REGNUM)
  2090. return 1;
  2091. }
  2092. }
  2093. return 0;
  2094. }
  2095. /* Search up to 32 insns starting at FIRST:
  2096. - at any kind of hinted branch, just return
  2097. - at any unconditional branch in the first 15 insns, just return
  2098. - at a call or indirect branch, after the first 15 insns, force it to
  2099. an even address and return
  2100. - at any unconditional branch, after the first 15 insns, force it to
  2101. an even address.
  2102. At then end of the search, insert an hbrp within 4 insns of FIRST,
  2103. and an hbrp within 16 instructions of FIRST.
  2104. */
  2105. static void
  2106. insert_hbrp_for_ilb_runout (rtx_insn *first)
  2107. {
  2108. rtx_insn *insn, *before_4 = 0, *before_16 = 0;
  2109. int addr = 0, length, first_addr = -1;
  2110. int hbrp_addr0 = 128 * 4, hbrp_addr1 = 128 * 4;
  2111. int insert_lnop_after = 0;
  2112. for (insn = first; insn; insn = NEXT_INSN (insn))
  2113. if (INSN_P (insn))
  2114. {
  2115. if (first_addr == -1)
  2116. first_addr = INSN_ADDRESSES (INSN_UID (insn));
  2117. addr = INSN_ADDRESSES (INSN_UID (insn)) - first_addr;
  2118. length = get_attr_length (insn);
  2119. if (before_4 == 0 && addr + length >= 4 * 4)
  2120. before_4 = insn;
  2121. /* We test for 14 instructions because the first hbrp will add
  2122. up to 2 instructions. */
  2123. if (before_16 == 0 && addr + length >= 14 * 4)
  2124. before_16 = insn;
  2125. if (INSN_CODE (insn) == CODE_FOR_hbr)
  2126. {
  2127. /* Make sure an hbrp is at least 2 cycles away from a hint.
  2128. Insert an lnop after the hbrp when necessary. */
  2129. if (before_4 == 0 && addr > 0)
  2130. {
  2131. before_4 = insn;
  2132. insert_lnop_after |= 1;
  2133. }
  2134. else if (before_4 && addr <= 4 * 4)
  2135. insert_lnop_after |= 1;
  2136. if (before_16 == 0 && addr > 10 * 4)
  2137. {
  2138. before_16 = insn;
  2139. insert_lnop_after |= 2;
  2140. }
  2141. else if (before_16 && addr <= 14 * 4)
  2142. insert_lnop_after |= 2;
  2143. }
  2144. if (INSN_CODE (insn) == CODE_FOR_iprefetch)
  2145. {
  2146. if (addr < hbrp_addr0)
  2147. hbrp_addr0 = addr;
  2148. else if (addr < hbrp_addr1)
  2149. hbrp_addr1 = addr;
  2150. }
  2151. if (CALL_P (insn) || JUMP_P (insn))
  2152. {
  2153. if (HINTED_P (insn))
  2154. return;
  2155. /* Any branch after the first 15 insns should be on an even
  2156. address to avoid a special case branch. There might be
  2157. some nops and/or hbrps inserted, so we test after 10
  2158. insns. */
  2159. if (addr > 10 * 4)
  2160. SCHED_ON_EVEN_P (insn) = 1;
  2161. }
  2162. if (CALL_P (insn) || tablejump_p (insn, 0, 0))
  2163. return;
  2164. if (addr + length >= 32 * 4)
  2165. {
  2166. gcc_assert (before_4 && before_16);
  2167. if (hbrp_addr0 > 4 * 4)
  2168. {
  2169. insn =
  2170. emit_insn_before (gen_iprefetch (GEN_INT (1)), before_4);
  2171. recog_memoized (insn);
  2172. INSN_LOCATION (insn) = INSN_LOCATION (before_4);
  2173. INSN_ADDRESSES_NEW (insn,
  2174. INSN_ADDRESSES (INSN_UID (before_4)));
  2175. PUT_MODE (insn, GET_MODE (before_4));
  2176. PUT_MODE (before_4, TImode);
  2177. if (insert_lnop_after & 1)
  2178. {
  2179. insn = emit_insn_before (gen_lnop (), before_4);
  2180. recog_memoized (insn);
  2181. INSN_LOCATION (insn) = INSN_LOCATION (before_4);
  2182. INSN_ADDRESSES_NEW (insn,
  2183. INSN_ADDRESSES (INSN_UID (before_4)));
  2184. PUT_MODE (insn, TImode);
  2185. }
  2186. }
  2187. if ((hbrp_addr0 <= 4 * 4 || hbrp_addr0 > 16 * 4)
  2188. && hbrp_addr1 > 16 * 4)
  2189. {
  2190. insn =
  2191. emit_insn_before (gen_iprefetch (GEN_INT (2)), before_16);
  2192. recog_memoized (insn);
  2193. INSN_LOCATION (insn) = INSN_LOCATION (before_16);
  2194. INSN_ADDRESSES_NEW (insn,
  2195. INSN_ADDRESSES (INSN_UID (before_16)));
  2196. PUT_MODE (insn, GET_MODE (before_16));
  2197. PUT_MODE (before_16, TImode);
  2198. if (insert_lnop_after & 2)
  2199. {
  2200. insn = emit_insn_before (gen_lnop (), before_16);
  2201. recog_memoized (insn);
  2202. INSN_LOCATION (insn) = INSN_LOCATION (before_16);
  2203. INSN_ADDRESSES_NEW (insn,
  2204. INSN_ADDRESSES (INSN_UID
  2205. (before_16)));
  2206. PUT_MODE (insn, TImode);
  2207. }
  2208. }
  2209. return;
  2210. }
  2211. }
  2212. else if (BARRIER_P (insn))
  2213. return;
  2214. }
  2215. /* The SPU might hang when it executes 48 inline instructions after a
  2216. hinted branch jumps to its hinted target. The beginning of a
  2217. function and the return from a call might have been hinted, and
  2218. must be handled as well. To prevent a hang we insert 2 hbrps. The
  2219. first should be within 6 insns of the branch target. The second
  2220. should be within 22 insns of the branch target. When determining
  2221. if hbrps are necessary, we look for only 32 inline instructions,
  2222. because up to 12 nops and 4 hbrps could be inserted. Similarily,
  2223. when inserting new hbrps, we insert them within 4 and 16 insns of
  2224. the target. */
  2225. static void
  2226. insert_hbrp (void)
  2227. {
  2228. rtx_insn *insn;
  2229. if (TARGET_SAFE_HINTS)
  2230. {
  2231. shorten_branches (get_insns ());
  2232. /* Insert hbrp at beginning of function */
  2233. insn = next_active_insn (get_insns ());
  2234. if (insn)
  2235. insert_hbrp_for_ilb_runout (insn);
  2236. /* Insert hbrp after hinted targets. */
  2237. for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
  2238. if ((LABEL_P (insn) && HINTED_P (insn)) || CALL_P (insn))
  2239. insert_hbrp_for_ilb_runout (next_active_insn (insn));
  2240. }
  2241. }
  2242. static int in_spu_reorg;
  2243. static void
  2244. spu_var_tracking (void)
  2245. {
  2246. if (flag_var_tracking)
  2247. {
  2248. df_analyze ();
  2249. timevar_push (TV_VAR_TRACKING);
  2250. variable_tracking_main ();
  2251. timevar_pop (TV_VAR_TRACKING);
  2252. df_finish_pass (false);
  2253. }
  2254. }
  2255. /* Insert branch hints. There are no branch optimizations after this
  2256. pass, so it's safe to set our branch hints now. */
  2257. static void
  2258. spu_machine_dependent_reorg (void)
  2259. {
  2260. sbitmap blocks;
  2261. basic_block bb;
  2262. rtx_insn *branch, *insn;
  2263. rtx branch_target = 0;
  2264. int branch_addr = 0, insn_addr, required_dist = 0;
  2265. int i;
  2266. unsigned int j;
  2267. if (!TARGET_BRANCH_HINTS || optimize == 0)
  2268. {
  2269. /* We still do it for unoptimized code because an external
  2270. function might have hinted a call or return. */
  2271. compute_bb_for_insn ();
  2272. insert_hbrp ();
  2273. pad_bb ();
  2274. spu_var_tracking ();
  2275. free_bb_for_insn ();
  2276. return;
  2277. }
  2278. blocks = sbitmap_alloc (last_basic_block_for_fn (cfun));
  2279. bitmap_clear (blocks);
  2280. in_spu_reorg = 1;
  2281. compute_bb_for_insn ();
  2282. /* (Re-)discover loops so that bb->loop_father can be used
  2283. in the analysis below. */
  2284. loop_optimizer_init (AVOID_CFG_MODIFICATIONS);
  2285. compact_blocks ();
  2286. spu_bb_info =
  2287. (struct spu_bb_info *) xcalloc (n_basic_blocks_for_fn (cfun),
  2288. sizeof (struct spu_bb_info));
  2289. /* We need exact insn addresses and lengths. */
  2290. shorten_branches (get_insns ());
  2291. for (i = n_basic_blocks_for_fn (cfun) - 1; i >= 0; i--)
  2292. {
  2293. bb = BASIC_BLOCK_FOR_FN (cfun, i);
  2294. branch = 0;
  2295. if (spu_bb_info[i].prop_jump)
  2296. {
  2297. branch = spu_bb_info[i].prop_jump;
  2298. branch_target = get_branch_target (branch);
  2299. branch_addr = INSN_ADDRESSES (INSN_UID (branch));
  2300. required_dist = spu_hint_dist;
  2301. }
  2302. /* Search from end of a block to beginning. In this loop, find
  2303. jumps which need a branch and emit them only when:
  2304. - it's an indirect branch and we're at the insn which sets
  2305. the register
  2306. - we're at an insn that will invalidate the hint. e.g., a
  2307. call, another hint insn, inline asm that clobbers $hbr, and
  2308. some inlined operations (divmodsi4). Don't consider jumps
  2309. because they are only at the end of a block and are
  2310. considered when we are deciding whether to propagate
  2311. - we're getting too far away from the branch. The hbr insns
  2312. only have a signed 10 bit offset
  2313. We go back as far as possible so the branch will be considered
  2314. for propagation when we get to the beginning of the block. */
  2315. for (insn = BB_END (bb); insn; insn = PREV_INSN (insn))
  2316. {
  2317. if (INSN_P (insn))
  2318. {
  2319. insn_addr = INSN_ADDRESSES (INSN_UID (insn));
  2320. if (branch
  2321. && ((GET_CODE (branch_target) == REG
  2322. && set_of (branch_target, insn) != NULL_RTX)
  2323. || insn_clobbers_hbr (insn)
  2324. || branch_addr - insn_addr > 600))
  2325. {
  2326. rtx_insn *next = NEXT_INSN (insn);
  2327. int next_addr = INSN_ADDRESSES (INSN_UID (next));
  2328. if (insn != BB_END (bb)
  2329. && branch_addr - next_addr >= required_dist)
  2330. {
  2331. if (dump_file)
  2332. fprintf (dump_file,
  2333. "hint for %i in block %i before %i\n",
  2334. INSN_UID (branch), bb->index,
  2335. INSN_UID (next));
  2336. spu_emit_branch_hint (next, branch, branch_target,
  2337. branch_addr - next_addr, blocks);
  2338. }
  2339. branch = 0;
  2340. }
  2341. /* JUMP_P will only be true at the end of a block. When
  2342. branch is already set it means we've previously decided
  2343. to propagate a hint for that branch into this block. */
  2344. if (CALL_P (insn) || (JUMP_P (insn) && !branch))
  2345. {
  2346. branch = 0;
  2347. if ((branch_target = get_branch_target (insn)))
  2348. {
  2349. branch = insn;
  2350. branch_addr = insn_addr;
  2351. required_dist = spu_hint_dist;
  2352. }
  2353. }
  2354. }
  2355. if (insn == BB_HEAD (bb))
  2356. break;
  2357. }
  2358. if (branch)
  2359. {
  2360. /* If we haven't emitted a hint for this branch yet, it might
  2361. be profitable to emit it in one of the predecessor blocks,
  2362. especially for loops. */
  2363. rtx_insn *bbend;
  2364. basic_block prev = 0, prop = 0, prev2 = 0;
  2365. int loop_exit = 0, simple_loop = 0;
  2366. int next_addr = INSN_ADDRESSES (INSN_UID (NEXT_INSN (insn)));
  2367. for (j = 0; j < EDGE_COUNT (bb->preds); j++)
  2368. if (EDGE_PRED (bb, j)->flags & EDGE_FALLTHRU)
  2369. prev = EDGE_PRED (bb, j)->src;
  2370. else
  2371. prev2 = EDGE_PRED (bb, j)->src;
  2372. for (j = 0; j < EDGE_COUNT (bb->succs); j++)
  2373. if (EDGE_SUCC (bb, j)->flags & EDGE_LOOP_EXIT)
  2374. loop_exit = 1;
  2375. else if (EDGE_SUCC (bb, j)->dest == bb)
  2376. simple_loop = 1;
  2377. /* If this branch is a loop exit then propagate to previous
  2378. fallthru block. This catches the cases when it is a simple
  2379. loop or when there is an initial branch into the loop. */
  2380. if (prev && (loop_exit || simple_loop)
  2381. && bb_loop_depth (prev) <= bb_loop_depth (bb))
  2382. prop = prev;
  2383. /* If there is only one adjacent predecessor. Don't propagate
  2384. outside this loop. */
  2385. else if (prev && single_pred_p (bb)
  2386. && prev->loop_father == bb->loop_father)
  2387. prop = prev;
  2388. /* If this is the JOIN block of a simple IF-THEN then
  2389. propagate the hint to the HEADER block. */
  2390. else if (prev && prev2
  2391. && EDGE_COUNT (bb->preds) == 2
  2392. && EDGE_COUNT (prev->preds) == 1
  2393. && EDGE_PRED (prev, 0)->src == prev2
  2394. && prev2->loop_father == bb->loop_father
  2395. && GET_CODE (branch_target) != REG)
  2396. prop = prev;
  2397. /* Don't propagate when:
  2398. - this is a simple loop and the hint would be too far
  2399. - this is not a simple loop and there are 16 insns in
  2400. this block already
  2401. - the predecessor block ends in a branch that will be
  2402. hinted
  2403. - the predecessor block ends in an insn that invalidates
  2404. the hint */
  2405. if (prop
  2406. && prop->index >= 0
  2407. && (bbend = BB_END (prop))
  2408. && branch_addr - INSN_ADDRESSES (INSN_UID (bbend)) <
  2409. (simple_loop ? 600 : 16 * 4) && get_branch_target (bbend) == 0
  2410. && (JUMP_P (bbend) || !insn_clobbers_hbr (bbend)))
  2411. {
  2412. if (dump_file)
  2413. fprintf (dump_file, "propagate from %i to %i (loop depth %i) "
  2414. "for %i (loop_exit %i simple_loop %i dist %i)\n",
  2415. bb->index, prop->index, bb_loop_depth (bb),
  2416. INSN_UID (branch), loop_exit, simple_loop,
  2417. branch_addr - INSN_ADDRESSES (INSN_UID (bbend)));
  2418. spu_bb_info[prop->index].prop_jump = branch;
  2419. spu_bb_info[prop->index].bb_index = i;
  2420. }
  2421. else if (branch_addr - next_addr >= required_dist)
  2422. {
  2423. if (dump_file)
  2424. fprintf (dump_file, "hint for %i in block %i before %i\n",
  2425. INSN_UID (branch), bb->index,
  2426. INSN_UID (NEXT_INSN (insn)));
  2427. spu_emit_branch_hint (NEXT_INSN (insn), branch, branch_target,
  2428. branch_addr - next_addr, blocks);
  2429. }
  2430. branch = 0;
  2431. }
  2432. }
  2433. free (spu_bb_info);
  2434. if (!bitmap_empty_p (blocks))
  2435. find_many_sub_basic_blocks (blocks);
  2436. /* We have to schedule to make sure alignment is ok. */
  2437. FOR_EACH_BB_FN (bb, cfun) bb->flags &= ~BB_DISABLE_SCHEDULE;
  2438. /* The hints need to be scheduled, so call it again. */
  2439. schedule_insns ();
  2440. df_finish_pass (true);
  2441. insert_hbrp ();
  2442. pad_bb ();
  2443. for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
  2444. if (NONJUMP_INSN_P (insn) && INSN_CODE (insn) == CODE_FOR_hbr)
  2445. {
  2446. /* Adjust the LABEL_REF in a hint when we have inserted a nop
  2447. between its branch label and the branch . We don't move the
  2448. label because GCC expects it at the beginning of the block. */
  2449. rtx unspec = SET_SRC (XVECEXP (PATTERN (insn), 0, 0));
  2450. rtx label_ref = XVECEXP (unspec, 0, 0);
  2451. rtx_insn *label = as_a <rtx_insn *> (XEXP (label_ref, 0));
  2452. rtx_insn *branch;
  2453. int offset = 0;
  2454. for (branch = NEXT_INSN (label);
  2455. !JUMP_P (branch) && !CALL_P (branch);
  2456. branch = NEXT_INSN (branch))
  2457. if (NONJUMP_INSN_P (branch))
  2458. offset += get_attr_length (branch);
  2459. if (offset > 0)
  2460. XVECEXP (unspec, 0, 0) = plus_constant (Pmode, label_ref, offset);
  2461. }
  2462. spu_var_tracking ();
  2463. loop_optimizer_finalize ();
  2464. free_bb_for_insn ();
  2465. in_spu_reorg = 0;
  2466. }
  2467. /* Insn scheduling routines, primarily for dual issue. */
  2468. static int
  2469. spu_sched_issue_rate (void)
  2470. {
  2471. return 2;
  2472. }
  2473. static int
  2474. uses_ls_unit(rtx_insn *insn)
  2475. {
  2476. rtx set = single_set (insn);
  2477. if (set != 0
  2478. && (GET_CODE (SET_DEST (set)) == MEM
  2479. || GET_CODE (SET_SRC (set)) == MEM))
  2480. return 1;
  2481. return 0;
  2482. }
  2483. static int
  2484. get_pipe (rtx_insn *insn)
  2485. {
  2486. enum attr_type t;
  2487. /* Handle inline asm */
  2488. if (INSN_CODE (insn) == -1)
  2489. return -1;
  2490. t = get_attr_type (insn);
  2491. switch (t)
  2492. {
  2493. case TYPE_CONVERT:
  2494. return -2;
  2495. case TYPE_MULTI0:
  2496. return -1;
  2497. case TYPE_FX2:
  2498. case TYPE_FX3:
  2499. case TYPE_SPR:
  2500. case TYPE_NOP:
  2501. case TYPE_FXB:
  2502. case TYPE_FPD:
  2503. case TYPE_FP6:
  2504. case TYPE_FP7:
  2505. return 0;
  2506. case TYPE_LNOP:
  2507. case TYPE_SHUF:
  2508. case TYPE_LOAD:
  2509. case TYPE_STORE:
  2510. case TYPE_BR:
  2511. case TYPE_MULTI1:
  2512. case TYPE_HBR:
  2513. case TYPE_IPREFETCH:
  2514. return 1;
  2515. default:
  2516. abort ();
  2517. }
  2518. }
  2519. /* haifa-sched.c has a static variable that keeps track of the current
  2520. cycle. It is passed to spu_sched_reorder, and we record it here for
  2521. use by spu_sched_variable_issue. It won't be accurate if the
  2522. scheduler updates it's clock_var between the two calls. */
  2523. static int clock_var;
  2524. /* This is used to keep track of insn alignment. Set to 0 at the
  2525. beginning of each block and increased by the "length" attr of each
  2526. insn scheduled. */
  2527. static int spu_sched_length;
  2528. /* Record when we've issued pipe0 and pipe1 insns so we can reorder the
  2529. ready list appropriately in spu_sched_reorder(). */
  2530. static int pipe0_clock;
  2531. static int pipe1_clock;
  2532. static int prev_clock_var;
  2533. static int prev_priority;
  2534. /* The SPU needs to load the next ilb sometime during the execution of
  2535. the previous ilb. There is a potential conflict if every cycle has a
  2536. load or store. To avoid the conflict we make sure the load/store
  2537. unit is free for at least one cycle during the execution of insns in
  2538. the previous ilb. */
  2539. static int spu_ls_first;
  2540. static int prev_ls_clock;
  2541. static void
  2542. spu_sched_init_global (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
  2543. int max_ready ATTRIBUTE_UNUSED)
  2544. {
  2545. spu_sched_length = 0;
  2546. }
  2547. static void
  2548. spu_sched_init (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
  2549. int max_ready ATTRIBUTE_UNUSED)
  2550. {
  2551. if (align_labels > 4 || align_loops > 4 || align_jumps > 4)
  2552. {
  2553. /* When any block might be at least 8-byte aligned, assume they
  2554. will all be at least 8-byte aligned to make sure dual issue
  2555. works out correctly. */
  2556. spu_sched_length = 0;
  2557. }
  2558. spu_ls_first = INT_MAX;
  2559. clock_var = -1;
  2560. prev_ls_clock = -1;
  2561. pipe0_clock = -1;
  2562. pipe1_clock = -1;
  2563. prev_clock_var = -1;
  2564. prev_priority = -1;
  2565. }
  2566. static int
  2567. spu_sched_variable_issue (FILE *file ATTRIBUTE_UNUSED,
  2568. int verbose ATTRIBUTE_UNUSED,
  2569. rtx_insn *insn, int more)
  2570. {
  2571. int len;
  2572. int p;
  2573. if (GET_CODE (PATTERN (insn)) == USE
  2574. || GET_CODE (PATTERN (insn)) == CLOBBER
  2575. || (len = get_attr_length (insn)) == 0)
  2576. return more;
  2577. spu_sched_length += len;
  2578. /* Reset on inline asm */
  2579. if (INSN_CODE (insn) == -1)
  2580. {
  2581. spu_ls_first = INT_MAX;
  2582. pipe0_clock = -1;
  2583. pipe1_clock = -1;
  2584. return 0;
  2585. }
  2586. p = get_pipe (insn);
  2587. if (p == 0)
  2588. pipe0_clock = clock_var;
  2589. else
  2590. pipe1_clock = clock_var;
  2591. if (in_spu_reorg)
  2592. {
  2593. if (clock_var - prev_ls_clock > 1
  2594. || INSN_CODE (insn) == CODE_FOR_iprefetch)
  2595. spu_ls_first = INT_MAX;
  2596. if (uses_ls_unit (insn))
  2597. {
  2598. if (spu_ls_first == INT_MAX)
  2599. spu_ls_first = spu_sched_length;
  2600. prev_ls_clock = clock_var;
  2601. }
  2602. /* The scheduler hasn't inserted the nop, but we will later on.
  2603. Include those nops in spu_sched_length. */
  2604. if (prev_clock_var == clock_var && (spu_sched_length & 7))
  2605. spu_sched_length += 4;
  2606. prev_clock_var = clock_var;
  2607. /* more is -1 when called from spu_sched_reorder for new insns
  2608. that don't have INSN_PRIORITY */
  2609. if (more >= 0)
  2610. prev_priority = INSN_PRIORITY (insn);
  2611. }
  2612. /* Always try issuing more insns. spu_sched_reorder will decide
  2613. when the cycle should be advanced. */
  2614. return 1;
  2615. }
  2616. /* This function is called for both TARGET_SCHED_REORDER and
  2617. TARGET_SCHED_REORDER2. */
  2618. static int
  2619. spu_sched_reorder (FILE *file ATTRIBUTE_UNUSED, int verbose ATTRIBUTE_UNUSED,
  2620. rtx_insn **ready, int *nreadyp, int clock)
  2621. {
  2622. int i, nready = *nreadyp;
  2623. int pipe_0, pipe_1, pipe_hbrp, pipe_ls, schedule_i;
  2624. rtx_insn *insn;
  2625. clock_var = clock;
  2626. if (nready <= 0 || pipe1_clock >= clock)
  2627. return 0;
  2628. /* Find any rtl insns that don't generate assembly insns and schedule
  2629. them first. */
  2630. for (i = nready - 1; i >= 0; i--)
  2631. {
  2632. insn = ready[i];
  2633. if (INSN_CODE (insn) == -1
  2634. || INSN_CODE (insn) == CODE_FOR_blockage
  2635. || (INSN_P (insn) && get_attr_length (insn) == 0))
  2636. {
  2637. ready[i] = ready[nready - 1];
  2638. ready[nready - 1] = insn;
  2639. return 1;
  2640. }
  2641. }
  2642. pipe_0 = pipe_1 = pipe_hbrp = pipe_ls = schedule_i = -1;
  2643. for (i = 0; i < nready; i++)
  2644. if (INSN_CODE (ready[i]) != -1)
  2645. {
  2646. insn = ready[i];
  2647. switch (get_attr_type (insn))
  2648. {
  2649. default:
  2650. case TYPE_MULTI0:
  2651. case TYPE_CONVERT:
  2652. case TYPE_FX2:
  2653. case TYPE_FX3:
  2654. case TYPE_SPR:
  2655. case TYPE_NOP:
  2656. case TYPE_FXB:
  2657. case TYPE_FPD:
  2658. case TYPE_FP6:
  2659. case TYPE_FP7:
  2660. pipe_0 = i;
  2661. break;
  2662. case TYPE_LOAD:
  2663. case TYPE_STORE:
  2664. pipe_ls = i;
  2665. case TYPE_LNOP:
  2666. case TYPE_SHUF:
  2667. case TYPE_BR:
  2668. case TYPE_MULTI1:
  2669. case TYPE_HBR:
  2670. pipe_1 = i;
  2671. break;
  2672. case TYPE_IPREFETCH:
  2673. pipe_hbrp = i;
  2674. break;
  2675. }
  2676. }
  2677. /* In the first scheduling phase, schedule loads and stores together
  2678. to increase the chance they will get merged during postreload CSE. */
  2679. if (!reload_completed && pipe_ls >= 0)
  2680. {
  2681. insn = ready[pipe_ls];
  2682. ready[pipe_ls] = ready[nready - 1];
  2683. ready[nready - 1] = insn;
  2684. return 1;
  2685. }
  2686. /* If there is an hbrp ready, prefer it over other pipe 1 insns. */
  2687. if (pipe_hbrp >= 0)
  2688. pipe_1 = pipe_hbrp;
  2689. /* When we have loads/stores in every cycle of the last 15 insns and
  2690. we are about to schedule another load/store, emit an hbrp insn
  2691. instead. */
  2692. if (in_spu_reorg
  2693. && spu_sched_length - spu_ls_first >= 4 * 15
  2694. && !(pipe0_clock < clock && pipe_0 >= 0) && pipe_1 == pipe_ls)
  2695. {
  2696. insn = sched_emit_insn (gen_iprefetch (GEN_INT (3)));
  2697. recog_memoized (insn);
  2698. if (pipe0_clock < clock)
  2699. PUT_MODE (insn, TImode);
  2700. spu_sched_variable_issue (file, verbose, insn, -1);
  2701. return 0;
  2702. }
  2703. /* In general, we want to emit nops to increase dual issue, but dual
  2704. issue isn't faster when one of the insns could be scheduled later
  2705. without effecting the critical path. We look at INSN_PRIORITY to
  2706. make a good guess, but it isn't perfect so -mdual-nops=n can be
  2707. used to effect it. */
  2708. if (in_spu_reorg && spu_dual_nops < 10)
  2709. {
  2710. /* When we are at an even address and we are not issuing nops to
  2711. improve scheduling then we need to advance the cycle. */
  2712. if ((spu_sched_length & 7) == 0 && prev_clock_var == clock
  2713. && (spu_dual_nops == 0
  2714. || (pipe_1 != -1
  2715. && prev_priority >
  2716. INSN_PRIORITY (ready[pipe_1]) + spu_dual_nops)))
  2717. return 0;
  2718. /* When at an odd address, schedule the highest priority insn
  2719. without considering pipeline. */
  2720. if ((spu_sched_length & 7) == 4 && prev_clock_var != clock
  2721. && (spu_dual_nops == 0
  2722. || (prev_priority >
  2723. INSN_PRIORITY (ready[nready - 1]) + spu_dual_nops)))
  2724. return 1;
  2725. }
  2726. /* We haven't issued a pipe0 insn yet this cycle, if there is a
  2727. pipe0 insn in the ready list, schedule it. */
  2728. if (pipe0_clock < clock && pipe_0 >= 0)
  2729. schedule_i = pipe_0;
  2730. /* Either we've scheduled a pipe0 insn already or there is no pipe0
  2731. insn to schedule. Put a pipe1 insn at the front of the ready list. */
  2732. else
  2733. schedule_i = pipe_1;
  2734. if (schedule_i > -1)
  2735. {
  2736. insn = ready[schedule_i];
  2737. ready[schedule_i] = ready[nready - 1];
  2738. ready[nready - 1] = insn;
  2739. return 1;
  2740. }
  2741. return 0;
  2742. }
  2743. /* INSN is dependent on DEP_INSN. */
  2744. static int
  2745. spu_sched_adjust_cost (rtx_insn *insn, rtx link, rtx_insn *dep_insn, int cost)
  2746. {
  2747. rtx set;
  2748. /* The blockage pattern is used to prevent instructions from being
  2749. moved across it and has no cost. */
  2750. if (INSN_CODE (insn) == CODE_FOR_blockage
  2751. || INSN_CODE (dep_insn) == CODE_FOR_blockage)
  2752. return 0;
  2753. if ((INSN_P (insn) && get_attr_length (insn) == 0)
  2754. || (INSN_P (dep_insn) && get_attr_length (dep_insn) == 0))
  2755. return 0;
  2756. /* Make sure hbrps are spread out. */
  2757. if (INSN_CODE (insn) == CODE_FOR_iprefetch
  2758. && INSN_CODE (dep_insn) == CODE_FOR_iprefetch)
  2759. return 8;
  2760. /* Make sure hints and hbrps are 2 cycles apart. */
  2761. if ((INSN_CODE (insn) == CODE_FOR_iprefetch
  2762. || INSN_CODE (insn) == CODE_FOR_hbr)
  2763. && (INSN_CODE (dep_insn) == CODE_FOR_iprefetch
  2764. || INSN_CODE (dep_insn) == CODE_FOR_hbr))
  2765. return 2;
  2766. /* An hbrp has no real dependency on other insns. */
  2767. if (INSN_CODE (insn) == CODE_FOR_iprefetch
  2768. || INSN_CODE (dep_insn) == CODE_FOR_iprefetch)
  2769. return 0;
  2770. /* Assuming that it is unlikely an argument register will be used in
  2771. the first cycle of the called function, we reduce the cost for
  2772. slightly better scheduling of dep_insn. When not hinted, the
  2773. mispredicted branch would hide the cost as well. */
  2774. if (CALL_P (insn))
  2775. {
  2776. rtx target = get_branch_target (insn);
  2777. if (GET_CODE (target) != REG || !set_of (target, insn))
  2778. return cost - 2;
  2779. return cost;
  2780. }
  2781. /* And when returning from a function, let's assume the return values
  2782. are completed sooner too. */
  2783. if (CALL_P (dep_insn))
  2784. return cost - 2;
  2785. /* Make sure an instruction that loads from the back chain is schedule
  2786. away from the return instruction so a hint is more likely to get
  2787. issued. */
  2788. if (INSN_CODE (insn) == CODE_FOR__return
  2789. && (set = single_set (dep_insn))
  2790. && GET_CODE (SET_DEST (set)) == REG
  2791. && REGNO (SET_DEST (set)) == LINK_REGISTER_REGNUM)
  2792. return 20;
  2793. /* The dfa scheduler sets cost to 0 for all anti-dependencies and the
  2794. scheduler makes every insn in a block anti-dependent on the final
  2795. jump_insn. We adjust here so higher cost insns will get scheduled
  2796. earlier. */
  2797. if (JUMP_P (insn) && REG_NOTE_KIND (link) == REG_DEP_ANTI)
  2798. return insn_cost (dep_insn) - 3;
  2799. return cost;
  2800. }
  2801. /* Create a CONST_DOUBLE from a string. */
  2802. rtx
  2803. spu_float_const (const char *string, machine_mode mode)
  2804. {
  2805. REAL_VALUE_TYPE value;
  2806. value = REAL_VALUE_ATOF (string, mode);
  2807. return CONST_DOUBLE_FROM_REAL_VALUE (value, mode);
  2808. }
  2809. int
  2810. spu_constant_address_p (rtx x)
  2811. {
  2812. return (GET_CODE (x) == LABEL_REF || GET_CODE (x) == SYMBOL_REF
  2813. || GET_CODE (x) == CONST_INT || GET_CODE (x) == CONST
  2814. || GET_CODE (x) == HIGH);
  2815. }
  2816. static enum spu_immediate
  2817. which_immediate_load (HOST_WIDE_INT val)
  2818. {
  2819. gcc_assert (val == trunc_int_for_mode (val, SImode));
  2820. if (val >= -0x8000 && val <= 0x7fff)
  2821. return SPU_IL;
  2822. if (val >= 0 && val <= 0x3ffff)
  2823. return SPU_ILA;
  2824. if ((val & 0xffff) == ((val >> 16) & 0xffff))
  2825. return SPU_ILH;
  2826. if ((val & 0xffff) == 0)
  2827. return SPU_ILHU;
  2828. return SPU_NONE;
  2829. }
  2830. /* Return true when OP can be loaded by one of the il instructions, or
  2831. when flow2 is not completed and OP can be loaded using ilhu and iohl. */
  2832. int
  2833. immediate_load_p (rtx op, machine_mode mode)
  2834. {
  2835. if (CONSTANT_P (op))
  2836. {
  2837. enum immediate_class c = classify_immediate (op, mode);
  2838. return c == IC_IL1 || c == IC_IL1s
  2839. || (!epilogue_completed && (c == IC_IL2 || c == IC_IL2s));
  2840. }
  2841. return 0;
  2842. }
  2843. /* Return true if the first SIZE bytes of arr is a constant that can be
  2844. generated with cbd, chd, cwd or cdd. When non-NULL, PRUN and PSTART
  2845. represent the size and offset of the instruction to use. */
  2846. static int
  2847. cpat_info(unsigned char *arr, int size, int *prun, int *pstart)
  2848. {
  2849. int cpat, run, i, start;
  2850. cpat = 1;
  2851. run = 0;
  2852. start = -1;
  2853. for (i = 0; i < size && cpat; i++)
  2854. if (arr[i] != i+16)
  2855. {
  2856. if (!run)
  2857. {
  2858. start = i;
  2859. if (arr[i] == 3)
  2860. run = 1;
  2861. else if (arr[i] == 2 && arr[i+1] == 3)
  2862. run = 2;
  2863. else if (arr[i] == 0)
  2864. {
  2865. while (arr[i+run] == run && i+run < 16)
  2866. run++;
  2867. if (run != 4 && run != 8)
  2868. cpat = 0;
  2869. }
  2870. else
  2871. cpat = 0;
  2872. if ((i & (run-1)) != 0)
  2873. cpat = 0;
  2874. i += run;
  2875. }
  2876. else
  2877. cpat = 0;
  2878. }
  2879. if (cpat && (run || size < 16))
  2880. {
  2881. if (run == 0)
  2882. run = 1;
  2883. if (prun)
  2884. *prun = run;
  2885. if (pstart)
  2886. *pstart = start == -1 ? 16-run : start;
  2887. return 1;
  2888. }
  2889. return 0;
  2890. }
  2891. /* OP is a CONSTANT_P. Determine what instructions can be used to load
  2892. it into a register. MODE is only valid when OP is a CONST_INT. */
  2893. static enum immediate_class
  2894. classify_immediate (rtx op, machine_mode mode)
  2895. {
  2896. HOST_WIDE_INT val;
  2897. unsigned char arr[16];
  2898. int i, j, repeated, fsmbi, repeat;
  2899. gcc_assert (CONSTANT_P (op));
  2900. if (GET_MODE (op) != VOIDmode)
  2901. mode = GET_MODE (op);
  2902. /* A V4SI const_vector with all identical symbols is ok. */
  2903. if (!flag_pic
  2904. && mode == V4SImode
  2905. && GET_CODE (op) == CONST_VECTOR
  2906. && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_INT
  2907. && GET_CODE (CONST_VECTOR_ELT (op, 0)) != CONST_DOUBLE
  2908. && CONST_VECTOR_ELT (op, 0) == CONST_VECTOR_ELT (op, 1)
  2909. && CONST_VECTOR_ELT (op, 1) == CONST_VECTOR_ELT (op, 2)
  2910. && CONST_VECTOR_ELT (op, 2) == CONST_VECTOR_ELT (op, 3))
  2911. op = CONST_VECTOR_ELT (op, 0);
  2912. switch (GET_CODE (op))
  2913. {
  2914. case SYMBOL_REF:
  2915. case LABEL_REF:
  2916. return TARGET_LARGE_MEM ? IC_IL2s : IC_IL1s;
  2917. case CONST:
  2918. /* We can never know if the resulting address fits in 18 bits and can be
  2919. loaded with ila. For now, assume the address will not overflow if
  2920. the displacement is "small" (fits 'K' constraint). */
  2921. if (!TARGET_LARGE_MEM && GET_CODE (XEXP (op, 0)) == PLUS)
  2922. {
  2923. rtx sym = XEXP (XEXP (op, 0), 0);
  2924. rtx cst = XEXP (XEXP (op, 0), 1);
  2925. if (GET_CODE (sym) == SYMBOL_REF
  2926. && GET_CODE (cst) == CONST_INT
  2927. && satisfies_constraint_K (cst))
  2928. return IC_IL1s;
  2929. }
  2930. return IC_IL2s;
  2931. case HIGH:
  2932. return IC_IL1s;
  2933. case CONST_VECTOR:
  2934. for (i = 0; i < GET_MODE_NUNITS (mode); i++)
  2935. if (GET_CODE (CONST_VECTOR_ELT (op, i)) != CONST_INT
  2936. && GET_CODE (CONST_VECTOR_ELT (op, i)) != CONST_DOUBLE)
  2937. return IC_POOL;
  2938. /* Fall through. */
  2939. case CONST_INT:
  2940. case CONST_DOUBLE:
  2941. constant_to_array (mode, op, arr);
  2942. /* Check that each 4-byte slot is identical. */
  2943. repeated = 1;
  2944. for (i = 4; i < 16; i += 4)
  2945. for (j = 0; j < 4; j++)
  2946. if (arr[j] != arr[i + j])
  2947. repeated = 0;
  2948. if (repeated)
  2949. {
  2950. val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
  2951. val = trunc_int_for_mode (val, SImode);
  2952. if (which_immediate_load (val) != SPU_NONE)
  2953. return IC_IL1;
  2954. }
  2955. /* Any mode of 2 bytes or smaller can be loaded with an il
  2956. instruction. */
  2957. gcc_assert (GET_MODE_SIZE (mode) > 2);
  2958. fsmbi = 1;
  2959. repeat = 0;
  2960. for (i = 0; i < 16 && fsmbi; i++)
  2961. if (arr[i] != 0 && repeat == 0)
  2962. repeat = arr[i];
  2963. else if (arr[i] != 0 && arr[i] != repeat)
  2964. fsmbi = 0;
  2965. if (fsmbi)
  2966. return repeat == 0xff ? IC_FSMBI : IC_FSMBI2;
  2967. if (cpat_info (arr, GET_MODE_SIZE (mode), 0, 0))
  2968. return IC_CPAT;
  2969. if (repeated)
  2970. return IC_IL2;
  2971. return IC_POOL;
  2972. default:
  2973. break;
  2974. }
  2975. gcc_unreachable ();
  2976. }
  2977. static enum spu_immediate
  2978. which_logical_immediate (HOST_WIDE_INT val)
  2979. {
  2980. gcc_assert (val == trunc_int_for_mode (val, SImode));
  2981. if (val >= -0x200 && val <= 0x1ff)
  2982. return SPU_ORI;
  2983. if (val >= 0 && val <= 0xffff)
  2984. return SPU_IOHL;
  2985. if ((val & 0xffff) == ((val >> 16) & 0xffff))
  2986. {
  2987. val = trunc_int_for_mode (val, HImode);
  2988. if (val >= -0x200 && val <= 0x1ff)
  2989. return SPU_ORHI;
  2990. if ((val & 0xff) == ((val >> 8) & 0xff))
  2991. {
  2992. val = trunc_int_for_mode (val, QImode);
  2993. if (val >= -0x200 && val <= 0x1ff)
  2994. return SPU_ORBI;
  2995. }
  2996. }
  2997. return SPU_NONE;
  2998. }
  2999. /* Return TRUE when X, a CONST_VECTOR, only contains CONST_INTs or
  3000. CONST_DOUBLEs. */
  3001. static int
  3002. const_vector_immediate_p (rtx x)
  3003. {
  3004. int i;
  3005. gcc_assert (GET_CODE (x) == CONST_VECTOR);
  3006. for (i = 0; i < GET_MODE_NUNITS (GET_MODE (x)); i++)
  3007. if (GET_CODE (CONST_VECTOR_ELT (x, i)) != CONST_INT
  3008. && GET_CODE (CONST_VECTOR_ELT (x, i)) != CONST_DOUBLE)
  3009. return 0;
  3010. return 1;
  3011. }
  3012. int
  3013. logical_immediate_p (rtx op, machine_mode mode)
  3014. {
  3015. HOST_WIDE_INT val;
  3016. unsigned char arr[16];
  3017. int i, j;
  3018. gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
  3019. || GET_CODE (op) == CONST_VECTOR);
  3020. if (GET_CODE (op) == CONST_VECTOR
  3021. && !const_vector_immediate_p (op))
  3022. return 0;
  3023. if (GET_MODE (op) != VOIDmode)
  3024. mode = GET_MODE (op);
  3025. constant_to_array (mode, op, arr);
  3026. /* Check that bytes are repeated. */
  3027. for (i = 4; i < 16; i += 4)
  3028. for (j = 0; j < 4; j++)
  3029. if (arr[j] != arr[i + j])
  3030. return 0;
  3031. val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
  3032. val = trunc_int_for_mode (val, SImode);
  3033. i = which_logical_immediate (val);
  3034. return i != SPU_NONE && i != SPU_IOHL;
  3035. }
  3036. int
  3037. iohl_immediate_p (rtx op, machine_mode mode)
  3038. {
  3039. HOST_WIDE_INT val;
  3040. unsigned char arr[16];
  3041. int i, j;
  3042. gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
  3043. || GET_CODE (op) == CONST_VECTOR);
  3044. if (GET_CODE (op) == CONST_VECTOR
  3045. && !const_vector_immediate_p (op))
  3046. return 0;
  3047. if (GET_MODE (op) != VOIDmode)
  3048. mode = GET_MODE (op);
  3049. constant_to_array (mode, op, arr);
  3050. /* Check that bytes are repeated. */
  3051. for (i = 4; i < 16; i += 4)
  3052. for (j = 0; j < 4; j++)
  3053. if (arr[j] != arr[i + j])
  3054. return 0;
  3055. val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
  3056. val = trunc_int_for_mode (val, SImode);
  3057. return val >= 0 && val <= 0xffff;
  3058. }
  3059. int
  3060. arith_immediate_p (rtx op, machine_mode mode,
  3061. HOST_WIDE_INT low, HOST_WIDE_INT high)
  3062. {
  3063. HOST_WIDE_INT val;
  3064. unsigned char arr[16];
  3065. int bytes, i, j;
  3066. gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
  3067. || GET_CODE (op) == CONST_VECTOR);
  3068. if (GET_CODE (op) == CONST_VECTOR
  3069. && !const_vector_immediate_p (op))
  3070. return 0;
  3071. if (GET_MODE (op) != VOIDmode)
  3072. mode = GET_MODE (op);
  3073. constant_to_array (mode, op, arr);
  3074. if (VECTOR_MODE_P (mode))
  3075. mode = GET_MODE_INNER (mode);
  3076. bytes = GET_MODE_SIZE (mode);
  3077. mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
  3078. /* Check that bytes are repeated. */
  3079. for (i = bytes; i < 16; i += bytes)
  3080. for (j = 0; j < bytes; j++)
  3081. if (arr[j] != arr[i + j])
  3082. return 0;
  3083. val = arr[0];
  3084. for (j = 1; j < bytes; j++)
  3085. val = (val << 8) | arr[j];
  3086. val = trunc_int_for_mode (val, mode);
  3087. return val >= low && val <= high;
  3088. }
  3089. /* TRUE when op is an immediate and an exact power of 2, and given that
  3090. OP is 2^scale, scale >= LOW && scale <= HIGH. When OP is a vector,
  3091. all entries must be the same. */
  3092. bool
  3093. exp2_immediate_p (rtx op, machine_mode mode, int low, int high)
  3094. {
  3095. machine_mode int_mode;
  3096. HOST_WIDE_INT val;
  3097. unsigned char arr[16];
  3098. int bytes, i, j;
  3099. gcc_assert (GET_CODE (op) == CONST_INT || GET_CODE (op) == CONST_DOUBLE
  3100. || GET_CODE (op) == CONST_VECTOR);
  3101. if (GET_CODE (op) == CONST_VECTOR
  3102. && !const_vector_immediate_p (op))
  3103. return 0;
  3104. if (GET_MODE (op) != VOIDmode)
  3105. mode = GET_MODE (op);
  3106. constant_to_array (mode, op, arr);
  3107. if (VECTOR_MODE_P (mode))
  3108. mode = GET_MODE_INNER (mode);
  3109. bytes = GET_MODE_SIZE (mode);
  3110. int_mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
  3111. /* Check that bytes are repeated. */
  3112. for (i = bytes; i < 16; i += bytes)
  3113. for (j = 0; j < bytes; j++)
  3114. if (arr[j] != arr[i + j])
  3115. return 0;
  3116. val = arr[0];
  3117. for (j = 1; j < bytes; j++)
  3118. val = (val << 8) | arr[j];
  3119. val = trunc_int_for_mode (val, int_mode);
  3120. /* Currently, we only handle SFmode */
  3121. gcc_assert (mode == SFmode);
  3122. if (mode == SFmode)
  3123. {
  3124. int exp = (val >> 23) - 127;
  3125. return val > 0 && (val & 0x007fffff) == 0
  3126. && exp >= low && exp <= high;
  3127. }
  3128. return FALSE;
  3129. }
  3130. /* Return true if X is a SYMBOL_REF to an __ea qualified variable. */
  3131. static bool
  3132. ea_symbol_ref_p (const_rtx x)
  3133. {
  3134. tree decl;
  3135. if (GET_CODE (x) == CONST && GET_CODE (XEXP (x, 0)) == PLUS)
  3136. {
  3137. rtx plus = XEXP (x, 0);
  3138. rtx op0 = XEXP (plus, 0);
  3139. rtx op1 = XEXP (plus, 1);
  3140. if (GET_CODE (op1) == CONST_INT)
  3141. x = op0;
  3142. }
  3143. return (GET_CODE (x) == SYMBOL_REF
  3144. && (decl = SYMBOL_REF_DECL (x)) != 0
  3145. && TREE_CODE (decl) == VAR_DECL
  3146. && TYPE_ADDR_SPACE (TREE_TYPE (decl)));
  3147. }
  3148. /* We accept:
  3149. - any 32-bit constant (SImode, SFmode)
  3150. - any constant that can be generated with fsmbi (any mode)
  3151. - a 64-bit constant where the high and low bits are identical
  3152. (DImode, DFmode)
  3153. - a 128-bit constant where the four 32-bit words match. */
  3154. bool
  3155. spu_legitimate_constant_p (machine_mode mode, rtx x)
  3156. {
  3157. subrtx_iterator::array_type array;
  3158. if (GET_CODE (x) == HIGH)
  3159. x = XEXP (x, 0);
  3160. /* Reject any __ea qualified reference. These can't appear in
  3161. instructions but must be forced to the constant pool. */
  3162. FOR_EACH_SUBRTX (iter, array, x, ALL)
  3163. if (ea_symbol_ref_p (*iter))
  3164. return 0;
  3165. /* V4SI with all identical symbols is valid. */
  3166. if (!flag_pic
  3167. && mode == V4SImode
  3168. && (GET_CODE (CONST_VECTOR_ELT (x, 0)) == SYMBOL_REF
  3169. || GET_CODE (CONST_VECTOR_ELT (x, 0)) == LABEL_REF
  3170. || GET_CODE (CONST_VECTOR_ELT (x, 0)) == CONST))
  3171. return CONST_VECTOR_ELT (x, 0) == CONST_VECTOR_ELT (x, 1)
  3172. && CONST_VECTOR_ELT (x, 1) == CONST_VECTOR_ELT (x, 2)
  3173. && CONST_VECTOR_ELT (x, 2) == CONST_VECTOR_ELT (x, 3);
  3174. if (GET_CODE (x) == CONST_VECTOR
  3175. && !const_vector_immediate_p (x))
  3176. return 0;
  3177. return 1;
  3178. }
  3179. /* Valid address are:
  3180. - symbol_ref, label_ref, const
  3181. - reg
  3182. - reg + const_int, where const_int is 16 byte aligned
  3183. - reg + reg, alignment doesn't matter
  3184. The alignment matters in the reg+const case because lqd and stqd
  3185. ignore the 4 least significant bits of the const. We only care about
  3186. 16 byte modes because the expand phase will change all smaller MEM
  3187. references to TImode. */
  3188. static bool
  3189. spu_legitimate_address_p (machine_mode mode,
  3190. rtx x, bool reg_ok_strict)
  3191. {
  3192. int aligned = GET_MODE_SIZE (mode) >= 16;
  3193. if (aligned
  3194. && GET_CODE (x) == AND
  3195. && GET_CODE (XEXP (x, 1)) == CONST_INT
  3196. && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT) - 16)
  3197. x = XEXP (x, 0);
  3198. switch (GET_CODE (x))
  3199. {
  3200. case LABEL_REF:
  3201. return !TARGET_LARGE_MEM;
  3202. case SYMBOL_REF:
  3203. case CONST:
  3204. /* Keep __ea references until reload so that spu_expand_mov can see them
  3205. in MEMs. */
  3206. if (ea_symbol_ref_p (x))
  3207. return !reload_in_progress && !reload_completed;
  3208. return !TARGET_LARGE_MEM;
  3209. case CONST_INT:
  3210. return INTVAL (x) >= 0 && INTVAL (x) <= 0x3ffff;
  3211. case SUBREG:
  3212. x = XEXP (x, 0);
  3213. if (REG_P (x))
  3214. return 0;
  3215. case REG:
  3216. return INT_REG_OK_FOR_BASE_P (x, reg_ok_strict);
  3217. case PLUS:
  3218. case LO_SUM:
  3219. {
  3220. rtx op0 = XEXP (x, 0);
  3221. rtx op1 = XEXP (x, 1);
  3222. if (GET_CODE (op0) == SUBREG)
  3223. op0 = XEXP (op0, 0);
  3224. if (GET_CODE (op1) == SUBREG)
  3225. op1 = XEXP (op1, 0);
  3226. if (GET_CODE (op0) == REG
  3227. && INT_REG_OK_FOR_BASE_P (op0, reg_ok_strict)
  3228. && GET_CODE (op1) == CONST_INT
  3229. && ((INTVAL (op1) >= -0x2000 && INTVAL (op1) <= 0x1fff)
  3230. /* If virtual registers are involved, the displacement will
  3231. change later on anyway, so checking would be premature.
  3232. Reload will make sure the final displacement after
  3233. register elimination is OK. */
  3234. || op0 == arg_pointer_rtx
  3235. || op0 == frame_pointer_rtx
  3236. || op0 == virtual_stack_vars_rtx)
  3237. && (!aligned || (INTVAL (op1) & 15) == 0))
  3238. return TRUE;
  3239. if (GET_CODE (op0) == REG
  3240. && INT_REG_OK_FOR_BASE_P (op0, reg_ok_strict)
  3241. && GET_CODE (op1) == REG
  3242. && INT_REG_OK_FOR_INDEX_P (op1, reg_ok_strict))
  3243. return TRUE;
  3244. }
  3245. break;
  3246. default:
  3247. break;
  3248. }
  3249. return FALSE;
  3250. }
  3251. /* Like spu_legitimate_address_p, except with named addresses. */
  3252. static bool
  3253. spu_addr_space_legitimate_address_p (machine_mode mode, rtx x,
  3254. bool reg_ok_strict, addr_space_t as)
  3255. {
  3256. if (as == ADDR_SPACE_EA)
  3257. return (REG_P (x) && (GET_MODE (x) == EAmode));
  3258. else if (as != ADDR_SPACE_GENERIC)
  3259. gcc_unreachable ();
  3260. return spu_legitimate_address_p (mode, x, reg_ok_strict);
  3261. }
  3262. /* When the address is reg + const_int, force the const_int into a
  3263. register. */
  3264. static rtx
  3265. spu_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
  3266. machine_mode mode ATTRIBUTE_UNUSED)
  3267. {
  3268. rtx op0, op1;
  3269. /* Make sure both operands are registers. */
  3270. if (GET_CODE (x) == PLUS)
  3271. {
  3272. op0 = XEXP (x, 0);
  3273. op1 = XEXP (x, 1);
  3274. if (ALIGNED_SYMBOL_REF_P (op0))
  3275. {
  3276. op0 = force_reg (Pmode, op0);
  3277. mark_reg_pointer (op0, 128);
  3278. }
  3279. else if (GET_CODE (op0) != REG)
  3280. op0 = force_reg (Pmode, op0);
  3281. if (ALIGNED_SYMBOL_REF_P (op1))
  3282. {
  3283. op1 = force_reg (Pmode, op1);
  3284. mark_reg_pointer (op1, 128);
  3285. }
  3286. else if (GET_CODE (op1) != REG)
  3287. op1 = force_reg (Pmode, op1);
  3288. x = gen_rtx_PLUS (Pmode, op0, op1);
  3289. }
  3290. return x;
  3291. }
  3292. /* Like spu_legitimate_address, except with named address support. */
  3293. static rtx
  3294. spu_addr_space_legitimize_address (rtx x, rtx oldx, machine_mode mode,
  3295. addr_space_t as)
  3296. {
  3297. if (as != ADDR_SPACE_GENERIC)
  3298. return x;
  3299. return spu_legitimize_address (x, oldx, mode);
  3300. }
  3301. /* Reload reg + const_int for out-of-range displacements. */
  3302. rtx
  3303. spu_legitimize_reload_address (rtx ad, machine_mode mode ATTRIBUTE_UNUSED,
  3304. int opnum, int type)
  3305. {
  3306. bool removed_and = false;
  3307. if (GET_CODE (ad) == AND
  3308. && CONST_INT_P (XEXP (ad, 1))
  3309. && INTVAL (XEXP (ad, 1)) == (HOST_WIDE_INT) - 16)
  3310. {
  3311. ad = XEXP (ad, 0);
  3312. removed_and = true;
  3313. }
  3314. if (GET_CODE (ad) == PLUS
  3315. && REG_P (XEXP (ad, 0))
  3316. && CONST_INT_P (XEXP (ad, 1))
  3317. && !(INTVAL (XEXP (ad, 1)) >= -0x2000
  3318. && INTVAL (XEXP (ad, 1)) <= 0x1fff))
  3319. {
  3320. /* Unshare the sum. */
  3321. ad = copy_rtx (ad);
  3322. /* Reload the displacement. */
  3323. push_reload (XEXP (ad, 1), NULL_RTX, &XEXP (ad, 1), NULL,
  3324. BASE_REG_CLASS, GET_MODE (ad), VOIDmode, 0, 0,
  3325. opnum, (enum reload_type) type);
  3326. /* Add back AND for alignment if we stripped it. */
  3327. if (removed_and)
  3328. ad = gen_rtx_AND (GET_MODE (ad), ad, GEN_INT (-16));
  3329. return ad;
  3330. }
  3331. return NULL_RTX;
  3332. }
  3333. /* Handle an attribute requiring a FUNCTION_DECL; arguments as in
  3334. struct attribute_spec.handler. */
  3335. static tree
  3336. spu_handle_fndecl_attribute (tree * node,
  3337. tree name,
  3338. tree args ATTRIBUTE_UNUSED,
  3339. int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
  3340. {
  3341. if (TREE_CODE (*node) != FUNCTION_DECL)
  3342. {
  3343. warning (0, "%qE attribute only applies to functions",
  3344. name);
  3345. *no_add_attrs = true;
  3346. }
  3347. return NULL_TREE;
  3348. }
  3349. /* Handle the "vector" attribute. */
  3350. static tree
  3351. spu_handle_vector_attribute (tree * node, tree name,
  3352. tree args ATTRIBUTE_UNUSED,
  3353. int flags ATTRIBUTE_UNUSED, bool * no_add_attrs)
  3354. {
  3355. tree type = *node, result = NULL_TREE;
  3356. machine_mode mode;
  3357. int unsigned_p;
  3358. while (POINTER_TYPE_P (type)
  3359. || TREE_CODE (type) == FUNCTION_TYPE
  3360. || TREE_CODE (type) == METHOD_TYPE || TREE_CODE (type) == ARRAY_TYPE)
  3361. type = TREE_TYPE (type);
  3362. mode = TYPE_MODE (type);
  3363. unsigned_p = TYPE_UNSIGNED (type);
  3364. switch (mode)
  3365. {
  3366. case DImode:
  3367. result = (unsigned_p ? unsigned_V2DI_type_node : V2DI_type_node);
  3368. break;
  3369. case SImode:
  3370. result = (unsigned_p ? unsigned_V4SI_type_node : V4SI_type_node);
  3371. break;
  3372. case HImode:
  3373. result = (unsigned_p ? unsigned_V8HI_type_node : V8HI_type_node);
  3374. break;
  3375. case QImode:
  3376. result = (unsigned_p ? unsigned_V16QI_type_node : V16QI_type_node);
  3377. break;
  3378. case SFmode:
  3379. result = V4SF_type_node;
  3380. break;
  3381. case DFmode:
  3382. result = V2DF_type_node;
  3383. break;
  3384. default:
  3385. break;
  3386. }
  3387. /* Propagate qualifiers attached to the element type
  3388. onto the vector type. */
  3389. if (result && result != type && TYPE_QUALS (type))
  3390. result = build_qualified_type (result, TYPE_QUALS (type));
  3391. *no_add_attrs = true; /* No need to hang on to the attribute. */
  3392. if (!result)
  3393. warning (0, "%qE attribute ignored", name);
  3394. else
  3395. *node = lang_hooks.types.reconstruct_complex_type (*node, result);
  3396. return NULL_TREE;
  3397. }
  3398. /* Return nonzero if FUNC is a naked function. */
  3399. static int
  3400. spu_naked_function_p (tree func)
  3401. {
  3402. tree a;
  3403. if (TREE_CODE (func) != FUNCTION_DECL)
  3404. abort ();
  3405. a = lookup_attribute ("naked", DECL_ATTRIBUTES (func));
  3406. return a != NULL_TREE;
  3407. }
  3408. int
  3409. spu_initial_elimination_offset (int from, int to)
  3410. {
  3411. int saved_regs_size = spu_saved_regs_size ();
  3412. int sp_offset = 0;
  3413. if (!crtl->is_leaf || crtl->outgoing_args_size
  3414. || get_frame_size () || saved_regs_size)
  3415. sp_offset = STACK_POINTER_OFFSET;
  3416. if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
  3417. return get_frame_size () + crtl->outgoing_args_size + sp_offset;
  3418. else if (from == FRAME_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
  3419. return get_frame_size ();
  3420. else if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
  3421. return sp_offset + crtl->outgoing_args_size
  3422. + get_frame_size () + saved_regs_size + STACK_POINTER_OFFSET;
  3423. else if (from == ARG_POINTER_REGNUM && to == HARD_FRAME_POINTER_REGNUM)
  3424. return get_frame_size () + saved_regs_size + sp_offset;
  3425. else
  3426. gcc_unreachable ();
  3427. }
  3428. rtx
  3429. spu_function_value (const_tree type, const_tree func ATTRIBUTE_UNUSED)
  3430. {
  3431. machine_mode mode = TYPE_MODE (type);
  3432. int byte_size = ((mode == BLKmode)
  3433. ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
  3434. /* Make sure small structs are left justified in a register. */
  3435. if ((mode == BLKmode || (type && AGGREGATE_TYPE_P (type)))
  3436. && byte_size <= UNITS_PER_WORD * MAX_REGISTER_RETURN && byte_size > 0)
  3437. {
  3438. machine_mode smode;
  3439. rtvec v;
  3440. int i;
  3441. int nregs = (byte_size + UNITS_PER_WORD - 1) / UNITS_PER_WORD;
  3442. int n = byte_size / UNITS_PER_WORD;
  3443. v = rtvec_alloc (nregs);
  3444. for (i = 0; i < n; i++)
  3445. {
  3446. RTVEC_ELT (v, i) = gen_rtx_EXPR_LIST (VOIDmode,
  3447. gen_rtx_REG (TImode,
  3448. FIRST_RETURN_REGNUM
  3449. + i),
  3450. GEN_INT (UNITS_PER_WORD * i));
  3451. byte_size -= UNITS_PER_WORD;
  3452. }
  3453. if (n < nregs)
  3454. {
  3455. if (byte_size < 4)
  3456. byte_size = 4;
  3457. smode =
  3458. smallest_mode_for_size (byte_size * BITS_PER_UNIT, MODE_INT);
  3459. RTVEC_ELT (v, n) =
  3460. gen_rtx_EXPR_LIST (VOIDmode,
  3461. gen_rtx_REG (smode, FIRST_RETURN_REGNUM + n),
  3462. GEN_INT (UNITS_PER_WORD * n));
  3463. }
  3464. return gen_rtx_PARALLEL (mode, v);
  3465. }
  3466. return gen_rtx_REG (mode, FIRST_RETURN_REGNUM);
  3467. }
  3468. static rtx
  3469. spu_function_arg (cumulative_args_t cum_v,
  3470. machine_mode mode,
  3471. const_tree type, bool named ATTRIBUTE_UNUSED)
  3472. {
  3473. CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
  3474. int byte_size;
  3475. if (*cum >= MAX_REGISTER_ARGS)
  3476. return 0;
  3477. byte_size = ((mode == BLKmode)
  3478. ? int_size_in_bytes (type) : GET_MODE_SIZE (mode));
  3479. /* The ABI does not allow parameters to be passed partially in
  3480. reg and partially in stack. */
  3481. if ((*cum + (byte_size + 15) / 16) > MAX_REGISTER_ARGS)
  3482. return 0;
  3483. /* Make sure small structs are left justified in a register. */
  3484. if ((mode == BLKmode || (type && AGGREGATE_TYPE_P (type)))
  3485. && byte_size < UNITS_PER_WORD && byte_size > 0)
  3486. {
  3487. machine_mode smode;
  3488. rtx gr_reg;
  3489. if (byte_size < 4)
  3490. byte_size = 4;
  3491. smode = smallest_mode_for_size (byte_size * BITS_PER_UNIT, MODE_INT);
  3492. gr_reg = gen_rtx_EXPR_LIST (VOIDmode,
  3493. gen_rtx_REG (smode, FIRST_ARG_REGNUM + *cum),
  3494. const0_rtx);
  3495. return gen_rtx_PARALLEL (mode, gen_rtvec (1, gr_reg));
  3496. }
  3497. else
  3498. return gen_rtx_REG (mode, FIRST_ARG_REGNUM + *cum);
  3499. }
  3500. static void
  3501. spu_function_arg_advance (cumulative_args_t cum_v, machine_mode mode,
  3502. const_tree type, bool named ATTRIBUTE_UNUSED)
  3503. {
  3504. CUMULATIVE_ARGS *cum = get_cumulative_args (cum_v);
  3505. *cum += (type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
  3506. ? 1
  3507. : mode == BLKmode
  3508. ? ((int_size_in_bytes (type) + 15) / 16)
  3509. : mode == VOIDmode
  3510. ? 1
  3511. : HARD_REGNO_NREGS (cum, mode));
  3512. }
  3513. /* Variable sized types are passed by reference. */
  3514. static bool
  3515. spu_pass_by_reference (cumulative_args_t cum ATTRIBUTE_UNUSED,
  3516. machine_mode mode ATTRIBUTE_UNUSED,
  3517. const_tree type, bool named ATTRIBUTE_UNUSED)
  3518. {
  3519. return type && TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST;
  3520. }
  3521. /* Var args. */
  3522. /* Create and return the va_list datatype.
  3523. On SPU, va_list is an array type equivalent to
  3524. typedef struct __va_list_tag
  3525. {
  3526. void *__args __attribute__((__aligned(16)));
  3527. void *__skip __attribute__((__aligned(16)));
  3528. } va_list[1];
  3529. where __args points to the arg that will be returned by the next
  3530. va_arg(), and __skip points to the previous stack frame such that
  3531. when __args == __skip we should advance __args by 32 bytes. */
  3532. static tree
  3533. spu_build_builtin_va_list (void)
  3534. {
  3535. tree f_args, f_skip, record, type_decl;
  3536. bool owp;
  3537. record = (*lang_hooks.types.make_type) (RECORD_TYPE);
  3538. type_decl =
  3539. build_decl (BUILTINS_LOCATION,
  3540. TYPE_DECL, get_identifier ("__va_list_tag"), record);
  3541. f_args = build_decl (BUILTINS_LOCATION,
  3542. FIELD_DECL, get_identifier ("__args"), ptr_type_node);
  3543. f_skip = build_decl (BUILTINS_LOCATION,
  3544. FIELD_DECL, get_identifier ("__skip"), ptr_type_node);
  3545. DECL_FIELD_CONTEXT (f_args) = record;
  3546. DECL_ALIGN (f_args) = 128;
  3547. DECL_USER_ALIGN (f_args) = 1;
  3548. DECL_FIELD_CONTEXT (f_skip) = record;
  3549. DECL_ALIGN (f_skip) = 128;
  3550. DECL_USER_ALIGN (f_skip) = 1;
  3551. TYPE_STUB_DECL (record) = type_decl;
  3552. TYPE_NAME (record) = type_decl;
  3553. TYPE_FIELDS (record) = f_args;
  3554. DECL_CHAIN (f_args) = f_skip;
  3555. /* We know this is being padded and we want it too. It is an internal
  3556. type so hide the warnings from the user. */
  3557. owp = warn_padded;
  3558. warn_padded = false;
  3559. layout_type (record);
  3560. warn_padded = owp;
  3561. /* The correct type is an array type of one element. */
  3562. return build_array_type (record, build_index_type (size_zero_node));
  3563. }
  3564. /* Implement va_start by filling the va_list structure VALIST.
  3565. NEXTARG points to the first anonymous stack argument.
  3566. The following global variables are used to initialize
  3567. the va_list structure:
  3568. crtl->args.info;
  3569. the CUMULATIVE_ARGS for this function
  3570. crtl->args.arg_offset_rtx:
  3571. holds the offset of the first anonymous stack argument
  3572. (relative to the virtual arg pointer). */
  3573. static void
  3574. spu_va_start (tree valist, rtx nextarg)
  3575. {
  3576. tree f_args, f_skip;
  3577. tree args, skip, t;
  3578. f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
  3579. f_skip = DECL_CHAIN (f_args);
  3580. valist = build_simple_mem_ref (valist);
  3581. args =
  3582. build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
  3583. skip =
  3584. build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
  3585. /* Find the __args area. */
  3586. t = make_tree (TREE_TYPE (args), nextarg);
  3587. if (crtl->args.pretend_args_size > 0)
  3588. t = fold_build_pointer_plus_hwi (t, -STACK_POINTER_OFFSET);
  3589. t = build2 (MODIFY_EXPR, TREE_TYPE (args), args, t);
  3590. TREE_SIDE_EFFECTS (t) = 1;
  3591. expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  3592. /* Find the __skip area. */
  3593. t = make_tree (TREE_TYPE (skip), virtual_incoming_args_rtx);
  3594. t = fold_build_pointer_plus_hwi (t, (crtl->args.pretend_args_size
  3595. - STACK_POINTER_OFFSET));
  3596. t = build2 (MODIFY_EXPR, TREE_TYPE (skip), skip, t);
  3597. TREE_SIDE_EFFECTS (t) = 1;
  3598. expand_expr (t, const0_rtx, VOIDmode, EXPAND_NORMAL);
  3599. }
  3600. /* Gimplify va_arg by updating the va_list structure
  3601. VALIST as required to retrieve an argument of type
  3602. TYPE, and returning that argument.
  3603. ret = va_arg(VALIST, TYPE);
  3604. generates code equivalent to:
  3605. paddedsize = (sizeof(TYPE) + 15) & -16;
  3606. if (VALIST.__args + paddedsize > VALIST.__skip
  3607. && VALIST.__args <= VALIST.__skip)
  3608. addr = VALIST.__skip + 32;
  3609. else
  3610. addr = VALIST.__args;
  3611. VALIST.__args = addr + paddedsize;
  3612. ret = *(TYPE *)addr;
  3613. */
  3614. static tree
  3615. spu_gimplify_va_arg_expr (tree valist, tree type, gimple_seq * pre_p,
  3616. gimple_seq * post_p ATTRIBUTE_UNUSED)
  3617. {
  3618. tree f_args, f_skip;
  3619. tree args, skip;
  3620. HOST_WIDE_INT size, rsize;
  3621. tree addr, tmp;
  3622. bool pass_by_reference_p;
  3623. f_args = TYPE_FIELDS (TREE_TYPE (va_list_type_node));
  3624. f_skip = DECL_CHAIN (f_args);
  3625. valist = build_simple_mem_ref (valist);
  3626. args =
  3627. build3 (COMPONENT_REF, TREE_TYPE (f_args), valist, f_args, NULL_TREE);
  3628. skip =
  3629. build3 (COMPONENT_REF, TREE_TYPE (f_skip), valist, f_skip, NULL_TREE);
  3630. addr = create_tmp_var (ptr_type_node, "va_arg");
  3631. /* if an object is dynamically sized, a pointer to it is passed
  3632. instead of the object itself. */
  3633. pass_by_reference_p = pass_by_reference (NULL, TYPE_MODE (type), type,
  3634. false);
  3635. if (pass_by_reference_p)
  3636. type = build_pointer_type (type);
  3637. size = int_size_in_bytes (type);
  3638. rsize = ((size + UNITS_PER_WORD - 1) / UNITS_PER_WORD) * UNITS_PER_WORD;
  3639. /* build conditional expression to calculate addr. The expression
  3640. will be gimplified later. */
  3641. tmp = fold_build_pointer_plus_hwi (unshare_expr (args), rsize);
  3642. tmp = build2 (TRUTH_AND_EXPR, boolean_type_node,
  3643. build2 (GT_EXPR, boolean_type_node, tmp, unshare_expr (skip)),
  3644. build2 (LE_EXPR, boolean_type_node, unshare_expr (args),
  3645. unshare_expr (skip)));
  3646. tmp = build3 (COND_EXPR, ptr_type_node, tmp,
  3647. fold_build_pointer_plus_hwi (unshare_expr (skip), 32),
  3648. unshare_expr (args));
  3649. gimplify_assign (addr, tmp, pre_p);
  3650. /* update VALIST.__args */
  3651. tmp = fold_build_pointer_plus_hwi (addr, rsize);
  3652. gimplify_assign (unshare_expr (args), tmp, pre_p);
  3653. addr = fold_convert (build_pointer_type_for_mode (type, ptr_mode, true),
  3654. addr);
  3655. if (pass_by_reference_p)
  3656. addr = build_va_arg_indirect_ref (addr);
  3657. return build_va_arg_indirect_ref (addr);
  3658. }
  3659. /* Save parameter registers starting with the register that corresponds
  3660. to the first unnamed parameters. If the first unnamed parameter is
  3661. in the stack then save no registers. Set pretend_args_size to the
  3662. amount of space needed to save the registers. */
  3663. static void
  3664. spu_setup_incoming_varargs (cumulative_args_t cum, machine_mode mode,
  3665. tree type, int *pretend_size, int no_rtl)
  3666. {
  3667. if (!no_rtl)
  3668. {
  3669. rtx tmp;
  3670. int regno;
  3671. int offset;
  3672. int ncum = *get_cumulative_args (cum);
  3673. /* cum currently points to the last named argument, we want to
  3674. start at the next argument. */
  3675. spu_function_arg_advance (pack_cumulative_args (&ncum), mode, type, true);
  3676. offset = -STACK_POINTER_OFFSET;
  3677. for (regno = ncum; regno < MAX_REGISTER_ARGS; regno++)
  3678. {
  3679. tmp = gen_frame_mem (V4SImode,
  3680. plus_constant (Pmode, virtual_incoming_args_rtx,
  3681. offset));
  3682. emit_move_insn (tmp,
  3683. gen_rtx_REG (V4SImode, FIRST_ARG_REGNUM + regno));
  3684. offset += 16;
  3685. }
  3686. *pretend_size = offset + STACK_POINTER_OFFSET;
  3687. }
  3688. }
  3689. static void
  3690. spu_conditional_register_usage (void)
  3691. {
  3692. if (flag_pic)
  3693. {
  3694. fixed_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
  3695. call_used_regs[PIC_OFFSET_TABLE_REGNUM] = 1;
  3696. }
  3697. }
  3698. /* This is called any time we inspect the alignment of a register for
  3699. addresses. */
  3700. static int
  3701. reg_aligned_for_addr (rtx x)
  3702. {
  3703. int regno =
  3704. REGNO (x) < FIRST_PSEUDO_REGISTER ? ORIGINAL_REGNO (x) : REGNO (x);
  3705. return REGNO_POINTER_ALIGN (regno) >= 128;
  3706. }
  3707. /* Encode symbol attributes (local vs. global, tls model) of a SYMBOL_REF
  3708. into its SYMBOL_REF_FLAGS. */
  3709. static void
  3710. spu_encode_section_info (tree decl, rtx rtl, int first)
  3711. {
  3712. default_encode_section_info (decl, rtl, first);
  3713. /* If a variable has a forced alignment to < 16 bytes, mark it with
  3714. SYMBOL_FLAG_ALIGN1. */
  3715. if (TREE_CODE (decl) == VAR_DECL
  3716. && DECL_USER_ALIGN (decl) && DECL_ALIGN (decl) < 128)
  3717. SYMBOL_REF_FLAGS (XEXP (rtl, 0)) |= SYMBOL_FLAG_ALIGN1;
  3718. }
  3719. /* Return TRUE if we are certain the mem refers to a complete object
  3720. which is both 16-byte aligned and padded to a 16-byte boundary. This
  3721. would make it safe to store with a single instruction.
  3722. We guarantee the alignment and padding for static objects by aligning
  3723. all of them to 16-bytes. (DATA_ALIGNMENT and CONSTANT_ALIGNMENT.)
  3724. FIXME: We currently cannot guarantee this for objects on the stack
  3725. because assign_parm_setup_stack calls assign_stack_local with the
  3726. alignment of the parameter mode and in that case the alignment never
  3727. gets adjusted by LOCAL_ALIGNMENT. */
  3728. static int
  3729. store_with_one_insn_p (rtx mem)
  3730. {
  3731. machine_mode mode = GET_MODE (mem);
  3732. rtx addr = XEXP (mem, 0);
  3733. if (mode == BLKmode)
  3734. return 0;
  3735. if (GET_MODE_SIZE (mode) >= 16)
  3736. return 1;
  3737. /* Only static objects. */
  3738. if (GET_CODE (addr) == SYMBOL_REF)
  3739. {
  3740. /* We use the associated declaration to make sure the access is
  3741. referring to the whole object.
  3742. We check both MEM_EXPR and SYMBOL_REF_DECL. I'm not sure
  3743. if it is necessary. Will there be cases where one exists, and
  3744. the other does not? Will there be cases where both exist, but
  3745. have different types? */
  3746. tree decl = MEM_EXPR (mem);
  3747. if (decl
  3748. && TREE_CODE (decl) == VAR_DECL
  3749. && GET_MODE (mem) == TYPE_MODE (TREE_TYPE (decl)))
  3750. return 1;
  3751. decl = SYMBOL_REF_DECL (addr);
  3752. if (decl
  3753. && TREE_CODE (decl) == VAR_DECL
  3754. && GET_MODE (mem) == TYPE_MODE (TREE_TYPE (decl)))
  3755. return 1;
  3756. }
  3757. return 0;
  3758. }
  3759. /* Return 1 when the address is not valid for a simple load and store as
  3760. required by the '_mov*' patterns. We could make this less strict
  3761. for loads, but we prefer mem's to look the same so they are more
  3762. likely to be merged. */
  3763. static int
  3764. address_needs_split (rtx mem)
  3765. {
  3766. if (GET_MODE_SIZE (GET_MODE (mem)) < 16
  3767. && (GET_MODE_SIZE (GET_MODE (mem)) < 4
  3768. || !(store_with_one_insn_p (mem)
  3769. || mem_is_padded_component_ref (mem))))
  3770. return 1;
  3771. return 0;
  3772. }
  3773. static GTY(()) rtx cache_fetch; /* __cache_fetch function */
  3774. static GTY(()) rtx cache_fetch_dirty; /* __cache_fetch_dirty function */
  3775. static alias_set_type ea_alias_set = -1; /* alias set for __ea memory */
  3776. /* MEM is known to be an __ea qualified memory access. Emit a call to
  3777. fetch the ppu memory to local store, and return its address in local
  3778. store. */
  3779. static void
  3780. ea_load_store (rtx mem, bool is_store, rtx ea_addr, rtx data_addr)
  3781. {
  3782. if (is_store)
  3783. {
  3784. rtx ndirty = GEN_INT (GET_MODE_SIZE (GET_MODE (mem)));
  3785. if (!cache_fetch_dirty)
  3786. cache_fetch_dirty = init_one_libfunc ("__cache_fetch_dirty");
  3787. emit_library_call_value (cache_fetch_dirty, data_addr, LCT_NORMAL, Pmode,
  3788. 2, ea_addr, EAmode, ndirty, SImode);
  3789. }
  3790. else
  3791. {
  3792. if (!cache_fetch)
  3793. cache_fetch = init_one_libfunc ("__cache_fetch");
  3794. emit_library_call_value (cache_fetch, data_addr, LCT_NORMAL, Pmode,
  3795. 1, ea_addr, EAmode);
  3796. }
  3797. }
  3798. /* Like ea_load_store, but do the cache tag comparison and, for stores,
  3799. dirty bit marking, inline.
  3800. The cache control data structure is an array of
  3801. struct __cache_tag_array
  3802. {
  3803. unsigned int tag_lo[4];
  3804. unsigned int tag_hi[4];
  3805. void *data_pointer[4];
  3806. int reserved[4];
  3807. vector unsigned short dirty_bits[4];
  3808. } */
  3809. static void
  3810. ea_load_store_inline (rtx mem, bool is_store, rtx ea_addr, rtx data_addr)
  3811. {
  3812. rtx ea_addr_si;
  3813. HOST_WIDE_INT v;
  3814. rtx tag_size_sym = gen_rtx_SYMBOL_REF (Pmode, "__cache_tag_array_size");
  3815. rtx tag_arr_sym = gen_rtx_SYMBOL_REF (Pmode, "__cache_tag_array");
  3816. rtx index_mask = gen_reg_rtx (SImode);
  3817. rtx tag_arr = gen_reg_rtx (Pmode);
  3818. rtx splat_mask = gen_reg_rtx (TImode);
  3819. rtx splat = gen_reg_rtx (V4SImode);
  3820. rtx splat_hi = NULL_RTX;
  3821. rtx tag_index = gen_reg_rtx (Pmode);
  3822. rtx block_off = gen_reg_rtx (SImode);
  3823. rtx tag_addr = gen_reg_rtx (Pmode);
  3824. rtx tag = gen_reg_rtx (V4SImode);
  3825. rtx cache_tag = gen_reg_rtx (V4SImode);
  3826. rtx cache_tag_hi = NULL_RTX;
  3827. rtx cache_ptrs = gen_reg_rtx (TImode);
  3828. rtx cache_ptrs_si = gen_reg_rtx (SImode);
  3829. rtx tag_equal = gen_reg_rtx (V4SImode);
  3830. rtx tag_equal_hi = NULL_RTX;
  3831. rtx tag_eq_pack = gen_reg_rtx (V4SImode);
  3832. rtx tag_eq_pack_si = gen_reg_rtx (SImode);
  3833. rtx eq_index = gen_reg_rtx (SImode);
  3834. rtx bcomp, hit_label, hit_ref, cont_label;
  3835. rtx_insn *insn;
  3836. if (spu_ea_model != 32)
  3837. {
  3838. splat_hi = gen_reg_rtx (V4SImode);
  3839. cache_tag_hi = gen_reg_rtx (V4SImode);
  3840. tag_equal_hi = gen_reg_rtx (V4SImode);
  3841. }
  3842. emit_move_insn (index_mask, plus_constant (Pmode, tag_size_sym, -128));
  3843. emit_move_insn (tag_arr, tag_arr_sym);
  3844. v = 0x0001020300010203LL;
  3845. emit_move_insn (splat_mask, immed_double_const (v, v, TImode));
  3846. ea_addr_si = ea_addr;
  3847. if (spu_ea_model != 32)
  3848. ea_addr_si = convert_to_mode (SImode, ea_addr, 1);
  3849. /* tag_index = ea_addr & (tag_array_size - 128) */
  3850. emit_insn (gen_andsi3 (tag_index, ea_addr_si, index_mask));
  3851. /* splat ea_addr to all 4 slots. */
  3852. emit_insn (gen_shufb (splat, ea_addr_si, ea_addr_si, splat_mask));
  3853. /* Similarly for high 32 bits of ea_addr. */
  3854. if (spu_ea_model != 32)
  3855. emit_insn (gen_shufb (splat_hi, ea_addr, ea_addr, splat_mask));
  3856. /* block_off = ea_addr & 127 */
  3857. emit_insn (gen_andsi3 (block_off, ea_addr_si, spu_const (SImode, 127)));
  3858. /* tag_addr = tag_arr + tag_index */
  3859. emit_insn (gen_addsi3 (tag_addr, tag_arr, tag_index));
  3860. /* Read cache tags. */
  3861. emit_move_insn (cache_tag, gen_rtx_MEM (V4SImode, tag_addr));
  3862. if (spu_ea_model != 32)
  3863. emit_move_insn (cache_tag_hi, gen_rtx_MEM (V4SImode,
  3864. plus_constant (Pmode,
  3865. tag_addr, 16)));
  3866. /* tag = ea_addr & -128 */
  3867. emit_insn (gen_andv4si3 (tag, splat, spu_const (V4SImode, -128)));
  3868. /* Read all four cache data pointers. */
  3869. emit_move_insn (cache_ptrs, gen_rtx_MEM (TImode,
  3870. plus_constant (Pmode,
  3871. tag_addr, 32)));
  3872. /* Compare tags. */
  3873. emit_insn (gen_ceq_v4si (tag_equal, tag, cache_tag));
  3874. if (spu_ea_model != 32)
  3875. {
  3876. emit_insn (gen_ceq_v4si (tag_equal_hi, splat_hi, cache_tag_hi));
  3877. emit_insn (gen_andv4si3 (tag_equal, tag_equal, tag_equal_hi));
  3878. }
  3879. /* At most one of the tags compare equal, so tag_equal has one
  3880. 32-bit slot set to all 1's, with the other slots all zero.
  3881. gbb picks off low bit from each byte in the 128-bit registers,
  3882. so tag_eq_pack is one of 0xf000, 0x0f00, 0x00f0, 0x000f, assuming
  3883. we have a hit. */
  3884. emit_insn (gen_spu_gbb (tag_eq_pack, spu_gen_subreg (V16QImode, tag_equal)));
  3885. emit_insn (gen_spu_convert (tag_eq_pack_si, tag_eq_pack));
  3886. /* So counting leading zeros will set eq_index to 16, 20, 24 or 28. */
  3887. emit_insn (gen_clzsi2 (eq_index, tag_eq_pack_si));
  3888. /* Allowing us to rotate the corresponding cache data pointer to slot0.
  3889. (rotating eq_index mod 16 bytes). */
  3890. emit_insn (gen_rotqby_ti (cache_ptrs, cache_ptrs, eq_index));
  3891. emit_insn (gen_spu_convert (cache_ptrs_si, cache_ptrs));
  3892. /* Add block offset to form final data address. */
  3893. emit_insn (gen_addsi3 (data_addr, cache_ptrs_si, block_off));
  3894. /* Check that we did hit. */
  3895. hit_label = gen_label_rtx ();
  3896. hit_ref = gen_rtx_LABEL_REF (VOIDmode, hit_label);
  3897. bcomp = gen_rtx_NE (SImode, tag_eq_pack_si, const0_rtx);
  3898. insn = emit_jump_insn (gen_rtx_SET (VOIDmode, pc_rtx,
  3899. gen_rtx_IF_THEN_ELSE (VOIDmode, bcomp,
  3900. hit_ref, pc_rtx)));
  3901. /* Say that this branch is very likely to happen. */
  3902. v = REG_BR_PROB_BASE - REG_BR_PROB_BASE / 100 - 1;
  3903. add_int_reg_note (insn, REG_BR_PROB, v);
  3904. ea_load_store (mem, is_store, ea_addr, data_addr);
  3905. cont_label = gen_label_rtx ();
  3906. emit_jump_insn (gen_jump (cont_label));
  3907. emit_barrier ();
  3908. emit_label (hit_label);
  3909. if (is_store)
  3910. {
  3911. HOST_WIDE_INT v_hi;
  3912. rtx dirty_bits = gen_reg_rtx (TImode);
  3913. rtx dirty_off = gen_reg_rtx (SImode);
  3914. rtx dirty_128 = gen_reg_rtx (TImode);
  3915. rtx neg_block_off = gen_reg_rtx (SImode);
  3916. /* Set up mask with one dirty bit per byte of the mem we are
  3917. writing, starting from top bit. */
  3918. v_hi = v = -1;
  3919. v <<= (128 - GET_MODE_SIZE (GET_MODE (mem))) & 63;
  3920. if ((128 - GET_MODE_SIZE (GET_MODE (mem))) >= 64)
  3921. {
  3922. v_hi = v;
  3923. v = 0;
  3924. }
  3925. emit_move_insn (dirty_bits, immed_double_const (v, v_hi, TImode));
  3926. /* Form index into cache dirty_bits. eq_index is one of
  3927. 0x10, 0x14, 0x18 or 0x1c. Multiplying by 4 gives us
  3928. 0x40, 0x50, 0x60 or 0x70 which just happens to be the
  3929. offset to each of the four dirty_bits elements. */
  3930. emit_insn (gen_ashlsi3 (dirty_off, eq_index, spu_const (SImode, 2)));
  3931. emit_insn (gen_spu_lqx (dirty_128, tag_addr, dirty_off));
  3932. /* Rotate bit mask to proper bit. */
  3933. emit_insn (gen_negsi2 (neg_block_off, block_off));
  3934. emit_insn (gen_rotqbybi_ti (dirty_bits, dirty_bits, neg_block_off));
  3935. emit_insn (gen_rotqbi_ti (dirty_bits, dirty_bits, neg_block_off));
  3936. /* Or in the new dirty bits. */
  3937. emit_insn (gen_iorti3 (dirty_128, dirty_bits, dirty_128));
  3938. /* Store. */
  3939. emit_insn (gen_spu_stqx (dirty_128, tag_addr, dirty_off));
  3940. }
  3941. emit_label (cont_label);
  3942. }
  3943. static rtx
  3944. expand_ea_mem (rtx mem, bool is_store)
  3945. {
  3946. rtx ea_addr;
  3947. rtx data_addr = gen_reg_rtx (Pmode);
  3948. rtx new_mem;
  3949. ea_addr = force_reg (EAmode, XEXP (mem, 0));
  3950. if (optimize_size || optimize == 0)
  3951. ea_load_store (mem, is_store, ea_addr, data_addr);
  3952. else
  3953. ea_load_store_inline (mem, is_store, ea_addr, data_addr);
  3954. if (ea_alias_set == -1)
  3955. ea_alias_set = new_alias_set ();
  3956. /* We generate a new MEM RTX to refer to the copy of the data
  3957. in the cache. We do not copy memory attributes (except the
  3958. alignment) from the original MEM, as they may no longer apply
  3959. to the cache copy. */
  3960. new_mem = gen_rtx_MEM (GET_MODE (mem), data_addr);
  3961. set_mem_alias_set (new_mem, ea_alias_set);
  3962. set_mem_align (new_mem, MIN (MEM_ALIGN (mem), 128 * 8));
  3963. return new_mem;
  3964. }
  3965. int
  3966. spu_expand_mov (rtx * ops, machine_mode mode)
  3967. {
  3968. if (GET_CODE (ops[0]) == SUBREG && !valid_subreg (ops[0]))
  3969. {
  3970. /* Perform the move in the destination SUBREG's inner mode. */
  3971. ops[0] = SUBREG_REG (ops[0]);
  3972. mode = GET_MODE (ops[0]);
  3973. ops[1] = gen_lowpart_common (mode, ops[1]);
  3974. gcc_assert (ops[1]);
  3975. }
  3976. if (GET_CODE (ops[1]) == SUBREG && !valid_subreg (ops[1]))
  3977. {
  3978. rtx from = SUBREG_REG (ops[1]);
  3979. machine_mode imode = int_mode_for_mode (GET_MODE (from));
  3980. gcc_assert (GET_MODE_CLASS (mode) == MODE_INT
  3981. && GET_MODE_CLASS (imode) == MODE_INT
  3982. && subreg_lowpart_p (ops[1]));
  3983. if (GET_MODE_SIZE (imode) < 4)
  3984. imode = SImode;
  3985. if (imode != GET_MODE (from))
  3986. from = gen_rtx_SUBREG (imode, from, 0);
  3987. if (GET_MODE_SIZE (mode) < GET_MODE_SIZE (imode))
  3988. {
  3989. enum insn_code icode = convert_optab_handler (trunc_optab,
  3990. mode, imode);
  3991. emit_insn (GEN_FCN (icode) (ops[0], from));
  3992. }
  3993. else
  3994. emit_insn (gen_extend_insn (ops[0], from, mode, imode, 1));
  3995. return 1;
  3996. }
  3997. /* At least one of the operands needs to be a register. */
  3998. if ((reload_in_progress | reload_completed) == 0
  3999. && !register_operand (ops[0], mode) && !register_operand (ops[1], mode))
  4000. {
  4001. rtx temp = force_reg (mode, ops[1]);
  4002. emit_move_insn (ops[0], temp);
  4003. return 1;
  4004. }
  4005. if (reload_in_progress || reload_completed)
  4006. {
  4007. if (CONSTANT_P (ops[1]))
  4008. return spu_split_immediate (ops);
  4009. return 0;
  4010. }
  4011. /* Catch the SImode immediates greater than 0x7fffffff, and sign
  4012. extend them. */
  4013. if (GET_CODE (ops[1]) == CONST_INT)
  4014. {
  4015. HOST_WIDE_INT val = trunc_int_for_mode (INTVAL (ops[1]), mode);
  4016. if (val != INTVAL (ops[1]))
  4017. {
  4018. emit_move_insn (ops[0], GEN_INT (val));
  4019. return 1;
  4020. }
  4021. }
  4022. if (MEM_P (ops[0]))
  4023. {
  4024. if (MEM_ADDR_SPACE (ops[0]))
  4025. ops[0] = expand_ea_mem (ops[0], true);
  4026. return spu_split_store (ops);
  4027. }
  4028. if (MEM_P (ops[1]))
  4029. {
  4030. if (MEM_ADDR_SPACE (ops[1]))
  4031. ops[1] = expand_ea_mem (ops[1], false);
  4032. return spu_split_load (ops);
  4033. }
  4034. return 0;
  4035. }
  4036. static void
  4037. spu_convert_move (rtx dst, rtx src)
  4038. {
  4039. machine_mode mode = GET_MODE (dst);
  4040. machine_mode int_mode = mode_for_size (GET_MODE_BITSIZE (mode), MODE_INT, 0);
  4041. rtx reg;
  4042. gcc_assert (GET_MODE (src) == TImode);
  4043. reg = int_mode != mode ? gen_reg_rtx (int_mode) : dst;
  4044. emit_insn (gen_rtx_SET (VOIDmode, reg,
  4045. gen_rtx_TRUNCATE (int_mode,
  4046. gen_rtx_LSHIFTRT (TImode, src,
  4047. GEN_INT (int_mode == DImode ? 64 : 96)))));
  4048. if (int_mode != mode)
  4049. {
  4050. reg = simplify_gen_subreg (mode, reg, int_mode, 0);
  4051. emit_move_insn (dst, reg);
  4052. }
  4053. }
  4054. /* Load TImode values into DST0 and DST1 (when it is non-NULL) using
  4055. the address from SRC and SRC+16. Return a REG or CONST_INT that
  4056. specifies how many bytes to rotate the loaded registers, plus any
  4057. extra from EXTRA_ROTQBY. The address and rotate amounts are
  4058. normalized to improve merging of loads and rotate computations. */
  4059. static rtx
  4060. spu_expand_load (rtx dst0, rtx dst1, rtx src, int extra_rotby)
  4061. {
  4062. rtx addr = XEXP (src, 0);
  4063. rtx p0, p1, rot, addr0, addr1;
  4064. int rot_amt;
  4065. rot = 0;
  4066. rot_amt = 0;
  4067. if (MEM_ALIGN (src) >= 128)
  4068. /* Address is already aligned; simply perform a TImode load. */ ;
  4069. else if (GET_CODE (addr) == PLUS)
  4070. {
  4071. /* 8 cases:
  4072. aligned reg + aligned reg => lqx
  4073. aligned reg + unaligned reg => lqx, rotqby
  4074. aligned reg + aligned const => lqd
  4075. aligned reg + unaligned const => lqd, rotqbyi
  4076. unaligned reg + aligned reg => lqx, rotqby
  4077. unaligned reg + unaligned reg => lqx, a, rotqby (1 scratch)
  4078. unaligned reg + aligned const => lqd, rotqby
  4079. unaligned reg + unaligned const -> not allowed by legitimate address
  4080. */
  4081. p0 = XEXP (addr, 0);
  4082. p1 = XEXP (addr, 1);
  4083. if (!reg_aligned_for_addr (p0))
  4084. {
  4085. if (REG_P (p1) && !reg_aligned_for_addr (p1))
  4086. {
  4087. rot = gen_reg_rtx (SImode);
  4088. emit_insn (gen_addsi3 (rot, p0, p1));
  4089. }
  4090. else if (GET_CODE (p1) == CONST_INT && (INTVAL (p1) & 15))
  4091. {
  4092. if (INTVAL (p1) > 0
  4093. && REG_POINTER (p0)
  4094. && INTVAL (p1) * BITS_PER_UNIT
  4095. < REGNO_POINTER_ALIGN (REGNO (p0)))
  4096. {
  4097. rot = gen_reg_rtx (SImode);
  4098. emit_insn (gen_addsi3 (rot, p0, p1));
  4099. addr = p0;
  4100. }
  4101. else
  4102. {
  4103. rtx x = gen_reg_rtx (SImode);
  4104. emit_move_insn (x, p1);
  4105. if (!spu_arith_operand (p1, SImode))
  4106. p1 = x;
  4107. rot = gen_reg_rtx (SImode);
  4108. emit_insn (gen_addsi3 (rot, p0, p1));
  4109. addr = gen_rtx_PLUS (Pmode, p0, x);
  4110. }
  4111. }
  4112. else
  4113. rot = p0;
  4114. }
  4115. else
  4116. {
  4117. if (GET_CODE (p1) == CONST_INT && (INTVAL (p1) & 15))
  4118. {
  4119. rot_amt = INTVAL (p1) & 15;
  4120. if (INTVAL (p1) & -16)
  4121. {
  4122. p1 = GEN_INT (INTVAL (p1) & -16);
  4123. addr = gen_rtx_PLUS (SImode, p0, p1);
  4124. }
  4125. else
  4126. addr = p0;
  4127. }
  4128. else if (REG_P (p1) && !reg_aligned_for_addr (p1))
  4129. rot = p1;
  4130. }
  4131. }
  4132. else if (REG_P (addr))
  4133. {
  4134. if (!reg_aligned_for_addr (addr))
  4135. rot = addr;
  4136. }
  4137. else if (GET_CODE (addr) == CONST)
  4138. {
  4139. if (GET_CODE (XEXP (addr, 0)) == PLUS
  4140. && ALIGNED_SYMBOL_REF_P (XEXP (XEXP (addr, 0), 0))
  4141. && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
  4142. {
  4143. rot_amt = INTVAL (XEXP (XEXP (addr, 0), 1));
  4144. if (rot_amt & -16)
  4145. addr = gen_rtx_CONST (Pmode,
  4146. gen_rtx_PLUS (Pmode,
  4147. XEXP (XEXP (addr, 0), 0),
  4148. GEN_INT (rot_amt & -16)));
  4149. else
  4150. addr = XEXP (XEXP (addr, 0), 0);
  4151. }
  4152. else
  4153. {
  4154. rot = gen_reg_rtx (Pmode);
  4155. emit_move_insn (rot, addr);
  4156. }
  4157. }
  4158. else if (GET_CODE (addr) == CONST_INT)
  4159. {
  4160. rot_amt = INTVAL (addr);
  4161. addr = GEN_INT (rot_amt & -16);
  4162. }
  4163. else if (!ALIGNED_SYMBOL_REF_P (addr))
  4164. {
  4165. rot = gen_reg_rtx (Pmode);
  4166. emit_move_insn (rot, addr);
  4167. }
  4168. rot_amt += extra_rotby;
  4169. rot_amt &= 15;
  4170. if (rot && rot_amt)
  4171. {
  4172. rtx x = gen_reg_rtx (SImode);
  4173. emit_insn (gen_addsi3 (x, rot, GEN_INT (rot_amt)));
  4174. rot = x;
  4175. rot_amt = 0;
  4176. }
  4177. if (!rot && rot_amt)
  4178. rot = GEN_INT (rot_amt);
  4179. addr0 = copy_rtx (addr);
  4180. addr0 = gen_rtx_AND (SImode, copy_rtx (addr), GEN_INT (-16));
  4181. emit_insn (gen__movti (dst0, change_address (src, TImode, addr0)));
  4182. if (dst1)
  4183. {
  4184. addr1 = plus_constant (SImode, copy_rtx (addr), 16);
  4185. addr1 = gen_rtx_AND (SImode, addr1, GEN_INT (-16));
  4186. emit_insn (gen__movti (dst1, change_address (src, TImode, addr1)));
  4187. }
  4188. return rot;
  4189. }
  4190. int
  4191. spu_split_load (rtx * ops)
  4192. {
  4193. machine_mode mode = GET_MODE (ops[0]);
  4194. rtx addr, load, rot;
  4195. int rot_amt;
  4196. if (GET_MODE_SIZE (mode) >= 16)
  4197. return 0;
  4198. addr = XEXP (ops[1], 0);
  4199. gcc_assert (GET_CODE (addr) != AND);
  4200. if (!address_needs_split (ops[1]))
  4201. {
  4202. ops[1] = change_address (ops[1], TImode, addr);
  4203. load = gen_reg_rtx (TImode);
  4204. emit_insn (gen__movti (load, ops[1]));
  4205. spu_convert_move (ops[0], load);
  4206. return 1;
  4207. }
  4208. rot_amt = GET_MODE_SIZE (mode) < 4 ? GET_MODE_SIZE (mode) - 4 : 0;
  4209. load = gen_reg_rtx (TImode);
  4210. rot = spu_expand_load (load, 0, ops[1], rot_amt);
  4211. if (rot)
  4212. emit_insn (gen_rotqby_ti (load, load, rot));
  4213. spu_convert_move (ops[0], load);
  4214. return 1;
  4215. }
  4216. int
  4217. spu_split_store (rtx * ops)
  4218. {
  4219. machine_mode mode = GET_MODE (ops[0]);
  4220. rtx reg;
  4221. rtx addr, p0, p1, p1_lo, smem;
  4222. int aform;
  4223. int scalar;
  4224. if (GET_MODE_SIZE (mode) >= 16)
  4225. return 0;
  4226. addr = XEXP (ops[0], 0);
  4227. gcc_assert (GET_CODE (addr) != AND);
  4228. if (!address_needs_split (ops[0]))
  4229. {
  4230. reg = gen_reg_rtx (TImode);
  4231. emit_insn (gen_spu_convert (reg, ops[1]));
  4232. ops[0] = change_address (ops[0], TImode, addr);
  4233. emit_move_insn (ops[0], reg);
  4234. return 1;
  4235. }
  4236. if (GET_CODE (addr) == PLUS)
  4237. {
  4238. /* 8 cases:
  4239. aligned reg + aligned reg => lqx, c?x, shuf, stqx
  4240. aligned reg + unaligned reg => lqx, c?x, shuf, stqx
  4241. aligned reg + aligned const => lqd, c?d, shuf, stqx
  4242. aligned reg + unaligned const => lqd, c?d, shuf, stqx
  4243. unaligned reg + aligned reg => lqx, c?x, shuf, stqx
  4244. unaligned reg + unaligned reg => lqx, c?x, shuf, stqx
  4245. unaligned reg + aligned const => lqd, c?d, shuf, stqx
  4246. unaligned reg + unaligned const -> lqx, c?d, shuf, stqx
  4247. */
  4248. aform = 0;
  4249. p0 = XEXP (addr, 0);
  4250. p1 = p1_lo = XEXP (addr, 1);
  4251. if (REG_P (p0) && GET_CODE (p1) == CONST_INT)
  4252. {
  4253. p1_lo = GEN_INT (INTVAL (p1) & 15);
  4254. if (reg_aligned_for_addr (p0))
  4255. {
  4256. p1 = GEN_INT (INTVAL (p1) & -16);
  4257. if (p1 == const0_rtx)
  4258. addr = p0;
  4259. else
  4260. addr = gen_rtx_PLUS (SImode, p0, p1);
  4261. }
  4262. else
  4263. {
  4264. rtx x = gen_reg_rtx (SImode);
  4265. emit_move_insn (x, p1);
  4266. addr = gen_rtx_PLUS (SImode, p0, x);
  4267. }
  4268. }
  4269. }
  4270. else if (REG_P (addr))
  4271. {
  4272. aform = 0;
  4273. p0 = addr;
  4274. p1 = p1_lo = const0_rtx;
  4275. }
  4276. else
  4277. {
  4278. aform = 1;
  4279. p0 = gen_rtx_REG (SImode, STACK_POINTER_REGNUM);
  4280. p1 = 0; /* aform doesn't use p1 */
  4281. p1_lo = addr;
  4282. if (ALIGNED_SYMBOL_REF_P (addr))
  4283. p1_lo = const0_rtx;
  4284. else if (GET_CODE (addr) == CONST
  4285. && GET_CODE (XEXP (addr, 0)) == PLUS
  4286. && ALIGNED_SYMBOL_REF_P (XEXP (XEXP (addr, 0), 0))
  4287. && GET_CODE (XEXP (XEXP (addr, 0), 1)) == CONST_INT)
  4288. {
  4289. HOST_WIDE_INT v = INTVAL (XEXP (XEXP (addr, 0), 1));
  4290. if ((v & -16) != 0)
  4291. addr = gen_rtx_CONST (Pmode,
  4292. gen_rtx_PLUS (Pmode,
  4293. XEXP (XEXP (addr, 0), 0),
  4294. GEN_INT (v & -16)));
  4295. else
  4296. addr = XEXP (XEXP (addr, 0), 0);
  4297. p1_lo = GEN_INT (v & 15);
  4298. }
  4299. else if (GET_CODE (addr) == CONST_INT)
  4300. {
  4301. p1_lo = GEN_INT (INTVAL (addr) & 15);
  4302. addr = GEN_INT (INTVAL (addr) & -16);
  4303. }
  4304. else
  4305. {
  4306. p1_lo = gen_reg_rtx (SImode);
  4307. emit_move_insn (p1_lo, addr);
  4308. }
  4309. }
  4310. gcc_assert (aform == 0 || aform == 1);
  4311. reg = gen_reg_rtx (TImode);
  4312. scalar = store_with_one_insn_p (ops[0]);
  4313. if (!scalar)
  4314. {
  4315. /* We could copy the flags from the ops[0] MEM to mem here,
  4316. We don't because we want this load to be optimized away if
  4317. possible, and copying the flags will prevent that in certain
  4318. cases, e.g. consider the volatile flag. */
  4319. rtx pat = gen_reg_rtx (TImode);
  4320. rtx lmem = change_address (ops[0], TImode, copy_rtx (addr));
  4321. set_mem_alias_set (lmem, 0);
  4322. emit_insn (gen_movti (reg, lmem));
  4323. if (!p0 || reg_aligned_for_addr (p0))
  4324. p0 = stack_pointer_rtx;
  4325. if (!p1_lo)
  4326. p1_lo = const0_rtx;
  4327. emit_insn (gen_cpat (pat, p0, p1_lo, GEN_INT (GET_MODE_SIZE (mode))));
  4328. emit_insn (gen_shufb (reg, ops[1], reg, pat));
  4329. }
  4330. else
  4331. {
  4332. if (GET_CODE (ops[1]) == REG)
  4333. emit_insn (gen_spu_convert (reg, ops[1]));
  4334. else if (GET_CODE (ops[1]) == SUBREG)
  4335. emit_insn (gen_spu_convert (reg, SUBREG_REG (ops[1])));
  4336. else
  4337. abort ();
  4338. }
  4339. if (GET_MODE_SIZE (mode) < 4 && scalar)
  4340. emit_insn (gen_ashlti3
  4341. (reg, reg, GEN_INT (32 - GET_MODE_BITSIZE (mode))));
  4342. smem = change_address (ops[0], TImode, copy_rtx (addr));
  4343. /* We can't use the previous alias set because the memory has changed
  4344. size and can potentially overlap objects of other types. */
  4345. set_mem_alias_set (smem, 0);
  4346. emit_insn (gen_movti (smem, reg));
  4347. return 1;
  4348. }
  4349. /* Return TRUE if X is MEM which is a struct member reference
  4350. and the member can safely be loaded and stored with a single
  4351. instruction because it is padded. */
  4352. static int
  4353. mem_is_padded_component_ref (rtx x)
  4354. {
  4355. tree t = MEM_EXPR (x);
  4356. tree r;
  4357. if (!t || TREE_CODE (t) != COMPONENT_REF)
  4358. return 0;
  4359. t = TREE_OPERAND (t, 1);
  4360. if (!t || TREE_CODE (t) != FIELD_DECL
  4361. || DECL_ALIGN (t) < 128 || AGGREGATE_TYPE_P (TREE_TYPE (t)))
  4362. return 0;
  4363. /* Only do this for RECORD_TYPEs, not UNION_TYPEs. */
  4364. r = DECL_FIELD_CONTEXT (t);
  4365. if (!r || TREE_CODE (r) != RECORD_TYPE)
  4366. return 0;
  4367. /* Make sure they are the same mode */
  4368. if (GET_MODE (x) != TYPE_MODE (TREE_TYPE (t)))
  4369. return 0;
  4370. /* If there are no following fields then the field alignment assures
  4371. the structure is padded to the alignment which means this field is
  4372. padded too. */
  4373. if (TREE_CHAIN (t) == 0)
  4374. return 1;
  4375. /* If the following field is also aligned then this field will be
  4376. padded. */
  4377. t = TREE_CHAIN (t);
  4378. if (TREE_CODE (t) == FIELD_DECL && DECL_ALIGN (t) >= 128)
  4379. return 1;
  4380. return 0;
  4381. }
  4382. /* Parse the -mfixed-range= option string. */
  4383. static void
  4384. fix_range (const char *const_str)
  4385. {
  4386. int i, first, last;
  4387. char *str, *dash, *comma;
  4388. /* str must be of the form REG1'-'REG2{,REG1'-'REG} where REG1 and
  4389. REG2 are either register names or register numbers. The effect
  4390. of this option is to mark the registers in the range from REG1 to
  4391. REG2 as ``fixed'' so they won't be used by the compiler. */
  4392. i = strlen (const_str);
  4393. str = (char *) alloca (i + 1);
  4394. memcpy (str, const_str, i + 1);
  4395. while (1)
  4396. {
  4397. dash = strchr (str, '-');
  4398. if (!dash)
  4399. {
  4400. warning (0, "value of -mfixed-range must have form REG1-REG2");
  4401. return;
  4402. }
  4403. *dash = '\0';
  4404. comma = strchr (dash + 1, ',');
  4405. if (comma)
  4406. *comma = '\0';
  4407. first = decode_reg_name (str);
  4408. if (first < 0)
  4409. {
  4410. warning (0, "unknown register name: %s", str);
  4411. return;
  4412. }
  4413. last = decode_reg_name (dash + 1);
  4414. if (last < 0)
  4415. {
  4416. warning (0, "unknown register name: %s", dash + 1);
  4417. return;
  4418. }
  4419. *dash = '-';
  4420. if (first > last)
  4421. {
  4422. warning (0, "%s-%s is an empty range", str, dash + 1);
  4423. return;
  4424. }
  4425. for (i = first; i <= last; ++i)
  4426. fixed_regs[i] = call_used_regs[i] = 1;
  4427. if (!comma)
  4428. break;
  4429. *comma = ',';
  4430. str = comma + 1;
  4431. }
  4432. }
  4433. /* Return TRUE if x is a CONST_INT, CONST_DOUBLE or CONST_VECTOR that
  4434. can be generated using the fsmbi instruction. */
  4435. int
  4436. fsmbi_const_p (rtx x)
  4437. {
  4438. if (CONSTANT_P (x))
  4439. {
  4440. /* We can always choose TImode for CONST_INT because the high bits
  4441. of an SImode will always be all 1s, i.e., valid for fsmbi. */
  4442. enum immediate_class c = classify_immediate (x, TImode);
  4443. return c == IC_FSMBI || (!epilogue_completed && c == IC_FSMBI2);
  4444. }
  4445. return 0;
  4446. }
  4447. /* Return TRUE if x is a CONST_INT, CONST_DOUBLE or CONST_VECTOR that
  4448. can be generated using the cbd, chd, cwd or cdd instruction. */
  4449. int
  4450. cpat_const_p (rtx x, machine_mode mode)
  4451. {
  4452. if (CONSTANT_P (x))
  4453. {
  4454. enum immediate_class c = classify_immediate (x, mode);
  4455. return c == IC_CPAT;
  4456. }
  4457. return 0;
  4458. }
  4459. rtx
  4460. gen_cpat_const (rtx * ops)
  4461. {
  4462. unsigned char dst[16];
  4463. int i, offset, shift, isize;
  4464. if (GET_CODE (ops[3]) != CONST_INT
  4465. || GET_CODE (ops[2]) != CONST_INT
  4466. || (GET_CODE (ops[1]) != CONST_INT
  4467. && GET_CODE (ops[1]) != REG))
  4468. return 0;
  4469. if (GET_CODE (ops[1]) == REG
  4470. && (!REG_POINTER (ops[1])
  4471. || REGNO_POINTER_ALIGN (ORIGINAL_REGNO (ops[1])) < 128))
  4472. return 0;
  4473. for (i = 0; i < 16; i++)
  4474. dst[i] = i + 16;
  4475. isize = INTVAL (ops[3]);
  4476. if (isize == 1)
  4477. shift = 3;
  4478. else if (isize == 2)
  4479. shift = 2;
  4480. else
  4481. shift = 0;
  4482. offset = (INTVAL (ops[2]) +
  4483. (GET_CODE (ops[1]) ==
  4484. CONST_INT ? INTVAL (ops[1]) : 0)) & 15;
  4485. for (i = 0; i < isize; i++)
  4486. dst[offset + i] = i + shift;
  4487. return array_to_constant (TImode, dst);
  4488. }
  4489. /* Convert a CONST_INT, CONST_DOUBLE, or CONST_VECTOR into a 16 byte
  4490. array. Use MODE for CONST_INT's. When the constant's mode is smaller
  4491. than 16 bytes, the value is repeated across the rest of the array. */
  4492. void
  4493. constant_to_array (machine_mode mode, rtx x, unsigned char arr[16])
  4494. {
  4495. HOST_WIDE_INT val;
  4496. int i, j, first;
  4497. memset (arr, 0, 16);
  4498. mode = GET_MODE (x) != VOIDmode ? GET_MODE (x) : mode;
  4499. if (GET_CODE (x) == CONST_INT
  4500. || (GET_CODE (x) == CONST_DOUBLE
  4501. && (mode == SFmode || mode == DFmode)))
  4502. {
  4503. gcc_assert (mode != VOIDmode && mode != BLKmode);
  4504. if (GET_CODE (x) == CONST_DOUBLE)
  4505. val = const_double_to_hwint (x);
  4506. else
  4507. val = INTVAL (x);
  4508. first = GET_MODE_SIZE (mode) - 1;
  4509. for (i = first; i >= 0; i--)
  4510. {
  4511. arr[i] = val & 0xff;
  4512. val >>= 8;
  4513. }
  4514. /* Splat the constant across the whole array. */
  4515. for (j = 0, i = first + 1; i < 16; i++)
  4516. {
  4517. arr[i] = arr[j];
  4518. j = (j == first) ? 0 : j + 1;
  4519. }
  4520. }
  4521. else if (GET_CODE (x) == CONST_DOUBLE)
  4522. {
  4523. val = CONST_DOUBLE_LOW (x);
  4524. for (i = 15; i >= 8; i--)
  4525. {
  4526. arr[i] = val & 0xff;
  4527. val >>= 8;
  4528. }
  4529. val = CONST_DOUBLE_HIGH (x);
  4530. for (i = 7; i >= 0; i--)
  4531. {
  4532. arr[i] = val & 0xff;
  4533. val >>= 8;
  4534. }
  4535. }
  4536. else if (GET_CODE (x) == CONST_VECTOR)
  4537. {
  4538. int units;
  4539. rtx elt;
  4540. mode = GET_MODE_INNER (mode);
  4541. units = CONST_VECTOR_NUNITS (x);
  4542. for (i = 0; i < units; i++)
  4543. {
  4544. elt = CONST_VECTOR_ELT (x, i);
  4545. if (GET_CODE (elt) == CONST_INT || GET_CODE (elt) == CONST_DOUBLE)
  4546. {
  4547. if (GET_CODE (elt) == CONST_DOUBLE)
  4548. val = const_double_to_hwint (elt);
  4549. else
  4550. val = INTVAL (elt);
  4551. first = GET_MODE_SIZE (mode) - 1;
  4552. if (first + i * GET_MODE_SIZE (mode) > 16)
  4553. abort ();
  4554. for (j = first; j >= 0; j--)
  4555. {
  4556. arr[j + i * GET_MODE_SIZE (mode)] = val & 0xff;
  4557. val >>= 8;
  4558. }
  4559. }
  4560. }
  4561. }
  4562. else
  4563. gcc_unreachable();
  4564. }
  4565. /* Convert a 16 byte array to a constant of mode MODE. When MODE is
  4566. smaller than 16 bytes, use the bytes that would represent that value
  4567. in a register, e.g., for QImode return the value of arr[3]. */
  4568. rtx
  4569. array_to_constant (machine_mode mode, const unsigned char arr[16])
  4570. {
  4571. machine_mode inner_mode;
  4572. rtvec v;
  4573. int units, size, i, j, k;
  4574. HOST_WIDE_INT val;
  4575. if (GET_MODE_CLASS (mode) == MODE_INT
  4576. && GET_MODE_BITSIZE (mode) <= HOST_BITS_PER_WIDE_INT)
  4577. {
  4578. j = GET_MODE_SIZE (mode);
  4579. i = j < 4 ? 4 - j : 0;
  4580. for (val = 0; i < j; i++)
  4581. val = (val << 8) | arr[i];
  4582. val = trunc_int_for_mode (val, mode);
  4583. return GEN_INT (val);
  4584. }
  4585. if (mode == TImode)
  4586. {
  4587. HOST_WIDE_INT high;
  4588. for (i = high = 0; i < 8; i++)
  4589. high = (high << 8) | arr[i];
  4590. for (i = 8, val = 0; i < 16; i++)
  4591. val = (val << 8) | arr[i];
  4592. return immed_double_const (val, high, TImode);
  4593. }
  4594. if (mode == SFmode)
  4595. {
  4596. val = (arr[0] << 24) | (arr[1] << 16) | (arr[2] << 8) | arr[3];
  4597. val = trunc_int_for_mode (val, SImode);
  4598. return hwint_to_const_double (SFmode, val);
  4599. }
  4600. if (mode == DFmode)
  4601. {
  4602. for (i = 0, val = 0; i < 8; i++)
  4603. val = (val << 8) | arr[i];
  4604. return hwint_to_const_double (DFmode, val);
  4605. }
  4606. if (!VECTOR_MODE_P (mode))
  4607. abort ();
  4608. units = GET_MODE_NUNITS (mode);
  4609. size = GET_MODE_UNIT_SIZE (mode);
  4610. inner_mode = GET_MODE_INNER (mode);
  4611. v = rtvec_alloc (units);
  4612. for (k = i = 0; i < units; ++i)
  4613. {
  4614. val = 0;
  4615. for (j = 0; j < size; j++, k++)
  4616. val = (val << 8) | arr[k];
  4617. if (GET_MODE_CLASS (inner_mode) == MODE_FLOAT)
  4618. RTVEC_ELT (v, i) = hwint_to_const_double (inner_mode, val);
  4619. else
  4620. RTVEC_ELT (v, i) = GEN_INT (trunc_int_for_mode (val, inner_mode));
  4621. }
  4622. if (k > 16)
  4623. abort ();
  4624. return gen_rtx_CONST_VECTOR (mode, v);
  4625. }
  4626. static void
  4627. reloc_diagnostic (rtx x)
  4628. {
  4629. tree decl = 0;
  4630. if (!flag_pic || !(TARGET_WARN_RELOC || TARGET_ERROR_RELOC))
  4631. return;
  4632. if (GET_CODE (x) == SYMBOL_REF)
  4633. decl = SYMBOL_REF_DECL (x);
  4634. else if (GET_CODE (x) == CONST
  4635. && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
  4636. decl = SYMBOL_REF_DECL (XEXP (XEXP (x, 0), 0));
  4637. /* SYMBOL_REF_DECL is not necessarily a DECL. */
  4638. if (decl && !DECL_P (decl))
  4639. decl = 0;
  4640. /* The decl could be a string constant. */
  4641. if (decl && DECL_P (decl))
  4642. {
  4643. location_t loc;
  4644. /* We use last_assemble_variable_decl to get line information. It's
  4645. not always going to be right and might not even be close, but will
  4646. be right for the more common cases. */
  4647. if (!last_assemble_variable_decl || in_section == ctors_section)
  4648. loc = DECL_SOURCE_LOCATION (decl);
  4649. else
  4650. loc = DECL_SOURCE_LOCATION (last_assemble_variable_decl);
  4651. if (TARGET_WARN_RELOC)
  4652. warning_at (loc, 0,
  4653. "creating run-time relocation for %qD", decl);
  4654. else
  4655. error_at (loc,
  4656. "creating run-time relocation for %qD", decl);
  4657. }
  4658. else
  4659. {
  4660. if (TARGET_WARN_RELOC)
  4661. warning_at (input_location, 0, "creating run-time relocation");
  4662. else
  4663. error_at (input_location, "creating run-time relocation");
  4664. }
  4665. }
  4666. /* Hook into assemble_integer so we can generate an error for run-time
  4667. relocations. The SPU ABI disallows them. */
  4668. static bool
  4669. spu_assemble_integer (rtx x, unsigned int size, int aligned_p)
  4670. {
  4671. /* By default run-time relocations aren't supported, but we allow them
  4672. in case users support it in their own run-time loader. And we provide
  4673. a warning for those users that don't. */
  4674. if ((GET_CODE (x) == SYMBOL_REF)
  4675. || GET_CODE (x) == LABEL_REF || GET_CODE (x) == CONST)
  4676. reloc_diagnostic (x);
  4677. return default_assemble_integer (x, size, aligned_p);
  4678. }
  4679. static void
  4680. spu_asm_globalize_label (FILE * file, const char *name)
  4681. {
  4682. fputs ("\t.global\t", file);
  4683. assemble_name (file, name);
  4684. fputs ("\n", file);
  4685. }
  4686. static bool
  4687. spu_rtx_costs (rtx x, int code, int outer_code ATTRIBUTE_UNUSED,
  4688. int opno ATTRIBUTE_UNUSED, int *total,
  4689. bool speed ATTRIBUTE_UNUSED)
  4690. {
  4691. machine_mode mode = GET_MODE (x);
  4692. int cost = COSTS_N_INSNS (2);
  4693. /* Folding to a CONST_VECTOR will use extra space but there might
  4694. be only a small savings in cycles. We'd like to use a CONST_VECTOR
  4695. only if it allows us to fold away multiple insns. Changing the cost
  4696. of a CONST_VECTOR here (or in CONST_COSTS) doesn't help though
  4697. because this cost will only be compared against a single insn.
  4698. if (code == CONST_VECTOR)
  4699. return spu_legitimate_constant_p (mode, x) ? cost : COSTS_N_INSNS (6);
  4700. */
  4701. /* Use defaults for float operations. Not accurate but good enough. */
  4702. if (mode == DFmode)
  4703. {
  4704. *total = COSTS_N_INSNS (13);
  4705. return true;
  4706. }
  4707. if (mode == SFmode)
  4708. {
  4709. *total = COSTS_N_INSNS (6);
  4710. return true;
  4711. }
  4712. switch (code)
  4713. {
  4714. case CONST_INT:
  4715. if (satisfies_constraint_K (x))
  4716. *total = 0;
  4717. else if (INTVAL (x) >= -0x80000000ll && INTVAL (x) <= 0xffffffffll)
  4718. *total = COSTS_N_INSNS (1);
  4719. else
  4720. *total = COSTS_N_INSNS (3);
  4721. return true;
  4722. case CONST:
  4723. *total = COSTS_N_INSNS (3);
  4724. return true;
  4725. case LABEL_REF:
  4726. case SYMBOL_REF:
  4727. *total = COSTS_N_INSNS (0);
  4728. return true;
  4729. case CONST_DOUBLE:
  4730. *total = COSTS_N_INSNS (5);
  4731. return true;
  4732. case FLOAT_EXTEND:
  4733. case FLOAT_TRUNCATE:
  4734. case FLOAT:
  4735. case UNSIGNED_FLOAT:
  4736. case FIX:
  4737. case UNSIGNED_FIX:
  4738. *total = COSTS_N_INSNS (7);
  4739. return true;
  4740. case PLUS:
  4741. if (mode == TImode)
  4742. {
  4743. *total = COSTS_N_INSNS (9);
  4744. return true;
  4745. }
  4746. break;
  4747. case MULT:
  4748. cost =
  4749. GET_CODE (XEXP (x, 0)) ==
  4750. REG ? COSTS_N_INSNS (12) : COSTS_N_INSNS (7);
  4751. if (mode == SImode && GET_CODE (XEXP (x, 0)) == REG)
  4752. {
  4753. if (GET_CODE (XEXP (x, 1)) == CONST_INT)
  4754. {
  4755. HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
  4756. cost = COSTS_N_INSNS (14);
  4757. if ((val & 0xffff) == 0)
  4758. cost = COSTS_N_INSNS (9);
  4759. else if (val > 0 && val < 0x10000)
  4760. cost = COSTS_N_INSNS (11);
  4761. }
  4762. }
  4763. *total = cost;
  4764. return true;
  4765. case DIV:
  4766. case UDIV:
  4767. case MOD:
  4768. case UMOD:
  4769. *total = COSTS_N_INSNS (20);
  4770. return true;
  4771. case ROTATE:
  4772. case ROTATERT:
  4773. case ASHIFT:
  4774. case ASHIFTRT:
  4775. case LSHIFTRT:
  4776. *total = COSTS_N_INSNS (4);
  4777. return true;
  4778. case UNSPEC:
  4779. if (XINT (x, 1) == UNSPEC_CONVERT)
  4780. *total = COSTS_N_INSNS (0);
  4781. else
  4782. *total = COSTS_N_INSNS (4);
  4783. return true;
  4784. }
  4785. /* Scale cost by mode size. Except when initializing (cfun->decl == 0). */
  4786. if (GET_MODE_CLASS (mode) == MODE_INT
  4787. && GET_MODE_SIZE (mode) > GET_MODE_SIZE (SImode) && cfun && cfun->decl)
  4788. cost = cost * (GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode))
  4789. * (GET_MODE_SIZE (mode) / GET_MODE_SIZE (SImode));
  4790. *total = cost;
  4791. return true;
  4792. }
  4793. static machine_mode
  4794. spu_unwind_word_mode (void)
  4795. {
  4796. return SImode;
  4797. }
  4798. /* Decide whether we can make a sibling call to a function. DECL is the
  4799. declaration of the function being targeted by the call and EXP is the
  4800. CALL_EXPR representing the call. */
  4801. static bool
  4802. spu_function_ok_for_sibcall (tree decl, tree exp ATTRIBUTE_UNUSED)
  4803. {
  4804. return decl && !TARGET_LARGE_MEM;
  4805. }
  4806. /* We need to correctly update the back chain pointer and the Available
  4807. Stack Size (which is in the second slot of the sp register.) */
  4808. void
  4809. spu_allocate_stack (rtx op0, rtx op1)
  4810. {
  4811. HOST_WIDE_INT v;
  4812. rtx chain = gen_reg_rtx (V4SImode);
  4813. rtx stack_bot = gen_frame_mem (V4SImode, stack_pointer_rtx);
  4814. rtx sp = gen_reg_rtx (V4SImode);
  4815. rtx splatted = gen_reg_rtx (V4SImode);
  4816. rtx pat = gen_reg_rtx (TImode);
  4817. /* copy the back chain so we can save it back again. */
  4818. emit_move_insn (chain, stack_bot);
  4819. op1 = force_reg (SImode, op1);
  4820. v = 0x1020300010203ll;
  4821. emit_move_insn (pat, immed_double_const (v, v, TImode));
  4822. emit_insn (gen_shufb (splatted, op1, op1, pat));
  4823. emit_insn (gen_spu_convert (sp, stack_pointer_rtx));
  4824. emit_insn (gen_subv4si3 (sp, sp, splatted));
  4825. if (flag_stack_check)
  4826. {
  4827. rtx avail = gen_reg_rtx(SImode);
  4828. rtx result = gen_reg_rtx(SImode);
  4829. emit_insn (gen_vec_extractv4si (avail, sp, GEN_INT (1)));
  4830. emit_insn (gen_cgt_si(result, avail, GEN_INT (-1)));
  4831. emit_insn (gen_spu_heq (result, GEN_INT(0) ));
  4832. }
  4833. emit_insn (gen_spu_convert (stack_pointer_rtx, sp));
  4834. emit_move_insn (stack_bot, chain);
  4835. emit_move_insn (op0, virtual_stack_dynamic_rtx);
  4836. }
  4837. void
  4838. spu_restore_stack_nonlocal (rtx op0 ATTRIBUTE_UNUSED, rtx op1)
  4839. {
  4840. static unsigned char arr[16] =
  4841. { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
  4842. rtx temp = gen_reg_rtx (SImode);
  4843. rtx temp2 = gen_reg_rtx (SImode);
  4844. rtx temp3 = gen_reg_rtx (V4SImode);
  4845. rtx temp4 = gen_reg_rtx (V4SImode);
  4846. rtx pat = gen_reg_rtx (TImode);
  4847. rtx sp = gen_rtx_REG (V4SImode, STACK_POINTER_REGNUM);
  4848. /* Restore the backchain from the first word, sp from the second. */
  4849. emit_move_insn (temp2, adjust_address_nv (op1, SImode, 0));
  4850. emit_move_insn (temp, adjust_address_nv (op1, SImode, 4));
  4851. emit_move_insn (pat, array_to_constant (TImode, arr));
  4852. /* Compute Available Stack Size for sp */
  4853. emit_insn (gen_subsi3 (temp, temp, stack_pointer_rtx));
  4854. emit_insn (gen_shufb (temp3, temp, temp, pat));
  4855. /* Compute Available Stack Size for back chain */
  4856. emit_insn (gen_subsi3 (temp2, temp2, stack_pointer_rtx));
  4857. emit_insn (gen_shufb (temp4, temp2, temp2, pat));
  4858. emit_insn (gen_addv4si3 (temp4, sp, temp4));
  4859. emit_insn (gen_addv4si3 (sp, sp, temp3));
  4860. emit_move_insn (gen_frame_mem (V4SImode, stack_pointer_rtx), temp4);
  4861. }
  4862. static void
  4863. spu_init_libfuncs (void)
  4864. {
  4865. set_optab_libfunc (smul_optab, DImode, "__muldi3");
  4866. set_optab_libfunc (sdiv_optab, DImode, "__divdi3");
  4867. set_optab_libfunc (smod_optab, DImode, "__moddi3");
  4868. set_optab_libfunc (udiv_optab, DImode, "__udivdi3");
  4869. set_optab_libfunc (umod_optab, DImode, "__umoddi3");
  4870. set_optab_libfunc (udivmod_optab, DImode, "__udivmoddi4");
  4871. set_optab_libfunc (ffs_optab, DImode, "__ffsdi2");
  4872. set_optab_libfunc (clz_optab, DImode, "__clzdi2");
  4873. set_optab_libfunc (ctz_optab, DImode, "__ctzdi2");
  4874. set_optab_libfunc (clrsb_optab, DImode, "__clrsbdi2");
  4875. set_optab_libfunc (popcount_optab, DImode, "__popcountdi2");
  4876. set_optab_libfunc (parity_optab, DImode, "__paritydi2");
  4877. set_conv_libfunc (ufloat_optab, DFmode, SImode, "__float_unssidf");
  4878. set_conv_libfunc (ufloat_optab, DFmode, DImode, "__float_unsdidf");
  4879. set_optab_libfunc (addv_optab, SImode, "__addvsi3");
  4880. set_optab_libfunc (subv_optab, SImode, "__subvsi3");
  4881. set_optab_libfunc (smulv_optab, SImode, "__mulvsi3");
  4882. set_optab_libfunc (sdivv_optab, SImode, "__divvsi3");
  4883. set_optab_libfunc (negv_optab, SImode, "__negvsi2");
  4884. set_optab_libfunc (absv_optab, SImode, "__absvsi2");
  4885. set_optab_libfunc (addv_optab, DImode, "__addvdi3");
  4886. set_optab_libfunc (subv_optab, DImode, "__subvdi3");
  4887. set_optab_libfunc (smulv_optab, DImode, "__mulvdi3");
  4888. set_optab_libfunc (sdivv_optab, DImode, "__divvdi3");
  4889. set_optab_libfunc (negv_optab, DImode, "__negvdi2");
  4890. set_optab_libfunc (absv_optab, DImode, "__absvdi2");
  4891. set_optab_libfunc (smul_optab, TImode, "__multi3");
  4892. set_optab_libfunc (sdiv_optab, TImode, "__divti3");
  4893. set_optab_libfunc (smod_optab, TImode, "__modti3");
  4894. set_optab_libfunc (udiv_optab, TImode, "__udivti3");
  4895. set_optab_libfunc (umod_optab, TImode, "__umodti3");
  4896. set_optab_libfunc (udivmod_optab, TImode, "__udivmodti4");
  4897. }
  4898. /* Make a subreg, stripping any existing subreg. We could possibly just
  4899. call simplify_subreg, but in this case we know what we want. */
  4900. rtx
  4901. spu_gen_subreg (machine_mode mode, rtx x)
  4902. {
  4903. if (GET_CODE (x) == SUBREG)
  4904. x = SUBREG_REG (x);
  4905. if (GET_MODE (x) == mode)
  4906. return x;
  4907. return gen_rtx_SUBREG (mode, x, 0);
  4908. }
  4909. static bool
  4910. spu_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
  4911. {
  4912. return (TYPE_MODE (type) == BLKmode
  4913. && ((type) == 0
  4914. || TREE_CODE (TYPE_SIZE (type)) != INTEGER_CST
  4915. || int_size_in_bytes (type) >
  4916. (MAX_REGISTER_RETURN * UNITS_PER_WORD)));
  4917. }
  4918. /* Create the built-in types and functions */
  4919. enum spu_function_code
  4920. {
  4921. #define DEF_BUILTIN(fcode, icode, name, type, params) fcode,
  4922. #include "spu-builtins.def"
  4923. #undef DEF_BUILTIN
  4924. NUM_SPU_BUILTINS
  4925. };
  4926. extern GTY(()) struct spu_builtin_description spu_builtins[NUM_SPU_BUILTINS];
  4927. struct spu_builtin_description spu_builtins[] = {
  4928. #define DEF_BUILTIN(fcode, icode, name, type, params) \
  4929. {fcode, icode, name, type, params},
  4930. #include "spu-builtins.def"
  4931. #undef DEF_BUILTIN
  4932. };
  4933. static GTY(()) tree spu_builtin_decls[NUM_SPU_BUILTINS];
  4934. /* Returns the spu builtin decl for CODE. */
  4935. static tree
  4936. spu_builtin_decl (unsigned code, bool initialize_p ATTRIBUTE_UNUSED)
  4937. {
  4938. if (code >= NUM_SPU_BUILTINS)
  4939. return error_mark_node;
  4940. return spu_builtin_decls[code];
  4941. }
  4942. static void
  4943. spu_init_builtins (void)
  4944. {
  4945. struct spu_builtin_description *d;
  4946. unsigned int i;
  4947. V16QI_type_node = build_vector_type (intQI_type_node, 16);
  4948. V8HI_type_node = build_vector_type (intHI_type_node, 8);
  4949. V4SI_type_node = build_vector_type (intSI_type_node, 4);
  4950. V2DI_type_node = build_vector_type (intDI_type_node, 2);
  4951. V4SF_type_node = build_vector_type (float_type_node, 4);
  4952. V2DF_type_node = build_vector_type (double_type_node, 2);
  4953. unsigned_V16QI_type_node = build_vector_type (unsigned_intQI_type_node, 16);
  4954. unsigned_V8HI_type_node = build_vector_type (unsigned_intHI_type_node, 8);
  4955. unsigned_V4SI_type_node = build_vector_type (unsigned_intSI_type_node, 4);
  4956. unsigned_V2DI_type_node = build_vector_type (unsigned_intDI_type_node, 2);
  4957. spu_builtin_types[SPU_BTI_QUADWORD] = V16QI_type_node;
  4958. spu_builtin_types[SPU_BTI_7] = global_trees[TI_INTSI_TYPE];
  4959. spu_builtin_types[SPU_BTI_S7] = global_trees[TI_INTSI_TYPE];
  4960. spu_builtin_types[SPU_BTI_U7] = global_trees[TI_INTSI_TYPE];
  4961. spu_builtin_types[SPU_BTI_S10] = global_trees[TI_INTSI_TYPE];
  4962. spu_builtin_types[SPU_BTI_S10_4] = global_trees[TI_INTSI_TYPE];
  4963. spu_builtin_types[SPU_BTI_U14] = global_trees[TI_INTSI_TYPE];
  4964. spu_builtin_types[SPU_BTI_16] = global_trees[TI_INTSI_TYPE];
  4965. spu_builtin_types[SPU_BTI_S16] = global_trees[TI_INTSI_TYPE];
  4966. spu_builtin_types[SPU_BTI_S16_2] = global_trees[TI_INTSI_TYPE];
  4967. spu_builtin_types[SPU_BTI_U16] = global_trees[TI_INTSI_TYPE];
  4968. spu_builtin_types[SPU_BTI_U16_2] = global_trees[TI_INTSI_TYPE];
  4969. spu_builtin_types[SPU_BTI_U18] = global_trees[TI_INTSI_TYPE];
  4970. spu_builtin_types[SPU_BTI_INTQI] = global_trees[TI_INTQI_TYPE];
  4971. spu_builtin_types[SPU_BTI_INTHI] = global_trees[TI_INTHI_TYPE];
  4972. spu_builtin_types[SPU_BTI_INTSI] = global_trees[TI_INTSI_TYPE];
  4973. spu_builtin_types[SPU_BTI_INTDI] = global_trees[TI_INTDI_TYPE];
  4974. spu_builtin_types[SPU_BTI_UINTQI] = global_trees[TI_UINTQI_TYPE];
  4975. spu_builtin_types[SPU_BTI_UINTHI] = global_trees[TI_UINTHI_TYPE];
  4976. spu_builtin_types[SPU_BTI_UINTSI] = global_trees[TI_UINTSI_TYPE];
  4977. spu_builtin_types[SPU_BTI_UINTDI] = global_trees[TI_UINTDI_TYPE];
  4978. spu_builtin_types[SPU_BTI_FLOAT] = global_trees[TI_FLOAT_TYPE];
  4979. spu_builtin_types[SPU_BTI_DOUBLE] = global_trees[TI_DOUBLE_TYPE];
  4980. spu_builtin_types[SPU_BTI_VOID] = global_trees[TI_VOID_TYPE];
  4981. spu_builtin_types[SPU_BTI_PTR] =
  4982. build_pointer_type (build_qualified_type
  4983. (void_type_node,
  4984. TYPE_QUAL_CONST | TYPE_QUAL_VOLATILE));
  4985. /* For each builtin we build a new prototype. The tree code will make
  4986. sure nodes are shared. */
  4987. for (i = 0, d = spu_builtins; i < NUM_SPU_BUILTINS; i++, d++)
  4988. {
  4989. tree p;
  4990. char name[64]; /* build_function will make a copy. */
  4991. int parm;
  4992. if (d->name == 0)
  4993. continue;
  4994. /* Find last parm. */
  4995. for (parm = 1; d->parm[parm] != SPU_BTI_END_OF_PARAMS; parm++)
  4996. ;
  4997. p = void_list_node;
  4998. while (parm > 1)
  4999. p = tree_cons (NULL_TREE, spu_builtin_types[d->parm[--parm]], p);
  5000. p = build_function_type (spu_builtin_types[d->parm[0]], p);
  5001. sprintf (name, "__builtin_%s", d->name);
  5002. spu_builtin_decls[i] =
  5003. add_builtin_function (name, p, i, BUILT_IN_MD, NULL, NULL_TREE);
  5004. if (d->fcode == SPU_MASK_FOR_LOAD)
  5005. TREE_READONLY (spu_builtin_decls[i]) = 1;
  5006. /* These builtins don't throw. */
  5007. TREE_NOTHROW (spu_builtin_decls[i]) = 1;
  5008. }
  5009. }
  5010. void
  5011. spu_restore_stack_block (rtx op0 ATTRIBUTE_UNUSED, rtx op1)
  5012. {
  5013. static unsigned char arr[16] =
  5014. { 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3 };
  5015. rtx temp = gen_reg_rtx (Pmode);
  5016. rtx temp2 = gen_reg_rtx (V4SImode);
  5017. rtx temp3 = gen_reg_rtx (V4SImode);
  5018. rtx pat = gen_reg_rtx (TImode);
  5019. rtx sp = gen_rtx_REG (V4SImode, STACK_POINTER_REGNUM);
  5020. emit_move_insn (pat, array_to_constant (TImode, arr));
  5021. /* Restore the sp. */
  5022. emit_move_insn (temp, op1);
  5023. emit_move_insn (temp2, gen_frame_mem (V4SImode, stack_pointer_rtx));
  5024. /* Compute available stack size for sp. */
  5025. emit_insn (gen_subsi3 (temp, temp, stack_pointer_rtx));
  5026. emit_insn (gen_shufb (temp3, temp, temp, pat));
  5027. emit_insn (gen_addv4si3 (sp, sp, temp3));
  5028. emit_move_insn (gen_frame_mem (V4SImode, stack_pointer_rtx), temp2);
  5029. }
  5030. int
  5031. spu_safe_dma (HOST_WIDE_INT channel)
  5032. {
  5033. return TARGET_SAFE_DMA && channel >= 21 && channel <= 27;
  5034. }
  5035. void
  5036. spu_builtin_splats (rtx ops[])
  5037. {
  5038. machine_mode mode = GET_MODE (ops[0]);
  5039. if (GET_CODE (ops[1]) == CONST_INT || GET_CODE (ops[1]) == CONST_DOUBLE)
  5040. {
  5041. unsigned char arr[16];
  5042. constant_to_array (GET_MODE_INNER (mode), ops[1], arr);
  5043. emit_move_insn (ops[0], array_to_constant (mode, arr));
  5044. }
  5045. else
  5046. {
  5047. rtx reg = gen_reg_rtx (TImode);
  5048. rtx shuf;
  5049. if (GET_CODE (ops[1]) != REG
  5050. && GET_CODE (ops[1]) != SUBREG)
  5051. ops[1] = force_reg (GET_MODE_INNER (mode), ops[1]);
  5052. switch (mode)
  5053. {
  5054. case V2DImode:
  5055. case V2DFmode:
  5056. shuf =
  5057. immed_double_const (0x0001020304050607ll, 0x1011121314151617ll,
  5058. TImode);
  5059. break;
  5060. case V4SImode:
  5061. case V4SFmode:
  5062. shuf =
  5063. immed_double_const (0x0001020300010203ll, 0x0001020300010203ll,
  5064. TImode);
  5065. break;
  5066. case V8HImode:
  5067. shuf =
  5068. immed_double_const (0x0203020302030203ll, 0x0203020302030203ll,
  5069. TImode);
  5070. break;
  5071. case V16QImode:
  5072. shuf =
  5073. immed_double_const (0x0303030303030303ll, 0x0303030303030303ll,
  5074. TImode);
  5075. break;
  5076. default:
  5077. abort ();
  5078. }
  5079. emit_move_insn (reg, shuf);
  5080. emit_insn (gen_shufb (ops[0], ops[1], ops[1], reg));
  5081. }
  5082. }
  5083. void
  5084. spu_builtin_extract (rtx ops[])
  5085. {
  5086. machine_mode mode;
  5087. rtx rot, from, tmp;
  5088. mode = GET_MODE (ops[1]);
  5089. if (GET_CODE (ops[2]) == CONST_INT)
  5090. {
  5091. switch (mode)
  5092. {
  5093. case V16QImode:
  5094. emit_insn (gen_vec_extractv16qi (ops[0], ops[1], ops[2]));
  5095. break;
  5096. case V8HImode:
  5097. emit_insn (gen_vec_extractv8hi (ops[0], ops[1], ops[2]));
  5098. break;
  5099. case V4SFmode:
  5100. emit_insn (gen_vec_extractv4sf (ops[0], ops[1], ops[2]));
  5101. break;
  5102. case V4SImode:
  5103. emit_insn (gen_vec_extractv4si (ops[0], ops[1], ops[2]));
  5104. break;
  5105. case V2DImode:
  5106. emit_insn (gen_vec_extractv2di (ops[0], ops[1], ops[2]));
  5107. break;
  5108. case V2DFmode:
  5109. emit_insn (gen_vec_extractv2df (ops[0], ops[1], ops[2]));
  5110. break;
  5111. default:
  5112. abort ();
  5113. }
  5114. return;
  5115. }
  5116. from = spu_gen_subreg (TImode, ops[1]);
  5117. rot = gen_reg_rtx (TImode);
  5118. tmp = gen_reg_rtx (SImode);
  5119. switch (mode)
  5120. {
  5121. case V16QImode:
  5122. emit_insn (gen_addsi3 (tmp, ops[2], GEN_INT (-3)));
  5123. break;
  5124. case V8HImode:
  5125. emit_insn (gen_addsi3 (tmp, ops[2], ops[2]));
  5126. emit_insn (gen_addsi3 (tmp, tmp, GEN_INT (-2)));
  5127. break;
  5128. case V4SFmode:
  5129. case V4SImode:
  5130. emit_insn (gen_ashlsi3 (tmp, ops[2], GEN_INT (2)));
  5131. break;
  5132. case V2DImode:
  5133. case V2DFmode:
  5134. emit_insn (gen_ashlsi3 (tmp, ops[2], GEN_INT (3)));
  5135. break;
  5136. default:
  5137. abort ();
  5138. }
  5139. emit_insn (gen_rotqby_ti (rot, from, tmp));
  5140. emit_insn (gen_spu_convert (ops[0], rot));
  5141. }
  5142. void
  5143. spu_builtin_insert (rtx ops[])
  5144. {
  5145. machine_mode mode = GET_MODE (ops[0]);
  5146. machine_mode imode = GET_MODE_INNER (mode);
  5147. rtx mask = gen_reg_rtx (TImode);
  5148. rtx offset;
  5149. if (GET_CODE (ops[3]) == CONST_INT)
  5150. offset = GEN_INT (INTVAL (ops[3]) * GET_MODE_SIZE (imode));
  5151. else
  5152. {
  5153. offset = gen_reg_rtx (SImode);
  5154. emit_insn (gen_mulsi3
  5155. (offset, ops[3], GEN_INT (GET_MODE_SIZE (imode))));
  5156. }
  5157. emit_insn (gen_cpat
  5158. (mask, stack_pointer_rtx, offset,
  5159. GEN_INT (GET_MODE_SIZE (imode))));
  5160. emit_insn (gen_shufb (ops[0], ops[1], ops[2], mask));
  5161. }
  5162. void
  5163. spu_builtin_promote (rtx ops[])
  5164. {
  5165. machine_mode mode, imode;
  5166. rtx rot, from, offset;
  5167. HOST_WIDE_INT pos;
  5168. mode = GET_MODE (ops[0]);
  5169. imode = GET_MODE_INNER (mode);
  5170. from = gen_reg_rtx (TImode);
  5171. rot = spu_gen_subreg (TImode, ops[0]);
  5172. emit_insn (gen_spu_convert (from, ops[1]));
  5173. if (GET_CODE (ops[2]) == CONST_INT)
  5174. {
  5175. pos = -GET_MODE_SIZE (imode) * INTVAL (ops[2]);
  5176. if (GET_MODE_SIZE (imode) < 4)
  5177. pos += 4 - GET_MODE_SIZE (imode);
  5178. offset = GEN_INT (pos & 15);
  5179. }
  5180. else
  5181. {
  5182. offset = gen_reg_rtx (SImode);
  5183. switch (mode)
  5184. {
  5185. case V16QImode:
  5186. emit_insn (gen_subsi3 (offset, GEN_INT (3), ops[2]));
  5187. break;
  5188. case V8HImode:
  5189. emit_insn (gen_subsi3 (offset, GEN_INT (1), ops[2]));
  5190. emit_insn (gen_addsi3 (offset, offset, offset));
  5191. break;
  5192. case V4SFmode:
  5193. case V4SImode:
  5194. emit_insn (gen_subsi3 (offset, GEN_INT (0), ops[2]));
  5195. emit_insn (gen_ashlsi3 (offset, offset, GEN_INT (2)));
  5196. break;
  5197. case V2DImode:
  5198. case V2DFmode:
  5199. emit_insn (gen_ashlsi3 (offset, ops[2], GEN_INT (3)));
  5200. break;
  5201. default:
  5202. abort ();
  5203. }
  5204. }
  5205. emit_insn (gen_rotqby_ti (rot, from, offset));
  5206. }
  5207. static void
  5208. spu_trampoline_init (rtx m_tramp, tree fndecl, rtx cxt)
  5209. {
  5210. rtx fnaddr = XEXP (DECL_RTL (fndecl), 0);
  5211. rtx shuf = gen_reg_rtx (V4SImode);
  5212. rtx insn = gen_reg_rtx (V4SImode);
  5213. rtx shufc;
  5214. rtx insnc;
  5215. rtx mem;
  5216. fnaddr = force_reg (SImode, fnaddr);
  5217. cxt = force_reg (SImode, cxt);
  5218. if (TARGET_LARGE_MEM)
  5219. {
  5220. rtx rotl = gen_reg_rtx (V4SImode);
  5221. rtx mask = gen_reg_rtx (V4SImode);
  5222. rtx bi = gen_reg_rtx (SImode);
  5223. static unsigned char const shufa[16] = {
  5224. 2, 3, 0, 1, 18, 19, 16, 17,
  5225. 0, 1, 2, 3, 16, 17, 18, 19
  5226. };
  5227. static unsigned char const insna[16] = {
  5228. 0x41, 0, 0, 79,
  5229. 0x41, 0, 0, STATIC_CHAIN_REGNUM,
  5230. 0x60, 0x80, 0, 79,
  5231. 0x60, 0x80, 0, STATIC_CHAIN_REGNUM
  5232. };
  5233. shufc = force_reg (TImode, array_to_constant (TImode, shufa));
  5234. insnc = force_reg (V4SImode, array_to_constant (V4SImode, insna));
  5235. emit_insn (gen_shufb (shuf, fnaddr, cxt, shufc));
  5236. emit_insn (gen_vrotlv4si3 (rotl, shuf, spu_const (V4SImode, 7)));
  5237. emit_insn (gen_movv4si (mask, spu_const (V4SImode, 0xffff << 7)));
  5238. emit_insn (gen_selb (insn, insnc, rotl, mask));
  5239. mem = adjust_address (m_tramp, V4SImode, 0);
  5240. emit_move_insn (mem, insn);
  5241. emit_move_insn (bi, GEN_INT (0x35000000 + (79 << 7)));
  5242. mem = adjust_address (m_tramp, Pmode, 16);
  5243. emit_move_insn (mem, bi);
  5244. }
  5245. else
  5246. {
  5247. rtx scxt = gen_reg_rtx (SImode);
  5248. rtx sfnaddr = gen_reg_rtx (SImode);
  5249. static unsigned char const insna[16] = {
  5250. 0x42, 0, 0, STATIC_CHAIN_REGNUM,
  5251. 0x30, 0, 0, 0,
  5252. 0, 0, 0, 0,
  5253. 0, 0, 0, 0
  5254. };
  5255. shufc = gen_reg_rtx (TImode);
  5256. insnc = force_reg (V4SImode, array_to_constant (V4SImode, insna));
  5257. /* By or'ing all of cxt with the ila opcode we are assuming cxt
  5258. fits 18 bits and the last 4 are zeros. This will be true if
  5259. the stack pointer is initialized to 0x3fff0 at program start,
  5260. otherwise the ila instruction will be garbage. */
  5261. emit_insn (gen_ashlsi3 (scxt, cxt, GEN_INT (7)));
  5262. emit_insn (gen_ashlsi3 (sfnaddr, fnaddr, GEN_INT (5)));
  5263. emit_insn (gen_cpat
  5264. (shufc, stack_pointer_rtx, GEN_INT (4), GEN_INT (4)));
  5265. emit_insn (gen_shufb (shuf, sfnaddr, scxt, shufc));
  5266. emit_insn (gen_iorv4si3 (insn, insnc, shuf));
  5267. mem = adjust_address (m_tramp, V4SImode, 0);
  5268. emit_move_insn (mem, insn);
  5269. }
  5270. emit_insn (gen_sync ());
  5271. }
  5272. static bool
  5273. spu_warn_func_return (tree decl)
  5274. {
  5275. /* Naked functions are implemented entirely in assembly, including the
  5276. return sequence, so suppress warnings about this. */
  5277. return !spu_naked_function_p (decl);
  5278. }
  5279. void
  5280. spu_expand_sign_extend (rtx ops[])
  5281. {
  5282. unsigned char arr[16];
  5283. rtx pat = gen_reg_rtx (TImode);
  5284. rtx sign, c;
  5285. int i, last;
  5286. last = GET_MODE (ops[0]) == DImode ? 7 : 15;
  5287. if (GET_MODE (ops[1]) == QImode)
  5288. {
  5289. sign = gen_reg_rtx (HImode);
  5290. emit_insn (gen_extendqihi2 (sign, ops[1]));
  5291. for (i = 0; i < 16; i++)
  5292. arr[i] = 0x12;
  5293. arr[last] = 0x13;
  5294. }
  5295. else
  5296. {
  5297. for (i = 0; i < 16; i++)
  5298. arr[i] = 0x10;
  5299. switch (GET_MODE (ops[1]))
  5300. {
  5301. case HImode:
  5302. sign = gen_reg_rtx (SImode);
  5303. emit_insn (gen_extendhisi2 (sign, ops[1]));
  5304. arr[last] = 0x03;
  5305. arr[last - 1] = 0x02;
  5306. break;
  5307. case SImode:
  5308. sign = gen_reg_rtx (SImode);
  5309. emit_insn (gen_ashrsi3 (sign, ops[1], GEN_INT (31)));
  5310. for (i = 0; i < 4; i++)
  5311. arr[last - i] = 3 - i;
  5312. break;
  5313. case DImode:
  5314. sign = gen_reg_rtx (SImode);
  5315. c = gen_reg_rtx (SImode);
  5316. emit_insn (gen_spu_convert (c, ops[1]));
  5317. emit_insn (gen_ashrsi3 (sign, c, GEN_INT (31)));
  5318. for (i = 0; i < 8; i++)
  5319. arr[last - i] = 7 - i;
  5320. break;
  5321. default:
  5322. abort ();
  5323. }
  5324. }
  5325. emit_move_insn (pat, array_to_constant (TImode, arr));
  5326. emit_insn (gen_shufb (ops[0], ops[1], sign, pat));
  5327. }
  5328. /* expand vector initialization. If there are any constant parts,
  5329. load constant parts first. Then load any non-constant parts. */
  5330. void
  5331. spu_expand_vector_init (rtx target, rtx vals)
  5332. {
  5333. machine_mode mode = GET_MODE (target);
  5334. int n_elts = GET_MODE_NUNITS (mode);
  5335. int n_var = 0;
  5336. bool all_same = true;
  5337. rtx first, x = NULL_RTX, first_constant = NULL_RTX;
  5338. int i;
  5339. first = XVECEXP (vals, 0, 0);
  5340. for (i = 0; i < n_elts; ++i)
  5341. {
  5342. x = XVECEXP (vals, 0, i);
  5343. if (!(CONST_INT_P (x)
  5344. || GET_CODE (x) == CONST_DOUBLE
  5345. || GET_CODE (x) == CONST_FIXED))
  5346. ++n_var;
  5347. else
  5348. {
  5349. if (first_constant == NULL_RTX)
  5350. first_constant = x;
  5351. }
  5352. if (i > 0 && !rtx_equal_p (x, first))
  5353. all_same = false;
  5354. }
  5355. /* if all elements are the same, use splats to repeat elements */
  5356. if (all_same)
  5357. {
  5358. if (!CONSTANT_P (first)
  5359. && !register_operand (first, GET_MODE (x)))
  5360. first = force_reg (GET_MODE (first), first);
  5361. emit_insn (gen_spu_splats (target, first));
  5362. return;
  5363. }
  5364. /* load constant parts */
  5365. if (n_var != n_elts)
  5366. {
  5367. if (n_var == 0)
  5368. {
  5369. emit_move_insn (target,
  5370. gen_rtx_CONST_VECTOR (mode, XVEC (vals, 0)));
  5371. }
  5372. else
  5373. {
  5374. rtx constant_parts_rtx = copy_rtx (vals);
  5375. gcc_assert (first_constant != NULL_RTX);
  5376. /* fill empty slots with the first constant, this increases
  5377. our chance of using splats in the recursive call below. */
  5378. for (i = 0; i < n_elts; ++i)
  5379. {
  5380. x = XVECEXP (constant_parts_rtx, 0, i);
  5381. if (!(CONST_INT_P (x)
  5382. || GET_CODE (x) == CONST_DOUBLE
  5383. || GET_CODE (x) == CONST_FIXED))
  5384. XVECEXP (constant_parts_rtx, 0, i) = first_constant;
  5385. }
  5386. spu_expand_vector_init (target, constant_parts_rtx);
  5387. }
  5388. }
  5389. /* load variable parts */
  5390. if (n_var != 0)
  5391. {
  5392. rtx insert_operands[4];
  5393. insert_operands[0] = target;
  5394. insert_operands[2] = target;
  5395. for (i = 0; i < n_elts; ++i)
  5396. {
  5397. x = XVECEXP (vals, 0, i);
  5398. if (!(CONST_INT_P (x)
  5399. || GET_CODE (x) == CONST_DOUBLE
  5400. || GET_CODE (x) == CONST_FIXED))
  5401. {
  5402. if (!register_operand (x, GET_MODE (x)))
  5403. x = force_reg (GET_MODE (x), x);
  5404. insert_operands[1] = x;
  5405. insert_operands[3] = GEN_INT (i);
  5406. spu_builtin_insert (insert_operands);
  5407. }
  5408. }
  5409. }
  5410. }
  5411. /* Return insn index for the vector compare instruction for given CODE,
  5412. and DEST_MODE, OP_MODE. Return -1 if valid insn is not available. */
  5413. static int
  5414. get_vec_cmp_insn (enum rtx_code code,
  5415. machine_mode dest_mode,
  5416. machine_mode op_mode)
  5417. {
  5418. switch (code)
  5419. {
  5420. case EQ:
  5421. if (dest_mode == V16QImode && op_mode == V16QImode)
  5422. return CODE_FOR_ceq_v16qi;
  5423. if (dest_mode == V8HImode && op_mode == V8HImode)
  5424. return CODE_FOR_ceq_v8hi;
  5425. if (dest_mode == V4SImode && op_mode == V4SImode)
  5426. return CODE_FOR_ceq_v4si;
  5427. if (dest_mode == V4SImode && op_mode == V4SFmode)
  5428. return CODE_FOR_ceq_v4sf;
  5429. if (dest_mode == V2DImode && op_mode == V2DFmode)
  5430. return CODE_FOR_ceq_v2df;
  5431. break;
  5432. case GT:
  5433. if (dest_mode == V16QImode && op_mode == V16QImode)
  5434. return CODE_FOR_cgt_v16qi;
  5435. if (dest_mode == V8HImode && op_mode == V8HImode)
  5436. return CODE_FOR_cgt_v8hi;
  5437. if (dest_mode == V4SImode && op_mode == V4SImode)
  5438. return CODE_FOR_cgt_v4si;
  5439. if (dest_mode == V4SImode && op_mode == V4SFmode)
  5440. return CODE_FOR_cgt_v4sf;
  5441. if (dest_mode == V2DImode && op_mode == V2DFmode)
  5442. return CODE_FOR_cgt_v2df;
  5443. break;
  5444. case GTU:
  5445. if (dest_mode == V16QImode && op_mode == V16QImode)
  5446. return CODE_FOR_clgt_v16qi;
  5447. if (dest_mode == V8HImode && op_mode == V8HImode)
  5448. return CODE_FOR_clgt_v8hi;
  5449. if (dest_mode == V4SImode && op_mode == V4SImode)
  5450. return CODE_FOR_clgt_v4si;
  5451. break;
  5452. default:
  5453. break;
  5454. }
  5455. return -1;
  5456. }
  5457. /* Emit vector compare for operands OP0 and OP1 using code RCODE.
  5458. DMODE is expected destination mode. This is a recursive function. */
  5459. static rtx
  5460. spu_emit_vector_compare (enum rtx_code rcode,
  5461. rtx op0, rtx op1,
  5462. machine_mode dmode)
  5463. {
  5464. int vec_cmp_insn;
  5465. rtx mask;
  5466. machine_mode dest_mode;
  5467. machine_mode op_mode = GET_MODE (op1);
  5468. gcc_assert (GET_MODE (op0) == GET_MODE (op1));
  5469. /* Floating point vector compare instructions uses destination V4SImode.
  5470. Double floating point vector compare instructions uses destination V2DImode.
  5471. Move destination to appropriate mode later. */
  5472. if (dmode == V4SFmode)
  5473. dest_mode = V4SImode;
  5474. else if (dmode == V2DFmode)
  5475. dest_mode = V2DImode;
  5476. else
  5477. dest_mode = dmode;
  5478. mask = gen_reg_rtx (dest_mode);
  5479. vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
  5480. if (vec_cmp_insn == -1)
  5481. {
  5482. bool swap_operands = false;
  5483. bool try_again = false;
  5484. switch (rcode)
  5485. {
  5486. case LT:
  5487. rcode = GT;
  5488. swap_operands = true;
  5489. try_again = true;
  5490. break;
  5491. case LTU:
  5492. rcode = GTU;
  5493. swap_operands = true;
  5494. try_again = true;
  5495. break;
  5496. case NE:
  5497. case UNEQ:
  5498. case UNLE:
  5499. case UNLT:
  5500. case UNGE:
  5501. case UNGT:
  5502. case UNORDERED:
  5503. /* Treat A != B as ~(A==B). */
  5504. {
  5505. enum rtx_code rev_code;
  5506. enum insn_code nor_code;
  5507. rtx rev_mask;
  5508. rev_code = reverse_condition_maybe_unordered (rcode);
  5509. rev_mask = spu_emit_vector_compare (rev_code, op0, op1, dest_mode);
  5510. nor_code = optab_handler (one_cmpl_optab, dest_mode);
  5511. gcc_assert (nor_code != CODE_FOR_nothing);
  5512. emit_insn (GEN_FCN (nor_code) (mask, rev_mask));
  5513. if (dmode != dest_mode)
  5514. {
  5515. rtx temp = gen_reg_rtx (dest_mode);
  5516. convert_move (temp, mask, 0);
  5517. return temp;
  5518. }
  5519. return mask;
  5520. }
  5521. break;
  5522. case GE:
  5523. case GEU:
  5524. case LE:
  5525. case LEU:
  5526. /* Try GT/GTU/LT/LTU OR EQ */
  5527. {
  5528. rtx c_rtx, eq_rtx;
  5529. enum insn_code ior_code;
  5530. enum rtx_code new_code;
  5531. switch (rcode)
  5532. {
  5533. case GE: new_code = GT; break;
  5534. case GEU: new_code = GTU; break;
  5535. case LE: new_code = LT; break;
  5536. case LEU: new_code = LTU; break;
  5537. default:
  5538. gcc_unreachable ();
  5539. }
  5540. c_rtx = spu_emit_vector_compare (new_code, op0, op1, dest_mode);
  5541. eq_rtx = spu_emit_vector_compare (EQ, op0, op1, dest_mode);
  5542. ior_code = optab_handler (ior_optab, dest_mode);
  5543. gcc_assert (ior_code != CODE_FOR_nothing);
  5544. emit_insn (GEN_FCN (ior_code) (mask, c_rtx, eq_rtx));
  5545. if (dmode != dest_mode)
  5546. {
  5547. rtx temp = gen_reg_rtx (dest_mode);
  5548. convert_move (temp, mask, 0);
  5549. return temp;
  5550. }
  5551. return mask;
  5552. }
  5553. break;
  5554. case LTGT:
  5555. /* Try LT OR GT */
  5556. {
  5557. rtx lt_rtx, gt_rtx;
  5558. enum insn_code ior_code;
  5559. lt_rtx = spu_emit_vector_compare (LT, op0, op1, dest_mode);
  5560. gt_rtx = spu_emit_vector_compare (GT, op0, op1, dest_mode);
  5561. ior_code = optab_handler (ior_optab, dest_mode);
  5562. gcc_assert (ior_code != CODE_FOR_nothing);
  5563. emit_insn (GEN_FCN (ior_code) (mask, lt_rtx, gt_rtx));
  5564. if (dmode != dest_mode)
  5565. {
  5566. rtx temp = gen_reg_rtx (dest_mode);
  5567. convert_move (temp, mask, 0);
  5568. return temp;
  5569. }
  5570. return mask;
  5571. }
  5572. break;
  5573. case ORDERED:
  5574. /* Implement as (A==A) & (B==B) */
  5575. {
  5576. rtx a_rtx, b_rtx;
  5577. enum insn_code and_code;
  5578. a_rtx = spu_emit_vector_compare (EQ, op0, op0, dest_mode);
  5579. b_rtx = spu_emit_vector_compare (EQ, op1, op1, dest_mode);
  5580. and_code = optab_handler (and_optab, dest_mode);
  5581. gcc_assert (and_code != CODE_FOR_nothing);
  5582. emit_insn (GEN_FCN (and_code) (mask, a_rtx, b_rtx));
  5583. if (dmode != dest_mode)
  5584. {
  5585. rtx temp = gen_reg_rtx (dest_mode);
  5586. convert_move (temp, mask, 0);
  5587. return temp;
  5588. }
  5589. return mask;
  5590. }
  5591. break;
  5592. default:
  5593. gcc_unreachable ();
  5594. }
  5595. /* You only get two chances. */
  5596. if (try_again)
  5597. vec_cmp_insn = get_vec_cmp_insn (rcode, dest_mode, op_mode);
  5598. gcc_assert (vec_cmp_insn != -1);
  5599. if (swap_operands)
  5600. {
  5601. rtx tmp;
  5602. tmp = op0;
  5603. op0 = op1;
  5604. op1 = tmp;
  5605. }
  5606. }
  5607. emit_insn (GEN_FCN (vec_cmp_insn) (mask, op0, op1));
  5608. if (dmode != dest_mode)
  5609. {
  5610. rtx temp = gen_reg_rtx (dest_mode);
  5611. convert_move (temp, mask, 0);
  5612. return temp;
  5613. }
  5614. return mask;
  5615. }
  5616. /* Emit vector conditional expression.
  5617. DEST is destination. OP1 and OP2 are two VEC_COND_EXPR operands.
  5618. CC_OP0 and CC_OP1 are the two operands for the relation operation COND. */
  5619. int
  5620. spu_emit_vector_cond_expr (rtx dest, rtx op1, rtx op2,
  5621. rtx cond, rtx cc_op0, rtx cc_op1)
  5622. {
  5623. machine_mode dest_mode = GET_MODE (dest);
  5624. enum rtx_code rcode = GET_CODE (cond);
  5625. rtx mask;
  5626. /* Get the vector mask for the given relational operations. */
  5627. mask = spu_emit_vector_compare (rcode, cc_op0, cc_op1, dest_mode);
  5628. emit_insn(gen_selb (dest, op2, op1, mask));
  5629. return 1;
  5630. }
  5631. static rtx
  5632. spu_force_reg (machine_mode mode, rtx op)
  5633. {
  5634. rtx x, r;
  5635. if (GET_MODE (op) == VOIDmode || GET_MODE (op) == BLKmode)
  5636. {
  5637. if ((SCALAR_INT_MODE_P (mode) && GET_CODE (op) == CONST_INT)
  5638. || GET_MODE (op) == BLKmode)
  5639. return force_reg (mode, convert_to_mode (mode, op, 0));
  5640. abort ();
  5641. }
  5642. r = force_reg (GET_MODE (op), op);
  5643. if (GET_MODE_SIZE (GET_MODE (op)) == GET_MODE_SIZE (mode))
  5644. {
  5645. x = simplify_gen_subreg (mode, r, GET_MODE (op), 0);
  5646. if (x)
  5647. return x;
  5648. }
  5649. x = gen_reg_rtx (mode);
  5650. emit_insn (gen_spu_convert (x, r));
  5651. return x;
  5652. }
  5653. static void
  5654. spu_check_builtin_parm (struct spu_builtin_description *d, rtx op, int p)
  5655. {
  5656. HOST_WIDE_INT v = 0;
  5657. int lsbits;
  5658. /* Check the range of immediate operands. */
  5659. if (p >= SPU_BTI_7 && p <= SPU_BTI_U18)
  5660. {
  5661. int range = p - SPU_BTI_7;
  5662. if (!CONSTANT_P (op))
  5663. error ("%s expects an integer literal in the range [%d, %d]",
  5664. d->name,
  5665. spu_builtin_range[range].low, spu_builtin_range[range].high);
  5666. if (GET_CODE (op) == CONST
  5667. && (GET_CODE (XEXP (op, 0)) == PLUS
  5668. || GET_CODE (XEXP (op, 0)) == MINUS))
  5669. {
  5670. v = INTVAL (XEXP (XEXP (op, 0), 1));
  5671. op = XEXP (XEXP (op, 0), 0);
  5672. }
  5673. else if (GET_CODE (op) == CONST_INT)
  5674. v = INTVAL (op);
  5675. else if (GET_CODE (op) == CONST_VECTOR
  5676. && GET_CODE (CONST_VECTOR_ELT (op, 0)) == CONST_INT)
  5677. v = INTVAL (CONST_VECTOR_ELT (op, 0));
  5678. /* The default for v is 0 which is valid in every range. */
  5679. if (v < spu_builtin_range[range].low
  5680. || v > spu_builtin_range[range].high)
  5681. error ("%s expects an integer literal in the range [%d, %d]. (%wd)",
  5682. d->name,
  5683. spu_builtin_range[range].low, spu_builtin_range[range].high,
  5684. v);
  5685. switch (p)
  5686. {
  5687. case SPU_BTI_S10_4:
  5688. lsbits = 4;
  5689. break;
  5690. case SPU_BTI_U16_2:
  5691. /* This is only used in lqa, and stqa. Even though the insns
  5692. encode 16 bits of the address (all but the 2 least
  5693. significant), only 14 bits are used because it is masked to
  5694. be 16 byte aligned. */
  5695. lsbits = 4;
  5696. break;
  5697. case SPU_BTI_S16_2:
  5698. /* This is used for lqr and stqr. */
  5699. lsbits = 2;
  5700. break;
  5701. default:
  5702. lsbits = 0;
  5703. }
  5704. if (GET_CODE (op) == LABEL_REF
  5705. || (GET_CODE (op) == SYMBOL_REF
  5706. && SYMBOL_REF_FUNCTION_P (op))
  5707. || (v & ((1 << lsbits) - 1)) != 0)
  5708. warning (0, "%d least significant bits of %s are ignored", lsbits,
  5709. d->name);
  5710. }
  5711. }
  5712. static int
  5713. expand_builtin_args (struct spu_builtin_description *d, tree exp,
  5714. rtx target, rtx ops[])
  5715. {
  5716. enum insn_code icode = (enum insn_code) d->icode;
  5717. int i = 0, a;
  5718. /* Expand the arguments into rtl. */
  5719. if (d->parm[0] != SPU_BTI_VOID)
  5720. ops[i++] = target;
  5721. for (a = 0; d->parm[a+1] != SPU_BTI_END_OF_PARAMS; i++, a++)
  5722. {
  5723. tree arg = CALL_EXPR_ARG (exp, a);
  5724. if (arg == 0)
  5725. abort ();
  5726. ops[i] = expand_expr (arg, NULL_RTX, VOIDmode, EXPAND_NORMAL);
  5727. }
  5728. gcc_assert (i == insn_data[icode].n_generator_args);
  5729. return i;
  5730. }
  5731. static rtx
  5732. spu_expand_builtin_1 (struct spu_builtin_description *d,
  5733. tree exp, rtx target)
  5734. {
  5735. rtx pat;
  5736. rtx ops[8];
  5737. enum insn_code icode = (enum insn_code) d->icode;
  5738. machine_mode mode, tmode;
  5739. int i, p;
  5740. int n_operands;
  5741. tree return_type;
  5742. /* Set up ops[] with values from arglist. */
  5743. n_operands = expand_builtin_args (d, exp, target, ops);
  5744. /* Handle the target operand which must be operand 0. */
  5745. i = 0;
  5746. if (d->parm[0] != SPU_BTI_VOID)
  5747. {
  5748. /* We prefer the mode specified for the match_operand otherwise
  5749. use the mode from the builtin function prototype. */
  5750. tmode = insn_data[d->icode].operand[0].mode;
  5751. if (tmode == VOIDmode)
  5752. tmode = TYPE_MODE (spu_builtin_types[d->parm[0]]);
  5753. /* Try to use target because not using it can lead to extra copies
  5754. and when we are using all of the registers extra copies leads
  5755. to extra spills. */
  5756. if (target && GET_CODE (target) == REG && GET_MODE (target) == tmode)
  5757. ops[0] = target;
  5758. else
  5759. target = ops[0] = gen_reg_rtx (tmode);
  5760. if (!(*insn_data[icode].operand[0].predicate) (ops[0], tmode))
  5761. abort ();
  5762. i++;
  5763. }
  5764. if (d->fcode == SPU_MASK_FOR_LOAD)
  5765. {
  5766. machine_mode mode = insn_data[icode].operand[1].mode;
  5767. tree arg;
  5768. rtx addr, op, pat;
  5769. /* get addr */
  5770. arg = CALL_EXPR_ARG (exp, 0);
  5771. gcc_assert (POINTER_TYPE_P (TREE_TYPE (arg)));
  5772. op = expand_expr (arg, NULL_RTX, Pmode, EXPAND_NORMAL);
  5773. addr = memory_address (mode, op);
  5774. /* negate addr */
  5775. op = gen_reg_rtx (GET_MODE (addr));
  5776. emit_insn (gen_rtx_SET (VOIDmode, op,
  5777. gen_rtx_NEG (GET_MODE (addr), addr)));
  5778. op = gen_rtx_MEM (mode, op);
  5779. pat = GEN_FCN (icode) (target, op);
  5780. if (!pat)
  5781. return 0;
  5782. emit_insn (pat);
  5783. return target;
  5784. }
  5785. /* Ignore align_hint, but still expand it's args in case they have
  5786. side effects. */
  5787. if (icode == CODE_FOR_spu_align_hint)
  5788. return 0;
  5789. /* Handle the rest of the operands. */
  5790. for (p = 1; i < n_operands; i++, p++)
  5791. {
  5792. if (insn_data[d->icode].operand[i].mode != VOIDmode)
  5793. mode = insn_data[d->icode].operand[i].mode;
  5794. else
  5795. mode = TYPE_MODE (spu_builtin_types[d->parm[i]]);
  5796. /* mode can be VOIDmode here for labels */
  5797. /* For specific intrinsics with an immediate operand, e.g.,
  5798. si_ai(), we sometimes need to convert the scalar argument to a
  5799. vector argument by splatting the scalar. */
  5800. if (VECTOR_MODE_P (mode)
  5801. && (GET_CODE (ops[i]) == CONST_INT
  5802. || GET_MODE_CLASS (GET_MODE (ops[i])) == MODE_INT
  5803. || GET_MODE_CLASS (GET_MODE (ops[i])) == MODE_FLOAT))
  5804. {
  5805. if (GET_CODE (ops[i]) == CONST_INT)
  5806. ops[i] = spu_const (mode, INTVAL (ops[i]));
  5807. else
  5808. {
  5809. rtx reg = gen_reg_rtx (mode);
  5810. machine_mode imode = GET_MODE_INNER (mode);
  5811. if (!spu_nonmem_operand (ops[i], GET_MODE (ops[i])))
  5812. ops[i] = force_reg (GET_MODE (ops[i]), ops[i]);
  5813. if (imode != GET_MODE (ops[i]))
  5814. ops[i] = convert_to_mode (imode, ops[i],
  5815. TYPE_UNSIGNED (spu_builtin_types
  5816. [d->parm[i]]));
  5817. emit_insn (gen_spu_splats (reg, ops[i]));
  5818. ops[i] = reg;
  5819. }
  5820. }
  5821. spu_check_builtin_parm (d, ops[i], d->parm[p]);
  5822. if (!(*insn_data[icode].operand[i].predicate) (ops[i], mode))
  5823. ops[i] = spu_force_reg (mode, ops[i]);
  5824. }
  5825. switch (n_operands)
  5826. {
  5827. case 0:
  5828. pat = GEN_FCN (icode) (0);
  5829. break;
  5830. case 1:
  5831. pat = GEN_FCN (icode) (ops[0]);
  5832. break;
  5833. case 2:
  5834. pat = GEN_FCN (icode) (ops[0], ops[1]);
  5835. break;
  5836. case 3:
  5837. pat = GEN_FCN (icode) (ops[0], ops[1], ops[2]);
  5838. break;
  5839. case 4:
  5840. pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3]);
  5841. break;
  5842. case 5:
  5843. pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3], ops[4]);
  5844. break;
  5845. case 6:
  5846. pat = GEN_FCN (icode) (ops[0], ops[1], ops[2], ops[3], ops[4], ops[5]);
  5847. break;
  5848. default:
  5849. abort ();
  5850. }
  5851. if (!pat)
  5852. abort ();
  5853. if (d->type == B_CALL || d->type == B_BISLED)
  5854. emit_call_insn (pat);
  5855. else if (d->type == B_JUMP)
  5856. {
  5857. emit_jump_insn (pat);
  5858. emit_barrier ();
  5859. }
  5860. else
  5861. emit_insn (pat);
  5862. return_type = spu_builtin_types[d->parm[0]];
  5863. if (d->parm[0] != SPU_BTI_VOID
  5864. && GET_MODE (target) != TYPE_MODE (return_type))
  5865. {
  5866. /* target is the return value. It should always be the mode of
  5867. the builtin function prototype. */
  5868. target = spu_force_reg (TYPE_MODE (return_type), target);
  5869. }
  5870. return target;
  5871. }
  5872. rtx
  5873. spu_expand_builtin (tree exp,
  5874. rtx target,
  5875. rtx subtarget ATTRIBUTE_UNUSED,
  5876. machine_mode mode ATTRIBUTE_UNUSED,
  5877. int ignore ATTRIBUTE_UNUSED)
  5878. {
  5879. tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
  5880. unsigned int fcode = DECL_FUNCTION_CODE (fndecl);
  5881. struct spu_builtin_description *d;
  5882. if (fcode < NUM_SPU_BUILTINS)
  5883. {
  5884. d = &spu_builtins[fcode];
  5885. return spu_expand_builtin_1 (d, exp, target);
  5886. }
  5887. abort ();
  5888. }
  5889. /* Implement targetm.vectorize.builtin_mask_for_load. */
  5890. static tree
  5891. spu_builtin_mask_for_load (void)
  5892. {
  5893. return spu_builtin_decls[SPU_MASK_FOR_LOAD];
  5894. }
  5895. /* Implement targetm.vectorize.builtin_vectorization_cost. */
  5896. static int
  5897. spu_builtin_vectorization_cost (enum vect_cost_for_stmt type_of_cost,
  5898. tree vectype,
  5899. int misalign ATTRIBUTE_UNUSED)
  5900. {
  5901. unsigned elements;
  5902. switch (type_of_cost)
  5903. {
  5904. case scalar_stmt:
  5905. case vector_stmt:
  5906. case vector_load:
  5907. case vector_store:
  5908. case vec_to_scalar:
  5909. case scalar_to_vec:
  5910. case cond_branch_not_taken:
  5911. case vec_perm:
  5912. case vec_promote_demote:
  5913. return 1;
  5914. case scalar_store:
  5915. return 10;
  5916. case scalar_load:
  5917. /* Load + rotate. */
  5918. return 2;
  5919. case unaligned_load:
  5920. return 2;
  5921. case cond_branch_taken:
  5922. return 6;
  5923. case vec_construct:
  5924. elements = TYPE_VECTOR_SUBPARTS (vectype);
  5925. return elements / 2 + 1;
  5926. default:
  5927. gcc_unreachable ();
  5928. }
  5929. }
  5930. /* Implement targetm.vectorize.init_cost. */
  5931. static void *
  5932. spu_init_cost (struct loop *loop_info ATTRIBUTE_UNUSED)
  5933. {
  5934. unsigned *cost = XNEWVEC (unsigned, 3);
  5935. cost[vect_prologue] = cost[vect_body] = cost[vect_epilogue] = 0;
  5936. return cost;
  5937. }
  5938. /* Implement targetm.vectorize.add_stmt_cost. */
  5939. static unsigned
  5940. spu_add_stmt_cost (void *data, int count, enum vect_cost_for_stmt kind,
  5941. struct _stmt_vec_info *stmt_info, int misalign,
  5942. enum vect_cost_model_location where)
  5943. {
  5944. unsigned *cost = (unsigned *) data;
  5945. unsigned retval = 0;
  5946. if (flag_vect_cost_model)
  5947. {
  5948. tree vectype = stmt_info ? stmt_vectype (stmt_info) : NULL_TREE;
  5949. int stmt_cost = spu_builtin_vectorization_cost (kind, vectype, misalign);
  5950. /* Statements in an inner loop relative to the loop being
  5951. vectorized are weighted more heavily. The value here is
  5952. arbitrary and could potentially be improved with analysis. */
  5953. if (where == vect_body && stmt_info && stmt_in_inner_loop_p (stmt_info))
  5954. count *= 50; /* FIXME. */
  5955. retval = (unsigned) (count * stmt_cost);
  5956. cost[where] += retval;
  5957. }
  5958. return retval;
  5959. }
  5960. /* Implement targetm.vectorize.finish_cost. */
  5961. static void
  5962. spu_finish_cost (void *data, unsigned *prologue_cost,
  5963. unsigned *body_cost, unsigned *epilogue_cost)
  5964. {
  5965. unsigned *cost = (unsigned *) data;
  5966. *prologue_cost = cost[vect_prologue];
  5967. *body_cost = cost[vect_body];
  5968. *epilogue_cost = cost[vect_epilogue];
  5969. }
  5970. /* Implement targetm.vectorize.destroy_cost_data. */
  5971. static void
  5972. spu_destroy_cost_data (void *data)
  5973. {
  5974. free (data);
  5975. }
  5976. /* Return true iff, data reference of TYPE can reach vector alignment (16)
  5977. after applying N number of iterations. This routine does not determine
  5978. how may iterations are required to reach desired alignment. */
  5979. static bool
  5980. spu_vector_alignment_reachable (const_tree type ATTRIBUTE_UNUSED, bool is_packed)
  5981. {
  5982. if (is_packed)
  5983. return false;
  5984. /* All other types are naturally aligned. */
  5985. return true;
  5986. }
  5987. /* Return the appropriate mode for a named address pointer. */
  5988. static machine_mode
  5989. spu_addr_space_pointer_mode (addr_space_t addrspace)
  5990. {
  5991. switch (addrspace)
  5992. {
  5993. case ADDR_SPACE_GENERIC:
  5994. return ptr_mode;
  5995. case ADDR_SPACE_EA:
  5996. return EAmode;
  5997. default:
  5998. gcc_unreachable ();
  5999. }
  6000. }
  6001. /* Return the appropriate mode for a named address address. */
  6002. static machine_mode
  6003. spu_addr_space_address_mode (addr_space_t addrspace)
  6004. {
  6005. switch (addrspace)
  6006. {
  6007. case ADDR_SPACE_GENERIC:
  6008. return Pmode;
  6009. case ADDR_SPACE_EA:
  6010. return EAmode;
  6011. default:
  6012. gcc_unreachable ();
  6013. }
  6014. }
  6015. /* Determine if one named address space is a subset of another. */
  6016. static bool
  6017. spu_addr_space_subset_p (addr_space_t subset, addr_space_t superset)
  6018. {
  6019. gcc_assert (subset == ADDR_SPACE_GENERIC || subset == ADDR_SPACE_EA);
  6020. gcc_assert (superset == ADDR_SPACE_GENERIC || superset == ADDR_SPACE_EA);
  6021. if (subset == superset)
  6022. return true;
  6023. /* If we have -mno-address-space-conversion, treat __ea and generic as not
  6024. being subsets but instead as disjoint address spaces. */
  6025. else if (!TARGET_ADDRESS_SPACE_CONVERSION)
  6026. return false;
  6027. else
  6028. return (subset == ADDR_SPACE_GENERIC && superset == ADDR_SPACE_EA);
  6029. }
  6030. /* Convert from one address space to another. */
  6031. static rtx
  6032. spu_addr_space_convert (rtx op, tree from_type, tree to_type)
  6033. {
  6034. addr_space_t from_as = TYPE_ADDR_SPACE (TREE_TYPE (from_type));
  6035. addr_space_t to_as = TYPE_ADDR_SPACE (TREE_TYPE (to_type));
  6036. gcc_assert (from_as == ADDR_SPACE_GENERIC || from_as == ADDR_SPACE_EA);
  6037. gcc_assert (to_as == ADDR_SPACE_GENERIC || to_as == ADDR_SPACE_EA);
  6038. if (to_as == ADDR_SPACE_GENERIC && from_as == ADDR_SPACE_EA)
  6039. {
  6040. rtx result, ls;
  6041. ls = gen_const_mem (DImode,
  6042. gen_rtx_SYMBOL_REF (Pmode, "__ea_local_store"));
  6043. set_mem_align (ls, 128);
  6044. result = gen_reg_rtx (Pmode);
  6045. ls = force_reg (Pmode, convert_modes (Pmode, DImode, ls, 1));
  6046. op = force_reg (Pmode, convert_modes (Pmode, EAmode, op, 1));
  6047. ls = emit_conditional_move (ls, NE, op, const0_rtx, Pmode,
  6048. ls, const0_rtx, Pmode, 1);
  6049. emit_insn (gen_subsi3 (result, op, ls));
  6050. return result;
  6051. }
  6052. else if (to_as == ADDR_SPACE_EA && from_as == ADDR_SPACE_GENERIC)
  6053. {
  6054. rtx result, ls;
  6055. ls = gen_const_mem (DImode,
  6056. gen_rtx_SYMBOL_REF (Pmode, "__ea_local_store"));
  6057. set_mem_align (ls, 128);
  6058. result = gen_reg_rtx (EAmode);
  6059. ls = force_reg (EAmode, convert_modes (EAmode, DImode, ls, 1));
  6060. op = force_reg (Pmode, op);
  6061. ls = emit_conditional_move (ls, NE, op, const0_rtx, Pmode,
  6062. ls, const0_rtx, EAmode, 1);
  6063. op = force_reg (EAmode, convert_modes (EAmode, Pmode, op, 1));
  6064. if (EAmode == SImode)
  6065. emit_insn (gen_addsi3 (result, op, ls));
  6066. else
  6067. emit_insn (gen_adddi3 (result, op, ls));
  6068. return result;
  6069. }
  6070. else
  6071. gcc_unreachable ();
  6072. }
  6073. /* Count the total number of instructions in each pipe and return the
  6074. maximum, which is used as the Minimum Iteration Interval (MII)
  6075. in the modulo scheduler. get_pipe() will return -2, -1, 0, or 1.
  6076. -2 are instructions that can go in pipe0 or pipe1. */
  6077. static int
  6078. spu_sms_res_mii (struct ddg *g)
  6079. {
  6080. int i;
  6081. unsigned t[4] = {0, 0, 0, 0};
  6082. for (i = 0; i < g->num_nodes; i++)
  6083. {
  6084. rtx_insn *insn = g->nodes[i].insn;
  6085. int p = get_pipe (insn) + 2;
  6086. gcc_assert (p >= 0);
  6087. gcc_assert (p < 4);
  6088. t[p]++;
  6089. if (dump_file && INSN_P (insn))
  6090. fprintf (dump_file, "i%d %s %d %d\n",
  6091. INSN_UID (insn),
  6092. insn_data[INSN_CODE(insn)].name,
  6093. p, t[p]);
  6094. }
  6095. if (dump_file)
  6096. fprintf (dump_file, "%d %d %d %d\n", t[0], t[1], t[2], t[3]);
  6097. return MAX ((t[0] + t[2] + t[3] + 1) / 2, MAX (t[2], t[3]));
  6098. }
  6099. void
  6100. spu_init_expanders (void)
  6101. {
  6102. if (cfun)
  6103. {
  6104. rtx r0, r1;
  6105. /* HARD_FRAME_REGISTER is only 128 bit aligned when
  6106. frame_pointer_needed is true. We don't know that until we're
  6107. expanding the prologue. */
  6108. REGNO_POINTER_ALIGN (HARD_FRAME_POINTER_REGNUM) = 8;
  6109. /* A number of passes use LAST_VIRTUAL_REGISTER+1 and
  6110. LAST_VIRTUAL_REGISTER+2 to test the back-end. We want them
  6111. to be treated as aligned, so generate them here. */
  6112. r0 = gen_reg_rtx (SImode);
  6113. r1 = gen_reg_rtx (SImode);
  6114. mark_reg_pointer (r0, 128);
  6115. mark_reg_pointer (r1, 128);
  6116. gcc_assert (REGNO (r0) == LAST_VIRTUAL_REGISTER + 1
  6117. && REGNO (r1) == LAST_VIRTUAL_REGISTER + 2);
  6118. }
  6119. }
  6120. static machine_mode
  6121. spu_libgcc_cmp_return_mode (void)
  6122. {
  6123. /* For SPU word mode is TI mode so it is better to use SImode
  6124. for compare returns. */
  6125. return SImode;
  6126. }
  6127. static machine_mode
  6128. spu_libgcc_shift_count_mode (void)
  6129. {
  6130. /* For SPU word mode is TI mode so it is better to use SImode
  6131. for shift counts. */
  6132. return SImode;
  6133. }
  6134. /* Implement targetm.section_type_flags. */
  6135. static unsigned int
  6136. spu_section_type_flags (tree decl, const char *name, int reloc)
  6137. {
  6138. /* .toe needs to have type @nobits. */
  6139. if (strcmp (name, ".toe") == 0)
  6140. return SECTION_BSS;
  6141. /* Don't load _ea into the current address space. */
  6142. if (strcmp (name, "._ea") == 0)
  6143. return SECTION_WRITE | SECTION_DEBUG;
  6144. return default_section_type_flags (decl, name, reloc);
  6145. }
  6146. /* Implement targetm.select_section. */
  6147. static section *
  6148. spu_select_section (tree decl, int reloc, unsigned HOST_WIDE_INT align)
  6149. {
  6150. /* Variables and constants defined in the __ea address space
  6151. go into a special section named "._ea". */
  6152. if (TREE_TYPE (decl) != error_mark_node
  6153. && TYPE_ADDR_SPACE (TREE_TYPE (decl)) == ADDR_SPACE_EA)
  6154. {
  6155. /* We might get called with string constants, but get_named_section
  6156. doesn't like them as they are not DECLs. Also, we need to set
  6157. flags in that case. */
  6158. if (!DECL_P (decl))
  6159. return get_section ("._ea", SECTION_WRITE | SECTION_DEBUG, NULL);
  6160. return get_named_section (decl, "._ea", reloc);
  6161. }
  6162. return default_elf_select_section (decl, reloc, align);
  6163. }
  6164. /* Implement targetm.unique_section. */
  6165. static void
  6166. spu_unique_section (tree decl, int reloc)
  6167. {
  6168. /* We don't support unique section names in the __ea address
  6169. space for now. */
  6170. if (TREE_TYPE (decl) != error_mark_node
  6171. && TYPE_ADDR_SPACE (TREE_TYPE (decl)) != 0)
  6172. return;
  6173. default_unique_section (decl, reloc);
  6174. }
  6175. /* Generate a constant or register which contains 2^SCALE. We assume
  6176. the result is valid for MODE. Currently, MODE must be V4SFmode and
  6177. SCALE must be SImode. */
  6178. rtx
  6179. spu_gen_exp2 (machine_mode mode, rtx scale)
  6180. {
  6181. gcc_assert (mode == V4SFmode);
  6182. gcc_assert (GET_MODE (scale) == SImode || GET_CODE (scale) == CONST_INT);
  6183. if (GET_CODE (scale) != CONST_INT)
  6184. {
  6185. /* unsigned int exp = (127 + scale) << 23;
  6186. __vector float m = (__vector float) spu_splats (exp); */
  6187. rtx reg = force_reg (SImode, scale);
  6188. rtx exp = gen_reg_rtx (SImode);
  6189. rtx mul = gen_reg_rtx (mode);
  6190. emit_insn (gen_addsi3 (exp, reg, GEN_INT (127)));
  6191. emit_insn (gen_ashlsi3 (exp, exp, GEN_INT (23)));
  6192. emit_insn (gen_spu_splats (mul, gen_rtx_SUBREG (GET_MODE_INNER (mode), exp, 0)));
  6193. return mul;
  6194. }
  6195. else
  6196. {
  6197. HOST_WIDE_INT exp = 127 + INTVAL (scale);
  6198. unsigned char arr[16];
  6199. arr[0] = arr[4] = arr[8] = arr[12] = exp >> 1;
  6200. arr[1] = arr[5] = arr[9] = arr[13] = exp << 7;
  6201. arr[2] = arr[6] = arr[10] = arr[14] = 0;
  6202. arr[3] = arr[7] = arr[11] = arr[15] = 0;
  6203. return array_to_constant (mode, arr);
  6204. }
  6205. }
  6206. /* After reload, just change the convert into a move instruction
  6207. or a dead instruction. */
  6208. void
  6209. spu_split_convert (rtx ops[])
  6210. {
  6211. if (REGNO (ops[0]) == REGNO (ops[1]))
  6212. emit_note (NOTE_INSN_DELETED);
  6213. else
  6214. {
  6215. /* Use TImode always as this might help hard reg copyprop. */
  6216. rtx op0 = gen_rtx_REG (TImode, REGNO (ops[0]));
  6217. rtx op1 = gen_rtx_REG (TImode, REGNO (ops[1]));
  6218. emit_insn (gen_move_insn (op0, op1));
  6219. }
  6220. }
  6221. void
  6222. spu_function_profiler (FILE * file, int labelno ATTRIBUTE_UNUSED)
  6223. {
  6224. fprintf (file, "# profile\n");
  6225. fprintf (file, "brsl $75, _mcount\n");
  6226. }
  6227. /* Implement targetm.ref_may_alias_errno. */
  6228. static bool
  6229. spu_ref_may_alias_errno (ao_ref *ref)
  6230. {
  6231. tree base = ao_ref_base (ref);
  6232. /* With SPU newlib, errno is defined as something like
  6233. _impure_data._errno
  6234. The default implementation of this target macro does not
  6235. recognize such expressions, so special-code for it here. */
  6236. if (TREE_CODE (base) == VAR_DECL
  6237. && !TREE_STATIC (base)
  6238. && DECL_EXTERNAL (base)
  6239. && TREE_CODE (TREE_TYPE (base)) == RECORD_TYPE
  6240. && strcmp (IDENTIFIER_POINTER (DECL_ASSEMBLER_NAME (base)),
  6241. "_impure_data") == 0
  6242. /* _errno is the first member of _impure_data. */
  6243. && ref->offset == 0)
  6244. return true;
  6245. return default_ref_may_alias_errno (ref);
  6246. }
  6247. /* Output thunk to FILE that implements a C++ virtual function call (with
  6248. multiple inheritance) to FUNCTION. The thunk adjusts the this pointer
  6249. by DELTA, and unless VCALL_OFFSET is zero, applies an additional adjustment
  6250. stored at VCALL_OFFSET in the vtable whose address is located at offset 0
  6251. relative to the resulting this pointer. */
  6252. static void
  6253. spu_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
  6254. HOST_WIDE_INT delta, HOST_WIDE_INT vcall_offset,
  6255. tree function)
  6256. {
  6257. rtx op[8];
  6258. /* Make sure unwind info is emitted for the thunk if needed. */
  6259. final_start_function (emit_barrier (), file, 1);
  6260. /* Operand 0 is the target function. */
  6261. op[0] = XEXP (DECL_RTL (function), 0);
  6262. /* Operand 1 is the 'this' pointer. */
  6263. if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
  6264. op[1] = gen_rtx_REG (Pmode, FIRST_ARG_REGNUM + 1);
  6265. else
  6266. op[1] = gen_rtx_REG (Pmode, FIRST_ARG_REGNUM);
  6267. /* Operands 2/3 are the low/high halfwords of delta. */
  6268. op[2] = GEN_INT (trunc_int_for_mode (delta, HImode));
  6269. op[3] = GEN_INT (trunc_int_for_mode (delta >> 16, HImode));
  6270. /* Operands 4/5 are the low/high halfwords of vcall_offset. */
  6271. op[4] = GEN_INT (trunc_int_for_mode (vcall_offset, HImode));
  6272. op[5] = GEN_INT (trunc_int_for_mode (vcall_offset >> 16, HImode));
  6273. /* Operands 6/7 are temporary registers. */
  6274. op[6] = gen_rtx_REG (Pmode, 79);
  6275. op[7] = gen_rtx_REG (Pmode, 78);
  6276. /* Add DELTA to this pointer. */
  6277. if (delta)
  6278. {
  6279. if (delta >= -0x200 && delta < 0x200)
  6280. output_asm_insn ("ai\t%1,%1,%2", op);
  6281. else if (delta >= -0x8000 && delta < 0x8000)
  6282. {
  6283. output_asm_insn ("il\t%6,%2", op);
  6284. output_asm_insn ("a\t%1,%1,%6", op);
  6285. }
  6286. else
  6287. {
  6288. output_asm_insn ("ilhu\t%6,%3", op);
  6289. output_asm_insn ("iohl\t%6,%2", op);
  6290. output_asm_insn ("a\t%1,%1,%6", op);
  6291. }
  6292. }
  6293. /* Perform vcall adjustment. */
  6294. if (vcall_offset)
  6295. {
  6296. output_asm_insn ("lqd\t%7,0(%1)", op);
  6297. output_asm_insn ("rotqby\t%7,%7,%1", op);
  6298. if (vcall_offset >= -0x200 && vcall_offset < 0x200)
  6299. output_asm_insn ("ai\t%7,%7,%4", op);
  6300. else if (vcall_offset >= -0x8000 && vcall_offset < 0x8000)
  6301. {
  6302. output_asm_insn ("il\t%6,%4", op);
  6303. output_asm_insn ("a\t%7,%7,%6", op);
  6304. }
  6305. else
  6306. {
  6307. output_asm_insn ("ilhu\t%6,%5", op);
  6308. output_asm_insn ("iohl\t%6,%4", op);
  6309. output_asm_insn ("a\t%7,%7,%6", op);
  6310. }
  6311. output_asm_insn ("lqd\t%6,0(%7)", op);
  6312. output_asm_insn ("rotqby\t%6,%6,%7", op);
  6313. output_asm_insn ("a\t%1,%1,%6", op);
  6314. }
  6315. /* Jump to target. */
  6316. output_asm_insn ("br\t%0", op);
  6317. final_end_function ();
  6318. }
  6319. /* Canonicalize a comparison from one we don't have to one we do have. */
  6320. static void
  6321. spu_canonicalize_comparison (int *code, rtx *op0, rtx *op1,
  6322. bool op0_preserve_value)
  6323. {
  6324. if (!op0_preserve_value
  6325. && (*code == LE || *code == LT || *code == LEU || *code == LTU))
  6326. {
  6327. rtx tem = *op0;
  6328. *op0 = *op1;
  6329. *op1 = tem;
  6330. *code = (int)swap_condition ((enum rtx_code)*code);
  6331. }
  6332. }
  6333. /* Table of machine attributes. */
  6334. static const struct attribute_spec spu_attribute_table[] =
  6335. {
  6336. /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler,
  6337. affects_type_identity } */
  6338. { "naked", 0, 0, true, false, false, spu_handle_fndecl_attribute,
  6339. false },
  6340. { "spu_vector", 0, 0, false, true, false, spu_handle_vector_attribute,
  6341. false },
  6342. { NULL, 0, 0, false, false, false, NULL, false }
  6343. };
  6344. /* TARGET overrides. */
  6345. #undef TARGET_ADDR_SPACE_POINTER_MODE
  6346. #define TARGET_ADDR_SPACE_POINTER_MODE spu_addr_space_pointer_mode
  6347. #undef TARGET_ADDR_SPACE_ADDRESS_MODE
  6348. #define TARGET_ADDR_SPACE_ADDRESS_MODE spu_addr_space_address_mode
  6349. #undef TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P
  6350. #define TARGET_ADDR_SPACE_LEGITIMATE_ADDRESS_P \
  6351. spu_addr_space_legitimate_address_p
  6352. #undef TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS
  6353. #define TARGET_ADDR_SPACE_LEGITIMIZE_ADDRESS spu_addr_space_legitimize_address
  6354. #undef TARGET_ADDR_SPACE_SUBSET_P
  6355. #define TARGET_ADDR_SPACE_SUBSET_P spu_addr_space_subset_p
  6356. #undef TARGET_ADDR_SPACE_CONVERT
  6357. #define TARGET_ADDR_SPACE_CONVERT spu_addr_space_convert
  6358. #undef TARGET_INIT_BUILTINS
  6359. #define TARGET_INIT_BUILTINS spu_init_builtins
  6360. #undef TARGET_BUILTIN_DECL
  6361. #define TARGET_BUILTIN_DECL spu_builtin_decl
  6362. #undef TARGET_EXPAND_BUILTIN
  6363. #define TARGET_EXPAND_BUILTIN spu_expand_builtin
  6364. #undef TARGET_UNWIND_WORD_MODE
  6365. #define TARGET_UNWIND_WORD_MODE spu_unwind_word_mode
  6366. #undef TARGET_LEGITIMIZE_ADDRESS
  6367. #define TARGET_LEGITIMIZE_ADDRESS spu_legitimize_address
  6368. /* The current assembler doesn't like .4byte foo@ppu, so use the normal .long
  6369. and .quad for the debugger. When it is known that the assembler is fixed,
  6370. these can be removed. */
  6371. #undef TARGET_ASM_UNALIGNED_SI_OP
  6372. #define TARGET_ASM_UNALIGNED_SI_OP "\t.long\t"
  6373. #undef TARGET_ASM_ALIGNED_DI_OP
  6374. #define TARGET_ASM_ALIGNED_DI_OP "\t.quad\t"
  6375. /* The .8byte directive doesn't seem to work well for a 32 bit
  6376. architecture. */
  6377. #undef TARGET_ASM_UNALIGNED_DI_OP
  6378. #define TARGET_ASM_UNALIGNED_DI_OP NULL
  6379. #undef TARGET_RTX_COSTS
  6380. #define TARGET_RTX_COSTS spu_rtx_costs
  6381. #undef TARGET_ADDRESS_COST
  6382. #define TARGET_ADDRESS_COST hook_int_rtx_mode_as_bool_0
  6383. #undef TARGET_SCHED_ISSUE_RATE
  6384. #define TARGET_SCHED_ISSUE_RATE spu_sched_issue_rate
  6385. #undef TARGET_SCHED_INIT_GLOBAL
  6386. #define TARGET_SCHED_INIT_GLOBAL spu_sched_init_global
  6387. #undef TARGET_SCHED_INIT
  6388. #define TARGET_SCHED_INIT spu_sched_init
  6389. #undef TARGET_SCHED_VARIABLE_ISSUE
  6390. #define TARGET_SCHED_VARIABLE_ISSUE spu_sched_variable_issue
  6391. #undef TARGET_SCHED_REORDER
  6392. #define TARGET_SCHED_REORDER spu_sched_reorder
  6393. #undef TARGET_SCHED_REORDER2
  6394. #define TARGET_SCHED_REORDER2 spu_sched_reorder
  6395. #undef TARGET_SCHED_ADJUST_COST
  6396. #define TARGET_SCHED_ADJUST_COST spu_sched_adjust_cost
  6397. #undef TARGET_ATTRIBUTE_TABLE
  6398. #define TARGET_ATTRIBUTE_TABLE spu_attribute_table
  6399. #undef TARGET_ASM_INTEGER
  6400. #define TARGET_ASM_INTEGER spu_assemble_integer
  6401. #undef TARGET_SCALAR_MODE_SUPPORTED_P
  6402. #define TARGET_SCALAR_MODE_SUPPORTED_P spu_scalar_mode_supported_p
  6403. #undef TARGET_VECTOR_MODE_SUPPORTED_P
  6404. #define TARGET_VECTOR_MODE_SUPPORTED_P spu_vector_mode_supported_p
  6405. #undef TARGET_FUNCTION_OK_FOR_SIBCALL
  6406. #define TARGET_FUNCTION_OK_FOR_SIBCALL spu_function_ok_for_sibcall
  6407. #undef TARGET_ASM_GLOBALIZE_LABEL
  6408. #define TARGET_ASM_GLOBALIZE_LABEL spu_asm_globalize_label
  6409. #undef TARGET_PASS_BY_REFERENCE
  6410. #define TARGET_PASS_BY_REFERENCE spu_pass_by_reference
  6411. #undef TARGET_FUNCTION_ARG
  6412. #define TARGET_FUNCTION_ARG spu_function_arg
  6413. #undef TARGET_FUNCTION_ARG_ADVANCE
  6414. #define TARGET_FUNCTION_ARG_ADVANCE spu_function_arg_advance
  6415. #undef TARGET_MUST_PASS_IN_STACK
  6416. #define TARGET_MUST_PASS_IN_STACK must_pass_in_stack_var_size
  6417. #undef TARGET_BUILD_BUILTIN_VA_LIST
  6418. #define TARGET_BUILD_BUILTIN_VA_LIST spu_build_builtin_va_list
  6419. #undef TARGET_EXPAND_BUILTIN_VA_START
  6420. #define TARGET_EXPAND_BUILTIN_VA_START spu_va_start
  6421. #undef TARGET_SETUP_INCOMING_VARARGS
  6422. #define TARGET_SETUP_INCOMING_VARARGS spu_setup_incoming_varargs
  6423. #undef TARGET_MACHINE_DEPENDENT_REORG
  6424. #define TARGET_MACHINE_DEPENDENT_REORG spu_machine_dependent_reorg
  6425. #undef TARGET_GIMPLIFY_VA_ARG_EXPR
  6426. #define TARGET_GIMPLIFY_VA_ARG_EXPR spu_gimplify_va_arg_expr
  6427. #undef TARGET_INIT_LIBFUNCS
  6428. #define TARGET_INIT_LIBFUNCS spu_init_libfuncs
  6429. #undef TARGET_RETURN_IN_MEMORY
  6430. #define TARGET_RETURN_IN_MEMORY spu_return_in_memory
  6431. #undef TARGET_ENCODE_SECTION_INFO
  6432. #define TARGET_ENCODE_SECTION_INFO spu_encode_section_info
  6433. #undef TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD
  6434. #define TARGET_VECTORIZE_BUILTIN_MASK_FOR_LOAD spu_builtin_mask_for_load
  6435. #undef TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST
  6436. #define TARGET_VECTORIZE_BUILTIN_VECTORIZATION_COST spu_builtin_vectorization_cost
  6437. #undef TARGET_VECTORIZE_INIT_COST
  6438. #define TARGET_VECTORIZE_INIT_COST spu_init_cost
  6439. #undef TARGET_VECTORIZE_ADD_STMT_COST
  6440. #define TARGET_VECTORIZE_ADD_STMT_COST spu_add_stmt_cost
  6441. #undef TARGET_VECTORIZE_FINISH_COST
  6442. #define TARGET_VECTORIZE_FINISH_COST spu_finish_cost
  6443. #undef TARGET_VECTORIZE_DESTROY_COST_DATA
  6444. #define TARGET_VECTORIZE_DESTROY_COST_DATA spu_destroy_cost_data
  6445. #undef TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE
  6446. #define TARGET_VECTORIZE_VECTOR_ALIGNMENT_REACHABLE spu_vector_alignment_reachable
  6447. #undef TARGET_LIBGCC_CMP_RETURN_MODE
  6448. #define TARGET_LIBGCC_CMP_RETURN_MODE spu_libgcc_cmp_return_mode
  6449. #undef TARGET_LIBGCC_SHIFT_COUNT_MODE
  6450. #define TARGET_LIBGCC_SHIFT_COUNT_MODE spu_libgcc_shift_count_mode
  6451. #undef TARGET_SCHED_SMS_RES_MII
  6452. #define TARGET_SCHED_SMS_RES_MII spu_sms_res_mii
  6453. #undef TARGET_SECTION_TYPE_FLAGS
  6454. #define TARGET_SECTION_TYPE_FLAGS spu_section_type_flags
  6455. #undef TARGET_ASM_SELECT_SECTION
  6456. #define TARGET_ASM_SELECT_SECTION spu_select_section
  6457. #undef TARGET_ASM_UNIQUE_SECTION
  6458. #define TARGET_ASM_UNIQUE_SECTION spu_unique_section
  6459. #undef TARGET_LEGITIMATE_ADDRESS_P
  6460. #define TARGET_LEGITIMATE_ADDRESS_P spu_legitimate_address_p
  6461. #undef TARGET_LEGITIMATE_CONSTANT_P
  6462. #define TARGET_LEGITIMATE_CONSTANT_P spu_legitimate_constant_p
  6463. #undef TARGET_TRAMPOLINE_INIT
  6464. #define TARGET_TRAMPOLINE_INIT spu_trampoline_init
  6465. #undef TARGET_WARN_FUNC_RETURN
  6466. #define TARGET_WARN_FUNC_RETURN spu_warn_func_return
  6467. #undef TARGET_OPTION_OVERRIDE
  6468. #define TARGET_OPTION_OVERRIDE spu_option_override
  6469. #undef TARGET_CONDITIONAL_REGISTER_USAGE
  6470. #define TARGET_CONDITIONAL_REGISTER_USAGE spu_conditional_register_usage
  6471. #undef TARGET_REF_MAY_ALIAS_ERRNO
  6472. #define TARGET_REF_MAY_ALIAS_ERRNO spu_ref_may_alias_errno
  6473. #undef TARGET_ASM_OUTPUT_MI_THUNK
  6474. #define TARGET_ASM_OUTPUT_MI_THUNK spu_output_mi_thunk
  6475. #undef TARGET_ASM_CAN_OUTPUT_MI_THUNK
  6476. #define TARGET_ASM_CAN_OUTPUT_MI_THUNK hook_bool_const_tree_hwi_hwi_const_tree_true
  6477. /* Variable tracking should be run after all optimizations which
  6478. change order of insns. It also needs a valid CFG. */
  6479. #undef TARGET_DELAY_VARTRACK
  6480. #define TARGET_DELAY_VARTRACK true
  6481. #undef TARGET_CANONICALIZE_COMPARISON
  6482. #define TARGET_CANONICALIZE_COMPARISON spu_canonicalize_comparison
  6483. #undef TARGET_CAN_USE_DOLOOP_P
  6484. #define TARGET_CAN_USE_DOLOOP_P can_use_doloop_if_innermost
  6485. struct gcc_target targetm = TARGET_INITIALIZER;
  6486. #include "gt-spu.h"