IRBuilderAsmJs.cpp 253 KB

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