IRBuilderAsmJs.cpp 259 KB

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