IRBuilderAsmJs.cpp 244 KB

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