Fixed AVX/XOP bugs when encoding instruction that uses register(s) with index greater than 7.

Refactored a bit testing code and added ability to asmjit_test_opcode to use registers having indexes greater than 7.
This commit is contained in:
kobalicek
2015-06-17 21:19:29 +02:00
parent ec8eb0dd47
commit 3c477177d2
19 changed files with 3127 additions and 3026 deletions

View File

@@ -37,8 +37,8 @@ script:
- make - make
- cd .. - cd ..
- ./build/asmjit_test - ./build/asmjit_test_unit
- ./build/asmjit_test_x86 - ./build/asmjit_test_x86
after_success: after_success:
- if [ "$TRAVIS_OS_NAME" = "linux" ]; then valgrind --leak-check=full --show-reachable=yes ./build/asmjit_test; fi; - if [ "$TRAVIS_OS_NAME" = "linux" ]; then valgrind --leak-check=full --show-reachable=yes ./build/asmjit_test_unit; fi;

View File

@@ -320,31 +320,31 @@ EndIf()
# ============================================================================= # =============================================================================
# AsmJit library is always embedded into the tests executable. This way it's # AsmJit library is always embedded into the tests executable. This way it's
# much easier to test private functions compared to just linking to AsmJit. # much easier to test private functions than just linking to `libasmjit.so`.
If(ASMJIT_BUILD_TEST) If(ASMJIT_BUILD_TEST)
AsmJit_AddSource(ASMJIT_TEST_SRC asmjit/test broken.cpp broken.h main.cpp) AsmJit_AddSource(ASMJIT_TEST_SRC test asmjit_test_unit.cpp broken.cpp broken.h)
Set(ASMJIT_TEST_CFLAGS Set(ASMJIT_TEST_CFLAGS
${ASMJIT_CFLAGS} ${ASMJIT_CFLAGS}
${ASMJIT_DEFINE}ASMJIT_STATIC ${ASMJIT_DEFINE}ASMJIT_STATIC
${ASMJIT_DEFINE}ASMJIT_TEST) ${ASMJIT_DEFINE}ASMJIT_TEST)
Add_Executable(asmjit_test ${ASMJIT_SRC} ${ASMJIT_TEST_SRC}) Add_Executable(asmjit_test_unit ${ASMJIT_SRC} ${ASMJIT_TEST_SRC})
Target_Link_Libraries(asmjit_test ${ASMJIT_DEPS}) Target_Link_Libraries(asmjit_test_unit ${ASMJIT_DEPS})
If(${CMAKE_BUILD_TYPE}) If(${CMAKE_BUILD_TYPE})
If(${CMAKE_BUILD_TYPE} MATCHES "Debug") If(${CMAKE_BUILD_TYPE} MATCHES "Debug")
Set_Target_Properties(asmjit_test PROPERTIES COMPILE_FLAGS ${ASMJIT_TEST_CFLAGS} ${ASMJIT_CFLAGS_DBG}) Set_Target_Properties(asmjit_test_unit PROPERTIES COMPILE_FLAGS ${ASMJIT_TEST_CFLAGS} ${ASMJIT_CFLAGS_DBG})
Else() Else()
Set_Target_Properties(asmjit_test PROPERTIES COMPILE_FLAGS ${ASMJIT_TEST_CFLAGS} ${ASMJIT_CFLAGS_REL}) Set_Target_Properties(asmjit_test_unit PROPERTIES COMPILE_FLAGS ${ASMJIT_TEST_CFLAGS} ${ASMJIT_CFLAGS_REL})
EndIf() EndIf()
Else() Else()
Target_Compile_Options(asmjit_test PUBLIC ${ASMJIT_TEST_CFLAGS} Target_Compile_Options(asmjit_test_unit PUBLIC ${ASMJIT_TEST_CFLAGS}
$<$<CONFIG:Debug>:${ASMJIT_CFLAGS_DBG}> $<$<CONFIG:Debug>:${ASMJIT_CFLAGS_DBG}>
$<$<NOT:$<CONFIG:Debug>>:${ASMJIT_CFLAGS_REL}>) $<$<NOT:$<CONFIG:Debug>>:${ASMJIT_CFLAGS_REL}>)
EndIf() EndIf()
Set_Target_Properties(asmjit_test PROPERTIES LINK_FLAGS "${ASMJIT_LFLAGS}") Set_Target_Properties(asmjit_test_unit PROPERTIES LINK_FLAGS "${ASMJIT_LFLAGS}")
EndIf() EndIf()
# ============================================================================= # =============================================================================
@@ -359,7 +359,7 @@ If(ASMJIT_BUILD_SAMPLES)
) )
ForEach(file ${ASMJIT_SRC_SAMPLES}) ForEach(file ${ASMJIT_SRC_SAMPLES})
Add_Executable(${file} src/app/test/${file}.cpp) Add_Executable(${file} src/test/${file}.cpp)
Target_Link_Libraries(${file} asmjit ${ASMJIT_DEPS}) Target_Link_Libraries(${file} asmjit ${ASMJIT_DEPS})
EndForEach(file) EndForEach(file)
EndIf() EndIf()

View File

