12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577457845794580458145824583458445854586458745884589459045914592459345944595459645974598459946004601460246034604460546064607460846094610461146124613461446154616461746184619462046214622462346244625462646274628462946304631463246334634463546364637463846394640464146424643464446454646464746484649465046514652465346544655465646574658465946604661466246634664466546664667466846694670467146724673467446754676467746784679468046814682468346844685468646874688468946904691469246934694469546964697469846994700470147024703470447054706470747084709471047114712471347144715471647174718471947204721472247234724472547264727472847294730473147324733473447354736473747384739474047414742474347444745474647474748474947504751475247534754475547564757475847594760476147624763476447654766476747684769477047714772477347744775477647774778477947804781478247834784478547864787478847894790479147924793479447954796479747984799480048014802480348044805480648074808480948104811481248134814481548164817481848194820482148224823482448254826482748284829483048314832483348344835483648374838483948404841484248434844484548464847484848494850485148524853485448554856485748584859486048614862486348644865486648674868486948704871487248734874487548764877487848794880488148824883488448854886488748884889489048914892489348944895489648974898489949004901490249034904490549064907490849094910491149124913491449154916491749184919492049214922492349244925492649274928492949304931493249334934493549364937493849394940494149424943494449454946494749484949495049514952495349544955495649574958495949604961496249634964496549664967496849694970497149724973497449754976497749784979498049814982498349844985498649874988498949904991499249934994499549964997499849995000500150025003500450055006500750085009501050115012501350145015501650175018501950205021502250235024502550265027502850295030503150325033503450355036503750385039504050415042504350445045504650475048504950505051505250535054505550565057505850595060506150625063506450655066506750685069507050715072507350745075507650775078507950805081508250835084508550865087508850895090509150925093509450955096509750985099510051015102510351045105510651075108510951105111511251135114511551165117511851195120512151225123512451255126512751285129513051315132513351345135513651375138513951405141514251435144514551465147514851495150515151525153515451555156515751585159516051615162516351645165516651675168516951705171517251735174517551765177517851795180518151825183518451855186518751885189519051915192519351945195519651975198519952005201520252035204520552065207520852095210521152125213521452155216521752185219522052215222522352245225522652275228522952305231523252335234523552365237523852395240524152425243524452455246524752485249525052515252525352545255525652575258525952605261526252635264526552665267526852695270527152725273527452755276527752785279528052815282528352845285528652875288528952905291529252935294529552965297529852995300530153025303530453055306530753085309531053115312531353145315531653175318531953205321532253235324532553265327532853295330533153325333533453355336533753385339534053415342534353445345534653475348534953505351535253535354535553565357535853595360536153625363536453655366536753685369537053715372537353745375537653775378537953805381538253835384538553865387538853895390539153925393539453955396539753985399540054015402540354045405540654075408540954105411541254135414541554165417541854195420542154225423542454255426542754285429543054315432543354345435543654375438543954405441544254435444544554465447544854495450545154525453545454555456545754585459546054615462546354645465546654675468546954705471547254735474547554765477547854795480548154825483548454855486548754885489549054915492549354945495549654975498549955005501550255035504550555065507550855095510551155125513551455155516551755185519552055215522552355245525552655275528552955305531553255335534553555365537553855395540554155425543554455455546554755485549555055515552555355545555555655575558555955605561556255635564556555665567556855695570557155725573557455755576557755785579558055815582558355845585558655875588558955905591559255935594559555965597559855995600560156025603560456055606560756085609561056115612561356145615561656175618561956205621562256235624562556265627562856295630563156325633563456355636563756385639564056415642564356445645564656475648564956505651565256535654565556565657565856595660566156625663566456655666566756685669567056715672567356745675567656775678567956805681568256835684568556865687568856895690569156925693569456955696569756985699570057015702570357045705570657075708570957105711571257135714571557165717571857195720572157225723572457255726572757285729573057315732573357345735573657375738573957405741574257435744574557465747574857495750575157525753575457555756575757585759576057615762576357645765576657675768576957705771577257735774577557765777577857795780578157825783578457855786578757885789579057915792579357945795579657975798579958005801580258035804580558065807580858095810581158125813581458155816581758185819582058215822582358245825582658275828582958305831583258335834583558365837583858395840584158425843584458455846584758485849585058515852585358545855585658575858585958605861586258635864586558665867586858695870587158725873587458755876587758785879588058815882588358845885588658875888588958905891589258935894589558965897589858995900590159025903590459055906590759085909591059115912591359145915591659175918591959205921592259235924592559265927592859295930593159325933593459355936593759385939594059415942594359445945594659475948594959505951595259535954595559565957595859595960596159625963596459655966596759685969597059715972597359745975597659775978597959805981598259835984598559865987598859895990599159925993599459955996599759985999600060016002600360046005600660076008600960106011601260136014601560166017601860196020602160226023602460256026602760286029603060316032603360346035603660376038603960406041604260436044604560466047604860496050605160526053605460556056605760586059606060616062606360646065606660676068606960706071607260736074607560766077607860796080608160826083608460856086608760886089609060916092609360946095609660976098609961006101610261036104610561066107610861096110611161126113611461156116611761186119612061216122612361246125612661276128612961306131613261336134613561366137613861396140614161426143614461456146614761486149615061516152615361546155615661576158615961606161616261636164616561666167616861696170617161726173617461756176617761786179618061816182618361846185618661876188618961906191619261936194619561966197619861996200620162026203620462056206620762086209621062116212621362146215621662176218621962206221622262236224622562266227622862296230623162326233623462356236623762386239624062416242624362446245624662476248624962506251625262536254625562566257625862596260626162626263626462656266626762686269627062716272627362746275627662776278627962806281628262836284628562866287628862896290629162926293629462956296629762986299630063016302630363046305630663076308630963106311631263136314631563166317631863196320632163226323632463256326632763286329633063316332633363346335633663376338633963406341634263436344634563466347634863496350635163526353635463556356635763586359636063616362636363646365636663676368636963706371637263736374637563766377637863796380638163826383638463856386638763886389639063916392639363946395639663976398639964006401640264036404640564066407640864096410641164126413641464156416641764186419642064216422642364246425642664276428642964306431643264336434643564366437643864396440644164426443644464456446644764486449645064516452645364546455645664576458645964606461646264636464646564666467646864696470647164726473647464756476647764786479648064816482648364846485648664876488648964906491649264936494649564966497649864996500650165026503650465056506650765086509651065116512651365146515651665176518651965206521652265236524652565266527652865296530653165326533653465356536653765386539654065416542654365446545654665476548654965506551655265536554655565566557655865596560656165626563656465656566656765686569657065716572657365746575657665776578657965806581658265836584658565866587658865896590659165926593659465956596659765986599660066016602660366046605660666076608660966106611661266136614661566166617661866196620662166226623662466256626662766286629663066316632663366346635663666376638663966406641664266436644664566466647664866496650665166526653665466556656665766586659666066616662666366646665666666676668666966706671667266736674667566766677667866796680668166826683668466856686668766886689669066916692669366946695669666976698669967006701670267036704670567066707670867096710671167126713671467156716671767186719672067216722672367246725672667276728672967306731673267336734673567366737673867396740674167426743674467456746674767486749675067516752675367546755675667576758675967606761676267636764676567666767676867696770677167726773677467756776677767786779678067816782678367846785678667876788678967906791679267936794679567966797679867996800680168026803680468056806680768086809681068116812681368146815681668176818681968206821682268236824682568266827682868296830683168326833683468356836683768386839684068416842684368446845684668476848684968506851685268536854685568566857685868596860686168626863686468656866686768686869687068716872687368746875687668776878687968806881688268836884688568866887688868896890689168926893689468956896689768986899690069016902690369046905690669076908690969106911691269136914691569166917691869196920692169226923692469256926692769286929693069316932693369346935693669376938693969406941694269436944694569466947694869496950695169526953695469556956695769586959696069616962696369646965696669676968696969706971697269736974697569766977697869796980698169826983698469856986698769886989699069916992699369946995699669976998699970007001700270037004700570067007700870097010701170127013701470157016701770187019702070217022702370247025702670277028702970307031703270337034703570367037703870397040704170427043704470457046704770487049705070517052705370547055705670577058705970607061706270637064706570667067706870697070707170727073707470757076707770787079708070817082708370847085708670877088708970907091709270937094709570967097709870997100710171027103710471057106710771087109711071117112711371147115711671177118711971207121712271237124712571267127712871297130713171327133713471357136713771387139714071417142714371447145714671477148714971507151715271537154715571567157715871597160716171627163716471657166716771687169717071717172717371747175717671777178717971807181718271837184718571867187718871897190719171927193719471957196719771987199720072017202720372047205720672077208720972107211721272137214721572167217721872197220722172227223722472257226722772287229723072317232723372347235723672377238723972407241724272437244724572467247724872497250725172527253725472557256725772587259726072617262726372647265726672677268726972707271727272737274727572767277727872797280728172827283728472857286728772887289729072917292729372947295729672977298729973007301730273037304730573067307730873097310731173127313731473157316731773187319732073217322732373247325732673277328732973307331733273337334733573367337733873397340734173427343734473457346734773487349735073517352735373547355735673577358735973607361736273637364736573667367736873697370737173727373737473757376737773787379738073817382738373847385738673877388738973907391739273937394739573967397739873997400740174027403740474057406740774087409741074117412741374147415741674177418741974207421742274237424742574267427742874297430743174327433743474357436743774387439744074417442744374447445744674477448744974507451745274537454745574567457745874597460746174627463746474657466746774687469747074717472747374747475747674777478747974807481748274837484748574867487748874897490749174927493749474957496749774987499750075017502750375047505750675077508750975107511751275137514751575167517751875197520752175227523752475257526752775287529753075317532753375347535753675377538753975407541754275437544754575467547754875497550755175527553755475557556755775587559756075617562756375647565756675677568756975707571757275737574757575767577757875797580758175827583758475857586758775887589759075917592759375947595759675977598759976007601760276037604760576067607760876097610761176127613761476157616761776187619762076217622762376247625762676277628762976307631763276337634763576367637763876397640764176427643764476457646764776487649765076517652765376547655765676577658765976607661766276637664766576667667766876697670767176727673767476757676767776787679768076817682768376847685768676877688768976907691769276937694769576967697769876997700770177027703770477057706770777087709771077117712771377147715771677177718771977207721772277237724772577267727772877297730773177327733773477357736773777387739774077417742774377447745774677477748774977507751775277537754775577567757775877597760776177627763776477657766776777687769777077717772777377747775777677777778777977807781778277837784778577867787778877897790779177927793779477957796779777987799780078017802780378047805780678077808780978107811781278137814781578167817781878197820782178227823782478257826782778287829783078317832783378347835783678377838783978407841784278437844784578467847784878497850785178527853785478557856785778587859786078617862786378647865786678677868786978707871787278737874787578767877787878797880788178827883788478857886788778887889789078917892789378947895789678977898789979007901790279037904790579067907790879097910791179127913791479157916791779187919792079217922792379247925792679277928792979307931793279337934793579367937793879397940794179427943794479457946794779487949795079517952795379547955795679577958795979607961796279637964796579667967796879697970797179727973797479757976797779787979798079817982798379847985798679877988798979907991799279937994799579967997799879998000800180028003800480058006800780088009801080118012801380148015801680178018801980208021802280238024802580268027802880298030803180328033803480358036803780388039804080418042804380448045804680478048804980508051805280538054805580568057805880598060806180628063806480658066806780688069807080718072807380748075807680778078807980808081808280838084808580868087808880898090809180928093809480958096809780988099810081018102810381048105810681078108810981108111811281138114811581168117811881198120812181228123812481258126812781288129813081318132813381348135813681378138813981408141814281438144814581468147814881498150815181528153815481558156815781588159816081618162816381648165816681678168816981708171817281738174817581768177817881798180818181828183818481858186818781888189819081918192819381948195819681978198819982008201820282038204820582068207820882098210821182128213821482158216821782188219822082218222822382248225822682278228822982308231823282338234823582368237823882398240824182428243824482458246824782488249825082518252825382548255825682578258825982608261826282638264826582668267826882698270827182728273827482758276827782788279828082818282828382848285828682878288828982908291829282938294829582968297829882998300830183028303830483058306830783088309831083118312831383148315831683178318831983208321832283238324832583268327832883298330833183328333833483358336833783388339834083418342834383448345834683478348834983508351835283538354835583568357835883598360836183628363836483658366836783688369837083718372837383748375837683778378837983808381838283838384838583868387838883898390839183928393839483958396839783988399840084018402840384048405840684078408840984108411841284138414841584168417841884198420842184228423842484258426842784288429843084318432843384348435843684378438843984408441844284438444844584468447844884498450845184528453845484558456845784588459846084618462846384648465846684678468846984708471847284738474847584768477847884798480848184828483848484858486848784888489849084918492849384948495849684978498849985008501850285038504850585068507850885098510851185128513851485158516851785188519852085218522852385248525852685278528852985308531853285338534853585368537853885398540854185428543854485458546854785488549855085518552855385548555855685578558855985608561856285638564856585668567856885698570857185728573857485758576857785788579858085818582858385848585858685878588858985908591859285938594859585968597859885998600860186028603860486058606860786088609861086118612861386148615861686178618861986208621862286238624862586268627862886298630863186328633863486358636863786388639864086418642864386448645864686478648864986508651865286538654865586568657865886598660866186628663866486658666866786688669867086718672867386748675867686778678867986808681868286838684868586868687868886898690869186928693869486958696869786988699870087018702870387048705870687078708870987108711871287138714871587168717871887198720872187228723872487258726872787288729873087318732873387348735873687378738873987408741874287438744874587468747874887498750875187528753875487558756875787588759876087618762876387648765876687678768876987708771877287738774877587768777877887798780878187828783878487858786878787888789879087918792879387948795879687978798879988008801880288038804880588068807880888098810881188128813881488158816881788188819882088218822882388248825882688278828882988308831883288338834883588368837883888398840884188428843884488458846884788488849885088518852885388548855885688578858885988608861886288638864886588668867886888698870887188728873887488758876887788788879888088818882888388848885888688878888888988908891889288938894889588968897889888998900890189028903890489058906890789088909891089118912891389148915891689178918891989208921892289238924892589268927892889298930893189328933893489358936893789388939894089418942894389448945894689478948894989508951895289538954895589568957895889598960896189628963896489658966896789688969897089718972897389748975897689778978897989808981898289838984898589868987898889898990899189928993899489958996899789988999900090019002900390049005900690079008900990109011901290139014901590169017901890199020902190229023902490259026902790289029903090319032903390349035903690379038903990409041904290439044904590469047904890499050905190529053905490559056905790589059906090619062906390649065906690679068906990709071907290739074907590769077907890799080908190829083908490859086908790889089909090919092909390949095909690979098909991009101910291039104910591069107910891099110911191129113911491159116911791189119912091219122912391249125912691279128912991309131913291339134913591369137913891399140914191429143914491459146914791489149915091519152915391549155915691579158915991609161916291639164916591669167916891699170917191729173917491759176917791789179918091819182918391849185918691879188918991909191919291939194919591969197919891999200920192029203920492059206920792089209921092119212921392149215921692179218921992209221922292239224922592269227922892299230923192329233923492359236923792389239924092419242924392449245924692479248924992509251925292539254925592569257925892599260926192629263926492659266926792689269927092719272927392749275927692779278927992809281928292839284928592869287928892899290929192929293929492959296929792989299930093019302930393049305930693079308930993109311931293139314931593169317931893199320932193229323932493259326932793289329933093319332933393349335933693379338933993409341934293439344934593469347934893499350935193529353935493559356935793589359936093619362936393649365936693679368 |
- --- a/configure
- +++ b/configure
- @@ -3350,6 +3350,9 @@ case "${target}" in
- *-*-freebsd*)
- noconfigdirs="$noconfigdirs target-newlib target-libgloss"
- ;;
- + ubicom32-*-*)
- + noconfigdirs="$noconfigdirs target-libffi"
- + ;;
- *-*-linux* | *-*-gnu* | *-*-k*bsd*-gnu | *-*-kopensolaris*-gnu)
- noconfigdirs="$noconfigdirs target-newlib target-libgloss"
- ;;
- --- /dev/null
- +++ b/gcc/config/ubicom32/constraints.md
- @@ -0,0 +1,149 @@
- +; Constraint definitions for Ubicom32
- +
- +; Copyright (C) 2009 Free Software Foundation, Inc.
- +; Contributed by Ubicom, Inc.
- +
- +; This file is part of GCC.
- +
- +; GCC is free software; you can redistribute it and/or modify it
- +; under the terms of the GNU General Public License as published
- +; by the Free Software Foundation; either version 3, or (at your
- +; option) any later version.
- +
- +; GCC is distributed in the hope that it will be useful, but WITHOUT
- +; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- +; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- +; License for more details.
- +
- +; You should have received a copy of the GNU General Public License
- +; along with GCC; see the file COPYING3. If not see
- +; <http://www.gnu.org/licenses/>.
- +
- +(define_register_constraint "a" "ALL_ADDRESS_REGS"
- + "An An register.")
- +
- +(define_register_constraint "d" "DATA_REGS"
- + "A Dn register.")
- +
- +(define_register_constraint "h" "ACC_REGS"
- + "An accumulator register.")
- +
- +(define_register_constraint "l" "ACC_LO_REGS"
- + "An accn_lo register.")
- +
- +(define_register_constraint "Z" "FDPIC_REG"
- + "The FD-PIC GOT pointer: A0.")
- +
- +(define_constraint "I"
- + "An 8-bit signed constant value."
- + (and (match_code "const_int")
- + (match_test "(ival >= -128) && (ival <= 127)")))
- +
- +(define_constraint "Q"
- + "An 8-bit signed constant value represented as unsigned."
- + (and (match_code "const_int")
- + (match_test "(ival >= 0x00) && (ival <= 0xff)")))
- +
- +(define_constraint "R"
- + "An 8-bit signed constant value represented as unsigned."
- + (and (match_code "const_int")
- + (match_test "((ival >= 0x0000) && (ival <= 0x007f)) || ((ival >= 0xff80) && (ival <= 0xffff))")))
- +
- +(define_constraint "J"
- + "A 7-bit unsigned constant value."
- + (and (match_code "const_int")
- + (match_test "(ival >= 0) && (ival <= 127)")))
- +
- +(define_constraint "K"
- + "A 7-bit unsigned constant value shifted << 1."
- + (and (match_code "const_int")
- + (match_test "(ival >= 0) && (ival <= 254) && ((ival & 1) == 0)")))
- +
- +(define_constraint "L"
- + "A 7-bit unsigned constant value shifted << 2."
- + (and (match_code "const_int")
- + (match_test "(ival >= 0) && (ival <= 508) && ((ival & 3) == 0)")))
- +
- +(define_constraint "M"
- + "A 5-bit unsigned constant value."
- + (and (match_code "const_int")
- + (match_test "(ival >= 0) && (ival <= 31)")))
- +
- +(define_constraint "N"
- + "A signed 16 bit constant value."
- + (and (match_code "const_int")
- + (match_test "(ival >= -32768) && (ival <= 32767)")))
- +
- +(define_constraint "O"
- + "An exact bitmask of contiguous 1 bits starting at bit 0."
- + (and (match_code "const_int")
- + (match_test "exact_log2 (ival + 1) != -1")))
- +
- +(define_constraint "P"
- + "A 7-bit negative constant value shifted << 2."
- + (and (match_code "const_int")
- + (match_test "(ival >= -504) && (ival <= 0) && ((ival & 3) == 0)")))
- +
- +(define_constraint "S"
- + "A symbolic reference."
- + (match_code "symbol_ref"))
- +
- +(define_constraint "Y"
- + "An FD-PIC symbolic reference."
- + (and (match_test "TARGET_FDPIC")
- + (match_test "GET_CODE (op) == UNSPEC")
- + (ior (match_test "XINT (op, 1) == UNSPEC_FDPIC_GOT")
- + (match_test "XINT (op, 1) == UNSPEC_FDPIC_GOT_FUNCDESC"))))
- +
- +(define_memory_constraint "T1"
- + "A memory operand that can be used for .1 instruction."
- + (and (match_test "memory_operand (op, GET_MODE(op))")
- + (match_test "GET_MODE (op) == QImode")))
- +
- +(define_memory_constraint "T2"
- + "A memory operand that can be used for .2 instruction."
- + (and (match_test "memory_operand (op, GET_MODE(op))")
- + (match_test "GET_MODE (op) == HImode")))
- +
- +(define_memory_constraint "T4"
- + "A memory operand that can be used for .4 instruction."
- + (and (match_test "memory_operand (op, GET_MODE(op))")
- + (ior (match_test "GET_MODE (op) == SImode")
- + (match_test "GET_MODE (op) == DImode")
- + (match_test "GET_MODE (op) == SFmode"))))
- +
- +(define_memory_constraint "U1"
- + "An offsettable memory operand that can be used for .1 instruction."
- + (and (match_test "memory_operand (op, GET_MODE(op))")
- + (match_test "GET_MODE (op) == QImode")
- + (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
- + (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
- + (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
- + (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
- + (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
- + (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
- +
- +(define_memory_constraint "U2"
- + "An offsettable memory operand that can be used for .2 instruction."
- + (and (match_test "memory_operand (op, GET_MODE(op))")
- + (match_test "GET_MODE (op) == HImode")
- + (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
- + (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
- + (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
- + (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
- + (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
- + (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
- +
- +(define_memory_constraint "U4"
- + "An offsettable memory operand that can be used for .4 instruction."
- + (and (match_test "memory_operand (op, GET_MODE(op))")
- + (ior (match_test "GET_MODE (op) == SImode")
- + (match_test "GET_MODE (op) == DImode")
- + (match_test "GET_MODE (op) == SFmode"))
- + (match_test "GET_CODE (XEXP (op, 0)) != POST_INC")
- + (match_test "GET_CODE (XEXP (op, 0)) != PRE_INC")
- + (match_test "GET_CODE (XEXP (op, 0)) != POST_DEC")
- + (match_test "GET_CODE (XEXP (op, 0)) != PRE_DEC")
- + (match_test "GET_CODE (XEXP (op, 0)) != POST_MODIFY")
- + (match_test "GET_CODE (XEXP (op, 0)) != PRE_MODIFY")))
- +
- --- /dev/null
- +++ b/gcc/config/ubicom32/crti.S
- @@ -0,0 +1,54 @@
- +/* Specialized code needed to support construction and destruction of
- + file-scope objects in C++ and Java code, and to support exception handling.
- + Copyright (C) 1999 Free Software Foundation, Inc.
- + Contributed by Charles-Antoine Gauthier ([email protected]).
- +
- +This file is part of GCC.
- +
- +GCC is free software; you can redistribute it and/or modify
- +it under the terms of the GNU General Public License as published by
- +the Free Software Foundation; either version 2, or (at your option)
- +any later version.
- +
- +GCC is distributed in the hope that it will be useful,
- +but WITHOUT ANY WARRANTY; without even the implied warranty of
- +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +GNU General Public License for more details.
- +
- +You should have received a copy of the GNU General Public License
- +along with GCC; see the file COPYING. If not, write to
- +the Free Software Foundation, 59 Temple Place - Suite 330,
- +Boston, MA 02111-1307, USA. */
- +
- +/* As a special exception, if you link this library with files
- + compiled with GCC to produce an executable, this does not cause
- + the resulting executable to be covered by the GNU General Public License.
- + This exception does not however invalidate any other reasons why
- + the executable file might be covered by the GNU General Public License. */
- +
- +/*
- + * This file just supplies function prologues for the .init and .fini
- + * sections. It is linked in before crtbegin.o.
- + */
- + .file "crti.o"
- + .ident "GNU C crti.o"
- +
- + .section .init
- + .align 2
- + .globl _init
- + .type _init, @function
- +_init:
- + move.4 -4(sp)++, a5
- +#ifdef __UBICOM32_FDPIC__
- + move.4 -4(sp)++, a0
- +#endif
- +
- + .section .fini
- + .align 2
- + .globl _fini
- + .type _fini, @function
- +_fini:
- + move.4 -4(sp)++, a5
- +#ifdef __UBICOM32_FDPIC__
- + move.4 -4(sp)++, a0
- +#endif
- --- /dev/null
- +++ b/gcc/config/ubicom32/crtn.S
- @@ -0,0 +1,47 @@
- +/* Specialized code needed to support construction and destruction of
- + file-scope objects in C++ and Java code, and to support exception handling.
- + Copyright (C) 1999 Free Software Foundation, Inc.
- + Contributed by Charles-Antoine Gauthier ([email protected]).
- +
- +This file is part of GCC.
- +
- +GCC is free software; you can redistribute it and/or modify
- +it under the terms of the GNU General Public License as published by
- +the Free Software Foundation; either version 2, or (at your option)
- +any later version.
- +
- +GCC is distributed in the hope that it will be useful,
- +but WITHOUT ANY WARRANTY; without even the implied warranty of
- +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +GNU General Public License for more details.
- +
- +You should have received a copy of the GNU General Public License
- +along with GCC; see the file COPYING. If not, write to
- +the Free Software Foundation, 59 Temple Place - Suite 330,
- +Boston, MA 02111-1307, USA. */
- +
- +/* As a special exception, if you link this library with files
- + compiled with GCC to produce an executable, this does not cause
- + the resulting executable to be covered by the GNU General Public License.
- + This exception does not however invalidate any other reasons why
- + the executable file might be covered by the GNU General Public License. */
- +
- +/*
- + * This file supplies function epilogues for the .init and .fini sections.
- + * It is linked in after all other files.
- + */
- +
- + .file "crtn.o"
- + .ident "GNU C crtn.o"
- +
- + .section .init
- +#ifdef __UBICOM32_FDPIC__
- + move.4 a0, (sp)4++
- +#endif
- + ret (sp)4++
- +
- + .section .fini
- +#ifdef __UBICOM32_FDPIC__
- + move.4 a0, (sp)4++
- +#endif
- + ret (sp)4++
- --- /dev/null
- +++ b/gcc/config/ubicom32/elf.h
- @@ -0,0 +1,29 @@
- +#undef STARTFILE_SPEC
- +#define STARTFILE_SPEC "\
- +%{msim:%{!shared:crt0%O%s}} \
- +crti%O%s crtbegin%O%s"
- +
- +#undef ENDFILE_SPEC
- +#define ENDFILE_SPEC "crtend%O%s crtn%O%s"
- +
- +#ifdef __UBICOM32_FDPIC__
- +#define CRT_CALL_STATIC_FUNCTION(SECTION_OP, FUNC) \
- + asm (SECTION_OP); \
- + asm ("move.4 a0, 0(sp);\n\t" \
- + "call a5," USER_LABEL_PREFIX #FUNC ";"); \
- + asm (TEXT_SECTION_ASM_OP);
- +#endif
- +
- +#undef SUBTARGET_DRIVER_SELF_SPECS
- +#define SUBTARGET_DRIVER_SELF_SPECS \
- + "%{mfdpic:-msim} "
- +
- +#define NO_IMPLICIT_EXTERN_C
- +
- +/*
- + * We need this to compile crtbegin/crtend. This should really be picked
- + * up from elfos.h but at the moment including elfos.h causes other more
- + * serous linker issues.
- + */
- +#define INIT_SECTION_ASM_OP "\t.section\t.init"
- +#define FINI_SECTION_ASM_OP "\t.section\t.fini"
- --- /dev/null
- +++ b/gcc/config/ubicom32/linux.h
- @@ -0,0 +1,80 @@
- +/* Definitions of target machine for Ubicom32-uclinux
- +
- + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- + 2009 Free Software Foundation, Inc.
- + Contributed by Ubicom, Inc.
- +
- + This file is part of GCC.
- +
- + GCC is free software; you can redistribute it and/or modify it
- + under the terms of the GNU General Public License as published
- + by the Free Software Foundation; either version 3, or (at your
- + option) any later version.
- +
- + GCC is distributed in the hope that it will be useful, but WITHOUT
- + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- + License for more details.
- +
- + You should have received a copy of the GNU General Public License
- + along with GCC; see the file COPYING3. If not see
- + <http://www.gnu.org/licenses/>. */
- +
- +/* Don't assume anything about the header files. */
- +#define NO_IMPLICIT_EXTERN_C
- +
- +#undef LIB_SPEC
- +#define LIB_SPEC \
- + "%{pthread:-lpthread} " \
- + "-lc"
- +
- +#undef LINK_GCC_C_SEQUENCE_SPEC
- +#define LINK_GCC_C_SEQUENCE_SPEC \
- + "%{static:--start-group} %G %L %{static:--end-group} " \
- + "%{!static: %G}"
- +
- +#undef STARTFILE_SPEC
- +#define STARTFILE_SPEC \
- + "%{!shared: %{pg|p|profile:gcrt1%O%s;pie:Scrt1%O%s;:crt1%O%s}} " \
- + "crtreloc%O%s crti%O%s %{shared|pie:crtbeginS%O%s;:crtbegin%O%s}"
- +
- +#undef ENDFILE_SPEC
- +#define ENDFILE_SPEC \
- + "%{shared|pie:crtendS%O%s;:crtend%O%s} crtn%O%s"
- +
- +/* taken from linux.h */
- +/* The GNU C++ standard library requires that these macros be defined. */
- +#undef CPLUSPLUS_CPP_SPEC
- +#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
- +
- +#define TARGET_OS_CPP_BUILTINS() \
- + do { \
- + builtin_define_std ("__UBICOM32__"); \
- + builtin_define_std ("__ubicom32__"); \
- + builtin_define ("__gnu_linux__"); \
- + builtin_define_std ("linux"); \
- + builtin_define_std ("unix"); \
- + builtin_assert ("system=linux"); \
- + builtin_assert ("system=unix"); \
- + builtin_assert ("system=posix"); \
- + } while (0)
- +
- +#define OBJECT_FORMAT_ELF
- +
- +
- +#undef DRIVER_SELF_SPECS
- +#define DRIVER_SELF_SPECS \
- + "%{!mno-fdpic:-mfdpic}"
- +
- +#undef LINK_SPEC
- +#define LINK_SPEC "%{mfdpic: -m elf32ubicom32fdpic -z text } %{shared} %{pie} \
- + %{static:-dn -Bstatic} \
- + %{shared:-G -Bdynamic} \
- + %{!shared: %{!static: \
- + %{rdynamic:-export-dynamic} \
- + %{!dynamic-linker:-dynamic-linker /lib/ld-uClibc.so.0}} \
- + %{static}} "
- +
- +/*
- +#define MD_UNWIND_SUPPORT "config/bfin/linux-unwind.h"
- +*/
- --- /dev/null
- +++ b/gcc/config/ubicom32/predicates.md
- @@ -0,0 +1,327 @@
- +; Predicate definitions for Ubicom32.
- +
- +; Copyright (C) 2009 Free Software Foundation, Inc.
- +; Contributed by Ubicom, Inc.
- +
- +; This file is part of GCC.
- +
- +; GCC is free software; you can redistribute it and/or modify it
- +; under the terms of the GNU General Public License as published
- +; by the Free Software Foundation; either version 3, or (at your
- +; option) any later version.
- +
- +; GCC is distributed in the hope that it will be useful, but WITHOUT
- +; ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- +; or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- +; License for more details.
- +
- +; You should have received a copy of the GNU General Public License
- +; along with GCC; see the file COPYING3. If not see
- +; <http://www.gnu.org/licenses/>.
- +
- +(define_predicate "ubicom32_move_operand"
- + (match_code "const_int, const_double, const, mem, subreg, reg, lo_sum")
- +{
- + if (CONST_INT_P (op))
- + return true;
- +
- + if (GET_CODE (op) == CONST_DOUBLE)
- + return true;
- +
- + if (GET_CODE (op) == CONST)
- + return memory_address_p (mode, op);
- +
- + if (GET_MODE (op) != mode)
- + return false;
- +
- + if (MEM_P (op))
- + return memory_address_p (mode, XEXP (op, 0));
- +
- + if (GET_CODE (op) == SUBREG) {
- + op = SUBREG_REG (op);
- +
- + if (REG_P (op))
- + return true;
- +
- + if (! MEM_P (op))
- + return false;
- +
- + /* Paradoxical SUBREG. */
- + if (GET_MODE_SIZE (mode) > GET_MODE_SIZE (GET_MODE (op)))
- + return false;
- +
- + return memory_address_p (GET_MODE (op), XEXP (op, 0));
- + }
- +
- + return register_operand (op, mode);
- +})
- +
- +;; Returns true if OP is either a symbol reference or a sum of a
- +;; symbol reference and a constant.
- +
- +(define_predicate "ubicom32_symbolic_address_operand"
- + (match_code "symbol_ref, label_ref, const")
- +{
- + switch (GET_CODE (op))
- + {
- + case SYMBOL_REF:
- + case LABEL_REF:
- + return true;
- +
- + case CONST:
- + op = XEXP (op, 0);
- + return ((GET_CODE (XEXP (op, 0)) == SYMBOL_REF
- + || GET_CODE (XEXP (op, 0)) == LABEL_REF)
- + && CONST_INT_P (XEXP (op, 1)));
- +
- + default:
- + return false;
- + }
- +})
- +
- +;; Return true if operand is the uClinux FD-PIC register.
- +
- +(define_predicate "ubicom32_fdpic_operand"
- + (match_code "reg")
- +{
- + if (! TARGET_FDPIC)
- + return false;
- +
- + if (!REG_P (op))
- + return false;
- +
- + if (GET_MODE (op) != mode && mode != VOIDmode)
- + return false;
- +
- + if (REGNO (op) != FDPIC_REGNUM && REGNO (op) < FIRST_PSEUDO_REGISTER)
- + return false;
- +
- + return true;
- +})
- +
- +(define_predicate "ubicom32_fdpic_got_offset_operand"
- + (match_code "unspec")
- +{
- + if (! TARGET_FDPIC)
- + return false;
- +
- + if (GET_CODE (op) != UNSPEC)
- + return false;
- +
- + if (XINT (op, 1) != UNSPEC_FDPIC_GOT
- + && XINT (op, 1) != UNSPEC_FDPIC_GOT_FUNCDESC)
- + return false;
- +
- + return true;
- +})
- +
- +(define_predicate "ubicom32_arith_operand"
- + (match_code "subreg, reg, const_int, lo_sum, mem")
- +{
- + return (ubicom32_move_operand (op, mode)
- + && ! ubicom32_symbolic_address_operand (op, mode)
- + && (! CONST_INT_P (op)
- + || satisfies_constraint_I (op)));
- +})
- +
- +(define_predicate "ubicom32_arith_operand_dot1"
- + (match_code "subreg, reg, const_int, lo_sum, mem")
- +{
- + return (ubicom32_move_operand (op, mode)
- + && ! ubicom32_symbolic_address_operand (op, mode)
- + && (! CONST_INT_P (op)
- + || satisfies_constraint_Q (op)));
- +})
- +
- +(define_predicate "ubicom32_arith_operand_dot2"
- + (match_code "subreg, reg, const_int, lo_sum, mem")
- +{
- + return (ubicom32_move_operand (op, mode)
- + && ! ubicom32_symbolic_address_operand (op, mode)
- + && (! CONST_INT_P (op)
- + || satisfies_constraint_R (op)));
- +})
- +
- +(define_predicate "ubicom32_compare_operand"
- + (match_code "subreg, reg, const_int, lo_sum, mem")
- +{
- + return (ubicom32_move_operand (op, mode)
- + && ! ubicom32_symbolic_address_operand (op, mode)
- + && (! CONST_INT_P (op)
- + || satisfies_constraint_N (op)));
- +})
- +
- +(define_predicate "ubicom32_compare_operator"
- + (match_code "compare"))
- +
- +(define_predicate "ubicom32_and_or_si3_operand"
- + (match_code "subreg, reg, const_int, lo_sum, mem")
- +{
- + return (ubicom32_arith_operand (op, mode)
- + || (CONST_INT_P (op)
- + && ((exact_log2 (INTVAL (op) + 1) != -1
- + && exact_log2 (INTVAL (op) + 1) <= 31)
- + || (exact_log2 (INTVAL (op)) != -1
- + && exact_log2 (INTVAL (op)) <= 31)
- + || (exact_log2 (~INTVAL (op)) != -1
- + && exact_log2 (~INTVAL (op)) <= 31))));
- +})
- +
- +(define_predicate "ubicom32_and_or_hi3_operand"
- + (match_code "subreg, reg, const_int, lo_sum, mem")
- +{
- + return (ubicom32_arith_operand (op, mode)
- + || (CONST_INT_P (op)
- + && exact_log2 (INTVAL (op) + 1) != -1
- + && exact_log2 (INTVAL (op) + 1) <= 15));
- +})
- +
- +(define_predicate "ubicom32_mem_or_address_register_operand"
- + (match_code "subreg, reg, mem")
- +{
- + unsigned int regno;
- +
- + if (MEM_P (op)
- + && memory_operand (op, mode))
- + return true;
- +
- + if (REG_P (op))
- + regno = REGNO (op);
- + else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
- + {
- + int offset;
- + if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
- + offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
- + else
- + offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
- + GET_MODE (SUBREG_REG (op)),
- + SUBREG_BYTE (op),
- + GET_MODE (op));
- + regno = REGNO (SUBREG_REG (op)) + offset;
- + }
- + else
- + return false;
- +
- + return (regno >= FIRST_PSEUDO_REGISTER
- + || REGNO_REG_CLASS (regno) == FDPIC_REG
- + || REGNO_REG_CLASS (regno) == ADDRESS_REGS);
- +})
- +
- +(define_predicate "ubicom32_data_register_operand"
- + (match_code "subreg, reg")
- +{
- + unsigned int regno;
- +
- + if (REG_P (op))
- + regno = REGNO (op);
- + else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
- + {
- + int offset;
- + if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
- + offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
- + else
- + offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
- + GET_MODE (SUBREG_REG (op)),
- + SUBREG_BYTE (op),
- + GET_MODE (op));
- + regno = REGNO (SUBREG_REG (op)) + offset;
- + }
- + else
- + return false;
- +
- + return ((regno >= FIRST_PSEUDO_REGISTER
- + && regno != REGNO (virtual_stack_vars_rtx))
- + || REGNO_REG_CLASS (regno) == DATA_REGS);
- +})
- +
- +(define_predicate "ubicom32_address_register_operand"
- + (match_code "subreg, reg")
- +{
- + unsigned int regno;
- +
- + if (REG_P (op))
- + regno = REGNO (op);
- + else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
- + {
- + int offset;
- + if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
- + offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
- + else
- + offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
- + GET_MODE (SUBREG_REG (op)),
- + SUBREG_BYTE (op),
- + GET_MODE (op));
- + regno = REGNO (SUBREG_REG (op)) + offset;
- + }
- + else
- + return false;
- +
- + return (regno >= FIRST_PSEUDO_REGISTER
- + || REGNO_REG_CLASS (regno) == FDPIC_REG
- + || REGNO_REG_CLASS (regno) == ADDRESS_REGS);
- +})
- +
- +(define_predicate "ubicom32_acc_lo_register_operand"
- + (match_code "subreg, reg")
- +{
- + unsigned int regno;
- +
- + if (REG_P (op))
- + regno = REGNO (op);
- + else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
- + {
- + int offset;
- + if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
- + offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
- + else
- + offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
- + GET_MODE (SUBREG_REG (op)),
- + SUBREG_BYTE (op),
- + GET_MODE (op));
- + regno = REGNO (SUBREG_REG (op)) + offset;
- + }
- + else
- + return false;
- +
- + return ((regno >= FIRST_PSEUDO_REGISTER
- + && regno != REGNO (virtual_stack_vars_rtx))
- + || REGNO_REG_CLASS (regno) == ACC_LO_REGS);
- +})
- +
- +(define_predicate "ubicom32_acc_hi_register_operand"
- + (match_code "subreg, reg")
- +{
- + unsigned int regno;
- +
- + if (REG_P (op))
- + regno = REGNO (op);
- + else if (GET_CODE (op) == SUBREG && REG_P (SUBREG_REG (op)))
- + {
- + int offset;
- + if (REGNO (SUBREG_REG (op)) >= FIRST_PSEUDO_REGISTER)
- + offset = SUBREG_BYTE (op) / (GET_MODE_SIZE (GET_MODE (op)));
- + else
- + offset = subreg_regno_offset (REGNO (SUBREG_REG (op)),
- + GET_MODE (SUBREG_REG (op)),
- + SUBREG_BYTE (op),
- + GET_MODE (op));
- + regno = REGNO (SUBREG_REG (op)) + offset;
- + }
- + else
- + return false;
- +
- + return ((regno >= FIRST_PSEUDO_REGISTER
- + && regno != REGNO (virtual_stack_vars_rtx))
- + || REGNO_REG_CLASS (regno) == ACC_REGS);
- +})
- +
- +(define_predicate "ubicom32_call_address_operand"
- + (match_code "symbol_ref, subreg, reg")
- +{
- + return (GET_CODE (op) == SYMBOL_REF || REG_P (op));
- +})
- +
- +(define_special_predicate "ubicom32_cc_register_operand"
- + (and (match_code "reg")
- + (match_test "REGNO (op) == CC_REGNUM")))
- +
- --- /dev/null
- +++ b/gcc/config/ubicom32/t-ubicom32
- @@ -0,0 +1,52 @@
- +# Name of assembly file containing libgcc1 functions.
- +# This entry must be present, but it can be empty if the target does
- +# not need any assembler functions to support its code generation.
- +CROSS_LIBGCC1 =
- +
- +# Alternatively if assembler functions *are* needed then define the
- +# entries below:
- +# CROSS_LIBGCC1 = libgcc1-asm.a
- +
- +LIB2FUNCS_EXTRA = \
- + $(srcdir)/config/udivmodsi4.c \
- + $(srcdir)/config/divmod.c \
- + $(srcdir)/config/udivmod.c
- +
- +# If any special flags are necessary when building libgcc2 put them here.
- +#
- +# TARGET_LIBGCC2_CFLAGS =
- +
- +# We want fine grained libraries, so use the new code to build the
- +# floating point emulation libraries.
- +FPBIT = fp-bit.c
- +DPBIT = dp-bit.c
- +
- +fp-bit.c: $(srcdir)/config/fp-bit.c
- + echo '#define FLOAT' > fp-bit.c
- + cat $(srcdir)/config/fp-bit.c >> fp-bit.c
- +
- +dp-bit.c: $(srcdir)/config/fp-bit.c
- + cat $(srcdir)/config/fp-bit.c > dp-bit.c
- +
- +# Commented out to speed up compiler development!
- +#
- +# MULTILIB_OPTIONS = march=ubicom32v1/march=ubicom32v2/march=ubicom32v3/march=ubicom32v4
- +# MULTILIB_DIRNAMES = ubicom32v1 ubicom32v2 ubicom32v3 ubicom32v4
- +
- +MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
- +MULTILIB_OPTIONS += mfdpic
- +MULTILIB_OPTIONS += mno-ipos-abi/mipos-abi
- +MULTILIB_OPTIONS += fno-leading-underscore/fleading-underscore
- +
- +# Assemble startup files.
- +$(T)crti.o: $(srcdir)/config/ubicom32/crti.S $(GCC_PASSES)
- + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- + -c -o $(T)crti.o -x assembler-with-cpp $(srcdir)/config/ubicom32/crti.S
- +
- +$(T)crtn.o: $(srcdir)/config/ubicom32/crtn.S $(GCC_PASSES)
- + $(GCC_FOR_TARGET) $(GCC_CFLAGS) $(MULTILIB_CFLAGS) $(INCLUDES) \
- + -c -o $(T)crtn.o -x assembler-with-cpp $(srcdir)/config/ubicom32/crtn.S
- +
- +# these parts are required because uClibc ldso needs them to link.
- +# they are not in the specfile so they will not be included automatically.
- +EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o crti.o crtn.o
- --- /dev/null
- +++ b/gcc/config/ubicom32/t-ubicom32-linux
- @@ -0,0 +1,35 @@
- +# Name of assembly file containing libgcc1 functions.
- +# This entry must be present, but it can be empty if the target does
- +# not need any assembler functions to support its code generation.
- +CROSS_LIBGCC1 =
- +
- +# Alternatively if assembler functions *are* needed then define the
- +# entries below:
- +# CROSS_LIBGCC1 = libgcc1-asm.a
- +
- +LIB2FUNCS_EXTRA = \
- + $(srcdir)/config/udivmodsi4.c \
- + $(srcdir)/config/divmod.c \
- + $(srcdir)/config/udivmod.c
- +
- +# If any special flags are necessary when building libgcc2 put them here.
- +#
- +# TARGET_LIBGCC2_CFLAGS =
- +
- +# We want fine grained libraries, so use the new code to build the
- +# floating point emulation libraries.
- +FPBIT = fp-bit.c
- +DPBIT = dp-bit.c
- +
- +fp-bit.c: $(srcdir)/config/fp-bit.c
- + echo '#define FLOAT' > fp-bit.c
- + cat $(srcdir)/config/fp-bit.c >> fp-bit.c
- +
- +dp-bit.c: $(srcdir)/config/fp-bit.c
- + cat $(srcdir)/config/fp-bit.c > dp-bit.c
- +
- +# We only support v3 and v4 ISAs for uClinux.
- +
- +MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
- +
- +#EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o crtbeginS.o crtendS.o
- --- /dev/null
- +++ b/gcc/config/ubicom32/t-ubicom32-uclinux
- @@ -0,0 +1,35 @@
- +# Name of assembly file containing libgcc1 functions.
- +# This entry must be present, but it can be empty if the target does
- +# not need any assembler functions to support its code generation.
- +CROSS_LIBGCC1 =
- +
- +# Alternatively if assembler functions *are* needed then define the
- +# entries below:
- +# CROSS_LIBGCC1 = libgcc1-asm.a
- +
- +LIB2FUNCS_EXTRA = \
- + $(srcdir)/config/udivmodsi4.c \
- + $(srcdir)/config/divmod.c \
- + $(srcdir)/config/udivmod.c
- +
- +# If any special flags are necessary when building libgcc2 put them here.
- +#
- +# TARGET_LIBGCC2_CFLAGS =
- +
- +# We want fine grained libraries, so use the new code to build the
- +# floating point emulation libraries.
- +FPBIT = fp-bit.c
- +DPBIT = dp-bit.c
- +
- +fp-bit.c: $(srcdir)/config/fp-bit.c
- + echo '#define FLOAT' > fp-bit.c
- + cat $(srcdir)/config/fp-bit.c >> fp-bit.c
- +
- +dp-bit.c: $(srcdir)/config/fp-bit.c
- + cat $(srcdir)/config/fp-bit.c > dp-bit.c
- +
- +# We only support v3 and v4 ISAs for uClinux.
- +
- +MULTILIB_OPTIONS = march=ubicom32v3/march=ubicom32v4
- +
- +EXTRA_MULTILIB_PARTS = crtbegin.o crtend.o # crtbeginS.o crtendS.o
- --- /dev/null
- +++ b/gcc/config/ubicom32/ubicom32-modes.def
- @@ -0,0 +1,30 @@
- +/* Definitions of target machine for GNU compiler, Ubicom32 architecture.
- + Copyright (C) 2009 Free Software Foundation, Inc.
- + Contributed by Ubicom, Inc.
- +
- + This file is part of GCC.
- +
- + GCC is free software; you can redistribute it and/or modify it
- + under the terms of the GNU General Public License as published
- + by the Free Software Foundation; either version 3, or (at your
- + option) any later version.
- +
- + GCC is distributed in the hope that it will be useful, but WITHOUT
- + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- + License for more details.
- +
- + You should have received a copy of the GNU General Public License
- + along with GCC; see the file COPYING3. If not see
- + <http://www.gnu.org/licenses/>. */
- +
- +/* Some insns set all condition code flags, some only set the Z and N flags, and
- + some only set the Z flag. */
- +
- +CC_MODE (CCW);
- +CC_MODE (CCWZN);
- +CC_MODE (CCWZ);
- +CC_MODE (CCS);
- +CC_MODE (CCSZN);
- +CC_MODE (CCSZ);
- +
- --- /dev/null
- +++ b/gcc/config/ubicom32/ubicom32-protos.h
- @@ -0,0 +1,84 @@
- +/* Function prototypes for Ubicom IP3000.
- +
- + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- + 2009 Free Software Foundation, Inc.
- + Contributed by Ubicom, Inc.
- +
- + This file is part of GNU CC.
- +
- + GNU CC is free software; you can redistribute it and/or modify it under
- + the terms of the GNU General Public License as published by the Free
- + Software Foundation; either version 2, or (at your option) any later
- + version.
- +
- + GNU CC is distributed in the hope that it will be useful, but WITHOUT
- + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- + FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- + for more details.
- +
- + You should have received a copy of the GNU General Public License along
- + with GNU CC; see the file COPYING. If not, write to the Free Software
- + Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
- +
- +#ifdef RTX_CODE
- +
- +#ifdef TREE_CODE
- +extern void ubicom32_va_start (tree, rtx);
- +#endif /* TREE_CODE */
- +
- +extern void ubicom32_print_operand (FILE *, rtx, int);
- +extern void ubicom32_print_operand_address (FILE *, rtx);
- +
- +extern void ubicom32_conditional_register_usage (void);
- +extern enum reg_class ubicom32_preferred_reload_class (rtx, enum reg_class);
- +extern int ubicom32_regno_ok_for_index_p (int, int);
- +extern void ubicom32_expand_movsi (rtx *);
- +extern void ubicom32_expand_addsi3 (rtx *);
- +extern int ubicom32_emit_mult_sequence (rtx *);
- +extern void ubicom32_emit_move_const_int (rtx, rtx);
- +extern bool ubicom32_legitimate_constant_p (rtx);
- +extern bool ubicom32_legitimate_address_p (enum machine_mode, rtx, int);
- +extern rtx ubicom32_legitimize_address (rtx, rtx, enum machine_mode);
- +extern rtx ubicom32_legitimize_reload_address (rtx, enum machine_mode, int, int);
- +extern void ubicom32_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1);
- +extern int ubicom32_mode_dependent_address_p (rtx);
- +extern void ubicom32_output_cond_jump (rtx, rtx, rtx);
- +extern void ubicom32_expand_eh_return (rtx *);
- +extern void ubicom32_expand_call_fdpic (rtx *);
- +extern void ubicom32_expand_call_value_fdpic (rtx *);
- +extern enum machine_mode ubicom32_select_cc_mode (RTX_CODE, rtx, rtx);
- +extern rtx ubicom32_gen_compare_reg (RTX_CODE, rtx, rtx);
- +extern int ubicom32_shiftable_const_int (int);
- +#endif /* RTX_CODE */
- +
- +#ifdef TREE_CODE
- +extern void init_cumulative_args (CUMULATIVE_ARGS *cum,
- + tree fntype,
- + struct rtx_def *libname,
- + int indirect);
- +extern struct rtx_def *function_arg (CUMULATIVE_ARGS *,
- + enum machine_mode, tree, int);
- +extern struct rtx_def *function_incoming_arg (CUMULATIVE_ARGS *,
- + enum machine_mode,
- + tree, int);
- +extern int function_arg_partial_nregs (CUMULATIVE_ARGS *,
- + enum machine_mode, tree, int);
- +extern struct rtx_def *ubicom32_va_arg (tree, tree);
- +extern int ubicom32_reg_parm_stack_space (tree);
- +#endif /* TREE_CODE */
- +
- +extern struct rtx_def * ubicom32_builtin_saveregs (void);
- +extern void asm_file_start (FILE *);
- +extern void ubicom32_expand_prologue (void);
- +extern void ubicom32_expand_epilogue (void);
- +extern int ubicom32_initial_elimination_offset (int, int);
- +extern int ubicom32_regno_ok_for_base_p (int, int);
- +extern bool ubicom32_hard_regno_mode_ok (unsigned int, enum machine_mode);
- +extern int ubicom32_can_use_return_insn_p (void);
- +extern rtx ubicom32_return_addr_rtx (int, rtx);
- +extern void ubicom32_optimization_options (int, int);
- +extern void ubicom32_override_options (void);
- +extern bool ubicom32_match_cc_mode (rtx, enum machine_mode);
- +
- +extern int ubicom32_reorg_completed;
- +
- --- /dev/null
- +++ b/gcc/config/ubicom32/ubicom32.c
- @@ -0,0 +1,2881 @@
- +/* Subroutines for insn-output.c for Ubicom32
- +
- + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- + 2009 Free Software Foundation, Inc.
- + Contributed by Ubicom, Inc.
- +
- + This file is part of GCC.
- +
- + GCC is free software; you can redistribute it and/or modify it
- + under the terms of the GNU General Public License as published
- + by the Free Software Foundation; either version 3, or (at your
- + option) any later version.
- +
- + GCC is distributed in the hope that it will be useful, but WITHOUT
- + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- + License for more details.
- +
- + You should have received a copy of the GNU General Public License
- + along with GCC; see the file COPYING3. If not see
- + <http://www.gnu.org/licenses/>. */
- +
- +#include "config.h"
- +#include "system.h"
- +#include "coretypes.h"
- +#include "tm.h"
- +#include "rtl.h"
- +#include "tree.h"
- +#include "regs.h"
- +#include "hard-reg-set.h"
- +#include "real.h"
- +#include "insn-config.h"
- +#include "conditions.h"
- +#include "insn-flags.h"
- +#include "output.h"
- +#include "insn-attr.h"
- +#include "insn-codes.h"
- +#include "flags.h"
- +#include "recog.h"
- +#include "expr.h"
- +#include "function.h"
- +#include "obstack.h"
- +#include "toplev.h"
- +#include "tm_p.h"
- +#include "tm-constrs.h"
- +#include "basic-block.h"
- +#include "integrate.h"
- +#include "target.h"
- +#include "target-def.h"
- +#include "reload.h"
- +#include "df.h"
- +#include "langhooks.h"
- +#include "optabs.h"
- +
- +static tree ubicom32_handle_fndecl_attribute (tree *, tree, tree, int, bool *);
- +static void ubicom32_layout_frame (void);
- +static void ubicom32_function_prologue (FILE *, HOST_WIDE_INT);
- +static void ubicom32_function_epilogue (FILE *, HOST_WIDE_INT);
- +static bool ubicom32_rtx_costs (rtx, int, int, int *, bool speed);
- +static bool ubicom32_fixed_condition_code_regs (unsigned int *,
- + unsigned int *);
- +static enum machine_mode ubicom32_cc_modes_compatible (enum machine_mode,
- + enum machine_mode);
- +static int ubicom32_naked_function_p (void);
- +static void ubicom32_machine_dependent_reorg (void);
- +static bool ubicom32_assemble_integer (rtx, unsigned int, int);
- +static void ubicom32_asm_init_sections (void);
- +static int ubicom32_arg_partial_bytes (CUMULATIVE_ARGS *, enum machine_mode,tree,
- + bool);
- +static bool ubicom32_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
- + enum machine_mode mode, const_tree type,
- + bool named ATTRIBUTE_UNUSED);
- +static bool ubicom32_callee_copies (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
- + enum machine_mode mode, const_tree type,
- + bool named ATTRIBUTE_UNUSED);
- +
- +static bool ubicom32_return_in_memory (const_tree type,
- + const_tree fntype ATTRIBUTE_UNUSED);
- +static bool ubicom32_is_base_reg (rtx, int);
- +static void ubicom32_init_builtins (void);
- +static rtx ubicom32_expand_builtin (tree, rtx, rtx, enum machine_mode, int);
- +static tree ubicom32_fold_builtin (tree, tree, bool);
- +static int ubicom32_get_valid_offset_mask (enum machine_mode);
- +static bool ubicom32_cannot_force_const_mem (rtx);
- +
- +/* Case values threshold */
- +int ubicom32_case_values_threshold = 6;
- +
- +/* Nonzero if this chip supports the Ubicom32 v3 ISA. */
- +int ubicom32_v3 = 1;
- +
- +/* Nonzero if this chip supports the Ubicom32 v4 ISA. */
- +int ubicom32_v4 = 1;
- +
- +/* Valid attributes:
- + naked - don't generate function prologue/epilogue and `ret' command. */
- +const struct attribute_spec ubicom32_attribute_table[] =
- +{
- + /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
- + { "naked", 0, 0, true, false, false, ubicom32_handle_fndecl_attribute },
- + { NULL, 0, 0, false, false, false, NULL }
- +};
- +
- +#undef TARGET_ASM_FUNCTION_PROLOGUE
- +#define TARGET_ASM_FUNCTION_PROLOGUE ubicom32_function_prologue
- +
- +#undef TARGET_ASM_FUNCTION_EPILOGUE
- +#define TARGET_ASM_FUNCTION_EPILOGUE ubicom32_function_epilogue
- +
- +#undef TARGET_ATTRIBUTE_TABLE
- +#define TARGET_ATTRIBUTE_TABLE ubicom32_attribute_table
- +
- +/* All addresses cost the same amount. */
- +#undef TARGET_ADDRESS_COST
- +#define TARGET_ADDRESS_COST hook_int_rtx_bool_0
- +
- +#undef TARGET_RTX_COSTS
- +#define TARGET_RTX_COSTS ubicom32_rtx_costs
- +
- +#undef TARGET_FIXED_CONDITION_CODE_REGS
- +#define TARGET_FIXED_CONDITION_CODE_REGS ubicom32_fixed_condition_code_regs
- +
- +#undef TARGET_CC_MODES_COMPATIBLE
- +#define TARGET_CC_MODES_COMPATIBLE ubicom32_cc_modes_compatible
- +
- +#undef TARGET_MACHINE_DEPENDENT_REORG
- +#define TARGET_MACHINE_DEPENDENT_REORG ubicom32_machine_dependent_reorg
- +
- +#undef TARGET_ASM_INTEGER
- +#define TARGET_ASM_INTEGER ubicom32_assemble_integer
- +
- +#undef TARGET_ASM_INIT_SECTIONS
- +#define TARGET_ASM_INIT_SECTIONS ubicom32_asm_init_sections
- +
- +#undef TARGET_ARG_PARTIAL_BYTES
- +#define TARGET_ARG_PARTIAL_BYTES ubicom32_arg_partial_bytes
- +
- +#undef TARGET_PASS_BY_REFERENCE
- +#define TARGET_PASS_BY_REFERENCE ubicom32_pass_by_reference
- +
- +#undef TARGET_CALLEE_COPIES
- +#define TARGET_CALLEE_COPIES ubicom32_callee_copies
- +
- +#undef TARGET_RETURN_IN_MEMORY
- +#define TARGET_RETURN_IN_MEMORY ubicom32_return_in_memory
- +
- +#undef TARGET_INIT_BUILTINS
- +#define TARGET_INIT_BUILTINS ubicom32_init_builtins
- +
- +#undef TARGET_EXPAND_BUILTIN
- +#define TARGET_EXPAND_BUILTIN ubicom32_expand_builtin
- +
- +#undef TARGET_FOLD_BUILTIN
- +#define TARGET_FOLD_BUILTIN ubicom32_fold_builtin
- +
- +#undef TARGET_CANNOT_FORCE_CONST_MEM
- +#define TARGET_CANNOT_FORCE_CONST_MEM ubicom32_cannot_force_const_mem
- +
- +struct gcc_target targetm = TARGET_INITIALIZER;
- +
- +static char save_regs[FIRST_PSEUDO_REGISTER];
- +static int nregs;
- +static int frame_size;
- +int ubicom32_stack_size = 0; /* size of allocated stack (including frame) */
- +int ubicom32_can_use_calli_to_ret;
- +
- +#define STACK_UNIT_BOUNDARY (STACK_BOUNDARY / BITS_PER_UNIT)
- +#define ROUND_CALL_BLOCK_SIZE(BYTES) \
- + (((BYTES) + (STACK_UNIT_BOUNDARY - 1)) & ~(STACK_UNIT_BOUNDARY - 1))
- +
- +/* In case of a PRE_INC, POST_INC, PRE_DEC, POST_DEC memory reference, we
- + must report the mode of the memory reference from PRINT_OPERAND to
- + PRINT_OPERAND_ADDRESS. */
- +enum machine_mode output_memory_reference_mode;
- +
- +/* Flag for some split insns from the ubicom32.md. */
- +int ubicom32_reorg_completed;
- +
- +enum reg_class const ubicom32_regclass_map[FIRST_PSEUDO_REGISTER] =
- +{
- + DATA_REGS,
- + DATA_REGS,
- + DATA_REGS,
- + DATA_REGS,
- + DATA_REGS,
- + DATA_REGS,
- + DATA_REGS,
- + DATA_REGS,
- + DATA_REGS,
- + DATA_REGS,
- + DATA_REGS,
- + DATA_REGS,
- + DATA_REGS,
- + DATA_REGS,
- + DATA_REGS,
- + DATA_REGS,
- + FDPIC_REG,
- + ADDRESS_REGS,
- + ADDRESS_REGS,
- + ADDRESS_REGS,
- + ADDRESS_REGS,
- + ADDRESS_REGS,
- + ADDRESS_REGS,
- + ADDRESS_REGS,
- + ACC_REGS,
- + ACC_LO_REGS,
- + ACC_REGS,
- + ACC_LO_REGS,
- + SOURCE3_REG,
- + ADDRESS_REGS,
- + NO_REGS, /* CC_REG must be NO_REGS */
- + SPECIAL_REGS,
- + SPECIAL_REGS,
- + SPECIAL_REGS,
- + SPECIAL_REGS,
- + SPECIAL_REGS,
- + SPECIAL_REGS,
- + SPECIAL_REGS,
- + SPECIAL_REGS
- +};
- +
- +rtx ubicom32_compare_op0;
- +rtx ubicom32_compare_op1;
- +
- +/* Handle command line option overrides. */
- +
- +void
- +ubicom32_override_options (void)
- +{
- + flag_pic = 0;
- +
- + if (strcmp (ubicom32_arch_name, "ubicom32v1") == 0) {
- + /* If we have a version 1 architecture then we want to avoid using jump
- + tables. */
- + ubicom32_case_values_threshold = 30000;
- + ubicom32_v3 = 0;
- + ubicom32_v4 = 0;
- + } else if (strcmp (ubicom32_arch_name, "ubicom32v2") == 0) {
- + ubicom32_v3 = 0;
- + ubicom32_v4 = 0;
- + } else if (strcmp (ubicom32_arch_name, "ubicom32v3") == 0) {
- + ubicom32_v3 = 1;
- + ubicom32_v4 = 0;
- + } else if (strcmp (ubicom32_arch_name, "ubicom32v4") == 0) {
- + ubicom32_v3 = 1;
- + ubicom32_v4 = 1;
- + }
- +
- + /* There is no single unaligned SI op for PIC code. Sometimes we
- + need to use ".4byte" and sometimes we need to use ".picptr".
- + See ubicom32_assemble_integer for details. */
- + if (TARGET_FDPIC)
- + targetm.asm_out.unaligned_op.si = 0;
- +}
- +
- +void
- +ubicom32_conditional_register_usage (void)
- +{
- + /* If we're using the old ipOS ABI we need to make D10 through D13
- + caller-clobbered. */
- + if (TARGET_IPOS_ABI)
- + {
- + call_used_regs[D10_REGNUM] = 1;
- + call_used_regs[D11_REGNUM] = 1;
- + call_used_regs[D12_REGNUM] = 1;
- + call_used_regs[D13_REGNUM] = 1;
- + }
- +}
- +
- +/* We have some number of optimizations that don't really work for the Ubicom32
- + architecture so we deal with them here. */
- +
- +void
- +ubicom32_optimization_options (int level ATTRIBUTE_UNUSED,
- + int size ATTRIBUTE_UNUSED)
- +{
- + /* The tree IVOPTs pass seems to do really bad things for the Ubicom32
- + architecture - it tends to turn things that would happily use pre/post
- + increment/decrement into operations involving unecessary loop
- + indicies. */
- + flag_ivopts = 0;
- +
- + /* We have problems where DSE at the RTL level misses partial stores
- + to the stack. For now we disable it to avoid this. */
- + flag_dse = 0;
- +}
- +
- +/* Print operand X using operand code CODE to assembly language output file
- + FILE. */
- +
- +void
- +ubicom32_print_operand (FILE *file, rtx x, int code)
- +{
- + switch (code)
- + {
- + case 'A':
- + /* Identify the correct accumulator to use. */
- + if (REGNO (x) == ACC0_HI_REGNUM || REGNO (x) == ACC0_LO_REGNUM)
- + fprintf (file, "acc0");
- + else if (REGNO (x) == ACC1_HI_REGNUM || REGNO (x) == ACC1_LO_REGNUM)
- + fprintf (file, "acc1");
- + else
- + abort ();
- + break;
- +
- + case 'b':
- + case 'B':
- + {
- + enum machine_mode mode;
- +
- + mode = GET_MODE (XEXP (x, 0));
- +
- + /* These are normal and reversed branches. */
- + switch (code == 'b' ? GET_CODE (x) : reverse_condition (GET_CODE (x)))
- + {
- + case NE:
- + fprintf (file, "ne");
- + break;
- +
- + case EQ:
- + fprintf (file, "eq");
- + break;
- +
- + case GE:
- + if (mode == CCSZNmode || mode == CCWZNmode)
- + fprintf (file, "pl");
- + else
- + fprintf (file, "ge");
- + break;
- +
- + case GT:
- + fprintf (file, "gt");
- + break;
- +
- + case LE:
- + fprintf (file, "le");
- + break;
- +
- + case LT:
- + if (mode == CCSZNmode || mode == CCWZNmode)
- + fprintf (file, "mi");
- + else
- + fprintf (file, "lt");
- + break;
- +
- + case GEU:
- + fprintf (file, "cs");
- + break;
- +
- + case GTU:
- + fprintf (file, "hi");
- + break;
- +
- + case LEU:
- + fprintf (file, "ls");
- + break;
- +
- + case LTU:
- + fprintf (file, "cc");
- + break;
- +
- + default:
- + abort ();
- + }
- + }
- + break;
- +
- + case 'C':
- + /* This is used for the operand to a call instruction;
- + if it's a REG, enclose it in parens, else output
- + the operand normally. */
- + if (REG_P (x))
- + {
- + fputc ('(', file);
- + ubicom32_print_operand (file, x, 0);
- + fputc (')', file);
- + }
- + else
- + ubicom32_print_operand (file, x, 0);
- + break;
- +
- + case 'd':
- + /* Bit operations we need bit numbers. */
- + fprintf (file, "%d", exact_log2 (INTVAL (x)));
- + break;
- +
- + case 'D':
- + /* Bit operations we need bit numbers. */
- + fprintf (file, "%d", exact_log2 (~ INTVAL (x)));
- + break;
- +
- + case 'E':
- + /* For lea, which we use to add address registers.
- + We don't want the '#' on a constant. */
- + if (CONST_INT_P (x))
- + {
- + fprintf (file, "%ld", INTVAL (x));
- + break;
- + }
- + /* FALL THROUGH */
- +
- + default:
- + switch (GET_CODE (x))
- + {
- + case MEM:
- + output_memory_reference_mode = GET_MODE (x);
- + output_address (XEXP (x, 0));
- + break;
- +
- + case PLUS:
- + output_address (x);
- + break;
- +
- + case REG:
- + fprintf (file, "%s", reg_names[REGNO (x)]);
- + break;
- +
- + case SUBREG:
- + fprintf (file, "%s", reg_names[subreg_regno (x)]);
- + break;
- +
- + /* This will only be single precision.... */
- + case CONST_DOUBLE:
- + {
- + unsigned long val;
- + REAL_VALUE_TYPE rv;
- +
- + REAL_VALUE_FROM_CONST_DOUBLE (rv, x);
- + REAL_VALUE_TO_TARGET_SINGLE (rv, val);
- + fprintf (file, "0x%lx", val);
- + break;
- + }
- +
- + case CONST_INT:
- + case SYMBOL_REF:
- + case CONST:
- + case LABEL_REF:
- + case CODE_LABEL:
- + case LO_SUM:
- + ubicom32_print_operand_address (file, x);
- + break;
- +
- + case HIGH:
- + fprintf (file, "#%%hi(");
- + ubicom32_print_operand_address (file, XEXP (x, 0));
- + fprintf (file, ")");
- + break;
- +
- + case UNSPEC:
- + switch (XINT (x, 1))
- + {
- + case UNSPEC_FDPIC_GOT:
- + fprintf (file, "#%%got_lo(");
- + ubicom32_print_operand_address (file, XVECEXP (x, 0, 0));
- + fprintf (file, ")");
- + break;
- +
- + case UNSPEC_FDPIC_GOT_FUNCDESC:
- + fprintf (file, "#%%got_funcdesc_lo(");
- + ubicom32_print_operand_address (file, XVECEXP (x, 0, 0));
- + fprintf (file, ")");
- + break;
- +
- + default:
- + abort ();
- + }
- + break;
- +
- + default:
- + abort ();
- + }
- + break;
- + }
- +}
- +
- +/* Output assembly language output for the address ADDR to FILE. */
- +
- +void
- +ubicom32_print_operand_address (FILE *file, rtx addr)
- +{
- + switch (GET_CODE (addr))
- + {
- + case POST_INC:
- + ubicom32_print_operand_address (file, XEXP (addr, 0));
- + fprintf (file, "%d++", GET_MODE_SIZE (output_memory_reference_mode));
- + break;
- +
- + case PRE_INC:
- + fprintf (file, "%d", GET_MODE_SIZE (output_memory_reference_mode));
- + ubicom32_print_operand_address (file, XEXP (addr, 0));
- + fprintf (file, "++");
- + break;
- +
- + case POST_DEC:
- + ubicom32_print_operand_address (file, XEXP (addr, 0));
- + fprintf (file, "%d++", -GET_MODE_SIZE (output_memory_reference_mode));
- + break;
- +
- + case PRE_DEC:
- + fprintf (file, "%d", -GET_MODE_SIZE (output_memory_reference_mode));
- + ubicom32_print_operand_address (file, XEXP (addr, 0));
- + fprintf (file, "++");
- + break;
- +
- + case POST_MODIFY:
- + ubicom32_print_operand_address (file, XEXP (addr, 0));
- + fprintf (file, "%ld++", INTVAL (XEXP (XEXP (addr,1), 1)));
- + break;
- +
- + case PRE_MODIFY:
- + fprintf (file, "%ld", INTVAL (XEXP (XEXP (addr,1), 1)));
- + ubicom32_print_operand_address (file, XEXP (addr, 0));
- + fprintf (file, "++");
- + break;
- +
- + case REG:
- + fputc ('(', file);
- + fprintf (file, "%s", reg_names[REGNO (addr)]);
- + fputc (')', file);
- + break;
- +
- + case PLUS:
- + {
- + rtx base = XEXP (addr, 0);
- + rtx index = XEXP (addr, 1);
- +
- + /* Switch around addresses of the form index * scaling + base. */
- + if (! ubicom32_is_base_reg (base, 1))
- + {
- + rtx tmp = base;
- + base = index;
- + index = tmp;
- + }
- +
- + if (CONST_INT_P (index))
- + {
- + fprintf (file, "%ld", INTVAL (index));
- + fputc ('(', file);
- + fputs (reg_names[REGNO (base)], file);
- + }
- + else if (GET_CODE (index) == MULT
- + || REG_P (index))
- + {
- + if (GET_CODE (index) == MULT)
- + index = XEXP (index, 0);
- + fputc ('(', file);
- + fputs (reg_names[REGNO (base)], file);
- + fputc (',', file);
- + fputs (reg_names[REGNO (index)], file);
- + }
- + else
- + abort ();
- +
- + fputc (')', file);
- + break;
- + }
- +
- + case LO_SUM:
- + fprintf (file, "%%lo(");
- + ubicom32_print_operand (file, XEXP (addr, 1), 'L');
- + fprintf (file, ")(");
- + ubicom32_print_operand (file, XEXP (addr, 0), 0);
- + fprintf (file, ")");
- + break;
- +
- + case CONST_INT:
- + fputc ('#', file);
- + output_addr_const (file, addr);
- + break;
- +
- + default:
- + output_addr_const (file, addr);
- + break;
- + }
- +}
- +
- +/* X and Y are two things to compare using CODE. Emit the compare insn and
- + return the rtx for the cc reg in the proper mode. */
- +
- +rtx
- +ubicom32_gen_compare_reg (enum rtx_code code, rtx x, rtx y)
- +{
- + enum machine_mode mode = SELECT_CC_MODE (code, x, y);
- + rtx cc_reg;
- +
- + cc_reg = gen_rtx_REG (mode, CC_REGNUM);
- +
- + emit_insn (gen_rtx_SET (VOIDmode, cc_reg,
- + gen_rtx_COMPARE (mode, x, y)));
- +
- + return cc_reg;
- +}
- +
- +/* Given a comparison code (EQ, NE, etc.) and the first operand of a COMPARE,
- + return the mode to be used for the comparison. */
- +
- +enum machine_mode
- +ubicom32_select_cc_mode (enum rtx_code op, rtx x, rtx y)
- +{
- + /* Is this a short compare? */
- + if (GET_MODE (x) == QImode
- + || GET_MODE (x) == HImode
- + || GET_MODE (y) == QImode
- + || GET_MODE (y) == HImode)
- + {
- + switch (op)
- + {
- + case EQ :
- + case NE :
- + return CCSZmode;
- +
- + case GE:
- + case LT:
- + if (y == const0_rtx)
- + return CCSZNmode;
- +
- + default :
- + return CCSmode;
- + }
- + }
- +
- + /* We have a word compare. */
- + switch (op)
- + {
- + case EQ :
- + case NE :
- + return CCWZmode;
- +
- + case GE :
- + case LT :
- + if (y == const0_rtx)
- + return CCWZNmode;
- +
- + default :
- + return CCWmode;
- + }
- +}
- +
- +/* Return TRUE or FALSE depending on whether the first SET in INSN
- + has source and destination with matching CC modes, and that the
- + CC mode is at least as constrained as REQ_MODE. */
- +bool
- +ubicom32_match_cc_mode (rtx insn, enum machine_mode req_mode)
- +{
- + rtx set;
- + enum machine_mode set_mode;
- +
- + set = PATTERN (insn);
- + if (GET_CODE (set) == PARALLEL)
- + set = XVECEXP (set, 0, 0);
- + gcc_assert (GET_CODE (set) == SET);
- + gcc_assert (GET_CODE (SET_SRC (set)) == COMPARE);
- +
- + /* SET_MODE is the mode we have in the instruction. This must either
- + be the same or less restrictive that the required mode REQ_MODE. */
- + set_mode = GET_MODE (SET_DEST (set));
- +
- + switch (req_mode)
- + {
- + case CCSZmode:
- + if (set_mode != CCSZmode)
- + return 0;
- + break;
- +
- + case CCSZNmode:
- + if (set_mode != CCSZmode
- + && set_mode != CCSZNmode)
- + return 0;
- + break;
- +
- + case CCSmode:
- + if (set_mode != CCSmode
- + && set_mode != CCSZmode
- + && set_mode != CCSZNmode)
- + return 0;
- + break;
- +
- + case CCWZmode:
- + if (set_mode != CCWZmode)
- + return 0;
- + break;
- +
- + case CCWZNmode:
- + if (set_mode != CCWZmode
- + && set_mode != CCWZNmode)
- + return 0;
- + break;
- +
- + case CCWmode:
- + if (set_mode != CCWmode
- + && set_mode != CCWZmode
- + && set_mode != CCWZNmode)
- + return 0;
- + break;
- +
- + default:
- + gcc_unreachable ();
- + }
- +
- + return (GET_MODE (SET_SRC (set)) == set_mode);
- +}
- +
- +/* Replace the comparison OP0 CODE OP1 by a semantically equivalent one
- + that we can implement more efficiently. */
- +
- +void
- +ubicom32_canonicalize_comparison (enum rtx_code *code, rtx *op0, rtx *op1)
- +{
- + /* If we have a REG and a MEM then compare the MEM with the REG and not
- + the other way round. */
- + if (REG_P (*op0) && MEM_P (*op1))
- + {
- + rtx tem = *op0;
- + *op0 = *op1;
- + *op1 = tem;
- + *code = swap_condition (*code);
- + return;
- + }
- +
- + /* If we have a REG and a CONST_INT then we may want to reverse things
- + if the constant can be represented as an "I" constraint. */
- + if (REG_P (*op0) && CONST_INT_P (*op1) && satisfies_constraint_I (*op1))
- + {
- + rtx tem = *op0;
- + *op0 = *op1;
- + *op1 = tem;
- + *code = swap_condition (*code);
- + return;
- + }
- +}
- +
- +/* Return the fixed registers used for condition codes. */
- +
- +static bool
- +ubicom32_fixed_condition_code_regs (unsigned int *p1, unsigned int *p2)
- +{
- + *p1 = CC_REGNUM;
- + *p2 = INVALID_REGNUM;
- +
- + return true;
- +}
- +
- +/* If two condition code modes are compatible, return a condition code
- + mode which is compatible with both. Otherwise, return
- + VOIDmode. */
- +
- +static enum machine_mode
- +ubicom32_cc_modes_compatible (enum machine_mode m1, enum machine_mode m2)
- +{
- + if (m1 == m2)
- + return m1;
- +
- + if (GET_MODE_CLASS (m1) != MODE_CC || GET_MODE_CLASS (m2) != MODE_CC)
- + return VOIDmode;
- +
- + switch (m1)
- + {
- + case CCWmode:
- + if (m2 == CCWZNmode || m2 == CCWZmode)
- + return m1;
- +
- + return VOIDmode;
- +
- + case CCWZNmode:
- + if (m2 == CCWmode)
- + return m2;
- +
- + if (m2 == CCWZmode)
- + return m1;
- +
- + return VOIDmode;
- +
- + case CCWZmode:
- + if (m2 == CCWmode || m2 == CCWZNmode)
- + return m2;
- +
- + return VOIDmode;
- +
- + case CCSmode:
- + if (m2 == CCSZNmode || m2 == CCSZmode)
- + return m1;
- +
- + return VOIDmode;
- +
- + case CCSZNmode:
- + if (m2 == CCSmode)
- + return m2;
- +
- + if (m2 == CCSZmode)
- + return m1;
- +
- + return VOIDmode;
- +
- + case CCSZmode:
- + if (m2 == CCSmode || m2 == CCSZNmode)
- + return m2;
- +
- + return VOIDmode;
- +
- + default:
- + gcc_unreachable ();
- + }
- +}
- +
- +static rtx
- +ubicom32_legitimize_fdpic_address_symbol (rtx orig, rtx reg, rtx fdpic_reg)
- +{
- + int unspec;
- + rtx got_offs;
- + rtx got_offs_scaled;
- + rtx plus_scaled;
- + rtx tmp;
- + rtx new_rtx;
- +
- + gcc_assert (reg != 0);
- +
- + if (GET_CODE (orig) == SYMBOL_REF
- + && SYMBOL_REF_FUNCTION_P (orig))
- + unspec = UNSPEC_FDPIC_GOT_FUNCDESC;
- + else
- + unspec = UNSPEC_FDPIC_GOT;
- +
- + got_offs = gen_reg_rtx (SImode);
- + tmp = gen_rtx_UNSPEC (Pmode, gen_rtvec (1, orig), unspec);
- + emit_move_insn (got_offs, tmp);
- +
- + got_offs_scaled = gen_rtx_MULT (SImode, got_offs, GEN_INT (4));
- + plus_scaled = gen_rtx_PLUS (Pmode, fdpic_reg, got_offs_scaled);
- + new_rtx = gen_const_mem (Pmode, plus_scaled);
- + emit_move_insn (reg, new_rtx);
- +
- + return reg;
- +}
- +
- +static rtx
- +ubicom32_legitimize_fdpic_address (rtx orig, rtx reg, rtx fdpic_reg)
- +{
- + rtx addr = orig;
- + rtx new_rtx = orig;
- +
- + if (GET_CODE (addr) == CONST || GET_CODE (addr) == PLUS)
- + {
- + rtx base;
- +
- + if (GET_CODE (addr) == CONST)
- + {
- + addr = XEXP (addr, 0);
- + gcc_assert (GET_CODE (addr) == PLUS);
- + }
- +
- + base = ubicom32_legitimize_fdpic_address_symbol (XEXP (addr, 0), reg, fdpic_reg);
- + return gen_rtx_PLUS (Pmode, base, XEXP (addr, 1));
- + }
- +
- + return new_rtx;
- +}
- +
- +/* Code generation. */
- +
- +void
- +ubicom32_expand_movsi (rtx *operands)
- +{
- + if (GET_CODE (operands[1]) == SYMBOL_REF
- + || (GET_CODE (operands[1]) == CONST
- + && GET_CODE (XEXP (operands[1], 0)) == PLUS
- + && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == SYMBOL_REF)
- + || CONSTANT_ADDRESS_P (operands[1]))
- + {
- + if (TARGET_FDPIC)
- + {
- + rtx tmp;
- + rtx fdpic_reg;
- +
- + gcc_assert (can_create_pseudo_p ());
- + tmp = gen_reg_rtx (Pmode);
- + fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
- + if (GET_CODE (operands[1]) == SYMBOL_REF
- + || GET_CODE (operands[1]) == LABEL_REF)
- + operands[1] = ubicom32_legitimize_fdpic_address_symbol (operands[1], tmp, fdpic_reg);
- + else
- + operands[1] = ubicom32_legitimize_fdpic_address (operands[1], tmp, fdpic_reg);
- + }
- + else
- + {
- + rtx tmp;
- + enum machine_mode mode;
- +
- + /* We want to avoid reusing operand 0 if we can because it limits
- + our ability to optimize later. */
- + tmp = ! can_create_pseudo_p () ? operands[0] : gen_reg_rtx (Pmode);
- +
- + mode = GET_MODE (operands[0]);
- + emit_insn (gen_rtx_SET (VOIDmode, tmp,
- + gen_rtx_HIGH (mode, operands[1])));
- + operands[1] = gen_rtx_LO_SUM (mode, tmp, operands[1]);
- + if (can_create_pseudo_p() && ! REG_P (operands[0]))
- + {
- + tmp = gen_reg_rtx (mode);
- + emit_insn (gen_rtx_SET (VOIDmode, tmp, operands[1]));
- + operands[1] = tmp;
- + }
- + }
- + }
- +}
- +
- +/* Emit code for addsi3. */
- +
- +void
- +ubicom32_expand_addsi3 (rtx *operands)
- +{
- + rtx op, clob;
- +
- + if (can_create_pseudo_p ())
- + {
- + /* If we have a non-data reg for operand 1 then prefer that over
- + a CONST_INT in operand 2. */
- + if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
- + && CONST_INT_P (operands[2]))
- + operands[2] = copy_to_mode_reg (SImode, operands[2]);
- +
- + if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
- + operands[2] = copy_to_mode_reg (SImode, operands[2]);
- + }
- +
- + /* Emit the instruction. */
- +
- + op = gen_rtx_SET (VOIDmode, operands[0],
- + gen_rtx_PLUS (SImode, operands[1], operands[2]));
- +
- + if (! can_create_pseudo_p ())
- + {
- + /* Reload doesn't know about the flags register, and doesn't know that
- + it doesn't want to clobber it. We can only do this with PLUS. */
- + emit_insn (op);
- + }
- + else
- + {
- + clob = gen_rtx_CLOBBER (VOIDmode, gen_rtx_REG (CCmode, CC_REGNUM));
- + emit_insn (gen_rtx_PARALLEL (VOIDmode, gen_rtvec (2, op, clob)));
- + }
- +}
- +
- +/* Emit code for mulsi3. Return 1 if we have generated all the code
- + necessary to do the multiplication. */
- +
- +int
- +ubicom32_emit_mult_sequence (rtx *operands)
- +{
- + if (! ubicom32_v4)
- + {
- + rtx a1, a1_1, a2;
- + rtx b1, b1_1, b2;
- + rtx mac_lo_rtx;
- + rtx t1, t2, t3;
- +
- + /* Give up if we cannot create new pseudos. */
- + if (!can_create_pseudo_p())
- + return 0;
- +
- + /* Synthesize 32-bit multiplication using 16-bit operations:
- +
- + a1 = highpart (a)
- + a2 = lowpart (a)
- +
- + b1 = highpart (b)
- + b2 = lowpart (b)
- +
- + c = (a1 * b1) << 32 + (a1 * b2) << 16 + (a2 * b1) << 16 + a2 * b2
- + = 0 + (a1 * b2) << 16 + (a2 * b1) << 16 + a2 * b2
- + ^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ^^^^^^^
- + Signed Signed Unsigned */
- +
- + if (!ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])))
- + {
- + rtx op1;
- +
- + op1 = gen_reg_rtx (SImode);
- + emit_move_insn (op1, operands[1]);
- + operands[1] = op1;
- + }
- +
- + if (!ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))
- + {
- + rtx op2;
- +
- + op2 = gen_reg_rtx (SImode);
- + emit_move_insn (op2, operands[2]);
- + operands[2] = op2;
- + }
- +
- + /* a1 = highpart (a) */
- + a1 = gen_reg_rtx (HImode);
- + a1_1 = gen_reg_rtx (SImode);
- + emit_insn (gen_ashrsi3 (a1_1, operands[1], GEN_INT (16)));
- + emit_move_insn (a1, gen_lowpart (HImode, a1_1));
- +
- + /* a2 = lowpart (a) */
- + a2 = gen_reg_rtx (HImode);
- + emit_move_insn (a2, gen_lowpart (HImode, operands[1]));
- +
- + /* b1 = highpart (b) */
- + b1 = gen_reg_rtx (HImode);
- + b1_1 = gen_reg_rtx (SImode);
- + emit_insn (gen_ashrsi3 (b1_1, operands[2], GEN_INT (16)));
- + emit_move_insn (b1, gen_lowpart (HImode, b1_1));
- +
- + /* b2 = lowpart (b) */
- + b2 = gen_reg_rtx (HImode);
- + emit_move_insn (b2, gen_lowpart (HImode, operands[2]));
- +
- + /* t1 = (a1 * b2) << 16 */
- + t1 = gen_reg_rtx (SImode);
- + mac_lo_rtx = gen_rtx_REG (SImode, ACC0_LO_REGNUM);
- + emit_insn (gen_mulhisi3 (mac_lo_rtx, a1, b2));
- + emit_insn (gen_ashlsi3 (t1, mac_lo_rtx, GEN_INT (16)));
- +
- + /* t2 = (a2 * b1) << 16 */
- + t2 = gen_reg_rtx (SImode);
- + emit_insn (gen_mulhisi3 (mac_lo_rtx, a2, b1));
- + emit_insn (gen_ashlsi3 (t2, mac_lo_rtx, GEN_INT (16)));
- +
- + /* mac_lo = a2 * b2 */
- + emit_insn (gen_umulhisi3 (mac_lo_rtx, a2, b2));
- +
- + /* t3 = t1 + t2 */
- + t3 = gen_reg_rtx (SImode);
- + emit_insn (gen_addsi3 (t3, t1, t2));
- +
- + /* c = t3 + mac_lo_rtx */
- + emit_insn (gen_addsi3 (operands[0], mac_lo_rtx, t3));
- +
- + return 1;
- + }
- + else
- + {
- + rtx acc_rtx;
- +
- + /* Give up if we cannot create new pseudos. */
- + if (!can_create_pseudo_p())
- + return 0;
- +
- + if (!ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])))
- + {
- + rtx op1;
- +
- + op1 = gen_reg_rtx (SImode);
- + emit_move_insn (op1, operands[1]);
- + operands[1] = op1;
- + }
- +
- + if (!ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))
- + {
- + rtx op2;
- +
- + op2 = gen_reg_rtx (SImode);
- + emit_move_insn (op2, operands[2]);
- + operands[2] = op2;
- + }
- +
- + acc_rtx = gen_reg_rtx (DImode);
- + emit_insn (gen_umulsidi3 (acc_rtx, operands[1], operands[2]));
- + emit_move_insn (operands[0], gen_lowpart (SImode, acc_rtx));
- +
- + return 1;
- + }
- +}
- +
- +/* Move the integer value VAL into OPERANDS[0]. */
- +
- +void
- +ubicom32_emit_move_const_int (rtx dest, rtx imm)
- +{
- + rtx xoperands[2];
- +
- + xoperands[0] = dest;
- + xoperands[1] = imm;
- +
- + /* Treat mem destinations separately. Values must be explicitly sign
- + extended. */
- + if (MEM_P (dest))
- + {
- + rtx low_hword_mem;
- + rtx low_hword_addr;
- +
- + /* Emit shorter sequence for signed 7-bit quantities. */
- + if (satisfies_constraint_I (imm))
- + {
- + output_asm_insn ("move.4\t%0, %1", xoperands);
- + return;
- + }
- +
- + /* Special case for pushing constants. */
- + if (GET_CODE (XEXP (dest, 0)) == PRE_DEC
- + && XEXP (XEXP (dest, 0), 0) == stack_pointer_rtx)
- + {
- + output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
- + output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
- + return;
- + }
- +
- + /* See if we can add 2 to the original address. This is only
- + possible if the original address is of the form REG or
- + REG+const. */
- + low_hword_addr = plus_constant (XEXP (dest, 0), 2);
- + if (ubicom32_legitimate_address_p (HImode, low_hword_addr, 1))
- + {
- + low_hword_mem = gen_rtx_MEM (HImode, low_hword_addr);
- + MEM_COPY_ATTRIBUTES (low_hword_mem, dest);
- + output_asm_insn ("movei\t%0, #%%hi(%E1)", xoperands);
- + xoperands[0] = low_hword_mem;
- + output_asm_insn ("movei\t%0, #%%lo(%E1)", xoperands);
- + return;
- + }
- +
- + /* The original address is too complex. We need to use a
- + scratch memory by (sp) and move that to the original
- + destination. */
- + if (! reg_mentioned_p (stack_pointer_rtx, dest))
- + {
- + output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
- + output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
- + output_asm_insn ("move.4\t%0, (sp)4++", xoperands);
- + return;
- + }
- +
- + /* Our address mentions the stack pointer so we need to
- + use our scratch data register here as well as scratch
- + memory. */
- + output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
- + output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
- + output_asm_insn ("move.4\td15, (sp)4++", xoperands);
- + output_asm_insn ("move.4\t%0, d15", xoperands);
- + return;
- + }
- +
- + /* Move into registers are zero extended by default. */
- + if (! REG_P (dest))
- + abort ();
- +
- + if (satisfies_constraint_N (imm))
- + {
- + output_asm_insn ("movei\t%0, %1", xoperands);
- + return;
- + }
- +
- + if (INTVAL (xoperands[1]) >= 0xff80
- + && INTVAL (xoperands[1]) < 0x10000)
- + {
- + xoperands[1] = GEN_INT (INTVAL (xoperands[1]) - 0x10000);
- + output_asm_insn ("move.2\t%0, %1", xoperands);
- + return;
- + }
- +
- + if ((REGNO_REG_CLASS (REGNO (xoperands[0])) == ADDRESS_REGS
- + || REGNO_REG_CLASS (REGNO (xoperands[0])) == FDPIC_REG)
- + && ((INTVAL (xoperands[1]) & 0x80000000) == 0))
- + {
- + output_asm_insn ("moveai\t%0, #%%hi(%E1)", xoperands);
- + if ((INTVAL (xoperands[1]) & 0x7f) != 0)
- + output_asm_insn ("lea.1\t%0, %%lo(%E1)(%0)", xoperands);
- + return;
- + }
- +
- + if ((INTVAL (xoperands[1]) & 0xffff0000) == 0)
- + {
- + output_asm_insn ("movei\t%0, #%%lo(%E1)", xoperands);
- + output_asm_insn ("move.2\t%0, %0", xoperands);
- + return;
- + }
- +
- + /* This is very expensive. The constant is so large that we
- + need to use the stack to do the load. */
- + output_asm_insn ("movei\t-4(sp)++, #%%hi(%E1)", xoperands);
- + output_asm_insn ("movei\t2(sp), #%%lo(%E1)", xoperands);
- + output_asm_insn ("move.4\t%0, (sp)4++", xoperands);
- +}
- +
- +/* Stack layout. Prologue/Epilogue. */
- +
- +static int save_regs_size;
- +
- +static void
- +ubicom32_layout_frame (void)
- +{
- + int regno;
- +
- + memset ((char *) &save_regs[0], 0, sizeof (save_regs));
- + nregs = 0;
- + frame_size = get_frame_size ();
- +
- + if (frame_pointer_needed || df_regs_ever_live_p (FRAME_POINTER_REGNUM))
- + {
- + save_regs[FRAME_POINTER_REGNUM] = 1;
- + ++nregs;
- + }
- +
- + if (current_function_is_leaf && ! df_regs_ever_live_p (LINK_REGNO))
- + ubicom32_can_use_calli_to_ret = 1;
- + else
- + {
- + ubicom32_can_use_calli_to_ret = 0;
- + save_regs[LINK_REGNO] = 1;
- + ++nregs;
- + }
- +
- + /* Figure out which register(s) needs to be saved. */
- + for (regno = 0; regno <= LAST_ADDRESS_REGNUM; regno++)
- + if (df_regs_ever_live_p(regno)
- + && ! call_used_regs[regno]
- + && ! fixed_regs[regno]
- + && ! save_regs[regno])
- + {
- + save_regs[regno] = 1;
- + ++nregs;
- + }
- +
- + save_regs_size = 4 * nregs;
- +}
- +
- +static void
- +ubicom32_emit_add_movsi (int regno, int adj)
- +{
- + rtx x;
- + rtx reg = gen_rtx_REG (SImode, regno);
- +
- + adj += 4;
- + if (adj > 8 * 4)
- + {
- + x = emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- + GEN_INT (-adj)));
- + RTX_FRAME_RELATED_P (x) = 1;
- + x = emit_move_insn (gen_rtx_MEM (SImode, stack_pointer_rtx), reg);
- + }
- + else
- + {
- + rtx addr = gen_rtx_PRE_MODIFY (Pmode, stack_pointer_rtx,
- + gen_rtx_PLUS (Pmode, stack_pointer_rtx,
- + GEN_INT (-adj)));
- + x = emit_move_insn (gen_rtx_MEM (SImode, addr), reg);
- + }
- + RTX_FRAME_RELATED_P (x) = 1;
- +}
- +
- +void
- +ubicom32_expand_prologue (void)
- +{
- + rtx x;
- + int regno;
- + int outgoing_args_size = crtl->outgoing_args_size;
- + int adj;
- +
- + if (ubicom32_naked_function_p ())
- + return;
- +
- + ubicom32_builtin_saveregs ();
- +
- + ubicom32_layout_frame ();
- + adj = (outgoing_args_size + get_frame_size () + save_regs_size
- + + crtl->args.pretend_args_size);
- +
- + if (!adj)
- + ;
- + else if (outgoing_args_size + save_regs_size < 508
- + && get_frame_size () + save_regs_size > 508)
- + {
- + int i = 0;
- + x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- + GEN_INT (-adj));
- + x = emit_insn (x);
- + RTX_FRAME_RELATED_P (x) = 1;
- +
- + for (regno = LAST_ADDRESS_REGNUM; regno >= 0; --regno)
- + if (save_regs[regno] && regno != LINK_REGNO)
- + {
- + x = gen_rtx_MEM (SImode,
- + gen_rtx_PLUS (Pmode,
- + stack_pointer_rtx,
- + GEN_INT (i * 4 + outgoing_args_size)));
- + x = emit_move_insn (x, gen_rtx_REG (SImode, regno));
- + RTX_FRAME_RELATED_P (x) = 1;
- + ++i;
- + }
- + if (save_regs[LINK_REGNO])
- + {
- + x = gen_rtx_MEM (SImode,
- + gen_rtx_PLUS (Pmode,
- + stack_pointer_rtx,
- + GEN_INT (i * 4 + outgoing_args_size)));
- + x = emit_move_insn (x, gen_rtx_REG (SImode, LINK_REGNO));
- + RTX_FRAME_RELATED_P (x) = 1;
- + }
- + }
- + else
- + {
- + int regno;
- + int adj = get_frame_size () + crtl->args.pretend_args_size;
- + int i = 0;
- +
- + if (save_regs[LINK_REGNO])
- + {
- + ubicom32_emit_add_movsi (LINK_REGNO, adj);
- + ++i;
- + }
- +
- + for (regno = 0; regno <= LAST_ADDRESS_REGNUM; ++regno)
- + if (save_regs[regno] && regno != LINK_REGNO)
- + {
- + if (i)
- + {
- + rtx mem = gen_rtx_MEM (SImode,
- + gen_rtx_PRE_DEC (Pmode,
- + stack_pointer_rtx));
- + x = emit_move_insn (mem, gen_rtx_REG (SImode, regno));
- + RTX_FRAME_RELATED_P (x) = 1;
- + }
- + else
- + ubicom32_emit_add_movsi (regno, adj);
- + ++i;
- + }
- +
- + if (outgoing_args_size || (!i && adj))
- + {
- + x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- + GEN_INT (-outgoing_args_size - (i ? 0 : adj)));
- + x = emit_insn (x);
- + RTX_FRAME_RELATED_P (x) = 1;
- + }
- + }
- +
- + if (frame_pointer_needed)
- + {
- + int fp_adj = save_regs_size + outgoing_args_size;
- + x = gen_addsi3 (frame_pointer_rtx, stack_pointer_rtx,
- + GEN_INT (fp_adj));
- + x = emit_insn (x);
- + RTX_FRAME_RELATED_P (x) = 1;
- + }
- +}
- +
- +void
- +ubicom32_expand_epilogue (void)
- +{
- + rtx x;
- + int regno;
- + int outgoing_args_size = crtl->outgoing_args_size;
- + int adj;
- + int i;
- +
- + if (ubicom32_naked_function_p ())
- + {
- + emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode,
- + LINK_REGNO)));
- + return;
- + }
- +
- + if (cfun->calls_alloca)
- + {
- + x = gen_addsi3 (stack_pointer_rtx, frame_pointer_rtx,
- + GEN_INT (-save_regs_size));
- + emit_insn (x);
- + outgoing_args_size = 0;
- + }
- +
- + if (outgoing_args_size)
- + {
- + x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- + GEN_INT (outgoing_args_size));
- + emit_insn (x);
- + }
- +
- + i = 0;
- + for (regno = LAST_ADDRESS_REGNUM; regno >= 0; --regno)
- + if (save_regs[regno] && regno != LINK_REGNO)
- + {
- + x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
- + emit_move_insn (gen_rtx_REG (SImode, regno), x);
- + ++i;
- + }
- +
- + /* Do we have to adjust the stack after we've finished restoring regs? */
- + adj = get_frame_size() + crtl->args.pretend_args_size;
- + if (cfun->stdarg)
- + adj += UBICOM32_FUNCTION_ARG_REGS * UNITS_PER_WORD;
- +
- +#if 0
- + if (crtl->calls_eh_return && 0)
- + {
- + if (save_regs[LINK_REGNO])
- + {
- + x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
- + emit_move_insn (gen_rtx_REG (SImode, LINK_REGNO), x);
- + }
- +
- + if (adj)
- + {
- + x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- + GEN_INT (adj));
- + x = emit_insn (x);
- + }
- +
- + /* Perform the additional bump for __throw. */
- + emit_insn (gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- + EH_RETURN_STACKADJ_RTX));
- + emit_jump_insn (gen_eh_return_internal ());
- + return;
- + }
- +#endif
- +
- + if (save_regs[LINK_REGNO])
- + {
- + if (adj >= 4 && adj <= (6 * 4))
- + {
- + x = GEN_INT (adj + 4);
- + emit_jump_insn (gen_return_from_post_modify_sp (x));
- + return;
- + }
- +
- + if (adj == 0)
- + {
- + x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
- + emit_jump_insn (gen_return_internal (x));
- + return;
- + }
- +
- + x = gen_rtx_MEM (SImode, gen_rtx_POST_INC (Pmode, stack_pointer_rtx));
- + emit_move_insn (gen_rtx_REG (SImode, LINK_REGNO), x);
- + }
- +
- + if (adj)
- + {
- + x = gen_addsi3 (stack_pointer_rtx, stack_pointer_rtx,
- + GEN_INT (adj));
- + x = emit_insn (x);
- + adj = 0;
- + }
- +
- + /* Given that we've just done all the hard work here we may as well use
- + a calli to return. */
- + ubicom32_can_use_calli_to_ret = 1;
- + emit_jump_insn (gen_return_internal (gen_rtx_REG (SImode, LINK_REGNO)));
- +}
- +
- +void
- +ubicom32_expand_call_fdpic (rtx *operands)
- +{
- + rtx c;
- + rtx addr;
- + rtx fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
- +
- + addr = XEXP (operands[0], 0);
- +
- + c = gen_call_fdpic (addr, operands[1], fdpic_reg);
- + emit_call_insn (c);
- +}
- +
- +void
- +ubicom32_expand_call_value_fdpic (rtx *operands)
- +{
- + rtx c;
- + rtx addr;
- + rtx fdpic_reg = get_hard_reg_initial_val (SImode, FDPIC_REGNUM);
- +
- + addr = XEXP (operands[1], 0);
- +
- + c = gen_call_value_fdpic (operands[0], addr, operands[2], fdpic_reg);
- + emit_call_insn (c);
- +}
- +
- +void
- +ubicom32_expand_eh_return (rtx *operands)
- +{
- + if (REG_P (operands[0])
- + || REGNO (operands[0]) != EH_RETURN_STACKADJ_REGNO)
- + {
- + rtx sp = EH_RETURN_STACKADJ_RTX;
- + emit_move_insn (sp, operands[0]);
- + operands[0] = sp;
- + }
- +
- + if (REG_P (operands[1])
- + || REGNO (operands[1]) != EH_RETURN_HANDLER_REGNO)
- + {
- + rtx ra = EH_RETURN_HANDLER_RTX;
- + emit_move_insn (ra, operands[1]);
- + operands[1] = ra;
- + }
- +}
- +
- +/* Compute the offsets between eliminable registers. */
- +
- +int
- +ubicom32_initial_elimination_offset (int from, int to)
- +{
- + ubicom32_layout_frame ();
- + if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
- + return save_regs_size + crtl->outgoing_args_size;
- +
- + if (from == ARG_POINTER_REGNUM && to == FRAME_POINTER_REGNUM)
- + return get_frame_size ()/* + save_regs_size */;
- +
- + if (from == ARG_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
- + return get_frame_size ()
- + + crtl->outgoing_args_size
- + + save_regs_size;
- +
- + return 0;
- +}
- +
- +/* Return 1 if it is appropriate to emit `ret' instructions in the
- + body of a function. Do this only if the epilogue is simple, needing a
- + couple of insns. Prior to reloading, we can't tell how many registers
- + must be saved, so return 0 then. Return 0 if there is no frame
- + marker to de-allocate.
- +
- + If NON_SAVING_SETJMP is defined and true, then it is not possible
- + for the epilogue to be simple, so return 0. This is a special case
- + since NON_SAVING_SETJMP will not cause regs_ever_live to change
- + until final, but jump_optimize may need to know sooner if a
- + `return' is OK. */
- +
- +int
- +ubicom32_can_use_return_insn_p (void)
- +{
- + if (! reload_completed || frame_pointer_needed)
- + return 0;
- +
- + return 1;
- +}
- +
- +/* Attributes and CC handling. */
- +
- +/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
- + struct attribute_spec.handler. */
- +static tree
- +ubicom32_handle_fndecl_attribute (tree *node, tree name,
- + tree args ATTRIBUTE_UNUSED,
- + int flags ATTRIBUTE_UNUSED,
- + bool *no_add_attrs)
- +{
- + if (TREE_CODE (*node) != FUNCTION_DECL)
- + {
- + warning ("'%s' attribute only applies to functions",
- + IDENTIFIER_POINTER (name));
- + *no_add_attrs = true;
- + }
- +
- + return NULL_TREE;
- +}
- +
- +/* A C expression that places additional restrictions on the register class to
- + use when it is necessary to copy value X into a register in class CLASS.
- + The value is a register class; perhaps CLASS, or perhaps another, smaller
- + class. On many machines, the following definition is safe:
- +
- + #define PREFERRED_RELOAD_CLASS(X,CLASS) CLASS
- +
- + Sometimes returning a more restrictive class makes better code. For
- + example, on the 68000, when X is an integer constant that is in range for a
- + `moveq' instruction, the value of this macro is always `DATA_REGS' as long
- + as CLASS includes the data registers. Requiring a data register guarantees
- + that a `moveq' will be used.
- +
- + If X is a `const_double', by returning `NO_REGS' you can force X into a
- + memory constant. This is useful on certain machines where immediate
- + floating values cannot be loaded into certain kinds of registers. */
- +
- +enum reg_class
- +ubicom32_preferred_reload_class (rtx x, enum reg_class class)
- +{
- + /* If a symbolic constant, HIGH or a PLUS is reloaded,
- + it is most likely being used as an address, so
- + prefer ADDRESS_REGS. If 'class' is not a superset
- + of ADDRESS_REGS, e.g. DATA_REGS, then reject this reload. */
- + if (GET_CODE (x) == PLUS
- + || GET_CODE (x) == HIGH
- + || GET_CODE (x) == LABEL_REF
- + || GET_CODE (x) == SYMBOL_REF
- + || GET_CODE (x) == CONST)
- + {
- + if (reg_class_subset_p (ALL_ADDRESS_REGS, class))
- + return ALL_ADDRESS_REGS;
- +
- + return NO_REGS;
- + }
- +
- + return class;
- +}
- +
- +/* Function arguments and varargs. */
- +
- +int
- +ubicom32_reg_parm_stack_space (tree fndecl)
- +{
- + return 0;
- +
- + if (fndecl
- + && TYPE_ARG_TYPES (TREE_TYPE (fndecl)) != 0
- + && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (TREE_TYPE (fndecl))))
- + != void_type_node))
- + return UBICOM32_FUNCTION_ARG_REGS * UNITS_PER_WORD;
- +
- + return 0;
- +}
- +
- +/* Flush the argument registers to the stack for a stdarg function;
- + return the new argument pointer. */
- +
- +rtx
- +ubicom32_builtin_saveregs (void)
- +{
- + int regno;
- +
- + if (! cfun->stdarg)
- + return 0;
- +
- + for (regno = UBICOM32_FUNCTION_ARG_REGS - 1; regno >= 0; --regno)
- + emit_move_insn (gen_rtx_MEM (SImode,
- + gen_rtx_PRE_DEC (SImode,
- + stack_pointer_rtx)),
- + gen_rtx_REG (SImode, regno));
- +
- + return stack_pointer_rtx;
- +}
- +
- +void
- +ubicom32_va_start (tree valist, rtx nextarg)
- +{
- + std_expand_builtin_va_start (valist, nextarg);
- +}
- +
- +rtx
- +ubicom32_va_arg (tree valist, tree type)
- +{
- + HOST_WIDE_INT size, rsize;
- + tree addr, incr, tmp;
- + rtx addr_rtx;
- + int indirect = 0;
- +
- + /* Round up sizeof(type) to a word. */
- + size = int_size_in_bytes (type);
- + rsize = (size + UNITS_PER_WORD - 1) & -UNITS_PER_WORD;
- +
- + /* Large types are passed by reference. */
- + if (size > 8)
- + {
- + indirect = 1;
- + size = rsize = UNITS_PER_WORD;
- + }
- +
- + incr = valist;
- + addr = incr = save_expr (incr);
- +
- + /* FIXME Nat's version - is it correct? */
- + tmp = fold_convert (ptr_type_node, size_int (rsize));
- + tmp = build2 (PLUS_EXPR, ptr_type_node, incr, tmp);
- + incr = fold (tmp);
- +
- + /* FIXME Nat's version - is it correct? */
- + incr = build2 (MODIFY_EXPR, ptr_type_node, valist, incr);
- +
- + TREE_SIDE_EFFECTS (incr) = 1;
- + expand_expr (incr, const0_rtx, VOIDmode, EXPAND_NORMAL);
- +
- + addr_rtx = expand_expr (addr, NULL, Pmode, EXPAND_NORMAL);
- +
- + if (size < UNITS_PER_WORD)
- + emit_insn (gen_addsi3 (addr_rtx, addr_rtx,
- + GEN_INT (UNITS_PER_WORD - size)));
- +
- + if (indirect)
- + {
- + addr_rtx = force_reg (Pmode, addr_rtx);
- + addr_rtx = gen_rtx_MEM (Pmode, addr_rtx);
- + set_mem_alias_set (addr_rtx, get_varargs_alias_set ());
- + }
- +
- + return addr_rtx;
- +}
- +
- +void
- +init_cumulative_args (CUMULATIVE_ARGS *cum, tree fntype, rtx libname,
- + int indirect ATTRIBUTE_UNUSED)
- +{
- + cum->nbytes = 0;
- +
- + if (!libname)
- + {
- + cum->stdarg = (TYPE_ARG_TYPES (fntype) != 0
- + && (TREE_VALUE (tree_last (TYPE_ARG_TYPES (fntype)))
- + != void_type_node));
- + }
- +}
- +
- +/* Return an RTX to represent where a value in mode MODE will be passed
- + to a function. If the result is 0, the argument will be pushed. */
- +
- +rtx
- +function_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
- + int named ATTRIBUTE_UNUSED)
- +{
- + rtx result = 0;
- + int size, align;
- + int nregs = UBICOM32_FUNCTION_ARG_REGS;
- +
- + /* Figure out the size of the object to be passed. */
- + if (mode == BLKmode)
- + size = int_size_in_bytes (type);
- + else
- + size = GET_MODE_SIZE (mode);
- +
- + /* Figure out the alignment of the object to be passed. */
- + align = size;
- +
- + cum->nbytes = (cum->nbytes + 3) & ~3;
- +
- + /* Don't pass this arg via a register if all the argument registers
- + are used up. */
- + if (cum->nbytes >= nregs * UNITS_PER_WORD)
- + return 0;
- +
- + /* Don't pass this arg via a register if it would be split between
- + registers and memory. */
- + result = gen_rtx_REG (mode, cum->nbytes / UNITS_PER_WORD);
- +
- + return result;
- +}
- +
- +rtx
- +function_incoming_arg (CUMULATIVE_ARGS *cum, enum machine_mode mode, tree type,
- + int named ATTRIBUTE_UNUSED)
- +{
- + if (cfun->stdarg)
- + return 0;
- +
- + return function_arg (cum, mode, type, named);
- +}
- +
- +
- +/* Implement hook TARGET_ARG_PARTIAL_BYTES.
- +
- + Returns the number of bytes at the beginning of an argument that
- + must be put in registers. The value must be zero for arguments
- + that are passed entirely in registers or that are entirely pushed
- + on the stack. */
- +static int
- +ubicom32_arg_partial_bytes (CUMULATIVE_ARGS *cum, enum machine_mode mode,
- + tree type, bool named ATTRIBUTE_UNUSED)
- +{
- + int size, diff;
- +
- + int nregs = UBICOM32_FUNCTION_ARG_REGS;
- +
- + /* round up to full word */
- + cum->nbytes = (cum->nbytes + 3) & ~3;
- +
- + if (targetm.calls.pass_by_reference (cum, mode, type, named))
- + return 0;
- +
- + /* number of bytes left in registers */
- + diff = nregs*UNITS_PER_WORD - cum->nbytes;
- +
- + /* regs all used up */
- + if (diff <= 0)
- + return 0;
- +
- + /* Figure out the size of the object to be passed. */
- + if (mode == BLKmode)
- + size = int_size_in_bytes (type);
- + else
- + size = GET_MODE_SIZE (mode);
- +
- + /* enough space left in regs for size */
- + if (size <= diff)
- + return 0;
- +
- + /* put diff bytes in regs and rest on stack */
- + return diff;
- +
- +}
- +
- +static bool
- +ubicom32_pass_by_reference (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
- + enum machine_mode mode, const_tree type,
- + bool named ATTRIBUTE_UNUSED)
- +{
- + int size;
- +
- + if (type)
- + size = int_size_in_bytes (type);
- + else
- + size = GET_MODE_SIZE (mode);
- +
- + return size <= 0 || size > 8;
- +}
- +
- +static bool
- +ubicom32_callee_copies (CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED,
- + enum machine_mode mode, const_tree type,
- + bool named ATTRIBUTE_UNUSED)
- +{
- + int size;
- +
- + if (type)
- + size = int_size_in_bytes (type);
- + else
- + size = GET_MODE_SIZE (mode);
- +
- + return size <= 0 || size > 8;
- +}
- +
- +static bool
- +ubicom32_return_in_memory (const_tree type, const_tree fntype ATTRIBUTE_UNUSED)
- +{
- + int size, mode;
- +
- + if (!type)
- + return true;
- +
- + size = int_size_in_bytes(type);
- + if (size > 8)
- + return true;
- +
- + mode = TYPE_MODE(type);
- + if (mode == BLKmode)
- + return true;
- +
- + return false;
- +}
- +
- +/* Return true if a given register number REGNO is acceptable for machine
- + mode MODE. */
- +bool
- +ubicom32_hard_regno_mode_ok (unsigned int regno, enum machine_mode mode)
- +{
- + /* If we're not at least a v3 ISA then ACC0_HI is only 16 bits. */
- + if (! ubicom32_v3)
- + {
- + if (regno == ACC0_HI_REGNUM)
- + return (mode == QImode || mode == HImode);
- + }
- +
- + /* Only the flags reg can hold CCmode. */
- + if (GET_MODE_CLASS (mode) == MODE_CC)
- + return regno == CC_REGNUM;
- +
- + /* We restrict the choice of DImode registers to only being address,
- + data or accumulator regs. We also restrict them to only start on
- + even register numbers so we never have to worry about partial
- + overlaps between operands in instructions. */
- + if (GET_MODE_SIZE (mode) > 4)
- + {
- + switch (REGNO_REG_CLASS (regno))
- + {
- + case ADDRESS_REGS:
- + case DATA_REGS:
- + case ACC_REGS:
- + return (regno & 1) == 0;
- +
- + default:
- + return false;
- + }
- + }
- +
- + return true;
- +}
- +
- +/* The macros REG_OK_FOR..._P assume that the arg is a REG rtx
- + and check its validity for a certain class.
- + We have two alternate definitions for each of them.
- + The usual definition accepts all pseudo regs; the other rejects
- + them unless they have been allocated suitable hard regs.
- + The symbol REG_OK_STRICT causes the latter definition to be used.
- +
- + Most source files want to accept pseudo regs in the hope that
- + they will get allocated to the class that the insn wants them to be in.
- + Source files for reload pass need to be strict.
- + After reload, it makes no difference, since pseudo regs have
- + been eliminated by then.
- +
- + These assume that REGNO is a hard or pseudo reg number.
- + They give nonzero only if REGNO is a hard reg of the suitable class
- + or a pseudo reg currently allocated to a suitable hard reg.
- + Since they use reg_renumber, they are safe only once reg_renumber
- + has been allocated, which happens in local-alloc.c. */
- +
- +int
- +ubicom32_regno_ok_for_base_p (int regno, int strict)
- +{
- + if ((regno >= FIRST_ADDRESS_REGNUM && regno <= STACK_POINTER_REGNUM)
- + || (!strict
- + && (regno >= FIRST_PSEUDO_REGISTER
- + || regno == ARG_POINTER_REGNUM))
- + || (strict && (reg_renumber
- + && reg_renumber[regno] >= FIRST_ADDRESS_REGNUM
- + && reg_renumber[regno] <= STACK_POINTER_REGNUM)))
- + return 1;
- +
- + return 0;
- +}
- +
- +int
- +ubicom32_regno_ok_for_index_p (int regno, int strict)
- +{
- + if ((regno >= FIRST_DATA_REGNUM && regno <= LAST_DATA_REGNUM)
- + || (!strict && regno >= FIRST_PSEUDO_REGISTER)
- + || (strict && (reg_renumber
- + && reg_renumber[regno] >= FIRST_DATA_REGNUM
- + && reg_renumber[regno] <= LAST_DATA_REGNUM)))
- + return 1;
- +
- + return 0;
- +}
- +
- +/* Returns 1 if X is a valid index register. STRICT is 1 if only hard
- + registers should be accepted. Accept either REG or SUBREG where a
- + register is valid. */
- +
- +static bool
- +ubicom32_is_index_reg (rtx x, int strict)
- +{
- + if ((REG_P (x) && ubicom32_regno_ok_for_index_p (REGNO (x), strict))
- + || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))
- + && ubicom32_regno_ok_for_index_p (REGNO (SUBREG_REG (x)), strict)))
- + return true;
- +
- + return false;
- +}
- +
- +/* Return 1 if X is a valid index for a memory address. */
- +
- +static bool
- +ubicom32_is_index_expr (enum machine_mode mode, rtx x, int strict)
- +{
- + /* Immediate index must be an unsigned 7-bit offset multiple of 1, 2
- + or 4 depending on mode. */
- + if (CONST_INT_P (x))
- + {
- + switch (mode)
- + {
- + case QImode:
- + return satisfies_constraint_J (x);
- +
- + case HImode:
- + return satisfies_constraint_K (x);
- +
- + case SImode:
- + case SFmode:
- + return satisfies_constraint_L (x);
- +
- + case DImode:
- + return satisfies_constraint_L (x)
- + && satisfies_constraint_L (GEN_INT (INTVAL (x) + 4));
- +
- + default:
- + return false;
- + }
- + }
- +
- + if (mode != SImode && mode != HImode && mode != QImode)
- + return false;
- +
- + /* Register index scaled by mode of operand: REG + REG * modesize.
- + Valid scaled index registers are:
- +
- + SImode (mult (dreg) 4))
- + HImode (mult (dreg) 2))
- + QImode (mult (dreg) 1)) */
- + if (GET_CODE (x) == MULT
- + && ubicom32_is_index_reg (XEXP (x, 0), strict)
- + && CONST_INT_P (XEXP (x, 1))
- + && INTVAL (XEXP (x, 1)) == (HOST_WIDE_INT)GET_MODE_SIZE (mode))
- + return true;
- +
- + /* REG + REG addressing is allowed for QImode. */
- + if (ubicom32_is_index_reg (x, strict) && mode == QImode)
- + return true;
- +
- + return false;
- +}
- +
- +static bool
- +ubicom32_is_valid_offset (enum machine_mode mode, HOST_WIDE_INT offs)
- +{
- + if (offs < 0)
- + return false;
- +
- + switch (mode)
- + {
- + case QImode:
- + return offs <= 127;
- +
- + case HImode:
- + return offs <= 254;
- +
- + case SImode:
- + case SFmode:
- + return offs <= 508;
- +
- + case DImode:
- + return offs <= 504;
- +
- + default:
- + return false;
- + }
- +}
- +
- +static int
- +ubicom32_get_valid_offset_mask (enum machine_mode mode)
- +{
- + switch (mode)
- + {
- + case QImode:
- + return 127;
- +
- + case HImode:
- + return 255;
- +
- + case SImode:
- + case SFmode:
- + return 511;
- +
- + case DImode:
- + return 255;
- +
- + default:
- + return 0;
- + }
- +}
- +
- +/* Returns 1 if X is a valid base register. STRICT is 1 if only hard
- + registers should be accepted. Accept either REG or SUBREG where a
- + register is valid. */
- +
- +static bool
- +ubicom32_is_base_reg (rtx x, int strict)
- +{
- + if ((REG_P (x) && ubicom32_regno_ok_for_base_p (REGNO (x), strict))
- + || (GET_CODE (x) == SUBREG && REG_P (SUBREG_REG (x))
- + && ubicom32_regno_ok_for_base_p (REGNO (SUBREG_REG (x)), strict)))
- + return true;
- +
- + return false;
- +}
- +
- +static bool
- +ubicom32_cannot_force_const_mem (rtx x ATTRIBUTE_UNUSED)
- +{
- + return TARGET_FDPIC;
- +}
- +
- +/* Determine if X is a legitimate constant. */
- +
- +bool
- +ubicom32_legitimate_constant_p (rtx x)
- +{
- + /* Among its other duties, LEGITIMATE_CONSTANT_P decides whether
- + a constant can be entered into reg_equiv_constant[]. If we return true,
- + reload can create new instances of the constant whenever it likes.
- +
- + The idea is therefore to accept as many constants as possible (to give
- + reload more freedom) while rejecting constants that can only be created
- + at certain times. In particular, anything with a symbolic component will
- + require use of the pseudo FDPIC register, which is only available before
- + reload. */
- + if (TARGET_FDPIC)
- + {
- + if (GET_CODE (x) == SYMBOL_REF
- + || (GET_CODE (x) == CONST
- + && GET_CODE (XEXP (x, 0)) == PLUS
- + && GET_CODE (XEXP (XEXP (x, 0), 0)) == SYMBOL_REF)
- + || CONSTANT_ADDRESS_P (x))
- + return false;
- +
- + return true;
- + }
- +
- + /* For non-PIC code anything goes! */
- + return true;
- +}
- +
- +/* Address validation. */
- +
- +bool
- +ubicom32_legitimate_address_p (enum machine_mode mode, rtx x, int strict)
- +{
- + if (TARGET_DEBUG_ADDRESS)
- + {
- + fprintf (stderr, "\n==> GO_IF_LEGITIMATE_ADDRESS%s\n",
- + (strict) ? " (STRICT)" : "");
- + debug_rtx (x);
- + }
- +
- + if (CONSTANT_ADDRESS_P (x))
- + return false;
- +
- + if (ubicom32_is_base_reg (x, strict))
- + return true;
- +
- + if ((GET_CODE (x) == POST_INC
- + || GET_CODE (x) == PRE_INC
- + || GET_CODE (x) == POST_DEC
- + || GET_CODE (x) == PRE_DEC)
- + && REG_P (XEXP (x, 0))
- + && ubicom32_is_base_reg (XEXP (x, 0), strict)
- + && mode != DImode)
- + return true;
- +
- + if ((GET_CODE (x) == PRE_MODIFY || GET_CODE (x) == POST_MODIFY)
- + && ubicom32_is_base_reg (XEXP (x, 0), strict)
- + && GET_CODE (XEXP (x, 1)) == PLUS
- + && rtx_equal_p (XEXP (x, 0), XEXP (XEXP (x, 1), 0))
- + && CONST_INT_P (XEXP (XEXP (x, 1), 1))
- + && mode != DImode)
- + {
- + HOST_WIDE_INT disp = INTVAL (XEXP (XEXP (x, 1), 1));
- + switch (mode)
- + {
- + case QImode:
- + return disp >= -8 && disp <= 7;
- +
- + case HImode:
- + return disp >= -16 && disp <= 14 && ! (disp & 1);
- +
- + case SImode:
- + return disp >= -32 && disp <= 28 && ! (disp & 3);
- +
- + default:
- + return false;
- + }
- + }
- +
- + /* Accept base + index * scale. */
- + if (GET_CODE (x) == PLUS
- + && ubicom32_is_base_reg (XEXP (x, 0), strict)
- + && ubicom32_is_index_expr (mode, XEXP (x, 1), strict))
- + return true;
- +
- + /* Accept index * scale + base. */
- + if (GET_CODE (x) == PLUS
- + && ubicom32_is_base_reg (XEXP (x, 1), strict)
- + && ubicom32_is_index_expr (mode, XEXP (x, 0), strict))
- + return true;
- +
- + if (! TARGET_FDPIC)
- + {
- + /* Accept (lo_sum (reg) (symbol_ref)) that can be used as a mem+7bits
- + displacement operand:
- +
- + moveai a1, #%hi(SYM)
- + move.4 d3, %lo(SYM)(a1) */
- + if (GET_CODE (x) == LO_SUM
- + && ubicom32_is_base_reg (XEXP (x, 0), strict)
- + && (GET_CODE (XEXP (x, 1)) == SYMBOL_REF
- + || GET_CODE (XEXP (x, 1)) == LABEL_REF /* FIXME: wrong */)
- + && mode != DImode)
- + return true;
- + }
- +
- + if (TARGET_DEBUG_ADDRESS)
- + fprintf (stderr, "\nNot a legitimate address.\n");
- +
- + return false;
- +}
- +
- +rtx
- +ubicom32_legitimize_address (rtx x, rtx oldx ATTRIBUTE_UNUSED,
- + enum machine_mode mode)
- +{
- + if (mode == BLKmode)
- + return NULL_RTX;
- +
- + if (GET_CODE (x) == PLUS
- + && REG_P (XEXP (x, 0))
- + && ! REGNO_PTR_FRAME_P (REGNO (XEXP (x, 0)))
- + && CONST_INT_P (XEXP (x, 1))
- + && ! ubicom32_is_valid_offset (mode, INTVAL (XEXP (x, 1))))
- + {
- + rtx base;
- + rtx plus;
- + rtx new_rtx;
- + HOST_WIDE_INT val = INTVAL (XEXP (x, 1));
- + HOST_WIDE_INT low = val & ubicom32_get_valid_offset_mask (mode);
- + HOST_WIDE_INT high = val ^ low;
- +
- + if (val < 0)
- + return NULL_RTX;
- +
- + if (! low)
- + return NULL_RTX;
- +
- + /* Reload the high part into a base reg; leave the low part
- + in the mem directly. */
- + base = XEXP (x, 0);
- + if (! ubicom32_is_base_reg (base, 0))
- + base = copy_to_mode_reg (Pmode, base);
- +
- + plus = expand_simple_binop (Pmode, PLUS,
- + gen_int_mode (high, Pmode),
- + base, NULL, 0, OPTAB_WIDEN);
- + new_rtx = plus_constant (plus, low);
- +
- + return new_rtx;
- + }
- +
- + return NULL_RTX;
- +}
- +
- +/* Try a machine-dependent way of reloading an illegitimate address AD
- + operand. If we find one, push the reload and and return the new address.
- +
- + MODE is the mode of the enclosing MEM. OPNUM is the operand number
- + and TYPE is the reload type of the current reload. */
- +
- +rtx
- +ubicom32_legitimize_reload_address (rtx ad, enum machine_mode mode,
- + int opnum, int type)
- +{
- + /* Is this an address that we've already fixed up? If it is then
- + recognize it and move on. */
- + if (GET_CODE (ad) == PLUS
- + && GET_CODE (XEXP (ad, 0)) == PLUS
- + && REG_P (XEXP (XEXP (ad, 0), 0))
- + && CONST_INT_P (XEXP (XEXP (ad, 0), 1))
- + && CONST_INT_P (XEXP (ad, 1)))
- + {
- + push_reload (XEXP (ad, 0), NULL_RTX, &XEXP (ad, 0), NULL,
- + BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
- + opnum, (enum reload_type) type);
- + return ad;
- + }
- +
- + /* Have we got an address where the offset is simply out of range? If
- + yes then reload the range as a high part and smaller offset. */
- + if (GET_CODE (ad) == PLUS
- + && REG_P (XEXP (ad, 0))
- + && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
- + && REGNO_OK_FOR_BASE_P (REGNO (XEXP (ad, 0)))
- + && CONST_INT_P (XEXP (ad, 1))
- + && ! ubicom32_is_valid_offset (mode, INTVAL (XEXP (ad, 1))))
- + {
- + rtx temp;
- + rtx new_rtx;
- +
- + HOST_WIDE_INT val = INTVAL (XEXP (ad, 1));
- + HOST_WIDE_INT low = val & ubicom32_get_valid_offset_mask (mode);
- + HOST_WIDE_INT high = val ^ low;
- +
- + /* Reload the high part into a base reg; leave the low part
- + in the mem directly. */
- + temp = gen_rtx_PLUS (Pmode, XEXP (ad, 0), GEN_INT (high));
- + new_rtx = gen_rtx_PLUS (Pmode, temp, GEN_INT (low));
- +
- + push_reload (XEXP (new_rtx, 0), NULL_RTX, &XEXP (new_rtx, 0), NULL,
- + BASE_REG_CLASS, Pmode, VOIDmode, 0, 0,
- + opnum, (enum reload_type) type);
- + return new_rtx;
- + }
- +
- + /* If we're presented with an pre/post inc/dec then we must force this
- + to be done in an address register. The register allocator should
- + work this out for itself but at times ends up trying to use the wrong
- + class. If we get the wrong class then reload will end up generating
- + at least 3 instructions whereas this way we can hopefully keep it to
- + just 2. */
- + if ((GET_CODE (ad) == POST_INC
- + || GET_CODE (ad) == PRE_INC
- + || GET_CODE (ad) == POST_DEC
- + || GET_CODE (ad) == PRE_DEC)
- + && REG_P (XEXP (ad, 0))
- + && REGNO (XEXP (ad, 0)) < FIRST_PSEUDO_REGISTER
- + && ! REGNO_OK_FOR_BASE_P (REGNO (XEXP (ad, 0))))
- + {
- + push_reload (XEXP (ad, 0), XEXP (ad, 0), &XEXP (ad, 0), &XEXP (ad, 0),
- + BASE_REG_CLASS, GET_MODE (XEXP (ad, 0)), GET_MODE (XEXP (ad, 0)), 0, 0,
- + opnum, RELOAD_OTHER);
- + return ad;
- + }
- +
- + return NULL_RTX;
- +}
- +
- +/* Compute a (partial) cost for rtx X. Return true if the complete
- + cost has been computed, and false if subexpressions should be
- + scanned. In either case, *TOTAL contains the cost result. */
- +
- +static bool
- +ubicom32_rtx_costs (rtx x, int code, int outer_code, int *total,
- + bool speed ATTRIBUTE_UNUSED)
- +{
- + enum machine_mode mode = GET_MODE (x);
- +
- + switch (code)
- + {
- + case CONST_INT:
- + /* Very short constants often fold into instructions so
- + we pretend that they don't cost anything! This is
- + really important as regards zero values as otherwise
- + the compiler has a nasty habit of wanting to reuse
- + zeroes that are in regs but that tends to pessimize
- + the code. */
- + if (satisfies_constraint_I (x))
- + {
- + *total = 0;
- + return true;
- + }
- +
- + /* Bit clearing costs nothing */
- + if (outer_code == AND
- + && exact_log2 (~INTVAL (x)) != -1)
- + {
- + *total = 0;
- + return true;
- + }
- +
- + /* Masking the lower set of bits costs nothing. */
- + if (outer_code == AND
- + && exact_log2 (INTVAL (x) + 1) != -1)
- + {
- + *total = 0;
- + return true;
- + }
- +
- + /* Bit setting costs nothing. */
- + if (outer_code == IOR
- + && exact_log2 (INTVAL (x)) != -1)
- + {
- + *total = 0;
- + return true;
- + }
- +
- + /* Larger constants that can be loaded via movei aren't too
- + bad. If we're just doing a set they cost nothing extra. */
- + if (satisfies_constraint_N (x))
- + {
- + if (mode == DImode)
- + *total = COSTS_N_INSNS (2);
- + else
- + *total = COSTS_N_INSNS (1);
- + return true;
- + }
- +
- + if (mode == DImode)
- + *total = COSTS_N_INSNS (5);
- + else
- + *total = COSTS_N_INSNS (3);
- + return true;
- +
- + case CONST_DOUBLE:
- + /* We don't optimize CONST_DOUBLEs well nor do we relax them well,
- + so their cost is very high. */
- + *total = COSTS_N_INSNS (6);
- + return true;
- +
- + case CONST:
- + case SYMBOL_REF:
- + case MEM:
- + *total = 0;
- + return true;
- +
- + case IF_THEN_ELSE:
- + *total = COSTS_N_INSNS (1);
- + return true;
- +
- + case LABEL_REF:
- + case HIGH:
- + case LO_SUM:
- + case BSWAP:
- + case PLUS:
- + case MINUS:
- + case AND:
- + case IOR:
- + case XOR:
- + case ASHIFT:
- + case ASHIFTRT:
- + case LSHIFTRT:
- + case NEG:
- + case NOT:
- + case SIGN_EXTEND:
- + case ZERO_EXTEND:
- + case ZERO_EXTRACT:
- + if (outer_code == SET)
- + {
- + if (mode == DImode)
- + *total = COSTS_N_INSNS (2);
- + else
- + *total = COSTS_N_INSNS (1);
- + }
- + return true;
- +
- + case COMPARE:
- + if (outer_code == SET)
- + {
- + if (GET_MODE (XEXP (x, 0)) == DImode
- + || GET_MODE (XEXP (x, 1)) == DImode)
- + *total = COSTS_N_INSNS (2);
- + else
- + *total = COSTS_N_INSNS (1);
- + }
- + return true;
- +
- + case UMOD:
- + case UDIV:
- + case MOD:
- + case DIV:
- + if (outer_code == SET)
- + {
- + if (mode == DImode)
- + *total = COSTS_N_INSNS (600);
- + else
- + *total = COSTS_N_INSNS (200);
- + }
- + return true;
- +
- + case MULT:
- + if (outer_code == SET)
- + {
- + if (! ubicom32_v4)
- + {
- + if (mode == DImode)
- + *total = COSTS_N_INSNS (15);
- + else
- + *total = COSTS_N_INSNS (5);
- + }
- + else
- + {
- + if (mode == DImode)
- + *total = COSTS_N_INSNS (6);
- + else
- + *total = COSTS_N_INSNS (2);
- + }
- + }
- + return true;
- +
- + case UNSPEC:
- + if (XINT (x, 1) == UNSPEC_FDPIC_GOT
- + || XINT (x, 1) == UNSPEC_FDPIC_GOT_FUNCDESC)
- + *total = 0;
- + return true;
- +
- + default:
- + return false;
- + }
- +}
- +
- +/* Return 1 if ADDR can have different meanings depending on the machine
- + mode of the memory reference it is used for or if the address is
- + valid for some modes but not others.
- +
- + Autoincrement and autodecrement addresses typically have
- + mode-dependent effects because the amount of the increment or
- + decrement is the size of the operand being addressed. Some machines
- + have other mode-dependent addresses. Many RISC machines have no
- + mode-dependent addresses.
- +
- + You may assume that ADDR is a valid address for the machine. */
- +
- +int
- +ubicom32_mode_dependent_address_p (rtx addr)
- +{
- + if (GET_CODE (addr) == POST_INC
- + || GET_CODE (addr) == PRE_INC
- + || GET_CODE (addr) == POST_DEC
- + || GET_CODE (addr) == PRE_DEC
- + || GET_CODE (addr) == POST_MODIFY
- + || GET_CODE (addr) == PRE_MODIFY)
- + return 1;
- +
- + return 0;
- +}
- +
- +static void
- +ubicom32_function_prologue (FILE *file, HOST_WIDE_INT size ATTRIBUTE_UNUSED)
- +{
- + fprintf (file, "/* frame/pretend: %ld/%d save_regs: %d out_args: %d %s */\n",
- + get_frame_size (), crtl->args.pretend_args_size,
- + save_regs_size, crtl->outgoing_args_size,
- + current_function_is_leaf ? "leaf" : "nonleaf");
- +}
- +
- +static void
- +ubicom32_function_epilogue (FILE *file ATTRIBUTE_UNUSED,
- + HOST_WIDE_INT size ATTRIBUTE_UNUSED)
- +{
- + ubicom32_reorg_completed = 0;
- +}
- +
- +static void
- +ubicom32_machine_dependent_reorg (void)
- +{
- +#if 0 /* Commenting out this optimization until it is fixed */
- + if (optimize)
- + {
- + compute_bb_for_insn ();
- +
- + /* Do a very simple CSE pass over just the hard registers. */
- + reload_cse_regs (get_insns ());
- +
- + /* Reload_cse_regs can eliminate potentially-trapping MEMs.
- + Remove any EH edges associated with them. */
- + if (flag_non_call_exceptions)
- + purge_all_dead_edges ();
- + }
- +#endif
- + ubicom32_reorg_completed = 1;
- +}
- +
- +void
- +ubicom32_output_cond_jump (rtx insn, rtx cond, rtx target)
- +{
- + rtx note;
- + int mostly_false_jump;
- + rtx xoperands[2];
- + rtx cc_reg;
- +
- + note = find_reg_note (insn, REG_BR_PROB, 0);
- + mostly_false_jump = !note || (INTVAL (XEXP (note, 0))
- + <= REG_BR_PROB_BASE / 2);
- +
- + xoperands[0] = target;
- + xoperands[1] = cond;
- + cc_reg = XEXP (cond, 0);
- +
- + if (GET_MODE (cc_reg) == CCWmode
- + || GET_MODE (cc_reg) == CCWZmode
- + || GET_MODE (cc_reg) == CCWZNmode)
- + {
- + if (mostly_false_jump)
- + output_asm_insn ("jmp%b1.w.f\t%0", xoperands);
- + else
- + output_asm_insn ("jmp%b1.w.t\t%0", xoperands);
- + return;
- + }
- +
- + if (GET_MODE (cc_reg) == CCSmode
- + || GET_MODE (cc_reg) == CCSZmode
- + || GET_MODE (cc_reg) == CCSZNmode)
- + {
- + if (mostly_false_jump)
- + output_asm_insn ("jmp%b1.s.f\t%0", xoperands);
- + else
- + output_asm_insn ("jmp%b1.s.t\t%0", xoperands);
- + return;
- + }
- +
- + abort ();
- +}
- +
- +/* Return non-zero if FUNC is a naked function. */
- +
- +static int
- +ubicom32_naked_function_p (void)
- +{
- + return lookup_attribute ("naked", DECL_ATTRIBUTES (current_function_decl)) != NULL_TREE;
- +}
- +
- +/* Return an RTX indicating where the return address to the
- + calling function can be found. */
- +rtx
- +ubicom32_return_addr_rtx (int count, rtx frame ATTRIBUTE_UNUSED)
- +{
- + if (count != 0)
- + return NULL_RTX;
- +
- + return get_hard_reg_initial_val (Pmode, LINK_REGNO);
- +}
- +
- +/*
- + * ubicom32_readonly_data_section: This routtine handles code
- + * at the start of readonly data sections
- + */
- +static void
- +ubicom32_readonly_data_section (const void *data ATTRIBUTE_UNUSED)
- +{
- + static int num = 0;
- + if (in_section == readonly_data_section){
- + fprintf (asm_out_file, "%s", DATA_SECTION_ASM_OP);
- + if (flag_data_sections){
- + fprintf (asm_out_file, ".rodata%d", num);
- + fprintf (asm_out_file, ",\"a\"");
- + }
- + fprintf (asm_out_file, "\n");
- + }
- + num++;
- +}
- +
- +/*
- + * ubicom32_text_section: not in readonly section
- + */
- +static void
- +ubicom32_text_section(const void *data ATTRIBUTE_UNUSED)
- +{
- + fprintf (asm_out_file, "%s\n", TEXT_SECTION_ASM_OP);
- +}
- +
- +/*
- + * ubicom32_data_section: not in readonly section
- + */
- +static void
- +ubicom32_data_section(const void *data ATTRIBUTE_UNUSED)
- +{
- + fprintf (asm_out_file, "%s\n", DATA_SECTION_ASM_OP);
- +}
- +
- +/*
- + * ubicom32_asm_init_sections: This routine implements special
- + * section handling
- + */
- +static void
- +ubicom32_asm_init_sections(void)
- +{
- + text_section = get_unnamed_section(SECTION_CODE, ubicom32_text_section, NULL);
- +
- + data_section = get_unnamed_section(SECTION_WRITE, ubicom32_data_section, NULL);
- +
- + readonly_data_section = get_unnamed_section(0, ubicom32_readonly_data_section, NULL);
- +}
- +
- +/*
- + * ubicom32_profiler: This routine would call
- + * mcount to support prof and gprof if mcount
- + * was supported. Currently, do nothing.
- + */
- +void
- +ubicom32_profiler(void)
- +{
- +}
- +
- +/* Initialise the builtin functions. Start by initialising
- + descriptions of different types of functions (e.g., void fn(int),
- + int fn(void)), and then use these to define the builtins. */
- +static void
- +ubicom32_init_builtins (void)
- +{
- + tree endlink;
- + tree short_unsigned_endlink;
- + tree unsigned_endlink;
- + tree short_unsigned_ftype_short_unsigned;
- + tree unsigned_ftype_unsigned;
- +
- + endlink = void_list_node;
- +
- + short_unsigned_endlink
- + = tree_cons (NULL_TREE, short_unsigned_type_node, endlink);
- +
- + unsigned_endlink
- + = tree_cons (NULL_TREE, unsigned_type_node, endlink);
- +
- + short_unsigned_ftype_short_unsigned
- + = build_function_type (short_unsigned_type_node, short_unsigned_endlink);
- +
- + unsigned_ftype_unsigned
- + = build_function_type (unsigned_type_node, unsigned_endlink);
- +
- + /* Initialise the byte swap function. */
- + add_builtin_function ("__builtin_ubicom32_swapb_2",
- + short_unsigned_ftype_short_unsigned,
- + UBICOM32_BUILTIN_UBICOM32_SWAPB_2,
- + BUILT_IN_MD, NULL,
- + NULL_TREE);
- +
- + /* Initialise the byte swap function. */
- + add_builtin_function ("__builtin_ubicom32_swapb_4",
- + unsigned_ftype_unsigned,
- + UBICOM32_BUILTIN_UBICOM32_SWAPB_4,
- + BUILT_IN_MD, NULL,
- + NULL_TREE);
- +}
- +
- +/* Given a builtin function taking 2 operands (i.e., target + source),
- + emit the RTL for the underlying instruction. */
- +static rtx
- +ubicom32_expand_builtin_2op (enum insn_code icode, tree arglist, rtx target)
- +{
- + tree arg0;
- + rtx op0, pat;
- + enum machine_mode tmode, mode0;
- +
- + /* Grab the incoming argument and emit its RTL. */
- + arg0 = TREE_VALUE (arglist);
- + op0 = expand_expr (arg0, NULL_RTX, VOIDmode, 0);
- +
- + /* Determine the modes of the instruction operands. */
- + tmode = insn_data[icode].operand[0].mode;
- + mode0 = insn_data[icode].operand[1].mode;
- +
- + /* Ensure that the incoming argument RTL is in a register of the
- + correct mode. */
- + if (!(*insn_data[icode].operand[1].predicate) (op0, mode0))
- + op0 = copy_to_mode_reg (mode0, op0);
- +
- + /* If there isn't a suitable target, emit a target register. */
- + if (target == 0
- + || GET_MODE (target) != tmode
- + || !(*insn_data[icode].operand[0].predicate) (target, tmode))
- + target = gen_reg_rtx (tmode);
- +
- + /* Emit and return the new instruction. */
- + pat = GEN_FCN (icode) (target, op0);
- + if (!pat)
- + return 0;
- + emit_insn (pat);
- +
- + return target;
- +}
- +
- +/* Expand a call to a builtin function. */
- +static rtx
- +ubicom32_expand_builtin (tree exp, rtx target, rtx subtarget ATTRIBUTE_UNUSED,
- + enum machine_mode mode ATTRIBUTE_UNUSED,
- + int ignore ATTRIBUTE_UNUSED)
- +{
- + tree fndecl = TREE_OPERAND (CALL_EXPR_FN (exp), 0);
- + tree arglist = CALL_EXPR_ARGS(exp);
- + int fcode = DECL_FUNCTION_CODE (fndecl);
- +
- + switch (fcode)
- + {
- + case UBICOM32_BUILTIN_UBICOM32_SWAPB_2:
- + return ubicom32_expand_builtin_2op (CODE_FOR_bswaphi, arglist, target);
- +
- + case UBICOM32_BUILTIN_UBICOM32_SWAPB_4:
- + return ubicom32_expand_builtin_2op (CODE_FOR_bswapsi, arglist, target);
- +
- + default:
- + gcc_unreachable();
- + }
- +
- + /* Should really do something sensible here. */
- + return NULL_RTX;
- +}
- +
- +/* Fold any constant argument for a swapb.2 instruction. */
- +static tree
- +ubicom32_fold_builtin_ubicom32_swapb_2 (tree fndecl, tree arglist)
- +{
- + tree arg0;
- +
- + arg0 = TREE_VALUE (arglist);
- +
- + /* Optimize constant value. */
- + if (TREE_CODE (arg0) == INTEGER_CST)
- + {
- + HOST_WIDE_INT v;
- + HOST_WIDE_INT res;
- +
- + v = TREE_INT_CST_LOW (arg0);
- + res = ((v >> 8) & 0xff)
- + | ((v & 0xff) << 8);
- +
- + return build_int_cst (TREE_TYPE (TREE_TYPE (fndecl)), res);
- + }
- +
- + return NULL_TREE;
- +}
- +
- +/* Fold any constant argument for a swapb.4 instruction. */
- +static tree
- +ubicom32_fold_builtin_ubicom32_swapb_4 (tree fndecl, tree arglist)
- +{
- + tree arg0;
- +
- + arg0 = TREE_VALUE (arglist);
- +
- + /* Optimize constant value. */
- + if (TREE_CODE (arg0) == INTEGER_CST)
- + {
- + unsigned HOST_WIDE_INT v;
- + unsigned HOST_WIDE_INT res;
- +
- + v = TREE_INT_CST_LOW (arg0);
- + res = ((v >> 24) & 0xff)
- + | (((v >> 16) & 0xff) << 8)
- + | (((v >> 8) & 0xff) << 16)
- + | ((v & 0xff) << 24);
- +
- + return build_int_cst_wide (TREE_TYPE (TREE_TYPE (fndecl)), res, 0);
- + }
- +
- + return NULL_TREE;
- +}
- +
- +/* Fold any constant arguments for builtin functions. */
- +static tree
- +ubicom32_fold_builtin (tree fndecl, tree arglist, bool ignore ATTRIBUTE_UNUSED)
- +{
- + switch (DECL_FUNCTION_CODE (fndecl))
- + {
- + case UBICOM32_BUILTIN_UBICOM32_SWAPB_2:
- + return ubicom32_fold_builtin_ubicom32_swapb_2 (fndecl, arglist);
- +
- + case UBICOM32_BUILTIN_UBICOM32_SWAPB_4:
- + return ubicom32_fold_builtin_ubicom32_swapb_4 (fndecl, arglist);
- +
- + default:
- + return NULL;
- + }
- +}
- +
- +/* Implementation of TARGET_ASM_INTEGER. When using FD-PIC, we need to
- + tell the assembler to generate pointers to function descriptors in
- + some cases. */
- +static bool
- +ubicom32_assemble_integer (rtx value, unsigned int size, int aligned_p)
- +{
- + if (TARGET_FDPIC && size == UNITS_PER_WORD)
- + {
- + if (GET_CODE (value) == SYMBOL_REF
- + && SYMBOL_REF_FUNCTION_P (value))
- + {
- + fputs ("\t.picptr\t%funcdesc(", asm_out_file);
- + output_addr_const (asm_out_file, value);
- + fputs (")\n", asm_out_file);
- + return true;
- + }
- +
- + if (!aligned_p)
- + {
- + /* We've set the unaligned SI op to NULL, so we always have to
- + handle the unaligned case here. */
- + assemble_integer_with_op ("\t.4byte\t", value);
- + return true;
- + }
- + }
- +
- + return default_assemble_integer (value, size, aligned_p);
- +}
- +
- +/* If the constant I can be constructed by shifting a source-1 immediate
- + by a constant number of bits then return the bit count. If not
- + return 0. */
- +
- +int
- +ubicom32_shiftable_const_int (int i)
- +{
- + int shift = 0;
- +
- + /* Note that any constant that can be represented as an immediate to
- + a movei instruction is automatically ignored here in the interests
- + of the clarity of the output asm code. */
- + if (i >= -32768 && i <= 32767)
- + return 0;
- +
- + /* Find the number of trailing zeroes. We could use __builtin_ctz
- + here but it's not obvious if this is supported on all build
- + compilers so we err on the side of caution. */
- + if ((i & 0xffff) == 0)
- + {
- + shift += 16;
- + i >>= 16;
- + }
- +
- + if ((i & 0xff) == 0)
- + {
- + shift += 8;
- + i >>= 8;
- + }
- +
- + if ((i & 0xf) == 0)
- + {
- + shift += 4;
- + i >>= 4;
- + }
- +
- + if ((i & 0x3) == 0)
- + {
- + shift += 2;
- + i >>= 2;
- + }
- +
- + if ((i & 0x1) == 0)
- + {
- + shift += 1;
- + i >>= 1;
- + }
- +
- + if (i >= -128 && i <= 127)
- + return shift;
- +
- + return 0;
- +}
- +
- --- /dev/null
- +++ b/gcc/config/ubicom32/ubicom32.h
- @@ -0,0 +1,1564 @@
- +/* Definitions of target machine for Ubicom32
- +
- + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- + 2009 Free Software Foundation, Inc.
- + Contributed by Ubicom, Inc.
- +
- + This file is part of GCC.
- +
- + GCC is free software; you can redistribute it and/or modify it
- + under the terms of the GNU General Public License as published
- + by the Free Software Foundation; either version 3, or (at your
- + option) any later version.
- +
- + GCC is distributed in the hope that it will be useful, but WITHOUT
- + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- + License for more details.
- +
- + You should have received a copy of the GNU General Public License
- + along with GCC; see the file COPYING3. If not see
- + <http://www.gnu.org/licenses/>. */
- +
- +
- +
- +#define OBJECT_FORMAT_ELF
- +
- +/* Run-time target specifications. */
- +
- +/* Target CPU builtins. */
- +#define TARGET_CPU_CPP_BUILTINS() \
- + do \
- + { \
- + builtin_define_std ("__UBICOM32__"); \
- + builtin_define_std ("__ubicom32__"); \
- + \
- + if (TARGET_FDPIC) \
- + { \
- + builtin_define ("__UBICOM32_FDPIC__"); \
- + builtin_define ("__FDPIC__"); \
- + } \
- + } \
- + while (0)
- +
- +#ifndef TARGET_DEFAULT
- +#define TARGET_DEFAULT 0
- +#endif
- +
- +extern int ubicom32_case_values_threshold;
- +
- +/* Nonzero if this chip supports the Ubicom32 v3 ISA. */
- +extern int ubicom32_v3;
- +
- +/* Nonzero if this chip supports the Ubicom32 v4 ISA. */
- +extern int ubicom32_v4;
- +
- +extern int ubicom32_stack_size;
- +
- +/* Flag for whether we can use calli instead of ret in returns. */
- +extern int ubicom32_can_use_calli_to_ret;
- +
- +/* This macro is a C statement to print on `stderr' a string describing the
- + particular machine description choice. Every machine description should
- + define `TARGET_VERSION'. */
- +#define TARGET_VERSION fprintf (stderr, " (UBICOM32)");
- +
- +/* We don't need a frame pointer to debug things. Doing this means
- + that gcc can turn on -fomit-frame-pointer when '-O' is specified. */
- +#define CAN_DEBUG_WITHOUT_FP
- +
- +/* We need to handle processor-specific options. */
- +#define OVERRIDE_OPTIONS ubicom32_override_options ()
- +
- +#define OPTIMIZATION_OPTIONS(LEVEL, SIZE) \
- + ubicom32_optimization_options (LEVEL, SIZE)
- +
- +/* For Ubicom32 the least significant bit has the lowest bit number
- + so we define this to be 0. */
- +#define BITS_BIG_ENDIAN 0
- +
- +/* For Ubicom32 the most significant byte in a word has the lowest
- + number. */
- +#define BYTES_BIG_ENDIAN 1
- +
- +/* For Ubicom32, in a multiword object, the most signifant word has the
- + lowest number. */
- +#define WORDS_BIG_ENDIAN 1
- +
- +/* Ubicom32 has 8 bits per byte. */
- +#define BITS_PER_UNIT 8
- +
- +/* Ubicom32 has 32 bits per word. */
- +#define BITS_PER_WORD 32
- +
- +/* Width of a word, in units (bytes). */
- +#define UNITS_PER_WORD 4
- +
- +/* Width of a pointer, in bits. */
- +#define POINTER_SIZE 32
- +
- +/* Alias for pointers. Ubicom32 is a 32-bit architecture so we use
- + SImode. */
- +#define Pmode SImode
- +
- +/* Normal alignment required for function parameters on the stack, in
- + bits. */
- +#define PARM_BOUNDARY 32
- +
- +/* We need to maintain the stack on a 32-bit boundary. */
- +#define STACK_BOUNDARY 32
- +
- +/* Alignment required for a function entry point, in bits. */
- +#define FUNCTION_BOUNDARY 32
- +
- +/* Alias for the machine mode used for memory references to functions being
- + called, in `call' RTL expressions. We use byte-oriented addresses
- + here. */
- +#define FUNCTION_MODE QImode
- +
- +/* Biggest alignment that any data type can require on this machine,
- + in bits. */
- +#define BIGGEST_ALIGNMENT 32
- +
- +/* this default to BIGGEST_ALIGNMENT unless defined */
- +/* ART: What's the correct value here? Default is (((unsigned int)1<<28)*8)*/
- +#undef MAX_OFILE_ALIGNMENT
- +#define MAX_OFILE_ALIGNMENT (128 * 8)
- +
- +/* Alignment in bits to be given to a structure bit field that follows an empty
- + field such as `int : 0;'. */
- +#define EMPTY_FIELD_BOUNDARY 32
- +
- +/* All structures must be a multiple of 32 bits in size. */
- +#define STRUCTURE_SIZE_BOUNDARY 32
- +
- +/* A bit-field declared as `int' forces `int' alignment for the struct. */
- +#define PCC_BITFIELD_TYPE_MATTERS 1
- +
- +/* For Ubicom32 we absolutely require that data be aligned with nominal
- + alignment. */
- +#define STRICT_ALIGNMENT 1
- +
- +/* Make strcpy of constants fast. */
- +#define CONSTANT_ALIGNMENT(EXP, ALIGN) \
- + (TREE_CODE (EXP) == STRING_CST \
- + && (ALIGN) < BITS_PER_WORD ? BITS_PER_WORD : (ALIGN))
- +
- +/* Define this macro as an expression for the alignment of a structure
- + (given by STRUCT as a tree node) if the alignment computed in the
- + usual way is COMPUTED and the alignment explicitly specified was
- + SPECIFIED. */
- +#define DATA_ALIGNMENT(TYPE, ALIGN) \
- + ((((ALIGN) < BITS_PER_WORD) \
- + && (TREE_CODE (TYPE) == ARRAY_TYPE \
- + || TREE_CODE (TYPE) == UNION_TYPE \
- + || TREE_CODE (TYPE) == RECORD_TYPE)) ? BITS_PER_WORD : (ALIGN))
- +
- +#define LOCAL_ALIGNMENT(TYPE,ALIGN) DATA_ALIGNMENT(TYPE,ALIGN)
- +
- +/* For Ubicom32 we default to unsigned chars. */
- +#define DEFAULT_SIGNED_CHAR 0
- +
- +/* Machine-specific data register numbers. */
- +#define FIRST_DATA_REGNUM 0
- +#define D10_REGNUM 10
- +#define D11_REGNUM 11
- +#define D12_REGNUM 12
- +#define D13_REGNUM 13
- +#define LAST_DATA_REGNUM 15
- +
- +/* Machine-specific address register numbers. */
- +#define FIRST_ADDRESS_REGNUM 16
- +#define LAST_ADDRESS_REGNUM 22
- +
- +/* Register numbers used for passing a function's static chain pointer. If
- + register windows are used, the register number as seen by the called
- + function is `STATIC_CHAIN_INCOMING_REGNUM', while the register number as
- + seen by the calling function is `STATIC_CHAIN_REGNUM'. If these registers
- + are the same, `STATIC_CHAIN_INCOMING_REGNUM' need not be defined.
- +
- + The static chain register need not be a fixed register.
- +
- + If the static chain is passed in memory, these macros should not be defined;
- + instead, the next two macros should be defined. */
- +#define STATIC_CHAIN_REGNUM (FIRST_ADDRESS_REGNUM + 1)
- +
- +/* The register number of the frame pointer register, which is used to access
- + automatic variables in the stack frame. We generally eliminate this anyway
- + for Ubicom32 but we make it A6 by default. */
- +#define FRAME_POINTER_REGNUM (LAST_ADDRESS_REGNUM)
- +
- +/* The register number of the stack pointer register, which is also be a
- + fixed register according to `FIXED_REGISTERS'. For Ubicom32 we don't
- + have a hardware requirement about which register this is, but by convention
- + we use A7. */
- +#define STACK_POINTER_REGNUM (LAST_ADDRESS_REGNUM + 1)
- +
- +/* Machine-specific accumulator register numbers. */
- +#define ACC0_HI_REGNUM 24
- +#define ACC0_LO_REGNUM 25
- +#define ACC1_HI_REGNUM 26
- +#define ACC1_LO_REGNUM 27
- +
- +/* source3 register number */
- +#define SOURCE3_REGNUM 28
- +
- +/* The register number of the arg pointer register, which is used to access the
- + function's argument list. On some machines, this is the same as the frame
- + pointer register. On some machines, the hardware determines which register
- + this is. On other machines, you can choose any register you wish for this
- + purpose. If this is not the same register as the frame pointer register,
- + then you must mark it as a fixed register according to `FIXED_REGISTERS', or
- + arrange to be able to eliminate it. */
- +#define ARG_POINTER_REGNUM 29
- +
- +/* Pseudo-reg for condition code. */
- +#define CC_REGNUM 30
- +
- +/* Interrupt set/clear registers. */
- +#define INT_SET0_REGNUM 31
- +#define INT_SET1_REGNUM 32
- +#define INT_CLR0_REGNUM 33
- +#define INT_CLR1_REGNUM 34
- +
- +/* Scratchpad registers. */
- +#define SCRATCHPAD0_REGNUM 35
- +#define SCRATCHPAD1_REGNUM 36
- +#define SCRATCHPAD2_REGNUM 37
- +#define SCRATCHPAD3_REGNUM 38
- +
- +/* FDPIC register. */
- +#define FDPIC_REGNUM 16
- +
- +/* Number of hardware registers known to the compiler. They receive numbers 0
- + through `FIRST_PSEUDO_REGISTER-1'; thus, the first pseudo register's number
- + really is assigned the number `FIRST_PSEUDO_REGISTER'. */
- +#define FIRST_PSEUDO_REGISTER 39
- +
- +/* An initializer that says which registers are used for fixed purposes all
- + throughout the compiled code and are therefore not available for general
- + allocation. These would include the stack pointer, the frame pointer
- + (except on machines where that can be used as a general register when no
- + frame pointer is needed), the program counter on machines where that is
- + considered one of the addressable registers, and any other numbered register
- + with a standard use.
- +
- + This information is expressed as a sequence of numbers, separated by commas
- + and surrounded by braces. The Nth number is 1 if register N is fixed, 0
- + otherwise.
- +
- + The table initialized from this macro, and the table initialized by the
- + following one, may be overridden at run time either automatically, by the
- + actions of the macro `CONDITIONAL_REGISTER_USAGE', or by the user with the
- + command options `-ffixed-REG', `-fcall-used-REG' and `-fcall-saved-REG'. */
- +#define FIXED_REGISTERS \
- + { \
- + 0, 0, 0, 0, 0, 0, 0, 0, /* d0 - d7 */ \
- + 0, 0, 0, 0, 0, 0, 0, 1, /* d8 - d15 */ \
- + 0, 0, 0, 0, 0, 0, 0, 1, /* a0 - a7 */ \
- + 0, 0, /* acc0 hi/lo */ \
- + 0, 0, /* acc1 hi/lo */ \
- + 0, /* source3 */ \
- + 1, /* arg */ \
- + 1, /* cc */ \
- + 1, 1, /* int_set[01] */ \
- + 1, 1, /* int_clr[01] */ \
- + 1, 1, 1, 1 /* scratchpad[0123] */ \
- + }
- +
- +/* Like `FIXED_REGISTERS' but has 1 for each register that is clobbered (in
- + general) by function calls as well as for fixed registers. This macro
- + therefore identifies the registers that are not available for general
- + allocation of values that must live across function calls.
- +
- + If a register has 0 in `CALL_USED_REGISTERS', the compiler automatically
- + saves it on function entry and restores it on function exit, if the register
- + is used within the function. */
- +#define CALL_USED_REGISTERS \
- + { \
- + 1, 1, 1, 1, 1, 1, 1, 1, /* d0 - d7 */ \
- + 1, 1, 0, 0, 0, 0, 1, 1, /* d8 - d15 */ \
- + 1, 0, 0, 1, 1, 1, 0, 1, /* a0 - a7 */ \
- + 1, 1, /* acc0 hi/lo */ \
- + 1, 1, /* acc1 hi/lo */ \
- + 1, /* source3 */ \
- + 1, /* arg */ \
- + 1, /* cc */ \
- + 1, 1, /* int_set[01] */ \
- + 1, 1, /* int_clr[01] */ \
- + 1, 1, 1, 1 /* scratchpad[0123] */ \
- + }
- +
- +/* How to refer to registers in assembler output.
- + This sequence is indexed by compiler's hard-register-number (see above). */
- +
- +/* A C initializer containing the assembler's names for the machine registers,
- + each one as a C string constant. This is what translates register numbers
- + in the compiler into assembler language. */
- +#define REGISTER_NAMES \
- + { \
- + "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7", \
- + "d8", "d9", "d10", "d11", "d12", "d13", "d14", "d15", \
- + "a0", "a1", "a2", "a3", "a4", "a5", "a6", "sp", \
- + "acc0_hi", "acc0_lo", \
- + "acc1_hi", "acc1_lo", \
- + "source3", \
- + "arg", \
- + "cc", \
- + "int_set0", "int_set1", \
- + "int_clr0", "int_clr1", \
- + "scratchpad0", "scratchpad1", "scratchpad2", "scratchpad3" \
- + }
- +
- +#define CONDITIONAL_REGISTER_USAGE \
- + ubicom32_conditional_register_usage ();
- +
- +/* Order of allocation of registers. */
- +
- +/* If defined, an initializer for a vector of integers, containing the numbers
- + of hard registers in the order in which GNU CC should prefer to use them
- + (from most preferred to least).
- +
- + For Ubicom32 we try using caller-clobbered data registers first, then
- + callee-saved data registers, then caller-clobbered address registers,
- + then callee-saved address registers and finally everything else.
- +
- + The caller-clobbered registers are usually slightly cheaper to use because
- + there's no need to save/restore. */
- +#define REG_ALLOC_ORDER \
- + { \
- + 0, 1, 2, 3, 4, /* d0 - d4 */ \
- + 5, 6, 7, 8, 9, /* d5 - d9 */ \
- + 14, /* d14 */ \
- + 10, 11, 12, 13, /* d10 - d13 */ \
- + 19, 20, 16, 21, /* a3, a4, a0, a5 */ \
- + 17, 18, 22, /* a1, a2, a6 */ \
- + 24, 25, /* acc0 hi/lo */ \
- + 26, 27, /* acc0 hi/lo */ \
- + 28 /* source3 */ \
- + }
- +
- +/* C expression for the number of consecutive hard registers, starting at
- + register number REGNO, required to hold a value of mode MODE. */
- +#define HARD_REGNO_NREGS(REGNO, MODE) \
- + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
- +
- +/* Most registers can hold QImode, HImode and SImode values but we have to
- + be able to indicate any hard registers that cannot hold values with some
- + modes. */
- +#define HARD_REGNO_MODE_OK(REGNO, MODE) \
- + ubicom32_hard_regno_mode_ok(REGNO, MODE)
- +
- +/* We can rename most registers aside from the FDPIC register if we're using
- + FDPIC. */
- +#define HARD_REGNO_RENAME_OK(from, to) (TARGET_FDPIC ? ((to) != FDPIC_REGNUM) : 1)
- +
- +/* A C expression that is nonzero if it is desirable to choose register
- + allocation so as to avoid move instructions between a value of mode MODE1
- + and a value of mode MODE2.
- +
- + If `HARD_REGNO_MODE_OK (R, MODE1)' and `HARD_REGNO_MODE_OK (R, MODE2)' are
- + ever different for any R, then `MODES_TIEABLE_P (MODE1, MODE2)' must be
- + zero. */
- +#define MODES_TIEABLE_P(MODE1, MODE2) 1
- +
- +/* An enumeral type that must be defined with all the register class names as
- + enumeral values. `NO_REGS' must be first. `ALL_REGS' must be the last
- + register class, followed by one more enumeral value, `LIM_REG_CLASSES',
- + which is not a register class but rather tells how many classes there are.
- +
- + Each register class has a number, which is the value of casting the class
- + name to type `int'. The number serves as an index in many of the tables
- + described below. */
- +
- +enum reg_class
- +{
- + NO_REGS,
- + DATA_REGS,
- + FDPIC_REG,
- + ADDRESS_REGS,
- + ALL_ADDRESS_REGS,
- + ACC_LO_REGS,
- + ACC_REGS,
- + CC_REG,
- + DATA_ACC_REGS,
- + SOURCE3_REG,
- + SPECIAL_REGS,
- + GENERAL_REGS,
- + ALL_REGS,
- + LIM_REG_CLASSES
- +};
- +
- +/* The number of distinct register classes. */
- +#define N_REG_CLASSES (int) LIM_REG_CLASSES
- +
- +/* An initializer containing the names of the register classes as C string
- + constants. These names are used in writing some of the debugging dumps. */
- +
- +#define REG_CLASS_NAMES \
- +{ \
- + "NO_REGS", \
- + "DATA_REGS", \
- + "FDPIC_REG", \
- + "ADDRESS_REGS", \
- + "ALL_ADDRESS_REGS", \
- + "ACC_LO_REGS", \
- + "ACC_REGS", \
- + "CC_REG", \
- + "DATA_ACC_REGS", \
- + "SOURCE3_REG", \
- + "SPECIAL_REGS", \
- + "GENERAL_REGS", \
- + "ALL_REGS", \
- + "LIM_REGS" \
- +}
- +
- +/* An initializer containing the contents of the register classes, as integers
- + which are bit masks. The Nth integer specifies the contents of class N.
- + The way the integer MASK is interpreted is that register R is in the class
- + if `MASK & (1 << R)' is 1.
- +
- + When the machine has more than 32 registers, an integer does not suffice.
- + Then the integers are replaced by sub-initializers, braced groupings
- + containing several integers. Each sub-initializer must be suitable as an
- + initializer for the type `HARD_REG_SET' which is defined in
- + `hard-reg-set.h'. */
- +#define REG_CLASS_CONTENTS \
- +{ \
- + {0x00000000, 0x00000000}, /* No regs */ \
- + {0x0000ffff, 0x00000000}, /* DATA_REGS */ \
- + {0x00010000, 0x00000000}, /* FDPIC_REG */ \
- + {0x20fe0000, 0x00000000}, /* ADDRESS_REGS */ \
- + {0x20ff0000, 0x00000000}, /* ALL_ADDRESS_REGS */ \
- + {0x0a000000, 0x00000000}, /* ACC_LO_REGS */ \
- + {0x0f000000, 0x00000000}, /* ACC_REGS */ \
- + {0x40000000, 0x00000000}, /* CC_REG */ \
- + {0x0f00ffff, 0x00000000}, /* DATA_ACC_REGS */ \
- + {0x10000000, 0x00000000}, /* SOURGE3_REG */ \
- + {0x80000000, 0x0000007f}, /* SPECIAL_REGS */ \
- + {0xbfffffff, 0x0000007f}, /* GENERAL_REGS */ \
- + {0xbfffffff, 0x0000007f} /* ALL_REGS */ \
- +}
- +
- +extern enum reg_class const ubicom32_regclass_map[FIRST_PSEUDO_REGISTER];
- +
- +/* A C expression whose value is a register class containing hard register
- + REGNO. In general there is more than one such class; choose a class which
- + is "minimal", meaning that no smaller class also contains the register. */
- +#define REGNO_REG_CLASS(REGNO) (ubicom32_regclass_map[REGNO])
- +
- +#define IRA_COVER_CLASSES \
- +{ \
- + GENERAL_REGS, \
- + LIM_REG_CLASSES \
- +}
- +
- +/* Ubicom32 base registers must be address registers since addresses can
- + only be reached via address registers. */
- +#define BASE_REG_CLASS ALL_ADDRESS_REGS
- +
- +/* Ubicom32 index registers must be data registers since we cannot add
- + two address registers together to form an address. */
- +#define INDEX_REG_CLASS DATA_REGS
- +
- +/* A C expression which is nonzero if register number NUM is suitable for use
- + as a base register in operand addresses. It may be either a suitable hard
- + register or a pseudo register that has been allocated such a hard register. */
- +
- +#ifndef REG_OK_STRICT
- +#define REGNO_OK_FOR_BASE_P(regno) \
- + ubicom32_regno_ok_for_base_p (regno, 0)
- +#else
- +#define REGNO_OK_FOR_BASE_P(regno) \
- + ubicom32_regno_ok_for_base_p (regno, 1)
- +#endif
- +
- +/* A C expression which is nonzero if register number NUM is suitable for use
- + as an index register in operand addresses. It may be either a suitable hard
- + register or a pseudo register that has been allocated such a hard register.
- +
- + The difference between an index register and a base register is that the
- + index register may be scaled. If an address involves the sum of two
- + registers, neither one of them scaled, then either one may be labeled the
- + "base" and the other the "index"; but whichever labeling is used must fit
- + the machine's constraints of which registers may serve in each capacity.
- + The compiler will try both labelings, looking for one that is valid, and
- + will reload one or both registers only if neither labeling works. */
- +#ifndef REG_OK_STRICT
- +#define REGNO_OK_FOR_INDEX_P(regno) \
- + ubicom32_regno_ok_for_index_p (regno, 0)
- +#else
- +#define REGNO_OK_FOR_INDEX_P(regno) \
- + ubicom32_regno_ok_for_index_p (regno, 1)
- +#endif
- +
- +/* Attempt to restrict the register class we need to copy value X intoto the
- + would-be register class CLASS. Most things are fine for Ubicom32 but we
- + have to restrict certain types of address loads. */
- +#define PREFERRED_RELOAD_CLASS(X, CLASS) \
- + ubicom32_preferred_reload_class (X, CLASS)
- +
- +/* A C expression for the maximum number of consecutive registers of
- + class CLASS needed to hold a value of mode MODE. For Ubicom32 this
- + is pretty much identical to HARD_REGNO_NREGS. */
- +#define CLASS_MAX_NREGS(CLASS, MODE) \
- + ((GET_MODE_SIZE (MODE) + UNITS_PER_WORD - 1) / UNITS_PER_WORD)
- +
- +/* For Ubicom32 the stack grows downwards when we push a word onto the stack
- + - i.e. it moves to a smaller address. */
- +#define STACK_GROWS_DOWNWARD 1
- +
- +/* Offset from the frame pointer to the first local variable slot to
- + be allocated. */
- +#define STARTING_FRAME_OFFSET 0
- +
- +/* Offset from the argument pointer register to the first argument's
- + address. */
- +#define FIRST_PARM_OFFSET(FNDECL) 0
- +
- +/* A C expression whose value is RTL representing the value of the return
- + address for the frame COUNT steps up from the current frame, after the
- + prologue. FRAMEADDR is the frame pointer of the COUNT frame, or the frame
- + pointer of the COUNT - 1 frame if `RETURN_ADDR_IN_PREVIOUS_FRAME' is
- + defined.
- +
- + The value of the expression must always be the correct address when COUNT is
- + zero, but may be `NULL_RTX' if there is not way to determine the return
- + address of other frames. */
- +#define RETURN_ADDR_RTX(COUNT, FRAME) \
- + ubicom32_return_addr_rtx (COUNT, FRAME)
- +
- +/* Register That Address the Stack Frame. */
- +
- +/* We don't actually require a frame pointer in most functions with the
- + Ubicom32 architecture so we allow it to be eliminated. */
- +#define FRAME_POINTER_REQUIRED 0
- +
- +/* Macro that defines a table of register pairs used to eliminate unecessary
- + registers that point into the stack frame.
- +
- + For Ubicom32 we don't generally need an arg pointer of a frame pointer
- + so we allow the arg pointer to be replaced by either the frame pointer or
- + the stack pointer. We also allow the frame pointer to be replaced by
- + the stack pointer. */
- +#define ELIMINABLE_REGS \
- +{ \
- + {ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
- + {ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
- + {FRAME_POINTER_REGNUM, STACK_POINTER_REGNUM} \
- +}
- +
- +/* Let the compiler know that we want to use the ELIMINABLE_REGS macro
- + above. */
- +#define CAN_ELIMINATE(FROM, TO) 1
- +
- +/* This macro is similar to `INITIAL_FRAME_POINTER_OFFSET'. It specifies the
- + initial difference between the specified pair of registers. This macro must
- + be defined if `ELIMINABLE_REGS' is defined. */
- +#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
- + (OFFSET) = ubicom32_initial_elimination_offset (FROM, TO)
- +
- +/* If defined, the maximum amount of space required for outgoing arguments will
- + be computed and placed into the variable
- + `current_function_outgoing_args_size'. No space will be pushed onto the
- + stack for each call; instead, the function prologue should increase the
- + stack frame size by this amount.
- +
- + Defining both `PUSH_ROUNDING' and `ACCUMULATE_OUTGOING_ARGS' is not
- + proper. */
- +#define ACCUMULATE_OUTGOING_ARGS 1
- +
- +/* Define this macro if functions should assume that stack space has been
- + allocated for arguments even when their values are passed in registers.
- +
- + The value of this macro is the size, in bytes, of the area reserved for
- + arguments passed in registers for the function represented by FNDECL.
- +
- + This space can be allocated by the caller, or be a part of the
- + machine-dependent stack frame: `OUTGOING_REG_PARM_STACK_SPACE' says
- + which. */
- +#define REG_PARM_STACK_SPACE(FNDECL) ubicom32_reg_parm_stack_space(FNDECL)
- +
- +/* A C expression that should indicate the number of bytes of its own arguments
- + that a function pops on returning, or 0 if the function pops no arguments
- + and the caller must therefore pop them all after the function returns.
- +
- + FUNDECL is a C variable whose value is a tree node that describes the
- + function in question. Normally it is a node of type `FUNCTION_DECL' that
- + describes the declaration of the function. From this it is possible to
- + obtain the DECL_MACHINE_ATTRIBUTES of the function.
- +
- + FUNTYPE is a C variable whose value is a tree node that describes the
- + function in question. Normally it is a node of type `FUNCTION_TYPE' that
- + describes the data type of the function. From this it is possible to obtain
- + the data types of the value and arguments (if known).
- +
- + When a call to a library function is being considered, FUNTYPE will contain
- + an identifier node for the library function. Thus, if you need to
- + distinguish among various library functions, you can do so by their names.
- + Note that "library function" in this context means a function used to
- + perform arithmetic, whose name is known specially in the compiler and was
- + not mentioned in the C code being compiled.
- +
- + STACK-SIZE is the number of bytes of arguments passed on the stack. If a
- + variable number of bytes is passed, it is zero, and argument popping will
- + always be the responsibility of the calling function.
- +
- + On the Vax, all functions always pop their arguments, so the definition of
- + this macro is STACK-SIZE. On the 68000, using the standard calling
- + convention, no functions pop their arguments, so the value of the macro is
- + always 0 in this case. But an alternative calling convention is available
- + in which functions that take a fixed number of arguments pop them but other
- + functions (such as `printf') pop nothing (the caller pops all). When this
- + convention is in use, FUNTYPE is examined to determine whether a function
- + takes a fixed number of arguments. */
- +#define RETURN_POPS_ARGS(FUNDECL, FUNTYPE, STACK_SIZE) 0
- +
- +/* A C expression that controls whether a function argument is passed in a
- + register, and which register.
- +
- + The arguments are CUM, of type CUMULATIVE_ARGS, which summarizes (in a way
- + defined by INIT_CUMULATIVE_ARGS and FUNCTION_ARG_ADVANCE) all of the previous
- + arguments so far passed in registers; MODE, the machine mode of the argument;
- + TYPE, the data type of the argument as a tree node or 0 if that is not known
- + (which happens for C support library functions); and NAMED, which is 1 for an
- + ordinary argument and 0 for nameless arguments that correspond to `...' in the
- + called function's prototype.
- +
- + The value of the expression should either be a `reg' RTX for the hard
- + register in which to pass the argument, or zero to pass the argument on the
- + stack.
- +
- + For machines like the Vax and 68000, where normally all arguments are
- + pushed, zero suffices as a definition.
- +
- + The usual way to make the ANSI library `stdarg.h' work on a machine where
- + some arguments are usually passed in registers, is to cause nameless
- + arguments to be passed on the stack instead. This is done by making
- + `FUNCTION_ARG' return 0 whenever NAMED is 0.
- +
- + You may use the macro `MUST_PASS_IN_STACK (MODE, TYPE)' in the definition of
- + this macro to determine if this argument is of a type that must be passed in
- + the stack. If `REG_PARM_STACK_SPACE' is not defined and `FUNCTION_ARG'
- + returns non-zero for such an argument, the compiler will abort. If
- + `REG_PARM_STACK_SPACE' is defined, the argument will be computed in the
- + stack and then loaded into a register. */
- +#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- + function_arg (&CUM, MODE, TYPE, NAMED)
- +
- +#define FUNCTION_INCOMING_ARG(CUM, MODE, TYPE, NAMED) \
- + function_incoming_arg (&CUM, MODE, TYPE, NAMED)
- +
- +/* A C expression for the number of words, at the beginning of an argument,
- + must be put in registers. The value must be zero for arguments that are
- + passed entirely in registers or that are entirely pushed on the stack.
- +
- + On some machines, certain arguments must be passed partially in registers
- + and partially in memory. On these machines, typically the first N words of
- + arguments are passed in registers, and the rest on the stack. If a
- + multi-word argument (a `double' or a structure) crosses that boundary, its
- + first few words must be passed in registers and the rest must be pushed.
- + This macro tells the compiler when this occurs, and how many of the words
- + should go in registers.
- +
- + `FUNCTION_ARG' for these arguments should return the first register to be
- + used by the caller for this argument; likewise `FUNCTION_INCOMING_ARG', for
- + the called function. */
- +
- +/* A C expression that indicates when an argument must be passed by reference.
- + If nonzero for an argument, a copy of that argument is made in memory and a
- + pointer to the argument is passed instead of the argument itself. The
- + pointer is passed in whatever way is appropriate for passing a pointer to
- + that type.
- +
- + On machines where `REG_PARM_STACK_SPACE' is not defined, a suitable
- + definition of this macro might be
- + #define FUNCTION_ARG_PASS_BY_REFERENCE(CUM, MODE, TYPE, NAMED) \
- + MUST_PASS_IN_STACK (MODE, TYPE) */
- +
- +/* If defined, a C expression that indicates when it is the called function's
- + responsibility to make a copy of arguments passed by invisible reference.
- + Normally, the caller makes a copy and passes the address of the copy to the
- + routine being called. When FUNCTION_ARG_CALLEE_COPIES is defined and is
- + nonzero, the caller does not make a copy. Instead, it passes a pointer to
- + the "live" value. The called function must not modify this value. If it
- + can be determined that the value won't be modified, it need not make a copy;
- + otherwise a copy must be made. */
- +
- +/* A C type for declaring a variable that is used as the first argument of
- + `FUNCTION_ARG' and other related values. For some target machines, the type
- + `int' suffices and can hold the number of bytes of argument so far.
- +
- + There is no need to record in `CUMULATIVE_ARGS' anything about the arguments
- + that have been passed on the stack. The compiler has other variables to
- + keep track of that. For target machines on which all arguments are passed
- + on the stack, there is no need to store anything in `CUMULATIVE_ARGS';
- + however, the data structure must exist and should not be empty, so use
- + `int'. */
- +struct cum_arg
- +{
- + int nbytes;
- + int reg;
- + int stdarg;
- +};
- +#define CUMULATIVE_ARGS struct cum_arg
- +
- +/* A C statement (sans semicolon) for initializing the variable CUM for the
- + state at the beginning of the argument list. The variable has type
- + `CUMULATIVE_ARGS'. The value of FNTYPE is the tree node for the data type
- + of the function which will receive the args, or 0 if the args are to a
- + compiler support library function. The value of INDIRECT is nonzero when
- + processing an indirect call, for example a call through a function pointer.
- + The value of INDIRECT is zero for a call to an explicitly named function, a
- + library function call, or when `INIT_CUMULATIVE_ARGS' is used to find
- + arguments for the function being compiled.
- +
- + When processing a call to a compiler support library function, LIBNAME
- + identifies which one. It is a `symbol_ref' rtx which contains the name of
- + the function, as a string. LIBNAME is 0 when an ordinary C function call is
- + being processed. Thus, each time this macro is called, either LIBNAME or
- + FNTYPE is nonzero, but never both of them at once. */
- +
- +#define INIT_CUMULATIVE_ARGS(CUM,FNTYPE,LIBNAME,INDIRECT, NAMED_ARGS) \
- + init_cumulative_args (&(CUM), FNTYPE, LIBNAME, INDIRECT);
- +
- +/* A C statement (sans semicolon) to update the summarizer variable CUM to
- + advance past an argument in the argument list. The values MODE, TYPE and
- + NAMED describe that argument. Once this is done, the variable CUM is
- + suitable for analyzing the *following* argument with `FUNCTION_ARG', etc.
- +
- + This macro need not do anything if the argument in question was passed on
- + the stack. The compiler knows how to track the amount of stack space used
- + for arguments without any special help. */
- +#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- + ((CUM).nbytes += ((MODE) != BLKmode \
- + ? (GET_MODE_SIZE (MODE) + 3) & ~3 \
- + : (int_size_in_bytes (TYPE) + 3) & ~3))
- +
- +/* For the Ubicom32 we define the upper function argument register here. */
- +#define UBICOM32_FUNCTION_ARG_REGS 10
- +
- +/* A C expression that is nonzero if REGNO is the number of a hard register in
- + which function arguments are sometimes passed. This does *not* include
- + implicit arguments such as the static chain and the structure-value address.
- + On many machines, no registers can be used for this purpose since all
- + function arguments are pushed on the stack. */
- +#define FUNCTION_ARG_REGNO_P(N) ((N) < UBICOM32_FUNCTION_ARG_REGS)
- +
- +
- +/* How Scalar Function Values are Returned. */
- +
- +/* The number of the hard register that is used to return a scalar value from a
- + function call. */
- +#define RETURN_VALUE_REGNUM 0
- +
- +/* A C expression to create an RTX representing the place where a function
- + returns a value of data type VALTYPE. VALTYPE is a tree node representing a
- + data type. Write `TYPE_MODE (VALTYPE)' to get the machine mode used to
- + represent that type. On many machines, only the mode is relevant.
- + (Actually, on most machines, scalar values are returned in the same place
- + regardless of mode).
- +
- + If `PROMOTE_FUNCTION_RETURN' is defined, you must apply the same promotion
- + rules specified in `PROMOTE_MODE' if VALTYPE is a scalar type.
- +
- + If the precise function being called is known, FUNC is a tree node
- + (`FUNCTION_DECL') for it; otherwise, FUNC is a null pointer. This makes it
- + possible to use a different value-returning convention for specific
- + functions when all their calls are known.
- +
- + `FUNCTION_VALUE' is not used for return vales with aggregate data types,
- + because these are returned in another way. See `STRUCT_VALUE_REGNUM' and
- + related macros, below. */
- +#define FUNCTION_VALUE(VALTYPE, FUNC) \
- + gen_rtx_REG (TYPE_MODE (VALTYPE), FIRST_DATA_REGNUM)
- +
- +/* A C expression to create an RTX representing the place where a library
- + function returns a value of mode MODE.
- +
- + Note that "library function" in this context means a compiler support
- + routine, used to perform arithmetic, whose name is known specially by the
- + compiler and was not mentioned in the C code being compiled.
- +
- + The definition of `LIBRARY_VALUE' need not be concerned aggregate data
- + types, because none of the library functions returns such types. */
- +#define LIBCALL_VALUE(MODE) gen_rtx_REG (MODE, FIRST_DATA_REGNUM)
- +
- +/* A C expression that is nonzero if REGNO is the number of a hard register in
- + which the values of called function may come back.
- +
- + A register whose use for returning values is limited to serving as the
- + second of a pair (for a value of type `double', say) need not be recognized
- + by this macro. So for most machines, this definition suffices:
- +
- + #define FUNCTION_VALUE_REGNO_P(N) ((N) == RETURN)
- +
- + If the machine has register windows, so that the caller and the called
- + function use different registers for the return value, this macro should
- + recognize only the caller's register numbers. */
- +#define FUNCTION_VALUE_REGNO_P(N) ((N) == FIRST_DATA_REGNUM)
- +
- +
- +/* How Large Values are Returned. */
- +
- +/* A C expression which can inhibit the returning of certain function values in
- + registers, based on the type of value. A nonzero value says to return the
- + function value in memory, just as large structures are always returned.
- + Here TYPE will be a C expression of type `tree', representing the data type
- + of the value.
- +
- + Note that values of mode `BLKmode' must be explicitly handled by this macro.
- + Also, the option `-fpcc-struct-return' takes effect regardless of this
- + macro. On most systems, it is possible to leave the macro undefined; this
- + causes a default definition to be used, whose value is the constant 1 for
- + `BLKmode' values, and 0 otherwise.
- +
- + Do not use this macro to indicate that structures and unions should always
- + be returned in memory. You should instead use `DEFAULT_PCC_STRUCT_RETURN'
- + to indicate this. */
- +#define RETURN_IN_MEMORY(TYPE) \
- + (int_size_in_bytes (TYPE) > 8 || TYPE_MODE (TYPE) == BLKmode)
- +
- +/* Define this macro to be 1 if all structure and union return values must be
- + in memory. Since this results in slower code, this should be defined only
- + if needed for compatibility with other compilers or with an ABI. If you
- + define this macro to be 0, then the conventions used for structure and union
- + return values are decided by the `RETURN_IN_MEMORY' macro.
- +
- + If not defined, this defaults to the value 1. */
- +#define DEFAULT_PCC_STRUCT_RETURN 0
- +
- +/* If the structure value address is not passed in a register, define
- + `STRUCT_VALUE' as an expression returning an RTX for the place
- + where the address is passed. If it returns 0, the address is
- + passed as an "invisible" first argument. */
- +#define STRUCT_VALUE 0
- +
- +/* Define this macro as a C expression that is nonzero if the return
- + instruction or the function epilogue ignores the value of the stack pointer;
- + in other words, if it is safe to delete an instruction to adjust the stack
- + pointer before a return from the function.
- +
- + Note that this macro's value is relevant only for functions for which frame
- + pointers are maintained. It is never safe to delete a final stack
- + adjustment in a function that has no frame pointer, and the compiler knows
- + this regardless of `EXIT_IGNORE_STACK'. */
- +#define EXIT_IGNORE_STACK 1
- +
- +/* A C statement or compound statement to output to FILE some assembler code to
- + call the profiling subroutine `mcount'. Before calling, the assembler code
- + must load the address of a counter variable into a register where `mcount'
- + expects to find the address. The name of this variable is `LP' followed by
- + the number LABELNO, so you would generate the name using `LP%d' in a
- + `fprintf'.
- +
- + The details of how the address should be passed to `mcount' are determined
- + by your operating system environment, not by GNU CC. To figure them out,
- + compile a small program for profiling using the system's installed C
- + compiler and look at the assembler code that results.
- +
- + This declaration must be present, but it can be an abort if profiling is
- + not implemented. */
- +
- +#define FUNCTION_PROFILER(file, labelno) ubicom32_profiler(file, labelno)
- +
- +/* A C statement to output, on the stream FILE, assembler code for a block of
- + data that contains the constant parts of a trampoline. This code should not
- + include a label--the label is taken care of automatically. */
- +#if 0
- +#define TRAMPOLINE_TEMPLATE(FILE) \
- + do { \
- + fprintf (FILE, "\tadd -4,sp\n"); \
- + fprintf (FILE, "\t.long 0x0004fffa\n"); \
- + fprintf (FILE, "\tmov (0,sp),a0\n"); \
- + fprintf (FILE, "\tadd 4,sp\n"); \
- + fprintf (FILE, "\tmov (13,a0),a1\n"); \
- + fprintf (FILE, "\tmov (17,a0),a0\n"); \
- + fprintf (FILE, "\tjmp (a0)\n"); \
- + fprintf (FILE, "\t.long 0\n"); \
- + fprintf (FILE, "\t.long 0\n"); \
- + } while (0)
- +#endif
- +
- +/* A C expression for the size in bytes of the trampoline, as an integer. */
- +#define TRAMPOLINE_SIZE 0x1b
- +
- +/* Alignment required for trampolines, in bits.
- +
- + If you don't define this macro, the value of `BIGGEST_ALIGNMENT' is used for
- + aligning trampolines. */
- +#define TRAMPOLINE_ALIGNMENT 32
- +
- +/* A C statement to initialize the variable parts of a trampoline. ADDR is an
- + RTX for the address of the trampoline; FNADDR is an RTX for the address of
- + the nested function; STATIC_CHAIN is an RTX for the static chain value that
- + should be passed to the function when it is called. */
- +#define INITIALIZE_TRAMPOLINE(TRAMP, FNADDR, CXT) \
- +{ \
- + emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 0x14)), \
- + (CXT)); \
- + emit_move_insn (gen_rtx_MEM (SImode, plus_constant ((TRAMP), 0x18)), \
- + (FNADDR)); \
- +}
- +
- +/* Ubicom32 supports pre and post increment/decrement addressing. */
- +#define HAVE_POST_INCREMENT 1
- +#define HAVE_PRE_INCREMENT 1
- +#define HAVE_POST_DECREMENT 1
- +#define HAVE_PRE_DECREMENT 1
- +
- +/* Ubicom32 supports pre and post address side-effects with constants
- + other than the size of the memory operand. */
- +#define HAVE_PRE_MODIFY_DISP 1
- +#define HAVE_POST_MODIFY_DISP 1
- +
- +/* A C expression that is 1 if the RTX X is a constant which is a valid
- + address. On most machines, this can be defined as `CONSTANT_P (X)',
- + but a few machines are more restrictive in which constant addresses
- + are supported.
- +
- + `CONSTANT_P' accepts integer-values expressions whose values are not
- + explicitly known, such as `symbol_ref', `label_ref', and `high'
- + expressions and `const' arithmetic expressions, in addition to
- + `const_int' and `const_double' expressions. */
- +#define CONSTANT_ADDRESS_P(X) \
- + (GET_CODE (X) == LABEL_REF \
- + || (GET_CODE (X) == CONST \
- + && GET_CODE (XEXP (X, 0)) == PLUS \
- + && GET_CODE (XEXP (XEXP (X, 0), 0)) == LABEL_REF))
- +
- +/* Ubicom32 supports a maximum of 2 registers in a valid memory address.
- + One is always an address register while a second, optional, one may be a
- + data register. */
- +#define MAX_REGS_PER_ADDRESS 2
- +
- +/* A C compound statement with a conditional `goto LABEL;' executed if X (an
- + RTX) is a legitimate memory address on the target machine for a memory
- + operand of mode MODE.
- +
- + It usually pays to define several simpler macros to serve as subroutines for
- + this one. Otherwise it may be too complicated to understand.
- +
- + This macro must exist in two variants: a strict variant and a non-strict
- + one. The strict variant is used in the reload pass. It must be defined so
- + that any pseudo-register that has not been allocated a hard register is
- + considered a memory reference. In contexts where some kind of register is
- + required, a pseudo-register with no hard register must be rejected.
- +
- + The non-strict variant is used in other passes. It must be defined to
- + accept all pseudo-registers in every context where some kind of register is
- + required.
- +
- + Compiler source files that want to use the strict variant of this macro
- + define the macro `REG_OK_STRICT'. You should use an `#ifdef REG_OK_STRICT'
- + conditional to define the strict variant in that case and the non-strict
- + variant otherwise.
- +
- + Subroutines to check for acceptable registers for various purposes (one for
- + base registers, one for index registers, and so on) are typically among the
- + subroutines used to define `GO_IF_LEGITIMATE_ADDRESS'. Then only these
- + subroutine macros need have two variants; the higher levels of macros may be
- + the same whether strict or not.
- +
- + Normally, constant addresses which are the sum of a `symbol_ref' and an
- + integer are stored inside a `const' RTX to mark them as constant.
- + Therefore, there is no need to recognize such sums specifically as
- + legitimate addresses. Normally you would simply recognize any `const' as
- + legitimate.
- +
- + Usually `PRINT_OPERAND_ADDRESS' is not prepared to handle constant sums that
- + are not marked with `const'. It assumes that a naked `plus' indicates
- + indexing. If so, then you *must* reject such naked constant sums as
- + illegitimate addresses, so that none of them will be given to
- + `PRINT_OPERAND_ADDRESS'.
- +
- + On some machines, whether a symbolic address is legitimate depends on the
- + section that the address refers to. On these machines, define the macro
- + `ENCODE_SECTION_INFO' to store the information into the `symbol_ref', and
- + then check for it here. When you see a `const', you will have to look
- + inside it to find the `symbol_ref' in order to determine the section.
- +
- + The best way to modify the name string is by adding text to the beginning,
- + with suitable punctuation to prevent any ambiguity. Allocate the new name
- + in `saveable_obstack'. You will have to modify `ASM_OUTPUT_LABELREF' to
- + remove and decode the added text and output the name accordingly, and define
- + `STRIP_NAME_ENCODING' to access the original name string.
- +
- + You can check the information stored here into the `symbol_ref' in the
- + definitions of the macros `GO_IF_LEGITIMATE_ADDRESS' and
- + `PRINT_OPERAND_ADDRESS'. */
- +/* On the ubicom32, the value in the address register must be
- + in the same memory space/segment as the effective address.
- +
- + This is problematical for reload since it does not understand
- + that base+index != index+base in a memory reference. */
- +
- +#ifdef REG_OK_STRICT
- +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
- + if (ubicom32_legitimate_address_p (MODE, X, 1)) goto ADDR;
- +#else
- +#define GO_IF_LEGITIMATE_ADDRESS(MODE, X, ADDR) \
- + if (ubicom32_legitimate_address_p (MODE, X, 0)) goto ADDR;
- +#endif
- +
- +/* Try machine-dependent ways of modifying an illegitimate address
- + to be legitimate. If we find one, return the new, valid address.
- + This macro is used in only one place: `memory_address' in explow.c.
- +
- + OLDX is the address as it was before break_out_memory_refs was called.
- + In some cases it is useful to look at this to decide what needs to be done.
- +
- + MODE and WIN are passed so that this macro can use
- + GO_IF_LEGITIMATE_ADDRESS.
- +
- + It is always safe for this macro to do nothing. It exists to recognize
- + opportunities to optimize the output.
- +
- + On RS/6000, first check for the sum of a register with a constant
- + integer that is out of range. If so, generate code to add the
- + constant with the low-order 16 bits masked to the register and force
- + this result into another register (this can be done with `cau').
- + Then generate an address of REG+(CONST&0xffff), allowing for the
- + possibility of bit 16 being a one.
- +
- + Then check for the sum of a register and something not constant, try to
- + load the other things into a register and return the sum. */
- +
- +#define LEGITIMIZE_ADDRESS(X, OLDX, MODE, WIN) \
- +{ \
- + rtx result = ubicom32_legitimize_address ((X), (OLDX), (MODE)); \
- + if (result != NULL_RTX) \
- + { \
- + (X) = result; \
- + goto WIN; \
- + } \
- +}
- +
- +/* Try a machine-dependent way of reloading an illegitimate address
- + operand. If we find one, push the reload and jump to WIN. This
- + macro is used in only one place: `find_reloads_address' in reload.c. */
- +#define LEGITIMIZE_RELOAD_ADDRESS(AD, MODE, OPNUM, TYPE, IND, WIN) \
- +{ \
- + rtx new_rtx = ubicom32_legitimize_reload_address ((AD), (MODE), (OPNUM), (int)(TYPE)); \
- + if (new_rtx) \
- + { \
- + (AD) = new_rtx; \
- + goto WIN; \
- + } \
- +}
- +
- +/* A C statement or compound statement with a conditional `goto LABEL;'
- + executed if memory address X (an RTX) can have different meanings depending
- + on the machine mode of the memory reference it is used for or if the address
- + is valid for some modes but not others.
- +
- + Autoincrement and autodecrement addresses typically have mode-dependent
- + effects because the amount of the increment or decrement is the size of the
- + operand being addressed. Some machines have other mode-dependent addresses.
- + Many RISC machines have no mode-dependent addresses.
- +
- + You may assume that ADDR is a valid address for the machine. */
- +#define GO_IF_MODE_DEPENDENT_ADDRESS(ADDR, LABEL) \
- + if (ubicom32_mode_dependent_address_p (ADDR)) \
- + goto LABEL;
- +
- +/* A C expression that is nonzero if X is a legitimate constant for an
- + immediate operand on the target machine. You can assume that X
- + satisfies `CONSTANT_P', so you need not check this. In fact, `1' is
- + a suitable definition for this macro on machines where anything
- + `CONSTANT_P' is valid. */
- +#define LEGITIMATE_CONSTANT_P(X) \
- + ubicom32_legitimate_constant_p ((X))
- +
- +/* Moves between registers are pretty-much single instructions for
- + Ubicom32. We make this the default "2" that gcc likes. */
- +#define REGISTER_MOVE_COST(MODE, FROM, TO) 2
- +
- +/* This is a little bit of magic from the S390 port that wins 2% on code
- + size when building the Linux kernel! Unfortunately while it wins on
- + that size the user-space apps built using FD-PIC don't improve and the
- + performance is lower because we put more pressure on the caches. We may
- + want this back on some future CPU that has higher cache performance. */
- +/* #define IRA_HARD_REGNO_ADD_COST_MULTIPLIER(regno) 0.5 */
- +
- +/* Moves between registers and memory are more expensive than between
- + registers because we have caches and write buffers that slow things
- + down! */
- +#define MEMORY_MOVE_COST(MODE, CLASS, IN) 2
- +
- +/* A fall-through branch is very low cost but anything that changes the PC
- + incurs a major pipeline hazard. We don't make the full extent of this
- + hazard visible because we hope that multiple threads will absorb much
- + of the cost and so we don't want a jump being replaced with, say, 7
- + instructions. */
- +#define BRANCH_COST(SPEED_P, PREDICTABLE_P) \
- + ((PREDICTABLE_P) ? 1 : 3)
- +
- +/* Define this macro as a C expression which is nonzero if accessing less than
- + a word of memory (i.e. a `char' or a `short') is no faster than accessing a
- + word of memory, i.e., if such access require more than one instruction or if
- + there is no difference in cost between byte and (aligned) word loads.
- +
- + When this macro is not defined, the compiler will access a field by finding
- + the smallest containing object; when it is defined, a fullword load will be
- + used if alignment permits. Unless bytes accesses are faster than word
- + accesses, using word accesses is preferable since it may eliminate
- + subsequent memory access if subsequent accesses occur to other fields in the
- + same word of the structure, but to different bytes. */
- +#define SLOW_BYTE_ACCESS 0
- +
- +/* The number of scalar move insns which should be generated instead of a
- + string move insn or a library call. Increasing the value will always make
- + code faster, but eventually incurs high cost in increased code size.
- +
- + If you don't define this, a reasonable default is used. */
- +/* According to expr.c, a value of around 6 should minimize code size. */
- +#define MOVE_RATIO(SPEED) 6
- +
- +/* We're much better off calling a constant function address with the
- + Ubicom32 architecture because we have an opcode for doing so. Don't
- + let the compiler extract function addresses as common subexpressions
- + into an address register. */
- +#define NO_FUNCTION_CSE
- +
- +#define SELECT_CC_MODE(OP, X, Y) ubicom32_select_cc_mode (OP, X, Y)
- +
- +#define REVERSIBLE_CC_MODE(MODE) 1
- +
- +/* Canonicalize a comparison from one we don't have to one we do have. */
- +#define CANONICALIZE_COMPARISON(CODE, OP0, OP1) \
- + ubicom32_canonicalize_comparison (&(CODE), &(OP0), &(OP1))
- +
- +/* Dividing the output into sections. */
- +
- +/* A C expression whose value is a string containing the assembler operation
- + that should precede instructions and read-only data. Normally `".text"' is
- + right. */
- +#define TEXT_SECTION_ASM_OP "\t.section .text"
- +
- +/* A C expression whose value is a string containing the assembler operation to
- + identify the following data as writable initialized data. Normally
- + `".data"' is right. */
- +#define DATA_SECTION_ASM_OP "\t.section .data"
- +
- +
- +/* If defined, a C expression whose value is a string containing the
- + assembler operation to identify the following data as
- + uninitialized global data. If not defined, and neither
- + `ASM_OUTPUT_BSS' nor `ASM_OUTPUT_ALIGNED_BSS' are defined,
- + uninitialized global data will be output in the data section if
- + `-fno-common' is passed, otherwise `ASM_OUTPUT_COMMON' will be
- + used. */
- +#define BSS_SECTION_ASM_OP "\t.section .bss"
- +
- +/* This is how we tell the assembler that a symbol is weak. */
- +
- +#define ASM_WEAKEN_LABEL(FILE, NAME) \
- + do \
- + { \
- + fputs ("\t.weak\t", (FILE)); \
- + assemble_name ((FILE), (NAME)); \
- + fputc ('\n', (FILE)); \
- + } \
- + while (0)
- +
- +/* The Overall Framework of an Assembler File. */
- +
- +#undef SET_ASM_OP
- +#define SET_ASM_OP "\t.set\t"
- +
- +/* A C string constant describing how to begin a comment in the target
- + assembler language. The compiler assumes that the comment will end at the
- + end of the line. */
- +#define ASM_COMMENT_START ";"
- +
- +/* A C string constant for text to be output before each `asm' statement or
- + group of consecutive ones. Normally this is `"#APP"', which is a comment
- + that has no effect on most assemblers but tells the GNU assembler that it
- + must check the lines that follow for all valid assembler constructs. */
- +#define ASM_APP_ON "#APP\n"
- +
- +/* A C string constant for text to be output after each `asm' statement or
- + group of consecutive ones. Normally this is `"#NO_APP"', which tells the
- + GNU assembler to resume making the time-saving assumptions that are valid
- + for ordinary compiler output. */
- +#define ASM_APP_OFF "#NO_APP\n"
- +
- +/* Like `ASM_OUTPUT_BSS' except takes the required alignment as a separate,
- + explicit argument. If you define this macro, it is used in place of
- + `ASM_OUTPUT_BSS', and gives you more flexibility in handling the required
- + alignment of the variable. The alignment is specified as the number of
- + bits.
- +
- + Try to use function `asm_output_aligned_bss' defined in file `varasm.c' when
- + defining this macro. */
- +#define ASM_OUTPUT_ALIGNED_BSS(FILE, DECL, NAME, SIZE, ALIGN) \
- + asm_output_aligned_bss ((FILE), (DECL), (NAME), (SIZE), (ALIGN))
- +
- +/* A C expression to assign to OUTVAR (which is a variable of type `char *') a
- + newly allocated string made from the string NAME and the number NUMBER, with
- + some suitable punctuation added. Use `alloca' to get space for the string.
- +
- + The string will be used as an argument to `ASM_OUTPUT_LABELREF' to produce
- + an assembler label for an internal static variable whose name is NAME.
- + Therefore, the string must be such as to result in valid assembler code.
- + The argument NUMBER is different each time this macro is executed; it
- + prevents conflicts between similarly-named internal static variables in
- + different scopes.
- +
- + Ideally this string should not be a valid C identifier, to prevent any
- + conflict with the user's own symbols. Most assemblers allow periods or
- + percent signs in assembler symbols; putting at least one of these between
- + the name and the number will suffice. */
- +#define ASM_FORMAT_PRIVATE_NAME(OUTPUT, NAME, LABELNO) \
- + ((OUTPUT) = (char *) alloca (strlen ((NAME)) + 10), \
- + sprintf ((OUTPUT), "%s___%d", (NAME), (LABELNO)))
- +
- +#define ASM_GENERATE_INTERNAL_LABEL(STRING, PREFIX, NUM) \
- + sprintf (STRING, "*.%s%ld", PREFIX, (long)(NUM))
- +/* A C statement to store into the string STRING a label whose name
- + is made from the string PREFIX and the number NUM.
- +
- + This string, when output subsequently by `assemble_name', should
- + produce the output that `(*targetm.asm_out.internal_label)' would produce
- + with the same PREFIX and NUM.
- +
- + If the string begins with `*', then `assemble_name' will output
- + the rest of the string unchanged. It is often convenient for
- + `ASM_GENERATE_INTERNAL_LABEL' to use `*' in this way. If the
- + string doesn't start with `*', then `ASM_OUTPUT_LABELREF' gets to
- + output the string, and may change it. (Of course,
- + `ASM_OUTPUT_LABELREF' is also part of your machine description, so
- + you should know what it does on your machine.) */
- +
- +/* This says how to output assembler code to declare an
- + uninitialized external linkage data object. Under SVR4,
- + the linker seems to want the alignment of data objects
- + to depend on their types. We do exactly that here. */
- +
- +#define COMMON_ASM_OP "\t.comm\t"
- +
- +#undef ASM_OUTPUT_COMMON
- +#define ASM_OUTPUT_COMMON(FILE, NAME, SIZE, ROUNDED) \
- + do \
- + { \
- + fprintf ((FILE), "%s", COMMON_ASM_OP); \
- + assemble_name ((FILE), (NAME)); \
- + fprintf ((FILE), ", %u\n", (SIZE)); \
- + } \
- + while (0)
- +
- +/* This says how to output assembler code to declare an
- + uninitialized internal linkage data object. Under SVR4,
- + the linker seems to want the alignment of data objects
- + to depend on their types. We do exactly that here. */
- +#define LOCAL_ASM_OP "\t.lcomm\t"
- +
- +#undef ASM_OUTPUT_LOCAL
- +#define ASM_OUTPUT_LOCAL(FILE, NAME, SIZE, ROUNDED) \
- + do \
- + { \
- + fprintf ((FILE), "%s", LOCAL_ASM_OP); \
- + assemble_name ((FILE), (NAME)); \
- + fprintf ((FILE), ", %u\n", (SIZE)); \
- + } \
- + while (0)
- +
- +/* Globalizing directive for a label. */
- +#define GLOBAL_ASM_OP ".global\t"
- +
- +/* Output the operand of an instruction. */
- +#define PRINT_OPERAND(FILE, X, CODE) \
- + ubicom32_print_operand(FILE, X, CODE)
- +
- +/* Output the address of an operand. */
- +#define PRINT_OPERAND_ADDRESS(FILE, ADDR) \
- + ubicom32_print_operand_address (FILE, ADDR)
- +
- +/* A C expression to output to STREAM some assembler code which will push hard
- + register number REGNO onto the stack. The code need not be optimal, since
- + this macro is used only when profiling. */
- +#define ASM_OUTPUT_REG_PUSH(FILE, REGNO)
- +
- +/* A C expression to output to STREAM some assembler code which will pop hard
- + register number REGNO off of the stack. The code need not be optimal, since
- + this macro is used only when profiling. */
- +#define ASM_OUTPUT_REG_POP(FILE, REGNO)
- +
- +/* This macro should be provided on machines where the addresses in a dispatch
- + table are relative to the table's own address.
- +
- + The definition should be a C statement to output to the stdio stream STREAM
- + an assembler pseudo-instruction to generate a difference between two labels.
- + VALUE and REL are the numbers of two internal labels. The definitions of
- + these labels are output using `ASM_OUTPUT_INTERNAL_LABEL', and they must be
- + printed in the same way here. For example,
- +
- + fprintf (STREAM, "\t.word L%d-L%d\n", VALUE, REL) */
- +#define ASM_OUTPUT_ADDR_DIFF_ELT(FILE, BODY, VALUE, REL) \
- + fprintf (FILE, "\t%s .L%d-.L%d\n", ".long", VALUE, REL)
- +
- +/* This macro should be provided on machines where the addresses in a dispatch
- + table are absolute.
- +
- + The definition should be a C statement to output to the stdio stream STREAM
- + an assembler pseudo-instruction to generate a reference to a label. VALUE
- + is the number of an internal label whose definition is output using
- + `ASM_OUTPUT_INTERNAL_LABEL'. For example,
- +
- + fprintf (STREAM, "\t.word L%d\n", VALUE) */
- +#define ASM_OUTPUT_ADDR_VEC_ELT(STREAM, VALUE) \
- + fprintf (STREAM, "\t.word .L%d\n", VALUE)
- +
- +/* Switch into a generic section. */
- +#define TARGET_ASM_NAMED_SECTION default_elf_asm_named_section
- +
- +/* Assembler Commands for Alignment. */
- +
- +#define ASM_OUTPUT_SKIP(STREAM, N) fprintf (STREAM, "\t.skip %d,0\n", N)
- +/* A C statement to output to the stdio stream STREAM an assembler
- + instruction to advance the location counter by NBYTES bytes.
- + Those bytes should be zero when loaded. NBYTES will be a C
- + expression of type `int'. */
- +
- +/* A C statement to output to the stdio stream STREAM an assembler command to
- + advance the location counter to a multiple of 2 to the POWER bytes. POWER
- + will be a C expression of type `int'. */
- +#define ASM_OUTPUT_ALIGN(FILE, LOG) \
- + if ((LOG) != 0) \
- + fprintf (FILE, "\t.align %d\n", (LOG))
- +
- +/* A C expression that returns the DBX register number for the compiler
- + register number REGNO. In simple cases, the value of this expression may be
- + REGNO itself. But sometimes there are some registers that the compiler
- + knows about and DBX does not, or vice versa. In such cases, some register
- + may need to have one number in the compiler and another for DBX.
- +
- + If two registers have consecutive numbers inside GNU CC, and they can be
- + used as a pair to hold a multiword value, then they *must* have consecutive
- + numbers after renumbering with `DBX_REGISTER_NUMBER'. Otherwise, debuggers
- + will be unable to access such a pair, because they expect register pairs to
- + be consecutive in their own numbering scheme.
- +
- + If you find yourself defining `DBX_REGISTER_NUMBER' in way that does not
- + preserve register pairs, then what you must do instead is redefine the
- + actual register numbering scheme.
- +
- + This declaration is required. */
- +#define DBX_REGISTER_NUMBER(REGNO) REGNO
- +
- +/* A C expression that returns the integer offset value for an automatic
- + variable having address X (an RTL expression). The default computation
- + assumes that X is based on the frame-pointer and gives the offset from the
- + frame-pointer. This is required for targets that produce debugging output
- + for DBX or COFF-style debugging output for SDB and allow the frame-pointer
- + to be eliminated when the `-g' options is used. */
- +#define DEBUGGER_AUTO_OFFSET(X) \
- + ((GET_CODE (X) == PLUS ? INTVAL (XEXP (X, 1)) : 0) \
- + + (frame_pointer_needed \
- + ? 0 : -initial_elimination_offset (FRAME_POINTER_REGNUM, \
- + STACK_POINTER_REGNUM)))
- +
- +/* A C expression that returns the integer offset value for an argument having
- + address X (an RTL expression). The nominal offset is OFFSET. */
- +#define DEBUGGER_ARG_OFFSET(OFFSET, X) \
- + ((GET_CODE (X) == PLUS ? OFFSET : 0) \
- + + (frame_pointer_needed \
- + ? 0 : -initial_elimination_offset (ARG_POINTER_REGNUM, \
- + STACK_POINTER_REGNUM)))
- +
- +/* A C expression that returns the type of debugging output GNU CC produces
- + when the user specifies `-g' or `-ggdb'. Define this if you have arranged
- + for GNU CC to support more than one format of debugging output. Currently,
- + the allowable values are `DBX_DEBUG', `SDB_DEBUG', `DWARF_DEBUG',
- + `DWARF2_DEBUG', and `XCOFF_DEBUG'.
- +
- + The value of this macro only affects the default debugging output; the user
- + can always get a specific type of output by using `-gstabs', `-gcoff',
- + `-gdwarf-1', `-gdwarf-2', or `-gxcoff'.
- +
- + Defined in svr4.h.
- +*/
- +#undef PREFERRED_DEBUGGING_TYPE
- +#define PREFERRED_DEBUGGING_TYPE DWARF2_DEBUG
- +
- +/* Define this macro if GNU CC should produce dwarf version 2 format debugging
- + output in response to the `-g' option.
- +
- + To support optional call frame debugging information, you must also define
- + `INCOMING_RETURN_ADDR_RTX' and either set `RTX_FRAME_RELATED_P' on the
- + prologue insns if you use RTL for the prologue, or call `dwarf2out_def_cfa'
- + and `dwarf2out_reg_save' as appropriate from `FUNCTION_PROLOGUE' if you
- + don't.
- +
- + Defined in svr4.h. */
- +
- +#define DWARF2_DEBUGGING_INFO 1
- +/*#define DWARF2_UNWIND_INFO 1*/
- +#define DWARF2_UNWIND_INFO 0
- +#define INCOMING_RETURN_ADDR_RTX gen_rtx_REG (Pmode, LINK_REGNO)
- +#define INCOMING_FRAME_SP_OFFSET 0
- +#define DWARF_FRAME_RETURN_COLUMN DWARF_FRAME_REGNUM (LINK_REGNO)
- +#define EH_RETURN_FIRST 9
- +#define EH_RETURN_DATA_REGNO(N) ((N) < 2 ? (N) + EH_RETURN_FIRST : INVALID_REGNUM)
- +
- +/* The EH_RETURN_STACKADJ_RTX macro returns RTL which describes the
- + location used to store the amount to ajdust the stack. This is
- + usually a registers that is available from end of the function's body
- + to the end of the epilogue. Thus, this cannot be a register used as a
- + temporary by the epilogue.
- +
- + This must be an integer register. */
- +#define EH_RETURN_STACKADJ_REGNO 11
- +#define EH_RETURN_STACKADJ_RTX \
- + gen_rtx_REG (Pmode, EH_RETURN_STACKADJ_REGNO)
- +
- +/* The EH_RETURN_HANDLER_RTX macro returns RTL which describes the
- + location used to store the address the processor should jump to
- + catch exception. This is usually a registers that is available from
- + end of the function's body to the end of the epilogue. Thus, this
- + cannot be a register used as a temporary by the epilogue.
- +
- + This must be an address register. */
- +#define EH_RETURN_HANDLER_REGNO 18
- +#define EH_RETURN_HANDLER_RTX \
- + gen_rtx_REG (Pmode, EH_RETURN_HANDLER_REGNO)
- +
- +/* #define DWARF2_DEBUGGING_INFO */
- +
- +/* Define this macro if GNU CC should produce dwarf version 2-style
- + line numbers. This usually requires extending the assembler to
- + support them, and #defining DWARF2_LINE_MIN_INSN_LENGTH in the
- + assembler configuration header files. */
- +/* #define DWARF2_ASM_LINE_DEBUG_INFO 1 */
- +
- +
- +/* An alias for a machine mode name. This is the machine mode that elements
- + of a jump-table have. */
- +#define CASE_VECTOR_MODE Pmode
- +
- +/* Smallest number of different values for which it is best to use a
- + jump-table instead of a tree of conditional branches. For most Ubicom32
- + targets this is quite small, but for the v1 architecture implementations
- + we had very little data memory and so heavily prefer the tree approach
- + rather than the jump tables. */
- +#define CASE_VALUES_THRESHOLD ubicom32_case_values_threshold
- +
- +/* Register operations within the Ubicom32 architecture always operate on
- + the whole register word and not just the sub-bits required for the opcode
- + mode size. */
- +#define WORD_REGISTER_OPERATIONS
- +
- +/* The maximum number of bytes that a single instruction can move quickly from
- + memory to memory. */
- +#define MOVE_MAX 4
- +
- +/* A C expression that is nonzero if on this machine the number of bits
- + actually used for the count of a shift operation is equal to the number of
- + bits needed to represent the size of the object being shifted. When this
- + macro is non-zero, the compiler will assume that it is safe to omit a
- + sign-extend, zero-extend, and certain bitwise `and' instructions that
- + truncates the count of a shift operation. On machines that have
- + instructions that act on bitfields at variable positions, which may include
- + `bit test' instructions, a nonzero `SHIFT_COUNT_TRUNCATED' also enables
- + deletion of truncations of the values that serve as arguments to bitfield
- + instructions.
- +
- + If both types of instructions truncate the count (for shifts) and position
- + (for bitfield operations), or if no variable-position bitfield instructions
- + exist, you should define this macro.
- +
- + However, on some machines, such as the 80386 and the 680x0, truncation only
- + applies to shift operations and not the (real or pretended) bitfield
- + operations. Define `SHIFT_COUNT_TRUNCATED' to be zero on such machines.
- + Instead, add patterns to the `md' file that include the implied truncation
- + of the shift instructions.
- +
- + You need not define this macro if it would always have the value of zero. */
- +#define SHIFT_COUNT_TRUNCATED 1
- +
- +/* A C expression which is nonzero if on this machine it is safe to "convert"
- + an integer of INPREC bits to one of OUTPREC bits (where OUTPREC is smaller
- + than INPREC) by merely operating on it as if it had only OUTPREC bits.
- +
- + On many machines, this expression can be 1.
- +
- + When `TRULY_NOOP_TRUNCATION' returns 1 for a pair of sizes for modes for
- + which `MODES_TIEABLE_P' is 0, suboptimal code can result. If this is the
- + case, making `TRULY_NOOP_TRUNCATION' return 0 in such cases may improve
- + things. */
- +#define TRULY_NOOP_TRUNCATION(OUTPREC, INPREC) 1
- +
- +/* A C string constant that tells the GNU CC driver program options to pass
- + to the assembler. It can also specify how to translate options you give
- + to GNU CC into options for GNU CC to pass to the assembler. See the
- + file `sun3.h' for an example of this.
- +
- + Defined in svr4.h. */
- +#undef ASM_SPEC
- +#define ASM_SPEC \
- + "%{march=*:-m%*} %{!march=*:-mubicom32v4} %{mfdpic:-mfdpic}"
- +
- +#define LINK_SPEC "\
- +%{h*} %{v:-V} \
- +%{b} \
- +%{mfdpic:-melf32ubicom32fdpic -z text} \
- +%{static:-dn -Bstatic} \
- +%{shared:-G -Bdynamic} \
- +%{symbolic:-Bsymbolic} \
- +%{G*} \
- +%{YP,*} \
- +%{Qy:} %{!Qn:-Qy}"
- +
- +#undef STARTFILE_SPEC
- +#undef ENDFILE_SPEC
- +
- +/* The svr4.h LIB_SPEC with -leval and --*group tacked on */
- +
- +#undef LIB_SPEC
- +#define LIB_SPEC "%{!shared:%{!symbolic:--start-group -lc -leval -lgcc --end-group}}"
- +
- +#undef HAVE_GAS_SHF_MERGE
- +#define HAVE_GAS_SHF_MERGE 0
- +
- +#define HANDLE_SYSV_PRAGMA 1
- +#undef HANDLE_PRAGMA_PACK
- +
- +typedef void (*ubicom32_func_ptr) (void);
- +
- +/* Define builtins for selected special-purpose instructions. */
- +enum ubicom32_builtins
- +{
- + UBICOM32_BUILTIN_UBICOM32_SWAPB_2,
- + UBICOM32_BUILTIN_UBICOM32_SWAPB_4
- +};
- +
- +extern rtx ubicom32_compare_op0;
- +extern rtx ubicom32_compare_op1;
- +
- +#define TYPE_ASM_OP "\t.type\t"
- +#define TYPE_OPERAND_FMT "@%s"
- +
- +#ifndef ASM_DECLARE_RESULT
- +#define ASM_DECLARE_RESULT(FILE, RESULT)
- +#endif
- +
- +/* These macros generate the special .type and .size directives which
- + are used to set the corresponding fields of the linker symbol table
- + entries in an ELF object file under SVR4. These macros also output
- + the starting labels for the relevant functions/objects. */
- +
- +/* Write the extra assembler code needed to declare a function properly.
- + Some svr4 assemblers need to also have something extra said about the
- + function's return value. We allow for that here. */
- +
- +#ifndef ASM_DECLARE_FUNCTION_NAME
- +#define ASM_DECLARE_FUNCTION_NAME(FILE, NAME, DECL) \
- + do \
- + { \
- + ASM_OUTPUT_TYPE_DIRECTIVE (FILE, NAME, "function"); \
- + ASM_DECLARE_RESULT (FILE, DECL_RESULT (DECL)); \
- + ASM_OUTPUT_LABEL (FILE, NAME); \
- + } \
- + while (0)
- +#endif
- --- /dev/null
- +++ b/gcc/config/ubicom32/ubicom32.md
- @@ -0,0 +1,3753 @@
- +; GCC machine description for Ubicom32
- +;
- +; Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software
- +; Foundation, Inc.
- +; Contributed by Ubicom, Inc.
- +;
- +; This file is part of GCC.
- +;
- +; GCC is free software; you can redistribute it and/or modify
- +; it under the terms of the GNU General Public License as published by
- +; the Free Software Foundation; either version 3, or (at your option)
- +; any later version.
- +;
- +; GCC is distributed in the hope that it will be useful,
- +; but WITHOUT ANY WARRANTY; without even the implied warranty of
- +; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +; GNU General Public License for more details.
- +;
- +; You should have received a copy of the GNU General Public License
- +; along with GCC; see the file COPYING3. If not see
- +; <http://www.gnu.org/licenses/>.
- +
- +(define_constants
- + [(AUX_DATA_REGNO 15)
- + (LINK_REGNO 21)
- + (SP_REGNO 23)
- + (ACC0_HI_REGNO 24)
- + (ACC1_HI_REGNO 26)
- + (CC_REGNO 30)])
- +
- +(define_constants
- + [(UNSPEC_FDPIC_GOT 0)
- + (UNSPEC_FDPIC_GOT_FUNCDESC 1)])
- +
- +(define_constants
- + [(UNSPEC_VOLATILE_LOAD_FDPIC_FUNCDESC 0)])
- +
- +;; Types of instructions (for scheduling purposes).
- +
- +(define_attr "type" "mul,addr,other"
- + (const_string "other"))
- +
- +; Define instruction scheduling characteristics. We can only issue
- +; one instruction per clock so we don't need to define CPU units.
- +;
- +(define_automaton "ubicom32")
- +
- +(define_cpu_unit "i_pipeline" "ubicom32");
- +
- +; We have a 4 cycle hazard associated with address calculations which
- +; seems rather tricky to avoid so we go with a defensive assumption
- +; that almost anything can be used to generate addresses.
- +;
- +;(define_insn_reservation "ubicom32_other" 4
- +; (eq_attr "type" "other")
- +; "i_pipeline")
- +
- +; Some moves don't generate hazards.
- +;
- +;(define_insn_reservation "ubicom32_addr" 1
- +; (eq_attr "type" "addr")
- +; "i_pipeline")
- +
- +; We need 3 cycles between a multiply instruction and any use of the
- +; matching accumulator register(s).
- +;
- +(define_insn_reservation "ubicom32_mul" 4
- + (eq_attr "type" "mul")
- + "i_pipeline")
- +
- +(define_attr "length" ""
- + (const_int 4))
- +
- +(include "predicates.md")
- +(include "constraints.md")
- +
- +; 8-bit move with no change to the flags reg.
- +;
- +(define_insn "movqi"
- + [(set (match_operand:QI 0 "nonimmediate_operand" "=rm")
- + (match_operand:QI 1 "ubicom32_move_operand" "g"))]
- + ""
- + "move.1\\t%0, %1")
- +
- +; Combiner-generated 8-bit move with the zero flag set accordingly.
- +;
- +(define_insn "movqi_ccszn"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:QI 0 "nonimmediate_operand" "rm")
- + (const_int 0)))
- + (set (match_operand:QI 1 "nonimmediate_operand" "=rm")
- + (match_dup 0))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "ext.1\\t%1, %0")
- +
- +; Combine isn't very good at merging some types of operations so we
- +; have to make do with a peephole. It's not as effective but it's better
- +; than doing nothing.
- +;
- +(define_peephole2
- + [(set (match_operand:QI 0 "nonimmediate_operand" "")
- + (match_operand:QI 1 "nonimmediate_operand" ""))
- + (set (match_operand 2 "ubicom32_cc_register_operand" "")
- + (match_operator 3 "ubicom32_compare_operator"
- + [(match_dup 0)
- + (const_int 0)]))]
- + "(GET_MODE (operands[2]) == CCSZNmode
- + || GET_MODE (operands[2]) == CCSZmode)"
- + [(parallel
- + [(set (match_dup 2)
- + (match_op_dup 3
- + [(match_dup 1)
- + (const_int 0)]))
- + (set (match_dup 0)
- + (match_dup 1))])]
- + "")
- +
- +; Combine isn't very good at merging some types of operations so we
- +; have to make do with a peephole. It's not as effective but it's better
- +; than doing nothing.
- +;
- +(define_peephole2
- + [(set (match_operand:QI 0 "nonimmediate_operand" "")
- + (match_operand:QI 1 "nonimmediate_operand" ""))
- + (set (match_operand 2 "ubicom32_cc_register_operand" "")
- + (match_operator 3 "ubicom32_compare_operator"
- + [(match_dup 1)
- + (const_int 0)]))]
- + "(GET_MODE (operands[2]) == CCSZNmode
- + || GET_MODE (operands[2]) == CCSZmode)"
- + [(parallel
- + [(set (match_dup 2)
- + (match_op_dup 3
- + [(match_dup 1)
- + (const_int 0)]))
- + (set (match_dup 0)
- + (match_dup 1))])]
- + "")
- +
- +; 16-bit move with no change to the flags reg.
- +;
- +(define_insn "movhi"
- + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
- + (match_operand:HI 1 "ubicom32_move_operand" "g"))]
- + ""
- + "*
- + {
- + if (CONST_INT_P (operands[1]))
- + return \"movei\\t%0, %1\";
- +
- + return \"move.2\\t%0, %1\";
- + }")
- +
- +; Combiner-generated 16-bit move with the zero flag set accordingly.
- +;
- +(define_insn "movhi_ccszn"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:HI 0 "nonimmediate_operand" "rm")
- + (const_int 0)))
- + (set (match_operand:HI 1 "nonimmediate_operand" "=rm")
- + (match_dup 0))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "ext.2\\t%1, %0")
- +
- +; Combine isn't very good at merging some types of operations so we
- +; have to make do with a peephole. It's not as effective but it's better
- +; than doing nothing.
- +;
- +(define_peephole2
- + [(set (match_operand:HI 0 "nonimmediate_operand" "")
- + (match_operand:HI 1 "nonimmediate_operand" ""))
- + (set (match_operand 2 "ubicom32_cc_register_operand" "")
- + (match_operator 3 "ubicom32_compare_operator"
- + [(match_dup 0)
- + (const_int 0)]))]
- + "(GET_MODE (operands[2]) == CCSZNmode
- + || GET_MODE (operands[2]) == CCSZmode)"
- + [(parallel
- + [(set (match_dup 2)
- + (match_op_dup 3
- + [(match_dup 1)
- + (const_int 0)]))
- + (set (match_dup 0)
- + (match_dup 1))])]
- + "")
- +
- +; Combine isn't very good at merging some types of operations so we
- +; have to make do with a peephole. It's not as effective but it's better
- +; than doing nothing.
- +;
- +(define_peephole2
- + [(set (match_operand:HI 0 "nonimmediate_operand" "")
- + (match_operand:HI 1 "nonimmediate_operand" ""))
- + (set (match_operand 2 "ubicom32_cc_register_operand" "")
- + (match_operator 3 "ubicom32_compare_operator"
- + [(match_dup 1)
- + (const_int 0)]))]
- + "(GET_MODE (operands[2]) == CCSZNmode
- + || GET_MODE (operands[2]) == CCSZmode)"
- + [(parallel
- + [(set (match_dup 2)
- + (match_op_dup 3
- + [(match_dup 1)
- + (const_int 0)]))
- + (set (match_dup 0)
- + (match_dup 1))])]
- + "")
- +
- +; 32-bit move with no change to the flags reg.
- +;
- +(define_expand "movsi"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "")
- + (match_operand:SI 1 "general_operand" ""))]
- + ""
- + "{
- + /* Convert any complexities in operand 1 into something that can just
- + fall into the default expander code. */
- + ubicom32_expand_movsi (operands);
- + }")
- +
- +(define_insn "movsi_high"
- + [(set (match_operand:SI 0 "ubicom32_address_register_operand" "=a")
- + (high:SI (match_operand:SI 1 "ubicom32_symbolic_address_operand" "s")))]
- + ""
- + "moveai\\t%0, #%%hi(%E1)")
- +
- +(define_insn "movsi_lo_sum"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- + (lo_sum:SI (match_operand:SI 1 "ubicom32_address_register_operand" "a")
- + (match_operand:SI 2 "immediate_operand" "s")))]
- + ""
- + "lea.1\\t%0, %%lo(%E2)(%1)")
- +
- +(define_insn "movsi_internal"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- + (match_operand:SI 1 "ubicom32_move_operand" "rmnY"))]
- + ""
- + "*
- + {
- + if (CONST_INT_P (operands[1]))
- + {
- + ubicom32_emit_move_const_int (operands[0], operands[1]);
- + return \"\";
- + }
- +
- + if (GET_CODE (operands[1]) == CONST_DOUBLE)
- + {
- + HOST_WIDE_INT i = CONST_DOUBLE_LOW (operands[1]);
- +
- + ubicom32_emit_move_const_int (operands[0], GEN_INT (i));
- + return \"\";
- + }
- +
- + if (ubicom32_address_register_operand (operands[0], VOIDmode)
- + && register_operand (operands[1], VOIDmode))
- + {
- + if (ubicom32_address_register_operand (operands[1], VOIDmode))
- + return \"lea.1\\t%0, 0(%1)\";
- +
- + /* Use movea here to utilize the hazard bypass in the >= v4 ISA. */
- + if (ubicom32_v4)
- + return \"movea\\t%0, %1\";
- +
- + return \"move.4\\t%0, %1\";
- + }
- +
- + return \"move.4\\t%0, %1\";
- + }")
- +
- +; If we're not dependent on the state of the condition codes we can construct
- +; constants of value 2^n by using a bset.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "nonimmediate_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))]
- + "(exact_log2 (INTVAL (operands[1])) > 14
- + && peep2_regno_dead_p (0, CC_REGNO))"
- + [(parallel
- + [(set (match_dup 0)
- + (ior:SI (const_int 0)
- + (match_dup 1)))
- + (clobber (reg:CC CC_REGNO))])]
- + "")
- +
- +; If we're not dependent on the state of the condition codes we can construct
- +; constants of value ~(2^n) by using a bclr.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "nonimmediate_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))]
- + "(exact_log2 (~INTVAL (operands[1])) > 14
- + && peep2_regno_dead_p (0, CC_REGNO))"
- + [(parallel
- + [(set (match_dup 0)
- + (and:SI (const_int -1)
- + (match_dup 1)))
- + (clobber (reg:CC CC_REGNO))])]
- + "")
- +
- +; For 32-bit constants that have bits 0 through 24 and bit 31 set the same
- +; we can use swapb.4!
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "nonimmediate_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))]
- + "(ubicom32_v4
- + && (INTVAL (operands[1]) & 0xffffffff) != 0xffffffff
- + && (INTVAL (operands[1]) & 0xffffffff) != 0
- + && ((INTVAL (operands[1]) & 0x80ffffff) == 0
- + || (INTVAL (operands[1]) & 0x80ffffff) == 0x80ffffff))"
- + [(set (match_dup 0)
- + (bswap:SI (match_dup 2)))]
- + "{
- + operands[2] = GEN_INT (INTVAL (operands[1]) >> 24);
- + }")
- +
- +; If this is a write of a constant to memory look to see if we can usefully
- +; transform this into 2 smaller writes.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "memory_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))]
- + "! satisfies_constraint_I (operands[1])
- + && ubicom32_legitimate_address_p (HImode, plus_constant (XEXP (operands[0], 0), 2), 1)"
- + [(set (match_dup 4) (match_dup 2))
- + (set (match_dup 5) (match_dup 3))]
- + "{
- + rtx low_hword_addr;
- +
- + operands[2] = gen_highpart_mode (HImode, SImode, operands[1]);
- + operands[3] = gen_lowpart (HImode, operands[1]);
- +
- + operands[4] = gen_rtx_MEM (HImode, XEXP (operands[0], 0));
- + MEM_COPY_ATTRIBUTES (operands[4], operands[0]);
- +
- + low_hword_addr = plus_constant (XEXP (operands[0], 0), 2);
- + operands[5] = gen_rtx_MEM (HImode, low_hword_addr);
- + MEM_COPY_ATTRIBUTES (operands[5], operands[0]);
- + }")
- +
- +; If we're writing memory and we've not found a better way to do this then
- +; try loading into a D register and then copying to memory. This will
- +; perform the fewest possible memory read/writes.
- +;
- +(define_peephole2
- + [(match_scratch:SI 2 "d")
- + (set (match_operand:SI 0 "memory_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))]
- + "! satisfies_constraint_I (operands[1])"
- + [(set (match_dup 2) (match_dup 1))
- + (set (match_dup 0) (match_dup 2))]
- + "")
- +
- +; If we're not dependent on the state of the condition codes we can construct
- +; constants of value (2^n - 1) by using an lsr.4.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))]
- + "(exact_log2 (INTVAL (operands[1]) + 1) > 14
- + && peep2_regno_dead_p (0, CC_REGNO))"
- + [(parallel
- + [(set (match_dup 0)
- + (lshiftrt:SI (const_int -1)
- + (match_dup 2)))
- + (clobber (reg:CC CC_REGNO))])]
- + "{
- + operands[2] = GEN_INT (32 - exact_log2 (INTVAL (operands[1]) + 1));
- + }")
- +
- +; If we're not dependent on the state of the condition codes we can construct
- +; constants of value (2^n - 1) by using an lsr.4.
- +;
- +(define_peephole2
- + [(match_scratch:SI 2 "d")
- + (set (match_operand:SI 0 "nonimmediate_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))]
- + "(exact_log2 (INTVAL (operands[1]) + 1) > 14
- + && peep2_regno_dead_p (0, CC_REGNO))"
- + [(parallel
- + [(set (match_dup 2)
- + (lshiftrt:SI (const_int -1)
- + (match_dup 3)))
- + (clobber (reg:CC CC_REGNO))])
- + (set (match_dup 0)
- + (match_dup 2))]
- + "{
- + operands[3] = GEN_INT (32 - exact_log2 (INTVAL (operands[1]) + 1));
- + }")
- +
- +; If we're not dependent on the state of the condition codes we can construct
- +; some other constants by using an lsl.4 to shift 7 bits left by some
- +; constant.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))]
- + "(ubicom32_shiftable_const_int (INTVAL (operands[1]))
- + && peep2_regno_dead_p (0, CC_REGNO))"
- + [(parallel
- + [(set (match_dup 0)
- + (ashift:SI (match_dup 2)
- + (match_dup 3)))
- + (clobber (reg:CC CC_REGNO))])]
- + "{
- + int shift = ubicom32_shiftable_const_int (INTVAL (operands[1]));
- + operands[2] = GEN_INT (INTVAL (operands[1]) >> shift);
- + operands[3] = GEN_INT (shift);
- + }")
- +
- +; If we're not dependent on the state of the condition codes we can construct
- +; some other constants by using an lsl.4 to shift 7 bits left by some
- +; constant.
- +;
- +(define_peephole2
- + [(match_scratch:SI 2 "d")
- + (set (match_operand:SI 0 "nonimmediate_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))]
- + "(ubicom32_shiftable_const_int (INTVAL (operands[1]))
- + && peep2_regno_dead_p (0, CC_REGNO))"
- + [(parallel
- + [(set (match_dup 2)
- + (ashift:SI (match_dup 3)
- + (match_dup 4)))
- + (clobber (reg:CC CC_REGNO))])
- + (set (match_dup 0)
- + (match_dup 2))]
- + "{
- + int shift = ubicom32_shiftable_const_int (INTVAL (operands[1]));
- + operands[3] = GEN_INT (INTVAL (operands[1]) >> shift);
- + operands[4] = GEN_INT (shift);
- + }")
- +
- +; For some 16-bit unsigned constants that have bit 15 set we can use
- +; swapb.2!
- +;
- +; Note that the movsi code emits the same sequence but by using a peephole2
- +; we split the pattern early enough to allow instruction scheduling to
- +; occur.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "register_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))]
- + "(ubicom32_v4
- + && (INTVAL (operands[1]) & 0xffff80ff) == 0x80ff)"
- + [(set (match_dup 0)
- + (zero_extend:SI (bswap:HI (match_dup 2))))]
- + "{
- + HOST_WIDE_INT i = INTVAL (operands[1]) >> 8;
- + if (i >= 0x80)
- + i -= 0x100;
- + operands[2] = GEN_INT (i);
- + }")
- +
- +; In general for a 16-bit unsigned constant that has bit 15 set
- +; then we need a movei/move.2 pair unless we can represent it
- +; via just a move.2.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "register_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))]
- + "(INTVAL (operands[1]) & 0xffff8000) == 0x8000
- + && (INTVAL (operands[1]) & 0xffff) < 0xff80"
- + [(set (match_dup 2)
- + (match_dup 1))
- + (set (match_dup 0)
- + (zero_extend:SI (match_dup 2)))]
- + "{
- + operands[2] = gen_rtx_REG (HImode, REGNO (operands[0]));
- + }")
- +
- +; If we're not dependent on the state of the condition codes we can construct
- +; 32-bit constants that have bits 16 through 31 set to arbitrary values
- +; and have bits 0 through 15 set to something representable as a default
- +; source-1 immediate - we use movei/shmrg.2
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))]
- + "(((INTVAL (operands[1]) >= 0x8000
- + && INTVAL (operands[1]) < 0xff80)
- + || INTVAL (operands[1]) >= 0x10000
- + || INTVAL (operands[1]) < -0x8000)
- + && ((INTVAL (operands[1]) & 0xffff) >= 0xff80
- + || (INTVAL (operands[1]) & 0xffff) < 0x80)
- + && peep2_regno_dead_p (0, CC_REGNO))"
- + [(set (match_dup 0)
- + (match_dup 2))
- + (parallel
- + [(set (match_dup 0)
- + (ior:SI
- + (ashift:SI (match_dup 0)
- + (const_int 16))
- + (zero_extend:SI
- + (match_dup 3))))
- + (clobber (reg:CC CC_REGNO))])]
- + "{
- + operands[2] = gen_highpart_mode (HImode, SImode, operands[1]);
- + operands[3] = gen_lowpart (HImode, operands[1]);
- + }")
- +
- +; Exactly the same as the peephole2 preceding except that this targets a
- +; general register instead of D register. Hopefully the later optimization
- +; passes will notice that the value ended up in a D register first here
- +; and eliminate away the other register!
- +;
- +(define_peephole2
- + [(match_scratch:SI 2 "d")
- + (set (match_operand:SI 0 "register_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))]
- + "(((INTVAL (operands[1]) >= 0x8000
- + && INTVAL (operands[1]) < 0xff80)
- + || INTVAL (operands[1]) >= 0x10000
- + || INTVAL (operands[1]) < -0x8000)
- + && ((INTVAL (operands[1]) & 0xffff) >= 0xff80
- + || (INTVAL (operands[1]) & 0xffff) < 0x80)
- + && peep2_regno_dead_p (0, CC_REGNO))"
- + [(set (match_dup 2)
- + (match_dup 3))
- + (parallel
- + [(set (match_dup 2)
- + (ior:SI
- + (ashift:SI (match_dup 2)
- + (const_int 16))
- + (zero_extend:SI
- + (match_dup 4))))
- + (clobber (reg:CC CC_REGNO))])
- + (set (match_dup 0)
- + (match_dup 2))]
- + "{
- + operands[3] = gen_highpart_mode (HImode, SImode, operands[1]);
- + operands[4] = gen_lowpart (HImode, operands[1]);
- + }")
- +
- +; If we have a load of a large integer constant which does not have bit 31
- +; set and we have a spare A reg then construct it with a moveai/lea.1 pair
- +; instead. This avoids constructing it in 3 instructions on the stack.
- +;
- +; Note that we have to be careful not to match anything that matches
- +; something we can do in a single instruction! There aren't many such
- +; constants but there are some.
- +;
- +(define_peephole2
- + [(match_scratch:SI 2 "a")
- + (set (match_operand:SI 0 "register_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))]
- + "(! (INTVAL (operands[1]) & 0x80000000)
- + && ((INTVAL (operands[1]) >= 0x8000
- + && INTVAL (operands[1]) < 0xff80)
- + || INTVAL (operands[1]) >= 0x10000))"
- + [(set (match_dup 2)
- + (match_dup 3))
- + (set (match_dup 0)
- + (plus:SI (match_dup 2)
- + (match_dup 4)))]
- + "{
- + HOST_WIDE_INT i = INTVAL (operands[1]);
- + operands[3] = GEN_INT (i & 0xffffff80);
- + operands[4] = GEN_INT (i & 0x7f);
- + }")
- +
- +; If we're not dependent on the state of the condition codes we can construct
- +; a 32-bit constant with a movei/movei/shmrg.2 sequence if possible.
- +;
- +(define_peephole2
- + [(match_scratch:HI 2 "d")
- + (set (match_operand:SI 0 "ubicom32_data_register_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))
- + (match_dup 2)]
- + "(INTVAL (operands[1]) & 0x80000000
- + && INTVAL (operands[1]) < -0x8000
- + && peep2_regno_dead_p (0, CC_REGNO))"
- + [(set (match_dup 0)
- + (match_dup 3))
- + (set (match_dup 2)
- + (match_dup 4))
- + (parallel
- + [(set (match_dup 0)
- + (ior:SI
- + (ashift:SI (match_dup 0)
- + (const_int 16))
- + (zero_extend:SI
- + (match_dup 2))))
- + (clobber (reg:CC CC_REGNO))])]
- + "{
- + operands[3] = gen_highpart_mode (HImode, SImode, operands[1]);
- + operands[4] = gen_lowpart (HImode, operands[1]);
- + }")
- +
- +; Exactly the same as the peephole2 preceding except that this targets a
- +; general register instead of D register. Hopefully the later optimization
- +; passes will notice that the value ended up in a D register first here
- +; and eliminate away the other register!
- +;
- +(define_peephole2
- + [(match_scratch:SI 2 "d")
- + (match_scratch:HI 3 "d")
- + (set (match_operand:SI 0 "register_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))
- + (match_dup 3)]
- + "(INTVAL (operands[1]) & 0x80000000
- + && INTVAL (operands[1]) < -0x8000
- + && peep2_regno_dead_p (0, CC_REGNO))"
- + [(set (match_dup 2)
- + (match_dup 4))
- + (set (match_dup 3)
- + (match_dup 5))
- + (parallel
- + [(set (match_dup 2)
- + (ior:SI
- + (ashift:SI (match_dup 2)
- + (const_int 16))
- + (zero_extend:SI
- + (match_dup 3))))
- + (clobber (reg:CC CC_REGNO))])
- + (set (match_dup 0)
- + (match_dup 2))]
- + "{
- + operands[4] = gen_highpart_mode (HImode, SImode, operands[1]);
- + operands[5] = gen_lowpart (HImode, operands[1]);
- + }")
- +
- +(define_insn "movsi_fdpic_got_offset"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (match_operand:SI 1 "ubicom32_fdpic_got_offset_operand" "Y"))]
- + ""
- + "movei\\t%0, %1")
- +
- +; The explicit MEM inside the UNSPEC prevents the compiler from moving
- +; the load before a branch after a NULL test, or before a store that
- +; initializes a function descriptor.
- +
- +(define_insn_and_split "load_fdpic_funcdesc"
- + [(set (match_operand:SI 0 "ubicom32_address_register_operand" "=a")
- + (unspec_volatile:SI [(mem:SI (match_operand:SI 1 "address_operand" "p"))]
- + UNSPEC_VOLATILE_LOAD_FDPIC_FUNCDESC))]
- + ""
- + "#"
- + "reload_completed"
- + [(set (match_dup 0)
- + (mem:SI (match_dup 1)))])
- +
- +; Combiner-generated 32-bit move with the zero flag set accordingly.
- +;
- +(define_insn "movsi_ccwzn"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:SI 0 "nonimmediate_operand" "rm, d")
- + (const_int 0)))
- + (set (match_operand:SI 1 "nonimmediate_operand" "=d,rm")
- + (match_dup 0))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "@
- + lsl.4\\t%1, %0, #0
- + add.4\\t%1, #0, %0")
- +
- +; Combiner-generated 32-bit move with all flags set accordingly.
- +;
- +(define_insn "movsi_ccw"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:SI 0 "ubicom32_data_register_operand" "d")
- + (const_int 0)))
- + (set (match_operand:SI 1 "nonimmediate_operand" "=rm")
- + (match_dup 0))]
- + "ubicom32_match_cc_mode(insn, CCWmode)"
- + "add.4\\t%1, #0, %0")
- +
- +; Combine isn't very good at merging some types of operations so we
- +; have to make do with a peephole. It's not as effective but it's better
- +; than doing nothing.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "")
- + (match_operand:SI 1 "nonimmediate_operand" ""))
- + (parallel
- + [(set (match_operand 2 "ubicom32_cc_register_operand" "")
- + (match_operator 3 "ubicom32_compare_operator"
- + [(match_dup 0)
- + (const_int 0)]))
- + (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])]
- + "(GET_MODE (operands[2]) == CCWZNmode
- + || GET_MODE (operands[2]) == CCWZmode)"
- + [(parallel
- + [(set (match_dup 2)
- + (match_op_dup 3
- + [(match_dup 1)
- + (const_int 0)]))
- + (set (match_dup 0)
- + (match_dup 1))])]
- + "")
- +
- +; Combine isn't very good at merging some types of operations so we
- +; have to make do with a peephole. It's not as effective but it's better
- +; than doing nothing.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "nonimmediate_operand" "")
- + (match_operand:SI 1 "ubicom32_data_register_operand" ""))
- + (parallel
- + [(set (match_operand 2 "ubicom32_cc_register_operand" "")
- + (match_operator 3 "ubicom32_compare_operator"
- + [(match_dup 1)
- + (const_int 0)]))
- + (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])]
- + "(GET_MODE (operands[2]) == CCWZNmode
- + || GET_MODE (operands[2]) == CCWZmode)"
- + [(parallel
- + [(set (match_dup 2)
- + (match_op_dup 3
- + [(match_dup 1)
- + (const_int 0)]))
- + (set (match_dup 0)
- + (match_dup 1))])]
- + "")
- +
- +; Combine isn't very good at merging some types of operations so we
- +; have to make do with a peephole. It's not as effective but it's better
- +; than doing nothing.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "register_operand" "")
- + (match_operand:SI 1 "nonimmediate_operand" ""))
- + (parallel
- + [(set (match_operand 2 "ubicom32_cc_register_operand" "")
- + (match_operator 3 "ubicom32_compare_operator"
- + [(match_dup 0)
- + (const_int 0)]))
- + (set (match_operand:SI 4 "ubicom32_data_register_operand" "")
- + (match_dup 0))])]
- + "(peep2_reg_dead_p (2, operands[0])
- + && (GET_MODE (operands[2]) == CCWZNmode
- + || GET_MODE (operands[2]) == CCWZmode))"
- + [(parallel
- + [(set (match_dup 2)
- + (match_op_dup 3
- + [(match_dup 1)
- + (const_int 0)]))
- + (set (match_dup 4)
- + (match_dup 1))])]
- + "")
- +
- +; Register renaming may make a general reg into a D reg in which case
- +; we may be able to simplify a compare.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "register_operand" "")
- + (match_operand:SI 1 "nonimmediate_operand" ""))
- + (parallel
- + [(set (match_operand 2 "ubicom32_cc_register_operand" "")
- + (match_operator 3 "ubicom32_compare_operator"
- + [(match_dup 0)
- + (const_int 0)]))
- + (clobber (match_operand:SI 4 "ubicom32_data_register_operand" ""))])]
- + "(peep2_reg_dead_p (2, operands[0])
- + && (GET_MODE (operands[2]) == CCWZNmode
- + || GET_MODE (operands[2]) == CCWZmode))"
- + [(parallel
- + [(set (match_dup 2)
- + (match_op_dup 3
- + [(match_dup 1)
- + (const_int 0)]))
- + (clobber (match_dup 4))])]
- + "")
- +
- +(define_insn_and_split "movdi"
- + [(set (match_operand:DI 0 "nonimmediate_operand" "=r,rm")
- + (match_operand:DI 1 "general_operand" "rmi,ri"))]
- + ""
- + "#"
- + "reload_completed"
- + [(set (match_dup 2) (match_dup 3))
- + (set (match_dup 4) (match_dup 5))]
- + "{
- + rtx dest_low;
- + rtx src_low;
- +
- + dest_low = gen_lowpart (SImode, operands[0]);
- + src_low = gen_lowpart (SImode, operands[1]);
- +
- + if (REG_P (operands[0])
- + && REG_P (operands[1])
- + && REGNO (operands[0]) < REGNO (operands[1]))
- + {
- + operands[2] = gen_highpart (SImode, operands[0]);
- + operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
- + operands[4] = dest_low;
- + operands[5] = src_low;
- + }
- + else if (reg_mentioned_p (dest_low, src_low))
- + {
- + operands[2] = gen_highpart (SImode, operands[0]);
- + operands[3] = gen_highpart_mode (SImode, DImode, operands[1]);
- + operands[4] = dest_low;
- + operands[5] = src_low;
- + }
- + else
- + {
- + operands[2] = dest_low;
- + operands[3] = src_low;
- + operands[4] = gen_highpart (SImode, operands[0]);
- + operands[5] = gen_highpart_mode (SImode, DImode, operands[1]);
- + }
- + }"
- + [(set_attr "length" "8")])
- +
- +; Combiner-generated 64-bit move with all flags set accordingly.
- +;
- +(define_insn "movdi_ccwzn"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:DI 0 "nonimmediate_operand" "d, m, r")
- + (const_int 0)))
- + (set (match_operand:DI 1 "nonimmediate_operand" "=&rm,rm,!&rm")
- + (match_dup 0))
- + (clobber (match_scratch:SI 2 "=X, d, d"))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "*
- + {
- + operands[3] = gen_lowpart (SImode, operands[0]);
- + operands[4] = gen_lowpart (SImode, operands[1]);
- + operands[5] = gen_highpart (SImode, operands[0]);
- + operands[6] = gen_highpart (SImode, operands[1]);
- +
- + if (ubicom32_data_register_operand (operands[0], VOIDmode))
- + return \"add.4\\t%4, #0, %3\;addc\\t%6, #0, %5\";
- +
- + return \"movei\\t%2, #0\;add.4\\t%4, %3, %2\;addc\\t%6, %5, %2\";
- + }"
- + [(set_attr "length" "8")])
- +
- +(define_insn "movdi_ccw"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:DI 0 "nonimmediate_operand" "d, m, r")
- + (const_int 0)))
- + (set (match_operand:DI 1 "nonimmediate_operand" "=&rm,rm,!&rm")
- + (match_dup 0))
- + (clobber (match_scratch:SI 2 "=X, d, d"))]
- + "ubicom32_match_cc_mode(insn, CCWmode)"
- + "*
- + {
- + operands[3] = gen_lowpart (SImode, operands[0]);
- + operands[4] = gen_lowpart (SImode, operands[1]);
- + operands[5] = gen_highpart (SImode, operands[0]);
- + operands[6] = gen_highpart (SImode, operands[1]);
- +
- + if (ubicom32_data_register_operand (operands[0], VOIDmode))
- + return \"add.4\\t%4, #0, %3\;addc\\t%6, #0, %5\";
- +
- + return \"movei\\t%2, #0\;add.4\\t%4, %3, %2\;addc\\t%6, %5, %2\";
- + }"
- + [(set_attr "length" "8")])
- +
- +(define_insn "movsf"
- + [(set (match_operand:SF 0 "nonimmediate_operand" "=!d,*rm")
- + (match_operand:SF 1 "ubicom32_move_operand" "rmF,rmF"))]
- + ""
- + "*
- + {
- + if (GET_CODE (operands[1]) == CONST_DOUBLE)
- + {
- + HOST_WIDE_INT val;
- + REAL_VALUE_TYPE rv;
- +
- + REAL_VALUE_FROM_CONST_DOUBLE (rv, operands[1]);
- + REAL_VALUE_TO_TARGET_SINGLE (rv, val);
- +
- + ubicom32_emit_move_const_int (operands[0], GEN_INT (val));
- + return \"\";
- + }
- +
- + return \"move.4\\t%0, %1\";
- + }")
- +
- +(define_insn "zero_extendqihi2"
- + [(set (match_operand:HI 0 "register_operand" "=r")
- + (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
- + ""
- + "move.1\\t%0, %1")
- +
- +(define_insn "zero_extendqisi2"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
- + ""
- + "move.1\\t%0, %1")
- +
- +(define_insn "zero_extendqisi2_ccwz_1"
- + [(set (reg CC_REGNO)
- + (compare
- + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm"))
- + (const_int 0)))
- + (set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (zero_extend:SI (match_dup 1)))]
- + "ubicom32_match_cc_mode(insn, CCWZmode)"
- + "shmrg.1\\t%0, %1, #0")
- +
- +(define_insn "zero_extendhisi2"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
- + ""
- + "move.2\\t%0, %1")
- +
- +(define_insn "zero_extendhisi2_ccwz_1"
- + [(set (reg CC_REGNO)
- + (compare
- + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm"))
- + (const_int 0)))
- + (set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (zero_extend:SI (match_dup 1)))]
- + "ubicom32_match_cc_mode(insn, CCWZmode)"
- + "shmrg.2\\t%0, %1, #0")
- +
- +(define_insn_and_split "zero_extendqidi2"
- + [(set (match_operand:DI 0 "register_operand" "=r")
- + (zero_extend:DI (match_operand:QI 1 "nonimmediate_operand" "rm")))]
- + ""
- + "#"
- + "reload_completed"
- + [(set (match_dup 2)
- + (zero_extend:SI (match_dup 1)))
- + (set (match_dup 3)
- + (const_int 0))]
- + "{
- + operands[2] = gen_lowpart (SImode, operands[0]);
- + operands[3] = gen_highpart (SImode, operands[0]);
- + }"
- + [(set_attr "length" "8")])
- +
- +(define_insn_and_split "zero_extendhidi2"
- + [(set (match_operand:DI 0 "register_operand" "=r")
- + (zero_extend:DI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
- + ""
- + "#"
- + "reload_completed"
- + [(set (match_dup 2)
- + (zero_extend:SI (match_dup 1)))
- + (set (match_dup 3)
- + (const_int 0))]
- + "{
- + operands[2] = gen_lowpart (SImode, operands[0]);
- + operands[3] = gen_highpart (SImode, operands[0]);
- + }"
- + [(set_attr "length" "8")])
- +
- +(define_insn_and_split "zero_extendsidi2"
- + [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
- + (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))]
- + ""
- + "#"
- + "reload_completed"
- + [(set (match_dup 2)
- + (match_dup 1))
- + (set (match_dup 3)
- + (const_int 0))]
- + "{
- + operands[2] = gen_lowpart (SImode, operands[0]);
- + operands[3] = gen_highpart (SImode, operands[0]);
- + }"
- + [(set_attr "length" "8")])
- +
- +(define_insn "extendqihi2"
- + [(set (match_operand:HI 0 "register_operand" "=r")
- + (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "rm")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "ext.1\\t%0, %1")
- +
- +(define_insn "extendqisi2"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "rm")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "ext.1\\t%0, %1")
- +
- +(define_insn "extendhisi2"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "ext.2\\t%0, %1")
- +
- +(define_insn_and_split "extendsidi2"
- + [(set (match_operand:DI 0 "nonimmediate_operand" "=d")
- + (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "rm")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "#"
- + "reload_completed"
- + [(set (match_dup 2)
- + (match_dup 1))
- + (parallel
- + [(set (match_dup 3)
- + (ashiftrt:SI (match_dup 2)
- + (const_int 31)))
- + (clobber (reg:CC CC_REGNO))])]
- + "{
- + operands[2] = gen_lowpart (SImode, operands[0]);
- + operands[3] = gen_highpart (SImode, operands[0]);
- + }"
- + [(set_attr "length" "8")])
- +
- +(define_insn "bswaphi"
- + [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
- + (bswap:HI (match_operand:HI 1 "ubicom32_arith_operand" "rmI")))]
- + "(ubicom32_v4)"
- + "swapb.2\\t%0, %1");
- +
- +(define_insn "bswaphisi"
- + [(set (match_operand:SI 0 "register_operand" "=r")
- + (zero_extend:SI
- + (bswap:HI (match_operand:HI 1 "ubicom32_arith_operand" "rmI"))))]
- + "(ubicom32_v4)"
- + "swapb.2\\t%0, %1");
- +
- +(define_insn "bswapsi"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- + (bswap:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")))]
- + "(ubicom32_v4)"
- + "swapb.4\\t%0, %1");
- +
- +(define_insn "tstqi_ext1"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:QI 0 "nonimmediate_operand" "rm")
- + (const_int 0)))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "ext.1\\t#0, %0")
- +
- +(define_expand "cmpqi"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:QI 0 "ubicom32_arith_operand" "")
- + (match_operand:QI 1 "ubicom32_data_register_operand" "")))]
- + "(ubicom32_v4)"
- + "{
- + ubicom32_compare_op0 = operands[0];
- + ubicom32_compare_op1 = operands[1];
- + DONE;
- + }")
- +
- +(define_insn "sub1_ccs"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:QI 0 "ubicom32_arith_operand" "rmI")
- + (match_operand:QI 1 "ubicom32_data_register_operand" "d")))]
- + "(ubicom32_v4)"
- + "sub.1\\t#0, %0, %1")
- +
- +; If we're testing for equality we don't have to worry about reversing conditions.
- +;
- +(define_insn "sub1_ccsz_1"
- + [(set (reg:CCSZ CC_REGNO)
- + (compare:CCSZ (match_operand:QI 0 "nonimmediate_operand" "rm")
- + (match_operand:QI 1 "ubicom32_data_register_operand" "d")))]
- + "(ubicom32_v4)"
- + "sub.1\\t#0, %0, %1")
- +
- +(define_insn "sub1_ccsz_2"
- + [(set (reg:CCSZ CC_REGNO)
- + (compare:CCSZ (match_operand:QI 0 "ubicom32_data_register_operand" "d")
- + (match_operand:QI 1 "ubicom32_arith_operand" "rmI")))]
- + "(ubicom32_v4)"
- + "sub.1\\t#0, %1, %0")
- +
- +; When the combiner runs it doesn't have any insight into whether or not an argument
- +; to a compare is spilled to the stack and therefore can't swap the comparison in
- +; an attempt to use sub.1 more effectively. We peephole this case here.
- +;
- +(define_peephole2
- + [(set (match_operand:QI 0 "register_operand" "")
- + (match_operand:QI 1 "ubicom32_arith_operand" ""))
- + (set (match_operand 2 "ubicom32_cc_register_operand" "")
- + (compare (match_operand:QI 3 "ubicom32_data_register_operand" "")
- + (match_dup 0)))
- + (set (pc)
- + (if_then_else (match_operator 4 "comparison_operator"
- + [(match_dup 2)
- + (const_int 0)])
- + (label_ref (match_operand 5 "" ""))
- + (pc)))]
- + "(peep2_reg_dead_p (2, operands[0])
- + && peep2_regno_dead_p (3, CC_REGNO))"
- + [(set (match_dup 2)
- + (compare (match_dup 1)
- + (match_dup 3)))
- + (set (pc)
- + (if_then_else (match_op_dup 6
- + [(match_dup 2)
- + (const_int 0)])
- + (label_ref (match_dup 5))
- + (pc)))]
- + "{
- + rtx cc_reg;
- +
- + cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
- + operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
- + GET_MODE (operands[4]),
- + cc_reg,
- + const0_rtx);
- + }")
- +
- +(define_insn "tsthi_ext2"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:HI 0 "nonimmediate_operand" "rm")
- + (const_int 0)))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "ext.2\\t#0, %0")
- +
- +(define_expand "cmphi"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:HI 0 "ubicom32_arith_operand" "")
- + (match_operand:HI 1 "ubicom32_compare_operand" "")))]
- + ""
- + "{
- + do
- + {
- + /* Is this a cmpi? */
- + if (CONST_INT_P (operands[1]))
- + break;
- +
- + /* Must be a sub.2 - if necessary copy an operand into a reg. */
- + if (! ubicom32_data_register_operand (operands[1], HImode))
- + operands[1] = copy_to_mode_reg (HImode, operands[1]);
- + }
- + while (0);
- +
- + ubicom32_compare_op0 = operands[0];
- + ubicom32_compare_op1 = operands[1];
- + DONE;
- + }")
- +
- +(define_insn "cmpi"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:HI 0 "nonimmediate_operand" "rm")
- + (match_operand 1 "const_int_operand" "N")))]
- + ""
- + "cmpi\\t%0, %1")
- +
- +(define_insn "sub2_ccs"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:HI 0 "ubicom32_arith_operand" "rmI")
- + (match_operand:HI 1 "ubicom32_data_register_operand" "d")))]
- + ""
- + "sub.2\\t#0, %0, %1")
- +
- +; If we're testing for equality we don't have to worry about reversing conditions.
- +;
- +(define_insn "sub2_ccsz_1"
- + [(set (reg:CCSZ CC_REGNO)
- + (compare:CCSZ (match_operand:HI 0 "nonimmediate_operand" "rm")
- + (match_operand:HI 1 "ubicom32_data_register_operand" "d")))]
- + ""
- + "sub.2\\t#0, %0, %1")
- +
- +(define_insn "sub2_ccsz_2"
- + [(set (reg:CCSZ CC_REGNO)
- + (compare:CCSZ (match_operand:HI 0 "ubicom32_data_register_operand" "d")
- + (match_operand:HI 1 "ubicom32_arith_operand" "rmI")))]
- + ""
- + "sub.2\\t#0, %1, %0")
- +
- +; When the combiner runs it doesn't have any insight into whether or not an argument
- +; to a compare is spilled to the stack and therefore can't swap the comparison in
- +; an attempt to use sub.2 more effectively. We peephole this case here.
- +;
- +(define_peephole2
- + [(set (match_operand:HI 0 "register_operand" "")
- + (match_operand:HI 1 "ubicom32_arith_operand" ""))
- + (set (match_operand 2 "ubicom32_cc_register_operand" "")
- + (compare (match_operand:HI 3 "ubicom32_data_register_operand" "")
- + (match_dup 0)))
- + (set (pc)
- + (if_then_else (match_operator 4 "comparison_operator"
- + [(match_dup 2)
- + (const_int 0)])
- + (label_ref (match_operand 5 "" ""))
- + (pc)))]
- + "(peep2_reg_dead_p (2, operands[0])
- + && peep2_regno_dead_p (3, CC_REGNO))"
- + [(set (match_dup 2)
- + (compare (match_dup 1)
- + (match_dup 3)))
- + (set (pc)
- + (if_then_else (match_op_dup 6
- + [(match_dup 2)
- + (const_int 0)])
- + (label_ref (match_dup 5))
- + (pc)))]
- + "{
- + rtx cc_reg;
- +
- + cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
- + operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
- + GET_MODE (operands[4]),
- + cc_reg,
- + const0_rtx);
- + }")
- +
- +(define_insn_and_split "tstsi_lsl4"
- + [(set (match_operand 0 "ubicom32_cc_register_operand" "=r")
- + (match_operator 1 "ubicom32_compare_operator"
- + [(match_operand:SI 2 "nonimmediate_operand" "rm")
- + (const_int 0)]))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "#"
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + [(parallel
- + [(set (match_dup 0)
- + (match_op_dup 1
- + [(match_dup 2)
- + (const_int 0)]))
- + (clobber (match_dup 3))])]
- + "{
- + operands[3] = gen_reg_rtx (SImode);
- + }")
- +
- +(define_insn "tstsi_lsl4_d"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:SI 0 "nonimmediate_operand" "rm")
- + (const_int 0)))
- + (clobber (match_operand:SI 1 "ubicom32_data_register_operand" "=d"))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "lsl.4\\t%1, %0, #0")
- +
- +; Comparison for equality with -1.
- +;
- +(define_insn "cmpsi_not4_ccwz"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:SI 0 "nonimmediate_operand" "rm")
- + (const_int -1)))]
- + "ubicom32_match_cc_mode(insn, CCWZmode)"
- + "not.4\\t#0, %0")
- +
- +(define_expand "cmpsi"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:SI 0 "ubicom32_arith_operand" "")
- + (match_operand:SI 1 "ubicom32_compare_operand" "")))]
- + ""
- + "{
- + do
- + {
- + /* Is this a cmpi? We can't take a memory address as cmpi takes
- + 16-bit operands. */
- + if (register_operand (operands[0], SImode)
- + && CONST_INT_P (operands[1])
- + && satisfies_constraint_N (operands[1]))
- + break;
- +
- + /* Must be a sub.4 - if necessary copy an operand into a reg. */
- + if (! ubicom32_data_register_operand (operands[1], SImode))
- + operands[1] = copy_to_mode_reg (SImode, operands[1]);
- + }
- + while (0);
- +
- + ubicom32_compare_op0 = operands[0];
- + ubicom32_compare_op1 = operands[1];
- + DONE;
- + }")
- +
- +(define_insn "cmpsi_cmpi"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:SI 0 "register_operand" "r")
- + (match_operand 1 "const_int_operand" "N")))]
- + "(satisfies_constraint_N (operands[1]))"
- + "cmpi\\t%0, %1")
- +
- +(define_insn "cmpsi_sub4"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:SI 0 "ubicom32_arith_operand" "rmI")
- + (match_operand:SI 1 "ubicom32_data_register_operand" "d")))]
- + ""
- + "sub.4\\t#0, %0, %1")
- +
- +; If we're testing for equality we don't have to worry about reversing conditions.
- +;
- +(define_insn "cmpsi_sub4_ccwz_1"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:SI 0 "nonimmediate_operand" "rm")
- + (match_operand:SI 1 "ubicom32_data_register_operand" "d")))]
- + "ubicom32_match_cc_mode(insn, CCWZmode)"
- + "sub.4\\t#0, %0, %1")
- +
- +(define_insn "cmpsi_sub4_ccwz_2"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:SI 0 "ubicom32_data_register_operand" "d")
- + (match_operand:SI 1 "nonimmediate_operand" "rm")))]
- + "ubicom32_match_cc_mode(insn, CCWZmode)"
- + "sub.4\\t#0, %1, %0")
- +
- +; When the combiner runs it doesn't have any insight into whether or not an argument
- +; to a compare is spilled to the stack and therefore can't swap the comparison in
- +; an attempt to use sub.4 more effectively. We peephole this case here.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "register_operand" "")
- + (match_operand:SI 1 "ubicom32_arith_operand" ""))
- + (set (match_operand 2 "ubicom32_cc_register_operand" "")
- + (compare (match_operand:SI 3 "ubicom32_data_register_operand" "")
- + (match_dup 0)))
- + (set (pc)
- + (if_then_else (match_operator 4 "comparison_operator"
- + [(match_dup 2)
- + (const_int 0)])
- + (label_ref (match_operand 5 "" ""))
- + (pc)))]
- + "(peep2_reg_dead_p (2, operands[0])
- + && peep2_regno_dead_p (3, CC_REGNO))"
- + [(set (match_dup 2)
- + (compare (match_dup 1)
- + (match_dup 3)))
- + (set (pc)
- + (if_then_else (match_op_dup 6
- + [(match_dup 2)
- + (const_int 0)])
- + (label_ref (match_dup 5))
- + (pc)))]
- + "{
- + rtx cc_reg;
- +
- + cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
- + operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
- + GET_MODE (operands[4]),
- + cc_reg,
- + const0_rtx);
- + }")
- +
- +(define_insn_and_split "tstdi_or4"
- + [(set (reg:CCWZ CC_REGNO)
- + (compare:CCWZ (match_operand:DI 0 "nonimmediate_operand" "rm")
- + (const_int 0)))]
- + ""
- + "#"
- + ""
- + [(parallel
- + [(set (reg:CCWZ CC_REGNO)
- + (compare:CCWZ (match_dup 0)
- + (const_int 0)))
- + (clobber (match_dup 1))])]
- + "{
- + operands[1] = gen_reg_rtx (SImode);
- + }")
- +
- +(define_insn "tstdi_or4_d"
- + [(set (reg:CCWZ CC_REGNO)
- + (compare:CCWZ (match_operand:DI 0 "nonimmediate_operand" "rm")
- + (const_int 0)))
- + (clobber (match_operand:SI 1 "ubicom32_data_register_operand" "=d"))]
- + ""
- + "*
- + {
- + operands[2] = gen_lowpart (SImode, operands[0]);
- + operands[3] = gen_highpart_mode (SImode, DImode, operands[0]);
- +
- + if (ubicom32_data_register_operand (operands[0], GET_MODE (operands[0])))
- + return \"or.4\\t#0, %2, %3\";
- +
- + return \"move.4\\t%1, %2\;or.4\\t%1, %3, %1\";
- + }"
- + [(set_attr "length" "8")])
- +
- +(define_expand "cmpdi"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:DI 0 "ubicom32_arith_operand" "")
- + (match_operand:DI 1 "ubicom32_data_register_operand" "")))]
- + ""
- + "{
- + ubicom32_compare_op0 = operands[0];
- + ubicom32_compare_op1 = operands[1];
- + DONE;
- + }")
- +
- +(define_insn "cmpdi_sub4subc"
- + [(set (reg CC_REGNO)
- + (compare (match_operand:DI 0 "ubicom32_arith_operand" "rmI")
- + (match_operand:DI 1 "ubicom32_data_register_operand" "d")))]
- + ""
- + "*
- + {
- + operands[2] = gen_lowpart (SImode, operands[0]);
- + operands[3] = gen_lowpart (SImode, operands[1]);
- + operands[4] = gen_highpart_mode (SImode, DImode, operands[0]);
- + operands[5] = gen_highpart_mode (SImode, DImode, operands[1]);
- +
- + return \"sub.4\\t#0, %2, %3\;subc\\t#0, %4, %5\";
- + }"
- + [(set_attr "length" "8")])
- +
- +; When the combiner runs it doesn't have any insight into whether or not an argument
- +; to a compare is spilled to the stack and therefore can't swap the comparison in
- +; an attempt to use sub.4/subc more effectively. We peephole this case here.
- +;
- +(define_peephole2
- + [(set (match_operand:DI 0 "register_operand" "")
- + (match_operand:DI 1 "ubicom32_arith_operand" ""))
- + (set (match_operand 2 "ubicom32_cc_register_operand" "")
- + (compare (match_operand:DI 3 "ubicom32_data_register_operand" "")
- + (match_dup 0)))
- + (set (pc)
- + (if_then_else (match_operator 4 "comparison_operator"
- + [(match_dup 2)
- + (const_int 0)])
- + (label_ref (match_operand 5 "" ""))
- + (pc)))]
- + "(peep2_reg_dead_p (2, operands[0])
- + && peep2_regno_dead_p (3, CC_REGNO))"
- + [(set (match_dup 2)
- + (compare (match_dup 1)
- + (match_dup 3)))
- + (set (pc)
- + (if_then_else (match_op_dup 6
- + [(match_dup 2)
- + (const_int 0)])
- + (label_ref (match_dup 5))
- + (pc)))]
- + "{
- + rtx cc_reg;
- +
- + cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
- + operands[6] = gen_rtx_fmt_ee (swap_condition (GET_CODE (operands[4])),
- + GET_MODE (operands[4]),
- + cc_reg,
- + const0_rtx);
- + }")
- +
- +(define_insn "btst"
- + [(set (reg:CCWZ CC_REGNO)
- + (compare:CCWZ
- + (zero_extract:SI
- + (match_operand:SI 0 "nonimmediate_operand" "rm")
- + (const_int 1)
- + (match_operand:SI 1 "ubicom32_arith_operand" "dM"))
- + (const_int 0)))]
- + ""
- + "btst\\t%0, %1")
- +
- +(define_insn "bfextu_ccwz_null"
- + [(set (reg:CCWZ CC_REGNO)
- + (compare:CCWZ
- + (zero_extract:SI
- + (match_operand:SI 0 "nonimmediate_operand" "rm")
- + (match_operand 1 "const_int_operand" "M")
- + (const_int 0))
- + (const_int 0)))
- + (clobber (match_scratch:SI 2 "=d"))]
- + ""
- + "bfextu\\t%2, %0, %1")
- +
- +(define_expand "addqi3"
- + [(parallel
- + [(set (match_operand:QI 0 "memory_operand" "")
- + (plus:QI (match_operand:QI 1 "nonimmediate_operand" "")
- + (match_operand:QI 2 "ubicom32_arith_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + "(ubicom32_v4)"
- + "{
- + if (!memory_operand (operands[0], QImode))
- + FAIL;
- +
- + /* If we have a non-data reg for operand 1 then prefer that over
- + a CONST_INT in operand 2. */
- + if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
- + && CONST_INT_P (operands[2]))
- + operands[2] = copy_to_mode_reg (QImode, operands[2]);
- +
- + if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
- + operands[2] = copy_to_mode_reg (QImode, operands[2]);
- + }")
- +
- +(define_insn "addqi3_add1"
- + [(set (match_operand:QI 0 "memory_operand" "=m, m")
- + (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4)"
- + "@
- + add.1\\t%0, %2, %1
- + add.1\\t%0, %1, %2")
- +
- +(define_insn "addqi3_add1_ccszn_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (neg:QI (match_operand:QI 0 "nonimmediate_operand" "%d,rm"))
- + (match_operand:QI 1 "ubicom32_arith_operand" "rmI, d")))]
- + "(ubicom32_v4
- + && ubicom32_match_cc_mode(insn, CCSZNmode))"
- + "@
- + add.1\\t#0, %1, %0
- + add.1\\t#0, %0, %1")
- +
- +(define_expand "addhi3"
- + [(parallel
- + [(set (match_operand:HI 0 "memory_operand" "")
- + (plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
- + (match_operand:HI 2 "ubicom32_arith_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + ""
- + "{
- + if (!memory_operand (operands[0], HImode))
- + FAIL;
- +
- + /* If we have a non-data reg for operand 1 then prefer that over
- + a CONST_INT in operand 2. */
- + if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
- + && CONST_INT_P (operands[2]))
- + operands[2] = copy_to_mode_reg (HImode, operands[2]);
- +
- + if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
- + operands[2] = copy_to_mode_reg (HImode, operands[2]);
- + }")
- +
- +(define_insn "addhi3_add2"
- + [(set (match_operand:HI 0 "memory_operand" "=m, m")
- + (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "@
- + add.2\\t%0, %2, %1
- + add.2\\t%0, %1, %2")
- +
- +(define_insn "addhi3_add2_ccszn_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (neg:HI (match_operand:HI 0 "nonimmediate_operand" "%d,rm"))
- + (match_operand:HI 1 "ubicom32_arith_operand" "rmI, d")))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "@
- + add.2\\t#0, %1, %0
- + add.2\\t#0, %0, %1")
- +
- +(define_expand "addsi3"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "")
- + (plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
- + (match_operand:SI 2 "ubicom32_move_operand" "")))]
- + ""
- + "{
- + ubicom32_expand_addsi3 (operands);
- + DONE;
- + }")
- +
- +; We start with an instruction pattern that can do all sorts of interesting
- +; things but we split out any uses of lea or pdec instructions because
- +; those instructions don't clobber the condition codes.
- +;
- +(define_insn_and_split "addsi3_1"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm,rm,rm,rm, rm,rm")
- + (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%a, a, a, a, a, d,rm")
- + (match_operand:SI 2 "ubicom32_move_operand" "L, K, J, P, d,rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "@
- + #
- + #
- + #
- + #
- + #
- + add.4\\t%0, %2, %1
- + add.4\\t%0, %1, %2"
- + "(reload_completed
- + && ubicom32_address_register_operand (operands[1], GET_MODE (operands[1])))"
- + [(set (match_dup 0)
- + (plus:SI (match_dup 1)
- + (match_dup 2)))]
- + ""
- +)
- +
- +(define_insn "addsi3_1_ccwzn"
- + [(set (reg CC_REGNO)
- + (compare
- + (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))
- + (set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
- + (plus:SI (match_dup 1)
- + (match_dup 2)))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "@
- + add.4\\t%0, %2, %1
- + add.4\\t%0, %1, %2")
- +
- +(define_insn "addsi3_1_ccwzn_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (neg:SI (match_operand:SI 0 "nonimmediate_operand" "%d,rm"))
- + (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d")))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "@
- + add.4\\t#0, %1, %0
- + add.4\\t#0, %0, %1")
- +
- +(define_insn_and_split "addsi3_2"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm,rm,rm,rm,rm")
- + (plus:SI (match_operand:SI 1 "ubicom32_address_register_operand" "%a, a, a, a, a, a")
- + (match_operand:SI 2 "ubicom32_move_operand" "L, K, J, P, d, n")))]
- + ""
- + "@
- + lea.4\\t%0, %E2(%1)
- + lea.2\\t%0, %E2(%1)
- + lea.1\\t%0, %E2(%1)
- + pdec\\t%0, %n2(%1)
- + lea.1\\t%0, (%1,%2)
- + #"
- + "(reload_completed
- + && ! satisfies_constraint_L (operands[2])
- + && ! satisfies_constraint_K (operands[2])
- + && ! satisfies_constraint_J (operands[2])
- + && ! satisfies_constraint_P (operands[2])
- + && ! ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))"
- + [(set (reg:SI AUX_DATA_REGNO)
- + (match_dup 2))
- + (set (match_dup 0)
- + (plus:SI (match_dup 1)
- + (reg:SI AUX_DATA_REGNO)))]
- + ""
- +)
- +
- +(define_insn "lea_2"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- + (plus:SI (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
- + (const_int 2))
- + (match_operand:SI 2 "ubicom32_address_register_operand" "a")))]
- + ""
- + "lea.2\\t%0, (%2,%1)")
- +
- +(define_insn "lea_4"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- + (plus:SI (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
- + (const_int 4))
- + (match_operand:SI 2 "ubicom32_address_register_operand" "a")))]
- + ""
- + "lea.4\\t%0, (%2,%1)")
- +
- +(define_expand "adddi3"
- + [(parallel
- + [(set (match_operand:DI 0 "nonimmediate_operand" "")
- + (plus:DI (match_operand:DI 1 "nonimmediate_operand" "")
- + (match_operand:DI 2 "ubicom32_arith_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + ""
- + "{
- + /* If we have a non-data reg for operand 1 then prefer that over
- + a CONST_INT in operand 2. */
- + if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
- + && CONST_INT_P (operands[2]))
- + operands[2] = copy_to_mode_reg (DImode, operands[2]);
- +
- + if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
- + operands[2] = copy_to_mode_reg (DImode, operands[2]);
- + }")
- +
- +; We construct a 64-bit add from 32-bit operations. Note that we use the
- +; & constraint to prevent overlapping registers being allocated. We do
- +; allow identical registers though as that won't break anything.
- +;
- +(define_insn "adddi3_add4addc"
- + [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,&r,rm, d, m, m")
- + (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%d,rm, 0, 0, d,rm")
- + (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d, d,rmI,rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "*
- + {
- + operands[3] = gen_lowpart (SImode, operands[0]);
- + operands[4] = gen_lowpart (SImode, operands[1]);
- + operands[5] = gen_lowpart (SImode, operands[2]);
- + operands[6] = gen_highpart (SImode, operands[0]);
- + operands[7] = gen_highpart (SImode, operands[1]);
- + operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
- +
- + if (ubicom32_data_register_operand (operands[2], GET_MODE (operands[2])))
- + return \"add.4\\t%3, %4, %5\;addc\\t%6, %7, %8\";
- +
- + return \"add.4\\t%3, %5, %4\;addc\\t%6, %8, %7\";
- + }"
- + [(set_attr "length" "8")])
- +
- +(define_insn "adddi3_ccwz"
- + [(set (reg CC_REGNO)
- + (compare
- + (plus:DI (match_operand:DI 1 "nonimmediate_operand" "%d,rm, 0, 0, d,rm")
- + (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d, d,rmI,rmI, d"))
- + (const_int 0)))
- + (set (match_operand:DI 0 "nonimmediate_operand" "=&r,&r,rm, d, m, m")
- + (plus:DI (match_dup 1)
- + (match_dup 2)))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "*
- + {
- + operands[3] = gen_lowpart (SImode, operands[0]);
- + operands[6] = gen_highpart (SImode, operands[0]);
- +
- + if (ubicom32_data_register_operand (operands[1], GET_MODE (operands[1])))
- + {
- + operands[4] = gen_lowpart (SImode, operands[1]);
- + operands[5] = gen_lowpart (SImode, operands[2]);
- + operands[7] = gen_highpart (SImode, operands[1]);
- + operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
- + }
- + else
- + {
- + operands[4] = gen_lowpart (SImode, operands[2]);
- + operands[5] = gen_lowpart (SImode, operands[1]);
- + operands[7] = gen_highpart (SImode, operands[2]);
- + operands[8] = gen_highpart (SImode, operands[1]);
- + }
- +
- + return \"add.4\\t%3, %5, %4\;addc\\t%6, %8, %7\";
- + }"
- + [(set_attr "length" "8")])
- +
- +(define_insn "adddi3_ccwz_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (neg:DI (match_operand:DI 0 "nonimmediate_operand" "%d,rm"))
- + (match_operand:DI 1 "ubicom32_arith_operand" "rmI, d")))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "*
- + {
- + if (ubicom32_data_register_operand (operands[0], GET_MODE (operands[0])))
- + {
- + operands[2] = gen_lowpart (SImode, operands[0]);
- + operands[3] = gen_lowpart (SImode, operands[1]);
- + operands[4] = gen_highpart (SImode, operands[0]);
- + operands[5] = gen_highpart_mode (SImode, DImode, operands[1]);
- + }
- + else
- + {
- + operands[2] = gen_lowpart (SImode, operands[1]);
- + operands[3] = gen_lowpart (SImode, operands[0]);
- + operands[4] = gen_highpart (SImode, operands[1]);
- + operands[5] = gen_highpart (SImode, operands[0]);
- + }
- +
- + return \"add.4\\t#0, %3, %2\;addc\\t#0, %5, %4\";
- + }"
- + [(set_attr "length" "8")])
- +
- +(define_expand "subqi3"
- + [(parallel
- + [(set (match_operand:QI 0 "memory_operand" "")
- + (minus:QI (match_operand:QI 1 "ubicom32_arith_operand" "")
- + (match_operand:QI 2 "ubicom32_data_register_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + "(ubicom32_v4)"
- + "{
- + if (!memory_operand (operands[0], QImode))
- + FAIL;
- + }")
- +
- +(define_insn "subqi3_sub1"
- + [(set (match_operand:QI 0 "memory_operand" "=m")
- + (minus:QI (match_operand:QI 1 "ubicom32_arith_operand" "rmI")
- + (match_operand:QI 2 "ubicom32_data_register_operand" "d")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4)"
- + "sub.1\\t%0, %1, %2")
- +
- +(define_expand "subhi3"
- + [(parallel
- + [(set (match_operand:HI 0 "memory_operand" "")
- + (minus:HI (match_operand:HI 1 "ubicom32_arith_operand" "")
- + (match_operand:HI 2 "ubicom32_data_register_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + "(ubicom32_v4)"
- + "{
- + if (!memory_operand (operands[0], HImode))
- + FAIL;
- + }")
- +
- +(define_insn "subhi3_sub2"
- + [(set (match_operand:HI 0 "memory_operand" "=m")
- + (minus:HI (match_operand:HI 1 "ubicom32_arith_operand" "rmI")
- + (match_operand:HI 2 "ubicom32_data_register_operand" "d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "sub.2\\t%0, %1, %2")
- +
- +(define_insn "subsi3"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- + (minus:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
- + (match_operand:SI 2 "ubicom32_data_register_operand" "d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "sub.4\\t%0, %1, %2")
- +
- +(define_insn "subsi3_ccwz"
- + [(set (reg CC_REGNO)
- + (compare
- + (minus:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
- + (match_operand:SI 2 "ubicom32_data_register_operand" "d"))
- + (const_int 0)))
- + (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- + (minus:SI (match_dup 1)
- + (match_dup 2)))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "sub.4\\t%0, %1, %2")
- +
- +; We construct a 64-bit add from 32-bit operations. Note that we use the
- +; & constraint to prevent overlapping registers being allocated. We do
- +; allow identical registers though as that won't break anything.
- +;
- +(define_insn "subdi3"
- + [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r, d, m")
- + (minus:DI (match_operand:DI 1 "ubicom32_arith_operand" "rmI,0,rmI,rmI")
- + (match_operand:DI 2 "ubicom32_data_register_operand" "d,d, 0, d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "*
- + {
- + operands[3] = gen_lowpart (SImode, operands[0]);
- + operands[4] = gen_lowpart (SImode, operands[1]);
- + operands[5] = gen_lowpart (SImode, operands[2]);
- + operands[6] = gen_highpart (SImode, operands[0]);
- + operands[7] = gen_highpart_mode (SImode, DImode, operands[1]);
- + operands[8] = gen_highpart (SImode, operands[2]);
- +
- + return \"sub.4\\t%3, %4, %5\;subc\\t%6, %7, %8\";
- + }"
- + [(set_attr "length" "8")])
- +
- +(define_insn "subdi3_ccwz"
- + [(set (reg CC_REGNO)
- + (compare
- + (minus:DI (match_operand:DI 1 "ubicom32_arith_operand" "rmI,rmI")
- + (match_operand:DI 2 "ubicom32_data_register_operand" "d, d"))
- + (const_int 0)))
- + (set (match_operand:DI 0 "nonimmediate_operand" "=&r, m")
- + (minus:DI (match_dup 1)
- + (match_dup 2)))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "*
- + {
- + operands[3] = gen_lowpart (SImode, operands[0]);
- + operands[4] = gen_lowpart (SImode, operands[1]);
- + operands[5] = gen_lowpart (SImode, operands[2]);
- + operands[6] = gen_highpart (SImode, operands[0]);
- + operands[7] = gen_highpart_mode (SImode, DImode, operands[1]);
- + operands[8] = gen_highpart (SImode, operands[2]);
- +
- + return \"sub.4\\t%3, %4, %5\;subc\\t%6, %7, %8\";
- + }"
- + [(set_attr "length" "8")])
- +
- +;(define_insn "negqi2"
- +; [(set (match_operand:QI 0 "nonimmediate_operand" "=rm")
- +; (neg:QI (match_operand:QI 1 "ubicom32_data_register_operand" "d")))
- +; (clobber (reg:CC CC_REGNO))]
- +; "(ubicom32_v4)"
- +; "sub.1\\t%0, #0, %1")
- +
- +;(define_insn "neghi2"
- +; [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
- +; (neg:HI (match_operand:HI 1 "ubicom32_data_register_operand" "d")))
- +; (clobber (reg:CC CC_REGNO))]
- +; ""
- +; "sub.2\\t%0, #0, %1")
- +
- +(define_insn "negsi2"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- + (neg:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "sub.4\\t%0, #0, %1")
- +
- +(define_insn_and_split "negdi2"
- + [(set (match_operand:DI 0 "nonimmediate_operand" "=&rm")
- + (neg:DI (match_operand:DI 1 "ubicom32_data_register_operand" "d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "#"
- + "reload_completed"
- + [(parallel [(set (match_dup 0)
- + (minus:DI (const_int 0)
- + (match_dup 1)))
- + (clobber (reg:CC CC_REGNO))])]
- + ""
- + [(set_attr "length" "8")])
- +
- +(define_insn "umulhisi3"
- + [(set (match_operand:SI 0 "ubicom32_acc_lo_register_operand" "=l, l")
- + (mult:SI
- + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "%d,rm"))
- + (zero_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rm, d"))))
- + (clobber (reg:HI ACC0_HI_REGNO))
- + (clobber (reg:HI ACC1_HI_REGNO))]
- + ""
- + "@
- + mulu\\t%A0, %2, %1
- + mulu\\t%A0, %1, %2"
- + [(set_attr "type" "mul,mul")])
- +
- +(define_insn "mulhisi3"
- + [(set (match_operand:SI 0 "ubicom32_acc_lo_register_operand" "=l, l")
- + (mult:SI
- + (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "%d,rm"))
- + (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "rm, d"))))
- + (clobber (reg:HI ACC0_HI_REGNO))
- + (clobber (reg:HI ACC1_HI_REGNO))]
- + ""
- + "@
- + muls\\t%A0, %2, %1
- + muls\\t%A0, %1, %2"
- + [(set_attr "type" "mul,mul")])
- +
- +(define_expand "mulsi3"
- + [(set (match_operand:SI 0 "ubicom32_acc_hi_register_operand" "")
- + (mult:SI (match_operand:SI 1 "ubicom32_arith_operand" "")
- + (match_operand:SI 2 "ubicom32_arith_operand" "")))]
- + ""
- + "{
- + if (ubicom32_emit_mult_sequence (operands))
- + DONE;
- + }")
- +
- +(define_insn "umulsidi3"
- + [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand" "=h, h")
- + (mult:DI
- + (zero_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%d,rm"))
- + (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm, d"))))]
- + "(ubicom32_v4)"
- + "@
- + mulu.4\\t%A0, %2, %1
- + mulu.4\\t%A0, %1, %2"
- + [(set_attr "type" "mul,mul")])
- +
- +(define_peephole2
- + [(set (match_operand:SI 0 "register_operand" "")
- + (match_operand:SI 1 "nonimmediate_operand" ""))
- + (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
- + (mult:DI
- + (zero_extend:DI (match_dup 0))
- + (zero_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))))]
- + "(peep2_reg_dead_p (2, operands[0])
- + || REGNO (operands[0]) == REGNO (operands[2])
- + || REGNO (operands[0]) == REGNO (operands[2]) + 1)
- + && ! rtx_equal_p (operands[0], operands[3])"
- + [(set (match_dup 2)
- + (mult:DI
- + (zero_extend:DI (match_dup 1))
- + (zero_extend:DI (match_dup 3))))]
- + "")
- +
- +(define_peephole2
- + [(set (match_operand:SI 0 "register_operand" "")
- + (match_operand:SI 1 "nonimmediate_operand" ""))
- + (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
- + (mult:DI
- + (zero_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))
- + (zero_extend:DI (match_dup 0))))]
- + "(peep2_reg_dead_p (2, operands[0])
- + || REGNO (operands[0]) == REGNO (operands[2])
- + || REGNO (operands[0]) == REGNO (operands[2]) + 1)
- + && ! rtx_equal_p (operands[0], operands[3])"
- + [(set (match_dup 2)
- + (mult:DI
- + (zero_extend:DI (match_dup 1))
- + (zero_extend:DI (match_dup 3))))]
- + "")
- +
- +(define_insn "umulsidi3_const"
- + [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand" "=h")
- + (mult:DI
- + (zero_extend:DI (match_operand:SI 1 "ubicom32_data_register_operand" "%d"))
- + (match_operand 2 "const_int_operand" "I")))]
- + "(ubicom32_v4 && satisfies_constraint_I (operands[2]))"
- + "mulu.4\\t%A0, %2, %1"
- + [(set_attr "type" "mul")])
- +
- +(define_insn "mulsidi3"
- + [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand" "=h, h")
- + (mult:DI
- + (sign_extend:DI (match_operand:SI 1 "nonimmediate_operand" "%d,rm"))
- + (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm, d"))))]
- + "(ubicom32_v4)"
- + "@
- + muls.4\\t%A0, %2, %1
- + muls.4\\t%A0, %1, %2"
- + [(set_attr "type" "mul,mul")])
- +
- +(define_peephole2
- + [(set (match_operand:SI 0 "register_operand" "")
- + (match_operand:SI 1 "nonimmediate_operand" ""))
- + (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
- + (mult:DI
- + (sign_extend:DI (match_dup 0))
- + (sign_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))))]
- + "(peep2_reg_dead_p (2, operands[0])
- + || REGNO (operands[0]) == REGNO (operands[2])
- + || REGNO (operands[0]) == REGNO (operands[2]) + 1)
- + && ! rtx_equal_p (operands[0], operands[3])"
- + [(set (match_dup 2)
- + (mult:DI
- + (sign_extend:DI (match_dup 1))
- + (sign_extend:DI (match_dup 3))))]
- + "")
- +
- +(define_peephole2
- + [(set (match_operand:SI 0 "register_operand" "")
- + (match_operand:SI 1 "nonimmediate_operand" ""))
- + (set (match_operand:DI 2 "ubicom32_acc_hi_register_operand" "")
- + (mult:DI
- + (sign_extend:DI (match_operand:SI 3 "ubicom32_data_register_operand" ""))
- + (sign_extend:DI (match_dup 0))))]
- + "(peep2_reg_dead_p (2, operands[0])
- + || REGNO (operands[0]) == REGNO (operands[2])
- + || REGNO (operands[0]) == REGNO (operands[2]) + 1)
- + && ! rtx_equal_p (operands[0], operands[3])"
- + [(set (match_dup 2)
- + (mult:DI
- + (sign_extend:DI (match_dup 1))
- + (sign_extend:DI (match_dup 3))))]
- + "")
- +
- +(define_insn "mulsidi3_const"
- + [(set (match_operand:DI 0 "ubicom32_acc_hi_register_operand" "=h")
- + (mult:DI
- + (sign_extend:DI (match_operand:SI 1 "ubicom32_data_register_operand" "%d"))
- + (match_operand 2 "const_int_operand" "I")))]
- + "(ubicom32_v4 && satisfies_constraint_I (operands[2]))"
- + "muls.4\\t%A0, %2, %1"
- + [(set_attr "type" "mul")])
- +
- +(define_expand "andqi3"
- + [(parallel
- + [(set (match_operand:QI 0 "memory_operand" "")
- + (and:QI (match_operand:QI 1 "nonimmediate_operand" "")
- + (match_operand:QI 2 "ubicom32_arith_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + "(ubicom32_v4)"
- + "{
- + if (!memory_operand (operands[0], QImode))
- + FAIL;
- +
- + /* If we have a non-data reg for operand 1 then prefer that over
- + a CONST_INT in operand 2. */
- + if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
- + && CONST_INT_P (operands[2]))
- + operands[2] = copy_to_mode_reg (QImode, operands[2]);
- +
- + if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
- + operands[2] = copy_to_mode_reg (QImode, operands[2]);
- + }")
- +
- +(define_insn "andqi3_and1"
- + [(set (match_operand:QI 0 "memory_operand" "=m, m")
- + (and:QI (match_operand:QI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4)"
- + "@
- + and.1\\t%0, %2, %1
- + and.1\\t%0, %1, %2")
- +
- +(define_insn "andqi3_and1_ccszn"
- + [(set (reg CC_REGNO)
- + (compare
- + (and:QI (match_operand:QI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))
- + (set (match_operand:QI 0 "memory_operand" "=m, m")
- + (and:QI (match_dup 1)
- + (match_dup 2)))]
- + "(ubicom32_v4
- + && ubicom32_match_cc_mode(insn, CCSZNmode))"
- + "@
- + and.1\\t%0, %2, %1
- + and.1\\t%0, %1, %2")
- +
- +(define_insn "andqi3_and1_ccszn_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (and:QI (match_operand:QI 0 "nonimmediate_operand" "%d,rm")
- + (match_operand:QI 1 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))]
- + "(ubicom32_v4
- + && ubicom32_match_cc_mode(insn, CCSZNmode))"
- + "@
- + and.1\\t#0, %1, %0
- + and.1\\t#0, %0, %1")
- +
- +(define_insn "and1_ccszn_null_1"
- + [(set (reg CC_REGNO)
- + (compare
- + (subreg:QI
- + (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
- + (match_operand:SI 1 "ubicom32_arith_operand" "rI"))
- + 3)
- + (const_int 0)))]
- + "(ubicom32_v4
- + && ubicom32_match_cc_mode(insn, CCSZNmode))"
- + "and.1\\t#0, %1, %0")
- +
- +(define_insn "and1_ccszn_null_2"
- + [(set (reg CC_REGNO)
- + (compare
- + (subreg:QI
- + (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
- + (subreg:SI
- + (match_operand:QI 1 "memory_operand" "m")
- + 0))
- + 3)
- + (const_int 0)))]
- + "(ubicom32_v4
- + && ubicom32_match_cc_mode(insn, CCSZNmode))"
- + "and.1\\t#0, %1, %0")
- +
- +(define_insn "and1_ccszn_null_3"
- + [(set (reg CC_REGNO)
- + (compare
- + (subreg:QI
- + (and:SI (subreg:SI
- + (match_operand:QI 0 "memory_operand" "m")
- + 0)
- + (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
- + 3)
- + (const_int 0)))]
- + "(ubicom32_v4
- + && ubicom32_match_cc_mode(insn, CCSZNmode))"
- + "and.1\\t#0, %0, %1")
- +
- +(define_expand "andhi3"
- + [(parallel
- + [(set (match_operand:HI 0 "memory_operand" "")
- + (and:HI (match_operand:HI 1 "nonimmediate_operand" "")
- + (match_operand:HI 2 "ubicom32_arith_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + ""
- + "{
- + if (!memory_operand (operands[0], HImode))
- + FAIL;
- +
- + /* If we have a non-data reg for operand 1 then prefer that over
- + a CONST_INT in operand 2. */
- + if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
- + && CONST_INT_P (operands[2]))
- + operands[2] = copy_to_mode_reg (HImode, operands[2]);
- +
- + if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
- + operands[2] = copy_to_mode_reg (HImode, operands[2]);
- + }")
- +
- +(define_insn "andhi3_and2"
- + [(set (match_operand:HI 0 "memory_operand" "=m, m")
- + (and:HI (match_operand:HI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "@
- + and.2\\t%0, %2, %1
- + and.2\\t%0, %1, %2")
- +
- +(define_insn "andhi3_and2_ccszn"
- + [(set (reg CC_REGNO)
- + (compare
- + (and:HI (match_operand:HI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))
- + (set (match_operand:HI 0 "memory_operand" "=m, m")
- + (and:HI (match_dup 1)
- + (match_dup 2)))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "@
- + and.2\\t%0, %2, %1
- + and.2\\t%0, %1, %2")
- +
- +(define_insn "andhi3_and2_ccszn_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (and:HI (match_operand:HI 0 "nonimmediate_operand" "%d,rm")
- + (match_operand:HI 1 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "@
- + and.2\\t#0, %1, %0
- + and.2\\t#0, %0, %1")
- +
- +(define_insn "and2_ccszn_null_1"
- + [(set (reg CC_REGNO)
- + (compare
- + (subreg:HI
- + (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
- + (match_operand:SI 1 "ubicom32_arith_operand" "rI"))
- + 2)
- + (const_int 0)))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "and.2\\t#0, %1, %0")
- +
- +(define_insn "and2_ccszn_null_2"
- + [(set (reg CC_REGNO)
- + (compare
- + (subreg:HI
- + (and:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
- + (subreg:SI
- + (match_operand:HI 1 "memory_operand" "m")
- + 0))
- + 2)
- + (const_int 0)))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "and.2\\t#0, %1, %0")
- +
- +(define_insn "and2_ccszn_null_3"
- + [(set (reg CC_REGNO)
- + (compare
- + (subreg:HI
- + (and:SI (subreg:SI
- + (match_operand:HI 0 "memory_operand" "m")
- + 0)
- + (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
- + 2)
- + (const_int 0)))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "and.2\\t#0, %0, %1")
- +
- +(define_expand "andsi3"
- + [(parallel
- + [(set (match_operand:SI 0 "nonimmediate_operand" "")
- + (and:SI (match_operand:SI 1 "nonimmediate_operand" "")
- + (match_operand:SI 2 "ubicom32_and_or_si3_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + ""
- + "{
- + do
- + {
- + /* Is this a bfextu? */
- + if (ubicom32_data_register_operand (operands[0], SImode)
- + && CONST_INT_P (operands[2])
- + && exact_log2 (INTVAL (operands[2]) + 1) != -1)
- + break;
- +
- + /* Is this a bclr? */
- + if (CONST_INT_P (operands[2])
- + && exact_log2 (~INTVAL (operands[2])) != -1)
- + break;
- +
- + /* Must be an and.4 */
- + if (!ubicom32_data_register_operand (operands[1], SImode))
- + operands[1] = copy_to_mode_reg (SImode, operands[1]);
- +
- + if (!ubicom32_arith_operand (operands[2], SImode))
- + operands[2] = copy_to_mode_reg (SImode, operands[2]);
- + }
- + while (0);
- + }")
- +
- +(define_insn "andsi3_bfextu"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (and:SI (match_operand:SI 1 "nonimmediate_operand" "%rm")
- + (match_operand:SI 2 "const_int_operand" "O")))
- + (clobber (reg:CC CC_REGNO))]
- + "(satisfies_constraint_O (operands[2]))"
- + "*
- + {
- + operands[3] = GEN_INT (exact_log2 (INTVAL (operands[2]) + 1));
- +
- + return \"bfextu\\t%0, %1, %3\";
- + }")
- +
- +(define_insn "andsi3_bfextu_ccwz"
- + [(set (reg CC_REGNO)
- + (compare
- + (and:SI (match_operand:SI 1 "nonimmediate_operand" "%rm")
- + (match_operand:SI 2 "const_int_operand" "O"))
- + (const_int 0)))
- + (set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (and:SI (match_dup 1)
- + (match_dup 2)))]
- + "(satisfies_constraint_O (operands[2])
- + && ubicom32_match_cc_mode(insn, CCWZmode))"
- + "*
- + {
- + operands[3] = GEN_INT (exact_log2 (INTVAL (operands[2]) + 1));
- +
- + return \"bfextu\\t%0, %1, %3\";
- + }")
- +
- +(define_insn "andsi3_bfextu_ccwz_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm")
- + (match_operand:SI 1 "const_int_operand" "O"))
- + (const_int 0)))
- + (clobber (match_scratch:SI 2 "=d"))]
- + "(satisfies_constraint_O (operands[1])
- + && ubicom32_match_cc_mode(insn, CCWZmode))"
- + "*
- + {
- + operands[3] = GEN_INT (exact_log2 (INTVAL (operands[1]) + 1));
- +
- + return \"bfextu\\t%2, %0, %3\";
- + }")
- +
- +(define_insn "andsi3_bclr"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- + (and:SI (match_operand:SI 1 "ubicom32_arith_operand" "%rmI")
- + (match_operand:SI 2 "const_int_operand" "n")))
- + (clobber (reg:CC CC_REGNO))]
- + "(exact_log2 (~INTVAL (operands[2])) != -1)"
- + "bclr\\t%0, %1, #%D2")
- +
- +(define_insn "andsi3_and4"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
- + (and:SI (match_operand:SI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "@
- + and.4\\t%0, %2, %1
- + and.4\\t%0, %1, %2")
- +
- +(define_insn "andsi3_and4_ccwzn"
- + [(set (reg CC_REGNO)
- + (compare
- + (and:SI (match_operand:SI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))
- + (set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
- + (and:SI (match_dup 1)
- + (match_dup 2)))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "@
- + and.4\\t%0, %2, %1
- + and.4\\t%0, %1, %2")
- +
- +(define_insn "andsi3_and4_ccwzn_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (and:SI (match_operand:SI 0 "nonimmediate_operand" "%d,rm")
- + (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "@
- + and.4\\t#0, %1, %0
- + and.4\\t#0, %0, %1")
- +
- +(define_insn "andsi3_lsr4_ccwz_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (and:SI (match_operand:SI 0 "nonimmediate_operand" "%rm")
- + (match_operand:SI 1 "const_int_operand" "n"))
- + (const_int 0)))
- + (clobber (match_scratch:SI 2 "=d"))]
- + "(exact_log2 ((~(INTVAL (operands[1]))) + 1) != -1
- + && ubicom32_match_cc_mode(insn, CCWZmode))"
- + "*
- + {
- + operands[3] = GEN_INT (exact_log2 ((~(INTVAL (operands[1]))) + 1));
- +
- + return \"lsr.4\\t%2, %0, %3\";
- + }")
- +
- +; We really would like the combiner to recognize this scenario and deal with
- +; it but unfortunately it tries to canonicalize zero_extract ops on MEMs
- +; into QImode operations and we can't match them in any useful way.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "register_operand" "")
- + (match_operand:SI 1 "const_int_operand" ""))
- + (set (reg:CCWZ CC_REGNO)
- + (compare:CCWZ
- + (and:SI (match_operand:SI 2 "nonimmediate_operand" "")
- + (match_dup 0))
- + (const_int 0)))]
- + "(exact_log2 (INTVAL (operands[1])) != -1
- + && peep2_reg_dead_p (2, operands[0]))"
- + [(set (reg:CCWZ CC_REGNO)
- + (compare:CCWZ
- + (zero_extract:SI
- + (match_dup 2)
- + (const_int 1)
- + (match_dup 3))
- + (const_int 0)))]
- + "{
- + operands[3] = GEN_INT (exact_log2 (INTVAL (operands[1])));
- + }")
- +
- +(define_expand "anddi3"
- + [(parallel
- + [(set (match_operand:DI 0 "nonimmediate_operand" "")
- + (and:DI (match_operand:DI 1 "nonimmediate_operand" "")
- + (match_operand:DI 2 "ubicom32_arith_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + ""
- + "{
- + /* If we have a non-data reg for operand 1 then prefer that over
- + a CONST_INT in operand 2. */
- + if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
- + && CONST_INT_P (operands[2]))
- + operands[2] = copy_to_mode_reg (DImode, operands[2]);
- +
- + if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
- + operands[2] = copy_to_mode_reg (DImode, operands[2]);
- + }")
- +
- +(define_insn_and_split "anddi3_and4"
- + [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,&r, d,rm, m, m")
- + (and:DI (match_operand:DI 1 "nonimmediate_operand" "%d,rm, 0, 0, d,rm")
- + (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "#"
- + "reload_completed"
- + [(parallel [(set (match_dup 3)
- + (and:SI (match_dup 4)
- + (match_dup 5)))
- + (clobber (reg:CC CC_REGNO))])
- + (parallel [(set (match_dup 6)
- + (and:SI (match_dup 7)
- + (match_dup 8)))
- + (clobber (reg:CC CC_REGNO))])]
- + "{
- + operands[3] = gen_lowpart (SImode, operands[0]);
- + operands[4] = gen_lowpart (SImode, operands[1]);
- + operands[5] = gen_lowpart (SImode, operands[2]);
- + operands[6] = gen_highpart (SImode, operands[0]);
- + operands[7] = gen_highpart (SImode, operands[1]);
- + operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
- + }"
- + [(set_attr "length" "8")])
- +
- +(define_expand "iorqi3"
- + [(parallel
- + [(set (match_operand:QI 0 "memory_operand" "")
- + (ior:QI (match_operand:QI 1 "nonimmediate_operand" "")
- + (match_operand:QI 2 "ubicom32_arith_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + "(ubicom32_v4)"
- + "{
- + if (!memory_operand (operands[0], QImode))
- + FAIL;
- +
- + /* If we have a non-data reg for operand 1 then prefer that over
- + a CONST_INT in operand 2. */
- + if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
- + && CONST_INT_P (operands[2]))
- + operands[2] = copy_to_mode_reg (QImode, operands[2]);
- +
- + if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
- + operands[2] = copy_to_mode_reg (QImode, operands[2]);
- + }")
- +
- +(define_insn "iorqi3_or1"
- + [(set (match_operand:QI 0 "memory_operand" "=m, m")
- + (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4)"
- + "@
- + or.1\\t%0, %2, %1
- + or.1\\t%0, %1, %2")
- +
- +(define_expand "iorhi3"
- + [(parallel
- + [(set (match_operand:HI 0 "memory_operand" "")
- + (ior:HI (match_operand:HI 1 "nonimmediate_operand" "")
- + (match_operand:HI 2 "ubicom32_arith_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + ""
- + "{
- + if (!memory_operand (operands[0], HImode))
- + FAIL;
- +
- + /* If we have a non-data reg for operand 1 then prefer that over
- + a CONST_INT in operand 2. */
- + if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
- + && CONST_INT_P (operands[2]))
- + operands[2] = copy_to_mode_reg (HImode, operands[2]);
- +
- + if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
- + operands[2] = copy_to_mode_reg (HImode, operands[2]);
- + }")
- +
- +(define_insn "iorhi3_or2"
- + [(set (match_operand:HI 0 "memory_operand" "=m, m")
- + (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "@
- + or.2\\t%0, %2, %1
- + or.2\\t%0, %1, %2")
- +
- +(define_expand "iorsi3"
- + [(parallel
- + [(set (match_operand:SI 0 "nonimmediate_operand" "")
- + (ior:SI (match_operand:SI 1 "nonimmediate_operand" "")
- + (match_operand:SI 2 "ubicom32_and_or_si3_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + ""
- + "{
- + do
- + {
- + /* Is this a bset? */
- + if (CONST_INT_P (operands[2])
- + && exact_log2 (INTVAL (operands[2])) != -1)
- + break;
- +
- + /* Must be an or.4 */
- + if (!ubicom32_data_register_operand (operands[1], SImode))
- + operands[1] = copy_to_mode_reg (SImode, operands[1]);
- +
- + if (!ubicom32_arith_operand (operands[2], SImode))
- + operands[2] = copy_to_mode_reg (SImode, operands[2]);
- + }
- + while (0);
- + }")
- +
- +(define_insn "iorsi3_bset"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- + (ior:SI (match_operand:SI 1 "ubicom32_arith_operand" "%rmI")
- + (match_operand 2 "const_int_operand" "n")))
- + (clobber (reg:CC CC_REGNO))]
- + "(exact_log2 (INTVAL (operands[2])) != -1)"
- + "bset\\t%0, %1, #%d2")
- +
- +(define_insn "iorsi3_or4"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
- + (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "@
- + or.4\\t%0, %2, %1
- + or.4\\t%0, %1, %2")
- +
- +(define_insn "iorsi3_ccwzn"
- + [(set (reg CC_REGNO)
- + (compare
- + (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))
- + (set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
- + (ior:SI (match_dup 1)
- + (match_dup 2)))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "@
- + or.4\\t%0, %2, %1
- + or.4\\t%0, %1, %2")
- +
- +(define_insn "iorsi3_ccwzn_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (ior:SI (match_operand:SI 0 "nonimmediate_operand" "%d,rm")
- + (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "@
- + or.4\\t#0, %1, %0
- + or.4\\t#0, %0, %1")
- +
- +(define_expand "iordi3"
- + [(parallel
- + [(set (match_operand:DI 0 "nonimmediate_operand" "")
- + (ior:DI (match_operand:DI 1 "nonimmediate_operand" "")
- + (match_operand:DI 2 "ubicom32_arith_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + ""
- + "{
- + /* If we have a non-data reg for operand 1 then prefer that over
- + a CONST_INT in operand 2. */
- + if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
- + && CONST_INT_P (operands[2]))
- + operands[2] = copy_to_mode_reg (DImode, operands[2]);
- +
- + if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
- + operands[2] = copy_to_mode_reg (DImode, operands[2]);
- + }")
- +
- +(define_insn_and_split "iordi3_or4"
- + [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,&r, d,rm, m, m")
- + (ior:DI (match_operand:DI 1 "nonimmediate_operand" "%d,rm, 0, 0, d,rm")
- + (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "#"
- + "reload_completed"
- + [(parallel [(set (match_dup 3)
- + (ior:SI (match_dup 4)
- + (match_dup 5)))
- + (clobber (reg:CC CC_REGNO))])
- + (parallel [(set (match_dup 6)
- + (ior:SI (match_dup 7)
- + (match_dup 8)))
- + (clobber (reg:CC CC_REGNO))])]
- + "{
- + operands[3] = gen_lowpart (SImode, operands[0]);
- + operands[4] = gen_lowpart (SImode, operands[1]);
- + operands[5] = gen_lowpart (SImode, operands[2]);
- + operands[6] = gen_highpart (SImode, operands[0]);
- + operands[7] = gen_highpart (SImode, operands[1]);
- + operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
- + }"
- + [(set_attr "length" "8")])
- +
- +(define_expand "xorqi3"
- + [(parallel
- + [(set (match_operand:QI 0 "memory_operand" "")
- + (xor:QI (match_operand:QI 1 "nonimmediate_operand" "")
- + (match_operand:QI 2 "ubicom32_arith_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + "(ubicom32_v4)"
- + "{
- + if (!memory_operand (operands[0], QImode))
- + FAIL;
- +
- + /* If we have a non-data reg for operand 1 then prefer that over
- + a CONST_INT in operand 2. */
- + if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
- + && CONST_INT_P (operands[2]))
- + operands[2] = copy_to_mode_reg (QImode, operands[2]);
- +
- + if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
- + operands[2] = copy_to_mode_reg (QImode, operands[2]);
- + }")
- +
- +(define_insn "xorqi3_xor1"
- + [(set (match_operand:QI 0 "memory_operand" "=m, m")
- + (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4)"
- + "@
- + xor.1\\t%0, %2, %1
- + xor.1\\t%0, %1, %2")
- +
- +(define_insn "xorqi3_xor1_ccszn"
- + [(set (reg CC_REGNO)
- + (compare
- + (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:QI 2 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))
- + (set (match_operand:QI 0 "memory_operand" "=m, m")
- + (xor:QI (match_dup 1)
- + (match_dup 2)))]
- + "(ubicom32_v4
- + && ubicom32_match_cc_mode(insn, CCSZNmode))"
- + "@
- + xor.1\\t%0, %2, %1
- + xor.1\\t%0, %1, %2")
- +
- +(define_insn "xorqi3_xor1_ccszn_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (xor:QI (match_operand:QI 0 "nonimmediate_operand" "%d,rm")
- + (match_operand:QI 1 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))]
- + "(ubicom32_v4
- + && ubicom32_match_cc_mode(insn, CCSZNmode))"
- + "@
- + xor.1\\t#0, %1, %0
- + xor.1\\t#0, %0, %1")
- +
- +(define_insn "xor1_ccszn_null_1"
- + [(set (reg CC_REGNO)
- + (compare
- + (subreg:QI
- + (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
- + (match_operand:SI 1 "ubicom32_arith_operand" "rI"))
- + 3)
- + (const_int 0)))]
- + "(ubicom32_v4
- + && ubicom32_match_cc_mode(insn, CCSZNmode))"
- + "xor.1\\t#0, %1, %0")
- +
- +(define_insn "xor1_ccszn_null_2"
- + [(set (reg CC_REGNO)
- + (compare
- + (subreg:QI
- + (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
- + (subreg:SI
- + (match_operand:QI 1 "memory_operand" "m")
- + 0))
- + 3)
- + (const_int 0)))]
- + "(ubicom32_v4
- + && ubicom32_match_cc_mode(insn, CCSZNmode))"
- + "xor.1\\t#0, %1, %0")
- +
- +(define_insn "xor1_ccwzn_null_3"
- + [(set (reg CC_REGNO)
- + (compare
- + (subreg:QI
- + (xor:SI (subreg:SI
- + (match_operand:QI 0 "memory_operand" "m")
- + 0)
- + (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
- + 3)
- + (const_int 0)))]
- + "(ubicom32_v4
- + && ubicom32_match_cc_mode(insn, CCSZNmode))"
- + "xor.1\\t#0, %0, %1")
- +
- +(define_expand "xorhi3"
- + [(parallel
- + [(set (match_operand:HI 0 "memory_operand" "")
- + (xor:HI (match_operand:HI 1 "nonimmediate_operand" "")
- + (match_operand:HI 2 "ubicom32_arith_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + ""
- + "{
- + if (!memory_operand (operands[0], HImode))
- + FAIL;
- +
- + /* If we have a non-data reg for operand 1 then prefer that over
- + a CONST_INT in operand 2. */
- + if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
- + && CONST_INT_P (operands[2]))
- + operands[2] = copy_to_mode_reg (HImode, operands[2]);
- +
- + if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
- + operands[2] = copy_to_mode_reg (HImode, operands[2]);
- + }")
- +
- +(define_insn "xorhi3_xor2"
- + [(set (match_operand:HI 0 "memory_operand" "=m, m")
- + (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "@
- + xor.2\\t%0, %2, %1
- + xor.2\\t%0, %1, %2")
- +
- +(define_insn "xorhi3_xor2_ccszn"
- + [(set (reg CC_REGNO)
- + (compare
- + (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:HI 2 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))
- + (set (match_operand:HI 0 "memory_operand" "=m, m")
- + (xor:HI (match_dup 1)
- + (match_dup 2)))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "@
- + xor.2\\t%0, %2, %1
- + xor.2\\t%0, %1, %2")
- +
- +(define_insn "xorhi3_xor2_ccszn_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (xor:HI (match_operand:HI 0 "nonimmediate_operand" "%d,rm")
- + (match_operand:HI 1 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "@
- + xor.2\\t#0, %1, %0
- + xor.2\\t#0, %0, %1")
- +
- +(define_insn "xor2_ccszn_null_1"
- + [(set (reg CC_REGNO)
- + (compare
- + (subreg:HI
- + (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "%d")
- + (match_operand:SI 1 "ubicom32_arith_operand" "rI"))
- + 2)
- + (const_int 0)))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "xor.2\\t#0, %1, %0")
- +
- +(define_insn "xor2_ccszn_null_2"
- + [(set (reg CC_REGNO)
- + (compare
- + (subreg:HI
- + (xor:SI (match_operand:SI 0 "ubicom32_data_register_operand" "d")
- + (subreg:SI
- + (match_operand:HI 1 "memory_operand" "m")
- + 0))
- + 2)
- + (const_int 0)))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "xor.2\\t#0, %1, %0")
- +
- +(define_insn "xor2_ccszn_null_3"
- + [(set (reg CC_REGNO)
- + (compare
- + (subreg:HI
- + (xor:SI (subreg:SI
- + (match_operand:HI 0 "memory_operand" "m")
- + 0)
- + (match_operand:SI 1 "ubicom32_data_register_operand" "d"))
- + 2)
- + (const_int 0)))]
- + "ubicom32_match_cc_mode(insn, CCSZNmode)"
- + "xor.2\\t#0, %0, %1")
- +
- +(define_insn "xorsi3"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
- + (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "@
- + xor.4\\t%0, %2, %1
- + xor.4\\t%0, %1, %2")
- +
- +(define_insn "xorsi3_ccwzn"
- + [(set (reg CC_REGNO)
- + (compare
- + (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%d,rm")
- + (match_operand:SI 2 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))
- + (set (match_operand:SI 0 "nonimmediate_operand" "=rm,rm")
- + (xor:SI (match_dup 1)
- + (match_dup 2)))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "@
- + xor.4\\t%0, %2, %1
- + xor.4\\t%0, %1, %2")
- +
- +(define_insn "xorsi3_ccwzn_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (xor:SI (match_operand:SI 0 "nonimmediate_operand" "%d,rm")
- + (match_operand:SI 1 "ubicom32_arith_operand" "rmI, d"))
- + (const_int 0)))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "@
- + xor.4\\t#0, %1, %0
- + xor.4\\t#0, %0, %1")
- +
- +(define_expand "xordi3"
- + [(parallel
- + [(set (match_operand:DI 0 "nonimmediate_operand" "")
- + (xor:DI (match_operand:DI 1 "nonimmediate_operand" "")
- + (match_operand:DI 2 "ubicom32_arith_operand" "")))
- + (clobber (reg:CC CC_REGNO))])]
- + ""
- + "{
- + /* If we have a non-data reg for operand 1 then prefer that over
- + a CONST_INT in operand 2. */
- + if (! ubicom32_data_register_operand (operands[1], GET_MODE (operands[1]))
- + && CONST_INT_P (operands[2]))
- + operands[2] = copy_to_mode_reg (DImode, operands[2]);
- +
- + if (CONST_INT_P (operands[2]) && ! satisfies_constraint_I (operands[2]))
- + operands[2] = copy_to_mode_reg (DImode, operands[2]);
- + }")
- +
- +(define_insn_and_split "xordi3_xor4"
- + [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,&r, d,rm, m, m")
- + (xor:DI (match_operand:DI 1 "nonimmediate_operand" "%d,rm, 0, 0, d,rm")
- + (match_operand:DI 2 "ubicom32_arith_operand" "rmI, d,rmI, d,rmI, d")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "#"
- + "reload_completed"
- + [(parallel [(set (match_dup 3)
- + (xor:SI (match_dup 4)
- + (match_dup 5)))
- + (clobber (reg:CC CC_REGNO))])
- + (parallel [(set (match_dup 6)
- + (xor:SI (match_dup 7)
- + (match_dup 8)))
- + (clobber (reg:CC CC_REGNO))])]
- + "{
- + operands[3] = gen_lowpart (SImode, operands[0]);
- + operands[4] = gen_lowpart (SImode, operands[1]);
- + operands[5] = gen_lowpart (SImode, operands[2]);
- + operands[6] = gen_highpart (SImode, operands[0]);
- + operands[7] = gen_highpart (SImode, operands[1]);
- + operands[8] = gen_highpart_mode (SImode, DImode, operands[2]);
- + }"
- + [(set_attr "length" "8")])
- +
- +(define_insn "not2_2"
- + [(set (match_operand:HI 0 "memory_operand" "=m")
- + (subreg:HI
- + (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI"))
- + 2))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "not.2\\t%0, %1")
- +
- +(define_insn "one_cmplsi2"
- + [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- + (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "not.4\\t%0, %1")
- +
- +(define_insn "one_cmplsi2_ccwzn"
- + [(set (reg CC_REGNO)
- + (compare
- + (not:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI"))
- + (const_int 0)))
- + (set (match_operand:SI 0 "nonimmediate_operand" "=rm")
- + (not:SI (match_dup 1)))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "not.4\\t%0, %1")
- +
- +(define_insn "one_cmplsi2_ccwzn_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (not:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI"))
- + (const_int 0)))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "not.4\\t#0, %0")
- +
- +(define_insn_and_split "one_cmpldi2"
- + [(set (match_operand:DI 0 "nonimmediate_operand" "=&rm")
- + (not:DI (match_operand:DI 1 "nonimmediate_operand" "rmI0")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "#"
- + ""
- + [(parallel [(set (match_dup 2)
- + (not:SI (match_dup 3)))
- + (clobber (reg:CC CC_REGNO))])
- + (parallel [(set (match_dup 4)
- + (not:SI (match_dup 5)))
- + (clobber (reg:CC CC_REGNO))])]
- + "{
- + operands[2] = gen_lowpart (SImode, operands[0]);
- + operands[3] = gen_lowpart (SImode, operands[1]);
- + operands[4] = gen_highpart (SImode, operands[0]);
- + operands[5] = gen_highpart (SImode, operands[1]);
- + }"
- + [(set_attr "length" "8")])
- +
- +; Conditional jump instructions
- +
- +(define_expand "beq"
- + [(set (pc)
- + (if_then_else (eq (match_dup 1)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- + "{
- + operands[1] = ubicom32_gen_compare_reg (EQ, ubicom32_compare_op0,
- + ubicom32_compare_op1);
- + }")
- +
- +(define_expand "bne"
- + [(set (pc)
- + (if_then_else (ne (match_dup 1)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- + "{
- + operands[1] = ubicom32_gen_compare_reg (NE, ubicom32_compare_op0,
- + ubicom32_compare_op1);
- + }")
- +
- +(define_expand "bgt"
- + [(set (pc)
- + (if_then_else (gt (match_dup 1)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- + "{
- + operands[1] = ubicom32_gen_compare_reg (GT, ubicom32_compare_op0,
- + ubicom32_compare_op1);
- + }")
- +
- +(define_expand "ble"
- + [(set (pc)
- + (if_then_else (le (match_dup 1)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- + "{
- + operands[1] = ubicom32_gen_compare_reg (LE, ubicom32_compare_op0,
- + ubicom32_compare_op1);
- + }")
- +
- +(define_expand "bge"
- + [(set (pc)
- + (if_then_else (ge (match_dup 1)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- + "{
- + operands[1] = ubicom32_gen_compare_reg (GE, ubicom32_compare_op0,
- + ubicom32_compare_op1);
- + }")
- +
- +(define_expand "blt"
- + [(set (pc)
- + (if_then_else (lt (match_dup 1)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- + "{
- + operands[1] = ubicom32_gen_compare_reg (LT, ubicom32_compare_op0,
- + ubicom32_compare_op1);
- + }")
- +
- +(define_expand "bgtu"
- + [(set (pc)
- + (if_then_else (gtu (match_dup 1)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- + "{
- + operands[1] = ubicom32_gen_compare_reg (GTU, ubicom32_compare_op0,
- + ubicom32_compare_op1);
- + }")
- +
- +(define_expand "bleu"
- + [(set (pc)
- + (if_then_else (leu (match_dup 1)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- + "{
- + operands[1] = ubicom32_gen_compare_reg (LEU, ubicom32_compare_op0,
- + ubicom32_compare_op1);
- + }")
- +
- +(define_expand "bgeu"
- + [(set (pc)
- + (if_then_else (geu (match_dup 1)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- + "{
- + operands[1] = ubicom32_gen_compare_reg (GEU, ubicom32_compare_op0,
- + ubicom32_compare_op1);
- + }")
- +
- +(define_expand "bltu"
- + [(set (pc)
- + (if_then_else (ltu (match_dup 1)
- + (const_int 0))
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- + "{
- + operands[1] = ubicom32_gen_compare_reg (LTU, ubicom32_compare_op0,
- + ubicom32_compare_op1);
- + }")
- +
- +(define_insn "jcc"
- + [(set (pc)
- + (if_then_else (match_operator 1 "comparison_operator"
- + [(match_operand 2 "ubicom32_cc_register_operand" "")
- + (const_int 0)])
- + (label_ref (match_operand 0 "" ""))
- + (pc)))]
- + ""
- + "*
- + {
- + ubicom32_output_cond_jump (insn, operands[1], operands[0]);
- + return \"\";
- + }")
- +
- +; Reverse branch - reverse our comparison condition so that we can
- +; branch in the opposite sense.
- +;
- +(define_insn_and_split "jcc_reverse"
- + [(set (pc)
- + (if_then_else (match_operator 1 "comparison_operator"
- + [(match_operand 2 "ubicom32_cc_register_operand" "")
- + (const_int 0)])
- + (pc)
- + (label_ref (match_operand 0 "" ""))))]
- + ""
- + "#"
- + "reload_completed"
- + [(set (pc)
- + (if_then_else (match_dup 3)
- + (label_ref (match_dup 0))
- + (pc)))]
- + "{
- + rtx cc_reg;
- +
- + cc_reg = gen_rtx_REG (GET_MODE (operands[2]), CC_REGNO);
- + operands[3] = gen_rtx_fmt_ee (reverse_condition (GET_CODE (operands[1])),
- + GET_MODE (operands[1]),
- + cc_reg,
- + const0_rtx);
- + }")
- +
- +(define_insn "jump"
- + [(set (pc)
- + (label_ref (match_operand 0 "" "")))]
- + ""
- + "jmpt\\t%l0")
- +
- +(define_expand "indirect_jump"
- + [(parallel [(set (pc)
- + (match_operand:SI 0 "register_operand" ""))
- + (clobber (match_dup 0))])]
- + ""
- + "")
- +
- +(define_insn "indirect_jump_internal"
- + [(set (pc)
- + (match_operand:SI 0 "register_operand" "a"))
- + (clobber (match_dup 0))]
- + ""
- + "calli\\t%0,0(%0)")
- +
- +; Program Space: The table contains instructions, typically jumps.
- +; CALL An,TABLE_SIZE(PC) ;An = Jump Table Base Address.
- +; <Jump Table is Here> ;An -> Here.
- +; LEA Ak, (An,Dn) ;Ak -> Table Entry
- +; JMP/CALL (Ak)
- +
- +(define_expand "tablejump"
- + [(parallel [(set (pc)
- + (match_operand:SI 0 "nonimmediate_operand" ""))
- + (use (label_ref (match_operand 1 "" "")))])]
- + ""
- + "")
- +
- +(define_insn "tablejump_internal"
- + [(set (pc)
- + (match_operand:SI 0 "nonimmediate_operand" "rm"))
- + (use (label_ref (match_operand 1 "" "")))]
- + ""
- + "ret\\t%0")
- +
- +; Call subroutine with no return value.
- +;
- +(define_expand "call"
- + [(call (match_operand:QI 0 "general_operand" "")
- + (match_operand:SI 1 "general_operand" ""))]
- + ""
- + "{
- + if (TARGET_FDPIC)
- + {
- + ubicom32_expand_call_fdpic (operands);
- + DONE;
- + }
- +
- + if (! ubicom32_call_address_operand (XEXP (operands[0], 0), VOIDmode))
- + XEXP (operands[0], 0) = force_reg (SImode, XEXP (operands[0], 0));
- + }")
- +
- +; We expand to a simple form that doesn't clobber the link register and
- +; then split to a form that does. This allows the RTL optimizers that
- +; run before the splitter to have the opportunity to eliminate the call
- +; without marking A5 as being clobbered and this in turn avoids saves
- +; and returns in a number of cases.
- +;
- +(define_insn_and_split "call_1"
- + [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
- + (match_operand:SI 1 "general_operand" "g,g"))]
- + "! TARGET_FDPIC"
- + "#"
- + ""
- + [(parallel
- + [(call (mem:QI (match_dup 0))
- + (match_dup 1))
- + (clobber (reg:SI LINK_REGNO))])]
- + "")
- +
- +(define_insn "call_slow"
- + [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
- + (match_operand:SI 1 "general_operand" "g,g"))
- + (clobber (reg:SI LINK_REGNO))]
- + "(! TARGET_FDPIC && ! TARGET_FASTCALL)"
- + "@
- + calli\\ta5, 0(%0)
- + moveai\\ta5, #%%hi(%C0)\;calli\\ta5, %%lo(%C0)(a5)")
- +
- +(define_insn "call_fast"
- + [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
- + (match_operand:SI 1 "general_operand" "g,g"))
- + (clobber (reg:SI LINK_REGNO))]
- + "(! TARGET_FDPIC && TARGET_FASTCALL)"
- + "@
- + calli\\ta5, 0(%0)
- + call\\ta5, %C0")
- +
- +; We expand to a simple form that doesn't clobber the link register and
- +; then split to a form that does. This allows the RTL optimizers that
- +; run before the splitter to have the opportunity to eliminate the call
- +; without marking A5 as being clobbered and this in turn avoids saves
- +; and returns in a number of cases.
- +;
- +(define_insn_and_split "call_fdpic"
- + [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
- + (match_operand:SI 1 "general_operand" "g,g"))
- + (use (match_operand:SI 2 "ubicom32_fdpic_operand" "Z,Z"))]
- + "TARGET_FDPIC"
- + "#"
- + ""
- + [(parallel
- + [(call (mem:QI (match_dup 0))
- + (match_dup 1))
- + (use (match_dup 2))
- + (clobber (reg:SI LINK_REGNO))])]
- + "")
- +
- +(define_insn "call_fdpic_clobber"
- + [(call (mem:QI (match_operand:SI 0 "ubicom32_call_address_operand" "a,S"))
- + (match_operand:SI 1 "general_operand" "g,g"))
- + (use (match_operand:SI 2 "ubicom32_fdpic_operand" "Z,Z"))
- + (clobber (reg:SI LINK_REGNO))]
- + "TARGET_FDPIC"
- + "@
- + move.4\\ta5, 0(%0)\;move.4\\t%2, 4(%0)\;calli\\ta5, 0(a5)
- + call\\ta5, %C0")
- +
- +; Call subroutine, returning value in operand 0
- +; (which must be a hard register).
- +;
- +(define_expand "call_value"
- + [(set (match_operand 0 "" "")
- + (call (match_operand:QI 1 "general_operand" "")
- + (match_operand:SI 2 "general_operand" "")))]
- + ""
- + "{
- + if (TARGET_FDPIC)
- + {
- + ubicom32_expand_call_value_fdpic (operands);
- + DONE;
- + }
- +
- + if (! ubicom32_call_address_operand (XEXP (operands[1], 0), VOIDmode))
- + XEXP (operands[1], 0) = force_reg (SImode, XEXP (operands[1], 0));
- + }")
- +
- +; We expand to a simple form that doesn't clobber the link register and
- +; then split to a form that does. This allows the RTL optimizers that
- +; run before the splitter to have the opportunity to eliminate the call
- +; without marking A5 as being clobbered and this in turn avoids saves
- +; and returns in a number of cases.
- +;
- +(define_insn_and_split "call_value_1"
- + [(set (match_operand 0 "register_operand" "=r,r")
- + (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
- + (match_operand:SI 2 "general_operand" "g,g")))]
- + "! TARGET_FDPIC"
- + "#"
- + ""
- + [(parallel
- + [(set (match_dup 0)
- + (call (mem:QI (match_dup 1))
- + (match_dup 2)))
- + (clobber (reg:SI LINK_REGNO))])]
- + "")
- +
- +(define_insn "call_value_slow"
- + [(set (match_operand 0 "register_operand" "=r,r")
- + (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
- + (match_operand:SI 2 "general_operand" "g,g")))
- + (clobber (reg:SI LINK_REGNO))]
- + "(! TARGET_FDPIC && ! TARGET_FASTCALL)"
- + "@
- + calli\\ta5, 0(%1)
- + moveai\\ta5, #%%hi(%C1)\;calli\\ta5, %%lo(%C1)(a5)")
- +
- +(define_insn "call_value_fast"
- + [(set (match_operand 0 "register_operand" "=r,r")
- + (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
- + (match_operand:SI 2 "general_operand" "g,g")))
- + (clobber (reg:SI LINK_REGNO))]
- + "(! TARGET_FDPIC && TARGET_FASTCALL)"
- + "@
- + calli\\ta5, 0(%1)
- + call\\ta5, %C1")
- +
- +; We expand to a simple form that doesn't clobber the link register and
- +; then split to a form that does. This allows the RTL optimizers that
- +; run before the splitter to have the opportunity to eliminate the call
- +; without marking A5 as being clobbered and this in turn avoids saves
- +; and returns in a number of cases.
- +;
- +(define_insn_and_split "call_value_fdpic"
- + [(set (match_operand 0 "register_operand" "=r,r")
- + (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
- + (match_operand:SI 2 "general_operand" "g,g")))
- + (use (match_operand:SI 3 "ubicom32_fdpic_operand" "Z,Z"))]
- + "TARGET_FDPIC"
- + "#"
- + ""
- + [(parallel
- + [(set (match_dup 0)
- + (call (mem:QI (match_dup 1))
- + (match_dup 2)))
- + (use (match_dup 3))
- + (clobber (reg:SI LINK_REGNO))])]
- + "")
- +
- +(define_insn "call_value_fdpic_clobber"
- + [(set (match_operand 0 "register_operand" "=r,r")
- + (call (mem:QI (match_operand:SI 1 "ubicom32_call_address_operand" "a,S"))
- + (match_operand:SI 2 "general_operand" "g,g")))
- + (use (match_operand:SI 3 "ubicom32_fdpic_operand" "Z,Z"))
- + (clobber (reg:SI LINK_REGNO))]
- + "TARGET_FDPIC"
- + "@
- + move.4\\ta5, 0(%1)\;move.4\\t%3, 4(%1)\;calli\\ta5, 0(a5)
- + call\\ta5, %C1")
- +
- +(define_expand "untyped_call"
- + [(parallel [(call (match_operand 0 "" "")
- + (const_int 0))
- + (match_operand 1 "" "")
- + (match_operand 2 "" "")])]
- + ""
- + "{
- + int i;
- +
- + emit_call_insn (gen_call (operands[0], const0_rtx));
- +
- + for (i = 0; i < XVECLEN (operands[2], 0); i++)
- + {
- + rtx set = XVECEXP (operands[2], 0, i);
- + emit_move_insn (SET_DEST (set), SET_SRC (set));
- + }
- + DONE;
- + }")
- +
- +(define_insn "lsl1_1"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (ashift:SI (subreg:SI
- + (match_operand:QI 1 "memory_operand" "m")
- + 0)
- + (match_operand:SI 2 "ubicom32_arith_operand" "dM")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4)"
- + "lsl.1\\t%0, %1, %2")
- +
- +; The combiner gets rather creative about left shifts of sub-word memory
- +; operands because it's uncertain about whether the memory is sign or
- +; zero extended. It only wants zero-extended behaviour and so throws
- +; in an extra and operation.
- +;
- +(define_insn "lsl1_2"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (and:SI
- + (ashift:SI (subreg:SI
- + (match_operand:QI 1 "memory_operand" "m")
- + 0)
- + (match_operand:SI 2 "const_int_operand" "M"))
- + (match_operand:SI 3 "const_int_operand" "n")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4
- + && INTVAL (operands[3]) == (0xff << INTVAL (operands[2])))"
- + "lsl.1\\t%0, %1, %2")
- +
- +(define_insn "lsl2_1"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (ashift:SI (subreg:SI
- + (match_operand:HI 1 "memory_operand" "m")
- + 0)
- + (match_operand:SI 2 "ubicom32_arith_operand" "dM")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4)"
- + "lsl.2\\t%0, %1, %2")
- +
- +; The combiner gets rather creative about left shifts of sub-word memory
- +; operands because it's uncertain about whether the memory is sign or
- +; zero extended. It only wants zero-extended behaviour and so throws
- +; in an extra and operation.
- +;
- +(define_insn "lsl2_2"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (and:SI
- + (ashift:SI (subreg:SI
- + (match_operand:HI 1 "memory_operand" "m")
- + 0)
- + (match_operand:SI 2 "const_int_operand" "M"))
- + (match_operand:SI 3 "const_int_operand" "n")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4
- + && INTVAL (operands[3]) == (0xffff << INTVAL (operands[2])))"
- + "lsl.2\\t%0, %1, %2")
- +
- +(define_insn "ashlsi3"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (ashift:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
- + (match_operand:SI 2 "ubicom32_arith_operand" "dM")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "lsl.4\\t%0, %1, %2")
- +
- +(define_insn "lshlsi3_ccwz"
- + [(set (reg CC_REGNO)
- + (compare
- + (ashift:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
- + (match_operand:SI 2 "ubicom32_arith_operand" "dM"))
- + (const_int 0)))
- + (set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (ashift:SI (match_dup 1)
- + (match_dup 2)))]
- + "ubicom32_match_cc_mode(insn, CCWZmode)"
- + "lsl.4\\t%0, %1, %2")
- +
- +(define_insn "lshlsi3_ccwz_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (ashift:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI")
- + (match_operand:SI 1 "ubicom32_arith_operand" "dM"))
- + (const_int 0)))
- + (clobber (match_scratch:SI 2 "=d"))]
- + "ubicom32_match_cc_mode(insn, CCWZmode)"
- + "lsl.4\\t%2, %0, %1")
- +
- +; The combiner finds this canonical form for what is in essence a right
- +; shift.
- +;
- +(define_insn "asr1_2"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (sign_extract:SI (match_operand:QI 1 "memory_operand" "m")
- + (match_operand:SI 2 "const_int_operand" "M")
- + (match_operand:SI 3 "const_int_operand" "M")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4
- + && (INTVAL (operands[2]) + INTVAL (operands[3]) == 8))"
- + "asr.1\\t%0, %1, %3")
- +
- +; The combiner finds this canonical form for what is in essence a right
- +; shift.
- +;
- +(define_insn "asr2_2"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (sign_extract:SI (match_operand:HI 1 "memory_operand" "m")
- + (match_operand:SI 2 "const_int_operand" "M")
- + (match_operand:SI 3 "const_int_operand" "M")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4
- + && (INTVAL (operands[2]) + INTVAL (operands[3]) == 16))"
- + "asr.2\\t%0, %1, %3")
- +
- +(define_insn "ashrsi3"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (ashiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmJ")
- + (match_operand:SI 2 "ubicom32_arith_operand" "dM")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "asr.4\\t%0, %1, %2")
- +
- +(define_insn "ashrsi3_ccwzn"
- + [(set (reg CC_REGNO)
- + (compare
- + (ashiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmJ")
- + (match_operand:SI 2 "ubicom32_arith_operand" "dM"))
- + (const_int 0)))
- + (set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (ashiftrt:SI (match_dup 1)
- + (match_dup 2)))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "asr.4\\t%0, %1, %2")
- +
- +(define_insn "ashrsi3_ccwzn_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (ashiftrt:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmJ")
- + (match_operand:SI 1 "ubicom32_arith_operand" "dM"))
- + (const_int 0)))
- + (clobber (match_scratch:SI 2 "=d"))]
- + "ubicom32_match_cc_mode(insn, CCWZNmode)"
- + "asr.4\\t%2, %0, %1")
- +
- +(define_insn "lsr1_1"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (lshiftrt:SI (subreg:SI
- + (match_operand:QI 1 "memory_operand" "m")
- + 0)
- + (match_operand:SI 2 "ubicom32_arith_operand" "dM")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4)"
- + "lsr.1\\t%0, %1, %2")
- +
- +; The combiner finds this canonical form for what is in essence a right
- +; shift.
- +;
- +(define_insn "lsr1_2"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (zero_extract:SI (match_operand:QI 1 "memory_operand" "m")
- + (match_operand:SI 2 "const_int_operand" "M")
- + (match_operand:SI 3 "const_int_operand" "M")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4
- + && (INTVAL (operands[2]) + INTVAL (operands[3]) == 8))"
- + "lsr.1\\t%0, %1, %3")
- +
- +(define_insn "lsr2_1"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (lshiftrt:SI (subreg:SI
- + (match_operand:HI 1 "memory_operand" "m")
- + 0)
- + (match_operand:SI 2 "ubicom32_arith_operand" "dM")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4)"
- + "lsr.2\\t%0, %1, %2")
- +
- +; The combiner finds this canonical form for what is in essence a right
- +; shift.
- +;
- +(define_insn "lsr2_2"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (zero_extract:SI (match_operand:HI 1 "memory_operand" "m")
- + (match_operand:SI 2 "const_int_operand" "M")
- + (match_operand:SI 3 "const_int_operand" "M")))
- + (clobber (reg:CC CC_REGNO))]
- + "(ubicom32_v4
- + && (INTVAL (operands[2]) + INTVAL (operands[3]) == 16))"
- + "lsr.2\\t%0, %1, %3")
- +
- +(define_insn "lshrsi3"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (lshiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
- + (match_operand:SI 2 "ubicom32_arith_operand" "dM")))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "lsr.4\\t%0, %1, %2")
- +
- +(define_insn "lshrsi3_ccwz"
- + [(set (reg CC_REGNO)
- + (compare
- + (lshiftrt:SI (match_operand:SI 1 "ubicom32_arith_operand" "rmI")
- + (match_operand:SI 2 "ubicom32_arith_operand" "dM"))
- + (const_int 0)))
- + (set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (lshiftrt:SI (match_dup 1)
- + (match_dup 2)))]
- + "ubicom32_match_cc_mode(insn, CCWZmode)"
- + "lsr.4\\t%0, %1, %2")
- +
- +(define_insn "lshrsi3_ccwz_null"
- + [(set (reg CC_REGNO)
- + (compare
- + (lshiftrt:SI (match_operand:SI 0 "ubicom32_arith_operand" "rmI")
- + (match_operand:SI 1 "ubicom32_arith_operand" "dM"))
- + (const_int 0)))
- + (clobber (match_scratch:SI 2 "=d"))]
- + "ubicom32_match_cc_mode(insn, CCWZmode)"
- + "lsr.4\\t%2, %0, %1")
- +
- +(define_expand "prologue"
- + [(const_int 0)]
- + ""
- + "{
- + ubicom32_expand_prologue ();
- + DONE;
- + }")
- +
- +(define_expand "epilogue"
- + [(return)]
- + ""
- + "{
- + ubicom32_expand_epilogue ();
- + DONE;
- + }")
- +
- +(define_expand "return"
- + [(return)]
- + ""
- + "{
- + ubicom32_expand_epilogue ();
- + DONE;
- + }")
- +
- +(define_expand "_eh_return"
- + [(use (match_operand:SI 0 "register_operand" "r"))
- + (use (match_operand:SI 1 "register_operand" "r"))]
- + ""
- + "{
- + ubicom32_expand_eh_return (operands);
- + DONE;
- + }")
- +
- +; XXX - it looks almost certain that we could make return_internal use a Dn
- +; register too. In that instance we'd have to use a ret instruction
- +; rather than a calli but it might save cycles.
- +;
- +(define_insn "return_internal"
- + [(const_int 2)
- + (return)
- + (use (match_operand:SI 0 "ubicom32_mem_or_address_register_operand" "rm"))]
- + ""
- + "*
- + {
- + if (REG_P (operands[0]) && REGNO (operands[0]) == LINK_REGNO
- + && ubicom32_can_use_calli_to_ret)
- + return \"calli\\t%0, 0(%0)\";
- +
- + return \"ret\\t%0\";
- + }")
- +
- +(define_insn "return_from_post_modify_sp"
- + [(parallel
- + [(const_int 2)
- + (return)
- + (use (mem:SI (post_modify:SI
- + (reg:SI SP_REGNO)
- + (plus:SI (reg:SI SP_REGNO)
- + (match_operand:SI 0 "const_int_operand" "n")))))])]
- + "INTVAL (operands[0]) >= 4 && INTVAL (operands[0]) <= 7 * 4"
- + "ret\\t(sp)%E0++")
- +
- +;(define_insn "eh_return_internal"
- +; [(const_int 4)
- +; (return)
- +; (use (reg:SI 34))]
- +; ""
- +; "ret\\ta2")
- +
- +; No operation, needed in case the user uses -g but not -O.
- +(define_expand "nop"
- + [(const_int 0)]
- + ""
- + "")
- +
- +(define_insn "nop_internal"
- + [(const_int 0)]
- + ""
- + "nop")
- +
- +; The combiner will generate this pattern given shift and add operations.
- +; The canonical form that the combiner wants to use appears to be multiplies
- +; instead of shifts even if the compiled sources use shifts.
- +;
- +(define_insn "shmrg1_add"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (plus:SI
- + (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
- + (const_int 256))
- + (zero_extend:SI
- + (match_operand:QI 2 "ubicom32_arith_operand" "rmI"))))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "shmrg.1\\t%0, %2, %1")
- +
- +; The combiner will generate this pattern given shift and or operations.
- +;
- +(define_insn "shmrg1_ior"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (ior:SI
- + (ashift:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
- + (const_int 8))
- + (zero_extend:SI
- + (match_operand:QI 2 "ubicom32_arith_operand" "rmI"))))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "shmrg.1\\t%0, %2, %1")
- +
- +; The combiner will generate this pattern given shift and add operations.
- +; The canonical form that the combiner wants to use appears to be multiplies
- +; instead of shifts even if the compiled sources use shifts.
- +;
- +(define_insn "shmrg2_add"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (plus:SI
- + (mult:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
- + (const_int 65536))
- + (zero_extend:SI
- + (match_operand:HI 2 "ubicom32_arith_operand" "rmI"))))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "shmrg.2\\t%0, %2, %1")
- +
- +; The combiner will generate this pattern given shift and or operations.
- +;
- +(define_insn "shmrg2_ior"
- + [(set (match_operand:SI 0 "ubicom32_data_register_operand" "=d")
- + (ior:SI
- + (ashift:SI (match_operand:SI 1 "ubicom32_data_register_operand" "d")
- + (const_int 16))
- + (zero_extend:SI
- + (match_operand:HI 2 "ubicom32_arith_operand" "rmI"))))
- + (clobber (reg:CC CC_REGNO))]
- + ""
- + "shmrg.2\\t%0, %2, %1")
- +
- +; Match the case where we load a word from the stack but then discard the
- +; upper 16 bits. We turn this into a zero-extended load of that useful
- +; 16 bits direct from the stack where possible.
- +;
- +
- +; XXX - do these peephole2 ops actually work after the CCmode conversion?
- +(define_peephole2
- + [(set (match_operand:SI 0 "register_operand" "")
- + (mem:SI (plus:SI (reg:SI SP_REGNO)
- + (match_operand:SI 1 "const_int_operand" ""))))
- + (set (match_operand:SI 2 "nonimmediate_operand" "")
- + (zero_extend:SI (match_operand:HI 3 "register_operand" "")))]
- + "(INTVAL (operands[1]) <= 252
- + && REGNO (operands[3]) == REGNO (operands[0])
- + && ((peep2_reg_dead_p (2, operands[0])
- + && ! reg_mentioned_p (operands[0], operands[2]))
- + || rtx_equal_p (operands[0], operands[2])))"
- + [(set (match_dup 2)
- + (zero_extend:SI (mem:HI (plus:SI (reg:SI SP_REGNO)
- + (match_dup 4)))))]
- + "{
- + operands[4] = GEN_INT (INTVAL (operands[1]) + 2);
- + }")
- +
- +; Match the case where we load a word from the stack but then discard the
- +; upper 16 bits. We turn this into a 16-bit load of that useful
- +; 16 bits direct from the stack where possible.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "register_operand" "")
- + (mem:SI (plus:SI (reg:SI SP_REGNO)
- + (match_operand:SI 1 "const_int_operand" ""))))
- + (set (match_operand:HI 2 "nonimmediate_operand" "")
- + (match_operand:HI 3 "register_operand" ""))]
- + "(INTVAL (operands[1]) <= 252
- + && REGNO (operands[3]) == REGNO (operands[0])
- + && ((peep2_reg_dead_p (2, operands[0])
- + && ! reg_mentioned_p (operands[0], operands[2]))
- + || rtx_equal_p (operands[0], operands[2])))"
- + [(set (match_dup 2)
- + (mem:HI (plus:SI (reg:SI SP_REGNO)
- + (match_dup 4))))]
- + "{
- + operands[4] = GEN_INT (INTVAL (operands[1]) + 2);
- + }")
- +
- +; Match the case where we load a word from the stack but then discard the
- +; upper 24 bits. We turn this into a zero-extended load of that useful
- +; 8 bits direct from the stack where possible.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "register_operand" "")
- + (mem:SI (plus:SI (reg:SI SP_REGNO)
- + (match_operand:SI 1 "const_int_operand" ""))))
- + (set (match_operand:SI 2 "nonimmediate_operand" "")
- + (zero_extend:SI (match_operand:QI 3 "register_operand" "")))]
- + "(INTVAL (operands[1]) <= 124
- + && REGNO (operands[3]) == REGNO (operands[0])
- + && ((peep2_reg_dead_p (2, operands[0])
- + && ! reg_mentioned_p (operands[0], operands[2]))
- + || rtx_equal_p (operands[0], operands[2])))"
- + [(set (match_dup 2)
- + (zero_extend:SI (mem:QI (plus:SI (reg:SI SP_REGNO)
- + (match_dup 4)))))]
- + "{
- + operands[4] = GEN_INT (INTVAL (operands[1]) + 3);
- + }")
- +
- +; Match the case where we load a word from the stack but then discard the
- +; upper 24 bits. We turn this into an 8-bit load of that useful
- +; 8 bits direct from the stack where possible.
- +;
- +(define_peephole2
- + [(set (match_operand:SI 0 "register_operand" "")
- + (mem:SI (plus:SI (reg:SI SP_REGNO)
- + (match_operand:SI 1 "const_int_operand" ""))))
- + (set (match_operand:QI 2 "nonimmediate_operand" "")
- + (match_operand:QI 3 "register_operand" ""))]
- + "(INTVAL (operands[1]) <= 124
- + && REGNO (operands[3]) == REGNO (operands[0])
- + && ((peep2_reg_dead_p (2, operands[0])
- + && ! reg_mentioned_p (operands[0], operands[2]))
- + || rtx_equal_p (operands[0], operands[2])))"
- + [(set (match_dup 2)
- + (mem:QI (plus:SI (reg:SI SP_REGNO)
- + (match_dup 4))))]
- + "{
- + operands[4] = GEN_INT (INTVAL (operands[1]) + 3);
- + }")
- +
- --- /dev/null
- +++ b/gcc/config/ubicom32/ubicom32.opt
- @@ -0,0 +1,27 @@
- +mdebug-address
- +Target RejectNegative Report Undocumented Mask(DEBUG_ADDRESS)
- +Debug addresses
- +
- +mdebug-context
- +Target RejectNegative Report Undocumented Mask(DEBUG_CONTEXT)
- +Debug contexts
- +
- +march=
- +Target Report Var(ubicom32_arch_name) Init("ubicom32v4") Joined
- +Specify the name of the target architecture
- +
- +mfdpic
- +Target Report Mask(FDPIC)
- +Enable Function Descriptor PIC mode
- +
- +minline-plt
- +Target Report Mask(INLINE_PLT)
- +Enable inlining of PLT in function calls
- +
- +mfastcall
- +Target Report Mask(FASTCALL)
- +Enable default fast (call) calling sequence for smaller applications
- +
- +mipos-abi
- +Target Report Mask(IPOS_ABI)
- +Enable the ipOS ABI in which D10-D13 are caller-clobbered
- --- /dev/null
- +++ b/gcc/config/ubicom32/uclinux.h
- @@ -0,0 +1,67 @@
- +/* Definitions of target machine for Ubicom32-uclinux
- +
- + Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
- + 2009 Free Software Foundation, Inc.
- + Contributed by Ubicom, Inc.
- +
- + This file is part of GCC.
- +
- + GCC is free software; you can redistribute it and/or modify it
- + under the terms of the GNU General Public License as published
- + by the Free Software Foundation; either version 3, or (at your
- + option) any later version.
- +
- + GCC is distributed in the hope that it will be useful, but WITHOUT
- + ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
- + or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
- + License for more details.
- +
- + You should have received a copy of the GNU General Public License
- + along with GCC; see the file COPYING3. If not see
- + <http://www.gnu.org/licenses/>. */
- +
- +/* Don't assume anything about the header files. */
- +#define NO_IMPLICIT_EXTERN_C
- +
- +#undef LIB_SPEC
- +#define LIB_SPEC \
- + "%{pthread:-lpthread} " \
- + "%{!shared:%{!symbolic: -lc}} "
- +
- +
- +#undef LINK_GCC_C_SEQUENCE_SPEC
- +#define LINK_GCC_C_SEQUENCE_SPEC \
- + "%{!shared:--start-group} %G %L %{!shared:--end-group}%{shared:%G} "
- +
- +#undef STARTFILE_SPEC
- +#define STARTFILE_SPEC \
- + "%{!shared: crt1%O%s}" \
- + " crti%O%s crtbegin%O%s"
- +
- +#undef ENDFILE_SPEC
- +#define ENDFILE_SPEC "crtend%O%s crtn%O%s"
- +
- +/* This macro applies on top of OBJECT_FORMAT_ELF and indicates that
- + we want to support both flat and ELF output. */
- +#define OBJECT_FORMAT_FLAT
- +
- +#undef DRIVER_SELF_SPECS
- +#define DRIVER_SELF_SPECS \
- + "%{!mno-fastcall:-mfastcall}"
- +
- +/* taken from linux.h */
- +/* The GNU C++ standard library requires that these macros be defined. */
- +#undef CPLUSPLUS_CPP_SPEC
- +#define CPLUSPLUS_CPP_SPEC "-D_GNU_SOURCE %(cpp)"
- +
- +#define TARGET_OS_CPP_BUILTINS() \
- + do { \
- + builtin_define_std ("__UBICOM32__"); \
- + builtin_define_std ("__ubicom32__"); \
- + builtin_define ("__gnu_linux__"); \
- + builtin_define_std ("linux"); \
- + builtin_define_std ("unix"); \
- + builtin_assert ("system=linux"); \
- + builtin_assert ("system=unix"); \
- + builtin_assert ("system=posix"); \
- + } while (0)
- --- /dev/null
- +++ b/gcc/config/ubicom32/xm-ubicom32.h
- @@ -0,0 +1,36 @@
- +/* Configuration for Ubicom's Ubicom32 architecture.
- + Copyright (C) 2004, 2005, 2006, 2007, 2008, 2009 Free Software
- + Foundation, Inc.
- + Contributed by Ubicom Inc.
- +
- +This file is part of GNU CC.
- +
- +GNU CC is free software; you can redistribute it and/or modify
- +it under the terms of the GNU General Public License as published by
- +the Free Software Foundation; either version 2, or (at your option)
- +any later version.
- +
- +GNU CC is distributed in the hope that it will be useful,
- +but WITHOUT ANY WARRANTY; without even the implied warranty of
- +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- +GNU General Public License for more details.
- +
- +You should have received a copy of the GNU General Public License
- +along with GNU CC; see the file COPYING. If not, write to
- +the Free Software Foundation, 59 Temple Place - Suite 330,
- +Boston, MA 02111-1307, USA. */
- +
- +/* #defines that need visibility everywhere. */
- +#define FALSE 0
- +#define TRUE 1
- +
- +/* This describes the machine the compiler is hosted on. */
- +#define HOST_BITS_PER_CHAR 8
- +#define HOST_BITS_PER_SHORT 16
- +#define HOST_BITS_PER_INT 32
- +#define HOST_BITS_PER_LONG 32
- +#define HOST_BITS_PER_LONGLONG 64
- +
- +/* Arguments to use with `exit'. */
- +#define SUCCESS_EXIT_CODE 0
- +#define FATAL_EXIT_CODE 33
- --- a/gcc/config.gcc
- +++ b/gcc/config.gcc
- @@ -2503,6 +2503,34 @@ tilepro-*-linux*)
- c_target_objs="tilepro-c.o"
- cxx_target_objs="tilepro-c.o"
- ;;
- +ubicom32-*-elf)
- + xm_file=ubicom32/xm-ubicom32.h
- + tm_file="${tm_file} ubicom32/elf.h" # still need dbxelf.h elfos.h
- + tmake_file=ubicom32/t-ubicom32
- + ;;
- +ubicom32-*-uclinux*)
- + xm_file=ubicom32/xm-ubicom32.h
- + tm_file="${tm_file} ubicom32/elf.h ubicom32/uclinux.h" # still need dbxelf.h elfos.h linux.h
- + tm_defines="${tm_defines} UCLIBC_DEFAULT=1"
- + extra_options="${extra_options} linux.opt"
- + tmake_file=ubicom32/t-ubicom32-uclinux
- + use_collect2=no
- + ;;
- +ubicom32-*-linux-uclibc)
- + xm_file=ubicom32/xm-ubicom32.h
- + tm_file="${tm_file} ubicom32/elf.h linux.h ubicom32/linux.h" # still need dbxelf.h elfos.h
- + tmake_file="t-slibgcc-elf-ver ubicom32/t-ubicom32-linux"
- + extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- + use_collect2=no
- + ;;
- +ubicom32-*-linux*)
- + xm_file=ubicom32/xm-ubicom32.h
- + tm_file="${tm_file} ubicom32/elf.h linux.h ubicom32/linux.h" # still need dbxelf.h elfos.h
- + tmake_file="t-slibgcc-elf-ver ubicom32/t-ubicom32-linux"
- + tm_defines="${tm_defines} UCLIBC_DEFAULT=1"
- + extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- + use_collect2=no
- + ;;
- v850*-*-*)
- case ${target} in
- v850e2v3-*-*)
- --- a/libgcc/config.host
- +++ b/libgcc/config.host
- @@ -1098,6 +1098,15 @@ tilepro-*-linux*)
- tmake_file="${tmake_file} tilepro/t-crtstuff t-softfp-sfdf t-softfp tilepro/t-tilepro"
- md_unwind_header=tilepro/linux-unwind.h
- ;;
- +ubicom32*-*-elf*)
- + ;;
- +ubicom32*-*-uclinux*)
- + ;;
- +ubicom32*-*-linux*)
- + # No need to build crtbeginT.o on uClibc systems. Should probably
- + # be moved to the OS specific section above.
- + extra_parts="crtbegin.o crtbeginS.o crtend.o crtendS.o"
- + ;;
- v850*-*-*)
- tmake_file="v850/t-v850 t-fdpbit"
- ;;
|