diff options
author | 2020-06-12 11:55:10 +0700 | |
---|---|---|
committer | 2020-06-12 11:55:10 +0700 | |
commit | 19214dd8e6528e056166a37b441568a9a264b086 (patch) | |
tree | 7403411d6d536153d1df6d8923f7594ace8b9a4f /3rdparty/asmjit/test | |
parent | 7b6dbd7a1442d6a77f3b410966fdc41769e417b5 (diff) |
asmjist: sync with upstream (nw)
Diffstat (limited to '3rdparty/asmjit/test')
-rw-r--r-- | 3rdparty/asmjit/test/asmjit_bench_x86.cpp | 36 | ||||
-rw-r--r-- | 3rdparty/asmjit/test/asmjit_test_misc.h | 6 | ||||
-rw-r--r-- | 3rdparty/asmjit/test/asmjit_test_opcode.cpp | 40 | ||||
-rw-r--r-- | 3rdparty/asmjit/test/asmjit_test_opcode.h | 1 | ||||
-rw-r--r-- | 3rdparty/asmjit/test/asmjit_test_unit.cpp | 166 | ||||
-rw-r--r-- | 3rdparty/asmjit/test/asmjit_test_x86_asm.cpp | 13 | ||||
-rw-r--r-- | 3rdparty/asmjit/test/asmjit_test_x86_cc.cpp | 590 | ||||
-rw-r--r-- | 3rdparty/asmjit/test/asmjit_test_x86_instinfo.cpp | 128 | ||||
-rw-r--r-- | 3rdparty/asmjit/test/asmjit_test_x86_sections.cpp | 17 |
9 files changed, 589 insertions, 408 deletions
diff --git a/3rdparty/asmjit/test/asmjit_bench_x86.cpp b/3rdparty/asmjit/test/asmjit_bench_x86.cpp index 95f792d0c03..40d90088c01 100644 --- a/3rdparty/asmjit/test/asmjit_bench_x86.cpp +++ b/3rdparty/asmjit/test/asmjit_bench_x86.cpp @@ -37,7 +37,7 @@ using namespace asmjit; // [Configuration] // ============================================================================ -static constexpr uint32_t kNumRepeats = 25; +static constexpr uint32_t kNumRepeats = 20; static constexpr uint32_t kNumIterations = 1000; // ============================================================================ @@ -80,12 +80,12 @@ namespace BenchUtils { } template<typename EmitterT, typename FuncT> - static void bench(CodeHolder& code, uint32_t archId, const char* testName, const FuncT& func) noexcept { + static void bench(CodeHolder& code, uint32_t arch, const char* testName, const FuncT& func) noexcept { EmitterT emitter; const char* archName = - archId == ArchInfo::kIdX86 ? "X86" : - archId == ArchInfo::kIdX64 ? "X64" : "???"; + arch == Environment::kArchX86 ? "X86" : + arch == Environment::kArchX64 ? "X64" : "???"; const char* emitterName = emitter.isAssembler() ? "Assembler" : @@ -95,14 +95,13 @@ namespace BenchUtils { Performance perf; uint64_t codeSize = 0; - CodeInfo codeInfo(archId); - codeInfo.setCdeclCallConv(archId == ArchInfo::kIdX86 ? CallConv::kIdX86CDecl : CallConv::kIdX86SysV64); + Environment env(arch); for (uint32_t r = 0; r < kNumRepeats; r++) { perf.start(); codeSize = 0; for (uint32_t i = 0; i < kNumIterations; i++) { - code.init(codeInfo); + code.init(env); code.attach(&emitter); func(emitter); @@ -113,7 +112,7 @@ namespace BenchUtils { perf.end(); } - printf("[%s] %-9s %-8s | Time:%6u [ms] | ", archName, emitterName, testName, perf.best); + printf("[%s] %-9s %-10s | Time:%6u [ms] | ", archName, emitterName, testName, perf.best); if (codeSize) printf("Speed: %7.3f [MB/s]", mbps(perf.best, codeSize)); else @@ -127,30 +126,35 @@ namespace BenchUtils { // ============================================================================ #ifdef ASMJIT_BUILD_X86 -static void benchX86(uint32_t archId) noexcept { +static void benchX86(uint32_t arch) noexcept { CodeHolder code; - BenchUtils::bench<x86::Assembler>(code, archId, "[raw]", [](x86::Assembler& a) { + BenchUtils::bench<x86::Assembler>(code, arch, "[fast]", [](x86::Assembler& a) { + asmtest::generateOpcodes(a.as<x86::Emitter>()); + }); + + BenchUtils::bench<x86::Assembler>(code, arch, "[validate]", [](x86::Assembler& a) { + a.addValidationOptions(BaseEmitter::kValidationOptionAssembler); asmtest::generateOpcodes(a.as<x86::Emitter>()); }); #ifndef ASMJIT_NO_BUILDER - BenchUtils::bench<x86::Builder>(code, archId, "[raw]", [](x86::Builder& cb) { + BenchUtils::bench<x86::Builder>(code, arch, "[no-asm]", [](x86::Builder& cb) { asmtest::generateOpcodes(cb.as<x86::Emitter>()); }); - BenchUtils::bench<x86::Builder>(code, archId, "[final]", [](x86::Builder& cb) { + BenchUtils::bench<x86::Builder>(code, arch, "[asm]", [](x86::Builder& cb) { asmtest::generateOpcodes(cb.as<x86::Emitter>()); cb.finalize(); }); #endif #ifndef ASMJIT_NO_COMPILER - BenchUtils::bench<x86::Compiler>(code, archId, "[raw]", [](x86::Compiler& cc) { + BenchUtils::bench<x86::Compiler>(code, arch, "[no-asm]", [](x86::Compiler& cc) { asmtest::generateAlphaBlend(cc); }); - BenchUtils::bench<x86::Compiler>(code, archId, "[final]", [](x86::Compiler& cc) { + BenchUtils::bench<x86::Compiler>(code, arch, "[asm]", [](x86::Compiler& cc) { asmtest::generateAlphaBlend(cc); cc.finalize(); }); @@ -160,8 +164,8 @@ static void benchX86(uint32_t archId) noexcept { int main() { #ifdef ASMJIT_BUILD_X86 - benchX86(ArchInfo::kIdX86); - benchX86(ArchInfo::kIdX64); + benchX86(Environment::kArchX86); + benchX86(Environment::kArchX64); #endif return 0; diff --git a/3rdparty/asmjit/test/asmjit_test_misc.h b/3rdparty/asmjit/test/asmjit_test_misc.h index be1757ab1c9..03273272d1b 100644 --- a/3rdparty/asmjit/test/asmjit_test_misc.h +++ b/3rdparty/asmjit/test/asmjit_test_misc.h @@ -52,7 +52,7 @@ static void generateAlphaBlend(asmjit::x86::Compiler& cc) { Label L_LargeEnd = cc.newLabel(); Label L_DataPool = cc.newLabel(); - cc.addFunc(FuncSignatureT<void, void*, const void*, size_t>(cc.codeInfo().cdeclCallConv())); + cc.addFunc(FuncSignatureT<void, void*, const void*, size_t>(CallConv::kIdHost)); cc.setArg(0, dst); cc.setArg(1, src); @@ -177,8 +177,8 @@ static void generateAlphaBlend(asmjit::x86::Compiler& cc) { // Data. cc.align(kAlignData, 16); cc.bind(L_DataPool); - cc.dxmm(Data128::fromI16(0x0080)); - cc.dxmm(Data128::fromI16(0x0101)); + cc.embedUInt16(uint16_t(0x0080u), 8); + cc.embedUInt16(uint16_t(0x0101u), 8); } } // {asmtest} diff --git a/3rdparty/asmjit/test/asmjit_test_opcode.cpp b/3rdparty/asmjit/test/asmjit_test_opcode.cpp index 908435beb00..d61a6e4bc29 100644 --- a/3rdparty/asmjit/test/asmjit_test_opcode.cpp +++ b/3rdparty/asmjit/test/asmjit_test_opcode.cpp @@ -21,9 +21,11 @@ // misrepresented as being the original software. // 3. This notice may not be removed or altered from any source distribution. +// ---------------------------------------------------------------------------- // This file is used to test opcodes generated by AsmJit. Output can be // disassembled in your IDE or by your favorite disassembler. Instructions // are grouped by category and then sorted alphabetically. +// ---------------------------------------------------------------------------- #include <asmjit/x86.h> #include <stdio.h> @@ -34,21 +36,21 @@ using namespace asmjit; struct OpcodeDumpInfo { - uint32_t archId; + uint32_t arch; bool useRex1; bool useRex2; }; -static const char* archIdToString(uint32_t archId) { - switch (archId) { - case ArchInfo::kIdNone: return "None"; - case ArchInfo::kIdX86 : return "X86"; - case ArchInfo::kIdX64 : return "X64"; - case ArchInfo::kIdA32 : return "A32"; - case ArchInfo::kIdA64 : return "A64"; - - default: - return "<unknown>"; +static const char* archToString(uint32_t arch) noexcept { + switch (arch & ~Environment::kArchBigEndianMask) { + case Environment::kArchX86 : return "X86"; + case Environment::kArchX64 : return "X64"; + case Environment::kArchARM : return "ARM"; + case Environment::kArchThumb : return "Thumb"; + case Environment::kArchAArch64 : return "AArch64"; + case Environment::kArchMIPS_LE : return "MIPS"; + case Environment::kArchMIPS64_LE: return "MIPS64"; + default: return "Unknown"; } } @@ -65,23 +67,23 @@ int main() { TestErrorHandler eh; OpcodeDumpInfo infoList[] = { - { ArchInfo::kIdX86, false, false }, - { ArchInfo::kIdX64, false, false }, - { ArchInfo::kIdX64, false, true }, - { ArchInfo::kIdX64, true , false }, - { ArchInfo::kIdX64, true , true } + { Environment::kArchX86, false, false }, + { Environment::kArchX64, false, false }, + { Environment::kArchX64, false, true }, + { Environment::kArchX64, true , false }, + { Environment::kArchX64, true , true } }; for (uint32_t i = 0; i < ASMJIT_ARRAY_SIZE(infoList); i++) { const OpcodeDumpInfo& info = infoList[i]; printf("Opcodes [ARCH=%s REX1=%s REX2=%s]\n", - archIdToString(info.archId), + archToString(info.arch), info.useRex1 ? "true" : "false", info.useRex2 ? "true" : "false"); CodeHolder code; - code.init(CodeInfo(info.archId)); + code.init(Environment(info.arch)); code.setErrorHandler(&eh); #ifndef ASMJIT_NO_LOGGING @@ -95,7 +97,7 @@ int main() { // If this is the host architecture the code generated can be executed // for debugging purposes (the first instruction is ret anyway). - if (code.archId() == ArchInfo::kIdHost) { + if (code.arch() == Environment::kArchHost) { JitRuntime runtime; VoidFunc p; diff --git a/3rdparty/asmjit/test/asmjit_test_opcode.h b/3rdparty/asmjit/test/asmjit_test_opcode.h index e89db426ffd..6f052f526b8 100644 --- a/3rdparty/asmjit/test/asmjit_test_opcode.h +++ b/3rdparty/asmjit/test/asmjit_test_opcode.h @@ -91,7 +91,6 @@ static void generateOpcodes(asmjit::x86::Emitter* e, bool useRex1 = false, bool Zmm zmmA = useRex1 ? zmm8 : zmm0; Zmm zmmB = useRex2 ? zmm9 : zmm1; Zmm zmmC = useRex2 ? zmm10 : zmm2; - Zmm zmmD = useRex2 ? zmm11 : zmm3; Mem vx_ptr = ptr(gzB, xmmB); Mem vy_ptr = ptr(gzB, ymmB); diff --git a/3rdparty/asmjit/test/asmjit_test_unit.cpp b/3rdparty/asmjit/test/asmjit_test_unit.cpp index f88018a7ac1..3aac7401e17 100644 --- a/3rdparty/asmjit/test/asmjit_test_unit.cpp +++ b/3rdparty/asmjit/test/asmjit_test_unit.cpp @@ -35,25 +35,26 @@ struct DumpCpuFeature { const char* name; }; -static const char* hostArch() noexcept { - switch (ArchInfo::kIdHost) { - case ArchInfo::kIdX86: return "X86"; - case ArchInfo::kIdX64: return "X64"; - case ArchInfo::kIdA32: return "ARM32"; - case ArchInfo::kIdA64: return "ARM64"; +static const char* archToString(uint32_t arch) noexcept { + switch (arch & ~Environment::kArchBigEndianMask) { + case Environment::kArchX86 : return "X86"; + case Environment::kArchX64 : return "X64"; + case Environment::kArchARM : return "ARM"; + case Environment::kArchThumb : return "Thumb"; + case Environment::kArchAArch64 : return "AArch64"; + case Environment::kArchMIPS_LE : return "MIPS"; + case Environment::kArchMIPS64_LE: return "MIPS64"; default: return "Unknown"; } } -static void dumpFeatures(const CpuInfo& cpu, const DumpCpuFeature* data, size_t count) noexcept { - for (size_t i = 0; i < count; i++) - if (cpu.hasFeature(data[i].feature)) - INFO(" %s", data[i].name); -} - static void dumpCpu(void) noexcept { const CpuInfo& cpu = CpuInfo::host(); + // -------------------------------------------------------------------------- + // [CPU Information] + // -------------------------------------------------------------------------- + INFO("Host CPU:"); INFO(" Vendor : %s", cpu.vendor()); INFO(" Brand : %s", cpu.brand()); @@ -68,137 +69,20 @@ static void dumpCpu(void) noexcept { INFO(""); // -------------------------------------------------------------------------- - // [X86] + // [CPU Features] // -------------------------------------------------------------------------- -#if ASMJIT_ARCH_X86 - static const DumpCpuFeature x86FeaturesList[] = { - { x86::Features::kNX , "NX" }, - { x86::Features::kMT , "MT" }, - { x86::Features::k3DNOW , "3DNOW" }, - { x86::Features::k3DNOW2 , "3DNOW2" }, - { x86::Features::kADX , "ADX" }, - { x86::Features::kAESNI , "AESNI" }, - { x86::Features::kALTMOVCR8 , "ALTMOVCR8" }, - { x86::Features::kAVX , "AVX" }, - { x86::Features::kAVX2 , "AVX2" }, - { x86::Features::kAVX512_4FMAPS , "AVX512_4FMAPS" }, - { x86::Features::kAVX512_4VNNIW , "AVX512_4VNNIW" }, - { x86::Features::kAVX512_BITALG , "AVX512_BITALG" }, - { x86::Features::kAVX512_BW , "AVX512_BW" }, - { x86::Features::kAVX512_CDI , "AVX512_CDI" }, - { x86::Features::kAVX512_DQ , "AVX512_DQ" }, - { x86::Features::kAVX512_ERI , "AVX512_ERI" }, - { x86::Features::kAVX512_F , "AVX512_F" }, - { x86::Features::kAVX512_IFMA , "AVX512_IFMA" }, - { x86::Features::kAVX512_PFI , "AVX512_PFI" }, - { x86::Features::kAVX512_VBMI , "AVX512_VBMI" }, - { x86::Features::kAVX512_VBMI2 , "AVX512_VBMI2" }, - { x86::Features::kAVX512_VL , "AVX512_VL" }, - { x86::Features::kAVX512_VNNI , "AVX512_VNNI" }, - { x86::Features::kAVX512_VPOPCNTDQ, "AVX512_VPOPCNTDQ" }, - { x86::Features::kBMI , "BMI" }, - { x86::Features::kBMI2 , "BMI2" }, - { x86::Features::kCLFLUSH , "CLFLUSH" }, - { x86::Features::kCLFLUSHOPT , "CLFLUSHOPT" }, - { x86::Features::kCLWB , "CLWB" }, - { x86::Features::kCLZERO , "CLZERO" }, - { x86::Features::kCMOV , "CMOV" }, - { x86::Features::kCMPXCHG16B , "CMPXCHG16B" }, - { x86::Features::kCMPXCHG8B , "CMPXCHG8B" }, - { x86::Features::kERMS , "ERMS" }, - { x86::Features::kF16C , "F16C" }, - { x86::Features::kFMA , "FMA" }, - { x86::Features::kFMA4 , "FMA4" }, - { x86::Features::kFPU , "FPU" }, - { x86::Features::kFSGSBASE , "FSGSBASE" }, - { x86::Features::kFXSR , "FXSR" }, - { x86::Features::kFXSROPT , "FXSROPT" }, - { x86::Features::kGEODE , "GEODE" }, - { x86::Features::kGFNI , "GFNI" }, - { x86::Features::kHLE , "HLE" }, - { x86::Features::kI486 , "I486" }, - { x86::Features::kLAHFSAHF , "LAHFSAHF" }, - { x86::Features::kLWP , "LWP" }, - { x86::Features::kLZCNT , "LZCNT" }, - { x86::Features::kMMX , "MMX" }, - { x86::Features::kMMX2 , "MMX2" }, - { x86::Features::kMONITOR , "MONITOR" }, - { x86::Features::kMONITORX , "MONITORX" }, - { x86::Features::kMOVBE , "MOVBE" }, - { x86::Features::kMPX , "MPX" }, - { x86::Features::kMSR , "MSR" }, - { x86::Features::kMSSE , "MSSE" }, - { x86::Features::kOSXSAVE , "OSXSAVE" }, - { x86::Features::kPCLMULQDQ , "PCLMULQDQ" }, - { x86::Features::kPCOMMIT , "PCOMMIT" }, - { x86::Features::kPOPCNT , "POPCNT" }, - { x86::Features::kPREFETCHW , "PREFETCHW" }, - { x86::Features::kPREFETCHWT1 , "PREFETCHWT1" }, - { x86::Features::kRDRAND , "RDRAND" }, - { x86::Features::kRDSEED , "RDSEED" }, - { x86::Features::kRDTSC , "RDTSC" }, - { x86::Features::kRDTSCP , "RDTSCP" }, - { x86::Features::kRTM , "RTM" }, - { x86::Features::kSHA , "SHA" }, - { x86::Features::kSKINIT , "SKINIT" }, - { x86::Features::kSMAP , "SMAP" }, - { x86::Features::kSMEP , "SMEP" }, - { x86::Features::kSMX , "SMX" }, - { x86::Features::kSSE , "SSE" }, - { x86::Features::kSSE2 , "SSE2" }, - { x86::Features::kSSE3 , "SSE3" }, - { x86::Features::kSSE4_1 , "SSE4.1" }, - { x86::Features::kSSE4_2 , "SSE4.2" }, - { x86::Features::kSSE4A , "SSE4A" }, - { x86::Features::kSSSE3 , "SSSE3" }, - { x86::Features::kSVM , "SVM" }, - { x86::Features::kTBM , "TBM" }, - { x86::Features::kTSX , "TSX" }, - { x86::Features::kVAES , "VAES" }, - { x86::Features::kVMX , "VMX" }, - { x86::Features::kVPCLMULQDQ , "VPCLMULQDQ" }, - { x86::Features::kXOP , "XOP" }, - { x86::Features::kXSAVE , "XSAVE" }, - { x86::Features::kXSAVEC , "XSAVEC" }, - { x86::Features::kXSAVEOPT , "XSAVEOPT" }, - { x86::Features::kXSAVES , "XSAVES" } +#ifndef ASMJIT_NO_LOGGING + INFO("CPU Features:"); + BaseFeatures::Iterator it(cpu.features().iterator()); + while (it.hasNext()) { + uint32_t featureId = uint32_t(it.next()); + StringTmp<64> featureString; + Formatter::formatFeature(featureString, cpu.arch(), featureId); + INFO(" %s\n", featureString.data()); }; - - INFO("X86 Features:"); - dumpFeatures(cpu, x86FeaturesList, ASMJIT_ARRAY_SIZE(x86FeaturesList)); INFO(""); -#endif - - // -------------------------------------------------------------------------- - // [ARM] - // -------------------------------------------------------------------------- - -#if ASMJIT_ARCH_ARM - static const DumpCpuFeature armFeaturesList[] = { - { arm::Features::kARMv6 , "ARMv6" }, - { arm::Features::kARMv7 , "ARMv7" }, - { arm::Features::kARMv8 , "ARMv8" }, - { arm::Features::kTHUMB , "THUMB" }, - { arm::Features::kTHUMBv2 , "THUMBv2" }, - { arm::Features::kVFP2 , "VFPv2" }, - { arm::Features::kVFP3 , "VFPv3" }, - { arm::Features::kVFP4 , "VFPv4" }, - { arm::Features::kVFP_D32 , "VFP D32" }, - { arm::Features::kNEON , "NEON" }, - { arm::Features::kDSP , "DSP" }, - { arm::Features::kIDIV , "IDIV" }, - { arm::Features::kAES , "AES" }, - { arm::Features::kCRC32 , "CRC32" }, - { arm::Features::kSHA1 , "SHA1" }, - { arm::Features::kSHA256 , "SHA256" }, - { arm::Features::kATOMIC64 , "ATOMIC64" } - }; - - INFO("ARM Features:"); - dumpFeatures(cpu, armFeaturesList, ASMJIT_ARRAY_SIZE(armFeaturesList)); - INFO(""); -#endif +#endif // !ASMJIT_NO_LOGGING } // ============================================================================ @@ -281,7 +165,7 @@ static void dumpSizeOf(void) noexcept { DUMP_TYPE(BaseCompiler); DUMP_TYPE(FuncNode); DUMP_TYPE(FuncRetNode); - DUMP_TYPE(FuncCallNode); + DUMP_TYPE(InvokeNode); INFO(""); #endif @@ -324,7 +208,7 @@ int main(int argc, const char* argv[]) { unsigned((ASMJIT_LIBRARY_VERSION >> 16) ), unsigned((ASMJIT_LIBRARY_VERSION >> 8) & 0xFF), unsigned((ASMJIT_LIBRARY_VERSION ) & 0xFF), - hostArch(), + archToString(Environment::kArchHost), buildType ); diff --git a/3rdparty/asmjit/test/asmjit_test_x86_asm.cpp b/3rdparty/asmjit/test/asmjit_test_x86_asm.cpp index a01185d80f9..ba85100dae0 100644 --- a/3rdparty/asmjit/test/asmjit_test_x86_asm.cpp +++ b/3rdparty/asmjit/test/asmjit_test_x86_asm.cpp @@ -48,7 +48,7 @@ static void makeRawFunc(x86::Emitter* emitter) noexcept { // Create and initialize `FuncDetail` and `FuncFrame`. FuncDetail func; - func.init(FuncSignatureT<void, int*, const int*, const int*>(CallConv::kIdHost)); + func.init(FuncSignatureT<void, int*, const int*, const int*>(CallConv::kIdHost), emitter->environment()); FuncFrame frame; frame.init(func); @@ -101,10 +101,11 @@ static void makeCompiledFunc(x86::Compiler* cc) noexcept { static uint32_t testFunc(JitRuntime& rt, uint32_t emitterType) noexcept { #ifndef ASMJIT_NO_LOGGING FileLogger logger(stdout); + logger.setIndentation(FormatOptions::kIndentationCode, 2); #endif CodeHolder code; - code.init(rt.codeInfo()); + code.init(rt.environment()); #ifndef ASMJIT_NO_LOGGING code.setLogger(&logger); @@ -173,8 +174,10 @@ static uint32_t testFunc(JitRuntime& rt, uint32_t emitterType) noexcept { } int main() { - unsigned nFailed = 0; + printf("AsmJit X86 Emitter Test\n\n"); + JitRuntime rt; + unsigned nFailed = 0; nFailed += testFunc(rt, BaseEmitter::kTypeAssembler); @@ -187,9 +190,9 @@ int main() { #endif if (!nFailed) - printf("[PASSED] All tests passed\n"); + printf("Success:\n All tests passed\n"); else - printf("[FAILED] %u %s failed\n", nFailed, nFailed == 1 ? "test" : "tests"); + printf("Failure:\n %u %s failed\n", nFailed, nFailed == 1 ? "test" : "tests"); return nFailed ? 1 : 0; } diff --git a/3rdparty/asmjit/test/asmjit_test_x86_cc.cpp b/3rdparty/asmjit/test/asmjit_test_x86_cc.cpp index a0e50e97097..9e80d871978 100644 --- a/3rdparty/asmjit/test/asmjit_test_x86_cc.cpp +++ b/3rdparty/asmjit/test/asmjit_test_x86_cc.cpp @@ -27,6 +27,12 @@ #include <stdlib.h> #include <string.h> +#include <memory> +#include <vector> + +// Required for function tests that pass / return XMM registers. +#include <emmintrin.h> + #include "./asmjit_test_misc.h" #ifdef _MSC_VER @@ -67,7 +73,7 @@ public: virtual void handleError(Error err, const char* message, BaseEmitter* origin) { DebugUtils::unused(origin); _err = err; - _message.assignString(message); + _message.assign(message); } Error _err; @@ -81,7 +87,7 @@ public: //! Base test interface for testing `x86::Compiler`. class X86Test { public: - X86Test(const char* name = nullptr) { _name.assignString(name); } + X86Test(const char* name = nullptr) { _name.assign(name); } virtual ~X86Test() {} inline const char* name() const { return _name.data(); } @@ -98,9 +104,7 @@ public: class X86TestApp { public: - Zone _zone; - ZoneAllocator _allocator; - ZoneVector<X86Test*> _tests; + std::vector<std::unique_ptr<X86Test>> _tests; unsigned _nFailed; size_t _outputSize; @@ -109,20 +113,15 @@ public: bool _dumpAsm; X86TestApp() noexcept - : _zone(8096 - Zone::kBlockOverhead), - _allocator(&_zone), - _nFailed(0), + : _nFailed(0), _outputSize(0), _verbose(false), _dumpAsm(false) {} - ~X86TestApp() noexcept { - for (X86Test* test : _tests) - delete test; - } + ~X86TestApp() noexcept {} - Error add(X86Test* test) noexcept{ - return _tests.append(&_allocator, test); + void add(X86Test* test) noexcept { + _tests.push_back(std::unique_ptr<X86Test>(test)); } template<class T> @@ -169,12 +168,12 @@ int X86TestApp::run() { stringLogger.addFlags(kFormatFlags); #endif - for (X86Test* test : _tests) { + for (std::unique_ptr<X86Test>& test : _tests) { JitRuntime runtime; CodeHolder code; SimpleErrorHandler errorHandler; - code.init(runtime.codeInfo()); + code.init(runtime.environment()); code.setErrorHandler(&errorHandler); #ifndef ASMJIT_NO_LOGGING @@ -207,7 +206,7 @@ int X86TestApp::run() { if (!_verbose) printf("\n"); String sb; - cc.dump(sb, kFormatFlags); + Formatter::formatNodeList(sb, kFormatFlags, &cc); printf("%s", sb.data()); } #endif @@ -261,11 +260,12 @@ int X86TestApp::run() { } if (_nFailed == 0) - printf("\n[PASSED] All %u tests passed\n", unsigned(_tests.size())); + printf("\nSuccess:\n All %u tests passed\n", unsigned(_tests.size())); else - printf("\n[FAILED] %u %s of %u failed\n", _nFailed, _nFailed == 1 ? "test" : "tests", unsigned(_tests.size())); + printf("\nFailure:\n %u %s of %u failed\n", _nFailed, _nFailed == 1 ? "test" : "tests", unsigned(_tests.size())); printf(" OutputSize=%zu\n", _outputSize); + printf("\n"); return _nFailed == 0 ? 0 : 1; } @@ -703,8 +703,8 @@ public: func(); - result.appendString("ret={}"); - expect.appendString("ret={}"); + result.append("ret={}"); + expect.append("ret={}"); return true; } @@ -750,8 +750,8 @@ public: func(); - result.appendString("ret={}"); - expect.appendString("ret={}"); + result.append("ret={}"); + expect.append("ret={}"); return true; } @@ -1051,8 +1051,8 @@ public: for (i = 0; i < ASMJIT_ARRAY_SIZE(resultBuf); i++) { if (i != 0) { - result.appendChar(','); - expect.appendChar(','); + result.append(','); + expect.append(','); } result.appendFormat("%u", resultBuf[i]); @@ -1971,6 +1971,59 @@ public: }; // ============================================================================ +// [X86Test_AllocArgsVec] +// ============================================================================ + +class X86Test_AllocArgsVec : public X86Test { +public: + X86Test_AllocArgsVec() : X86Test("AllocArgsVec") {} + + static void add(X86TestApp& app) { + // Not supported on Windows. +#ifndef _WIN32 + app.add(new X86Test_AllocArgsVec()); +#endif + } + + virtual void compile(x86::Compiler& cc) { + cc.addFunc(FuncSignatureT<x86::Xmm, x86::Xmm, x86::Xmm>(CallConv::kIdHost)); + + x86::Xmm a = cc.newXmm("aXmm"); + x86::Xmm b = cc.newXmm("bXmm"); + + cc.setArg(0, a); + cc.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; + } +}; + +// ============================================================================ // [X86Test_AllocRetFloat1] // ============================================================================ @@ -2253,21 +2306,21 @@ public: func(dstBuffer, srcBuffer, kCount); - result.assignString("buf={"); - expect.assignString("buf={"); + result.assign("buf={"); + expect.assign("buf={"); for (i = 0; i < kCount; i++) { if (i != 0) { - result.appendString(", "); - expect.appendString(", "); + result.append(", "); + expect.append(", "); } result.appendFormat("%u", unsigned(dstBuffer[i])); expect.appendFormat("%u", unsigned(srcBuffer[i])); } - result.appendString("}"); - expect.appendString("}"); + result.append("}"); + expect.append("}"); return result == expect; } @@ -2395,21 +2448,21 @@ public: func(dstBuffer, srcBuffer, kCount); - result.assignString("buf={"); - expect.assignString("buf={"); + result.assign("buf={"); + expect.assign("buf={"); for (i = 0; i < kCount; i++) { if (i != 0) { - result.appendString(", "); - expect.appendString(", "); + result.append(", "); + expect.append(", "); } result.appendFormat("%08X", unsigned(dstBuffer[i])); expect.appendFormat("%08X", unsigned(expBuffer[i])); } - result.appendString("}"); - expect.appendString("}"); + result.append("}"); + expect.append("}"); return result == expect; } @@ -2443,11 +2496,12 @@ public: cc.shl(v2, 1); // Call a function. - FuncCallNode* call = cc.call(imm((void*)calledFunc), FuncSignatureT<int, int, int, int>(CallConv::kIdHost)); - call->setArg(0, v2); - call->setArg(1, v1); - call->setArg(2, v0); - call->setRet(0, v0); + InvokeNode* invokeNode; + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int, int, int>(CallConv::kIdHost)); + invokeNode->setArg(0, v2); + invokeNode->setArg(1, v1); + invokeNode->setArg(2, v0); + invokeNode->setRet(0, v0); cc.ret(v0); cc.endFunc(); @@ -2498,29 +2552,29 @@ public: Label L_Exit = cc.newLabel(); static const char token[kTokenSize] = "-+:|abcdefghijklmnopqrstuvwxyz|"; - FuncCallNode* call; + InvokeNode* invokeNode; cc.lea(p1, s1); cc.lea(p2, s2); // Try to corrupt the stack if wrongly allocated. - call = cc.call(imm((void*)memcpy), FuncSignatureT<void*, void*, void*, size_t>(CallConv::kIdHostCDecl)); - call->setArg(0, p1); - call->setArg(1, imm(token)); - call->setArg(2, imm(kTokenSize)); - call->setRet(0, p1); - - call = cc.call(imm((void*)memcpy), FuncSignatureT<void*, void*, void*, size_t>(CallConv::kIdHostCDecl)); - call->setArg(0, p2); - call->setArg(1, imm(token)); - call->setArg(2, imm(kTokenSize)); - call->setRet(0, p2); - - call = cc.call(imm((void*)memcmp), FuncSignatureT<int, void*, void*, size_t>(CallConv::kIdHostCDecl)); - call->setArg(0, p1); - call->setArg(1, p2); - call->setArg(2, imm(kTokenSize)); - call->setRet(0, ret); + cc.invoke(&invokeNode, imm((void*)memcpy), FuncSignatureT<void*, void*, void*, size_t>(CallConv::kIdCDecl)); + invokeNode->setArg(0, p1); + invokeNode->setArg(1, imm(token)); + invokeNode->setArg(2, imm(kTokenSize)); + invokeNode->setRet(0, p1); + + cc.invoke(&invokeNode, imm((void*)memcpy), FuncSignatureT<void*, void*, void*, size_t>(CallConv::kIdCDecl)); + invokeNode->setArg(0, p2); + invokeNode->setArg(1, imm(token)); + invokeNode->setArg(2, imm(kTokenSize)); + invokeNode->setRet(0, p2); + + cc.invoke(&invokeNode, imm((void*)memcmp), FuncSignatureT<int, void*, void*, size_t>(CallConv::kIdCDecl)); + 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. @@ -2573,13 +2627,14 @@ public: cc.setArg(1, y); cc.setArg(2, z); - FuncCallNode* call = cc.call( + InvokeNode* invokeNode; + cc.invoke(&invokeNode, imm((void*)calledFunc), - FuncSignatureT<int, int, int, int>(CallConv::kIdHostStdCall)); - call->setArg(0, x); - call->setArg(1, y); - call->setArg(2, z); - call->setRet(0, x); + FuncSignatureT<int, int, int, int>(CallConv::kIdStdCall)); + invokeNode->setArg(0, x); + invokeNode->setArg(1, y); + invokeNode->setArg(2, z); + invokeNode->setRet(0, x); cc.ret(x); cc.endFunc(); @@ -2622,18 +2677,15 @@ public: cc.addFunc(FuncSignatureT<int, int>(CallConv::kIdHost)); cc.setArg(0, var); - FuncCallNode* call; - call = cc.call( - imm((void*)calledFunc), - FuncSignatureT<int, int>(CallConv::kIdHostFastCall)); - call->setArg(0, var); - call->setRet(0, var); + InvokeNode* invokeNode; - call = cc.call( - imm((void*)calledFunc), - FuncSignatureT<int, int>(CallConv::kIdHostFastCall)); - call->setArg(0, var); - call->setRet(0, var); + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int>(CallConv::kIdFastCall)); + invokeNode->setArg(0, var); + invokeNode->setRet(0, var); + + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int>(CallConv::kIdFastCall)); + invokeNode->setArg(0, var); + invokeNode->setRet(0, var); cc.ret(var); cc.endFunc(); @@ -2659,6 +2711,97 @@ public: }; // ============================================================================ +// [X86Test_FuncCallSIMD] +// ============================================================================ + +class X86Test_FuncCallSIMD : public X86Test { +public: + bool _useVectorCall; + + X86Test_FuncCallSIMD(bool useVectorCall) + : X86Test(), + _useVectorCall(useVectorCall) { + _name.assignFormat("FuncCallSIMD {%s}", _useVectorCall ? "__vectorcall" : "__cdecl"); + } + + static void add(X86TestApp& app) { + app.add(new X86Test_FuncCallSIMD(false)); +#ifdef _MSC_VER + app.add(new X86Test_FuncCallSIMD(true)); +#endif + } + + virtual void compile(x86::Compiler& cc) { + cc.addFunc(FuncSignatureT<void, void*, const void*, const void*>(CallConv::kIdHost)); + + 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"); + + cc.setArg(0, resultPtr); + cc.setArg(1, aPtr); + cc.setArg(2, bPtr); + + uint32_t ccId = CallConv::kIdCDecl; + Imm pFnImm = imm((void*)calledFunc_cdecl); + +#ifdef _MSC_VER + if (_useVectorCall) { + ccId = CallConv::kIdVectorCall; + 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, FuncSignatureT<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 +}; + +// ============================================================================ // [X86Test_FuncCallLight] // ============================================================================ @@ -2671,8 +2814,8 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncSignatureT<void, const void*, const void*, const void*, const void*, void*> funcSig(CallConv::kIdHostCDecl); - FuncSignatureT<x86::Xmm, x86::Xmm, x86::Xmm> fastSig(CallConv::kIdHostLightCall2); + FuncSignatureT<void, const void*, const void*, const void*, const void*, void*> funcSig(CallConv::kIdCDecl); + FuncSignatureT<x86::Xmm, x86::Xmm, x86::Xmm> fastSig(CallConv::kIdLightCall2); FuncNode* func = cc.newFunc(funcSig); FuncNode* fast = cc.newFunc(fastSig); @@ -2705,15 +2848,17 @@ public: x86::Xmm xXmm = cc.newXmm("xXmm"); x86::Xmm yXmm = cc.newXmm("yXmm"); - FuncCallNode* call1 = cc.call(fast->label(), fastSig); - call1->setArg(0, aXmm); - call1->setArg(1, bXmm); - call1->setRet(0, xXmm); + InvokeNode* invokeNode; + + cc.invoke(&invokeNode, fast->label(), fastSig); + invokeNode->setArg(0, aXmm); + invokeNode->setArg(1, bXmm); + invokeNode->setRet(0, xXmm); - FuncCallNode* call2 = cc.call(fast->label(), fastSig); - call2->setArg(0, cXmm); - call2->setArg(1, dXmm); - call2->setRet(0, yXmm); + cc.invoke(&invokeNode, fast->label(), fastSig); + invokeNode->setArg(0, cXmm); + invokeNode->setArg(1, dXmm); + invokeNode->setRet(0, yXmm); cc.pmullw(xXmm, yXmm); cc.movups(x86::ptr(pOut), xXmm); @@ -2798,21 +2943,22 @@ public: cc.mov(vi, 0x18); cc.mov(vj, 0x1E); - // Call function. - FuncCallNode* call = cc.call( + // Function call. + InvokeNode* invokeNode; + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConv::kIdHost)); - call->setArg(0, va); - call->setArg(1, vb); - call->setArg(2, vc); - call->setArg(3, vd); - call->setArg(4, ve); - call->setArg(5, vf); - call->setArg(6, vg); - call->setArg(7, vh); - call->setArg(8, vi); - call->setArg(9, vj); - call->setRet(0, va); + 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(); @@ -2856,20 +3002,21 @@ public: cc.mov(a, 3); // Call function. - FuncCallNode* call = cc.call( + InvokeNode* invokeNode; + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConv::kIdHost)); - call->setArg(0, a); - call->setArg(1, a); - call->setArg(2, a); - call->setArg(3, a); - call->setArg(4, a); - call->setArg(5, a); - call->setArg(6, a); - call->setArg(7, a); - call->setArg(8, a); - call->setArg(9, a); - call->setRet(0, a); + 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(); @@ -2908,21 +3055,22 @@ public: x86::Gp rv = cc.newInt32("rv"); // Call function. - FuncCallNode* call = cc.call( + InvokeNode* invokeNode; + cc.invoke(&invokeNode, imm((void*)X86Test_FuncCallManyArgs::calledFunc), FuncSignatureT<int, int, int, int, int, int, int, int, int, int, int>(CallConv::kIdHost)); - call->setArg(0, imm(0x03)); - call->setArg(1, imm(0x12)); - call->setArg(2, imm(0xA0)); - call->setArg(3, imm(0x0B)); - call->setArg(4, imm(0x2F)); - call->setArg(5, imm(0x02)); - call->setArg(6, imm(0x0C)); - call->setArg(7, imm(0x12)); - call->setArg(8, imm(0x18)); - call->setArg(9, imm(0x1E)); - call->setRet(0, rv); + 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(); @@ -2974,21 +3122,22 @@ public: x86::Gp rv = cc.newInt32("rv"); // Call function. - FuncCallNode* call = cc.call( + InvokeNode* invokeNode; + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, void*, void*, void*, void*, void*, void*, void*, void*, void*, void*>(CallConv::kIdHost)); - call->setArg(0, imm(0x01)); - call->setArg(1, imm(0x02)); - call->setArg(2, imm(0x03)); - call->setArg(3, imm(0x04)); - call->setArg(4, imm(0x05)); - call->setArg(5, imm(0x06)); - call->setArg(6, imm(0x07)); - call->setArg(7, imm(0x08)); - call->setArg(8, imm(0x09)); - call->setArg(9, imm(0x0A)); - call->setRet(0, rv); + 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(); @@ -3044,15 +3193,16 @@ public: cc.setArg(3, arg4); // Call function. - FuncCallNode* call = cc.call( + InvokeNode* invokeNode; + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, int&, int&, int&, int&>(CallConv::kIdHost)); - call->setArg(0, arg1); - call->setArg(1, arg2); - call->setArg(2, arg3); - call->setArg(3, arg4); - call->setRet(0, rv); + 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(); @@ -3101,12 +3251,11 @@ public: cc.setArg(1, b); // Call function. - FuncCallNode* call = cc.call( - imm((void*)calledFunc), - FuncSignatureT<float, float, float>(CallConv::kIdHost)); - call->setArg(0, a); - call->setArg(1, b); - call->setRet(0, ret); + InvokeNode* invokeNode; + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<float, float, float>(CallConv::kIdHost)); + invokeNode->setArg(0, a); + invokeNode->setArg(1, b); + invokeNode->setRet(0, ret); cc.ret(ret); cc.endFunc(); @@ -3152,12 +3301,11 @@ public: cc.setArg(0, a); cc.setArg(1, b); - FuncCallNode* call = cc.call( - imm((void*)calledFunc), - FuncSignatureT<double, double, double>(CallConv::kIdHost)); - call->setArg(0, a); - call->setArg(1, b); - call->setRet(0, ret); + InvokeNode* invokeNode; + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<double, double, double>(CallConv::kIdHost)); + invokeNode->setArg(0, a); + invokeNode->setArg(1, b); + invokeNode->setRet(0, ret); cc.ret(ret); cc.endFunc(); @@ -3194,7 +3342,7 @@ public: x86::Gp y = cc.newInt32("y"); x86::Gp op = cc.newInt32("op"); - FuncCallNode* call; + InvokeNode* invokeNode; x86::Gp result; cc.addFunc(FuncSignatureT<int, int, int, int>(CallConv::kIdHost)); @@ -3217,19 +3365,19 @@ public: cc.bind(opAdd); result = cc.newInt32("result_1"); - call = cc.call((uint64_t)calledFuncAdd, FuncSignatureT<int, int, int>(CallConv::kIdHost)); - call->setArg(0, x); - call->setArg(1, y); - call->setRet(0, result); + cc.invoke(&invokeNode, (uint64_t)calledFuncAdd, FuncSignatureT<int, int, int>(CallConv::kIdHost)); + invokeNode->setArg(0, x); + invokeNode->setArg(1, y); + invokeNode->setRet(0, result); cc.ret(result); cc.bind(opMul); result = cc.newInt32("result_2"); - call = cc.call((uint64_t)calledFuncMul, FuncSignatureT<int, int, int>(CallConv::kIdHost)); - call->setArg(0, x); - call->setArg(1, y); - call->setRet(0, result); + cc.invoke(&invokeNode, (uint64_t)calledFuncMul, FuncSignatureT<int, int, int>(CallConv::kIdHost)); + invokeNode->setArg(0, x); + invokeNode->setArg(1, y); + invokeNode->setRet(0, result); cc.ret(result); cc.endFunc(); @@ -3291,25 +3439,25 @@ public: x86::Gp ret = cc.newInt32("ret"); x86::Gp ptr = cc.newIntPtr("ptr"); x86::Gp idx = cc.newInt32("idx"); - FuncCallNode* call; + InvokeNode* invokeNode; cc.mov(ptr, buf); cc.mov(idx, int(i)); - call = cc.call((uint64_t)calledFunc, FuncSignatureT<int, int*, int>(CallConv::kIdHostFastCall)); - call->setArg(0, ptr); - call->setArg(1, idx); - call->setRet(0, ret); + cc.invoke(&invokeNode, (uint64_t)calledFunc, FuncSignatureT<int, int*, int>(CallConv::kIdFastCall)); + 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)); - call = cc.call((uint64_t)calledFunc, FuncSignatureT<int, int*, int>(CallConv::kIdHostFastCall)); - call->setArg(0, ptr); - call->setArg(1, idx); - call->setRet(0, ret); + cc.invoke(&invokeNode, (uint64_t)calledFunc, FuncSignatureT<int, int*, int>(CallConv::kIdFastCall)); + invokeNode->setArg(0, ptr); + invokeNode->setArg(1, idx); + invokeNode->setRet(0, ret); cc.sub(acc1, ret); } @@ -3361,9 +3509,11 @@ public: cc.mov(tmp, val); cc.dec(tmp); - FuncCallNode* call = cc.call(func->label(), FuncSignatureT<int, int>(CallConv::kIdHost)); - call->setArg(0, tmp); - call->setRet(0, tmp); + InvokeNode* invokeNode; + + cc.invoke(&invokeNode, func->label(), FuncSignatureT<int, int>(CallConv::kIdHost)); + invokeNode->setArg(0, tmp); + invokeNode->setRet(0, tmp); cc.mul(cc.newInt32(), val, tmp); cc.bind(skip); @@ -3413,15 +3563,16 @@ public: // 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. - FuncCallNode* call = cc.call( + InvokeNode* invokeNode; + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<int, size_t, int, int, int, int>(CallConv::kIdHost, 1)); - call->setArg(0, imm(4)); - call->setArg(1, a0); - call->setArg(2, a1); - call->setArg(3, a2); - call->setArg(4, a3); - call->setRet(0, a0); + 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(); @@ -3481,15 +3632,16 @@ public: // 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. - FuncCallNode* call = cc.call( + InvokeNode* invokeNode; + cc.invoke(&invokeNode, imm((void*)calledFunc), FuncSignatureT<double, size_t, double, double, double, double>(CallConv::kIdHost, 1)); - call->setArg(0, imm(4)); - call->setArg(1, a0); - call->setArg(2, a1); - call->setArg(3, a2); - call->setArg(4, a3); - call->setRet(0, a0); + 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(); @@ -3545,11 +3697,12 @@ public: cc.setArg(0, a); cc.setArg(1, b); - FuncCallNode* call = cc.call( + InvokeNode* invokeNode; + cc.invoke(&invokeNode, imm((void*)dummy), FuncSignatureT<void, int, int>(CallConv::kIdHost)); - call->setArg(0, a); - call->setArg(1, b); + invokeNode->setArg(0, a); + invokeNode->setArg(1, b); cc.lea(r, x86::ptr(a, b)); cc.ret(r); @@ -3593,11 +3746,12 @@ public: cc.setArg(0, p); cc.movsd(arg, x86::ptr(p)); - FuncCallNode* call = cc.call( + InvokeNode* invokeNode; + cc.invoke(&invokeNode, imm((void*)op), FuncSignatureT<double, double>(CallConv::kIdHost)); - call->setArg(0, arg); - call->setRet(0, ret); + invokeNode->setArg(0, arg); + invokeNode->setRet(0, ret); cc.ret(ret); cc.endFunc(); @@ -3643,11 +3797,12 @@ public: cc.setArg(0, p); cc.movsd(arg, x86::ptr(p)); - FuncCallNode* call = cc.call( + InvokeNode* invokeNode; + cc.invoke(&invokeNode, imm((void*)op), FuncSignatureT<double, double>(CallConv::kIdHost)); - call->setArg(0, arg); - call->setRet(0, ret); + invokeNode->setArg(0, arg); + invokeNode->setRet(0, ret); cc.xorps(arg, arg); cc.subsd(arg, ret); @@ -3687,18 +3842,20 @@ public: } virtual void compile(x86::Compiler& cc) { - FuncSignatureBuilder funcPrototype; - funcPrototype.setCallConv(CallConv::kIdHost); - funcPrototype.setRet(Type::kIdF64); - cc.addFunc(funcPrototype); + InvokeNode* invokeNode; - FuncSignatureBuilder callPrototype; - callPrototype.setCallConv(CallConv::kIdHost); - callPrototype.setRet(Type::kIdF64); - FuncCallNode* call = cc.call(imm((void*)calledFunc), callPrototype); + FuncSignatureBuilder funcSignature; + funcSignature.setCallConv(CallConv::kIdHost); + funcSignature.setRet(Type::kIdF64); + cc.addFunc(funcSignature); + FuncSignatureBuilder invokeSignature; + invokeSignature.setCallConv(CallConv::kIdHost); + invokeSignature.setRet(Type::kIdF64); + + cc.invoke(&invokeNode, imm((void*)calledFunc), invokeSignature); x86::Xmm ret = cc.newXmmSd("ret"); - call->setRet(0, ret); + invokeNode->setRet(0, ret); cc.ret(ret); cc.endFunc(); @@ -3739,7 +3896,7 @@ public: x86::Gp pFn = cc.newIntPtr("pFn"); x86::Gp vars[16]; - uint32_t i, regCount = cc.gpCount(); + uint32_t i, regCount = cc.arch() == Environment::kArchX86 ? 8 : 16; ASMJIT_ASSERT(regCount <= ASMJIT_ARRAY_SIZE(vars)); cc.mov(pFn, imm((void*)calledFunc)); @@ -3752,7 +3909,9 @@ public: cc.mov(vars[i], 1); } - cc.call(pFn, FuncSignatureT<void>(CallConv::kIdHost)); + InvokeNode* invokeNode; + cc.invoke(&invokeNode, pFn, FuncSignatureT<void>(CallConv::kIdHost)); + for (i = 1; i < regCount; i++) if (vars[i].isValid()) cc.add(vars[0], vars[i]); @@ -3979,10 +4138,11 @@ public: cc.setArg(0, a); cc.setArg(1, b); - FuncCallNode* call = cc.call(f2->label(), FuncSignatureT<int, int, int>(CallConv::kIdHost)); - call->setArg(0, a); - call->setArg(1, b); - call->setRet(0, a); + InvokeNode* invokeNode; + cc.invoke(&invokeNode, f2->label(), FuncSignatureT<int, int, int>(CallConv::kIdHost)); + invokeNode->setArg(0, a); + invokeNode->setArg(1, b); + invokeNode->setRet(0, a); cc.ret(a); cc.endFunc(); @@ -4037,7 +4197,7 @@ public: // arguments will be passed by registers and there won't be any stack // misalignment when we call the `handler()`. This was failing on OSX // when targeting 32-bit. - cc.addFunc(FuncSignatureT<int, int, void*>(CallConv::kIdHostFastCall)); + cc.addFunc(FuncSignatureT<int, int, void*>(CallConv::kIdFastCall)); x86::Gp a = cc.newInt32("a"); x86::Gp b = cc.newIntPtr("b"); @@ -4123,6 +4283,7 @@ int main(int argc, char* argv[]) { app.addT<X86Test_AllocArgsIntPtr>(); app.addT<X86Test_AllocArgsFloat>(); app.addT<X86Test_AllocArgsDouble>(); + app.addT<X86Test_AllocArgsVec>(); app.addT<X86Test_AllocRetFloat1>(); app.addT<X86Test_AllocRetFloat2>(); app.addT<X86Test_AllocRetDouble1>(); @@ -4137,6 +4298,7 @@ int main(int argc, char* argv[]) { app.addT<X86Test_FuncCallBase2>(); app.addT<X86Test_FuncCallStd>(); app.addT<X86Test_FuncCallFast>(); + app.addT<X86Test_FuncCallSIMD>(); app.addT<X86Test_FuncCallLight>(); app.addT<X86Test_FuncCallManyArgs>(); app.addT<X86Test_FuncCallDuplicateArgs>(); diff --git a/3rdparty/asmjit/test/asmjit_test_x86_instinfo.cpp b/3rdparty/asmjit/test/asmjit_test_x86_instinfo.cpp new file mode 100644 index 00000000000..1d7d5003f8b --- /dev/null +++ b/3rdparty/asmjit/test/asmjit_test_x86_instinfo.cpp @@ -0,0 +1,128 @@ +// AsmJit - Machine code generation for C++ +// +// * Official AsmJit Home Page: https://asmjit.com +// * Official Github Repository: https://github.com/asmjit/asmjit +// +// Copyright (c) 2008-2020 The AsmJit Authors +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgment in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +#include <asmjit/x86.h> +#include <stdio.h> + +using namespace asmjit; + +static void printInfo(uint32_t arch, const BaseInst& inst, const Operand_* operands, size_t opCount) { + StringTmp<512> sb; + + // Read & Write Information + // ------------------------ + + InstRWInfo rw; + InstAPI::queryRWInfo(arch, inst, operands, opCount, &rw); + + sb.append("Instruction:\n"); + sb.append(" "); +#ifndef ASMJIT_NO_LOGGING + Formatter::formatInstruction(sb, 0, nullptr, arch, inst, operands, opCount); +#else + sb.append("<Logging-Not-Available>"); +#endif + sb.append("\n"); + + sb.append("Operands:\n"); + for (uint32_t i = 0; i < rw.opCount(); i++) { + const OpRWInfo& op = rw.operand(i); + const char* access = op.isReadOnly() ? "R" : + op.isWriteOnly() ? "W" : + op.isReadWrite() ? "X" : "_"; + + sb.appendFormat(" [%u] RW=%s Read=%016llX Write=%016llX Extend=%016llX", + i, access, op.readByteMask(), op.writeByteMask(), op.extendByteMask()); + sb.append("\n"); + } + + // CPU Features + // ------------ + + BaseFeatures features; + InstAPI::queryFeatures(arch, inst, operands, opCount, &features); + +#ifndef ASMJIT_NO_LOGGING + if (!features.empty()) { + sb.append("Features:\n"); + sb.append(" "); + + bool first = true; + BaseFeatures::Iterator it(features.iterator()); + while (it.hasNext()) { + uint32_t featureId = uint32_t(it.next()); + if (!first) + sb.append(" & "); + Formatter::formatFeature(sb, arch, featureId); + first = false; + } + sb.append("\n"); + } +#endif + + printf("%s\n", sb.data()); +} + +template<typename... Args> +static void printInfoSimple(uint32_t arch, uint32_t instId, Args&&... args) { + BaseInst inst(instId); + Operand_ opArray[] = { std::forward<Args>(args)... }; + printInfo(arch, inst, opArray, sizeof...(args)); +} + +int main() { + using namespace x86; + uint32_t arch = Environment::kArchX64; + + printf("AsmJit X86 Instruction Information Test\n\n"); + + printInfoSimple(arch, + x86::Inst::kIdAdd, + x86::eax, x86::ebx); + + printInfoSimple(arch, + x86::Inst::kIdPshufd, + x86::xmm0, x86::xmm1, imm(0)); + + printInfoSimple(arch, + x86::Inst::kIdPextrw, + x86::eax, x86::xmm1, imm(0)); + + printInfoSimple(arch, + x86::Inst::kIdPextrw, + x86::ptr(rax), x86::xmm1, imm(0)); + + printInfoSimple(arch, + x86::Inst::kIdVaddpd, + x86::ymm0, x86::ymm1, x86::ymm2); + + printInfoSimple(arch, + x86::Inst::kIdVaddpd, + x86::ymm0, x86::ymm30, x86::ymm31); + + printInfoSimple(arch, + x86::Inst::kIdVaddpd, + x86::zmm0, x86::zmm1, x86::zmm2); + + return 0; +} diff --git a/3rdparty/asmjit/test/asmjit_test_x86_sections.cpp b/3rdparty/asmjit/test/asmjit_test_x86_sections.cpp index a9645b31649..ddafd63b8bc 100644 --- a/3rdparty/asmjit/test/asmjit_test_x86_sections.cpp +++ b/3rdparty/asmjit/test/asmjit_test_x86_sections.cpp @@ -53,7 +53,9 @@ static void fail(const char* message, Error err) { } int main() { - CodeInfo codeInfo(ArchInfo::kIdHost); + printf("AsmJit X86 Sections Test\n\n"); + + Environment env = hostEnvironment(); JitAllocator allocator; #ifndef ASMJIT_NO_LOGGING @@ -62,7 +64,7 @@ int main() { #endif CodeHolder code; - code.init(codeInfo); + code.init(env); #ifndef ASMJIT_NO_LOGGING code.setLogger(&logger); @@ -83,7 +85,7 @@ int main() { Label data = a.newLabel(); FuncDetail func; - func.init(FuncSignatureT<size_t, size_t>(CallConv::kIdHost)); + func.init(FuncSignatureT<size_t, size_t>(CallConv::kIdHost), code.environment()); FuncFrame frame; frame.init(func); @@ -159,18 +161,15 @@ int main() { typedef size_t (*Func)(size_t idx); Func fn = (Func)roPtr; - printf("\nTesting the generated function:\n"); + printf("\n"); if (fn(0) != dataArray[0] || fn(3) != dataArray[3] || fn(6) != dataArray[6] || fn(9) != dataArray[9] ) { - printf(" [FAILED] The generated function returned incorrect result(s)\n"); + printf("Failure:\n The generated function returned incorrect result(s)\n"); return 1; } - else { - printf(" [PASSED] The generated function returned expected results\n"); - } - allocator.release((void*)fn); + printf("Success:\n The generated function returned expected results\n"); return 0; } |