@@ -1,42 +0,0 @@
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// This file is used to test opcodes generated by AsmJit. Output can be
// disassembled in your IDE or by your favourite disassembler. Instructions
// are grouped by category and then sorted alphabetically.
// [Dependencies - AsmJit]
#include <asmjit/asmjit.h>
// [Dependencies - Test]
#include "genopcode.h"
// [Dependencies - C]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef void (*VoidFunc)(void);
int main(int argc, char* argv[]) {
using namespace asmjit;
using namespace asmjit::host;
FileLogger logger(stdout);
logger.setOption(kLoggerOptionBinaryForm, true);
JitRuntime runtime;
X86Assembler a(&runtime);
a.setLogger(&logger);
asmgen::opcode(a);
VoidFunc p = asmjit_cast<VoidFunc>(a.make());
p();
runtime.release((void*)p);
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -365,15 +365,15 @@
//! \brief Contributions. //! \brief Contributions.
// [Dependencies - Base] // [Dependencies - Base]
#include "base.h" #include "./base.h"
// [Dependencies - X86/X64] // [Dependencies - X86/X64]
#if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64) #if defined(ASMJIT_BUILD_X86) || defined(ASMJIT_BUILD_X64)
#include "x86.h" #include "./x86.h"
#endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64 #endif // ASMJIT_BUILD_X86 || ASMJIT_BUILD_X64
// [Dependencies - Host] // [Dependencies - Host]
#include "host.h" #include "./host.h"
// [Guard] // [Guard]
#endif // _ASMJIT_ASMJIT_H #endif // _ASMJIT_ASMJIT_H

View File

@@ -9,26 +9,26 @@
#define _ASMJIT_BASE_H #define _ASMJIT_BASE_H
// [Dependencies - AsmJit] // [Dependencies - AsmJit]
#include "build.h" #include "./build.h"
#include "base/assembler.h" #include "./base/assembler.h"
#include "base/codegen.h" #include "./base/codegen.h"
#include "base/compiler.h" #include "./base/compiler.h"
#include "base/constpool.h" #include "./base/constpool.h"
#include "base/containers.h" #include "./base/containers.h"
#include "base/cpuinfo.h" #include "./base/cpuinfo.h"
#include "base/cputicks.h" #include "./base/cputicks.h"
#include "base/error.h" #include "./base/error.h"
#include "base/globals.h" #include "./base/globals.h"
#include "base/intutil.h" #include "./base/intutil.h"
#include "base/lock.h" #include "./base/lock.h"
#include "base/logger.h" #include "./base/logger.h"
#include "base/operand.h" #include "./base/operand.h"
#include "base/runtime.h" #include "./base/runtime.h"
#include "base/string.h" #include "./base/string.h"
#include "base/vectypes.h" #include "./base/vectypes.h"
#include "base/vmem.h" #include "./base/vmem.h"
#include "base/zone.h" #include "./base/zone.h"
// [Guard] // [Guard]
#endif // _ASMJIT_BASE_H #endif // _ASMJIT_BASE_H

View File

@@ -389,7 +389,7 @@ typedef unsigned __int64 uint64_t;
// Include a unit testing package if this is a `asmjit_test` build. // Include a unit testing package if this is a `asmjit_test` build.
#if defined(ASMJIT_TEST) #if defined(ASMJIT_TEST)
#include "./test/broken.h" #include "../test/broken.h"
#endif // ASMJIT_TEST #endif // ASMJIT_TEST
// [Guard] // [Guard]

View File

@@ -9,14 +9,14 @@
#define _ASMJIT_HOST_H #define _ASMJIT_HOST_H
// [Dependencies - Core] // [Dependencies - Core]
#include "base.h" #include "./base.h"
// ============================================================================ // ============================================================================
// [asmjit::host - X86 / X64] // [asmjit::host - X86 / X64]
// ============================================================================ // ============================================================================
#if defined(ASMJIT_ARCH_X86) || defined(ASMJIT_ARCH_X64) #if defined(ASMJIT_ARCH_X86) || defined(ASMJIT_ARCH_X64)
#include "x86.h" #include "./x86.h"
namespace asmjit { namespace asmjit {

View File

@@ -9,13 +9,13 @@
#define _ASMJIT_X86_H #define _ASMJIT_X86_H
// [Dependencies - AsmJit] // [Dependencies - AsmJit]
#include "base.h" #include "./base.h"
#include "x86/x86assembler.h" #include "./x86/x86assembler.h"
#include "x86/x86compiler.h" #include "./x86/x86compiler.h"
#include "x86/x86cpuinfo.h" #include "./x86/x86cpuinfo.h"
#include "x86/x86inst.h" #include "./x86/x86inst.h"
#include "x86/x86operand.h" #include "./x86/x86operand.h"
// [Guard] // [Guard]
#endif // _ASMJIT_X86_H #endif // _ASMJIT_X86_H

View File

@@ -155,11 +155,17 @@ static ASMJIT_INLINE bool x86RexIsInvalid(uint32_t rex) {
//! Encode ModR/M. //! Encode ModR/M.
static ASMJIT_INLINE uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) { static ASMJIT_INLINE uint32_t x86EncodeMod(uint32_t m, uint32_t o, uint32_t rm) {
ASMJIT_ASSERT(m <= 7);
ASMJIT_ASSERT(o <= 7);
ASMJIT_ASSERT(rm <= 7);
return (m << 6) + (o << 3) + rm; return (m << 6) + (o << 3) + rm;
} }
//! Encode SIB. //! Encode SIB.
static ASMJIT_INLINE uint32_t x86EncodeSib(uint32_t s, uint32_t i, uint32_t b) { static ASMJIT_INLINE uint32_t x86EncodeSib(uint32_t s, uint32_t i, uint32_t b) {
ASMJIT_ASSERT(s <= 7);
ASMJIT_ASSERT(i <= 7);
ASMJIT_ASSERT(b <= 7);
return (s << 6) + (i << 3) + b; return (s << 6) + (i << 3) + b;
} }
@@ -187,7 +193,7 @@ static ASMJIT_INLINE uint32_t x86RegAndVvvv(uint32_t regIndex, uint32_t vvvvInde
//! Get `O` field of `opCode`. //! Get `O` field of `opCode`.
static ASMJIT_INLINE uint32_t x86ExtractO(uint32_t opCode) { static ASMJIT_INLINE uint32_t x86ExtractO(uint32_t opCode) {
return (opCode >> kX86InstOpCode_O_Shift) & 0x7; return (opCode >> kX86InstOpCode_O_Shift) & 0x07;
} }
// ============================================================================ // ============================================================================
@@ -1429,7 +1435,7 @@ _Prepare:
// INC r16|r32 is not encodable in 64-bit mode. // INC r16|r32 is not encodable in 64-bit mode.
if (Arch == kArchX86 && (o0->getSize() == 2 || o0->getSize() == 4)) { if (Arch == kArchX86 && (o0->getSize() == 2 || o0->getSize() == 4)) {
opCode &= kX86InstOpCode_PP_66 | kX86InstOpCode_W; opCode &= kX86InstOpCode_PP_66 | kX86InstOpCode_W;
opCode |= extendedInfo.getSecondaryOpCode() + (static_cast<uint32_t>(rmReg) & 0x7); opCode |= extendedInfo.getSecondaryOpCode() + (static_cast<uint32_t>(rmReg) & 0x07);
goto _EmitX86Op; goto _EmitX86Op;
} }
else { else {
@@ -3493,7 +3499,7 @@ _EmitX86OpWithOpReg:
if (rex & ~static_cast<uint32_t>(_kX86InstOptionNoRex)) { if (rex & ~static_cast<uint32_t>(_kX86InstOptionNoRex)) {
rex |= kX86ByteRex; rex |= kX86ByteRex;
opReg &= 0x7; opReg &= 0x07;
EMIT_BYTE(rex); EMIT_BYTE(rex);
if (x86RexIsInvalid(rex)) if (x86RexIsInvalid(rex))
@@ -3524,8 +3530,8 @@ _EmitX86R:
if (rex & ~static_cast<uint32_t>(_kX86InstOptionNoRex)) { if (rex & ~static_cast<uint32_t>(_kX86InstOptionNoRex)) {
rex |= kX86ByteRex; rex |= kX86ByteRex;
opReg &= 0x7; opReg &= 0x07;
rmReg &= 0x7; rmReg &= 0x07;
EMIT_BYTE(rex); EMIT_BYTE(rex);
if (x86RexIsInvalid(rex)) if (x86RexIsInvalid(rex))
@@ -3582,14 +3588,14 @@ _EmitX86M:
if (rex & ~static_cast<uint32_t>(_kX86InstOptionNoRex)) { if (rex & ~static_cast<uint32_t>(_kX86InstOptionNoRex)) {
rex |= kX86ByteRex; rex |= kX86ByteRex;
opReg &= 0x7; opReg &= 0x07;
EMIT_BYTE(rex); EMIT_BYTE(rex);
if (x86RexIsInvalid(rex)) if (x86RexIsInvalid(rex))
goto _IllegalInst; goto _IllegalInst;
} }
mBase &= 0x7; mBase &= 0x07;
} }
// Instruction opcodes. // Instruction opcodes.
@@ -3643,7 +3649,7 @@ _EmitSib:
uint32_t shift = rmMem->getShift(); uint32_t shift = rmMem->getShift();
// Esp/Rsp/R12 register can't be used as an index. // Esp/Rsp/R12 register can't be used as an index.
mIndex &= 0x7; mIndex &= 0x07;
ASMJIT_ASSERT(mIndex != kX86RegIndexSp); ASMJIT_ASSERT(mIndex != kX86RegIndexSp);
if (mBase != kX86RegIndexBp && dispOffset == 0) { if (mBase != kX86RegIndexBp && dispOffset == 0) {
@@ -3734,7 +3740,7 @@ _EmitSib:
} }
else { else {
// [Disp32 + Index * Scale]. // [Disp32 + Index * Scale].
mIndex &= 0x7; mIndex &= 0x07;
ASMJIT_ASSERT(mIndex != kX86RegIndexSp); ASMJIT_ASSERT(mIndex != kX86RegIndexSp);
uint32_t shift = rmMem->getShift(); uint32_t shift = rmMem->getShift();
@@ -3857,8 +3863,8 @@ _EmitFpuOp:
} \ } \
} \ } \
\ \
mBase &= 0x7; \ mBase &= 0x07; \
opReg &= 0x7; opReg &= 0x07;
_EmitAvxOp: _EmitAvxOp:
{ {
@@ -3920,7 +3926,7 @@ _EmitAvxR:
} }
} }
EMIT_BYTE(x86EncodeMod(3, opReg, static_cast<uint32_t>(rmReg))); EMIT_BYTE(x86EncodeMod(3, opReg & 0x07, static_cast<uint32_t>(rmReg)));
if (imLen == 0) if (imLen == 0)
goto _EmitDone; goto _EmitDone;
@@ -3939,7 +3945,7 @@ _EmitAvxV:
goto _IllegalInst; goto _IllegalInst;
if (Arch == kArchX64) if (Arch == kArchX64)
mIndex &= 0x7; mIndex &= 0x07;
dispOffset = rmMem->getDisplacement(); dispOffset = rmMem->getDisplacement();
if (rmMem->isBaseIndexType()) { if (rmMem->isBaseIndexType()) {
@@ -4046,8 +4052,8 @@ _EmitAvxV:
EMIT_OP(opCode); \ EMIT_OP(opCode); \
} \ } \
\ \
mBase &= 0x7; \ mBase &= 0x07; \
opReg &= 0x7; opReg &= 0x07;
_EmitXopR: _EmitXopR:
{ {
@@ -4074,7 +4080,7 @@ _EmitXopR:
rmReg &= 0x07; rmReg &= 0x07;
} }
EMIT_BYTE(x86EncodeMod(3, opReg, static_cast<uint32_t>(rmReg))); EMIT_BYTE(x86EncodeMod(3, opReg & 0x07, static_cast<uint32_t>(rmReg)));
if (imLen == 0) if (imLen == 0)
goto _EmitDone; goto _EmitDone;

View File

@@ -1887,7 +1887,7 @@ static ASMJIT_INLINE X86Mem ptr(const Label& label, const X86GpReg& index, uint3
//! Create `[RIP + disp]` memory operand with no/custom size information. //! Create `[RIP + disp]` memory operand with no/custom size information.
static ASMJIT_INLINE X86Mem ptr(const X86RipReg& rip, int32_t disp = 0, uint32_t size = 0) { static ASMJIT_INLINE X86Mem ptr(const X86RipReg& rip, int32_t disp = 0, uint32_t size = 0) {
return X86Mem(rip, disp, size); return X86Mem(rip, disp, size);
} }
//! Create `[pAbs + disp]` absolute memory operand with no/custom size information. //! Create `[pAbs + disp]` absolute memory operand with no/custom size information.

View File

@@ -5,11 +5,11 @@
// Zlib - See LICENSE.md file in the package. // Zlib - See LICENSE.md file in the package.
// [Dependencies - AsmJit] // [Dependencies - AsmJit]
#include <asmjit/asmjit.h> #include "../asmjit/asmjit.h"
// [Dependencies - Test] // [Dependencies - Test]
#include "genblend.h" #include "./asmjit_test_opcode.h"
#include "genopcode.h" #include "./genblend.h"
// [Dependencies - C] // [Dependencies - C]
#include <stdio.h> #include <stdio.h>

View File

@@ -0,0 +1,75 @@
// [AsmJit]
// Complete x86/x64 JIT and Remote Assembler for C++.
//
// [License]
// Zlib - See LICENSE.md file in the package.
// This file is used to test opcodes generated by AsmJit. Output can be
// disassembled in your IDE or by your favourite disassembler. Instructions
// are grouped by category and then sorted alphabetically.
// [Dependencies - AsmJit]
#include "../asmjit/asmjit.h"
// [Dependencies - Test]
#include "./asmjit_test_opcode.h"
// [Dependencies - C]
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef void (*VoidFunc)(void);
struct OpcodeDumpInfo {
uint32_t arch;
bool useRex;
};
static const char* archIdToString(uint32_t archId) {
switch (archId) {
case asmjit::kArchNone: return "None";
case asmjit::kArchX86: return "X86";
case asmjit::kArchX64: return "X64";
case asmjit::kArchArm: return "ARM";
default: return "<unknown>";
}
}
int main(int argc, char* argv[]) {
asmjit::FileLogger logger(stdout);
logger.setOption(asmjit::kLoggerOptionBinaryForm, true);
OpcodeDumpInfo infoList[] = {
# if defined(ASMJIT_BUILD_X86)
{ asmjit::kArchX86, false },
# endif // ASMJIT_BUILD_X86
# if defined(ASMJIT_BUILD_X64)
{ asmjit::kArchX64, false },
{ asmjit::kArchX64, true }
# endif // ASMJIT_BUILD_X64
};
for (int i = 0; i < ASMJIT_ARRAY_SIZE(infoList); i++) {
const OpcodeDumpInfo& info = infoList[i];
printf("Opcodes [ARCH=%s REX=%s]\n",
archIdToString(info.arch),
info.useRex ? "true" : "false");
asmjit::JitRuntime runtime;
asmjit::X86Assembler a(&runtime, info.arch);
a.setLogger(&logger);
asmgen::opcode(a, info.useRex);
VoidFunc p = asmjit_cast<VoidFunc>(a.make());
// Only run if disassembly makes sense.
if (info.arch == asmjit::kArchHost)
p();
runtime.release((void*)p);
}
return 0;
}

File diff suppressed because it is too large Load Diff

View File

@@ -5,9 +5,7 @@
// Zlib - See LICENSE.md file in the package. // Zlib - See LICENSE.md file in the package.
// [Dependencies - AsmJit] // [Dependencies - AsmJit]
#include "../asmjit.h" #include "../asmjit/asmjit.h"
using namespace asmjit;
// ============================================================================ // ============================================================================
// [DumpCpu] // [DumpCpu]
@@ -18,14 +16,14 @@ struct DumpCpuFeature {
const char* name; const char* name;
}; };
static void dumpCpuFeatures(const CpuInfo* cpuInfo, const DumpCpuFeature* data, size_t count) { static void dumpCpuFeatures(const asmjit::CpuInfo* cpuInfo, const DumpCpuFeature* data, size_t count) {
for (size_t i = 0; i < count; i++) for (size_t i = 0; i < count; i++)
if (cpuInfo->hasFeature(data[i].feature)) if (cpuInfo->hasFeature(data[i].feature))
INFO(" %s", data[i].name); INFO(" %s", data[i].name);
} }
static void dumpCpu(void) { static void dumpCpu(void) {
const CpuInfo* cpu = CpuInfo::getHost(); const asmjit::CpuInfo* cpu = asmjit::CpuInfo::getHost();
INFO("Host CPU Info:"); INFO("Host CPU Info:");
INFO(" Vendor string : %s", cpu->getVendorString()); INFO(" Vendor string : %s", cpu->getVendorString());
@@ -41,67 +39,67 @@ static void dumpCpu(void) {
// -------------------------------------------------------------------------- // --------------------------------------------------------------------------
#if defined(ASMJIT_ARCH_X86) || defined(ASMJIT_ARCH_X64) #if defined(ASMJIT_ARCH_X86) || defined(ASMJIT_ARCH_X64)
const X86CpuInfo* x86Cpu = static_cast<const X86CpuInfo*>(cpu); const asmjit::X86CpuInfo* x86Cpu = static_cast<const asmjit::X86CpuInfo*>(cpu);
static const DumpCpuFeature x86FeaturesList[] = { static const DumpCpuFeature x86FeaturesList[] = {
{ kX86CpuFeatureNX , "NX (Non-Execute Bit)" }, { asmjit::kX86CpuFeatureNX , "NX (Non-Execute Bit)" },
{ kX86CpuFeatureMT , "MT (Multi-Threading)" }, { asmjit::kX86CpuFeatureMT , "MT (Multi-Threading)" },
{ kX86CpuFeatureRDTSC , "RDTSC" }, { asmjit::kX86CpuFeatureRDTSC , "RDTSC" },
{ kX86CpuFeatureRDTSCP , "RDTSCP" }, { asmjit::kX86CpuFeatureRDTSCP , "RDTSCP" },
{ kX86CpuFeatureCMOV , "CMOV" }, { asmjit::kX86CpuFeatureCMOV , "CMOV" },
{ kX86CpuFeatureCMPXCHG8B , "CMPXCHG8B" }, { asmjit::kX86CpuFeatureCMPXCHG8B , "CMPXCHG8B" },
{ kX86CpuFeatureCMPXCHG16B , "CMPXCHG16B" }, { asmjit::kX86CpuFeatureCMPXCHG16B , "CMPXCHG16B" },
{ kX86CpuFeatureCLFLUSH , "CLFLUSH" }, { asmjit::kX86CpuFeatureCLFLUSH , "CLFLUSH" },
{ kX86CpuFeatureCLFLUSHOpt , "CLFLUSH (Opt)" }, { asmjit::kX86CpuFeatureCLFLUSHOpt , "CLFLUSH (Opt)" },
{ kX86CpuFeaturePREFETCH , "PREFETCH" }, { asmjit::kX86CpuFeaturePREFETCH , "PREFETCH" },
{ kX86CpuFeaturePREFETCHWT1 , "PREFETCHWT1" }, { asmjit::kX86CpuFeaturePREFETCHWT1 , "PREFETCHWT1" },
{ kX86CpuFeatureLahfSahf , "LAHF/SAHF" }, { asmjit::kX86CpuFeatureLahfSahf , "LAHF/SAHF" },
{ kX86CpuFeatureFXSR , "FXSR" }, { asmjit::kX86CpuFeatureFXSR , "FXSR" },
{ kX86CpuFeatureFXSROpt , "FXSR (Opt)" }, { asmjit::kX86CpuFeatureFXSROpt , "FXSR (Opt)" },
{ kX86CpuFeatureMMX , "MMX" }, { asmjit::kX86CpuFeatureMMX , "MMX" },
{ kX86CpuFeatureMMX2 , "MMX2" }, { asmjit::kX86CpuFeatureMMX2 , "MMX2" },
{ kX86CpuFeature3DNOW , "3DNOW" }, { asmjit::kX86CpuFeature3DNOW , "3DNOW" },
{ kX86CpuFeature3DNOW2 , "3DNOW2" }, { asmjit::kX86CpuFeature3DNOW2 , "3DNOW2" },
{ kX86CpuFeatureSSE , "SSE" }, { asmjit::kX86CpuFeatureSSE , "SSE" },
{ kX86CpuFeatureSSE2 , "SSE2" }, { asmjit::kX86CpuFeatureSSE2 , "SSE2" },
{ kX86CpuFeatureSSE3 , "SSE3" }, { asmjit::kX86CpuFeatureSSE3 , "SSE3" },
{ kX86CpuFeatureSSSE3 , "SSSE3" }, { asmjit::kX86CpuFeatureSSSE3 , "SSSE3" },
{ kX86CpuFeatureSSE4A , "SSE4A" }, { asmjit::kX86CpuFeatureSSE4A , "SSE4A" },
{ kX86CpuFeatureSSE4_1 , "SSE4.1" }, { asmjit::kX86CpuFeatureSSE4_1 , "SSE4.1" },
{ kX86CpuFeatureSSE4_2 , "SSE4.2" }, { asmjit::kX86CpuFeatureSSE4_2 , "SSE4.2" },
{ kX86CpuFeatureMSSE , "Misaligned SSE" }, { asmjit::kX86CpuFeatureMSSE , "Misaligned SSE" },
{ kX86CpuFeatureMONITOR , "MONITOR/MWAIT" }, { asmjit::kX86CpuFeatureMONITOR , "MONITOR/MWAIT" },
{ kX86CpuFeatureMOVBE , "MOVBE" }, { asmjit::kX86CpuFeatureMOVBE , "MOVBE" },
{ kX86CpuFeaturePOPCNT , "POPCNT" }, { asmjit::kX86CpuFeaturePOPCNT , "POPCNT" },
{ kX86CpuFeatureLZCNT , "LZCNT" }, { asmjit::kX86CpuFeatureLZCNT , "LZCNT" },
{ kX86CpuFeatureAESNI , "AESNI" }, { asmjit::kX86CpuFeatureAESNI , "AESNI" },
{ kX86CpuFeaturePCLMULQDQ , "PCLMULQDQ" }, { asmjit::kX86CpuFeaturePCLMULQDQ , "PCLMULQDQ" },
{ kX86CpuFeatureRDRAND , "RDRAND" }, { asmjit::kX86CpuFeatureRDRAND , "RDRAND" },
{ kX86CpuFeatureRDSEED , "RDSEED" }, { asmjit::kX86CpuFeatureRDSEED , "RDSEED" },
{ kX86CpuFeatureSHA , "SHA" }, { asmjit::kX86CpuFeatureSHA , "SHA" },
{ kX86CpuFeatureXSave , "XSAVE" }, { asmjit::kX86CpuFeatureXSave , "XSAVE" },
{ kX86CpuFeatureXSaveOS , "XSAVE (OS)" }, { asmjit::kX86CpuFeatureXSaveOS , "XSAVE (OS)" },
{ kX86CpuFeatureAVX , "AVX" }, { asmjit::kX86CpuFeatureAVX , "AVX" },
{ kX86CpuFeatureAVX2 , "AVX2" }, { asmjit::kX86CpuFeatureAVX2 , "AVX2" },
{ kX86CpuFeatureF16C , "F16C" }, { asmjit::kX86CpuFeatureF16C , "F16C" },
{ kX86CpuFeatureFMA3 , "FMA3" }, { asmjit::kX86CpuFeatureFMA3 , "FMA3" },
{ kX86CpuFeatureFMA4 , "FMA4" }, { asmjit::kX86CpuFeatureFMA4 , "FMA4" },
{ kX86CpuFeatureXOP , "XOP" }, { asmjit::kX86CpuFeatureXOP , "XOP" },
{ kX86CpuFeatureBMI , "BMI" }, { asmjit::kX86CpuFeatureBMI , "BMI" },
{ kX86CpuFeatureBMI2 , "BMI2" }, { asmjit::kX86CpuFeatureBMI2 , "BMI2" },
{ kX86CpuFeatureHLE , "HLE" }, { asmjit::kX86CpuFeatureHLE , "HLE" },
{ kX86CpuFeatureRTM , "RTM" }, { asmjit::kX86CpuFeatureRTM , "RTM" },
{ kX86CpuFeatureADX , "ADX" }, { asmjit::kX86CpuFeatureADX , "ADX" },
{ kX86CpuFeatureMPX , "MPX" }, { asmjit::kX86CpuFeatureMPX , "MPX" },
{ kX86CpuFeatureFSGSBase , "FS/GS Base" }, { asmjit::kX86CpuFeatureFSGSBase , "FS/GS Base" },
{ kX86CpuFeatureMOVSBSTOSBOpt , "REP MOVSB/STOSB (Opt)" }, { asmjit::kX86CpuFeatureMOVSBSTOSBOpt , "REP MOVSB/STOSB (Opt)" },
{ kX86CpuFeatureAVX512F , "AVX512F" }, { asmjit::kX86CpuFeatureAVX512F , "AVX512F" },
{ kX86CpuFeatureAVX512CD , "AVX512CD" }, { asmjit::kX86CpuFeatureAVX512CD , "AVX512CD" },
{ kX86CpuFeatureAVX512PF , "AVX512PF" }, { asmjit::kX86CpuFeatureAVX512PF , "AVX512PF" },
{ kX86CpuFeatureAVX512ER , "AVX512ER" }, { asmjit::kX86CpuFeatureAVX512ER , "AVX512ER" },
{ kX86CpuFeatureAVX512DQ , "AVX512DQ" }, { asmjit::kX86CpuFeatureAVX512DQ , "AVX512DQ" },
{ kX86CpuFeatureAVX512BW , "AVX512BW" }, { asmjit::kX86CpuFeatureAVX512BW , "AVX512BW" },
{ kX86CpuFeatureAVX512VL , "AVX512VL" } { asmjit::kX86CpuFeatureAVX512VL , "AVX512VL" }
}; };
INFO("Host CPU Info (X86/X64):"); INFO("Host CPU Info (X86/X64):");

View File

@@ -5,10 +5,10 @@
// Zlib - See LICENSE.md file in the package. // Zlib - See LICENSE.md file in the package.
// [Dependencies - AsmJit] // [Dependencies - AsmJit]
#include <asmjit/asmjit.h> #include "../asmjit/asmjit.h"
// [Dependencies - Test] // [Dependencies - Test]
#include "genblend.h" #include "./genblend.h"
// [Dependencies - C] // [Dependencies - C]
#include <stdio.h> #include <stdio.h>
@@ -1799,7 +1799,7 @@ struct X86Test_CallBase : public X86Test {
// Call function. // Call function.
X86GpVar fn(c, kVarTypeIntPtr, "fn"); X86GpVar fn(c, kVarTypeIntPtr, "fn");
c.mov(fn, imm_ptr((void*)calledFunc)); c.mov(fn, imm_ptr(calledFunc));
X86CallNode* call = c.call(fn, kFuncConvHost, FuncBuilder3<int, int, int, int>()); X86CallNode* call = c.call(fn, kFuncConvHost, FuncBuilder3<int, int, int, int>());
call->setArg(0, v2); call->setArg(0, v2);
@@ -1845,7 +1845,7 @@ struct X86Test_CallFast : public X86Test {
c.addFunc(kFuncConvHost, FuncBuilder1<int, int>()); c.addFunc(kFuncConvHost, FuncBuilder1<int, int>());
c.setArg(0, var); c.setArg(0, var);
c.mov(fn, imm_ptr((void*)calledFunc)); c.mov(fn, imm_ptr(calledFunc));
X86CallNode* call; X86CallNode* call;
call = c.call(fn, kFuncConvHostFastCall, FuncBuilder1<int, int>()); call = c.call(fn, kFuncConvHostFastCall, FuncBuilder1<int, int>());
@@ -1910,7 +1910,7 @@ struct X86Test_CallManyArgs : public X86Test {
X86GpVar vi(c, kVarTypeInt32, "vi"); X86GpVar vi(c, kVarTypeInt32, "vi");
X86GpVar vj(c, kVarTypeInt32, "vj"); X86GpVar vj(c, kVarTypeInt32, "vj");
c.mov(fn, imm_ptr((void*)calledFunc)); c.mov(fn, imm_ptr(calledFunc));
c.mov(va, 0x03); c.mov(va, 0x03);
c.mov(vb, 0x12); c.mov(vb, 0x12);
c.mov(vc, 0xA0); c.mov(vc, 0xA0);
@@ -1977,7 +1977,7 @@ struct X86Test_CallDuplicateArgs : public X86Test {
X86GpVar fn(c, kVarTypeIntPtr, "fn"); X86GpVar fn(c, kVarTypeIntPtr, "fn");
X86GpVar a(c, kVarTypeInt32, "a"); X86GpVar a(c, kVarTypeInt32, "a");
c.mov(fn, imm_ptr((void*)calledFunc)); c.mov(fn, imm_ptr(calledFunc));
c.mov(a, 3); c.mov(a, 3);
// Call function. // Call function.
@@ -2031,7 +2031,7 @@ struct X86Test_CallImmArgs : public X86Test {
X86GpVar fn(c, kVarTypeIntPtr, "fn"); X86GpVar fn(c, kVarTypeIntPtr, "fn");
X86GpVar rv(c, kVarTypeInt32, "rv"); X86GpVar rv(c, kVarTypeInt32, "rv");
c.mov(fn, imm_ptr((void*)X86Test_CallManyArgs::calledFunc)); c.mov(fn, imm_ptr(X86Test_CallManyArgs::calledFunc));
// Call function. // Call function.
X86CallNode* call = c.call(fn, kFuncConvHost, X86CallNode* call = c.call(fn, kFuncConvHost,
@@ -2097,7 +2097,7 @@ struct X86Test_CallPtrArgs : public X86Test {
X86GpVar fn(c, kVarTypeIntPtr, "fn"); X86GpVar fn(c, kVarTypeIntPtr, "fn");
X86GpVar rv(c, kVarTypeInt32, "rv"); X86GpVar rv(c, kVarTypeInt32, "rv");
c.mov(fn, imm_ptr((void*)calledFunc)); c.mov(fn, imm_ptr(calledFunc));
// Call function. // Call function.
X86CallNode* call = c.call(fn, kFuncConvHost, X86CallNode* call = c.call(fn, kFuncConvHost,
@@ -2159,7 +2159,7 @@ struct X86Test_CallFloatAsXmmRet : public X86Test {
// Prepare. // Prepare.
X86GpVar fn(c); X86GpVar fn(c);
c.mov(fn, imm_ptr((void*)calledFunc)); c.mov(fn, imm_ptr(calledFunc));
// Call function. // Call function.
X86CallNode* call = c.call(fn, kFuncConvHost, X86CallNode* call = c.call(fn, kFuncConvHost,
@@ -2213,7 +2213,7 @@ struct X86Test_CallDoubleAsXmmRet : public X86Test {
c.setArg(1, b); c.setArg(1, b);
X86GpVar fn(c); X86GpVar fn(c);
c.mov(fn, imm_ptr((void*)calledFunc)); c.mov(fn, imm_ptr(calledFunc));
X86CallNode* call = c.call(fn, kFuncConvHost, X86CallNode* call = c.call(fn, kFuncConvHost,
FuncBuilder2<double, double, double>()); FuncBuilder2<double, double, double>());
@@ -2474,7 +2474,7 @@ struct X86Test_CallMisc1 : public X86Test {
c.alloc(a, x86::eax); c.alloc(a, x86::eax);
c.alloc(b, x86::ebx); c.alloc(b, x86::ebx);
X86CallNode* call = c.call(imm_ptr((void*)dummy), kFuncConvHost, FuncBuilder2<void, int, int>()); X86CallNode* call = c.call(imm_ptr(dummy), kFuncConvHost, FuncBuilder2<void, int, int>());
call->setArg(0, a); call->setArg(0, a);
call->setArg(1, b); call->setArg(1, b);
@@ -2520,7 +2520,7 @@ struct X86Test_CallMisc2 : public X86Test {
c.setArg(0, p); c.setArg(0, p);
c.movsd(arg, x86::ptr(p)); c.movsd(arg, x86::ptr(p));
c.mov(fn, imm_ptr((void*)op)); c.mov(fn, imm_ptr(op));
X86CallNode* call = c.call(fn, kFuncConvHost, FuncBuilder1<double, double>()); X86CallNode* call = c.call(fn, kFuncConvHost, FuncBuilder1<double, double>());
call->setArg(0, arg); call->setArg(0, arg);
@@ -2570,7 +2570,7 @@ struct X86Test_CallMisc3 : public X86Test {
c.setArg(0, p); c.setArg(0, p);
c.movsd(arg, x86::ptr(p)); c.movsd(arg, x86::ptr(p));
c.mov(fn, imm_ptr((void*)op)); c.mov(fn, imm_ptr(op));
X86CallNode* call = c.call(fn, kFuncConvHost, FuncBuilder1<double, double>()); X86CallNode* call = c.call(fn, kFuncConvHost, FuncBuilder1<double, double>());
call->setArg(0, arg); call->setArg(0, arg);
@@ -2601,6 +2601,49 @@ struct X86Test_CallMisc3 : public X86Test {
static double op(double a) { return a * a; } static double op(double a) { return a * a; }
}; };
// ============================================================================
// [X86Test_CallMisc4]
// ============================================================================
struct X86Test_CallMisc4 : public X86Test {
X86Test_CallMisc4() : X86Test("[Call] Misc #4") {}
static void add(PodVector<X86Test*>& tests) {
tests.append(new X86Test_CallMisc4());
}
virtual void compile(X86Compiler& c) {
FuncBuilderX funcPrototype;
funcPrototype.setRet(kVarTypeFp64);
X86FuncNode* func = c.addFunc(kFuncConvHost, funcPrototype);
FuncBuilderX callPrototype;
callPrototype.setRet(kVarTypeFp64);
X86CallNode* call = c.call(imm_ptr(calledFunc), kFuncConvHost, callPrototype);
X86XmmVar ret(c, kX86VarTypeXmmSd, "ret");
call->setRet(0, ret);
c.ret(ret);
c.endFunc();
}
virtual bool run(void* _func, StringBuilder& result, StringBuilder& expect) {
typedef double (*Func)(void);
Func func = asmjit_cast<Func>(_func);
double resultRet = func();
double expectRet = 3.14;
result.setFormat("ret=%g", resultRet);
expect.setFormat("ret=%g", expectRet);
return resultRet == expectRet;
}
static double calledFunc() { return 3.14; }
};
// ============================================================================ // ============================================================================
// [X86Test_MiscConstPool] // [X86Test_MiscConstPool]
// ============================================================================ // ============================================================================
@@ -2732,14 +2775,14 @@ struct X86Test_MiscMultiRet : public X86Test {
expect.setFormat("ret={%d %d %d %d}", e0, e1, e2, e3); expect.setFormat("ret={%d %d %d %d}", e0, e1, e2, e3);
return result.eq(expect); return result.eq(expect);
} }
}; };
// ============================================================================ // ============================================================================
// [X86Test_MiscUnfollow] // [X86Test_MiscUnfollow]
// ============================================================================ // ============================================================================
// Global (I didn't find better way to really test this). // Global (I didn't find a better way to test this).
static jmp_buf globalJmpBuf; static jmp_buf globalJmpBuf;
struct X86Test_MiscUnfollow : public X86Test { struct X86Test_MiscUnfollow : public X86Test {
@@ -2881,6 +2924,7 @@ X86TestSuite::X86TestSuite() :
ADD_TEST(X86Test_CallMisc1); ADD_TEST(X86Test_CallMisc1);
ADD_TEST(X86Test_CallMisc2); ADD_TEST(X86Test_CallMisc2);
ADD_TEST(X86Test_CallMisc3); ADD_TEST(X86Test_CallMisc3);
ADD_TEST(X86Test_CallMisc4);
// Misc. // Misc.
ADD_TEST(X86Test_MiscConstPool); ADD_TEST(X86Test_MiscConstPool);

View File

@@ -5,11 +5,11 @@
// Zlib - See LICENSE.md file in the package. // Zlib - See LICENSE.md file in the package.
// [Guard] // [Guard]
#ifndef _APP_TEST_GENBLEND_H #ifndef _TEST_GENBLEND_H
#define _APP_TEST_GENBLEND_H #define _TEST_GENBLEND_H
// [Dependencies] // [Dependencies]
#include <asmjit/asmjit.h> #include "../asmjit/asmjit.h"
namespace asmgen { namespace asmgen {
@@ -177,4 +177,4 @@ static void blend(asmjit::X86Compiler& c) {
} // asmgen namespace } // asmgen namespace
// [Guard] // [Guard]
#endif // _APP_TEST_GENBLEND_H #endif // _TEST_GENBLEND_H