IRBuilderAsmJs.cpp 250 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743474447454746474747484749475047514752475347544755475647574758475947604761476247634764476547664767476847694770477147724773477447754776477747784779478047814782478347844785478647874788478947904791479247934794479547964797479847994800480148024803480448054806480748084809481048114812481348144815481648174818481948204821482248234824482548264827482848294830483148324833483448354836483748384839484048414842484348444845484648474848484948504851485248534854485548564857485848594860486148624863486448654866486748684869487048714872487348744875487648774878487948804881488248834884488548864887488848894890489148924893489448954896489748984899490049014902490349044905490649074908490949104911491249134914491549164917491849194920492149224923492449254926492749284929493049314932493349344935493649374938493949404941494249434944494549464947494849494950495149524953495449554956495749584959496049614962496349644965496649674968496949704971497249734974497549764977497849794980498149824983498449854986498749884989499049914992499349944995499649974998499950005001500250035004500550065007500850095010501150125013501450155016501750185019502050215022502350245025502650275028502950305031503250335034503550365037503850395040504150425043504450455046504750485049505050515052505350545055505650575058505950605061506250635064506550665067506850695070507150725073507450755076507750785079508050815082508350845085508650875088508950905091509250935094509550965097509850995100510151025103510451055106510751085109511051115112511351145115511651175118511951205121512251235124512551265127512851295130513151325133513451355136513751385139514051415142514351445145514651475148514951505151515251535154515551565157515851595160516151625163516451655166516751685169517051715172517351745175517651775178517951805181518251835184518551865187518851895190519151925193519451955196519751985199520052015202520352045205520652075208520952105211521252135214521552165217521852195220522152225223522452255226522752285229523052315232523352345235523652375238523952405241524252435244524552465247524852495250525152525253525452555256525752585259526052615262526352645265526652675268526952705271527252735274527552765277527852795280528152825283528452855286528752885289529052915292529352945295529652975298529953005301530253035304530553065307530853095310531153125313531453155316531753185319532053215322532353245325532653275328532953305331533253335334533553365337533853395340534153425343534453455346534753485349535053515352535353545355535653575358535953605361536253635364536553665367536853695370537153725373537453755376537753785379538053815382538353845385538653875388538953905391539253935394539553965397539853995400540154025403540454055406540754085409541054115412541354145415541654175418541954205421542254235424542554265427542854295430543154325433543454355436543754385439544054415442544354445445544654475448544954505451545254535454545554565457545854595460546154625463546454655466546754685469547054715472547354745475547654775478547954805481548254835484548554865487548854895490549154925493549454955496549754985499550055015502550355045505550655075508550955105511551255135514551555165517551855195520552155225523552455255526552755285529553055315532553355345535553655375538553955405541554255435544554555465547554855495550555155525553555455555556555755585559556055615562556355645565556655675568556955705571557255735574557555765577557855795580558155825583558455855586558755885589559055915592559355945595559655975598559956005601560256035604560556065607560856095610561156125613561456155616561756185619562056215622562356245625562656275628562956305631563256335634563556365637563856395640564156425643564456455646564756485649565056515652565356545655565656575658565956605661566256635664566556665667566856695670567156725673567456755676567756785679568056815682568356845685568656875688568956905691569256935694569556965697569856995700570157025703570457055706570757085709571057115712571357145715571657175718571957205721572257235724572557265727572857295730573157325733573457355736573757385739574057415742574357445745574657475748574957505751575257535754575557565757575857595760576157625763576457655766576757685769577057715772577357745775577657775778577957805781578257835784578557865787578857895790579157925793579457955796579757985799580058015802580358045805580658075808580958105811581258135814581558165817581858195820582158225823582458255826582758285829583058315832583358345835583658375838583958405841584258435844584558465847584858495850585158525853585458555856585758585859586058615862586358645865586658675868586958705871587258735874587558765877587858795880588158825883588458855886588758885889589058915892589358945895589658975898589959005901590259035904590559065907590859095910591159125913591459155916591759185919592059215922592359245925592659275928592959305931593259335934593559365937593859395940594159425943594459455946594759485949595059515952595359545955595659575958595959605961596259635964596559665967596859695970597159725973597459755976597759785979598059815982598359845985598659875988598959905991599259935994599559965997599859996000600160026003600460056006600760086009601060116012601360146015601660176018601960206021602260236024602560266027602860296030603160326033603460356036603760386039604060416042604360446045604660476048604960506051605260536054605560566057605860596060606160626063606460656066606760686069607060716072607360746075607660776078607960806081608260836084608560866087608860896090609160926093609460956096609760986099610061016102610361046105610661076108610961106111611261136114611561166117611861196120612161226123612461256126612761286129613061316132613361346135613661376138613961406141614261436144614561466147614861496150615161526153615461556156615761586159616061616162616361646165616661676168616961706171617261736174617561766177617861796180618161826183618461856186618761886189619061916192619361946195619661976198619962006201620262036204620562066207620862096210621162126213621462156216621762186219622062216222622362246225622662276228622962306231623262336234623562366237623862396240624162426243624462456246624762486249625062516252625362546255625662576258625962606261626262636264626562666267626862696270627162726273627462756276627762786279628062816282628362846285628662876288628962906291629262936294629562966297629862996300630163026303630463056306630763086309631063116312631363146315631663176318631963206321632263236324632563266327632863296330633163326333633463356336633763386339634063416342634363446345634663476348634963506351635263536354635563566357635863596360636163626363636463656366636763686369637063716372637363746375637663776378637963806381638263836384638563866387638863896390639163926393639463956396639763986399640064016402640364046405640664076408640964106411641264136414641564166417641864196420642164226423642464256426642764286429643064316432643364346435643664376438643964406441644264436444644564466447644864496450645164526453645464556456645764586459646064616462646364646465646664676468646964706471647264736474647564766477647864796480648164826483648464856486648764886489649064916492649364946495649664976498649965006501650265036504650565066507650865096510651165126513651465156516651765186519652065216522652365246525652665276528652965306531653265336534653565366537653865396540654165426543654465456546654765486549655065516552655365546555655665576558655965606561656265636564656565666567656865696570657165726573657465756576657765786579658065816582658365846585658665876588658965906591659265936594659565966597659865996600660166026603660466056606660766086609661066116612661366146615661666176618661966206621662266236624662566266627662866296630663166326633663466356636663766386639664066416642664366446645664666476648664966506651665266536654665566566657665866596660666166626663666466656666666766686669667066716672667366746675667666776678667966806681668266836684668566866687668866896690669166926693669466956696669766986699670067016702670367046705670667076708
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft Corporation and contributors. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "Backend.h"
  6. #ifdef ASMJS_PLAT
  7. #include "ByteCode/OpCodeUtilAsmJs.h"
  8. void
  9. IRBuilderAsmJs::Build()
  10. {
  11. m_funcAlloc = m_func->m_alloc;
  12. NoRecoverMemoryJitArenaAllocator localAlloc(_u("BE-IRBuilder"), m_funcAlloc->GetPageAllocator(), Js::Throw::OutOfMemory);
  13. m_tempAlloc = &localAlloc;
  14. uint32 offset;
  15. uint32 statementIndex = m_statementReader.GetStatementIndex();
  16. m_argStack = JitAnew(m_tempAlloc, SList<IR::Instr *>, m_tempAlloc);
  17. m_tempList = JitAnew(m_tempAlloc, SList<IR::Instr *>, m_tempAlloc);
  18. m_argOffsetStack = JitAnew(m_tempAlloc, SList<int32>, m_tempAlloc);
  19. m_branchRelocList = JitAnew(m_tempAlloc, SList<BranchReloc *>, m_tempAlloc);
  20. m_switchBuilder.Init(m_func, m_tempAlloc, true);
  21. m_firstVarConst = 0;
  22. Js::RegSlot tempCount = 0;
  23. m_firstsType[0] = m_firstVarConst + AsmJsRegSlots::RegCount;
  24. for (int i = 0, j = 1; i < WAsmJs::LIMIT; ++i, ++j)
  25. {
  26. WAsmJs::Types type = (WAsmJs::Types)i;
  27. const auto typedInfo = m_asmFuncInfo->GetTypedSlotInfo(type);
  28. m_firstsType[j] = typedInfo.constCount;
  29. m_firstsType[j + WAsmJs::LIMIT] = typedInfo.varCount;
  30. m_firstsType[j + 2 * WAsmJs::LIMIT] = typedInfo.tmpCount;
  31. tempCount += typedInfo.tmpCount;
  32. }
  33. // Fixup the firsts by looking at the previous value
  34. for (int i = 1; i < m_firstsTypeCount; ++i)
  35. {
  36. m_firstsType[i] += m_firstsType[i - 1];
  37. }
  38. m_firstIRTemp = m_firstsType[m_firstsTypeCount - 1];
  39. m_simdOpcodesMap = JitAnewArrayZ(m_tempAlloc, Js::OpCode, Js::Simd128AsmJsOpcodeCount());
  40. {
  41. #define MACRO_SIMD(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) m_simdOpcodesMap[(uint32)(Js::OpCodeAsmJs::opcode - Js::OpCodeAsmJs::Simd128_Start)] = Js::OpCode::opcode;
  42. #define MACRO_SIMD_WMS(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) MACRO_SIMD(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr)
  43. // append extended opcodes
  44. #define MACRO_SIMD_EXTEND(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) \
  45. m_simdOpcodesMap[(uint32)(Js::OpCodeAsmJs::opcode - Js::OpCodeAsmJs::Simd128_Start_Extend) + (Js::OpCodeAsmJs::Simd128_End - Js::OpCodeAsmJs::Simd128_Start + 1)] = Js::OpCode::opcode;
  46. #define MACRO_SIMD_EXTEND_WMS(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr, ...) MACRO_SIMD_EXTEND(opcode, asmjsLayout, opCodeAttrAsmJs, OpCodeAttr)
  47. #include "ByteCode/OpCodesSimd.h"
  48. }
  49. // we will be using lower space for type specialized syms, so bump up where new temp syms can be created
  50. m_func->m_symTable->IncreaseStartingID(m_firstIRTemp - m_func->m_symTable->GetMaxSymID());
  51. if (tempCount > 0)
  52. {
  53. m_tempMap = (SymID*)m_tempAlloc->AllocZero(sizeof(SymID) * tempCount);
  54. m_fbvTempUsed = BVFixed::New<JitArenaAllocator>(tempCount, m_tempAlloc);
  55. }
  56. else
  57. {
  58. m_tempMap = nullptr;
  59. m_fbvTempUsed = nullptr;
  60. }
  61. m_func->m_headInstr = IR::EntryInstr::New(Js::OpCode::FunctionEntry, m_func);
  62. m_func->m_exitInstr = IR::ExitInstr::New(Js::OpCode::FunctionExit, m_func);
  63. m_func->m_tailInstr = m_func->m_exitInstr;
  64. m_func->m_headInstr->InsertAfter(m_func->m_tailInstr);
  65. m_func->m_isLeaf = true; // until proven otherwise
  66. m_functionStartOffset = m_jnReader.GetCurrentOffset();
  67. m_lastInstr = m_func->m_headInstr;
  68. AssertMsg(sizeof(SymID) >= sizeof(Js::RegSlot), "sizeof(SymID) != sizeof(Js::RegSlot)!!");
  69. offset = m_functionStartOffset;
  70. // Skip the last EndOfBlock opcode
  71. // EndOfBlock opcode has same value in Asm
  72. Assert(!OpCodeAttr::HasMultiSizeLayout(Js::OpCode::EndOfBlock));
  73. uint32 lastOffset = m_func->GetJITFunctionBody()->GetByteCodeLength() - Js::OpCodeUtil::EncodedSize(Js::OpCode::EndOfBlock, Js::SmallLayout);
  74. uint32 offsetToInstructionCount = lastOffset;
  75. if (this->IsLoopBody())
  76. {
  77. // LdSlot needs to cover all the register, including the temps, because we might treat
  78. // those as if they are local for the value of the with statement
  79. this->m_ldSlots = BVFixed::New<JitArenaAllocator>(GetLastTmp(WAsmJs::LastType), m_tempAlloc);
  80. this->m_stSlots = BVFixed::New<JitArenaAllocator>(GetFirstTmp(WAsmJs::FirstType), m_tempAlloc);
  81. this->m_loopBodyRetIPSym = StackSym::New(TyInt32, this->m_func);
  82. #if DBG
  83. uint32 tmpCount = GetLastTmp(WAsmJs::LastType) - GetFirstTmp(WAsmJs::FirstType);
  84. if (tmpCount != 0)
  85. {
  86. this->m_usedAsTemp = BVFixed::New<JitArenaAllocator>(tmpCount, m_tempAlloc);
  87. }
  88. #endif
  89. lastOffset = m_func->GetWorkItem()->GetLoopHeader()->endOffset;
  90. // Ret is created at lastOffset + 1, so we need lastOffset + 2 entries
  91. offsetToInstructionCount = lastOffset + 2;
  92. }
  93. #if DBG
  94. m_offsetToInstructionCount = offsetToInstructionCount;
  95. #endif
  96. m_offsetToInstruction = JitAnewArrayZ(m_tempAlloc, IR::Instr *, offsetToInstructionCount);
  97. LoadNativeCodeData();
  98. BuildConstantLoads();
  99. if (!this->IsLoopBody() && m_func->GetJITFunctionBody()->HasImplicitArgIns())
  100. {
  101. BuildImplicitArgIns();
  102. }
  103. if (m_statementReader.AtStatementBoundary(&m_jnReader))
  104. {
  105. statementIndex = AddStatementBoundary(statementIndex, offset);
  106. }
  107. Js::LayoutSize layoutSize;
  108. for (Js::OpCodeAsmJs newOpcode = m_jnReader.ReadAsmJsOp(layoutSize); (uint)m_jnReader.GetCurrentOffset() <= lastOffset; newOpcode = m_jnReader.ReadAsmJsOp(layoutSize))
  109. {
  110. Assert(newOpcode != Js::OpCodeAsmJs::EndOfBlock);
  111. AssertOrFailFastMsg(Js::OpCodeUtilAsmJs::IsValidByteCodeOpcode(newOpcode), "Error getting opcode from m_jnReader.Op()");
  112. uint layoutAndSize = layoutSize * Js::OpLayoutTypeAsmJs::Count + Js::OpCodeUtilAsmJs::GetOpCodeLayout(newOpcode);
  113. switch (layoutAndSize)
  114. {
  115. #define LAYOUT_TYPE(layout) \
  116. case Js::OpLayoutTypeAsmJs::layout: \
  117. Assert(layoutSize == Js::SmallLayout); \
  118. Build##layout(newOpcode, offset); \
  119. break;
  120. #define LAYOUT_TYPE_WMS(layout) \
  121. case Js::SmallLayout * Js::OpLayoutTypeAsmJs::Count + Js::OpLayoutTypeAsmJs::layout: \
  122. Build##layout<Js::SmallLayoutSizePolicy>(newOpcode, offset); \
  123. break; \
  124. case Js::MediumLayout * Js::OpLayoutTypeAsmJs::Count + Js::OpLayoutTypeAsmJs::layout: \
  125. Build##layout<Js::MediumLayoutSizePolicy>(newOpcode, offset); \
  126. break; \
  127. case Js::LargeLayout * Js::OpLayoutTypeAsmJs::Count + Js::OpLayoutTypeAsmJs::layout: \
  128. Build##layout<Js::LargeLayoutSizePolicy>(newOpcode, offset); \
  129. break;
  130. #define EXCLUDE_FRONTEND_LAYOUT
  131. #include "ByteCode/LayoutTypesAsmJs.h"
  132. default:
  133. AssertMsg(UNREACHED, "Unimplemented layout");
  134. Js::Throw::InternalError();
  135. break;
  136. }
  137. offset = m_jnReader.GetCurrentOffset();
  138. if (m_statementReader.AtStatementBoundary(&m_jnReader))
  139. {
  140. statementIndex = AddStatementBoundary(statementIndex, offset);
  141. }
  142. }
  143. if (Js::Constants::NoStatementIndex != statementIndex)
  144. {
  145. statementIndex = AddStatementBoundary(statementIndex, Js::Constants::NoByteCodeOffset);
  146. }
  147. if (IsLoopBody())
  148. {
  149. // Insert the LdSlot/StSlot and Ret
  150. IR::Opnd * retOpnd = this->InsertLoopBodyReturnIPInstr(offset, offset);
  151. // Restore and Ret are at the last offset + 1
  152. GenerateLoopBodySlotAccesses(lastOffset + 1);
  153. IR::Instr * retInstr = IR::Instr::New(Js::OpCode::Ret, m_func);
  154. retInstr->SetSrc1(retOpnd);
  155. this->AddInstr(retInstr, lastOffset + 1);
  156. }
  157. // Now fix up the targets for all the branches we've introduced.
  158. InsertLabels();
  159. // Now that we know whether the func is a leaf or not, decide whether we'll emit fast paths.
  160. // Do this once and for all, per-func, since the source size on the ThreadContext will be
  161. // changing while we JIT.
  162. if (m_func->IsTopFunc())
  163. {
  164. m_func->SetDoFastPaths();
  165. }
  166. }
  167. void
  168. IRBuilderAsmJs::LoadNativeCodeData()
  169. {
  170. Assert(m_func->IsTopFunc());
  171. if (m_func->IsOOPJIT())
  172. {
  173. IR::RegOpnd * nativeDataOpnd = IR::RegOpnd::New(TyVar, m_func);
  174. IR::Instr * instr = IR::Instr::New(Js::OpCode::LdNativeCodeData, nativeDataOpnd, m_func);
  175. this->AddInstr(instr, Js::Constants::NoByteCodeOffset);
  176. m_func->SetNativeCodeDataSym(nativeDataOpnd->GetStackSym());
  177. }
  178. }
  179. void
  180. IRBuilderAsmJs::AddInstr(IR::Instr * instr, uint32 offset)
  181. {
  182. m_lastInstr->InsertAfter(instr);
  183. if (offset != Js::Constants::NoByteCodeOffset)
  184. {
  185. Assert(offset < m_offsetToInstructionCount);
  186. if (m_offsetToInstruction[offset] == nullptr)
  187. {
  188. m_offsetToInstruction[offset] = instr;
  189. }
  190. else
  191. {
  192. Assert(m_lastInstr->GetByteCodeOffset() == offset);
  193. }
  194. instr->SetByteCodeOffset(offset);
  195. }
  196. else
  197. {
  198. instr->SetByteCodeOffset(m_lastInstr->GetByteCodeOffset());
  199. }
  200. m_lastInstr = instr;
  201. Func *topFunc = m_func->GetTopFunc();
  202. if (!topFunc->GetHasTempObjectProducingInstr())
  203. {
  204. if (OpCodeAttr::TempObjectProducing(instr->m_opcode))
  205. {
  206. topFunc->SetHasTempObjectProducingInstr(true);
  207. }
  208. }
  209. #if DBG_DUMP
  210. if (Js::Configuration::Global.flags.Trace.IsEnabled(Js::IRBuilderPhase, m_func->GetTopFunc()->GetSourceContextId(), m_func->GetTopFunc()->GetLocalFunctionId()))
  211. {
  212. instr->Dump();
  213. }
  214. #endif
  215. }
  216. IR::RegOpnd *
  217. IRBuilderAsmJs::BuildDstOpnd(Js::RegSlot dstRegSlot, IRType type)
  218. {
  219. SymID symID;
  220. if (RegIsTemp(dstRegSlot))
  221. {
  222. #if DBG
  223. if (this->IsLoopBody())
  224. {
  225. // If we are doing loop body, and a temp reg slot is loaded via LdSlot
  226. // That means that we have detected that the slot is live coming in to the loop.
  227. // This would only happen for the value of a "with" statement, so there shouldn't
  228. // be any def for those
  229. Assert(!this->m_ldSlots->Test(dstRegSlot));
  230. this->m_usedAsTemp->Set(dstRegSlot - GetFirstTmp(WAsmJs::FirstType));
  231. }
  232. #endif
  233. // This is a def of a temp. Create a new sym ID for it if it's been used since its last def.
  234. // !!!NOTE: always process an instruction's temp uses before its temp defs!!!
  235. if (GetTempUsed(dstRegSlot))
  236. {
  237. symID = m_func->m_symTable->NewID();
  238. SetTempUsed(dstRegSlot, FALSE);
  239. SetMappedTemp(dstRegSlot, symID);
  240. }
  241. else
  242. {
  243. symID = GetMappedTemp(dstRegSlot);
  244. // The temp hasn't been used since its last def. There are 2 possibilities:
  245. if (symID == 0)
  246. {
  247. // First time we've seen the temp. Just use the number that the front end gave it.
  248. symID = static_cast<SymID>(dstRegSlot);
  249. SetMappedTemp(dstRegSlot, symID);
  250. }
  251. else if (IRType_IsSimd128(type))
  252. {
  253. //In Asm.js, SIMD register space is untyped, so we could have SIMD temp registers.
  254. //Make sure that the StackSym types matches before reusing simd temps.
  255. StackSym * stackSym = m_func->m_symTable->FindStackSym(symID);
  256. if (!stackSym || stackSym->GetType() != type)
  257. {
  258. symID = m_func->m_symTable->NewID();
  259. SetMappedTemp(dstRegSlot, symID);
  260. }
  261. }
  262. }
  263. }
  264. else
  265. {
  266. symID = static_cast<SymID>(dstRegSlot);
  267. if (RegIsConstant(dstRegSlot))
  268. {
  269. // Don't need to track constant registers for bailout. Don't set the byte code register for constant.
  270. dstRegSlot = Js::Constants::NoRegister;
  271. }
  272. else if (IsLoopBody() && RegIsVar(dstRegSlot))
  273. {
  274. // Loop body and not constants
  275. this->m_stSlots->Set(symID);
  276. // We need to make sure that the symbols is loaded as well
  277. // so that the sym will be defined on all path.
  278. this->EnsureLoopBodyAsmJsLoadSlot(symID, type);
  279. }
  280. else
  281. {
  282. Assert(!IsLoopBody() || dstRegSlot == 0); // if loop body then one of the above two conditions should hold true
  283. }
  284. }
  285. //Simd return values of different IR types share the same reg slot.
  286. //To avoid symbol type mismatch, use the stack symbol with a dummy simd type.
  287. if (RegIsSimd128ReturnVar(symID))
  288. {
  289. type = TySimd128F4;
  290. }
  291. StackSym * symDst = StackSym::FindOrCreate(symID, dstRegSlot, m_func, type);
  292. // Always reset isSafeThis to false. We'll set it to true for singleDef cases,
  293. // but want to reset it to false if it is multi-def.
  294. // NOTE: We could handle the multiDef if they are all safe, but it probably isn't very common.
  295. symDst->m_isSafeThis = false;
  296. IR::RegOpnd *regOpnd = IR::RegOpnd::New(symDst, type, m_func);
  297. return regOpnd;
  298. }
  299. IR::RegOpnd *
  300. IRBuilderAsmJs::BuildSrcOpnd(Js::RegSlot srcRegSlot, IRType type)
  301. {
  302. StackSym * symSrc = m_func->m_symTable->FindStackSym(BuildSrcStackSymID(srcRegSlot, type));
  303. AssertMsg(symSrc, "Tried to use an undefined stack slot?");
  304. IR::RegOpnd * regOpnd = IR::RegOpnd::New(symSrc, type, m_func);
  305. return regOpnd;
  306. }
  307. IR::RegOpnd *
  308. IRBuilderAsmJs::BuildIntConstOpnd(Js::RegSlot regSlot)
  309. {
  310. Js::Var * constTable = (Js::Var*)m_func->GetJITFunctionBody()->GetConstTable();
  311. const WAsmJs::TypedSlotInfo& info = m_func->GetJITFunctionBody()->GetAsmJsInfo()->GetTypedSlotInfo(WAsmJs::INT32);
  312. Assert(info.constSrcByteOffset != Js::Constants::InvalidOffset);
  313. int* intConstTable = reinterpret_cast<int*>(((byte*)constTable) + info.constSrcByteOffset);
  314. Js::RegSlot srcReg = GetTypedRegFromRegSlot(regSlot, WAsmJs::INT32);
  315. Assert(srcReg >= Js::FunctionBody::FirstRegSlot && srcReg < info.constCount);
  316. const int32 value = intConstTable[srcReg];
  317. IR::IntConstOpnd *opnd = IR::IntConstOpnd::New(value, TyInt32, m_func);
  318. return (IR::RegOpnd*)opnd;
  319. }
  320. SymID
  321. IRBuilderAsmJs::BuildSrcStackSymID(Js::RegSlot regSlot, IRType type /*= IRType::TyVar*/)
  322. {
  323. SymID symID;
  324. if (this->RegIsTemp(regSlot))
  325. {
  326. // This is a use of a temp. Map the reg slot to its sym ID.
  327. // !!!NOTE: always process an instruction's temp uses before its temp defs!!!
  328. symID = this->GetMappedTemp(regSlot);
  329. if (symID == 0)
  330. {
  331. // We might have temps that are live through the loop body via "with" statement
  332. // We need to treat those as if they are locals and don't remap them
  333. Assert(this->IsLoopBody());
  334. Assert(!this->m_usedAsTemp->Test(regSlot - GetFirstTmp(WAsmJs::FirstType)));
  335. symID = static_cast<SymID>(regSlot);
  336. this->SetMappedTemp(regSlot, symID);
  337. this->EnsureLoopBodyAsmJsLoadSlot(symID, type);
  338. }
  339. this->SetTempUsed(regSlot, TRUE);
  340. }
  341. else
  342. {
  343. symID = static_cast<SymID>(regSlot);
  344. if (IsLoopBody() && RegIsVar(regSlot))
  345. {
  346. this->EnsureLoopBodyAsmJsLoadSlot(symID, type);
  347. }
  348. else
  349. {
  350. Assert(!IsLoopBody() || this->RegIsConstant(regSlot) || regSlot == 0);
  351. }
  352. }
  353. return symID;
  354. }
  355. IR::SymOpnd *
  356. IRBuilderAsmJs::BuildFieldOpnd(Js::RegSlot reg, Js::PropertyId propertyId, PropertyKind propertyKind, IRType type, bool scale)
  357. {
  358. Js::PropertyId scaledPropertyId = propertyId;
  359. if (scale)
  360. {
  361. scaledPropertyId *= TySize[type];
  362. }
  363. PropertySym * propertySym = BuildFieldSym(reg, scaledPropertyId, propertyKind);
  364. IR::SymOpnd * symOpnd = IR::SymOpnd::New(propertySym, type, m_func);
  365. return symOpnd;
  366. }
  367. PropertySym *
  368. IRBuilderAsmJs::BuildFieldSym(Js::RegSlot reg, Js::PropertyId propertyId, PropertyKind propertyKind)
  369. {
  370. SymID symId = BuildSrcStackSymID(reg);
  371. AssertMsg(m_func->m_symTable->FindStackSym(symId), "Tried to use an undefined stacksym?");
  372. PropertySym * propertySym = PropertySym::FindOrCreate(symId, propertyId, (Js::PropertyIdIndexType)-1, (uint)-1, propertyKind, m_func);
  373. return propertySym;
  374. }
  375. uint
  376. IRBuilderAsmJs::AddStatementBoundary(uint statementIndex, uint offset)
  377. {
  378. if (m_func->GetJITFunctionBody()->IsWasmFunction())
  379. {
  380. return 0;
  381. }
  382. IR::PragmaInstr* pragmaInstr = IR::PragmaInstr::New(Js::OpCode::StatementBoundary, statementIndex, m_func);
  383. this->AddInstr(pragmaInstr, offset);
  384. return m_statementReader.MoveNextStatementBoundary();
  385. }
  386. Js::RegSlot IRBuilderAsmJs::GetTypedRegFromRegSlot(Js::RegSlot reg, WAsmJs::Types type)
  387. {
  388. const auto typedInfo = m_asmFuncInfo->GetTypedSlotInfo(type);
  389. Js::RegSlot srcReg = reg;
  390. if (RegIsTypedVar(reg, type))
  391. {
  392. srcReg = reg - GetFirstVar(type);
  393. Assert(srcReg < typedInfo.varCount);
  394. srcReg += typedInfo.constCount;
  395. }
  396. else if (RegIsTemp(reg))
  397. {
  398. srcReg = reg - GetFirstTmp(type);
  399. Assert(srcReg < typedInfo.tmpCount);
  400. srcReg += typedInfo.varCount + typedInfo.constCount;
  401. }
  402. else if (RegIsConstant(reg))
  403. {
  404. srcReg = reg - GetFirstConst(type);
  405. Assert(srcReg < typedInfo.constCount);
  406. }
  407. return srcReg;
  408. }
  409. Js::RegSlot
  410. IRBuilderAsmJs::GetRegSlotFromTypedReg(Js::RegSlot srcReg, WAsmJs::Types type)
  411. {
  412. const auto typedInfo = m_asmFuncInfo->GetTypedSlotInfo(type);
  413. Js::RegSlot reg;
  414. if (srcReg < typedInfo.constCount)
  415. {
  416. reg = srcReg + GetFirstConst(type);
  417. Assert(reg >= GetFirstConst(type) && reg < GetLastConst(type));
  418. return reg;
  419. }
  420. srcReg -= typedInfo.constCount;
  421. if (srcReg < typedInfo.varCount)
  422. {
  423. reg = srcReg + GetFirstVar(type);
  424. Assert(reg >= GetFirstVar(type) && reg < GetLastVar(type));
  425. return reg;
  426. }
  427. srcReg -= typedInfo.varCount;
  428. Assert(srcReg < typedInfo.tmpCount);
  429. reg = srcReg + GetFirstTmp(type);
  430. Assert(reg >= GetFirstTmp(type) && reg < GetLastTmp(type));
  431. return reg;
  432. }
  433. IR::Instr *
  434. IRBuilderAsmJs::AddExtendedArg(IR::RegOpnd *src1, IR::RegOpnd *src2, uint32 offset)
  435. {
  436. Assert(src1);
  437. IR::RegOpnd * dst = IR::RegOpnd::New(src1->GetType(), m_func);
  438. dst->SetValueType(src1->GetValueType());
  439. IR::Instr * instr = IR::Instr::New(Js::OpCode::ExtendArg_A, dst, src1, m_func);
  440. if (src2)
  441. {
  442. instr->SetSrc2(src2);
  443. }
  444. AddInstr(instr, offset);
  445. return instr;
  446. }
  447. Js::RegSlot
  448. IRBuilderAsmJs::GetRegSlotFromVarReg(Js::RegSlot srcVarReg)
  449. {
  450. Js::RegSlot reg;
  451. if (srcVarReg < (Js::RegSlot)(AsmJsRegSlots::RegCount - 1))
  452. {
  453. reg = srcVarReg + m_firstVarConst;
  454. Assert(reg >= m_firstVarConst && reg < GetFirstConst(WAsmJs::FirstType));
  455. }
  456. else
  457. {
  458. reg = srcVarReg - AsmJsRegSlots::RegCount + GetFirstTmp(WAsmJs::FirstType) - 1;
  459. }
  460. return reg;
  461. }
  462. SymID
  463. IRBuilderAsmJs::GetMappedTemp(Js::RegSlot reg)
  464. {
  465. AssertMsg(RegIsTemp(reg), "Processing non-temp reg as a temp?");
  466. AssertMsg(m_tempMap, "Processing non-temp reg without a temp map?");
  467. return m_tempMap[reg - GetFirstTmp(WAsmJs::FirstType)];
  468. }
  469. void
  470. IRBuilderAsmJs::SetMappedTemp(Js::RegSlot reg, SymID tempId)
  471. {
  472. AssertMsg(RegIsTemp(reg), "Processing non-temp reg as a temp?");
  473. AssertMsg(m_tempMap, "Processing non-temp reg without a temp map?");
  474. m_tempMap[reg - GetFirstTmp(WAsmJs::FirstType)] = tempId;
  475. }
  476. BOOL
  477. IRBuilderAsmJs::GetTempUsed(Js::RegSlot reg)
  478. {
  479. AssertMsg(RegIsTemp(reg), "Processing non-temp reg as a temp?");
  480. AssertMsg(m_fbvTempUsed, "Processing non-temp reg without a used BV?");
  481. return m_fbvTempUsed->Test(reg - GetFirstTmp(WAsmJs::FirstType));
  482. }
  483. void
  484. IRBuilderAsmJs::SetTempUsed(Js::RegSlot reg, BOOL used)
  485. {
  486. AssertMsg(RegIsTemp(reg), "Processing non-temp reg as a temp?");
  487. AssertMsg(m_fbvTempUsed, "Processing non-temp reg without a used BV?");
  488. if (used)
  489. {
  490. m_fbvTempUsed->Set(reg - GetFirstTmp(WAsmJs::FirstType));
  491. }
  492. else
  493. {
  494. m_fbvTempUsed->Clear(reg - GetFirstTmp(WAsmJs::FirstType));
  495. }
  496. }
  497. BOOL
  498. IRBuilderAsmJs::RegIsTemp(Js::RegSlot reg)
  499. {
  500. return reg >= GetFirstTmp(WAsmJs::FirstType);
  501. }
  502. BOOL
  503. IRBuilderAsmJs::RegIsVar(Js::RegSlot reg)
  504. {
  505. for (int i = 0; i < WAsmJs::LIMIT; ++i)
  506. {
  507. if (RegIsTypedVar(reg, (WAsmJs::Types)i))
  508. {
  509. return true;
  510. }
  511. }
  512. return false;
  513. }
  514. BOOL
  515. IRBuilderAsmJs::RegIsTypedVar(Js::RegSlot reg, WAsmJs::Types type)
  516. {
  517. return reg >= GetFirstVar(type) && reg < GetLastVar(type);
  518. }
  519. bool
  520. IRBuilderAsmJs::RegIsSimd128ReturnVar(Js::RegSlot reg)
  521. {
  522. return (reg == GetFirstConst(WAsmJs::SIMD) &&
  523. Js::AsmJsRetType(m_asmFuncInfo->GetRetType()).toVarType().isSIMD());
  524. }
  525. BOOL
  526. IRBuilderAsmJs::RegIsConstant(Js::RegSlot reg)
  527. {
  528. return (reg > 0 && reg < GetLastConst(WAsmJs::LastType));
  529. }
  530. BranchReloc *
  531. IRBuilderAsmJs::AddBranchInstr(IR::BranchInstr * branchInstr, uint32 offset, uint32 targetOffset)
  532. {
  533. //
  534. // Loop jitting would be done only till the LoopEnd
  535. // Any branches beyond that offset are for the return statement
  536. //
  537. if (IsLoopBodyOuterOffset(targetOffset))
  538. {
  539. // if we have loaded the loop IP sym from the ProfiledLoopEnd then don't add it here
  540. if (!IsLoopBodyReturnIPInstr(m_lastInstr))
  541. {
  542. this->InsertLoopBodyReturnIPInstr(targetOffset, offset);
  543. }
  544. // Jump the restore StSlot and Ret instruction
  545. targetOffset = GetLoopBodyExitInstrOffset();
  546. }
  547. BranchReloc * reloc = nullptr;
  548. reloc = CreateRelocRecord(branchInstr, offset, targetOffset);
  549. AddInstr(branchInstr, offset);
  550. return reloc;
  551. }
  552. BranchReloc *
  553. IRBuilderAsmJs::CreateRelocRecord(IR::BranchInstr * branchInstr, uint32 offset, uint32 targetOffset)
  554. {
  555. BranchReloc * reloc = JitAnew(m_tempAlloc, BranchReloc, branchInstr, offset, targetOffset);
  556. m_branchRelocList->Prepend(reloc);
  557. return reloc;
  558. }
  559. void
  560. IRBuilderAsmJs::BuildHeapBufferReload(uint32 offset)
  561. {
  562. #ifdef ENABLE_WASM
  563. if(m_func->GetJITFunctionBody()->IsWasmFunction())
  564. {
  565. // WebAssembly.Memory
  566. IR::RegOpnd * dstOpnd = BuildDstOpnd(AsmJsRegSlots::WasmMemoryReg, TyVar);
  567. IR::Opnd * srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ModuleMemReg, TyVar), (int32)Js::WebAssemblyModule::GetMemoryOffset(), TyVar, m_func);
  568. IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  569. AddInstr(instr, offset);
  570. // ArrayBuffer
  571. dstOpnd = BuildDstOpnd(AsmJsRegSlots::ArrayReg, TyVar);
  572. srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::WasmMemoryReg, TyVar), Js::WebAssemblyMemory::GetOffsetOfArrayBuffer(), TyVar, m_func);
  573. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  574. AddInstr(instr, offset);
  575. }
  576. else
  577. #endif
  578. {
  579. // ArrayBuffer
  580. IR::RegOpnd * dstOpnd = BuildDstOpnd(AsmJsRegSlots::ArrayReg, TyVar);
  581. IR::Opnd * srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ModuleMemReg, TyVar), (int32)Js::AsmJsModuleMemory::MemoryTableBeginOffset, TyVar, m_func);
  582. IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  583. AddInstr(instr, offset);
  584. }
  585. // ArrayBuffer buffer
  586. IR::RegOpnd * dstOpnd = BuildDstOpnd(AsmJsRegSlots::BufferReg, TyVar);
  587. IR::Opnd * srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ArrayReg, TyVar), Js::ArrayBuffer::GetBufferOffset(), TyVar, m_func);
  588. IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  589. AddInstr(instr, offset);
  590. // ArrayBuffer length
  591. dstOpnd = BuildDstOpnd(AsmJsRegSlots::LengthReg, TyUint32);
  592. srcOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ArrayReg, TyVar), Js::ArrayBuffer::GetByteLengthOffset(), TyUint32, m_func);
  593. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  594. AddInstr(instr, offset);
  595. }
  596. template<typename T, typename ConstOpnd, typename F>
  597. void IRBuilderAsmJs::CreateLoadConstInstrForType(
  598. byte* table,
  599. Js::RegSlot& regAllocated,
  600. uint32 constCount,
  601. uint32 byteOffset,
  602. IRType irType,
  603. ValueType valueType,
  604. Js::OpCode opcode,
  605. F extraProcess
  606. )
  607. {
  608. T* typedTable = (T*)(table + byteOffset);
  609. // 1 for return register
  610. ++regAllocated;
  611. ++typedTable;
  612. for (uint32 i = 1; i < constCount; ++i)
  613. {
  614. uint32 reg = regAllocated++;
  615. T constVal = *typedTable++;
  616. IR::RegOpnd * dstOpnd = BuildDstOpnd(reg, irType);
  617. Assert(RegIsConstant(reg));
  618. dstOpnd->m_sym->SetIsFromByteCodeConstantTable();
  619. dstOpnd->SetValueType(valueType);
  620. IR::Instr *instr = IR::Instr::New(opcode, dstOpnd, ConstOpnd::New(constVal, irType, m_func), m_func);
  621. extraProcess(instr, constVal);
  622. AddInstr(instr, Js::Constants::NoByteCodeOffset);
  623. }
  624. }
  625. void
  626. IRBuilderAsmJs::BuildConstantLoads()
  627. {
  628. Js::Var * constTable = (Js::Var *)m_func->GetJITFunctionBody()->GetConstTable();
  629. // Load FrameDisplay
  630. IR::RegOpnd * asmJsEnvDstOpnd = BuildDstOpnd(AsmJsRegSlots::ModuleMemReg, TyVar);
  631. IR::Instr * ldAsmJsEnvInstr = IR::Instr::New(Js::OpCode::LdAsmJsEnv, asmJsEnvDstOpnd, m_func);
  632. AddInstr(ldAsmJsEnvInstr, Js::Constants::NoByteCodeOffset);
  633. // Load heap buffer
  634. if (m_asmFuncInfo->UsesHeapBuffer())
  635. {
  636. BuildHeapBufferReload(Js::Constants::NoByteCodeOffset);
  637. }
  638. if (!constTable)
  639. {
  640. return;
  641. }
  642. uint32 regAllocated = AsmJsRegSlots::RegCount;
  643. byte* table = (byte*)constTable;
  644. const bool isOOPJIT = m_func->IsOOPJIT();
  645. for (int i = 0; i < WAsmJs::LIMIT; ++i)
  646. {
  647. WAsmJs::Types type = (WAsmJs::Types)i;
  648. WAsmJs::TypedSlotInfo info = m_asmFuncInfo->GetTypedSlotInfo(type);
  649. if (info.constCount == 0)
  650. {
  651. continue;
  652. }
  653. switch(type)
  654. {
  655. case WAsmJs::INT32:
  656. CreateLoadConstInstrForType<int32, IR::IntConstOpnd>(
  657. table,
  658. regAllocated,
  659. info.constCount,
  660. info.constSrcByteOffset,
  661. TyInt32,
  662. ValueType::GetInt(false),
  663. Js::OpCode::Ld_I4,
  664. [isOOPJIT](IR::Instr* instr, int32 val)
  665. {
  666. IR::RegOpnd* dstOpnd = instr->GetDst()->AsRegOpnd();
  667. if (!isOOPJIT && dstOpnd->m_sym->IsSingleDef())
  668. {
  669. dstOpnd->m_sym->SetIsIntConst(val);
  670. }
  671. }
  672. );
  673. break;
  674. case WAsmJs::FLOAT32:
  675. CreateLoadConstInstrForType<float, IR::FloatConstOpnd>(
  676. table,
  677. regAllocated,
  678. info.constCount,
  679. info.constSrcByteOffset,
  680. TyFloat32,
  681. ValueType::Float,
  682. Js::OpCode::LdC_F8_R8,
  683. [isOOPJIT](IR::Instr* instr, float val)
  684. {
  685. #if _M_IX86
  686. IR::RegOpnd* dstOpnd = instr->GetDst()->AsRegOpnd();
  687. if (!isOOPJIT && dstOpnd->m_sym->IsSingleDef())
  688. {
  689. dstOpnd->m_sym->SetIsFloatConst();
  690. }
  691. #endif
  692. }
  693. );
  694. break;
  695. case WAsmJs::FLOAT64:
  696. CreateLoadConstInstrForType<double, IR::FloatConstOpnd>(
  697. table,
  698. regAllocated,
  699. info.constCount,
  700. info.constSrcByteOffset,
  701. TyFloat64,
  702. ValueType::Float,
  703. Js::OpCode::LdC_F8_R8,
  704. [isOOPJIT](IR::Instr* instr, double val)
  705. {
  706. #if _M_IX86
  707. IR::RegOpnd* dstOpnd = instr->GetDst()->AsRegOpnd();
  708. if (!isOOPJIT && dstOpnd->m_sym->IsSingleDef())
  709. {
  710. dstOpnd->m_sym->SetIsFloatConst();
  711. }
  712. #endif
  713. }
  714. );
  715. break;
  716. case WAsmJs::SIMD:
  717. CreateLoadConstInstrForType<AsmJsSIMDValue, IR::Simd128ConstOpnd>(
  718. table,
  719. regAllocated,
  720. info.constCount,
  721. info.constSrcByteOffset,
  722. TySimd128F4,
  723. ValueType::UninitializedObject,
  724. Js::OpCode::Simd128_LdC,
  725. [isOOPJIT](IR::Instr* instr, AsmJsSIMDValue val)
  726. {
  727. #if _M_IX86
  728. IR::RegOpnd* dstOpnd = instr->GetDst()->AsRegOpnd();
  729. if (!isOOPJIT && dstOpnd->m_sym->IsSingleDef())
  730. {
  731. dstOpnd->m_sym->SetIsSimd128Const();
  732. }
  733. #endif
  734. }
  735. );
  736. break;
  737. default:
  738. Assert(false);
  739. break;
  740. }
  741. }
  742. }
  743. void
  744. IRBuilderAsmJs::BuildImplicitArgIns()
  745. {
  746. int32 intArgInCount = 0;
  747. int32 int64ArgInCount = 0;
  748. int32 floatArgInCount = 0;
  749. int32 doubleArgInCount = 0;
  750. int32 simd128ArgInCount = 0;
  751. // formal params are offset from EBP by the EBP chain, return address, and function object
  752. int32 offset = 3 * MachPtr;
  753. for (Js::ArgSlot i = 1; i < m_func->GetJITFunctionBody()->GetInParamsCount(); ++i)
  754. {
  755. StackSym * symSrc = nullptr;
  756. IR::Opnd * srcOpnd = nullptr;
  757. IR::RegOpnd * dstOpnd = nullptr;
  758. IR::Instr * instr = nullptr;
  759. // TODO: double args are not aligned on stack
  760. Js::AsmJsVarType varType = m_func->GetJITFunctionBody()->GetAsmJsInfo()->GetArgType(i - 1);
  761. switch (varType.which())
  762. {
  763. case Js::AsmJsVarType::Which::Int:
  764. symSrc = StackSym::NewParamSlotSym(i, m_func, TyInt32);
  765. m_func->SetArgOffset(symSrc, offset);
  766. srcOpnd = IR::SymOpnd::New(symSrc, TyInt32, m_func);
  767. dstOpnd = BuildDstOpnd(GetFirstVar(WAsmJs::INT32) + intArgInCount, TyInt32);
  768. dstOpnd->SetValueType(ValueType::GetInt(false));
  769. instr = IR::Instr::New(Js::OpCode::ArgIn_A, dstOpnd, srcOpnd, m_func);
  770. offset += MachPtr;
  771. ++intArgInCount;
  772. break;
  773. case Js::AsmJsVarType::Which::Float:
  774. symSrc = StackSym::NewParamSlotSym(i, m_func, TyFloat32);
  775. m_func->SetArgOffset(symSrc, offset);
  776. srcOpnd = IR::SymOpnd::New(symSrc, TyFloat32, m_func);
  777. dstOpnd = BuildDstOpnd(GetFirstVar(WAsmJs::FLOAT32) + floatArgInCount, TyFloat32);
  778. dstOpnd->SetValueType(ValueType::Float);
  779. instr = IR::Instr::New(Js::OpCode::ArgIn_A, dstOpnd, srcOpnd, m_func);
  780. offset += MachPtr;
  781. ++floatArgInCount;
  782. break;
  783. case Js::AsmJsVarType::Which::Double:
  784. symSrc = StackSym::NewParamSlotSym(i, m_func, TyFloat64);
  785. m_func->SetArgOffset(symSrc, offset);
  786. srcOpnd = IR::SymOpnd::New(symSrc, TyFloat64, m_func);
  787. dstOpnd = BuildDstOpnd(GetFirstVar(WAsmJs::FLOAT64) + doubleArgInCount, TyFloat64);
  788. dstOpnd->SetValueType(ValueType::Float);
  789. instr = IR::Instr::New(Js::OpCode::ArgIn_A, dstOpnd, srcOpnd, m_func);
  790. offset += MachDouble;
  791. ++doubleArgInCount;
  792. break;
  793. case Js::AsmJsVarType::Which::Int64:
  794. symSrc = StackSym::NewParamSlotSym(i, m_func, TyInt64);
  795. m_func->SetArgOffset(symSrc, offset);
  796. srcOpnd = IR::SymOpnd::New(symSrc, TyInt64, m_func);
  797. dstOpnd = BuildDstOpnd(GetFirstVar(WAsmJs::INT64) + int64ArgInCount, TyInt64);
  798. dstOpnd->SetValueType(ValueType::GetInt(false));
  799. instr = IR::Instr::New(Js::OpCode::ArgIn_A, dstOpnd, srcOpnd, m_func);
  800. offset += 8;
  801. ++int64ArgInCount;
  802. break;
  803. default:
  804. {
  805. // SIMD_JS
  806. IRType argType;
  807. GetSimdTypesFromAsmType((Js::AsmJsType::Which)varType.which(), &argType);
  808. symSrc = StackSym::NewParamSlotSym(i, m_func, argType);
  809. m_func->SetArgOffset(symSrc, offset);
  810. srcOpnd = IR::SymOpnd::New(symSrc, argType, m_func);
  811. dstOpnd = BuildDstOpnd(GetFirstVar(WAsmJs::SIMD) + simd128ArgInCount, argType);
  812. dstOpnd->SetValueType(ValueType::UninitializedObject);
  813. instr = IR::Instr::New(Js::OpCode::ArgIn_A, dstOpnd, srcOpnd, m_func);
  814. offset += sizeof(AsmJsSIMDValue);
  815. ++simd128ArgInCount;
  816. break;
  817. }
  818. }
  819. AddInstr(instr, Js::Constants::NoByteCodeOffset);
  820. }
  821. }
  822. void
  823. IRBuilderAsmJs::InsertLabels()
  824. {
  825. AssertMsg(m_branchRelocList, "Malformed branch reloc list");
  826. SList<BranchReloc *>::Iterator iter(m_branchRelocList);
  827. while (iter.Next())
  828. {
  829. IR::LabelInstr * labelInstr;
  830. BranchReloc * reloc = iter.Data();
  831. IR::BranchInstr * branchInstr = reloc->GetBranchInstr();
  832. uint offset = reloc->GetOffset();
  833. uint const branchOffset = reloc->GetBranchOffset();
  834. Assert(!IsLoopBody() || offset <= GetLoopBodyExitInstrOffset());
  835. if (branchInstr->m_opcode == Js::OpCode::MultiBr)
  836. {
  837. IR::MultiBranchInstr * multiBranchInstr = branchInstr->AsBranchInstr()->AsMultiBrInstr();
  838. multiBranchInstr->UpdateMultiBrTargetOffsets([&](uint32 offset) -> IR::LabelInstr *
  839. {
  840. labelInstr = this->CreateLabel(branchInstr, offset);
  841. multiBranchInstr->ChangeLabelRef(nullptr, labelInstr);
  842. return labelInstr;
  843. });
  844. }
  845. else
  846. {
  847. labelInstr = CreateLabel(branchInstr, offset);
  848. branchInstr->SetTarget(labelInstr);
  849. }
  850. if (!reloc->IsNotBackEdge() && branchOffset >= offset)
  851. {
  852. labelInstr->m_isLoopTop = true;
  853. }
  854. }
  855. }
  856. IR::LabelInstr *
  857. IRBuilderAsmJs::CreateLabel(IR::BranchInstr * branchInstr, uint & offset)
  858. {
  859. IR::Instr * targetInstr = nullptr;
  860. while (targetInstr == nullptr)
  861. {
  862. targetInstr = m_offsetToInstruction[offset];
  863. Assert(offset < m_offsetToInstructionCount);
  864. ++offset;
  865. }
  866. IR::Instr *instrPrev = targetInstr->m_prev;
  867. if (instrPrev)
  868. {
  869. instrPrev = targetInstr->GetPrevRealInstrOrLabel();
  870. }
  871. IR::LabelInstr * labelInstr;
  872. if (instrPrev && instrPrev->IsLabelInstr())
  873. {
  874. // Found an existing label at the right offset. Just reuse it.
  875. labelInstr = instrPrev->AsLabelInstr();
  876. }
  877. else
  878. {
  879. // No label at the desired offset. Create one.
  880. labelInstr = IR::LabelInstr::New(Js::OpCode::Label, m_func);
  881. labelInstr->SetByteCodeOffset(offset);
  882. if (instrPrev)
  883. {
  884. instrPrev->InsertAfter(labelInstr);
  885. }
  886. else
  887. {
  888. targetInstr->InsertBefore(labelInstr);
  889. }
  890. }
  891. return labelInstr;
  892. }
  893. void
  894. IRBuilderAsmJs::BuildEmpty(Js::OpCodeAsmJs newOpcode, uint32 offset)
  895. {
  896. m_jnReader.Empty();
  897. IR::Instr * instr = nullptr;
  898. IR::RegOpnd * regOpnd = nullptr;
  899. Js::RegSlot retSlot;
  900. switch (newOpcode)
  901. {
  902. case Js::OpCodeAsmJs::Unreachable_Void:
  903. instr = IR::Instr::New(Js::OpCode::ThrowRuntimeError, m_func);
  904. instr->SetSrc1(IR::IntConstOpnd::New(SCODE_CODE(WASMERR_Unreachable), TyInt32, instr->m_func));
  905. AddInstr(instr, offset);
  906. break;
  907. case Js::OpCodeAsmJs::Ret:
  908. instr = IR::Instr::New(Js::OpCode::Ret, m_func);
  909. switch (m_asmFuncInfo->GetRetType())
  910. {
  911. case Js::AsmJsRetType::Which::Signed:
  912. retSlot = GetRegSlotFromIntReg(0);
  913. regOpnd = BuildDstOpnd(retSlot, TyInt32);
  914. regOpnd->SetValueType(ValueType::GetInt(false));
  915. break;
  916. case Js::AsmJsRetType::Which::Float:
  917. retSlot = GetRegSlotFromFloatReg(0);
  918. regOpnd = BuildDstOpnd(retSlot, TyFloat32);
  919. regOpnd->SetValueType(ValueType::Float);
  920. break;
  921. case Js::AsmJsRetType::Which::Double:
  922. retSlot = GetRegSlotFromDoubleReg(0);
  923. regOpnd = BuildDstOpnd(retSlot, TyFloat64);
  924. regOpnd->SetValueType(ValueType::Float);
  925. break;
  926. case Js::AsmJsVarType::Which::Int64:
  927. retSlot = GetRegSlotFromInt64Reg(0);
  928. regOpnd = BuildDstOpnd(retSlot, TyInt64);
  929. regOpnd->SetValueType(ValueType::GetInt(false));
  930. break;
  931. case Js::AsmJsRetType::Which::Void:
  932. retSlot = GetRegSlotFromVarReg(0);
  933. regOpnd = BuildDstOpnd(retSlot, TyVar);
  934. break;
  935. default:
  936. {
  937. IRType irType;
  938. ValueType vType;
  939. GetSimdTypesFromAsmType(Js::AsmJsRetType(m_asmFuncInfo->GetRetType()).toType().GetWhich(), &irType, &vType);
  940. retSlot = GetRegSlotFromSimd128Reg(0);
  941. regOpnd = BuildDstOpnd(retSlot, irType);
  942. regOpnd->SetValueType(vType);
  943. }
  944. }
  945. instr->SetSrc1(regOpnd);
  946. AddInstr(instr, offset);
  947. break;
  948. case Js::OpCodeAsmJs::Label:
  949. // NOP
  950. break;
  951. default:
  952. Assume(UNREACHED);
  953. }
  954. }
  955. template <typename SizePolicy>
  956. void
  957. IRBuilderAsmJs::BuildElementSlot(Js::OpCodeAsmJs newOpcode, uint32 offset)
  958. {
  959. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  960. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_ElementSlot<SizePolicy>>();
  961. //TraceIrBuilder(newOpcode, ElementSlot, layout);
  962. BuildElementSlot(newOpcode, offset, layout->SlotIndex, layout->Value, layout->Instance);
  963. }
  964. template <typename SizePolicy>
  965. void
  966. IRBuilderAsmJs::BuildAsmUnsigned1(Js::OpCodeAsmJs newOpcode, uint value)
  967. {
  968. // we do not support counter in loop body ,just read the layout here
  969. m_jnReader.GetLayout<Js::OpLayoutT_AsmUnsigned1<SizePolicy>>();
  970. }
  971. void
  972. IRBuilderAsmJs::BuildElementSlot(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 slotIndex, Js::RegSlot value, Js::RegSlot instance)
  973. {
  974. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  975. Assert(instance == 1 || newOpcode == Js::OpCodeAsmJs::LdArr_Func || newOpcode == Js::OpCodeAsmJs::LdArr_WasmFunc);
  976. Js::RegSlot valueRegSlot;
  977. IR::Opnd * slotOpnd;
  978. IR::RegOpnd * regOpnd;
  979. IR::Instr * instr = nullptr;
  980. WAsmJs::Types type;
  981. IRType irType;
  982. ValueType valueType;
  983. bool isStore = false;
  984. switch (newOpcode)
  985. {
  986. case Js::OpCodeAsmJs::LdSlot:
  987. valueRegSlot = GetRegSlotFromVarReg(value);
  988. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlotArray, TyVar);
  989. regOpnd = BuildDstOpnd(valueRegSlot, TyVar);
  990. instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
  991. break;
  992. case Js::OpCodeAsmJs::LdSlotArr:
  993. valueRegSlot = GetRegSlotFromVarReg(value);
  994. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, TyVar);
  995. regOpnd = BuildDstOpnd(valueRegSlot, TyVar);
  996. instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
  997. break;
  998. case Js::OpCodeAsmJs::LdArr_Func:
  999. {
  1000. IR::RegOpnd * baseOpnd = BuildSrcOpnd(GetRegSlotFromVarReg(instance), TyVar);
  1001. IR::RegOpnd * indexOpnd = BuildSrcOpnd(GetRegSlotFromIntReg(slotIndex), TyUint32);
  1002. IR::IndirOpnd * indirOpnd = IR::IndirOpnd::New(baseOpnd, indexOpnd, TyVar, m_func);
  1003. regOpnd = BuildDstOpnd(GetRegSlotFromVarReg(value), TyVar);
  1004. instr = IR::Instr::New(Js::OpCode::LdAsmJsFunc, regOpnd, indirOpnd, m_func);
  1005. break;
  1006. }
  1007. case Js::OpCodeAsmJs::LdArr_WasmFunc:
  1008. {
  1009. IR::RegOpnd * baseOpnd = BuildSrcOpnd(GetRegSlotFromVarReg(instance), TyVar);
  1010. IR::RegOpnd * indexOpnd = BuildSrcOpnd(GetRegSlotFromIntReg(slotIndex), TyUint32);
  1011. regOpnd = BuildDstOpnd(GetRegSlotFromVarReg(value), TyVar);
  1012. instr = IR::Instr::New(Js::OpCode::LdWasmFunc, regOpnd, baseOpnd, indexOpnd, m_func);
  1013. break;
  1014. }
  1015. case Js::OpCodeAsmJs::StSlot_Int:
  1016. case Js::OpCodeAsmJs::LdSlot_Int:
  1017. type = WAsmJs::INT32;
  1018. irType = TyInt32;
  1019. valueType = ValueType::GetInt(false);
  1020. isStore = newOpcode == Js::OpCodeAsmJs::StSlot_Int;
  1021. goto ProcessGenericSlot;
  1022. case Js::OpCodeAsmJs::StSlot_Long:
  1023. case Js::OpCodeAsmJs::LdSlot_Long:
  1024. type = WAsmJs::INT64;
  1025. irType = TyInt64;
  1026. valueType = ValueType::GetInt(false);
  1027. isStore = newOpcode == Js::OpCodeAsmJs::StSlot_Long;
  1028. goto ProcessGenericSlot;
  1029. case Js::OpCodeAsmJs::StSlot_Flt:
  1030. case Js::OpCodeAsmJs::LdSlot_Flt:
  1031. type = WAsmJs::FLOAT32;
  1032. irType = TyFloat32;
  1033. valueType = ValueType::Float;
  1034. isStore = newOpcode == Js::OpCodeAsmJs::StSlot_Flt;
  1035. goto ProcessGenericSlot;
  1036. case Js::OpCodeAsmJs::StSlot_Db:
  1037. case Js::OpCodeAsmJs::LdSlot_Db:
  1038. type = WAsmJs::FLOAT64;
  1039. irType = TyFloat64;
  1040. valueType = ValueType::Float;
  1041. isStore = newOpcode == Js::OpCodeAsmJs::StSlot_Db;
  1042. goto ProcessGenericSlot;
  1043. case Js::OpCodeAsmJs::Simd128_StSlot_I4:
  1044. case Js::OpCodeAsmJs::Simd128_LdSlot_I4:
  1045. irType = TySimd128I4;
  1046. isStore = newOpcode == Js::OpCodeAsmJs::Simd128_StSlot_I4;
  1047. goto ProcessSimdSlot;
  1048. case Js::OpCodeAsmJs::Simd128_StSlot_B4:
  1049. case Js::OpCodeAsmJs::Simd128_LdSlot_B4:
  1050. irType = TySimd128B4;
  1051. isStore = newOpcode == Js::OpCodeAsmJs::Simd128_StSlot_B4;
  1052. goto ProcessSimdSlot;
  1053. case Js::OpCodeAsmJs::Simd128_StSlot_B8:
  1054. case Js::OpCodeAsmJs::Simd128_LdSlot_B8:
  1055. irType = TySimd128B8;
  1056. isStore = newOpcode == Js::OpCodeAsmJs::Simd128_StSlot_B8;
  1057. goto ProcessSimdSlot;
  1058. case Js::OpCodeAsmJs::Simd128_StSlot_B16:
  1059. case Js::OpCodeAsmJs::Simd128_LdSlot_B16:
  1060. irType = TySimd128B16;
  1061. isStore = newOpcode == Js::OpCodeAsmJs::Simd128_StSlot_B16;
  1062. goto ProcessSimdSlot;
  1063. case Js::OpCodeAsmJs::Simd128_StSlot_F4:
  1064. case Js::OpCodeAsmJs::Simd128_LdSlot_F4:
  1065. irType = TySimd128F4;
  1066. isStore = newOpcode == Js::OpCodeAsmJs::Simd128_StSlot_F4;
  1067. goto ProcessSimdSlot;
  1068. #if 0
  1069. case Js::OpCodeAsmJs::Simd128_StSlot_D2:
  1070. case Js::OpCodeAsmJs::Simd128_LdSlot_D2:
  1071. irType = TySimd128D2;
  1072. isStore = newOpcode == Js::OpCodeAsmJs::Simd128_StSlot_D2;
  1073. goto ProcessSimdSlot;
  1074. #endif // 0
  1075. case Js::OpCodeAsmJs::Simd128_StSlot_I8:
  1076. case Js::OpCodeAsmJs::Simd128_LdSlot_I8:
  1077. irType = TySimd128I8;
  1078. isStore = newOpcode == Js::OpCodeAsmJs::Simd128_StSlot_I8;
  1079. goto ProcessSimdSlot;
  1080. case Js::OpCodeAsmJs::Simd128_StSlot_I16:
  1081. case Js::OpCodeAsmJs::Simd128_LdSlot_I16:
  1082. irType = TySimd128I16;
  1083. isStore = newOpcode == Js::OpCodeAsmJs::Simd128_StSlot_I16;
  1084. goto ProcessSimdSlot;
  1085. case Js::OpCodeAsmJs::Simd128_StSlot_U4:
  1086. case Js::OpCodeAsmJs::Simd128_LdSlot_U4:
  1087. irType = TySimd128U4;
  1088. isStore = newOpcode == Js::OpCodeAsmJs::Simd128_StSlot_U4;
  1089. goto ProcessSimdSlot;
  1090. case Js::OpCodeAsmJs::Simd128_StSlot_U8:
  1091. case Js::OpCodeAsmJs::Simd128_LdSlot_U8:
  1092. irType = TySimd128U8;
  1093. isStore = newOpcode == Js::OpCodeAsmJs::Simd128_StSlot_U8;
  1094. goto ProcessSimdSlot;
  1095. case Js::OpCodeAsmJs::Simd128_StSlot_U16:
  1096. case Js::OpCodeAsmJs::Simd128_LdSlot_U16:
  1097. irType = TySimd128U16;
  1098. isStore = newOpcode == Js::OpCodeAsmJs::Simd128_StSlot_U16;
  1099. goto ProcessSimdSlot;
  1100. default:
  1101. Assume(UNREACHED);
  1102. break;
  1103. ProcessSimdSlot:
  1104. type = WAsmJs::SIMD;
  1105. valueType = GetSimdValueTypeFromIRType(irType);
  1106. ProcessGenericSlot:
  1107. valueRegSlot = GetRegSlotFromTypedReg(value, type);
  1108. slotOpnd = BuildFieldOpnd(AsmJsRegSlots::ModuleMemReg, slotIndex, PropertyKindSlots, irType);
  1109. if (isStore)
  1110. {
  1111. regOpnd = BuildSrcOpnd(valueRegSlot, irType);
  1112. regOpnd->SetValueType(valueType);
  1113. instr = IR::Instr::New(Js::OpCode::StSlot, slotOpnd, regOpnd, m_func);
  1114. }
  1115. else
  1116. {
  1117. regOpnd = BuildDstOpnd(valueRegSlot, irType);
  1118. regOpnd->SetValueType(valueType);
  1119. instr = IR::Instr::New(Js::OpCode::LdSlot, regOpnd, slotOpnd, m_func);
  1120. }
  1121. break;
  1122. }
  1123. AddInstr(instr, offset);
  1124. }
  1125. void
  1126. IRBuilderAsmJs::BuildStartCall(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1127. {
  1128. Assert(!OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1129. const unaligned Js::OpLayoutStartCall * layout = m_jnReader.StartCall();
  1130. IR::RegOpnd * dstOpnd = IR::RegOpnd::New(TyVar, m_func);
  1131. IR::IntConstOpnd * srcOpnd = IR::IntConstOpnd::New(layout->ArgCount, TyInt32, m_func);
  1132. IR::Instr * instr = nullptr;
  1133. StackSym * symDst = nullptr;
  1134. IR::SymOpnd * argDst = nullptr;
  1135. IR::AddrOpnd * addrOpnd = nullptr;
  1136. switch (newOpcode)
  1137. {
  1138. case Js::OpCodeAsmJs::I_StartCall:
  1139. instr = IR::Instr::New(Js::OpCode::StartCall, dstOpnd, srcOpnd, m_func);
  1140. AddInstr(instr, offset);
  1141. // save this so we can calculate arg offsets later on
  1142. m_argOffsetStack->Push(layout->ArgCount);
  1143. m_argStack->Push(instr);
  1144. break;
  1145. case Js::OpCodeAsmJs::StartCall:
  1146. instr = IR::Instr::New(Js::OpCode::StartCall, dstOpnd, srcOpnd, m_func);
  1147. AddInstr(instr, offset);
  1148. m_argStack->Push(instr);
  1149. // also need to add undefined as arg0
  1150. addrOpnd = IR::AddrOpnd::New(m_func->GetScriptContextInfo()->GetUndefinedAddr(), IR::AddrOpndKindDynamicVar, m_func, true);
  1151. addrOpnd->SetValueType(ValueType::Undefined);
  1152. symDst = m_func->m_symTable->GetArgSlotSym(1);
  1153. argDst = IR::SymOpnd::New(symDst, TyVar, m_func);
  1154. instr = IR::Instr::New(Js::OpCode::ArgOut_A, argDst, addrOpnd, m_func);
  1155. AddInstr(instr, offset);
  1156. m_argStack->Push(instr);
  1157. break;
  1158. default:
  1159. Assume(UNREACHED);
  1160. }
  1161. }
  1162. void
  1163. IRBuilderAsmJs::InitializeMemAccessTypeInfo(Js::ArrayBufferView::ViewType viewType, _Out_ MemAccessTypeInfo * typeInfo)
  1164. {
  1165. typeInfo->type = TyInt32;
  1166. typeInfo->valueRegType = WAsmJs::INT32;
  1167. switch (viewType)
  1168. {
  1169. case Js::ArrayBufferView::TYPE_INT8_TO_INT64:
  1170. typeInfo->valueRegType = WAsmJs::INT64;
  1171. case Js::ArrayBufferView::TYPE_INT8:
  1172. typeInfo->arrayType = ValueType::GetObject(ObjectType::Int8Array);
  1173. typeInfo->type = TyInt8;
  1174. break;
  1175. case Js::ArrayBufferView::TYPE_UINT8_TO_INT64:
  1176. typeInfo->valueRegType = WAsmJs::INT64;
  1177. case Js::ArrayBufferView::TYPE_UINT8:
  1178. typeInfo->arrayType = ValueType::GetObject(ObjectType::Uint8Array);
  1179. typeInfo->type = TyUint8;
  1180. break;
  1181. case Js::ArrayBufferView::TYPE_INT16_TO_INT64:
  1182. typeInfo->valueRegType = WAsmJs::INT64;
  1183. case Js::ArrayBufferView::TYPE_INT16:
  1184. typeInfo->arrayType = ValueType::GetObject(ObjectType::Int16Array);
  1185. typeInfo->type = TyInt16;
  1186. break;
  1187. case Js::ArrayBufferView::TYPE_UINT16_TO_INT64:
  1188. typeInfo->valueRegType = WAsmJs::INT64;
  1189. case Js::ArrayBufferView::TYPE_UINT16:
  1190. typeInfo->arrayType = ValueType::GetObject(ObjectType::Uint16Array);
  1191. typeInfo->type = TyUint16;
  1192. break;
  1193. case Js::ArrayBufferView::TYPE_INT32_TO_INT64:
  1194. typeInfo->valueRegType = WAsmJs::INT64;
  1195. case Js::ArrayBufferView::TYPE_INT32:
  1196. typeInfo->arrayType = ValueType::GetObject(ObjectType::Int32Array);
  1197. typeInfo->type = TyInt32;
  1198. break;
  1199. case Js::ArrayBufferView::TYPE_UINT32_TO_INT64:
  1200. typeInfo->valueRegType = WAsmJs::INT64;
  1201. case Js::ArrayBufferView::TYPE_UINT32:
  1202. typeInfo->arrayType = ValueType::GetObject(ObjectType::Uint32Array);
  1203. typeInfo->type = TyUint32;
  1204. break;
  1205. case Js::ArrayBufferView::TYPE_FLOAT32:
  1206. typeInfo->valueRegType = WAsmJs::FLOAT32;
  1207. typeInfo->arrayType = ValueType::GetObject(ObjectType::Float32Array);
  1208. typeInfo->type = TyFloat32;
  1209. break;
  1210. case Js::ArrayBufferView::TYPE_FLOAT64:
  1211. typeInfo->valueRegType = WAsmJs::FLOAT64;
  1212. typeInfo->arrayType = ValueType::GetObject(ObjectType::Float64Array);
  1213. typeInfo->type = TyFloat64;
  1214. break;
  1215. case Js::ArrayBufferView::TYPE_INT64:
  1216. typeInfo->valueRegType = WAsmJs::INT64;
  1217. typeInfo->arrayType = ValueType::GetObject(ObjectType::Int64Array);
  1218. typeInfo->type = TyInt64;
  1219. break;
  1220. default:
  1221. Assume(UNREACHED);
  1222. }
  1223. }
  1224. template <typename SizePolicy>
  1225. void
  1226. IRBuilderAsmJs::BuildWasmMemAccess(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1227. {
  1228. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1229. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_WasmMemAccess<SizePolicy>>();
  1230. BuildWasmMemAccess(newOpcode, offset, layout->SlotIndex, layout->Value, layout->Offset, layout->ViewType);
  1231. }
  1232. void
  1233. IRBuilderAsmJs::BuildWasmMemAccess(Js::OpCodeAsmJs newOpcode, uint32 offset, uint32 slotIndex, Js::RegSlot value, uint32 constOffset, Js::ArrayBufferView::ViewType viewType)
  1234. {
  1235. bool isLd = newOpcode == Js::OpCodeAsmJs::LdArrWasm;
  1236. Js::OpCode op = isLd ? Js::OpCode::LdArrViewElemWasm : Js::OpCode::StArrViewElem;
  1237. MemAccessTypeInfo typeInfo;
  1238. InitializeMemAccessTypeInfo(viewType, &typeInfo);
  1239. Js::RegSlot valueRegSlot = GetRegSlotFromTypedReg(value, typeInfo.valueRegType);
  1240. IR::Instr * instr = nullptr;
  1241. IR::RegOpnd * regOpnd = nullptr;
  1242. IR::IndirOpnd * indirOpnd = nullptr;
  1243. Js::RegSlot indexRegSlot = GetRegSlotFromIntReg(slotIndex);
  1244. IR::RegOpnd * indexOpnd = BuildSrcOpnd(indexRegSlot, TyUint32);
  1245. indirOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::BufferReg, TyVar), constOffset, typeInfo.type, m_func);
  1246. indirOpnd->SetIndexOpnd(indexOpnd);
  1247. indirOpnd->GetBaseOpnd()->SetValueType(typeInfo.arrayType);
  1248. // Setup the value/destination
  1249. if (typeInfo.valueRegType == WAsmJs::FLOAT32 || typeInfo.valueRegType == WAsmJs::FLOAT64)
  1250. {
  1251. Assert(IRType_IsFloat(typeInfo.type));
  1252. regOpnd = !isLd ? BuildSrcOpnd(valueRegSlot, typeInfo.type) : BuildDstOpnd(valueRegSlot, typeInfo.type);
  1253. regOpnd->SetValueType(ValueType::Float);
  1254. }
  1255. else if (typeInfo.valueRegType == WAsmJs::INT64)
  1256. {
  1257. Assert(IRType_IsNativeInt(typeInfo.type));
  1258. regOpnd = !isLd ? BuildSrcOpnd(valueRegSlot, TyInt64) : BuildDstOpnd(valueRegSlot, TyInt64);
  1259. regOpnd->SetValueType(ValueType::GetInt(false));
  1260. }
  1261. else
  1262. {
  1263. Assert(IRType_IsNativeInt(typeInfo.type));
  1264. Assert(typeInfo.valueRegType == WAsmJs::INT32);
  1265. regOpnd = !isLd ? BuildSrcOpnd(valueRegSlot, TyInt32) : BuildDstOpnd(valueRegSlot, TyInt32);
  1266. regOpnd->SetValueType(ValueType::GetInt(false));
  1267. }
  1268. // Create the instruction
  1269. if (isLd)
  1270. {
  1271. instr = IR::Instr::New(op, regOpnd, indirOpnd, m_func);
  1272. }
  1273. else
  1274. {
  1275. instr = IR::Instr::New(op, indirOpnd, regOpnd, m_func);
  1276. }
  1277. #if ENABLE_FAST_ARRAYBUFFER
  1278. if (!CONFIG_FLAG(WasmFastArray))
  1279. #endif
  1280. {
  1281. instr->SetSrc2(BuildSrcOpnd(AsmJsRegSlots::LengthReg, TyUint32));
  1282. }
  1283. AddInstr(instr, offset);
  1284. }
  1285. template <typename SizePolicy>
  1286. void
  1287. IRBuilderAsmJs::BuildAsmTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1288. {
  1289. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1290. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_AsmTypedArr<SizePolicy>>();
  1291. BuildAsmTypedArr(newOpcode, offset, layout->SlotIndex, layout->Value, layout->ViewType);
  1292. }
  1293. void
  1294. IRBuilderAsmJs::BuildAsmTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, uint32 slotIndex, Js::RegSlot value, Js::ArrayBufferView::ViewType viewType)
  1295. {
  1296. bool isLd = newOpcode == Js::OpCodeAsmJs::LdArr || newOpcode == Js::OpCodeAsmJs::LdArrConst;
  1297. Js::OpCode op = isLd ? Js::OpCode::LdArrViewElem : Js::OpCode::StArrViewElem;
  1298. MemAccessTypeInfo typeInfo;
  1299. InitializeMemAccessTypeInfo(viewType, &typeInfo);
  1300. Js::RegSlot valueRegSlot = GetRegSlotFromTypedReg(value, typeInfo.valueRegType);
  1301. IR::Instr * instr = nullptr;
  1302. IR::Instr * maskInstr = nullptr;
  1303. IR::RegOpnd * regOpnd = nullptr;
  1304. IR::IndirOpnd * indirOpnd = nullptr;
  1305. // Get the index
  1306. if (newOpcode == Js::OpCodeAsmJs::LdArr || newOpcode == Js::OpCodeAsmJs::StArr)
  1307. {
  1308. uint32 mask = Js::ArrayBufferView::ViewMask[viewType];
  1309. Js::RegSlot indexRegSlot = GetRegSlotFromIntReg(slotIndex);
  1310. IR::RegOpnd * maskedOpnd = nullptr;
  1311. if (mask != ~0)
  1312. {
  1313. maskedOpnd = IR::RegOpnd::New(TyUint32, m_func);
  1314. maskInstr = IR::Instr::New(Js::OpCode::And_I4, maskedOpnd, BuildSrcOpnd(indexRegSlot, TyInt32), IR::IntConstOpnd::New(mask, TyUint32, m_func), m_func);
  1315. AddInstr(maskInstr, offset);
  1316. }
  1317. else
  1318. {
  1319. maskedOpnd = BuildSrcOpnd(indexRegSlot, TyInt32);
  1320. }
  1321. indirOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::BufferReg, TyVar), maskedOpnd, typeInfo.type, m_func);
  1322. indirOpnd->GetBaseOpnd()->SetValueType(typeInfo.arrayType);
  1323. }
  1324. else
  1325. {
  1326. Assert(newOpcode == Js::OpCodeAsmJs::LdArrConst || newOpcode == Js::OpCodeAsmJs::StArrConst);
  1327. indirOpnd = IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::BufferReg, TyVar), slotIndex, typeInfo.type, m_func);
  1328. indirOpnd->GetBaseOpnd()->SetValueType(typeInfo.arrayType);
  1329. }
  1330. // Setup the value/destination
  1331. if (typeInfo.valueRegType == WAsmJs::FLOAT32 || typeInfo.valueRegType == WAsmJs::FLOAT64)
  1332. {
  1333. Assert(IRType_IsFloat(typeInfo.type));
  1334. regOpnd = !isLd ? BuildSrcOpnd(valueRegSlot, typeInfo.type) : BuildDstOpnd(valueRegSlot, typeInfo.type);
  1335. regOpnd->SetValueType(ValueType::Float);
  1336. }
  1337. else
  1338. {
  1339. Assert(IRType_IsNativeInt(typeInfo.type));
  1340. Assert(typeInfo.valueRegType == WAsmJs::INT32);
  1341. regOpnd = !isLd ? BuildSrcOpnd(valueRegSlot, TyInt32) : BuildDstOpnd(valueRegSlot, TyInt32);
  1342. regOpnd->SetValueType(ValueType::GetInt(false));
  1343. }
  1344. // Create the instruction
  1345. if (isLd)
  1346. {
  1347. instr = IR::Instr::New(op, regOpnd, indirOpnd, m_func);
  1348. }
  1349. else
  1350. {
  1351. instr = IR::Instr::New(op, indirOpnd, regOpnd, m_func);
  1352. }
  1353. #if !ENABLE_FAST_ARRAYBUFFER
  1354. instr->SetSrc2(BuildSrcOpnd(AsmJsRegSlots::LengthReg, TyUint32));
  1355. #endif
  1356. AddInstr(instr, offset);
  1357. }
  1358. template <typename SizePolicy>
  1359. void
  1360. IRBuilderAsmJs::BuildAsmCall(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1361. {
  1362. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1363. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_AsmCall<SizePolicy>>();
  1364. BuildAsmCall(newOpcode, offset, layout->ArgCount, layout->Return, layout->Function, layout->ReturnType);
  1365. }
  1366. void
  1367. IRBuilderAsmJs::BuildAsmCall(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::ArgSlot argCount, Js::RegSlot ret, Js::RegSlot function, int8 returnType)
  1368. {
  1369. #if DBG
  1370. int count = 0;
  1371. #endif
  1372. IR::Instr * instr = nullptr;
  1373. IR::RegOpnd * dstOpnd = nullptr;
  1374. IR::Opnd * srcOpnd = nullptr;
  1375. Js::RegSlot dstRegSlot;
  1376. Js::RegSlot srcRegSlot;
  1377. int32 argOffset = 0;
  1378. switch (newOpcode)
  1379. {
  1380. case Js::OpCodeAsmJs::I_Call:
  1381. srcRegSlot = GetRegSlotFromVarReg(function);
  1382. srcOpnd = BuildSrcOpnd(srcRegSlot, TyVar);
  1383. switch ((Js::AsmJsRetType::Which)returnType)
  1384. {
  1385. case Js::AsmJsRetType::Which::Signed:
  1386. dstRegSlot = GetRegSlotFromIntReg(ret);
  1387. dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1388. dstOpnd->SetValueType(ValueType::GetInt(false));
  1389. break;
  1390. case Js::AsmJsRetType::Which::Float:
  1391. dstRegSlot = GetRegSlotFromFloatReg(ret);
  1392. dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  1393. dstOpnd->SetValueType(ValueType::Float);
  1394. break;
  1395. case Js::AsmJsRetType::Which::Double:
  1396. dstRegSlot = GetRegSlotFromDoubleReg(ret);
  1397. dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
  1398. dstOpnd->SetValueType(ValueType::Float);
  1399. break;
  1400. case Js::AsmJsRetType::Which::Int64:
  1401. dstRegSlot = GetRegSlotFromInt64Reg(ret);
  1402. dstOpnd = BuildDstOpnd(dstRegSlot, TyInt64);
  1403. dstOpnd->SetValueType(ValueType::GetInt(false));
  1404. break;
  1405. case Js::AsmJsRetType::Which::Void:
  1406. break;
  1407. case Js::AsmJsRetType::Which::Float32x4:
  1408. dstRegSlot = GetRegSlotFromSimd128Reg(ret);
  1409. dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  1410. break;
  1411. case Js::AsmJsRetType::Which::Int32x4:
  1412. dstRegSlot = GetRegSlotFromSimd128Reg(ret);
  1413. dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  1414. break;
  1415. case Js::AsmJsRetType::Which::Bool32x4:
  1416. dstRegSlot = GetRegSlotFromSimd128Reg(ret);
  1417. dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128B4);
  1418. break;
  1419. case Js::AsmJsRetType::Which::Bool16x8:
  1420. dstRegSlot = GetRegSlotFromSimd128Reg(ret);
  1421. dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128B8);
  1422. break;
  1423. case Js::AsmJsRetType::Which::Bool8x16:
  1424. dstRegSlot = GetRegSlotFromSimd128Reg(ret);
  1425. dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128B16);
  1426. break;
  1427. case Js::AsmJsRetType::Which::Float64x2:
  1428. dstRegSlot = GetRegSlotFromSimd128Reg(ret);
  1429. dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  1430. break;
  1431. case Js::AsmJsRetType::Which::Int16x8:
  1432. dstRegSlot = GetRegSlotFromSimd128Reg(ret);
  1433. dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I8);
  1434. break;
  1435. case Js::AsmJsRetType::Which::Int8x16:
  1436. dstRegSlot = GetRegSlotFromSimd128Reg(ret);
  1437. dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I16);
  1438. break;
  1439. case Js::AsmJsRetType::Which::Uint32x4:
  1440. dstRegSlot = GetRegSlotFromSimd128Reg(ret);
  1441. dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128U4);
  1442. break;
  1443. case Js::AsmJsRetType::Which::Uint16x8:
  1444. dstRegSlot = GetRegSlotFromSimd128Reg(ret);
  1445. dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128U8);
  1446. break;
  1447. case Js::AsmJsRetType::Which::Uint8x16:
  1448. dstRegSlot = GetRegSlotFromSimd128Reg(ret);
  1449. dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128U16);
  1450. break;
  1451. default:
  1452. Assume(UNREACHED);
  1453. }
  1454. instr = IR::Instr::New(Js::OpCode::AsmJsCallI, m_func);
  1455. instr->SetSrc1(srcOpnd);
  1456. if (dstOpnd)
  1457. {
  1458. instr->SetDst(dstOpnd);
  1459. }
  1460. argOffset = m_argOffsetStack->Pop();
  1461. argOffset -= MachPtr;
  1462. break;
  1463. case Js::OpCodeAsmJs::Call:
  1464. srcRegSlot = GetRegSlotFromVarReg(function);
  1465. srcOpnd = BuildSrcOpnd(srcRegSlot, TyVar);
  1466. dstRegSlot = GetRegSlotFromVarReg(ret);
  1467. dstOpnd = BuildDstOpnd(dstRegSlot, TyVar);
  1468. instr = IR::Instr::New(Js::OpCode::AsmJsCallE, dstOpnd, srcOpnd, m_func);
  1469. break;
  1470. default:
  1471. Assume(UNREACHED);
  1472. }
  1473. AddInstr(instr, offset);
  1474. IR::Instr * argInstr = nullptr;
  1475. IR::Instr * prevInstr = instr;
  1476. for (argInstr = m_argStack->Pop(); argInstr && argInstr->m_opcode != Js::OpCode::StartCall; argInstr = m_argStack->Pop())
  1477. {
  1478. if (newOpcode == Js::OpCodeAsmJs::I_Call)
  1479. {
  1480. #if _M_IX86
  1481. argOffset -= argInstr->GetDst()->GetSize();
  1482. #elif _M_X64
  1483. argOffset -= (argInstr->GetDst()->GetSize() <= MachPtr ? MachPtr : argInstr->GetDst()->GetSize());
  1484. #else
  1485. Assert(UNREACHED);
  1486. #endif
  1487. argInstr->GetDst()->GetStackSym()->m_offset = argOffset;
  1488. }
  1489. // associate the ArgOuts with this call via src2
  1490. prevInstr->SetSrc2(argInstr->GetDst());
  1491. prevInstr = argInstr;
  1492. #if defined(_M_X64)
  1493. if (m_func->IsSIMDEnabled())
  1494. {
  1495. m_tempList->Push(argInstr);
  1496. }
  1497. #endif
  1498. #if DBG
  1499. count++;
  1500. #endif
  1501. }
  1502. Assert(argOffset == 0);
  1503. AnalysisAssert(argInstr);
  1504. prevInstr->SetSrc2(argInstr->GetDst());
  1505. #if defined(_M_X64)
  1506. // Without SIMD vars, all args are Var in size. So offset in Var = arg position in args list.
  1507. // With SIMD, args have variable size, so we need to track argument position in the args list to be able to assign arg register for first four args on x64.
  1508. if (m_func->IsSIMDEnabled())
  1509. {
  1510. for (uint i = 1; !m_tempList->Empty(); i++)
  1511. {
  1512. IR::Instr * instrArg = m_tempList->Pop();
  1513. // record argument position and make room for implicit args
  1514. instrArg->GetDst()->GetStackSym()->m_argPosition = i;
  1515. if (newOpcode == Js::OpCodeAsmJs::I_Call)
  1516. {
  1517. // implicit func obj arg
  1518. instrArg->GetDst()->GetStackSym()->m_argPosition += 1;
  1519. }
  1520. else
  1521. {
  1522. // implicit func obj + callInfo args
  1523. Assert(newOpcode == Js::OpCodeAsmJs::Call);
  1524. instrArg->GetDst()->GetStackSym()->m_argPosition += 2;
  1525. }
  1526. }
  1527. }
  1528. #endif
  1529. if (m_func->m_argSlotsForFunctionsCalled < argCount)
  1530. {
  1531. m_func->m_argSlotsForFunctionsCalled = argCount;
  1532. }
  1533. if (m_asmFuncInfo->UsesHeapBuffer())
  1534. {
  1535. // heap buffer can change for wasm
  1536. #ifdef ENABLE_WASM
  1537. if (m_func->GetJITFunctionBody()->IsWasmFunction())
  1538. {
  1539. BuildHeapBufferReload(offset);
  1540. }
  1541. #endif
  1542. // after foreign function call, we need to make sure that the heap hasn't been detached
  1543. if (newOpcode == Js::OpCodeAsmJs::Call)
  1544. {
  1545. IR::Instr * instrArrayDetachedCheck = IR::Instr::New(Js::OpCode::ArrayDetachedCheck, m_func);
  1546. instrArrayDetachedCheck->SetSrc1(IR::IndirOpnd::New(BuildSrcOpnd(AsmJsRegSlots::ArrayReg, TyVar), Js::ArrayBuffer::GetIsDetachedOffset(), TyInt8, m_func));
  1547. AddInstr(instrArrayDetachedCheck, offset);
  1548. }
  1549. }
  1550. }
  1551. void
  1552. IRBuilderAsmJs::BuildAsmBr(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1553. {
  1554. Assert(!OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1555. const unaligned Js::OpLayoutAsmBr * branchInsn = m_jnReader.AsmBr();
  1556. uint targetOffset = m_jnReader.GetCurrentOffset() + branchInsn->RelativeJumpOffset;
  1557. if (newOpcode == Js::OpCodeAsmJs::EndSwitch_Int)
  1558. {
  1559. m_switchBuilder.EndSwitch(offset, targetOffset);
  1560. return;
  1561. }
  1562. IR::BranchInstr * branchInstr = IR::BranchInstr::New(Js::OpCode::Br, NULL, m_func);
  1563. AddBranchInstr(branchInstr, offset, targetOffset);
  1564. }
  1565. template <typename SizePolicy>
  1566. void
  1567. IRBuilderAsmJs::BuildAsmReg1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  1568. {
  1569. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  1570. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_AsmReg1<SizePolicy>>();
  1571. BuildAsmReg1(newOpcode, offset, layout->R0);
  1572. }
  1573. void
  1574. IRBuilderAsmJs::BuildAsmReg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg)
  1575. {
  1576. if (newOpcode == Js::OpCodeAsmJs::LdUndef)
  1577. {
  1578. Js::RegSlot dstRegSlot = GetRegSlotFromVarReg(dstReg);
  1579. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyVar);
  1580. if (dstOpnd->m_sym->m_isSingleDef)
  1581. {
  1582. dstOpnd->m_sym->m_isConst = true;
  1583. dstOpnd->m_sym->m_isNotInt = true;
  1584. }
  1585. IR::AddrOpnd * addrOpnd = IR::AddrOpnd::New(m_func->GetScriptContextInfo()->GetUndefinedAddr(), IR::AddrOpndKindDynamicVar, m_func, true);
  1586. addrOpnd->SetValueType(ValueType::Undefined);
  1587. IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, addrOpnd, m_func);
  1588. AddInstr(instr, offset);
  1589. }
  1590. else
  1591. {
  1592. Assert(newOpcode == Js::OpCodeAsmJs::CurrentMemory_Int);
  1593. Js::RegSlot dstRegSlot = GetRegSlotFromIntReg(dstReg);
  1594. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1595. IR::IntConstOpnd* constZero = IR::IntConstOpnd::New(0, TyInt32, m_func);
  1596. IR::IntConstOpnd* constSixteen = IR::IntConstOpnd::New(16, TyUint8, m_func);
  1597. IR::Instr * instr = m_asmFuncInfo->UsesHeapBuffer() ?
  1598. IR::Instr::New(Js::OpCode::ShrU_I4, dstOpnd, BuildSrcOpnd(AsmJsRegSlots::LengthReg, TyUint32), constSixteen, m_func) :
  1599. IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, constZero, m_func);
  1600. AddInstr(instr, offset);
  1601. }
  1602. }
  1603. #define BUILD_LAYOUT_IMPL(layout, ...) \
  1604. template <typename SizePolicy> void IRBuilderAsmJs::Build##layout (Js::OpCodeAsmJs newOpcode, uint32 offset) \
  1605. { \
  1606. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));\
  1607. auto _layout = m_jnReader.GetLayout<Js::OpLayoutT_##layout <SizePolicy>>();\
  1608. Build##layout(newOpcode, offset, __VA_ARGS__);\
  1609. }
  1610. #define RegProc(v) v
  1611. #define IntProc(v) GetRegSlotFromIntReg(v)
  1612. #define LongProc(v) GetRegSlotFromInt64Reg(v)
  1613. #define FloatProc(v) GetRegSlotFromFloatReg(v)
  1614. #define DoubleProc(v) GetRegSlotFromDoubleReg(v)
  1615. #define IntConstProc(v) v
  1616. #define LongConstProc(v) v
  1617. #define FloatConstProc(v) v
  1618. #define DoubleConstProc(v) v
  1619. #define Float32x4Proc(v) GetRegSlotFromSimd128Reg(v)
  1620. #define Bool32x4Proc(v) GetRegSlotFromSimd128Reg(v)
  1621. #define Int32x4Proc(v) GetRegSlotFromSimd128Reg(v)
  1622. #define Float64x2Proc(v) GetRegSlotFromSimd128Reg(v)
  1623. #define Int16x8Proc(v) GetRegSlotFromSimd128Reg(v)
  1624. #define Bool16x8Proc(v) GetRegSlotFromSimd128Reg(v)
  1625. #define Int8x16Proc(v) GetRegSlotFromSimd128Reg(v)
  1626. #define Bool8x16Proc(v) GetRegSlotFromSimd128Reg(v)
  1627. #define Uint32x4Proc(v) GetRegSlotFromSimd128Reg(v)
  1628. #define Uint16x8Proc(v) GetRegSlotFromSimd128Reg(v)
  1629. #define Uint8x16Proc(v) GetRegSlotFromSimd128Reg(v)
  1630. #define _PREFIX_HELPER(prefix, index) prefix##index
  1631. #define _PREFIX_NAME(prefix, index) _PREFIX_HELPER(prefix, index)
  1632. #define _M(ti, i) ti##Proc(_layout-> _PREFIX_NAME(LAYOUT_PREFIX_##ti(), i))
  1633. #define LAYOUT_TYPE_WMS_REG2(layout, t0, t1) BUILD_LAYOUT_IMPL(layout, _M(t0, 0), _M(t1, 1))
  1634. #define LAYOUT_TYPE_WMS_REG3(layout, t0, t1, t2) BUILD_LAYOUT_IMPL(layout, _M(t0, 0), _M(t1, 1), _M(t2, 2))
  1635. #define LAYOUT_TYPE_WMS_REG4(layout, t0, t1, t2, t3) BUILD_LAYOUT_IMPL(layout, _M(t0, 0), _M(t1, 1), _M(t2, 2), _M(t3, 3))
  1636. #define LAYOUT_TYPE_WMS_REG5(layout, t0, t1, t2, t3, t4) BUILD_LAYOUT_IMPL(layout, _M(t0, 0), _M(t1, 1), _M(t2, 2), _M(t3, 3), _M(t4, 4))
  1637. #define LAYOUT_TYPE_WMS_REG6(layout, t0, t1, t2, t3, t4, t5) BUILD_LAYOUT_IMPL(layout, _M(t0, 0), _M(t1, 1), _M(t2, 2), _M(t3, 3), _M(t4, 4), _M(t5, 5))
  1638. #define LAYOUT_TYPE_WMS_REG7(layout, t0, t1, t2, t3, t4, t5, t6) BUILD_LAYOUT_IMPL(layout, _M(t0, 0), _M(t1, 1), _M(t2, 2), _M(t3, 3), _M(t4, 4), _M(t5, 5), _M(t6, 6))
  1639. #define LAYOUT_TYPE_WMS_REG9(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8) BUILD_LAYOUT_IMPL(layout, _M(t0, 0), _M(t1, 1), _M(t2, 2), _M(t3, 3), _M(t4, 4), _M(t5, 5), _M(t6, 6), _M(t7, 7), _M(t8, 8))
  1640. #define LAYOUT_TYPE_WMS_REG10(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9) BUILD_LAYOUT_IMPL(layout, _M(t0, 0), _M(t1, 1), _M(t2, 2), _M(t3, 3), _M(t4, 4), _M(t5, 5), _M(t6, 6), _M(t7, 7), _M(t8, 8), _M(t9, 9))
  1641. #define LAYOUT_TYPE_WMS_REG11(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10) BUILD_LAYOUT_IMPL(layout, _M(t0, 0), _M(t1, 1), _M(t2, 2), _M(t3, 3), _M(t4, 4), _M(t5, 5), _M(t6, 6), _M(t7, 7), _M(t8, 8), _M(t9, 9), _M(t10, 10))
  1642. #define LAYOUT_TYPE_WMS_REG17(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16) BUILD_LAYOUT_IMPL(layout, _M(t0, 0), _M(t1, 1), _M(t2, 2), _M(t3, 3), _M(t4, 4), _M(t5, 5), _M(t6, 6), _M(t7, 7), _M(t8, 8), _M(t9, 9), _M(t10, 10), _M(t11, 11), _M(t12, 12), _M(t13, 13), _M(t14, 14), _M(t15, 15), _M(t16, 16))
  1643. #define LAYOUT_TYPE_WMS_REG18(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17) BUILD_LAYOUT_IMPL(layout, _M(t0, 0), _M(t1, 1), _M(t2, 2), _M(t3, 3), _M(t4, 4), _M(t5, 5), _M(t6, 6), _M(t7, 7), _M(t8, 8), _M(t9, 9), _M(t10, 10), _M(t11, 11), _M(t12, 12), _M(t13, 13), _M(t14, 14), _M(t15, 15), _M(t16, 16), _M(t17, 17))
  1644. #define LAYOUT_TYPE_WMS_REG19(layout, t0, t1, t2, t3, t4, t5, t6, t7, t8, t9, t10, t11, t12, t13, t14, t15, t16, t17, t18) BUILD_LAYOUT_IMPL(layout, _M(t0, 0), _M(t1, 1), _M(t2, 2), _M(t3, 3), _M(t4, 4), _M(t5, 5), _M(t6, 6), _M(t7, 7), _M(t8, 8), _M(t9, 9), _M(t10, 10), _M(t11, 11), _M(t12, 12), _M(t13, 13), _M(t14, 14), _M(t15, 15), _M(t16, 16), _M(t17, 17), _M(t18, 18))
  1645. #define EXCLUDE_FRONTEND_LAYOUT
  1646. #include "LayoutTypesAsmJs.h"
  1647. #undef BUILD_LAYOUT_IMPL
  1648. #undef _PREFIX_NAME
  1649. #undef _PREFIX_HELPER
  1650. #undef _M
  1651. #undef RegProc
  1652. #undef IntProc
  1653. #undef LongProc
  1654. #undef FloatProc
  1655. #undef DoubleProc
  1656. #undef IntConstProc
  1657. #undef LongConstProc
  1658. #undef FloatConstProc
  1659. #undef DoubleConstProc
  1660. #undef Float32x4Proc
  1661. #undef Bool32x4Proc
  1662. #undef Int32x4Proc
  1663. #undef Float64x2Proc
  1664. #undef Int16x8Proc
  1665. #undef Bool16x8Proc
  1666. #undef Int8x16Proc
  1667. #undef Bool8x16Proc
  1668. #undef Uint32x4Proc
  1669. #undef Uint16x8Proc
  1670. #undef Uint8x16Proc
  1671. void IRBuilderAsmJs::BuildArgOut(IR::Opnd* srcOpnd, uint32 dstRegSlot, uint32 offset, IRType type, ValueType valueType)
  1672. {
  1673. Js::ArgSlot dstArgSlot = (Js::ArgSlot)dstRegSlot;
  1674. if ((uint32)dstArgSlot != dstRegSlot)
  1675. {
  1676. AssertMsg(UNREACHED, "Arg count too big...");
  1677. Fatal();
  1678. }
  1679. StackSym * symDst = nullptr;
  1680. if (type == TyVar)
  1681. {
  1682. symDst = m_func->m_symTable->GetArgSlotSym(ArgSlotMath::Add(dstArgSlot, 1));
  1683. IR::Opnd * tmpDst = IR::RegOpnd::New(StackSym::New(m_func), TyVar, m_func);
  1684. IR::Instr * instr = IR::Instr::New(Js::OpCode::ToVar, tmpDst, srcOpnd, m_func);
  1685. AddInstr(instr, offset);
  1686. srcOpnd = tmpDst;
  1687. }
  1688. else
  1689. {
  1690. symDst = StackSym::NewArgSlotSym(dstArgSlot, m_func, type);
  1691. symDst->m_allocated = true;
  1692. }
  1693. IR::Opnd * dstOpnd = IR::SymOpnd::New(symDst, type, m_func);
  1694. if (!valueType.IsUninitialized())
  1695. {
  1696. dstOpnd->SetValueType(valueType);
  1697. }
  1698. IR::Instr * instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  1699. AddInstr(instr, offset);
  1700. m_argStack->Push(instr);
  1701. }
  1702. void IRBuilderAsmJs::BuildFromVar(uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot, IRType irType, ValueType valueType)
  1703. {
  1704. IR::RegOpnd * srcOpnd = BuildSrcOpnd(GetRegSlotFromVarReg(srcRegSlot), TyVar);
  1705. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, irType);
  1706. dstOpnd->SetValueType(valueType);
  1707. IR::Instr * instr = IR::Instr::New(Js::OpCode::FromVar, dstOpnd, srcOpnd, m_func);
  1708. AddInstr(instr, offset);
  1709. }
  1710. void
  1711. IRBuilderAsmJs::BuildInt1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  1712. {
  1713. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat64);
  1714. srcOpnd->SetValueType(ValueType::Float);
  1715. IR::RegOpnd * dstOpnd = nullptr;
  1716. switch (newOpcode)
  1717. {
  1718. case Js::OpCodeAsmJs::Conv_DTI:
  1719. dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1720. break;
  1721. case Js::OpCodeAsmJs::Conv_DTU:
  1722. dstOpnd = BuildDstOpnd(dstRegSlot, TyUint32);
  1723. break;
  1724. case Js::OpCodeAsmJs::Conv_Check_DTI:
  1725. case Js::OpCodeAsmJs::Conv_Check_DTU:
  1726. {
  1727. IR::RegOpnd* tmpDst = IR::RegOpnd::New(TyFloat64, m_func);
  1728. tmpDst->SetValueType(ValueType::Float);
  1729. AddInstr(IR::Instr::New(Js::OpCode::TrapIfTruncOverflow, tmpDst, srcOpnd, m_func), offset);
  1730. dstOpnd = BuildDstOpnd(dstRegSlot, newOpcode == Js::OpCodeAsmJs::Conv_Check_DTI ? TyInt32 : TyUint32);
  1731. dstOpnd->m_dontDeadStore = true;
  1732. srcOpnd = tmpDst;
  1733. break;
  1734. }
  1735. default:
  1736. Assume(UNREACHED);
  1737. }
  1738. dstOpnd->SetValueType(ValueType::GetInt(false));
  1739. IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
  1740. AddInstr(instr, offset);
  1741. }
  1742. void
  1743. IRBuilderAsmJs::BuildInt1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  1744. {
  1745. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat32);
  1746. srcOpnd->SetValueType(ValueType::Float);
  1747. IR::RegOpnd * dstOpnd = nullptr;
  1748. Js::OpCode op = Js::OpCode::Nop;
  1749. switch (newOpcode)
  1750. {
  1751. case Js::OpCodeAsmJs::Conv_FTI:
  1752. dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1753. op = Js::OpCode::Conv_Prim;
  1754. break;
  1755. case Js::OpCodeAsmJs::Conv_FTU:
  1756. dstOpnd = BuildDstOpnd(dstRegSlot, TyUint32);
  1757. op = Js::OpCode::Conv_Prim;
  1758. break;
  1759. case Js::OpCodeAsmJs::Reinterpret_FTI:
  1760. dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1761. op = Js::OpCode::Reinterpret_Prim;
  1762. break;
  1763. case Js::OpCodeAsmJs::Conv_Check_FTI:
  1764. case Js::OpCodeAsmJs::Conv_Check_FTU:
  1765. {
  1766. IR::RegOpnd* tmpDst = IR::RegOpnd::New(TyFloat32, m_func);
  1767. tmpDst->SetValueType(ValueType::Float);
  1768. AddInstr(IR::Instr::New(Js::OpCode::TrapIfTruncOverflow, tmpDst, srcOpnd, m_func), offset);
  1769. dstOpnd = BuildDstOpnd(dstRegSlot, newOpcode == Js::OpCodeAsmJs::Conv_Check_FTI ? TyInt32 : TyUint32);
  1770. dstOpnd->m_dontDeadStore = true;
  1771. srcOpnd = tmpDst;
  1772. op = Js::OpCode::Conv_Prim;
  1773. break;
  1774. }
  1775. default:
  1776. Assume(UNREACHED);
  1777. }
  1778. dstOpnd->SetValueType(ValueType::GetInt(false));
  1779. IR::Instr * instr = IR::Instr::New(op, dstOpnd, srcOpnd, m_func);
  1780. AddInstr(instr, offset);
  1781. }
  1782. void
  1783. IRBuilderAsmJs::BuildDouble1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  1784. {
  1785. IR::RegOpnd * srcOpnd = nullptr;
  1786. switch (newOpcode)
  1787. {
  1788. case Js::OpCodeAsmJs::Conv_ITD:
  1789. srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
  1790. break;
  1791. case Js::OpCodeAsmJs::Conv_UTD:
  1792. srcOpnd = BuildSrcOpnd(srcRegSlot, TyUint32);
  1793. break;
  1794. default:
  1795. Assume(UNREACHED);
  1796. }
  1797. srcOpnd->SetValueType(ValueType::GetInt(false));
  1798. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
  1799. dstOpnd->SetValueType(ValueType::Float);
  1800. IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
  1801. AddInstr(instr, offset);
  1802. }
  1803. void
  1804. IRBuilderAsmJs::BuildDouble1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  1805. {
  1806. Assert(newOpcode == Js::OpCodeAsmJs::Conv_FTD);
  1807. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat32);
  1808. srcOpnd->SetValueType(ValueType::Float);
  1809. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
  1810. srcOpnd->SetValueType(ValueType::Float);
  1811. IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
  1812. AddInstr(instr, offset);
  1813. }
  1814. void
  1815. IRBuilderAsmJs::BuildFloat1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  1816. {
  1817. Assert(newOpcode == Js::OpCodeAsmJs::Conv_VTF);
  1818. BuildFromVar(offset, dstRegSlot, srcRegSlot, TyFloat32, ValueType::Float);
  1819. }
  1820. void
  1821. IRBuilderAsmJs::BuildDouble1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  1822. {
  1823. Assert(newOpcode == Js::OpCodeAsmJs::Conv_VTD);
  1824. BuildFromVar(offset, dstRegSlot, srcRegSlot, TyFloat64, ValueType::Float);
  1825. }
  1826. void
  1827. IRBuilderAsmJs::BuildInt1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  1828. {
  1829. Assert(newOpcode == Js::OpCodeAsmJs::Conv_VTI);
  1830. BuildFromVar(offset, dstRegSlot, srcRegSlot, TyInt32, ValueType::GetInt(false));
  1831. }
  1832. void
  1833. IRBuilderAsmJs::BuildReg1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg, Js::RegSlot srcRegSlot)
  1834. {
  1835. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat64);
  1836. srcOpnd->SetValueType(ValueType::Float);
  1837. switch (newOpcode)
  1838. {
  1839. case Js::OpCodeAsmJs::ArgOut_Db:
  1840. BuildArgOut(srcOpnd, dstReg, offset, TyVar);
  1841. break;
  1842. case Js::OpCodeAsmJs::I_ArgOut_Db:
  1843. BuildArgOut(srcOpnd, dstReg, offset, TyFloat64, ValueType::Float);
  1844. break;
  1845. default:
  1846. Assume(UNREACHED);
  1847. }
  1848. }
  1849. void
  1850. IRBuilderAsmJs::BuildReg1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg, Js::RegSlot srcRegSlot)
  1851. {
  1852. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat32);
  1853. srcOpnd->SetValueType(ValueType::Float);
  1854. switch (newOpcode)
  1855. {
  1856. case Js::OpCodeAsmJs::ArgOut_Flt:
  1857. BuildArgOut(srcOpnd, dstReg, offset, TyVar);
  1858. break;
  1859. case Js::OpCodeAsmJs::I_ArgOut_Flt:
  1860. BuildArgOut(srcOpnd, dstReg, offset, TyFloat32, ValueType::Float);
  1861. break;
  1862. default:
  1863. Assume(UNREACHED);
  1864. }
  1865. }
  1866. void
  1867. IRBuilderAsmJs::BuildReg1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg, Js::RegSlot srcRegSlot)
  1868. {
  1869. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
  1870. srcOpnd->SetValueType(ValueType::GetInt(false));
  1871. switch (newOpcode)
  1872. {
  1873. case Js::OpCodeAsmJs::ArgOut_Int:
  1874. BuildArgOut(srcOpnd, dstReg, offset, TyVar);
  1875. break;
  1876. case Js::OpCodeAsmJs::I_ArgOut_Int:
  1877. BuildArgOut(srcOpnd, dstReg, offset, TyInt32, ValueType::GetInt(false));
  1878. break;
  1879. default:
  1880. Assume(UNREACHED);
  1881. }
  1882. }
  1883. void
  1884. IRBuilderAsmJs::BuildInt1Const1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, int constInt)
  1885. {
  1886. Assert(newOpcode == Js::OpCodeAsmJs::Ld_IntConst);
  1887. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1888. dstOpnd->SetValueType(ValueType::GetInt(false));
  1889. IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, IR::IntConstOpnd::New(constInt, TyInt32, m_func), m_func);
  1890. if (dstOpnd->m_sym->IsSingleDef())
  1891. {
  1892. dstOpnd->m_sym->SetIsIntConst(constInt);
  1893. }
  1894. AddInstr(instr, offset);
  1895. }
  1896. void
  1897. IRBuilderAsmJs::BuildReg1IntConst1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot reg1, int constInt)
  1898. {
  1899. Assert(newOpcode == Js::OpCodeAsmJs::CheckSignature);
  1900. IR::RegOpnd * funcReg = BuildSrcOpnd(reg1, TyMachPtr);
  1901. IR::IntConstOpnd * sigIndex = IR::IntConstOpnd::New(constInt, TyInt32, m_func);
  1902. IR::Instr * instr = IR::Instr::New(Js::OpCode::CheckWasmSignature, m_func);
  1903. instr->SetSrc1(funcReg);
  1904. instr->SetSrc2(sigIndex);
  1905. AddInstr(instr, offset);
  1906. }
  1907. void
  1908. IRBuilderAsmJs::BuildFloat1Const1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, float constVal)
  1909. {
  1910. Assert(newOpcode == Js::OpCodeAsmJs::Ld_FltConst);
  1911. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  1912. dstOpnd->SetValueType(ValueType::Float);
  1913. IR::Instr * instr = IR::Instr::New(Js::OpCode::LdC_F8_R8, dstOpnd, IR::FloatConstOpnd::New(constVal, TyFloat32, m_func), m_func);
  1914. AddInstr(instr, offset);
  1915. }
  1916. void
  1917. IRBuilderAsmJs::BuildDouble1Const1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, double constVal)
  1918. {
  1919. Assert(newOpcode == Js::OpCodeAsmJs::Ld_DbConst);
  1920. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
  1921. dstOpnd->SetValueType(ValueType::Float);
  1922. IR::Instr * instr = IR::Instr::New(Js::OpCode::LdC_F8_R8, dstOpnd, IR::FloatConstOpnd::New(constVal, TyFloat64, m_func), m_func);
  1923. AddInstr(instr, offset);
  1924. }
  1925. void
  1926. IRBuilderAsmJs::BuildInt1Double2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot)
  1927. {
  1928. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat64);
  1929. src1Opnd->SetValueType(ValueType::Float);
  1930. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat64);
  1931. src2Opnd->SetValueType(ValueType::Float);
  1932. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1933. dstOpnd->SetValueType(ValueType::GetInt(false));
  1934. IR::Instr * instr = nullptr;
  1935. switch (newOpcode)
  1936. {
  1937. case Js::OpCodeAsmJs::CmLt_Db:
  1938. instr = IR::Instr::New(Js::OpCode::CmLt_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1939. break;
  1940. case Js::OpCodeAsmJs::CmLe_Db:
  1941. instr = IR::Instr::New(Js::OpCode::CmLe_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1942. break;
  1943. case Js::OpCodeAsmJs::CmGt_Db:
  1944. instr = IR::Instr::New(Js::OpCode::CmGt_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1945. break;
  1946. case Js::OpCodeAsmJs::CmGe_Db:
  1947. instr = IR::Instr::New(Js::OpCode::CmGe_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1948. break;
  1949. case Js::OpCodeAsmJs::CmEq_Db:
  1950. instr = IR::Instr::New(Js::OpCode::CmEq_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1951. break;
  1952. case Js::OpCodeAsmJs::CmNe_Db:
  1953. instr = IR::Instr::New(Js::OpCode::CmNeq_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1954. break;
  1955. default:
  1956. Assume(UNREACHED);
  1957. }
  1958. AddInstr(instr, offset);
  1959. }
  1960. void
  1961. IRBuilderAsmJs::BuildInt1Float2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot)
  1962. {
  1963. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
  1964. src1Opnd->SetValueType(ValueType::Float);
  1965. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat32);
  1966. src2Opnd->SetValueType(ValueType::Float);
  1967. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  1968. dstOpnd->SetValueType(ValueType::GetInt(false));
  1969. IR::Instr * instr = nullptr;
  1970. switch (newOpcode)
  1971. {
  1972. case Js::OpCodeAsmJs::CmLt_Flt:
  1973. instr = IR::Instr::New(Js::OpCode::CmLt_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1974. break;
  1975. case Js::OpCodeAsmJs::CmLe_Flt:
  1976. instr = IR::Instr::New(Js::OpCode::CmLe_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1977. break;
  1978. case Js::OpCodeAsmJs::CmGt_Flt:
  1979. instr = IR::Instr::New(Js::OpCode::CmGt_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1980. break;
  1981. case Js::OpCodeAsmJs::CmGe_Flt:
  1982. instr = IR::Instr::New(Js::OpCode::CmGe_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1983. break;
  1984. case Js::OpCodeAsmJs::CmEq_Flt:
  1985. instr = IR::Instr::New(Js::OpCode::CmEq_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1986. break;
  1987. case Js::OpCodeAsmJs::CmNe_Flt:
  1988. instr = IR::Instr::New(Js::OpCode::CmNeq_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  1989. break;
  1990. default:
  1991. Assume(UNREACHED);
  1992. }
  1993. AddInstr(instr, offset);
  1994. }
  1995. void
  1996. IRBuilderAsmJs::BuildInt2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  1997. {
  1998. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
  1999. srcOpnd->SetValueType(ValueType::GetInt(false));
  2000. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  2001. dstOpnd->SetValueType(ValueType::GetInt(false));
  2002. IR::Instr * instr = nullptr;
  2003. switch (newOpcode)
  2004. {
  2005. case Js::OpCodeAsmJs::BeginSwitch_Int:
  2006. m_switchBuilder.BeginSwitch();
  2007. // fall-through
  2008. case Js::OpCodeAsmJs::Ld_Int:
  2009. instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, srcOpnd, m_func);
  2010. break;
  2011. case Js::OpCodeAsmJs::Neg_Int:
  2012. instr = IR::Instr::New(Js::OpCode::Neg_I4, dstOpnd, srcOpnd, m_func);
  2013. break;
  2014. case Js::OpCodeAsmJs::Not_Int:
  2015. instr = IR::Instr::New(Js::OpCode::Not_I4, dstOpnd, srcOpnd, m_func);
  2016. break;
  2017. case Js::OpCodeAsmJs::LogNot_Int:
  2018. instr = IR::Instr::New(Js::OpCode::CmEq_I4, dstOpnd, srcOpnd, IR::IntConstOpnd::New(0, TyInt32, m_func), m_func);
  2019. break;
  2020. case Js::OpCodeAsmJs::Conv_ITB:
  2021. instr = IR::Instr::New(Js::OpCode::CmNeq_I4, dstOpnd, srcOpnd, IR::IntConstOpnd::New(0, TyInt32, m_func), m_func);
  2022. break;
  2023. case Js::OpCodeAsmJs::Abs_Int:
  2024. instr = IR::Instr::New(Js::OpCode::InlineMathAbs, dstOpnd, srcOpnd, m_func);
  2025. break;
  2026. case Js::OpCodeAsmJs::Clz32_Int:
  2027. instr = IR::Instr::New(Js::OpCode::InlineMathClz, dstOpnd, srcOpnd, m_func);
  2028. break;
  2029. case Js::OpCodeAsmJs::Ctz_Int:
  2030. instr = IR::Instr::New(Js::OpCode::Ctz, dstOpnd, srcOpnd, m_func);
  2031. break;
  2032. case Js::OpCodeAsmJs::I_Conv_VTI:
  2033. instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, srcOpnd, m_func);
  2034. break;
  2035. case Js::OpCodeAsmJs::PopCnt_Int:
  2036. instr = IR::Instr::New(Js::OpCode::PopCnt, dstOpnd, srcOpnd, m_func);
  2037. break;
  2038. case Js::OpCodeAsmJs::Return_Int:
  2039. instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, srcOpnd, m_func);
  2040. if (m_func->IsLoopBody())
  2041. {
  2042. IR::Instr* slotInstr = GenerateStSlotForReturn(srcOpnd, IRType::TyInt32);
  2043. AddInstr(slotInstr, offset);
  2044. }
  2045. break;
  2046. case Js::OpCodeAsmJs::Eqz_Int:
  2047. instr = IR::Instr::New(Js::OpCode::CmEq_I4, dstOpnd, srcOpnd, IR::IntConstOpnd::New(0, TyInt32, m_func), m_func);
  2048. break;
  2049. case Js::OpCodeAsmJs::GrowMemory:
  2050. instr = IR::Instr::New(Js::OpCode::GrowWasmMemory, dstOpnd, BuildSrcOpnd(AsmJsRegSlots::WasmMemoryReg, TyVar), srcOpnd, m_func);
  2051. break;
  2052. default:
  2053. Assume(UNREACHED);
  2054. }
  2055. AddInstr(instr, offset);
  2056. if (newOpcode == Js::OpCodeAsmJs::GrowMemory)
  2057. {
  2058. BuildHeapBufferReload(offset);
  2059. }
  2060. }
  2061. IR::RegOpnd* IRBuilderAsmJs::BuildTrapIfZero(IR::RegOpnd* srcOpnd, uint32 offset)
  2062. {
  2063. IR::RegOpnd* newSrc = IR::RegOpnd::New(srcOpnd->GetType(), m_func);
  2064. newSrc->SetValueType(ValueType::GetInt(false));
  2065. AddInstr(IR::Instr::New(Js::OpCode::TrapIfZero, newSrc, srcOpnd, m_func), offset);
  2066. return newSrc;
  2067. }
  2068. IR::RegOpnd* IRBuilderAsmJs::BuildTrapIfMinIntOverNegOne(IR::RegOpnd* src1Opnd, IR::RegOpnd* src2Opnd, uint32 offset)
  2069. {
  2070. IR::RegOpnd* newSrc = IR::RegOpnd::New(src2Opnd->GetType(), m_func);
  2071. newSrc->SetValueType(ValueType::GetInt(false));
  2072. AddInstr(IR::Instr::New(Js::OpCode::TrapIfMinIntOverNegOne, newSrc, src1Opnd, src2Opnd, m_func), offset);
  2073. return newSrc;
  2074. }
  2075. void
  2076. IRBuilderAsmJs::BuildInt3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot)
  2077. {
  2078. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
  2079. src1Opnd->SetValueType(ValueType::GetInt(false));
  2080. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  2081. src2Opnd->SetValueType(ValueType::GetInt(false));
  2082. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  2083. dstOpnd->SetValueType(ValueType::GetInt(false));
  2084. IR::Instr * instr = nullptr;
  2085. switch (newOpcode)
  2086. {
  2087. case Js::OpCodeAsmJs::Add_Int:
  2088. instr = IR::Instr::New(Js::OpCode::Add_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2089. break;
  2090. case Js::OpCodeAsmJs::Sub_Int:
  2091. instr = IR::Instr::New(Js::OpCode::Sub_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2092. break;
  2093. case Js::OpCodeAsmJs::Mul_Int:
  2094. instr = IR::Instr::New(Js::OpCode::Mul_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2095. break;
  2096. case Js::OpCodeAsmJs::Div_Trap_UInt:
  2097. src1Opnd->SetType(TyUint32);
  2098. src2Opnd->SetType(TyUint32);
  2099. // Fall through for trap
  2100. case Js::OpCodeAsmJs::Div_Trap_Int:
  2101. #ifdef _M_X64
  2102. src2Opnd = BuildTrapIfZero(src2Opnd, offset);
  2103. if (newOpcode == Js::OpCodeAsmJs::Div_Trap_Int)
  2104. {
  2105. src1Opnd = BuildTrapIfMinIntOverNegOne(src1Opnd, src2Opnd, offset);
  2106. }
  2107. #endif
  2108. instr = IR::Instr::New(newOpcode == Js::OpCodeAsmJs::Div_Trap_UInt ? Js::OpCode::DivU_I4 : Js::OpCode::Div_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2109. break;
  2110. case Js::OpCodeAsmJs::Div_UInt:
  2111. src1Opnd->SetType(TyUint32);
  2112. src2Opnd->SetType(TyUint32);
  2113. instr = IR::Instr::New(Js::OpCode::DivU_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2114. break;
  2115. case Js::OpCodeAsmJs::Div_Int:
  2116. instr = IR::Instr::New(Js::OpCode::Div_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2117. break;
  2118. case Js::OpCodeAsmJs::Rem_Trap_UInt:
  2119. src1Opnd->SetType(TyUint32);
  2120. src2Opnd->SetType(TyUint32);
  2121. // Fall through for trap
  2122. case Js::OpCodeAsmJs::Rem_Trap_Int:
  2123. #ifdef _M_X64
  2124. src2Opnd = BuildTrapIfZero(src2Opnd, offset);
  2125. #endif
  2126. instr = IR::Instr::New(newOpcode == Js::OpCodeAsmJs::Rem_Trap_UInt ? Js::OpCode::RemU_I4 : Js::OpCode::Rem_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2127. break;
  2128. case Js::OpCodeAsmJs::Rem_UInt:
  2129. src1Opnd->SetType(TyUint32);
  2130. src2Opnd->SetType(TyUint32);
  2131. instr = IR::Instr::New(Js::OpCode::RemU_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2132. break;
  2133. case Js::OpCodeAsmJs::Rem_Int:
  2134. instr = IR::Instr::New(Js::OpCode::Rem_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2135. break;
  2136. case Js::OpCodeAsmJs::And_Int:
  2137. instr = IR::Instr::New(Js::OpCode::And_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2138. break;
  2139. case Js::OpCodeAsmJs::Or_Int:
  2140. instr = IR::Instr::New(Js::OpCode::Or_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2141. break;
  2142. case Js::OpCodeAsmJs::Xor_Int:
  2143. instr = IR::Instr::New(Js::OpCode::Xor_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2144. break;
  2145. case Js::OpCodeAsmJs::Shl_Int:
  2146. instr = IR::Instr::New(Js::OpCode::Shl_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2147. break;
  2148. case Js::OpCodeAsmJs::Shr_Int:
  2149. instr = IR::Instr::New(Js::OpCode::Shr_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2150. break;
  2151. case Js::OpCodeAsmJs::Shr_UInt:
  2152. instr = IR::Instr::New(Js::OpCode::ShrU_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2153. break;
  2154. case Js::OpCodeAsmJs::CmLt_Int:
  2155. instr = IR::Instr::New(Js::OpCode::CmLt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2156. break;
  2157. case Js::OpCodeAsmJs::CmLe_Int:
  2158. instr = IR::Instr::New(Js::OpCode::CmLe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2159. break;
  2160. case Js::OpCodeAsmJs::CmGt_Int:
  2161. instr = IR::Instr::New(Js::OpCode::CmGt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2162. break;
  2163. case Js::OpCodeAsmJs::CmGe_Int:
  2164. instr = IR::Instr::New(Js::OpCode::CmGe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2165. break;
  2166. case Js::OpCodeAsmJs::CmEq_Int:
  2167. instr = IR::Instr::New(Js::OpCode::CmEq_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2168. break;
  2169. case Js::OpCodeAsmJs::CmNe_Int:
  2170. instr = IR::Instr::New(Js::OpCode::CmNeq_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2171. break;
  2172. case Js::OpCodeAsmJs::CmLt_UInt:
  2173. instr = IR::Instr::New(Js::OpCode::CmUnLt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2174. break;
  2175. case Js::OpCodeAsmJs::CmLe_UInt:
  2176. instr = IR::Instr::New(Js::OpCode::CmUnLe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2177. break;
  2178. case Js::OpCodeAsmJs::CmGt_UInt:
  2179. instr = IR::Instr::New(Js::OpCode::CmUnGt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2180. break;
  2181. case Js::OpCodeAsmJs::CmGe_UInt:
  2182. instr = IR::Instr::New(Js::OpCode::CmUnGe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2183. break;
  2184. case Js::OpCodeAsmJs::Min_Int:
  2185. instr = IR::Instr::New(Js::OpCode::InlineMathMin, dstOpnd, src1Opnd, src2Opnd, m_func);
  2186. break;
  2187. case Js::OpCodeAsmJs::Max_Int:
  2188. instr = IR::Instr::New(Js::OpCode::InlineMathMax, dstOpnd, src1Opnd, src2Opnd, m_func);
  2189. break;
  2190. case Js::OpCodeAsmJs::Imul_Int:
  2191. instr = IR::Instr::New(Js::OpCode::InlineMathImul, dstOpnd, src1Opnd, src2Opnd, m_func);
  2192. break;
  2193. case Js::OpCodeAsmJs::Rol_Int:
  2194. instr = IR::Instr::New(Js::OpCode::Rol_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2195. break;
  2196. case Js::OpCodeAsmJs::Ror_Int:
  2197. instr = IR::Instr::New(Js::OpCode::Ror_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2198. break;
  2199. default:
  2200. Assume(UNREACHED);
  2201. }
  2202. AddInstr(instr, offset);
  2203. }
  2204. void
  2205. IRBuilderAsmJs::BuildDouble2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  2206. {
  2207. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat64);
  2208. srcOpnd->SetValueType(ValueType::Float);
  2209. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
  2210. dstOpnd->SetValueType(ValueType::Float);
  2211. IR::Instr * instr = nullptr;
  2212. switch (newOpcode)
  2213. {
  2214. case Js::OpCodeAsmJs::Ld_Db:
  2215. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  2216. break;
  2217. case Js::OpCodeAsmJs::Neg_Db:
  2218. instr = IR::Instr::New(Js::OpCode::Neg_A, dstOpnd, srcOpnd, m_func);
  2219. break;
  2220. case Js::OpCodeAsmJs::Sin_Db:
  2221. instr = IR::Instr::New(Js::OpCode::InlineMathSin, dstOpnd, srcOpnd, m_func);
  2222. break;
  2223. case Js::OpCodeAsmJs::Cos_Db:
  2224. instr = IR::Instr::New(Js::OpCode::InlineMathCos, dstOpnd, srcOpnd, m_func);
  2225. break;
  2226. case Js::OpCodeAsmJs::Tan_Db:
  2227. instr = IR::Instr::New(Js::OpCode::InlineMathTan, dstOpnd, srcOpnd, m_func);
  2228. break;
  2229. case Js::OpCodeAsmJs::Asin_Db:
  2230. instr = IR::Instr::New(Js::OpCode::InlineMathAsin, dstOpnd, srcOpnd, m_func);
  2231. break;
  2232. case Js::OpCodeAsmJs::Acos_Db:
  2233. instr = IR::Instr::New(Js::OpCode::InlineMathAcos, dstOpnd, srcOpnd, m_func);
  2234. break;
  2235. case Js::OpCodeAsmJs::Atan_Db:
  2236. instr = IR::Instr::New(Js::OpCode::InlineMathAtan, dstOpnd, srcOpnd, m_func);
  2237. break;
  2238. case Js::OpCodeAsmJs::Abs_Db:
  2239. instr = IR::Instr::New(Js::OpCode::InlineMathAbs, dstOpnd, srcOpnd, m_func);
  2240. break;
  2241. case Js::OpCodeAsmJs::Ceil_Db:
  2242. instr = IR::Instr::New(Js::OpCode::InlineMathCeil, dstOpnd, srcOpnd, m_func);
  2243. break;
  2244. case Js::OpCodeAsmJs::Floor_Db:
  2245. instr = IR::Instr::New(Js::OpCode::InlineMathFloor, dstOpnd, srcOpnd, m_func);
  2246. break;
  2247. case Js::OpCodeAsmJs::Exp_Db:
  2248. instr = IR::Instr::New(Js::OpCode::InlineMathExp, dstOpnd, srcOpnd, m_func);
  2249. break;
  2250. case Js::OpCodeAsmJs::Log_Db:
  2251. instr = IR::Instr::New(Js::OpCode::InlineMathLog, dstOpnd, srcOpnd, m_func);
  2252. break;
  2253. case Js::OpCodeAsmJs::Sqrt_Db:
  2254. instr = IR::Instr::New(Js::OpCode::InlineMathSqrt, dstOpnd, srcOpnd, m_func);
  2255. break;
  2256. case Js::OpCodeAsmJs::Return_Db:
  2257. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  2258. if (m_func->IsLoopBody())
  2259. {
  2260. IR::Instr* slotInstr = GenerateStSlotForReturn(srcOpnd, IRType::TyFloat64);
  2261. AddInstr(slotInstr, offset);
  2262. }
  2263. break;
  2264. case Js::OpCodeAsmJs::I_Conv_VTD:
  2265. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  2266. break;
  2267. case Js::OpCodeAsmJs::Trunc_Db:
  2268. instr = IR::Instr::New(Js::OpCode::Trunc_A, dstOpnd, srcOpnd, m_func);
  2269. break;
  2270. case Js::OpCodeAsmJs::Nearest_Db:
  2271. instr = IR::Instr::New(Js::OpCode::Nearest_A, dstOpnd, srcOpnd, m_func);
  2272. break;
  2273. default:
  2274. Assume(UNREACHED);
  2275. }
  2276. AddInstr(instr, offset);
  2277. }
  2278. void
  2279. IRBuilderAsmJs::BuildFloat2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  2280. {
  2281. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat32);
  2282. srcOpnd->SetValueType(ValueType::Float);
  2283. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  2284. dstOpnd->SetValueType(ValueType::Float);
  2285. IR::Instr * instr = nullptr;
  2286. switch (newOpcode)
  2287. {
  2288. case Js::OpCodeAsmJs::Ld_Flt:
  2289. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  2290. break;
  2291. case Js::OpCodeAsmJs::Neg_Flt:
  2292. instr = IR::Instr::New(Js::OpCode::Neg_A, dstOpnd, srcOpnd, m_func);
  2293. break;
  2294. case Js::OpCodeAsmJs::Ceil_Flt:
  2295. instr = IR::Instr::New(Js::OpCode::InlineMathCeil, dstOpnd, srcOpnd, m_func);
  2296. break;
  2297. case Js::OpCodeAsmJs::Floor_Flt:
  2298. instr = IR::Instr::New(Js::OpCode::InlineMathFloor, dstOpnd, srcOpnd, m_func);
  2299. break;
  2300. case Js::OpCodeAsmJs::Sqrt_Flt:
  2301. instr = IR::Instr::New(Js::OpCode::InlineMathSqrt, dstOpnd, srcOpnd, m_func);
  2302. break;
  2303. case Js::OpCodeAsmJs::Abs_Flt:
  2304. instr = IR::Instr::New(Js::OpCode::InlineMathAbs, dstOpnd, srcOpnd, m_func);
  2305. break;
  2306. case Js::OpCodeAsmJs::Fround_Flt:
  2307. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  2308. break;
  2309. case Js::OpCodeAsmJs::Return_Flt:
  2310. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  2311. if (m_func->IsLoopBody())
  2312. {
  2313. IR::Instr* slotInstr = GenerateStSlotForReturn(srcOpnd, IRType::TyFloat32);
  2314. AddInstr(slotInstr, offset);
  2315. }
  2316. break;
  2317. case Js::OpCodeAsmJs::I_Conv_VTF:
  2318. instr = IR::Instr::New(Js::OpCode::Ld_A, dstOpnd, srcOpnd, m_func);
  2319. break;
  2320. case Js::OpCodeAsmJs::Trunc_Flt:
  2321. instr = IR::Instr::New(Js::OpCode::Trunc_A, dstOpnd, srcOpnd, m_func);
  2322. break;
  2323. case Js::OpCodeAsmJs::Nearest_Flt:
  2324. instr = IR::Instr::New(Js::OpCode::Nearest_A, dstOpnd, srcOpnd, m_func);
  2325. break;
  2326. default:
  2327. Assume(UNREACHED);
  2328. }
  2329. AddInstr(instr, offset);
  2330. }
  2331. void
  2332. IRBuilderAsmJs::BuildFloat3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot)
  2333. {
  2334. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
  2335. src1Opnd->SetValueType(ValueType::Float);
  2336. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat32);
  2337. src2Opnd->SetValueType(ValueType::Float);
  2338. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  2339. dstOpnd->SetValueType(ValueType::Float);
  2340. IR::Instr * instr = nullptr;
  2341. switch (newOpcode)
  2342. {
  2343. case Js::OpCodeAsmJs::Add_Flt:
  2344. instr = IR::Instr::New(Js::OpCode::Add_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2345. break;
  2346. case Js::OpCodeAsmJs::Sub_Flt:
  2347. instr = IR::Instr::New(Js::OpCode::Sub_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2348. break;
  2349. case Js::OpCodeAsmJs::Mul_Flt:
  2350. instr = IR::Instr::New(Js::OpCode::Mul_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2351. break;
  2352. case Js::OpCodeAsmJs::Div_Flt:
  2353. instr = IR::Instr::New(Js::OpCode::Div_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2354. break;
  2355. case Js::OpCodeAsmJs::Copysign_Flt:
  2356. instr = IR::Instr::New(Js::OpCode::Copysign_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2357. break;
  2358. case Js::OpCodeAsmJs::Min_Flt:
  2359. instr = IR::Instr::New(Js::OpCode::InlineMathMin, dstOpnd, src1Opnd, src2Opnd, m_func);
  2360. break;
  2361. case Js::OpCodeAsmJs::Max_Flt:
  2362. instr = IR::Instr::New(Js::OpCode::InlineMathMax, dstOpnd, src1Opnd, src2Opnd, m_func);
  2363. break;
  2364. default:
  2365. Assume(UNREACHED);
  2366. }
  2367. AddInstr(instr, offset);
  2368. }
  2369. void
  2370. IRBuilderAsmJs::BuildFloat1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  2371. {
  2372. Assert(newOpcode == Js::OpCodeAsmJs::Fround_Db);
  2373. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyFloat64);
  2374. srcOpnd->SetValueType(ValueType::Float);
  2375. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  2376. dstOpnd->SetValueType(ValueType::Float);
  2377. IR::Instr * instr = IR::Instr::New(Js::OpCode::InlineMathFround, dstOpnd, srcOpnd, m_func);
  2378. AddInstr(instr, offset);
  2379. }
  2380. void
  2381. IRBuilderAsmJs::BuildFloat1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  2382. {
  2383. Assert(newOpcode == Js::OpCodeAsmJs::Fround_Int || newOpcode == Js::OpCodeAsmJs::Conv_UTF || newOpcode == Js::OpCodeAsmJs::Reinterpret_ITF);
  2384. Js::OpCode op = Js::OpCode::Conv_Prim;
  2385. IR::RegOpnd * srcOpnd = nullptr;
  2386. switch (newOpcode)
  2387. {
  2388. case Js::OpCodeAsmJs::Fround_Int:
  2389. srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
  2390. break;
  2391. case Js::OpCodeAsmJs::Conv_UTF:
  2392. srcOpnd = BuildSrcOpnd(srcRegSlot, TyUint32);
  2393. break;
  2394. case Js::OpCodeAsmJs::Reinterpret_ITF:
  2395. srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
  2396. op = Js::OpCode::Reinterpret_Prim;
  2397. break;
  2398. default:
  2399. Assume(UNREACHED);
  2400. }
  2401. srcOpnd->SetValueType(ValueType::GetInt(false));
  2402. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  2403. dstOpnd->SetValueType(ValueType::Float);
  2404. IR::Instr * instr = IR::Instr::New(op, dstOpnd, srcOpnd, m_func);
  2405. AddInstr(instr, offset);
  2406. }
  2407. void
  2408. IRBuilderAsmJs::BuildDouble3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot)
  2409. {
  2410. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat64);
  2411. src1Opnd->SetValueType(ValueType::Float);
  2412. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat64);
  2413. src2Opnd->SetValueType(ValueType::Float);
  2414. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
  2415. dstOpnd->SetValueType(ValueType::Float);
  2416. IR::Instr * instr = nullptr;
  2417. switch (newOpcode)
  2418. {
  2419. case Js::OpCodeAsmJs::Add_Db:
  2420. instr = IR::Instr::New(Js::OpCode::Add_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2421. break;
  2422. case Js::OpCodeAsmJs::Sub_Db:
  2423. instr = IR::Instr::New(Js::OpCode::Sub_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2424. break;
  2425. case Js::OpCodeAsmJs::Mul_Db:
  2426. instr = IR::Instr::New(Js::OpCode::Mul_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2427. break;
  2428. case Js::OpCodeAsmJs::Div_Db:
  2429. instr = IR::Instr::New(Js::OpCode::Div_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2430. break;
  2431. case Js::OpCodeAsmJs::Rem_Db:
  2432. instr = IR::Instr::New(Js::OpCode::Rem_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2433. break;
  2434. case Js::OpCodeAsmJs::Pow_Db:
  2435. instr = IR::Instr::New(Js::OpCode::InlineMathPow, dstOpnd, src1Opnd, src2Opnd, m_func);
  2436. break;
  2437. case Js::OpCodeAsmJs::Atan2_Db:
  2438. instr = IR::Instr::New(Js::OpCode::InlineMathAtan2, dstOpnd, src1Opnd, src2Opnd, m_func);
  2439. break;
  2440. case Js::OpCodeAsmJs::Min_Db:
  2441. instr = IR::Instr::New(Js::OpCode::InlineMathMin, dstOpnd, src1Opnd, src2Opnd, m_func);
  2442. break;
  2443. case Js::OpCodeAsmJs::Max_Db:
  2444. instr = IR::Instr::New(Js::OpCode::InlineMathMax, dstOpnd, src1Opnd, src2Opnd, m_func);
  2445. break;
  2446. case Js::OpCodeAsmJs::Copysign_Db:
  2447. instr = IR::Instr::New(Js::OpCode::Copysign_A, dstOpnd, src1Opnd, src2Opnd, m_func);
  2448. break;
  2449. default:
  2450. Assume(UNREACHED);
  2451. }
  2452. AddInstr(instr, offset);
  2453. }
  2454. template <typename SizePolicy>
  2455. void
  2456. IRBuilderAsmJs::BuildBrInt1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2457. {
  2458. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2459. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_BrInt1<SizePolicy>>();
  2460. BuildBrInt1(newOpcode, offset, layout->RelativeJumpOffset, layout->I1);
  2461. }
  2462. void
  2463. IRBuilderAsmJs::BuildBrInt1(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, Js::RegSlot src)
  2464. {
  2465. Js::OpCode op = Js::OpCode::Nop;
  2466. switch (newOpcode)
  2467. {
  2468. case Js::OpCodeAsmJs::BrTrue_Int:
  2469. op = Js::OpCode::BrTrue_I4;
  2470. break;
  2471. case Js::OpCodeAsmJs::BrFalse_Int:
  2472. op = Js::OpCode::BrFalse_I4;
  2473. break;
  2474. default:
  2475. Assume(UNREACHED);
  2476. }
  2477. Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(src);
  2478. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
  2479. src1Opnd->SetValueType(ValueType::GetInt(false));
  2480. uint targetOffset = m_jnReader.GetCurrentOffset() + relativeOffset;
  2481. IR::BranchInstr * branchInstr = IR::BranchInstr::New(op, nullptr, src1Opnd, m_func);
  2482. AddBranchInstr(branchInstr, offset, targetOffset);
  2483. }
  2484. template <typename SizePolicy>
  2485. void
  2486. IRBuilderAsmJs::BuildBrInt2(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2487. {
  2488. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2489. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_BrInt2<SizePolicy>>();
  2490. BuildBrInt2(newOpcode, offset, layout->RelativeJumpOffset, layout->I1, layout->I2);
  2491. }
  2492. template <typename SizePolicy>
  2493. void
  2494. IRBuilderAsmJs::BuildBrInt1Const1(Js::OpCodeAsmJs newOpcode, uint32 offset)
  2495. {
  2496. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  2497. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_BrInt1Const1<SizePolicy>>();
  2498. BuildBrInt1Const1(newOpcode, offset, layout->RelativeJumpOffset, layout->I1, layout->C1);
  2499. }
  2500. void
  2501. IRBuilderAsmJs::BuildBrInt2(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, Js::RegSlot src1, Js::RegSlot src2)
  2502. {
  2503. Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(src1);
  2504. Js::RegSlot src2RegSlot = GetRegSlotFromIntReg(src2);
  2505. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
  2506. src1Opnd->SetValueType(ValueType::GetInt(false));
  2507. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  2508. src2Opnd->SetValueType(ValueType::GetInt(false));
  2509. BuildBrCmp(newOpcode, offset, relativeOffset, src1Opnd, src2Opnd);
  2510. }
  2511. void
  2512. IRBuilderAsmJs::BuildBrInt1Const1(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, Js::RegSlot src1, int32 src2)
  2513. {
  2514. Js::RegSlot src1RegSlot = GetRegSlotFromIntReg(src1);
  2515. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
  2516. src1Opnd->SetValueType(ValueType::GetInt(false));
  2517. IR::Opnd * src2Opnd = IR::IntConstOpnd::New(src2, TyInt32, this->m_func);
  2518. src2Opnd->SetValueType(ValueType::GetInt(false));
  2519. BuildBrCmp(newOpcode, offset, relativeOffset, src1Opnd, src2Opnd);
  2520. }
  2521. void
  2522. IRBuilderAsmJs::BuildBrCmp(Js::OpCodeAsmJs newOpcode, uint32 offset, int32 relativeOffset, IR::RegOpnd* src1Opnd, IR::Opnd* src2Opnd)
  2523. {
  2524. uint targetOffset = m_jnReader.GetCurrentOffset() + relativeOffset;
  2525. if (newOpcode == Js::OpCodeAsmJs::Case_Int || newOpcode == Js::OpCodeAsmJs::Case_IntConst)
  2526. {
  2527. // branches for cases are generated entirely by the switch builder
  2528. m_switchBuilder.OnCase(
  2529. src1Opnd,
  2530. src2Opnd,
  2531. offset,
  2532. targetOffset);
  2533. }
  2534. else
  2535. {
  2536. Assert(newOpcode == Js::OpCodeAsmJs::BrEq_Int);
  2537. IR::BranchInstr * branchInstr = IR::BranchInstr::New(Js::OpCode::BrEq_I4, nullptr, src1Opnd, src2Opnd, m_func);
  2538. AddBranchInstr(branchInstr, offset, targetOffset);
  2539. }
  2540. }
  2541. void
  2542. IRBuilderAsmJs::BuildLong1Reg1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot)
  2543. {
  2544. Assert(newOpcode == Js::OpCodeAsmJs::Conv_VTL);
  2545. BuildFromVar(offset, dstRegSlot, src1RegSlot, TyInt64, ValueType::GetInt(false));
  2546. }
  2547. void
  2548. IRBuilderAsmJs::BuildReg1Long1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstReg, Js::RegSlot srcRegSlot)
  2549. {
  2550. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt64);
  2551. srcOpnd->SetValueType(ValueType::GetInt(false));
  2552. switch (newOpcode)
  2553. {
  2554. case Js::OpCodeAsmJs::ArgOut_Long:
  2555. BuildArgOut(srcOpnd, dstReg, offset, TyVar);
  2556. break;
  2557. case Js::OpCodeAsmJs::I_ArgOut_Long:
  2558. BuildArgOut(srcOpnd, dstReg, offset, TyInt64, ValueType::GetInt(false));
  2559. break;
  2560. default:
  2561. Assume(UNREACHED);
  2562. }
  2563. }
  2564. void
  2565. IRBuilderAsmJs::BuildLong1Const1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, int64 constInt64)
  2566. {
  2567. Assert(newOpcode == Js::OpCodeAsmJs::Ld_LongConst);
  2568. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt64);
  2569. dstOpnd->SetValueType(ValueType::GetInt(false));
  2570. IR::Instr * instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, IR::Int64ConstOpnd::New(constInt64, TyInt64, m_func), m_func);
  2571. if (dstOpnd->m_sym->IsSingleDef())
  2572. {
  2573. dstOpnd->m_sym->SetIsInt64Const();
  2574. }
  2575. AddInstr(instr, offset);
  2576. }
  2577. void
  2578. IRBuilderAsmJs::BuildLong2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  2579. {
  2580. IR::RegOpnd * srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt64);
  2581. srcOpnd->SetValueType(ValueType::GetInt(false));
  2582. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt64);
  2583. dstOpnd->SetValueType(ValueType::GetInt(false));
  2584. IR::Instr * instr = nullptr;
  2585. switch (newOpcode)
  2586. {
  2587. case Js::OpCodeAsmJs::Ld_Long:
  2588. instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, srcOpnd, m_func);
  2589. break;
  2590. case Js::OpCodeAsmJs::Clz_Long:
  2591. instr = IR::Instr::New(Js::OpCode::InlineMathClz, dstOpnd, srcOpnd, m_func);
  2592. break;
  2593. case Js::OpCodeAsmJs::Ctz_Long:
  2594. instr = IR::Instr::New(Js::OpCode::Ctz, dstOpnd, srcOpnd, m_func);
  2595. break;
  2596. case Js::OpCodeAsmJs::PopCnt_Long:
  2597. instr = IR::Instr::New(Js::OpCode::PopCnt, dstOpnd, srcOpnd, m_func);
  2598. break;
  2599. case Js::OpCodeAsmJs::Return_Long:
  2600. instr = IR::Instr::New(Js::OpCode::Ld_I4, dstOpnd, srcOpnd, m_func);
  2601. if (m_func->IsLoopBody())
  2602. {
  2603. IR::Instr* slotInstr = GenerateStSlotForReturn(srcOpnd, IRType::TyInt64);
  2604. AddInstr(slotInstr, offset);
  2605. }
  2606. break;
  2607. default:
  2608. Assume(UNREACHED);
  2609. }
  2610. AddInstr(instr, offset);
  2611. }
  2612. void
  2613. IRBuilderAsmJs::BuildLong3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot)
  2614. {
  2615. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt64);
  2616. src1Opnd->SetValueType(ValueType::GetInt(false));
  2617. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt64);
  2618. src2Opnd->SetValueType(ValueType::GetInt(false));
  2619. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt64);
  2620. dstOpnd->SetValueType(ValueType::GetInt(false));
  2621. IR::Instr * instr = nullptr;
  2622. switch (newOpcode)
  2623. {
  2624. case Js::OpCodeAsmJs::Add_Long:
  2625. instr = IR::Instr::New(Js::OpCode::Add_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2626. break;
  2627. case Js::OpCodeAsmJs::Sub_Long:
  2628. instr = IR::Instr::New(Js::OpCode::Sub_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2629. break;
  2630. case Js::OpCodeAsmJs::Mul_Long:
  2631. instr = IR::Instr::New(Js::OpCode::Mul_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2632. break;
  2633. case Js::OpCodeAsmJs::Div_Trap_ULong:
  2634. src1Opnd->SetType(TyUint64);
  2635. src2Opnd->SetType(TyUint64);
  2636. // Fall Through for trap
  2637. case Js::OpCodeAsmJs::Div_Trap_Long:
  2638. {
  2639. #ifdef _M_X64
  2640. src2Opnd = BuildTrapIfZero(src2Opnd, offset);
  2641. if (newOpcode == Js::OpCodeAsmJs::Div_Trap_Long)
  2642. {
  2643. src1Opnd = BuildTrapIfMinIntOverNegOne(src1Opnd, src2Opnd, offset);
  2644. }
  2645. #endif
  2646. Js::OpCode op = newOpcode == Js::OpCodeAsmJs::Div_Trap_ULong ? Js::OpCode::DivU_I4 : Js::OpCode::Div_I4;
  2647. instr = IR::Instr::New(op, dstOpnd, src1Opnd, src2Opnd, m_func);
  2648. break;
  2649. }
  2650. case Js::OpCodeAsmJs::Rem_Trap_ULong:
  2651. src1Opnd->SetType(TyUint64);
  2652. src2Opnd->SetType(TyUint64);
  2653. // Fall Through for trap
  2654. case Js::OpCodeAsmJs::Rem_Trap_Long:
  2655. {
  2656. #ifdef _M_X64
  2657. src2Opnd = BuildTrapIfZero(src2Opnd, offset);
  2658. #endif
  2659. Js::OpCode op = newOpcode == Js::OpCodeAsmJs::Rem_Trap_ULong ? Js::OpCode::RemU_I4 : Js::OpCode::Rem_I4;
  2660. instr = IR::Instr::New(op, dstOpnd, src1Opnd, src2Opnd, m_func);
  2661. break;
  2662. }
  2663. case Js::OpCodeAsmJs::And_Long:
  2664. instr = IR::Instr::New(Js::OpCode::And_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2665. break;
  2666. case Js::OpCodeAsmJs::Or_Long:
  2667. instr = IR::Instr::New(Js::OpCode::Or_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2668. break;
  2669. case Js::OpCodeAsmJs::Xor_Long:
  2670. instr = IR::Instr::New(Js::OpCode::Xor_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2671. break;
  2672. case Js::OpCodeAsmJs::Shl_Long:
  2673. instr = IR::Instr::New(Js::OpCode::Shl_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2674. break;
  2675. case Js::OpCodeAsmJs::Shr_Long:
  2676. instr = IR::Instr::New(Js::OpCode::Shr_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2677. break;
  2678. case Js::OpCodeAsmJs::Shr_ULong:
  2679. instr = IR::Instr::New(Js::OpCode::ShrU_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2680. break;
  2681. case Js::OpCodeAsmJs::Rol_Long:
  2682. instr = IR::Instr::New(Js::OpCode::Rol_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2683. break;
  2684. case Js::OpCodeAsmJs::Ror_Long:
  2685. instr = IR::Instr::New(Js::OpCode::Ror_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2686. break;
  2687. default:
  2688. Assume(UNREACHED);
  2689. }
  2690. AddInstr(instr, offset);
  2691. }
  2692. void
  2693. IRBuilderAsmJs::BuildInt1Long2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot)
  2694. {
  2695. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt64);
  2696. src1Opnd->SetValueType(ValueType::GetInt(false));
  2697. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt64);
  2698. src2Opnd->SetValueType(ValueType::GetInt(false));
  2699. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  2700. dstOpnd->SetValueType(ValueType::GetInt(false));
  2701. IR::Instr * instr = nullptr;
  2702. switch (newOpcode)
  2703. {
  2704. case Js::OpCodeAsmJs::CmLt_Long:
  2705. instr = IR::Instr::New(Js::OpCode::CmLt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2706. break;
  2707. case Js::OpCodeAsmJs::CmLe_Long:
  2708. instr = IR::Instr::New(Js::OpCode::CmLe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2709. break;
  2710. case Js::OpCodeAsmJs::CmGt_Long:
  2711. instr = IR::Instr::New(Js::OpCode::CmGt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2712. break;
  2713. case Js::OpCodeAsmJs::CmGe_Long:
  2714. instr = IR::Instr::New(Js::OpCode::CmGe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2715. break;
  2716. case Js::OpCodeAsmJs::CmEq_Long:
  2717. instr = IR::Instr::New(Js::OpCode::CmEq_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2718. break;
  2719. case Js::OpCodeAsmJs::CmNe_Long:
  2720. instr = IR::Instr::New(Js::OpCode::CmNeq_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2721. break;
  2722. case Js::OpCodeAsmJs::CmLt_ULong:
  2723. instr = IR::Instr::New(Js::OpCode::CmUnLt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2724. break;
  2725. case Js::OpCodeAsmJs::CmLe_ULong:
  2726. instr = IR::Instr::New(Js::OpCode::CmUnLe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2727. break;
  2728. case Js::OpCodeAsmJs::CmGt_ULong:
  2729. instr = IR::Instr::New(Js::OpCode::CmUnGt_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2730. break;
  2731. case Js::OpCodeAsmJs::CmGe_ULong:
  2732. instr = IR::Instr::New(Js::OpCode::CmUnGe_I4, dstOpnd, src1Opnd, src2Opnd, m_func);
  2733. break;
  2734. default:
  2735. Assume(UNREACHED);
  2736. }
  2737. AddInstr(instr, offset);
  2738. }
  2739. void
  2740. IRBuilderAsmJs::BuildLong1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  2741. {
  2742. IR::RegOpnd * srcOpnd = nullptr;
  2743. switch (newOpcode)
  2744. {
  2745. case Js::OpCodeAsmJs::Conv_ITL:
  2746. srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt32);
  2747. break;
  2748. case Js::OpCodeAsmJs::Conv_UTL:
  2749. srcOpnd = BuildSrcOpnd(srcRegSlot, TyUint32);
  2750. break;
  2751. default:
  2752. Assume(UNREACHED);
  2753. }
  2754. srcOpnd->SetValueType(ValueType::GetInt(false));
  2755. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt64);
  2756. dstOpnd->SetValueType(ValueType::Float);
  2757. IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
  2758. AddInstr(instr, offset);
  2759. }
  2760. void
  2761. IRBuilderAsmJs::BuildInt1Long1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot)
  2762. {
  2763. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt64);
  2764. src1Opnd->SetValueType(ValueType::GetInt(false));
  2765. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  2766. dstOpnd->SetValueType(ValueType::GetInt(false));
  2767. IR::Instr * instr = nullptr;
  2768. switch (newOpcode)
  2769. {
  2770. case Js::OpCodeAsmJs::Eqz_Long:
  2771. instr = IR::Instr::New(Js::OpCode::CmEq_I4, dstOpnd, src1Opnd, IR::Int64ConstOpnd::New(0, TyInt64, m_func), m_func);
  2772. break;
  2773. case Js::OpCodeAsmJs::Conv_LTI:
  2774. instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, src1Opnd, m_func);
  2775. break;
  2776. default:
  2777. Assume(UNREACHED);
  2778. }
  2779. AddInstr(instr, offset);
  2780. }
  2781. void
  2782. IRBuilderAsmJs::BuildLong1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot)
  2783. {
  2784. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
  2785. IR::RegOpnd * dstOpnd = nullptr;
  2786. switch (newOpcode)
  2787. {
  2788. case Js::OpCodeAsmJs::Conv_Check_FTL:
  2789. dstOpnd = BuildDstOpnd(dstRegSlot, TyInt64);
  2790. break;
  2791. case Js::OpCodeAsmJs::Conv_Check_FTUL:
  2792. dstOpnd = BuildDstOpnd(dstRegSlot, TyUint64);
  2793. break;
  2794. default:
  2795. Assume(UNREACHED);
  2796. }
  2797. IR::RegOpnd* tmpDst = IR::RegOpnd::New(src1Opnd->GetType(), m_func);
  2798. tmpDst->SetValueType(ValueType::Float);
  2799. AddInstr(IR::Instr::New(Js::OpCode::TrapIfTruncOverflow, tmpDst, src1Opnd, m_func), offset);
  2800. dstOpnd->m_dontDeadStore = true;
  2801. IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, tmpDst, m_func);
  2802. AddInstr(instr, offset);
  2803. }
  2804. void
  2805. IRBuilderAsmJs::BuildFloat1Long1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot)
  2806. {
  2807. IR::RegOpnd * srcOpnd = nullptr;
  2808. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  2809. switch (newOpcode)
  2810. {
  2811. case Js::OpCodeAsmJs::Conv_LTF:
  2812. srcOpnd = BuildSrcOpnd(src1RegSlot, TyInt64);
  2813. break;
  2814. case Js::OpCodeAsmJs::Conv_ULTF:
  2815. srcOpnd = BuildSrcOpnd(src1RegSlot, TyUint64);
  2816. break;
  2817. default:
  2818. Assume(UNREACHED);
  2819. }
  2820. IR::Instr * instr = IR::Instr::New(Js::OpCode::Conv_Prim, dstOpnd, srcOpnd, m_func);
  2821. AddInstr(instr, offset);
  2822. }
  2823. void
  2824. IRBuilderAsmJs::BuildLong1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot)
  2825. {
  2826. IR::RegOpnd * srcOpnd = BuildSrcOpnd(src1RegSlot, TyFloat64);
  2827. srcOpnd->SetValueType(ValueType::Float);
  2828. IRType dstType;
  2829. Js::OpCode op;
  2830. bool doTruncTrapCheck = false;
  2831. switch (newOpcode)
  2832. {
  2833. case Js::OpCodeAsmJs::Conv_Check_DTL:
  2834. op = Js::OpCode::Conv_Prim;
  2835. dstType = TyInt64;
  2836. doTruncTrapCheck = true;
  2837. break;
  2838. case Js::OpCodeAsmJs::Conv_Check_DTUL:
  2839. op = Js::OpCode::Conv_Prim;
  2840. dstType = TyUint64;
  2841. doTruncTrapCheck = true;
  2842. break;
  2843. case Js::OpCodeAsmJs::Reinterpret_DTL:
  2844. op = Js::OpCode::Reinterpret_Prim;
  2845. dstType = TyInt64;
  2846. break;
  2847. default:
  2848. Assume(UNREACHED);
  2849. Js::Throw::FatalInternalError();
  2850. }
  2851. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, dstType);
  2852. dstOpnd->SetValueType(ValueType::GetInt(false));
  2853. if (doTruncTrapCheck)
  2854. {
  2855. IR::RegOpnd* tmpDst = IR::RegOpnd::New(srcOpnd->GetType(), m_func);
  2856. tmpDst->SetValueType(ValueType::Float);
  2857. AddInstr(IR::Instr::New(Js::OpCode::TrapIfTruncOverflow, tmpDst, srcOpnd, m_func), offset);
  2858. dstOpnd->m_dontDeadStore = true;
  2859. srcOpnd = tmpDst;
  2860. }
  2861. IR::Instr * instr = IR::Instr::New(op, dstOpnd, srcOpnd, m_func);
  2862. AddInstr(instr, offset);
  2863. }
  2864. void
  2865. IRBuilderAsmJs::BuildDouble1Long1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot)
  2866. {
  2867. IR::RegOpnd * srcOpnd = nullptr;
  2868. Js::OpCode op = Js::OpCode::Conv_Prim;
  2869. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat64);
  2870. dstOpnd->SetValueType(ValueType::Float);
  2871. switch (newOpcode)
  2872. {
  2873. case Js::OpCodeAsmJs::Conv_LTD:
  2874. srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt64);
  2875. break;
  2876. case Js::OpCodeAsmJs::Conv_ULTD:
  2877. srcOpnd = BuildSrcOpnd(srcRegSlot, TyUint64);
  2878. break;
  2879. case Js::OpCodeAsmJs::Reinterpret_LTD:
  2880. srcOpnd = BuildSrcOpnd(srcRegSlot, TyInt64);
  2881. op = Js::OpCode::Reinterpret_Prim;
  2882. break;
  2883. default:
  2884. Assume(UNREACHED);
  2885. }
  2886. srcOpnd->SetValueType(ValueType::GetInt(false));
  2887. IR::Instr* instr = IR::Instr::New(op, dstOpnd, srcOpnd, m_func);
  2888. AddInstr(instr, offset);
  2889. }
  2890. ///Loop Body Code
  2891. bool
  2892. IRBuilderAsmJs::IsLoopBody() const
  2893. {
  2894. return m_func->IsLoopBody();
  2895. }
  2896. bool
  2897. IRBuilderAsmJs::IsLoopBodyReturnIPInstr(IR::Instr * instr) const
  2898. {
  2899. IR::Opnd * dst = instr->GetDst();
  2900. return (dst && dst->IsRegOpnd() && dst->AsRegOpnd()->m_sym == m_loopBodyRetIPSym);
  2901. }
  2902. bool
  2903. IRBuilderAsmJs::IsLoopBodyOuterOffset(uint offset) const
  2904. {
  2905. if (!IsLoopBody())
  2906. {
  2907. return false;
  2908. }
  2909. return (offset >= m_func->GetWorkItem()->GetLoopHeader()->endOffset || offset < m_func->GetWorkItem()->GetLoopHeader()->startOffset);
  2910. }
  2911. uint
  2912. IRBuilderAsmJs::GetLoopBodyExitInstrOffset() const
  2913. {
  2914. // End of loop body, start of StSlot and Ret instruction at endOffset + 1
  2915. return m_func->GetWorkItem()->GetLoopHeader()->endOffset + 1;
  2916. }
  2917. IR::Instr *
  2918. IRBuilderAsmJs::CreateLoopBodyReturnIPInstr(uint targetOffset, uint offset)
  2919. {
  2920. IR::RegOpnd * retOpnd = IR::RegOpnd::New(m_loopBodyRetIPSym, TyInt32, m_func);
  2921. IR::IntConstOpnd * exitOffsetOpnd = IR::IntConstOpnd::New(targetOffset, TyInt32, m_func);
  2922. return IR::Instr::New(Js::OpCode::Ld_I4, retOpnd, exitOffsetOpnd, m_func);
  2923. }
  2924. IR::Opnd *
  2925. IRBuilderAsmJs::InsertLoopBodyReturnIPInstr(uint targetOffset, uint offset)
  2926. {
  2927. IR::Instr * setRetValueInstr = CreateLoopBodyReturnIPInstr(targetOffset, offset);
  2928. this->AddInstr(setRetValueInstr, offset);
  2929. return setRetValueInstr->GetDst();
  2930. }
  2931. IR::SymOpnd *
  2932. IRBuilderAsmJs::BuildAsmJsLoopBodySlotOpnd(SymID symId, IRType opndType)
  2933. {
  2934. // There is no unsigned locals, make sure we create only signed locals
  2935. opndType = IRType_EnsureSigned(opndType);
  2936. // Get the interpreter frame instance that was passed in.
  2937. StackSym *loopParamSym = m_func->EnsureLoopParamSym();
  2938. // property ID is the offset
  2939. Js::PropertyId propOffSet = CalculatePropertyOffset(symId, opndType);
  2940. // Get the bytecodeRegSlot and Get the offset from m_localSlots
  2941. PropertySym * fieldSym = PropertySym::FindOrCreate(loopParamSym->m_id, propOffSet, (uint32)-1, (uint)-1, PropertyKindLocalSlots, m_func);
  2942. return IR::SymOpnd::New(fieldSym, opndType, m_func);
  2943. }
  2944. void
  2945. IRBuilderAsmJs::EnsureLoopBodyAsmJsLoadSlot(SymID symId, IRType type)
  2946. {
  2947. if (this->m_ldSlots->TestAndSet(symId))
  2948. {
  2949. return;
  2950. }
  2951. IR::SymOpnd * fieldSymOpnd = this->BuildAsmJsLoopBodySlotOpnd(symId, type);
  2952. StackSym * symDst = StackSym::FindOrCreate(symId, (Js::RegSlot)symId, m_func, fieldSymOpnd->GetType());
  2953. IR::RegOpnd * dstOpnd = IR::RegOpnd::New(symDst, symDst->GetType(), m_func);
  2954. IR::Instr * ldSlotInstr = IR::Instr::New(Js::OpCode::LdSlot, dstOpnd, fieldSymOpnd, m_func);
  2955. m_func->m_headInstr->InsertAfter(ldSlotInstr);
  2956. if (m_lastInstr == m_func->m_headInstr)
  2957. {
  2958. m_lastInstr = ldSlotInstr;
  2959. }
  2960. }
  2961. void
  2962. IRBuilderAsmJs::GenerateLoopBodySlotAccesses(uint offset)
  2963. {
  2964. //
  2965. // The interpreter instance is passed as 0th argument to the JITted loop body function.
  2966. // Always load the argument, then use it to generate any necessary store-slots.
  2967. //
  2968. uint16 argument = 0;
  2969. StackSym *symSrc = StackSym::NewParamSlotSym(argument + 1, m_func);
  2970. symSrc->m_offset = (argument + LowererMD::GetFormalParamOffset()) * MachPtr;
  2971. symSrc->m_allocated = true;
  2972. m_func->SetHasImplicitParamLoad();
  2973. IR::SymOpnd *srcOpnd = IR::SymOpnd::New(symSrc, TyMachPtr, m_func);
  2974. StackSym *loopParamSym = m_func->EnsureLoopParamSym();
  2975. IR::RegOpnd *loopParamOpnd = IR::RegOpnd::New(loopParamSym, TyMachPtr, m_func);
  2976. IR::Instr *instrArgIn = IR::Instr::New(Js::OpCode::ArgIn_A, loopParamOpnd, srcOpnd, m_func);
  2977. m_func->m_headInstr->InsertAfter(instrArgIn);
  2978. GenerateLoopBodyStSlots(loopParamSym->m_id, offset);
  2979. }
  2980. void
  2981. IRBuilderAsmJs::GenerateLoopBodyStSlots(SymID loopParamSymId, uint offset)
  2982. {
  2983. if (this->m_stSlots->Count() == 0)
  2984. {
  2985. return;
  2986. }
  2987. FOREACH_BITSET_IN_FIXEDBV(regSlot, this->m_stSlots)
  2988. {
  2989. Assert(!this->RegIsConstant((Js::RegSlot)regSlot));
  2990. IRType type = IRType::TyInt32;
  2991. ValueType valueType = ValueType::GetInt(false);
  2992. if (RegIsIntVar(regSlot))
  2993. {
  2994. type = IRType::TyInt32;
  2995. valueType = ValueType::GetInt(false);
  2996. }
  2997. else if (RegIsFloatVar(regSlot))
  2998. {
  2999. type = IRType::TyFloat32;
  3000. valueType = ValueType::Float;
  3001. }
  3002. else if (RegIsDoubleVar(regSlot))
  3003. {
  3004. type = IRType::TyFloat64;
  3005. valueType = ValueType::Float;
  3006. }
  3007. else if (RegIsInt64Var(regSlot))
  3008. {
  3009. type = IRType::TyInt64;
  3010. valueType = ValueType::GetInt(false);
  3011. }
  3012. else if (RegIsSimd128Var(regSlot))
  3013. {
  3014. type = IRType::TySimd128F4;
  3015. // SIMD regs are non-typed. There is no way to know the incoming SIMD type to a StSlot after a loop body, so we pick any type.
  3016. // However, at this point all src syms are already defined and assigned a type.
  3017. valueType = ValueType::GetObject(ObjectType::UninitializedObject);
  3018. }
  3019. else
  3020. {
  3021. AnalysisAssert(UNREACHED);
  3022. }
  3023. Js::PropertyId propOffSet = CalculatePropertyOffset(regSlot, type);
  3024. IR::RegOpnd* regOpnd = this->BuildSrcOpnd((Js::RegSlot)regSlot, type);
  3025. regOpnd->SetValueType(valueType);
  3026. // Get the bytecodeRegSlot and Get the offset from m_localSlots
  3027. PropertySym * fieldSym = PropertySym::FindOrCreate(loopParamSymId, propOffSet, (uint32)-1, (uint)-1, PropertyKindLocalSlots, m_func);
  3028. IR::SymOpnd * fieldSymOpnd = IR::SymOpnd::New(fieldSym, regOpnd->GetType(), m_func);
  3029. Js::OpCode opcode = Js::OpCode::StSlot;
  3030. IR::Instr * stSlotInstr = IR::Instr::New(opcode, fieldSymOpnd, regOpnd, m_func);
  3031. this->AddInstr(stSlotInstr, offset);
  3032. }
  3033. NEXT_BITSET_IN_FIXEDBV;
  3034. }
  3035. Js::PropertyId IRBuilderAsmJs::CalculatePropertyOffset(SymID id, IRType type, bool isVar)
  3036. {
  3037. // Compute the offset to the start of the interpreter frame's locals array as a Var index.
  3038. size_t localsOffset = 0;
  3039. if (!m_IsTJLoopBody)
  3040. {
  3041. localsOffset = Js::InterpreterStackFrame::GetOffsetOfLocals();
  3042. }
  3043. Assert(localsOffset % sizeof(AsmJsSIMDValue) == 0);
  3044. WAsmJs::Types asmType = WAsmJs::FromIRType(type);
  3045. const auto typedInfo = m_asmFuncInfo->GetTypedSlotInfo(asmType);
  3046. uint32 regSlot = 0;
  3047. if (isVar)
  3048. {
  3049. // Get the bytecodeRegSlot
  3050. regSlot = id - GetFirstVar(asmType) + typedInfo.constCount;
  3051. }
  3052. return (Js::PropertyId)(regSlot * TySize[type] + typedInfo.byteOffset + localsOffset);
  3053. }
  3054. IR::Instr* IRBuilderAsmJs::GenerateStSlotForReturn(IR::RegOpnd* srcOpnd, IRType retType)
  3055. {
  3056. // Compute the offset to the start of the interpreter frame's locals array as a Var index.
  3057. size_t localsOffset = 0;
  3058. if (!m_IsTJLoopBody)
  3059. {
  3060. localsOffset = Js::InterpreterStackFrame::GetOffsetOfLocals();
  3061. }
  3062. Assert(localsOffset % sizeof(AsmJsSIMDValue) == 0);
  3063. StackSym *loopParamSym = m_func->EnsureLoopParamSym();
  3064. Js::PropertyId propOffSet = CalculatePropertyOffset(0, retType, false);
  3065. // Get the bytecodeRegSlot and Get the offset from m_localSlots
  3066. PropertySym * fieldSym = PropertySym::FindOrCreate(loopParamSym->m_id, propOffSet, (uint32)-1, (uint)-1, PropertyKindLocalSlots, m_func);
  3067. IR::SymOpnd * fieldSymOpnd = IR::SymOpnd::New(fieldSym, srcOpnd->GetType(), m_func);
  3068. Js::OpCode opcode = Js::OpCode::StSlot;
  3069. IR::Instr * stSlotInstr = IR::Instr::New(opcode, fieldSymOpnd, srcOpnd, m_func);
  3070. return stSlotInstr;
  3071. }
  3072. Js::OpCode IRBuilderAsmJs::GetSimdOpcode(Js::OpCodeAsmJs asmjsOpcode)
  3073. {
  3074. Js::OpCode opcode = (Js::OpCode) 0;
  3075. Assert(IsSimd128AsmJsOpcode(asmjsOpcode));
  3076. if (asmjsOpcode <= Js::OpCodeAsmJs::Simd128_End)
  3077. {
  3078. opcode = m_simdOpcodesMap[(uint32)((Js::OpCodeAsmJs)asmjsOpcode - Js::OpCodeAsmJs::Simd128_Start)];
  3079. }
  3080. else
  3081. {
  3082. Assert(asmjsOpcode >= Js::OpCodeAsmJs::Simd128_Start_Extend && asmjsOpcode <= Js::OpCodeAsmJs::Simd128_End_Extend);
  3083. opcode = m_simdOpcodesMap[(uint32)((Js::OpCodeAsmJs)asmjsOpcode - Js::OpCodeAsmJs::Simd128_Start_Extend) + (uint32)(Js::OpCodeAsmJs::Simd128_End - Js::OpCodeAsmJs::Simd128_Start) + 1];
  3084. }
  3085. Assert(IsSimd128Opcode(opcode));
  3086. return opcode;
  3087. }
  3088. void IRBuilderAsmJs::GetSimdTypesFromAsmType(Js::AsmJsType::Which asmType, IRType *pIRType, ValueType *pValueType /* = nullptr */)
  3089. {
  3090. IRType irType = IRType::TyVar;
  3091. ValueType vType = ValueType::Uninitialized;
  3092. #define SIMD_TYPE_CHECK(type1, type2, type3) \
  3093. case Js::AsmJsType::Which::##type1: \
  3094. irType = type2; \
  3095. vType = ValueType::GetSimd128(ObjectType::##type3); \
  3096. break;
  3097. switch (asmType)
  3098. {
  3099. SIMD_TYPE_CHECK(Float32x4, TySimd128F4, Simd128Float32x4)
  3100. SIMD_TYPE_CHECK(Int32x4, TySimd128I4, Simd128Int32x4 )
  3101. SIMD_TYPE_CHECK(Int16x8, TySimd128I8, Simd128Int16x8 )
  3102. SIMD_TYPE_CHECK(Int8x16, TySimd128I16, Simd128Int8x16 )
  3103. SIMD_TYPE_CHECK(Uint32x4, TySimd128U4, Simd128Uint32x4 )
  3104. SIMD_TYPE_CHECK(Uint16x8, TySimd128U8, Simd128Uint16x8 )
  3105. SIMD_TYPE_CHECK(Uint8x16, TySimd128U16, Simd128Uint8x16 )
  3106. SIMD_TYPE_CHECK(Bool32x4, TySimd128B4, Simd128Bool32x4 )
  3107. SIMD_TYPE_CHECK(Bool16x8, TySimd128B8, Simd128Bool16x8 )
  3108. SIMD_TYPE_CHECK(Bool8x16, TySimd128B16, Simd128Bool8x16 )
  3109. default:
  3110. Assert(UNREACHED);
  3111. }
  3112. *pIRType = irType;
  3113. if (pValueType)
  3114. {
  3115. *pValueType = vType;
  3116. }
  3117. #undef SIMD_TYPE_CHECK
  3118. }
  3119. // !!NOTE: Always build the src opnds first, before dst. So we record the use of any temps before assigning new symId for the dst temp.
  3120. #define BUILD_SIMD_ARGS_REG2 Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot
  3121. #define BUILD_SIMD_ARGS_REG3 BUILD_SIMD_ARGS_REG2, Js::RegSlot src2RegSlot
  3122. #define BUILD_SIMD_ARGS_REG4 BUILD_SIMD_ARGS_REG3, Js::RegSlot src3RegSlot
  3123. #define BUILD_SIMD_ARGS_REG5 BUILD_SIMD_ARGS_REG4, Js::RegSlot src4RegSlot
  3124. #define BUILD_SIMD_ARGS_REG6 BUILD_SIMD_ARGS_REG5, Js::RegSlot src5RegSlot
  3125. #define BUILD_SIMD_ARGS_REG7 BUILD_SIMD_ARGS_REG6, Js::RegSlot src6RegSlot
  3126. #define BUILD_SIMD_ARGS_REG9 BUILD_SIMD_ARGS_REG7, Js::RegSlot src7RegSlot, Js::RegSlot src8RegSlot
  3127. #define BUILD_SIMD_ARGS_REG10 BUILD_SIMD_ARGS_REG9, Js::RegSlot src9RegSlot
  3128. #define BUILD_SIMD_ARGS_REG11 BUILD_SIMD_ARGS_REG10, Js::RegSlot src10RegSlot
  3129. #define BUILD_SIMD_ARGS_REG17 BUILD_SIMD_ARGS_REG11, Js::RegSlot src11RegSlot, Js::RegSlot src12RegSlot, Js::RegSlot src13RegSlot, Js::RegSlot src14RegSlot, Js::RegSlot src15RegSlot, Js::RegSlot src16RegSlot
  3130. #define BUILD_SIMD_ARGS_REG18 BUILD_SIMD_ARGS_REG17, Js::RegSlot src17RegSlot
  3131. #define BUILD_SIMD_ARGS_REG19 BUILD_SIMD_ARGS_REG18, Js::RegSlot src18RegSlot
  3132. // Float32x4
  3133. void
  3134. IRBuilderAsmJs::BuildFloat32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3135. {
  3136. BuildSimd_2(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128F4);
  3137. }
  3138. void
  3139. IRBuilderAsmJs::BuildFloat32x4_3(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3140. {
  3141. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128F4);
  3142. }
  3143. void
  3144. IRBuilderAsmJs::BuildBool32x4_1Float32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3145. {
  3146. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128B4, TySimd128F4);
  3147. }
  3148. void
  3149. IRBuilderAsmJs::BuildFloat32x4_1Bool32x4_1Float32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  3150. {
  3151. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128B4);
  3152. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128F4);
  3153. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128F4);
  3154. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  3155. IR::Instr * instr = nullptr;
  3156. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3157. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool32x4));
  3158. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3159. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3160. // Given bytecode: dst = op s1, s2, s3
  3161. // Generate:
  3162. // t1 = ExtendedArg_A s1
  3163. // t2 = ExtendedArg_A s2, t1
  3164. // t3 = ExtendedArg_A s3, t2
  3165. // dst = op t3
  3166. // Later phases will chain the arguments by following singleDefInstr of each use of ti.
  3167. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3168. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3169. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3170. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3171. AssertMsg(opcode == Js::OpCode::Simd128_Select_F4, "Unexpected opcode for this format.");
  3172. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3173. }
  3174. void
  3175. IRBuilderAsmJs::BuildFloat32x4_4(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  3176. {
  3177. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  3178. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128F4);
  3179. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128F4);
  3180. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  3181. IR::Instr * instr = nullptr;
  3182. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3183. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3184. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3185. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3186. // Given bytecode: dst = op s1, s2, s3
  3187. // Generate:
  3188. // t1 = ExtendedArg_A s1
  3189. // t2 = ExtendedArg_A s2, t1
  3190. // t3 = ExtendedArg_A s3, t2
  3191. // dst = op t3
  3192. // Later phases will chain the arguments by following singleDefInstr of each use of ti.
  3193. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3194. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3195. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3196. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3197. AssertMsg(opcode == Js::OpCode::Simd128_Select_I4, "Unexpected opcode for this format.");
  3198. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3199. }
  3200. void IRBuilderAsmJs::BuildFloat32x4_1Float4(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG5)
  3201. {
  3202. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
  3203. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat32);
  3204. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TyFloat32);
  3205. IR::RegOpnd * src4Opnd = BuildSrcOpnd(src4RegSlot, TyFloat32);
  3206. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  3207. IR::Instr * instr = nullptr;
  3208. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3209. src1Opnd->SetValueType(ValueType::Float);
  3210. src2Opnd->SetValueType(ValueType::Float);
  3211. src3Opnd->SetValueType(ValueType::Float);
  3212. src4Opnd->SetValueType(ValueType::Float);
  3213. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3214. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3215. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3216. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3217. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3218. AssertMsg(opcode == Js::OpCode::Simd128_FloatsToF4, "Unexpected opcode for this format.");
  3219. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3220. }
  3221. void
  3222. IRBuilderAsmJs::BuildFloat32x4_2Int4(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG6)
  3223. {
  3224. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  3225. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  3226. IR::RegOpnd * src2Opnd = BuildIntConstOpnd(src2RegSlot);
  3227. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(src3RegSlot);
  3228. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(src4RegSlot);
  3229. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(src5RegSlot);
  3230. IR::Instr * instr = nullptr;
  3231. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3232. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3233. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3234. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3235. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3236. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3237. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3238. Js::OpCode opcode = Js::OpCode::Simd128_Swizzle_F4;
  3239. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3240. }
  3241. void
  3242. IRBuilderAsmJs::BuildFloat32x4_3Int4(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG7)
  3243. {
  3244. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  3245. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  3246. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128F4);
  3247. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(src3RegSlot);
  3248. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(src4RegSlot);
  3249. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(src5RegSlot);
  3250. IR::RegOpnd * src6Opnd = BuildIntConstOpnd(src6RegSlot);
  3251. IR::Instr * instr = nullptr;
  3252. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3253. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3254. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3255. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3256. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3257. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3258. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3259. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3260. instr = AddExtendedArg(src6Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3261. Js::OpCode opcode = Js::OpCode::Simd128_Shuffle_F4;
  3262. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3263. }
  3264. void
  3265. IRBuilderAsmJs::BuildFloat32x4_1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3266. {
  3267. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat32);
  3268. src1Opnd->SetValueType(ValueType::Float);
  3269. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  3270. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3271. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_F4);
  3272. Js::OpCode opcode = Js::OpCode::Simd128_Splat_F4;
  3273. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3274. AddInstr(instr, offset);
  3275. }
  3276. void
  3277. IRBuilderAsmJs::BuildFloat32x4_2Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3278. {
  3279. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  3280. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3281. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat32);
  3282. src1Opnd->SetValueType(ValueType::Float);
  3283. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  3284. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3285. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3286. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  3287. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  3288. AddInstr(instr, offset);
  3289. }
  3290. // Disable for now
  3291. #if 0
  3292. void
  3293. IRBuilderAsmJs::BuildFloat32x4_1Float64x2_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3294. {
  3295. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  3296. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3297. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  3298. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3299. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3300. AssertMsg(opcode == Js::OpCode::Simd128_FromFloat64x2_F4 || opcode == Js::OpCode::Simd128_FromFloat64x2Bits_F4, "Unexpected opcode for this format.");
  3301. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3302. AddInstr(instr, offset);
  3303. }
  3304. #endif // 0
  3305. void
  3306. IRBuilderAsmJs::BuildFloat32x4_1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3307. {
  3308. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt32x4_F4 || newOpcode == Js::OpCodeAsmJs::Simd128_FromInt32x4Bits_F4, "Unexpected opcode for this format.");
  3309. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128F4, TySimd128I4);
  3310. }
  3311. void
  3312. IRBuilderAsmJs::BuildFloat32x4_1Uint32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3313. {
  3314. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint32x4_F4 || newOpcode == Js::OpCodeAsmJs::Simd128_FromUint32x4Bits_F4, "Unexpected opcode for this format.");
  3315. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128F4, TySimd128U4);
  3316. }
  3317. void
  3318. IRBuilderAsmJs::BuildFloat32x4_1Int16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3319. {
  3320. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt16x8Bits_F4, "Unexpected opcode for this format.");
  3321. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128F4, TySimd128I8);
  3322. }
  3323. void
  3324. IRBuilderAsmJs::BuildFloat32x4_1Uint16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3325. {
  3326. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint16x8Bits_F4, "Unexpected opcode for this format.");
  3327. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128F4, TySimd128U8);
  3328. }
  3329. void
  3330. IRBuilderAsmJs::BuildFloat32x4_1Int8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3331. {
  3332. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt8x16Bits_F4, "Unexpected opcode for this format.");
  3333. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128F4, TySimd128I16);
  3334. }
  3335. void
  3336. IRBuilderAsmJs::BuildFloat32x4_1Uint8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3337. {
  3338. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint8x16Bits_F4, "Unexpected opcode for this format.");
  3339. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128F4, TySimd128U16);
  3340. }
  3341. void IRBuilderAsmJs::BuildReg1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3342. {
  3343. IR::RegOpnd * srcOpnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  3344. srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3345. IR::Instr * instr = nullptr;
  3346. IR::Opnd * dstOpnd = nullptr;
  3347. StackSym * symDst = nullptr;
  3348. if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_F4)
  3349. {
  3350. symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128F4);
  3351. symDst->m_allocated = true;
  3352. if ((uint16)(dstRegSlot) != (dstRegSlot))
  3353. {
  3354. AssertMsg(UNREACHED, "Arg count too big...");
  3355. Fatal();
  3356. }
  3357. dstOpnd = IR::SymOpnd::New(symDst, TySimd128F4, m_func);
  3358. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3359. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  3360. AddInstr(instr, offset);
  3361. m_argStack->Push(instr);
  3362. }
  3363. else
  3364. {
  3365. Assert(UNREACHED);
  3366. }
  3367. }
  3368. /* Int32x4 */
  3369. void
  3370. IRBuilderAsmJs::BuildInt32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3371. {
  3372. BuildSimd_2(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I4);
  3373. }
  3374. void
  3375. IRBuilderAsmJs::BuildInt32x4_3(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3376. {
  3377. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128I4);
  3378. }
  3379. void
  3380. IRBuilderAsmJs::BuildBool32x4_1Int32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3381. {
  3382. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128B4, TySimd128I4);
  3383. }
  3384. void
  3385. IRBuilderAsmJs::BuildInt32x4_1Bool32x4_1Int32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  3386. {
  3387. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128B4);
  3388. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128I4);
  3389. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128I4);
  3390. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  3391. IR::Instr * instr = nullptr;
  3392. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3393. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool32x4));
  3394. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3395. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3396. // Given bytecode: dst = op s1, s2, s3
  3397. // Generate:
  3398. // t1 = ExtendedArg_A s1
  3399. // t2 = ExtendedArg_A s2, t1
  3400. // t3 = ExtendedArg_A s3, t2
  3401. // dst = op t3
  3402. // Later phases will chain the arguments by following singleDefInstr of each use of ti.
  3403. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3404. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3405. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3406. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3407. AssertMsg(opcode == Js::OpCode::Simd128_Select_I4, "Unexpected opcode for this format.");
  3408. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3409. }
  3410. void IRBuilderAsmJs::BuildInt32x4_1Int4(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG5)
  3411. {
  3412. uint const LANES = 4;
  3413. Js::RegSlot srcRegSlot[LANES];
  3414. srcRegSlot[0] = src1RegSlot;
  3415. srcRegSlot[1] = src2RegSlot;
  3416. srcRegSlot[2] = src3RegSlot;
  3417. srcRegSlot[3] = src4RegSlot;
  3418. BuildSimd_1Ints(newOpcode, offset, TySimd128I4, srcRegSlot, dstRegSlot, LANES);
  3419. }
  3420. void IRBuilderAsmJs::BuildInt32x4_2Int4(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG6)
  3421. {
  3422. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  3423. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3424. IR::RegOpnd * src2Opnd = BuildIntConstOpnd(src2RegSlot);
  3425. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(src3RegSlot);
  3426. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(src4RegSlot);
  3427. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(src5RegSlot);
  3428. IR::Instr * instr = nullptr;
  3429. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3430. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3431. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3432. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3433. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3434. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3435. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3436. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Swizzle_I4);
  3437. Js::OpCode opcode = Js::OpCode::Simd128_Swizzle_I4;
  3438. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3439. }
  3440. void IRBuilderAsmJs::BuildInt32x4_3Int4(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG7)
  3441. {
  3442. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I4);
  3443. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3444. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128I4);
  3445. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(src3RegSlot);
  3446. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(src4RegSlot);
  3447. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(src5RegSlot);
  3448. IR::RegOpnd * src6Opnd = BuildIntConstOpnd(src6RegSlot);
  3449. IR::Instr * instr = nullptr;
  3450. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3451. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3452. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3453. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3454. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3455. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3456. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3457. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3458. instr = AddExtendedArg(src6Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3459. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Shuffle_I4);
  3460. Js::OpCode opcode = Js::OpCode::Simd128_Shuffle_I4;
  3461. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3462. }
  3463. void
  3464. IRBuilderAsmJs::BuildInt32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3465. {
  3466. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_I4);
  3467. BuildSimd_1Int1(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I4);
  3468. }
  3469. void
  3470. IRBuilderAsmJs::BuildInt32x4_2Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3471. {
  3472. BuildSimd_2Int1(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128I4);
  3473. }
  3474. //ReplaceLane
  3475. void
  3476. IRBuilderAsmJs::BuildInt32x4_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  3477. {
  3478. AssertMsg((newOpcode == Js::OpCodeAsmJs::Simd128_ReplaceLane_I4), "Unexpected opcode for this format.");
  3479. BuildSimd_2Int2(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, src3RegSlot, TySimd128I4);
  3480. }
  3481. void
  3482. IRBuilderAsmJs::BuildInt1Int32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3483. {
  3484. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3485. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3486. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  3487. src2Opnd->SetValueType(ValueType::GetInt(false));
  3488. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  3489. dstOpnd->SetValueType(ValueType::GetInt(false));
  3490. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3491. AssertMsg((opcode == Js::OpCode::Simd128_ExtractLane_I4), "Unexpected opcode for this format.");
  3492. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  3493. AddInstr(instr, offset);
  3494. }
  3495. void
  3496. IRBuilderAsmJs::BuildFloat32x4_2Int1Float1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  3497. {
  3498. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  3499. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3500. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  3501. src2Opnd->SetValueType(ValueType::GetInt(false));
  3502. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TyFloat32);
  3503. src3Opnd->SetValueType(ValueType::Float);
  3504. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128F4);
  3505. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3506. // Given bytecode: dst = op s1, s2, s3
  3507. // Generate:
  3508. // t1 = ExtendedArg_A s1
  3509. // t2 = ExtendedArg_A s2, t1
  3510. // t3 = ExtendedArg_A s3, t2
  3511. // dst = op t3
  3512. IR::Instr* instr = nullptr;
  3513. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3514. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3515. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3516. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3517. AssertMsg((opcode == Js::OpCode::Simd128_ReplaceLane_F4), "Unexpected opcode for this format.");
  3518. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3519. }
  3520. void
  3521. IRBuilderAsmJs::BuildFloat1Float32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3522. {
  3523. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  3524. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3525. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  3526. src2Opnd->SetValueType(ValueType::GetInt(false));
  3527. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyFloat32);
  3528. dstOpnd->SetValueType(ValueType::Float);
  3529. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3530. AssertMsg((opcode == Js::OpCode::Simd128_ExtractLane_F4), "Unexpected opcode for this format.");
  3531. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  3532. AddInstr(instr, offset);
  3533. }
  3534. void
  3535. IRBuilderAsmJs::BuildInt32x4_1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3536. {
  3537. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromFloat32x4_I4 || newOpcode == Js::OpCodeAsmJs::Simd128_FromFloat32x4Bits_I4, "Unexpected opcode for this format.");
  3538. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I4, TySimd128F4);
  3539. }
  3540. void
  3541. IRBuilderAsmJs::BuildInt32x4_1Uint32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3542. {
  3543. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint32x4Bits_I4, "Unexpected opcode for this format.");
  3544. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I4, TySimd128U4);
  3545. }
  3546. void
  3547. IRBuilderAsmJs::BuildInt32x4_1Int16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3548. {
  3549. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt16x8Bits_I4, "Unexpected opcode for this format.");
  3550. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I4, TySimd128I8);
  3551. }
  3552. void
  3553. IRBuilderAsmJs::BuildInt32x4_1Uint16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3554. {
  3555. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint16x8Bits_I4, "Unexpected opcode for this format.");
  3556. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I4, TySimd128U8);
  3557. }
  3558. void
  3559. IRBuilderAsmJs::BuildInt32x4_1Int8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3560. {
  3561. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt8x16Bits_I4, "Unexpected opcode for this format.");
  3562. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I4, TySimd128I16);
  3563. }
  3564. void
  3565. IRBuilderAsmJs::BuildInt32x4_1Uint8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3566. {
  3567. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint8x16Bits_I4, "Unexpected opcode for this format.");
  3568. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I4, TySimd128U16);
  3569. }
  3570. #if 0
  3571. void
  3572. IRBuilderAsmJs::BuildInt32x4_1Float64x2_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3573. {
  3574. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromFloat64x2_I4 || newOpcode == Js::OpCodeAsmJs::Simd128_FromFloat64x2Bits_I4, "Unexpected opcode for this format.");
  3575. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I4, TySimd128D2);
  3576. }
  3577. #endif //0
  3578. void IRBuilderAsmJs::BuildReg1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3579. {
  3580. IR::RegOpnd * srcOpnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  3581. srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3582. IR::Instr * instr = nullptr;
  3583. IR::Opnd * dstOpnd = nullptr;
  3584. StackSym * symDst = nullptr;
  3585. if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_I4)
  3586. {
  3587. symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128I4);
  3588. symDst->m_allocated = true;
  3589. if ((uint16)(dstRegSlot) != (dstRegSlot))
  3590. {
  3591. AssertMsg(UNREACHED, "Arg count too big...");
  3592. Fatal();
  3593. }
  3594. dstOpnd = IR::SymOpnd::New(symDst, TySimd128I4, m_func);
  3595. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  3596. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  3597. AddInstr(instr, offset);
  3598. m_argStack->Push(instr);
  3599. }
  3600. else
  3601. {
  3602. Assert(UNREACHED);
  3603. }
  3604. }
  3605. //Int8x16
  3606. void
  3607. IRBuilderAsmJs::BuildInt8x16_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3608. {
  3609. BuildSimd_2(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I16);
  3610. }
  3611. //
  3612. void
  3613. IRBuilderAsmJs::BuildInt8x16_3(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3614. {
  3615. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128I16);
  3616. }
  3617. void IRBuilderAsmJs::BuildInt8x16_1Int16(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG17)
  3618. {
  3619. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_IntsToI16, "Unexpected opcode for this format.");
  3620. uint const LANES = 16;
  3621. Js::RegSlot srcRegSlots[LANES] = {
  3622. srcRegSlots[0] = src1RegSlot,
  3623. srcRegSlots[1] = src2RegSlot,
  3624. srcRegSlots[2] = src3RegSlot,
  3625. srcRegSlots[3] = src4RegSlot,
  3626. srcRegSlots[4] = src5RegSlot,
  3627. srcRegSlots[5] = src6RegSlot,
  3628. srcRegSlots[6] = src7RegSlot,
  3629. srcRegSlots[7] = src8RegSlot,
  3630. srcRegSlots[8] = src9RegSlot,
  3631. srcRegSlots[9] = src10RegSlot,
  3632. srcRegSlots[10] = src11RegSlot,
  3633. srcRegSlots[11] = src12RegSlot,
  3634. srcRegSlots[12] = src13RegSlot,
  3635. srcRegSlots[13] = src14RegSlot,
  3636. srcRegSlots[14] = src15RegSlot,
  3637. srcRegSlots[15] = src16RegSlot
  3638. };
  3639. BuildSimd_1Ints(newOpcode, offset, TySimd128I16, srcRegSlots, dstRegSlot, LANES);
  3640. }
  3641. void
  3642. IRBuilderAsmJs::BuildBool8x16_1Int8x16_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3643. {
  3644. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128B8, TySimd128I8);
  3645. }
  3646. void
  3647. IRBuilderAsmJs::BuildInt8x16_1Bool8x16_1Int8x16_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  3648. {
  3649. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128B16);
  3650. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128I16);
  3651. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128I16);
  3652. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I16);
  3653. IR::Instr * instr = nullptr;
  3654. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
  3655. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool8x16));
  3656. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
  3657. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
  3658. // Given bytecode: dst = op s1, s2, s3
  3659. // Generate:
  3660. // t1 = ExtendedArg_A s1
  3661. // t2 = ExtendedArg_A s2, t1
  3662. // t3 = ExtendedArg_A s3, t2
  3663. // dst = op t3
  3664. // Later phases will chain the arguments by following singleDefInstr of each use of ti.
  3665. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3666. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3667. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3668. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3669. AssertMsg(opcode == Js::OpCode::Simd128_Select_I16, "Unexpected opcode for this format.");
  3670. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3671. }
  3672. void
  3673. IRBuilderAsmJs::BuildInt8x16_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3674. {
  3675. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_I16);
  3676. BuildSimd_1Int1(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I16);
  3677. }
  3678. //ExtractLane ReplaceLane
  3679. void
  3680. IRBuilderAsmJs::BuildInt8x16_2Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3681. {
  3682. BuildSimd_2Int1(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128I16);
  3683. }
  3684. void
  3685. IRBuilderAsmJs::BuildInt8x16_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  3686. {
  3687. AssertMsg((newOpcode == Js::OpCodeAsmJs::Simd128_ReplaceLane_I16), "Unexpected opcode for this format.");
  3688. BuildSimd_2Int2(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, src3RegSlot, TySimd128I16);
  3689. }
  3690. void
  3691. IRBuilderAsmJs::BuildInt1Int8x16_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3692. {
  3693. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I16);
  3694. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
  3695. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  3696. src2Opnd->SetValueType(ValueType::GetInt(false));
  3697. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  3698. dstOpnd->SetValueType(ValueType::GetInt(false));
  3699. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3700. AssertMsg((opcode == Js::OpCode::Simd128_ExtractLane_I16), "Unexpected opcode for this format.");
  3701. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  3702. AddInstr(instr, offset);
  3703. }
  3704. void IRBuilderAsmJs::BuildInt8x16_3Int16(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG19)
  3705. {
  3706. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I16);
  3707. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I16);
  3708. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128I16);
  3709. IR::RegOpnd* srcOpnds[16];
  3710. srcOpnds[0] = BuildIntConstOpnd(src3RegSlot);
  3711. srcOpnds[1] = BuildIntConstOpnd(src4RegSlot);
  3712. srcOpnds[2] = BuildIntConstOpnd(src5RegSlot);
  3713. srcOpnds[3] = BuildIntConstOpnd(src6RegSlot);
  3714. srcOpnds[4] = BuildIntConstOpnd(src7RegSlot);
  3715. srcOpnds[5] = BuildIntConstOpnd(src8RegSlot);
  3716. srcOpnds[6] = BuildIntConstOpnd(src9RegSlot);
  3717. srcOpnds[7] = BuildIntConstOpnd(src10RegSlot);
  3718. srcOpnds[8] = BuildIntConstOpnd(src11RegSlot);
  3719. srcOpnds[9] = BuildIntConstOpnd(src12RegSlot);
  3720. srcOpnds[10] = BuildIntConstOpnd(src13RegSlot);
  3721. srcOpnds[11] = BuildIntConstOpnd(src14RegSlot);
  3722. srcOpnds[12] = BuildIntConstOpnd(src15RegSlot);
  3723. srcOpnds[13] = BuildIntConstOpnd(src16RegSlot);
  3724. srcOpnds[14] = BuildIntConstOpnd(src17RegSlot);
  3725. srcOpnds[15] = BuildIntConstOpnd(src18RegSlot);
  3726. IR::Instr * instr = nullptr;
  3727. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
  3728. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
  3729. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
  3730. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3731. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3732. for (int i = 0; i < 16; ++i)
  3733. {
  3734. instr = AddExtendedArg(srcOpnds[i], instr->GetDst()->AsRegOpnd(), offset);
  3735. }
  3736. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Shuffle_I16);
  3737. Js::OpCode opcode = Js::OpCode::Simd128_Shuffle_I16;
  3738. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3739. }
  3740. void IRBuilderAsmJs::BuildInt8x16_2Int16(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG18)
  3741. {
  3742. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I16);
  3743. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I16);
  3744. IR::RegOpnd* srcOpnds[16];
  3745. srcOpnds[0] = BuildIntConstOpnd(src2RegSlot);
  3746. srcOpnds[1] = BuildIntConstOpnd(src3RegSlot);
  3747. srcOpnds[2] = BuildIntConstOpnd(src4RegSlot);
  3748. srcOpnds[3] = BuildIntConstOpnd(src5RegSlot);
  3749. srcOpnds[4] = BuildIntConstOpnd(src6RegSlot);
  3750. srcOpnds[5] = BuildIntConstOpnd(src7RegSlot);
  3751. srcOpnds[6] = BuildIntConstOpnd(src8RegSlot);
  3752. srcOpnds[7] = BuildIntConstOpnd(src9RegSlot);
  3753. srcOpnds[8] = BuildIntConstOpnd(src10RegSlot);
  3754. srcOpnds[9] = BuildIntConstOpnd(src11RegSlot);
  3755. srcOpnds[10] = BuildIntConstOpnd(src12RegSlot);
  3756. srcOpnds[11] = BuildIntConstOpnd(src13RegSlot);
  3757. srcOpnds[12] = BuildIntConstOpnd(src14RegSlot);
  3758. srcOpnds[13] = BuildIntConstOpnd(src15RegSlot);
  3759. srcOpnds[14] = BuildIntConstOpnd(src16RegSlot);
  3760. srcOpnds[15] = BuildIntConstOpnd(src17RegSlot);
  3761. IR::Instr * instr = nullptr;
  3762. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
  3763. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
  3764. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3765. for (int i = 0; i < 16; ++i)
  3766. {
  3767. instr = AddExtendedArg(srcOpnds[i], instr->GetDst()->AsRegOpnd(), offset);
  3768. }
  3769. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Swizzle_I16);
  3770. Js::OpCode opcode = Js::OpCode::Simd128_Swizzle_I16;
  3771. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3772. }
  3773. void
  3774. IRBuilderAsmJs::BuildInt8x16_1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3775. {
  3776. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromFloat32x4Bits_I16, "Unexpected opcode for this format.");
  3777. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I16, TySimd128F4);
  3778. }
  3779. void
  3780. IRBuilderAsmJs::BuildInt8x16_1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3781. {
  3782. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt32x4Bits_I16, "Unexpected opcode for this format.");
  3783. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I16, TySimd128I4);
  3784. }
  3785. void
  3786. IRBuilderAsmJs::BuildInt8x16_1Int16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3787. {
  3788. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt16x8Bits_I16, "Unexpected opcode for this format.");
  3789. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I16, TySimd128I8);
  3790. }
  3791. void
  3792. IRBuilderAsmJs::BuildInt8x16_1Uint32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3793. {
  3794. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint32x4Bits_I16, "Unexpected opcode for this format.");
  3795. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I16, TySimd128U4);
  3796. }
  3797. void
  3798. IRBuilderAsmJs::BuildInt8x16_1Uint16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3799. {
  3800. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint16x8Bits_I16, "Unexpected opcode for this format.");
  3801. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I16, TySimd128U8);
  3802. }
  3803. void
  3804. IRBuilderAsmJs::BuildInt8x16_1Uint8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3805. {
  3806. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint8x16Bits_I16, "Unexpected opcode for this format.");
  3807. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I16, TySimd128U16);
  3808. }
  3809. void IRBuilderAsmJs::BuildReg1Int8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3810. {
  3811. IR::RegOpnd * srcOpnd = BuildSrcOpnd(src1RegSlot, TySimd128I16);
  3812. srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
  3813. IR::Instr * instr = nullptr;
  3814. IR::Opnd * dstOpnd = nullptr;
  3815. StackSym * symDst = nullptr;
  3816. if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_I16)
  3817. {
  3818. symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128I16);
  3819. symDst->m_allocated = true;
  3820. if (symDst == NULL || (uint16)(dstRegSlot) != (dstRegSlot))
  3821. {
  3822. AssertMsg(UNREACHED, "Arg count too big...");
  3823. Fatal();
  3824. }
  3825. dstOpnd = IR::SymOpnd::New(symDst, TySimd128I16, m_func);
  3826. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int8x16));
  3827. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  3828. AddInstr(instr, offset);
  3829. m_argStack->Push(instr);
  3830. }
  3831. else
  3832. {
  3833. Assert(UNREACHED);
  3834. }
  3835. }
  3836. /* Float64x2 */
  3837. // Disabled for now
  3838. #if 0
  3839. void
  3840. IRBuilderAsmJs::BuildFloat64x2_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3841. {
  3842. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  3843. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3844. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3845. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3846. Js::OpCode opcode;
  3847. switch (newOpcode)
  3848. {
  3849. case Js::OpCodeAsmJs::Simd128_Return_D2:
  3850. if (m_func->IsLoopBody())
  3851. {
  3852. IR::Instr* slotInstr = GenerateStSlotForReturn(src1Opnd, IRType::TySimd128D2);
  3853. AddInstr(slotInstr, offset);
  3854. }
  3855. opcode = Js::OpCode::Ld_A;
  3856. break;
  3857. case Js::OpCodeAsmJs::Simd128_I_Conv_VTD2:
  3858. case Js::OpCodeAsmJs::Simd128_Ld_D2:
  3859. opcode = Js::OpCode::Ld_A;
  3860. break;
  3861. default:
  3862. opcode = GetSimdOpcode(newOpcode);
  3863. }
  3864. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  3865. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3866. AddInstr(instr, offset);
  3867. }
  3868. void
  3869. IRBuilderAsmJs::BuildFloat64x2_3(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3870. {
  3871. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  3872. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3873. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128D2);
  3874. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3875. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3876. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3877. Js::OpCode opcode;
  3878. opcode = GetSimdOpcode(newOpcode);
  3879. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  3880. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  3881. AddInstr(instr, offset);
  3882. }
  3883. void
  3884. IRBuilderAsmJs::BuildFloat64x2_4(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  3885. {
  3886. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  3887. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128D2);
  3888. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128D2);
  3889. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3890. IR::Instr * instr = nullptr;
  3891. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3892. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3893. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3894. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3895. // Given bytecode: dst = op s1, s2, s3
  3896. // Generate:
  3897. // t1 = ExtendedArg_A s1
  3898. // t2 = ExtendedArg_A s2, t1
  3899. // t3 = ExtendedArg_A s3, t2
  3900. // dst = op t3
  3901. // Later phases will chain the arguments by following singleDefInstr of each use of ti.
  3902. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3903. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3904. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3905. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3906. AssertMsg(opcode == Js::OpCode::Simd128_Clamp_D2, "Unexpected opcode for this format.");
  3907. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3908. }
  3909. void IRBuilderAsmJs::BuildFloat64x2_1Double2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3910. {
  3911. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat64);
  3912. src1Opnd->SetValueType(ValueType::Float);
  3913. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat64);
  3914. src2Opnd->SetValueType(ValueType::Float);
  3915. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3916. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3917. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3918. AssertMsg(opcode == Js::OpCode::Simd128_DoublesToD2, "Invalid backend SIMD opcode");
  3919. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  3920. AddInstr(instr, offset);
  3921. }
  3922. void IRBuilderAsmJs::BuildFloat64x2_1Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3923. {
  3924. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyFloat64);
  3925. src1Opnd->SetValueType(ValueType::Float);
  3926. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3927. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3928. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3929. AssertMsg(opcode == Js::OpCode::Simd128_Splat_D2, "Invalid backend SIMD opcode");
  3930. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3931. AddInstr(instr, offset);
  3932. }
  3933. void
  3934. IRBuilderAsmJs::BuildFloat64x2_2Double1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  3935. {
  3936. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  3937. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3938. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyFloat64);
  3939. src1Opnd->SetValueType(ValueType::Float);
  3940. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3941. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3942. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3943. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  3944. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  3945. AddInstr(instr, offset);
  3946. }
  3947. void
  3948. IRBuilderAsmJs::BuildFloat64x2_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  3949. {
  3950. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3951. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  3952. IR::RegOpnd * src2Opnd = BuildIntConstOpnd(src2RegSlot);
  3953. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(src3RegSlot);
  3954. IR::Instr * instr = nullptr;
  3955. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3956. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3957. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3958. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3959. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3960. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Swizzle_D2);
  3961. Js::OpCode opcode = Js::OpCode::Simd128_Swizzle_D2;
  3962. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3963. }
  3964. void
  3965. IRBuilderAsmJs::BuildFloat64x2_3Int2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG5)
  3966. {
  3967. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3968. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  3969. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128D2);
  3970. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(src3RegSlot);
  3971. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(src4RegSlot);
  3972. IR::Instr * instr = nullptr;
  3973. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3974. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3975. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3976. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  3977. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3978. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3979. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  3980. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Shuffle_D2);
  3981. Js::OpCode opcode = Js::OpCode::Simd128_Shuffle_D2;
  3982. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  3983. }
  3984. void
  3985. IRBuilderAsmJs::BuildFloat64x2_1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3986. {
  3987. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128F4);
  3988. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float32x4));
  3989. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  3990. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  3991. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  3992. AssertMsg(opcode == Js::OpCode::Simd128_FromFloat32x4_D2 || opcode == Js::OpCode::Simd128_FromFloat32x4Bits_D2, "Unexpected opcode for this format.");
  3993. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  3994. AddInstr(instr, offset);
  3995. }
  3996. void
  3997. IRBuilderAsmJs::BuildFloat64x2_1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  3998. {
  3999. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  4000. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  4001. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  4002. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  4003. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  4004. AssertMsg(opcode == Js::OpCode::Simd128_FromInt32x4_D2 || opcode == Js::OpCode::Simd128_FromInt32x4Bits_D2, "Unexpected opcode for this format.");
  4005. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  4006. AddInstr(instr, offset);
  4007. }
  4008. void
  4009. IRBuilderAsmJs::BuildFloat64x2_1Int32x4_1Float64x2_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  4010. {
  4011. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I4);
  4012. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128D2);
  4013. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128D2);
  4014. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128D2);
  4015. IR::Instr * instr = nullptr;
  4016. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  4017. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int32x4));
  4018. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  4019. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  4020. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  4021. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4022. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4023. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  4024. AssertMsg(opcode == Js::OpCode::Simd128_Select_D2, "Unexpected opcode for this format.");
  4025. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  4026. }
  4027. void IRBuilderAsmJs::BuildReg1Float64x2_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4028. {
  4029. IR::RegOpnd * srcOpnd = BuildSrcOpnd(src1RegSlot, TySimd128D2);
  4030. srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  4031. IR::Instr * instr = nullptr;
  4032. IR::Opnd * dstOpnd = nullptr;
  4033. StackSym * symDst = nullptr;
  4034. if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_D2)
  4035. {
  4036. symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128D2);
  4037. symDst->m_allocated = true;
  4038. if ((uint16)(dstRegSlot) != (dstRegSlot))
  4039. {
  4040. AssertMsg(UNREACHED, "Arg count too big...");
  4041. Fatal();
  4042. }
  4043. dstOpnd = IR::SymOpnd::New(symDst, TySimd128D2, m_func);
  4044. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Float64x2));
  4045. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  4046. AddInstr(instr, offset);
  4047. m_argStack->Push(instr);
  4048. }
  4049. else
  4050. {
  4051. Assert(UNREACHED);
  4052. }
  4053. }
  4054. #endif // 0
  4055. /* Int16x8 */
  4056. void IRBuilderAsmJs::BuildInt16x8_1Int8(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG9)
  4057. {
  4058. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_IntsToI8, "Unexpected opcode for this format.");
  4059. uint const LANES = 8;
  4060. Js::RegSlot srcRegSlots[LANES];
  4061. srcRegSlots[0] = src1RegSlot;
  4062. srcRegSlots[1] = src2RegSlot;
  4063. srcRegSlots[2] = src3RegSlot;
  4064. srcRegSlots[3] = src4RegSlot;
  4065. srcRegSlots[4] = src5RegSlot;
  4066. srcRegSlots[5] = src6RegSlot;
  4067. srcRegSlots[6] = src7RegSlot;
  4068. srcRegSlots[7] = src8RegSlot;
  4069. BuildSimd_1Ints(newOpcode, offset, TySimd128I8, srcRegSlots, dstRegSlot, LANES);
  4070. }
  4071. void IRBuilderAsmJs::BuildReg1Int16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4072. {
  4073. IR::RegOpnd * srcOpnd = BuildSrcOpnd(src1RegSlot, TySimd128I8);
  4074. srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
  4075. IR::Instr * instr = nullptr;
  4076. IR::Opnd * dstOpnd = nullptr;
  4077. StackSym * symDst = nullptr;
  4078. if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_I8)
  4079. {
  4080. symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128I8);
  4081. symDst->m_allocated = true;
  4082. if (symDst == nullptr || (uint16)(dstRegSlot) != (dstRegSlot))
  4083. {
  4084. AssertMsg(UNREACHED, "Arg count too big...");
  4085. Fatal();
  4086. }
  4087. dstOpnd = IR::SymOpnd::New(symDst, TySimd128I8, m_func);
  4088. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
  4089. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  4090. AddInstr(instr, offset);
  4091. m_argStack->Push(instr);
  4092. }
  4093. else
  4094. {
  4095. Assert(UNREACHED);
  4096. }
  4097. }
  4098. void
  4099. IRBuilderAsmJs::BuildInt1Int16x8_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4100. {
  4101. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I8);
  4102. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
  4103. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  4104. src2Opnd->SetValueType(ValueType::GetInt(false));
  4105. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  4106. dstOpnd->SetValueType(ValueType::GetInt(false));
  4107. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  4108. AssertMsg((opcode == Js::OpCode::Simd128_ExtractLane_I8), "Unexpected opcode for this format.");
  4109. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  4110. AddInstr(instr, offset);
  4111. }
  4112. void IRBuilderAsmJs::BuildInt16x8_2Int8(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG10)
  4113. {
  4114. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I8);
  4115. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I8);
  4116. IR::RegOpnd * src2Opnd = BuildIntConstOpnd(src2RegSlot);
  4117. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(src3RegSlot);
  4118. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(src4RegSlot);
  4119. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(src5RegSlot);
  4120. IR::RegOpnd * src6Opnd = BuildIntConstOpnd(src6RegSlot);
  4121. IR::RegOpnd * src7Opnd = BuildIntConstOpnd(src7RegSlot);
  4122. IR::RegOpnd * src8Opnd = BuildIntConstOpnd(src8RegSlot);
  4123. IR::RegOpnd * src9Opnd = BuildIntConstOpnd(src9RegSlot);
  4124. IR::Instr * instr = nullptr;
  4125. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
  4126. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
  4127. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  4128. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4129. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4130. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4131. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4132. instr = AddExtendedArg(src6Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4133. instr = AddExtendedArg(src7Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4134. instr = AddExtendedArg(src8Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4135. instr = AddExtendedArg(src9Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4136. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Swizzle_I8);
  4137. Js::OpCode opcode = Js::OpCode::Simd128_Swizzle_I8;
  4138. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  4139. }
  4140. void IRBuilderAsmJs::BuildInt16x8_3Int8(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG11)
  4141. {
  4142. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I8);
  4143. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128I8);
  4144. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128I8);
  4145. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(src3RegSlot);
  4146. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(src4RegSlot);
  4147. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(src5RegSlot);
  4148. IR::RegOpnd * src6Opnd = BuildIntConstOpnd(src6RegSlot);
  4149. IR::RegOpnd * src7Opnd = BuildIntConstOpnd(src7RegSlot);
  4150. IR::RegOpnd * src8Opnd = BuildIntConstOpnd(src8RegSlot);
  4151. IR::RegOpnd * src9Opnd = BuildIntConstOpnd(src9RegSlot);
  4152. IR::RegOpnd * src10Opnd = BuildIntConstOpnd(src10RegSlot);
  4153. IR::Instr * instr = nullptr;
  4154. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
  4155. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
  4156. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
  4157. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  4158. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4159. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4160. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4161. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4162. instr = AddExtendedArg(src6Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4163. instr = AddExtendedArg(src7Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4164. instr = AddExtendedArg(src8Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4165. instr = AddExtendedArg(src9Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4166. instr = AddExtendedArg(src10Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4167. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Shuffle_I8);
  4168. Js::OpCode opcode = Js::OpCode::Simd128_Shuffle_U8;
  4169. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  4170. }
  4171. void
  4172. IRBuilderAsmJs::BuildInt16x8_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4173. {
  4174. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_I8);
  4175. BuildSimd_1Int1(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I8);
  4176. }
  4177. void
  4178. IRBuilderAsmJs::BuildInt16x8_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  4179. {
  4180. AssertMsg((newOpcode == Js::OpCodeAsmJs::Simd128_ReplaceLane_I8), "Unexpected opcode for this format.");
  4181. BuildSimd_2Int2(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, src3RegSlot, TySimd128I8);
  4182. }
  4183. void
  4184. IRBuilderAsmJs::BuildInt16x8_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4185. {
  4186. BuildSimd_2(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I8);
  4187. }
  4188. void
  4189. IRBuilderAsmJs::BuildInt16x8_3(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4190. {
  4191. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128I8);
  4192. }
  4193. void
  4194. IRBuilderAsmJs::BuildBool16x8_1Int16x8_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4195. {
  4196. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128B8, TySimd128I8);
  4197. }
  4198. void
  4199. IRBuilderAsmJs::BuildInt16x8_1Bool16x8_1Int16x8_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  4200. {
  4201. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128B8);
  4202. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128I8);
  4203. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128I8);
  4204. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128I8);
  4205. IR::Instr * instr = nullptr;
  4206. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
  4207. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool16x8));
  4208. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
  4209. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Int16x8));
  4210. // Given bytecode: dst = op s1, s2, s3
  4211. // Generate:
  4212. // t1 = ExtendedArg_A s1
  4213. // t2 = ExtendedArg_A s2, t1
  4214. // t3 = ExtendedArg_A s3, t2
  4215. // dst = op t3
  4216. // Later phases will chain the arguments by following singleDefInstr of each use of ti.
  4217. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  4218. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4219. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4220. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  4221. AssertMsg(opcode == Js::OpCode::Simd128_Select_I8, "Unexpected opcode for this format.");
  4222. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  4223. }
  4224. void
  4225. IRBuilderAsmJs::BuildInt16x8_2Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4226. {
  4227. BuildSimd_2Int1(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128I8);
  4228. }
  4229. void
  4230. IRBuilderAsmJs::BuildInt16x8_1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4231. {
  4232. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromFloat32x4Bits_I8, "Unexpected opcode for this format.");
  4233. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I8, TySimd128F4);
  4234. }
  4235. void
  4236. IRBuilderAsmJs::BuildInt16x8_1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4237. {
  4238. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt32x4Bits_I8, "Unexpected opcode for this format.");
  4239. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I8, TySimd128I4);
  4240. }
  4241. void
  4242. IRBuilderAsmJs::BuildInt16x8_1Int8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4243. {
  4244. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt8x16Bits_I8, "Unexpected opcode for this format.");
  4245. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I8, TySimd128I16);
  4246. }
  4247. void
  4248. IRBuilderAsmJs::BuildInt16x8_1Uint32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4249. {
  4250. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint32x4Bits_I8, "Unexpected opcode for this format.");
  4251. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I8, TySimd128U4);
  4252. }
  4253. void
  4254. IRBuilderAsmJs::BuildInt16x8_1Uint16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4255. {
  4256. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint16x8Bits_I8, "Unexpected opcode for this format.");
  4257. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I8, TySimd128U8);
  4258. }
  4259. void
  4260. IRBuilderAsmJs::BuildInt16x8_1Uint8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4261. {
  4262. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint8x16Bits_I8, "Unexpected opcode for this format.");
  4263. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128I8, TySimd128U16);
  4264. }
  4265. /* Uint32x4 */
  4266. void IRBuilderAsmJs::BuildUint32x4_1Int4(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG5)
  4267. {
  4268. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_IntsToU4, "Unexpected opcode for this format.");
  4269. uint const LANES = 4;
  4270. Js::RegSlot srcRegSlot[LANES];
  4271. srcRegSlot[0] = src1RegSlot;
  4272. srcRegSlot[1] = src2RegSlot;
  4273. srcRegSlot[2] = src3RegSlot;
  4274. srcRegSlot[3] = src4RegSlot;
  4275. BuildSimd_1Ints(newOpcode, offset, TySimd128U4, srcRegSlot, dstRegSlot, LANES);
  4276. }
  4277. void IRBuilderAsmJs::BuildReg1Uint32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4278. {
  4279. IR::RegOpnd * srcOpnd = BuildSrcOpnd(src1RegSlot, TySimd128U4);
  4280. srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
  4281. IR::Instr * instr = nullptr;
  4282. IR::Opnd * dstOpnd = nullptr;
  4283. StackSym * symDst = nullptr;
  4284. if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_U4)
  4285. {
  4286. symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128U4);
  4287. symDst->m_allocated = true;
  4288. if (symDst == nullptr || (uint16)(dstRegSlot) != (dstRegSlot))
  4289. {
  4290. AssertMsg(UNREACHED, "Arg count too big...");
  4291. Fatal();
  4292. }
  4293. dstOpnd = IR::SymOpnd::New(symDst, TySimd128U4, m_func);
  4294. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
  4295. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  4296. AddInstr(instr, offset);
  4297. m_argStack->Push(instr);
  4298. }
  4299. else
  4300. {
  4301. Assert(UNREACHED);
  4302. }
  4303. }
  4304. void
  4305. IRBuilderAsmJs::BuildInt1Uint32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4306. {
  4307. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128U4);
  4308. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
  4309. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  4310. src2Opnd->SetValueType(ValueType::GetInt(false));
  4311. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  4312. dstOpnd->SetValueType(ValueType::GetInt(false));
  4313. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  4314. AssertMsg((opcode == Js::OpCode::Simd128_ExtractLane_U4), "Unexpected opcode for this format.");
  4315. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  4316. AddInstr(instr, offset);
  4317. }
  4318. void IRBuilderAsmJs::BuildUint32x4_2Int4(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG6)
  4319. {
  4320. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128U4);
  4321. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128U4);
  4322. IR::RegOpnd * src2Opnd = BuildIntConstOpnd(src2RegSlot);
  4323. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(src3RegSlot);
  4324. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(src4RegSlot);
  4325. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(src5RegSlot);
  4326. IR::Instr * instr = nullptr;
  4327. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
  4328. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
  4329. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  4330. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4331. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4332. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4333. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4334. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Swizzle_U4);
  4335. Js::OpCode opcode = Js::OpCode::Simd128_Swizzle_U4;
  4336. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  4337. }
  4338. void IRBuilderAsmJs::BuildUint32x4_3Int4(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG7)
  4339. {
  4340. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128U4);
  4341. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128U4);
  4342. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128U4);
  4343. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(src3RegSlot);
  4344. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(src4RegSlot);
  4345. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(src5RegSlot);
  4346. IR::RegOpnd * src6Opnd = BuildIntConstOpnd(src6RegSlot);
  4347. IR::Instr * instr = nullptr;
  4348. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
  4349. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
  4350. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
  4351. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  4352. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4353. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4354. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4355. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4356. instr = AddExtendedArg(src6Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4357. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Shuffle_U4);
  4358. Js::OpCode opcode = Js::OpCode::Simd128_Shuffle_U4;
  4359. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  4360. }
  4361. void
  4362. IRBuilderAsmJs::BuildUint32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4363. {
  4364. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_U4);
  4365. BuildSimd_1Int1(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U4);
  4366. }
  4367. void
  4368. IRBuilderAsmJs::BuildUint32x4_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  4369. {
  4370. AssertMsg((newOpcode == Js::OpCodeAsmJs::Simd128_ReplaceLane_U4), "Unexpected opcode for this format.");
  4371. BuildSimd_2Int2(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, src3RegSlot, TySimd128U4);
  4372. }
  4373. void
  4374. IRBuilderAsmJs::BuildUint32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4375. {
  4376. BuildSimd_2(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U4);
  4377. }
  4378. void
  4379. IRBuilderAsmJs::BuildUint32x4_3(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4380. {
  4381. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128U4);
  4382. }
  4383. void
  4384. IRBuilderAsmJs::BuildBool32x4_1Uint32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4385. {
  4386. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128B4, TySimd128U4);
  4387. }
  4388. void
  4389. IRBuilderAsmJs::BuildUint32x4_1Bool32x4_1Uint32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  4390. {
  4391. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128B4);
  4392. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128U4);
  4393. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128U4);
  4394. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128U4);
  4395. IR::Instr * instr = nullptr;
  4396. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
  4397. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool32x4));
  4398. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
  4399. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint32x4));
  4400. // Given bytecode: dst = op s1, s2, s3
  4401. // Generate:
  4402. // t1 = ExtendedArg_A s1
  4403. // t2 = ExtendedArg_A s2, t1
  4404. // t3 = ExtendedArg_A s3, t2
  4405. // dst = op t3
  4406. // Later phases will chain the arguments by following singleDefInstr of each use of ti.
  4407. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  4408. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4409. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4410. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  4411. AssertMsg(opcode == Js::OpCode::Simd128_Select_U4, "Unexpected opcode for this format.");
  4412. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  4413. }
  4414. void
  4415. IRBuilderAsmJs::BuildUint32x4_2Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4416. {
  4417. BuildSimd_2Int1(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128U4);
  4418. }
  4419. void
  4420. IRBuilderAsmJs::BuildUint32x4_1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4421. {
  4422. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromFloat32x4_U4 || newOpcode == Js::OpCodeAsmJs::Simd128_FromFloat32x4Bits_U4, "Unexpected opcode for this format.");
  4423. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U4, TySimd128F4);
  4424. }
  4425. void
  4426. IRBuilderAsmJs::BuildUint32x4_1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4427. {
  4428. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt32x4Bits_U4, "Unexpected opcode for this format.");
  4429. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U4, TySimd128I4);
  4430. }
  4431. void
  4432. IRBuilderAsmJs::BuildUint32x4_1Int16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4433. {;
  4434. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt16x8Bits_U4, "Unexpected opcode for this format.");
  4435. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U4, TySimd128I8);
  4436. }
  4437. /* Enable with Int8x16 support*/
  4438. void
  4439. IRBuilderAsmJs::BuildUint32x4_1Int8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4440. {
  4441. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt8x16Bits_U4, "Unexpected opcode for this format.");
  4442. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U4, TySimd128I16);
  4443. }
  4444. void
  4445. IRBuilderAsmJs::BuildUint32x4_1Uint16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4446. {
  4447. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint16x8Bits_U4, "Unexpected opcode for this format.");
  4448. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U4, TySimd128U8);
  4449. }
  4450. void
  4451. IRBuilderAsmJs::BuildUint32x4_1Uint8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4452. {
  4453. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint8x16Bits_U4, "Unexpected opcode for this format.");
  4454. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U4, TySimd128U16);
  4455. }
  4456. /* Uint16x8 */
  4457. void IRBuilderAsmJs::BuildUint16x8_1Int8(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG9)
  4458. {
  4459. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_IntsToU8, "Unexpected opcode for this format.");
  4460. uint const LANES = 8;
  4461. Js::RegSlot srcRegSlots[LANES];
  4462. srcRegSlots[0] = src1RegSlot;
  4463. srcRegSlots[1] = src2RegSlot;
  4464. srcRegSlots[2] = src3RegSlot;
  4465. srcRegSlots[3] = src4RegSlot;
  4466. srcRegSlots[4] = src5RegSlot;
  4467. srcRegSlots[5] = src6RegSlot;
  4468. srcRegSlots[6] = src7RegSlot;
  4469. srcRegSlots[7] = src8RegSlot;
  4470. BuildSimd_1Ints(newOpcode, offset, TySimd128U8, srcRegSlots, dstRegSlot, LANES);
  4471. }
  4472. void IRBuilderAsmJs::BuildReg1Uint16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4473. {
  4474. IR::RegOpnd * srcOpnd = BuildSrcOpnd(src1RegSlot, TySimd128U8);
  4475. srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
  4476. IR::Instr * instr = nullptr;
  4477. IR::Opnd * dstOpnd = nullptr;
  4478. StackSym * symDst = nullptr;
  4479. if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_U8)
  4480. {
  4481. symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128U8);
  4482. symDst->m_allocated = true;
  4483. if (symDst == nullptr || (uint16)(dstRegSlot) != (dstRegSlot))
  4484. {
  4485. AssertMsg(UNREACHED, "Arg count too big...");
  4486. Fatal();
  4487. }
  4488. dstOpnd = IR::SymOpnd::New(symDst, TySimd128U4, m_func);
  4489. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
  4490. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  4491. AddInstr(instr, offset);
  4492. m_argStack->Push(instr);
  4493. }
  4494. else
  4495. {
  4496. Assert(UNREACHED);
  4497. }
  4498. }
  4499. void
  4500. IRBuilderAsmJs::BuildInt1Uint16x8_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4501. {
  4502. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128U8);
  4503. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
  4504. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  4505. src2Opnd->SetValueType(ValueType::GetInt(false));
  4506. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  4507. dstOpnd->SetValueType(ValueType::GetInt(false));
  4508. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  4509. AssertMsg((opcode == Js::OpCode::Simd128_ExtractLane_U8), "Unexpected opcode for this format.");
  4510. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  4511. AddInstr(instr, offset);
  4512. }
  4513. void IRBuilderAsmJs::BuildUint16x8_2Int8(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG10)
  4514. {
  4515. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128U8);
  4516. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128U8);
  4517. IR::RegOpnd * src2Opnd = BuildIntConstOpnd(src2RegSlot);
  4518. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(src3RegSlot);
  4519. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(src4RegSlot);
  4520. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(src5RegSlot);
  4521. IR::RegOpnd * src6Opnd = BuildIntConstOpnd(src6RegSlot);
  4522. IR::RegOpnd * src7Opnd = BuildIntConstOpnd(src7RegSlot);
  4523. IR::RegOpnd * src8Opnd = BuildIntConstOpnd(src8RegSlot);
  4524. IR::RegOpnd * src9Opnd = BuildIntConstOpnd(src9RegSlot);
  4525. IR::Instr * instr = nullptr;
  4526. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
  4527. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
  4528. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  4529. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4530. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4531. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4532. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4533. instr = AddExtendedArg(src6Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4534. instr = AddExtendedArg(src7Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4535. instr = AddExtendedArg(src8Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4536. instr = AddExtendedArg(src9Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4537. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Swizzle_U8);
  4538. Js::OpCode opcode = Js::OpCode::Simd128_Swizzle_U8;
  4539. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  4540. }
  4541. void IRBuilderAsmJs::BuildUint16x8_3Int8(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG11)
  4542. {
  4543. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128U8);
  4544. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128U8);
  4545. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128U8);
  4546. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(src3RegSlot);
  4547. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(src4RegSlot);
  4548. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(src5RegSlot);
  4549. IR::RegOpnd * src6Opnd = BuildIntConstOpnd(src6RegSlot);
  4550. IR::RegOpnd * src7Opnd = BuildIntConstOpnd(src7RegSlot);
  4551. IR::RegOpnd * src8Opnd = BuildIntConstOpnd(src8RegSlot);
  4552. IR::RegOpnd * src9Opnd = BuildIntConstOpnd(src9RegSlot);
  4553. IR::RegOpnd * src10Opnd = BuildIntConstOpnd(src10RegSlot);
  4554. IR::Instr * instr = nullptr;
  4555. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
  4556. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
  4557. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
  4558. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  4559. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4560. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4561. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4562. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4563. instr = AddExtendedArg(src6Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4564. instr = AddExtendedArg(src7Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4565. instr = AddExtendedArg(src8Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4566. instr = AddExtendedArg(src9Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4567. instr = AddExtendedArg(src10Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4568. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Shuffle_U8);
  4569. Js::OpCode opcode = Js::OpCode::Simd128_Shuffle_U8;
  4570. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  4571. }
  4572. void
  4573. IRBuilderAsmJs::BuildUint16x8_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4574. {
  4575. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_U8);
  4576. BuildSimd_1Int1(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U8);
  4577. }
  4578. void
  4579. IRBuilderAsmJs::BuildUint16x8_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  4580. {
  4581. AssertMsg((newOpcode == Js::OpCodeAsmJs::Simd128_ReplaceLane_U8), "Unexpected opcode for this format.");
  4582. BuildSimd_2Int2(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, src3RegSlot, TySimd128U8);
  4583. }
  4584. void
  4585. IRBuilderAsmJs::BuildUint16x8_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4586. {
  4587. BuildSimd_2(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U8);
  4588. }
  4589. void
  4590. IRBuilderAsmJs::BuildUint16x8_3(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4591. {
  4592. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128U8);
  4593. }
  4594. void
  4595. IRBuilderAsmJs::BuildBool16x8_1Uint16x8_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4596. {
  4597. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128B8, TySimd128U8);
  4598. }
  4599. void
  4600. IRBuilderAsmJs::BuildUint16x8_1Bool16x8_1Uint16x8_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  4601. {
  4602. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128B8);
  4603. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128U8);
  4604. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128U8);
  4605. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128U8);
  4606. IR::Instr * instr = nullptr;
  4607. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
  4608. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool16x8));
  4609. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
  4610. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
  4611. // Given bytecode: dst = op s1, s2, s3
  4612. // Generate:
  4613. // t1 = ExtendedArg_A s1
  4614. // t2 = ExtendedArg_A s2, t1
  4615. // t3 = ExtendedArg_A s3, t2
  4616. // dst = op t3
  4617. // Later phases will chain the arguments by following singleDefInstr of each use of ti.
  4618. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  4619. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4620. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4621. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  4622. AssertMsg(opcode == Js::OpCode::Simd128_Select_U8, "Unexpected opcode for this format.");
  4623. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  4624. }
  4625. void
  4626. IRBuilderAsmJs::BuildUint16x8_2Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4627. {
  4628. BuildSimd_2Int1(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128U8);
  4629. }
  4630. void
  4631. IRBuilderAsmJs::BuildUint16x8_1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4632. {
  4633. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromFloat32x4Bits_U8, "Unexpected opcode for this format.");
  4634. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U8, TySimd128F4);
  4635. }
  4636. void
  4637. IRBuilderAsmJs::BuildUint16x8_1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4638. {
  4639. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt32x4Bits_U8, "Unexpected opcode for this format.");
  4640. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U8, TySimd128I4);
  4641. }
  4642. void
  4643. IRBuilderAsmJs::BuildUint16x8_1Int16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4644. {
  4645. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt16x8Bits_U8, "Unexpected opcode for this format.");
  4646. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U8, TySimd128I8);
  4647. }
  4648. void
  4649. IRBuilderAsmJs::BuildUint16x8_1Int8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4650. {
  4651. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt8x16Bits_U8, "Unexpected opcode for this format.");
  4652. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U8, TySimd128I16);
  4653. }
  4654. void
  4655. IRBuilderAsmJs::BuildUint16x8_1Uint32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4656. {
  4657. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint32x4Bits_U8, "Unexpected opcode for this format.");
  4658. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U8, TySimd128U4);
  4659. }
  4660. void
  4661. IRBuilderAsmJs::BuildUint16x8_1Uint8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4662. {
  4663. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint8x16Bits_U8, "Unexpected opcode for this format.");
  4664. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U8, TySimd128U16);
  4665. }
  4666. /* Uint8x16 */
  4667. void IRBuilderAsmJs::BuildUint8x16_1Int16(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG17)
  4668. {
  4669. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_IntsToU16, "Unexpected opcode for this format.");
  4670. uint const LANES = 16;
  4671. Js::RegSlot srcRegSlots[LANES];
  4672. srcRegSlots[0] = src1RegSlot;
  4673. srcRegSlots[1] = src2RegSlot;
  4674. srcRegSlots[2] = src3RegSlot;
  4675. srcRegSlots[3] = src4RegSlot;
  4676. srcRegSlots[4] = src5RegSlot;
  4677. srcRegSlots[5] = src6RegSlot;
  4678. srcRegSlots[6] = src7RegSlot;
  4679. srcRegSlots[7] = src8RegSlot;
  4680. srcRegSlots[8] = src9RegSlot;
  4681. srcRegSlots[9] = src10RegSlot;
  4682. srcRegSlots[10] = src11RegSlot;
  4683. srcRegSlots[11] = src12RegSlot;
  4684. srcRegSlots[12] = src13RegSlot;
  4685. srcRegSlots[13] = src14RegSlot;
  4686. srcRegSlots[14] = src15RegSlot;
  4687. srcRegSlots[15] = src16RegSlot;
  4688. BuildSimd_1Ints(newOpcode, offset, TySimd128U16, srcRegSlots, dstRegSlot, LANES);
  4689. }
  4690. void IRBuilderAsmJs::BuildReg1Uint8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4691. {
  4692. IR::RegOpnd * srcOpnd = BuildSrcOpnd(src1RegSlot, TySimd128U16);
  4693. srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint8x16));
  4694. IR::Instr * instr = nullptr;
  4695. IR::Opnd * dstOpnd = nullptr;
  4696. StackSym * symDst = nullptr;
  4697. if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_U16)
  4698. {
  4699. symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128U16);
  4700. symDst->m_allocated = true;
  4701. if (symDst == nullptr || (uint16)(dstRegSlot) != (dstRegSlot))
  4702. {
  4703. AssertMsg(UNREACHED, "Arg count too big...");
  4704. Fatal();
  4705. }
  4706. dstOpnd = IR::SymOpnd::New(symDst, TySimd128U16, m_func);
  4707. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint16x8));
  4708. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  4709. AddInstr(instr, offset);
  4710. m_argStack->Push(instr);
  4711. }
  4712. else
  4713. {
  4714. Assert(UNREACHED);
  4715. }
  4716. }
  4717. void
  4718. IRBuilderAsmJs::BuildUint8x16_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4719. {
  4720. BuildSimd_2(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U16);
  4721. }
  4722. void
  4723. IRBuilderAsmJs::BuildInt1Uint8x16_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4724. {
  4725. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128U16);
  4726. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint8x16));
  4727. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  4728. src2Opnd->SetValueType(ValueType::GetInt(false));
  4729. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  4730. dstOpnd->SetValueType(ValueType::GetInt(false));
  4731. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  4732. AssertMsg((opcode == Js::OpCode::Simd128_ExtractLane_U16), "Unexpected opcode for this format.");
  4733. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  4734. AddInstr(instr, offset);
  4735. }
  4736. void IRBuilderAsmJs::BuildUint8x16_2Int16(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG18)
  4737. {
  4738. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128U16);
  4739. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128U16);
  4740. IR::RegOpnd * src2Opnd = BuildIntConstOpnd(src2RegSlot);
  4741. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(src3RegSlot);
  4742. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(src4RegSlot);
  4743. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(src5RegSlot);
  4744. IR::RegOpnd * src6Opnd = BuildIntConstOpnd(src6RegSlot);
  4745. IR::RegOpnd * src7Opnd = BuildIntConstOpnd(src7RegSlot);
  4746. IR::RegOpnd * src8Opnd = BuildIntConstOpnd(src8RegSlot);
  4747. IR::RegOpnd * src9Opnd = BuildIntConstOpnd(src9RegSlot);
  4748. IR::RegOpnd * src10Opnd = BuildIntConstOpnd(src10RegSlot);
  4749. IR::RegOpnd * src11Opnd = BuildIntConstOpnd(src11RegSlot);
  4750. IR::RegOpnd * src12Opnd = BuildIntConstOpnd(src12RegSlot);
  4751. IR::RegOpnd * src13Opnd = BuildIntConstOpnd(src13RegSlot);
  4752. IR::RegOpnd * src14Opnd = BuildIntConstOpnd(src14RegSlot);
  4753. IR::RegOpnd * src15Opnd = BuildIntConstOpnd(src15RegSlot);
  4754. IR::RegOpnd * src16Opnd = BuildIntConstOpnd(src16RegSlot);
  4755. IR::RegOpnd * src17Opnd = BuildIntConstOpnd(src17RegSlot);
  4756. IR::Instr * instr = nullptr;
  4757. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint8x16));
  4758. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint8x16));
  4759. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  4760. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4761. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4762. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4763. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4764. instr = AddExtendedArg(src6Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4765. instr = AddExtendedArg(src7Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4766. instr = AddExtendedArg(src8Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4767. instr = AddExtendedArg(src9Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4768. instr = AddExtendedArg(src10Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4769. instr = AddExtendedArg(src11Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4770. instr = AddExtendedArg(src12Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4771. instr = AddExtendedArg(src13Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4772. instr = AddExtendedArg(src14Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4773. instr = AddExtendedArg(src15Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4774. instr = AddExtendedArg(src16Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4775. instr = AddExtendedArg(src17Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4776. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Swizzle_U16);
  4777. Js::OpCode opcode = Js::OpCode::Simd128_Swizzle_U16;
  4778. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  4779. }
  4780. void IRBuilderAsmJs::BuildUint8x16_3Int16(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG19)
  4781. {
  4782. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128U16);
  4783. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128U16);
  4784. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128U16);
  4785. IR::RegOpnd * src3Opnd = BuildIntConstOpnd(src3RegSlot);
  4786. IR::RegOpnd * src4Opnd = BuildIntConstOpnd(src4RegSlot);
  4787. IR::RegOpnd * src5Opnd = BuildIntConstOpnd(src5RegSlot);
  4788. IR::RegOpnd * src6Opnd = BuildIntConstOpnd(src6RegSlot);
  4789. IR::RegOpnd * src7Opnd = BuildIntConstOpnd(src7RegSlot);
  4790. IR::RegOpnd * src8Opnd = BuildIntConstOpnd(src8RegSlot);
  4791. IR::RegOpnd * src9Opnd = BuildIntConstOpnd(src9RegSlot);
  4792. IR::RegOpnd * src10Opnd = BuildIntConstOpnd(src10RegSlot);
  4793. IR::RegOpnd * src11Opnd = BuildIntConstOpnd(src11RegSlot);
  4794. IR::RegOpnd * src12Opnd = BuildIntConstOpnd(src12RegSlot);
  4795. IR::RegOpnd * src13Opnd = BuildIntConstOpnd(src13RegSlot);
  4796. IR::RegOpnd * src14Opnd = BuildIntConstOpnd(src14RegSlot);
  4797. IR::RegOpnd * src15Opnd = BuildIntConstOpnd(src15RegSlot);
  4798. IR::RegOpnd * src16Opnd = BuildIntConstOpnd(src16RegSlot);
  4799. IR::RegOpnd * src17Opnd = BuildIntConstOpnd(src17RegSlot);
  4800. IR::RegOpnd * src18Opnd = BuildIntConstOpnd(src18RegSlot);
  4801. IR::Instr * instr = nullptr;
  4802. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint8x16));
  4803. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint8x16));
  4804. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint8x16));
  4805. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  4806. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4807. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4808. instr = AddExtendedArg(src4Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4809. instr = AddExtendedArg(src5Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4810. instr = AddExtendedArg(src6Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4811. instr = AddExtendedArg(src7Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4812. instr = AddExtendedArg(src8Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4813. instr = AddExtendedArg(src9Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4814. instr = AddExtendedArg(src10Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4815. instr = AddExtendedArg(src11Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4816. instr = AddExtendedArg(src12Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4817. instr = AddExtendedArg(src13Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4818. instr = AddExtendedArg(src14Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4819. instr = AddExtendedArg(src15Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4820. instr = AddExtendedArg(src16Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4821. instr = AddExtendedArg(src17Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4822. instr = AddExtendedArg(src18Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4823. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Shuffle_U16);
  4824. Js::OpCode opcode = Js::OpCode::Simd128_Shuffle_U16;
  4825. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  4826. }
  4827. void
  4828. IRBuilderAsmJs::BuildUint8x16_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  4829. {
  4830. AssertMsg((newOpcode == Js::OpCodeAsmJs::Simd128_ReplaceLane_U16), "Unexpected opcode for this format.");
  4831. BuildSimd_2Int2(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, src3RegSlot, TySimd128U16);
  4832. }
  4833. void
  4834. IRBuilderAsmJs::BuildUint8x16_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4835. {
  4836. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_U16);
  4837. BuildSimd_1Int1(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U16);
  4838. }
  4839. void
  4840. IRBuilderAsmJs::BuildUint8x16_3(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4841. {
  4842. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128U16);
  4843. }
  4844. void
  4845. IRBuilderAsmJs::BuildBool8x16_1Uint8x16_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4846. {
  4847. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128B16, TySimd128U16);
  4848. }
  4849. void
  4850. IRBuilderAsmJs::BuildUint8x16_1Bool8x16_1Uint8x16_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  4851. {
  4852. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128B16);
  4853. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TySimd128U16);
  4854. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TySimd128U16);
  4855. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TySimd128U16);
  4856. IR::Instr * instr = nullptr;
  4857. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint8x16));
  4858. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool8x16));
  4859. src2Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint8x16));
  4860. src3Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Uint8x16));
  4861. // Given bytecode: dst = op s1, s2, s3
  4862. // Generate:
  4863. // t1 = ExtendedArg_A s1
  4864. // t2 = ExtendedArg_A s2, t1
  4865. // t3 = ExtendedArg_A s3, t2
  4866. // dst = op t3
  4867. // Later phases will chain the arguments by following singleDefInstr of each use of ti.
  4868. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  4869. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4870. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  4871. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  4872. AssertMsg(opcode == Js::OpCode::Simd128_Select_U16, "Unexpected opcode for this format.");
  4873. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  4874. }
  4875. void
  4876. IRBuilderAsmJs::BuildUint8x16_2Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4877. {
  4878. BuildSimd_2Int1(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128U16);
  4879. }
  4880. void
  4881. IRBuilderAsmJs::BuildUint8x16_1Float32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4882. {
  4883. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromFloat32x4Bits_U16, "Unexpected opcode for this format.");
  4884. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U16, TySimd128F4);
  4885. }
  4886. void
  4887. IRBuilderAsmJs::BuildUint8x16_1Int32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4888. {
  4889. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt32x4Bits_U16, "Unexpected opcode for this format.");
  4890. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U16, TySimd128I4);
  4891. }
  4892. void
  4893. IRBuilderAsmJs::BuildUint8x16_1Int16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4894. {
  4895. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt16x8Bits_U16, "Unexpected opcode for this format.");
  4896. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U16, TySimd128I8);
  4897. }
  4898. /* Enable with Int8x16 support */
  4899. void
  4900. IRBuilderAsmJs::BuildUint8x16_1Int8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4901. {
  4902. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromInt8x16Bits_U16, "Unexpected opcode for this format.");
  4903. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U16, TySimd128I16);
  4904. }
  4905. void
  4906. IRBuilderAsmJs::BuildUint8x16_1Uint32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4907. {
  4908. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint32x4Bits_U16, "Unexpected opcode for this format.");
  4909. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U16, TySimd128U4);
  4910. }
  4911. void
  4912. IRBuilderAsmJs::BuildUint8x16_1Uint16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4913. {
  4914. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_FromUint16x8Bits_U16, "Unexpected opcode for this format.");
  4915. BuildSimdConversion(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128U16, TySimd128U8);
  4916. }
  4917. //Bool32x4
  4918. void IRBuilderAsmJs::BuildBool32x4_1Int4(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG5)
  4919. {
  4920. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_IntsToB4, "Unexpected opcode for this format.");
  4921. uint const LANES = 4;
  4922. Js::RegSlot srcRegSlot[LANES];
  4923. srcRegSlot[0] = src1RegSlot;
  4924. srcRegSlot[1] = src2RegSlot;
  4925. srcRegSlot[2] = src3RegSlot;
  4926. srcRegSlot[3] = src4RegSlot;
  4927. BuildSimd_1Ints(newOpcode, offset, TySimd128B4, srcRegSlot, dstRegSlot, LANES);
  4928. }
  4929. void
  4930. IRBuilderAsmJs::BuildInt1Bool32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4931. {
  4932. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128B4);
  4933. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool32x4));
  4934. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  4935. dstOpnd->SetValueType(ValueType::GetInt(false));
  4936. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  4937. AssertMsg((opcode == Js::OpCode::Simd128_AllTrue_B4 || opcode == Js::OpCode::Simd128_AnyTrue_B4),
  4938. "Unexpected opcode for this format.");
  4939. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  4940. AddInstr(instr, offset);
  4941. }
  4942. void
  4943. IRBuilderAsmJs::BuildBool32x4_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4944. {
  4945. BuildSimd_2(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128B4);
  4946. }
  4947. void
  4948. IRBuilderAsmJs::BuildBool32x4_3(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  4949. {
  4950. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128B4);
  4951. }
  4952. void IRBuilderAsmJs::BuildReg1Bool32x4_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4953. {
  4954. IR::RegOpnd * srcOpnd = BuildSrcOpnd(src1RegSlot, TySimd128B4);
  4955. srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool32x4));
  4956. IR::Instr * instr = nullptr;
  4957. IR::Opnd * dstOpnd = nullptr;
  4958. StackSym * symDst = nullptr;
  4959. if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_B4)
  4960. {
  4961. symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128B4);
  4962. symDst->m_allocated = true;
  4963. if ((uint16)(dstRegSlot) != (dstRegSlot))
  4964. {
  4965. AssertMsg(UNREACHED, "Arg count too big...");
  4966. Fatal();
  4967. }
  4968. dstOpnd = IR::SymOpnd::New(symDst, TySimd128B4, m_func);
  4969. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool32x4));
  4970. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  4971. AddInstr(instr, offset);
  4972. m_argStack->Push(instr);
  4973. }
  4974. else
  4975. {
  4976. Assert(UNREACHED);
  4977. }
  4978. }
  4979. //Bool16x8
  4980. void IRBuilderAsmJs::BuildBool16x8_1Int8(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG9)
  4981. {
  4982. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_IntsToB8, "Unexpected opcode for this format.");
  4983. uint const LANES = 8;
  4984. Js::RegSlot srcRegSlots[LANES];
  4985. srcRegSlots[0] = src1RegSlot;
  4986. srcRegSlots[1] = src2RegSlot;
  4987. srcRegSlots[2] = src3RegSlot;
  4988. srcRegSlots[3] = src4RegSlot;
  4989. srcRegSlots[4] = src5RegSlot;
  4990. srcRegSlots[5] = src6RegSlot;
  4991. srcRegSlots[6] = src7RegSlot;
  4992. srcRegSlots[7] = src8RegSlot;
  4993. BuildSimd_1Ints(newOpcode, offset, TySimd128B8, srcRegSlots, dstRegSlot, LANES);
  4994. }
  4995. void
  4996. IRBuilderAsmJs::BuildInt1Bool16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  4997. {
  4998. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128B8);
  4999. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool16x8));
  5000. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  5001. dstOpnd->SetValueType(ValueType::GetInt(false));
  5002. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  5003. AssertMsg((opcode == Js::OpCode::Simd128_AllTrue_B8 || opcode == Js::OpCode::Simd128_AnyTrue_B8),
  5004. "Unexpected opcode for this format.");
  5005. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  5006. AddInstr(instr, offset);
  5007. }
  5008. void
  5009. IRBuilderAsmJs::BuildBool16x8_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  5010. {
  5011. BuildSimd_2(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128B8);
  5012. }
  5013. void
  5014. IRBuilderAsmJs::BuildBool16x8_3(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  5015. {
  5016. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128B8);
  5017. }
  5018. void
  5019. IRBuilderAsmJs::BuildReg1Bool16x8_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  5020. {
  5021. IR::RegOpnd * srcOpnd = BuildSrcOpnd(src1RegSlot, TySimd128B8);
  5022. srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool16x8));
  5023. IR::Instr * instr = nullptr;
  5024. IR::Opnd * dstOpnd = nullptr;
  5025. StackSym * symDst = nullptr;
  5026. if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_B8)
  5027. {
  5028. symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128B8);
  5029. symDst->m_allocated = true;
  5030. if ((uint16)(dstRegSlot) != (dstRegSlot))
  5031. {
  5032. AssertMsg(UNREACHED, "Arg count too big...");
  5033. Fatal();
  5034. }
  5035. dstOpnd = IR::SymOpnd::New(symDst, TySimd128B8, m_func);
  5036. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool16x8));
  5037. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  5038. AddInstr(instr, offset);
  5039. m_argStack->Push(instr);
  5040. }
  5041. else
  5042. {
  5043. Assert(UNREACHED);
  5044. }
  5045. }
  5046. //Bool8x16
  5047. void IRBuilderAsmJs::BuildBool8x16_1Int16(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG17)
  5048. {
  5049. AssertMsg(newOpcode == Js::OpCodeAsmJs::Simd128_IntsToB16, "Unexpected opcode for this format.");
  5050. uint const LANES = 16;
  5051. Js::RegSlot srcRegSlots[LANES];
  5052. srcRegSlots[0] = src1RegSlot;
  5053. srcRegSlots[1] = src2RegSlot;
  5054. srcRegSlots[2] = src3RegSlot;
  5055. srcRegSlots[3] = src4RegSlot;
  5056. srcRegSlots[4] = src5RegSlot;
  5057. srcRegSlots[5] = src6RegSlot;
  5058. srcRegSlots[6] = src7RegSlot;
  5059. srcRegSlots[7] = src8RegSlot;
  5060. srcRegSlots[8] = src9RegSlot;
  5061. srcRegSlots[9] = src10RegSlot;
  5062. srcRegSlots[10] = src11RegSlot;
  5063. srcRegSlots[11] = src12RegSlot;
  5064. srcRegSlots[12] = src13RegSlot;
  5065. srcRegSlots[13] = src14RegSlot;
  5066. srcRegSlots[14] = src15RegSlot;
  5067. srcRegSlots[15] = src16RegSlot;
  5068. BuildSimd_1Ints(newOpcode, offset, TySimd128B16, srcRegSlots, dstRegSlot, LANES);
  5069. }
  5070. void
  5071. IRBuilderAsmJs::BuildInt1Bool8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  5072. {
  5073. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128B16);
  5074. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool8x16));
  5075. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  5076. dstOpnd->SetValueType(ValueType::GetInt(false));
  5077. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  5078. AssertMsg((opcode == Js::OpCode::Simd128_AllTrue_B16 || opcode == Js::OpCode::Simd128_AnyTrue_B16),
  5079. "Unexpected opcode for this format.");
  5080. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  5081. AddInstr(instr, offset);
  5082. }
  5083. void
  5084. IRBuilderAsmJs::BuildBool8x16_2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  5085. {
  5086. BuildSimd_2(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128B16);
  5087. }
  5088. void
  5089. IRBuilderAsmJs::BuildBool8x16_3(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  5090. {
  5091. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, TySimd128B16);
  5092. }
  5093. void IRBuilderAsmJs::BuildReg1Bool8x16_1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  5094. {
  5095. IR::RegOpnd * srcOpnd = BuildSrcOpnd(src1RegSlot, TySimd128B16);
  5096. srcOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool8x16));
  5097. IR::Instr * instr = nullptr;
  5098. IR::Opnd * dstOpnd = nullptr;
  5099. StackSym * symDst = nullptr;
  5100. if (newOpcode == Js::OpCodeAsmJs::Simd128_I_ArgOut_B16)
  5101. {
  5102. symDst = StackSym::NewArgSlotSym((uint16)dstRegSlot, m_func, TySimd128B16);
  5103. symDst->m_allocated = true;
  5104. if ((uint16)(dstRegSlot) != (dstRegSlot))
  5105. {
  5106. AssertMsg(UNREACHED, "Arg count too big...");
  5107. Fatal();
  5108. }
  5109. dstOpnd = IR::SymOpnd::New(symDst, TySimd128B16, m_func);
  5110. dstOpnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool8x16));
  5111. instr = IR::Instr::New(Js::OpCode::ArgOut_A, dstOpnd, srcOpnd, m_func);
  5112. AddInstr(instr, offset);
  5113. m_argStack->Push(instr);
  5114. }
  5115. else
  5116. {
  5117. Assert(UNREACHED);
  5118. }
  5119. }
  5120. //Bool extractLane/ReplaceLane
  5121. void
  5122. IRBuilderAsmJs::BuildBool32x4_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  5123. {
  5124. AssertMsg((newOpcode == Js::OpCodeAsmJs::Simd128_ReplaceLane_B4), "Unexpected opcode for this format.");
  5125. BuildSimd_2Int2(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, src3RegSlot, TySimd128B4);
  5126. }
  5127. void
  5128. IRBuilderAsmJs::BuildBool16x8_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  5129. {
  5130. AssertMsg((newOpcode == Js::OpCodeAsmJs::Simd128_ReplaceLane_B8), "Unexpected opcode for this format.");
  5131. BuildSimd_2Int2(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, src3RegSlot, TySimd128B8);
  5132. }
  5133. void
  5134. IRBuilderAsmJs::BuildBool8x16_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG4)
  5135. {
  5136. AssertMsg((newOpcode == Js::OpCodeAsmJs::Simd128_ReplaceLane_B16), "Unexpected opcode for this format.");
  5137. BuildSimd_2Int2(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, src3RegSlot, TySimd128B16);
  5138. }
  5139. void
  5140. IRBuilderAsmJs::BuildInt1Bool32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  5141. {
  5142. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128B4);
  5143. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool32x4));
  5144. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  5145. src2Opnd->SetValueType(ValueType::GetInt(false));
  5146. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  5147. dstOpnd->SetValueType(ValueType::GetInt(false));
  5148. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  5149. AssertMsg((opcode == Js::OpCode::Simd128_ExtractLane_B4), "Unexpected opcode for this format.");
  5150. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  5151. AddInstr(instr, offset);
  5152. }
  5153. void
  5154. IRBuilderAsmJs::BuildInt1Bool16x8_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  5155. {
  5156. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128B8);
  5157. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool16x8));
  5158. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  5159. src2Opnd->SetValueType(ValueType::GetInt(false));
  5160. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  5161. dstOpnd->SetValueType(ValueType::GetInt(false));
  5162. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  5163. AssertMsg((opcode == Js::OpCode::Simd128_ExtractLane_B8), "Unexpected opcode for this format.");
  5164. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  5165. AddInstr(instr, offset);
  5166. }
  5167. void
  5168. IRBuilderAsmJs::BuildInt1Bool8x16_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG3)
  5169. {
  5170. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TySimd128B16);
  5171. src1Opnd->SetValueType(ValueType::GetSimd128(ObjectType::Simd128Bool8x16));
  5172. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  5173. src2Opnd->SetValueType(ValueType::GetInt(false));
  5174. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, TyInt32);
  5175. dstOpnd->SetValueType(ValueType::GetInt(false));
  5176. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  5177. AssertMsg((opcode == Js::OpCode::Simd128_ExtractLane_B16), "Unexpected opcode for this format.");
  5178. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  5179. AddInstr(instr, offset);
  5180. }
  5181. void IRBuilderAsmJs::BuildSimd_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, IRType simdType)
  5182. {
  5183. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, TyInt32);
  5184. src1Opnd->SetValueType(ValueType::GetInt(false));
  5185. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, simdType);
  5186. dstOpnd->SetValueType(GetSimdValueTypeFromIRType(simdType));
  5187. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  5188. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  5189. AddInstr(instr, offset);
  5190. }
  5191. void IRBuilderAsmJs::BuildSimd_2Int2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot, Js::RegSlot src3RegSlot, IRType simdType)
  5192. {
  5193. ValueType valueType = GetSimdValueTypeFromIRType(simdType);
  5194. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, simdType);
  5195. src1Opnd->SetValueType(valueType);
  5196. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  5197. src2Opnd->SetValueType(ValueType::GetInt(false));
  5198. IR::RegOpnd * src3Opnd = BuildSrcOpnd(src3RegSlot, TyInt32);
  5199. src3Opnd->SetValueType(ValueType::GetInt(false));
  5200. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, simdType);
  5201. dstOpnd->SetValueType(valueType);
  5202. // Given bytecode: dst = op s1, s2, s3
  5203. // Generate:
  5204. // t1 = ExtendedArg_A s1
  5205. // t2 = ExtendedArg_A s2, t1
  5206. // t3 = ExtendedArg_A s3, t2
  5207. // dst = op t3
  5208. IR::Instr* instr = nullptr;
  5209. instr = AddExtendedArg(src1Opnd, nullptr, offset);
  5210. instr = AddExtendedArg(src2Opnd, instr->GetDst()->AsRegOpnd(), offset);
  5211. instr = AddExtendedArg(src3Opnd, instr->GetDst()->AsRegOpnd(), offset);
  5212. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  5213. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  5214. }
  5215. void IRBuilderAsmJs::BuildSimd_2(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, IRType simdType)
  5216. {
  5217. ValueType valueType = GetSimdValueTypeFromIRType(simdType);
  5218. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, simdType);
  5219. src1Opnd->SetValueType(valueType);
  5220. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, simdType);
  5221. dstOpnd->SetValueType(valueType);
  5222. Js::OpCode opcode;
  5223. switch (newOpcode)
  5224. {
  5225. case Js::OpCodeAsmJs::Simd128_Return_F4:
  5226. case Js::OpCodeAsmJs::Simd128_Return_I4:
  5227. case Js::OpCodeAsmJs::Simd128_Return_I8:
  5228. case Js::OpCodeAsmJs::Simd128_Return_I16:
  5229. case Js::OpCodeAsmJs::Simd128_Return_U4:
  5230. case Js::OpCodeAsmJs::Simd128_Return_U8:
  5231. case Js::OpCodeAsmJs::Simd128_Return_U16:
  5232. case Js::OpCodeAsmJs::Simd128_Return_B4:
  5233. case Js::OpCodeAsmJs::Simd128_Return_B8:
  5234. case Js::OpCodeAsmJs::Simd128_Return_B16:
  5235. if (m_func->IsLoopBody())
  5236. {
  5237. IR::Instr* slotInstr = GenerateStSlotForReturn(src1Opnd, simdType);
  5238. AddInstr(slotInstr, offset);
  5239. }
  5240. opcode = Js::OpCode::Ld_A;
  5241. break;
  5242. case Js::OpCodeAsmJs::Simd128_I_Conv_VTF4:
  5243. case Js::OpCodeAsmJs::Simd128_I_Conv_VTI4:
  5244. case Js::OpCodeAsmJs::Simd128_I_Conv_VTI8:
  5245. case Js::OpCodeAsmJs::Simd128_I_Conv_VTI16:
  5246. case Js::OpCodeAsmJs::Simd128_I_Conv_VTU4:
  5247. case Js::OpCodeAsmJs::Simd128_I_Conv_VTU8:
  5248. case Js::OpCodeAsmJs::Simd128_I_Conv_VTU16:
  5249. case Js::OpCodeAsmJs::Simd128_I_Conv_VTB4:
  5250. case Js::OpCodeAsmJs::Simd128_I_Conv_VTB8:
  5251. case Js::OpCodeAsmJs::Simd128_I_Conv_VTB16:
  5252. case Js::OpCodeAsmJs::Simd128_Ld_F4:
  5253. case Js::OpCodeAsmJs::Simd128_Ld_I4:
  5254. case Js::OpCodeAsmJs::Simd128_Ld_I8:
  5255. case Js::OpCodeAsmJs::Simd128_Ld_I16:
  5256. case Js::OpCodeAsmJs::Simd128_Ld_U4:
  5257. case Js::OpCodeAsmJs::Simd128_Ld_U8:
  5258. case Js::OpCodeAsmJs::Simd128_Ld_U16:
  5259. case Js::OpCodeAsmJs::Simd128_Ld_B4:
  5260. case Js::OpCodeAsmJs::Simd128_Ld_B8:
  5261. case Js::OpCodeAsmJs::Simd128_Ld_B16:
  5262. opcode = Js::OpCode::Ld_A;
  5263. break;
  5264. default:
  5265. opcode = GetSimdOpcode(newOpcode);
  5266. }
  5267. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  5268. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  5269. AddInstr(instr, offset);
  5270. }
  5271. void IRBuilderAsmJs::BuildSimd_2Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot, IRType simdType)
  5272. {
  5273. ValueType valueType = GetSimdValueTypeFromIRType(simdType);
  5274. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, simdType);
  5275. src1Opnd->SetValueType(valueType);
  5276. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, TyInt32);
  5277. src2Opnd->SetValueType(ValueType::GetInt(false));
  5278. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, simdType);
  5279. dstOpnd->SetValueType(valueType);
  5280. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  5281. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  5282. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  5283. AddInstr(instr, offset);
  5284. }
  5285. void IRBuilderAsmJs::BuildSimd_3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot, IRType simdType)
  5286. {
  5287. BuildSimd_3(newOpcode, offset, dstRegSlot, src1RegSlot, src2RegSlot, simdType, simdType);
  5288. }
  5289. void IRBuilderAsmJs::BuildSimd_3(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot src1RegSlot, Js::RegSlot src2RegSlot, IRType dstSimdType, IRType srcSimdType)
  5290. {
  5291. ValueType valueType = GetSimdValueTypeFromIRType(srcSimdType);
  5292. IR::RegOpnd * src1Opnd = BuildSrcOpnd(src1RegSlot, srcSimdType);
  5293. src1Opnd->SetValueType(valueType);
  5294. IR::RegOpnd * src2Opnd = BuildSrcOpnd(src2RegSlot, srcSimdType);
  5295. src2Opnd->SetValueType(valueType);
  5296. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, dstSimdType);
  5297. dstOpnd->SetValueType(GetSimdValueTypeFromIRType(dstSimdType));
  5298. Js::OpCode opcode;
  5299. opcode = GetSimdOpcode(newOpcode);
  5300. AssertMsg((uint32)opcode, "Invalid backend SIMD opcode");
  5301. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, src2Opnd, m_func);
  5302. AddInstr(instr, offset);
  5303. }
  5304. // bool32x4
  5305. void
  5306. IRBuilderAsmJs::BuildBool32x4_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  5307. {
  5308. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_B4);
  5309. BuildSimd_1Int1(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128B4);
  5310. }
  5311. // bool16x8
  5312. void
  5313. IRBuilderAsmJs::BuildBool16x8_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  5314. {
  5315. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_B8);
  5316. BuildSimd_1Int1(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128B8);
  5317. }
  5318. // bool8x16
  5319. void
  5320. IRBuilderAsmJs::BuildBool8x16_1Int1(Js::OpCodeAsmJs newOpcode, uint32 offset, BUILD_SIMD_ARGS_REG2)
  5321. {
  5322. Assert(newOpcode == Js::OpCodeAsmJs::Simd128_Splat_B16);
  5323. BuildSimd_1Int1(newOpcode, offset, dstRegSlot, src1RegSlot, TySimd128B16);
  5324. }
  5325. void IRBuilderAsmJs::BuildSimdConversion(Js::OpCodeAsmJs newOpcode, uint32 offset, Js::RegSlot dstRegSlot, Js::RegSlot srcRegSlot, IRType dstSimdType, IRType srcSimdType)
  5326. {
  5327. ValueType srcValueType = GetSimdValueTypeFromIRType(srcSimdType);
  5328. ValueType dstValueType = GetSimdValueTypeFromIRType(dstSimdType);
  5329. IR::RegOpnd * src1Opnd = BuildSrcOpnd(srcRegSlot, srcSimdType);
  5330. src1Opnd->SetValueType(srcValueType);
  5331. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, dstSimdType);
  5332. dstOpnd->SetValueType(dstValueType);
  5333. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  5334. IR::Instr * instr = IR::Instr::New(opcode, dstOpnd, src1Opnd, m_func);
  5335. AddInstr(instr, offset);
  5336. }
  5337. ValueType IRBuilderAsmJs::GetSimdValueTypeFromIRType(IRType type)
  5338. {
  5339. switch (type)
  5340. {
  5341. case TySimd128F4:
  5342. return ValueType::GetSimd128(ObjectType::Simd128Float32x4);
  5343. case TySimd128D2:
  5344. return ValueType::GetSimd128(ObjectType::Simd128Float64x2);
  5345. case TySimd128I4:
  5346. return ValueType::GetSimd128(ObjectType::Simd128Int32x4);
  5347. case TySimd128I8:
  5348. return ValueType::GetSimd128(ObjectType::Simd128Int16x8);
  5349. case TySimd128I16:
  5350. return ValueType::GetSimd128(ObjectType::Simd128Int8x16);
  5351. case TySimd128U4:
  5352. return ValueType::GetSimd128(ObjectType::Simd128Uint32x4);
  5353. case TySimd128U8:
  5354. return ValueType::GetSimd128(ObjectType::Simd128Uint16x8);
  5355. case TySimd128U16:
  5356. return ValueType::GetSimd128(ObjectType::Simd128Uint8x16);
  5357. case TySimd128B4:
  5358. return ValueType::GetSimd128(ObjectType::Simd128Bool32x4);
  5359. case TySimd128B8:
  5360. return ValueType::GetSimd128(ObjectType::Simd128Bool16x8);
  5361. case TySimd128B16:
  5362. return ValueType::GetSimd128(ObjectType::Simd128Bool8x16);
  5363. default:
  5364. Assert(UNREACHED);
  5365. }
  5366. return ValueType::GetObject(ObjectType::UninitializedObject);
  5367. }
  5368. void IRBuilderAsmJs::BuildSimd_1Ints(Js::OpCodeAsmJs newOpcode, uint32 offset, IRType dstSimdType, Js::RegSlot* srcRegSlots, Js::RegSlot dstRegSlot, uint LANES)
  5369. {
  5370. Assert(dstSimdType == TySimd128B4 || dstSimdType == TySimd128I4 || dstSimdType == TySimd128U4 ||
  5371. dstSimdType == TySimd128B8 || dstSimdType == TySimd128I8 || dstSimdType == TySimd128U8 ||
  5372. dstSimdType == TySimd128B16|| dstSimdType == TySimd128I16|| dstSimdType == TySimd128U16);
  5373. IR::RegOpnd * srcOpnds[16];
  5374. IR::Instr * instr = nullptr;
  5375. Assert(LANES <= 16);
  5376. Js::OpCode opcode = GetSimdOpcode(newOpcode);
  5377. // first arg
  5378. srcOpnds[0] = BuildSrcOpnd(srcRegSlots[0], TyInt32);
  5379. srcOpnds[0]->SetValueType(ValueType::GetInt(false));
  5380. instr = AddExtendedArg(srcOpnds[0], nullptr, offset);
  5381. // reset of args
  5382. for (uint i = 1; i < LANES && i < 16; i++)
  5383. {
  5384. srcOpnds[i] = BuildSrcOpnd(srcRegSlots[i], TyInt32);
  5385. srcOpnds[i]->SetValueType(ValueType::GetInt(false));
  5386. instr = AddExtendedArg(srcOpnds[i], instr->GetDst()->AsRegOpnd(), offset);
  5387. }
  5388. IR::RegOpnd * dstOpnd = BuildDstOpnd(dstRegSlot, dstSimdType);
  5389. dstOpnd->SetValueType(GetSimdValueTypeFromIRType(dstSimdType));
  5390. AddInstr(IR::Instr::New(opcode, dstOpnd, instr->GetDst(), m_func), offset);
  5391. }
  5392. template<typename SizePolicy>
  5393. void IRBuilderAsmJs::BuildAsmSimdTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset)
  5394. {
  5395. Assert(OpCodeAttrAsmJs::HasMultiSizeLayout(newOpcode));
  5396. auto layout = m_jnReader.GetLayout<Js::OpLayoutT_AsmSimdTypedArr<SizePolicy>>();
  5397. BuildAsmSimdTypedArr(newOpcode, offset, layout->SlotIndex, layout->Value, layout->ViewType, layout->DataWidth);
  5398. }
  5399. void
  5400. IRBuilderAsmJs::BuildAsmSimdTypedArr(Js::OpCodeAsmJs newOpcode, uint32 offset, uint32 slotIndex, Js::RegSlot value, Js::ArrayBufferView::ViewType viewType, uint8 dataWidth)
  5401. {
  5402. IRType type = TySimd128F4;
  5403. Js::RegSlot valueRegSlot = GetRegSlotFromSimd128Reg(value);
  5404. IR::RegOpnd * maskedOpnd = nullptr;
  5405. IR::Instr * maskInstr = nullptr;
  5406. Js::OpCode op = GetSimdOpcode(newOpcode);
  5407. ValueType arrayType, valueType;
  5408. bool isLd = false, isConst = false;
  5409. uint32 mask = 0;
  5410. switch (newOpcode)
  5411. {
  5412. case Js::OpCodeAsmJs::Simd128_LdArr_I4:
  5413. valueType = ValueType::GetObject(ObjectType::Simd128Int32x4);
  5414. isLd = true;
  5415. isConst = false;
  5416. type = TySimd128I4;
  5417. break;
  5418. case Js::OpCodeAsmJs::Simd128_LdArr_I8:
  5419. valueType = ValueType::GetObject(ObjectType::Simd128Int16x8);
  5420. isLd = true;
  5421. isConst = false;
  5422. type = TySimd128I8;
  5423. break;
  5424. case Js::OpCodeAsmJs::Simd128_LdArr_I16:
  5425. valueType = ValueType::GetObject(ObjectType::Simd128Int8x16);
  5426. isLd = true;
  5427. isConst = false;
  5428. type = TySimd128I16;
  5429. break;
  5430. case Js::OpCodeAsmJs::Simd128_LdArr_U4:
  5431. valueType = ValueType::GetObject(ObjectType::Simd128Uint32x4);
  5432. isLd = true;
  5433. isConst = false;
  5434. type = TySimd128U4;
  5435. break;
  5436. case Js::OpCodeAsmJs::Simd128_LdArr_U8:
  5437. valueType = ValueType::GetObject(ObjectType::Simd128Uint16x8);
  5438. isLd = true;
  5439. isConst = false;
  5440. type = TySimd128U8;
  5441. break;
  5442. case Js::OpCodeAsmJs::Simd128_LdArr_U16:
  5443. valueType = ValueType::GetObject(ObjectType::Simd128Uint8x16);
  5444. isLd = true;
  5445. isConst = false;
  5446. type = TySimd128U16;
  5447. break;
  5448. case Js::OpCodeAsmJs::Simd128_LdArr_F4:
  5449. valueType = ValueType::GetObject(ObjectType::Simd128Float32x4);
  5450. isLd = true;
  5451. isConst = false;
  5452. type = TySimd128F4;
  5453. break;
  5454. #if 0
  5455. case Js::OpCodeAsmJs::Simd128_LdArr_D2:
  5456. valueType = ValueType::GetObject(ObjectType::Simd128Float64x2);
  5457. isLd = true;
  5458. isConst = false;
  5459. type = TySimd128D2;
  5460. break;
  5461. #endif // 0
  5462. case Js::OpCodeAsmJs::Simd128_StArr_I4:
  5463. valueType = ValueType::GetObject(ObjectType::Simd128Int32x4);
  5464. isLd = false;
  5465. isConst = false;
  5466. type = TySimd128I4;
  5467. break;
  5468. case Js::OpCodeAsmJs::Simd128_StArr_I8:
  5469. valueType = ValueType::GetObject(ObjectType::Simd128Int16x8);
  5470. isLd = false;
  5471. isConst = false;
  5472. type = TySimd128I8;
  5473. break;
  5474. case Js::OpCodeAsmJs::Simd128_StArr_I16:
  5475. valueType = ValueType::GetObject(ObjectType::Simd128Int8x16);
  5476. isLd = false;
  5477. isConst = false;
  5478. type = TySimd128I16;
  5479. break;
  5480. case Js::OpCodeAsmJs::Simd128_StArr_U4:
  5481. valueType = ValueType::GetObject(ObjectType::Simd128Uint32x4);
  5482. isLd = false;
  5483. isConst = false;
  5484. type = TySimd128U4;
  5485. break;
  5486. case Js::OpCodeAsmJs::Simd128_StArr_U8:
  5487. valueType = ValueType::GetObject(ObjectType::Simd128Uint16x8);
  5488. isLd = false;
  5489. isConst = false;
  5490. type = TySimd128U8;
  5491. break;
  5492. case Js::OpCodeAsmJs::Simd128_StArr_U16:
  5493. valueType = ValueType::GetObject(ObjectType::Simd128Uint8x16);
  5494. isLd = false;
  5495. isConst = false;
  5496. type = TySimd128U16;
  5497. break;
  5498. case Js::OpCodeAsmJs::Simd128_StArr_F4:
  5499. valueType = ValueType::GetObject(ObjectType::Simd128Float32x4);
  5500. isLd = false;
  5501. isConst = false;
  5502. type = TySimd128F4;
  5503. break;
  5504. #if 0
  5505. case Js::OpCodeAsmJs::Simd128_StArr_D2:
  5506. valueType = ValueType::GetObject(ObjectType::Simd128Float64x2);
  5507. isLd = false;
  5508. isConst = false;
  5509. type = TySimd128D2;
  5510. break;
  5511. #endif // 0
  5512. case Js::OpCodeAsmJs::Simd128_LdArrConst_I4:
  5513. valueType = ValueType::GetObject(ObjectType::Simd128Int32x4);
  5514. isLd = true;
  5515. isConst = true;
  5516. type = TySimd128I4;
  5517. break;
  5518. case Js::OpCodeAsmJs::Simd128_LdArrConst_I8:
  5519. valueType = ValueType::GetObject(ObjectType::Simd128Int16x8);
  5520. isLd = true;
  5521. isConst = true;
  5522. type = TySimd128I8;
  5523. break;
  5524. case Js::OpCodeAsmJs::Simd128_LdArrConst_I16:
  5525. valueType = ValueType::GetObject(ObjectType::Simd128Int8x16);
  5526. isLd = true;
  5527. isConst = true;
  5528. type = TySimd128I16;
  5529. break;
  5530. case Js::OpCodeAsmJs::Simd128_LdArrConst_U4:
  5531. valueType = ValueType::GetObject(ObjectType::Simd128Uint32x4);
  5532. isLd = true;
  5533. isConst = true;
  5534. type = TySimd128U4;
  5535. break;
  5536. case Js::OpCodeAsmJs::Simd128_LdArrConst_U8:
  5537. valueType = ValueType::GetObject(ObjectType::Simd128Uint16x8);
  5538. isLd = true;
  5539. isConst = true;
  5540. type = TySimd128U8;
  5541. break;
  5542. case Js::OpCodeAsmJs::Simd128_LdArrConst_U16:
  5543. valueType = ValueType::GetObject(ObjectType::Simd128Uint8x16);
  5544. isLd = true;
  5545. isConst = true;
  5546. type = TySimd128U16;
  5547. break;
  5548. case Js::OpCodeAsmJs::Simd128_LdArrConst_F4:
  5549. valueType = ValueType::GetObject(ObjectType::Simd128Float32x4);
  5550. isLd = true;
  5551. isConst = true;
  5552. type = TySimd128F4;
  5553. break;
  5554. #if 0
  5555. case Js::OpCodeAsmJs::Simd128_LdArrConst_D2:
  5556. valueType = ValueType::GetObject(ObjectType::Simd128Float64x2);
  5557. isLd = true;
  5558. isConst = true;
  5559. type = TySimd128D2;
  5560. break;
  5561. #endif
  5562. case Js::OpCodeAsmJs::Simd128_StArrConst_I4:
  5563. valueType = ValueType::GetObject(ObjectType::Simd128Int32x4);
  5564. isLd = false;
  5565. type = TySimd128I4;
  5566. isConst = true;
  5567. break;
  5568. case Js::OpCodeAsmJs::Simd128_StArrConst_I8:
  5569. valueType = ValueType::GetObject(ObjectType::Simd128Int16x8);
  5570. isLd = false;
  5571. isConst = true;
  5572. type = TySimd128I8;
  5573. break;
  5574. case Js::OpCodeAsmJs::Simd128_StArrConst_I16:
  5575. valueType = ValueType::GetObject(ObjectType::Simd128Int8x16);
  5576. isLd = false;
  5577. isConst = true;
  5578. type = TySimd128I16;
  5579. break;
  5580. case Js::OpCodeAsmJs::Simd128_StArrConst_U4:
  5581. valueType = ValueType::GetObject(ObjectType::Simd128Uint32x4);
  5582. isLd = false;
  5583. isConst = true;
  5584. type = TySimd128U4;
  5585. break;
  5586. case Js::OpCodeAsmJs::Simd128_StArrConst_U8:
  5587. valueType = ValueType::GetObject(ObjectType::Simd128Uint16x8);
  5588. isLd = false;
  5589. isConst = true;
  5590. type = TySimd128U8;
  5591. break;
  5592. case Js::OpCodeAsmJs::Simd128_StArrConst_U16:
  5593. valueType = ValueType::GetObject(ObjectType::Simd128Uint8x16);
  5594. isLd = false;
  5595. isConst = true;
  5596. type = TySimd128U16;
  5597. break;
  5598. case Js::OpCodeAsmJs::Simd128_StArrConst_F4:
  5599. valueType = ValueType::GetObject(ObjectType::Simd128Float32x4);
  5600. isLd = false;
  5601. isConst = true;
  5602. type = TySimd128F4;
  5603. break;
  5604. #if 0
  5605. case Js::OpCodeAsmJs::Simd128_StArrConst_D2:
  5606. valueType = ValueType::GetObject(ObjectType::Simd128Float64x2);
  5607. isLd = false;
  5608. isConst = true;
  5609. type = TySimd128D2;
  5610. break;
  5611. #endif
  5612. default:
  5613. Assert(UNREACHED);
  5614. }
  5615. switch (viewType)
  5616. {
  5617. case Js::ArrayBufferView::TYPE_INT8:
  5618. arrayType = ValueType::GetObject(ObjectType::Int8Array);
  5619. break;
  5620. case Js::ArrayBufferView::TYPE_UINT8:
  5621. arrayType = ValueType::GetObject(ObjectType::Uint8Array);
  5622. break;
  5623. case Js::ArrayBufferView::TYPE_INT16:
  5624. arrayType = ValueType::GetObject(ObjectType::Int16Array);
  5625. mask = (uint32)~1;
  5626. break;
  5627. case Js::ArrayBufferView::TYPE_UINT16:
  5628. arrayType = ValueType::GetObject(ObjectType::Uint16Array);
  5629. mask = (uint32)~1;
  5630. break;
  5631. case Js::ArrayBufferView::TYPE_INT32:
  5632. arrayType = ValueType::GetObject(ObjectType::Int32Array);
  5633. mask = (uint32)~3;
  5634. break;
  5635. case Js::ArrayBufferView::TYPE_UINT32:
  5636. arrayType = ValueType::GetObject(ObjectType::Uint32Array);
  5637. mask = (uint32)~3;
  5638. break;
  5639. case Js::ArrayBufferView::TYPE_FLOAT32:
  5640. arrayType = ValueType::GetObject(ObjectType::Float32Array);
  5641. mask = (uint32)~3;
  5642. break;
  5643. case Js::ArrayBufferView::TYPE_FLOAT64:
  5644. arrayType = ValueType::GetObject(ObjectType::Float64Array);
  5645. mask = (uint32)~7;
  5646. break;
  5647. default:
  5648. Assert(UNREACHED);
  5649. }
  5650. IR::Opnd * sizeOpnd = BuildSrcOpnd(AsmJsRegSlots::LengthReg, TyUint32);
  5651. if (!isConst)
  5652. {
  5653. Js::RegSlot indexRegSlot = GetRegSlotFromIntReg(slotIndex);
  5654. if (mask)
  5655. {
  5656. // AND_I4 index, mask
  5657. maskedOpnd = IR::RegOpnd::New(TyUint32, m_func);
  5658. maskInstr = IR::Instr::New(Js::OpCode::And_I4, maskedOpnd, BuildSrcOpnd(indexRegSlot, TyInt32), IR::IntConstOpnd::New(mask, TyUint32, m_func), m_func);
  5659. }
  5660. else
  5661. {
  5662. maskedOpnd = BuildSrcOpnd(indexRegSlot, TyInt32);
  5663. }
  5664. }
  5665. IR::Instr * instr = nullptr;
  5666. IR::RegOpnd * regOpnd = nullptr;
  5667. IR::IndirOpnd * indirOpnd = nullptr;
  5668. IR::RegOpnd * baseOpnd = BuildSrcOpnd(AsmJsRegSlots::BufferReg, TyVar);
  5669. baseOpnd->SetValueType(arrayType);
  5670. baseOpnd->SetValueTypeFixed();
  5671. if (isLd)
  5672. {
  5673. regOpnd = BuildDstOpnd(valueRegSlot, type);
  5674. regOpnd->SetValueType(valueType);
  5675. if (!isConst)
  5676. {
  5677. Assert(maskedOpnd);
  5678. // Js::OpCodeAsmJs::Simd128_LdArr_I4:
  5679. // Js::OpCodeAsmJs::Simd128_LdArr_F4:
  5680. // Js::OpCodeAsmJs::Simd128_LdArr_D2:
  5681. indirOpnd = IR::IndirOpnd::New(baseOpnd, maskedOpnd, type, m_func);
  5682. }
  5683. else
  5684. {
  5685. // Js::OpCodeAsmJs::Simd128_LdArrConst_I4:
  5686. // Js::OpCodeAsmJs::Simd128_LdArrConst_F4:
  5687. // Js::OpCodeAsmJs::Simd128_LdArrConst_D2:
  5688. indirOpnd = IR::IndirOpnd::New(baseOpnd, slotIndex, type, m_func);
  5689. }
  5690. instr = IR::Instr::New(op, regOpnd, indirOpnd, sizeOpnd, m_func);
  5691. }
  5692. else
  5693. {
  5694. regOpnd = BuildSrcOpnd(valueRegSlot, type);
  5695. regOpnd->SetValueType(valueType);
  5696. if (!isConst)
  5697. {
  5698. Assert(maskedOpnd);
  5699. // Js::OpCodeAsmJs::Simd128_StArr_I4:
  5700. // Js::OpCodeAsmJs::Simd128_StArr_F4:
  5701. // Js::OpCodeAsmJs::Simd128_StArr_D2:
  5702. indirOpnd = IR::IndirOpnd::New(baseOpnd, maskedOpnd, type, m_func);
  5703. }
  5704. else
  5705. {
  5706. // Js::OpCodeAsmJs::Simd128_StArrConst_I4:
  5707. // Js::OpCodeAsmJs::Simd128_StArrConst_F4:
  5708. // Js::OpCodeAsmJs::Simd128_StArrConst_D2:
  5709. indirOpnd = IR::IndirOpnd::New(baseOpnd, slotIndex, type, m_func);
  5710. }
  5711. instr = IR::Instr::New(op, indirOpnd, regOpnd, sizeOpnd, m_func);
  5712. }
  5713. // REVIEW: Store dataWidth in the instruction itself instead of an argument to avoid using ExtendedArgs or excessive opcodes.
  5714. Assert(dataWidth >= 4 && dataWidth <= 16);
  5715. instr->dataWidth = dataWidth;
  5716. if (maskInstr)
  5717. {
  5718. AddInstr(maskInstr, offset);
  5719. }
  5720. AddInstr(instr, offset);
  5721. }
  5722. #endif