3 Star 1 Fork 1

Gitee 极速下载 / AsmJit

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
此仓库是为了提升国内下载速度的镜像仓库,每日同步一次。 原始仓库: https://github.com/asmjit/asmjit
克隆/下载
asmjit_test_compiler_x86.cpp 116.60 KB
一键复制 编辑 原始数据 按行查看 历史
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465246624672468246924702471247224732474247524762477247824792480248124822483248424852486248724882489249024912492249324942495249624972498249925002501250225032504250525062507250825092510251125122513251425152516251725182519252025212522252325242525252625272528252925302531253225332534253525362537253825392540254125422543254425452546254725482549255025512552255325542555255625572558255925602561256225632564256525662567256825692570257125722573257425752576257725782579258025812582258325842585258625872588258925902591259225932594259525962597259825992600260126022603260426052606260726082609261026112612261326142615261626172618261926202621262226232624262526262627262826292630263126322633263426352636263726382639264026412642264326442645264626472648264926502651265226532654265526562657265826592660266126622663266426652666266726682669267026712672267326742675267626772678267926802681268226832684268526862687268826892690269126922693269426952696269726982699270027012702270327042705270627072708270927102711271227132714271527162717271827192720272127222723272427252726272727282729273027312732273327342735273627372738273927402741274227432744274527462747274827492750275127522753275427552756275727582759276027612762276327642765276627672768276927702771277227732774277527762777277827792780278127822783278427852786278727882789279027912792279327942795279627972798279928002801280228032804280528062807280828092810281128122813281428152816281728182819282028212822282328242825282628272828282928302831283228332834283528362837283828392840284128422843284428452846284728482849285028512852285328542855285628572858285928602861286228632864286528662867286828692870287128722873287428752876287728782879288028812882288328842885288628872888288928902891289228932894289528962897289828992900290129022903290429052906290729082909291029112912291329142915291629172918291929202921292229232924292529262927292829292930293129322933293429352936293729382939294029412942294329442945294629472948294929502951295229532954295529562957295829592960296129622963296429652966296729682969297029712972297329742975297629772978297929802981298229832984298529862987298829892990299129922993299429952996299729982999300030013002300330043005300630073008300930103011301230133014301530163017301830193020302130223023302430253026302730283029303030313032303330343035303630373038303930403041304230433044304530463047304830493050305130523053305430553056305730583059306030613062306330643065306630673068306930703071307230733074307530763077307830793080308130823083308430853086308730883089309030913092309330943095309630973098309931003101310231033104310531063107310831093110311131123113311431153116311731183119312031213122312331243125312631273128312931303131313231333134313531363137313831393140314131423143314431453146314731483149315031513152315331543155315631573158315931603161316231633164316531663167316831693170317131723173317431753176317731783179318031813182318331843185318631873188318931903191319231933194319531963197319831993200320132023203320432053206320732083209321032113212321332143215321632173218321932203221322232233224322532263227322832293230323132323233323432353236323732383239324032413242324332443245324632473248324932503251325232533254325532563257325832593260326132623263326432653266326732683269327032713272327332743275327632773278327932803281328232833284328532863287328832893290329132923293329432953296329732983299330033013302330333043305330633073308330933103311331233133314331533163317331833193320332133223323332433253326332733283329333033313332333333343335333633373338333933403341334233433344334533463347334833493350335133523353335433553356335733583359336033613362336333643365336633673368336933703371337233733374337533763377337833793380338133823383338433853386338733883389339033913392339333943395339633973398339934003401340234033404340534063407340834093410341134123413341434153416341734183419342034213422342334243425342634273428342934303431343234333434343534363437343834393440344134423443344434453446344734483449345034513452345334543455345634573458345934603461346234633464346534663467346834693470347134723473347434753476347734783479348034813482348334843485348634873488348934903491349234933494349534963497349834993500350135023503350435053506350735083509351035113512351335143515351635173518351935203521352235233524352535263527352835293530353135323533353435353536353735383539354035413542354335443545354635473548354935503551355235533554355535563557355835593560356135623563356435653566356735683569357035713572357335743575357635773578357935803581358235833584358535863587358835893590359135923593359435953596359735983599360036013602360336043605360636073608360936103611361236133614361536163617361836193620362136223623362436253626362736283629363036313632363336343635363636373638363936403641364236433644364536463647364836493650365136523653365436553656365736583659366036613662366336643665366636673668366936703671367236733674367536763677367836793680368136823683368436853686368736883689369036913692369336943695369636973698369937003701370237033704370537063707370837093710371137123713371437153716371737183719372037213722372337243725372637273728372937303731373237333734373537363737373837393740374137423743374437453746374737483749375037513752375337543755375637573758375937603761376237633764376537663767376837693770377137723773377437753776377737783779378037813782378337843785378637873788378937903791379237933794379537963797379837993800380138023803380438053806380738083809381038113812381338143815381638173818381938203821382238233824382538263827382838293830383138323833383438353836383738383839384038413842384338443845384638473848384938503851385238533854385538563857385838593860386138623863386438653866386738683869387038713872387338743875387638773878387938803881388238833884388538863887388838893890389138923893389438953896389738983899390039013902390339043905390639073908390939103911391239133914391539163917391839193920392139223923392439253926392739283929393039313932393339343935393639373938393939403941394239433944394539463947394839493950395139523953395439553956395739583959396039613962396339643965396639673968396939703971397239733974397539763977397839793980398139823983398439853986398739883989399039913992399339943995399639973998399940004001400240034004400540064007400840094010401140124013401440154016401740184019402040214022402340244025402640274028402940304031403240334034403540364037403840394040404140424043404440454046404740484049405040514052405340544055405640574058405940604061406240634064406540664067406840694070407140724073407440754076407740784079408040814082408340844085408640874088408940904091409240934094409540964097409840994100410141024103410441054106410741084109411041114112411341144115411641174118411941204121412241234124412541264127412841294130413141324133413441354136413741384139414041414142414341444145414641474148414941504151415241534154415541564157415841594160416141624163416441654166416741684169417041714172417341744175417641774178417941804181418241834184418541864187418841894190419141924193419441954196419741984199420042014202420342044205420642074208420942104211421242134214421542164217421842194220422142224223422442254226422742284229423042314232423342344235423642374238423942404241424242434244424542464247424842494250425142524253425442554256425742584259426042614262426342644265426642674268426942704271427242734274427542764277427842794280428142824283428442854286428742884289429042914292429342944295429642974298429943004301430243034304430543064307430843094310431143124313431443154316431743184319432043214322432343244325432643274328432943304331433243334334433543364337433843394340434143424343434443454346434743484349435043514352435343544355435643574358435943604361436243634364436543664367436843694370437143724373437443754376437743784379438043814382438343844385438643874388438943904391439243934394439543964397439843994400440144024403440444054406440744084409441044114412441344144415441644174418441944204421442244234424442544264427442844294430443144324433443444354436443744384439444044414442444344444445444644474448444944504451445244534454445544564457445844594460446144624463446444654466446744684469447044714472447344744475447644774478447944804481448244834484448544864487448844894490449144924493449444954496449744984499450045014502450345044505450645074508450945104511451245134514451545164517451845194520452145224523452445254526452745284529453045314532453345344535453645374538453945404541454245434544454545464547454845494550455145524553455445554556455745584559456045614562456345644565456645674568456945704571457245734574457545764577
// This file is part of AsmJit project <https://asmjit.com>
//
// See asmjit.h or LICENSE.md for license and copyright information
// SPDX-License-Identifier: Zlib
#include <asmjit/core.h>
#if !defined(ASMJIT_NO_X86) && !defined(ASMJIT_NO_COMPILER)
#include <asmjit/x86.h>
#include <setjmp.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if ASMJIT_ARCH_X86
// Required for function tests that pass / return XMM registers.
#include <emmintrin.h>
#endif
#include "asmjit_test_misc.h"
#include "asmjit_test_compiler.h"
#ifdef _MSC_VER
// Interaction between '_setjmp' and C++ object destruction is non-portable.
#pragma warning(disable: 4611)
#endif
using namespace asmjit;
// x86::Compiler - X86TestCase
// ===========================
class X86TestCase : public TestCase {
public:
X86TestCase(const char* name = nullptr)
: TestCase(name, Arch::kHost == Arch::kX86 ? Arch::kX86 : Arch::kX64) {}
virtual void compile(BaseCompiler& cc) override {
compile(static_cast<x86::Compiler&>(cc));
}
virtual void compile(x86::Compiler& cc) = 0;
};
// x86::Compiler - X86Test_AlignBase
// =================================
class X86Test_AlignBase : public X86TestCase {
public:
X86Test_AlignBase(uint32_t argCount, uint32_t alignment, bool preserveFP)
: _argCount(argCount),
_alignment(alignment),
_preserveFP(preserveFP) {
_name.assignFormat("AlignBase {NumArgs=%u Alignment=%u PreserveFP=%c}", argCount, alignment, preserveFP ? 'Y' : 'N');
}
static void add(TestApp& app) {
for (uint32_t i = 0; i <= 16; i++) {
for (uint32_t a = 16; a <= 32; a += 16) {
app.add(new X86Test_AlignBase(i, a, true));
app.add(new X86Test_AlignBase(i, a, false));
}
}
}
virtual void compile(x86::Compiler& cc) {
uint32_t i;
uint32_t argCount = _argCount;
FuncSignature signature(CallConvId::kCDecl);
signature.setRetT<int>();
for (i = 0; i < argCount; i++)
signature.addArgT<int>();
FuncNode* funcNode = cc.addFunc(signature);
if (_preserveFP)
funcNode->frame().setPreservedFP();
x86::Gp gpVar = cc.newIntPtr("gpVar");
x86::Gp gpSum;
x86::Mem stack = cc.newStack(_alignment, _alignment);
// Do a sum of arguments to verify a possible relocation when misaligned.
if (argCount) {
for (i = 0; i < argCount; i++) {
x86::Gp gpArg = cc.newInt32("gpArg%u", i);
funcNode->setArg(i, gpArg);
if (i == 0)
gpSum = gpArg;
else
cc.add(gpSum, gpArg);
}
}
// Check alignment of xmmVar (has to be 16).
cc.lea(gpVar, stack);
cc.and_(gpVar, _alignment - 1);
// Add a sum of all arguments to check if they are correct.
if (argCount)
cc.or_(gpVar.r32(), gpSum);
cc.ret(gpVar);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef unsigned int U;
typedef U (*Func0)();
typedef U (*Func1)(U);
typedef U (*Func2)(U, U);
typedef U (*Func3)(U, U, U);
typedef U (*Func4)(U, U, U, U);
typedef U (*Func5)(U, U, U, U, U);
typedef U (*Func6)(U, U, U, U, U, U);
typedef U (*Func7)(U, U, U, U, U, U, U);
typedef U (*Func8)(U, U, U, U, U, U, U, U);
typedef U (*Func9)(U, U, U, U, U, U, U, U, U);
typedef U (*Func10)(U, U, U, U, U, U, U, U, U, U);
typedef U (*Func11)(U, U, U, U, U, U, U, U, U, U, U);
typedef U (*Func12)(U, U, U, U, U, U, U, U, U, U, U, U);
typedef U (*Func13)(U, U, U, U, U, U, U, U, U, U, U, U, U);
typedef U (*Func14)(U, U, U, U, U, U, U, U, U, U, U, U, U, U);
typedef U (*Func15)(U, U, U, U, U, U, U, U, U, U, U, U, U, U, U);
typedef U (*Func16)(U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U);
unsigned int resultRet = 0;
unsigned int expectRet = 0;
switch (_argCount) {
case 0:
resultRet = ptr_as_func<Func0>(_func)();
expectRet = 0;
break;
case 1:
resultRet = ptr_as_func<Func1>(_func)(1);
expectRet = 1;
break;
case 2:
resultRet = ptr_as_func<Func2>(_func)(1, 2);
expectRet = 1 + 2;
break;
case 3:
resultRet = ptr_as_func<Func3>(_func)(1, 2, 3);
expectRet = 1 + 2 + 3;
break;
case 4:
resultRet = ptr_as_func<Func4>(_func)(1, 2, 3, 4);
expectRet = 1 + 2 + 3 + 4;
break;
case 5:
resultRet = ptr_as_func<Func5>(_func)(1, 2, 3, 4, 5);
expectRet = 1 + 2 + 3 + 4 + 5;
break;
case 6:
resultRet = ptr_as_func<Func6>(_func)(1, 2, 3, 4, 5, 6);
expectRet = 1 + 2 + 3 + 4 + 5 + 6;
break;
case 7:
resultRet = ptr_as_func<Func7>(_func)(1, 2, 3, 4, 5, 6, 7);
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7;
break;
case 8:
resultRet = ptr_as_func<Func8>(_func)(1, 2, 3, 4, 5, 6, 7, 8);
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8;
break;
case 9:
resultRet = ptr_as_func<Func9>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9);
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9;
break;
case 10:
resultRet = ptr_as_func<Func10>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10;
break;
case 11:
resultRet = ptr_as_func<Func11>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11);
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11;
break;
case 12:
resultRet = ptr_as_func<Func12>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12;
break;
case 13:
resultRet = ptr_as_func<Func13>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13;
break;
case 14:
resultRet = ptr_as_func<Func14>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14;
break;
case 15:
resultRet = ptr_as_func<Func15>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15);
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15;
break;
case 16:
resultRet = ptr_as_func<Func16>(_func)(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
expectRet = 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + 15 + 16;
break;
}
result.assignFormat("ret={%u, %u}", resultRet >> 28, resultRet & 0x0FFFFFFFu);
expect.assignFormat("ret={%u, %u}", expectRet >> 28, expectRet & 0x0FFFFFFFu);
return result == expect;
}
uint32_t _argCount;
uint32_t _alignment;
bool _preserveFP;
};
// x86::Compiler - X86Test_NoCode
// ==============================
class X86Test_NoCode : public X86TestCase {
public:
X86Test_NoCode() : X86TestCase("NoCode") {}
static void add(TestApp& app) {
app.add(new X86Test_NoCode());
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<void>());
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
DebugUtils::unused(result, expect);
typedef void(*Func)(void);
Func func = ptr_as_func<Func>(_func);
func();
return true;
}
};
// x86::Compiler - X86Test_NoAlign
// ===============================
class X86Test_NoAlign : public X86TestCase {
public:
X86Test_NoAlign() : X86TestCase("NoAlign") {}
static void add(TestApp& app) {
app.add(new X86Test_NoAlign());
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<void>());
cc.align(AlignMode::kCode, 0);
cc.align(AlignMode::kCode, 1);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
DebugUtils::unused(result, expect);
typedef void (*Func)(void);
Func func = ptr_as_func<Func>(_func);
func();
return true;
}
};
// x86::Compiler - X86Test_IndirectBranchProtection
// ================================================
class X86Test_IndirectBranchProtection : public X86TestCase {
public:
X86Test_IndirectBranchProtection() : X86TestCase("IndirectBranchProtection") {}
static void add(TestApp& app) {
app.add(new X86Test_IndirectBranchProtection());
}
virtual void compile(x86::Compiler& cc) {
FuncNode* func = cc.addFunc(FuncSignature::build<void>());
func->addAttributes(FuncAttributes::kIndirectBranchProtection);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
DebugUtils::unused(result, expect);
typedef void (*Func)(void);
Func func = ptr_as_func<Func>(_func);
func();
return true;
}
};
// x86::Compiler - X86Test_JumpMerge
// =================================
class X86Test_JumpMerge : public X86TestCase {
public:
X86Test_JumpMerge() : X86TestCase("JumpMerge") {}
static void add(TestApp& app) {
app.add(new X86Test_JumpMerge());
}
virtual void compile(x86::Compiler& cc) {
Label L0 = cc.newLabel();
Label L1 = cc.newLabel();
Label L2 = cc.newLabel();
Label LEnd = cc.newLabel();
x86::Gp dst = cc.newIntPtr("dst");
x86::Gp val = cc.newInt32("val");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<void, int*, int>());
funcNode->setArg(0, dst);
funcNode->setArg(1, val);
cc.cmp(val, 0);
cc.je(L2);
cc.cmp(val, 1);
cc.je(L1);
cc.cmp(val, 2);
cc.je(L0);
cc.mov(x86::dword_ptr(dst), val);
cc.jmp(LEnd);
// On purpose. This tests whether the CFG constructs a single basic-block
// from multiple labels next to each other.
cc.bind(L0);
cc.bind(L1);
cc.bind(L2);
cc.mov(x86::dword_ptr(dst), 0);
cc.bind(LEnd);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void(*Func)(int*, int);
Func func = ptr_as_func<Func>(_func);
int arr[5] = { -1, -1, -1, -1, -1 };
int exp[5] = { 0, 0, 0, 3, 4 };
for (int i = 0; i < 5; i++)
func(&arr[i], i);
result.assignFormat("ret={%d, %d, %d, %d, %d}", arr[0], arr[1], arr[2], arr[3], arr[4]);
expect.assignFormat("ret={%d, %d, %d, %d, %d}", exp[0], exp[1], exp[2], exp[3], exp[4]);
return result == expect;
}
};
// x86::Compiler - X86Test_JumpCross
// =================================
class X86Test_JumpCross : public X86TestCase {
public:
X86Test_JumpCross() : X86TestCase("JumpCross") {}
static void add(TestApp& app) {
app.add(new X86Test_JumpCross());
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<void>());
Label L1 = cc.newLabel();
Label L2 = cc.newLabel();
Label L3 = cc.newLabel();
cc.jmp(L2);
cc.bind(L1);
cc.jmp(L3);
cc.bind(L2);
cc.jmp(L1);
cc.bind(L3);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
DebugUtils::unused(result, expect);
typedef void (*Func)(void);
Func func = ptr_as_func<Func>(_func);
func();
return true;
}
};
// x86::Compiler - X86Test_JumpMany
// ================================
class X86Test_JumpMany : public X86TestCase {
public:
X86Test_JumpMany() : X86TestCase("JumpMany") {}
static void add(TestApp& app) {
app.add(new X86Test_JumpMany());
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<int>());
for (uint32_t i = 0; i < 1000; i++) {
Label L = cc.newLabel();
cc.jmp(L);
cc.bind(L);
}
x86::Gp ret = cc.newInt32("ret");
cc.xor_(ret, ret);
cc.ret(ret);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(void);
Func func = ptr_as_func<Func>(_func);
int resultRet = func();
int expectRet = 0;
result.assignFormat("ret={%d}", resultRet);
expect.assignFormat("ret={%d}", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_JumpUnreachable1
// ========================================
class X86Test_JumpUnreachable1 : public X86TestCase {
public:
X86Test_JumpUnreachable1() : X86TestCase("JumpUnreachable1") {}
static void add(TestApp& app) {
app.add(new X86Test_JumpUnreachable1());
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<void>());
Label L_1 = cc.newLabel();
Label L_2 = cc.newLabel();
Label L_3 = cc.newLabel();
Label L_4 = cc.newLabel();
Label L_5 = cc.newLabel();
Label L_6 = cc.newLabel();
Label L_7 = cc.newLabel();
x86::Gp v0 = cc.newUInt32("v0");
x86::Gp v1 = cc.newUInt32("v1");
cc.bind(L_2);
cc.bind(L_3);
cc.jmp(L_1);
cc.bind(L_5);
cc.mov(v0, 0);
cc.bind(L_6);
cc.jmp(L_3);
cc.mov(v1, 1);
cc.jmp(L_1);
cc.bind(L_4);
cc.jmp(L_2);
cc.bind(L_7);
cc.add(v0, v1);
cc.align(AlignMode::kCode, 16);
cc.bind(L_1);
cc.ret();
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(void);
Func func = ptr_as_func<Func>(_func);
func();
result.append("ret={}");
expect.append("ret={}");
return true;
}
};
// x86::Compiler - X86Test_JumpUnreachable2
// ========================================
class X86Test_JumpUnreachable2 : public X86TestCase {
public:
X86Test_JumpUnreachable2() : X86TestCase("JumpUnreachable2") {}
static void add(TestApp& app) {
app.add(new X86Test_JumpUnreachable2());
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<void>());
Label L_1 = cc.newLabel();
Label L_2 = cc.newLabel();
x86::Gp v0 = cc.newUInt32("v0");
x86::Gp v1 = cc.newUInt32("v1");
cc.jmp(L_1);
cc.bind(L_2);
cc.mov(v0, 1);
cc.mov(v1, 2);
cc.cmp(v0, v1);
cc.jz(L_2);
cc.jmp(L_1);
cc.bind(L_1);
cc.ret();
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(void);
Func func = ptr_as_func<Func>(_func);
func();
result.append("ret={}");
expect.append("ret={}");
return true;
}
};
// x86::Compiler - X86Test_JumpTable1
// ==================================
class X86Test_JumpTable1 : public X86TestCase {
public:
bool _annotated;
X86Test_JumpTable1(bool annotated)
: X86TestCase("X86Test_JumpTable1"),
_annotated(annotated) {
_name.assignFormat("JumpTable {%s}", annotated ? "Annotated" : "Unknown Reg/Mem");
}
enum Operator {
kOperatorAdd = 0,
kOperatorSub = 1,
kOperatorMul = 2,
kOperatorDiv = 3
};
static void add(TestApp& app) {
app.add(new X86Test_JumpTable1(false));
app.add(new X86Test_JumpTable1(true));
}
virtual void compile(x86::Compiler& cc) {
x86::Xmm a = cc.newXmmSs("a");
x86::Xmm b = cc.newXmmSs("b");
x86::Gp op = cc.newUInt32("op");
x86::Gp target = cc.newIntPtr("target");
x86::Gp offset = cc.newIntPtr("offset");
Label L_Table = cc.newLabel();
Label L_Add = cc.newLabel();
Label L_Sub = cc.newLabel();
Label L_Mul = cc.newLabel();
Label L_Div = cc.newLabel();
Label L_End = cc.newLabel();
FuncNode* funcNode = cc.addFunc(FuncSignature::build<float, float, float, uint32_t>());
funcNode->setArg(0, a);
funcNode->setArg(1, b);
funcNode->setArg(2, op);
cc.lea(offset, x86::ptr(L_Table));
if (cc.is64Bit())
cc.movsxd(target, x86::dword_ptr(offset, op.cloneAs(offset), 2));
else
cc.mov(target, x86::dword_ptr(offset, op.cloneAs(offset), 2));
cc.add(target, offset);
// JumpAnnotation allows to annotate all possible jump targets of
// instructions where it cannot be deduced from operands.
if (_annotated) {
JumpAnnotation* annotation = cc.newJumpAnnotation();
annotation->addLabel(L_Add);
annotation->addLabel(L_Sub);
annotation->addLabel(L_Mul);
annotation->addLabel(L_Div);
cc.jmp(target, annotation);
}
else {
cc.jmp(target);
}
cc.bind(L_Add);
cc.addss(a, b);
cc.jmp(L_End);
cc.bind(L_Sub);
cc.subss(a, b);
cc.jmp(L_End);
cc.bind(L_Mul);
cc.mulss(a, b);
cc.jmp(L_End);
cc.bind(L_Div);
cc.divss(a, b);
cc.bind(L_End);
cc.ret(a);
cc.endFunc();
cc.bind(L_Table);
cc.embedLabelDelta(L_Add, L_Table, 4);
cc.embedLabelDelta(L_Sub, L_Table, 4);
cc.embedLabelDelta(L_Mul, L_Table, 4);
cc.embedLabelDelta(L_Div, L_Table, 4);
}
virtual bool run(void* _func, String& result, String& expect) {
typedef float (*Func)(float, float, uint32_t);
Func func = ptr_as_func<Func>(_func);
float results[4];
float expected[4];
results[0] = func(33.0f, 14.0f, kOperatorAdd);
results[1] = func(33.0f, 14.0f, kOperatorSub);
results[2] = func(10.0f, 6.0f, kOperatorMul);
results[3] = func(80.0f, 8.0f, kOperatorDiv);
expected[0] = 47.0f;
expected[1] = 19.0f;
expected[2] = 60.0f;
expected[3] = 10.0f;
result.assignFormat("ret={%f, %f, %f, %f}", results[0], results[1], results[2], results[3]);
expect.assignFormat("ret={%f, %f, %f, %f}", expected[0], expected[1], expected[2], expected[3]);
return result == expect;
}
};
// x86::Compiler - X86Test_JumpTable2
// ==================================
class X86Test_JumpTable2 : public X86TestCase {
public:
X86Test_JumpTable2()
: X86TestCase("JumpTable {Jumping to Begin}") {}
static void add(TestApp& app) {
app.add(new X86Test_JumpTable2());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp result = cc.newUInt32("result");
x86::Gp value = cc.newUInt32("value");
x86::Gp target = cc.newIntPtr("target");
x86::Gp offset = cc.newIntPtr("offset");
Label L_Table = cc.newLabel();
Label L_Begin = cc.newLabel();
Label L_Case0 = cc.newLabel();
Label L_Case1 = cc.newLabel();
Label L_End = cc.newLabel();
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int>());
funcNode->setArg(0, value);
cc.bind(L_Begin);
cc.lea(offset, x86::ptr(L_Table));
if (cc.is64Bit())
cc.movsxd(target, x86::dword_ptr(offset, value.cloneAs(offset), 2));
else
cc.mov(target, x86::dword_ptr(offset, value.cloneAs(offset), 2));
cc.add(target, offset);
{
JumpAnnotation* annotation = cc.newJumpAnnotation();
annotation->addLabel(L_Case0);
annotation->addLabel(L_Case1);
annotation->addLabel(L_Begin); // Never used, just for the purpose of the test.
cc.jmp(target, annotation);
cc.bind(L_Case0);
cc.mov(result, 0);
cc.jmp(L_End);
cc.bind(L_Case1);
cc.mov(result, 1);
cc.jmp(L_End);
}
cc.bind(L_End);
cc.ret(result);
cc.endFunc();
cc.bind(L_Table);
cc.embedLabelDelta(L_Case0, L_Table, 4);
cc.embedLabelDelta(L_Case1, L_Table, 4);
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int);
Func func = ptr_as_func<Func>(_func);
int results[2];
int expected[2];
results[0] = func(0);
results[1] = func(1);
expected[0] = 0;
expected[1] = 1;
result.assignFormat("ret={%d, %d}", results[0], results[1]);
expect.assignFormat("ret={%d, %d}", expected[0], expected[1]);
return result == expect;
}
};
// x86::Compiler - X86Test_JumpTable3
// ==================================
class X86Test_JumpTable3 : public X86TestCase {
public:
X86Test_JumpTable3()
: X86TestCase("JumpTable {Jumping to a single label}") {}
static void add(TestApp& app) {
app.add(new X86Test_JumpTable3());
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<int>());
Label L_Target = cc.newLabel();
x86::Gp target = cc.newUIntPtr("target");
x86::Gp result = cc.newUInt32("result");
JumpAnnotation* annotation = cc.newJumpAnnotation();
annotation->addLabel(L_Target);
cc.lea(target, x86::ptr(L_Target));
cc.jmp(target, annotation);
cc.bind(L_Target);
cc.mov(result, 1234);
cc.ret(result);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(void);
Func func = ptr_as_func<Func>(_func);
int out = func();
int expected = 1234;
result.assignFormat("ret=%d", out);
expect.assignFormat("ret=%d", expected);
return result == expect;
}
};
// x86::Compiler - X86Test_JumpTable4
// ==================================
class X86Test_JumpTable4 : public X86TestCase {
public:
X86Test_JumpTable4()
: X86TestCase("JumpTable {Jumping to a single label and multiple labels}") {}
static void add(TestApp& app) {
app.add(new X86Test_JumpTable4());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp result = cc.newUInt32("result");
x86::Gp condition = cc.newUInt32("condition");
FuncNode* func = cc.addFunc(FuncSignature::build<int, int>());
func->setArg(0, condition);
Label L_NonZero = cc.newLabel();
cc.test(condition, condition);
cc.jnz(L_NonZero);
{
JumpAnnotation* annotation = cc.newJumpAnnotation();
Label L_Target = cc.newLabel();
annotation->addLabel(L_Target);
x86::Gp target = cc.newUIntPtr("target");
cc.lea(target, x86::ptr(L_Target));
cc.jmp(target, annotation);
cc.bind(L_Target);
cc.mov(result, 1234);
cc.ret(result);
}
{
JumpAnnotation* annotation = cc.newJumpAnnotation();
Label L_Target1 = cc.newLabel();
Label L_Target2 = cc.newLabel();
annotation->addLabel(L_Target1);
annotation->addLabel(L_Target2);
cc.bind(L_NonZero);
x86::Gp target = cc.newUIntPtr("target");
cc.lea(target, x86::ptr(L_Target1));
cc.jmp(target, annotation);
cc.bind(L_Target1);
cc.mov(result, 4321);
cc.ret(result);
// Never executed.
cc.bind(L_Target2);
cc.mov(result, 0);
cc.ret(result);
}
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int);
Func func = ptr_as_func<Func>(_func);
int results[2] = { func(0), func(1) };
int expected[2] = { 1234, 4321 };
result.assignFormat("ret={%d, %d}", results[0], results[1]);
expect.assignFormat("ret={%d, %d}", expected[0], expected[1]);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocBase
// =================================
class X86Test_AllocBase : public X86TestCase {
public:
X86Test_AllocBase() : X86TestCase("AllocBase") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocBase());
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<int>());
x86::Gp v0 = cc.newInt32("v0");
x86::Gp v1 = cc.newInt32("v1");
x86::Gp v2 = cc.newInt32("v2");
x86::Gp v3 = cc.newInt32("v3");
x86::Gp v4 = cc.newInt32("v4");
cc.xor_(v0, v0);
cc.mov(v1, 1);
cc.mov(v2, 2);
cc.mov(v3, 3);
cc.mov(v4, 4);
cc.add(v0, v1);
cc.add(v0, v2);
cc.add(v0, v3);
cc.add(v0, v4);
cc.ret(v0);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(void);
Func func = ptr_as_func<Func>(_func);
int resultRet = func();
int expectRet = 1 + 2 + 3 + 4;
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocMany1
// ==================================
class X86Test_AllocMany1 : public X86TestCase {
public:
X86Test_AllocMany1() : X86TestCase("AllocMany1") {}
enum { kCount = 8 };
static void add(TestApp& app) {
app.add(new X86Test_AllocMany1());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp a0 = cc.newIntPtr("a0");
x86::Gp a1 = cc.newIntPtr("a1");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<void, int*, int*>());
funcNode->setArg(0, a0);
funcNode->setArg(1, a1);
// Create some variables.
x86::Gp t = cc.newInt32("t");
x86::Gp x[kCount];
uint32_t i;
// Setup variables (use mov with reg/imm to se if register allocator works).
for (i = 0; i < kCount; i++) x[i] = cc.newInt32("x%u", i);
for (i = 0; i < kCount; i++) cc.mov(x[i], int(i + 1));
// Make sum (addition).
cc.xor_(t, t);
for (i = 0; i < kCount; i++) cc.add(t, x[i]);
// Store result to a given pointer in first argument.
cc.mov(x86::dword_ptr(a0), t);
// Clear t.
cc.xor_(t, t);
// Make sum (subtraction).
for (i = 0; i < kCount; i++) cc.sub(t, x[i]);
// Store result to a given pointer in second argument.
cc.mov(x86::dword_ptr(a1), t);
// End of function.
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(int*, int*);
Func func = ptr_as_func<Func>(_func);
int resultX = 0;
int resultY = 0;
int expectX = 36;
int expectY = -36;
func(&resultX, &resultY);
result.assignFormat("ret={x=%d, y=%d}", resultX, resultY);
expect.assignFormat("ret={x=%d, y=%d}", expectX, expectY);
return resultX == expectX && resultY == expectY;
}
};
// x86::Compiler - X86Test_AllocMany2
// ==================================
class X86Test_AllocMany2 : public X86TestCase {
public:
X86Test_AllocMany2() : X86TestCase("AllocMany2") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocMany2());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp a = cc.newIntPtr("a");
x86::Gp v[32];
FuncNode* funcNode = cc.addFunc(FuncSignature::build<void, uint32_t*>());
funcNode->setArg(0, a);
for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) v[i] = cc.newInt32("v%d", i);
for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.xor_(v[i], v[i]);
x86::Gp x = cc.newInt32("x");
Label L = cc.newLabel();
cc.mov(x, 32);
cc.bind(L);
for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.add(v[i], i);
cc.dec(x);
cc.jnz(L);
for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(v); i++) cc.mov(x86::dword_ptr(a, int(i * 4)), v[i]);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(uint32_t*);
Func func = ptr_as_func<Func>(_func);
uint32_t i;
uint32_t resultBuf[32] {};
uint32_t expectBuf[32] {};
for (i = 0; i < ASMJIT_ARRAY_SIZE(resultBuf); i++)
expectBuf[i] = i * 32;
func(resultBuf);
for (i = 0; i < ASMJIT_ARRAY_SIZE(resultBuf); i++) {
if (i != 0) {
result.append(',');
expect.append(',');
}
result.appendFormat("%u", resultBuf[i]);
expect.appendFormat("%u", expectBuf[i]);
}
return result == expect;
}
};
// x86::Compiler - X86Test_AllocImul1
// ==================================
class X86Test_AllocImul1 : public X86TestCase {
public:
X86Test_AllocImul1() : X86TestCase("AllocImul1") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocImul1());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp dstHi = cc.newIntPtr("dstHi");
x86::Gp dstLo = cc.newIntPtr("dstLo");
x86::Gp vHi = cc.newInt32("vHi");
x86::Gp vLo = cc.newInt32("vLo");
x86::Gp src = cc.newInt32("src");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<void, int*, int*, int, int>());
funcNode->setArg(0, dstHi);
funcNode->setArg(1, dstLo);
funcNode->setArg(2, vLo);
funcNode->setArg(3, src);
cc.imul(vHi, vLo, src);
cc.mov(x86::dword_ptr(dstHi), vHi);
cc.mov(x86::dword_ptr(dstLo), vLo);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(int*, int*, int, int);
Func func = ptr_as_func<Func>(_func);
int v0 = 4;
int v1 = 4;
int resultHi = 0;
int resultLo = 0;
int expectHi = 0;
int expectLo = v0 * v1;
func(&resultHi, &resultLo, v0, v1);
result.assignFormat("hi=%d, lo=%d", resultHi, resultLo);
expect.assignFormat("hi=%d, lo=%d", expectHi, expectLo);
return resultHi == expectHi && resultLo == expectLo;
}
};
// x86::Compiler - X86Test_AllocImul2
// ==================================
class X86Test_AllocImul2 : public X86TestCase {
public:
X86Test_AllocImul2() : X86TestCase("AllocImul2") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocImul2());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp dst = cc.newIntPtr("dst");
x86::Gp src = cc.newIntPtr("src");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<void, int*, const int*>());
funcNode->setArg(0, dst);
funcNode->setArg(1, src);
for (unsigned int i = 0; i < 4; i++) {
x86::Gp x = cc.newInt32("x");
x86::Gp y = cc.newInt32("y");
x86::Gp hi = cc.newInt32("hi");
cc.mov(x, x86::dword_ptr(src, 0));
cc.mov(y, x86::dword_ptr(src, 4));
cc.imul(hi, x, y);
cc.add(x86::dword_ptr(dst, 0), hi);
cc.add(x86::dword_ptr(dst, 4), x);
}
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(int*, const int*);
Func func = ptr_as_func<Func>(_func);
int src[2] = { 4, 9 };
int resultRet[2] = { 0, 0 };
int expectRet[2] = { 0, (4 * 9) * 4 };
func(resultRet, src);
result.assignFormat("ret={%d, %d}", resultRet[0], resultRet[1]);
expect.assignFormat("ret={%d, %d}", expectRet[0], expectRet[1]);
return resultRet[0] == expectRet[0] && resultRet[1] == expectRet[1];
}
};
// x86::Compiler - X86Test_AllocIdiv1
// ==================================
class X86Test_AllocIdiv1 : public X86TestCase {
public:
X86Test_AllocIdiv1() : X86TestCase("AllocIdiv1") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocIdiv1());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp a = cc.newInt32("a");
x86::Gp b = cc.newInt32("b");
x86::Gp dummy = cc.newInt32("dummy");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int, int>());
funcNode->setArg(0, a);
funcNode->setArg(1, b);
cc.xor_(dummy, dummy);
cc.idiv(dummy, a, b);
cc.ret(a);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int, int);
Func func = ptr_as_func<Func>(_func);
int v0 = 2999;
int v1 = 245;
int resultRet = func(v0, v1);
int expectRet = 2999 / 245;
result.assignFormat("result=%d", resultRet);
expect.assignFormat("result=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocSetz
// =================================
class X86Test_AllocSetz : public X86TestCase {
public:
X86Test_AllocSetz() : X86TestCase("AllocSetz") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocSetz());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp src0 = cc.newInt32("src0");
x86::Gp src1 = cc.newInt32("src1");
x86::Gp dst0 = cc.newIntPtr("dst0");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<void, int, int, char*>());
funcNode->setArg(0, src0);
funcNode->setArg(1, src1);
funcNode->setArg(2, dst0);
cc.cmp(src0, src1);
cc.setz(x86::byte_ptr(dst0));
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(int, int, char*);
Func func = ptr_as_func<Func>(_func);
char resultBuf[4] {};
char expectBuf[4] = { 1, 0, 0, 1 };
func(0, 0, &resultBuf[0]); // We are expecting 1 (0 == 0).
func(0, 1, &resultBuf[1]); // We are expecting 0 (0 != 1).
func(1, 0, &resultBuf[2]); // We are expecting 0 (1 != 0).
func(1, 1, &resultBuf[3]); // We are expecting 1 (1 == 1).
result.assignFormat("out={%d, %d, %d, %d}", resultBuf[0], resultBuf[1], resultBuf[2], resultBuf[3]);
expect.assignFormat("out={%d, %d, %d, %d}", expectBuf[0], expectBuf[1], expectBuf[2], expectBuf[3]);
return resultBuf[0] == expectBuf[0] &&
resultBuf[1] == expectBuf[1] &&
resultBuf[2] == expectBuf[2] &&
resultBuf[3] == expectBuf[3] ;
}
};
// x86::Compiler - X86Test_AllocShlRor
// ===================================
class X86Test_AllocShlRor : public X86TestCase {
public:
X86Test_AllocShlRor() : X86TestCase("AllocShlRor") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocShlRor());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp dst = cc.newIntPtr("dst");
x86::Gp var = cc.newInt32("var");
x86::Gp vShlParam = cc.newInt32("vShlParam");
x86::Gp vRorParam = cc.newInt32("vRorParam");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<void, int*, int, int, int>());
funcNode->setArg(0, dst);
funcNode->setArg(1, var);
funcNode->setArg(2, vShlParam);
funcNode->setArg(3, vRorParam);
cc.shl(var, vShlParam);
cc.ror(var, vRorParam);
cc.mov(x86::dword_ptr(dst), var);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(int*, int, int, int);
Func func = ptr_as_func<Func>(_func);
int v0 = 0x000000FF;
int resultRet = 0;
int expectRet = 0x0000FF00;
func(&resultRet, v0, 16, 8);
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocGpbLo
// ==================================
class X86Test_AllocGpbLo1 : public X86TestCase {
public:
X86Test_AllocGpbLo1() : X86TestCase("AllocGpbLo1") {}
enum : uint32_t { kCount = 32 };
static void add(TestApp& app) {
app.add(new X86Test_AllocGpbLo1());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp rPtr = cc.newUIntPtr("rPtr");
x86::Gp rSum = cc.newUInt32("rSum");
x86::Gp x[kCount];
FuncNode* funcNode = cc.addFunc(FuncSignature::build<uint32_t, uint32_t*>());
funcNode->setArg(0, rPtr);
for (uint32_t i = 0; i < kCount; i++) {
x[i] = cc.newUInt32("x%u", i);
}
// Init pseudo-regs with values from our array.
for (uint32_t i = 0; i < kCount; i++) {
cc.mov(x[i], x86::dword_ptr(rPtr, int(i * 4)));
}
for (uint32_t i = 2; i < kCount; i++) {
// Add and truncate to 8 bit; no purpose, just mess with jit.
cc.add (x[i ], x[i-1]);
cc.movzx(x[i ], x[i ].r8());
cc.movzx(x[i-2], x[i-1].r8());
cc.movzx(x[i-1], x[i-2].r8());
}
// Sum up all computed values.
cc.mov(rSum, 0);
for (uint32_t i = 0; i < kCount; i++) {
cc.add(rSum, x[i]);
}
// Return the sum.
cc.ret(rSum);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef uint32_t (*Func)(uint32_t*);
Func func = ptr_as_func<Func>(_func);
uint32_t i;
uint32_t buf[kCount];
uint32_t resultRet = 0;
uint32_t expectRet = 0;
for (i = 0; i < kCount; i++) {
buf[i] = 1;
}
for (i = 2; i < kCount; i++) {
buf[i ]+= buf[i-1];
buf[i ] = buf[i ] & 0xFF;
buf[i-2] = buf[i-1] & 0xFF;
buf[i-1] = buf[i-2] & 0xFF;
}
for (i = 0; i < kCount; i++) {
expectRet += buf[i];
}
for (i = 0; i < kCount; i++) {
buf[i] = 1;
}
resultRet = func(buf);
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocGpbLo2
// ===================================
class X86Test_AllocGpbLo2 : public X86TestCase {
public:
X86Test_AllocGpbLo2() : X86TestCase("AllocGpbLo2") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocGpbLo2());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp v = cc.newUInt32("v");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<uint32_t, uint32_t>());
funcNode->setArg(0, v);
cc.mov(v.r8(), 0xFF);
cc.ret(v);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef uint32_t (*Func)(uint32_t);
Func func = ptr_as_func<Func>(_func);
uint32_t resultRet = func(0x12345678u);
uint32_t expectRet = 0x123456FFu;
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocRepMovsb
// =====================================
class X86Test_AllocRepMovsb : public X86TestCase {
public:
X86Test_AllocRepMovsb() : X86TestCase("AllocRepMovsb") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocRepMovsb());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp dst = cc.newIntPtr("dst");
x86::Gp src = cc.newIntPtr("src");
x86::Gp cnt = cc.newIntPtr("cnt");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<void, void*, void*, size_t>());
funcNode->setArg(0, dst);
funcNode->setArg(1, src);
funcNode->setArg(2, cnt);
cc.rep(cnt).movs(x86::byte_ptr(dst), x86::byte_ptr(src));
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(void*, void*, size_t);
Func func = ptr_as_func<Func>(_func);
char dst[20] = { 0 };
char src[20] = "Hello AsmJit!";
func(dst, src, strlen(src) + 1);
result.assignFormat("ret=\"%s\"", dst);
expect.assignFormat("ret=\"%s\"", src);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocIfElse1
// ====================================
class X86Test_AllocIfElse1 : public X86TestCase {
public:
X86Test_AllocIfElse1() : X86TestCase("AllocIfElse1") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocIfElse1());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp v1 = cc.newInt32("v1");
x86::Gp v2 = cc.newInt32("v2");
Label L_1 = cc.newLabel();
Label L_2 = cc.newLabel();
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int, int>());
funcNode->setArg(0, v1);
funcNode->setArg(1, v2);
cc.cmp(v1, v2);
cc.jg(L_1);
cc.mov(v1, 1);
cc.jmp(L_2);
cc.bind(L_1);
cc.mov(v1, 2);
cc.bind(L_2);
cc.ret(v1);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int, int);
Func func = ptr_as_func<Func>(_func);
int a = func(0, 1);
int b = func(1, 0);
result.appendFormat("ret={%d, %d}", a, b);
expect.appendFormat("ret={%d, %d}", 1, 2);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocIfElse2
// ====================================
class X86Test_AllocIfElse2 : public X86TestCase {
public:
X86Test_AllocIfElse2() : X86TestCase("AllocIfElse2") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocIfElse2());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp v1 = cc.newInt32("v1");
x86::Gp v2 = cc.newInt32("v2");
Label L_1 = cc.newLabel();
Label L_2 = cc.newLabel();
Label L_3 = cc.newLabel();
Label L_4 = cc.newLabel();
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int, int>());
funcNode->setArg(0, v1);
funcNode->setArg(1, v2);
cc.jmp(L_1);
cc.bind(L_2);
cc.jmp(L_4);
cc.bind(L_1);
cc.cmp(v1, v2);
cc.jg(L_3);
cc.mov(v1, 1);
cc.jmp(L_2);
cc.bind(L_3);
cc.mov(v1, 2);
cc.jmp(L_2);
cc.bind(L_4);
cc.ret(v1);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int, int);
Func func = ptr_as_func<Func>(_func);
int a = func(0, 1);
int b = func(1, 0);
result.appendFormat("ret={%d, %d}", a, b);
expect.appendFormat("ret={%d, %d}", 1, 2);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocIfElse3
// ====================================
class X86Test_AllocIfElse3 : public X86TestCase {
public:
X86Test_AllocIfElse3() : X86TestCase("AllocIfElse3") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocIfElse3());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp v1 = cc.newInt32("v1");
x86::Gp v2 = cc.newInt32("v2");
x86::Gp counter = cc.newInt32("counter");
Label L_1 = cc.newLabel();
Label L_Loop = cc.newLabel();
Label L_Exit = cc.newLabel();
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int, int>());
funcNode->setArg(0, v1);
funcNode->setArg(1, v2);
cc.cmp(v1, v2);
cc.jg(L_1);
cc.mov(counter, 0);
cc.bind(L_Loop);
cc.mov(v1, counter);
cc.inc(counter);
cc.cmp(counter, 1);
cc.jle(L_Loop);
cc.jmp(L_Exit);
cc.bind(L_1);
cc.mov(v1, 2);
cc.bind(L_Exit);
cc.ret(v1);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int, int);
Func func = ptr_as_func<Func>(_func);
int a = func(0, 1);
int b = func(1, 0);
result.appendFormat("ret={%d, %d}", a, b);
expect.appendFormat("ret={%d, %d}", 1, 2);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocIfElse4
// ====================================
class X86Test_AllocIfElse4 : public X86TestCase {
public:
X86Test_AllocIfElse4() : X86TestCase("AllocIfElse4") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocIfElse4());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp v1 = cc.newInt32("v1");
x86::Gp v2 = cc.newInt32("v2");
x86::Gp counter = cc.newInt32("counter");
Label L_1 = cc.newLabel();
Label L_Loop1 = cc.newLabel();
Label L_Loop2 = cc.newLabel();
Label L_Exit = cc.newLabel();
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int, int>());
funcNode->setArg(0, v1);
funcNode->setArg(1, v2);
cc.mov(counter, 0);
cc.cmp(v1, v2);
cc.jg(L_1);
cc.bind(L_Loop1);
cc.mov(v1, counter);
cc.inc(counter);
cc.cmp(counter, 1);
cc.jle(L_Loop1);
cc.jmp(L_Exit);
cc.bind(L_1);
cc.bind(L_Loop2);
cc.mov(v1, counter);
cc.inc(counter);
cc.cmp(counter, 2);
cc.jle(L_Loop2);
cc.bind(L_Exit);
cc.ret(v1);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int, int);
Func func = ptr_as_func<Func>(_func);
int a = func(0, 1);
int b = func(1, 0);
result.appendFormat("ret={%d, %d}", a, b);
expect.appendFormat("ret={%d, %d}", 1, 2);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocInt8
// =================================
class X86Test_AllocInt8 : public X86TestCase {
public:
X86Test_AllocInt8() : X86TestCase("AllocInt8") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocInt8());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp x = cc.newInt8("x");
x86::Gp y = cc.newInt32("y");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int8_t>());
funcNode->setArg(0, x);
cc.movsx(y, x);
cc.ret(y);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int8_t);
Func func = ptr_as_func<Func>(_func);
int resultRet = func(int8_t(-13));
int expectRet = -13;
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocUnhandledArg
// =========================================
class X86Test_AllocUnhandledArg : public X86TestCase {
public:
X86Test_AllocUnhandledArg() : X86TestCase("AllocUnhandledArg") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocUnhandledArg());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp x = cc.newInt32("x");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int, int, int>());
funcNode->setArg(2, x);
cc.ret(x);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int, int, int);
Func func = ptr_as_func<Func>(_func);
int resultRet = func(42, 155, 199);
int expectRet = 199;
result.assignFormat("ret={%d}", resultRet);
expect.assignFormat("ret={%d}", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocArgsIntPtr
// =======================================
class X86Test_AllocArgsIntPtr : public X86TestCase {
public:
X86Test_AllocArgsIntPtr() : X86TestCase("AllocArgsIntPtr") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocArgsIntPtr());
}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<void, void*, void*, void*, void*, void*, void*, void*, void*>());
x86::Gp var[8];
for (uint32_t i = 0; i < 8; i++) {
var[i] = cc.newIntPtr("var%u", i);
funcNode->setArg(i, var[i]);
}
for (uint32_t i = 0; i < 8; i++) {
cc.add(var[i], int(i + 1));
}
// Move some data into buffer provided by arguments so we can verify if it
// really works without looking into assembler output.
for (uint32_t i = 0; i < 8; i++) {
cc.add(x86::byte_ptr(var[i]), int(i + 1));
}
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(void*, void*, void*, void*, void*, void*, void*, void*);
Func func = ptr_as_func<Func>(_func);
uint8_t resultBuf[9] = { 0, 0, 0, 0, 0, 0, 0, 0, 0 };
uint8_t expectBuf[9] = { 0, 1, 2, 3, 4, 5, 6, 7, 8 };
func(resultBuf, resultBuf, resultBuf, resultBuf,
resultBuf, resultBuf, resultBuf, resultBuf);
result.assignFormat("buf={%d, %d, %d, %d, %d, %d, %d, %d, %d}",
resultBuf[0], resultBuf[1], resultBuf[2], resultBuf[3],
resultBuf[4], resultBuf[5], resultBuf[6], resultBuf[7],
resultBuf[8]);
expect.assignFormat("buf={%d, %d, %d, %d, %d, %d, %d, %d, %d}",
expectBuf[0], expectBuf[1], expectBuf[2], expectBuf[3],
expectBuf[4], expectBuf[5], expectBuf[6], expectBuf[7],
expectBuf[8]);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocArgsFloat
// ======================================
class X86Test_AllocArgsFloat : public X86TestCase {
public:
X86Test_AllocArgsFloat() : X86TestCase("AllocArgsFloat") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocArgsFloat());
}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<void, float, float, float, float, float, float, float, void*>());
x86::Gp p = cc.newIntPtr("p");
x86::Xmm xv[7];
for (uint32_t i = 0; i < 7; i++) {
xv[i] = cc.newXmmSs("xv%u", i);
funcNode->setArg(i, xv[i]);
}
funcNode->setArg(7, p);
cc.addss(xv[0], xv[1]);
cc.addss(xv[0], xv[2]);
cc.addss(xv[0], xv[3]);
cc.addss(xv[0], xv[4]);
cc.addss(xv[0], xv[5]);
cc.addss(xv[0], xv[6]);
cc.movss(x86::ptr(p), xv[0]);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(float, float, float, float, float, float, float, float*);
Func func = ptr_as_func<Func>(_func);
float resultRet = 0;
float expectRet = 1.0f + 2.0f + 3.0f + 4.0f + 5.0f + 6.0f + 7.0f;
func(1.0f, 2.0f, 3.0f, 4.0f, 5.0f, 6.0f, 7.0f, &resultRet);
result.assignFormat("ret={%g}", resultRet);
expect.assignFormat("ret={%g}", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocArgsDouble
// =======================================
class X86Test_AllocArgsDouble : public X86TestCase {
public:
X86Test_AllocArgsDouble() : X86TestCase("AllocArgsDouble") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocArgsDouble());
}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<void, double, double, double, double, double, double, double, void*>());
x86::Gp p = cc.newIntPtr("p");
x86::Xmm xv[7];
for (uint32_t i = 0; i < 7; i++) {
xv[i] = cc.newXmmSd("xv%u", i);
funcNode->setArg(i, xv[i]);
}
funcNode->setArg(7, p);
cc.addsd(xv[0], xv[1]);
cc.addsd(xv[0], xv[2]);
cc.addsd(xv[0], xv[3]);
cc.addsd(xv[0], xv[4]);
cc.addsd(xv[0], xv[5]);
cc.addsd(xv[0], xv[6]);
cc.movsd(x86::ptr(p), xv[0]);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(double, double, double, double, double, double, double, double*);
Func func = ptr_as_func<Func>(_func);
double resultRet = 0;
double expectRet = 1.0 + 2.0 + 3.0 + 4.0 + 5.0 + 6.0 + 7.0;
func(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, &resultRet);
result.assignFormat("ret={%g}", resultRet);
expect.assignFormat("ret={%g}", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocArgsVec
// ====================================
#if ASMJIT_ARCH_X86
class X86Test_AllocArgsVec : public X86TestCase {
public:
X86Test_AllocArgsVec() : X86TestCase("AllocArgsVec") {}
static void add(TestApp& app) {
// Not supported on Windows.
#ifndef _WIN32
app.add(new X86Test_AllocArgsVec());
#else
DebugUtils::unused(app);
#endif
}
virtual void compile(x86::Compiler& cc) {
x86::Xmm a = cc.newXmm("aXmm");
x86::Xmm b = cc.newXmm("bXmm");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<x86::Xmm, x86::Xmm, x86::Xmm>());
funcNode->setArg(0, a);
funcNode->setArg(1, b);
cc.paddb(a, b);
cc.ret(a);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef __m128i (*Func)(__m128i, __m128i);
Func func = ptr_as_func<Func>(_func);
uint8_t aData[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
uint8_t bData[16] = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
uint8_t rData[16] {};
uint8_t eData[16] = { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 };
__m128i aVec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(aData));
__m128i bVec = _mm_loadu_si128(reinterpret_cast<const __m128i*>(bData));
__m128i rVec = func(aVec, bVec);
_mm_storeu_si128(reinterpret_cast<__m128i*>(rData), rVec);
result.appendHex(rData, 16);
expect.appendHex(eData, 16);
return result == expect;
}
};
#endif // ASMJIT_ARCH_X86
// x86::Compiler - X86Test_AllocRetFloat1
// ======================================
class X86Test_AllocRetFloat1 : public X86TestCase {
public:
X86Test_AllocRetFloat1() : X86TestCase("AllocRetFloat1") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocRetFloat1());
}
virtual void compile(x86::Compiler& cc) {
x86::Xmm x = cc.newXmmSs("x");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<float, float>());
funcNode->setArg(0, x);
cc.ret(x);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef float (*Func)(float);
Func func = ptr_as_func<Func>(_func);
float resultRet = func(42.0f);
float expectRet = 42.0f;
result.assignFormat("ret={%g}", resultRet);
expect.assignFormat("ret={%g}", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocRetFloat2
// ======================================
class X86Test_AllocRetFloat2 : public X86TestCase {
public:
X86Test_AllocRetFloat2() : X86TestCase("AllocRetFloat2") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocRetFloat2());
}
virtual void compile(x86::Compiler& cc) {
x86::Xmm x = cc.newXmmSs("x");
x86::Xmm y = cc.newXmmSs("y");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<float, float, float>());
funcNode->setArg(0, x);
funcNode->setArg(1, y);
cc.addss(x, y);
cc.ret(x);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef float (*Func)(float, float);
Func func = ptr_as_func<Func>(_func);
float resultRet = func(1.0f, 2.0f);
float expectRet = 1.0f + 2.0f;
result.assignFormat("ret={%g}", resultRet);
expect.assignFormat("ret={%g}", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocRetDouble1
// =======================================
class X86Test_AllocRetDouble1 : public X86TestCase {
public:
X86Test_AllocRetDouble1() : X86TestCase("AllocRetDouble1") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocRetDouble1());
}
virtual void compile(x86::Compiler& cc) {
x86::Xmm x = cc.newXmmSd("x");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<double, double>());
funcNode->setArg(0, x);
cc.ret(x);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef double (*Func)(double);
Func func = ptr_as_func<Func>(_func);
double resultRet = func(42.0);
double expectRet = 42.0;
result.assignFormat("ret={%g}", resultRet);
expect.assignFormat("ret={%g}", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocRetDouble2
// =======================================
class X86Test_AllocRetDouble2 : public X86TestCase {
public:
X86Test_AllocRetDouble2() : X86TestCase("AllocRetDouble2") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocRetDouble2());
}
virtual void compile(x86::Compiler& cc) {
x86::Xmm x = cc.newXmmSd("x");
x86::Xmm y = cc.newXmmSd("y");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<double, double, double>());
funcNode->setArg(0, x);
funcNode->setArg(1, y);
cc.addsd(x, y);
cc.ret(x);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef double (*Func)(double, double);
Func func = ptr_as_func<Func>(_func);
double resultRet = func(1.0, 2.0);
double expectRet = 1.0 + 2.0;
result.assignFormat("ret={%g}", resultRet);
expect.assignFormat("ret={%g}", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocStack
// ==================================
class X86Test_AllocStack : public X86TestCase {
public:
X86Test_AllocStack() : X86TestCase("AllocStack") {}
enum { kSize = 256 };
static void add(TestApp& app) {
app.add(new X86Test_AllocStack());
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<int>());
x86::Mem stack = cc.newStack(kSize, 1);
stack.setSize(1);
x86::Gp i = cc.newIntPtr("i");
x86::Gp a = cc.newInt32("a");
x86::Gp b = cc.newInt32("b");
Label L_1 = cc.newLabel();
Label L_2 = cc.newLabel();
// Fill stack by sequence [0, 1, 2, 3 ... 255].
cc.xor_(i, i);
x86::Mem stackWithIndex = stack.clone();
stackWithIndex.setIndex(i, 0);
cc.bind(L_1);
cc.mov(stackWithIndex, i.r8());
cc.inc(i);
cc.cmp(i, 255);
cc.jle(L_1);
// Sum sequence in stack.
cc.xor_(i, i);
cc.xor_(a, a);
cc.bind(L_2);
cc.movzx(b, stackWithIndex);
cc.add(a, b);
cc.inc(i);
cc.cmp(i, 255);
cc.jle(L_2);
cc.ret(a);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(void);
Func func = ptr_as_func<Func>(_func);
int resultRet = func();
int expectRet = 32640;
result.assignInt(resultRet);
expect.assignInt(expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocMemcpy
// ===================================
class X86Test_AllocMemcpy : public X86TestCase {
public:
X86Test_AllocMemcpy() : X86TestCase("AllocMemcpy") {}
enum { kCount = 32 };
static void add(TestApp& app) {
app.add(new X86Test_AllocMemcpy());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp dst = cc.newIntPtr("dst");
x86::Gp src = cc.newIntPtr("src");
x86::Gp cnt = cc.newUIntPtr("cnt");
Label L_Loop = cc.newLabel(); // Create base labels we use
Label L_Exit = cc.newLabel(); // in our function.
FuncNode* funcNode = cc.addFunc(FuncSignature::build<void, uint32_t*, const uint32_t*, size_t>());
funcNode->setArg(0, dst);
funcNode->setArg(1, src);
funcNode->setArg(2, cnt);
cc.test(cnt, cnt); // Exit if the size is zero.
cc.jz(L_Exit);
cc.bind(L_Loop); // Bind the loop label here.
x86::Gp tmp = cc.newInt32("tmp"); // Copy a single dword (4 bytes).
cc.mov(tmp, x86::dword_ptr(src));
cc.mov(x86::dword_ptr(dst), tmp);
cc.add(src, 4); // Increment dst/src pointers.
cc.add(dst, 4);
cc.dec(cnt); // Loop until cnt isn't zero.
cc.jnz(L_Loop);
cc.bind(L_Exit); // Bind the exit label here.
cc.endFunc(); // End of function.
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(uint32_t*, const uint32_t*, size_t);
Func func = ptr_as_func<Func>(_func);
uint32_t i;
uint32_t dstBuffer[kCount];
uint32_t srcBuffer[kCount];
for (i = 0; i < kCount; i++) {
dstBuffer[i] = 0;
srcBuffer[i] = i;
}
func(dstBuffer, srcBuffer, kCount);
result.assign("buf={");
expect.assign("buf={");
for (i = 0; i < kCount; i++) {
if (i != 0) {
result.append(", ");
expect.append(", ");
}
result.appendFormat("%u", unsigned(dstBuffer[i]));
expect.appendFormat("%u", unsigned(srcBuffer[i]));
}
result.append("}");
expect.append("}");
return result == expect;
}
};
// x86::Compiler - X86Test_AllocExtraBlock
// =======================================
class X86Test_AllocExtraBlock : public X86TestCase {
public:
X86Test_AllocExtraBlock() : X86TestCase("AllocExtraBlock") {}
static void add(TestApp& app) {
app.add(new X86Test_AllocExtraBlock());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp cond = cc.newInt32("cond");
x86::Gp ret = cc.newInt32("ret");
x86::Gp a = cc.newInt32("a");
x86::Gp b = cc.newInt32("b");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int, int, int>());
funcNode->setArg(0, cond);
funcNode->setArg(1, a);
funcNode->setArg(2, b);
Label L_Ret = cc.newLabel();
Label L_Extra = cc.newLabel();
cc.test(cond, cond);
cc.jnz(L_Extra);
cc.mov(ret, a);
cc.add(ret, b);
cc.bind(L_Ret);
cc.ret(ret);
// Emit code sequence at the end of the function.
BaseNode* prevCursor = cc.setCursor(funcNode->endNode()->prev());
cc.bind(L_Extra);
cc.mov(ret, a);
cc.sub(ret, b);
cc.jmp(L_Ret);
cc.setCursor(prevCursor);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int, int, int);
Func func = ptr_as_func<Func>(_func);
int ret1 = func(0, 4, 5);
int ret2 = func(1, 4, 5);
int exp1 = 4 + 5;
int exp2 = 4 - 5;
result.assignFormat("ret={%d, %d}", ret1, ret2);
expect.assignFormat("ret={%d, %d}", exp1, exp2);
return result == expect;
}
};
// x86::Compiler - X86Test_AllocAlphaBlend
// =======================================
class X86Test_AllocAlphaBlend : public X86TestCase {
public:
X86Test_AllocAlphaBlend() : X86TestCase("AllocAlphaBlend") {}
enum { kCount = 17 };
static void add(TestApp& app) {
app.add(new X86Test_AllocAlphaBlend());
}
static uint32_t blendSrcOver(uint32_t d, uint32_t s) {
uint32_t saInv = ~s >> 24;
uint32_t d_20 = (d ) & 0x00FF00FF;
uint32_t d_31 = (d >> 8) & 0x00FF00FF;
d_20 *= saInv;
d_31 *= saInv;
d_20 = ((d_20 + ((d_20 >> 8) & 0x00FF00FFu) + 0x00800080u) & 0xFF00FF00u) >> 8;
d_31 = ((d_31 + ((d_31 >> 8) & 0x00FF00FFu) + 0x00800080u) & 0xFF00FF00u);
return d_20 + d_31 + s;
}
virtual void compile(x86::Compiler& cc) {
asmtest::generateSseAlphaBlend(cc, true);
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(void*, const void*, size_t);
Func func = ptr_as_func<Func>(_func);
static const uint32_t dstConstData[] = { 0x00000000, 0x10101010, 0x20100804, 0x30200003, 0x40204040, 0x5000004D, 0x60302E2C, 0x706F6E6D, 0x807F4F2F, 0x90349001, 0xA0010203, 0xB03204AB, 0xC023AFBD, 0xD0D0D0C0, 0xE0AABBCC, 0xFFFFFFFF, 0xF8F4F2F1 };
static const uint32_t srcConstData[] = { 0xE0E0E0E0, 0xA0008080, 0x341F1E1A, 0xFEFEFEFE, 0x80302010, 0x49490A0B, 0x998F7798, 0x00000000, 0x01010101, 0xA0264733, 0xBAB0B1B9, 0xFF000000, 0xDAB0A0C1, 0xE0BACFDA, 0x99887766, 0xFFFFFF80, 0xEE0A5FEC };
uint32_t _dstBuffer[kCount + 3];
uint32_t _srcBuffer[kCount + 3];
// Has to be aligned.
uint32_t* dstBuffer = (uint32_t*)Support::alignUp<intptr_t>((intptr_t)_dstBuffer, 16);
uint32_t* srcBuffer = (uint32_t*)Support::alignUp<intptr_t>((intptr_t)_srcBuffer, 16);
memcpy(dstBuffer, dstConstData, sizeof(dstConstData));
memcpy(srcBuffer, srcConstData, sizeof(srcConstData));
uint32_t i;
uint32_t expBuffer[kCount];
for (i = 0; i < kCount; i++) {
expBuffer[i] = blendSrcOver(dstBuffer[i], srcBuffer[i]);
}
func(dstBuffer, srcBuffer, kCount);
result.assign("buf={");
expect.assign("buf={");
for (i = 0; i < kCount; i++) {
if (i != 0) {
result.append(", ");
expect.append(", ");
}
result.appendFormat("%08X", unsigned(dstBuffer[i]));
expect.appendFormat("%08X", unsigned(expBuffer[i]));
}
result.append("}");
expect.append("}");
return result == expect;
}
};
// x86::Compiler - X86Test_FuncArgInt8
// ===================================
class X86Test_FuncArgInt8 : public X86TestCase {
public:
X86Test_FuncArgInt8() : X86TestCase("FuncArgInt8") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncArgInt8());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp v0 = cc.newUInt32("v0");
x86::Gp v1 = cc.newUInt32("v1");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<unsigned, uint8_t, uint8_t, uint32_t>());
funcNode->setArg(0, v0);
funcNode->setArg(1, v1);
cc.add(v0, v1);
cc.ret(v0);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef uint32_t (*Func)(uint8_t, uint8_t, uint32_t);
Func func = ptr_as_func<Func>(_func);
uint32_t arg = uint32_t(uintptr_t(_func) & 0xFFFFFFFF);
unsigned resultRet = func(uint8_t(arg & 0xFF), uint8_t(arg & 0xFF), arg);
unsigned expectRet = (arg & 0xFF) * 2;
result.assignFormat("ret=%u", resultRet);
expect.assignFormat("ret=%u", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_FuncCallBase1
// =====================================
class X86Test_FuncCallBase1 : public X86TestCase {
public:
X86Test_FuncCallBase1() : X86TestCase("FuncCallBase1") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallBase1());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp v0 = cc.newInt32("v0");
x86::Gp v1 = cc.newInt32("v1");
x86::Gp v2 = cc.newInt32("v2");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int, int, int>());
funcNode->setArg(0, v0);
funcNode->setArg(1, v1);
funcNode->setArg(2, v2);
// Just do something.
cc.shl(v0, 1);
cc.shl(v1, 1);
cc.shl(v2, 1);
// Call a function.
InvokeNode* invokeNode;
cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignature::build<int, int, int, int>());
invokeNode->setArg(0, v2);
invokeNode->setArg(1, v1);
invokeNode->setArg(2, v0);
invokeNode->setRet(0, v0);
cc.ret(v0);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int, int, int);
Func func = ptr_as_func<Func>(_func);
int resultRet = func(3, 2, 1);
int expectRet = 36;
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
static int calledFunc(int a, int b, int c) { return (a + b) * c; }
};
// x86::Compiler - X86Test_FuncCallBase2
// =====================================
class X86Test_FuncCallBase2 : public X86TestCase {
public:
X86Test_FuncCallBase2() : X86TestCase("FuncCallBase2") {}
enum { kSize = 256 };
static void add(TestApp& app) {
app.add(new X86Test_FuncCallBase2());
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<int>());
const int kTokenSize = 32;
x86::Mem s1 = cc.newStack(kTokenSize, 32);
x86::Mem s2 = cc.newStack(kTokenSize, 32);
x86::Gp p1 = cc.newIntPtr("p1");
x86::Gp p2 = cc.newIntPtr("p2");
x86::Gp ret = cc.newInt32("ret");
Label L_Exit = cc.newLabel();
static const char token[kTokenSize] = "-+:|abcdefghijklmnopqrstuvwxyz|";
InvokeNode* invokeNode;
cc.lea(p1, s1);
cc.lea(p2, s2);
// Try to corrupt the stack if wrongly allocated.
cc.invoke(&invokeNode, imm((void*)memcpy), FuncSignature::build<void*, void*, void*, size_t>());
invokeNode->setArg(0, p1);
invokeNode->setArg(1, imm(token));
invokeNode->setArg(2, imm(kTokenSize));
invokeNode->setRet(0, p1);
cc.invoke(&invokeNode, imm((void*)memcpy), FuncSignature::build<void*, void*, void*, size_t>());
invokeNode->setArg(0, p2);
invokeNode->setArg(1, imm(token));
invokeNode->setArg(2, imm(kTokenSize));
invokeNode->setRet(0, p2);
cc.invoke(&invokeNode, imm((void*)memcmp), FuncSignature::build<int, void*, void*, size_t>());
invokeNode->setArg(0, p1);
invokeNode->setArg(1, p2);
invokeNode->setArg(2, imm(kTokenSize));
invokeNode->setRet(0, ret);
// This should be 0 on success, however, if both `p1` and `p2` were
// allocated in the same address this check will still pass.
cc.cmp(ret, 0);
cc.jnz(L_Exit);
// Checks whether `p1` and `p2` are different (must be).
cc.xor_(ret, ret);
cc.cmp(p1, p2);
cc.setz(ret.r8());
cc.bind(L_Exit);
cc.ret(ret);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(void);
Func func = ptr_as_func<Func>(_func);
int resultRet = func();
int expectRet = 0; // Must be zero, stack addresses must be different.
result.assignInt(resultRet);
expect.assignInt(expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_FuncCallStd
// ===================================
class X86Test_FuncCallStd : public X86TestCase {
public:
X86Test_FuncCallStd() : X86TestCase("FuncCallStd") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallStd());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp x = cc.newInt32("x");
x86::Gp y = cc.newInt32("y");
x86::Gp z = cc.newInt32("z");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int, int, int>());
funcNode->setArg(0, x);
funcNode->setArg(1, y);
funcNode->setArg(2, z);
InvokeNode* invokeNode;
cc.invoke(&invokeNode,
imm((void*)calledFunc),
FuncSignature::build<int, int, int, int>(CallConvId::kStdCall));
invokeNode->setArg(0, x);
invokeNode->setArg(1, y);
invokeNode->setArg(2, z);
invokeNode->setRet(0, x);
cc.ret(x);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int, int, int);
Func func = ptr_as_func<Func>(_func);
int resultRet = func(1, 42, 3);
int expectRet = calledFunc(1, 42, 3);
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
// STDCALL function that is called inside the generated one.
static int ASMJIT_STDCALL calledFunc(int a, int b, int c) noexcept {
return (a + b) * c;
}
};
// x86::Compiler - X86Test_FuncCallFast
// ====================================
class X86Test_FuncCallFast : public X86TestCase {
public:
X86Test_FuncCallFast() : X86TestCase("FuncCallFast") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallFast());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp var = cc.newInt32("var");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int>());
funcNode->setArg(0, var);
InvokeNode* invokeNode;
cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignature::build<int, int>(CallConvId::kFastCall));
invokeNode->setArg(0, var);
invokeNode->setRet(0, var);
cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignature::build<int, int>(CallConvId::kFastCall));
invokeNode->setArg(0, var);
invokeNode->setRet(0, var);
cc.ret(var);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int);
Func func = ptr_as_func<Func>(_func);
int resultRet = func(9);
int expectRet = (9 * 9) * (9 * 9);
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
// FASTCALL function that is called inside the generated one.
static int ASMJIT_FASTCALL calledFunc(int a) noexcept {
return a * a;
}
};
// x86::Compiler - X86Test_FuncCallSIMD
// ====================================
#if ASMJIT_ARCH_X86
class X86Test_FuncCallSIMD : public X86TestCase {
public:
bool _useVectorCall;
X86Test_FuncCallSIMD(bool useVectorCall)
: X86TestCase(),
_useVectorCall(useVectorCall) {
_name.assignFormat("FuncCallSIMD {%s}", _useVectorCall ? "__vectorcall" : "__cdecl");
}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallSIMD(false));
#ifdef _MSC_VER
app.add(new X86Test_FuncCallSIMD(true));
#endif
}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<void, void*, const void*, const void*>());
x86::Gp resultPtr = cc.newIntPtr("resultPtr");
x86::Gp aPtr = cc.newIntPtr("aPtr");
x86::Gp bPtr = cc.newIntPtr("bPtr");
x86::Gp pFn = cc.newIntPtr("pFn");
x86::Xmm aXmm = cc.newXmm("aXmm");
x86::Xmm bXmm = cc.newXmm("bXmm");
funcNode->setArg(0, resultPtr);
funcNode->setArg(1, aPtr);
funcNode->setArg(2, bPtr);
CallConvId ccId = CallConvId::kCDecl;
Imm pFnImm = imm((void*)calledFunc_cdecl);
#ifdef _MSC_VER
if (_useVectorCall) {
ccId = CallConvId::kVectorCall;
pFnImm = imm((void*)calledFunc_vcall);
}
#endif
cc.mov(pFn, pFnImm);
cc.movdqu(aXmm, x86::ptr(aPtr));
cc.movdqu(bXmm, x86::ptr(bPtr));
InvokeNode* invokeNode;
cc.invoke(&invokeNode, pFn, FuncSignature::build<x86::Xmm, x86::Xmm, x86::Xmm>(ccId));
invokeNode->setArg(0, aXmm);
invokeNode->setArg(1, bXmm);
invokeNode->setRet(0, aXmm);
cc.movdqu(x86::ptr(resultPtr), aXmm);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(void*, const void*, const void*);
Func func = ptr_as_func<Func>(_func);
uint8_t aData[16] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
uint8_t bData[16] = { 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0 };
uint8_t rData[16] {};
uint8_t eData[16] = { 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, 15 };
func(rData, aData, bData);
result.appendHex(rData, 16);
expect.appendHex(eData, 16);
return result == expect;
}
static __m128i calledFunc_cdecl(__m128i a, __m128i b) {
return _mm_add_epi8(a, b);
}
#ifdef _MSC_VER
static __m128i __vectorcall calledFunc_vcall(__m128i a, __m128i b) {
return _mm_add_epi8(a, b);
}
#endif
};
#endif // ASMJIT_ARCH_X86
// x86::Compiler - X86Test_FuncCallLight
// =====================================
class X86Test_FuncCallLight : public X86TestCase {
public:
X86Test_FuncCallLight() : X86TestCase("FuncCallLight") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallLight());
}
virtual void compile(x86::Compiler& cc) {
FuncSignature f1Sig = FuncSignature::build<void, const void*, const void*, const void*, const void*, void*>();
FuncSignature f2Sig = FuncSignature::build<x86::Xmm, x86::Xmm, x86::Xmm>(CallConvId::kLightCall2);
FuncNode* f1Node = cc.newFunc(f1Sig);
FuncNode* f2Node = cc.newFunc(f2Sig);
{
x86::Gp aPtr = cc.newIntPtr("aPtr");
x86::Gp bPtr = cc.newIntPtr("bPtr");
x86::Gp cPtr = cc.newIntPtr("cPtr");
x86::Gp dPtr = cc.newIntPtr("dPtr");
x86::Gp pOut = cc.newIntPtr("pOut");
x86::Xmm aXmm = cc.newXmm("aXmm");
x86::Xmm bXmm = cc.newXmm("bXmm");
x86::Xmm cXmm = cc.newXmm("cXmm");
x86::Xmm dXmm = cc.newXmm("dXmm");
cc.addFunc(f1Node);
f1Node->setArg(0, aPtr);
f1Node->setArg(1, bPtr);
f1Node->setArg(2, cPtr);
f1Node->setArg(3, dPtr);
f1Node->setArg(4, pOut);
cc.movups(aXmm, x86::ptr(aPtr));
cc.movups(bXmm, x86::ptr(bPtr));
cc.movups(cXmm, x86::ptr(cPtr));
cc.movups(dXmm, x86::ptr(dPtr));
x86::Xmm xXmm = cc.newXmm("xXmm");
x86::Xmm yXmm = cc.newXmm("yXmm");
InvokeNode* invokeNode;
cc.invoke(&invokeNode, f2Node->label(), f2Sig);
invokeNode->setArg(0, aXmm);
invokeNode->setArg(1, bXmm);
invokeNode->setRet(0, xXmm);
cc.invoke(&invokeNode, f2Node->label(), f2Sig);
invokeNode->setArg(0, cXmm);
invokeNode->setArg(1, dXmm);
invokeNode->setRet(0, yXmm);
cc.pmullw(xXmm, yXmm);
cc.movups(x86::ptr(pOut), xXmm);
cc.endFunc();
}
{
x86::Xmm aXmm = cc.newXmm("aXmm");
x86::Xmm bXmm = cc.newXmm("bXmm");
cc.addFunc(f2Node);
f2Node->setArg(0, aXmm);
f2Node->setArg(1, bXmm);
cc.paddw(aXmm, bXmm);
cc.ret(aXmm);
cc.endFunc();
}
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(const void*, const void*, const void*, const void*, void*);
Func func = ptr_as_func<Func>(_func);
int16_t a[8] = { 0, 1, 2, 3, 4, 5, 6, 7 };
int16_t b[8] = { 7, 6, 5, 4, 3, 2, 1, 0 };
int16_t c[8] = { 1, 3, 9, 7, 5, 4, 2, 1 };
int16_t d[8] = { 2, 0,-6,-4,-2,-1, 1, 2 };
int16_t o[8] {};
int oExp = 7 * 3;
func(a, b, c, d, o);
result.assignFormat("ret={%02X %02X %02X %02X %02X %02X %02X %02X}", o[0], o[1], o[2], o[3], o[4], o[5], o[6], o[7]);
expect.assignFormat("ret={%02X %02X %02X %02X %02X %02X %02X %02X}", oExp, oExp, oExp, oExp, oExp, oExp, oExp, oExp);
return result == expect;
}
};
// x86::Compiler - X86Test_FuncCallManyArgs
// ========================================
class X86Test_FuncCallManyArgs : public X86TestCase {
public:
X86Test_FuncCallManyArgs() : X86TestCase("FuncCallManyArgs") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallManyArgs());
}
static int calledFunc(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
return (a * b * c * d * e) + (f * g * h * i * j);
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<int>());
// Prepare.
x86::Gp va = cc.newInt32("va");
x86::Gp vb = cc.newInt32("vb");
x86::Gp vc = cc.newInt32("vc");
x86::Gp vd = cc.newInt32("vd");
x86::Gp ve = cc.newInt32("ve");
x86::Gp vf = cc.newInt32("vf");
x86::Gp vg = cc.newInt32("vg");
x86::Gp vh = cc.newInt32("vh");
x86::Gp vi = cc.newInt32("vi");
x86::Gp vj = cc.newInt32("vj");
cc.mov(va, 0x03);
cc.mov(vb, 0x12);
cc.mov(vc, 0xA0);
cc.mov(vd, 0x0B);
cc.mov(ve, 0x2F);
cc.mov(vf, 0x02);
cc.mov(vg, 0x0C);
cc.mov(vh, 0x12);
cc.mov(vi, 0x18);
cc.mov(vj, 0x1E);
// Function call.
InvokeNode* invokeNode;
cc.invoke(&invokeNode,
imm((void*)calledFunc),
FuncSignature::build<int, int, int, int, int, int, int, int, int, int, int>());
invokeNode->setArg(0, va);
invokeNode->setArg(1, vb);
invokeNode->setArg(2, vc);
invokeNode->setArg(3, vd);
invokeNode->setArg(4, ve);
invokeNode->setArg(5, vf);
invokeNode->setArg(6, vg);
invokeNode->setArg(7, vh);
invokeNode->setArg(8, vi);
invokeNode->setArg(9, vj);
invokeNode->setRet(0, va);
cc.ret(va);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(void);
Func func = ptr_as_func<Func>(_func);
int resultRet = func();
int expectRet = calledFunc(0x03, 0x12, 0xA0, 0x0B, 0x2F, 0x02, 0x0C, 0x12, 0x18, 0x1E);
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_FuncCallDuplicateArgs
// =============================================
class X86Test_FuncCallDuplicateArgs : public X86TestCase {
public:
X86Test_FuncCallDuplicateArgs() : X86TestCase("FuncCallDuplicateArgs") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallDuplicateArgs());
}
static int calledFunc(int a, int b, int c, int d, int e, int f, int g, int h, int i, int j) {
return (a * b * c * d * e) + (f * g * h * i * j);
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<int>());
// Prepare.
x86::Gp a = cc.newInt32("a");
cc.mov(a, 3);
// Call function.
InvokeNode* invokeNode;
cc.invoke(&invokeNode,
imm((void*)calledFunc),
FuncSignature::build<int, int, int, int, int, int, int, int, int, int, int>());
invokeNode->setArg(0, a);
invokeNode->setArg(1, a);
invokeNode->setArg(2, a);
invokeNode->setArg(3, a);
invokeNode->setArg(4, a);
invokeNode->setArg(5, a);
invokeNode->setArg(6, a);
invokeNode->setArg(7, a);
invokeNode->setArg(8, a);
invokeNode->setArg(9, a);
invokeNode->setRet(0, a);
cc.ret(a);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(void);
Func func = ptr_as_func<Func>(_func);
int resultRet = func();
int expectRet = calledFunc(3, 3, 3, 3, 3, 3, 3, 3, 3, 3);
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_FuncCallImmArgs
// =======================================
class X86Test_FuncCallImmArgs : public X86TestCase {
public:
X86Test_FuncCallImmArgs() : X86TestCase("FuncCallImmArgs") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallImmArgs());
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<int>());
// Prepare.
x86::Gp rv = cc.newInt32("rv");
// Call function.
InvokeNode* invokeNode;
cc.invoke(&invokeNode,
imm((void*)X86Test_FuncCallManyArgs::calledFunc),
FuncSignature::build<int, int, int, int, int, int, int, int, int, int, int>());
invokeNode->setArg(0, imm(0x03));
invokeNode->setArg(1, imm(0x12));
invokeNode->setArg(2, imm(0xA0));
invokeNode->setArg(3, imm(0x0B));
invokeNode->setArg(4, imm(0x2F));
invokeNode->setArg(5, imm(0x02));
invokeNode->setArg(6, imm(0x0C));
invokeNode->setArg(7, imm(0x12));
invokeNode->setArg(8, imm(0x18));
invokeNode->setArg(9, imm(0x1E));
invokeNode->setRet(0, rv);
cc.ret(rv);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(void);
Func func = ptr_as_func<Func>(_func);
int resultRet = func();
int expectRet = X86Test_FuncCallManyArgs::calledFunc(0x03, 0x12, 0xA0, 0x0B, 0x2F, 0x02, 0x0C, 0x12, 0x18, 0x1E);
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_FuncCallPtrArgs
// =======================================
class X86Test_FuncCallPtrArgs : public X86TestCase {
public:
X86Test_FuncCallPtrArgs() : X86TestCase("FuncCallPtrArgs") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallPtrArgs());
}
static int calledFunc(void* a, void* b, void* c, void* d, void* e, void* f, void* g, void* h, void* i, void* j) {
return int((intptr_t)a) +
int((intptr_t)b) +
int((intptr_t)c) +
int((intptr_t)d) +
int((intptr_t)e) +
int((intptr_t)f) +
int((intptr_t)g) +
int((intptr_t)h) +
int((intptr_t)i) +
int((intptr_t)j) ;
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<int>());
// Prepare.
x86::Gp rv = cc.newInt32("rv");
// Call function.
InvokeNode* invokeNode;
cc.invoke(&invokeNode,
imm((void*)calledFunc),
FuncSignature::build<int, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*>());
invokeNode->setArg(0, imm(0x01));
invokeNode->setArg(1, imm(0x02));
invokeNode->setArg(2, imm(0x03));
invokeNode->setArg(3, imm(0x04));
invokeNode->setArg(4, imm(0x05));
invokeNode->setArg(5, imm(0x06));
invokeNode->setArg(6, imm(0x07));
invokeNode->setArg(7, imm(0x08));
invokeNode->setArg(8, imm(0x09));
invokeNode->setArg(9, imm(0x0A));
invokeNode->setRet(0, rv);
cc.ret(rv);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(void);
Func func = ptr_as_func<Func>(_func);
int resultRet = func();
int expectRet = 55;
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_FuncCallRefArgs
// =======================================
class X86Test_FuncCallRefArgs : public X86TestCase {
public:
X86Test_FuncCallRefArgs() : X86TestCase("FuncCallRefArgs") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallRefArgs());
}
static int calledFunc(int& a, int& b, int& c, int& d) {
a += a;
b += b;
c += c;
d += d;
return a + b + c + d;
}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int&, int&, int&, int&>());
// Prepare.
x86::Gp arg1 = cc.newInt32();
x86::Gp arg2 = cc.newInt32();
x86::Gp arg3 = cc.newInt32();
x86::Gp arg4 = cc.newInt32();
x86::Gp rv = cc.newInt32("rv");
funcNode->setArg(0, arg1);
funcNode->setArg(1, arg2);
funcNode->setArg(2, arg3);
funcNode->setArg(3, arg4);
// Call function.
InvokeNode* invokeNode;
cc.invoke(&invokeNode,
imm((void*)calledFunc),
FuncSignature::build<int, int&, int&, int&, int&>());
invokeNode->setArg(0, arg1);
invokeNode->setArg(1, arg2);
invokeNode->setArg(2, arg3);
invokeNode->setArg(3, arg4);
invokeNode->setRet(0, rv);
cc.ret(rv);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int&, int&, int&, int&);
Func func = ptr_as_func<Func>(_func);
int inputs[4] = { 1, 2, 3, 4 };
int outputs[4] = { 2, 4, 6, 8 };
int resultRet = func(inputs[0], inputs[1], inputs[2], inputs[3]);
int expectRet = 20;
result.assignFormat("ret={%08X %08X %08X %08X %08X}", resultRet, inputs[0], inputs[1], inputs[2], inputs[3]);
expect.assignFormat("ret={%08X %08X %08X %08X %08X}", expectRet, outputs[0], outputs[1], outputs[2], outputs[3]);
return result == expect;
}
};
// x86::Compiler - X86Test_FuncCallFloatAsXmmRet
// =============================================
class X86Test_FuncCallFloatAsXmmRet : public X86TestCase {
public:
X86Test_FuncCallFloatAsXmmRet() : X86TestCase("FuncCallFloatAsXmmRet") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallFloatAsXmmRet());
}
static float calledFunc(float a, float b) {
return a * b;
}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<float, float, float>());
x86::Xmm a = cc.newXmmSs("a");
x86::Xmm b = cc.newXmmSs("b");
x86::Xmm ret = cc.newXmmSs("ret");
funcNode->setArg(0, a);
funcNode->setArg(1, b);
// Call function.
InvokeNode* invokeNode;
cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignature::build<float, float, float>());
invokeNode->setArg(0, a);
invokeNode->setArg(1, b);
invokeNode->setRet(0, ret);
cc.ret(ret);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef float (*Func)(float, float);
Func func = ptr_as_func<Func>(_func);
float resultRet = func(15.5f, 2.0f);
float expectRet = calledFunc(15.5f, 2.0f);
result.assignFormat("ret=%g", resultRet);
expect.assignFormat("ret=%g", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_FuncCallDoubleAsXmmRet
// ==============================================
class X86Test_FuncCallDoubleAsXmmRet : public X86TestCase {
public:
X86Test_FuncCallDoubleAsXmmRet() : X86TestCase("FuncCallDoubleAsXmmRet") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallDoubleAsXmmRet());
}
static double calledFunc(double a, double b) {
return a * b;
}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<double, double, double>());
x86::Xmm a = cc.newXmmSd("a");
x86::Xmm b = cc.newXmmSd("b");
x86::Xmm ret = cc.newXmmSd("ret");
funcNode->setArg(0, a);
funcNode->setArg(1, b);
InvokeNode* invokeNode;
cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignature::build<double, double, double>());
invokeNode->setArg(0, a);
invokeNode->setArg(1, b);
invokeNode->setRet(0, ret);
cc.ret(ret);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef double (*Func)(double, double);
Func func = ptr_as_func<Func>(_func);
double resultRet = func(15.5, 2.0);
double expectRet = calledFunc(15.5, 2.0);
result.assignFormat("ret=%g", resultRet);
expect.assignFormat("ret=%g", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_FuncCallConditional
// ===========================================
class X86Test_FuncCallConditional : public X86TestCase {
public:
X86Test_FuncCallConditional() : X86TestCase("FuncCallConditional") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallConditional());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp x = cc.newInt32("x");
x86::Gp y = cc.newInt32("y");
x86::Gp op = cc.newInt32("op");
InvokeNode* invokeNode;
x86::Gp result;
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int, int, int>());
funcNode->setArg(0, x);
funcNode->setArg(1, y);
funcNode->setArg(2, op);
Label opAdd = cc.newLabel();
Label opMul = cc.newLabel();
cc.cmp(op, 0);
cc.jz(opAdd);
cc.cmp(op, 1);
cc.jz(opMul);
result = cc.newInt32("result_0");
cc.mov(result, 0);
cc.ret(result);
cc.bind(opAdd);
result = cc.newInt32("result_1");
cc.invoke(&invokeNode, (uint64_t)calledFuncAdd, FuncSignature::build<int, int, int>());
invokeNode->setArg(0, x);
invokeNode->setArg(1, y);
invokeNode->setRet(0, result);
cc.ret(result);
cc.bind(opMul);
result = cc.newInt32("result_2");
cc.invoke(&invokeNode, (uint64_t)calledFuncMul, FuncSignature::build<int, int, int>());
invokeNode->setArg(0, x);
invokeNode->setArg(1, y);
invokeNode->setRet(0, result);
cc.ret(result);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int, int, int);
Func func = ptr_as_func<Func>(_func);
int arg1 = 4;
int arg2 = 8;
int resultAdd = func(arg1, arg2, 0);
int expectAdd = calledFuncAdd(arg1, arg2);
int resultMul = func(arg1, arg2, 1);
int expectMul = calledFuncMul(arg1, arg2);
result.assignFormat("ret={add=%d, mul=%d}", resultAdd, resultMul);
expect.assignFormat("ret={add=%d, mul=%d}", expectAdd, expectMul);
return (resultAdd == expectAdd) && (resultMul == expectMul);
}
static int calledFuncAdd(int x, int y) { return x + y; }
static int calledFuncMul(int x, int y) { return x * y; }
};
// x86::Compiler - X86Test_FuncCallMultiple
// ========================================
class X86Test_FuncCallMultiple : public X86TestCase {
public:
X86Test_FuncCallMultiple() : X86TestCase("FuncCallMultiple") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallMultiple());
}
static int ASMJIT_FASTCALL calledFunc(int* pInt, int index) {
return pInt[index];
}
virtual void compile(x86::Compiler& cc) {
unsigned int i;
x86::Gp buf = cc.newIntPtr("buf");
x86::Gp acc0 = cc.newInt32("acc0");
x86::Gp acc1 = cc.newInt32("acc1");
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int*>());
funcNode->setArg(0, buf);
cc.mov(acc0, 0);
cc.mov(acc1, 0);
for (i = 0; i < 4; i++) {
x86::Gp ret = cc.newInt32("ret");
x86::Gp ptr = cc.newIntPtr("ptr");
x86::Gp idx = cc.newInt32("idx");
InvokeNode* invokeNode;
cc.mov(ptr, buf);
cc.mov(idx, int(i));
cc.invoke(&invokeNode, (uint64_t)calledFunc, FuncSignature::build<int, int*, int>(CallConvId::kFastCall));
invokeNode->setArg(0, ptr);
invokeNode->setArg(1, idx);
invokeNode->setRet(0, ret);
cc.add(acc0, ret);
cc.mov(ptr, buf);
cc.mov(idx, int(i));
cc.invoke(&invokeNode, (uint64_t)calledFunc, FuncSignature::build<int, int*, int>(CallConvId::kFastCall));
invokeNode->setArg(0, ptr);
invokeNode->setArg(1, idx);
invokeNode->setRet(0, ret);
cc.sub(acc1, ret);
}
cc.add(acc0, acc1);
cc.ret(acc0);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int*);
Func func = ptr_as_func<Func>(_func);
int buffer[4] = { 127, 87, 23, 17 };
int resultRet = func(buffer);
int expectRet = 0;
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_FuncCallRecursive
// =========================================
class X86Test_FuncCallRecursive : public X86TestCase {
public:
X86Test_FuncCallRecursive() : X86TestCase("FuncCallRecursive") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallRecursive());
}
virtual void compile(x86::Compiler& cc) {
x86::Gp val = cc.newInt32("val");
Label skip = cc.newLabel();
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int>());
funcNode->setArg(0, val);
cc.cmp(val, 1);
cc.jle(skip);
x86::Gp tmp = cc.newInt32("tmp");
cc.mov(tmp, val);
cc.dec(tmp);
InvokeNode* invokeNode;
cc.invoke(&invokeNode, funcNode->label(), FuncSignature::build<int, int>());
invokeNode->setArg(0, tmp);
invokeNode->setRet(0, tmp);
cc.mul(cc.newInt32(), val, tmp);
cc.bind(skip);
cc.ret(val);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int);
Func func = ptr_as_func<Func>(_func);
int resultRet = func(5);
int expectRet = 1 * 2 * 3 * 4 * 5;
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_FuncCallVarArg1
// =======================================
class X86Test_FuncCallVarArg1 : public X86TestCase {
public:
X86Test_FuncCallVarArg1() : X86TestCase("FuncCallVarArg1") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallVarArg1());
}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int, int, int, int>());
x86::Gp a0 = cc.newInt32("a0");
x86::Gp a1 = cc.newInt32("a1");
x86::Gp a2 = cc.newInt32("a2");
x86::Gp a3 = cc.newInt32("a3");
funcNode->setArg(0, a0);
funcNode->setArg(1, a1);
funcNode->setArg(2, a2);
funcNode->setArg(3, a3);
// We call `int func(size_t, ...)`
// - The `vaIndex` must be 1 (first argument after size_t).
// - The full signature of varargs (int, int, int, int) must follow.
InvokeNode* invokeNode;
cc.invoke(&invokeNode,
imm((void*)calledFunc),
FuncSignature::build<int, size_t, int, int, int, int>(CallConvId::kCDecl, 1));
invokeNode->setArg(0, imm(4));
invokeNode->setArg(1, a0);
invokeNode->setArg(2, a1);
invokeNode->setArg(3, a2);
invokeNode->setArg(4, a3);
invokeNode->setRet(0, a0);
cc.ret(a0);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int, int, int, int);
Func func = ptr_as_func<Func>(_func);
int resultRet = func(1, 2, 3, 4);
int expectRet = 1 + 2 + 3 + 4;
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
static int calledFunc(size_t n, ...) {
int sum = 0;
va_list ap;
va_start(ap, n);
for (size_t i = 0; i < n; i++) {
int arg = va_arg(ap, int);
sum += arg;
}
va_end(ap);
return sum;
}
};
// x86::Compiler - X86Test_FuncCallVarArg2
// =======================================
class X86Test_FuncCallVarArg2 : public X86TestCase {
public:
X86Test_FuncCallVarArg2() : X86TestCase("FuncCallVarArg2") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallVarArg2());
}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<double, double, double, double, double>());
x86::Xmm a0 = cc.newXmmSd("a0");
x86::Xmm a1 = cc.newXmmSd("a1");
x86::Xmm a2 = cc.newXmmSd("a2");
x86::Xmm a3 = cc.newXmmSd("a3");
funcNode->setArg(0, a0);
funcNode->setArg(1, a1);
funcNode->setArg(2, a2);
funcNode->setArg(3, a3);
// We call `double func(size_t, ...)`
// - The `vaIndex` must be 1 (first argument after size_t).
// - The full signature of varargs (double, double, double, double) must follow.
InvokeNode* invokeNode;
cc.invoke(&invokeNode,
imm((void*)calledFunc),
FuncSignature::build<double, size_t, double, double, double, double>(CallConvId::kCDecl, 1));
invokeNode->setArg(0, imm(4));
invokeNode->setArg(1, a0);
invokeNode->setArg(2, a1);
invokeNode->setArg(3, a2);
invokeNode->setArg(4, a3);
invokeNode->setRet(0, a0);
cc.ret(a0);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef double (*Func)(double, double, double, double);
Func func = ptr_as_func<Func>(_func);
double resultRet = func(1.0, 2.0, 3.0, 4.0);
double expectRet = 1.0 + 2.0 + 3.0 + 4.0;
result.assignFormat("ret=%f", resultRet);
expect.assignFormat("ret=%f", expectRet);
return result == expect;
}
static double calledFunc(size_t n, ...) {
double sum = 0;
va_list ap;
va_start(ap, n);
for (size_t i = 0; i < n; i++) {
double arg = va_arg(ap, double);
sum += arg;
}
va_end(ap);
return sum;
}
};
// x86::Compiler - X86Test_FuncCallInt64Arg
// ========================================
class X86Test_FuncCallInt64Arg : public X86TestCase {
public:
X86Test_FuncCallInt64Arg() : X86TestCase("FuncCallInt64Arg") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallInt64Arg());
}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<uint64_t, uint64_t>());
if (cc.is64Bit()) {
x86::Gp reg = cc.newUInt64();
funcNode->setArg(0, reg);
cc.add(reg, 1);
cc.ret(reg);
}
else {
x86::Gp hi = cc.newUInt32("hi");
x86::Gp lo = cc.newUInt32("lo");
funcNode->setArg(0, 0, lo);
funcNode->setArg(0, 1, hi);
cc.add(lo, 1);
cc.adc(hi, 0);
cc.ret(lo, hi);
}
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef uint64_t (*Func)(uint64_t);
Func func = ptr_as_func<Func>(_func);
uint64_t resultRet = func(uint64_t(0xFFFFFFFF));
uint64_t expectRet = 0x100000000;
result.assignFormat("ret=%llu", (unsigned long long)resultRet);
expect.assignFormat("ret=%llu", (unsigned long long)expectRet);
return result == expect;
}
static double calledFunc(size_t n, ...) {
double sum = 0;
va_list ap;
va_start(ap, n);
for (size_t i = 0; i < n; i++) {
double arg = va_arg(ap, double);
sum += arg;
}
va_end(ap);
return sum;
}
};
// x86::Compiler - X86Test_FuncCallMisc1
// =====================================
class X86Test_FuncCallMisc1 : public X86TestCase {
public:
X86Test_FuncCallMisc1() : X86TestCase("FuncCallMisc1") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallMisc1());
}
static void dummy(int, int) {}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int, int>());
x86::Gp a = cc.newInt32("a");
x86::Gp b = cc.newInt32("b");
x86::Gp r = cc.newInt32("r");
funcNode->setArg(0, a);
funcNode->setArg(1, b);
InvokeNode* invokeNode;
cc.invoke(&invokeNode,
imm((void*)dummy),
FuncSignature::build<void, int, int>());
invokeNode->setArg(0, a);
invokeNode->setArg(1, b);
cc.lea(r, x86::ptr(a, b));
cc.ret(r);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int, int);
Func func = ptr_as_func<Func>(_func);
int resultRet = func(44, 199);
int expectRet = 243;
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_FuncCallMisc2
// =====================================
class X86Test_FuncCallMisc2 : public X86TestCase {
public:
X86Test_FuncCallMisc2() : X86TestCase("FuncCallMisc2") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallMisc2());
}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<double, const double*>());
x86::Gp p = cc.newIntPtr("p");
x86::Xmm arg = cc.newXmmSd("arg");
x86::Xmm ret = cc.newXmmSd("ret");
funcNode->setArg(0, p);
cc.movsd(arg, x86::ptr(p));
InvokeNode* invokeNode;
cc.invoke(&invokeNode,
imm((void*)op),
FuncSignature::build<double, double>());
invokeNode->setArg(0, arg);
invokeNode->setRet(0, ret);
cc.ret(ret);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef double (*Func)(const double*);
Func func = ptr_as_func<Func>(_func);
double arg = 2;
double resultRet = func(&arg);
double expectRet = op(arg);
result.assignFormat("ret=%g", resultRet);
expect.assignFormat("ret=%g", expectRet);
return result == expect;
}
static double op(double a) { return a * a; }
};
// x86::Compiler - X86Test_FuncCallMisc3
// =====================================
class X86Test_FuncCallMisc3 : public X86TestCase {
public:
X86Test_FuncCallMisc3() : X86TestCase("FuncCallMisc3") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallMisc3());
}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<double, const double*>());
x86::Gp p = cc.newIntPtr("p");
x86::Xmm arg = cc.newXmmSd("arg");
x86::Xmm ret = cc.newXmmSd("ret");
funcNode->setArg(0, p);
cc.movsd(arg, x86::ptr(p));
InvokeNode* invokeNode;
cc.invoke(&invokeNode,
imm((void*)op),
FuncSignature::build<double, double>());
invokeNode->setArg(0, arg);
invokeNode->setRet(0, ret);
cc.xorps(arg, arg);
cc.subsd(arg, ret);
cc.ret(arg);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef double (*Func)(const double*);
Func func = ptr_as_func<Func>(_func);
double arg = 2;
double resultRet = func(&arg);
double expectRet = -op(arg);
result.assignFormat("ret=%g", resultRet);
expect.assignFormat("ret=%g", expectRet);
return result == expect;
}
static double op(double a) { return a * a; }
};
// x86::Compiler - X86Test_FuncCallMisc4
// =====================================
class X86Test_FuncCallMisc4 : public X86TestCase {
public:
X86Test_FuncCallMisc4() : X86TestCase("FuncCallMisc4") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallMisc4());
}
virtual void compile(x86::Compiler& cc) {
InvokeNode* invokeNode;
FuncSignature funcSignature;
funcSignature.setCallConvId(CallConvId::kCDecl);
funcSignature.setRet(TypeId::kFloat64);
cc.addFunc(funcSignature);
FuncSignature invokeSignature;
invokeSignature.setCallConvId(CallConvId::kCDecl);
invokeSignature.setRet(TypeId::kFloat64);
cc.invoke(&invokeNode, imm((void*)calledFunc), invokeSignature);
x86::Xmm ret = cc.newXmmSd("ret");
invokeNode->setRet(0, ret);
cc.ret(ret);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef double (*Func)(void);
Func func = ptr_as_func<Func>(_func);
double resultRet = func();
double expectRet = 3.14;
result.assignFormat("ret=%g", resultRet);
expect.assignFormat("ret=%g", expectRet);
return result == expect;
}
static double calledFunc() { return 3.14; }
};
// x86::Compiler - X86Test_FuncCallMisc5
// =====================================
// The register allocator should clobber the register used by the `call` itself.
class X86Test_FuncCallMisc5 : public X86TestCase {
public:
X86Test_FuncCallMisc5() : X86TestCase("FuncCallMisc5") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallMisc5());
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<int>());
x86::Gp pFn = cc.newIntPtr("pFn");
x86::Gp vars[16];
uint32_t i, regCount = cc.arch() == Arch::kX86 ? 8 : 16;
ASMJIT_ASSERT(regCount <= ASMJIT_ARRAY_SIZE(vars));
cc.mov(pFn, imm((void*)calledFunc));
for (i = 0; i < regCount; i++) {
if (i == x86::Gp::kIdBp || i == x86::Gp::kIdSp)
continue;
vars[i] = cc.newInt32("%%%u", unsigned(i));
cc.mov(vars[i], 1);
}
InvokeNode* invokeNode;
cc.invoke(&invokeNode, pFn, FuncSignature::build<void>());
for (i = 1; i < regCount; i++)
if (vars[i].isValid())
cc.add(vars[0], vars[i]);
cc.ret(vars[0]);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(void);
Func func = ptr_as_func<Func>(_func);
int resultRet = func();
int expectRet = sizeof(void*) == 4 ? 6 : 14;
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
static void calledFunc() {}
};
// x86::Compiler - X86Test_FuncCallMisc6
// =====================================
class X86Test_FuncCallMisc6 : public X86TestCase {
public:
X86Test_FuncCallMisc6() : X86TestCase("FuncCallMisc6") {}
static void add(TestApp& app) {
app.add(new X86Test_FuncCallMisc6());
}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<uint32_t, uint32_t>());
constexpr uint32_t kCount = 16;
x86::Gp v[kCount];
x86::Gp argVal = cc.newUInt32("argVal");
x86::Gp retVal = cc.newUInt32("retVal");
uint32_t i;
funcNode->setArg(0, argVal);
cc.add(argVal, 1);
for (i = 0; i < kCount; i++)
v[i] = cc.newUInt32("v%u", i);
InvokeNode* invokeNode;
cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignature::build<uint32_t, uint32_t>());
invokeNode->setArg(0, argVal);
invokeNode->setRet(0, retVal);
for (i = 0; i < kCount; i++)
cc.mov(v[i], i + 1);
for (i = 0; i < kCount; i++)
cc.add(argVal, v[i]);
cc.add(retVal, argVal);
cc.ret(retVal);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef uint32_t (*Func)(uint32_t x);
Func func = ptr_as_func<Func>(_func);
uint32_t resultRet = func(111);
uint32_t expectRet = 111 + 112 + 2 + (1 + 16) * 8;
result.assignFormat("ret=%u", resultRet);
expect.assignFormat("ret=%u", expectRet);
return result == expect;
}
static uint32_t calledFunc(uint32_t x) { return x + 1; }
};
// x86::Compiler - X86Test_FuncCallAVXClobber
// ==========================================
class X86Test_FuncCallAVXClobber : public X86TestCase {
public:
X86Test_FuncCallAVXClobber() : X86TestCase("FuncCallAVXClobber") {}
static void add(TestApp& app) {
const CpuInfo& cpuInfo = CpuInfo::host();
if (cpuInfo.features().x86().hasAVX2() && sizeof(void*) == 8)
app.add(new X86Test_FuncCallAVXClobber());
}
virtual void compile(x86::Compiler& cc) {
FuncNode* mainFunc = cc.addFunc(FuncSignature::build<void, void*, const void*, const void*>());
mainFunc->frame().setAvxEnabled();
mainFunc->frame().setAvxCleanup();
// We need a Windows calling convention to test this properly also on a non-Windows machine.
FuncNode* helperFunc = cc.newFunc(FuncSignature::build<void, void*, const void*>(CallConvId::kX64Windows));
helperFunc->frame().setAvxEnabled();
helperFunc->frame().setAvxCleanup();
{
size_t i;
x86::Gp dPtr = cc.newIntPtr("dPtr");
x86::Gp aPtr = cc.newIntPtr("aPtr");
x86::Gp bPtr = cc.newIntPtr("bPtr");
x86::Gp tPtr = cc.newIntPtr("tPtr");
x86::Ymm acc[8];
x86::Mem stack = cc.newStack(32, 1, "stack");
mainFunc->setArg(0, dPtr);
mainFunc->setArg(1, aPtr);
mainFunc->setArg(2, bPtr);
cc.lea(tPtr, stack);
for (i = 0; i < 8; i++) {
acc[i] = cc.newYmm("acc%zu", i);
cc.vmovdqu(acc[i], x86::ptr(aPtr));
}
InvokeNode* invokeNode;
cc.invoke(&invokeNode,
helperFunc->label(),
FuncSignature::build<void, void*, const void*>(CallConvId::kX64Windows));
invokeNode->setArg(0, tPtr);
invokeNode->setArg(1, bPtr);
for (i = 1; i < 8; i++) {
cc.vpaddd(acc[0], acc[0], acc[i]);
}
cc.vpaddd(acc[0], acc[0], x86::ptr(tPtr));
cc.vmovdqu(x86::ptr(dPtr), acc[0]);
cc.endFunc();
}
{
cc.addFunc(helperFunc);
x86::Gp dPtr = cc.newIntPtr("dPtr");
x86::Gp aPtr = cc.newIntPtr("aPtr");
helperFunc->setArg(0, dPtr);
helperFunc->setArg(1, aPtr);
x86::Gp tmp = cc.newIntPtr("tmp");
x86::Ymm acc = cc.newYmm("acc");
cc.mov(tmp, 1);
cc.vmovd(acc.xmm(), tmp);
cc.vpbroadcastd(acc, acc.xmm());
cc.vpaddd(acc, acc, x86::ptr(aPtr));
cc.vmovdqu(x86::ptr(dPtr), acc);
cc.endFunc();
}
}
virtual bool run(void* _func, String& result, String& expect) {
typedef void (*Func)(void*, const void*, const void*);
Func func = ptr_as_func<Func>(_func);
size_t i;
static const uint32_t aData[8] = { 1, 2, 3, 4, 5, 6, 7, 8 };
static const uint32_t bData[8] = { 6, 3, 5, 9, 1, 8, 7, 2 };
uint32_t resultData[8] {};
uint32_t expectData[8] {};
for (i = 0; i < 8; i++)
expectData[i] = aData[i] * 8 + bData[i] + 1;
func(resultData, aData, bData);
result.assign("{");
expect.assign("{");
for (i = 0; i < 8; i++) {
result.appendFormat("%u", resultData[i]);
expect.appendFormat("%u", expectData[i]);
if (i != 7) result.append(", ");
if (i != 7) expect.append(", ");
}
result.append("}");
expect.append("}");
return result == expect;
}
};
// x86::Compiler - X86Test_VecToScalar
// ===================================
class X86Test_VecToScalar : public X86TestCase {
public:
static constexpr uint32_t kVecCount = 64;
X86Test_VecToScalar() : X86TestCase("VecToScalar") {}
static void add(TestApp& app) {
app.add(new X86Test_VecToScalar());
}
virtual void compile(x86::Compiler& cc) {
FuncNode* func = cc.addFunc(FuncSignature::build<uint32_t, uint32_t>());
x86::Gp x = cc.newInt32("x");
x86::Gp t = cc.newInt32("t");
x86::Xmm v[kVecCount];
func->setArg(0, x);
for (size_t i = 0; i < kVecCount; i++) {
v[i] = cc.newXmm("v%d", i);
if (i != 0)
cc.add(x, 1);
cc.movd(v[i], x);
}
cc.xor_(x, x);
for (size_t i = 0; i < kVecCount; i++) {
cc.movd(t, v[i]);
cc.add(x, t);
}
cc.ret(x);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef uint32_t (*Func)(uint32_t);
Func func = ptr_as_func<Func>(_func);
uint32_t resultRet = func(1);
uint32_t expectRet = 2080; // 1 + 2 + 3 + ... + 64
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_MiscLocalConstPool
// ==========================================
class X86Test_MiscLocalConstPool : public X86TestCase {
public:
X86Test_MiscLocalConstPool() : X86TestCase("MiscLocalConstPool") {}
static void add(TestApp& app) {
app.add(new X86Test_MiscLocalConstPool());
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<int>());
x86::Gp v0 = cc.newInt32("v0");
x86::Gp v1 = cc.newInt32("v1");
x86::Mem c0 = cc.newInt32Const(ConstPoolScope::kLocal, 200);
x86::Mem c1 = cc.newInt32Const(ConstPoolScope::kLocal, 33);
cc.mov(v0, c0);
cc.mov(v1, c1);
cc.add(v0, v1);
cc.ret(v0);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(void);
Func func = ptr_as_func<Func>(_func);
int resultRet = func();
int expectRet = 233;
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_MiscGlobalConstPool
// ===========================================
class X86Test_MiscGlobalConstPool : public X86TestCase {
public:
X86Test_MiscGlobalConstPool() : X86TestCase("MiscGlobalConstPool") {}
static void add(TestApp& app) {
app.add(new X86Test_MiscGlobalConstPool());
}
virtual void compile(x86::Compiler& cc) {
cc.addFunc(FuncSignature::build<int>());
x86::Gp v0 = cc.newInt32("v0");
x86::Gp v1 = cc.newInt32("v1");
x86::Mem c0 = cc.newInt32Const(ConstPoolScope::kGlobal, 200);
x86::Mem c1 = cc.newInt32Const(ConstPoolScope::kGlobal, 33);
cc.mov(v0, c0);
cc.mov(v1, c1);
cc.add(v0, v1);
cc.ret(v0);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(void);
Func func = ptr_as_func<Func>(_func);
int resultRet = func();
int expectRet = 233;
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_MiscMultiRet
// ====================================
struct X86Test_MiscMultiRet : public X86TestCase {
X86Test_MiscMultiRet() : X86TestCase("MiscMultiRet") {}
static void add(TestApp& app) {
app.add(new X86Test_MiscMultiRet());
}
virtual void compile(x86::Compiler& cc) {
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int, int, int>());
x86::Gp op = cc.newInt32("op");
x86::Gp a = cc.newInt32("a");
x86::Gp b = cc.newInt32("b");
Label L_Zero = cc.newLabel();
Label L_Add = cc.newLabel();
Label L_Sub = cc.newLabel();
Label L_Mul = cc.newLabel();
Label L_Div = cc.newLabel();
funcNode->setArg(0, op);
funcNode->setArg(1, a);
funcNode->setArg(2, b);
cc.cmp(op, 0);
cc.jz(L_Add);
cc.cmp(op, 1);
cc.jz(L_Sub);
cc.cmp(op, 2);
cc.jz(L_Mul);
cc.cmp(op, 3);
cc.jz(L_Div);
cc.bind(L_Zero);
cc.xor_(a, a);
cc.ret(a);
cc.bind(L_Add);
cc.add(a, b);
cc.ret(a);
cc.bind(L_Sub);
cc.sub(a, b);
cc.ret(a);
cc.bind(L_Mul);
cc.imul(a, b);
cc.ret(a);
cc.bind(L_Div);
cc.cmp(b, 0);
cc.jz(L_Zero);
x86::Gp zero = cc.newInt32("zero");
cc.xor_(zero, zero);
cc.idiv(zero, a, b);
cc.ret(a);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int, int, int);
Func func = ptr_as_func<Func>(_func);
int a = 44;
int b = 3;
int r0 = func(0, a, b);
int r1 = func(1, a, b);
int r2 = func(2, a, b);
int r3 = func(3, a, b);
int e0 = a + b;
int e1 = a - b;
int e2 = a * b;
int e3 = a / b;
result.assignFormat("ret={%d %d %d %d}", r0, r1, r2, r3);
expect.assignFormat("ret={%d %d %d %d}", e0, e1, e2, e3);
return result == expect;
}
};
// x86::Compiler - X86Test_MiscMultiFunc
// =====================================
class X86Test_MiscMultiFunc : public X86TestCase {
public:
X86Test_MiscMultiFunc() : X86TestCase("MiscMultiFunc") {}
static void add(TestApp& app) {
app.add(new X86Test_MiscMultiFunc());
}
virtual void compile(x86::Compiler& cc) {
FuncNode* f1Node = cc.newFunc(FuncSignature::build<int, int, int>());
FuncNode* f2Node = cc.newFunc(FuncSignature::build<int, int, int>());
{
x86::Gp a = cc.newInt32("a");
x86::Gp b = cc.newInt32("b");
cc.addFunc(f1Node);
f1Node->setArg(0, a);
f1Node->setArg(1, b);
InvokeNode* invokeNode;
cc.invoke(&invokeNode, f2Node->label(), FuncSignature::build<int, int, int>());
invokeNode->setArg(0, a);
invokeNode->setArg(1, b);
invokeNode->setRet(0, a);
cc.ret(a);
cc.endFunc();
}
{
x86::Gp a = cc.newInt32("a");
x86::Gp b = cc.newInt32("b");
cc.addFunc(f2Node);
f2Node->setArg(0, a);
f2Node->setArg(1, b);
cc.add(a, b);
cc.ret(a);
cc.endFunc();
}
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (*Func)(int, int);
Func func = ptr_as_func<Func>(_func);
int resultRet = func(56, 22);
int expectRet = 56 + 22;
result.assignFormat("ret=%d", resultRet);
expect.assignFormat("ret=%d", expectRet);
return result == expect;
}
};
// x86::Compiler - X86Test_MiscUnfollow
// ====================================
// Global (I didn't find a better way to test this).
static jmp_buf globalJmpBuf;
class X86Test_MiscUnfollow : public X86TestCase {
public:
X86Test_MiscUnfollow() : X86TestCase("MiscUnfollow") {}
static void add(TestApp& app) {
app.add(new X86Test_MiscUnfollow());
}
virtual void compile(x86::Compiler& cc) {
// NOTE: Fastcall calling convention is the most appropriate here as all arguments are passed via registers and
// there won't be any stack misalignment in the `handler()`. This was failing on MacOS when targeting 32-bit mode.
x86::Gp a = cc.newInt32("a");
x86::Gp b = cc.newIntPtr("b");
Label tramp = cc.newLabel();
FuncNode* funcNode = cc.addFunc(FuncSignature::build<int, int, void*>(CallConvId::kFastCall));
funcNode->setArg(0, a);
funcNode->setArg(1, b);
cc.cmp(a, 0);
cc.jz(tramp);
cc.ret(a);
cc.bind(tramp);
cc.unfollow().jmp(b);
cc.endFunc();
}
virtual bool run(void* _func, String& result, String& expect) {
typedef int (ASMJIT_FASTCALL *Func)(int, void*);
Func func = ptr_as_func<Func>(_func);
int resultRet = 0;
int expectRet = 1;
if (!setjmp(globalJmpBuf))
resultRet = func(0, (void*)handler);
else
resultRet = 1;
result.assignFormat("ret={%d}", resultRet);
expect.assignFormat("ret={%d}", expectRet);
return result == expect;
}
static void ASMJIT_FASTCALL handler() { longjmp(globalJmpBuf, 1); }
};
// x86::Compiler - Tests
// =====================
void compiler_add_x86_tests(TestApp& app) {
// Base tests.
app.addT<X86Test_NoCode>();
app.addT<X86Test_NoAlign>();
app.addT<X86Test_IndirectBranchProtection>();
app.addT<X86Test_AlignBase>();
// Jump tests.
app.addT<X86Test_JumpMerge>();
app.addT<X86Test_JumpCross>();
app.addT<X86Test_JumpMany>();
app.addT<X86Test_JumpUnreachable1>();
app.addT<X86Test_JumpUnreachable2>();
app.addT<X86Test_JumpTable1>();
app.addT<X86Test_JumpTable2>();
app.addT<X86Test_JumpTable3>();
app.addT<X86Test_JumpTable4>();
// Alloc tests.
app.addT<X86Test_AllocBase>();
app.addT<X86Test_AllocMany1>();
app.addT<X86Test_AllocMany2>();
app.addT<X86Test_AllocImul1>();
app.addT<X86Test_AllocImul2>();
app.addT<X86Test_AllocIdiv1>();
app.addT<X86Test_AllocSetz>();
app.addT<X86Test_AllocShlRor>();
app.addT<X86Test_AllocGpbLo1>();
app.addT<X86Test_AllocGpbLo2>();
app.addT<X86Test_AllocRepMovsb>();
app.addT<X86Test_AllocIfElse1>();
app.addT<X86Test_AllocIfElse2>();
app.addT<X86Test_AllocIfElse3>();
app.addT<X86Test_AllocIfElse4>();
app.addT<X86Test_AllocInt8>();
app.addT<X86Test_AllocUnhandledArg>();
app.addT<X86Test_AllocArgsIntPtr>();
app.addT<X86Test_AllocArgsFloat>();
app.addT<X86Test_AllocArgsDouble>();
#if ASMJIT_ARCH_X86
app.addT<X86Test_AllocArgsVec>();
#endif
app.addT<X86Test_AllocRetFloat1>();
app.addT<X86Test_AllocRetFloat2>();
app.addT<X86Test_AllocRetDouble1>();
app.addT<X86Test_AllocRetDouble2>();
app.addT<X86Test_AllocStack>();
app.addT<X86Test_AllocMemcpy>();
app.addT<X86Test_AllocExtraBlock>();
app.addT<X86Test_AllocAlphaBlend>();
// Function arguments handling tests.
app.addT<X86Test_FuncArgInt8>();
// Function call tests.
app.addT<X86Test_FuncCallBase1>();
app.addT<X86Test_FuncCallBase2>();
app.addT<X86Test_FuncCallStd>();
app.addT<X86Test_FuncCallFast>();
#if ASMJIT_ARCH_X86
app.addT<X86Test_FuncCallSIMD>();
#endif
app.addT<X86Test_FuncCallLight>();
app.addT<X86Test_FuncCallManyArgs>();
app.addT<X86Test_FuncCallDuplicateArgs>();
app.addT<X86Test_FuncCallImmArgs>();
app.addT<X86Test_FuncCallPtrArgs>();
app.addT<X86Test_FuncCallRefArgs>();
app.addT<X86Test_FuncCallFloatAsXmmRet>();
app.addT<X86Test_FuncCallDoubleAsXmmRet>();
app.addT<X86Test_FuncCallConditional>();
app.addT<X86Test_FuncCallMultiple>();
app.addT<X86Test_FuncCallRecursive>();
app.addT<X86Test_FuncCallVarArg1>();
app.addT<X86Test_FuncCallVarArg2>();
app.addT<X86Test_FuncCallInt64Arg>();
app.addT<X86Test_FuncCallMisc1>();
app.addT<X86Test_FuncCallMisc2>();
app.addT<X86Test_FuncCallMisc3>();
app.addT<X86Test_FuncCallMisc4>();
app.addT<X86Test_FuncCallMisc5>();
app.addT<X86Test_FuncCallMisc6>();
app.addT<X86Test_FuncCallAVXClobber>();
// Miscellaneous tests.
app.addT<X86Test_VecToScalar>();
app.addT<X86Test_MiscLocalConstPool>();
app.addT<X86Test_MiscGlobalConstPool>();
app.addT<X86Test_MiscMultiRet>();
app.addT<X86Test_MiscMultiFunc>();
app.addT<X86Test_MiscUnfollow>();
}
#endif // !ASMJIT_NO_X86 && !ASMJIT_NO_COMPILER
C/C++
1
https://gitee.com/mirrors/AsmJit.git
git@gitee.com:mirrors/AsmJit.git
mirrors
AsmJit
AsmJit
master

搜索帮助

53164aa7 5694891 3bd8fe86 5694891