add x86 asmjit
This commit is contained in:
@@ -22,7 +22,6 @@ mono_crash.*
|
||||
[Rr]elease/
|
||||
[Rr]eleases/
|
||||
x64/
|
||||
x86/
|
||||
[Ww][Ii][Nn]32/
|
||||
[Aa][Rr][Mm]/
|
||||
[Aa][Rr][Mm]64/
|
||||
|
||||
+6680
File diff suppressed because it is too large
Load Diff
+5626
File diff suppressed because it is too large
Load Diff
+523
@@ -0,0 +1,523 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_X86_X86CONTEXT_P_H
|
||||
#define _ASMJIT_X86_X86CONTEXT_P_H
|
||||
|
||||
#include "../build.h"
|
||||
#if !defined(ASMJIT_DISABLE_COMPILER)
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/compiler.h"
|
||||
#include "../base/context_p.h"
|
||||
#include "../base/intutil.h"
|
||||
#include "../x86/x86assembler.h"
|
||||
#include "../x86/x86compiler.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
//! \addtogroup asmjit_x86_compiler
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::X86Context]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_DEBUG)
|
||||
# define ASMJIT_X86_CHECK_STATE _checkState();
|
||||
#else
|
||||
# define ASMJIT_X86_CHECK_STATE
|
||||
#endif // ASMJIT_DEBUG
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! Compiler context is used by `X86Compiler`.
|
||||
//!
|
||||
//! Compiler context is used during compilation and normally developer doesn't
|
||||
//! need access to it. The context is user per function (it's reset after each
|
||||
//! function is generated).
|
||||
struct X86Context : public Context {
|
||||
ASMJIT_NO_COPY(X86Context)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Create a new `X86Context` instance.
|
||||
X86Context(X86Compiler* compiler);
|
||||
//! Destroy the `X86Context` instance.
|
||||
virtual ~X86Context();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Reset]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
virtual void reset(bool releaseMemory = false);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Arch]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE bool isX64() const {
|
||||
return _zsp.getSize() == 16;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get compiler as `X86Compiler`.
|
||||
ASMJIT_INLINE X86Compiler* getCompiler() const {
|
||||
return static_cast<X86Compiler*>(_compiler);
|
||||
}
|
||||
|
||||
//! Get function as `X86FuncNode`.
|
||||
ASMJIT_INLINE X86FuncNode* getFunc() const {
|
||||
return reinterpret_cast<X86FuncNode*>(_func);
|
||||
}
|
||||
|
||||
//! Get clobbered registers (global).
|
||||
ASMJIT_INLINE uint32_t getClobberedRegs(uint32_t c) {
|
||||
return _clobberedRegs.get(c);
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Helpers]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE X86VarMap* newVarMap(uint32_t vaCount) {
|
||||
return static_cast<X86VarMap*>(
|
||||
_baseZone.alloc(sizeof(X86VarMap) + vaCount * sizeof(VarAttr)));
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Emit]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
void emitLoad(VarData* vd, uint32_t regIndex, const char* reason);
|
||||
void emitSave(VarData* vd, uint32_t regIndex, const char* reason);
|
||||
void emitMove(VarData* vd, uint32_t toRegIndex, uint32_t fromRegIndex, const char* reason);
|
||||
void emitSwapGp(VarData* aVd, VarData* bVd, uint32_t aIndex, uint32_t bIndex, const char* reason);
|
||||
|
||||
void emitPushSequence(uint32_t regs);
|
||||
void emitPopSequence(uint32_t regs);
|
||||
|
||||
void emitConvertVarToVar(uint32_t dstType, uint32_t dstIndex, uint32_t srcType, uint32_t srcIndex);
|
||||
void emitMoveVarOnStack(uint32_t dstType, const X86Mem* dst, uint32_t srcType, uint32_t srcIndex);
|
||||
void emitMoveImmOnStack(uint32_t dstType, const X86Mem* dst, const Imm* src);
|
||||
|
||||
void emitMoveImmToReg(uint32_t dstType, uint32_t dstIndex, const Imm* src);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Register Management]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
void _checkState();
|
||||
|
||||
ASMJIT_INLINE uint32_t getRegSize() const {
|
||||
return _zsp.getSize();
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Attach / Detach]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Attach.
|
||||
//!
|
||||
//! Attach a register to the 'VarData', changing 'VarData' members to show
|
||||
//! that the variable is currently alive and linking variable with the
|
||||
//! current 'X86VarState'.
|
||||
template<int C>
|
||||
ASMJIT_INLINE void attach(VarData* vd, uint32_t regIndex, bool modified) {
|
||||
ASMJIT_ASSERT(vd->getClass() == C);
|
||||
ASMJIT_ASSERT(regIndex != kInvalidReg);
|
||||
|
||||
// Prevent Esp allocation if C==Gp.
|
||||
ASMJIT_ASSERT(C != kX86RegClassGp || regIndex != kX86RegIndexSp);
|
||||
|
||||
uint32_t regMask = IntUtil::mask(regIndex);
|
||||
|
||||
vd->setState(kVarStateReg);
|
||||
vd->setRegIndex(regIndex);
|
||||
vd->addHomeIndex(regIndex);
|
||||
vd->setModified(modified);
|
||||
|
||||
_x86State.getListByClass(C)[regIndex] = vd;
|
||||
_x86State._occupied.or_(C, regMask);
|
||||
_x86State._modified.or_(C, static_cast<uint32_t>(modified) << regIndex);
|
||||
|
||||
ASMJIT_X86_CHECK_STATE
|
||||
}
|
||||
|
||||
//! Detach.
|
||||
//!
|
||||
//! The opposite of 'Attach'. Detach resets the members in 'VarData'
|
||||
//! (regIndex, state and changed flags) and unlinks the variable with the
|
||||
//! current 'X86VarState'.
|
||||
template<int C>
|
||||
ASMJIT_INLINE void detach(VarData* vd, uint32_t regIndex, uint32_t vState) {
|
||||
ASMJIT_ASSERT(vd->getClass() == C);
|
||||
ASMJIT_ASSERT(vd->getRegIndex() == regIndex);
|
||||
ASMJIT_ASSERT(vState != kVarStateReg);
|
||||
|
||||
uint32_t regMask = IntUtil::mask(regIndex);
|
||||
|
||||
vd->setState(vState);
|
||||
vd->resetRegIndex();
|
||||
vd->setModified(false);
|
||||
|
||||
_x86State.getListByClass(C)[regIndex] = NULL;
|
||||
_x86State._occupied.andNot(C, regMask);
|
||||
_x86State._modified.andNot(C, regMask);
|
||||
|
||||
ASMJIT_X86_CHECK_STATE
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Rebase]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Rebase.
|
||||
//!
|
||||
//! Change the register of the 'VarData' changing also the current 'X86VarState'.
|
||||
//! Rebase is nearly identical to 'Detach' and 'Attach' sequence, but doesn't
|
||||
// change the 'VarData' modified flag.
|
||||
template<int C>
|
||||
ASMJIT_INLINE void rebase(VarData* vd, uint32_t newRegIndex, uint32_t oldRegIndex) {
|
||||
ASMJIT_ASSERT(vd->getClass() == C);
|
||||
|
||||
uint32_t newRegMask = IntUtil::mask(newRegIndex);
|
||||
uint32_t oldRegMask = IntUtil::mask(oldRegIndex);
|
||||
uint32_t bothRegMask = newRegMask ^ oldRegMask;
|
||||
|
||||
vd->setRegIndex(newRegIndex);
|
||||
|
||||
_x86State.getListByClass(C)[oldRegIndex] = NULL;
|
||||
_x86State.getListByClass(C)[newRegIndex] = vd;
|
||||
|
||||
_x86State._occupied.xor_(C, bothRegMask);
|
||||
_x86State._modified.xor_(C, bothRegMask & -static_cast<int32_t>(vd->isModified()));
|
||||
|
||||
ASMJIT_X86_CHECK_STATE
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Load / Save]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Load.
|
||||
//!
|
||||
//! Load variable from its memory slot to a register, emitting 'Load'
|
||||
//! instruction and changing the variable state to allocated.
|
||||
template<int C>
|
||||
ASMJIT_INLINE void load(VarData* vd, uint32_t regIndex) {
|
||||
// Can be only called if variable is not allocated.
|
||||
ASMJIT_ASSERT(vd->getClass() == C);
|
||||
ASMJIT_ASSERT(vd->getState() != kVarStateReg);
|
||||
ASMJIT_ASSERT(vd->getRegIndex() == kInvalidReg);
|
||||
|
||||
emitLoad(vd, regIndex, "Load");
|
||||
attach<C>(vd, regIndex, false);
|
||||
|
||||
ASMJIT_X86_CHECK_STATE
|
||||
}
|
||||
|
||||
//! Save.
|
||||
//!
|
||||
//! Save the variable into its home location, but keep it as allocated.
|
||||
template<int C>
|
||||
ASMJIT_INLINE void save(VarData* vd) {
|
||||
ASMJIT_ASSERT(vd->getClass() == C);
|
||||
ASMJIT_ASSERT(vd->getState() == kVarStateReg);
|
||||
ASMJIT_ASSERT(vd->getRegIndex() != kInvalidReg);
|
||||
|
||||
uint32_t regIndex = vd->getRegIndex();
|
||||
uint32_t regMask = IntUtil::mask(regIndex);
|
||||
|
||||
emitSave(vd, regIndex, "Save");
|
||||
|
||||
vd->setModified(false);
|
||||
_x86State._modified.andNot(C, regMask);
|
||||
|
||||
ASMJIT_X86_CHECK_STATE
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Move / Swap]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Move a register.
|
||||
//!
|
||||
//! Move register from one index to another, emitting 'Move' if needed. This
|
||||
//! function does nothing if register is already at the given index.
|
||||
template<int C>
|
||||
ASMJIT_INLINE void move(VarData* vd, uint32_t regIndex) {
|
||||
ASMJIT_ASSERT(vd->getClass() == C);
|
||||
ASMJIT_ASSERT(vd->getState() == kVarStateReg);
|
||||
ASMJIT_ASSERT(vd->getRegIndex() != kInvalidReg);
|
||||
|
||||
uint32_t oldIndex = vd->getRegIndex();
|
||||
if (regIndex != oldIndex) {
|
||||
emitMove(vd, regIndex, oldIndex, "Move");
|
||||
rebase<C>(vd, regIndex, oldIndex);
|
||||
}
|
||||
|
||||
ASMJIT_X86_CHECK_STATE
|
||||
}
|
||||
|
||||
//! Swap two registers
|
||||
//!
|
||||
//! It's only possible to swap Gp registers.
|
||||
ASMJIT_INLINE void swapGp(VarData* aVd, VarData* bVd) {
|
||||
ASMJIT_ASSERT(aVd != bVd);
|
||||
|
||||
ASMJIT_ASSERT(aVd->getClass() == kX86RegClassGp);
|
||||
ASMJIT_ASSERT(aVd->getState() == kVarStateReg);
|
||||
ASMJIT_ASSERT(aVd->getRegIndex() != kInvalidReg);
|
||||
|
||||
ASMJIT_ASSERT(bVd->getClass() == kX86RegClassGp);
|
||||
ASMJIT_ASSERT(bVd->getState() == kVarStateReg);
|
||||
ASMJIT_ASSERT(bVd->getRegIndex() != kInvalidReg);
|
||||
|
||||
uint32_t aIndex = aVd->getRegIndex();
|
||||
uint32_t bIndex = bVd->getRegIndex();
|
||||
|
||||
emitSwapGp(aVd, bVd, aIndex, bIndex, "Swap");
|
||||
|
||||
aVd->setRegIndex(bIndex);
|
||||
bVd->setRegIndex(aIndex);
|
||||
|
||||
_x86State.getListByClass(kX86RegClassGp)[aIndex] = bVd;
|
||||
_x86State.getListByClass(kX86RegClassGp)[bIndex] = aVd;
|
||||
|
||||
uint32_t m = aVd->isModified() ^ bVd->isModified();
|
||||
_x86State._modified.xor_(kX86RegClassGp, (m << aIndex) | (m << bIndex));
|
||||
|
||||
ASMJIT_X86_CHECK_STATE
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Alloc / Spill]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Alloc.
|
||||
template<int C>
|
||||
ASMJIT_INLINE void alloc(VarData* vd, uint32_t regIndex) {
|
||||
ASMJIT_ASSERT(vd->getClass() == C);
|
||||
ASMJIT_ASSERT(regIndex != kInvalidReg);
|
||||
|
||||
uint32_t oldRegIndex = vd->getRegIndex();
|
||||
uint32_t oldState = vd->getState();
|
||||
uint32_t regMask = IntUtil::mask(regIndex);
|
||||
|
||||
ASMJIT_ASSERT(_x86State.getListByClass(C)[regIndex] == NULL || regIndex == oldRegIndex);
|
||||
|
||||
if (oldState != kVarStateReg) {
|
||||
if (oldState == kVarStateMem)
|
||||
emitLoad(vd, regIndex, "Alloc");
|
||||
vd->setModified(false);
|
||||
}
|
||||
else if (oldRegIndex != regIndex) {
|
||||
emitMove(vd, regIndex, oldRegIndex, "Alloc");
|
||||
|
||||
_x86State.getListByClass(C)[oldRegIndex] = NULL;
|
||||
regMask ^= IntUtil::mask(oldRegIndex);
|
||||
}
|
||||
else {
|
||||
ASMJIT_X86_CHECK_STATE
|
||||
return;
|
||||
}
|
||||
|
||||
vd->setState(kVarStateReg);
|
||||
vd->setRegIndex(regIndex);
|
||||
|
||||
_x86State.getListByClass(C)[regIndex] = vd;
|
||||
_x86State._occupied.xor_(C, regMask);
|
||||
_x86State._modified.xor_(C, regMask & -static_cast<int32_t>(vd->isModified()));
|
||||
|
||||
ASMJIT_X86_CHECK_STATE
|
||||
}
|
||||
|
||||
//! Spill.
|
||||
//!
|
||||
//! Spill variable/register, saves the content to the memory-home if modified.
|
||||
template<int C>
|
||||
ASMJIT_INLINE void spill(VarData* vd) {
|
||||
ASMJIT_ASSERT(vd->getClass() == C);
|
||||
|
||||
if (vd->getState() != kVarStateReg) {
|
||||
ASMJIT_X86_CHECK_STATE
|
||||
return;
|
||||
}
|
||||
|
||||
uint32_t regIndex = vd->getRegIndex();
|
||||
|
||||
ASMJIT_ASSERT(regIndex != kInvalidReg);
|
||||
ASMJIT_ASSERT(_x86State.getListByClass(C)[regIndex] == vd);
|
||||
|
||||
if (vd->isModified())
|
||||
emitSave(vd, regIndex, "Spill");
|
||||
detach<C>(vd, regIndex, kVarStateMem);
|
||||
|
||||
ASMJIT_X86_CHECK_STATE
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Modify]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
template<int C>
|
||||
ASMJIT_INLINE void modify(VarData* vd) {
|
||||
ASMJIT_ASSERT(vd->getClass() == C);
|
||||
|
||||
uint32_t regIndex = vd->getRegIndex();
|
||||
uint32_t regMask = IntUtil::mask(regIndex);
|
||||
|
||||
vd->setModified(true);
|
||||
_x86State._modified.or_(C, regMask);
|
||||
|
||||
ASMJIT_X86_CHECK_STATE
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Unuse]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Unuse.
|
||||
//!
|
||||
//! Unuse variable, it will be detached it if it's allocated then its state
|
||||
//! will be changed to kVarStateUnused.
|
||||
template<int C>
|
||||
ASMJIT_INLINE void unuse(VarData* vd, uint32_t vState = kVarStateUnused) {
|
||||
ASMJIT_ASSERT(vd->getClass() == C);
|
||||
ASMJIT_ASSERT(vState != kVarStateReg);
|
||||
|
||||
uint32_t regIndex = vd->getRegIndex();
|
||||
if (regIndex != kInvalidReg)
|
||||
detach<C>(vd, regIndex, vState);
|
||||
else
|
||||
vd->setState(vState);
|
||||
|
||||
ASMJIT_X86_CHECK_STATE
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [State]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get state as `X86VarState`.
|
||||
ASMJIT_INLINE X86VarState* getState() const {
|
||||
return const_cast<X86VarState*>(&_x86State);
|
||||
}
|
||||
|
||||
virtual void loadState(VarState* src);
|
||||
virtual VarState* saveState();
|
||||
|
||||
virtual void switchState(VarState* src);
|
||||
virtual void intersectStates(VarState* a, VarState* b);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Memory]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE X86Mem getVarMem(VarData* vd) {
|
||||
(void)getVarCell(vd);
|
||||
|
||||
X86Mem mem(_memSlot);
|
||||
mem.setBase(vd->getId());
|
||||
return mem;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Fetch]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
virtual Error fetch();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Annotate]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
virtual Error annotate();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Translate]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
virtual Error translate();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Schedule]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
virtual Error schedule();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Serialize]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
virtual Error serialize(Assembler* assembler, Node* start, Node* stop);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Count of X86/X64 registers.
|
||||
X86RegCount _regCount;
|
||||
//! X86/X64 stack-pointer (esp or rsp).
|
||||
X86GpReg _zsp;
|
||||
//! X86/X64 frame-pointer (ebp or rbp).
|
||||
X86GpReg _zbp;
|
||||
//! Temporary memory operand.
|
||||
X86Mem _memSlot;
|
||||
|
||||
//! X86/X64 specific compiler state, linked to `_state`.
|
||||
X86VarState _x86State;
|
||||
//! Clobbered registers (for the whole function).
|
||||
X86RegMask _clobberedRegs;
|
||||
|
||||
//! Memory cell where is stored address used to restore manually
|
||||
//! aligned stack.
|
||||
MemCell* _stackFrameCell;
|
||||
|
||||
//! Global allocable registers mask.
|
||||
uint32_t _gaRegs[kX86RegClassCount];
|
||||
|
||||
//! Function arguments base pointer (register).
|
||||
uint8_t _argBaseReg;
|
||||
//! Function variables base pointer (register).
|
||||
uint8_t _varBaseReg;
|
||||
//! Whether to emit comments.
|
||||
uint8_t _emitComments;
|
||||
|
||||
//! Function arguments base offset.
|
||||
int32_t _argBaseOffset;
|
||||
//! Function variables base offset.
|
||||
int32_t _varBaseOffset;
|
||||
|
||||
//! Function arguments displacement.
|
||||
int32_t _argActualDisp;
|
||||
//! Function variables displacement.
|
||||
int32_t _varActualDisp;
|
||||
|
||||
//! Temporary string builder used for logging.
|
||||
StringBuilderT<256> _stringBuilder;
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // !ASMJIT_DISABLE_COMPILER
|
||||
#endif // _ASMJIT_X86_X86CONTEXT_P_H
|
||||
+263
@@ -0,0 +1,263 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_X86_X86CPUINFO_H
|
||||
#define _ASMJIT_X86_X86CPUINFO_H
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../base/cpuinfo.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
// ============================================================================
|
||||
// [Forward Declarations]
|
||||
// ============================================================================
|
||||
|
||||
struct X86CpuInfo;
|
||||
|
||||
//! \addtogroup asmjit_x86_general
|
||||
//! \{
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::kX86CpuFeature]
|
||||
// ============================================================================
|
||||
|
||||
//! X86 CPU features.
|
||||
ASMJIT_ENUM(kX86CpuFeature) {
|
||||
//! Cpu has Not-Execute-Bit.
|
||||
kX86CpuFeatureNX = 0,
|
||||
//! Cpu has multithreading.
|
||||
kX86CpuFeatureMT,
|
||||
//! Cpu has RDTSC.
|
||||
kX86CpuFeatureRDTSC,
|
||||
//! Cpu has RDTSCP.
|
||||
kX86CpuFeatureRDTSCP,
|
||||
//! Cpu has CMOV.
|
||||
kX86CpuFeatureCMOV,
|
||||
//! Cpu has CMPXCHG8B.
|
||||
kX86CpuFeatureCMPXCHG8B,
|
||||
//! Cpu has CMPXCHG16B (X64).
|
||||
kX86CpuFeatureCMPXCHG16B,
|
||||
//! Cpu has CLFUSH.
|
||||
kX86CpuFeatureCLFLUSH,
|
||||
//! Cpu has CLFUSH (Optimized).
|
||||
kX86CpuFeatureCLFLUSHOpt,
|
||||
//! Cpu has PREFETCH.
|
||||
kX86CpuFeaturePREFETCH,
|
||||
//! Cpu has PREFETCHWT1.
|
||||
kX86CpuFeaturePREFETCHWT1,
|
||||
//! Cpu has LAHF/SAHF.
|
||||
kX86CpuFeatureLahfSahf,
|
||||
//! Cpu has FXSAVE/FXRSTOR.
|
||||
kX86CpuFeatureFXSR,
|
||||
//! Cpu has FXSAVE/FXRSTOR (Optimized).
|
||||
kX86CpuFeatureFXSROpt,
|
||||
//! Cpu has MMX.
|
||||
kX86CpuFeatureMMX,
|
||||
//! Cpu has extended MMX.
|
||||
kX86CpuFeatureMMX2,
|
||||
//! Cpu has 3dNow!
|
||||
kX86CpuFeature3DNOW,
|
||||
//! Cpu has enchanced 3dNow!
|
||||
kX86CpuFeature3DNOW2,
|
||||
//! Cpu has SSE.
|
||||
kX86CpuFeatureSSE,
|
||||
//! Cpu has SSE2.
|
||||
kX86CpuFeatureSSE2,
|
||||
//! Cpu has SSE3.
|
||||
kX86CpuFeatureSSE3,
|
||||
//! Cpu has SSSE3.
|
||||
kX86CpuFeatureSSSE3,
|
||||
//! Cpu has SSE4.A.
|
||||
kX86CpuFeatureSSE4A,
|
||||
//! Cpu has SSE4.1.
|
||||
kX86CpuFeatureSSE4_1,
|
||||
//! Cpu has SSE4.2.
|
||||
kX86CpuFeatureSSE4_2,
|
||||
//! Cpu has Misaligned SSE (MSSE).
|
||||
kX86CpuFeatureMSSE,
|
||||
//! Cpu has MONITOR and MWAIT.
|
||||
kX86CpuFeatureMONITOR,
|
||||
//! Cpu has MOVBE.
|
||||
kX86CpuFeatureMOVBE,
|
||||
//! Cpu has POPCNT.
|
||||
kX86CpuFeaturePOPCNT,
|
||||
//! Cpu has LZCNT.
|
||||
kX86CpuFeatureLZCNT,
|
||||
//! Cpu has AESNI.
|
||||
kX86CpuFeatureAESNI,
|
||||
//! Cpu has PCLMULQDQ.
|
||||
kX86CpuFeaturePCLMULQDQ,
|
||||
//! Cpu has RDRAND.
|
||||
kX86CpuFeatureRDRAND,
|
||||
//! Cpu has RDSEED.
|
||||
kX86CpuFeatureRDSEED,
|
||||
//! Cpu has SHA-1 and SHA-256.
|
||||
kX86CpuFeatureSHA,
|
||||
//! Cpu has XSAVE support - XSAVE/XRSTOR, XSETBV/XGETBV, and XCR0.
|
||||
kX86CpuFeatureXSave,
|
||||
//! OS has enabled XSAVE, you can call XGETBV to get value of XCR0.
|
||||
kX86CpuFeatureXSaveOS,
|
||||
//! Cpu has AVX.
|
||||
kX86CpuFeatureAVX,
|
||||
//! Cpu has AVX2.
|
||||
kX86CpuFeatureAVX2,
|
||||
//! Cpu has F16C.
|
||||
kX86CpuFeatureF16C,
|
||||
//! Cpu has FMA3.
|
||||
kX86CpuFeatureFMA3,
|
||||
//! Cpu has FMA4.
|
||||
kX86CpuFeatureFMA4,
|
||||
//! Cpu has XOP.
|
||||
kX86CpuFeatureXOP,
|
||||
//! Cpu has BMI.
|
||||
kX86CpuFeatureBMI,
|
||||
//! Cpu has BMI2.
|
||||
kX86CpuFeatureBMI2,
|
||||
//! Cpu has HLE.
|
||||
kX86CpuFeatureHLE,
|
||||
//! Cpu has RTM.
|
||||
kX86CpuFeatureRTM,
|
||||
//! Cpu has ADX.
|
||||
kX86CpuFeatureADX,
|
||||
//! Cpu has MPX (Memory Protection Extensions).
|
||||
kX86CpuFeatureMPX,
|
||||
//! Cpu has FSGSBASE.
|
||||
kX86CpuFeatureFSGSBase,
|
||||
//! Cpu has optimized REP MOVSB/STOSB.
|
||||
kX86CpuFeatureMOVSBSTOSBOpt,
|
||||
|
||||
//! Cpu has AVX-512F (Foundation).
|
||||
kX86CpuFeatureAVX512F,
|
||||
//! Cpu has AVX-512CD (Conflict Detection).
|
||||
kX86CpuFeatureAVX512CD,
|
||||
//! Cpu has AVX-512PF (Prefetch Instructions).
|
||||
kX86CpuFeatureAVX512PF,
|
||||
//! Cpu has AVX-512ER (Exponential and Reciprocal Instructions).
|
||||
kX86CpuFeatureAVX512ER,
|
||||
//! Cpu has AVX-512DQ (DWord/QWord).
|
||||
kX86CpuFeatureAVX512DQ,
|
||||
//! Cpu has AVX-512BW (Byte/Word).
|
||||
kX86CpuFeatureAVX512BW,
|
||||
//! Cpu has AVX VL (Vector Length Excensions).
|
||||
kX86CpuFeatureAVX512VL,
|
||||
|
||||
//! Count of X86/X64 Cpu features.
|
||||
kX86CpuFeatureCount
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::X86CpuId]
|
||||
// ============================================================================
|
||||
|
||||
//! X86/X64 CPUID output.
|
||||
union X86CpuId {
|
||||
//! EAX/EBX/ECX/EDX output.
|
||||
uint32_t i[4];
|
||||
|
||||
struct {
|
||||
//! EAX output.
|
||||
uint32_t eax;
|
||||
//! EBX output.
|
||||
uint32_t ebx;
|
||||
//! ECX output.
|
||||
uint32_t ecx;
|
||||
//! EDX output.
|
||||
uint32_t edx;
|
||||
};
|
||||
};
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::X86CpuUtil]
|
||||
// ============================================================================
|
||||
|
||||
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
|
||||
//! CPU utilities available only if the host processor is X86/X64.
|
||||
struct X86CpuUtil {
|
||||
//! Get the result of calling CPUID instruction to `out`.
|
||||
ASMJIT_API static void callCpuId(uint32_t inEax, uint32_t inEcx, X86CpuId* out);
|
||||
|
||||
//! Detect the Host CPU.
|
||||
ASMJIT_API static void detect(X86CpuInfo* cpuInfo);
|
||||
};
|
||||
#endif // ASMJIT_HOST_X86 || ASMJIT_HOST_X64
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::X86CpuInfo]
|
||||
// ============================================================================
|
||||
|
||||
struct X86CpuInfo : public CpuInfo {
|
||||
ASMJIT_NO_COPY(X86CpuInfo)
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
ASMJIT_INLINE X86CpuInfo(uint32_t size = sizeof(X86CpuInfo)) :
|
||||
CpuInfo(size) {}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Accessors]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Get processor type.
|
||||
ASMJIT_INLINE uint32_t getProcessorType() const {
|
||||
return _processorType;
|
||||
}
|
||||
|
||||
//! Get brand index.
|
||||
ASMJIT_INLINE uint32_t getBrandIndex() const {
|
||||
return _brandIndex;
|
||||
}
|
||||
|
||||
//! Get flush cache line size.
|
||||
ASMJIT_INLINE uint32_t getFlushCacheLineSize() const {
|
||||
return _flushCacheLineSize;
|
||||
}
|
||||
|
||||
//! Get maximum logical processors count.
|
||||
ASMJIT_INLINE uint32_t getMaxLogicalProcessors() const {
|
||||
return _maxLogicalProcessors;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Statics]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#if defined(ASMJIT_HOST_X86) || defined(ASMJIT_HOST_X64)
|
||||
//! Get global instance of `X86CpuInfo`.
|
||||
static ASMJIT_INLINE const X86CpuInfo* getHost() {
|
||||
return static_cast<const X86CpuInfo*>(CpuInfo::getHost());
|
||||
}
|
||||
#endif // ASMJIT_HOST_X86 || ASMJIT_HOST_X64
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Processor type.
|
||||
uint32_t _processorType;
|
||||
//! Brand index.
|
||||
uint32_t _brandIndex;
|
||||
//! Flush cache line size in bytes.
|
||||
uint32_t _flushCacheLineSize;
|
||||
//! Maximum number of addressable IDs for logical processors.
|
||||
uint32_t _maxLogicalProcessors;
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // _ASMJIT_X86_X86CPUINFO_H
|
||||
+2410
File diff suppressed because it is too large
Load Diff
+1974
File diff suppressed because it is too large
Load Diff
+63
@@ -0,0 +1,63 @@
|
||||
// [AsmJit]
|
||||
// Complete x86/x64 JIT and Remote Assembler for C++.
|
||||
//
|
||||
// [License]
|
||||
// Zlib - See LICENSE.md file in the package.
|
||||
|
||||
// [Guard]
|
||||
#ifndef _ASMJIT_X86_X86SCHEDULER_P_H
|
||||
#define _ASMJIT_X86_X86SCHEDULER_P_H
|
||||
|
||||
#include "../build.h"
|
||||
#if !defined(ASMJIT_DISABLE_COMPILER)
|
||||
|
||||
// [Dependencies - AsmJit]
|
||||
#include "../x86/x86compiler.h"
|
||||
#include "../x86/x86context_p.h"
|
||||
#include "../x86/x86cpuinfo.h"
|
||||
#include "../x86/x86inst.h"
|
||||
|
||||
// [Api-Begin]
|
||||
#include "../apibegin.h"
|
||||
|
||||
namespace asmjit {
|
||||
|
||||
// ============================================================================
|
||||
// [asmjit::X86Scheduler]
|
||||
// ============================================================================
|
||||
|
||||
//! \internal
|
||||
//!
|
||||
//! X86 scheduler.
|
||||
struct X86Scheduler {
|
||||
// --------------------------------------------------------------------------
|
||||
// [Construction / Destruction]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
X86Scheduler(X86Compiler* compiler, const X86CpuInfo* cpuInfo);
|
||||
~X86Scheduler();
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Run]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
Error run(Node* start, Node* stop);
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// [Members]
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
//! Attached compiler.
|
||||
X86Compiler* _compiler;
|
||||
//! CPU information used for scheduling.
|
||||
const X86CpuInfo* _cpuInfo;
|
||||
};
|
||||
|
||||
} // asmjit namespace
|
||||
|
||||
// [Api-End]
|
||||
#include "../apiend.h"
|
||||
|
||||
// [Guard]
|
||||
#endif // !ASMJIT_DISABLE_COMPILER
|
||||
#endif // _ASMJIT_X86_X86SCHEDULER_P_H
|
||||
Reference in New Issue
Block a user