IRBuilderAsmJs.cpp 251 KB

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