vm_ppc.dasc 135 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069407040714072407340744075407640774078407940804081408240834084408540864087408840894090409140924093409440954096409740984099410041014102410341044105410641074108410941104111411241134114411541164117411841194120412141224123412441254126412741284129413041314132413341344135413641374138413941404141414241434144414541464147414841494150415141524153415441554156415741584159416041614162416341644165416641674168416941704171417241734174417541764177417841794180418141824183418441854186418741884189419041914192419341944195419641974198419942004201420242034204420542064207420842094210421142124213421442154216421742184219422042214222422342244225422642274228422942304231423242334234423542364237423842394240424142424243424442454246424742484249425042514252425342544255425642574258425942604261426242634264426542664267426842694270427142724273427442754276427742784279428042814282428342844285428642874288428942904291429242934294429542964297429842994300430143024303430443054306430743084309431043114312431343144315431643174318431943204321432243234324432543264327432843294330433143324333433443354336433743384339434043414342434343444345434643474348434943504351435243534354435543564357435843594360436143624363436443654366436743684369437043714372437343744375437643774378437943804381438243834384438543864387438843894390439143924393439443954396439743984399440044014402440344044405440644074408440944104411441244134414441544164417441844194420442144224423442444254426442744284429443044314432443344344435443644374438443944404441444244434444444544464447444844494450445144524453445444554456445744584459446044614462446344644465446644674468446944704471447244734474447544764477447844794480448144824483448444854486448744884489449044914492449344944495449644974498449945004501450245034504450545064507450845094510451145124513451445154516451745184519452045214522452345244525452645274528452945304531453245334534453545364537453845394540454145424543454445454546454745484549455045514552455345544555455645574558455945604561456245634564456545664567456845694570457145724573457445754576457745784579458045814582458345844585458645874588458945904591459245934594459545964597459845994600460146024603460446054606460746084609461046114612461346144615461646174618461946204621462246234624462546264627462846294630463146324633463446354636463746384639464046414642464346444645464646474648464946504651465246534654465546564657465846594660466146624663466446654666466746684669467046714672467346744675467646774678467946804681468246834684468546864687468846894690469146924693469446954696469746984699470047014702470347044705470647074708470947104711471247134714471547164717471847194720472147224723472447254726472747284729473047314732473347344735473647374738473947404741474247434744474547464747474847494750475147524753475447554756475747584759476047614762476347644765476647674768476947704771477247734774477547764777477847794780478147824783478447854786478747884789479047914792479347944795479647974798479948004801480248034804480548064807480848094810481148124813481448154816481748184819482048214822482348244825482648274828482948304831483248334834483548364837483848394840484148424843484448454846484748484849485048514852485348544855485648574858485948604861486248634864486548664867486848694870487148724873487448754876487748784879488048814882488348844885488648874888488948904891489248934894489548964897489848994900490149024903490449054906490749084909491049114912491349144915491649174918491949204921492249234924492549264927492849294930493149324933493449354936493749384939494049414942494349444945494649474948494949504951495249534954495549564957495849594960496149624963496449654966496749684969497049714972497349744975497649774978497949804981498249834984498549864987498849894990499149924993499449954996499749984999500050015002500350045005500650075008500950105011501250135014501550165017501850195020502150225023502450255026502750285029503050315032503350345035503650375038503950405041504250435044504550465047504850495050505150525053505450555056505750585059506050615062506350645065506650675068506950705071507250735074507550765077507850795080508150825083508450855086508750885089509050915092509350945095509650975098509951005101510251035104510551065107510851095110511151125113511451155116511751185119512051215122512351245125512651275128512951305131513251335134513551365137
  1. |// Low-level VM code for PowerPC CPUs.
  2. |// Bytecode interpreter, fast functions and helper functions.
  3. |// Copyright (C) 2005-2014 Mike Pall. See Copyright Notice in luajit.h
  4. |
  5. |.arch ppc
  6. |.section code_op, code_sub
  7. |
  8. |.actionlist build_actionlist
  9. |.globals GLOB_
  10. |.globalnames globnames
  11. |.externnames extnames
  12. |
  13. |// Note: The ragged indentation of the instructions is intentional.
  14. |// The starting columns indicate data dependencies.
  15. |
  16. |//-----------------------------------------------------------------------
  17. |
  18. |// DynASM defines used by the PPC port:
  19. |//
  20. |// P64 64 bit pointers (only for GPR64 testing).
  21. |// Note: a full PPC64 _LP64 port is not planned.
  22. |// GPR64 64 bit registers (but possibly 32 bit pointers, e.g. PS3).
  23. |// Affects reg saves, stack layout, carry/overflow/dot flags etc.
  24. |// FRAME32 Use 32 bit frame layout, even with GPR64 (Xbox 360).
  25. |// TOC Need table of contents (64 bit or 32 bit variant, e.g. PS3).
  26. |// Function pointers are really a struct: code, TOC, env (optional).
  27. |// TOCENV Function pointers have an environment pointer, too (not on PS3).
  28. |// PPE Power Processor Element of Cell (PS3) or Xenon (Xbox 360).
  29. |// Must avoid (slow) micro-coded instructions.
  30. |
  31. |.if P64
  32. |.define TOC, 1
  33. |.define TOCENV, 1
  34. |.macro lpx, a, b, c; ldx a, b, c; .endmacro
  35. |.macro lp, a, b; ld a, b; .endmacro
  36. |.macro stp, a, b; std a, b; .endmacro
  37. |.define decode_OPP, decode_OP8
  38. |.if FFI
  39. |// Missing: Calling conventions, 64 bit regs, TOC.
  40. |.error lib_ffi not yet implemented for PPC64
  41. |.endif
  42. |.else
  43. |.macro lpx, a, b, c; lwzx a, b, c; .endmacro
  44. |.macro lp, a, b; lwz a, b; .endmacro
  45. |.macro stp, a, b; stw a, b; .endmacro
  46. |.define decode_OPP, decode_OP4
  47. |.endif
  48. |
  49. |// Convenience macros for TOC handling.
  50. |.if TOC
  51. |// Linker needs a TOC patch area for every external call relocation.
  52. |.macro blex, target; bl extern target@plt; nop; .endmacro
  53. |.macro .toc, a, b; a, b; .endmacro
  54. |.if P64
  55. |.define TOC_OFS, 8
  56. |.define ENV_OFS, 16
  57. |.else
  58. |.define TOC_OFS, 4
  59. |.define ENV_OFS, 8
  60. |.endif
  61. |.else // No TOC.
  62. |.macro blex, target; bl extern target@plt; .endmacro
  63. |.macro .toc, a, b; .endmacro
  64. |.endif
  65. |.macro .tocenv, a, b; .if TOCENV; a, b; .endif; .endmacro
  66. |
  67. |.macro .gpr64, a, b; .if GPR64; a, b; .endif; .endmacro
  68. |
  69. |.macro andix., y, a, i
  70. |.if PPE
  71. | rlwinm y, a, 0, 31-lj_fls(i), 31-lj_ffs(i)
  72. | cmpwi y, 0
  73. |.else
  74. | andi. y, a, i
  75. |.endif
  76. |.endmacro
  77. |
  78. |//-----------------------------------------------------------------------
  79. |
  80. |// Fixed register assignments for the interpreter.
  81. |// Don't use: r1 = sp, r2 and r13 = reserved (TOC, TLS or SDATA)
  82. |
  83. |// The following must be C callee-save (but BASE is often refetched).
  84. |.define BASE, r14 // Base of current Lua stack frame.
  85. |.define KBASE, r15 // Constants of current Lua function.
  86. |.define PC, r16 // Next PC.
  87. |.define DISPATCH, r17 // Opcode dispatch table.
  88. |.define LREG, r18 // Register holding lua_State (also in SAVE_L).
  89. |.define MULTRES, r19 // Size of multi-result: (nresults+1)*8.
  90. |.define JGL, r31 // On-trace: global_State + 32768.
  91. |
  92. |// Constants for type-comparisons, stores and conversions. C callee-save.
  93. |.define TISNUM, r22
  94. |.define TISNIL, r23
  95. |.define ZERO, r24
  96. |.define TOBIT, f30 // 2^52 + 2^51.
  97. |.define TONUM, f31 // 2^52 + 2^51 + 2^31.
  98. |
  99. |// The following temporaries are not saved across C calls, except for RA.
  100. |.define RA, r20 // Callee-save.
  101. |.define RB, r10
  102. |.define RC, r11
  103. |.define RD, r12
  104. |.define INS, r7 // Overlaps CARG5.
  105. |
  106. |.define TMP0, r0
  107. |.define TMP1, r8
  108. |.define TMP2, r9
  109. |.define TMP3, r6 // Overlaps CARG4.
  110. |
  111. |// Saved temporaries.
  112. |.define SAVE0, r21
  113. |
  114. |// Calling conventions.
  115. |.define CARG1, r3
  116. |.define CARG2, r4
  117. |.define CARG3, r5
  118. |.define CARG4, r6 // Overlaps TMP3.
  119. |.define CARG5, r7 // Overlaps INS.
  120. |
  121. |.define FARG1, f1
  122. |.define FARG2, f2
  123. |
  124. |.define CRET1, r3
  125. |.define CRET2, r4
  126. |
  127. |.define TOCREG, r2 // TOC register (only used by C code).
  128. |.define ENVREG, r11 // Environment pointer (nested C functions).
  129. |
  130. |// Stack layout while in interpreter. Must match with lj_frame.h.
  131. |.if GPR64
  132. |.if FRAME32
  133. |
  134. |// 456(sp) // \ 32/64 bit C frame info
  135. |.define TONUM_LO, 452(sp) // |
  136. |.define TONUM_HI, 448(sp) // |
  137. |.define TMPD_LO, 444(sp) // |
  138. |.define TMPD_HI, 440(sp) // |
  139. |.define SAVE_CR, 432(sp) // | 64 bit CR save.
  140. |.define SAVE_ERRF, 424(sp) // > Parameter save area.
  141. |.define SAVE_NRES, 420(sp) // |
  142. |.define SAVE_L, 416(sp) // |
  143. |.define SAVE_PC, 412(sp) // |
  144. |.define SAVE_MULTRES, 408(sp) // |
  145. |.define SAVE_CFRAME, 400(sp) // / 64 bit C frame chain.
  146. |// 392(sp) // Reserved.
  147. |.define CFRAME_SPACE, 384 // Delta for sp.
  148. |// Back chain for sp: 384(sp) <-- sp entering interpreter
  149. |.define SAVE_LR, 376(sp) // 32 bit LR stored in hi-part.
  150. |.define SAVE_GPR_, 232 // .. 232+18*8: 64 bit GPR saves.
  151. |.define SAVE_FPR_, 88 // .. 88+18*8: 64 bit FPR saves.
  152. |// 80(sp) // Needed for 16 byte stack frame alignment.
  153. |// 16(sp) // Callee parameter save area (ABI mandated).
  154. |// 8(sp) // Reserved
  155. |// Back chain for sp: 0(sp) <-- sp while in interpreter
  156. |// 32 bit sp stored in hi-part of 0(sp).
  157. |
  158. |.define TMPD_BLO, 447(sp)
  159. |.define TMPD, TMPD_HI
  160. |.define TONUM_D, TONUM_HI
  161. |
  162. |.else
  163. |
  164. |// 508(sp) // \ 32 bit C frame info.
  165. |.define SAVE_ERRF, 472(sp) // |
  166. |.define SAVE_NRES, 468(sp) // |
  167. |.define SAVE_L, 464(sp) // > Parameter save area.
  168. |.define SAVE_PC, 460(sp) // |
  169. |.define SAVE_MULTRES, 456(sp) // |
  170. |.define SAVE_CFRAME, 448(sp) // / 64 bit C frame chain.
  171. |.define SAVE_LR, 416(sp)
  172. |.define CFRAME_SPACE, 400 // Delta for sp.
  173. |// Back chain for sp: 400(sp) <-- sp entering interpreter
  174. |.define SAVE_FPR_, 256 // .. 256+18*8: 64 bit FPR saves.
  175. |.define SAVE_GPR_, 112 // .. 112+18*8: 64 bit GPR saves.
  176. |// 48(sp) // Callee parameter save area (ABI mandated).
  177. |.define SAVE_TOC, 40(sp) // TOC save area.
  178. |.define TMPD_LO, 36(sp) // \ Link editor temp (ABI mandated).
  179. |.define TMPD_HI, 32(sp) // /
  180. |.define TONUM_LO, 28(sp) // \ Compiler temp (ABI mandated).
  181. |.define TONUM_HI, 24(sp) // /
  182. |// Next frame lr: 16(sp)
  183. |.define SAVE_CR, 8(sp) // 64 bit CR save.
  184. |// Back chain for sp: 0(sp) <-- sp while in interpreter
  185. |
  186. |.define TMPD_BLO, 39(sp)
  187. |.define TMPD, TMPD_HI
  188. |.define TONUM_D, TONUM_HI
  189. |
  190. |.endif
  191. |.else
  192. |
  193. |.define SAVE_LR, 276(sp)
  194. |.define CFRAME_SPACE, 272 // Delta for sp.
  195. |// Back chain for sp: 272(sp) <-- sp entering interpreter
  196. |.define SAVE_FPR_, 128 // .. 128+18*8: 64 bit FPR saves.
  197. |.define SAVE_GPR_, 56 // .. 56+18*4: 32 bit GPR saves.
  198. |.define SAVE_CR, 52(sp) // 32 bit CR save.
  199. |.define SAVE_ERRF, 48(sp) // 32 bit C frame info.
  200. |.define SAVE_NRES, 44(sp)
  201. |.define SAVE_CFRAME, 40(sp)
  202. |.define SAVE_L, 36(sp)
  203. |.define SAVE_PC, 32(sp)
  204. |.define SAVE_MULTRES, 28(sp)
  205. |.define UNUSED1, 24(sp)
  206. |.define TMPD_LO, 20(sp)
  207. |.define TMPD_HI, 16(sp)
  208. |.define TONUM_LO, 12(sp)
  209. |.define TONUM_HI, 8(sp)
  210. |// Next frame lr: 4(sp)
  211. |// Back chain for sp: 0(sp) <-- sp while in interpreter
  212. |
  213. |.define TMPD_BLO, 23(sp)
  214. |.define TMPD, TMPD_HI
  215. |.define TONUM_D, TONUM_HI
  216. |
  217. |.endif
  218. |
  219. |.macro save_, reg
  220. |.if GPR64
  221. | std r..reg, SAVE_GPR_+(reg-14)*8(sp)
  222. |.else
  223. | stw r..reg, SAVE_GPR_+(reg-14)*4(sp)
  224. |.endif
  225. | stfd f..reg, SAVE_FPR_+(reg-14)*8(sp)
  226. |.endmacro
  227. |.macro rest_, reg
  228. |.if GPR64
  229. | ld r..reg, SAVE_GPR_+(reg-14)*8(sp)
  230. |.else
  231. | lwz r..reg, SAVE_GPR_+(reg-14)*4(sp)
  232. |.endif
  233. | lfd f..reg, SAVE_FPR_+(reg-14)*8(sp)
  234. |.endmacro
  235. |
  236. |.macro saveregs
  237. |.if GPR64 and not FRAME32
  238. | stdu sp, -CFRAME_SPACE(sp)
  239. |.else
  240. | stwu sp, -CFRAME_SPACE(sp)
  241. |.endif
  242. | save_ 14; save_ 15; save_ 16
  243. | mflr r0
  244. | save_ 17; save_ 18; save_ 19; save_ 20; save_ 21; save_ 22
  245. |.if GPR64 and not FRAME32
  246. | std r0, SAVE_LR
  247. |.else
  248. | stw r0, SAVE_LR
  249. |.endif
  250. | save_ 23; save_ 24; save_ 25
  251. | mfcr r0
  252. | save_ 26; save_ 27; save_ 28; save_ 29; save_ 30; save_ 31
  253. |.if GPR64
  254. | std r0, SAVE_CR
  255. |.else
  256. | stw r0, SAVE_CR
  257. |.endif
  258. | .toc std TOCREG, SAVE_TOC
  259. |.endmacro
  260. |
  261. |.macro restoreregs
  262. |.if GPR64 and not FRAME32
  263. | ld r0, SAVE_LR
  264. |.else
  265. | lwz r0, SAVE_LR
  266. |.endif
  267. |.if GPR64
  268. | ld r12, SAVE_CR
  269. |.else
  270. | lwz r12, SAVE_CR
  271. |.endif
  272. | rest_ 14; rest_ 15; rest_ 16; rest_ 17; rest_ 18; rest_ 19
  273. | mtlr r0;
  274. |.if PPE; mtocrf 0x20, r12; .else; mtcrf 0x38, r12; .endif
  275. | rest_ 20; rest_ 21; rest_ 22; rest_ 23; rest_ 24; rest_ 25
  276. |.if PPE; mtocrf 0x10, r12; .endif
  277. | rest_ 26; rest_ 27; rest_ 28; rest_ 29; rest_ 30; rest_ 31
  278. |.if PPE; mtocrf 0x08, r12; .endif
  279. | addi sp, sp, CFRAME_SPACE
  280. |.endmacro
  281. |
  282. |// Type definitions. Some of these are only used for documentation.
  283. |.type L, lua_State, LREG
  284. |.type GL, global_State
  285. |.type TVALUE, TValue
  286. |.type GCOBJ, GCobj
  287. |.type STR, GCstr
  288. |.type TAB, GCtab
  289. |.type LFUNC, GCfuncL
  290. |.type CFUNC, GCfuncC
  291. |.type PROTO, GCproto
  292. |.type UPVAL, GCupval
  293. |.type NODE, Node
  294. |.type NARGS8, int
  295. |.type TRACE, GCtrace
  296. |
  297. |//-----------------------------------------------------------------------
  298. |
  299. |// These basic macros should really be part of DynASM.
  300. |.macro srwi, rx, ry, n; rlwinm rx, ry, 32-n, n, 31; .endmacro
  301. |.macro slwi, rx, ry, n; rlwinm rx, ry, n, 0, 31-n; .endmacro
  302. |.macro rotlwi, rx, ry, n; rlwinm rx, ry, n, 0, 31; .endmacro
  303. |.macro rotlw, rx, ry, rn; rlwnm rx, ry, rn, 0, 31; .endmacro
  304. |.macro subi, rx, ry, i; addi rx, ry, -i; .endmacro
  305. |
  306. |// Trap for not-yet-implemented parts.
  307. |.macro NYI; tw 4, sp, sp; .endmacro
  308. |
  309. |// int/FP conversions.
  310. |.macro tonum_i, freg, reg
  311. | xoris reg, reg, 0x8000
  312. | stw reg, TONUM_LO
  313. | lfd freg, TONUM_D
  314. | fsub freg, freg, TONUM
  315. |.endmacro
  316. |
  317. |.macro tonum_u, freg, reg
  318. | stw reg, TONUM_LO
  319. | lfd freg, TONUM_D
  320. | fsub freg, freg, TOBIT
  321. |.endmacro
  322. |
  323. |.macro toint, reg, freg, tmpfreg
  324. | fctiwz tmpfreg, freg
  325. | stfd tmpfreg, TMPD
  326. | lwz reg, TMPD_LO
  327. |.endmacro
  328. |
  329. |.macro toint, reg, freg
  330. | toint reg, freg, freg
  331. |.endmacro
  332. |
  333. |//-----------------------------------------------------------------------
  334. |
  335. |// Access to frame relative to BASE.
  336. |.define FRAME_PC, -8
  337. |.define FRAME_FUNC, -4
  338. |
  339. |// Instruction decode.
  340. |.macro decode_OP4, dst, ins; rlwinm dst, ins, 2, 22, 29; .endmacro
  341. |.macro decode_OP8, dst, ins; rlwinm dst, ins, 3, 21, 28; .endmacro
  342. |.macro decode_RA8, dst, ins; rlwinm dst, ins, 27, 21, 28; .endmacro
  343. |.macro decode_RB8, dst, ins; rlwinm dst, ins, 11, 21, 28; .endmacro
  344. |.macro decode_RC8, dst, ins; rlwinm dst, ins, 19, 21, 28; .endmacro
  345. |.macro decode_RD8, dst, ins; rlwinm dst, ins, 19, 13, 28; .endmacro
  346. |
  347. |.macro decode_OP1, dst, ins; rlwinm dst, ins, 0, 24, 31; .endmacro
  348. |.macro decode_RD4, dst, ins; rlwinm dst, ins, 18, 14, 29; .endmacro
  349. |
  350. |// Instruction fetch.
  351. |.macro ins_NEXT1
  352. | lwz INS, 0(PC)
  353. | addi PC, PC, 4
  354. |.endmacro
  355. |// Instruction decode+dispatch. Note: optimized for e300!
  356. |.macro ins_NEXT2
  357. | decode_OPP TMP1, INS
  358. | lpx TMP0, DISPATCH, TMP1
  359. | mtctr TMP0
  360. | decode_RB8 RB, INS
  361. | decode_RD8 RD, INS
  362. | decode_RA8 RA, INS
  363. | decode_RC8 RC, INS
  364. | bctr
  365. |.endmacro
  366. |.macro ins_NEXT
  367. | ins_NEXT1
  368. | ins_NEXT2
  369. |.endmacro
  370. |
  371. |// Instruction footer.
  372. |.if 1
  373. | // Replicated dispatch. Less unpredictable branches, but higher I-Cache use.
  374. | .define ins_next, ins_NEXT
  375. | .define ins_next_, ins_NEXT
  376. | .define ins_next1, ins_NEXT1
  377. | .define ins_next2, ins_NEXT2
  378. |.else
  379. | // Common dispatch. Lower I-Cache use, only one (very) unpredictable branch.
  380. | // Affects only certain kinds of benchmarks (and only with -j off).
  381. | .macro ins_next
  382. | b ->ins_next
  383. | .endmacro
  384. | .macro ins_next1
  385. | .endmacro
  386. | .macro ins_next2
  387. | b ->ins_next
  388. | .endmacro
  389. | .macro ins_next_
  390. | ->ins_next:
  391. | ins_NEXT
  392. | .endmacro
  393. |.endif
  394. |
  395. |// Call decode and dispatch.
  396. |.macro ins_callt
  397. | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC
  398. | lwz PC, LFUNC:RB->pc
  399. | lwz INS, 0(PC)
  400. | addi PC, PC, 4
  401. | decode_OPP TMP1, INS
  402. | decode_RA8 RA, INS
  403. | lpx TMP0, DISPATCH, TMP1
  404. | add RA, RA, BASE
  405. | mtctr TMP0
  406. | bctr
  407. |.endmacro
  408. |
  409. |.macro ins_call
  410. | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, PC = caller PC
  411. | stw PC, FRAME_PC(BASE)
  412. | ins_callt
  413. |.endmacro
  414. |
  415. |//-----------------------------------------------------------------------
  416. |
  417. |// Macros to test operand types.
  418. |.macro checknum, reg; cmplw reg, TISNUM; .endmacro
  419. |.macro checknum, cr, reg; cmplw cr, reg, TISNUM; .endmacro
  420. |.macro checkstr, reg; cmpwi reg, LJ_TSTR; .endmacro
  421. |.macro checktab, reg; cmpwi reg, LJ_TTAB; .endmacro
  422. |.macro checkfunc, reg; cmpwi reg, LJ_TFUNC; .endmacro
  423. |.macro checknil, reg; cmpwi reg, LJ_TNIL; .endmacro
  424. |
  425. |.macro branch_RD
  426. | srwi TMP0, RD, 1
  427. | addis PC, PC, -(BCBIAS_J*4 >> 16)
  428. | add PC, PC, TMP0
  429. |.endmacro
  430. |
  431. |// Assumes DISPATCH is relative to GL.
  432. #define DISPATCH_GL(field) (GG_DISP2G + (int)offsetof(global_State, field))
  433. #define DISPATCH_J(field) (GG_DISP2J + (int)offsetof(jit_State, field))
  434. |
  435. #define PC2PROTO(field) ((int)offsetof(GCproto, field)-(int)sizeof(GCproto))
  436. |
  437. |.macro hotcheck, delta, target
  438. | rlwinm TMP1, PC, 31, 25, 30
  439. | addi TMP1, TMP1, GG_DISP2HOT
  440. | lhzx TMP2, DISPATCH, TMP1
  441. | addic. TMP2, TMP2, -delta
  442. | sthx TMP2, DISPATCH, TMP1
  443. | blt target
  444. |.endmacro
  445. |
  446. |.macro hotloop
  447. | hotcheck HOTCOUNT_LOOP, ->vm_hotloop
  448. |.endmacro
  449. |
  450. |.macro hotcall
  451. | hotcheck HOTCOUNT_CALL, ->vm_hotcall
  452. |.endmacro
  453. |
  454. |// Set current VM state. Uses TMP0.
  455. |.macro li_vmstate, st; li TMP0, ~LJ_VMST_..st; .endmacro
  456. |.macro st_vmstate; stw TMP0, DISPATCH_GL(vmstate)(DISPATCH); .endmacro
  457. |
  458. |// Move table write barrier back. Overwrites mark and tmp.
  459. |.macro barrierback, tab, mark, tmp
  460. | lwz tmp, DISPATCH_GL(gc.grayagain)(DISPATCH)
  461. | // Assumes LJ_GC_BLACK is 0x04.
  462. | rlwinm mark, mark, 0, 30, 28 // black2gray(tab)
  463. | stw tab, DISPATCH_GL(gc.grayagain)(DISPATCH)
  464. | stb mark, tab->marked
  465. | stw tmp, tab->gclist
  466. |.endmacro
  467. |
  468. |//-----------------------------------------------------------------------
  469. /* Generate subroutines used by opcodes and other parts of the VM. */
  470. /* The .code_sub section should be last to help static branch prediction. */
  471. static void build_subroutines(BuildCtx *ctx)
  472. {
  473. |.code_sub
  474. |
  475. |//-----------------------------------------------------------------------
  476. |//-- Return handling ----------------------------------------------------
  477. |//-----------------------------------------------------------------------
  478. |
  479. |->vm_returnp:
  480. | // See vm_return. Also: TMP2 = previous base.
  481. | andix. TMP0, PC, FRAME_P
  482. | li TMP1, LJ_TTRUE
  483. | beq ->cont_dispatch
  484. |
  485. | // Return from pcall or xpcall fast func.
  486. | lwz PC, FRAME_PC(TMP2) // Fetch PC of previous frame.
  487. | mr BASE, TMP2 // Restore caller base.
  488. | // Prepending may overwrite the pcall frame, so do it at the end.
  489. | stwu TMP1, FRAME_PC(RA) // Prepend true to results.
  490. |
  491. |->vm_returnc:
  492. | addi RD, RD, 8 // RD = (nresults+1)*8.
  493. | andix. TMP0, PC, FRAME_TYPE
  494. | cmpwi cr1, RD, 0
  495. | li CRET1, LUA_YIELD
  496. | beq cr1, ->vm_unwind_c_eh
  497. | mr MULTRES, RD
  498. | beq ->BC_RET_Z // Handle regular return to Lua.
  499. |
  500. |->vm_return:
  501. | // BASE = base, RA = resultptr, RD/MULTRES = (nresults+1)*8, PC = return
  502. | // TMP0 = PC & FRAME_TYPE
  503. | cmpwi TMP0, FRAME_C
  504. | rlwinm TMP2, PC, 0, 0, 28
  505. | li_vmstate C
  506. | sub TMP2, BASE, TMP2 // TMP2 = previous base.
  507. | bney ->vm_returnp
  508. |
  509. | addic. TMP1, RD, -8
  510. | stp TMP2, L->base
  511. | lwz TMP2, SAVE_NRES
  512. | subi BASE, BASE, 8
  513. | st_vmstate
  514. | slwi TMP2, TMP2, 3
  515. | beq >2
  516. |1:
  517. | addic. TMP1, TMP1, -8
  518. | lfd f0, 0(RA)
  519. | addi RA, RA, 8
  520. | stfd f0, 0(BASE)
  521. | addi BASE, BASE, 8
  522. | bney <1
  523. |
  524. |2:
  525. | cmpw TMP2, RD // More/less results wanted?
  526. | bne >6
  527. |3:
  528. | stp BASE, L->top // Store new top.
  529. |
  530. |->vm_leave_cp:
  531. | lp TMP0, SAVE_CFRAME // Restore previous C frame.
  532. | li CRET1, 0 // Ok return status for vm_pcall.
  533. | stp TMP0, L->cframe
  534. |
  535. |->vm_leave_unw:
  536. | restoreregs
  537. | blr
  538. |
  539. |6:
  540. | ble >7 // Less results wanted?
  541. | // More results wanted. Check stack size and fill up results with nil.
  542. | lwz TMP1, L->maxstack
  543. | cmplw BASE, TMP1
  544. | bge >8
  545. | stw TISNIL, 0(BASE)
  546. | addi RD, RD, 8
  547. | addi BASE, BASE, 8
  548. | b <2
  549. |
  550. |7: // Less results wanted.
  551. | subfic TMP3, TMP2, 0 // LUA_MULTRET+1 case?
  552. | sub TMP0, RD, TMP2
  553. | subfe TMP1, TMP1, TMP1 // TMP1 = TMP2 == 0 ? 0 : -1
  554. | and TMP0, TMP0, TMP1
  555. | sub BASE, BASE, TMP0 // Either keep top or shrink it.
  556. | b <3
  557. |
  558. |8: // Corner case: need to grow stack for filling up results.
  559. | // This can happen if:
  560. | // - A C function grows the stack (a lot).
  561. | // - The GC shrinks the stack in between.
  562. | // - A return back from a lua_call() with (high) nresults adjustment.
  563. | stp BASE, L->top // Save current top held in BASE (yes).
  564. | mr SAVE0, RD
  565. | mr CARG2, TMP2
  566. | mr CARG1, L
  567. | bl extern lj_state_growstack // (lua_State *L, int n)
  568. | lwz TMP2, SAVE_NRES
  569. | mr RD, SAVE0
  570. | slwi TMP2, TMP2, 3
  571. | lp BASE, L->top // Need the (realloced) L->top in BASE.
  572. | b <2
  573. |
  574. |->vm_unwind_c: // Unwind C stack, return from vm_pcall.
  575. | // (void *cframe, int errcode)
  576. | mr sp, CARG1
  577. | mr CRET1, CARG2
  578. |->vm_unwind_c_eh: // Landing pad for external unwinder.
  579. | lwz L, SAVE_L
  580. | .toc ld TOCREG, SAVE_TOC
  581. | li TMP0, ~LJ_VMST_C
  582. | lwz GL:TMP1, L->glref
  583. | stw TMP0, GL:TMP1->vmstate
  584. | b ->vm_leave_unw
  585. |
  586. |->vm_unwind_ff: // Unwind C stack, return from ff pcall.
  587. | // (void *cframe)
  588. |.if GPR64
  589. | rldicr sp, CARG1, 0, 61
  590. |.else
  591. | rlwinm sp, CARG1, 0, 0, 29
  592. |.endif
  593. |->vm_unwind_ff_eh: // Landing pad for external unwinder.
  594. | lwz L, SAVE_L
  595. | .toc ld TOCREG, SAVE_TOC
  596. | li TISNUM, LJ_TISNUM // Setup type comparison constants.
  597. | lp BASE, L->base
  598. | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
  599. | lwz DISPATCH, L->glref // Setup pointer to dispatch table.
  600. | li ZERO, 0
  601. | stw TMP3, TMPD
  602. | li TMP1, LJ_TFALSE
  603. | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float).
  604. | li TISNIL, LJ_TNIL
  605. | li_vmstate INTERP
  606. | lfs TOBIT, TMPD
  607. | lwz PC, FRAME_PC(BASE) // Fetch PC of previous frame.
  608. | la RA, -8(BASE) // Results start at BASE-8.
  609. | stw TMP3, TMPD
  610. | addi DISPATCH, DISPATCH, GG_G2DISP
  611. | stw TMP1, 0(RA) // Prepend false to error message.
  612. | li RD, 16 // 2 results: false + error message.
  613. | st_vmstate
  614. | lfs TONUM, TMPD
  615. | b ->vm_returnc
  616. |
  617. |//-----------------------------------------------------------------------
  618. |//-- Grow stack for calls -----------------------------------------------
  619. |//-----------------------------------------------------------------------
  620. |
  621. |->vm_growstack_c: // Grow stack for C function.
  622. | li CARG2, LUA_MINSTACK
  623. | b >2
  624. |
  625. |->vm_growstack_l: // Grow stack for Lua function.
  626. | // BASE = new base, RA = BASE+framesize*8, RC = nargs*8, PC = first PC
  627. | add RC, BASE, RC
  628. | sub RA, RA, BASE
  629. | stp BASE, L->base
  630. | addi PC, PC, 4 // Must point after first instruction.
  631. | stp RC, L->top
  632. | srwi CARG2, RA, 3
  633. |2:
  634. | // L->base = new base, L->top = top
  635. | stw PC, SAVE_PC
  636. | mr CARG1, L
  637. | bl extern lj_state_growstack // (lua_State *L, int n)
  638. | lp BASE, L->base
  639. | lp RC, L->top
  640. | lwz LFUNC:RB, FRAME_FUNC(BASE)
  641. | sub RC, RC, BASE
  642. | // BASE = new base, RB = LFUNC/CFUNC, RC = nargs*8, FRAME_PC(BASE) = PC
  643. | ins_callt // Just retry the call.
  644. |
  645. |//-----------------------------------------------------------------------
  646. |//-- Entry points into the assembler VM ---------------------------------
  647. |//-----------------------------------------------------------------------
  648. |
  649. |->vm_resume: // Setup C frame and resume thread.
  650. | // (lua_State *L, TValue *base, int nres1 = 0, ptrdiff_t ef = 0)
  651. | saveregs
  652. | mr L, CARG1
  653. | lwz DISPATCH, L->glref // Setup pointer to dispatch table.
  654. | mr BASE, CARG2
  655. | lbz TMP1, L->status
  656. | stw L, SAVE_L
  657. | li PC, FRAME_CP
  658. | addi TMP0, sp, CFRAME_RESUME
  659. | addi DISPATCH, DISPATCH, GG_G2DISP
  660. | stw CARG3, SAVE_NRES
  661. | cmplwi TMP1, 0
  662. | stw CARG3, SAVE_ERRF
  663. | stp TMP0, L->cframe
  664. | stp CARG3, SAVE_CFRAME
  665. | stw CARG1, SAVE_PC // Any value outside of bytecode is ok.
  666. | beq >3
  667. |
  668. | // Resume after yield (like a return).
  669. | mr RA, BASE
  670. | lp BASE, L->base
  671. | li TISNUM, LJ_TISNUM // Setup type comparison constants.
  672. | lp TMP1, L->top
  673. | lwz PC, FRAME_PC(BASE)
  674. | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
  675. | stb CARG3, L->status
  676. | stw TMP3, TMPD
  677. | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float).
  678. | lfs TOBIT, TMPD
  679. | sub RD, TMP1, BASE
  680. | stw TMP3, TMPD
  681. | lus TMP0, 0x4338 // Hiword of 2^52 + 2^51 (double)
  682. | addi RD, RD, 8
  683. | stw TMP0, TONUM_HI
  684. | li_vmstate INTERP
  685. | li ZERO, 0
  686. | st_vmstate
  687. | andix. TMP0, PC, FRAME_TYPE
  688. | mr MULTRES, RD
  689. | lfs TONUM, TMPD
  690. | li TISNIL, LJ_TNIL
  691. | beq ->BC_RET_Z
  692. | b ->vm_return
  693. |
  694. |->vm_pcall: // Setup protected C frame and enter VM.
  695. | // (lua_State *L, TValue *base, int nres1, ptrdiff_t ef)
  696. | saveregs
  697. | li PC, FRAME_CP
  698. | stw CARG4, SAVE_ERRF
  699. | b >1
  700. |
  701. |->vm_call: // Setup C frame and enter VM.
  702. | // (lua_State *L, TValue *base, int nres1)
  703. | saveregs
  704. | li PC, FRAME_C
  705. |
  706. |1: // Entry point for vm_pcall above (PC = ftype).
  707. | lp TMP1, L:CARG1->cframe
  708. | stw CARG3, SAVE_NRES
  709. | mr L, CARG1
  710. | stw CARG1, SAVE_L
  711. | mr BASE, CARG2
  712. | stp sp, L->cframe // Add our C frame to cframe chain.
  713. | lwz DISPATCH, L->glref // Setup pointer to dispatch table.
  714. | stw CARG1, SAVE_PC // Any value outside of bytecode is ok.
  715. | stp TMP1, SAVE_CFRAME
  716. | addi DISPATCH, DISPATCH, GG_G2DISP
  717. |
  718. |3: // Entry point for vm_cpcall/vm_resume (BASE = base, PC = ftype).
  719. | lp TMP2, L->base // TMP2 = old base (used in vmeta_call).
  720. | li TISNUM, LJ_TISNUM // Setup type comparison constants.
  721. | lp TMP1, L->top
  722. | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
  723. | add PC, PC, BASE
  724. | stw TMP3, TMPD
  725. | li ZERO, 0
  726. | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float).
  727. | lfs TOBIT, TMPD
  728. | sub PC, PC, TMP2 // PC = frame delta + frame type
  729. | stw TMP3, TMPD
  730. | lus TMP0, 0x4338 // Hiword of 2^52 + 2^51 (double)
  731. | sub NARGS8:RC, TMP1, BASE
  732. | stw TMP0, TONUM_HI
  733. | li_vmstate INTERP
  734. | lfs TONUM, TMPD
  735. | li TISNIL, LJ_TNIL
  736. | st_vmstate
  737. |
  738. |->vm_call_dispatch:
  739. | // TMP2 = old base, BASE = new base, RC = nargs*8, PC = caller PC
  740. | lwz TMP0, FRAME_PC(BASE)
  741. | lwz LFUNC:RB, FRAME_FUNC(BASE)
  742. | checkfunc TMP0; bne ->vmeta_call
  743. |
  744. |->vm_call_dispatch_f:
  745. | ins_call
  746. | // BASE = new base, RB = func, RC = nargs*8, PC = caller PC
  747. |
  748. |->vm_cpcall: // Setup protected C frame, call C.
  749. | // (lua_State *L, lua_CFunction func, void *ud, lua_CPFunction cp)
  750. | saveregs
  751. | mr L, CARG1
  752. | lwz TMP0, L:CARG1->stack
  753. | stw CARG1, SAVE_L
  754. | lp TMP1, L->top
  755. | stw CARG1, SAVE_PC // Any value outside of bytecode is ok.
  756. | sub TMP0, TMP0, TMP1 // Compute -savestack(L, L->top).
  757. | lp TMP1, L->cframe
  758. | stp sp, L->cframe // Add our C frame to cframe chain.
  759. | .toc lp CARG4, 0(CARG4)
  760. | li TMP2, 0
  761. | stw TMP0, SAVE_NRES // Neg. delta means cframe w/o frame.
  762. | stw TMP2, SAVE_ERRF // No error function.
  763. | stp TMP1, SAVE_CFRAME
  764. | mtctr CARG4
  765. | bctrl // (lua_State *L, lua_CFunction func, void *ud)
  766. |.if PPE
  767. | mr BASE, CRET1
  768. | cmpwi CRET1, 0
  769. |.else
  770. | mr. BASE, CRET1
  771. |.endif
  772. | lwz DISPATCH, L->glref // Setup pointer to dispatch table.
  773. | li PC, FRAME_CP
  774. | addi DISPATCH, DISPATCH, GG_G2DISP
  775. | bne <3 // Else continue with the call.
  776. | b ->vm_leave_cp // No base? Just remove C frame.
  777. |
  778. |//-----------------------------------------------------------------------
  779. |//-- Metamethod handling ------------------------------------------------
  780. |//-----------------------------------------------------------------------
  781. |
  782. |// The lj_meta_* functions (except for lj_meta_cat) don't reallocate the
  783. |// stack, so BASE doesn't need to be reloaded across these calls.
  784. |
  785. |//-- Continuation dispatch ----------------------------------------------
  786. |
  787. |->cont_dispatch:
  788. | // BASE = meta base, RA = resultptr, RD = (nresults+1)*8
  789. | lwz TMP0, -12(BASE) // Continuation.
  790. | mr RB, BASE
  791. | mr BASE, TMP2 // Restore caller BASE.
  792. | lwz LFUNC:TMP1, FRAME_FUNC(TMP2)
  793. |.if FFI
  794. | cmplwi TMP0, 1
  795. |.endif
  796. | lwz PC, -16(RB) // Restore PC from [cont|PC].
  797. | subi TMP2, RD, 8
  798. | lwz TMP1, LFUNC:TMP1->pc
  799. | stwx TISNIL, RA, TMP2 // Ensure one valid arg.
  800. |.if FFI
  801. | ble >1
  802. |.endif
  803. | lwz KBASE, PC2PROTO(k)(TMP1)
  804. | // BASE = base, RA = resultptr, RB = meta base
  805. | mtctr TMP0
  806. | bctr // Jump to continuation.
  807. |
  808. |.if FFI
  809. |1:
  810. | beq ->cont_ffi_callback // cont = 1: return from FFI callback.
  811. | // cont = 0: tailcall from C function.
  812. | subi TMP1, RB, 16
  813. | sub RC, TMP1, BASE
  814. | b ->vm_call_tail
  815. |.endif
  816. |
  817. |->cont_cat: // RA = resultptr, RB = meta base
  818. | lwz INS, -4(PC)
  819. | subi CARG2, RB, 16
  820. | decode_RB8 SAVE0, INS
  821. | lfd f0, 0(RA)
  822. | add TMP1, BASE, SAVE0
  823. | stp BASE, L->base
  824. | cmplw TMP1, CARG2
  825. | sub CARG3, CARG2, TMP1
  826. | decode_RA8 RA, INS
  827. | stfd f0, 0(CARG2)
  828. | bney ->BC_CAT_Z
  829. | stfdx f0, BASE, RA
  830. | b ->cont_nop
  831. |
  832. |//-- Table indexing metamethods -----------------------------------------
  833. |
  834. |->vmeta_tgets1:
  835. | la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
  836. | li TMP0, LJ_TSTR
  837. | decode_RB8 RB, INS
  838. | stw STR:RC, 4(CARG3)
  839. | add CARG2, BASE, RB
  840. | stw TMP0, 0(CARG3)
  841. | b >1
  842. |
  843. |->vmeta_tgets:
  844. | la CARG2, DISPATCH_GL(tmptv)(DISPATCH)
  845. | li TMP0, LJ_TTAB
  846. | stw TAB:RB, 4(CARG2)
  847. | la CARG3, DISPATCH_GL(tmptv2)(DISPATCH)
  848. | stw TMP0, 0(CARG2)
  849. | li TMP1, LJ_TSTR
  850. | stw STR:RC, 4(CARG3)
  851. | stw TMP1, 0(CARG3)
  852. | b >1
  853. |
  854. |->vmeta_tgetb: // TMP0 = index
  855. |.if not DUALNUM
  856. | tonum_u f0, TMP0
  857. |.endif
  858. | decode_RB8 RB, INS
  859. | la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
  860. | add CARG2, BASE, RB
  861. |.if DUALNUM
  862. | stw TISNUM, 0(CARG3)
  863. | stw TMP0, 4(CARG3)
  864. |.else
  865. | stfd f0, 0(CARG3)
  866. |.endif
  867. | b >1
  868. |
  869. |->vmeta_tgetv:
  870. | decode_RB8 RB, INS
  871. | decode_RC8 RC, INS
  872. | add CARG2, BASE, RB
  873. | add CARG3, BASE, RC
  874. |1:
  875. | stp BASE, L->base
  876. | mr CARG1, L
  877. | stw PC, SAVE_PC
  878. | bl extern lj_meta_tget // (lua_State *L, TValue *o, TValue *k)
  879. | // Returns TValue * (finished) or NULL (metamethod).
  880. | cmplwi CRET1, 0
  881. | beq >3
  882. | lfd f0, 0(CRET1)
  883. | ins_next1
  884. | stfdx f0, BASE, RA
  885. | ins_next2
  886. |
  887. |3: // Call __index metamethod.
  888. | // BASE = base, L->top = new base, stack = cont/func/t/k
  889. | subfic TMP1, BASE, FRAME_CONT
  890. | lp BASE, L->top
  891. | stw PC, -16(BASE) // [cont|PC]
  892. | add PC, TMP1, BASE
  893. | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here.
  894. | li NARGS8:RC, 16 // 2 args for func(t, k).
  895. | b ->vm_call_dispatch_f
  896. |
  897. |//-----------------------------------------------------------------------
  898. |
  899. |->vmeta_tsets1:
  900. | la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
  901. | li TMP0, LJ_TSTR
  902. | decode_RB8 RB, INS
  903. | stw STR:RC, 4(CARG3)
  904. | add CARG2, BASE, RB
  905. | stw TMP0, 0(CARG3)
  906. | b >1
  907. |
  908. |->vmeta_tsets:
  909. | la CARG2, DISPATCH_GL(tmptv)(DISPATCH)
  910. | li TMP0, LJ_TTAB
  911. | stw TAB:RB, 4(CARG2)
  912. | la CARG3, DISPATCH_GL(tmptv2)(DISPATCH)
  913. | stw TMP0, 0(CARG2)
  914. | li TMP1, LJ_TSTR
  915. | stw STR:RC, 4(CARG3)
  916. | stw TMP1, 0(CARG3)
  917. | b >1
  918. |
  919. |->vmeta_tsetb: // TMP0 = index
  920. |.if not DUALNUM
  921. | tonum_u f0, TMP0
  922. |.endif
  923. | decode_RB8 RB, INS
  924. | la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
  925. | add CARG2, BASE, RB
  926. |.if DUALNUM
  927. | stw TISNUM, 0(CARG3)
  928. | stw TMP0, 4(CARG3)
  929. |.else
  930. | stfd f0, 0(CARG3)
  931. |.endif
  932. | b >1
  933. |
  934. |->vmeta_tsetv:
  935. | decode_RB8 RB, INS
  936. | decode_RC8 RC, INS
  937. | add CARG2, BASE, RB
  938. | add CARG3, BASE, RC
  939. |1:
  940. | stp BASE, L->base
  941. | mr CARG1, L
  942. | stw PC, SAVE_PC
  943. | bl extern lj_meta_tset // (lua_State *L, TValue *o, TValue *k)
  944. | // Returns TValue * (finished) or NULL (metamethod).
  945. | cmplwi CRET1, 0
  946. | lfdx f0, BASE, RA
  947. | beq >3
  948. | // NOBARRIER: lj_meta_tset ensures the table is not black.
  949. | ins_next1
  950. | stfd f0, 0(CRET1)
  951. | ins_next2
  952. |
  953. |3: // Call __newindex metamethod.
  954. | // BASE = base, L->top = new base, stack = cont/func/t/k/(v)
  955. | subfic TMP1, BASE, FRAME_CONT
  956. | lp BASE, L->top
  957. | stw PC, -16(BASE) // [cont|PC]
  958. | add PC, TMP1, BASE
  959. | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here.
  960. | li NARGS8:RC, 24 // 3 args for func(t, k, v)
  961. | stfd f0, 16(BASE) // Copy value to third argument.
  962. | b ->vm_call_dispatch_f
  963. |
  964. |//-- Comparison metamethods ---------------------------------------------
  965. |
  966. |->vmeta_comp:
  967. | mr CARG1, L
  968. | subi PC, PC, 4
  969. |.if DUALNUM
  970. | mr CARG2, RA
  971. |.else
  972. | add CARG2, BASE, RA
  973. |.endif
  974. | stw PC, SAVE_PC
  975. |.if DUALNUM
  976. | mr CARG3, RD
  977. |.else
  978. | add CARG3, BASE, RD
  979. |.endif
  980. | stp BASE, L->base
  981. | decode_OP1 CARG4, INS
  982. | bl extern lj_meta_comp // (lua_State *L, TValue *o1, *o2, int op)
  983. | // Returns 0/1 or TValue * (metamethod).
  984. |3:
  985. | cmplwi CRET1, 1
  986. | bgt ->vmeta_binop
  987. | subfic CRET1, CRET1, 0
  988. |4:
  989. | lwz INS, 0(PC)
  990. | addi PC, PC, 4
  991. | decode_RD4 TMP2, INS
  992. | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
  993. | and TMP2, TMP2, CRET1
  994. | add PC, PC, TMP2
  995. |->cont_nop:
  996. | ins_next
  997. |
  998. |->cont_ra: // RA = resultptr
  999. | lwz INS, -4(PC)
  1000. | lfd f0, 0(RA)
  1001. | decode_RA8 TMP1, INS
  1002. | stfdx f0, BASE, TMP1
  1003. | b ->cont_nop
  1004. |
  1005. |->cont_condt: // RA = resultptr
  1006. | lwz TMP0, 0(RA)
  1007. | .gpr64 extsw TMP0, TMP0
  1008. | subfic TMP0, TMP0, LJ_TTRUE // Branch if result is true.
  1009. | subfe CRET1, CRET1, CRET1
  1010. | not CRET1, CRET1
  1011. | b <4
  1012. |
  1013. |->cont_condf: // RA = resultptr
  1014. | lwz TMP0, 0(RA)
  1015. | .gpr64 extsw TMP0, TMP0
  1016. | subfic TMP0, TMP0, LJ_TTRUE // Branch if result is false.
  1017. | subfe CRET1, CRET1, CRET1
  1018. | b <4
  1019. |
  1020. |->vmeta_equal:
  1021. | // CARG2, CARG3, CARG4 are already set by BC_ISEQV/BC_ISNEV.
  1022. | subi PC, PC, 4
  1023. | stp BASE, L->base
  1024. | mr CARG1, L
  1025. | stw PC, SAVE_PC
  1026. | bl extern lj_meta_equal // (lua_State *L, GCobj *o1, *o2, int ne)
  1027. | // Returns 0/1 or TValue * (metamethod).
  1028. | b <3
  1029. |
  1030. |->vmeta_equal_cd:
  1031. |.if FFI
  1032. | mr CARG2, INS
  1033. | subi PC, PC, 4
  1034. | stp BASE, L->base
  1035. | mr CARG1, L
  1036. | stw PC, SAVE_PC
  1037. | bl extern lj_meta_equal_cd // (lua_State *L, BCIns op)
  1038. | // Returns 0/1 or TValue * (metamethod).
  1039. | b <3
  1040. |.endif
  1041. |
  1042. |//-- Arithmetic metamethods ---------------------------------------------
  1043. |
  1044. |->vmeta_arith_nv:
  1045. | add CARG3, KBASE, RC
  1046. | add CARG4, BASE, RB
  1047. | b >1
  1048. |->vmeta_arith_nv2:
  1049. |.if DUALNUM
  1050. | mr CARG3, RC
  1051. | mr CARG4, RB
  1052. | b >1
  1053. |.endif
  1054. |
  1055. |->vmeta_unm:
  1056. | mr CARG3, RD
  1057. | mr CARG4, RD
  1058. | b >1
  1059. |
  1060. |->vmeta_arith_vn:
  1061. | add CARG3, BASE, RB
  1062. | add CARG4, KBASE, RC
  1063. | b >1
  1064. |
  1065. |->vmeta_arith_vv:
  1066. | add CARG3, BASE, RB
  1067. | add CARG4, BASE, RC
  1068. |.if DUALNUM
  1069. | b >1
  1070. |.endif
  1071. |->vmeta_arith_vn2:
  1072. |->vmeta_arith_vv2:
  1073. |.if DUALNUM
  1074. | mr CARG3, RB
  1075. | mr CARG4, RC
  1076. |.endif
  1077. |1:
  1078. | add CARG2, BASE, RA
  1079. | stp BASE, L->base
  1080. | mr CARG1, L
  1081. | stw PC, SAVE_PC
  1082. | decode_OP1 CARG5, INS // Caveat: CARG5 overlaps INS.
  1083. | bl extern lj_meta_arith // (lua_State *L, TValue *ra,*rb,*rc, BCReg op)
  1084. | // Returns NULL (finished) or TValue * (metamethod).
  1085. | cmplwi CRET1, 0
  1086. | beq ->cont_nop
  1087. |
  1088. | // Call metamethod for binary op.
  1089. |->vmeta_binop:
  1090. | // BASE = old base, CRET1 = new base, stack = cont/func/o1/o2
  1091. | sub TMP1, CRET1, BASE
  1092. | stw PC, -16(CRET1) // [cont|PC]
  1093. | mr TMP2, BASE
  1094. | addi PC, TMP1, FRAME_CONT
  1095. | mr BASE, CRET1
  1096. | li NARGS8:RC, 16 // 2 args for func(o1, o2).
  1097. | b ->vm_call_dispatch
  1098. |
  1099. |->vmeta_len:
  1100. #if LJ_52
  1101. | mr SAVE0, CARG1
  1102. #endif
  1103. | mr CARG2, RD
  1104. | stp BASE, L->base
  1105. | mr CARG1, L
  1106. | stw PC, SAVE_PC
  1107. | bl extern lj_meta_len // (lua_State *L, TValue *o)
  1108. | // Returns NULL (retry) or TValue * (metamethod base).
  1109. #if LJ_52
  1110. | cmplwi CRET1, 0
  1111. | bne ->vmeta_binop // Binop call for compatibility.
  1112. | mr CARG1, SAVE0
  1113. | b ->BC_LEN_Z
  1114. #else
  1115. | b ->vmeta_binop // Binop call for compatibility.
  1116. #endif
  1117. |
  1118. |//-- Call metamethod ----------------------------------------------------
  1119. |
  1120. |->vmeta_call: // Resolve and call __call metamethod.
  1121. | // TMP2 = old base, BASE = new base, RC = nargs*8
  1122. | mr CARG1, L
  1123. | stp TMP2, L->base // This is the callers base!
  1124. | subi CARG2, BASE, 8
  1125. | stw PC, SAVE_PC
  1126. | add CARG3, BASE, RC
  1127. | mr SAVE0, NARGS8:RC
  1128. | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top)
  1129. | lwz LFUNC:RB, FRAME_FUNC(BASE) // Guaranteed to be a function here.
  1130. | addi NARGS8:RC, SAVE0, 8 // Got one more argument now.
  1131. | ins_call
  1132. |
  1133. |->vmeta_callt: // Resolve __call for BC_CALLT.
  1134. | // BASE = old base, RA = new base, RC = nargs*8
  1135. | mr CARG1, L
  1136. | stp BASE, L->base
  1137. | subi CARG2, RA, 8
  1138. | stw PC, SAVE_PC
  1139. | add CARG3, RA, RC
  1140. | mr SAVE0, NARGS8:RC
  1141. | bl extern lj_meta_call // (lua_State *L, TValue *func, TValue *top)
  1142. | lwz TMP1, FRAME_PC(BASE)
  1143. | addi NARGS8:RC, SAVE0, 8 // Got one more argument now.
  1144. | lwz LFUNC:RB, FRAME_FUNC(RA) // Guaranteed to be a function here.
  1145. | b ->BC_CALLT_Z
  1146. |
  1147. |//-- Argument coercion for 'for' statement ------------------------------
  1148. |
  1149. |->vmeta_for:
  1150. | mr CARG1, L
  1151. | stp BASE, L->base
  1152. | mr CARG2, RA
  1153. | stw PC, SAVE_PC
  1154. | mr SAVE0, INS
  1155. | bl extern lj_meta_for // (lua_State *L, TValue *base)
  1156. |.if JIT
  1157. | decode_OP1 TMP0, SAVE0
  1158. |.endif
  1159. | decode_RA8 RA, SAVE0
  1160. |.if JIT
  1161. | cmpwi TMP0, BC_JFORI
  1162. |.endif
  1163. | decode_RD8 RD, SAVE0
  1164. |.if JIT
  1165. | beqy =>BC_JFORI
  1166. |.endif
  1167. | b =>BC_FORI
  1168. |
  1169. |//-----------------------------------------------------------------------
  1170. |//-- Fast functions -----------------------------------------------------
  1171. |//-----------------------------------------------------------------------
  1172. |
  1173. |.macro .ffunc, name
  1174. |->ff_ .. name:
  1175. |.endmacro
  1176. |
  1177. |.macro .ffunc_1, name
  1178. |->ff_ .. name:
  1179. | cmplwi NARGS8:RC, 8
  1180. | lwz CARG3, 0(BASE)
  1181. | lwz CARG1, 4(BASE)
  1182. | blt ->fff_fallback
  1183. |.endmacro
  1184. |
  1185. |.macro .ffunc_2, name
  1186. |->ff_ .. name:
  1187. | cmplwi NARGS8:RC, 16
  1188. | lwz CARG3, 0(BASE)
  1189. | lwz CARG4, 8(BASE)
  1190. | lwz CARG1, 4(BASE)
  1191. | lwz CARG2, 12(BASE)
  1192. | blt ->fff_fallback
  1193. |.endmacro
  1194. |
  1195. |.macro .ffunc_n, name
  1196. |->ff_ .. name:
  1197. | cmplwi NARGS8:RC, 8
  1198. | lwz CARG3, 0(BASE)
  1199. | lfd FARG1, 0(BASE)
  1200. | blt ->fff_fallback
  1201. | checknum CARG3; bge ->fff_fallback
  1202. |.endmacro
  1203. |
  1204. |.macro .ffunc_nn, name
  1205. |->ff_ .. name:
  1206. | cmplwi NARGS8:RC, 16
  1207. | lwz CARG3, 0(BASE)
  1208. | lfd FARG1, 0(BASE)
  1209. | lwz CARG4, 8(BASE)
  1210. | lfd FARG2, 8(BASE)
  1211. | blt ->fff_fallback
  1212. | checknum CARG3; bge ->fff_fallback
  1213. | checknum CARG4; bge ->fff_fallback
  1214. |.endmacro
  1215. |
  1216. |// Inlined GC threshold check. Caveat: uses TMP0 and TMP1.
  1217. |.macro ffgccheck
  1218. | lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH)
  1219. | lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH)
  1220. | cmplw TMP0, TMP1
  1221. | bgel ->fff_gcstep
  1222. |.endmacro
  1223. |
  1224. |//-- Base library: checks -----------------------------------------------
  1225. |
  1226. |.ffunc_1 assert
  1227. | li TMP1, LJ_TFALSE
  1228. | la RA, -8(BASE)
  1229. | cmplw cr1, CARG3, TMP1
  1230. | lwz PC, FRAME_PC(BASE)
  1231. | bge cr1, ->fff_fallback
  1232. | stw CARG3, 0(RA)
  1233. | addi RD, NARGS8:RC, 8 // Compute (nresults+1)*8.
  1234. | stw CARG1, 4(RA)
  1235. | beq ->fff_res // Done if exactly 1 argument.
  1236. | li TMP1, 8
  1237. | subi RC, RC, 8
  1238. |1:
  1239. | cmplw TMP1, RC
  1240. | lfdx f0, BASE, TMP1
  1241. | stfdx f0, RA, TMP1
  1242. | addi TMP1, TMP1, 8
  1243. | bney <1
  1244. | b ->fff_res
  1245. |
  1246. |.ffunc type
  1247. | cmplwi NARGS8:RC, 8
  1248. | lwz CARG1, 0(BASE)
  1249. | blt ->fff_fallback
  1250. | .gpr64 extsw CARG1, CARG1
  1251. | subfc TMP0, TISNUM, CARG1
  1252. | subfe TMP2, CARG1, CARG1
  1253. | orc TMP1, TMP2, TMP0
  1254. | addi TMP1, TMP1, ~LJ_TISNUM+1
  1255. | slwi TMP1, TMP1, 3
  1256. | la TMP2, CFUNC:RB->upvalue
  1257. | lfdx FARG1, TMP2, TMP1
  1258. | b ->fff_resn
  1259. |
  1260. |//-- Base library: getters and setters ---------------------------------
  1261. |
  1262. |.ffunc_1 getmetatable
  1263. | checktab CARG3; bne >6
  1264. |1: // Field metatable must be at same offset for GCtab and GCudata!
  1265. | lwz TAB:CARG1, TAB:CARG1->metatable
  1266. |2:
  1267. | li CARG3, LJ_TNIL
  1268. | cmplwi TAB:CARG1, 0
  1269. | lwz STR:RC, DISPATCH_GL(gcroot[GCROOT_MMNAME+MM_metatable])(DISPATCH)
  1270. | beq ->fff_restv
  1271. | lwz TMP0, TAB:CARG1->hmask
  1272. | li CARG3, LJ_TTAB // Use metatable as default result.
  1273. | lwz TMP1, STR:RC->hash
  1274. | lwz NODE:TMP2, TAB:CARG1->node
  1275. | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask
  1276. | slwi TMP0, TMP1, 5
  1277. | slwi TMP1, TMP1, 3
  1278. | sub TMP1, TMP0, TMP1
  1279. | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8)
  1280. |3: // Rearranged logic, because we expect _not_ to find the key.
  1281. | lwz CARG4, NODE:TMP2->key
  1282. | lwz TMP0, 4+offsetof(Node, key)(NODE:TMP2)
  1283. | lwz CARG2, NODE:TMP2->val
  1284. | lwz TMP1, 4+offsetof(Node, val)(NODE:TMP2)
  1285. | checkstr CARG4; bne >4
  1286. | cmpw TMP0, STR:RC; beq >5
  1287. |4:
  1288. | lwz NODE:TMP2, NODE:TMP2->next
  1289. | cmplwi NODE:TMP2, 0
  1290. | beq ->fff_restv // Not found, keep default result.
  1291. | b <3
  1292. |5:
  1293. | checknil CARG2
  1294. | beq ->fff_restv // Ditto for nil value.
  1295. | mr CARG3, CARG2 // Return value of mt.__metatable.
  1296. | mr CARG1, TMP1
  1297. | b ->fff_restv
  1298. |
  1299. |6:
  1300. | cmpwi CARG3, LJ_TUDATA; beq <1
  1301. | .gpr64 extsw CARG3, CARG3
  1302. | subfc TMP0, TISNUM, CARG3
  1303. | subfe TMP2, CARG3, CARG3
  1304. | orc TMP1, TMP2, TMP0
  1305. | addi TMP1, TMP1, ~LJ_TISNUM+1
  1306. | slwi TMP1, TMP1, 2
  1307. | la TMP2, DISPATCH_GL(gcroot[GCROOT_BASEMT])(DISPATCH)
  1308. | lwzx TAB:CARG1, TMP2, TMP1
  1309. | b <2
  1310. |
  1311. |.ffunc_2 setmetatable
  1312. | // Fast path: no mt for table yet and not clearing the mt.
  1313. | checktab CARG3; bne ->fff_fallback
  1314. | lwz TAB:TMP1, TAB:CARG1->metatable
  1315. | checktab CARG4; bne ->fff_fallback
  1316. | cmplwi TAB:TMP1, 0
  1317. | lbz TMP3, TAB:CARG1->marked
  1318. | bne ->fff_fallback
  1319. | andix. TMP0, TMP3, LJ_GC_BLACK // isblack(table)
  1320. | stw TAB:CARG2, TAB:CARG1->metatable
  1321. | beq ->fff_restv
  1322. | barrierback TAB:CARG1, TMP3, TMP0
  1323. | b ->fff_restv
  1324. |
  1325. |.ffunc rawget
  1326. | cmplwi NARGS8:RC, 16
  1327. | lwz CARG4, 0(BASE)
  1328. | lwz TAB:CARG2, 4(BASE)
  1329. | blt ->fff_fallback
  1330. | checktab CARG4; bne ->fff_fallback
  1331. | la CARG3, 8(BASE)
  1332. | mr CARG1, L
  1333. | bl extern lj_tab_get // (lua_State *L, GCtab *t, cTValue *key)
  1334. | // Returns cTValue *.
  1335. | lfd FARG1, 0(CRET1)
  1336. | b ->fff_resn
  1337. |
  1338. |//-- Base library: conversions ------------------------------------------
  1339. |
  1340. |.ffunc tonumber
  1341. | // Only handles the number case inline (without a base argument).
  1342. | cmplwi NARGS8:RC, 8
  1343. | lwz CARG1, 0(BASE)
  1344. | lfd FARG1, 0(BASE)
  1345. | bne ->fff_fallback // Exactly one argument.
  1346. | checknum CARG1; bgt ->fff_fallback
  1347. | b ->fff_resn
  1348. |
  1349. |.ffunc_1 tostring
  1350. | // Only handles the string or number case inline.
  1351. | checkstr CARG3
  1352. | // A __tostring method in the string base metatable is ignored.
  1353. | beq ->fff_restv // String key?
  1354. | // Handle numbers inline, unless a number base metatable is present.
  1355. | lwz TMP0, DISPATCH_GL(gcroot[GCROOT_BASEMT_NUM])(DISPATCH)
  1356. | checknum CARG3
  1357. | cmplwi cr1, TMP0, 0
  1358. | stp BASE, L->base // Add frame since C call can throw.
  1359. | crorc 4*cr0+eq, 4*cr0+gt, 4*cr1+eq
  1360. | stw PC, SAVE_PC // Redundant (but a defined value).
  1361. | beq ->fff_fallback
  1362. | ffgccheck
  1363. | mr CARG1, L
  1364. | mr CARG2, BASE
  1365. |.if DUALNUM
  1366. | bl extern lj_str_fromnumber // (lua_State *L, cTValue *o)
  1367. |.else
  1368. | bl extern lj_str_fromnum // (lua_State *L, lua_Number *np)
  1369. |.endif
  1370. | // Returns GCstr *.
  1371. | li CARG3, LJ_TSTR
  1372. | b ->fff_restv
  1373. |
  1374. |//-- Base library: iterators -------------------------------------------
  1375. |
  1376. |.ffunc next
  1377. | cmplwi NARGS8:RC, 8
  1378. | lwz CARG1, 0(BASE)
  1379. | lwz TAB:CARG2, 4(BASE)
  1380. | blt ->fff_fallback
  1381. | stwx TISNIL, BASE, NARGS8:RC // Set missing 2nd arg to nil.
  1382. | checktab CARG1
  1383. | lwz PC, FRAME_PC(BASE)
  1384. | bne ->fff_fallback
  1385. | stp BASE, L->base // Add frame since C call can throw.
  1386. | mr CARG1, L
  1387. | stp BASE, L->top // Dummy frame length is ok.
  1388. | la CARG3, 8(BASE)
  1389. | stw PC, SAVE_PC
  1390. | bl extern lj_tab_next // (lua_State *L, GCtab *t, TValue *key)
  1391. | // Returns 0 at end of traversal.
  1392. | cmplwi CRET1, 0
  1393. | li CARG3, LJ_TNIL
  1394. | beq ->fff_restv // End of traversal: return nil.
  1395. | lfd f0, 8(BASE) // Copy key and value to results.
  1396. | la RA, -8(BASE)
  1397. | lfd f1, 16(BASE)
  1398. | stfd f0, 0(RA)
  1399. | li RD, (2+1)*8
  1400. | stfd f1, 8(RA)
  1401. | b ->fff_res
  1402. |
  1403. |.ffunc_1 pairs
  1404. | checktab CARG3
  1405. | lwz PC, FRAME_PC(BASE)
  1406. | bne ->fff_fallback
  1407. #if LJ_52
  1408. | lwz TAB:TMP2, TAB:CARG1->metatable
  1409. | lfd f0, CFUNC:RB->upvalue[0]
  1410. | cmplwi TAB:TMP2, 0
  1411. | la RA, -8(BASE)
  1412. | bne ->fff_fallback
  1413. #else
  1414. | lfd f0, CFUNC:RB->upvalue[0]
  1415. | la RA, -8(BASE)
  1416. #endif
  1417. | stw TISNIL, 8(BASE)
  1418. | li RD, (3+1)*8
  1419. | stfd f0, 0(RA)
  1420. | b ->fff_res
  1421. |
  1422. |.ffunc ipairs_aux
  1423. | cmplwi NARGS8:RC, 16
  1424. | lwz CARG3, 0(BASE)
  1425. | lwz TAB:CARG1, 4(BASE)
  1426. | lwz CARG4, 8(BASE)
  1427. |.if DUALNUM
  1428. | lwz TMP2, 12(BASE)
  1429. |.else
  1430. | lfd FARG2, 8(BASE)
  1431. |.endif
  1432. | blt ->fff_fallback
  1433. | checktab CARG3
  1434. | checknum cr1, CARG4
  1435. | lwz PC, FRAME_PC(BASE)
  1436. |.if DUALNUM
  1437. | bne ->fff_fallback
  1438. | bne cr1, ->fff_fallback
  1439. |.else
  1440. | lus TMP0, 0x3ff0
  1441. | stw ZERO, TMPD_LO
  1442. | bne ->fff_fallback
  1443. | stw TMP0, TMPD_HI
  1444. | bge cr1, ->fff_fallback
  1445. | lfd FARG1, TMPD
  1446. | toint TMP2, FARG2, f0
  1447. |.endif
  1448. | lwz TMP0, TAB:CARG1->asize
  1449. | lwz TMP1, TAB:CARG1->array
  1450. |.if not DUALNUM
  1451. | fadd FARG2, FARG2, FARG1
  1452. |.endif
  1453. | addi TMP2, TMP2, 1
  1454. | la RA, -8(BASE)
  1455. | cmplw TMP0, TMP2
  1456. |.if DUALNUM
  1457. | stw TISNUM, 0(RA)
  1458. | slwi TMP3, TMP2, 3
  1459. | stw TMP2, 4(RA)
  1460. |.else
  1461. | slwi TMP3, TMP2, 3
  1462. | stfd FARG2, 0(RA)
  1463. |.endif
  1464. | ble >2 // Not in array part?
  1465. | lwzx TMP2, TMP1, TMP3
  1466. | lfdx f0, TMP1, TMP3
  1467. |1:
  1468. | checknil TMP2
  1469. | li RD, (0+1)*8
  1470. | beq ->fff_res // End of iteration, return 0 results.
  1471. | li RD, (2+1)*8
  1472. | stfd f0, 8(RA)
  1473. | b ->fff_res
  1474. |2: // Check for empty hash part first. Otherwise call C function.
  1475. | lwz TMP0, TAB:CARG1->hmask
  1476. | cmplwi TMP0, 0
  1477. | li RD, (0+1)*8
  1478. | beq ->fff_res
  1479. | mr CARG2, TMP2
  1480. | bl extern lj_tab_getinth // (GCtab *t, int32_t key)
  1481. | // Returns cTValue * or NULL.
  1482. | cmplwi CRET1, 0
  1483. | li RD, (0+1)*8
  1484. | beq ->fff_res
  1485. | lwz TMP2, 0(CRET1)
  1486. | lfd f0, 0(CRET1)
  1487. | b <1
  1488. |
  1489. |.ffunc_1 ipairs
  1490. | checktab CARG3
  1491. | lwz PC, FRAME_PC(BASE)
  1492. | bne ->fff_fallback
  1493. #if LJ_52
  1494. | lwz TAB:TMP2, TAB:CARG1->metatable
  1495. | lfd f0, CFUNC:RB->upvalue[0]
  1496. | cmplwi TAB:TMP2, 0
  1497. | la RA, -8(BASE)
  1498. | bne ->fff_fallback
  1499. #else
  1500. | lfd f0, CFUNC:RB->upvalue[0]
  1501. | la RA, -8(BASE)
  1502. #endif
  1503. |.if DUALNUM
  1504. | stw TISNUM, 8(BASE)
  1505. |.else
  1506. | stw ZERO, 8(BASE)
  1507. |.endif
  1508. | stw ZERO, 12(BASE)
  1509. | li RD, (3+1)*8
  1510. | stfd f0, 0(RA)
  1511. | b ->fff_res
  1512. |
  1513. |//-- Base library: catch errors ----------------------------------------
  1514. |
  1515. |.ffunc pcall
  1516. | cmplwi NARGS8:RC, 8
  1517. | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH)
  1518. | blt ->fff_fallback
  1519. | mr TMP2, BASE
  1520. | la BASE, 8(BASE)
  1521. | // Remember active hook before pcall.
  1522. | rlwinm TMP3, TMP3, 32-HOOK_ACTIVE_SHIFT, 31, 31
  1523. | subi NARGS8:RC, NARGS8:RC, 8
  1524. | addi PC, TMP3, 8+FRAME_PCALL
  1525. | b ->vm_call_dispatch
  1526. |
  1527. |.ffunc xpcall
  1528. | cmplwi NARGS8:RC, 16
  1529. | lwz CARG4, 8(BASE)
  1530. | lfd FARG2, 8(BASE)
  1531. | lfd FARG1, 0(BASE)
  1532. | blt ->fff_fallback
  1533. | lbz TMP1, DISPATCH_GL(hookmask)(DISPATCH)
  1534. | mr TMP2, BASE
  1535. | checkfunc CARG4; bne ->fff_fallback // Traceback must be a function.
  1536. | la BASE, 16(BASE)
  1537. | // Remember active hook before pcall.
  1538. | rlwinm TMP1, TMP1, 32-HOOK_ACTIVE_SHIFT, 31, 31
  1539. | stfd FARG2, 0(TMP2) // Swap function and traceback.
  1540. | subi NARGS8:RC, NARGS8:RC, 16
  1541. | stfd FARG1, 8(TMP2)
  1542. | addi PC, TMP1, 16+FRAME_PCALL
  1543. | b ->vm_call_dispatch
  1544. |
  1545. |//-- Coroutine library --------------------------------------------------
  1546. |
  1547. |.macro coroutine_resume_wrap, resume
  1548. |.if resume
  1549. |.ffunc_1 coroutine_resume
  1550. | cmpwi CARG3, LJ_TTHREAD; bne ->fff_fallback
  1551. |.else
  1552. |.ffunc coroutine_wrap_aux
  1553. | lwz L:CARG1, CFUNC:RB->upvalue[0].gcr
  1554. |.endif
  1555. | lbz TMP0, L:CARG1->status
  1556. | lp TMP1, L:CARG1->cframe
  1557. | lp CARG2, L:CARG1->top
  1558. | cmplwi cr0, TMP0, LUA_YIELD
  1559. | lp TMP2, L:CARG1->base
  1560. | cmplwi cr1, TMP1, 0
  1561. | lwz TMP0, L:CARG1->maxstack
  1562. | cmplw cr7, CARG2, TMP2
  1563. | lwz PC, FRAME_PC(BASE)
  1564. | crorc 4*cr6+lt, 4*cr0+gt, 4*cr1+eq // st>LUA_YIELD || cframe!=0
  1565. | add TMP2, CARG2, NARGS8:RC
  1566. | crandc 4*cr6+gt, 4*cr7+eq, 4*cr0+eq // base==top && st!=LUA_YIELD
  1567. | cmplw cr1, TMP2, TMP0
  1568. | cror 4*cr6+lt, 4*cr6+lt, 4*cr6+gt
  1569. | stw PC, SAVE_PC
  1570. | cror 4*cr6+lt, 4*cr6+lt, 4*cr1+gt // cond1 || cond2 || stackov
  1571. | stp BASE, L->base
  1572. | blt cr6, ->fff_fallback
  1573. |1:
  1574. |.if resume
  1575. | addi BASE, BASE, 8 // Keep resumed thread in stack for GC.
  1576. | subi NARGS8:RC, NARGS8:RC, 8
  1577. | subi TMP2, TMP2, 8
  1578. |.endif
  1579. | stp TMP2, L:CARG1->top
  1580. | li TMP1, 0
  1581. | stp BASE, L->top
  1582. |2: // Move args to coroutine.
  1583. | cmpw TMP1, NARGS8:RC
  1584. | lfdx f0, BASE, TMP1
  1585. | beq >3
  1586. | stfdx f0, CARG2, TMP1
  1587. | addi TMP1, TMP1, 8
  1588. | b <2
  1589. |3:
  1590. | li CARG3, 0
  1591. | mr L:SAVE0, L:CARG1
  1592. | li CARG4, 0
  1593. | bl ->vm_resume // (lua_State *L, TValue *base, 0, 0)
  1594. | // Returns thread status.
  1595. |4:
  1596. | lp TMP2, L:SAVE0->base
  1597. | cmplwi CRET1, LUA_YIELD
  1598. | lp TMP3, L:SAVE0->top
  1599. | li_vmstate INTERP
  1600. | lp BASE, L->base
  1601. | st_vmstate
  1602. | bgt >8
  1603. | sub RD, TMP3, TMP2
  1604. | lwz TMP0, L->maxstack
  1605. | cmplwi RD, 0
  1606. | add TMP1, BASE, RD
  1607. | beq >6 // No results?
  1608. | cmplw TMP1, TMP0
  1609. | li TMP1, 0
  1610. | bgt >9 // Need to grow stack?
  1611. |
  1612. | subi TMP3, RD, 8
  1613. | stp TMP2, L:SAVE0->top // Clear coroutine stack.
  1614. |5: // Move results from coroutine.
  1615. | cmplw TMP1, TMP3
  1616. | lfdx f0, TMP2, TMP1
  1617. | stfdx f0, BASE, TMP1
  1618. | addi TMP1, TMP1, 8
  1619. | bne <5
  1620. |6:
  1621. | andix. TMP0, PC, FRAME_TYPE
  1622. |.if resume
  1623. | li TMP1, LJ_TTRUE
  1624. | la RA, -8(BASE)
  1625. | stw TMP1, -8(BASE) // Prepend true to results.
  1626. | addi RD, RD, 16
  1627. |.else
  1628. | mr RA, BASE
  1629. | addi RD, RD, 8
  1630. |.endif
  1631. |7:
  1632. | stw PC, SAVE_PC
  1633. | mr MULTRES, RD
  1634. | beq ->BC_RET_Z
  1635. | b ->vm_return
  1636. |
  1637. |8: // Coroutine returned with error (at co->top-1).
  1638. |.if resume
  1639. | andix. TMP0, PC, FRAME_TYPE
  1640. | la TMP3, -8(TMP3)
  1641. | li TMP1, LJ_TFALSE
  1642. | lfd f0, 0(TMP3)
  1643. | stp TMP3, L:SAVE0->top // Remove error from coroutine stack.
  1644. | li RD, (2+1)*8
  1645. | stw TMP1, -8(BASE) // Prepend false to results.
  1646. | la RA, -8(BASE)
  1647. | stfd f0, 0(BASE) // Copy error message.
  1648. | b <7
  1649. |.else
  1650. | mr CARG1, L
  1651. | mr CARG2, L:SAVE0
  1652. | bl extern lj_ffh_coroutine_wrap_err // (lua_State *L, lua_State *co)
  1653. |.endif
  1654. |
  1655. |9: // Handle stack expansion on return from yield.
  1656. | mr CARG1, L
  1657. | srwi CARG2, RD, 3
  1658. | bl extern lj_state_growstack // (lua_State *L, int n)
  1659. | li CRET1, 0
  1660. | b <4
  1661. |.endmacro
  1662. |
  1663. | coroutine_resume_wrap 1 // coroutine.resume
  1664. | coroutine_resume_wrap 0 // coroutine.wrap
  1665. |
  1666. |.ffunc coroutine_yield
  1667. | lp TMP0, L->cframe
  1668. | add TMP1, BASE, NARGS8:RC
  1669. | stp BASE, L->base
  1670. | andix. TMP0, TMP0, CFRAME_RESUME
  1671. | stp TMP1, L->top
  1672. | li CRET1, LUA_YIELD
  1673. | beq ->fff_fallback
  1674. | stp ZERO, L->cframe
  1675. | stb CRET1, L->status
  1676. | b ->vm_leave_unw
  1677. |
  1678. |//-- Math library -------------------------------------------------------
  1679. |
  1680. |.ffunc_1 math_abs
  1681. | checknum CARG3
  1682. |.if DUALNUM
  1683. | bne >2
  1684. | srawi TMP1, CARG1, 31
  1685. | xor TMP2, TMP1, CARG1
  1686. |.if GPR64
  1687. | lus TMP0, 0x8000
  1688. | sub CARG1, TMP2, TMP1
  1689. | cmplw CARG1, TMP0
  1690. | beq >1
  1691. |.else
  1692. | sub. CARG1, TMP2, TMP1
  1693. | blt >1
  1694. |.endif
  1695. |->fff_resi:
  1696. | lwz PC, FRAME_PC(BASE)
  1697. | la RA, -8(BASE)
  1698. | stw TISNUM, -8(BASE)
  1699. | stw CRET1, -4(BASE)
  1700. | b ->fff_res1
  1701. |1:
  1702. | lus CARG3, 0x41e0 // 2^31.
  1703. | li CARG1, 0
  1704. | b ->fff_restv
  1705. |2:
  1706. |.endif
  1707. | bge ->fff_fallback
  1708. | rlwinm CARG3, CARG3, 0, 1, 31
  1709. | // Fallthrough.
  1710. |
  1711. |->fff_restv:
  1712. | // CARG3/CARG1 = TValue result.
  1713. | lwz PC, FRAME_PC(BASE)
  1714. | stw CARG3, -8(BASE)
  1715. | la RA, -8(BASE)
  1716. | stw CARG1, -4(BASE)
  1717. |->fff_res1:
  1718. | // RA = results, PC = return.
  1719. | li RD, (1+1)*8
  1720. |->fff_res:
  1721. | // RA = results, RD = (nresults+1)*8, PC = return.
  1722. | andix. TMP0, PC, FRAME_TYPE
  1723. | mr MULTRES, RD
  1724. | bney ->vm_return
  1725. | lwz INS, -4(PC)
  1726. | decode_RB8 RB, INS
  1727. |5:
  1728. | cmplw RB, RD // More results expected?
  1729. | decode_RA8 TMP0, INS
  1730. | bgt >6
  1731. | ins_next1
  1732. | // Adjust BASE. KBASE is assumed to be set for the calling frame.
  1733. | sub BASE, RA, TMP0
  1734. | ins_next2
  1735. |
  1736. |6: // Fill up results with nil.
  1737. | subi TMP1, RD, 8
  1738. | addi RD, RD, 8
  1739. | stwx TISNIL, RA, TMP1
  1740. | b <5
  1741. |
  1742. |.macro math_extern, func
  1743. | .ffunc_n math_ .. func
  1744. | blex func
  1745. | b ->fff_resn
  1746. |.endmacro
  1747. |
  1748. |.macro math_extern2, func
  1749. | .ffunc_nn math_ .. func
  1750. | blex func
  1751. | b ->fff_resn
  1752. |.endmacro
  1753. |
  1754. |.macro math_round, func
  1755. | .ffunc_1 math_ .. func
  1756. | checknum CARG3; beqy ->fff_restv
  1757. | rlwinm TMP2, CARG3, 12, 21, 31
  1758. | bge ->fff_fallback
  1759. | addic. TMP2, TMP2, -1023 // exp = exponent(x) - 1023
  1760. | cmplwi cr1, TMP2, 31 // 0 <= exp < 31?
  1761. | subfic TMP0, TMP2, 31
  1762. | blt >3
  1763. | slwi TMP1, CARG3, 11
  1764. | srwi TMP3, CARG1, 21
  1765. | oris TMP1, TMP1, 0x8000
  1766. | addi TMP2, TMP2, 1
  1767. | or TMP1, TMP1, TMP3
  1768. | slwi CARG2, CARG1, 11
  1769. | bge cr1, >4
  1770. | slw TMP3, TMP1, TMP2
  1771. | srw RD, TMP1, TMP0
  1772. | or TMP3, TMP3, CARG2
  1773. | srawi TMP2, CARG3, 31
  1774. |.if "func" == "floor"
  1775. | and TMP1, TMP3, TMP2
  1776. | addic TMP0, TMP1, -1
  1777. | subfe TMP1, TMP0, TMP1
  1778. | add CARG1, RD, TMP1
  1779. | xor CARG1, CARG1, TMP2
  1780. | sub CARG1, CARG1, TMP2
  1781. | b ->fff_resi
  1782. |.else
  1783. | andc TMP1, TMP3, TMP2
  1784. | addic TMP0, TMP1, -1
  1785. | subfe TMP1, TMP0, TMP1
  1786. | add CARG1, RD, TMP1
  1787. | cmpw CARG1, RD
  1788. | xor CARG1, CARG1, TMP2
  1789. | sub CARG1, CARG1, TMP2
  1790. | bge ->fff_resi
  1791. | // Overflow to 2^31.
  1792. | lus CARG3, 0x41e0 // 2^31.
  1793. | li CARG1, 0
  1794. | b ->fff_restv
  1795. |.endif
  1796. |3: // |x| < 1
  1797. | slwi TMP2, CARG3, 1
  1798. | srawi TMP1, CARG3, 31
  1799. | or TMP2, CARG1, TMP2 // ztest = (hi+hi) | lo
  1800. |.if "func" == "floor"
  1801. | and TMP1, TMP2, TMP1 // (ztest & sign) == 0 ? 0 : -1
  1802. | subfic TMP2, TMP1, 0
  1803. | subfe CARG1, CARG1, CARG1
  1804. |.else
  1805. | andc TMP1, TMP2, TMP1 // (ztest & ~sign) == 0 ? 0 : 1
  1806. | addic TMP2, TMP1, -1
  1807. | subfe CARG1, TMP2, TMP1
  1808. |.endif
  1809. | b ->fff_resi
  1810. |4: // exp >= 31. Check for -(2^31).
  1811. | xoris TMP1, TMP1, 0x8000
  1812. | srawi TMP2, CARG3, 31
  1813. |.if "func" == "floor"
  1814. | or TMP1, TMP1, CARG2
  1815. |.endif
  1816. |.if PPE
  1817. | orc TMP1, TMP1, TMP2
  1818. | cmpwi TMP1, 0
  1819. |.else
  1820. | orc. TMP1, TMP1, TMP2
  1821. |.endif
  1822. | crand 4*cr0+eq, 4*cr0+eq, 4*cr1+eq
  1823. | lus CARG1, 0x8000 // -(2^31).
  1824. | beqy ->fff_resi
  1825. |5:
  1826. | lfd FARG1, 0(BASE)
  1827. | blex func
  1828. | b ->fff_resn
  1829. |.endmacro
  1830. |
  1831. |.if DUALNUM
  1832. | math_round floor
  1833. | math_round ceil
  1834. |.else
  1835. | // NYI: use internal implementation.
  1836. | math_extern floor
  1837. | math_extern ceil
  1838. |.endif
  1839. |
  1840. |.if SQRT
  1841. |.ffunc_n math_sqrt
  1842. | fsqrt FARG1, FARG1
  1843. | b ->fff_resn
  1844. |.else
  1845. | math_extern sqrt
  1846. |.endif
  1847. |
  1848. |.ffunc math_log
  1849. | cmplwi NARGS8:RC, 8
  1850. | lwz CARG3, 0(BASE)
  1851. | lfd FARG1, 0(BASE)
  1852. | bne ->fff_fallback // Need exactly 1 argument.
  1853. | checknum CARG3; bge ->fff_fallback
  1854. | blex log
  1855. | b ->fff_resn
  1856. |
  1857. | math_extern log10
  1858. | math_extern exp
  1859. | math_extern sin
  1860. | math_extern cos
  1861. | math_extern tan
  1862. | math_extern asin
  1863. | math_extern acos
  1864. | math_extern atan
  1865. | math_extern sinh
  1866. | math_extern cosh
  1867. | math_extern tanh
  1868. | math_extern2 pow
  1869. | math_extern2 atan2
  1870. | math_extern2 fmod
  1871. |
  1872. |->ff_math_deg:
  1873. |.ffunc_n math_rad
  1874. | lfd FARG2, CFUNC:RB->upvalue[0]
  1875. | fmul FARG1, FARG1, FARG2
  1876. | b ->fff_resn
  1877. |
  1878. |.if DUALNUM
  1879. |.ffunc math_ldexp
  1880. | cmplwi NARGS8:RC, 16
  1881. | lwz CARG3, 0(BASE)
  1882. | lfd FARG1, 0(BASE)
  1883. | lwz CARG4, 8(BASE)
  1884. |.if GPR64
  1885. | lwz CARG2, 12(BASE)
  1886. |.else
  1887. | lwz CARG1, 12(BASE)
  1888. |.endif
  1889. | blt ->fff_fallback
  1890. | checknum CARG3; bge ->fff_fallback
  1891. | checknum CARG4; bne ->fff_fallback
  1892. |.else
  1893. |.ffunc_nn math_ldexp
  1894. |.if GPR64
  1895. | toint CARG2, FARG2
  1896. |.else
  1897. | toint CARG1, FARG2
  1898. |.endif
  1899. |.endif
  1900. | blex ldexp
  1901. | b ->fff_resn
  1902. |
  1903. |.ffunc_n math_frexp
  1904. |.if GPR64
  1905. | la CARG2, DISPATCH_GL(tmptv)(DISPATCH)
  1906. |.else
  1907. | la CARG1, DISPATCH_GL(tmptv)(DISPATCH)
  1908. |.endif
  1909. | lwz PC, FRAME_PC(BASE)
  1910. | blex frexp
  1911. | lwz TMP1, DISPATCH_GL(tmptv)(DISPATCH)
  1912. | la RA, -8(BASE)
  1913. |.if not DUALNUM
  1914. | tonum_i FARG2, TMP1
  1915. |.endif
  1916. | stfd FARG1, 0(RA)
  1917. | li RD, (2+1)*8
  1918. |.if DUALNUM
  1919. | stw TISNUM, 8(RA)
  1920. | stw TMP1, 12(RA)
  1921. |.else
  1922. | stfd FARG2, 8(RA)
  1923. |.endif
  1924. | b ->fff_res
  1925. |
  1926. |.ffunc_n math_modf
  1927. |.if GPR64
  1928. | la CARG2, -8(BASE)
  1929. |.else
  1930. | la CARG1, -8(BASE)
  1931. |.endif
  1932. | lwz PC, FRAME_PC(BASE)
  1933. | blex modf
  1934. | la RA, -8(BASE)
  1935. | stfd FARG1, 0(BASE)
  1936. | li RD, (2+1)*8
  1937. | b ->fff_res
  1938. |
  1939. |.macro math_minmax, name, ismax
  1940. |.if DUALNUM
  1941. | .ffunc_1 name
  1942. | checknum CARG3
  1943. | addi TMP1, BASE, 8
  1944. | add TMP2, BASE, NARGS8:RC
  1945. | bne >4
  1946. |1: // Handle integers.
  1947. | lwz CARG4, 0(TMP1)
  1948. | cmplw cr1, TMP1, TMP2
  1949. | lwz CARG2, 4(TMP1)
  1950. | bge cr1, ->fff_resi
  1951. | checknum CARG4
  1952. | xoris TMP0, CARG1, 0x8000
  1953. | xoris TMP3, CARG2, 0x8000
  1954. | bne >3
  1955. | subfc TMP3, TMP3, TMP0
  1956. | subfe TMP0, TMP0, TMP0
  1957. |.if ismax
  1958. | andc TMP3, TMP3, TMP0
  1959. |.else
  1960. | and TMP3, TMP3, TMP0
  1961. |.endif
  1962. | add CARG1, TMP3, CARG2
  1963. |.if GPR64
  1964. | rldicl CARG1, CARG1, 0, 32
  1965. |.endif
  1966. | addi TMP1, TMP1, 8
  1967. | b <1
  1968. |3:
  1969. | bge ->fff_fallback
  1970. | // Convert intermediate result to number and continue below.
  1971. | tonum_i FARG1, CARG1
  1972. | lfd FARG2, 0(TMP1)
  1973. | b >6
  1974. |4:
  1975. | lfd FARG1, 0(BASE)
  1976. | bge ->fff_fallback
  1977. |5: // Handle numbers.
  1978. | lwz CARG4, 0(TMP1)
  1979. | cmplw cr1, TMP1, TMP2
  1980. | lfd FARG2, 0(TMP1)
  1981. | bge cr1, ->fff_resn
  1982. | checknum CARG4; bge >7
  1983. |6:
  1984. | fsub f0, FARG1, FARG2
  1985. | addi TMP1, TMP1, 8
  1986. |.if ismax
  1987. | fsel FARG1, f0, FARG1, FARG2
  1988. |.else
  1989. | fsel FARG1, f0, FARG2, FARG1
  1990. |.endif
  1991. | b <5
  1992. |7: // Convert integer to number and continue above.
  1993. | lwz CARG2, 4(TMP1)
  1994. | bne ->fff_fallback
  1995. | tonum_i FARG2, CARG2
  1996. | b <6
  1997. |.else
  1998. | .ffunc_n name
  1999. | li TMP1, 8
  2000. |1:
  2001. | lwzx CARG2, BASE, TMP1
  2002. | lfdx FARG2, BASE, TMP1
  2003. | cmplw cr1, TMP1, NARGS8:RC
  2004. | checknum CARG2
  2005. | bge cr1, ->fff_resn
  2006. | bge ->fff_fallback
  2007. | fsub f0, FARG1, FARG2
  2008. | addi TMP1, TMP1, 8
  2009. |.if ismax
  2010. | fsel FARG1, f0, FARG1, FARG2
  2011. |.else
  2012. | fsel FARG1, f0, FARG2, FARG1
  2013. |.endif
  2014. | b <1
  2015. |.endif
  2016. |.endmacro
  2017. |
  2018. | math_minmax math_min, 0
  2019. | math_minmax math_max, 1
  2020. |
  2021. |//-- String library -----------------------------------------------------
  2022. |
  2023. |.ffunc_1 string_len
  2024. | checkstr CARG3; bne ->fff_fallback
  2025. | lwz CRET1, STR:CARG1->len
  2026. | b ->fff_resi
  2027. |
  2028. |.ffunc string_byte // Only handle the 1-arg case here.
  2029. | cmplwi NARGS8:RC, 8
  2030. | lwz CARG3, 0(BASE)
  2031. | lwz STR:CARG1, 4(BASE)
  2032. | bne ->fff_fallback // Need exactly 1 argument.
  2033. | checkstr CARG3
  2034. | bne ->fff_fallback
  2035. | lwz TMP0, STR:CARG1->len
  2036. |.if DUALNUM
  2037. | lbz CARG1, STR:CARG1[1] // Access is always ok (NUL at end).
  2038. | li RD, (0+1)*8
  2039. | lwz PC, FRAME_PC(BASE)
  2040. | cmplwi TMP0, 0
  2041. | la RA, -8(BASE)
  2042. | beqy ->fff_res
  2043. | b ->fff_resi
  2044. |.else
  2045. | lbz TMP1, STR:CARG1[1] // Access is always ok (NUL at end).
  2046. | addic TMP3, TMP0, -1 // RD = ((str->len != 0)+1)*8
  2047. | subfe RD, TMP3, TMP0
  2048. | stw TMP1, TONUM_LO // Inlined tonum_u f0, TMP1.
  2049. | addi RD, RD, 1
  2050. | lfd f0, TONUM_D
  2051. | la RA, -8(BASE)
  2052. | lwz PC, FRAME_PC(BASE)
  2053. | fsub f0, f0, TOBIT
  2054. | slwi RD, RD, 3
  2055. | stfd f0, 0(RA)
  2056. | b ->fff_res
  2057. |.endif
  2058. |
  2059. |.ffunc string_char // Only handle the 1-arg case here.
  2060. | ffgccheck
  2061. | cmplwi NARGS8:RC, 8
  2062. | lwz CARG3, 0(BASE)
  2063. |.if DUALNUM
  2064. | lwz TMP0, 4(BASE)
  2065. | bne ->fff_fallback // Exactly 1 argument.
  2066. | checknum CARG3; bne ->fff_fallback
  2067. | la CARG2, 7(BASE)
  2068. |.else
  2069. | lfd FARG1, 0(BASE)
  2070. | bne ->fff_fallback // Exactly 1 argument.
  2071. | checknum CARG3; bge ->fff_fallback
  2072. | toint TMP0, FARG1
  2073. | la CARG2, TMPD_BLO
  2074. |.endif
  2075. | li CARG3, 1
  2076. | cmplwi TMP0, 255; bgt ->fff_fallback
  2077. |->fff_newstr:
  2078. | mr CARG1, L
  2079. | stp BASE, L->base
  2080. | stw PC, SAVE_PC
  2081. | bl extern lj_str_new // (lua_State *L, char *str, size_t l)
  2082. | // Returns GCstr *.
  2083. | lp BASE, L->base
  2084. | li CARG3, LJ_TSTR
  2085. | b ->fff_restv
  2086. |
  2087. |.ffunc string_sub
  2088. | ffgccheck
  2089. | cmplwi NARGS8:RC, 16
  2090. | lwz CARG3, 16(BASE)
  2091. |.if not DUALNUM
  2092. | lfd f0, 16(BASE)
  2093. |.endif
  2094. | lwz TMP0, 0(BASE)
  2095. | lwz STR:CARG1, 4(BASE)
  2096. | blt ->fff_fallback
  2097. | lwz CARG2, 8(BASE)
  2098. |.if DUALNUM
  2099. | lwz TMP1, 12(BASE)
  2100. |.else
  2101. | lfd f1, 8(BASE)
  2102. |.endif
  2103. | li TMP2, -1
  2104. | beq >1
  2105. |.if DUALNUM
  2106. | checknum CARG3
  2107. | lwz TMP2, 20(BASE)
  2108. | bne ->fff_fallback
  2109. |1:
  2110. | checknum CARG2; bne ->fff_fallback
  2111. |.else
  2112. | checknum CARG3; bge ->fff_fallback
  2113. | toint TMP2, f0
  2114. |1:
  2115. | checknum CARG2; bge ->fff_fallback
  2116. |.endif
  2117. | checkstr TMP0; bne ->fff_fallback
  2118. |.if not DUALNUM
  2119. | toint TMP1, f1
  2120. |.endif
  2121. | lwz TMP0, STR:CARG1->len
  2122. | cmplw TMP0, TMP2 // len < end? (unsigned compare)
  2123. | addi TMP3, TMP2, 1
  2124. | blt >5
  2125. |2:
  2126. | cmpwi TMP1, 0 // start <= 0?
  2127. | add TMP3, TMP1, TMP0
  2128. | ble >7
  2129. |3:
  2130. | sub CARG3, TMP2, TMP1
  2131. | addi CARG2, STR:CARG1, #STR-1
  2132. | srawi TMP0, CARG3, 31
  2133. | addi CARG3, CARG3, 1
  2134. | add CARG2, CARG2, TMP1
  2135. | andc CARG3, CARG3, TMP0
  2136. |.if GPR64
  2137. | rldicl CARG2, CARG2, 0, 32
  2138. | rldicl CARG3, CARG3, 0, 32
  2139. |.endif
  2140. | b ->fff_newstr
  2141. |
  2142. |5: // Negative end or overflow.
  2143. | cmpw TMP0, TMP2 // len >= end? (signed compare)
  2144. | add TMP2, TMP0, TMP3 // Negative end: end = end+len+1.
  2145. | bge <2
  2146. | mr TMP2, TMP0 // Overflow: end = len.
  2147. | b <2
  2148. |
  2149. |7: // Negative start or underflow.
  2150. | .gpr64 extsw TMP1, TMP1
  2151. | addic CARG3, TMP1, -1
  2152. | subfe CARG3, CARG3, CARG3
  2153. | srawi CARG2, TMP3, 31 // Note: modifies carry.
  2154. | andc TMP3, TMP3, CARG3
  2155. | andc TMP1, TMP3, CARG2
  2156. | addi TMP1, TMP1, 1 // start = 1 + (start ? start+len : 0)
  2157. | b <3
  2158. |
  2159. |.ffunc string_rep // Only handle the 1-char case inline.
  2160. | ffgccheck
  2161. | cmplwi NARGS8:RC, 16
  2162. | lwz TMP0, 0(BASE)
  2163. | lwz STR:CARG1, 4(BASE)
  2164. | lwz CARG4, 8(BASE)
  2165. |.if DUALNUM
  2166. | lwz CARG3, 12(BASE)
  2167. |.else
  2168. | lfd FARG2, 8(BASE)
  2169. |.endif
  2170. | bne ->fff_fallback // Exactly 2 arguments.
  2171. | checkstr TMP0; bne ->fff_fallback
  2172. |.if DUALNUM
  2173. | checknum CARG4; bne ->fff_fallback
  2174. |.else
  2175. | checknum CARG4; bge ->fff_fallback
  2176. | toint CARG3, FARG2
  2177. |.endif
  2178. | lwz TMP0, STR:CARG1->len
  2179. | cmpwi CARG3, 0
  2180. | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
  2181. | ble >2 // Count <= 0? (or non-int)
  2182. | cmplwi TMP0, 1
  2183. | subi TMP2, CARG3, 1
  2184. | blt >2 // Zero length string?
  2185. | cmplw cr1, TMP1, CARG3
  2186. | bne ->fff_fallback // Fallback for > 1-char strings.
  2187. | lbz TMP0, STR:CARG1[1]
  2188. | lp CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
  2189. | blt cr1, ->fff_fallback
  2190. |1: // Fill buffer with char. Yes, this is suboptimal code (do you care?).
  2191. | cmplwi TMP2, 0
  2192. | stbx TMP0, CARG2, TMP2
  2193. | subi TMP2, TMP2, 1
  2194. | bne <1
  2195. | b ->fff_newstr
  2196. |2: // Return empty string.
  2197. | la STR:CARG1, DISPATCH_GL(strempty)(DISPATCH)
  2198. | li CARG3, LJ_TSTR
  2199. | b ->fff_restv
  2200. |
  2201. |.ffunc string_reverse
  2202. | ffgccheck
  2203. | cmplwi NARGS8:RC, 8
  2204. | lwz CARG3, 0(BASE)
  2205. | lwz STR:CARG1, 4(BASE)
  2206. | blt ->fff_fallback
  2207. | checkstr CARG3
  2208. | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
  2209. | bne ->fff_fallback
  2210. | lwz CARG3, STR:CARG1->len
  2211. | la CARG1, #STR(STR:CARG1)
  2212. | lp CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
  2213. | li TMP2, 0
  2214. | cmplw TMP1, CARG3
  2215. | subi TMP3, CARG3, 1
  2216. | blt ->fff_fallback
  2217. |1: // Reverse string copy.
  2218. | cmpwi TMP3, 0
  2219. | lbzx TMP1, CARG1, TMP2
  2220. | blty ->fff_newstr
  2221. | stbx TMP1, CARG2, TMP3
  2222. | subi TMP3, TMP3, 1
  2223. | addi TMP2, TMP2, 1
  2224. | b <1
  2225. |
  2226. |.macro ffstring_case, name, lo
  2227. | .ffunc name
  2228. | ffgccheck
  2229. | cmplwi NARGS8:RC, 8
  2230. | lwz CARG3, 0(BASE)
  2231. | lwz STR:CARG1, 4(BASE)
  2232. | blt ->fff_fallback
  2233. | checkstr CARG3
  2234. | lwz TMP1, DISPATCH_GL(tmpbuf.sz)(DISPATCH)
  2235. | bne ->fff_fallback
  2236. | lwz CARG3, STR:CARG1->len
  2237. | la CARG1, #STR(STR:CARG1)
  2238. | lp CARG2, DISPATCH_GL(tmpbuf.buf)(DISPATCH)
  2239. | cmplw TMP1, CARG3
  2240. | li TMP2, 0
  2241. | blt ->fff_fallback
  2242. |1: // ASCII case conversion.
  2243. | cmplw TMP2, CARG3
  2244. | lbzx TMP1, CARG1, TMP2
  2245. | bgey ->fff_newstr
  2246. | subi TMP0, TMP1, lo
  2247. | xori TMP3, TMP1, 0x20
  2248. | addic TMP0, TMP0, -26
  2249. | subfe TMP3, TMP3, TMP3
  2250. | rlwinm TMP3, TMP3, 0, 26, 26 // x &= 0x20.
  2251. | xor TMP1, TMP1, TMP3
  2252. | stbx TMP1, CARG2, TMP2
  2253. | addi TMP2, TMP2, 1
  2254. | b <1
  2255. |.endmacro
  2256. |
  2257. |ffstring_case string_lower, 65
  2258. |ffstring_case string_upper, 97
  2259. |
  2260. |//-- Table library ------------------------------------------------------
  2261. |
  2262. |.ffunc_1 table_getn
  2263. | checktab CARG3; bne ->fff_fallback
  2264. | bl extern lj_tab_len // (GCtab *t)
  2265. | // Returns uint32_t (but less than 2^31).
  2266. | b ->fff_resi
  2267. |
  2268. |//-- Bit library --------------------------------------------------------
  2269. |
  2270. |.macro .ffunc_bit, name
  2271. |.if DUALNUM
  2272. | .ffunc_1 bit_..name
  2273. | checknum CARG3; bnel ->fff_tobit_fb
  2274. |.else
  2275. | .ffunc_n bit_..name
  2276. | fadd FARG1, FARG1, TOBIT
  2277. | stfd FARG1, TMPD
  2278. | lwz CARG1, TMPD_LO
  2279. |.endif
  2280. |.endmacro
  2281. |
  2282. |.macro .ffunc_bit_op, name, ins
  2283. | .ffunc_bit name
  2284. | addi TMP1, BASE, 8
  2285. | add TMP2, BASE, NARGS8:RC
  2286. |1:
  2287. | lwz CARG4, 0(TMP1)
  2288. | cmplw cr1, TMP1, TMP2
  2289. |.if DUALNUM
  2290. | lwz CARG2, 4(TMP1)
  2291. |.else
  2292. | lfd FARG1, 0(TMP1)
  2293. |.endif
  2294. | bgey cr1, ->fff_resi
  2295. | checknum CARG4
  2296. |.if DUALNUM
  2297. | bnel ->fff_bitop_fb
  2298. |.else
  2299. | fadd FARG1, FARG1, TOBIT
  2300. | bge ->fff_fallback
  2301. | stfd FARG1, TMPD
  2302. | lwz CARG2, TMPD_LO
  2303. |.endif
  2304. | ins CARG1, CARG1, CARG2
  2305. | addi TMP1, TMP1, 8
  2306. | b <1
  2307. |.endmacro
  2308. |
  2309. |.ffunc_bit_op band, and
  2310. |.ffunc_bit_op bor, or
  2311. |.ffunc_bit_op bxor, xor
  2312. |
  2313. |.ffunc_bit bswap
  2314. | rotlwi TMP0, CARG1, 8
  2315. | rlwimi TMP0, CARG1, 24, 0, 7
  2316. | rlwimi TMP0, CARG1, 24, 16, 23
  2317. | mr CRET1, TMP0
  2318. | b ->fff_resi
  2319. |
  2320. |.ffunc_bit bnot
  2321. | not CRET1, CARG1
  2322. | b ->fff_resi
  2323. |
  2324. |.macro .ffunc_bit_sh, name, ins, shmod
  2325. |.if DUALNUM
  2326. | .ffunc_2 bit_..name
  2327. | checknum CARG3; bnel ->fff_tobit_fb
  2328. | // Note: no inline conversion from number for 2nd argument!
  2329. | checknum CARG4; bne ->fff_fallback
  2330. |.else
  2331. | .ffunc_nn bit_..name
  2332. | fadd FARG1, FARG1, TOBIT
  2333. | fadd FARG2, FARG2, TOBIT
  2334. | stfd FARG1, TMPD
  2335. | lwz CARG1, TMPD_LO
  2336. | stfd FARG2, TMPD
  2337. | lwz CARG2, TMPD_LO
  2338. |.endif
  2339. |.if shmod == 1
  2340. | rlwinm CARG2, CARG2, 0, 27, 31
  2341. |.elif shmod == 2
  2342. | neg CARG2, CARG2
  2343. |.endif
  2344. | ins CRET1, CARG1, CARG2
  2345. | b ->fff_resi
  2346. |.endmacro
  2347. |
  2348. |.ffunc_bit_sh lshift, slw, 1
  2349. |.ffunc_bit_sh rshift, srw, 1
  2350. |.ffunc_bit_sh arshift, sraw, 1
  2351. |.ffunc_bit_sh rol, rotlw, 0
  2352. |.ffunc_bit_sh ror, rotlw, 2
  2353. |
  2354. |.ffunc_bit tobit
  2355. |.if DUALNUM
  2356. | b ->fff_resi
  2357. |.else
  2358. |->fff_resi:
  2359. | tonum_i FARG1, CRET1
  2360. |.endif
  2361. |->fff_resn:
  2362. | lwz PC, FRAME_PC(BASE)
  2363. | la RA, -8(BASE)
  2364. | stfd FARG1, -8(BASE)
  2365. | b ->fff_res1
  2366. |
  2367. |// Fallback FP number to bit conversion.
  2368. |->fff_tobit_fb:
  2369. |.if DUALNUM
  2370. | lfd FARG1, 0(BASE)
  2371. | bgt ->fff_fallback
  2372. | fadd FARG1, FARG1, TOBIT
  2373. | stfd FARG1, TMPD
  2374. | lwz CARG1, TMPD_LO
  2375. | blr
  2376. |.endif
  2377. |->fff_bitop_fb:
  2378. |.if DUALNUM
  2379. | lfd FARG1, 0(TMP1)
  2380. | bgt ->fff_fallback
  2381. | fadd FARG1, FARG1, TOBIT
  2382. | stfd FARG1, TMPD
  2383. | lwz CARG2, TMPD_LO
  2384. | blr
  2385. |.endif
  2386. |
  2387. |//-----------------------------------------------------------------------
  2388. |
  2389. |->fff_fallback: // Call fast function fallback handler.
  2390. | // BASE = new base, RB = CFUNC, RC = nargs*8
  2391. | lp TMP3, CFUNC:RB->f
  2392. | add TMP1, BASE, NARGS8:RC
  2393. | lwz PC, FRAME_PC(BASE) // Fallback may overwrite PC.
  2394. | addi TMP0, TMP1, 8*LUA_MINSTACK
  2395. | lwz TMP2, L->maxstack
  2396. | stw PC, SAVE_PC // Redundant (but a defined value).
  2397. | .toc lp TMP3, 0(TMP3)
  2398. | cmplw TMP0, TMP2
  2399. | stp BASE, L->base
  2400. | stp TMP1, L->top
  2401. | mr CARG1, L
  2402. | bgt >5 // Need to grow stack.
  2403. | mtctr TMP3
  2404. | bctrl // (lua_State *L)
  2405. | // Either throws an error, or recovers and returns -1, 0 or nresults+1.
  2406. | lp BASE, L->base
  2407. | cmpwi CRET1, 0
  2408. | slwi RD, CRET1, 3
  2409. | la RA, -8(BASE)
  2410. | bgt ->fff_res // Returned nresults+1?
  2411. |1: // Returned 0 or -1: retry fast path.
  2412. | lp TMP0, L->top
  2413. | lwz LFUNC:RB, FRAME_FUNC(BASE)
  2414. | sub NARGS8:RC, TMP0, BASE
  2415. | bne ->vm_call_tail // Returned -1?
  2416. | ins_callt // Returned 0: retry fast path.
  2417. |
  2418. |// Reconstruct previous base for vmeta_call during tailcall.
  2419. |->vm_call_tail:
  2420. | andix. TMP0, PC, FRAME_TYPE
  2421. | rlwinm TMP1, PC, 0, 0, 28
  2422. | bne >3
  2423. | lwz INS, -4(PC)
  2424. | decode_RA8 TMP1, INS
  2425. | addi TMP1, TMP1, 8
  2426. |3:
  2427. | sub TMP2, BASE, TMP1
  2428. | b ->vm_call_dispatch // Resolve again for tailcall.
  2429. |
  2430. |5: // Grow stack for fallback handler.
  2431. | li CARG2, LUA_MINSTACK
  2432. | bl extern lj_state_growstack // (lua_State *L, int n)
  2433. | lp BASE, L->base
  2434. | cmpw TMP0, TMP0 // Set 4*cr0+eq to force retry.
  2435. | b <1
  2436. |
  2437. |->fff_gcstep: // Call GC step function.
  2438. | // BASE = new base, RC = nargs*8
  2439. | mflr SAVE0
  2440. | stp BASE, L->base
  2441. | add TMP0, BASE, NARGS8:RC
  2442. | stw PC, SAVE_PC // Redundant (but a defined value).
  2443. | stp TMP0, L->top
  2444. | mr CARG1, L
  2445. | bl extern lj_gc_step // (lua_State *L)
  2446. | lp BASE, L->base
  2447. | mtlr SAVE0
  2448. | lp TMP0, L->top
  2449. | sub NARGS8:RC, TMP0, BASE
  2450. | lwz CFUNC:RB, FRAME_FUNC(BASE)
  2451. | blr
  2452. |
  2453. |//-----------------------------------------------------------------------
  2454. |//-- Special dispatch targets -------------------------------------------
  2455. |//-----------------------------------------------------------------------
  2456. |
  2457. |->vm_record: // Dispatch target for recording phase.
  2458. |.if JIT
  2459. | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH)
  2460. | andix. TMP0, TMP3, HOOK_VMEVENT // No recording while in vmevent.
  2461. | bne >5
  2462. | // Decrement the hookcount for consistency, but always do the call.
  2463. | lwz TMP2, DISPATCH_GL(hookcount)(DISPATCH)
  2464. | andix. TMP0, TMP3, HOOK_ACTIVE
  2465. | bne >1
  2466. | subi TMP2, TMP2, 1
  2467. | andi. TMP0, TMP3, LUA_MASKLINE|LUA_MASKCOUNT
  2468. | beqy >1
  2469. | stw TMP2, DISPATCH_GL(hookcount)(DISPATCH)
  2470. | b >1
  2471. |.endif
  2472. |
  2473. |->vm_rethook: // Dispatch target for return hooks.
  2474. | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH)
  2475. | andix. TMP0, TMP3, HOOK_ACTIVE // Hook already active?
  2476. | beq >1
  2477. |5: // Re-dispatch to static ins.
  2478. | addi TMP1, TMP1, GG_DISP2STATIC // Assumes decode_OPP TMP1, INS.
  2479. | lpx TMP0, DISPATCH, TMP1
  2480. | mtctr TMP0
  2481. | bctr
  2482. |
  2483. |->vm_inshook: // Dispatch target for instr/line hooks.
  2484. | lbz TMP3, DISPATCH_GL(hookmask)(DISPATCH)
  2485. | lwz TMP2, DISPATCH_GL(hookcount)(DISPATCH)
  2486. | andix. TMP0, TMP3, HOOK_ACTIVE // Hook already active?
  2487. | rlwinm TMP0, TMP3, 31-LUA_HOOKLINE, 31, 0
  2488. | bne <5
  2489. |
  2490. | cmpwi cr1, TMP0, 0
  2491. | addic. TMP2, TMP2, -1
  2492. | beq cr1, <5
  2493. | stw TMP2, DISPATCH_GL(hookcount)(DISPATCH)
  2494. | beq >1
  2495. | bge cr1, <5
  2496. |1:
  2497. | mr CARG1, L
  2498. | stw MULTRES, SAVE_MULTRES
  2499. | mr CARG2, PC
  2500. | stp BASE, L->base
  2501. | // SAVE_PC must hold the _previous_ PC. The callee updates it with PC.
  2502. | bl extern lj_dispatch_ins // (lua_State *L, const BCIns *pc)
  2503. |3:
  2504. | lp BASE, L->base
  2505. |4: // Re-dispatch to static ins.
  2506. | lwz INS, -4(PC)
  2507. | decode_OPP TMP1, INS
  2508. | decode_RB8 RB, INS
  2509. | addi TMP1, TMP1, GG_DISP2STATIC
  2510. | decode_RD8 RD, INS
  2511. | lpx TMP0, DISPATCH, TMP1
  2512. | decode_RA8 RA, INS
  2513. | decode_RC8 RC, INS
  2514. | mtctr TMP0
  2515. | bctr
  2516. |
  2517. |->cont_hook: // Continue from hook yield.
  2518. | addi PC, PC, 4
  2519. | lwz MULTRES, -20(RB) // Restore MULTRES for *M ins.
  2520. | b <4
  2521. |
  2522. |->vm_hotloop: // Hot loop counter underflow.
  2523. |.if JIT
  2524. | lwz LFUNC:TMP1, FRAME_FUNC(BASE)
  2525. | addi CARG1, DISPATCH, GG_DISP2J
  2526. | stw PC, SAVE_PC
  2527. | lwz TMP1, LFUNC:TMP1->pc
  2528. | mr CARG2, PC
  2529. | stw L, DISPATCH_J(L)(DISPATCH)
  2530. | lbz TMP1, PC2PROTO(framesize)(TMP1)
  2531. | stp BASE, L->base
  2532. | slwi TMP1, TMP1, 3
  2533. | add TMP1, BASE, TMP1
  2534. | stp TMP1, L->top
  2535. | bl extern lj_trace_hot // (jit_State *J, const BCIns *pc)
  2536. | b <3
  2537. |.endif
  2538. |
  2539. |->vm_callhook: // Dispatch target for call hooks.
  2540. | mr CARG2, PC
  2541. |.if JIT
  2542. | b >1
  2543. |.endif
  2544. |
  2545. |->vm_hotcall: // Hot call counter underflow.
  2546. |.if JIT
  2547. | ori CARG2, PC, 1
  2548. |1:
  2549. |.endif
  2550. | add TMP0, BASE, RC
  2551. | stw PC, SAVE_PC
  2552. | mr CARG1, L
  2553. | stp BASE, L->base
  2554. | sub RA, RA, BASE
  2555. | stp TMP0, L->top
  2556. | bl extern lj_dispatch_call // (lua_State *L, const BCIns *pc)
  2557. | // Returns ASMFunction.
  2558. | lp BASE, L->base
  2559. | lp TMP0, L->top
  2560. | stw ZERO, SAVE_PC // Invalidate for subsequent line hook.
  2561. | sub NARGS8:RC, TMP0, BASE
  2562. | add RA, BASE, RA
  2563. | lwz LFUNC:RB, FRAME_FUNC(BASE)
  2564. | lwz INS, -4(PC)
  2565. | mtctr CRET1
  2566. | bctr
  2567. |
  2568. |//-----------------------------------------------------------------------
  2569. |//-- Trace exit handler -------------------------------------------------
  2570. |//-----------------------------------------------------------------------
  2571. |
  2572. |.macro savex_, a, b, c, d
  2573. | stfd f..a, 16+a*8(sp)
  2574. | stfd f..b, 16+b*8(sp)
  2575. | stfd f..c, 16+c*8(sp)
  2576. | stfd f..d, 16+d*8(sp)
  2577. |.endmacro
  2578. |
  2579. |->vm_exit_handler:
  2580. |.if JIT
  2581. | addi sp, sp, -(16+32*8+32*4)
  2582. | stmw r2, 16+32*8+2*4(sp)
  2583. | addi DISPATCH, JGL, -GG_DISP2G-32768
  2584. | li CARG2, ~LJ_VMST_EXIT
  2585. | lwz CARG1, 16+32*8+32*4(sp) // Get stack chain.
  2586. | stw CARG2, DISPATCH_GL(vmstate)(DISPATCH)
  2587. | savex_ 0,1,2,3
  2588. | stw CARG1, 0(sp) // Store extended stack chain.
  2589. | mcrxr cr0 // Clear SO flag.
  2590. | savex_ 4,5,6,7
  2591. | addi CARG2, sp, 16+32*8+32*4 // Recompute original value of sp.
  2592. | savex_ 8,9,10,11
  2593. | stw CARG2, 16+32*8+1*4(sp) // Store sp in RID_SP.
  2594. | savex_ 12,13,14,15
  2595. | mflr CARG3
  2596. | li TMP1, 0
  2597. | savex_ 16,17,18,19
  2598. | stw TMP1, 16+32*8+0*4(sp) // Clear RID_TMP.
  2599. | savex_ 20,21,22,23
  2600. | lhz CARG4, 2(CARG3) // Load trace number.
  2601. | savex_ 24,25,26,27
  2602. | lwz L, DISPATCH_GL(jit_L)(DISPATCH)
  2603. | savex_ 28,29,30,31
  2604. | sub CARG3, TMP0, CARG3 // Compute exit number.
  2605. | lp BASE, DISPATCH_GL(jit_base)(DISPATCH)
  2606. | srwi CARG3, CARG3, 2
  2607. | stw L, DISPATCH_J(L)(DISPATCH)
  2608. | subi CARG3, CARG3, 2
  2609. | stw TMP1, DISPATCH_GL(jit_L)(DISPATCH)
  2610. | stw CARG4, DISPATCH_J(parent)(DISPATCH)
  2611. | stp BASE, L->base
  2612. | addi CARG1, DISPATCH, GG_DISP2J
  2613. | stw CARG3, DISPATCH_J(exitno)(DISPATCH)
  2614. | addi CARG2, sp, 16
  2615. | bl extern lj_trace_exit // (jit_State *J, ExitState *ex)
  2616. | // Returns MULTRES (unscaled) or negated error code.
  2617. | lp TMP1, L->cframe
  2618. | lwz TMP2, 0(sp)
  2619. | lp BASE, L->base
  2620. |.if GPR64
  2621. | rldicr sp, TMP1, 0, 61
  2622. |.else
  2623. | rlwinm sp, TMP1, 0, 0, 29
  2624. |.endif
  2625. | lwz PC, SAVE_PC // Get SAVE_PC.
  2626. | stw TMP2, 0(sp)
  2627. | stw L, SAVE_L // Set SAVE_L (on-trace resume/yield).
  2628. | b >1
  2629. |.endif
  2630. |->vm_exit_interp:
  2631. |.if JIT
  2632. | // CARG1 = MULTRES or negated error code, BASE, PC and JGL set.
  2633. | lwz L, SAVE_L
  2634. | addi DISPATCH, JGL, -GG_DISP2G-32768
  2635. |1:
  2636. | cmpwi CARG1, 0
  2637. | blt >3 // Check for error from exit.
  2638. | lwz LFUNC:TMP1, FRAME_FUNC(BASE)
  2639. | slwi MULTRES, CARG1, 3
  2640. | li TMP2, 0
  2641. | stw MULTRES, SAVE_MULTRES
  2642. | lwz TMP1, LFUNC:TMP1->pc
  2643. | stw TMP2, DISPATCH_GL(jit_L)(DISPATCH)
  2644. | lwz KBASE, PC2PROTO(k)(TMP1)
  2645. | // Setup type comparison constants.
  2646. | li TISNUM, LJ_TISNUM
  2647. | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
  2648. | stw TMP3, TMPD
  2649. | li ZERO, 0
  2650. | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float).
  2651. | lfs TOBIT, TMPD
  2652. | stw TMP3, TMPD
  2653. | lus TMP0, 0x4338 // Hiword of 2^52 + 2^51 (double)
  2654. | li TISNIL, LJ_TNIL
  2655. | stw TMP0, TONUM_HI
  2656. | lfs TONUM, TMPD
  2657. | // Modified copy of ins_next which handles function header dispatch, too.
  2658. | lwz INS, 0(PC)
  2659. | addi PC, PC, 4
  2660. | // Assumes TISNIL == ~LJ_VMST_INTERP == -1.
  2661. | stw TISNIL, DISPATCH_GL(vmstate)(DISPATCH)
  2662. | decode_OPP TMP1, INS
  2663. | decode_RA8 RA, INS
  2664. | lpx TMP0, DISPATCH, TMP1
  2665. | mtctr TMP0
  2666. | cmplwi TMP1, BC_FUNCF*4 // Function header?
  2667. | bge >2
  2668. | decode_RB8 RB, INS
  2669. | decode_RD8 RD, INS
  2670. | decode_RC8 RC, INS
  2671. | bctr
  2672. |2:
  2673. | subi RC, MULTRES, 8
  2674. | add RA, RA, BASE
  2675. | bctr
  2676. |
  2677. |3: // Rethrow error from the right C frame.
  2678. | neg CARG2, CARG1
  2679. | mr CARG1, L
  2680. | bl extern lj_err_throw // (lua_State *L, int errcode)
  2681. |.endif
  2682. |
  2683. |//-----------------------------------------------------------------------
  2684. |//-- Math helper functions ----------------------------------------------
  2685. |//-----------------------------------------------------------------------
  2686. |
  2687. |// NYI: Use internal implementations of floor, ceil, trunc.
  2688. |
  2689. |->vm_modi:
  2690. | divwo. TMP0, CARG1, CARG2
  2691. | bso >1
  2692. |.if GPR64
  2693. | xor CARG3, CARG1, CARG2
  2694. | cmpwi CARG3, 0
  2695. |.else
  2696. | xor. CARG3, CARG1, CARG2
  2697. |.endif
  2698. | mullw TMP0, TMP0, CARG2
  2699. | sub CARG1, CARG1, TMP0
  2700. | bgelr
  2701. | cmpwi CARG1, 0; beqlr
  2702. | add CARG1, CARG1, CARG2
  2703. | blr
  2704. |1:
  2705. | cmpwi CARG2, 0
  2706. | li CARG1, 0
  2707. | beqlr
  2708. | mcrxr cr0 // Clear SO for -2147483648 % -1 and return 0.
  2709. | blr
  2710. |
  2711. |//-----------------------------------------------------------------------
  2712. |//-- Miscellaneous functions --------------------------------------------
  2713. |//-----------------------------------------------------------------------
  2714. |
  2715. |// void lj_vm_cachesync(void *start, void *end)
  2716. |// Flush D-Cache and invalidate I-Cache. Assumes 32 byte cache line size.
  2717. |// This is a good lower bound, except for very ancient PPC models.
  2718. |->vm_cachesync:
  2719. |.if JIT or FFI
  2720. | // Compute start of first cache line and number of cache lines.
  2721. | rlwinm CARG1, CARG1, 0, 0, 26
  2722. | sub CARG2, CARG2, CARG1
  2723. | addi CARG2, CARG2, 31
  2724. | rlwinm. CARG2, CARG2, 27, 5, 31
  2725. | beqlr
  2726. | mtctr CARG2
  2727. | mr CARG3, CARG1
  2728. |1: // Flush D-Cache.
  2729. | dcbst r0, CARG1
  2730. | addi CARG1, CARG1, 32
  2731. | bdnz <1
  2732. | sync
  2733. | mtctr CARG2
  2734. |1: // Invalidate I-Cache.
  2735. | icbi r0, CARG3
  2736. | addi CARG3, CARG3, 32
  2737. | bdnz <1
  2738. | isync
  2739. | blr
  2740. |.endif
  2741. |
  2742. |//-----------------------------------------------------------------------
  2743. |//-- FFI helper functions -----------------------------------------------
  2744. |//-----------------------------------------------------------------------
  2745. |
  2746. |// Handler for callback functions. Callback slot number in r11, g in r12.
  2747. |->vm_ffi_callback:
  2748. |.if FFI
  2749. |.type CTSTATE, CTState, PC
  2750. | saveregs
  2751. | lwz CTSTATE, GL:r12->ctype_state
  2752. | addi DISPATCH, r12, GG_G2DISP
  2753. | stw r11, CTSTATE->cb.slot
  2754. | stw r3, CTSTATE->cb.gpr[0]
  2755. | stfd f1, CTSTATE->cb.fpr[0]
  2756. | stw r4, CTSTATE->cb.gpr[1]
  2757. | stfd f2, CTSTATE->cb.fpr[1]
  2758. | stw r5, CTSTATE->cb.gpr[2]
  2759. | stfd f3, CTSTATE->cb.fpr[2]
  2760. | stw r6, CTSTATE->cb.gpr[3]
  2761. | stfd f4, CTSTATE->cb.fpr[3]
  2762. | stw r7, CTSTATE->cb.gpr[4]
  2763. | stfd f5, CTSTATE->cb.fpr[4]
  2764. | stw r8, CTSTATE->cb.gpr[5]
  2765. | stfd f6, CTSTATE->cb.fpr[5]
  2766. | stw r9, CTSTATE->cb.gpr[6]
  2767. | stfd f7, CTSTATE->cb.fpr[6]
  2768. | stw r10, CTSTATE->cb.gpr[7]
  2769. | stfd f8, CTSTATE->cb.fpr[7]
  2770. | addi TMP0, sp, CFRAME_SPACE+8
  2771. | stw TMP0, CTSTATE->cb.stack
  2772. | mr CARG1, CTSTATE
  2773. | stw CTSTATE, SAVE_PC // Any value outside of bytecode is ok.
  2774. | mr CARG2, sp
  2775. | bl extern lj_ccallback_enter // (CTState *cts, void *cf)
  2776. | // Returns lua_State *.
  2777. | lp BASE, L:CRET1->base
  2778. | li TISNUM, LJ_TISNUM // Setup type comparison constants.
  2779. | lp RC, L:CRET1->top
  2780. | lus TMP3, 0x59c0 // TOBIT = 2^52 + 2^51 (float).
  2781. | li ZERO, 0
  2782. | mr L, CRET1
  2783. | stw TMP3, TMPD
  2784. | lus TMP0, 0x4338 // Hiword of 2^52 + 2^51 (double)
  2785. | lwz LFUNC:RB, FRAME_FUNC(BASE)
  2786. | ori TMP3, TMP3, 0x0004 // TONUM = 2^52 + 2^51 + 2^31 (float).
  2787. | stw TMP0, TONUM_HI
  2788. | li TISNIL, LJ_TNIL
  2789. | li_vmstate INTERP
  2790. | lfs TOBIT, TMPD
  2791. | stw TMP3, TMPD
  2792. | sub RC, RC, BASE
  2793. | st_vmstate
  2794. | lfs TONUM, TMPD
  2795. | ins_callt
  2796. |.endif
  2797. |
  2798. |->cont_ffi_callback: // Return from FFI callback.
  2799. |.if FFI
  2800. | lwz CTSTATE, DISPATCH_GL(ctype_state)(DISPATCH)
  2801. | stp BASE, L->base
  2802. | stp RB, L->top
  2803. | stp L, CTSTATE->L
  2804. | mr CARG1, CTSTATE
  2805. | mr CARG2, RA
  2806. | bl extern lj_ccallback_leave // (CTState *cts, TValue *o)
  2807. | lwz CRET1, CTSTATE->cb.gpr[0]
  2808. | lfd FARG1, CTSTATE->cb.fpr[0]
  2809. | lwz CRET2, CTSTATE->cb.gpr[1]
  2810. | b ->vm_leave_unw
  2811. |.endif
  2812. |
  2813. |->vm_ffi_call: // Call C function via FFI.
  2814. | // Caveat: needs special frame unwinding, see below.
  2815. |.if FFI
  2816. | .type CCSTATE, CCallState, CARG1
  2817. | lwz TMP1, CCSTATE->spadj
  2818. | mflr TMP0
  2819. | lbz CARG2, CCSTATE->nsp
  2820. | lbz CARG3, CCSTATE->nfpr
  2821. | neg TMP1, TMP1
  2822. | stw TMP0, 4(sp)
  2823. | cmpwi cr1, CARG3, 0
  2824. | mr TMP2, sp
  2825. | addic. CARG2, CARG2, -1
  2826. | stwux sp, sp, TMP1
  2827. | crnot 4*cr1+eq, 4*cr1+eq // For vararg calls.
  2828. | stw r14, -4(TMP2)
  2829. | stw CCSTATE, -8(TMP2)
  2830. | mr r14, TMP2
  2831. | la TMP1, CCSTATE->stack
  2832. | slwi CARG2, CARG2, 2
  2833. | blty >2
  2834. | la TMP2, 8(sp)
  2835. |1:
  2836. | lwzx TMP0, TMP1, CARG2
  2837. | stwx TMP0, TMP2, CARG2
  2838. | addic. CARG2, CARG2, -4
  2839. | bge <1
  2840. |2:
  2841. | bney cr1, >3
  2842. | lfd f1, CCSTATE->fpr[0]
  2843. | lfd f2, CCSTATE->fpr[1]
  2844. | lfd f3, CCSTATE->fpr[2]
  2845. | lfd f4, CCSTATE->fpr[3]
  2846. | lfd f5, CCSTATE->fpr[4]
  2847. | lfd f6, CCSTATE->fpr[5]
  2848. | lfd f7, CCSTATE->fpr[6]
  2849. | lfd f8, CCSTATE->fpr[7]
  2850. |3:
  2851. | lp TMP0, CCSTATE->func
  2852. | lwz CARG2, CCSTATE->gpr[1]
  2853. | lwz CARG3, CCSTATE->gpr[2]
  2854. | lwz CARG4, CCSTATE->gpr[3]
  2855. | lwz CARG5, CCSTATE->gpr[4]
  2856. | mtctr TMP0
  2857. | lwz r8, CCSTATE->gpr[5]
  2858. | lwz r9, CCSTATE->gpr[6]
  2859. | lwz r10, CCSTATE->gpr[7]
  2860. | lwz CARG1, CCSTATE->gpr[0] // Do this last, since CCSTATE is CARG1.
  2861. | bctrl
  2862. | lwz CCSTATE:TMP1, -8(r14)
  2863. | lwz TMP2, -4(r14)
  2864. | lwz TMP0, 4(r14)
  2865. | stw CARG1, CCSTATE:TMP1->gpr[0]
  2866. | stfd FARG1, CCSTATE:TMP1->fpr[0]
  2867. | stw CARG2, CCSTATE:TMP1->gpr[1]
  2868. | mtlr TMP0
  2869. | stw CARG3, CCSTATE:TMP1->gpr[2]
  2870. | mr sp, r14
  2871. | stw CARG4, CCSTATE:TMP1->gpr[3]
  2872. | mr r14, TMP2
  2873. | blr
  2874. |.endif
  2875. |// Note: vm_ffi_call must be the last function in this object file!
  2876. |
  2877. |//-----------------------------------------------------------------------
  2878. }
  2879. /* Generate the code for a single instruction. */
  2880. static void build_ins(BuildCtx *ctx, BCOp op, int defop)
  2881. {
  2882. int vk = 0;
  2883. |=>defop:
  2884. switch (op) {
  2885. /* -- Comparison ops ---------------------------------------------------- */
  2886. /* Remember: all ops branch for a true comparison, fall through otherwise. */
  2887. case BC_ISLT: case BC_ISGE: case BC_ISLE: case BC_ISGT:
  2888. | // RA = src1*8, RD = src2*8, JMP with RD = target
  2889. |.if DUALNUM
  2890. | lwzux TMP0, RA, BASE
  2891. | addi PC, PC, 4
  2892. | lwz CARG2, 4(RA)
  2893. | lwzux TMP1, RD, BASE
  2894. | lwz TMP2, -4(PC)
  2895. | checknum cr0, TMP0
  2896. | lwz CARG3, 4(RD)
  2897. | decode_RD4 TMP2, TMP2
  2898. | checknum cr1, TMP1
  2899. | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
  2900. | bne cr0, >7
  2901. | bne cr1, >8
  2902. | cmpw CARG2, CARG3
  2903. if (op == BC_ISLT) {
  2904. | bge >2
  2905. } else if (op == BC_ISGE) {
  2906. | blt >2
  2907. } else if (op == BC_ISLE) {
  2908. | bgt >2
  2909. } else {
  2910. | ble >2
  2911. }
  2912. |1:
  2913. | add PC, PC, TMP2
  2914. |2:
  2915. | ins_next
  2916. |
  2917. |7: // RA is not an integer.
  2918. | bgt cr0, ->vmeta_comp
  2919. | // RA is a number.
  2920. | lfd f0, 0(RA)
  2921. | bgt cr1, ->vmeta_comp
  2922. | blt cr1, >4
  2923. | // RA is a number, RD is an integer.
  2924. | tonum_i f1, CARG3
  2925. | b >5
  2926. |
  2927. |8: // RA is an integer, RD is not an integer.
  2928. | bgt cr1, ->vmeta_comp
  2929. | // RA is an integer, RD is a number.
  2930. | tonum_i f0, CARG2
  2931. |4:
  2932. | lfd f1, 0(RD)
  2933. |5:
  2934. | fcmpu cr0, f0, f1
  2935. if (op == BC_ISLT) {
  2936. | bge <2
  2937. } else if (op == BC_ISGE) {
  2938. | blt <2
  2939. } else if (op == BC_ISLE) {
  2940. | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq
  2941. | bge <2
  2942. } else {
  2943. | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq
  2944. | blt <2
  2945. }
  2946. | b <1
  2947. |.else
  2948. | lwzx TMP0, BASE, RA
  2949. | addi PC, PC, 4
  2950. | lfdx f0, BASE, RA
  2951. | lwzx TMP1, BASE, RD
  2952. | checknum cr0, TMP0
  2953. | lwz TMP2, -4(PC)
  2954. | lfdx f1, BASE, RD
  2955. | checknum cr1, TMP1
  2956. | decode_RD4 TMP2, TMP2
  2957. | bge cr0, ->vmeta_comp
  2958. | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
  2959. | bge cr1, ->vmeta_comp
  2960. | fcmpu cr0, f0, f1
  2961. if (op == BC_ISLT) {
  2962. | bge >1
  2963. } else if (op == BC_ISGE) {
  2964. | blt >1
  2965. } else if (op == BC_ISLE) {
  2966. | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq
  2967. | bge >1
  2968. } else {
  2969. | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+eq
  2970. | blt >1
  2971. }
  2972. | add PC, PC, TMP2
  2973. |1:
  2974. | ins_next
  2975. |.endif
  2976. break;
  2977. case BC_ISEQV: case BC_ISNEV:
  2978. vk = op == BC_ISEQV;
  2979. | // RA = src1*8, RD = src2*8, JMP with RD = target
  2980. |.if DUALNUM
  2981. | lwzux TMP0, RA, BASE
  2982. | addi PC, PC, 4
  2983. | lwz CARG2, 4(RA)
  2984. | lwzux TMP1, RD, BASE
  2985. | checknum cr0, TMP0
  2986. | lwz TMP2, -4(PC)
  2987. | checknum cr1, TMP1
  2988. | decode_RD4 TMP2, TMP2
  2989. | lwz CARG3, 4(RD)
  2990. | cror 4*cr7+gt, 4*cr0+gt, 4*cr1+gt
  2991. | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
  2992. if (vk) {
  2993. | ble cr7, ->BC_ISEQN_Z
  2994. } else {
  2995. | ble cr7, ->BC_ISNEN_Z
  2996. }
  2997. |.else
  2998. | lwzux TMP0, RA, BASE
  2999. | lwz TMP2, 0(PC)
  3000. | lfd f0, 0(RA)
  3001. | addi PC, PC, 4
  3002. | lwzux TMP1, RD, BASE
  3003. | checknum cr0, TMP0
  3004. | decode_RD4 TMP2, TMP2
  3005. | lfd f1, 0(RD)
  3006. | checknum cr1, TMP1
  3007. | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
  3008. | bge cr0, >5
  3009. | bge cr1, >5
  3010. | fcmpu cr0, f0, f1
  3011. if (vk) {
  3012. | bne >1
  3013. | add PC, PC, TMP2
  3014. } else {
  3015. | beq >1
  3016. | add PC, PC, TMP2
  3017. }
  3018. |1:
  3019. | ins_next
  3020. |.endif
  3021. |5: // Either or both types are not numbers.
  3022. |.if not DUALNUM
  3023. | lwz CARG2, 4(RA)
  3024. | lwz CARG3, 4(RD)
  3025. |.endif
  3026. |.if FFI
  3027. | cmpwi cr7, TMP0, LJ_TCDATA
  3028. | cmpwi cr5, TMP1, LJ_TCDATA
  3029. |.endif
  3030. | not TMP3, TMP0
  3031. | cmplw TMP0, TMP1
  3032. | cmplwi cr1, TMP3, ~LJ_TISPRI // Primitive?
  3033. |.if FFI
  3034. | cror 4*cr7+eq, 4*cr7+eq, 4*cr5+eq
  3035. |.endif
  3036. | cmplwi cr6, TMP3, ~LJ_TISTABUD // Table or userdata?
  3037. |.if FFI
  3038. | beq cr7, ->vmeta_equal_cd
  3039. |.endif
  3040. | cmplw cr5, CARG2, CARG3
  3041. | crandc 4*cr0+gt, 4*cr0+eq, 4*cr1+gt // 2: Same type and primitive.
  3042. | crorc 4*cr0+lt, 4*cr5+eq, 4*cr0+eq // 1: Same tv or different type.
  3043. | crand 4*cr0+eq, 4*cr0+eq, 4*cr5+eq // 0: Same type and same tv.
  3044. | mr SAVE0, PC
  3045. | cror 4*cr0+eq, 4*cr0+eq, 4*cr0+gt // 0 or 2.
  3046. | cror 4*cr0+lt, 4*cr0+lt, 4*cr0+gt // 1 or 2.
  3047. if (vk) {
  3048. | bne cr0, >6
  3049. | add PC, PC, TMP2
  3050. |6:
  3051. } else {
  3052. | beq cr0, >6
  3053. | add PC, PC, TMP2
  3054. |6:
  3055. }
  3056. |.if DUALNUM
  3057. | bge cr0, >2 // Done if 1 or 2.
  3058. |1:
  3059. | ins_next
  3060. |2:
  3061. |.else
  3062. | blt cr0, <1 // Done if 1 or 2.
  3063. |.endif
  3064. | blt cr6, <1 // Done if not tab/ud.
  3065. |
  3066. | // Different tables or userdatas. Need to check __eq metamethod.
  3067. | // Field metatable must be at same offset for GCtab and GCudata!
  3068. | lwz TAB:TMP2, TAB:CARG2->metatable
  3069. | li CARG4, 1-vk // ne = 0 or 1.
  3070. | cmplwi TAB:TMP2, 0
  3071. | beq <1 // No metatable?
  3072. | lbz TMP2, TAB:TMP2->nomm
  3073. | andix. TMP2, TMP2, 1<<MM_eq
  3074. | bne <1 // Or 'no __eq' flag set?
  3075. | mr PC, SAVE0 // Restore old PC.
  3076. | b ->vmeta_equal // Handle __eq metamethod.
  3077. break;
  3078. case BC_ISEQS: case BC_ISNES:
  3079. vk = op == BC_ISEQS;
  3080. | // RA = src*8, RD = str_const*8 (~), JMP with RD = target
  3081. | lwzux TMP0, RA, BASE
  3082. | srwi RD, RD, 1
  3083. | lwz STR:TMP3, 4(RA)
  3084. | lwz TMP2, 0(PC)
  3085. | subfic RD, RD, -4
  3086. | addi PC, PC, 4
  3087. |.if FFI
  3088. | cmpwi TMP0, LJ_TCDATA
  3089. |.endif
  3090. | lwzx STR:TMP1, KBASE, RD // KBASE-4-str_const*4
  3091. | .gpr64 extsw TMP0, TMP0
  3092. | subfic TMP0, TMP0, LJ_TSTR
  3093. |.if FFI
  3094. | beq ->vmeta_equal_cd
  3095. |.endif
  3096. | sub TMP1, STR:TMP1, STR:TMP3
  3097. | or TMP0, TMP0, TMP1
  3098. | decode_RD4 TMP2, TMP2
  3099. | subfic TMP0, TMP0, 0
  3100. | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
  3101. | subfe TMP1, TMP1, TMP1
  3102. if (vk) {
  3103. | andc TMP2, TMP2, TMP1
  3104. } else {
  3105. | and TMP2, TMP2, TMP1
  3106. }
  3107. | add PC, PC, TMP2
  3108. | ins_next
  3109. break;
  3110. case BC_ISEQN: case BC_ISNEN:
  3111. vk = op == BC_ISEQN;
  3112. | // RA = src*8, RD = num_const*8, JMP with RD = target
  3113. |.if DUALNUM
  3114. | lwzux TMP0, RA, BASE
  3115. | addi PC, PC, 4
  3116. | lwz CARG2, 4(RA)
  3117. | lwzux TMP1, RD, KBASE
  3118. | checknum cr0, TMP0
  3119. | lwz TMP2, -4(PC)
  3120. | checknum cr1, TMP1
  3121. | decode_RD4 TMP2, TMP2
  3122. | lwz CARG3, 4(RD)
  3123. | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
  3124. if (vk) {
  3125. |->BC_ISEQN_Z:
  3126. } else {
  3127. |->BC_ISNEN_Z:
  3128. }
  3129. | bne cr0, >7
  3130. | bne cr1, >8
  3131. | cmpw CARG2, CARG3
  3132. |4:
  3133. |.else
  3134. if (vk) {
  3135. |->BC_ISEQN_Z: // Dummy label.
  3136. } else {
  3137. |->BC_ISNEN_Z: // Dummy label.
  3138. }
  3139. | lwzx TMP0, BASE, RA
  3140. | addi PC, PC, 4
  3141. | lfdx f0, BASE, RA
  3142. | lwz TMP2, -4(PC)
  3143. | lfdx f1, KBASE, RD
  3144. | decode_RD4 TMP2, TMP2
  3145. | checknum TMP0
  3146. | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
  3147. | bge >3
  3148. | fcmpu cr0, f0, f1
  3149. |.endif
  3150. if (vk) {
  3151. | bne >1
  3152. | add PC, PC, TMP2
  3153. |1:
  3154. |.if not FFI
  3155. |3:
  3156. |.endif
  3157. } else {
  3158. | beq >2
  3159. |1:
  3160. |.if not FFI
  3161. |3:
  3162. |.endif
  3163. | add PC, PC, TMP2
  3164. |2:
  3165. }
  3166. | ins_next
  3167. |.if FFI
  3168. |3:
  3169. | cmpwi TMP0, LJ_TCDATA
  3170. | beq ->vmeta_equal_cd
  3171. | b <1
  3172. |.endif
  3173. |.if DUALNUM
  3174. |7: // RA is not an integer.
  3175. | bge cr0, <3
  3176. | // RA is a number.
  3177. | lfd f0, 0(RA)
  3178. | blt cr1, >1
  3179. | // RA is a number, RD is an integer.
  3180. | tonum_i f1, CARG3
  3181. | b >2
  3182. |
  3183. |8: // RA is an integer, RD is a number.
  3184. | tonum_i f0, CARG2
  3185. |1:
  3186. | lfd f1, 0(RD)
  3187. |2:
  3188. | fcmpu cr0, f0, f1
  3189. | b <4
  3190. |.endif
  3191. break;
  3192. case BC_ISEQP: case BC_ISNEP:
  3193. vk = op == BC_ISEQP;
  3194. | // RA = src*8, RD = primitive_type*8 (~), JMP with RD = target
  3195. | lwzx TMP0, BASE, RA
  3196. | srwi TMP1, RD, 3
  3197. | lwz TMP2, 0(PC)
  3198. | not TMP1, TMP1
  3199. | addi PC, PC, 4
  3200. |.if FFI
  3201. | cmpwi TMP0, LJ_TCDATA
  3202. |.endif
  3203. | sub TMP0, TMP0, TMP1
  3204. |.if FFI
  3205. | beq ->vmeta_equal_cd
  3206. |.endif
  3207. | decode_RD4 TMP2, TMP2
  3208. | .gpr64 extsw TMP0, TMP0
  3209. | addic TMP0, TMP0, -1
  3210. | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
  3211. | subfe TMP1, TMP1, TMP1
  3212. if (vk) {
  3213. | and TMP2, TMP2, TMP1
  3214. } else {
  3215. | andc TMP2, TMP2, TMP1
  3216. }
  3217. | add PC, PC, TMP2
  3218. | ins_next
  3219. break;
  3220. /* -- Unary test and copy ops ------------------------------------------- */
  3221. case BC_ISTC: case BC_ISFC: case BC_IST: case BC_ISF:
  3222. | // RA = dst*8 or unused, RD = src*8, JMP with RD = target
  3223. | lwzx TMP0, BASE, RD
  3224. | lwz INS, 0(PC)
  3225. | addi PC, PC, 4
  3226. if (op == BC_IST || op == BC_ISF) {
  3227. | .gpr64 extsw TMP0, TMP0
  3228. | subfic TMP0, TMP0, LJ_TTRUE
  3229. | decode_RD4 TMP2, INS
  3230. | subfe TMP1, TMP1, TMP1
  3231. | addis TMP2, TMP2, -(BCBIAS_J*4 >> 16)
  3232. if (op == BC_IST) {
  3233. | andc TMP2, TMP2, TMP1
  3234. } else {
  3235. | and TMP2, TMP2, TMP1
  3236. }
  3237. | add PC, PC, TMP2
  3238. } else {
  3239. | li TMP1, LJ_TFALSE
  3240. | lfdx f0, BASE, RD
  3241. | cmplw TMP0, TMP1
  3242. if (op == BC_ISTC) {
  3243. | bge >1
  3244. } else {
  3245. | blt >1
  3246. }
  3247. | addis PC, PC, -(BCBIAS_J*4 >> 16)
  3248. | decode_RD4 TMP2, INS
  3249. | stfdx f0, BASE, RA
  3250. | add PC, PC, TMP2
  3251. |1:
  3252. }
  3253. | ins_next
  3254. break;
  3255. /* -- Unary ops --------------------------------------------------------- */
  3256. case BC_MOV:
  3257. | // RA = dst*8, RD = src*8
  3258. | ins_next1
  3259. | lfdx f0, BASE, RD
  3260. | stfdx f0, BASE, RA
  3261. | ins_next2
  3262. break;
  3263. case BC_NOT:
  3264. | // RA = dst*8, RD = src*8
  3265. | ins_next1
  3266. | lwzx TMP0, BASE, RD
  3267. | .gpr64 extsw TMP0, TMP0
  3268. | subfic TMP1, TMP0, LJ_TTRUE
  3269. | adde TMP0, TMP0, TMP1
  3270. | stwx TMP0, BASE, RA
  3271. | ins_next2
  3272. break;
  3273. case BC_UNM:
  3274. | // RA = dst*8, RD = src*8
  3275. | lwzux TMP1, RD, BASE
  3276. | lwz TMP0, 4(RD)
  3277. | checknum TMP1
  3278. |.if DUALNUM
  3279. | bne >5
  3280. |.if GPR64
  3281. | lus TMP2, 0x8000
  3282. | neg TMP0, TMP0
  3283. | cmplw TMP0, TMP2
  3284. | beq >4
  3285. |.else
  3286. | nego. TMP0, TMP0
  3287. | bso >4
  3288. |1:
  3289. |.endif
  3290. | ins_next1
  3291. | stwux TISNUM, RA, BASE
  3292. | stw TMP0, 4(RA)
  3293. |3:
  3294. | ins_next2
  3295. |4:
  3296. |.if not GPR64
  3297. | // Potential overflow.
  3298. | mcrxr cr0; bley <1 // Ignore unrelated overflow.
  3299. |.endif
  3300. | lus TMP1, 0x41e0 // 2^31.
  3301. | li TMP0, 0
  3302. | b >7
  3303. |.endif
  3304. |5:
  3305. | bge ->vmeta_unm
  3306. | xoris TMP1, TMP1, 0x8000
  3307. |7:
  3308. | ins_next1
  3309. | stwux TMP1, RA, BASE
  3310. | stw TMP0, 4(RA)
  3311. |.if DUALNUM
  3312. | b <3
  3313. |.else
  3314. | ins_next2
  3315. |.endif
  3316. break;
  3317. case BC_LEN:
  3318. | // RA = dst*8, RD = src*8
  3319. | lwzux TMP0, RD, BASE
  3320. | lwz CARG1, 4(RD)
  3321. | checkstr TMP0; bne >2
  3322. | lwz CRET1, STR:CARG1->len
  3323. |1:
  3324. |.if DUALNUM
  3325. | ins_next1
  3326. | stwux TISNUM, RA, BASE
  3327. | stw CRET1, 4(RA)
  3328. |.else
  3329. | tonum_u f0, CRET1 // Result is a non-negative integer.
  3330. | ins_next1
  3331. | stfdx f0, BASE, RA
  3332. |.endif
  3333. | ins_next2
  3334. |2:
  3335. | checktab TMP0; bne ->vmeta_len
  3336. #if LJ_52
  3337. | lwz TAB:TMP2, TAB:CARG1->metatable
  3338. | cmplwi TAB:TMP2, 0
  3339. | bne >9
  3340. |3:
  3341. #endif
  3342. |->BC_LEN_Z:
  3343. | bl extern lj_tab_len // (GCtab *t)
  3344. | // Returns uint32_t (but less than 2^31).
  3345. | b <1
  3346. #if LJ_52
  3347. |9:
  3348. | lbz TMP0, TAB:TMP2->nomm
  3349. | andix. TMP0, TMP0, 1<<MM_len
  3350. | bne <3 // 'no __len' flag set: done.
  3351. | b ->vmeta_len
  3352. #endif
  3353. break;
  3354. /* -- Binary ops -------------------------------------------------------- */
  3355. |.macro ins_arithpre
  3356. | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8
  3357. ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
  3358. ||switch (vk) {
  3359. ||case 0:
  3360. | lwzx TMP1, BASE, RB
  3361. | .if DUALNUM
  3362. | lwzx TMP2, KBASE, RC
  3363. | .endif
  3364. | lfdx f14, BASE, RB
  3365. | lfdx f15, KBASE, RC
  3366. | .if DUALNUM
  3367. | checknum cr0, TMP1
  3368. | checknum cr1, TMP2
  3369. | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
  3370. | bge ->vmeta_arith_vn
  3371. | .else
  3372. | checknum TMP1; bge ->vmeta_arith_vn
  3373. | .endif
  3374. || break;
  3375. ||case 1:
  3376. | lwzx TMP1, BASE, RB
  3377. | .if DUALNUM
  3378. | lwzx TMP2, KBASE, RC
  3379. | .endif
  3380. | lfdx f15, BASE, RB
  3381. | lfdx f14, KBASE, RC
  3382. | .if DUALNUM
  3383. | checknum cr0, TMP1
  3384. | checknum cr1, TMP2
  3385. | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
  3386. | bge ->vmeta_arith_nv
  3387. | .else
  3388. | checknum TMP1; bge ->vmeta_arith_nv
  3389. | .endif
  3390. || break;
  3391. ||default:
  3392. | lwzx TMP1, BASE, RB
  3393. | lwzx TMP2, BASE, RC
  3394. | lfdx f14, BASE, RB
  3395. | lfdx f15, BASE, RC
  3396. | checknum cr0, TMP1
  3397. | checknum cr1, TMP2
  3398. | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
  3399. | bge ->vmeta_arith_vv
  3400. || break;
  3401. ||}
  3402. |.endmacro
  3403. |
  3404. |.macro ins_arithfallback, ins
  3405. ||switch (vk) {
  3406. ||case 0:
  3407. | ins ->vmeta_arith_vn2
  3408. || break;
  3409. ||case 1:
  3410. | ins ->vmeta_arith_nv2
  3411. || break;
  3412. ||default:
  3413. | ins ->vmeta_arith_vv2
  3414. || break;
  3415. ||}
  3416. |.endmacro
  3417. |
  3418. |.macro intmod, a, b, c
  3419. | bl ->vm_modi
  3420. |.endmacro
  3421. |
  3422. |.macro fpmod, a, b, c
  3423. |->BC_MODVN_Z:
  3424. | fdiv FARG1, b, c
  3425. | // NYI: Use internal implementation of floor.
  3426. | blex floor // floor(b/c)
  3427. | fmul a, FARG1, c
  3428. | fsub a, b, a // b - floor(b/c)*c
  3429. |.endmacro
  3430. |
  3431. |.macro ins_arithfp, fpins
  3432. | ins_arithpre
  3433. |.if "fpins" == "fpmod_"
  3434. | b ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway.
  3435. |.else
  3436. | fpins f0, f14, f15
  3437. | ins_next1
  3438. | stfdx f0, BASE, RA
  3439. | ins_next2
  3440. |.endif
  3441. |.endmacro
  3442. |
  3443. |.macro ins_arithdn, intins, fpins
  3444. | // RA = dst*8, RB = src1*8, RC = src2*8 | num_const*8
  3445. ||vk = ((int)op - BC_ADDVN) / (BC_ADDNV-BC_ADDVN);
  3446. ||switch (vk) {
  3447. ||case 0:
  3448. | lwzux TMP1, RB, BASE
  3449. | lwzux TMP2, RC, KBASE
  3450. | lwz CARG1, 4(RB)
  3451. | checknum cr0, TMP1
  3452. | lwz CARG2, 4(RC)
  3453. || break;
  3454. ||case 1:
  3455. | lwzux TMP1, RB, BASE
  3456. | lwzux TMP2, RC, KBASE
  3457. | lwz CARG2, 4(RB)
  3458. | checknum cr0, TMP1
  3459. | lwz CARG1, 4(RC)
  3460. || break;
  3461. ||default:
  3462. | lwzux TMP1, RB, BASE
  3463. | lwzux TMP2, RC, BASE
  3464. | lwz CARG1, 4(RB)
  3465. | checknum cr0, TMP1
  3466. | lwz CARG2, 4(RC)
  3467. || break;
  3468. ||}
  3469. | checknum cr1, TMP2
  3470. | bne >5
  3471. | bne cr1, >5
  3472. | intins CARG1, CARG1, CARG2
  3473. | bso >4
  3474. |1:
  3475. | ins_next1
  3476. | stwux TISNUM, RA, BASE
  3477. | stw CARG1, 4(RA)
  3478. |2:
  3479. | ins_next2
  3480. |4: // Overflow.
  3481. | mcrxr cr0; bley <1 // Ignore unrelated overflow.
  3482. | ins_arithfallback b
  3483. |5: // FP variant.
  3484. ||if (vk == 1) {
  3485. | lfd f15, 0(RB)
  3486. | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
  3487. | lfd f14, 0(RC)
  3488. ||} else {
  3489. | lfd f14, 0(RB)
  3490. | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
  3491. | lfd f15, 0(RC)
  3492. ||}
  3493. | ins_arithfallback bge
  3494. |.if "fpins" == "fpmod_"
  3495. | b ->BC_MODVN_Z // Avoid 3 copies. It's slow anyway.
  3496. |.else
  3497. | fpins f0, f14, f15
  3498. | ins_next1
  3499. | stfdx f0, BASE, RA
  3500. | b <2
  3501. |.endif
  3502. |.endmacro
  3503. |
  3504. |.macro ins_arith, intins, fpins
  3505. |.if DUALNUM
  3506. | ins_arithdn intins, fpins
  3507. |.else
  3508. | ins_arithfp fpins
  3509. |.endif
  3510. |.endmacro
  3511. case BC_ADDVN: case BC_ADDNV: case BC_ADDVV:
  3512. |.if GPR64
  3513. |.macro addo32., y, a, b
  3514. | // Need to check overflow for (a<<32) + (b<<32).
  3515. | rldicr TMP0, a, 32, 31
  3516. | rldicr TMP3, b, 32, 31
  3517. | addo. TMP0, TMP0, TMP3
  3518. | add y, a, b
  3519. |.endmacro
  3520. | ins_arith addo32., fadd
  3521. |.else
  3522. | ins_arith addo., fadd
  3523. |.endif
  3524. break;
  3525. case BC_SUBVN: case BC_SUBNV: case BC_SUBVV:
  3526. |.if GPR64
  3527. |.macro subo32., y, a, b
  3528. | // Need to check overflow for (a<<32) - (b<<32).
  3529. | rldicr TMP0, a, 32, 31
  3530. | rldicr TMP3, b, 32, 31
  3531. | subo. TMP0, TMP0, TMP3
  3532. | sub y, a, b
  3533. |.endmacro
  3534. | ins_arith subo32., fsub
  3535. |.else
  3536. | ins_arith subo., fsub
  3537. |.endif
  3538. break;
  3539. case BC_MULVN: case BC_MULNV: case BC_MULVV:
  3540. | ins_arith mullwo., fmul
  3541. break;
  3542. case BC_DIVVN: case BC_DIVNV: case BC_DIVVV:
  3543. | ins_arithfp fdiv
  3544. break;
  3545. case BC_MODVN:
  3546. | ins_arith intmod, fpmod
  3547. break;
  3548. case BC_MODNV: case BC_MODVV:
  3549. | ins_arith intmod, fpmod_
  3550. break;
  3551. case BC_POW:
  3552. | // NYI: (partial) integer arithmetic.
  3553. | lwzx TMP1, BASE, RB
  3554. | lfdx FARG1, BASE, RB
  3555. | lwzx TMP2, BASE, RC
  3556. | lfdx FARG2, BASE, RC
  3557. | checknum cr0, TMP1
  3558. | checknum cr1, TMP2
  3559. | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
  3560. | bge ->vmeta_arith_vv
  3561. | blex pow
  3562. | ins_next1
  3563. | stfdx FARG1, BASE, RA
  3564. | ins_next2
  3565. break;
  3566. case BC_CAT:
  3567. | // RA = dst*8, RB = src_start*8, RC = src_end*8
  3568. | sub CARG3, RC, RB
  3569. | stp BASE, L->base
  3570. | add CARG2, BASE, RC
  3571. | mr SAVE0, RB
  3572. |->BC_CAT_Z:
  3573. | stw PC, SAVE_PC
  3574. | mr CARG1, L
  3575. | srwi CARG3, CARG3, 3
  3576. | bl extern lj_meta_cat // (lua_State *L, TValue *top, int left)
  3577. | // Returns NULL (finished) or TValue * (metamethod).
  3578. | cmplwi CRET1, 0
  3579. | lp BASE, L->base
  3580. | bne ->vmeta_binop
  3581. | ins_next1
  3582. | lfdx f0, BASE, SAVE0 // Copy result from RB to RA.
  3583. | stfdx f0, BASE, RA
  3584. | ins_next2
  3585. break;
  3586. /* -- Constant ops ------------------------------------------------------ */
  3587. case BC_KSTR:
  3588. | // RA = dst*8, RD = str_const*8 (~)
  3589. | srwi TMP1, RD, 1
  3590. | subfic TMP1, TMP1, -4
  3591. | ins_next1
  3592. | lwzx TMP0, KBASE, TMP1 // KBASE-4-str_const*4
  3593. | li TMP2, LJ_TSTR
  3594. | stwux TMP2, RA, BASE
  3595. | stw TMP0, 4(RA)
  3596. | ins_next2
  3597. break;
  3598. case BC_KCDATA:
  3599. |.if FFI
  3600. | // RA = dst*8, RD = cdata_const*8 (~)
  3601. | srwi TMP1, RD, 1
  3602. | subfic TMP1, TMP1, -4
  3603. | ins_next1
  3604. | lwzx TMP0, KBASE, TMP1 // KBASE-4-cdata_const*4
  3605. | li TMP2, LJ_TCDATA
  3606. | stwux TMP2, RA, BASE
  3607. | stw TMP0, 4(RA)
  3608. | ins_next2
  3609. |.endif
  3610. break;
  3611. case BC_KSHORT:
  3612. | // RA = dst*8, RD = int16_literal*8
  3613. |.if DUALNUM
  3614. | slwi RD, RD, 13
  3615. | srawi RD, RD, 16
  3616. | ins_next1
  3617. | stwux TISNUM, RA, BASE
  3618. | stw RD, 4(RA)
  3619. | ins_next2
  3620. |.else
  3621. | // The soft-float approach is faster.
  3622. | slwi RD, RD, 13
  3623. | srawi TMP1, RD, 31
  3624. | xor TMP2, TMP1, RD
  3625. | sub TMP2, TMP2, TMP1 // TMP2 = abs(x)
  3626. | cntlzw TMP3, TMP2
  3627. | subfic TMP1, TMP3, 0x40d // TMP1 = exponent-1
  3628. | slw TMP2, TMP2, TMP3 // TMP2 = left aligned mantissa
  3629. | subfic TMP3, RD, 0
  3630. | slwi TMP1, TMP1, 20
  3631. | rlwimi RD, TMP2, 21, 1, 31 // hi = sign(x) | (mantissa>>11)
  3632. | subfe TMP0, TMP0, TMP0
  3633. | add RD, RD, TMP1 // hi = hi + exponent-1
  3634. | and RD, RD, TMP0 // hi = x == 0 ? 0 : hi
  3635. | ins_next1
  3636. | stwux RD, RA, BASE
  3637. | stw ZERO, 4(RA)
  3638. | ins_next2
  3639. |.endif
  3640. break;
  3641. case BC_KNUM:
  3642. | // RA = dst*8, RD = num_const*8
  3643. | ins_next1
  3644. | lfdx f0, KBASE, RD
  3645. | stfdx f0, BASE, RA
  3646. | ins_next2
  3647. break;
  3648. case BC_KPRI:
  3649. | // RA = dst*8, RD = primitive_type*8 (~)
  3650. | srwi TMP1, RD, 3
  3651. | not TMP0, TMP1
  3652. | ins_next1
  3653. | stwx TMP0, BASE, RA
  3654. | ins_next2
  3655. break;
  3656. case BC_KNIL:
  3657. | // RA = base*8, RD = end*8
  3658. | stwx TISNIL, BASE, RA
  3659. | addi RA, RA, 8
  3660. |1:
  3661. | stwx TISNIL, BASE, RA
  3662. | cmpw RA, RD
  3663. | addi RA, RA, 8
  3664. | blt <1
  3665. | ins_next_
  3666. break;
  3667. /* -- Upvalue and function ops ------------------------------------------ */
  3668. case BC_UGET:
  3669. | // RA = dst*8, RD = uvnum*8
  3670. | lwz LFUNC:RB, FRAME_FUNC(BASE)
  3671. | srwi RD, RD, 1
  3672. | addi RD, RD, offsetof(GCfuncL, uvptr)
  3673. | lwzx UPVAL:RB, LFUNC:RB, RD
  3674. | ins_next1
  3675. | lwz TMP1, UPVAL:RB->v
  3676. | lfd f0, 0(TMP1)
  3677. | stfdx f0, BASE, RA
  3678. | ins_next2
  3679. break;
  3680. case BC_USETV:
  3681. | // RA = uvnum*8, RD = src*8
  3682. | lwz LFUNC:RB, FRAME_FUNC(BASE)
  3683. | srwi RA, RA, 1
  3684. | addi RA, RA, offsetof(GCfuncL, uvptr)
  3685. | lfdux f0, RD, BASE
  3686. | lwzx UPVAL:RB, LFUNC:RB, RA
  3687. | lbz TMP3, UPVAL:RB->marked
  3688. | lwz CARG2, UPVAL:RB->v
  3689. | andix. TMP3, TMP3, LJ_GC_BLACK // isblack(uv)
  3690. | lbz TMP0, UPVAL:RB->closed
  3691. | lwz TMP2, 0(RD)
  3692. | stfd f0, 0(CARG2)
  3693. | cmplwi cr1, TMP0, 0
  3694. | lwz TMP1, 4(RD)
  3695. | cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq
  3696. | subi TMP2, TMP2, (LJ_TNUMX+1)
  3697. | bne >2 // Upvalue is closed and black?
  3698. |1:
  3699. | ins_next
  3700. |
  3701. |2: // Check if new value is collectable.
  3702. | cmplwi TMP2, LJ_TISGCV - (LJ_TNUMX+1)
  3703. | bge <1 // tvisgcv(v)
  3704. | lbz TMP3, GCOBJ:TMP1->gch.marked
  3705. | andix. TMP3, TMP3, LJ_GC_WHITES // iswhite(v)
  3706. | la CARG1, GG_DISP2G(DISPATCH)
  3707. | // Crossed a write barrier. Move the barrier forward.
  3708. | beq <1
  3709. | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv)
  3710. | b <1
  3711. break;
  3712. case BC_USETS:
  3713. | // RA = uvnum*8, RD = str_const*8 (~)
  3714. | lwz LFUNC:RB, FRAME_FUNC(BASE)
  3715. | srwi TMP1, RD, 1
  3716. | srwi RA, RA, 1
  3717. | subfic TMP1, TMP1, -4
  3718. | addi RA, RA, offsetof(GCfuncL, uvptr)
  3719. | lwzx STR:TMP1, KBASE, TMP1 // KBASE-4-str_const*4
  3720. | lwzx UPVAL:RB, LFUNC:RB, RA
  3721. | lbz TMP3, UPVAL:RB->marked
  3722. | lwz CARG2, UPVAL:RB->v
  3723. | andix. TMP3, TMP3, LJ_GC_BLACK // isblack(uv)
  3724. | lbz TMP3, STR:TMP1->marked
  3725. | lbz TMP2, UPVAL:RB->closed
  3726. | li TMP0, LJ_TSTR
  3727. | stw STR:TMP1, 4(CARG2)
  3728. | stw TMP0, 0(CARG2)
  3729. | bne >2
  3730. |1:
  3731. | ins_next
  3732. |
  3733. |2: // Check if string is white and ensure upvalue is closed.
  3734. | andix. TMP3, TMP3, LJ_GC_WHITES // iswhite(str)
  3735. | cmplwi cr1, TMP2, 0
  3736. | cror 4*cr0+eq, 4*cr0+eq, 4*cr1+eq
  3737. | la CARG1, GG_DISP2G(DISPATCH)
  3738. | // Crossed a write barrier. Move the barrier forward.
  3739. | beq <1
  3740. | bl extern lj_gc_barrieruv // (global_State *g, TValue *tv)
  3741. | b <1
  3742. break;
  3743. case BC_USETN:
  3744. | // RA = uvnum*8, RD = num_const*8
  3745. | lwz LFUNC:RB, FRAME_FUNC(BASE)
  3746. | srwi RA, RA, 1
  3747. | addi RA, RA, offsetof(GCfuncL, uvptr)
  3748. | lfdx f0, KBASE, RD
  3749. | lwzx UPVAL:RB, LFUNC:RB, RA
  3750. | ins_next1
  3751. | lwz TMP1, UPVAL:RB->v
  3752. | stfd f0, 0(TMP1)
  3753. | ins_next2
  3754. break;
  3755. case BC_USETP:
  3756. | // RA = uvnum*8, RD = primitive_type*8 (~)
  3757. | lwz LFUNC:RB, FRAME_FUNC(BASE)
  3758. | srwi RA, RA, 1
  3759. | srwi TMP0, RD, 3
  3760. | addi RA, RA, offsetof(GCfuncL, uvptr)
  3761. | not TMP0, TMP0
  3762. | lwzx UPVAL:RB, LFUNC:RB, RA
  3763. | ins_next1
  3764. | lwz TMP1, UPVAL:RB->v
  3765. | stw TMP0, 0(TMP1)
  3766. | ins_next2
  3767. break;
  3768. case BC_UCLO:
  3769. | // RA = level*8, RD = target
  3770. | lwz TMP1, L->openupval
  3771. | branch_RD // Do this first since RD is not saved.
  3772. | stp BASE, L->base
  3773. | cmplwi TMP1, 0
  3774. | mr CARG1, L
  3775. | beq >1
  3776. | add CARG2, BASE, RA
  3777. | bl extern lj_func_closeuv // (lua_State *L, TValue *level)
  3778. | lp BASE, L->base
  3779. |1:
  3780. | ins_next
  3781. break;
  3782. case BC_FNEW:
  3783. | // RA = dst*8, RD = proto_const*8 (~) (holding function prototype)
  3784. | srwi TMP1, RD, 1
  3785. | stp BASE, L->base
  3786. | subfic TMP1, TMP1, -4
  3787. | stw PC, SAVE_PC
  3788. | lwzx CARG2, KBASE, TMP1 // KBASE-4-tab_const*4
  3789. | mr CARG1, L
  3790. | lwz CARG3, FRAME_FUNC(BASE)
  3791. | // (lua_State *L, GCproto *pt, GCfuncL *parent)
  3792. | bl extern lj_func_newL_gc
  3793. | // Returns GCfuncL *.
  3794. | lp BASE, L->base
  3795. | li TMP0, LJ_TFUNC
  3796. | stwux TMP0, RA, BASE
  3797. | stw LFUNC:CRET1, 4(RA)
  3798. | ins_next
  3799. break;
  3800. /* -- Table ops --------------------------------------------------------- */
  3801. case BC_TNEW:
  3802. case BC_TDUP:
  3803. | // RA = dst*8, RD = (hbits|asize)*8 | tab_const*8 (~)
  3804. | lwz TMP0, DISPATCH_GL(gc.total)(DISPATCH)
  3805. | mr CARG1, L
  3806. | lwz TMP1, DISPATCH_GL(gc.threshold)(DISPATCH)
  3807. | stp BASE, L->base
  3808. | cmplw TMP0, TMP1
  3809. | stw PC, SAVE_PC
  3810. | bge >5
  3811. |1:
  3812. if (op == BC_TNEW) {
  3813. | rlwinm CARG2, RD, 29, 21, 31
  3814. | rlwinm CARG3, RD, 18, 27, 31
  3815. | cmpwi CARG2, 0x7ff; beq >3
  3816. |2:
  3817. | bl extern lj_tab_new // (lua_State *L, int32_t asize, uint32_t hbits)
  3818. | // Returns Table *.
  3819. } else {
  3820. | srwi TMP1, RD, 1
  3821. | subfic TMP1, TMP1, -4
  3822. | lwzx CARG2, KBASE, TMP1 // KBASE-4-tab_const*4
  3823. | bl extern lj_tab_dup // (lua_State *L, Table *kt)
  3824. | // Returns Table *.
  3825. }
  3826. | lp BASE, L->base
  3827. | li TMP0, LJ_TTAB
  3828. | stwux TMP0, RA, BASE
  3829. | stw TAB:CRET1, 4(RA)
  3830. | ins_next
  3831. if (op == BC_TNEW) {
  3832. |3:
  3833. | li CARG2, 0x801
  3834. | b <2
  3835. }
  3836. |5:
  3837. | mr SAVE0, RD
  3838. | bl extern lj_gc_step_fixtop // (lua_State *L)
  3839. | mr RD, SAVE0
  3840. | mr CARG1, L
  3841. | b <1
  3842. break;
  3843. case BC_GGET:
  3844. | // RA = dst*8, RD = str_const*8 (~)
  3845. case BC_GSET:
  3846. | // RA = src*8, RD = str_const*8 (~)
  3847. | lwz LFUNC:TMP2, FRAME_FUNC(BASE)
  3848. | srwi TMP1, RD, 1
  3849. | lwz TAB:RB, LFUNC:TMP2->env
  3850. | subfic TMP1, TMP1, -4
  3851. | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4
  3852. if (op == BC_GGET) {
  3853. | b ->BC_TGETS_Z
  3854. } else {
  3855. | b ->BC_TSETS_Z
  3856. }
  3857. break;
  3858. case BC_TGETV:
  3859. | // RA = dst*8, RB = table*8, RC = key*8
  3860. | lwzux CARG1, RB, BASE
  3861. | lwzux CARG2, RC, BASE
  3862. | lwz TAB:RB, 4(RB)
  3863. |.if DUALNUM
  3864. | lwz RC, 4(RC)
  3865. |.else
  3866. | lfd f0, 0(RC)
  3867. |.endif
  3868. | checktab CARG1
  3869. | checknum cr1, CARG2
  3870. | bne ->vmeta_tgetv
  3871. |.if DUALNUM
  3872. | lwz TMP0, TAB:RB->asize
  3873. | bne cr1, >5
  3874. | lwz TMP1, TAB:RB->array
  3875. | cmplw TMP0, RC
  3876. | slwi TMP2, RC, 3
  3877. |.else
  3878. | bge cr1, >5
  3879. | // Convert number key to integer, check for integerness and range.
  3880. | fctiwz f1, f0
  3881. | fadd f2, f0, TOBIT
  3882. | stfd f1, TMPD
  3883. | lwz TMP0, TAB:RB->asize
  3884. | fsub f2, f2, TOBIT
  3885. | lwz TMP2, TMPD_LO
  3886. | lwz TMP1, TAB:RB->array
  3887. | fcmpu cr1, f0, f2
  3888. | cmplw cr0, TMP0, TMP2
  3889. | crand 4*cr0+gt, 4*cr0+gt, 4*cr1+eq
  3890. | slwi TMP2, TMP2, 3
  3891. |.endif
  3892. | ble ->vmeta_tgetv // Integer key and in array part?
  3893. | lwzx TMP0, TMP1, TMP2
  3894. | lfdx f14, TMP1, TMP2
  3895. | checknil TMP0; beq >2
  3896. |1:
  3897. | ins_next1
  3898. | stfdx f14, BASE, RA
  3899. | ins_next2
  3900. |
  3901. |2: // Check for __index if table value is nil.
  3902. | lwz TAB:TMP2, TAB:RB->metatable
  3903. | cmplwi TAB:TMP2, 0
  3904. | beq <1 // No metatable: done.
  3905. | lbz TMP0, TAB:TMP2->nomm
  3906. | andix. TMP0, TMP0, 1<<MM_index
  3907. | bne <1 // 'no __index' flag set: done.
  3908. | b ->vmeta_tgetv
  3909. |
  3910. |5:
  3911. | checkstr CARG2; bne ->vmeta_tgetv
  3912. |.if not DUALNUM
  3913. | lwz STR:RC, 4(RC)
  3914. |.endif
  3915. | b ->BC_TGETS_Z // String key?
  3916. break;
  3917. case BC_TGETS:
  3918. | // RA = dst*8, RB = table*8, RC = str_const*8 (~)
  3919. | lwzux CARG1, RB, BASE
  3920. | srwi TMP1, RC, 1
  3921. | lwz TAB:RB, 4(RB)
  3922. | subfic TMP1, TMP1, -4
  3923. | checktab CARG1
  3924. | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4
  3925. | bne ->vmeta_tgets1
  3926. |->BC_TGETS_Z:
  3927. | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = dst*8
  3928. | lwz TMP0, TAB:RB->hmask
  3929. | lwz TMP1, STR:RC->hash
  3930. | lwz NODE:TMP2, TAB:RB->node
  3931. | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask
  3932. | slwi TMP0, TMP1, 5
  3933. | slwi TMP1, TMP1, 3
  3934. | sub TMP1, TMP0, TMP1
  3935. | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8)
  3936. |1:
  3937. | lwz CARG1, NODE:TMP2->key
  3938. | lwz TMP0, 4+offsetof(Node, key)(NODE:TMP2)
  3939. | lwz CARG2, NODE:TMP2->val
  3940. | lwz TMP1, 4+offsetof(Node, val)(NODE:TMP2)
  3941. | checkstr CARG1; bne >4
  3942. | cmpw TMP0, STR:RC; bne >4
  3943. | checknil CARG2; beq >5 // Key found, but nil value?
  3944. |3:
  3945. | stwux CARG2, RA, BASE
  3946. | stw TMP1, 4(RA)
  3947. | ins_next
  3948. |
  3949. |4: // Follow hash chain.
  3950. | lwz NODE:TMP2, NODE:TMP2->next
  3951. | cmplwi NODE:TMP2, 0
  3952. | bne <1
  3953. | // End of hash chain: key not found, nil result.
  3954. | li CARG2, LJ_TNIL
  3955. |
  3956. |5: // Check for __index if table value is nil.
  3957. | lwz TAB:TMP2, TAB:RB->metatable
  3958. | cmplwi TAB:TMP2, 0
  3959. | beq <3 // No metatable: done.
  3960. | lbz TMP0, TAB:TMP2->nomm
  3961. | andix. TMP0, TMP0, 1<<MM_index
  3962. | bne <3 // 'no __index' flag set: done.
  3963. | b ->vmeta_tgets
  3964. break;
  3965. case BC_TGETB:
  3966. | // RA = dst*8, RB = table*8, RC = index*8
  3967. | lwzux CARG1, RB, BASE
  3968. | srwi TMP0, RC, 3
  3969. | lwz TAB:RB, 4(RB)
  3970. | checktab CARG1; bne ->vmeta_tgetb
  3971. | lwz TMP1, TAB:RB->asize
  3972. | lwz TMP2, TAB:RB->array
  3973. | cmplw TMP0, TMP1; bge ->vmeta_tgetb
  3974. | lwzx TMP1, TMP2, RC
  3975. | lfdx f0, TMP2, RC
  3976. | checknil TMP1; beq >5
  3977. |1:
  3978. | ins_next1
  3979. | stfdx f0, BASE, RA
  3980. | ins_next2
  3981. |
  3982. |5: // Check for __index if table value is nil.
  3983. | lwz TAB:TMP2, TAB:RB->metatable
  3984. | cmplwi TAB:TMP2, 0
  3985. | beq <1 // No metatable: done.
  3986. | lbz TMP2, TAB:TMP2->nomm
  3987. | andix. TMP2, TMP2, 1<<MM_index
  3988. | bne <1 // 'no __index' flag set: done.
  3989. | b ->vmeta_tgetb // Caveat: preserve TMP0!
  3990. break;
  3991. case BC_TSETV:
  3992. | // RA = src*8, RB = table*8, RC = key*8
  3993. | lwzux CARG1, RB, BASE
  3994. | lwzux CARG2, RC, BASE
  3995. | lwz TAB:RB, 4(RB)
  3996. |.if DUALNUM
  3997. | lwz RC, 4(RC)
  3998. |.else
  3999. | lfd f0, 0(RC)
  4000. |.endif
  4001. | checktab CARG1
  4002. | checknum cr1, CARG2
  4003. | bne ->vmeta_tsetv
  4004. |.if DUALNUM
  4005. | lwz TMP0, TAB:RB->asize
  4006. | bne cr1, >5
  4007. | lwz TMP1, TAB:RB->array
  4008. | cmplw TMP0, RC
  4009. | slwi TMP0, RC, 3
  4010. |.else
  4011. | bge cr1, >5
  4012. | // Convert number key to integer, check for integerness and range.
  4013. | fctiwz f1, f0
  4014. | fadd f2, f0, TOBIT
  4015. | stfd f1, TMPD
  4016. | lwz TMP0, TAB:RB->asize
  4017. | fsub f2, f2, TOBIT
  4018. | lwz TMP2, TMPD_LO
  4019. | lwz TMP1, TAB:RB->array
  4020. | fcmpu cr1, f0, f2
  4021. | cmplw cr0, TMP0, TMP2
  4022. | crand 4*cr0+gt, 4*cr0+gt, 4*cr1+eq
  4023. | slwi TMP0, TMP2, 3
  4024. |.endif
  4025. | ble ->vmeta_tsetv // Integer key and in array part?
  4026. | lwzx TMP2, TMP1, TMP0
  4027. | lbz TMP3, TAB:RB->marked
  4028. | lfdx f14, BASE, RA
  4029. | checknil TMP2; beq >3
  4030. |1:
  4031. | andix. TMP2, TMP3, LJ_GC_BLACK // isblack(table)
  4032. | stfdx f14, TMP1, TMP0
  4033. | bne >7
  4034. |2:
  4035. | ins_next
  4036. |
  4037. |3: // Check for __newindex if previous value is nil.
  4038. | lwz TAB:TMP2, TAB:RB->metatable
  4039. | cmplwi TAB:TMP2, 0
  4040. | beq <1 // No metatable: done.
  4041. | lbz TMP2, TAB:TMP2->nomm
  4042. | andix. TMP2, TMP2, 1<<MM_newindex
  4043. | bne <1 // 'no __newindex' flag set: done.
  4044. | b ->vmeta_tsetv
  4045. |
  4046. |5:
  4047. | checkstr CARG2; bne ->vmeta_tsetv
  4048. |.if not DUALNUM
  4049. | lwz STR:RC, 4(RC)
  4050. |.endif
  4051. | b ->BC_TSETS_Z // String key?
  4052. |
  4053. |7: // Possible table write barrier for the value. Skip valiswhite check.
  4054. | barrierback TAB:RB, TMP3, TMP0
  4055. | b <2
  4056. break;
  4057. case BC_TSETS:
  4058. | // RA = src*8, RB = table*8, RC = str_const*8 (~)
  4059. | lwzux CARG1, RB, BASE
  4060. | srwi TMP1, RC, 1
  4061. | lwz TAB:RB, 4(RB)
  4062. | subfic TMP1, TMP1, -4
  4063. | checktab CARG1
  4064. | lwzx STR:RC, KBASE, TMP1 // KBASE-4-str_const*4
  4065. | bne ->vmeta_tsets1
  4066. |->BC_TSETS_Z:
  4067. | // TAB:RB = GCtab *, STR:RC = GCstr *, RA = src*8
  4068. | lwz TMP0, TAB:RB->hmask
  4069. | lwz TMP1, STR:RC->hash
  4070. | lwz NODE:TMP2, TAB:RB->node
  4071. | stb ZERO, TAB:RB->nomm // Clear metamethod cache.
  4072. | and TMP1, TMP1, TMP0 // idx = str->hash & tab->hmask
  4073. | lfdx f14, BASE, RA
  4074. | slwi TMP0, TMP1, 5
  4075. | slwi TMP1, TMP1, 3
  4076. | sub TMP1, TMP0, TMP1
  4077. | lbz TMP3, TAB:RB->marked
  4078. | add NODE:TMP2, NODE:TMP2, TMP1 // node = tab->node + (idx*32-idx*8)
  4079. |1:
  4080. | lwz CARG1, NODE:TMP2->key
  4081. | lwz TMP0, 4+offsetof(Node, key)(NODE:TMP2)
  4082. | lwz CARG2, NODE:TMP2->val
  4083. | lwz NODE:TMP1, NODE:TMP2->next
  4084. | checkstr CARG1; bne >5
  4085. | cmpw TMP0, STR:RC; bne >5
  4086. | checknil CARG2; beq >4 // Key found, but nil value?
  4087. |2:
  4088. | andix. TMP0, TMP3, LJ_GC_BLACK // isblack(table)
  4089. | stfd f14, NODE:TMP2->val
  4090. | bne >7
  4091. |3:
  4092. | ins_next
  4093. |
  4094. |4: // Check for __newindex if previous value is nil.
  4095. | lwz TAB:TMP1, TAB:RB->metatable
  4096. | cmplwi TAB:TMP1, 0
  4097. | beq <2 // No metatable: done.
  4098. | lbz TMP0, TAB:TMP1->nomm
  4099. | andix. TMP0, TMP0, 1<<MM_newindex
  4100. | bne <2 // 'no __newindex' flag set: done.
  4101. | b ->vmeta_tsets
  4102. |
  4103. |5: // Follow hash chain.
  4104. | cmplwi NODE:TMP1, 0
  4105. | mr NODE:TMP2, NODE:TMP1
  4106. | bne <1
  4107. | // End of hash chain: key not found, add a new one.
  4108. |
  4109. | // But check for __newindex first.
  4110. | lwz TAB:TMP1, TAB:RB->metatable
  4111. | la CARG3, DISPATCH_GL(tmptv)(DISPATCH)
  4112. | stw PC, SAVE_PC
  4113. | mr CARG1, L
  4114. | cmplwi TAB:TMP1, 0
  4115. | stp BASE, L->base
  4116. | beq >6 // No metatable: continue.
  4117. | lbz TMP0, TAB:TMP1->nomm
  4118. | andix. TMP0, TMP0, 1<<MM_newindex
  4119. | beq ->vmeta_tsets // 'no __newindex' flag NOT set: check.
  4120. |6:
  4121. | li TMP0, LJ_TSTR
  4122. | stw STR:RC, 4(CARG3)
  4123. | mr CARG2, TAB:RB
  4124. | stw TMP0, 0(CARG3)
  4125. | bl extern lj_tab_newkey // (lua_State *L, GCtab *t, TValue *k)
  4126. | // Returns TValue *.
  4127. | lp BASE, L->base
  4128. | stfd f14, 0(CRET1)
  4129. | b <3 // No 2nd write barrier needed.
  4130. |
  4131. |7: // Possible table write barrier for the value. Skip valiswhite check.
  4132. | barrierback TAB:RB, TMP3, TMP0
  4133. | b <3
  4134. break;
  4135. case BC_TSETB:
  4136. | // RA = src*8, RB = table*8, RC = index*8
  4137. | lwzux CARG1, RB, BASE
  4138. | srwi TMP0, RC, 3
  4139. | lwz TAB:RB, 4(RB)
  4140. | checktab CARG1; bne ->vmeta_tsetb
  4141. | lwz TMP1, TAB:RB->asize
  4142. | lwz TMP2, TAB:RB->array
  4143. | lbz TMP3, TAB:RB->marked
  4144. | cmplw TMP0, TMP1
  4145. | lfdx f14, BASE, RA
  4146. | bge ->vmeta_tsetb
  4147. | lwzx TMP1, TMP2, RC
  4148. | checknil TMP1; beq >5
  4149. |1:
  4150. | andix. TMP0, TMP3, LJ_GC_BLACK // isblack(table)
  4151. | stfdx f14, TMP2, RC
  4152. | bne >7
  4153. |2:
  4154. | ins_next
  4155. |
  4156. |5: // Check for __newindex if previous value is nil.
  4157. | lwz TAB:TMP1, TAB:RB->metatable
  4158. | cmplwi TAB:TMP1, 0
  4159. | beq <1 // No metatable: done.
  4160. | lbz TMP1, TAB:TMP1->nomm
  4161. | andix. TMP1, TMP1, 1<<MM_newindex
  4162. | bne <1 // 'no __newindex' flag set: done.
  4163. | b ->vmeta_tsetb // Caveat: preserve TMP0!
  4164. |
  4165. |7: // Possible table write barrier for the value. Skip valiswhite check.
  4166. | barrierback TAB:RB, TMP3, TMP0
  4167. | b <2
  4168. break;
  4169. case BC_TSETM:
  4170. | // RA = base*8 (table at base-1), RD = num_const*8 (start index)
  4171. | add RA, BASE, RA
  4172. |1:
  4173. | add TMP3, KBASE, RD
  4174. | lwz TAB:CARG2, -4(RA) // Guaranteed to be a table.
  4175. | addic. TMP0, MULTRES, -8
  4176. | lwz TMP3, 4(TMP3) // Integer constant is in lo-word.
  4177. | srwi CARG3, TMP0, 3
  4178. | beq >4 // Nothing to copy?
  4179. | add CARG3, CARG3, TMP3
  4180. | lwz TMP2, TAB:CARG2->asize
  4181. | slwi TMP1, TMP3, 3
  4182. | lbz TMP3, TAB:CARG2->marked
  4183. | cmplw CARG3, TMP2
  4184. | add TMP2, RA, TMP0
  4185. | lwz TMP0, TAB:CARG2->array
  4186. | bgt >5
  4187. | add TMP1, TMP1, TMP0
  4188. | andix. TMP0, TMP3, LJ_GC_BLACK // isblack(table)
  4189. |3: // Copy result slots to table.
  4190. | lfd f0, 0(RA)
  4191. | addi RA, RA, 8
  4192. | cmpw cr1, RA, TMP2
  4193. | stfd f0, 0(TMP1)
  4194. | addi TMP1, TMP1, 8
  4195. | blt cr1, <3
  4196. | bne >7
  4197. |4:
  4198. | ins_next
  4199. |
  4200. |5: // Need to resize array part.
  4201. | stp BASE, L->base
  4202. | mr CARG1, L
  4203. | stw PC, SAVE_PC
  4204. | mr SAVE0, RD
  4205. | bl extern lj_tab_reasize // (lua_State *L, GCtab *t, int nasize)
  4206. | // Must not reallocate the stack.
  4207. | mr RD, SAVE0
  4208. | b <1
  4209. |
  4210. |7: // Possible table write barrier for any value. Skip valiswhite check.
  4211. | barrierback TAB:CARG2, TMP3, TMP0
  4212. | b <4
  4213. break;
  4214. /* -- Calls and vararg handling ----------------------------------------- */
  4215. case BC_CALLM:
  4216. | // RA = base*8, (RB = (nresults+1)*8,) RC = extra_nargs*8
  4217. | add NARGS8:RC, NARGS8:RC, MULTRES
  4218. | // Fall through. Assumes BC_CALL follows.
  4219. break;
  4220. case BC_CALL:
  4221. | // RA = base*8, (RB = (nresults+1)*8,) RC = (nargs+1)*8
  4222. | mr TMP2, BASE
  4223. | lwzux TMP0, BASE, RA
  4224. | lwz LFUNC:RB, 4(BASE)
  4225. | subi NARGS8:RC, NARGS8:RC, 8
  4226. | addi BASE, BASE, 8
  4227. | checkfunc TMP0; bne ->vmeta_call
  4228. | ins_call
  4229. break;
  4230. case BC_CALLMT:
  4231. | // RA = base*8, (RB = 0,) RC = extra_nargs*8
  4232. | add NARGS8:RC, NARGS8:RC, MULTRES
  4233. | // Fall through. Assumes BC_CALLT follows.
  4234. break;
  4235. case BC_CALLT:
  4236. | // RA = base*8, (RB = 0,) RC = (nargs+1)*8
  4237. | lwzux TMP0, RA, BASE
  4238. | lwz LFUNC:RB, 4(RA)
  4239. | subi NARGS8:RC, NARGS8:RC, 8
  4240. | lwz TMP1, FRAME_PC(BASE)
  4241. | checkfunc TMP0
  4242. | addi RA, RA, 8
  4243. | bne ->vmeta_callt
  4244. |->BC_CALLT_Z:
  4245. | andix. TMP0, TMP1, FRAME_TYPE // Caveat: preserve cr0 until the crand.
  4246. | lbz TMP3, LFUNC:RB->ffid
  4247. | xori TMP2, TMP1, FRAME_VARG
  4248. | cmplwi cr1, NARGS8:RC, 0
  4249. | bne >7
  4250. |1:
  4251. | stw LFUNC:RB, FRAME_FUNC(BASE) // Copy function down, but keep PC.
  4252. | li TMP2, 0
  4253. | cmplwi cr7, TMP3, 1 // (> FF_C) Calling a fast function?
  4254. | beq cr1, >3
  4255. |2:
  4256. | addi TMP3, TMP2, 8
  4257. | lfdx f0, RA, TMP2
  4258. | cmplw cr1, TMP3, NARGS8:RC
  4259. | stfdx f0, BASE, TMP2
  4260. | mr TMP2, TMP3
  4261. | bne cr1, <2
  4262. |3:
  4263. | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+gt
  4264. | beq >5
  4265. |4:
  4266. | ins_callt
  4267. |
  4268. |5: // Tailcall to a fast function with a Lua frame below.
  4269. | lwz INS, -4(TMP1)
  4270. | decode_RA8 RA, INS
  4271. | sub TMP1, BASE, RA
  4272. | lwz LFUNC:TMP1, FRAME_FUNC-8(TMP1)
  4273. | lwz TMP1, LFUNC:TMP1->pc
  4274. | lwz KBASE, PC2PROTO(k)(TMP1) // Need to prepare KBASE.
  4275. | b <4
  4276. |
  4277. |7: // Tailcall from a vararg function.
  4278. | andix. TMP0, TMP2, FRAME_TYPEP
  4279. | bne <1 // Vararg frame below?
  4280. | sub BASE, BASE, TMP2 // Relocate BASE down.
  4281. | lwz TMP1, FRAME_PC(BASE)
  4282. | andix. TMP0, TMP1, FRAME_TYPE
  4283. | b <1
  4284. break;
  4285. case BC_ITERC:
  4286. | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 ((2+1)*8))
  4287. | mr TMP2, BASE
  4288. | add BASE, BASE, RA
  4289. | lwz TMP1, -24(BASE)
  4290. | lwz LFUNC:RB, -20(BASE)
  4291. | lfd f1, -8(BASE)
  4292. | lfd f0, -16(BASE)
  4293. | stw TMP1, 0(BASE) // Copy callable.
  4294. | stw LFUNC:RB, 4(BASE)
  4295. | checkfunc TMP1
  4296. | stfd f1, 16(BASE) // Copy control var.
  4297. | li NARGS8:RC, 16 // Iterators get 2 arguments.
  4298. | stfdu f0, 8(BASE) // Copy state.
  4299. | bne ->vmeta_call
  4300. | ins_call
  4301. break;
  4302. case BC_ITERN:
  4303. | // RA = base*8, (RB = (nresults+1)*8, RC = (nargs+1)*8 (2+1)*8)
  4304. |.if JIT
  4305. | // NYI: add hotloop, record BC_ITERN.
  4306. |.endif
  4307. | add RA, BASE, RA
  4308. | lwz TAB:RB, -12(RA)
  4309. | lwz RC, -4(RA) // Get index from control var.
  4310. | lwz TMP0, TAB:RB->asize
  4311. | lwz TMP1, TAB:RB->array
  4312. | addi PC, PC, 4
  4313. |1: // Traverse array part.
  4314. | cmplw RC, TMP0
  4315. | slwi TMP3, RC, 3
  4316. | bge >5 // Index points after array part?
  4317. | lwzx TMP2, TMP1, TMP3
  4318. | lfdx f0, TMP1, TMP3
  4319. | checknil TMP2
  4320. | lwz INS, -4(PC)
  4321. | beq >4
  4322. |.if DUALNUM
  4323. | stw RC, 4(RA)
  4324. | stw TISNUM, 0(RA)
  4325. |.else
  4326. | tonum_u f1, RC
  4327. |.endif
  4328. | addi RC, RC, 1
  4329. | addis TMP3, PC, -(BCBIAS_J*4 >> 16)
  4330. | stfd f0, 8(RA)
  4331. | decode_RD4 TMP1, INS
  4332. | stw RC, -4(RA) // Update control var.
  4333. | add PC, TMP1, TMP3
  4334. |.if not DUALNUM
  4335. | stfd f1, 0(RA)
  4336. |.endif
  4337. |3:
  4338. | ins_next
  4339. |
  4340. |4: // Skip holes in array part.
  4341. | addi RC, RC, 1
  4342. | b <1
  4343. |
  4344. |5: // Traverse hash part.
  4345. | lwz TMP1, TAB:RB->hmask
  4346. | sub RC, RC, TMP0
  4347. | lwz TMP2, TAB:RB->node
  4348. |6:
  4349. | cmplw RC, TMP1 // End of iteration? Branch to ITERL+1.
  4350. | slwi TMP3, RC, 5
  4351. | bgty <3
  4352. | slwi RB, RC, 3
  4353. | sub TMP3, TMP3, RB
  4354. | lwzx RB, TMP2, TMP3
  4355. | lfdx f0, TMP2, TMP3
  4356. | add NODE:TMP3, TMP2, TMP3
  4357. | checknil RB
  4358. | lwz INS, -4(PC)
  4359. | beq >7
  4360. | lfd f1, NODE:TMP3->key
  4361. | addis TMP2, PC, -(BCBIAS_J*4 >> 16)
  4362. | stfd f0, 8(RA)
  4363. | add RC, RC, TMP0
  4364. | decode_RD4 TMP1, INS
  4365. | stfd f1, 0(RA)
  4366. | addi RC, RC, 1
  4367. | add PC, TMP1, TMP2
  4368. | stw RC, -4(RA) // Update control var.
  4369. | b <3
  4370. |
  4371. |7: // Skip holes in hash part.
  4372. | addi RC, RC, 1
  4373. | b <6
  4374. break;
  4375. case BC_ISNEXT:
  4376. | // RA = base*8, RD = target (points to ITERN)
  4377. | add RA, BASE, RA
  4378. | lwz TMP0, -24(RA)
  4379. | lwz CFUNC:TMP1, -20(RA)
  4380. | lwz TMP2, -16(RA)
  4381. | lwz TMP3, -8(RA)
  4382. | cmpwi cr0, TMP2, LJ_TTAB
  4383. | cmpwi cr1, TMP0, LJ_TFUNC
  4384. | cmpwi cr6, TMP3, LJ_TNIL
  4385. | bne cr1, >5
  4386. | lbz TMP1, CFUNC:TMP1->ffid
  4387. | crand 4*cr0+eq, 4*cr0+eq, 4*cr6+eq
  4388. | cmpwi cr7, TMP1, FF_next_N
  4389. | srwi TMP0, RD, 1
  4390. | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq
  4391. | add TMP3, PC, TMP0
  4392. | bne cr0, >5
  4393. | lus TMP1, 0xfffe
  4394. | ori TMP1, TMP1, 0x7fff
  4395. | stw ZERO, -4(RA) // Initialize control var.
  4396. | stw TMP1, -8(RA)
  4397. | addis PC, TMP3, -(BCBIAS_J*4 >> 16)
  4398. |1:
  4399. | ins_next
  4400. |5: // Despecialize bytecode if any of the checks fail.
  4401. | li TMP0, BC_JMP
  4402. | li TMP1, BC_ITERC
  4403. | stb TMP0, -1(PC)
  4404. | addis PC, TMP3, -(BCBIAS_J*4 >> 16)
  4405. | stb TMP1, 3(PC)
  4406. | b <1
  4407. break;
  4408. case BC_VARG:
  4409. | // RA = base*8, RB = (nresults+1)*8, RC = numparams*8
  4410. | lwz TMP0, FRAME_PC(BASE)
  4411. | add RC, BASE, RC
  4412. | add RA, BASE, RA
  4413. | addi RC, RC, FRAME_VARG
  4414. | add TMP2, RA, RB
  4415. | subi TMP3, BASE, 8 // TMP3 = vtop
  4416. | sub RC, RC, TMP0 // RC = vbase
  4417. | // Note: RC may now be even _above_ BASE if nargs was < numparams.
  4418. | cmplwi cr1, RB, 0
  4419. |.if PPE
  4420. | sub TMP1, TMP3, RC
  4421. | cmpwi TMP1, 0
  4422. |.else
  4423. | sub. TMP1, TMP3, RC
  4424. |.endif
  4425. | beq cr1, >5 // Copy all varargs?
  4426. | subi TMP2, TMP2, 16
  4427. | ble >2 // No vararg slots?
  4428. |1: // Copy vararg slots to destination slots.
  4429. | lfd f0, 0(RC)
  4430. | addi RC, RC, 8
  4431. | stfd f0, 0(RA)
  4432. | cmplw RA, TMP2
  4433. | cmplw cr1, RC, TMP3
  4434. | bge >3 // All destination slots filled?
  4435. | addi RA, RA, 8
  4436. | blt cr1, <1 // More vararg slots?
  4437. |2: // Fill up remainder with nil.
  4438. | stw TISNIL, 0(RA)
  4439. | cmplw RA, TMP2
  4440. | addi RA, RA, 8
  4441. | blt <2
  4442. |3:
  4443. | ins_next
  4444. |
  4445. |5: // Copy all varargs.
  4446. | lwz TMP0, L->maxstack
  4447. | li MULTRES, 8 // MULTRES = (0+1)*8
  4448. | bley <3 // No vararg slots?
  4449. | add TMP2, RA, TMP1
  4450. | cmplw TMP2, TMP0
  4451. | addi MULTRES, TMP1, 8
  4452. | bgt >7
  4453. |6:
  4454. | lfd f0, 0(RC)
  4455. | addi RC, RC, 8
  4456. | stfd f0, 0(RA)
  4457. | cmplw RC, TMP3
  4458. | addi RA, RA, 8
  4459. | blt <6 // More vararg slots?
  4460. | b <3
  4461. |
  4462. |7: // Grow stack for varargs.
  4463. | mr CARG1, L
  4464. | stp RA, L->top
  4465. | sub SAVE0, RC, BASE // Need delta, because BASE may change.
  4466. | stp BASE, L->base
  4467. | sub RA, RA, BASE
  4468. | stw PC, SAVE_PC
  4469. | srwi CARG2, TMP1, 3
  4470. | bl extern lj_state_growstack // (lua_State *L, int n)
  4471. | lp BASE, L->base
  4472. | add RA, BASE, RA
  4473. | add RC, BASE, SAVE0
  4474. | subi TMP3, BASE, 8
  4475. | b <6
  4476. break;
  4477. /* -- Returns ----------------------------------------------------------- */
  4478. case BC_RETM:
  4479. | // RA = results*8, RD = extra_nresults*8
  4480. | add RD, RD, MULTRES // MULTRES >= 8, so RD >= 8.
  4481. | // Fall through. Assumes BC_RET follows.
  4482. break;
  4483. case BC_RET:
  4484. | // RA = results*8, RD = (nresults+1)*8
  4485. | lwz PC, FRAME_PC(BASE)
  4486. | add RA, BASE, RA
  4487. | mr MULTRES, RD
  4488. |1:
  4489. | andix. TMP0, PC, FRAME_TYPE
  4490. | xori TMP1, PC, FRAME_VARG
  4491. | bne ->BC_RETV_Z
  4492. |
  4493. |->BC_RET_Z:
  4494. | // BASE = base, RA = resultptr, RD = (nresults+1)*8, PC = return
  4495. | lwz INS, -4(PC)
  4496. | cmpwi RD, 8
  4497. | subi TMP2, BASE, 8
  4498. | subi RC, RD, 8
  4499. | decode_RB8 RB, INS
  4500. | beq >3
  4501. | li TMP1, 0
  4502. |2:
  4503. | addi TMP3, TMP1, 8
  4504. | lfdx f0, RA, TMP1
  4505. | cmpw TMP3, RC
  4506. | stfdx f0, TMP2, TMP1
  4507. | beq >3
  4508. | addi TMP1, TMP3, 8
  4509. | lfdx f1, RA, TMP3
  4510. | cmpw TMP1, RC
  4511. | stfdx f1, TMP2, TMP3
  4512. | bne <2
  4513. |3:
  4514. |5:
  4515. | cmplw RB, RD
  4516. | decode_RA8 RA, INS
  4517. | bgt >6
  4518. | sub BASE, TMP2, RA
  4519. | lwz LFUNC:TMP1, FRAME_FUNC(BASE)
  4520. | ins_next1
  4521. | lwz TMP1, LFUNC:TMP1->pc
  4522. | lwz KBASE, PC2PROTO(k)(TMP1)
  4523. | ins_next2
  4524. |
  4525. |6: // Fill up results with nil.
  4526. | subi TMP1, RD, 8
  4527. | addi RD, RD, 8
  4528. | stwx TISNIL, TMP2, TMP1
  4529. | b <5
  4530. |
  4531. |->BC_RETV_Z: // Non-standard return case.
  4532. | andix. TMP2, TMP1, FRAME_TYPEP
  4533. | bne ->vm_return
  4534. | // Return from vararg function: relocate BASE down.
  4535. | sub BASE, BASE, TMP1
  4536. | lwz PC, FRAME_PC(BASE)
  4537. | b <1
  4538. break;
  4539. case BC_RET0: case BC_RET1:
  4540. | // RA = results*8, RD = (nresults+1)*8
  4541. | lwz PC, FRAME_PC(BASE)
  4542. | add RA, BASE, RA
  4543. | mr MULTRES, RD
  4544. | andix. TMP0, PC, FRAME_TYPE
  4545. | xori TMP1, PC, FRAME_VARG
  4546. | bney ->BC_RETV_Z
  4547. |
  4548. | lwz INS, -4(PC)
  4549. | subi TMP2, BASE, 8
  4550. | decode_RB8 RB, INS
  4551. if (op == BC_RET1) {
  4552. | lfd f0, 0(RA)
  4553. | stfd f0, 0(TMP2)
  4554. }
  4555. |5:
  4556. | cmplw RB, RD
  4557. | decode_RA8 RA, INS
  4558. | bgt >6
  4559. | sub BASE, TMP2, RA
  4560. | lwz LFUNC:TMP1, FRAME_FUNC(BASE)
  4561. | ins_next1
  4562. | lwz TMP1, LFUNC:TMP1->pc
  4563. | lwz KBASE, PC2PROTO(k)(TMP1)
  4564. | ins_next2
  4565. |
  4566. |6: // Fill up results with nil.
  4567. | subi TMP1, RD, 8
  4568. | addi RD, RD, 8
  4569. | stwx TISNIL, TMP2, TMP1
  4570. | b <5
  4571. break;
  4572. /* -- Loops and branches ------------------------------------------------ */
  4573. case BC_FORL:
  4574. |.if JIT
  4575. | hotloop
  4576. |.endif
  4577. | // Fall through. Assumes BC_IFORL follows.
  4578. break;
  4579. case BC_JFORI:
  4580. case BC_JFORL:
  4581. #if !LJ_HASJIT
  4582. break;
  4583. #endif
  4584. case BC_FORI:
  4585. case BC_IFORL:
  4586. | // RA = base*8, RD = target (after end of loop or start of loop)
  4587. vk = (op == BC_IFORL || op == BC_JFORL);
  4588. |.if DUALNUM
  4589. | // Integer loop.
  4590. | lwzux TMP1, RA, BASE
  4591. | lwz CARG1, FORL_IDX*8+4(RA)
  4592. | cmplw cr0, TMP1, TISNUM
  4593. if (vk) {
  4594. | lwz CARG3, FORL_STEP*8+4(RA)
  4595. | bne >9
  4596. |.if GPR64
  4597. | // Need to check overflow for (a<<32) + (b<<32).
  4598. | rldicr TMP0, CARG1, 32, 31
  4599. | rldicr TMP2, CARG3, 32, 31
  4600. | add CARG1, CARG1, CARG3
  4601. | addo. TMP0, TMP0, TMP2
  4602. |.else
  4603. | addo. CARG1, CARG1, CARG3
  4604. |.endif
  4605. | cmpwi cr6, CARG3, 0
  4606. | lwz CARG2, FORL_STOP*8+4(RA)
  4607. | bso >6
  4608. |4:
  4609. | stw CARG1, FORL_IDX*8+4(RA)
  4610. } else {
  4611. | lwz TMP3, FORL_STEP*8(RA)
  4612. | lwz CARG3, FORL_STEP*8+4(RA)
  4613. | lwz TMP2, FORL_STOP*8(RA)
  4614. | lwz CARG2, FORL_STOP*8+4(RA)
  4615. | cmplw cr7, TMP3, TISNUM
  4616. | cmplw cr1, TMP2, TISNUM
  4617. | crand 4*cr0+eq, 4*cr0+eq, 4*cr7+eq
  4618. | crand 4*cr0+eq, 4*cr0+eq, 4*cr1+eq
  4619. | cmpwi cr6, CARG3, 0
  4620. | bne >9
  4621. }
  4622. | blt cr6, >5
  4623. | cmpw CARG1, CARG2
  4624. |1:
  4625. | stw TISNUM, FORL_EXT*8(RA)
  4626. if (op != BC_JFORL) {
  4627. | srwi RD, RD, 1
  4628. }
  4629. | stw CARG1, FORL_EXT*8+4(RA)
  4630. if (op != BC_JFORL) {
  4631. | add RD, PC, RD
  4632. }
  4633. if (op == BC_FORI) {
  4634. | bgt >3 // See FP loop below.
  4635. } else if (op == BC_JFORI) {
  4636. | addis PC, RD, -(BCBIAS_J*4 >> 16)
  4637. | bley >7
  4638. } else if (op == BC_IFORL) {
  4639. | bgt >2
  4640. | addis PC, RD, -(BCBIAS_J*4 >> 16)
  4641. } else {
  4642. | bley =>BC_JLOOP
  4643. }
  4644. |2:
  4645. | ins_next
  4646. |5: // Invert check for negative step.
  4647. | cmpw CARG2, CARG1
  4648. | b <1
  4649. if (vk) {
  4650. |6: // Potential overflow.
  4651. | mcrxr cr0; bley <4 // Ignore unrelated overflow.
  4652. | b <2
  4653. }
  4654. |.endif
  4655. if (vk) {
  4656. |.if DUALNUM
  4657. |9: // FP loop.
  4658. | lfd f1, FORL_IDX*8(RA)
  4659. |.else
  4660. | lfdux f1, RA, BASE
  4661. |.endif
  4662. | lfd f3, FORL_STEP*8(RA)
  4663. | lfd f2, FORL_STOP*8(RA)
  4664. | lwz TMP3, FORL_STEP*8(RA)
  4665. | fadd f1, f1, f3
  4666. | stfd f1, FORL_IDX*8(RA)
  4667. } else {
  4668. |.if DUALNUM
  4669. |9: // FP loop.
  4670. |.else
  4671. | lwzux TMP1, RA, BASE
  4672. | lwz TMP3, FORL_STEP*8(RA)
  4673. | lwz TMP2, FORL_STOP*8(RA)
  4674. | cmplw cr0, TMP1, TISNUM
  4675. | cmplw cr7, TMP3, TISNUM
  4676. | cmplw cr1, TMP2, TISNUM
  4677. |.endif
  4678. | lfd f1, FORL_IDX*8(RA)
  4679. | crand 4*cr0+lt, 4*cr0+lt, 4*cr7+lt
  4680. | crand 4*cr0+lt, 4*cr0+lt, 4*cr1+lt
  4681. | lfd f2, FORL_STOP*8(RA)
  4682. | bge ->vmeta_for
  4683. }
  4684. | cmpwi cr6, TMP3, 0
  4685. if (op != BC_JFORL) {
  4686. | srwi RD, RD, 1
  4687. }
  4688. | stfd f1, FORL_EXT*8(RA)
  4689. if (op != BC_JFORL) {
  4690. | add RD, PC, RD
  4691. }
  4692. | fcmpu cr0, f1, f2
  4693. if (op == BC_JFORI) {
  4694. | addis PC, RD, -(BCBIAS_J*4 >> 16)
  4695. }
  4696. | blt cr6, >5
  4697. if (op == BC_FORI) {
  4698. | bgt >3
  4699. } else if (op == BC_IFORL) {
  4700. |.if DUALNUM
  4701. | bgty <2
  4702. |.else
  4703. | bgt >2
  4704. |.endif
  4705. |1:
  4706. | addis PC, RD, -(BCBIAS_J*4 >> 16)
  4707. } else if (op == BC_JFORI) {
  4708. | bley >7
  4709. } else {
  4710. | bley =>BC_JLOOP
  4711. }
  4712. |.if DUALNUM
  4713. | b <2
  4714. |.else
  4715. |2:
  4716. | ins_next
  4717. |.endif
  4718. |5: // Negative step.
  4719. if (op == BC_FORI) {
  4720. | bge <2
  4721. |3: // Used by integer loop, too.
  4722. | addis PC, RD, -(BCBIAS_J*4 >> 16)
  4723. } else if (op == BC_IFORL) {
  4724. | bgey <1
  4725. } else if (op == BC_JFORI) {
  4726. | bgey >7
  4727. } else {
  4728. | bgey =>BC_JLOOP
  4729. }
  4730. | b <2
  4731. if (op == BC_JFORI) {
  4732. |7:
  4733. | lwz INS, -4(PC)
  4734. | decode_RD8 RD, INS
  4735. | b =>BC_JLOOP
  4736. }
  4737. break;
  4738. case BC_ITERL:
  4739. |.if JIT
  4740. | hotloop
  4741. |.endif
  4742. | // Fall through. Assumes BC_IITERL follows.
  4743. break;
  4744. case BC_JITERL:
  4745. #if !LJ_HASJIT
  4746. break;
  4747. #endif
  4748. case BC_IITERL:
  4749. | // RA = base*8, RD = target
  4750. | lwzux TMP1, RA, BASE
  4751. | lwz TMP2, 4(RA)
  4752. | checknil TMP1; beq >1 // Stop if iterator returned nil.
  4753. if (op == BC_JITERL) {
  4754. | stw TMP1, -8(RA)
  4755. | stw TMP2, -4(RA)
  4756. | b =>BC_JLOOP
  4757. } else {
  4758. | branch_RD // Otherwise save control var + branch.
  4759. | stw TMP1, -8(RA)
  4760. | stw TMP2, -4(RA)
  4761. }
  4762. |1:
  4763. | ins_next
  4764. break;
  4765. case BC_LOOP:
  4766. | // RA = base*8, RD = target (loop extent)
  4767. | // Note: RA/RD is only used by trace recorder to determine scope/extent
  4768. | // This opcode does NOT jump, it's only purpose is to detect a hot loop.
  4769. |.if JIT
  4770. | hotloop
  4771. |.endif
  4772. | // Fall through. Assumes BC_ILOOP follows.
  4773. break;
  4774. case BC_ILOOP:
  4775. | // RA = base*8, RD = target (loop extent)
  4776. | ins_next
  4777. break;
  4778. case BC_JLOOP:
  4779. |.if JIT
  4780. | // RA = base*8 (ignored), RD = traceno*8
  4781. | lwz TMP1, DISPATCH_J(trace)(DISPATCH)
  4782. | srwi RD, RD, 1
  4783. | // Traces on PPC don't store the trace number, so use 0.
  4784. | stw ZERO, DISPATCH_GL(vmstate)(DISPATCH)
  4785. | lwzx TRACE:TMP2, TMP1, RD
  4786. | mcrxr cr0 // Clear SO flag.
  4787. | lp TMP2, TRACE:TMP2->mcode
  4788. | stw BASE, DISPATCH_GL(jit_base)(DISPATCH)
  4789. | mtctr TMP2
  4790. | stw L, DISPATCH_GL(jit_L)(DISPATCH)
  4791. | addi JGL, DISPATCH, GG_DISP2G+32768
  4792. | bctr
  4793. |.endif
  4794. break;
  4795. case BC_JMP:
  4796. | // RA = base*8 (only used by trace recorder), RD = target
  4797. | branch_RD
  4798. | ins_next
  4799. break;
  4800. /* -- Function headers -------------------------------------------------- */
  4801. case BC_FUNCF:
  4802. |.if JIT
  4803. | hotcall
  4804. |.endif
  4805. case BC_FUNCV: /* NYI: compiled vararg functions. */
  4806. | // Fall through. Assumes BC_IFUNCF/BC_IFUNCV follow.
  4807. break;
  4808. case BC_JFUNCF:
  4809. #if !LJ_HASJIT
  4810. break;
  4811. #endif
  4812. case BC_IFUNCF:
  4813. | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8
  4814. | lwz TMP2, L->maxstack
  4815. | lbz TMP1, -4+PC2PROTO(numparams)(PC)
  4816. | lwz KBASE, -4+PC2PROTO(k)(PC)
  4817. | cmplw RA, TMP2
  4818. | slwi TMP1, TMP1, 3
  4819. | bgt ->vm_growstack_l
  4820. if (op != BC_JFUNCF) {
  4821. | ins_next1
  4822. }
  4823. |2:
  4824. | cmplw NARGS8:RC, TMP1 // Check for missing parameters.
  4825. | blt >3
  4826. if (op == BC_JFUNCF) {
  4827. | decode_RD8 RD, INS
  4828. | b =>BC_JLOOP
  4829. } else {
  4830. | ins_next2
  4831. }
  4832. |
  4833. |3: // Clear missing parameters.
  4834. | stwx TISNIL, BASE, NARGS8:RC
  4835. | addi NARGS8:RC, NARGS8:RC, 8
  4836. | b <2
  4837. break;
  4838. case BC_JFUNCV:
  4839. #if !LJ_HASJIT
  4840. break;
  4841. #endif
  4842. | NYI // NYI: compiled vararg functions
  4843. break; /* NYI: compiled vararg functions. */
  4844. case BC_IFUNCV:
  4845. | // BASE = new base, RA = BASE+framesize*8, RB = LFUNC, RC = nargs*8
  4846. | lwz TMP2, L->maxstack
  4847. | add TMP1, BASE, RC
  4848. | add TMP0, RA, RC
  4849. | stw LFUNC:RB, 4(TMP1) // Store copy of LFUNC.
  4850. | addi TMP3, RC, 8+FRAME_VARG
  4851. | lwz KBASE, -4+PC2PROTO(k)(PC)
  4852. | cmplw TMP0, TMP2
  4853. | stw TMP3, 0(TMP1) // Store delta + FRAME_VARG.
  4854. | bge ->vm_growstack_l
  4855. | lbz TMP2, -4+PC2PROTO(numparams)(PC)
  4856. | mr RA, BASE
  4857. | mr RC, TMP1
  4858. | ins_next1
  4859. | cmpwi TMP2, 0
  4860. | addi BASE, TMP1, 8
  4861. | beq >3
  4862. |1:
  4863. | cmplw RA, RC // Less args than parameters?
  4864. | lwz TMP0, 0(RA)
  4865. | lwz TMP3, 4(RA)
  4866. | bge >4
  4867. | stw TISNIL, 0(RA) // Clear old fixarg slot (help the GC).
  4868. | addi RA, RA, 8
  4869. |2:
  4870. | addic. TMP2, TMP2, -1
  4871. | stw TMP0, 8(TMP1)
  4872. | stw TMP3, 12(TMP1)
  4873. | addi TMP1, TMP1, 8
  4874. | bne <1
  4875. |3:
  4876. | ins_next2
  4877. |
  4878. |4: // Clear missing parameters.
  4879. | li TMP0, LJ_TNIL
  4880. | b <2
  4881. break;
  4882. case BC_FUNCC:
  4883. case BC_FUNCCW:
  4884. | // BASE = new base, RA = BASE+framesize*8, RB = CFUNC, RC = nargs*8
  4885. if (op == BC_FUNCC) {
  4886. | lp RD, CFUNC:RB->f
  4887. } else {
  4888. | lp RD, DISPATCH_GL(wrapf)(DISPATCH)
  4889. }
  4890. | add TMP1, RA, NARGS8:RC
  4891. | lwz TMP2, L->maxstack
  4892. | .toc lp TMP3, 0(RD)
  4893. | add RC, BASE, NARGS8:RC
  4894. | stp BASE, L->base
  4895. | cmplw TMP1, TMP2
  4896. | stp RC, L->top
  4897. | li_vmstate C
  4898. |.if TOC
  4899. | mtctr TMP3
  4900. |.else
  4901. | mtctr RD
  4902. |.endif
  4903. if (op == BC_FUNCCW) {
  4904. | lp CARG2, CFUNC:RB->f
  4905. }
  4906. | mr CARG1, L
  4907. | bgt ->vm_growstack_c // Need to grow stack.
  4908. | .toc lp TOCREG, TOC_OFS(RD)
  4909. | .tocenv lp ENVREG, ENV_OFS(RD)
  4910. | st_vmstate
  4911. | bctrl // (lua_State *L [, lua_CFunction f])
  4912. | // Returns nresults.
  4913. | lp BASE, L->base
  4914. | .toc ld TOCREG, SAVE_TOC
  4915. | slwi RD, CRET1, 3
  4916. | lp TMP1, L->top
  4917. | li_vmstate INTERP
  4918. | lwz PC, FRAME_PC(BASE) // Fetch PC of caller.
  4919. | sub RA, TMP1, RD // RA = L->top - nresults*8
  4920. | st_vmstate
  4921. | b ->vm_returnc
  4922. break;
  4923. /* ---------------------------------------------------------------------- */
  4924. default:
  4925. fprintf(stderr, "Error: undefined opcode BC_%s\n", bc_names[op]);
  4926. exit(2);
  4927. break;
  4928. }
  4929. }
  4930. static int build_backend(BuildCtx *ctx)
  4931. {
  4932. int op;
  4933. dasm_growpc(Dst, BC__MAX);
  4934. build_subroutines(ctx);
  4935. |.code_op
  4936. for (op = 0; op < BC__MAX; op++)
  4937. build_ins(ctx, (BCOp)op, op);
  4938. return BC__MAX;
  4939. }
  4940. /* Emit pseudo frame-info for all assembler functions. */
  4941. static void emit_asm_debug(BuildCtx *ctx)
  4942. {
  4943. int fcofs = (int)((uint8_t *)ctx->glob[GLOB_vm_ffi_call] - ctx->code);
  4944. int i;
  4945. switch (ctx->mode) {
  4946. case BUILD_elfasm:
  4947. fprintf(ctx->fp, "\t.section .debug_frame,\"\",@progbits\n");
  4948. fprintf(ctx->fp,
  4949. ".Lframe0:\n"
  4950. "\t.long .LECIE0-.LSCIE0\n"
  4951. ".LSCIE0:\n"
  4952. "\t.long 0xffffffff\n"
  4953. "\t.byte 0x1\n"
  4954. "\t.string \"\"\n"
  4955. "\t.uleb128 0x1\n"
  4956. "\t.sleb128 -4\n"
  4957. "\t.byte 65\n"
  4958. "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n"
  4959. "\t.align 2\n"
  4960. ".LECIE0:\n\n");
  4961. fprintf(ctx->fp,
  4962. ".LSFDE0:\n"
  4963. "\t.long .LEFDE0-.LASFDE0\n"
  4964. ".LASFDE0:\n"
  4965. "\t.long .Lframe0\n"
  4966. "\t.long .Lbegin\n"
  4967. "\t.long %d\n"
  4968. "\t.byte 0xe\n\t.uleb128 %d\n"
  4969. "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n"
  4970. "\t.byte 0x5\n\t.uleb128 70\n\t.uleb128 55\n",
  4971. fcofs, CFRAME_SIZE);
  4972. for (i = 14; i <= 31; i++)
  4973. fprintf(ctx->fp,
  4974. "\t.byte %d\n\t.uleb128 %d\n"
  4975. "\t.byte %d\n\t.uleb128 %d\n",
  4976. 0x80+i, 37+(31-i), 0x80+32+i, 2+2*(31-i));
  4977. fprintf(ctx->fp,
  4978. "\t.align 2\n"
  4979. ".LEFDE0:\n\n");
  4980. #if LJ_HASFFI
  4981. fprintf(ctx->fp,
  4982. ".LSFDE1:\n"
  4983. "\t.long .LEFDE1-.LASFDE1\n"
  4984. ".LASFDE1:\n"
  4985. "\t.long .Lframe0\n"
  4986. #if LJ_TARGET_PS3
  4987. "\t.long .lj_vm_ffi_call\n"
  4988. #else
  4989. "\t.long lj_vm_ffi_call\n"
  4990. #endif
  4991. "\t.long %d\n"
  4992. "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n"
  4993. "\t.byte 0x8e\n\t.uleb128 2\n"
  4994. "\t.byte 0xd\n\t.uleb128 0xe\n"
  4995. "\t.align 2\n"
  4996. ".LEFDE1:\n\n", (int)ctx->codesz - fcofs);
  4997. #endif
  4998. #if !LJ_NO_UNWIND
  4999. fprintf(ctx->fp, "\t.section .eh_frame,\"a\",@progbits\n");
  5000. fprintf(ctx->fp,
  5001. ".Lframe1:\n"
  5002. "\t.long .LECIE1-.LSCIE1\n"
  5003. ".LSCIE1:\n"
  5004. "\t.long 0\n"
  5005. "\t.byte 0x1\n"
  5006. "\t.string \"zPR\"\n"
  5007. "\t.uleb128 0x1\n"
  5008. "\t.sleb128 -4\n"
  5009. "\t.byte 65\n"
  5010. "\t.uleb128 6\n" /* augmentation length */
  5011. "\t.byte 0x1b\n" /* pcrel|sdata4 */
  5012. "\t.long lj_err_unwind_dwarf-.\n"
  5013. "\t.byte 0x1b\n" /* pcrel|sdata4 */
  5014. "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n"
  5015. "\t.align 2\n"
  5016. ".LECIE1:\n\n");
  5017. fprintf(ctx->fp,
  5018. ".LSFDE2:\n"
  5019. "\t.long .LEFDE2-.LASFDE2\n"
  5020. ".LASFDE2:\n"
  5021. "\t.long .LASFDE2-.Lframe1\n"
  5022. "\t.long .Lbegin-.\n"
  5023. "\t.long %d\n"
  5024. "\t.uleb128 0\n" /* augmentation length */
  5025. "\t.byte 0xe\n\t.uleb128 %d\n"
  5026. "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n"
  5027. "\t.byte 0x5\n\t.uleb128 70\n\t.uleb128 55\n",
  5028. fcofs, CFRAME_SIZE);
  5029. for (i = 14; i <= 31; i++)
  5030. fprintf(ctx->fp,
  5031. "\t.byte %d\n\t.uleb128 %d\n"
  5032. "\t.byte %d\n\t.uleb128 %d\n",
  5033. 0x80+i, 37+(31-i), 0x80+32+i, 2+2*(31-i));
  5034. fprintf(ctx->fp,
  5035. "\t.align 2\n"
  5036. ".LEFDE2:\n\n");
  5037. #if LJ_HASFFI
  5038. fprintf(ctx->fp,
  5039. ".Lframe2:\n"
  5040. "\t.long .LECIE2-.LSCIE2\n"
  5041. ".LSCIE2:\n"
  5042. "\t.long 0\n"
  5043. "\t.byte 0x1\n"
  5044. "\t.string \"zR\"\n"
  5045. "\t.uleb128 0x1\n"
  5046. "\t.sleb128 -4\n"
  5047. "\t.byte 65\n"
  5048. "\t.uleb128 1\n" /* augmentation length */
  5049. "\t.byte 0x1b\n" /* pcrel|sdata4 */
  5050. "\t.byte 0xc\n\t.uleb128 1\n\t.uleb128 0\n"
  5051. "\t.align 2\n"
  5052. ".LECIE2:\n\n");
  5053. fprintf(ctx->fp,
  5054. ".LSFDE3:\n"
  5055. "\t.long .LEFDE3-.LASFDE3\n"
  5056. ".LASFDE3:\n"
  5057. "\t.long .LASFDE3-.Lframe2\n"
  5058. "\t.long lj_vm_ffi_call-.\n"
  5059. "\t.long %d\n"
  5060. "\t.uleb128 0\n" /* augmentation length */
  5061. "\t.byte 0x11\n\t.uleb128 65\n\t.sleb128 -1\n"
  5062. "\t.byte 0x8e\n\t.uleb128 2\n"
  5063. "\t.byte 0xd\n\t.uleb128 0xe\n"
  5064. "\t.align 2\n"
  5065. ".LEFDE3:\n\n", (int)ctx->codesz - fcofs);
  5066. #endif
  5067. #endif
  5068. break;
  5069. default:
  5070. break;
  5071. }
  5072. }