IRBuilderAsmJs.cpp 264 KB

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