mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 20:44:37 +03:00
Use ASMJIT_INLINE_NODEBUG to make debugging easier
Having 'inline' is fine, however, when debugging a class that has abstractions then sometimes to step over all of them can be very frustrating. This is solved by ASMJIT_INLINE_NODEBUG, which tells compiler that the body of a function doesn't have to be debuggable. This mostly applies to getters, setters, and wrappers around API functions. In addition - some assembler tests were split to make the compilation a little bit faster, especially when compiling with UBSAN.
This commit is contained in:
@@ -35,10 +35,10 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Gets whether the current ARM mode is THUMB (alternative to 32-bit ARM encoding).
|
||||
inline bool isInThumbMode() const noexcept { return _environment.isArchThumb(); }
|
||||
ASMJIT_INLINE_NODEBUG bool isInThumbMode() const noexcept { return _environment.isArchThumb(); }
|
||||
|
||||
//! Gets the current code alignment of the current mode (ARM vs THUMB).
|
||||
inline uint32_t codeAlignment() const noexcept { return isInThumbMode() ? 2 : 4; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t codeAlignment() const noexcept { return isInThumbMode() ? 2 : 4; }
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
// See asmjit.h or LICENSE.md for license and copyright information
|
||||
// SPDX-License-Identifier: Zlib
|
||||
|
||||
#ifndef ASMJIT_ARM_ARMCOMPILER_H_INCLUDED
|
||||
#define ASMJIT_ARM_ARMCOMPILER_H_INCLUDED
|
||||
#ifndef ASMJIT_ARM_A64COMPILER_H_INCLUDED
|
||||
#define ASMJIT_ARM_A64COMPILER_H_INCLUDED
|
||||
|
||||
#include "../core/api-config.h"
|
||||
#ifndef ASMJIT_NO_COMPILER
|
||||
@@ -39,14 +39,14 @@ public:
|
||||
|
||||
//! \cond INTERNAL
|
||||
template<typename RegT, typename Type>
|
||||
inline RegT _newRegInternal(const Type& type) {
|
||||
ASMJIT_INLINE_NODEBUG RegT _newRegInternal(const Type& type) {
|
||||
RegT reg(Globals::NoInit);
|
||||
_newReg(®, type, nullptr);
|
||||
return reg;
|
||||
}
|
||||
|
||||
template<typename RegT, typename Type, typename... Args>
|
||||
inline RegT _newRegInternal(const Type& type, const char* s, Args&&... args) {
|
||||
ASMJIT_INLINE_NODEBUG RegT _newRegInternal(const Type& type, const char* s, Args&&... args) {
|
||||
#ifndef ASMJIT_NO_LOGGING
|
||||
RegT reg(Globals::NoInit);
|
||||
if (sizeof...(Args) == 0)
|
||||
@@ -64,49 +64,49 @@ public:
|
||||
//! \endcond
|
||||
|
||||
template<typename RegT, typename... Args>
|
||||
inline RegT newSimilarReg(const RegT& ref, Args&&... args) {
|
||||
ASMJIT_INLINE_NODEBUG RegT newSimilarReg(const RegT& ref, Args&&... args) {
|
||||
return _newRegInternal<RegT>(ref, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
inline Reg newReg(TypeId typeId, Args&&... args) { return _newRegInternal<Reg>(typeId, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Reg newReg(TypeId typeId, Args&&... args) { return _newRegInternal<Reg>(typeId, std::forward<Args>(args)...); }
|
||||
|
||||
template<typename... Args>
|
||||
inline Gp newGp(TypeId typeId, Args&&... args) { return _newRegInternal<Gp>(typeId, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Gp newGp(TypeId typeId, Args&&... args) { return _newRegInternal<Gp>(typeId, std::forward<Args>(args)...); }
|
||||
|
||||
template<typename... Args>
|
||||
inline Vec newVec(TypeId typeId, Args&&... args) { return _newRegInternal<Vec>(typeId, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Vec newVec(TypeId typeId, Args&&... args) { return _newRegInternal<Vec>(typeId, std::forward<Args>(args)...); }
|
||||
|
||||
template<typename... Args>
|
||||
inline Gp newInt32(Args&&... args) { return _newRegInternal<Gp>(TypeId::kInt32, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Gp newInt32(Args&&... args) { return _newRegInternal<Gp>(TypeId::kInt32, std::forward<Args>(args)...); }
|
||||
template<typename... Args>
|
||||
inline Gp newUInt32(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt32, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Gp newUInt32(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt32, std::forward<Args>(args)...); }
|
||||
|
||||
template<typename... Args>
|
||||
inline Gp newInt64(Args&&... args) { return _newRegInternal<Gp>(TypeId::kInt64, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Gp newInt64(Args&&... args) { return _newRegInternal<Gp>(TypeId::kInt64, std::forward<Args>(args)...); }
|
||||
template<typename... Args>
|
||||
inline Gp newUInt64(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt64, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Gp newUInt64(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt64, std::forward<Args>(args)...); }
|
||||
|
||||
template<typename... Args>
|
||||
inline Gp newIntPtr(Args&&... args) { return _newRegInternal<Gp>(TypeId::kIntPtr, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Gp newIntPtr(Args&&... args) { return _newRegInternal<Gp>(TypeId::kIntPtr, std::forward<Args>(args)...); }
|
||||
template<typename... Args>
|
||||
inline Gp newUIntPtr(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Gp newUIntPtr(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); }
|
||||
|
||||
template<typename... Args>
|
||||
inline Gp newGpw(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt32, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Gp newGpw(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt32, std::forward<Args>(args)...); }
|
||||
template<typename... Args>
|
||||
inline Gp newGpx(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt64, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Gp newGpx(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUInt64, std::forward<Args>(args)...); }
|
||||
template<typename... Args>
|
||||
inline Gp newGpz(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Gp newGpz(Args&&... args) { return _newRegInternal<Gp>(TypeId::kUIntPtr, std::forward<Args>(args)...); }
|
||||
|
||||
template<typename... Args>
|
||||
inline Vec newVecS(Args&&... args) { return _newRegInternal<Vec>(TypeId::kFloat32, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Vec newVecS(Args&&... args) { return _newRegInternal<Vec>(TypeId::kFloat32, std::forward<Args>(args)...); }
|
||||
|
||||
template<typename... Args>
|
||||
inline Vec newVecD(Args&&... args) { return _newRegInternal<Vec>(TypeId::kFloat64, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Vec newVecD(Args&&... args) { return _newRegInternal<Vec>(TypeId::kFloat64, std::forward<Args>(args)...); }
|
||||
|
||||
template<typename... Args>
|
||||
inline Vec newVecQ(Args&&... args) { return _newRegInternal<Vec>(TypeId::kUInt8x16, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG Vec newVecQ(Args&&... args) { return _newRegInternal<Vec>(TypeId::kUInt8x16, std::forward<Args>(args)...); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -114,7 +114,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a new memory chunk allocated on the current function's stack.
|
||||
inline Mem newStack(uint32_t size, uint32_t alignment, const char* name = nullptr) {
|
||||
ASMJIT_INLINE_NODEBUG Mem newStack(uint32_t size, uint32_t alignment, const char* name = nullptr) {
|
||||
Mem m(Globals::NoInit);
|
||||
_newStack(&m, size, alignment, name);
|
||||
return m;
|
||||
@@ -126,38 +126,38 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Put data to a constant-pool and get a memory reference to it.
|
||||
inline Mem newConst(ConstPoolScope scope, const void* data, size_t size) {
|
||||
ASMJIT_INLINE_NODEBUG Mem newConst(ConstPoolScope scope, const void* data, size_t size) {
|
||||
Mem m(Globals::NoInit);
|
||||
_newConst(&m, scope, data, size);
|
||||
return m;
|
||||
}
|
||||
|
||||
//! Put a BYTE `val` to a constant-pool (8 bits).
|
||||
inline Mem newByteConst(ConstPoolScope scope, uint8_t val) noexcept { return newConst(scope, &val, 1); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newByteConst(ConstPoolScope scope, uint8_t val) noexcept { return newConst(scope, &val, 1); }
|
||||
//! Put a HWORD `val` to a constant-pool (16 bits).
|
||||
inline Mem newHWordConst(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newHWordConst(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
|
||||
//! Put a WORD `val` to a constant-pool (32 bits).
|
||||
inline Mem newWordConst(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newWordConst(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
|
||||
//! Put a DWORD `val` to a constant-pool (64 bits).
|
||||
inline Mem newDWordConst(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newDWordConst(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
|
||||
|
||||
//! Put a WORD `val` to a constant-pool.
|
||||
inline Mem newInt16Const(ConstPoolScope scope, int16_t val) noexcept { return newConst(scope, &val, 2); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newInt16Const(ConstPoolScope scope, int16_t val) noexcept { return newConst(scope, &val, 2); }
|
||||
//! Put a WORD `val` to a constant-pool.
|
||||
inline Mem newUInt16Const(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newUInt16Const(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
|
||||
//! Put a DWORD `val` to a constant-pool.
|
||||
inline Mem newInt32Const(ConstPoolScope scope, int32_t val) noexcept { return newConst(scope, &val, 4); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newInt32Const(ConstPoolScope scope, int32_t val) noexcept { return newConst(scope, &val, 4); }
|
||||
//! Put a DWORD `val` to a constant-pool.
|
||||
inline Mem newUInt32Const(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newUInt32Const(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
|
||||
//! Put a QWORD `val` to a constant-pool.
|
||||
inline Mem newInt64Const(ConstPoolScope scope, int64_t val) noexcept { return newConst(scope, &val, 8); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newInt64Const(ConstPoolScope scope, int64_t val) noexcept { return newConst(scope, &val, 8); }
|
||||
//! Put a QWORD `val` to a constant-pool.
|
||||
inline Mem newUInt64Const(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newUInt64Const(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
|
||||
|
||||
//! Put a SP-FP `val` to a constant-pool.
|
||||
inline Mem newFloatConst(ConstPoolScope scope, float val) noexcept { return newConst(scope, &val, 4); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newFloatConst(ConstPoolScope scope, float val) noexcept { return newConst(scope, &val, 4); }
|
||||
//! Put a DP-FP `val` to a constant-pool.
|
||||
inline Mem newDoubleConst(ConstPoolScope scope, double val) noexcept { return newConst(scope, &val, 8); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newDoubleConst(ConstPoolScope scope, double val) noexcept { return newConst(scope, &val, 8); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -165,7 +165,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Force the compiler to not follow the conditional or unconditional jump.
|
||||
inline Compiler& unfollow() noexcept { _instOptions |= InstOptions::kUnfollow; return *this; }
|
||||
ASMJIT_INLINE_NODEBUG Compiler& unfollow() noexcept { _instOptions |= InstOptions::kUnfollow; return *this; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -177,7 +177,7 @@ public:
|
||||
//! \note At the moment this instruction is only useful to load a stack allocated address into a GP register
|
||||
//! for further use. It makes very little sense to use it for anything else. The semantics of this instruction
|
||||
//! is the same as X86 `LEA` (load effective address) instruction.
|
||||
inline Error loadAddressOf(const Gp& o0, const Mem& o1) { return _emitter()->_emitI(Inst::kIdAdr, o0, o1); }
|
||||
ASMJIT_INLINE_NODEBUG Error loadAddressOf(const Gp& o0, const Mem& o1) { return _emitter()->_emitI(Inst::kIdAdr, o0, o1); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -185,7 +185,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Invoke a function call without `target` type enforcement.
|
||||
inline Error invoke_(InvokeNode** out, const Operand_& target, const FuncSignature& signature) {
|
||||
ASMJIT_INLINE_NODEBUG Error invoke_(InvokeNode** out, const Operand_& target, const FuncSignature& signature) {
|
||||
return addInvokeNode(out, Inst::kIdBlr, target, signature);
|
||||
}
|
||||
|
||||
@@ -194,22 +194,22 @@ public:
|
||||
//! Creates a new \ref InvokeNode, initializes all the necessary members to match the given function `signature`,
|
||||
//! adds the node to the compiler, and stores its pointer to `out`. The operation is atomic, if anything fails
|
||||
//! nullptr is stored in `out` and error code is returned.
|
||||
inline Error invoke(InvokeNode** out, const Gp& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Gp& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
//! \overload
|
||||
inline Error invoke(InvokeNode** out, const Mem& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Mem& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
//! \overload
|
||||
inline Error invoke(InvokeNode** out, const Label& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Label& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
//! \overload
|
||||
inline Error invoke(InvokeNode** out, const Imm& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Imm& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
//! \overload
|
||||
inline Error invoke(InvokeNode** out, uint64_t target, const FuncSignature& signature) { return invoke_(out, Imm(int64_t(target)), signature); }
|
||||
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, uint64_t target, const FuncSignature& signature) { return invoke_(out, Imm(int64_t(target)), signature); }
|
||||
|
||||
//! Return.
|
||||
inline Error ret() { return addRet(Operand(), Operand()); }
|
||||
ASMJIT_INLINE_NODEBUG Error ret() { return addRet(Operand(), Operand()); }
|
||||
//! \overload
|
||||
inline Error ret(const BaseReg& o0) { return addRet(o0, Operand()); }
|
||||
ASMJIT_INLINE_NODEBUG Error ret(const BaseReg& o0) { return addRet(o0, Operand()); }
|
||||
//! \overload
|
||||
inline Error ret(const BaseReg& o0, const BaseReg& o1) { return addRet(o0, o1); }
|
||||
ASMJIT_INLINE_NODEBUG Error ret(const BaseReg& o0, const BaseReg& o1) { return addRet(o0, o1); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -219,7 +219,7 @@ public:
|
||||
using EmitterExplicitT<Compiler>::br;
|
||||
|
||||
//! Adds a jump to the given `target` with the provided jump `annotation`.
|
||||
inline Error br(const BaseReg& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdBr, target, annotation); }
|
||||
ASMJIT_INLINE_NODEBUG Error br(const BaseReg& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdBr, target, annotation); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -244,4 +244,4 @@ public:
|
||||
ASMJIT_END_SUB_NAMESPACE
|
||||
|
||||
#endif // !ASMJIT_NO_COMPILER
|
||||
#endif // ASMJIT_ARM_ARMCOMPILER_H_INCLUDED
|
||||
#endif // ASMJIT_ARM_A64COMPILER_H_INCLUDED
|
||||
|
||||
@@ -21,7 +21,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(a64)
|
||||
|
||||
class EmitHelper : public BaseEmitHelper {
|
||||
public:
|
||||
inline explicit EmitHelper(BaseEmitter* emitter = nullptr) noexcept
|
||||
ASMJIT_INLINE_NODEBUG explicit EmitHelper(BaseEmitter* emitter = nullptr) noexcept
|
||||
: BaseEmitHelper(emitter) {}
|
||||
|
||||
Error emitRegMove(
|
||||
|
||||
@@ -797,14 +797,14 @@ struct Inst {
|
||||
};
|
||||
|
||||
//! Tests whether the `instId` is defined (counts also Inst::kIdNone, which must be zero).
|
||||
static inline bool isDefinedId(InstId instId) noexcept { return (instId & uint32_t(InstIdParts::kRealId)) < _kIdCount; }
|
||||
static ASMJIT_INLINE_NODEBUG bool isDefinedId(InstId instId) noexcept { return (instId & uint32_t(InstIdParts::kRealId)) < _kIdCount; }
|
||||
};
|
||||
|
||||
namespace Predicate {
|
||||
|
||||
//! Address translate options (AT).
|
||||
namespace AT {
|
||||
static inline constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept {
|
||||
return (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0);
|
||||
}
|
||||
|
||||
@@ -862,7 +862,7 @@ namespace DB {
|
||||
|
||||
//! Data cache maintenance options.
|
||||
namespace DC {
|
||||
static inline constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept {
|
||||
return (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0);
|
||||
}
|
||||
|
||||
@@ -901,7 +901,7 @@ namespace DC {
|
||||
|
||||
//! Instruction cache maintenance options.
|
||||
namespace IC {
|
||||
static inline constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept {
|
||||
return (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0);
|
||||
}
|
||||
|
||||
@@ -955,7 +955,7 @@ namespace PSB {
|
||||
}
|
||||
|
||||
namespace TLBI {
|
||||
static inline constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr uint32_t encode(uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept {
|
||||
return (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0);
|
||||
}
|
||||
|
||||
@@ -1054,7 +1054,7 @@ namespace TSB {
|
||||
//! Processor state access through MSR.
|
||||
namespace PState {
|
||||
//! Encodes a pstate from `op0` and `op1`.
|
||||
static inline constexpr uint32_t encode(uint32_t op0, uint32_t op1) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr uint32_t encode(uint32_t op0, uint32_t op1) noexcept {
|
||||
return (op0 << 3) | (op1 << 0);
|
||||
}
|
||||
|
||||
@@ -1083,17 +1083,17 @@ namespace SysReg {
|
||||
};
|
||||
|
||||
//! Encodes a system register from `op0`, `op1`, `cRn`, `cRm`, and `op2` fields.
|
||||
static inline constexpr uint32_t encode(uint32_t op0, uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr uint32_t encode(uint32_t op0, uint32_t op1, uint32_t cRn, uint32_t cRm, uint32_t op2) noexcept {
|
||||
return (op0 << 14) | (op1 << 11) | (cRn << 7) | (cRm << 3) | (op2 << 0);
|
||||
}
|
||||
|
||||
//! Encodes a system register from `fields`.
|
||||
static inline constexpr uint32_t encode(const Fields& fields) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr uint32_t encode(const Fields& fields) noexcept {
|
||||
return encode(fields.op0, fields.op1, fields.cRn, fields.cRm, fields.op2);
|
||||
}
|
||||
|
||||
//! Decodes a system register to \ref Fields.
|
||||
static inline constexpr Fields decode(uint32_t id) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Fields decode(uint32_t id) noexcept {
|
||||
return Fields {
|
||||
uint8_t((id >> 14) & 0x3u),
|
||||
uint8_t((id >> 11) & 0x7u),
|
||||
|
||||
@@ -47,10 +47,10 @@ struct InstInfo {
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline uint32_t rwInfoIndex() const noexcept { return _rwInfoIndex; }
|
||||
inline uint32_t flags() const noexcept { return _flags; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t rwInfoIndex() const noexcept { return _rwInfoIndex; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t flags() const noexcept { return _flags; }
|
||||
|
||||
inline bool hasFlag(uint32_t flag) const { return (_flags & flag) != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(uint32_t flag) const { return (_flags & flag) != 0; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
@@ -262,7 +262,7 @@ namespace EncodingData {
|
||||
|
||||
#define M_OPCODE(field, bits) \
|
||||
uint32_t _##field : bits; \
|
||||
inline constexpr uint32_t field() const noexcept { return uint32_t(_##field) << (32 - bits); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr uint32_t field() const noexcept { return uint32_t(_##field) << (32 - bits); }
|
||||
|
||||
struct BaseOp {
|
||||
uint32_t opcode;
|
||||
|
||||
@@ -45,10 +45,10 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the compiler casted to `arm::Compiler`.
|
||||
inline Compiler* cc() const noexcept { return static_cast<Compiler*>(_cb); }
|
||||
ASMJIT_INLINE_NODEBUG Compiler* cc() const noexcept { return static_cast<Compiler*>(_cb); }
|
||||
|
||||
//! Returns emit helper.
|
||||
inline EmitHelper* emitHelper() noexcept { return &_emitHelper; }
|
||||
ASMJIT_INLINE_NODEBUG EmitHelper* emitHelper() noexcept { return &_emitHelper; }
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
@@ -57,67 +57,67 @@ public:
|
||||
ASMJIT_DEFINE_ABSTRACT_REG(Reg, BaseReg)
|
||||
|
||||
//! Gets whether the register is a `R|W` register (32-bit).
|
||||
inline constexpr bool isGpW() const noexcept { return baseSignature() == RegTraits<RegType::kARM_GpW>::kSignature; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isGpW() const noexcept { return baseSignature() == RegTraits<RegType::kARM_GpW>::kSignature; }
|
||||
//! Gets whether the register is an `X` register (64-bit).
|
||||
inline constexpr bool isGpX() const noexcept { return baseSignature() == RegTraits<RegType::kARM_GpX>::kSignature; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isGpX() const noexcept { return baseSignature() == RegTraits<RegType::kARM_GpX>::kSignature; }
|
||||
//! Gets whether the register is a VEC-B register (8-bit).
|
||||
inline constexpr bool isVecB() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecB>::kSignature; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecB() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecB>::kSignature; }
|
||||
//! Gets whether the register is a VEC-H register (16-bit).
|
||||
inline constexpr bool isVecH() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecH>::kSignature; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecH() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecH>::kSignature; }
|
||||
//! Gets whether the register is a VEC-S register (32-bit).
|
||||
inline constexpr bool isVecS() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecS>::kSignature; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecS() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecS>::kSignature; }
|
||||
//! Gets whether the register is a VEC-D register (64-bit).
|
||||
inline constexpr bool isVecD() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecD>::kSignature; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecD() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecD>::kSignature; }
|
||||
//! Gets whether the register is a VEC-Q register (128-bit).
|
||||
inline constexpr bool isVecQ() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecV>::kSignature; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecQ() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecV>::kSignature; }
|
||||
|
||||
//! Gets whether the register is either VEC-D (64-bit) or VEC-Q (128-bit).
|
||||
inline constexpr bool isVecDOrQ() const noexcept { return uint32_t(type()) - uint32_t(RegType::kARM_VecD) <= 1u; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecDOrQ() const noexcept { return uint32_t(type()) - uint32_t(RegType::kARM_VecD) <= 1u; }
|
||||
|
||||
//! Gets whether the register is a VEC-V register (128-bit).
|
||||
inline constexpr bool isVecV() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecV>::kSignature; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecV() const noexcept { return baseSignature() == RegTraits<RegType::kARM_VecV>::kSignature; }
|
||||
|
||||
template<RegType kRegType>
|
||||
inline void setRegT(uint32_t id) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void setRegT(uint32_t id) noexcept {
|
||||
setSignature(RegTraits<kRegType>::kSignature);
|
||||
setId(id);
|
||||
}
|
||||
|
||||
inline void setTypeAndId(RegType type, uint32_t id) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void setTypeAndId(RegType type, uint32_t id) noexcept {
|
||||
setSignature(signatureOf(type));
|
||||
setId(id);
|
||||
}
|
||||
|
||||
static inline RegGroup groupOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToGroup(type); }
|
||||
static inline TypeId typeIdOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToTypeId(type); }
|
||||
static inline OperandSignature signatureOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToSignature(type); }
|
||||
static ASMJIT_INLINE_NODEBUG RegGroup groupOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToGroup(type); }
|
||||
static ASMJIT_INLINE_NODEBUG TypeId typeIdOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToTypeId(type); }
|
||||
static ASMJIT_INLINE_NODEBUG OperandSignature signatureOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kAArch64).regTypeToSignature(type); }
|
||||
|
||||
template<RegType kRegType>
|
||||
static inline RegGroup groupOfT() noexcept { return RegTraits<kRegType>::kGroup; }
|
||||
static ASMJIT_INLINE_NODEBUG RegGroup groupOfT() noexcept { return RegTraits<kRegType>::kGroup; }
|
||||
|
||||
template<RegType kRegType>
|
||||
static inline TypeId typeIdOfT() noexcept { return RegTraits<kRegType>::kTypeId; }
|
||||
static ASMJIT_INLINE_NODEBUG TypeId typeIdOfT() noexcept { return RegTraits<kRegType>::kTypeId; }
|
||||
|
||||
template<RegType kRegType>
|
||||
static inline OperandSignature signatureOfT() noexcept { return RegTraits<kRegType>::kSignature; }
|
||||
static ASMJIT_INLINE_NODEBUG OperandSignature signatureOfT() noexcept { return RegTraits<kRegType>::kSignature; }
|
||||
|
||||
static inline bool isGpW(const Operand_& op) noexcept { return op.as<Reg>().isGpW(); }
|
||||
static inline bool isGpX(const Operand_& op) noexcept { return op.as<Reg>().isGpX(); }
|
||||
static inline bool isVecB(const Operand_& op) noexcept { return op.as<Reg>().isVecB(); }
|
||||
static inline bool isVecH(const Operand_& op) noexcept { return op.as<Reg>().isVecH(); }
|
||||
static inline bool isVecS(const Operand_& op) noexcept { return op.as<Reg>().isVecS(); }
|
||||
static inline bool isVecD(const Operand_& op) noexcept { return op.as<Reg>().isVecD(); }
|
||||
static inline bool isVecQ(const Operand_& op) noexcept { return op.as<Reg>().isVecQ(); }
|
||||
static inline bool isVecV(const Operand_& op) noexcept { return op.as<Reg>().isVecV(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpW(const Operand_& op) noexcept { return op.as<Reg>().isGpW(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpX(const Operand_& op) noexcept { return op.as<Reg>().isGpX(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isVecB(const Operand_& op) noexcept { return op.as<Reg>().isVecB(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isVecH(const Operand_& op) noexcept { return op.as<Reg>().isVecH(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isVecS(const Operand_& op) noexcept { return op.as<Reg>().isVecS(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isVecD(const Operand_& op) noexcept { return op.as<Reg>().isVecD(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isVecQ(const Operand_& op) noexcept { return op.as<Reg>().isVecQ(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isVecV(const Operand_& op) noexcept { return op.as<Reg>().isVecV(); }
|
||||
|
||||
static inline bool isGpW(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isGpW(op)) & unsigned(op.id() == id)); }
|
||||
static inline bool isGpX(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isGpX(op)) & unsigned(op.id() == id)); }
|
||||
static inline bool isVecB(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecB(op)) & unsigned(op.id() == id)); }
|
||||
static inline bool isVecH(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecH(op)) & unsigned(op.id() == id)); }
|
||||
static inline bool isVecS(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecS(op)) & unsigned(op.id() == id)); }
|
||||
static inline bool isVecD(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecD(op)) & unsigned(op.id() == id)); }
|
||||
static inline bool isVecQ(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecQ(op)) & unsigned(op.id() == id)); }
|
||||
static inline bool isVecV(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecV(op)) & unsigned(op.id() == id)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpW(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isGpW(op)) & unsigned(op.id() == id)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpX(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isGpX(op)) & unsigned(op.id() == id)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isVecB(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecB(op)) & unsigned(op.id() == id)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isVecH(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecH(op)) & unsigned(op.id() == id)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isVecS(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecS(op)) & unsigned(op.id() == id)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isVecD(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecD(op)) & unsigned(op.id() == id)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isVecQ(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecQ(op)) & unsigned(op.id() == id)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isVecV(const Operand_& op, uint32_t id) noexcept { return bool(unsigned(isVecV(op)) & unsigned(op.id() == id)); }
|
||||
};
|
||||
|
||||
//! General purpose register (ARM).
|
||||
@@ -146,13 +146,13 @@ public:
|
||||
kIdZr = 63
|
||||
};
|
||||
|
||||
inline constexpr bool isZR() const noexcept { return id() == kIdZr; }
|
||||
inline constexpr bool isSP() const noexcept { return id() == kIdSp; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isZR() const noexcept { return id() == kIdZr; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isSP() const noexcept { return id() == kIdSp; }
|
||||
|
||||
//! Cast this register to a 32-bit R|W.
|
||||
inline GpW w() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG GpW w() const noexcept;
|
||||
//! Cast this register to a 64-bit X.
|
||||
inline GpX x() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG GpX x() const noexcept;
|
||||
};
|
||||
|
||||
//! Vector register (ARM).
|
||||
@@ -216,92 +216,92 @@ public:
|
||||
//! \endcond
|
||||
|
||||
//! Returns whether the register has associated an element type.
|
||||
inline constexpr bool hasElementType() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool hasElementType() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask>(); }
|
||||
//! Returns whether the register has element index (it's an element index access).
|
||||
inline constexpr bool hasElementIndex() const noexcept { return _signature.hasField<kSignatureRegElementFlagMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool hasElementIndex() const noexcept { return _signature.hasField<kSignatureRegElementFlagMask>(); }
|
||||
//! Returns whether the reggister has element type or element index (or both).
|
||||
inline constexpr bool hasElementTypeOrIndex() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask | kSignatureRegElementFlagMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool hasElementTypeOrIndex() const noexcept { return _signature.hasField<kSignatureRegElementTypeMask | kSignatureRegElementFlagMask>(); }
|
||||
|
||||
//! Returns element type of the register.
|
||||
inline constexpr uint32_t elementType() const noexcept { return _signature.getField<kSignatureRegElementTypeMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr uint32_t elementType() const noexcept { return _signature.getField<kSignatureRegElementTypeMask>(); }
|
||||
//! Sets element type of the register to `elementType`.
|
||||
inline void setElementType(uint32_t elementType) noexcept { _signature.setField<kSignatureRegElementTypeMask>(elementType); }
|
||||
ASMJIT_INLINE_NODEBUG void setElementType(uint32_t elementType) noexcept { _signature.setField<kSignatureRegElementTypeMask>(elementType); }
|
||||
//! Resets element type to none.
|
||||
inline void resetElementType() noexcept { _signature.setField<kSignatureRegElementTypeMask>(0); }
|
||||
ASMJIT_INLINE_NODEBUG void resetElementType() noexcept { _signature.setField<kSignatureRegElementTypeMask>(0); }
|
||||
|
||||
//! Returns element index of the register.
|
||||
inline constexpr uint32_t elementIndex() const noexcept { return _signature.getField<kSignatureRegElementIndexMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr uint32_t elementIndex() const noexcept { return _signature.getField<kSignatureRegElementIndexMask>(); }
|
||||
//! Sets element index of the register to `elementType`.
|
||||
inline void setElementIndex(uint32_t elementIndex) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void setElementIndex(uint32_t elementIndex) noexcept {
|
||||
_signature |= kSignatureRegElementFlagMask;
|
||||
_signature.setField<kSignatureRegElementIndexMask>(elementIndex);
|
||||
}
|
||||
//! Resets element index of the register.
|
||||
inline void resetElementIndex() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void resetElementIndex() noexcept {
|
||||
_signature &= ~(kSignatureRegElementFlagMask | kSignatureRegElementIndexMask);
|
||||
}
|
||||
|
||||
inline constexpr bool isVecB8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementB); }
|
||||
inline constexpr bool isVecH4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementH); }
|
||||
inline constexpr bool isVecS2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementS); }
|
||||
inline constexpr bool isVecD1() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecB8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementB); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecH4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementH); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecS2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature | kSignatureElementS); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecD1() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecD>::kSignature); }
|
||||
|
||||
inline constexpr bool isVecB16() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB); }
|
||||
inline constexpr bool isVecH8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH); }
|
||||
inline constexpr bool isVecS4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementS); }
|
||||
inline constexpr bool isVecD2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementD); }
|
||||
inline constexpr bool isVecB4x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB4); }
|
||||
inline constexpr bool isVecH2x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH2); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecB16() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecH8() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecS4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementS); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecD2() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementD); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecB4x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementB4); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isVecH2x4() const noexcept { return _signature.subset(kBaseSignatureMask | kSignatureRegElementTypeMask) == (RegTraits<RegType::kARM_VecV>::kSignature | kSignatureElementH2); }
|
||||
|
||||
//! Creates a cloned register with element access.
|
||||
inline Vec at(uint32_t elementIndex) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Vec at(uint32_t elementIndex) const noexcept {
|
||||
return Vec((signature() & ~kSignatureRegElementIndexMask) | (elementIndex << kSignatureRegElementIndexShift) | kSignatureRegElementFlagMask, id());
|
||||
}
|
||||
|
||||
//! Cast this register to an 8-bit B register (AArch64 only).
|
||||
inline VecB b() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecB b() const noexcept;
|
||||
//! Cast this register to a 16-bit H register (AArch64 only).
|
||||
inline VecH h() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecH h() const noexcept;
|
||||
//! Cast this register to a 32-bit S register.
|
||||
inline VecS s() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecS s() const noexcept;
|
||||
//! Cast this register to a 64-bit D register.
|
||||
inline VecD d() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecD d() const noexcept;
|
||||
//! Cast this register to a 128-bit Q register.
|
||||
inline VecV q() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecV q() const noexcept;
|
||||
//! Cast this register to a 128-bit V register.
|
||||
inline VecV v() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecV v() const noexcept;
|
||||
|
||||
//! Cast this register to a 128-bit V.B[elementIndex] register.
|
||||
inline VecV b(uint32_t elementIndex) const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecV b(uint32_t elementIndex) const noexcept;
|
||||
//! Cast this register to a 128-bit V.H[elementIndex] register.
|
||||
inline VecV h(uint32_t elementIndex) const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecV h(uint32_t elementIndex) const noexcept;
|
||||
//! Cast this register to a 128-bit V.S[elementIndex] register.
|
||||
inline VecV s(uint32_t elementIndex) const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecV s(uint32_t elementIndex) const noexcept;
|
||||
//! Cast this register to a 128-bit V.D[elementIndex] register.
|
||||
inline VecV d(uint32_t elementIndex) const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecV d(uint32_t elementIndex) const noexcept;
|
||||
//! Cast this register to a 128-bit V.H2[elementIndex] register.
|
||||
inline VecV h2(uint32_t elementIndex) const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecV h2(uint32_t elementIndex) const noexcept;
|
||||
//! Cast this register to a 128-bit V.B4[elementIndex] register.
|
||||
inline VecV b4(uint32_t elementIndex) const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecV b4(uint32_t elementIndex) const noexcept;
|
||||
|
||||
//! Cast this register to V.8B.
|
||||
inline VecD b8() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecD b8() const noexcept;
|
||||
//! Cast this register to V.16B.
|
||||
inline VecV b16() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecV b16() const noexcept;
|
||||
//! Cast this register to V.2H.
|
||||
inline VecS h2() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecS h2() const noexcept;
|
||||
//! Cast this register to V.4H.
|
||||
inline VecD h4() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecD h4() const noexcept;
|
||||
//! Cast this register to V.8H.
|
||||
inline VecV h8() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecV h8() const noexcept;
|
||||
//! Cast this register to V.2S.
|
||||
inline VecD s2() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecD s2() const noexcept;
|
||||
//! Cast this register to V.4S.
|
||||
inline VecV s4() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecV s4() const noexcept;
|
||||
//! Cast this register to V.2D.
|
||||
inline VecV d2() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG VecV d2() const noexcept;
|
||||
|
||||
static inline constexpr OperandSignature _makeElementAccessSignature(uint32_t elementType, uint32_t elementIndex) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr OperandSignature _makeElementAccessSignature(uint32_t elementType, uint32_t elementIndex) noexcept {
|
||||
return OperandSignature{
|
||||
uint32_t(RegTraits<RegType::kARM_VecV>::kSignature) |
|
||||
uint32_t(kSignatureRegElementFlagMask) |
|
||||
@@ -326,46 +326,46 @@ class VecD : public Vec { ASMJIT_DEFINE_FINAL_REG(VecD, Vec, RegTraits<RegType::
|
||||
//! 128-bit vector register (Q or V).
|
||||
class VecV : public Vec { ASMJIT_DEFINE_FINAL_REG(VecV, Vec, RegTraits<RegType::kARM_VecV>) };
|
||||
|
||||
inline GpW Gp::w() const noexcept { return GpW(id()); }
|
||||
inline GpX Gp::x() const noexcept { return GpX(id()); }
|
||||
ASMJIT_INLINE_NODEBUG GpW Gp::w() const noexcept { return GpW(id()); }
|
||||
ASMJIT_INLINE_NODEBUG GpX Gp::x() const noexcept { return GpX(id()); }
|
||||
|
||||
inline VecB Vec::b() const noexcept { return VecB(id()); }
|
||||
inline VecH Vec::h() const noexcept { return VecH(id()); }
|
||||
inline VecS Vec::s() const noexcept { return VecS(id()); }
|
||||
inline VecD Vec::d() const noexcept { return VecD(id()); }
|
||||
inline VecV Vec::q() const noexcept { return VecV(id()); }
|
||||
inline VecV Vec::v() const noexcept { return VecV(id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecB Vec::b() const noexcept { return VecB(id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecH Vec::h() const noexcept { return VecH(id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecS Vec::s() const noexcept { return VecS(id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecD Vec::d() const noexcept { return VecD(id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecV Vec::q() const noexcept { return VecV(id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecV Vec::v() const noexcept { return VecV(id()); }
|
||||
|
||||
inline VecV Vec::b(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB, elementIndex), id()); }
|
||||
inline VecV Vec::h(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH, elementIndex), id()); }
|
||||
inline VecV Vec::s(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeS, elementIndex), id()); }
|
||||
inline VecV Vec::d(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeD, elementIndex), id()); }
|
||||
inline VecV Vec::h2(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH2, elementIndex), id()); }
|
||||
inline VecV Vec::b4(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB4, elementIndex), id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecV Vec::b(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB, elementIndex), id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecV Vec::h(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH, elementIndex), id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecV Vec::s(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeS, elementIndex), id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecV Vec::d(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeD, elementIndex), id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecV Vec::h2(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeH2, elementIndex), id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecV Vec::b4(uint32_t elementIndex) const noexcept { return VecV(_makeElementAccessSignature(kElementTypeB4, elementIndex), id()); }
|
||||
|
||||
inline VecD Vec::b8() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementB}, id()); }
|
||||
inline VecS Vec::h2() const noexcept { return VecS(OperandSignature{VecS::kSignature | kSignatureElementH}, id()); }
|
||||
inline VecD Vec::h4() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementH}, id()); }
|
||||
inline VecD Vec::s2() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementS}, id()); }
|
||||
inline VecV Vec::b16() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementB}, id()); }
|
||||
inline VecV Vec::h8() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementH}, id()); }
|
||||
inline VecV Vec::s4() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementS}, id()); }
|
||||
inline VecV Vec::d2() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementD}, id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecD Vec::b8() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementB}, id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecS Vec::h2() const noexcept { return VecS(OperandSignature{VecS::kSignature | kSignatureElementH}, id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecD Vec::h4() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementH}, id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecD Vec::s2() const noexcept { return VecD(OperandSignature{VecD::kSignature | kSignatureElementS}, id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecV Vec::b16() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementB}, id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecV Vec::h8() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementH}, id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecV Vec::s4() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementS}, id()); }
|
||||
ASMJIT_INLINE_NODEBUG VecV Vec::d2() const noexcept { return VecV(OperandSignature{VecV::kSignature | kSignatureElementD}, id()); }
|
||||
|
||||
#ifndef _DOXYGEN
|
||||
namespace regs {
|
||||
#endif
|
||||
|
||||
//! Creates a 32-bit W register operand (ARM/AArch64).
|
||||
static inline constexpr GpW w(uint32_t id) noexcept { return GpW(id); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr GpW w(uint32_t id) noexcept { return GpW(id); }
|
||||
//! Creates a 64-bit X register operand (AArch64).
|
||||
static inline constexpr GpX x(uint32_t id) noexcept { return GpX(id); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr GpX x(uint32_t id) noexcept { return GpX(id); }
|
||||
//! Creates a 32-bit S register operand (ARM/AArch64).
|
||||
static inline constexpr VecS s(uint32_t id) noexcept { return VecS(id); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr VecS s(uint32_t id) noexcept { return VecS(id); }
|
||||
//! Creates a 64-bit D register operand (ARM/AArch64).
|
||||
static inline constexpr VecD d(uint32_t id) noexcept { return VecD(id); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr VecD d(uint32_t id) noexcept { return VecD(id); }
|
||||
//! Creates a 1282-bit V register operand (ARM/AArch64).
|
||||
static inline constexpr VecV v(uint32_t id) noexcept { return VecV(id); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr VecV v(uint32_t id) noexcept { return VecV(id); }
|
||||
|
||||
#ifndef _DOXYGEN
|
||||
} // {regs}
|
||||
@@ -406,35 +406,35 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Construct a default `Mem` operand, that points to [0].
|
||||
inline constexpr Mem() noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem() noexcept
|
||||
: BaseMem() {}
|
||||
|
||||
inline constexpr Mem(const Mem& other) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem(const Mem& other) noexcept
|
||||
: BaseMem(other) {}
|
||||
|
||||
inline explicit Mem(Globals::NoInit_) noexcept
|
||||
ASMJIT_INLINE_NODEBUG explicit Mem(Globals::NoInit_) noexcept
|
||||
: BaseMem(Globals::NoInit) {}
|
||||
|
||||
inline constexpr Mem(const Signature& signature, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem(const Signature& signature, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept
|
||||
: BaseMem(signature, baseId, indexId, offset) {}
|
||||
|
||||
inline constexpr explicit Mem(const Label& base, int32_t off = 0, Signature signature = Signature{0}) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr explicit Mem(const Label& base, int32_t off = 0, Signature signature = Signature{0}) noexcept
|
||||
: BaseMem(Signature::fromOpType(OperandType::kMem) |
|
||||
Signature::fromMemBaseType(RegType::kLabelTag) |
|
||||
signature, base.id(), 0, off) {}
|
||||
|
||||
inline constexpr explicit Mem(const BaseReg& base, int32_t off = 0, Signature signature = Signature{0}) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr explicit Mem(const BaseReg& base, int32_t off = 0, Signature signature = Signature{0}) noexcept
|
||||
: BaseMem(Signature::fromOpType(OperandType::kMem) |
|
||||
Signature::fromMemBaseType(base.type()) |
|
||||
signature, base.id(), 0, off) {}
|
||||
|
||||
inline constexpr Mem(const BaseReg& base, const BaseReg& index, Signature signature = Signature{0}) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem(const BaseReg& base, const BaseReg& index, Signature signature = Signature{0}) noexcept
|
||||
: BaseMem(Signature::fromOpType(OperandType::kMem) |
|
||||
Signature::fromMemBaseType(base.type()) |
|
||||
Signature::fromMemIndexType(index.type()) |
|
||||
signature, base.id(), index.id(), 0) {}
|
||||
|
||||
inline constexpr Mem(const BaseReg& base, const BaseReg& index, const Shift& shift, Signature signature = Signature{0}) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem(const BaseReg& base, const BaseReg& index, const Shift& shift, Signature signature = Signature{0}) noexcept
|
||||
: BaseMem(Signature::fromOpType(OperandType::kMem) |
|
||||
Signature::fromMemBaseType(base.type()) |
|
||||
Signature::fromMemIndexType(index.type()) |
|
||||
@@ -442,7 +442,7 @@ public:
|
||||
Signature::fromValue<kSignatureMemShiftValueMask>(shift.value()) |
|
||||
signature, base.id(), index.id(), 0) {}
|
||||
|
||||
inline constexpr Mem(uint64_t base, Signature signature = Signature{0}) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem(uint64_t base, Signature signature = Signature{0}) noexcept
|
||||
: BaseMem(Signature::fromOpType(OperandType::kMem) |
|
||||
signature, uint32_t(base >> 32), 0, int32_t(uint32_t(base & 0xFFFFFFFFu))) {}
|
||||
|
||||
@@ -451,7 +451,7 @@ public:
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
inline Mem& operator=(const Mem& other) noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG Mem& operator=(const Mem& other) noexcept = default;
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -459,24 +459,24 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Clones the memory operand.
|
||||
inline constexpr Mem clone() const noexcept { return Mem(*this); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem clone() const noexcept { return Mem(*this); }
|
||||
|
||||
//! Gets new memory operand adjusted by `off`.
|
||||
inline Mem cloneAdjusted(int64_t off) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Mem cloneAdjusted(int64_t off) const noexcept {
|
||||
Mem result(*this);
|
||||
result.addOffset(off);
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Clones the memory operand and makes it pre-index.
|
||||
inline Mem pre() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Mem pre() const noexcept {
|
||||
Mem result(*this);
|
||||
result.setPredicate(kOffsetPreIndex);
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Clones the memory operand, applies a given offset `off` and makes it pre-index.
|
||||
inline Mem pre(int64_t off) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Mem pre(int64_t off) const noexcept {
|
||||
Mem result(*this);
|
||||
result.setPredicate(kOffsetPreIndex);
|
||||
result.addOffset(off);
|
||||
@@ -484,14 +484,14 @@ public:
|
||||
}
|
||||
|
||||
//! Clones the memory operand and makes it post-index.
|
||||
inline Mem post() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Mem post() const noexcept {
|
||||
Mem result(*this);
|
||||
result.setPredicate(kOffsetPostIndex);
|
||||
return result;
|
||||
}
|
||||
|
||||
//! Clones the memory operand, applies a given offset `off` and makes it post-index.
|
||||
inline Mem post(int64_t off) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Mem post(int64_t off) const noexcept {
|
||||
Mem result(*this);
|
||||
result.setPredicate(kOffsetPostIndex);
|
||||
result.addOffset(off);
|
||||
@@ -506,16 +506,16 @@ public:
|
||||
//! Converts memory `baseType` and `baseId` to `arm::Reg` instance.
|
||||
//!
|
||||
//! The memory must have a valid base register otherwise the result will be wrong.
|
||||
inline Reg baseReg() const noexcept { return Reg::fromTypeAndId(baseType(), baseId()); }
|
||||
ASMJIT_INLINE_NODEBUG Reg baseReg() const noexcept { return Reg::fromTypeAndId(baseType(), baseId()); }
|
||||
|
||||
//! Converts memory `indexType` and `indexId` to `arm::Reg` instance.
|
||||
//!
|
||||
//! The memory must have a valid index register otherwise the result will be wrong.
|
||||
inline Reg indexReg() const noexcept { return Reg::fromTypeAndId(indexType(), indexId()); }
|
||||
ASMJIT_INLINE_NODEBUG Reg indexReg() const noexcept { return Reg::fromTypeAndId(indexType(), indexId()); }
|
||||
|
||||
using BaseMem::setIndex;
|
||||
|
||||
inline void setIndex(const BaseReg& index, uint32_t shift) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void setIndex(const BaseReg& index, uint32_t shift) noexcept {
|
||||
setIndex(index);
|
||||
setShift(shift);
|
||||
}
|
||||
@@ -526,77 +526,77 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Gets whether the memory operand has shift (aka scale) constant.
|
||||
inline constexpr bool hasShift() const noexcept { return _signature.hasField<kSignatureMemShiftValueMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool hasShift() const noexcept { return _signature.hasField<kSignatureMemShiftValueMask>(); }
|
||||
//! Gets the memory operand's shift (aka scale) constant.
|
||||
inline constexpr uint32_t shift() const noexcept { return _signature.getField<kSignatureMemShiftValueMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr uint32_t shift() const noexcept { return _signature.getField<kSignatureMemShiftValueMask>(); }
|
||||
//! Sets the memory operand's shift (aka scale) constant.
|
||||
inline void setShift(uint32_t shift) noexcept { _signature.setField<kSignatureMemShiftValueMask>(shift); }
|
||||
ASMJIT_INLINE_NODEBUG void setShift(uint32_t shift) noexcept { _signature.setField<kSignatureMemShiftValueMask>(shift); }
|
||||
//! Resets the memory operand's shift (aka scale) constant to zero.
|
||||
inline void resetShift() noexcept { _signature.setField<kSignatureMemShiftValueMask>(0); }
|
||||
ASMJIT_INLINE_NODEBUG void resetShift() noexcept { _signature.setField<kSignatureMemShiftValueMask>(0); }
|
||||
|
||||
//! Gets memory predicate (shift mode or offset mode), see \ref ShiftOp and \ref OffsetMode.
|
||||
inline constexpr uint32_t predicate() const noexcept { return _signature.getField<kSignatureMemPredicateMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr uint32_t predicate() const noexcept { return _signature.getField<kSignatureMemPredicateMask>(); }
|
||||
//! Sets memory predicate to `predicate`, see `Mem::ShiftOp`.
|
||||
inline void setPredicate(uint32_t predicate) noexcept { _signature.setField<kSignatureMemPredicateMask>(predicate); }
|
||||
ASMJIT_INLINE_NODEBUG void setPredicate(uint32_t predicate) noexcept { _signature.setField<kSignatureMemPredicateMask>(predicate); }
|
||||
//! Resets shift mode to LSL (default).
|
||||
inline void resetPredicate() noexcept { _signature.setField<kSignatureMemPredicateMask>(0); }
|
||||
ASMJIT_INLINE_NODEBUG void resetPredicate() noexcept { _signature.setField<kSignatureMemPredicateMask>(0); }
|
||||
|
||||
inline constexpr bool isFixedOffset() const noexcept { return predicate() < kOffsetPreIndex; }
|
||||
inline constexpr bool isPreOrPost() const noexcept { return predicate() >= kOffsetPreIndex; }
|
||||
inline constexpr bool isPreIndex() const noexcept { return predicate() == kOffsetPreIndex; }
|
||||
inline constexpr bool isPostIndex() const noexcept { return predicate() == kOffsetPostIndex; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isFixedOffset() const noexcept { return predicate() < kOffsetPreIndex; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isPreOrPost() const noexcept { return predicate() >= kOffsetPreIndex; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isPreIndex() const noexcept { return predicate() == kOffsetPreIndex; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isPostIndex() const noexcept { return predicate() == kOffsetPostIndex; }
|
||||
|
||||
inline void resetToFixedOffset() noexcept { resetPredicate(); }
|
||||
inline void makePreIndex() noexcept { setPredicate(kOffsetPreIndex); }
|
||||
inline void makePostIndex() noexcept { setPredicate(kOffsetPostIndex); }
|
||||
ASMJIT_INLINE_NODEBUG void resetToFixedOffset() noexcept { resetPredicate(); }
|
||||
ASMJIT_INLINE_NODEBUG void makePreIndex() noexcept { setPredicate(kOffsetPreIndex); }
|
||||
ASMJIT_INLINE_NODEBUG void makePostIndex() noexcept { setPredicate(kOffsetPostIndex); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! Creates `[base, offset]` memory operand (offset mode).
|
||||
static inline constexpr Mem ptr(const Gp& base, int32_t offset = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, int32_t offset = 0) noexcept {
|
||||
return Mem(base, offset);
|
||||
}
|
||||
|
||||
//! Creates `[base, offset]!` memory operand (pre-index mode).
|
||||
static inline constexpr Mem ptr_pre(const Gp& base, int32_t offset = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_pre(const Gp& base, int32_t offset = 0) noexcept {
|
||||
return Mem(base, offset, OperandSignature::fromValue<Mem::kSignatureMemPredicateMask>(Mem::kOffsetPreIndex));
|
||||
}
|
||||
|
||||
//! Creates `[base], offset` memory operand (post-index mode).
|
||||
static inline constexpr Mem ptr_post(const Gp& base, int32_t offset = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_post(const Gp& base, int32_t offset = 0) noexcept {
|
||||
return Mem(base, offset, OperandSignature::fromValue<Mem::kSignatureMemPredicateMask>(Mem::kOffsetPostIndex));
|
||||
}
|
||||
|
||||
//! Creates `[base, index]` memory operand.
|
||||
static inline constexpr Mem ptr(const Gp& base, const Gp& index) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, const Gp& index) noexcept {
|
||||
return Mem(base, index);
|
||||
}
|
||||
|
||||
//! Creates `[base, index]!` memory operand (pre-index mode).
|
||||
static inline constexpr Mem ptr_pre(const Gp& base, const Gp& index) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_pre(const Gp& base, const Gp& index) noexcept {
|
||||
return Mem(base, index, OperandSignature::fromValue<Mem::kSignatureMemPredicateMask>(Mem::kOffsetPreIndex));
|
||||
}
|
||||
|
||||
//! Creates `[base], index` memory operand (post-index mode).
|
||||
static inline constexpr Mem ptr_post(const Gp& base, const Gp& index) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_post(const Gp& base, const Gp& index) noexcept {
|
||||
return Mem(base, index, OperandSignature::fromValue<Mem::kSignatureMemPredicateMask>(Mem::kOffsetPostIndex));
|
||||
}
|
||||
|
||||
//! Creates `[base, index, SHIFT_OP #shift]` memory operand.
|
||||
static inline constexpr Mem ptr(const Gp& base, const Gp& index, const Shift& shift) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, const Gp& index, const Shift& shift) noexcept {
|
||||
return Mem(base, index, shift);
|
||||
}
|
||||
|
||||
//! Creates `[base, offset]` memory operand.
|
||||
static inline constexpr Mem ptr(const Label& base, int32_t offset = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Label& base, int32_t offset = 0) noexcept {
|
||||
return Mem(base, offset);
|
||||
}
|
||||
|
||||
// TODO: [ARM] PC + offset address.
|
||||
#if 0
|
||||
//! Creates `[PC + offset]` (relative) memory operand.
|
||||
static inline constexpr Mem ptr(const PC& pc, int32_t offset = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const PC& pc, int32_t offset = 0) noexcept {
|
||||
return Mem(pc, offset);
|
||||
}
|
||||
#endif
|
||||
@@ -607,7 +607,7 @@ static inline constexpr Mem ptr(const PC& pc, int32_t offset = 0) noexcept {
|
||||
//! Absolute memory operands can only be used if it's known that the PC relative offset is encodable and that it
|
||||
//! would be within the limits. Absolute address is also often output from disassemblers, so AsmJit supports it to
|
||||
//! make it possible to assemble such output back.
|
||||
static inline constexpr Mem ptr(uint64_t base) noexcept { return Mem(base); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(uint64_t base) noexcept { return Mem(base); }
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ static bool encodeLogicalImm(uint64_t imm, uint32_t width, LogicalImm* out) noex
|
||||
//! width of the operation, and must be either 32 or 64. This function can be used to test whether an immediate
|
||||
//! value can be used with AND, ANDS, BIC, BICS, EON, EOR, ORN, and ORR instruction.
|
||||
ASMJIT_MAYBE_UNUSED
|
||||
static ASMJIT_FORCE_INLINE bool isLogicalImm(uint64_t imm, uint32_t width) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isLogicalImm(uint64_t imm, uint32_t width) noexcept {
|
||||
LogicalImm dummy;
|
||||
return encodeLogicalImm(imm, width, &dummy);
|
||||
}
|
||||
@@ -98,13 +98,13 @@ static ASMJIT_FORCE_INLINE bool isLogicalImm(uint64_t imm, uint32_t width) noexc
|
||||
//! 0x00 or 0xFF. Some ARM instructions accept immediates that form a byte-mask and this function can be used to
|
||||
//! verify that the immediate is encodable before using the value.
|
||||
template<typename T>
|
||||
static ASMJIT_FORCE_INLINE bool isByteMaskImm8(const T& imm) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isByteMaskImm8(const T& imm) noexcept {
|
||||
constexpr T kMask = T(0x0101010101010101 & Support::allOnes<T>());
|
||||
return imm == (imm & kMask) * T(255);
|
||||
}
|
||||
|
||||
// [.......A|B.......|.......C|D.......|.......E|F.......|.......G|H.......]
|
||||
static ASMJIT_FORCE_INLINE uint32_t encodeImm64ByteMaskToImm8(uint64_t imm) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG uint32_t encodeImm64ByteMaskToImm8(uint64_t imm) noexcept {
|
||||
return uint32_t(((imm >> (7 - 0)) & 0b00000011) | // [.......G|H.......]
|
||||
((imm >> (23 - 2)) & 0b00001100) | // [.......E|F.......]
|
||||
((imm >> (39 - 4)) & 0b00110000) | // [.......C|D.......]
|
||||
@@ -134,7 +134,7 @@ static ASMJIT_FORCE_INLINE bool isFPImm8Generic(T val) noexcept {
|
||||
//! ```
|
||||
//! [aBbbcdef|gh000000]
|
||||
//! ```
|
||||
static ASMJIT_FORCE_INLINE bool isFP16Imm8(uint32_t val) noexcept { return isFPImm8Generic<uint32_t, 3, 6, 6>(val); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isFP16Imm8(uint32_t val) noexcept { return isFPImm8Generic<uint32_t, 3, 6, 6>(val); }
|
||||
|
||||
//! Returns true if the given single precision floating point `val` can be encoded as ARM IMM8 value, which represents
|
||||
//! a limited set of floating point immediate values, which can be used with FMOV instruction.
|
||||
@@ -144,9 +144,9 @@ static ASMJIT_FORCE_INLINE bool isFP16Imm8(uint32_t val) noexcept { return isFPI
|
||||
//! ```
|
||||
//! [aBbbbbbc|defgh000|00000000|00000000]
|
||||
//! ```
|
||||
static ASMJIT_FORCE_INLINE bool isFP32Imm8(uint32_t val) noexcept { return isFPImm8Generic<uint32_t, 6, 6, 19>(val); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isFP32Imm8(uint32_t val) noexcept { return isFPImm8Generic<uint32_t, 6, 6, 19>(val); }
|
||||
//! \overload
|
||||
static ASMJIT_FORCE_INLINE bool isFP32Imm8(float val) noexcept { return isFP32Imm8(Support::bitCast<uint32_t>(val)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isFP32Imm8(float val) noexcept { return isFP32Imm8(Support::bitCast<uint32_t>(val)); }
|
||||
|
||||
//! Returns true if the given double precision floating point `val` can be encoded as ARM IMM8 value, which represents
|
||||
//! a limited set of floating point immediate values, which can be used with FMOV instruction.
|
||||
@@ -156,13 +156,13 @@ static ASMJIT_FORCE_INLINE bool isFP32Imm8(float val) noexcept { return isFP32Im
|
||||
//! ```
|
||||
//! [aBbbbbbb|bbcdefgh|00000000|00000000|00000000|00000000|00000000|00000000]
|
||||
//! ```
|
||||
static ASMJIT_FORCE_INLINE bool isFP64Imm8(uint64_t val) noexcept { return isFPImm8Generic<uint64_t, 9, 6, 48>(val); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isFP64Imm8(uint64_t val) noexcept { return isFPImm8Generic<uint64_t, 9, 6, 48>(val); }
|
||||
//! \overload
|
||||
static ASMJIT_FORCE_INLINE bool isFP64Imm8(double val) noexcept { return isFP64Imm8(Support::bitCast<uint64_t>(val)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isFP64Imm8(double val) noexcept { return isFP64Imm8(Support::bitCast<uint64_t>(val)); }
|
||||
|
||||
//! \cond
|
||||
template<typename T, uint32_t kNumBBits, uint32_t kNumCDEFGHBits, uint32_t kNumZeroBits>
|
||||
static ASMJIT_FORCE_INLINE uint32_t encodeFPToImm8Generic(T val) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG uint32_t encodeFPToImm8Generic(T val) noexcept {
|
||||
uint32_t bits = uint32_t(val >> kNumZeroBits);
|
||||
return ((bits >> (kNumBBits + kNumCDEFGHBits - 7)) & 0x80u) | (bits & 0x7F);
|
||||
}
|
||||
@@ -172,9 +172,9 @@ static ASMJIT_FORCE_INLINE uint32_t encodeFPToImm8Generic(T val) noexcept {
|
||||
//!
|
||||
//! \note This function expects that `isFP64Imm8(val) == true` so it doesn't perform any checks of the value and just
|
||||
//! rearranges some bits into Imm8 order.
|
||||
static ASMJIT_FORCE_INLINE uint32_t encodeFP64ToImm8(uint64_t val) noexcept { return encodeFPToImm8Generic<uint64_t, 9, 6, 48>(val); }
|
||||
static ASMJIT_INLINE_NODEBUG uint32_t encodeFP64ToImm8(uint64_t val) noexcept { return encodeFPToImm8Generic<uint64_t, 9, 6, 48>(val); }
|
||||
//! \overload
|
||||
static ASMJIT_FORCE_INLINE uint32_t encodeFP64ToImm8(double val) noexcept { return encodeFP64ToImm8(Support::bitCast<uint64_t>(val)); }
|
||||
static ASMJIT_INLINE_NODEBUG uint32_t encodeFP64ToImm8(double val) noexcept { return encodeFP64ToImm8(Support::bitCast<uint64_t>(val)); }
|
||||
|
||||
} // {Utils}
|
||||
|
||||
|
||||
@@ -317,6 +317,15 @@ namespace asmjit {
|
||||
#define ASMJIT_FORCE_INLINE inline
|
||||
#endif
|
||||
|
||||
|
||||
#if defined(__clang__)
|
||||
#define ASMJIT_INLINE_NODEBUG inline __attribute__((__always_inline__, __nodebug__))
|
||||
#elif defined(__GNUC__)
|
||||
#define ASMJIT_INLINE_NODEBUG inline __attribute__((__always_inline__, __artificial__))
|
||||
#else
|
||||
#define ASMJIT_INLINE_NODEBUG inline
|
||||
#endif
|
||||
|
||||
#if defined(__GNUC__)
|
||||
#define ASMJIT_NOINLINE __attribute__((__noinline__))
|
||||
#define ASMJIT_NORETURN __attribute__((__noreturn__))
|
||||
@@ -549,34 +558,34 @@ namespace asmjit {
|
||||
#define ASMJIT_DEFINE_ENUM_FLAGS(T)
|
||||
#else
|
||||
#define ASMJIT_DEFINE_ENUM_FLAGS(T) \
|
||||
static ASMJIT_FORCE_INLINE constexpr T operator~(T a) noexcept { \
|
||||
static ASMJIT_INLINE_NODEBUG constexpr T operator~(T a) noexcept { \
|
||||
return T(~(std::underlying_type<T>::type)(a)); \
|
||||
} \
|
||||
\
|
||||
static ASMJIT_FORCE_INLINE constexpr T operator|(T a, T b) noexcept { \
|
||||
static ASMJIT_INLINE_NODEBUG constexpr T operator|(T a, T b) noexcept { \
|
||||
return T((std::underlying_type<T>::type)(a) | \
|
||||
(std::underlying_type<T>::type)(b)); \
|
||||
} \
|
||||
static ASMJIT_FORCE_INLINE constexpr T operator&(T a, T b) noexcept { \
|
||||
static ASMJIT_INLINE_NODEBUG constexpr T operator&(T a, T b) noexcept { \
|
||||
return T((std::underlying_type<T>::type)(a) & \
|
||||
(std::underlying_type<T>::type)(b)); \
|
||||
} \
|
||||
static ASMJIT_FORCE_INLINE constexpr T operator^(T a, T b) noexcept { \
|
||||
static ASMJIT_INLINE_NODEBUG constexpr T operator^(T a, T b) noexcept { \
|
||||
return T((std::underlying_type<T>::type)(a) ^ \
|
||||
(std::underlying_type<T>::type)(b)); \
|
||||
} \
|
||||
\
|
||||
static ASMJIT_FORCE_INLINE T& operator|=(T& a, T b) noexcept { \
|
||||
static ASMJIT_INLINE_NODEBUG T& operator|=(T& a, T b) noexcept { \
|
||||
a = T((std::underlying_type<T>::type)(a) | \
|
||||
(std::underlying_type<T>::type)(b)); \
|
||||
return a; \
|
||||
} \
|
||||
static ASMJIT_FORCE_INLINE T& operator&=(T& a, T b) noexcept { \
|
||||
static ASMJIT_INLINE_NODEBUG T& operator&=(T& a, T b) noexcept { \
|
||||
a = T((std::underlying_type<T>::type)(a) & \
|
||||
(std::underlying_type<T>::type)(b)); \
|
||||
return a; \
|
||||
} \
|
||||
static ASMJIT_FORCE_INLINE T& operator^=(T& a, T b) noexcept { \
|
||||
static ASMJIT_INLINE_NODEBUG T& operator^=(T& a, T b) noexcept { \
|
||||
a = T((std::underlying_type<T>::type)(a) ^ \
|
||||
(std::underlying_type<T>::type)(b)); \
|
||||
return a; \
|
||||
@@ -590,16 +599,16 @@ namespace asmjit {
|
||||
#define ASMJIT_DEFINE_ENUM_COMPARE(T)
|
||||
#else
|
||||
#define ASMJIT_DEFINE_ENUM_COMPARE(T) \
|
||||
static ASMJIT_FORCE_INLINE bool operator<(T a, T b) noexcept { \
|
||||
static ASMJIT_INLINE_NODEBUG bool operator<(T a, T b) noexcept { \
|
||||
return (std::underlying_type<T>::type)(a) < (std::underlying_type<T>::type)(b); \
|
||||
} \
|
||||
static ASMJIT_FORCE_INLINE bool operator<=(T a, T b) noexcept { \
|
||||
static ASMJIT_INLINE_NODEBUG bool operator<=(T a, T b) noexcept { \
|
||||
return (std::underlying_type<T>::type)(a) <= (std::underlying_type<T>::type)(b); \
|
||||
} \
|
||||
static ASMJIT_FORCE_INLINE bool operator>(T a, T b) noexcept { \
|
||||
static ASMJIT_INLINE_NODEBUG bool operator>(T a, T b) noexcept { \
|
||||
return (std::underlying_type<T>::type)(a) > (std::underlying_type<T>::type)(b); \
|
||||
} \
|
||||
static ASMJIT_FORCE_INLINE bool operator>=(T a, T b) noexcept { \
|
||||
static ASMJIT_INLINE_NODEBUG bool operator>=(T a, T b) noexcept { \
|
||||
return (std::underlying_type<T>::type)(a) >= (std::underlying_type<T>::type)(b); \
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -73,7 +73,7 @@ enum class CondCode : uint8_t {
|
||||
};
|
||||
|
||||
//! Negates a condition code.
|
||||
static inline constexpr CondCode negateCond(CondCode cond) noexcept { return CondCode(uint8_t(cond) ^ uint8_t(1)); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr CondCode negateCond(CondCode cond) noexcept { return CondCode(uint8_t(cond) ^ uint8_t(1)); }
|
||||
|
||||
//! Data type that can be encoded with the instruction (AArch32 only).
|
||||
enum class DataType : uint32_t {
|
||||
@@ -172,57 +172,57 @@ public:
|
||||
uint32_t _value;
|
||||
|
||||
//! Default constructed Shift is not initialized.
|
||||
inline Shift() noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG Shift() noexcept = default;
|
||||
|
||||
//! Copy constructor (default)
|
||||
constexpr Shift(const Shift& other) noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG constexpr Shift(const Shift& other) noexcept = default;
|
||||
|
||||
//! Constructs Shift from operation `op` and shift `value`.
|
||||
constexpr Shift(ShiftOp op, uint32_t value) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Shift(ShiftOp op, uint32_t value) noexcept
|
||||
: _op(op),
|
||||
_value(value) {}
|
||||
|
||||
//! Returns the shift operation.
|
||||
constexpr ShiftOp op() const noexcept { return _op; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr ShiftOp op() const noexcept { return _op; }
|
||||
//! Sets shift operation to `op`.
|
||||
inline void setOp(ShiftOp op) noexcept { _op = op; }
|
||||
ASMJIT_INLINE_NODEBUG void setOp(ShiftOp op) noexcept { _op = op; }
|
||||
|
||||
//! Returns the shift smount.
|
||||
constexpr uint32_t value() const noexcept { return _value; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr uint32_t value() const noexcept { return _value; }
|
||||
//! Sets shift amount to `value`.
|
||||
inline void setValue(uint32_t value) noexcept { _value = value; }
|
||||
ASMJIT_INLINE_NODEBUG void setValue(uint32_t value) noexcept { _value = value; }
|
||||
};
|
||||
|
||||
//! Constructs a `LSL #value` shift (logical shift left).
|
||||
static constexpr Shift lsl(uint32_t value) noexcept { return Shift(ShiftOp::kLSL, value); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Shift lsl(uint32_t value) noexcept { return Shift(ShiftOp::kLSL, value); }
|
||||
//! Constructs a `LSR #value` shift (logical shift right).
|
||||
static constexpr Shift lsr(uint32_t value) noexcept { return Shift(ShiftOp::kLSR, value); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Shift lsr(uint32_t value) noexcept { return Shift(ShiftOp::kLSR, value); }
|
||||
//! Constructs a `ASR #value` shift (arithmetic shift right).
|
||||
static constexpr Shift asr(uint32_t value) noexcept { return Shift(ShiftOp::kASR, value); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Shift asr(uint32_t value) noexcept { return Shift(ShiftOp::kASR, value); }
|
||||
//! Constructs a `ROR #value` shift (rotate right).
|
||||
static constexpr Shift ror(uint32_t value) noexcept { return Shift(ShiftOp::kROR, value); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Shift ror(uint32_t value) noexcept { return Shift(ShiftOp::kROR, value); }
|
||||
//! Constructs a `RRX` shift (rotate with carry by 1).
|
||||
static constexpr Shift rrx() noexcept { return Shift(ShiftOp::kRRX, 0); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Shift rrx() noexcept { return Shift(ShiftOp::kRRX, 0); }
|
||||
//! Constructs a `MSL #value` shift (logical shift left filling ones).
|
||||
static constexpr Shift msl(uint32_t value) noexcept { return Shift(ShiftOp::kMSL, value); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Shift msl(uint32_t value) noexcept { return Shift(ShiftOp::kMSL, value); }
|
||||
|
||||
//! Constructs a `UXTB #value` extend and shift (unsigned byte extend).
|
||||
static constexpr Shift uxtb(uint32_t value) noexcept { return Shift(ShiftOp::kUXTB, value); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Shift uxtb(uint32_t value) noexcept { return Shift(ShiftOp::kUXTB, value); }
|
||||
//! Constructs a `UXTH #value` extend and shift (unsigned hword extend).
|
||||
static constexpr Shift uxth(uint32_t value) noexcept { return Shift(ShiftOp::kUXTH, value); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Shift uxth(uint32_t value) noexcept { return Shift(ShiftOp::kUXTH, value); }
|
||||
//! Constructs a `UXTW #value` extend and shift (unsigned word extend).
|
||||
static constexpr Shift uxtw(uint32_t value) noexcept { return Shift(ShiftOp::kUXTW, value); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Shift uxtw(uint32_t value) noexcept { return Shift(ShiftOp::kUXTW, value); }
|
||||
//! Constructs a `UXTX #value` extend and shift (unsigned dword extend).
|
||||
static constexpr Shift uxtx(uint32_t value) noexcept { return Shift(ShiftOp::kUXTX, value); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Shift uxtx(uint32_t value) noexcept { return Shift(ShiftOp::kUXTX, value); }
|
||||
|
||||
//! Constructs a `SXTB #value` extend and shift (signed byte extend).
|
||||
static constexpr Shift sxtb(uint32_t value) noexcept { return Shift(ShiftOp::kSXTB, value); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Shift sxtb(uint32_t value) noexcept { return Shift(ShiftOp::kSXTB, value); }
|
||||
//! Constructs a `SXTH #value` extend and shift (signed hword extend).
|
||||
static constexpr Shift sxth(uint32_t value) noexcept { return Shift(ShiftOp::kSXTH, value); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Shift sxth(uint32_t value) noexcept { return Shift(ShiftOp::kSXTH, value); }
|
||||
//! Constructs a `SXTW #value` extend and shift (signed word extend).
|
||||
static constexpr Shift sxtw(uint32_t value) noexcept { return Shift(ShiftOp::kSXTW, value); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Shift sxtw(uint32_t value) noexcept { return Shift(ShiftOp::kSXTW, value); }
|
||||
//! Constructs a `SXTX #value` extend and shift (signed dword extend).
|
||||
static constexpr Shift sxtx(uint32_t value) noexcept { return Shift(ShiftOp::kSXTX, value); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Shift sxtx(uint32_t value) noexcept { return Shift(ShiftOp::kSXTX, value); }
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
@@ -202,50 +202,50 @@ struct ArchTraits {
|
||||
//! \{
|
||||
|
||||
//! Returns stack pointer register id.
|
||||
inline uint32_t spRegId() const noexcept { return _spRegId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t spRegId() const noexcept { return _spRegId; }
|
||||
//! Returns stack frame register id.
|
||||
inline uint32_t fpRegId() const noexcept { return _fpRegId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t fpRegId() const noexcept { return _fpRegId; }
|
||||
//! Returns link register id, if the architecture provides it.
|
||||
inline uint32_t linkRegId() const noexcept { return _linkRegId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t linkRegId() const noexcept { return _linkRegId; }
|
||||
//! Returns instruction pointer register id, if the architecture provides it.
|
||||
inline uint32_t ipRegId() const noexcept { return _ipRegId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t ipRegId() const noexcept { return _ipRegId; }
|
||||
|
||||
//! Returns a hardware stack alignment requirement.
|
||||
//!
|
||||
//! \note This is a hardware constraint. Architectures that don't constrain it would return the lowest alignment
|
||||
//! (1), however, some architectures may constrain the alignment, for example AArch64 requires 16-byte alignment.
|
||||
inline uint32_t hwStackAlignment() const noexcept { return _hwStackAlignment; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t hwStackAlignment() const noexcept { return _hwStackAlignment; }
|
||||
|
||||
//! Tests whether the architecture provides link register, which is used across function calls. If the link
|
||||
//! register is not provided then a function call pushes the return address on stack (X86/X64).
|
||||
inline bool hasLinkReg() const noexcept { return _linkRegId != BaseReg::kIdBad; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasLinkReg() const noexcept { return _linkRegId != BaseReg::kIdBad; }
|
||||
|
||||
//! Returns minimum addressable offset on stack guaranteed for all instructions.
|
||||
inline uint32_t minStackOffset() const noexcept { return _minStackOffset; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t minStackOffset() const noexcept { return _minStackOffset; }
|
||||
//! Returns maximum addressable offset on stack depending on specific instruction.
|
||||
inline uint32_t maxStackOffset() const noexcept { return _maxStackOffset; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t maxStackOffset() const noexcept { return _maxStackOffset; }
|
||||
|
||||
//! Returns ISA flags of the given register `group`.
|
||||
inline InstHints instFeatureHints(RegGroup group) const noexcept { return _instHints[group]; }
|
||||
ASMJIT_INLINE_NODEBUG InstHints instFeatureHints(RegGroup group) const noexcept { return _instHints[group]; }
|
||||
//! Tests whether the given register `group` has the given `flag` set.
|
||||
inline bool hasInstHint(RegGroup group, InstHints feature) const noexcept { return Support::test(_instHints[group], feature); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasInstHint(RegGroup group, InstHints feature) const noexcept { return Support::test(_instHints[group], feature); }
|
||||
//! Tests whether the ISA provides register swap instruction for the given register `group`.
|
||||
inline bool hasInstRegSwap(RegGroup group) const noexcept { return hasInstHint(group, InstHints::kRegSwap); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasInstRegSwap(RegGroup group) const noexcept { return hasInstHint(group, InstHints::kRegSwap); }
|
||||
//! Tests whether the ISA provides push/pop instructions for the given register `group`.
|
||||
inline bool hasInstPushPop(RegGroup group) const noexcept { return hasInstHint(group, InstHints::kPushPop); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasInstPushPop(RegGroup group) const noexcept { return hasInstHint(group, InstHints::kPushPop); }
|
||||
|
||||
inline bool hasRegType(RegType type) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool hasRegType(RegType type) const noexcept {
|
||||
return type <= RegType::kMaxValue && _regSignature[type].isValid();
|
||||
}
|
||||
|
||||
//! Returns an operand signature from the given register `type` of this architecture.
|
||||
inline OperandSignature regTypeToSignature(RegType type) const noexcept { return _regSignature[type]; }
|
||||
ASMJIT_INLINE_NODEBUG OperandSignature regTypeToSignature(RegType type) const noexcept { return _regSignature[type]; }
|
||||
//! Returns a register from the given register `type` of this architecture.
|
||||
inline RegGroup regTypeToGroup(RegType type) const noexcept { return _regSignature[type].regGroup(); }
|
||||
ASMJIT_INLINE_NODEBUG RegGroup regTypeToGroup(RegType type) const noexcept { return _regSignature[type].regGroup(); }
|
||||
//! Returns a register size the given register `type` of this architecture.
|
||||
inline uint32_t regTypeToSize(RegType type) const noexcept { return _regSignature[type].size(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t regTypeToSize(RegType type) const noexcept { return _regSignature[type].size(); }
|
||||
//! Returns a corresponding `TypeId` from the given register `type` of this architecture.
|
||||
inline TypeId regTypeToTypeId(RegType type) const noexcept { return _regTypeToTypeId[type]; }
|
||||
ASMJIT_INLINE_NODEBUG TypeId regTypeToTypeId(RegType type) const noexcept { return _regTypeToTypeId[type]; }
|
||||
|
||||
//! Returns a table of ISA word names that appear in formatted text. Word names are ISA dependent.
|
||||
//!
|
||||
@@ -254,10 +254,10 @@ struct ArchTraits {
|
||||
//! - [1] 16-bits
|
||||
//! - [2] 32-bits
|
||||
//! - [3] 64-bits
|
||||
inline const ArchTypeNameId* typeNameIdTable() const noexcept { return _typeNameIdTable; }
|
||||
ASMJIT_INLINE_NODEBUG const ArchTypeNameId* typeNameIdTable() const noexcept { return _typeNameIdTable; }
|
||||
|
||||
//! Returns an ISA word name identifier of the given `index`, see \ref typeNameIdTable() for more details.
|
||||
inline ArchTypeNameId typeNameIdByIndex(uint32_t index) const noexcept { return _typeNameIdTable[index]; }
|
||||
ASMJIT_INLINE_NODEBUG ArchTypeNameId typeNameIdByIndex(uint32_t index) const noexcept { return _typeNameIdTable[index]; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -265,7 +265,7 @@ struct ArchTraits {
|
||||
//! \{
|
||||
|
||||
//! Returns a const reference to `ArchTraits` for the given architecture `arch`.
|
||||
static inline const ArchTraits& byArch(Arch arch) noexcept;
|
||||
static ASMJIT_INLINE_NODEBUG const ArchTraits& byArch(Arch arch) noexcept;
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -273,7 +273,7 @@ struct ArchTraits {
|
||||
ASMJIT_VARAPI const ArchTraits _archTraits[uint32_t(Arch::kMaxValue) + 1];
|
||||
|
||||
//! \cond
|
||||
inline const ArchTraits& ArchTraits::byArch(Arch arch) noexcept { return _archTraits[uint32_t(arch)]; }
|
||||
ASMJIT_INLINE_NODEBUG const ArchTraits& ArchTraits::byArch(Arch arch) noexcept { return _archTraits[uint32_t(arch)]; }
|
||||
//! \endcond
|
||||
|
||||
//! Architecture utilities.
|
||||
|
||||
@@ -53,12 +53,12 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the capacity of the current CodeBuffer.
|
||||
inline size_t bufferCapacity() const noexcept { return (size_t)(_bufferEnd - _bufferData); }
|
||||
ASMJIT_INLINE_NODEBUG size_t bufferCapacity() const noexcept { return (size_t)(_bufferEnd - _bufferData); }
|
||||
//! Returns the number of remaining bytes in the current CodeBuffer.
|
||||
inline size_t remainingSpace() const noexcept { return (size_t)(_bufferEnd - _bufferPtr); }
|
||||
ASMJIT_INLINE_NODEBUG size_t remainingSpace() const noexcept { return (size_t)(_bufferEnd - _bufferPtr); }
|
||||
|
||||
//! Returns the current position in the CodeBuffer.
|
||||
inline size_t offset() const noexcept { return (size_t)(_bufferPtr - _bufferData); }
|
||||
ASMJIT_INLINE_NODEBUG size_t offset() const noexcept { return (size_t)(_bufferPtr - _bufferData); }
|
||||
|
||||
//! Sets the current position in the CodeBuffer to `offset`.
|
||||
//!
|
||||
@@ -67,11 +67,11 @@ public:
|
||||
ASMJIT_API Error setOffset(size_t offset);
|
||||
|
||||
//! Returns the start of the CodeBuffer in the current section.
|
||||
inline uint8_t* bufferData() const noexcept { return _bufferData; }
|
||||
ASMJIT_INLINE_NODEBUG uint8_t* bufferData() const noexcept { return _bufferData; }
|
||||
//! Returns the end (first invalid byte) in the current section.
|
||||
inline uint8_t* bufferEnd() const noexcept { return _bufferEnd; }
|
||||
ASMJIT_INLINE_NODEBUG uint8_t* bufferEnd() const noexcept { return _bufferEnd; }
|
||||
//! Returns the current pointer in the CodeBuffer in the current section.
|
||||
inline uint8_t* bufferPtr() const noexcept { return _bufferPtr; }
|
||||
ASMJIT_INLINE_NODEBUG uint8_t* bufferPtr() const noexcept { return _bufferPtr; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -79,7 +79,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the current section.
|
||||
inline Section* currentSection() const noexcept { return _section; }
|
||||
ASMJIT_INLINE_NODEBUG Section* currentSection() const noexcept { return _section; }
|
||||
|
||||
ASMJIT_API Error section(Section* section) override;
|
||||
|
||||
|
||||
@@ -179,9 +179,9 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the first node.
|
||||
inline BaseNode* firstNode() const noexcept { return _firstNode; }
|
||||
ASMJIT_INLINE_NODEBUG BaseNode* firstNode() const noexcept { return _firstNode; }
|
||||
//! Returns the last node.
|
||||
inline BaseNode* lastNode() const noexcept { return _lastNode; }
|
||||
ASMJIT_INLINE_NODEBUG BaseNode* lastNode() const noexcept { return _lastNode; }
|
||||
|
||||
//! Allocates and instantiates a new node of type `T` and returns its instance. If the allocation fails `nullptr`
|
||||
//! is returned.
|
||||
@@ -227,7 +227,7 @@ public:
|
||||
//! When the Builder/Compiler is created it automatically creates a '.text' \ref SectionNode, which will be the
|
||||
//! initial one. When instructions are added they are always added after the cursor and the cursor is changed
|
||||
//! to be that newly added node. Use `setCursor()` to change where new nodes are inserted.
|
||||
inline BaseNode* cursor() const noexcept { return _cursor; }
|
||||
ASMJIT_INLINE_NODEBUG BaseNode* cursor() const noexcept { return _cursor; }
|
||||
|
||||
//! Sets the current node to `node` and return the previous one.
|
||||
ASMJIT_API BaseNode* setCursor(BaseNode* node) noexcept;
|
||||
@@ -236,7 +236,7 @@ public:
|
||||
//!
|
||||
//! Only use this function if you are concerned about performance and want this inlined (for example if you set
|
||||
//! the cursor in a loop, etc...).
|
||||
inline void _setCursor(BaseNode* node) noexcept { _cursor = node; }
|
||||
ASMJIT_INLINE_NODEBUG void _setCursor(BaseNode* node) noexcept { _cursor = node; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -247,12 +247,12 @@ public:
|
||||
//!
|
||||
//! \note If a section of some id is not associated with the Builder/Compiler it would be null, so always check
|
||||
//! for nulls if you iterate over the vector.
|
||||
inline const ZoneVector<SectionNode*>& sectionNodes() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG const ZoneVector<SectionNode*>& sectionNodes() const noexcept {
|
||||
return _sectionNodes;
|
||||
}
|
||||
|
||||
//! Tests whether the `SectionNode` of the given `sectionId` was registered.
|
||||
inline bool hasRegisteredSectionNode(uint32_t sectionId) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool hasRegisteredSectionNode(uint32_t sectionId) const noexcept {
|
||||
return sectionId < _sectionNodes.size() && _sectionNodes[sectionId] != nullptr;
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ public:
|
||||
|
||||
//! Returns whether the section links of active section nodes are dirty. You can update these links by calling
|
||||
//! `updateSectionLinks()` in such case.
|
||||
inline bool hasDirtySectionLinks() const noexcept { return _dirtySectionLinks; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasDirtySectionLinks() const noexcept { return _dirtySectionLinks; }
|
||||
|
||||
//! Updates links of all active section nodes.
|
||||
ASMJIT_API void updateSectionLinks() noexcept;
|
||||
@@ -280,15 +280,15 @@ public:
|
||||
//!
|
||||
//! \note If a label of some id is not associated with the Builder/Compiler it would be null, so always check for
|
||||
//! nulls if you iterate over the vector.
|
||||
inline const ZoneVector<LabelNode*>& labelNodes() const noexcept { return _labelNodes; }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneVector<LabelNode*>& labelNodes() const noexcept { return _labelNodes; }
|
||||
|
||||
//! Tests whether the `LabelNode` of the given `labelId` was registered.
|
||||
inline bool hasRegisteredLabelNode(uint32_t labelId) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool hasRegisteredLabelNode(uint32_t labelId) const noexcept {
|
||||
return labelId < _labelNodes.size() && _labelNodes[labelId] != nullptr;
|
||||
}
|
||||
|
||||
//! \overload
|
||||
inline bool hasRegisteredLabelNode(const Label& label) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool hasRegisteredLabelNode(const Label& label) const noexcept {
|
||||
return hasRegisteredLabelNode(label.id());
|
||||
}
|
||||
|
||||
@@ -299,7 +299,7 @@ public:
|
||||
ASMJIT_API Error labelNodeOf(LabelNode** ASMJIT_NONNULL(out), uint32_t labelId);
|
||||
|
||||
//! \overload
|
||||
inline Error labelNodeOf(LabelNode** ASMJIT_NONNULL(out), const Label& label) {
|
||||
ASMJIT_INLINE_NODEBUG Error labelNodeOf(LabelNode** ASMJIT_NONNULL(out), const Label& label) {
|
||||
return labelNodeOf(out, label.id());
|
||||
}
|
||||
|
||||
@@ -319,7 +319,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns a vector of `Pass` instances that will be executed by `runPasses()`.
|
||||
inline const ZoneVector<Pass*>& passes() const noexcept { return _passes; }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneVector<Pass*>& passes() const noexcept { return _passes; }
|
||||
|
||||
//! Allocates and instantiates a new pass of type `T` and returns its instance. If the allocation fails `nullptr` is
|
||||
//! returned.
|
||||
@@ -529,7 +529,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a new `BaseNode` - always use `BaseBuilder` to allocate nodes.
|
||||
inline BaseNode(BaseBuilder* cb, NodeType nodeType, NodeFlags nodeFlags = NodeFlags::kNone) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG BaseNode(BaseBuilder* cb, NodeType nodeType, NodeFlags nodeFlags = NodeFlags::kNone) noexcept {
|
||||
_prev = nullptr;
|
||||
_next = nullptr;
|
||||
_any._nodeType = nodeType;
|
||||
@@ -549,85 +549,85 @@ public:
|
||||
|
||||
//! Casts this node to `T*`.
|
||||
template<typename T>
|
||||
inline T* as() noexcept { return static_cast<T*>(this); }
|
||||
ASMJIT_INLINE_NODEBUG T* as() noexcept { return static_cast<T*>(this); }
|
||||
//! Casts this node to `const T*`.
|
||||
template<typename T>
|
||||
inline const T* as() const noexcept { return static_cast<const T*>(this); }
|
||||
ASMJIT_INLINE_NODEBUG const T* as() const noexcept { return static_cast<const T*>(this); }
|
||||
|
||||
//! Returns previous node or `nullptr` if this node is either first or not
|
||||
//! part of Builder/Compiler node-list.
|
||||
inline BaseNode* prev() const noexcept { return _prev; }
|
||||
ASMJIT_INLINE_NODEBUG BaseNode* prev() const noexcept { return _prev; }
|
||||
//! Returns next node or `nullptr` if this node is either last or not part
|
||||
//! of Builder/Compiler node-list.
|
||||
inline BaseNode* next() const noexcept { return _next; }
|
||||
ASMJIT_INLINE_NODEBUG BaseNode* next() const noexcept { return _next; }
|
||||
|
||||
//! Returns the type of the node, see `NodeType`.
|
||||
inline NodeType type() const noexcept { return _any._nodeType; }
|
||||
ASMJIT_INLINE_NODEBUG NodeType type() const noexcept { return _any._nodeType; }
|
||||
|
||||
//! Sets the type of the node, see `NodeType` (internal).
|
||||
//!
|
||||
//! \remarks You should never set a type of a node to anything else than the initial value. This function is only
|
||||
//! provided for users that use custom nodes and need to change the type either during construction or later.
|
||||
inline void setType(NodeType type) noexcept { _any._nodeType = type; }
|
||||
ASMJIT_INLINE_NODEBUG void setType(NodeType type) noexcept { _any._nodeType = type; }
|
||||
|
||||
//! Tests whether this node is either `InstNode` or extends it.
|
||||
inline bool isInst() const noexcept { return hasFlag(NodeFlags::kActsAsInst); }
|
||||
ASMJIT_INLINE_NODEBUG bool isInst() const noexcept { return hasFlag(NodeFlags::kActsAsInst); }
|
||||
//! Tests whether this node is `SectionNode`.
|
||||
inline bool isSection() const noexcept { return type() == NodeType::kSection; }
|
||||
ASMJIT_INLINE_NODEBUG bool isSection() const noexcept { return type() == NodeType::kSection; }
|
||||
//! Tests whether this node is either `LabelNode` or extends it.
|
||||
inline bool isLabel() const noexcept { return hasFlag(NodeFlags::kActsAsLabel); }
|
||||
ASMJIT_INLINE_NODEBUG bool isLabel() const noexcept { return hasFlag(NodeFlags::kActsAsLabel); }
|
||||
//! Tests whether this node is `AlignNode`.
|
||||
inline bool isAlign() const noexcept { return type() == NodeType::kAlign; }
|
||||
ASMJIT_INLINE_NODEBUG bool isAlign() const noexcept { return type() == NodeType::kAlign; }
|
||||
//! Tests whether this node is `EmbedDataNode`.
|
||||
inline bool isEmbedData() const noexcept { return type() == NodeType::kEmbedData; }
|
||||
ASMJIT_INLINE_NODEBUG bool isEmbedData() const noexcept { return type() == NodeType::kEmbedData; }
|
||||
//! Tests whether this node is `EmbedLabelNode`.
|
||||
inline bool isEmbedLabel() const noexcept { return type() == NodeType::kEmbedLabel; }
|
||||
ASMJIT_INLINE_NODEBUG bool isEmbedLabel() const noexcept { return type() == NodeType::kEmbedLabel; }
|
||||
//! Tests whether this node is `EmbedLabelDeltaNode`.
|
||||
inline bool isEmbedLabelDelta() const noexcept { return type() == NodeType::kEmbedLabelDelta; }
|
||||
ASMJIT_INLINE_NODEBUG bool isEmbedLabelDelta() const noexcept { return type() == NodeType::kEmbedLabelDelta; }
|
||||
//! Tests whether this node is `ConstPoolNode`.
|
||||
inline bool isConstPool() const noexcept { return type() == NodeType::kConstPool; }
|
||||
ASMJIT_INLINE_NODEBUG bool isConstPool() const noexcept { return type() == NodeType::kConstPool; }
|
||||
//! Tests whether this node is `CommentNode`.
|
||||
inline bool isComment() const noexcept { return type() == NodeType::kComment; }
|
||||
ASMJIT_INLINE_NODEBUG bool isComment() const noexcept { return type() == NodeType::kComment; }
|
||||
//! Tests whether this node is `SentinelNode`.
|
||||
inline bool isSentinel() const noexcept { return type() == NodeType::kSentinel; }
|
||||
ASMJIT_INLINE_NODEBUG bool isSentinel() const noexcept { return type() == NodeType::kSentinel; }
|
||||
|
||||
//! Tests whether this node is `FuncNode`.
|
||||
inline bool isFunc() const noexcept { return type() == NodeType::kFunc; }
|
||||
ASMJIT_INLINE_NODEBUG bool isFunc() const noexcept { return type() == NodeType::kFunc; }
|
||||
//! Tests whether this node is `FuncRetNode`.
|
||||
inline bool isFuncRet() const noexcept { return type() == NodeType::kFuncRet; }
|
||||
ASMJIT_INLINE_NODEBUG bool isFuncRet() const noexcept { return type() == NodeType::kFuncRet; }
|
||||
//! Tests whether this node is `InvokeNode`.
|
||||
inline bool isInvoke() const noexcept { return type() == NodeType::kInvoke; }
|
||||
ASMJIT_INLINE_NODEBUG bool isInvoke() const noexcept { return type() == NodeType::kInvoke; }
|
||||
|
||||
//! Returns the node flags.
|
||||
inline NodeFlags flags() const noexcept { return _any._nodeFlags; }
|
||||
ASMJIT_INLINE_NODEBUG NodeFlags flags() const noexcept { return _any._nodeFlags; }
|
||||
//! Tests whether the node has the given `flag` set.
|
||||
inline bool hasFlag(NodeFlags flag) const noexcept { return Support::test(_any._nodeFlags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(NodeFlags flag) const noexcept { return Support::test(_any._nodeFlags, flag); }
|
||||
//! Replaces node flags with `flags`.
|
||||
inline void setFlags(NodeFlags flags) noexcept { _any._nodeFlags = flags; }
|
||||
ASMJIT_INLINE_NODEBUG void setFlags(NodeFlags flags) noexcept { _any._nodeFlags = flags; }
|
||||
//! Adds the given `flags` to node flags.
|
||||
inline void addFlags(NodeFlags flags) noexcept { _any._nodeFlags |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG void addFlags(NodeFlags flags) noexcept { _any._nodeFlags |= flags; }
|
||||
//! Clears the given `flags` from node flags.
|
||||
inline void clearFlags(NodeFlags flags) noexcept { _any._nodeFlags &= ~flags; }
|
||||
ASMJIT_INLINE_NODEBUG void clearFlags(NodeFlags flags) noexcept { _any._nodeFlags &= ~flags; }
|
||||
|
||||
//! Tests whether the node is code that can be executed.
|
||||
inline bool isCode() const noexcept { return hasFlag(NodeFlags::kIsCode); }
|
||||
ASMJIT_INLINE_NODEBUG bool isCode() const noexcept { return hasFlag(NodeFlags::kIsCode); }
|
||||
//! Tests whether the node is data that cannot be executed.
|
||||
inline bool isData() const noexcept { return hasFlag(NodeFlags::kIsData); }
|
||||
ASMJIT_INLINE_NODEBUG bool isData() const noexcept { return hasFlag(NodeFlags::kIsData); }
|
||||
//! Tests whether the node is informative only (is never encoded like comment, etc...).
|
||||
inline bool isInformative() const noexcept { return hasFlag(NodeFlags::kIsInformative); }
|
||||
ASMJIT_INLINE_NODEBUG bool isInformative() const noexcept { return hasFlag(NodeFlags::kIsInformative); }
|
||||
//! Tests whether the node is removable if it's in an unreachable code block.
|
||||
inline bool isRemovable() const noexcept { return hasFlag(NodeFlags::kIsRemovable); }
|
||||
ASMJIT_INLINE_NODEBUG bool isRemovable() const noexcept { return hasFlag(NodeFlags::kIsRemovable); }
|
||||
//! Tests whether the node has no effect when executed (label, .align, nop, ...).
|
||||
inline bool hasNoEffect() const noexcept { return hasFlag(NodeFlags::kHasNoEffect); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasNoEffect() const noexcept { return hasFlag(NodeFlags::kHasNoEffect); }
|
||||
//! Tests whether the node is part of the code.
|
||||
inline bool isActive() const noexcept { return hasFlag(NodeFlags::kIsActive); }
|
||||
ASMJIT_INLINE_NODEBUG bool isActive() const noexcept { return hasFlag(NodeFlags::kIsActive); }
|
||||
|
||||
//! Tests whether the node has a position assigned.
|
||||
//!
|
||||
//! \remarks Returns `true` if node position is non-zero.
|
||||
inline bool hasPosition() const noexcept { return _position != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasPosition() const noexcept { return _position != 0; }
|
||||
//! Returns node position.
|
||||
inline uint32_t position() const noexcept { return _position; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t position() const noexcept { return _position; }
|
||||
//! Sets node position.
|
||||
//!
|
||||
//! Node position is a 32-bit unsigned integer that is used by Compiler to track where the node is relatively to
|
||||
@@ -636,49 +636,49 @@ public:
|
||||
//!
|
||||
//! If you don't use Compiler then you may use `position()` and `setPosition()` freely for your own purposes if
|
||||
//! the 32-bit value limit is okay for you.
|
||||
inline void setPosition(uint32_t position) noexcept { _position = position; }
|
||||
ASMJIT_INLINE_NODEBUG void setPosition(uint32_t position) noexcept { _position = position; }
|
||||
|
||||
//! Returns user data casted to `T*`.
|
||||
//!
|
||||
//! User data is decicated to be used only by AsmJit users and not touched by the library. The data has a pointer
|
||||
//! size so you can either store a pointer or `intptr_t` value through `setUserDataAsIntPtr()`.
|
||||
template<typename T>
|
||||
inline T* userDataAsPtr() const noexcept { return static_cast<T*>(_userDataPtr); }
|
||||
ASMJIT_INLINE_NODEBUG T* userDataAsPtr() const noexcept { return static_cast<T*>(_userDataPtr); }
|
||||
//! Returns user data casted to `int64_t`.
|
||||
inline int64_t userDataAsInt64() const noexcept { return int64_t(_userDataU64); }
|
||||
ASMJIT_INLINE_NODEBUG int64_t userDataAsInt64() const noexcept { return int64_t(_userDataU64); }
|
||||
//! Returns user data casted to `uint64_t`.
|
||||
inline uint64_t userDataAsUInt64() const noexcept { return _userDataU64; }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t userDataAsUInt64() const noexcept { return _userDataU64; }
|
||||
|
||||
//! Sets user data to `data`.
|
||||
template<typename T>
|
||||
inline void setUserDataAsPtr(T* data) noexcept { _userDataPtr = static_cast<void*>(data); }
|
||||
ASMJIT_INLINE_NODEBUG void setUserDataAsPtr(T* data) noexcept { _userDataPtr = static_cast<void*>(data); }
|
||||
//! Sets used data to the given 64-bit signed `value`.
|
||||
inline void setUserDataAsInt64(int64_t value) noexcept { _userDataU64 = uint64_t(value); }
|
||||
ASMJIT_INLINE_NODEBUG void setUserDataAsInt64(int64_t value) noexcept { _userDataU64 = uint64_t(value); }
|
||||
//! Sets used data to the given 64-bit unsigned `value`.
|
||||
inline void setUserDataAsUInt64(uint64_t value) noexcept { _userDataU64 = value; }
|
||||
ASMJIT_INLINE_NODEBUG void setUserDataAsUInt64(uint64_t value) noexcept { _userDataU64 = value; }
|
||||
|
||||
//! Resets user data to zero / nullptr.
|
||||
inline void resetUserData() noexcept { _userDataU64 = 0; }
|
||||
ASMJIT_INLINE_NODEBUG void resetUserData() noexcept { _userDataU64 = 0; }
|
||||
|
||||
//! Tests whether the node has an associated pass data.
|
||||
inline bool hasPassData() const noexcept { return _passData != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasPassData() const noexcept { return _passData != nullptr; }
|
||||
//! Returns the node pass data - data used during processing & transformations.
|
||||
template<typename T>
|
||||
inline T* passData() const noexcept { return (T*)_passData; }
|
||||
ASMJIT_INLINE_NODEBUG T* passData() const noexcept { return (T*)_passData; }
|
||||
//! Sets the node pass data to `data`.
|
||||
template<typename T>
|
||||
inline void setPassData(T* data) noexcept { _passData = (void*)data; }
|
||||
ASMJIT_INLINE_NODEBUG void setPassData(T* data) noexcept { _passData = (void*)data; }
|
||||
//! Resets the node pass data to nullptr.
|
||||
inline void resetPassData() noexcept { _passData = nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG void resetPassData() noexcept { _passData = nullptr; }
|
||||
|
||||
//! Tests whether the node has an inline comment/annotation.
|
||||
inline bool hasInlineComment() const noexcept { return _inlineComment != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasInlineComment() const noexcept { return _inlineComment != nullptr; }
|
||||
//! Returns an inline comment/annotation string.
|
||||
inline const char* inlineComment() const noexcept { return _inlineComment; }
|
||||
ASMJIT_INLINE_NODEBUG const char* inlineComment() const noexcept { return _inlineComment; }
|
||||
//! Sets an inline comment/annotation string to `s`.
|
||||
inline void setInlineComment(const char* s) noexcept { _inlineComment = s; }
|
||||
ASMJIT_INLINE_NODEBUG void setInlineComment(const char* s) noexcept { _inlineComment = s; }
|
||||
//! Resets an inline comment/annotation string to nullptr.
|
||||
inline void resetInlineComment() noexcept { _inlineComment = nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG void resetInlineComment() noexcept { _inlineComment = nullptr; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -716,7 +716,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a new `InstNode` instance.
|
||||
inline InstNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCount, uint32_t opCapacity = kBaseOpCapacity) noexcept
|
||||
ASMJIT_INLINE_NODEBUG InstNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCount, uint32_t opCapacity = kBaseOpCapacity) noexcept
|
||||
: BaseNode(cb, NodeType::kInst, NodeFlags::kIsCode | NodeFlags::kIsRemovable | NodeFlags::kActsAsInst),
|
||||
_baseInst(instId, options) {
|
||||
_inst._opCapacity = uint8_t(opCapacity);
|
||||
@@ -725,7 +725,7 @@ public:
|
||||
|
||||
//! \cond INTERNAL
|
||||
//! Reset all built-in operands, including `extraReg`.
|
||||
inline void _resetOps() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void _resetOps() noexcept {
|
||||
_baseInst.resetExtraReg();
|
||||
resetOpRange(0, opCapacity());
|
||||
}
|
||||
@@ -736,8 +736,8 @@ public:
|
||||
//! \name Instruction Object
|
||||
//! \{
|
||||
|
||||
inline BaseInst& baseInst() noexcept { return _baseInst; }
|
||||
inline const BaseInst& baseInst() const noexcept { return _baseInst; }
|
||||
ASMJIT_INLINE_NODEBUG BaseInst& baseInst() noexcept { return _baseInst; }
|
||||
ASMJIT_INLINE_NODEBUG const BaseInst& baseInst() const noexcept { return _baseInst; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -745,24 +745,24 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the instruction id, see `BaseInst::Id`.
|
||||
inline InstId id() const noexcept { return _baseInst.id(); }
|
||||
ASMJIT_INLINE_NODEBUG InstId id() const noexcept { return _baseInst.id(); }
|
||||
//! Returns the instruction real id, see `BaseInst::Id`.
|
||||
inline InstId realId() const noexcept { return _baseInst.realId(); }
|
||||
ASMJIT_INLINE_NODEBUG InstId realId() const noexcept { return _baseInst.realId(); }
|
||||
|
||||
//! Sets the instruction id to `id`, see `BaseInst::Id`.
|
||||
inline void setId(InstId id) noexcept { _baseInst.setId(id); }
|
||||
ASMJIT_INLINE_NODEBUG void setId(InstId id) noexcept { _baseInst.setId(id); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Instruction Options
|
||||
//! \{
|
||||
|
||||
inline InstOptions options() const noexcept { return _baseInst.options(); }
|
||||
inline bool hasOption(InstOptions option) const noexcept { return _baseInst.hasOption(option); }
|
||||
inline void setOptions(InstOptions options) noexcept { _baseInst.setOptions(options); }
|
||||
inline void addOptions(InstOptions options) noexcept { _baseInst.addOptions(options); }
|
||||
inline void clearOptions(InstOptions options) noexcept { _baseInst.clearOptions(options); }
|
||||
inline void resetOptions() noexcept { _baseInst.resetOptions(); }
|
||||
ASMJIT_INLINE_NODEBUG InstOptions options() const noexcept { return _baseInst.options(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasOption(InstOptions option) const noexcept { return _baseInst.hasOption(option); }
|
||||
ASMJIT_INLINE_NODEBUG void setOptions(InstOptions options) noexcept { _baseInst.setOptions(options); }
|
||||
ASMJIT_INLINE_NODEBUG void addOptions(InstOptions options) noexcept { _baseInst.addOptions(options); }
|
||||
ASMJIT_INLINE_NODEBUG void clearOptions(InstOptions options) noexcept { _baseInst.clearOptions(options); }
|
||||
ASMJIT_INLINE_NODEBUG void resetOptions() noexcept { _baseInst.resetOptions(); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -770,17 +770,17 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether the node has an extra register operand.
|
||||
inline bool hasExtraReg() const noexcept { return _baseInst.hasExtraReg(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasExtraReg() const noexcept { return _baseInst.hasExtraReg(); }
|
||||
//! Returns extra register operand.
|
||||
inline RegOnly& extraReg() noexcept { return _baseInst.extraReg(); }
|
||||
ASMJIT_INLINE_NODEBUG RegOnly& extraReg() noexcept { return _baseInst.extraReg(); }
|
||||
//! \overload
|
||||
inline const RegOnly& extraReg() const noexcept { return _baseInst.extraReg(); }
|
||||
ASMJIT_INLINE_NODEBUG const RegOnly& extraReg() const noexcept { return _baseInst.extraReg(); }
|
||||
//! Sets extra register operand to `reg`.
|
||||
inline void setExtraReg(const BaseReg& reg) noexcept { _baseInst.setExtraReg(reg); }
|
||||
ASMJIT_INLINE_NODEBUG void setExtraReg(const BaseReg& reg) noexcept { _baseInst.setExtraReg(reg); }
|
||||
//! Sets extra register operand to `reg`.
|
||||
inline void setExtraReg(const RegOnly& reg) noexcept { _baseInst.setExtraReg(reg); }
|
||||
ASMJIT_INLINE_NODEBUG void setExtraReg(const RegOnly& reg) noexcept { _baseInst.setExtraReg(reg); }
|
||||
//! Resets extra register operand.
|
||||
inline void resetExtraReg() noexcept { _baseInst.resetExtraReg(); }
|
||||
ASMJIT_INLINE_NODEBUG void resetExtraReg() noexcept { _baseInst.resetExtraReg(); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -788,17 +788,17 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns operand count.
|
||||
inline uint32_t opCount() const noexcept { return _inst._opCount; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t opCount() const noexcept { return _inst._opCount; }
|
||||
//! Returns operand capacity.
|
||||
inline uint32_t opCapacity() const noexcept { return _inst._opCapacity; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t opCapacity() const noexcept { return _inst._opCapacity; }
|
||||
|
||||
//! Sets operand count.
|
||||
inline void setOpCount(uint32_t opCount) noexcept { _inst._opCount = uint8_t(opCount); }
|
||||
ASMJIT_INLINE_NODEBUG void setOpCount(uint32_t opCount) noexcept { _inst._opCount = uint8_t(opCount); }
|
||||
|
||||
//! Returns operands array.
|
||||
inline Operand* operands() noexcept { return (Operand*)_opArray; }
|
||||
ASMJIT_INLINE_NODEBUG Operand* operands() noexcept { return (Operand*)_opArray; }
|
||||
//! Returns operands array (const).
|
||||
inline const Operand* operands() const noexcept { return (const Operand*)_opArray; }
|
||||
ASMJIT_INLINE_NODEBUG const Operand* operands() const noexcept { return (const Operand*)_opArray; }
|
||||
|
||||
//! Returns operand at the given `index`.
|
||||
inline Operand& op(uint32_t index) noexcept {
|
||||
@@ -870,8 +870,8 @@ public:
|
||||
//! \{
|
||||
|
||||
//! \cond INTERNAL
|
||||
inline uint32_t* _getRewriteArray() noexcept { return &_baseInst._extraReg._id; }
|
||||
inline const uint32_t* _getRewriteArray() const noexcept { return &_baseInst._extraReg._id; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t* _getRewriteArray() noexcept { return &_baseInst._extraReg._id; }
|
||||
ASMJIT_INLINE_NODEBUG const uint32_t* _getRewriteArray() const noexcept { return &_baseInst._extraReg._id; }
|
||||
|
||||
inline uint32_t getRewriteIndex(const uint32_t* id) const noexcept {
|
||||
const uint32_t* array = _getRewriteArray();
|
||||
@@ -895,11 +895,11 @@ public:
|
||||
//! \{
|
||||
|
||||
//! \cond INTERNAL
|
||||
static inline uint32_t capacityOfOpCount(uint32_t opCount) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG uint32_t capacityOfOpCount(uint32_t opCount) noexcept {
|
||||
return opCount <= kBaseOpCapacity ? kBaseOpCapacity : Globals::kMaxOpCount;
|
||||
}
|
||||
|
||||
static inline size_t nodeSizeOfOpCapacity(uint32_t opCapacity) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG size_t nodeSizeOfOpCapacity(uint32_t opCapacity) noexcept {
|
||||
size_t base = sizeof(InstNode) - kBaseOpCapacity * sizeof(Operand);
|
||||
return base + opCapacity * sizeof(Operand);
|
||||
}
|
||||
@@ -928,7 +928,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a new `InstExNode` instance.
|
||||
inline InstExNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCapacity = Globals::kMaxOpCount) noexcept
|
||||
ASMJIT_INLINE_NODEBUG InstExNode(BaseBuilder* cb, InstId instId, InstOptions options, uint32_t opCapacity = Globals::kMaxOpCount) noexcept
|
||||
: InstNode(cb, instId, options, opCapacity) {}
|
||||
|
||||
//! \}
|
||||
@@ -958,7 +958,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a new `SectionNode` instance.
|
||||
inline SectionNode(BaseBuilder* cb, uint32_t secionId = 0) noexcept
|
||||
ASMJIT_INLINE_NODEBUG SectionNode(BaseBuilder* cb, uint32_t secionId = 0) noexcept
|
||||
: BaseNode(cb, NodeType::kSection, NodeFlags::kHasNoEffect),
|
||||
_id(secionId),
|
||||
_nextSection(nullptr) {}
|
||||
@@ -969,7 +969,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the section id.
|
||||
inline uint32_t id() const noexcept { return _id; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t id() const noexcept { return _id; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -991,7 +991,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a new `LabelNode` instance.
|
||||
inline LabelNode(BaseBuilder* cb, uint32_t labelId = 0) noexcept
|
||||
ASMJIT_INLINE_NODEBUG LabelNode(BaseBuilder* cb, uint32_t labelId = 0) noexcept
|
||||
: BaseNode(cb, NodeType::kLabel, NodeFlags::kHasNoEffect | NodeFlags::kActsAsLabel),
|
||||
_labelId(labelId) {}
|
||||
|
||||
@@ -1001,9 +1001,9 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns \ref Label representation of the \ref LabelNode.
|
||||
inline Label label() const noexcept { return Label(_labelId); }
|
||||
ASMJIT_INLINE_NODEBUG Label label() const noexcept { return Label(_labelId); }
|
||||
//! Returns the id of the label.
|
||||
inline uint32_t labelId() const noexcept { return _labelId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t labelId() const noexcept { return _labelId; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -1027,7 +1027,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a new `AlignNode` instance.
|
||||
inline AlignNode(BaseBuilder* cb, AlignMode alignMode, uint32_t alignment) noexcept
|
||||
ASMJIT_INLINE_NODEBUG AlignNode(BaseBuilder* cb, AlignMode alignMode, uint32_t alignment) noexcept
|
||||
: BaseNode(cb, NodeType::kAlign, NodeFlags::kIsCode | NodeFlags::kHasNoEffect) {
|
||||
|
||||
_alignData._alignMode = alignMode;
|
||||
@@ -1040,14 +1040,14 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns align mode.
|
||||
inline AlignMode alignMode() const noexcept { return _alignData._alignMode; }
|
||||
ASMJIT_INLINE_NODEBUG AlignMode alignMode() const noexcept { return _alignData._alignMode; }
|
||||
//! Sets align mode to `alignMode`.
|
||||
inline void setAlignMode(AlignMode alignMode) noexcept { _alignData._alignMode = alignMode; }
|
||||
ASMJIT_INLINE_NODEBUG void setAlignMode(AlignMode alignMode) noexcept { _alignData._alignMode = alignMode; }
|
||||
|
||||
//! Returns align offset in bytes.
|
||||
inline uint32_t alignment() const noexcept { return _alignment; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t alignment() const noexcept { return _alignment; }
|
||||
//! Sets align offset in bytes to `offset`.
|
||||
inline void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; }
|
||||
ASMJIT_INLINE_NODEBUG void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -1083,7 +1083,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a new `EmbedDataNode` instance.
|
||||
inline EmbedDataNode(BaseBuilder* cb) noexcept
|
||||
ASMJIT_INLINE_NODEBUG EmbedDataNode(BaseBuilder* cb) noexcept
|
||||
: BaseNode(cb, NodeType::kEmbedData, NodeFlags::kIsData),
|
||||
_itemCount(0),
|
||||
_repeatCount(0) {
|
||||
@@ -1098,31 +1098,31 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns data type as \ref TypeId.
|
||||
inline TypeId typeId() const noexcept { return _embed._typeId; }
|
||||
ASMJIT_INLINE_NODEBUG TypeId typeId() const noexcept { return _embed._typeId; }
|
||||
//! Returns the size of a single data element.
|
||||
inline uint32_t typeSize() const noexcept { return _embed._typeSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t typeSize() const noexcept { return _embed._typeSize; }
|
||||
|
||||
//! Returns a pointer to the data casted to `uint8_t`.
|
||||
inline uint8_t* data() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG uint8_t* data() const noexcept {
|
||||
return dataSize() <= kInlineBufferSize ? const_cast<uint8_t*>(_inlineData) : _externalData;
|
||||
}
|
||||
|
||||
//! Returns a pointer to the data casted to `T`.
|
||||
template<typename T>
|
||||
inline T* dataAs() const noexcept { return reinterpret_cast<T*>(data()); }
|
||||
ASMJIT_INLINE_NODEBUG T* dataAs() const noexcept { return reinterpret_cast<T*>(data()); }
|
||||
|
||||
//! Returns the number of (typed) items in the array.
|
||||
inline size_t itemCount() const noexcept { return _itemCount; }
|
||||
ASMJIT_INLINE_NODEBUG size_t itemCount() const noexcept { return _itemCount; }
|
||||
|
||||
//! Returns how many times the data is repeated (default 1).
|
||||
//!
|
||||
//! Repeated data is useful when defining constants for SIMD, for example.
|
||||
inline size_t repeatCount() const noexcept { return _repeatCount; }
|
||||
ASMJIT_INLINE_NODEBUG size_t repeatCount() const noexcept { return _repeatCount; }
|
||||
|
||||
//! Returns the size of the data, not considering the number of times it repeats.
|
||||
//!
|
||||
//! \note The returned value is the same as `typeSize() * itemCount()`.
|
||||
inline size_t dataSize() const noexcept { return typeSize() * _itemCount; }
|
||||
ASMJIT_INLINE_NODEBUG size_t dataSize() const noexcept { return typeSize() * _itemCount; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -1144,7 +1144,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a new `EmbedLabelNode` instance.
|
||||
inline EmbedLabelNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t dataSize = 0) noexcept
|
||||
ASMJIT_INLINE_NODEBUG EmbedLabelNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t dataSize = 0) noexcept
|
||||
: BaseNode(cb, NodeType::kEmbedLabel, NodeFlags::kIsData),
|
||||
_labelId(labelId),
|
||||
_dataSize(dataSize) {}
|
||||
@@ -1155,19 +1155,19 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the label to embed as \ref Label operand.
|
||||
inline Label label() const noexcept { return Label(_labelId); }
|
||||
ASMJIT_INLINE_NODEBUG Label label() const noexcept { return Label(_labelId); }
|
||||
//! Returns the id of the label.
|
||||
inline uint32_t labelId() const noexcept { return _labelId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t labelId() const noexcept { return _labelId; }
|
||||
|
||||
//! Sets the label id from `label` operand.
|
||||
inline void setLabel(const Label& label) noexcept { setLabelId(label.id()); }
|
||||
ASMJIT_INLINE_NODEBUG void setLabel(const Label& label) noexcept { setLabelId(label.id()); }
|
||||
//! Sets the label id (use with caution, improper use can break a lot of things).
|
||||
inline void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; }
|
||||
ASMJIT_INLINE_NODEBUG void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; }
|
||||
|
||||
//! Returns the data size.
|
||||
inline uint32_t dataSize() const noexcept { return _dataSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t dataSize() const noexcept { return _dataSize; }
|
||||
//! Sets the data size.
|
||||
inline void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; }
|
||||
ASMJIT_INLINE_NODEBUG void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -1190,7 +1190,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a new `EmbedLabelDeltaNode` instance.
|
||||
inline EmbedLabelDeltaNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t baseLabelId = 0, uint32_t dataSize = 0) noexcept
|
||||
ASMJIT_INLINE_NODEBUG EmbedLabelDeltaNode(BaseBuilder* cb, uint32_t labelId = 0, uint32_t baseLabelId = 0, uint32_t dataSize = 0) noexcept
|
||||
: BaseNode(cb, NodeType::kEmbedLabelDelta, NodeFlags::kIsData),
|
||||
_labelId(labelId),
|
||||
_baseLabelId(baseLabelId),
|
||||
@@ -1202,29 +1202,29 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the label as `Label` operand.
|
||||
inline Label label() const noexcept { return Label(_labelId); }
|
||||
ASMJIT_INLINE_NODEBUG Label label() const noexcept { return Label(_labelId); }
|
||||
//! Returns the id of the label.
|
||||
inline uint32_t labelId() const noexcept { return _labelId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t labelId() const noexcept { return _labelId; }
|
||||
|
||||
//! Sets the label id from `label` operand.
|
||||
inline void setLabel(const Label& label) noexcept { setLabelId(label.id()); }
|
||||
ASMJIT_INLINE_NODEBUG void setLabel(const Label& label) noexcept { setLabelId(label.id()); }
|
||||
//! Sets the label id.
|
||||
inline void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; }
|
||||
ASMJIT_INLINE_NODEBUG void setLabelId(uint32_t labelId) noexcept { _labelId = labelId; }
|
||||
|
||||
//! Returns the base label as `Label` operand.
|
||||
inline Label baseLabel() const noexcept { return Label(_baseLabelId); }
|
||||
ASMJIT_INLINE_NODEBUG Label baseLabel() const noexcept { return Label(_baseLabelId); }
|
||||
//! Returns the id of the base label.
|
||||
inline uint32_t baseLabelId() const noexcept { return _baseLabelId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t baseLabelId() const noexcept { return _baseLabelId; }
|
||||
|
||||
//! Sets the base label id from `label` operand.
|
||||
inline void setBaseLabel(const Label& baseLabel) noexcept { setBaseLabelId(baseLabel.id()); }
|
||||
ASMJIT_INLINE_NODEBUG void setBaseLabel(const Label& baseLabel) noexcept { setBaseLabelId(baseLabel.id()); }
|
||||
//! Sets the base label id.
|
||||
inline void setBaseLabelId(uint32_t baseLabelId) noexcept { _baseLabelId = baseLabelId; }
|
||||
ASMJIT_INLINE_NODEBUG void setBaseLabelId(uint32_t baseLabelId) noexcept { _baseLabelId = baseLabelId; }
|
||||
|
||||
//! Returns the size of the embedded label address.
|
||||
inline uint32_t dataSize() const noexcept { return _dataSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t dataSize() const noexcept { return _dataSize; }
|
||||
//! Sets the size of the embedded label address.
|
||||
inline void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; }
|
||||
ASMJIT_INLINE_NODEBUG void setDataSize(uint32_t dataSize) noexcept { _dataSize = dataSize; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -1245,7 +1245,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a new `ConstPoolNode` instance.
|
||||
inline ConstPoolNode(BaseBuilder* cb, uint32_t id = 0) noexcept
|
||||
ASMJIT_INLINE_NODEBUG ConstPoolNode(BaseBuilder* cb, uint32_t id = 0) noexcept
|
||||
: LabelNode(cb, id),
|
||||
_constPool(&cb->_codeZone) {
|
||||
|
||||
@@ -1260,16 +1260,16 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether the constant-pool is empty.
|
||||
inline bool empty() const noexcept { return _constPool.empty(); }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _constPool.empty(); }
|
||||
//! Returns the size of the constant-pool in bytes.
|
||||
inline size_t size() const noexcept { return _constPool.size(); }
|
||||
ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return _constPool.size(); }
|
||||
//! Returns minimum alignment.
|
||||
inline size_t alignment() const noexcept { return _constPool.alignment(); }
|
||||
ASMJIT_INLINE_NODEBUG size_t alignment() const noexcept { return _constPool.alignment(); }
|
||||
|
||||
//! Returns the wrapped `ConstPool` instance.
|
||||
inline ConstPool& constPool() noexcept { return _constPool; }
|
||||
ASMJIT_INLINE_NODEBUG ConstPool& constPool() noexcept { return _constPool; }
|
||||
//! Returns the wrapped `ConstPool` instance (const).
|
||||
inline const ConstPool& constPool() const noexcept { return _constPool; }
|
||||
ASMJIT_INLINE_NODEBUG const ConstPool& constPool() const noexcept { return _constPool; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -1277,7 +1277,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! See `ConstPool::add()`.
|
||||
inline Error add(const void* data, size_t size, size_t& dstOffset) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error add(const void* data, size_t size, size_t& dstOffset) noexcept {
|
||||
return _constPool.add(data, size, dstOffset);
|
||||
}
|
||||
|
||||
@@ -1293,7 +1293,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a new `CommentNode` instance.
|
||||
inline CommentNode(BaseBuilder* cb, const char* comment) noexcept
|
||||
ASMJIT_INLINE_NODEBUG CommentNode(BaseBuilder* cb, const char* comment) noexcept
|
||||
: BaseNode(cb, NodeType::kComment, NodeFlags::kIsInformative | NodeFlags::kHasNoEffect | NodeFlags::kIsRemovable) {
|
||||
_inlineComment = comment;
|
||||
}
|
||||
@@ -1313,7 +1313,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a new `SentinelNode` instance.
|
||||
inline SentinelNode(BaseBuilder* cb, SentinelType sentinelType = SentinelType::kUnknown) noexcept
|
||||
ASMJIT_INLINE_NODEBUG SentinelNode(BaseBuilder* cb, SentinelType sentinelType = SentinelType::kUnknown) noexcept
|
||||
: BaseNode(cb, NodeType::kSentinel, NodeFlags::kIsInformative | NodeFlags::kHasNoEffect) {
|
||||
|
||||
_sentinel._sentinelType = sentinelType;
|
||||
@@ -1325,12 +1325,12 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the type of the sentinel.
|
||||
inline SentinelType sentinelType() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG SentinelType sentinelType() const noexcept {
|
||||
return _sentinel._sentinelType;
|
||||
}
|
||||
|
||||
//! Sets the type of the sentinel.
|
||||
inline void setSentinelType(SentinelType type) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void setSentinelType(SentinelType type) noexcept {
|
||||
_sentinel._sentinelType = type;
|
||||
}
|
||||
|
||||
@@ -1365,9 +1365,9 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns \ref BaseBuilder associated with the pass.
|
||||
inline const BaseBuilder* cb() const noexcept { return _cb; }
|
||||
ASMJIT_INLINE_NODEBUG const BaseBuilder* cb() const noexcept { return _cb; }
|
||||
//! Returns the name of the pass.
|
||||
inline const char* name() const noexcept { return _name; }
|
||||
ASMJIT_INLINE_NODEBUG const char* name() const noexcept { return _name; }
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
@@ -61,46 +61,46 @@ struct CodeBuffer {
|
||||
//! \{
|
||||
|
||||
//! Returns code buffer flags.
|
||||
inline CodeBufferFlags flags() const noexcept { return _flags; }
|
||||
ASMJIT_INLINE_NODEBUG CodeBufferFlags flags() const noexcept { return _flags; }
|
||||
//! Tests whether the code buffer has the given `flag` set.
|
||||
inline bool hasFlag(CodeBufferFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(CodeBufferFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
|
||||
//! Tests whether this code buffer has a fixed size.
|
||||
//!
|
||||
//! Fixed size means that the code buffer is fixed and cannot grow.
|
||||
inline bool isFixed() const noexcept { return hasFlag(CodeBufferFlags::kIsFixed); }
|
||||
ASMJIT_INLINE_NODEBUG bool isFixed() const noexcept { return hasFlag(CodeBufferFlags::kIsFixed); }
|
||||
|
||||
//! Tests whether the data in this code buffer is external.
|
||||
//!
|
||||
//! External data can only be provided by users, it's never used by AsmJit.
|
||||
inline bool isExternal() const noexcept { return hasFlag(CodeBufferFlags::kIsExternal); }
|
||||
ASMJIT_INLINE_NODEBUG bool isExternal() const noexcept { return hasFlag(CodeBufferFlags::kIsExternal); }
|
||||
|
||||
//! Tests whether the data in this code buffer is allocated (non-null).
|
||||
inline bool isAllocated() const noexcept { return _data != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool isAllocated() const noexcept { return _data != nullptr; }
|
||||
|
||||
//! Tests whether the code buffer is empty.
|
||||
inline bool empty() const noexcept { return !_size; }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return !_size; }
|
||||
|
||||
//! Returns the size of the data.
|
||||
inline size_t size() const noexcept { return _size; }
|
||||
ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return _size; }
|
||||
//! Returns the capacity of the data.
|
||||
inline size_t capacity() const noexcept { return _capacity; }
|
||||
ASMJIT_INLINE_NODEBUG size_t capacity() const noexcept { return _capacity; }
|
||||
|
||||
//! Returns the pointer to the data the buffer references.
|
||||
inline uint8_t* data() noexcept { return _data; }
|
||||
ASMJIT_INLINE_NODEBUG uint8_t* data() noexcept { return _data; }
|
||||
//! \overload
|
||||
inline const uint8_t* data() const noexcept { return _data; }
|
||||
ASMJIT_INLINE_NODEBUG const uint8_t* data() const noexcept { return _data; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Iterators
|
||||
//! \{
|
||||
|
||||
inline uint8_t* begin() noexcept { return _data; }
|
||||
inline const uint8_t* begin() const noexcept { return _data; }
|
||||
ASMJIT_INLINE_NODEBUG uint8_t* begin() noexcept { return _data; }
|
||||
ASMJIT_INLINE_NODEBUG const uint8_t* begin() const noexcept { return _data; }
|
||||
|
||||
inline uint8_t* end() noexcept { return _data + _size; }
|
||||
inline const uint8_t* end() const noexcept { return _data + _size; }
|
||||
ASMJIT_INLINE_NODEBUG uint8_t* end() noexcept { return _data + _size; }
|
||||
ASMJIT_INLINE_NODEBUG const uint8_t* end() const noexcept { return _data + _size; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
@@ -89,22 +89,22 @@ struct Expression {
|
||||
//! Resets the whole expression.
|
||||
//!
|
||||
//! Changes both values to \ref ExpressionValueType::kNone.
|
||||
inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = Expression{}; }
|
||||
|
||||
//! Sets the value type at `index` to \ref ExpressionValueType::kConstant and its content to `constant`.
|
||||
inline void setValueAsConstant(size_t index, uint64_t constant) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void setValueAsConstant(size_t index, uint64_t constant) noexcept {
|
||||
valueType[index] = ExpressionValueType::kConstant;
|
||||
value[index].constant = constant;
|
||||
}
|
||||
|
||||
//! Sets the value type at `index` to \ref ExpressionValueType::kLabel and its content to `labelEntry`.
|
||||
inline void setValueAsLabel(size_t index, LabelEntry* labelEntry) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void setValueAsLabel(size_t index, LabelEntry* labelEntry) noexcept {
|
||||
valueType[index] = ExpressionValueType::kLabel;
|
||||
value[index].label = labelEntry;
|
||||
}
|
||||
|
||||
//! Sets the value type at `index` to \ref ExpressionValueType::kExpression and its content to `expression`.
|
||||
inline void setValueAsExpression(size_t index, Expression* expression) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void setValueAsExpression(size_t index, Expression* expression) noexcept {
|
||||
valueType[index] = ExpressionValueType::kExpression;
|
||||
value[index].expression = expression;
|
||||
}
|
||||
@@ -175,36 +175,36 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the section id.
|
||||
inline uint32_t id() const noexcept { return _id; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t id() const noexcept { return _id; }
|
||||
//! Returns the section name, as a null terminated string.
|
||||
inline const char* name() const noexcept { return _name.str; }
|
||||
ASMJIT_INLINE_NODEBUG const char* name() const noexcept { return _name.str; }
|
||||
|
||||
//! Returns the section data.
|
||||
inline uint8_t* data() noexcept { return _buffer.data(); }
|
||||
ASMJIT_INLINE_NODEBUG uint8_t* data() noexcept { return _buffer.data(); }
|
||||
//! \overload
|
||||
inline const uint8_t* data() const noexcept { return _buffer.data(); }
|
||||
ASMJIT_INLINE_NODEBUG const uint8_t* data() const noexcept { return _buffer.data(); }
|
||||
|
||||
//! Returns the section flags.
|
||||
inline SectionFlags flags() const noexcept { return _flags; }
|
||||
ASMJIT_INLINE_NODEBUG SectionFlags flags() const noexcept { return _flags; }
|
||||
//! Tests whether the section has the given `flag`.
|
||||
inline bool hasFlag(SectionFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(SectionFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
//! Adds `flags` to the section flags.
|
||||
inline void addFlags(SectionFlags flags) noexcept { _flags |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG void addFlags(SectionFlags flags) noexcept { _flags |= flags; }
|
||||
//! Removes `flags` from the section flags.
|
||||
inline void clearFlags(SectionFlags flags) noexcept { _flags &= ~flags; }
|
||||
ASMJIT_INLINE_NODEBUG void clearFlags(SectionFlags flags) noexcept { _flags &= ~flags; }
|
||||
|
||||
//! Returns the minimum section alignment
|
||||
inline uint32_t alignment() const noexcept { return _alignment; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t alignment() const noexcept { return _alignment; }
|
||||
//! Sets the minimum section alignment
|
||||
inline void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; }
|
||||
ASMJIT_INLINE_NODEBUG void setAlignment(uint32_t alignment) noexcept { _alignment = alignment; }
|
||||
|
||||
//! Returns the section order, which has a higher priority than section id.
|
||||
inline int32_t order() const noexcept { return _order; }
|
||||
ASMJIT_INLINE_NODEBUG int32_t order() const noexcept { return _order; }
|
||||
|
||||
//! Returns the section offset, relative to base.
|
||||
inline uint64_t offset() const noexcept { return _offset; }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t offset() const noexcept { return _offset; }
|
||||
//! Set the section offset.
|
||||
inline void setOffset(uint64_t offset) noexcept { _offset = offset; }
|
||||
ASMJIT_INLINE_NODEBUG void setOffset(uint64_t offset) noexcept { _offset = offset; }
|
||||
|
||||
//! Returns the virtual size of the section.
|
||||
//!
|
||||
@@ -212,19 +212,19 @@ public:
|
||||
//! size returned by `bufferSize()` as the buffer stores real data emitted by assemblers or appended by users.
|
||||
//!
|
||||
//! Use `realSize()` to get the real and final size of this section.
|
||||
inline uint64_t virtualSize() const noexcept { return _virtualSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t virtualSize() const noexcept { return _virtualSize; }
|
||||
//! Sets the virtual size of the section.
|
||||
inline void setVirtualSize(uint64_t virtualSize) noexcept { _virtualSize = virtualSize; }
|
||||
ASMJIT_INLINE_NODEBUG void setVirtualSize(uint64_t virtualSize) noexcept { _virtualSize = virtualSize; }
|
||||
|
||||
//! Returns the buffer size of the section.
|
||||
inline size_t bufferSize() const noexcept { return _buffer.size(); }
|
||||
ASMJIT_INLINE_NODEBUG size_t bufferSize() const noexcept { return _buffer.size(); }
|
||||
//! Returns the real size of the section calculated from virtual and buffer sizes.
|
||||
inline uint64_t realSize() const noexcept { return Support::max<uint64_t>(virtualSize(), bufferSize()); }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t realSize() const noexcept { return Support::max<uint64_t>(virtualSize(), bufferSize()); }
|
||||
|
||||
//! Returns the `CodeBuffer` used by this section.
|
||||
inline CodeBuffer& buffer() noexcept { return _buffer; }
|
||||
ASMJIT_INLINE_NODEBUG CodeBuffer& buffer() noexcept { return _buffer; }
|
||||
//! Returns the `CodeBuffer` used by this section (const).
|
||||
inline const CodeBuffer& buffer() const noexcept { return _buffer; }
|
||||
ASMJIT_INLINE_NODEBUG const CodeBuffer& buffer() const noexcept { return _buffer; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -247,7 +247,7 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline explicit AddressTableEntry(uint64_t address) noexcept
|
||||
ASMJIT_INLINE_NODEBUG explicit AddressTableEntry(uint64_t address) noexcept
|
||||
: _address(address),
|
||||
_slot(0xFFFFFFFFu) {}
|
||||
|
||||
@@ -256,16 +256,16 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline uint64_t address() const noexcept { return _address; }
|
||||
inline uint32_t slot() const noexcept { return _slot; }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t address() const noexcept { return _address; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t slot() const noexcept { return _slot; }
|
||||
|
||||
inline bool hasAssignedSlot() const noexcept { return _slot != 0xFFFFFFFFu; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAssignedSlot() const noexcept { return _slot != 0xFFFFFFFFu; }
|
||||
|
||||
inline bool operator<(const AddressTableEntry& other) const noexcept { return _address < other._address; }
|
||||
inline bool operator>(const AddressTableEntry& other) const noexcept { return _address > other._address; }
|
||||
ASMJIT_INLINE_NODEBUG bool operator<(const AddressTableEntry& other) const noexcept { return _address < other._address; }
|
||||
ASMJIT_INLINE_NODEBUG bool operator>(const AddressTableEntry& other) const noexcept { return _address > other._address; }
|
||||
|
||||
inline bool operator<(uint64_t queryAddress) const noexcept { return _address < queryAddress; }
|
||||
inline bool operator>(uint64_t queryAddress) const noexcept { return _address > queryAddress; }
|
||||
ASMJIT_INLINE_NODEBUG bool operator<(uint64_t queryAddress) const noexcept { return _address < queryAddress; }
|
||||
ASMJIT_INLINE_NODEBUG bool operator>(uint64_t queryAddress) const noexcept { return _address > queryAddress; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -348,26 +348,26 @@ struct OffsetFormat {
|
||||
//! \{
|
||||
|
||||
//! Returns the type of the offset.
|
||||
inline OffsetType type() const noexcept { return _type; }
|
||||
ASMJIT_INLINE_NODEBUG OffsetType type() const noexcept { return _type; }
|
||||
|
||||
//! Returns flags.
|
||||
inline uint32_t flags() const noexcept { return _flags; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t flags() const noexcept { return _flags; }
|
||||
|
||||
//! Returns the size of the region/instruction where the offset is encoded.
|
||||
inline uint32_t regionSize() const noexcept { return _regionSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t regionSize() const noexcept { return _regionSize; }
|
||||
|
||||
//! Returns the offset of the word relative to the start of the region where the offset is.
|
||||
inline uint32_t valueOffset() const noexcept { return _valueOffset; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t valueOffset() const noexcept { return _valueOffset; }
|
||||
|
||||
//! Returns the size of the data-type (word) that contains the offset, in bytes.
|
||||
inline uint32_t valueSize() const noexcept { return _valueSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t valueSize() const noexcept { return _valueSize; }
|
||||
//! Returns the count of bits of the offset value in the data it's stored in.
|
||||
inline uint32_t immBitCount() const noexcept { return _immBitCount; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t immBitCount() const noexcept { return _immBitCount; }
|
||||
//! Returns the bit-shift of the offset value in the data it's stored in.
|
||||
inline uint32_t immBitShift() const noexcept { return _immBitShift; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t immBitShift() const noexcept { return _immBitShift; }
|
||||
//! Returns the number of least significant bits of the offset value, that must be zero and that are not part of
|
||||
//! the encoded data.
|
||||
inline uint32_t immDiscardLsb() const noexcept { return _immDiscardLsb; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t immDiscardLsb() const noexcept { return _immDiscardLsb; }
|
||||
|
||||
//! Resets this offset format to a simple data value of `dataSize` bytes.
|
||||
//!
|
||||
@@ -456,18 +456,18 @@ struct RelocEntry {
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline uint32_t id() const noexcept { return _id; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t id() const noexcept { return _id; }
|
||||
|
||||
inline RelocType relocType() const noexcept { return _relocType; }
|
||||
inline const OffsetFormat& format() const noexcept { return _format; }
|
||||
ASMJIT_INLINE_NODEBUG RelocType relocType() const noexcept { return _relocType; }
|
||||
ASMJIT_INLINE_NODEBUG const OffsetFormat& format() const noexcept { return _format; }
|
||||
|
||||
inline uint32_t sourceSectionId() const noexcept { return _sourceSectionId; }
|
||||
inline uint32_t targetSectionId() const noexcept { return _targetSectionId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t sourceSectionId() const noexcept { return _sourceSectionId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t targetSectionId() const noexcept { return _targetSectionId; }
|
||||
|
||||
inline uint64_t sourceOffset() const noexcept { return _sourceOffset; }
|
||||
inline uint64_t payload() const noexcept { return _payload; }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t sourceOffset() const noexcept { return _sourceOffset; }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t payload() const noexcept { return _payload; }
|
||||
|
||||
Expression* payloadAsExpression() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Expression* payloadAsExpression() const noexcept {
|
||||
return reinterpret_cast<Expression*>(uintptr_t(_payload));
|
||||
}
|
||||
|
||||
@@ -562,53 +562,53 @@ public:
|
||||
// compiler targeting 64-bit CPU will add to align the structure to 64-bits.
|
||||
|
||||
//! Returns label id.
|
||||
inline uint32_t id() const noexcept { return _customData; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t id() const noexcept { return _customData; }
|
||||
//! Sets label id (internal, used only by `CodeHolder`).
|
||||
inline void _setId(uint32_t id) noexcept { _customData = id; }
|
||||
ASMJIT_INLINE_NODEBUG void _setId(uint32_t id) noexcept { _customData = id; }
|
||||
|
||||
//! Returns label type.
|
||||
inline LabelType type() const noexcept { return _type; }
|
||||
ASMJIT_INLINE_NODEBUG LabelType type() const noexcept { return _type; }
|
||||
|
||||
//! Tests whether the label has a parent label.
|
||||
inline bool hasParent() const noexcept { return _parentId != Globals::kInvalidId; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasParent() const noexcept { return _parentId != Globals::kInvalidId; }
|
||||
//! Returns label's parent id.
|
||||
inline uint32_t parentId() const noexcept { return _parentId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t parentId() const noexcept { return _parentId; }
|
||||
|
||||
//! Returns the section where the label was bound.
|
||||
//!
|
||||
//! If the label was not yet bound the return value is `nullptr`.
|
||||
inline Section* section() const noexcept { return _section; }
|
||||
ASMJIT_INLINE_NODEBUG Section* section() const noexcept { return _section; }
|
||||
|
||||
//! Tests whether the label has name.
|
||||
inline bool hasName() const noexcept { return !_name.empty(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasName() const noexcept { return !_name.empty(); }
|
||||
|
||||
//! Returns the label's name.
|
||||
//!
|
||||
//! \note Local labels will return their local name without their parent part, for example ".L1".
|
||||
inline const char* name() const noexcept { return _name.data(); }
|
||||
ASMJIT_INLINE_NODEBUG const char* name() const noexcept { return _name.data(); }
|
||||
|
||||
//! Returns size of label's name.
|
||||
//!
|
||||
//! \note Label name is always null terminated, so you can use `strlen()` to get it, however, it's also cached in
|
||||
//! `LabelEntry` itself, so if you want to know the size the fastest way is to call `LabelEntry::nameSize()`.
|
||||
inline uint32_t nameSize() const noexcept { return _name.size(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t nameSize() const noexcept { return _name.size(); }
|
||||
|
||||
//! Returns links associated with this label.
|
||||
inline LabelLink* links() const noexcept { return _links; }
|
||||
ASMJIT_INLINE_NODEBUG LabelLink* links() const noexcept { return _links; }
|
||||
|
||||
//! Tests whether the label is bound.
|
||||
inline bool isBound() const noexcept { return _section != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool isBound() const noexcept { return _section != nullptr; }
|
||||
//! Tests whether the label is bound to a the given `sectionId`.
|
||||
inline bool isBoundTo(Section* section) const noexcept { return _section == section; }
|
||||
ASMJIT_INLINE_NODEBUG bool isBoundTo(Section* section) const noexcept { return _section == section; }
|
||||
|
||||
//! Returns the label offset (only useful if the label is bound).
|
||||
inline uint64_t offset() const noexcept { return _offset; }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t offset() const noexcept { return _offset; }
|
||||
|
||||
//! Returns the hash-value of label's name and its parent label (if any).
|
||||
//!
|
||||
//! Label hash is calculated as `HASH(Name) ^ ParentId`. The hash function is implemented in `Support::hashString()`
|
||||
//! and `Support::hashRound()`.
|
||||
inline uint32_t hashCode() const noexcept { return _hashCode; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t hashCode() const noexcept { return _hashCode; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -687,7 +687,7 @@ public:
|
||||
ASMJIT_API explicit CodeHolder(const Support::Temporary* temporary = nullptr) noexcept;
|
||||
|
||||
//! \overload
|
||||
inline explicit CodeHolder(const Support::Temporary& temporary) noexcept
|
||||
ASMJIT_INLINE_NODEBUG explicit CodeHolder(const Support::Temporary& temporary) noexcept
|
||||
: CodeHolder(&temporary) {}
|
||||
|
||||
//! Destroys the CodeHolder and frees all resources it has allocated.
|
||||
@@ -696,7 +696,7 @@ public:
|
||||
//! Tests whether the `CodeHolder` has been initialized.
|
||||
//!
|
||||
//! Emitters can be only attached to initialized `CodeHolder` instances.
|
||||
inline bool isInitialized() const noexcept { return _environment.isInitialized(); }
|
||||
ASMJIT_INLINE_NODEBUG bool isInitialized() const noexcept { return _environment.isInitialized(); }
|
||||
|
||||
//! Initializes CodeHolder to hold code described by the given `environment` and `baseAddress`.
|
||||
ASMJIT_API Error init(const Environment& environment, uint64_t baseAddress = Globals::kNoBaseAddress) noexcept;
|
||||
@@ -725,7 +725,7 @@ public:
|
||||
//! \note This should be only used for AsmJit's purposes. Code holder uses arena allocator to allocate everything,
|
||||
//! so anything allocated through this allocator will be invalidated by \ref CodeHolder::reset() or by CodeHolder's
|
||||
//! destructor.
|
||||
inline ZoneAllocator* allocator() const noexcept { return const_cast<ZoneAllocator*>(&_allocator); }
|
||||
ASMJIT_INLINE_NODEBUG ZoneAllocator* allocator() const noexcept { return const_cast<ZoneAllocator*>(&_allocator); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -733,20 +733,20 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the target environment information.
|
||||
inline const Environment& environment() const noexcept { return _environment; }
|
||||
ASMJIT_INLINE_NODEBUG const Environment& environment() const noexcept { return _environment; }
|
||||
|
||||
//! Returns the target architecture.
|
||||
inline Arch arch() const noexcept { return environment().arch(); }
|
||||
ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return environment().arch(); }
|
||||
//! Returns the target sub-architecture.
|
||||
inline SubArch subArch() const noexcept { return environment().subArch(); }
|
||||
ASMJIT_INLINE_NODEBUG SubArch subArch() const noexcept { return environment().subArch(); }
|
||||
|
||||
//! Returns the minimum CPU features of the target architecture.
|
||||
inline const CpuFeatures& cpuFeatures() const noexcept { return _cpuFeatures; }
|
||||
ASMJIT_INLINE_NODEBUG const CpuFeatures& cpuFeatures() const noexcept { return _cpuFeatures; }
|
||||
|
||||
//! Tests whether a static base-address is set.
|
||||
inline bool hasBaseAddress() const noexcept { return _baseAddress != Globals::kNoBaseAddress; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasBaseAddress() const noexcept { return _baseAddress != Globals::kNoBaseAddress; }
|
||||
//! Returns a static base-address or \ref Globals::kNoBaseAddress, if not set.
|
||||
inline uint64_t baseAddress() const noexcept { return _baseAddress; }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t baseAddress() const noexcept { return _baseAddress; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -754,7 +754,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns a vector of attached emitters.
|
||||
inline const ZoneVector<BaseEmitter*>& emitters() const noexcept { return _emitters; }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneVector<BaseEmitter*>& emitters() const noexcept { return _emitters; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -762,23 +762,23 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the attached logger.
|
||||
inline Logger* logger() const noexcept { return _logger; }
|
||||
ASMJIT_INLINE_NODEBUG Logger* logger() const noexcept { return _logger; }
|
||||
//! Attaches a `logger` to CodeHolder and propagates it to all attached emitters.
|
||||
ASMJIT_API void setLogger(Logger* logger) noexcept;
|
||||
//! Resets the logger to none.
|
||||
inline void resetLogger() noexcept { setLogger(nullptr); }
|
||||
ASMJIT_INLINE_NODEBUG void resetLogger() noexcept { setLogger(nullptr); }
|
||||
|
||||
//! \name Error Handling
|
||||
//! \{
|
||||
|
||||
//! Tests whether the CodeHolder has an attached error handler, see \ref ErrorHandler.
|
||||
inline bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; }
|
||||
//! Returns the attached error handler.
|
||||
inline ErrorHandler* errorHandler() const noexcept { return _errorHandler; }
|
||||
ASMJIT_INLINE_NODEBUG ErrorHandler* errorHandler() const noexcept { return _errorHandler; }
|
||||
//! Attach an error handler to this `CodeHolder`.
|
||||
ASMJIT_API void setErrorHandler(ErrorHandler* errorHandler) noexcept;
|
||||
//! Resets the error handler to none.
|
||||
inline void resetErrorHandler() noexcept { setErrorHandler(nullptr); }
|
||||
ASMJIT_INLINE_NODEBUG void resetErrorHandler() noexcept { setErrorHandler(nullptr); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -801,14 +801,14 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns an array of `Section*` records.
|
||||
inline const ZoneVector<Section*>& sections() const noexcept { return _sections; }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneVector<Section*>& sections() const noexcept { return _sections; }
|
||||
//! Returns an array of `Section*` records sorted according to section order first, then section id.
|
||||
inline const ZoneVector<Section*>& sectionsByOrder() const noexcept { return _sectionsByOrder; }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneVector<Section*>& sectionsByOrder() const noexcept { return _sectionsByOrder; }
|
||||
//! Returns the number of sections.
|
||||
inline uint32_t sectionCount() const noexcept { return _sections.size(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t sectionCount() const noexcept { return _sections.size(); }
|
||||
|
||||
//! Tests whether the given `sectionId` is valid.
|
||||
inline bool isSectionValid(uint32_t sectionId) const noexcept { return sectionId < _sections.size(); }
|
||||
ASMJIT_INLINE_NODEBUG bool isSectionValid(uint32_t sectionId) const noexcept { return sectionId < _sections.size(); }
|
||||
|
||||
//! Creates a new section and return its pointer in `sectionOut`.
|
||||
//!
|
||||
@@ -816,7 +816,7 @@ public:
|
||||
ASMJIT_API Error newSection(Section** sectionOut, const char* name, size_t nameSize = SIZE_MAX, SectionFlags flags = SectionFlags::kNone, uint32_t alignment = 1, int32_t order = 0) noexcept;
|
||||
|
||||
//! Returns a section entry of the given index.
|
||||
inline Section* sectionById(uint32_t sectionId) const noexcept { return _sections[sectionId]; }
|
||||
ASMJIT_INLINE_NODEBUG Section* sectionById(uint32_t sectionId) const noexcept { return _sections[sectionId]; }
|
||||
|
||||
//! Returns section-id that matches the given `name`.
|
||||
//!
|
||||
@@ -826,10 +826,10 @@ public:
|
||||
//! Returns '.text' section (section that commonly represents code).
|
||||
//!
|
||||
//! \note Text section is always the first section in \ref CodeHolder::sections() array.
|
||||
inline Section* textSection() const noexcept { return _sections[0]; }
|
||||
ASMJIT_INLINE_NODEBUG Section* textSection() const noexcept { return _sections[0]; }
|
||||
|
||||
//! Tests whether '.addrtab' section exists.
|
||||
inline bool hasAddressTable() const noexcept { return _addressTableSection != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAddressTable() const noexcept { return _addressTableSection != nullptr; }
|
||||
|
||||
//! Returns '.addrtab' section.
|
||||
//!
|
||||
@@ -837,7 +837,7 @@ public:
|
||||
//! addresses that cannot be encoded in instructions like 'jmp' or 'call'.
|
||||
//!
|
||||
//! \note This section is created on demand, the returned pointer can be null.
|
||||
inline Section* addressTableSection() const noexcept { return _addressTableSection; }
|
||||
ASMJIT_INLINE_NODEBUG Section* addressTableSection() const noexcept { return _addressTableSection; }
|
||||
|
||||
//! Ensures that '.addrtab' section exists (creates it if it doesn't) and
|
||||
//! returns it. Can return `nullptr` on out of memory condition.
|
||||
@@ -859,40 +859,40 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns array of `LabelEntry*` records.
|
||||
inline const ZoneVector<LabelEntry*>& labelEntries() const noexcept { return _labelEntries; }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneVector<LabelEntry*>& labelEntries() const noexcept { return _labelEntries; }
|
||||
|
||||
//! Returns number of labels created.
|
||||
inline uint32_t labelCount() const noexcept { return _labelEntries.size(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t labelCount() const noexcept { return _labelEntries.size(); }
|
||||
|
||||
//! Tests whether the label having `id` is valid (i.e. created by `newLabelEntry()`).
|
||||
inline bool isLabelValid(uint32_t labelId) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool isLabelValid(uint32_t labelId) const noexcept {
|
||||
return labelId < _labelEntries.size();
|
||||
}
|
||||
|
||||
//! Tests whether the `label` is valid (i.e. created by `newLabelEntry()`).
|
||||
inline bool isLabelValid(const Label& label) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool isLabelValid(const Label& label) const noexcept {
|
||||
return label.id() < _labelEntries.size();
|
||||
}
|
||||
|
||||
//! \overload
|
||||
inline bool isLabelBound(uint32_t labelId) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool isLabelBound(uint32_t labelId) const noexcept {
|
||||
return isLabelValid(labelId) && _labelEntries[labelId]->isBound();
|
||||
}
|
||||
|
||||
//! Tests whether the `label` is already bound.
|
||||
//!
|
||||
//! Returns `false` if the `label` is not valid.
|
||||
inline bool isLabelBound(const Label& label) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool isLabelBound(const Label& label) const noexcept {
|
||||
return isLabelBound(label.id());
|
||||
}
|
||||
|
||||
//! Returns LabelEntry of the given label `id`.
|
||||
inline LabelEntry* labelEntry(uint32_t labelId) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG LabelEntry* labelEntry(uint32_t labelId) const noexcept {
|
||||
return isLabelValid(labelId) ? _labelEntries[labelId] : static_cast<LabelEntry*>(nullptr);
|
||||
}
|
||||
|
||||
//! Returns LabelEntry of the given `label`.
|
||||
inline LabelEntry* labelEntry(const Label& label) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG LabelEntry* labelEntry(const Label& label) const noexcept {
|
||||
return labelEntry(label.id());
|
||||
}
|
||||
|
||||
@@ -900,13 +900,13 @@ public:
|
||||
//!
|
||||
//! The offset returned is relative to the start of the section. Zero offset is returned for unbound labels,
|
||||
//! which is their initial offset value.
|
||||
inline uint64_t labelOffset(uint32_t labelId) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG uint64_t labelOffset(uint32_t labelId) const noexcept {
|
||||
ASMJIT_ASSERT(isLabelValid(labelId));
|
||||
return _labelEntries[labelId]->offset();
|
||||
}
|
||||
|
||||
//! \overload
|
||||
inline uint64_t labelOffset(const Label& label) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG uint64_t labelOffset(const Label& label) const noexcept {
|
||||
return labelOffset(label.id());
|
||||
}
|
||||
|
||||
@@ -951,7 +951,7 @@ public:
|
||||
//!
|
||||
//! If the named label doesn't a default constructed \ref Label is returned,
|
||||
//! which has its id set to \ref Globals::kInvalidId.
|
||||
inline Label labelByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Label labelByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept {
|
||||
return Label(labelIdByName(name, nameSize, parentId));
|
||||
}
|
||||
|
||||
@@ -961,9 +961,9 @@ public:
|
||||
ASMJIT_API uint32_t labelIdByName(const char* name, size_t nameSize = SIZE_MAX, uint32_t parentId = Globals::kInvalidId) noexcept;
|
||||
|
||||
//! Tests whether there are any unresolved label links.
|
||||
inline bool hasUnresolvedLinks() const noexcept { return _unresolvedLinkCount != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasUnresolvedLinks() const noexcept { return _unresolvedLinkCount != 0; }
|
||||
//! Returns the number of label links, which are unresolved.
|
||||
inline size_t unresolvedLinkCount() const noexcept { return _unresolvedLinkCount; }
|
||||
ASMJIT_INLINE_NODEBUG size_t unresolvedLinkCount() const noexcept { return _unresolvedLinkCount; }
|
||||
|
||||
//! Creates a new label-link used to store information about yet unbound labels.
|
||||
//!
|
||||
@@ -986,12 +986,12 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether the code contains relocation entries.
|
||||
inline bool hasRelocEntries() const noexcept { return !_relocations.empty(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasRelocEntries() const noexcept { return !_relocations.empty(); }
|
||||
//! Returns array of `RelocEntry*` records.
|
||||
inline const ZoneVector<RelocEntry*>& relocEntries() const noexcept { return _relocations; }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneVector<RelocEntry*>& relocEntries() const noexcept { return _relocations; }
|
||||
|
||||
//! Returns a RelocEntry of the given `id`.
|
||||
inline RelocEntry* relocEntry(uint32_t id) const noexcept { return _relocations[id]; }
|
||||
ASMJIT_INLINE_NODEBUG RelocEntry* relocEntry(uint32_t id) const noexcept { return _relocations[id]; }
|
||||
|
||||
//! Creates a new relocation entry of type `relocType`.
|
||||
//!
|
||||
|
||||
@@ -95,7 +95,7 @@ public:
|
||||
ASMJIT_API Error addFuncRetNode(FuncRetNode** ASMJIT_NONNULL(out), const Operand_& o0, const Operand_& o1);
|
||||
|
||||
//! Returns the current function.
|
||||
inline FuncNode* func() const noexcept { return _func; }
|
||||
ASMJIT_INLINE_NODEBUG FuncNode* func() const noexcept { return _func; }
|
||||
|
||||
//! Creates a new \ref FuncNode with the given `signature` and returns it.
|
||||
inline FuncNode* newFunc(const FuncSignature& signature) {
|
||||
@@ -172,12 +172,12 @@ public:
|
||||
ASMJIT_API Error _newRegFmt(BaseReg* ASMJIT_NONNULL(out), const BaseReg& ref, const char* fmt, ...);
|
||||
|
||||
//! Tests whether the given `id` is a valid virtual register id.
|
||||
inline bool isVirtIdValid(uint32_t id) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool isVirtIdValid(uint32_t id) const noexcept {
|
||||
uint32_t index = Operand::virtIdToIndex(id);
|
||||
return index < _vRegArray.size();
|
||||
}
|
||||
//! Tests whether the given `reg` is a virtual register having a valid id.
|
||||
inline bool isVirtRegValid(const BaseReg& reg) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool isVirtRegValid(const BaseReg& reg) const noexcept {
|
||||
return isVirtIdValid(reg.id());
|
||||
}
|
||||
|
||||
@@ -188,16 +188,16 @@ public:
|
||||
}
|
||||
|
||||
//! Returns \ref VirtReg associated with the given `reg`.
|
||||
inline VirtReg* virtRegByReg(const BaseReg& reg) const noexcept { return virtRegById(reg.id()); }
|
||||
ASMJIT_INLINE_NODEBUG VirtReg* virtRegByReg(const BaseReg& reg) const noexcept { return virtRegById(reg.id()); }
|
||||
|
||||
//! Returns \ref VirtReg associated with the given virtual register `index`.
|
||||
//!
|
||||
//! \note This is not the same as virtual register id. The conversion between id and its index is implemented
|
||||
//! by \ref Operand_::virtIdToIndex() and \ref Operand_::indexToVirtId() functions.
|
||||
inline VirtReg* virtRegByIndex(uint32_t index) const noexcept { return _vRegArray[index]; }
|
||||
ASMJIT_INLINE_NODEBUG VirtReg* virtRegByIndex(uint32_t index) const noexcept { return _vRegArray[index]; }
|
||||
|
||||
//! Returns an array of all virtual registers managed by the Compiler.
|
||||
inline const ZoneVector<VirtReg*>& virtRegs() const noexcept { return _vRegArray; }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneVector<VirtReg*>& virtRegs() const noexcept { return _vRegArray; }
|
||||
|
||||
//! \name Stack
|
||||
//! \{
|
||||
@@ -211,7 +211,7 @@ public:
|
||||
ASMJIT_API Error setStackSize(uint32_t virtId, uint32_t newSize, uint32_t newAlignment = 0);
|
||||
|
||||
//! Updates the stack size of a stack created by `_newStack()`.
|
||||
inline Error setStackSize(const BaseMem& mem, uint32_t newSize, uint32_t newAlignment = 0) {
|
||||
ASMJIT_INLINE_NODEBUG Error setStackSize(const BaseMem& mem, uint32_t newSize, uint32_t newAlignment = 0) {
|
||||
return setStackSize(mem.id(), newSize, newAlignment);
|
||||
}
|
||||
|
||||
@@ -239,7 +239,7 @@ public:
|
||||
//! \name Jump Annotations
|
||||
//! \{
|
||||
|
||||
inline const ZoneVector<JumpAnnotation*>& jumpAnnotations() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG const ZoneVector<JumpAnnotation*>& jumpAnnotations() const noexcept {
|
||||
return _jumpAnnotations;
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline JumpAnnotation(BaseCompiler* ASMJIT_NONNULL(compiler), uint32_t annotationId) noexcept
|
||||
ASMJIT_INLINE_NODEBUG JumpAnnotation(BaseCompiler* ASMJIT_NONNULL(compiler), uint32_t annotationId) noexcept
|
||||
: _compiler(compiler),
|
||||
_annotationId(annotationId) {}
|
||||
|
||||
@@ -296,16 +296,16 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the compiler that owns this JumpAnnotation.
|
||||
inline BaseCompiler* compiler() const noexcept { return _compiler; }
|
||||
ASMJIT_INLINE_NODEBUG BaseCompiler* compiler() const noexcept { return _compiler; }
|
||||
//! Returns the annotation id.
|
||||
inline uint32_t annotationId() const noexcept { return _annotationId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t annotationId() const noexcept { return _annotationId; }
|
||||
//! Returns a vector of label identifiers that lists all targets of the jump.
|
||||
const ZoneVector<uint32_t>& labelIds() const noexcept { return _labelIds; }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneVector<uint32_t>& labelIds() const noexcept { return _labelIds; }
|
||||
|
||||
//! Tests whether the given `label` is a target of this JumpAnnotation.
|
||||
inline bool hasLabel(const Label& label) const noexcept { return hasLabelId(label.id()); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasLabel(const Label& label) const noexcept { return hasLabelId(label.id()); }
|
||||
//! Tests whether the given `labelId` is a target of this JumpAnnotation.
|
||||
inline bool hasLabelId(uint32_t labelId) const noexcept { return _labelIds.contains(labelId); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasLabelId(uint32_t labelId) const noexcept { return _labelIds.contains(labelId); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -313,9 +313,9 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Adds the `label` to the list of targets of this JumpAnnotation.
|
||||
inline Error addLabel(const Label& label) noexcept { return addLabelId(label.id()); }
|
||||
ASMJIT_INLINE_NODEBUG Error addLabel(const Label& label) noexcept { return addLabelId(label.id()); }
|
||||
//! Adds the `labelId` to the list of targets of this JumpAnnotation.
|
||||
inline Error addLabelId(uint32_t labelId) noexcept { return _labelIds.append(&_compiler->_allocator, labelId); }
|
||||
ASMJIT_INLINE_NODEBUG Error addLabelId(uint32_t labelId) noexcept { return _labelIds.append(&_compiler->_allocator, labelId); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -351,11 +351,11 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether this JumpNode has associated a \ref JumpAnnotation.
|
||||
inline bool hasAnnotation() const noexcept { return _annotation != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAnnotation() const noexcept { return _annotation != nullptr; }
|
||||
//! Returns the \ref JumpAnnotation associated with this jump, or `nullptr`.
|
||||
inline JumpAnnotation* annotation() const noexcept { return _annotation; }
|
||||
ASMJIT_INLINE_NODEBUG JumpAnnotation* annotation() const noexcept { return _annotation; }
|
||||
//! Sets the \ref JumpAnnotation associated with this jump to `annotation`.
|
||||
inline void setAnnotation(JumpAnnotation* annotation) noexcept { _annotation = annotation; }
|
||||
ASMJIT_INLINE_NODEBUG void setAnnotation(JumpAnnotation* annotation) noexcept { _annotation = annotation; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -455,35 +455,35 @@ public:
|
||||
//! \name Accessors
|
||||
|
||||
//! Returns function exit `LabelNode`.
|
||||
inline LabelNode* exitNode() const noexcept { return _exitNode; }
|
||||
ASMJIT_INLINE_NODEBUG LabelNode* exitNode() const noexcept { return _exitNode; }
|
||||
//! Returns function exit label.
|
||||
inline Label exitLabel() const noexcept { return _exitNode->label(); }
|
||||
ASMJIT_INLINE_NODEBUG Label exitLabel() const noexcept { return _exitNode->label(); }
|
||||
|
||||
//! Returns "End of Func" sentinel node.
|
||||
inline SentinelNode* endNode() const noexcept { return _end; }
|
||||
ASMJIT_INLINE_NODEBUG SentinelNode* endNode() const noexcept { return _end; }
|
||||
|
||||
//! Returns function detail.
|
||||
inline FuncDetail& detail() noexcept { return _funcDetail; }
|
||||
ASMJIT_INLINE_NODEBUG FuncDetail& detail() noexcept { return _funcDetail; }
|
||||
//! Returns function detail.
|
||||
inline const FuncDetail& detail() const noexcept { return _funcDetail; }
|
||||
ASMJIT_INLINE_NODEBUG const FuncDetail& detail() const noexcept { return _funcDetail; }
|
||||
|
||||
//! Returns function frame.
|
||||
inline FuncFrame& frame() noexcept { return _frame; }
|
||||
ASMJIT_INLINE_NODEBUG FuncFrame& frame() noexcept { return _frame; }
|
||||
//! Returns function frame.
|
||||
inline const FuncFrame& frame() const noexcept { return _frame; }
|
||||
ASMJIT_INLINE_NODEBUG const FuncFrame& frame() const noexcept { return _frame; }
|
||||
|
||||
//! Returns function attributes.
|
||||
inline FuncAttributes attributes() const noexcept { return _frame.attributes(); }
|
||||
ASMJIT_INLINE_NODEBUG FuncAttributes attributes() const noexcept { return _frame.attributes(); }
|
||||
//! Adds `attrs` to the function attributes.
|
||||
inline void addAttributes(FuncAttributes attrs) noexcept { _frame.addAttributes(attrs); }
|
||||
ASMJIT_INLINE_NODEBUG void addAttributes(FuncAttributes attrs) noexcept { _frame.addAttributes(attrs); }
|
||||
|
||||
//! Returns arguments count.
|
||||
inline uint32_t argCount() const noexcept { return _funcDetail.argCount(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t argCount() const noexcept { return _funcDetail.argCount(); }
|
||||
//! Returns argument packs.
|
||||
inline ArgPack* argPacks() const noexcept { return _args; }
|
||||
ASMJIT_INLINE_NODEBUG ArgPack* argPacks() const noexcept { return _args; }
|
||||
|
||||
//! Tests whether the function has a return value.
|
||||
inline bool hasRet() const noexcept { return _funcDetail.hasRet(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasRet() const noexcept { return _funcDetail.hasRet(); }
|
||||
|
||||
//! Returns argument pack at `argIndex`.
|
||||
inline ArgPack& argPack(size_t argIndex) const noexcept {
|
||||
@@ -614,29 +614,29 @@ public:
|
||||
}
|
||||
|
||||
//! Returns the function detail.
|
||||
inline FuncDetail& detail() noexcept { return _funcDetail; }
|
||||
ASMJIT_INLINE_NODEBUG FuncDetail& detail() noexcept { return _funcDetail; }
|
||||
//! Returns the function detail.
|
||||
inline const FuncDetail& detail() const noexcept { return _funcDetail; }
|
||||
ASMJIT_INLINE_NODEBUG const FuncDetail& detail() const noexcept { return _funcDetail; }
|
||||
|
||||
//! Returns the target operand.
|
||||
inline Operand& target() noexcept { return _opArray[0].as<Operand>(); }
|
||||
ASMJIT_INLINE_NODEBUG Operand& target() noexcept { return _opArray[0].as<Operand>(); }
|
||||
//! \overload
|
||||
inline const Operand& target() const noexcept { return _opArray[0].as<Operand>(); }
|
||||
ASMJIT_INLINE_NODEBUG const Operand& target() const noexcept { return _opArray[0].as<Operand>(); }
|
||||
|
||||
//! Returns the number of function return values.
|
||||
inline bool hasRet() const noexcept { return _funcDetail.hasRet(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasRet() const noexcept { return _funcDetail.hasRet(); }
|
||||
//! Returns the number of function arguments.
|
||||
inline uint32_t argCount() const noexcept { return _funcDetail.argCount(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t argCount() const noexcept { return _funcDetail.argCount(); }
|
||||
|
||||
//! Returns operand pack representing function return value(s).
|
||||
inline OperandPack& retPack() noexcept { return _rets; }
|
||||
ASMJIT_INLINE_NODEBUG OperandPack& retPack() noexcept { return _rets; }
|
||||
//! Returns operand pack representing function return value(s).
|
||||
inline const OperandPack& retPack() const noexcept { return _rets; }
|
||||
ASMJIT_INLINE_NODEBUG const OperandPack& retPack() const noexcept { return _rets; }
|
||||
|
||||
//! Returns the return value at the given `valueIndex`.
|
||||
inline Operand& ret(size_t valueIndex = 0) noexcept { return _rets[valueIndex]; }
|
||||
ASMJIT_INLINE_NODEBUG Operand& ret(size_t valueIndex = 0) noexcept { return _rets[valueIndex]; }
|
||||
//! \overload
|
||||
inline const Operand& ret(size_t valueIndex = 0) const noexcept { return _rets[valueIndex]; }
|
||||
ASMJIT_INLINE_NODEBUG const Operand& ret(size_t valueIndex = 0) const noexcept { return _rets[valueIndex]; }
|
||||
|
||||
//! Returns operand pack representing function return value(s).
|
||||
inline OperandPack& argPack(size_t argIndex) noexcept {
|
||||
@@ -669,17 +669,17 @@ public:
|
||||
}
|
||||
|
||||
//! Sets the function return value at `valueIndex` to `reg`.
|
||||
inline void setRet(size_t valueIndex, const BaseReg& reg) noexcept { _setRet(valueIndex, reg); }
|
||||
ASMJIT_INLINE_NODEBUG void setRet(size_t valueIndex, const BaseReg& reg) noexcept { _setRet(valueIndex, reg); }
|
||||
|
||||
//! Sets the first function argument in a value-pack at `argIndex` to `reg`.
|
||||
inline void setArg(size_t argIndex, const BaseReg& reg) noexcept { _setArg(argIndex, 0, reg); }
|
||||
ASMJIT_INLINE_NODEBUG void setArg(size_t argIndex, const BaseReg& reg) noexcept { _setArg(argIndex, 0, reg); }
|
||||
//! Sets the first function argument in a value-pack at `argIndex` to `imm`.
|
||||
inline void setArg(size_t argIndex, const Imm& imm) noexcept { _setArg(argIndex, 0, imm); }
|
||||
ASMJIT_INLINE_NODEBUG void setArg(size_t argIndex, const Imm& imm) noexcept { _setArg(argIndex, 0, imm); }
|
||||
|
||||
//! Sets the function argument at `argIndex` and `valueIndex` to `reg`.
|
||||
inline void setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg) noexcept { _setArg(argIndex, valueIndex, reg); }
|
||||
ASMJIT_INLINE_NODEBUG void setArg(size_t argIndex, size_t valueIndex, const BaseReg& reg) noexcept { _setArg(argIndex, valueIndex, reg); }
|
||||
//! Sets the function argument at `argIndex` and `valueIndex` to `imm`.
|
||||
inline void setArg(size_t argIndex, size_t valueIndex, const Imm& imm) noexcept { _setArg(argIndex, valueIndex, imm); }
|
||||
ASMJIT_INLINE_NODEBUG void setArg(size_t argIndex, size_t valueIndex, const Imm& imm) noexcept { _setArg(argIndex, valueIndex, imm); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -701,7 +701,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the associated `BaseCompiler`.
|
||||
inline BaseCompiler* cc() const noexcept { return static_cast<BaseCompiler*>(_cb); }
|
||||
ASMJIT_INLINE_NODEBUG BaseCompiler* cc() const noexcept { return static_cast<BaseCompiler*>(_cb); }
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
@@ -66,18 +66,16 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline VirtReg(OperandSignature signature, uint32_t id, uint32_t virtSize, uint32_t alignment, TypeId typeId) noexcept
|
||||
ASMJIT_INLINE_NODEBUG VirtReg(OperandSignature signature, uint32_t id, uint32_t virtSize, uint32_t alignment, TypeId typeId) noexcept
|
||||
: _signature(signature),
|
||||
_id(id),
|
||||
_virtSize(virtSize),
|
||||
_alignment(uint8_t(alignment)),
|
||||
_typeId(typeId),
|
||||
_isFixed(false),
|
||||
_isStack(false),
|
||||
_hasStackSlot(false),
|
||||
_reservedBits(0),
|
||||
_stackOffset(0),
|
||||
_reservedU32(0) {}
|
||||
_isFixed(0),
|
||||
_isStack(0),
|
||||
_hasStackSlot(0),
|
||||
_reservedBits(0) {}
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -85,64 +83,64 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the virtual register id.
|
||||
inline uint32_t id() const noexcept { return _id; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t id() const noexcept { return _id; }
|
||||
|
||||
//! Returns the virtual register name.
|
||||
inline const char* name() const noexcept { return _name.data(); }
|
||||
ASMJIT_INLINE_NODEBUG const char* name() const noexcept { return _name.data(); }
|
||||
//! Returns the size of the virtual register name.
|
||||
inline uint32_t nameSize() const noexcept { return _name.size(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t nameSize() const noexcept { return _name.size(); }
|
||||
|
||||
//! Returns a register signature of this virtual register.
|
||||
inline OperandSignature signature() const noexcept { return _signature; }
|
||||
ASMJIT_INLINE_NODEBUG OperandSignature signature() const noexcept { return _signature; }
|
||||
//! Returns a virtual register type (maps to the physical register type as well).
|
||||
inline RegType type() const noexcept { return _signature.regType(); }
|
||||
ASMJIT_INLINE_NODEBUG RegType type() const noexcept { return _signature.regType(); }
|
||||
//! Returns a virtual register group (maps to the physical register group as well).
|
||||
inline RegGroup group() const noexcept { return _signature.regGroup(); }
|
||||
ASMJIT_INLINE_NODEBUG RegGroup group() const noexcept { return _signature.regGroup(); }
|
||||
|
||||
//! Returns a real size of the register this virtual register maps to.
|
||||
//!
|
||||
//! For example if this is a 128-bit SIMD register used for a scalar single precision floating point value then
|
||||
//! its virtSize would be 4, however, the `regSize` would still say 16 (128-bits), because it's the smallest size
|
||||
//! of that register type.
|
||||
inline uint32_t regSize() const noexcept { return _signature.size(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t regSize() const noexcept { return _signature.size(); }
|
||||
|
||||
//! Returns the virtual register size.
|
||||
//!
|
||||
//! The virtual register size describes how many bytes the virtual register needs to store its content. It can be
|
||||
//! smaller than the physical register size, see `regSize()`.
|
||||
inline uint32_t virtSize() const noexcept { return _virtSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t virtSize() const noexcept { return _virtSize; }
|
||||
|
||||
//! Returns the virtual register alignment.
|
||||
inline uint32_t alignment() const noexcept { return _alignment; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t alignment() const noexcept { return _alignment; }
|
||||
|
||||
//! Returns the virtual register type id.
|
||||
inline TypeId typeId() const noexcept { return _typeId; }
|
||||
ASMJIT_INLINE_NODEBUG TypeId typeId() const noexcept { return _typeId; }
|
||||
|
||||
//! Returns the virtual register weight - the register allocator can use it as explicit hint for alloc/spill
|
||||
//! decisions.
|
||||
inline uint32_t weight() const noexcept { return _weight; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t weight() const noexcept { return _weight; }
|
||||
//! Sets the virtual register weight (0 to 255) - the register allocator can use it as explicit hint for
|
||||
//! alloc/spill decisions and initial bin-packing.
|
||||
inline void setWeight(uint32_t weight) noexcept { _weight = uint8_t(weight); }
|
||||
ASMJIT_INLINE_NODEBUG void setWeight(uint32_t weight) noexcept { _weight = uint8_t(weight); }
|
||||
|
||||
//! Returns whether the virtual register is always allocated to a fixed physical register (and never reallocated).
|
||||
//!
|
||||
//! \note This is only used for special purposes and it's mostly internal.
|
||||
inline bool isFixed() const noexcept { return bool(_isFixed); }
|
||||
ASMJIT_INLINE_NODEBUG bool isFixed() const noexcept { return bool(_isFixed); }
|
||||
|
||||
//! Tests whether the virtual register is in fact a stack that only uses the virtual register id.
|
||||
//!
|
||||
//! \note It's an error if a stack is accessed as a register.
|
||||
inline bool isStack() const noexcept { return bool(_isStack); }
|
||||
ASMJIT_INLINE_NODEBUG bool isStack() const noexcept { return bool(_isStack); }
|
||||
|
||||
//! Tests whether this virtual register (or stack) has assigned a stack offset.
|
||||
//!
|
||||
//! If this is a virtual register that was never allocated on stack, it would return false, otherwise if
|
||||
//! it's a virtual register that was spilled or explicitly allocated stack, the return value would be true.
|
||||
inline bool hasStackSlot() const noexcept { return bool(_hasStackSlot); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasStackSlot() const noexcept { return bool(_hasStackSlot); }
|
||||
|
||||
//! Assigns a stack offset of this virtual register to `stackOffset` and sets `_hasStackSlot` to true.
|
||||
inline void assignStackSlot(int32_t stackOffset) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void assignStackSlot(int32_t stackOffset) noexcept {
|
||||
_hasStackSlot = 1;
|
||||
_stackOffset = stackOffset;
|
||||
}
|
||||
@@ -151,16 +149,16 @@ public:
|
||||
//!
|
||||
//! \note Always verify that the stack offset has been assigned by calling \ref hasStackSlot(). The return
|
||||
//! value will be zero when the stack offset was not assigned.
|
||||
inline int32_t stackOffset() const noexcept { return _stackOffset; }
|
||||
ASMJIT_INLINE_NODEBUG int32_t stackOffset() const noexcept { return _stackOffset; }
|
||||
|
||||
//! Tests whether the virtual register has an associated `RAWorkReg` at the moment.
|
||||
inline bool hasWorkReg() const noexcept { return _workReg != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasWorkReg() const noexcept { return _workReg != nullptr; }
|
||||
//! Returns an associated RAWorkReg with this virtual register (only valid during register allocation).
|
||||
inline RAWorkReg* workReg() const noexcept { return _workReg; }
|
||||
ASMJIT_INLINE_NODEBUG RAWorkReg* workReg() const noexcept { return _workReg; }
|
||||
//! Associates a RAWorkReg with this virtual register (used by register allocator).
|
||||
inline void setWorkReg(RAWorkReg* workReg) noexcept { _workReg = workReg; }
|
||||
ASMJIT_INLINE_NODEBUG void setWorkReg(RAWorkReg* workReg) noexcept { _workReg = workReg; }
|
||||
//! Reset the RAWorkReg association (used by register allocator).
|
||||
inline void resetWorkReg() noexcept { _workReg = nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG void resetWorkReg() noexcept { _workReg = nullptr; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
@@ -65,12 +65,12 @@ public:
|
||||
//! Data offset from the beginning of the pool.
|
||||
uint32_t _offset;
|
||||
|
||||
inline Node(size_t offset, bool shared) noexcept
|
||||
ASMJIT_INLINE_NODEBUG Node(size_t offset, bool shared) noexcept
|
||||
: ZoneTreeNodeT<Node>(),
|
||||
_shared(shared),
|
||||
_offset(uint32_t(offset)) {}
|
||||
|
||||
inline void* data() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void* data() const noexcept {
|
||||
return static_cast<void*>(const_cast<ConstPool::Node*>(this) + 1);
|
||||
}
|
||||
};
|
||||
@@ -80,14 +80,14 @@ public:
|
||||
public:
|
||||
size_t _dataSize;
|
||||
|
||||
inline Compare(size_t dataSize) noexcept
|
||||
ASMJIT_INLINE_NODEBUG Compare(size_t dataSize) noexcept
|
||||
: _dataSize(dataSize) {}
|
||||
|
||||
inline int operator()(const Node& a, const Node& b) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG int operator()(const Node& a, const Node& b) const noexcept {
|
||||
return ::memcmp(a.data(), b.data(), _dataSize);
|
||||
}
|
||||
|
||||
inline int operator()(const Node& a, const void* data) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG int operator()(const Node& a, const void* data) const noexcept {
|
||||
return ::memcmp(a.data(), data, _dataSize);
|
||||
}
|
||||
};
|
||||
@@ -101,30 +101,30 @@ public:
|
||||
//! Size of the data.
|
||||
size_t _dataSize;
|
||||
|
||||
inline explicit Tree(size_t dataSize = 0) noexcept
|
||||
ASMJIT_INLINE_NODEBUG explicit Tree(size_t dataSize = 0) noexcept
|
||||
: _tree(),
|
||||
_size(0),
|
||||
_dataSize(dataSize) {}
|
||||
|
||||
inline void reset() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept {
|
||||
_tree.reset();
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
inline bool empty() const noexcept { return _size == 0; }
|
||||
inline size_t size() const noexcept { return _size; }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _size == 0; }
|
||||
ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return _size; }
|
||||
|
||||
inline void setDataSize(size_t dataSize) noexcept {
|
||||
ASMJIT_ASSERT(empty());
|
||||
_dataSize = dataSize;
|
||||
}
|
||||
|
||||
inline Node* get(const void* data) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Node* get(const void* data) noexcept {
|
||||
Compare cmp(_dataSize);
|
||||
return _tree.get(data, cmp);
|
||||
}
|
||||
|
||||
inline void insert(Node* node) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void insert(Node* node) noexcept {
|
||||
Compare cmp(_dataSize);
|
||||
_tree.insert(node, cmp);
|
||||
_size++;
|
||||
@@ -210,13 +210,13 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether the constant-pool is empty.
|
||||
inline bool empty() const noexcept { return _size == 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _size == 0; }
|
||||
//! Returns the size of the constant-pool in bytes.
|
||||
inline size_t size() const noexcept { return _size; }
|
||||
ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return _size; }
|
||||
//! Returns minimum alignment.
|
||||
inline size_t alignment() const noexcept { return _alignment; }
|
||||
ASMJIT_INLINE_NODEBUG size_t alignment() const noexcept { return _alignment; }
|
||||
//! Returns the minimum size of all items added to the constant pool.
|
||||
inline size_t minItemSize() const noexcept { return _minItemSize; }
|
||||
ASMJIT_INLINE_NODEBUG size_t minItemSize() const noexcept { return _minItemSize; }
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
@@ -55,8 +55,8 @@ public:
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
inline bool operator==(const Data& other) noexcept { return eq(other); }
|
||||
inline bool operator!=(const Data& other) noexcept { return !eq(other); }
|
||||
ASMJIT_INLINE_NODEBUG bool operator==(const Data& other) noexcept { return eq(other); }
|
||||
ASMJIT_INLINE_NODEBUG bool operator!=(const Data& other) noexcept { return !eq(other); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -64,22 +64,22 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns true if there are no features set.
|
||||
inline bool empty() const noexcept { return _bits.aggregate<Support::Or>(0) == 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _bits.aggregate<Support::Or>(0) == 0; }
|
||||
|
||||
//! Returns all features as array of bitwords (see \ref Support::BitWord).
|
||||
inline BitWord* bits() noexcept { return _bits.data(); }
|
||||
ASMJIT_INLINE_NODEBUG BitWord* bits() noexcept { return _bits.data(); }
|
||||
//! Returns all features as array of bitwords (const).
|
||||
inline const BitWord* bits() const noexcept { return _bits.data(); }
|
||||
ASMJIT_INLINE_NODEBUG const BitWord* bits() const noexcept { return _bits.data(); }
|
||||
|
||||
//! Returns the number of BitWords returned by \ref bits().
|
||||
inline size_t bitWordCount() const noexcept { return kNumBitWords; }
|
||||
ASMJIT_INLINE_NODEBUG size_t bitWordCount() const noexcept { return kNumBitWords; }
|
||||
|
||||
//! Returns \ref Support::BitVectorIterator, that can be used to iterate over all features efficiently.
|
||||
inline Iterator iterator() const noexcept { return Iterator(_bits.data(), kNumBitWords); }
|
||||
ASMJIT_INLINE_NODEBUG Iterator iterator() const noexcept { return Iterator(_bits.data(), kNumBitWords); }
|
||||
|
||||
//! Tests whether the feature `featureId` is present.
|
||||
template<typename FeatureId>
|
||||
ASMJIT_FORCE_INLINE bool has(const FeatureId& featureId) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool has(const FeatureId& featureId) const noexcept {
|
||||
ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures);
|
||||
|
||||
uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits;
|
||||
@@ -89,17 +89,17 @@ public:
|
||||
}
|
||||
|
||||
template<typename FeatureId>
|
||||
ASMJIT_FORCE_INLINE bool hasAny(const FeatureId& featureId) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool hasAny(const FeatureId& featureId) const noexcept {
|
||||
return has(featureId);
|
||||
}
|
||||
|
||||
template<typename FeatureId, typename... Args>
|
||||
ASMJIT_FORCE_INLINE bool hasAny(const FeatureId& featureId, Args&&... otherFeatureIds) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool hasAny(const FeatureId& featureId, Args&&... otherFeatureIds) const noexcept {
|
||||
return bool(unsigned(has(featureId)) | unsigned(hasAny(std::forward<Args>(otherFeatureIds)...)));
|
||||
}
|
||||
|
||||
//! Tests whether all features as defined by `other` are present.
|
||||
ASMJIT_FORCE_INLINE bool hasAll(const Data& other) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool hasAll(const Data& other) const noexcept {
|
||||
uint32_t result = 1;
|
||||
for (uint32_t i = 0; i < kNumBitWords; i++)
|
||||
result &= uint32_t((_bits[i] & other._bits[i]) == other._bits[i]);
|
||||
@@ -111,11 +111,11 @@ public:
|
||||
//! \name Manipulation
|
||||
//! \{
|
||||
|
||||
inline void reset() noexcept { _bits.fill(0); }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { _bits.fill(0); }
|
||||
|
||||
//! Adds the given CPU `featureId` to the list of features.
|
||||
template<typename FeatureId>
|
||||
ASMJIT_FORCE_INLINE void add(const FeatureId& featureId) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void add(const FeatureId& featureId) noexcept {
|
||||
ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures);
|
||||
|
||||
uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits;
|
||||
@@ -125,13 +125,13 @@ public:
|
||||
}
|
||||
|
||||
template<typename FeatureId, typename... Args>
|
||||
ASMJIT_FORCE_INLINE void add(const FeatureId& featureId, Args&&... otherFeatureIds) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void add(const FeatureId& featureId, Args&&... otherFeatureIds) noexcept {
|
||||
add(featureId);
|
||||
add(std::forward<Args>(otherFeatureIds)...);
|
||||
}
|
||||
|
||||
template<typename FeatureId>
|
||||
ASMJIT_FORCE_INLINE void addIf(bool condition, const FeatureId& featureId) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void addIf(bool condition, const FeatureId& featureId) noexcept {
|
||||
ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures);
|
||||
|
||||
uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits;
|
||||
@@ -141,14 +141,14 @@ public:
|
||||
}
|
||||
|
||||
template<typename FeatureId, typename... Args>
|
||||
ASMJIT_FORCE_INLINE void addIf(bool condition, const FeatureId& featureId, Args&&... otherFeatureIds) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void addIf(bool condition, const FeatureId& featureId, Args&&... otherFeatureIds) noexcept {
|
||||
addIf(condition, featureId);
|
||||
addIf(condition, std::forward<Args>(otherFeatureIds)...);
|
||||
}
|
||||
|
||||
//! Removes the given CPU `featureId` from the list of features.
|
||||
template<typename FeatureId>
|
||||
ASMJIT_FORCE_INLINE void remove(const FeatureId& featureId) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void remove(const FeatureId& featureId) noexcept {
|
||||
ASMJIT_ASSERT(uint32_t(featureId) < kMaxFeatures);
|
||||
|
||||
uint32_t idx = uint32_t(featureId) / Support::kBitWordSizeInBits;
|
||||
@@ -158,13 +158,13 @@ public:
|
||||
}
|
||||
|
||||
template<typename FeatureId, typename... Args>
|
||||
ASMJIT_FORCE_INLINE void remove(const FeatureId& featureId, Args&&... otherFeatureIds) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void remove(const FeatureId& featureId, Args&&... otherFeatureIds) noexcept {
|
||||
remove(featureId);
|
||||
remove(std::forward<Args>(otherFeatureIds)...);
|
||||
}
|
||||
|
||||
//! Tests whether this CPU features data matches `other`.
|
||||
ASMJIT_FORCE_INLINE bool eq(const Data& other) const noexcept { return _bits == other._bits; }
|
||||
ASMJIT_INLINE_NODEBUG bool eq(const Data& other) const noexcept { return _bits == other._bits; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -327,7 +327,7 @@ public:
|
||||
};
|
||||
|
||||
#define ASMJIT_X86_FEATURE(FEATURE) \
|
||||
inline bool has##FEATURE() const noexcept { return has(X86::k##FEATURE); }
|
||||
ASMJIT_INLINE_NODEBUG bool has##FEATURE() const noexcept { return has(X86::k##FEATURE); }
|
||||
|
||||
ASMJIT_X86_FEATURE(MT)
|
||||
ASMJIT_X86_FEATURE(NX)
|
||||
@@ -616,7 +616,7 @@ public:
|
||||
};
|
||||
|
||||
#define ASMJIT_ARM_FEATURE(FEATURE) \
|
||||
inline bool has##FEATURE() const noexcept { return has(ARM::k##FEATURE); }
|
||||
ASMJIT_INLINE_NODEBUG bool has##FEATURE() const noexcept { return has(ARM::k##FEATURE); }
|
||||
|
||||
ASMJIT_ARM_FEATURE(THUMB)
|
||||
ASMJIT_ARM_FEATURE(THUMBv2)
|
||||
@@ -766,19 +766,19 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline CpuFeatures() noexcept {}
|
||||
inline CpuFeatures(const CpuFeatures& other) noexcept = default;
|
||||
inline explicit CpuFeatures(Globals::NoInit_) noexcept {}
|
||||
ASMJIT_INLINE_NODEBUG CpuFeatures() noexcept {}
|
||||
ASMJIT_INLINE_NODEBUG CpuFeatures(const CpuFeatures& other) noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG explicit CpuFeatures(Globals::NoInit_) noexcept {}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
inline CpuFeatures& operator=(const CpuFeatures& other) noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG CpuFeatures& operator=(const CpuFeatures& other) noexcept = default;
|
||||
|
||||
inline bool operator==(const CpuFeatures& other) noexcept { return eq(other); }
|
||||
inline bool operator!=(const CpuFeatures& other) noexcept { return !eq(other); }
|
||||
ASMJIT_INLINE_NODEBUG bool operator==(const CpuFeatures& other) noexcept { return eq(other); }
|
||||
ASMJIT_INLINE_NODEBUG bool operator!=(const CpuFeatures& other) noexcept { return !eq(other); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -786,68 +786,68 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns true if there are no features set.
|
||||
inline bool empty() const noexcept { return _data.empty(); }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _data.empty(); }
|
||||
|
||||
//! Casts this base class into a derived type `T`.
|
||||
template<typename T = Data>
|
||||
inline T& data() noexcept { return static_cast<T&>(_data); }
|
||||
ASMJIT_INLINE_NODEBUG T& data() noexcept { return static_cast<T&>(_data); }
|
||||
|
||||
//! Casts this base class into a derived type `T` (const).
|
||||
template<typename T = Data>
|
||||
inline const T& data() const noexcept { return static_cast<const T&>(_data); }
|
||||
ASMJIT_INLINE_NODEBUG const T& data() const noexcept { return static_cast<const T&>(_data); }
|
||||
|
||||
//! Returns CpuFeatures::Data as \ref CpuFeatures::X86.
|
||||
inline X86& x86() noexcept { return data<X86>(); }
|
||||
ASMJIT_INLINE_NODEBUG X86& x86() noexcept { return data<X86>(); }
|
||||
//! Returns CpuFeatures::Data as \ref CpuFeatures::X86 (const).
|
||||
inline const X86& x86() const noexcept { return data<X86>(); }
|
||||
ASMJIT_INLINE_NODEBUG const X86& x86() const noexcept { return data<X86>(); }
|
||||
|
||||
//! Returns CpuFeatures::Data as \ref CpuFeatures::ARM.
|
||||
inline ARM& arm() noexcept { return data<ARM>(); }
|
||||
ASMJIT_INLINE_NODEBUG ARM& arm() noexcept { return data<ARM>(); }
|
||||
//! Returns CpuFeatures::Data as \ref CpuFeatures::ARM (const).
|
||||
inline const ARM& arm() const noexcept { return data<ARM>(); }
|
||||
ASMJIT_INLINE_NODEBUG const ARM& arm() const noexcept { return data<ARM>(); }
|
||||
|
||||
//! Returns all features as array of bitwords (see \ref Support::BitWord).
|
||||
inline BitWord* bits() noexcept { return _data.bits(); }
|
||||
ASMJIT_INLINE_NODEBUG BitWord* bits() noexcept { return _data.bits(); }
|
||||
//! Returns all features as array of bitwords (const).
|
||||
inline const BitWord* bits() const noexcept { return _data.bits(); }
|
||||
ASMJIT_INLINE_NODEBUG const BitWord* bits() const noexcept { return _data.bits(); }
|
||||
//! Returns the number of BitWords returned by \ref bits().
|
||||
inline size_t bitWordCount() const noexcept { return _data.bitWordCount(); }
|
||||
ASMJIT_INLINE_NODEBUG size_t bitWordCount() const noexcept { return _data.bitWordCount(); }
|
||||
|
||||
//! Returns \ref Support::BitVectorIterator, that can be used to iterate over all features efficiently.
|
||||
inline Iterator iterator() const noexcept { return _data.iterator(); }
|
||||
ASMJIT_INLINE_NODEBUG Iterator iterator() const noexcept { return _data.iterator(); }
|
||||
|
||||
//! Tests whether the feature `featureId` is present.
|
||||
template<typename FeatureId>
|
||||
inline bool has(const FeatureId& featureId) const noexcept { return _data.has(featureId); }
|
||||
ASMJIT_INLINE_NODEBUG bool has(const FeatureId& featureId) const noexcept { return _data.has(featureId); }
|
||||
|
||||
//! Tests whether any of the features is present.
|
||||
template<typename... Args>
|
||||
inline bool hasAny(Args&&... args) const noexcept { return _data.hasAny(std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAny(Args&&... args) const noexcept { return _data.hasAny(std::forward<Args>(args)...); }
|
||||
|
||||
//! Tests whether all features as defined by `other` are present.
|
||||
inline bool hasAll(const CpuFeatures& other) const noexcept { return _data.hasAll(other._data); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAll(const CpuFeatures& other) const noexcept { return _data.hasAll(other._data); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Manipulation
|
||||
//! \{
|
||||
|
||||
inline void reset() noexcept { _data.reset(); }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { _data.reset(); }
|
||||
|
||||
//! Adds the given CPU `featureId` to the list of features.
|
||||
template<typename... Args>
|
||||
inline void add(Args&&... args) noexcept { return _data.add(std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG void add(Args&&... args) noexcept { return _data.add(std::forward<Args>(args)...); }
|
||||
|
||||
//! Adds the given CPU `featureId` to the list of features if `condition` is true.
|
||||
template<typename... Args>
|
||||
inline void addIf(bool condition, Args&&... args) noexcept { return _data.addIf(condition, std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG void addIf(bool condition, Args&&... args) noexcept { return _data.addIf(condition, std::forward<Args>(args)...); }
|
||||
|
||||
//! Removes the given CPU `featureId` from the list of features.
|
||||
template<typename... Args>
|
||||
inline void remove(Args&&... args) noexcept { return _data.remove(std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG void remove(Args&&... args) noexcept { return _data.remove(std::forward<Args>(args)...); }
|
||||
|
||||
//! Tests whether this CPU features matches `other`.
|
||||
inline bool eq(const CpuFeatures& other) const noexcept { return _data.eq(other._data); }
|
||||
ASMJIT_INLINE_NODEBUG bool eq(const CpuFeatures& other) const noexcept { return _data.eq(other._data); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -895,29 +895,29 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline CpuInfo() noexcept { reset(); }
|
||||
inline CpuInfo(const CpuInfo& other) noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG CpuInfo() noexcept { reset(); }
|
||||
ASMJIT_INLINE_NODEBUG CpuInfo(const CpuInfo& other) noexcept = default;
|
||||
|
||||
inline explicit CpuInfo(Globals::NoInit_) noexcept
|
||||
ASMJIT_INLINE_NODEBUG explicit CpuInfo(Globals::NoInit_) noexcept
|
||||
: _features(Globals::NoInit) {};
|
||||
|
||||
//! Returns the host CPU information.
|
||||
ASMJIT_API static const CpuInfo& host() noexcept;
|
||||
|
||||
//! Initializes CpuInfo architecture and sub-architecture members to `arch` and `subArch`, respectively.
|
||||
inline void initArch(Arch arch, SubArch subArch = SubArch::kUnknown) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void initArch(Arch arch, SubArch subArch = SubArch::kUnknown) noexcept {
|
||||
_arch = arch;
|
||||
_subArch = subArch;
|
||||
}
|
||||
|
||||
inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { memset(this, 0, sizeof(*this)); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
inline CpuInfo& operator=(const CpuInfo& other) noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG CpuInfo& operator=(const CpuInfo& other) noexcept = default;
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -925,16 +925,16 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the CPU architecture this information relates to.
|
||||
inline Arch arch() const noexcept { return _arch; }
|
||||
ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return _arch; }
|
||||
|
||||
//! Returns the CPU sub-architecture this information relates to.
|
||||
inline SubArch subArch() const noexcept { return _subArch; }
|
||||
ASMJIT_INLINE_NODEBUG SubArch subArch() const noexcept { return _subArch; }
|
||||
|
||||
//! Returns whether the CPU was detected successfully.
|
||||
//!
|
||||
//! If the returned value is false it means that AsmJit either failed to detect the CPU or it doesn't have
|
||||
//! implementation targeting the host architecture and operating system.
|
||||
inline bool wasDetected() const noexcept { return _wasDetected; }
|
||||
ASMJIT_INLINE_NODEBUG bool wasDetected() const noexcept { return _wasDetected; }
|
||||
|
||||
//! Returns the CPU family ID.
|
||||
//!
|
||||
@@ -943,71 +943,71 @@ public:
|
||||
//! - Family identifier matches the FamilyId read by using CPUID.
|
||||
//! - ARM:
|
||||
//! - Apple - returns Apple Family identifier returned by sysctlbyname("hw.cpufamily").
|
||||
inline uint32_t familyId() const noexcept { return _familyId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t familyId() const noexcept { return _familyId; }
|
||||
|
||||
//! Returns the CPU model ID.
|
||||
//!
|
||||
//! The information provided depends on architecture and OS:
|
||||
//! - X86:
|
||||
//! - Model identifier matches the ModelId read by using CPUID.
|
||||
inline uint32_t modelId() const noexcept { return _modelId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t modelId() const noexcept { return _modelId; }
|
||||
|
||||
//! Returns the CPU brand id.
|
||||
//!
|
||||
//! The information provided depends on architecture and OS:
|
||||
//! - X86:
|
||||
//! - Brand identifier matches the BrandId read by using CPUID.
|
||||
inline uint32_t brandId() const noexcept { return _brandId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t brandId() const noexcept { return _brandId; }
|
||||
|
||||
//! Returns the CPU stepping.
|
||||
//!
|
||||
//! The information provided depends on architecture and OS:
|
||||
//! - X86:
|
||||
//! - Stepping identifier matches the Stepping information read by using CPUID.
|
||||
inline uint32_t stepping() const noexcept { return _stepping; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t stepping() const noexcept { return _stepping; }
|
||||
|
||||
//! Returns the processor type.
|
||||
//!
|
||||
//! The information provided depends on architecture and OS:
|
||||
//! - X86:
|
||||
//! - Processor type identifier matches the ProcessorType read by using CPUID.
|
||||
inline uint32_t processorType() const noexcept { return _processorType; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t processorType() const noexcept { return _processorType; }
|
||||
|
||||
//! Returns the maximum number of logical processors.
|
||||
inline uint32_t maxLogicalProcessors() const noexcept { return _maxLogicalProcessors; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t maxLogicalProcessors() const noexcept { return _maxLogicalProcessors; }
|
||||
|
||||
//! Returns the size of a CPU cache line.
|
||||
//!
|
||||
//! On a multi-architecture system this should return the smallest cache line of all CPUs.
|
||||
inline uint32_t cacheLineSize() const noexcept { return _cacheLineSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t cacheLineSize() const noexcept { return _cacheLineSize; }
|
||||
|
||||
//! Returns number of hardware threads available.
|
||||
inline uint32_t hwThreadCount() const noexcept { return _hwThreadCount; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t hwThreadCount() const noexcept { return _hwThreadCount; }
|
||||
|
||||
//! Returns a CPU vendor string.
|
||||
inline const char* vendor() const noexcept { return _vendor.str; }
|
||||
ASMJIT_INLINE_NODEBUG const char* vendor() const noexcept { return _vendor.str; }
|
||||
//! Tests whether the CPU vendor string is equal to `s`.
|
||||
inline bool isVendor(const char* s) const noexcept { return _vendor.eq(s); }
|
||||
ASMJIT_INLINE_NODEBUG bool isVendor(const char* s) const noexcept { return _vendor.eq(s); }
|
||||
|
||||
//! Returns a CPU brand string.
|
||||
inline const char* brand() const noexcept { return _brand.str; }
|
||||
ASMJIT_INLINE_NODEBUG const char* brand() const noexcept { return _brand.str; }
|
||||
|
||||
//! Returns CPU features.
|
||||
inline CpuFeatures& features() noexcept { return _features; }
|
||||
ASMJIT_INLINE_NODEBUG CpuFeatures& features() noexcept { return _features; }
|
||||
//! Returns CPU features (const).
|
||||
inline const CpuFeatures& features() const noexcept { return _features; }
|
||||
ASMJIT_INLINE_NODEBUG const CpuFeatures& features() const noexcept { return _features; }
|
||||
|
||||
//! Tests whether the CPU has the given `feature`.
|
||||
template<typename FeatureId>
|
||||
inline bool hasFeature(const FeatureId& featureId) const noexcept { return _features.has(featureId); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFeature(const FeatureId& featureId) const noexcept { return _features.has(featureId); }
|
||||
|
||||
//! Adds the given CPU `featureId` to the list of features.
|
||||
template<typename... Args>
|
||||
inline void addFeature(Args&&... args) noexcept { return _features.add(std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG void addFeature(Args&&... args) noexcept { return _features.add(std::forward<Args>(args)...); }
|
||||
|
||||
//! Removes the given CPU `featureId` from the list of features.
|
||||
template<typename... Args>
|
||||
inline void removeFeature(Args&&... args) noexcept { return _features.remove(std::forward<Args>(args)...); }
|
||||
ASMJIT_INLINE_NODEBUG void removeFeature(Args&&... args) noexcept { return _features.remove(std::forward<Args>(args)...); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
@@ -21,11 +21,11 @@ class BaseEmitHelper {
|
||||
public:
|
||||
BaseEmitter* _emitter;
|
||||
|
||||
inline explicit BaseEmitHelper(BaseEmitter* emitter = nullptr) noexcept
|
||||
ASMJIT_INLINE_NODEBUG explicit BaseEmitHelper(BaseEmitter* emitter = nullptr) noexcept
|
||||
: _emitter(emitter) {}
|
||||
|
||||
inline BaseEmitter* emitter() const noexcept { return _emitter; }
|
||||
inline void setEmitter(BaseEmitter* emitter) noexcept { _emitter = emitter; }
|
||||
ASMJIT_INLINE_NODEBUG BaseEmitter* emitter() const noexcept { return _emitter; }
|
||||
ASMJIT_INLINE_NODEBUG void setEmitter(BaseEmitter* emitter) noexcept { _emitter = emitter; }
|
||||
|
||||
//! Emits a pure move operation between two registers or the same type or between a register and its home
|
||||
//! slot. This function does not handle register conversion.
|
||||
|
||||
@@ -276,7 +276,7 @@ public:
|
||||
ValidateFunc validate;
|
||||
|
||||
//! Resets all functions to nullptr.
|
||||
inline void reset() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept {
|
||||
emitProlog = nullptr;
|
||||
emitEpilog = nullptr;
|
||||
emitArgsAssignment = nullptr;
|
||||
@@ -300,10 +300,10 @@ public:
|
||||
//! \{
|
||||
|
||||
template<typename T>
|
||||
inline T* as() noexcept { return reinterpret_cast<T*>(this); }
|
||||
ASMJIT_INLINE_NODEBUG T* as() noexcept { return reinterpret_cast<T*>(this); }
|
||||
|
||||
template<typename T>
|
||||
inline const T* as() const noexcept { return reinterpret_cast<const T*>(this); }
|
||||
ASMJIT_INLINE_NODEBUG const T* as() const noexcept { return reinterpret_cast<const T*>(this); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -311,28 +311,28 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the type of this emitter, see `EmitterType`.
|
||||
inline EmitterType emitterType() const noexcept { return _emitterType; }
|
||||
ASMJIT_INLINE_NODEBUG EmitterType emitterType() const noexcept { return _emitterType; }
|
||||
//! Returns emitter flags , see `Flags`.
|
||||
inline EmitterFlags emitterFlags() const noexcept { return _emitterFlags; }
|
||||
ASMJIT_INLINE_NODEBUG EmitterFlags emitterFlags() const noexcept { return _emitterFlags; }
|
||||
|
||||
//! Tests whether the emitter inherits from `BaseAssembler`.
|
||||
inline bool isAssembler() const noexcept { return _emitterType == EmitterType::kAssembler; }
|
||||
ASMJIT_INLINE_NODEBUG bool isAssembler() const noexcept { return _emitterType == EmitterType::kAssembler; }
|
||||
//! Tests whether the emitter inherits from `BaseBuilder`.
|
||||
//!
|
||||
//! \note Both Builder and Compiler emitters would return `true`.
|
||||
inline bool isBuilder() const noexcept { return uint32_t(_emitterType) >= uint32_t(EmitterType::kBuilder); }
|
||||
ASMJIT_INLINE_NODEBUG bool isBuilder() const noexcept { return uint32_t(_emitterType) >= uint32_t(EmitterType::kBuilder); }
|
||||
//! Tests whether the emitter inherits from `BaseCompiler`.
|
||||
inline bool isCompiler() const noexcept { return _emitterType == EmitterType::kCompiler; }
|
||||
ASMJIT_INLINE_NODEBUG bool isCompiler() const noexcept { return _emitterType == EmitterType::kCompiler; }
|
||||
|
||||
//! Tests whether the emitter has the given `flag` enabled.
|
||||
inline bool hasEmitterFlag(EmitterFlags flag) const noexcept { return Support::test(_emitterFlags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasEmitterFlag(EmitterFlags flag) const noexcept { return Support::test(_emitterFlags, flag); }
|
||||
//! Tests whether the emitter is finalized.
|
||||
inline bool isFinalized() const noexcept { return hasEmitterFlag(EmitterFlags::kFinalized); }
|
||||
ASMJIT_INLINE_NODEBUG bool isFinalized() const noexcept { return hasEmitterFlag(EmitterFlags::kFinalized); }
|
||||
//! Tests whether the emitter is destroyed (only used during destruction).
|
||||
inline bool isDestroyed() const noexcept { return hasEmitterFlag(EmitterFlags::kDestroyed); }
|
||||
ASMJIT_INLINE_NODEBUG bool isDestroyed() const noexcept { return hasEmitterFlag(EmitterFlags::kDestroyed); }
|
||||
|
||||
inline void _addEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags |= flags; }
|
||||
inline void _clearEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags &= _emitterFlags & ~flags; }
|
||||
ASMJIT_INLINE_NODEBUG void _addEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG void _clearEmitterFlags(EmitterFlags flags) noexcept { _emitterFlags &= _emitterFlags & ~flags; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -340,25 +340,25 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the CodeHolder this emitter is attached to.
|
||||
inline CodeHolder* code() const noexcept { return _code; }
|
||||
ASMJIT_INLINE_NODEBUG CodeHolder* code() const noexcept { return _code; }
|
||||
|
||||
//! Returns the target environment.
|
||||
//!
|
||||
//! The returned \ref Environment reference matches \ref CodeHolder::environment().
|
||||
inline const Environment& environment() const noexcept { return _environment; }
|
||||
ASMJIT_INLINE_NODEBUG const Environment& environment() const noexcept { return _environment; }
|
||||
|
||||
//! Tests whether the target architecture is 32-bit.
|
||||
inline bool is32Bit() const noexcept { return environment().is32Bit(); }
|
||||
ASMJIT_INLINE_NODEBUG bool is32Bit() const noexcept { return environment().is32Bit(); }
|
||||
//! Tests whether the target architecture is 64-bit.
|
||||
inline bool is64Bit() const noexcept { return environment().is64Bit(); }
|
||||
ASMJIT_INLINE_NODEBUG bool is64Bit() const noexcept { return environment().is64Bit(); }
|
||||
|
||||
//! Returns the target architecture type.
|
||||
inline Arch arch() const noexcept { return environment().arch(); }
|
||||
ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return environment().arch(); }
|
||||
//! Returns the target architecture sub-type.
|
||||
inline SubArch subArch() const noexcept { return environment().subArch(); }
|
||||
ASMJIT_INLINE_NODEBUG SubArch subArch() const noexcept { return environment().subArch(); }
|
||||
|
||||
//! Returns the target architecture's GP register size (4 or 8 bytes).
|
||||
inline uint32_t registerSize() const noexcept { return environment().registerSize(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t registerSize() const noexcept { return environment().registerSize(); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -366,7 +366,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether the emitter is initialized (i.e. attached to \ref CodeHolder).
|
||||
inline bool isInitialized() const noexcept { return _code != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool isInitialized() const noexcept { return _code != nullptr; }
|
||||
|
||||
//! Finalizes this emitter.
|
||||
//!
|
||||
@@ -383,19 +383,19 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether the emitter has a logger.
|
||||
inline bool hasLogger() const noexcept { return _logger != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasLogger() const noexcept { return _logger != nullptr; }
|
||||
|
||||
//! Tests whether the emitter has its own logger.
|
||||
//!
|
||||
//! Own logger means that it overrides the possible logger that may be used by \ref CodeHolder this emitter is
|
||||
//! attached to.
|
||||
inline bool hasOwnLogger() const noexcept { return hasEmitterFlag(EmitterFlags::kOwnLogger); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasOwnLogger() const noexcept { return hasEmitterFlag(EmitterFlags::kOwnLogger); }
|
||||
|
||||
//! Returns the logger this emitter uses.
|
||||
//!
|
||||
//! The returned logger is either the emitter's own logger or it's logger used by \ref CodeHolder this emitter
|
||||
//! is attached to.
|
||||
inline Logger* logger() const noexcept { return _logger; }
|
||||
ASMJIT_INLINE_NODEBUG Logger* logger() const noexcept { return _logger; }
|
||||
|
||||
//! Sets or resets the logger of the emitter.
|
||||
//!
|
||||
@@ -408,7 +408,7 @@ public:
|
||||
//!
|
||||
//! The emitter will bail to using a logger attached to \ref CodeHolder this emitter is attached to, or no logger
|
||||
//! at all if \ref CodeHolder doesn't have one.
|
||||
inline void resetLogger() noexcept { return setLogger(nullptr); }
|
||||
ASMJIT_INLINE_NODEBUG void resetLogger() noexcept { return setLogger(nullptr); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -416,25 +416,25 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether the emitter has an error handler attached.
|
||||
inline bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasErrorHandler() const noexcept { return _errorHandler != nullptr; }
|
||||
|
||||
//! Tests whether the emitter has its own error handler.
|
||||
//!
|
||||
//! Own error handler means that it overrides the possible error handler that may be used by \ref CodeHolder this
|
||||
//! emitter is attached to.
|
||||
inline bool hasOwnErrorHandler() const noexcept { return hasEmitterFlag(EmitterFlags::kOwnErrorHandler); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasOwnErrorHandler() const noexcept { return hasEmitterFlag(EmitterFlags::kOwnErrorHandler); }
|
||||
|
||||
//! Returns the error handler this emitter uses.
|
||||
//!
|
||||
//! The returned error handler is either the emitter's own error handler or it's error handler used by
|
||||
//! \ref CodeHolder this emitter is attached to.
|
||||
inline ErrorHandler* errorHandler() const noexcept { return _errorHandler; }
|
||||
ASMJIT_INLINE_NODEBUG ErrorHandler* errorHandler() const noexcept { return _errorHandler; }
|
||||
|
||||
//! Sets or resets the error handler of the emitter.
|
||||
ASMJIT_API void setErrorHandler(ErrorHandler* errorHandler) noexcept;
|
||||
|
||||
//! Resets the error handler.
|
||||
inline void resetErrorHandler() noexcept { setErrorHandler(nullptr); }
|
||||
ASMJIT_INLINE_NODEBUG void resetErrorHandler() noexcept { setErrorHandler(nullptr); }
|
||||
|
||||
//! Handles the given error in the following way:
|
||||
//! 1. If the emitter has \ref ErrorHandler attached, it calls its \ref ErrorHandler::handleError() member function
|
||||
@@ -448,14 +448,14 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns encoding options.
|
||||
inline EncodingOptions encodingOptions() const noexcept { return _encodingOptions; }
|
||||
ASMJIT_INLINE_NODEBUG EncodingOptions encodingOptions() const noexcept { return _encodingOptions; }
|
||||
//! Tests whether the encoding `option` is set.
|
||||
inline bool hasEncodingOption(EncodingOptions option) const noexcept { return Support::test(_encodingOptions, option); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasEncodingOption(EncodingOptions option) const noexcept { return Support::test(_encodingOptions, option); }
|
||||
|
||||
//! Enables the given encoding `options`.
|
||||
inline void addEncodingOptions(EncodingOptions options) noexcept { _encodingOptions |= options; }
|
||||
ASMJIT_INLINE_NODEBUG void addEncodingOptions(EncodingOptions options) noexcept { _encodingOptions |= options; }
|
||||
//! Disables the given encoding `options`.
|
||||
inline void clearEncodingOptions(EncodingOptions options) noexcept { _encodingOptions &= ~options; }
|
||||
ASMJIT_INLINE_NODEBUG void clearEncodingOptions(EncodingOptions options) noexcept { _encodingOptions &= ~options; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -463,10 +463,10 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the emitter's diagnostic options.
|
||||
inline DiagnosticOptions diagnosticOptions() const noexcept { return _diagnosticOptions; }
|
||||
ASMJIT_INLINE_NODEBUG DiagnosticOptions diagnosticOptions() const noexcept { return _diagnosticOptions; }
|
||||
|
||||
//! Tests whether the given `option` is present in the emitter's diagnostic options.
|
||||
inline bool hasDiagnosticOption(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasDiagnosticOption(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option); }
|
||||
|
||||
//! Activates the given diagnostic `options`.
|
||||
//!
|
||||
@@ -503,50 +503,50 @@ public:
|
||||
//! Forced instruction options are merged with next instruction options before the instruction is encoded. These
|
||||
//! options have some bits reserved that are used by error handling, logging, and instruction validation purposes.
|
||||
//! Other options are globals that affect each instruction.
|
||||
inline InstOptions forcedInstOptions() const noexcept { return _forcedInstOptions; }
|
||||
ASMJIT_INLINE_NODEBUG InstOptions forcedInstOptions() const noexcept { return _forcedInstOptions; }
|
||||
|
||||
//! Returns options of the next instruction.
|
||||
inline InstOptions instOptions() const noexcept { return _instOptions; }
|
||||
ASMJIT_INLINE_NODEBUG InstOptions instOptions() const noexcept { return _instOptions; }
|
||||
//! Returns options of the next instruction.
|
||||
inline void setInstOptions(InstOptions options) noexcept { _instOptions = options; }
|
||||
ASMJIT_INLINE_NODEBUG void setInstOptions(InstOptions options) noexcept { _instOptions = options; }
|
||||
//! Adds options of the next instruction.
|
||||
inline void addInstOptions(InstOptions options) noexcept { _instOptions |= options; }
|
||||
ASMJIT_INLINE_NODEBUG void addInstOptions(InstOptions options) noexcept { _instOptions |= options; }
|
||||
//! Resets options of the next instruction.
|
||||
inline void resetInstOptions() noexcept { _instOptions = InstOptions::kNone; }
|
||||
ASMJIT_INLINE_NODEBUG void resetInstOptions() noexcept { _instOptions = InstOptions::kNone; }
|
||||
|
||||
//! Tests whether the extra register operand is valid.
|
||||
inline bool hasExtraReg() const noexcept { return _extraReg.isReg(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasExtraReg() const noexcept { return _extraReg.isReg(); }
|
||||
//! Returns an extra operand that will be used by the next instruction (architecture specific).
|
||||
inline const RegOnly& extraReg() const noexcept { return _extraReg; }
|
||||
ASMJIT_INLINE_NODEBUG const RegOnly& extraReg() const noexcept { return _extraReg; }
|
||||
//! Sets an extra operand that will be used by the next instruction (architecture specific).
|
||||
inline void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); }
|
||||
ASMJIT_INLINE_NODEBUG void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); }
|
||||
//! Sets an extra operand that will be used by the next instruction (architecture specific).
|
||||
inline void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); }
|
||||
ASMJIT_INLINE_NODEBUG void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); }
|
||||
//! Resets an extra operand that will be used by the next instruction (architecture specific).
|
||||
inline void resetExtraReg() noexcept { _extraReg.reset(); }
|
||||
ASMJIT_INLINE_NODEBUG void resetExtraReg() noexcept { _extraReg.reset(); }
|
||||
|
||||
//! Returns comment/annotation of the next instruction.
|
||||
inline const char* inlineComment() const noexcept { return _inlineComment; }
|
||||
ASMJIT_INLINE_NODEBUG const char* inlineComment() const noexcept { return _inlineComment; }
|
||||
//! Sets comment/annotation of the next instruction.
|
||||
//!
|
||||
//! \note This string is set back to null by `_emit()`, but until that it has to remain valid as the Emitter is not
|
||||
//! required to make a copy of it (and it would be slow to do that for each instruction).
|
||||
inline void setInlineComment(const char* s) noexcept { _inlineComment = s; }
|
||||
ASMJIT_INLINE_NODEBUG void setInlineComment(const char* s) noexcept { _inlineComment = s; }
|
||||
//! Resets the comment/annotation to nullptr.
|
||||
inline void resetInlineComment() noexcept { _inlineComment = nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG void resetInlineComment() noexcept { _inlineComment = nullptr; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Emitter State
|
||||
//! \{
|
||||
|
||||
inline void resetState() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void resetState() noexcept {
|
||||
resetInstOptions();
|
||||
resetExtraReg();
|
||||
resetInlineComment();
|
||||
}
|
||||
|
||||
inline State _grabState() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG State _grabState() noexcept {
|
||||
State s{_instOptions | _forcedInstOptions, _extraReg, _inlineComment};
|
||||
resetState();
|
||||
return s;
|
||||
@@ -570,9 +570,9 @@ public:
|
||||
virtual Label newNamedLabel(const char* name, size_t nameSize = SIZE_MAX, LabelType type = LabelType::kGlobal, uint32_t parentId = Globals::kInvalidId) = 0;
|
||||
|
||||
//! Creates a new anonymous label with a name, which can only be used for debugging purposes.
|
||||
inline Label newAnonymousLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kAnonymous); }
|
||||
ASMJIT_INLINE_NODEBUG Label newAnonymousLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kAnonymous); }
|
||||
//! Creates a new external label.
|
||||
inline Label newExternalLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kExternal); }
|
||||
ASMJIT_INLINE_NODEBUG Label newExternalLabel(const char* name, size_t nameSize = SIZE_MAX) { return newNamedLabel(name, nameSize, LabelType::kExternal); }
|
||||
|
||||
//! Returns `Label` by `name`.
|
||||
//!
|
||||
@@ -590,7 +590,7 @@ public:
|
||||
//! Tests whether the label `id` is valid (i.e. registered).
|
||||
ASMJIT_API bool isLabelValid(uint32_t labelId) const noexcept;
|
||||
//! Tests whether the `label` is valid (i.e. registered).
|
||||
inline bool isLabelValid(const Label& label) const noexcept { return isLabelValid(label.id()); }
|
||||
ASMJIT_INLINE_NODEBUG bool isLabelValid(const Label& label) const noexcept { return isLabelValid(label.id()); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -621,11 +621,11 @@ public:
|
||||
|
||||
//! Emits an instruction `instId` with the given `operands`.
|
||||
template<typename... Args>
|
||||
ASMJIT_FORCE_INLINE Error emit(InstId instId, Args&&... operands) {
|
||||
ASMJIT_INLINE_NODEBUG Error emit(InstId instId, Args&&... operands) {
|
||||
return _emitI(instId, Support::ForwardOp<Args>::forward(operands)...);
|
||||
}
|
||||
|
||||
ASMJIT_FORCE_INLINE Error emitOpArray(InstId instId, const Operand_* operands, size_t opCount) {
|
||||
ASMJIT_INLINE_NODEBUG Error emitOpArray(InstId instId, const Operand_* operands, size_t opCount) {
|
||||
return _emitOpArray(instId, operands, opCount);
|
||||
}
|
||||
|
||||
@@ -683,25 +683,25 @@ public:
|
||||
virtual Error embedDataArray(TypeId typeId, const void* data, size_t itemCount, size_t repeatCount = 1) = 0;
|
||||
|
||||
//! Embeds int8_t `value` repeated by `repeatCount`.
|
||||
inline Error embedInt8(int8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt8, &value, 1, repeatCount); }
|
||||
ASMJIT_INLINE_NODEBUG Error embedInt8(int8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt8, &value, 1, repeatCount); }
|
||||
//! Embeds uint8_t `value` repeated by `repeatCount`.
|
||||
inline Error embedUInt8(uint8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt8, &value, 1, repeatCount); }
|
||||
ASMJIT_INLINE_NODEBUG Error embedUInt8(uint8_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt8, &value, 1, repeatCount); }
|
||||
//! Embeds int16_t `value` repeated by `repeatCount`.
|
||||
inline Error embedInt16(int16_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt16, &value, 1, repeatCount); }
|
||||
ASMJIT_INLINE_NODEBUG Error embedInt16(int16_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt16, &value, 1, repeatCount); }
|
||||
//! Embeds uint16_t `value` repeated by `repeatCount`.
|
||||
inline Error embedUInt16(uint16_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt16, &value, 1, repeatCount); }
|
||||
ASMJIT_INLINE_NODEBUG Error embedUInt16(uint16_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt16, &value, 1, repeatCount); }
|
||||
//! Embeds int32_t `value` repeated by `repeatCount`.
|
||||
inline Error embedInt32(int32_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt32, &value, 1, repeatCount); }
|
||||
ASMJIT_INLINE_NODEBUG Error embedInt32(int32_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt32, &value, 1, repeatCount); }
|
||||
//! Embeds uint32_t `value` repeated by `repeatCount`.
|
||||
inline Error embedUInt32(uint32_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt32, &value, 1, repeatCount); }
|
||||
ASMJIT_INLINE_NODEBUG Error embedUInt32(uint32_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt32, &value, 1, repeatCount); }
|
||||
//! Embeds int64_t `value` repeated by `repeatCount`.
|
||||
inline Error embedInt64(int64_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt64, &value, 1, repeatCount); }
|
||||
ASMJIT_INLINE_NODEBUG Error embedInt64(int64_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kInt64, &value, 1, repeatCount); }
|
||||
//! Embeds uint64_t `value` repeated by `repeatCount`.
|
||||
inline Error embedUInt64(uint64_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt64, &value, 1, repeatCount); }
|
||||
ASMJIT_INLINE_NODEBUG Error embedUInt64(uint64_t value, size_t repeatCount = 1) { return embedDataArray(TypeId::kUInt64, &value, 1, repeatCount); }
|
||||
//! Embeds a floating point `value` repeated by `repeatCount`.
|
||||
inline Error embedFloat(float value, size_t repeatCount = 1) { return embedDataArray(TypeId(TypeUtils::TypeIdOfT<float>::kTypeId), &value, 1, repeatCount); }
|
||||
ASMJIT_INLINE_NODEBUG Error embedFloat(float value, size_t repeatCount = 1) { return embedDataArray(TypeId(TypeUtils::TypeIdOfT<float>::kTypeId), &value, 1, repeatCount); }
|
||||
//! Embeds a floating point `value` repeated by `repeatCount`.
|
||||
inline Error embedDouble(double value, size_t repeatCount = 1) { return embedDataArray(TypeId(TypeUtils::TypeIdOfT<double>::kTypeId), &value, 1, repeatCount); }
|
||||
ASMJIT_INLINE_NODEBUG Error embedDouble(double value, size_t repeatCount = 1) { return embedDataArray(TypeId(TypeUtils::TypeIdOfT<double>::kTypeId), &value, 1, repeatCount); }
|
||||
|
||||
//! Embeds a constant pool at the current offset by performing the following:
|
||||
//! 1. Aligns by using AlignMode::kData to the minimum `pool` alignment.
|
||||
|
||||
@@ -205,7 +205,7 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline Environment() noexcept :
|
||||
ASMJIT_INLINE_NODEBUG Environment() noexcept :
|
||||
_arch(Arch::kUnknown),
|
||||
_subArch(SubArch::kUnknown),
|
||||
_vendor(Vendor::kUnknown),
|
||||
@@ -214,7 +214,7 @@ public:
|
||||
_objectFormat(ObjectFormat::kUnknown),
|
||||
_reserved { 0, 0 } {}
|
||||
|
||||
inline explicit Environment(
|
||||
ASMJIT_INLINE_NODEBUG explicit Environment(
|
||||
Arch arch,
|
||||
SubArch subArch = SubArch::kUnknown,
|
||||
Vendor vendor = Vendor::kUnknown,
|
||||
@@ -225,13 +225,13 @@ public:
|
||||
init(arch, subArch, vendor, platform, abi, objectFormat);
|
||||
}
|
||||
|
||||
inline Environment(const Environment& other) noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG Environment(const Environment& other) noexcept = default;
|
||||
|
||||
//! Returns the host environment constructed from preprocessor macros defined by the compiler.
|
||||
//!
|
||||
//! The returned environment should precisely match the target host architecture, sub-architecture, platform,
|
||||
//! and ABI.
|
||||
static inline Environment host() noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG Environment host() noexcept {
|
||||
return Environment(Arch::kHost, SubArch::kHost, Vendor::kHost, Platform::kHost, PlatformABI::kHost, ObjectFormat::kUnknown);
|
||||
}
|
||||
|
||||
@@ -240,10 +240,10 @@ public:
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
inline Environment& operator=(const Environment& other) noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG Environment& operator=(const Environment& other) noexcept = default;
|
||||
|
||||
inline bool operator==(const Environment& other) const noexcept { return equals(other); }
|
||||
inline bool operator!=(const Environment& other) const noexcept { return !equals(other); }
|
||||
ASMJIT_INLINE_NODEBUG bool operator==(const Environment& other) const noexcept { return equals(other); }
|
||||
ASMJIT_INLINE_NODEBUG bool operator!=(const Environment& other) const noexcept { return !equals(other); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -253,25 +253,25 @@ public:
|
||||
//! Tests whether the environment is not set up.
|
||||
//!
|
||||
//! Returns true if all members are zero, and thus unknown.
|
||||
inline bool empty() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept {
|
||||
// Unfortunately compilers won't optimize fields are checked one by one...
|
||||
return _packed() == 0;
|
||||
}
|
||||
|
||||
//! Tests whether the environment is initialized, which means it must have
|
||||
//! a valid architecture.
|
||||
inline bool isInitialized() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool isInitialized() const noexcept {
|
||||
return _arch != Arch::kUnknown;
|
||||
}
|
||||
|
||||
inline uint64_t _packed() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG uint64_t _packed() const noexcept {
|
||||
uint64_t x;
|
||||
memcpy(&x, this, 8);
|
||||
return x;
|
||||
}
|
||||
|
||||
//! Resets all members of the environment to zero / unknown.
|
||||
inline void reset() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept {
|
||||
_arch = Arch::kUnknown;
|
||||
_subArch = SubArch::kUnknown;
|
||||
_vendor = Vendor::kUnknown;
|
||||
@@ -282,22 +282,22 @@ public:
|
||||
_reserved[1] = 0;
|
||||
}
|
||||
|
||||
inline bool equals(const Environment& other) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool equals(const Environment& other) const noexcept {
|
||||
return _packed() == other._packed();
|
||||
}
|
||||
|
||||
//! Returns the architecture.
|
||||
inline Arch arch() const noexcept { return _arch; }
|
||||
ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return _arch; }
|
||||
//! Returns the sub-architecture.
|
||||
inline SubArch subArch() const noexcept { return _subArch; }
|
||||
ASMJIT_INLINE_NODEBUG SubArch subArch() const noexcept { return _subArch; }
|
||||
//! Returns vendor.
|
||||
inline Vendor vendor() const noexcept { return _vendor; }
|
||||
ASMJIT_INLINE_NODEBUG Vendor vendor() const noexcept { return _vendor; }
|
||||
//! Returns target's platform or operating system.
|
||||
inline Platform platform() const noexcept { return _platform; }
|
||||
ASMJIT_INLINE_NODEBUG Platform platform() const noexcept { return _platform; }
|
||||
//! Returns target's ABI.
|
||||
inline PlatformABI platformABI() const noexcept { return _platformABI; }
|
||||
ASMJIT_INLINE_NODEBUG PlatformABI platformABI() const noexcept { return _platformABI; }
|
||||
//! Returns target's object format.
|
||||
inline ObjectFormat objectFormat() const noexcept { return _objectFormat; }
|
||||
ASMJIT_INLINE_NODEBUG ObjectFormat objectFormat() const noexcept { return _objectFormat; }
|
||||
|
||||
inline void init(
|
||||
Arch arch,
|
||||
@@ -317,53 +317,53 @@ public:
|
||||
_reserved[1] = 0;
|
||||
}
|
||||
|
||||
inline bool isArchX86() const noexcept { return _arch == Arch::kX86; }
|
||||
inline bool isArchX64() const noexcept { return _arch == Arch::kX64; }
|
||||
inline bool isArchARM() const noexcept { return isArchARM(_arch); }
|
||||
inline bool isArchThumb() const noexcept { return isArchThumb(_arch); }
|
||||
inline bool isArchAArch64() const noexcept { return isArchAArch64(_arch); }
|
||||
inline bool isArchMIPS32() const noexcept { return isArchMIPS32(_arch); }
|
||||
inline bool isArchMIPS64() const noexcept { return isArchMIPS64(_arch); }
|
||||
inline bool isArchRISCV32() const noexcept { return _arch == Arch::kRISCV32; }
|
||||
inline bool isArchRISCV64() const noexcept { return _arch == Arch::kRISCV64; }
|
||||
ASMJIT_INLINE_NODEBUG bool isArchX86() const noexcept { return _arch == Arch::kX86; }
|
||||
ASMJIT_INLINE_NODEBUG bool isArchX64() const noexcept { return _arch == Arch::kX64; }
|
||||
ASMJIT_INLINE_NODEBUG bool isArchARM() const noexcept { return isArchARM(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool isArchThumb() const noexcept { return isArchThumb(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool isArchAArch64() const noexcept { return isArchAArch64(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool isArchMIPS32() const noexcept { return isArchMIPS32(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool isArchMIPS64() const noexcept { return isArchMIPS64(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool isArchRISCV32() const noexcept { return _arch == Arch::kRISCV32; }
|
||||
ASMJIT_INLINE_NODEBUG bool isArchRISCV64() const noexcept { return _arch == Arch::kRISCV64; }
|
||||
|
||||
//! Tests whether the architecture is 32-bit.
|
||||
inline bool is32Bit() const noexcept { return is32Bit(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool is32Bit() const noexcept { return is32Bit(_arch); }
|
||||
//! Tests whether the architecture is 64-bit.
|
||||
inline bool is64Bit() const noexcept { return is64Bit(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool is64Bit() const noexcept { return is64Bit(_arch); }
|
||||
|
||||
//! Tests whether the architecture is little endian.
|
||||
inline bool isLittleEndian() const noexcept { return isLittleEndian(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool isLittleEndian() const noexcept { return isLittleEndian(_arch); }
|
||||
//! Tests whether the architecture is big endian.
|
||||
inline bool isBigEndian() const noexcept { return isBigEndian(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool isBigEndian() const noexcept { return isBigEndian(_arch); }
|
||||
|
||||
//! Tests whether this architecture is of X86 family.
|
||||
inline bool isFamilyX86() const noexcept { return isFamilyX86(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool isFamilyX86() const noexcept { return isFamilyX86(_arch); }
|
||||
//! Tests whether this architecture family is ARM, THUMB, or AArch64.
|
||||
inline bool isFamilyARM() const noexcept { return isFamilyARM(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool isFamilyARM() const noexcept { return isFamilyARM(_arch); }
|
||||
//! Tests whether this architecture family is AArch32 (ARM or THUMB).
|
||||
inline bool isFamilyAArch32() const noexcept { return isFamilyAArch32(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool isFamilyAArch32() const noexcept { return isFamilyAArch32(_arch); }
|
||||
//! Tests whether this architecture family is AArch64.
|
||||
inline bool isFamilyAArch64() const noexcept { return isFamilyAArch64(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool isFamilyAArch64() const noexcept { return isFamilyAArch64(_arch); }
|
||||
//! Tests whether this architecture family is MISP or MIPS64.
|
||||
inline bool isFamilyMIPS() const noexcept { return isFamilyMIPS(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool isFamilyMIPS() const noexcept { return isFamilyMIPS(_arch); }
|
||||
//! Tests whether this architecture family is RISC-V (both 32-bit and 64-bit).
|
||||
inline bool isFamilyRISCV() const noexcept { return isFamilyRISCV(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG bool isFamilyRISCV() const noexcept { return isFamilyRISCV(_arch); }
|
||||
|
||||
//! Tests whether the environment platform is Windows.
|
||||
inline bool isPlatformWindows() const noexcept { return _platform == Platform::kWindows; }
|
||||
ASMJIT_INLINE_NODEBUG bool isPlatformWindows() const noexcept { return _platform == Platform::kWindows; }
|
||||
|
||||
//! Tests whether the environment platform is Linux.
|
||||
inline bool isPlatformLinux() const noexcept { return _platform == Platform::kLinux; }
|
||||
ASMJIT_INLINE_NODEBUG bool isPlatformLinux() const noexcept { return _platform == Platform::kLinux; }
|
||||
|
||||
//! Tests whether the environment platform is Hurd.
|
||||
inline bool isPlatformHurd() const noexcept { return _platform == Platform::kHurd; }
|
||||
ASMJIT_INLINE_NODEBUG bool isPlatformHurd() const noexcept { return _platform == Platform::kHurd; }
|
||||
|
||||
//! Tests whether the environment platform is Haiku.
|
||||
inline bool isPlatformHaiku() const noexcept { return _platform == Platform::kHaiku; }
|
||||
ASMJIT_INLINE_NODEBUG bool isPlatformHaiku() const noexcept { return _platform == Platform::kHaiku; }
|
||||
|
||||
//! Tests whether the environment platform is any BSD.
|
||||
inline bool isPlatformBSD() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool isPlatformBSD() const noexcept {
|
||||
return _platform == Platform::kFreeBSD ||
|
||||
_platform == Platform::kOpenBSD ||
|
||||
_platform == Platform::kNetBSD ||
|
||||
@@ -371,7 +371,7 @@ public:
|
||||
}
|
||||
|
||||
//! Tests whether the environment platform is any Apple platform (OSX, iOS, TVOS, WatchOS).
|
||||
inline bool isPlatformApple() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool isPlatformApple() const noexcept {
|
||||
return _platform == Platform::kOSX ||
|
||||
_platform == Platform::kIOS ||
|
||||
_platform == Platform::kTVOS ||
|
||||
@@ -379,119 +379,119 @@ public:
|
||||
}
|
||||
|
||||
//! Tests whether the ABI is MSVC.
|
||||
inline bool isMSVC() const noexcept { return _platformABI == PlatformABI::kMSVC; }
|
||||
ASMJIT_INLINE_NODEBUG bool isMSVC() const noexcept { return _platformABI == PlatformABI::kMSVC; }
|
||||
//! Tests whether the ABI is GNU.
|
||||
inline bool isGNU() const noexcept { return _platformABI == PlatformABI::kGNU; }
|
||||
ASMJIT_INLINE_NODEBUG bool isGNU() const noexcept { return _platformABI == PlatformABI::kGNU; }
|
||||
|
||||
//! Returns a calculated stack alignment for this environment.
|
||||
ASMJIT_API uint32_t stackAlignment() const noexcept;
|
||||
|
||||
//! Returns a native register size of this architecture.
|
||||
uint32_t registerSize() const noexcept { return registerSizeFromArch(_arch); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t registerSize() const noexcept { return registerSizeFromArch(_arch); }
|
||||
|
||||
//! Sets the architecture to `arch`.
|
||||
inline void setArch(Arch arch) noexcept { _arch = arch; }
|
||||
ASMJIT_INLINE_NODEBUG void setArch(Arch arch) noexcept { _arch = arch; }
|
||||
//! Sets the sub-architecture to `subArch`.
|
||||
inline void setSubArch(SubArch subArch) noexcept { _subArch = subArch; }
|
||||
ASMJIT_INLINE_NODEBUG void setSubArch(SubArch subArch) noexcept { _subArch = subArch; }
|
||||
//! Sets the vendor to `vendor`.
|
||||
inline void setVendor(Vendor vendor) noexcept { _vendor = vendor; }
|
||||
ASMJIT_INLINE_NODEBUG void setVendor(Vendor vendor) noexcept { _vendor = vendor; }
|
||||
//! Sets the platform to `platform`.
|
||||
inline void setPlatform(Platform platform) noexcept { _platform = platform; }
|
||||
ASMJIT_INLINE_NODEBUG void setPlatform(Platform platform) noexcept { _platform = platform; }
|
||||
//! Sets the ABI to `platformABI`.
|
||||
inline void setPlatformABI(PlatformABI platformABI) noexcept { _platformABI = platformABI; }
|
||||
ASMJIT_INLINE_NODEBUG void setPlatformABI(PlatformABI platformABI) noexcept { _platformABI = platformABI; }
|
||||
//! Sets the object format to `objectFormat`.
|
||||
inline void setObjectFormat(ObjectFormat objectFormat) noexcept { _objectFormat = objectFormat; }
|
||||
ASMJIT_INLINE_NODEBUG void setObjectFormat(ObjectFormat objectFormat) noexcept { _objectFormat = objectFormat; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Static Utilities
|
||||
//! \{
|
||||
|
||||
static inline bool isDefinedArch(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isDefinedArch(Arch arch) noexcept {
|
||||
return uint32_t(arch) <= uint32_t(Arch::kMaxValue);
|
||||
}
|
||||
|
||||
static inline bool isValidArch(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isValidArch(Arch arch) noexcept {
|
||||
return arch != Arch::kUnknown && uint32_t(arch) <= uint32_t(Arch::kMaxValue);
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture `arch` is 32-bit.
|
||||
static inline bool is32Bit(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool is32Bit(Arch arch) noexcept {
|
||||
return (uint32_t(arch) & uint32_t(Arch::k32BitMask)) == uint32_t(Arch::k32BitMask);
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture `arch` is 64-bit.
|
||||
static inline bool is64Bit(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool is64Bit(Arch arch) noexcept {
|
||||
return (uint32_t(arch) & uint32_t(Arch::k32BitMask)) == 0;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture `arch` is little endian.
|
||||
static inline bool isLittleEndian(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isLittleEndian(Arch arch) noexcept {
|
||||
return uint32_t(arch) < uint32_t(Arch::kBigEndian);
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture `arch` is big endian.
|
||||
static inline bool isBigEndian(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isBigEndian(Arch arch) noexcept {
|
||||
return uint32_t(arch) >= uint32_t(Arch::kBigEndian);
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture is Thumb or Thumb_BE.
|
||||
static inline bool isArchThumb(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isArchThumb(Arch arch) noexcept {
|
||||
return arch == Arch::kThumb || arch == Arch::kThumb_BE;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture is ARM or ARM_BE.
|
||||
static inline bool isArchARM(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isArchARM(Arch arch) noexcept {
|
||||
return arch == Arch::kARM || arch == Arch::kARM_BE;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture is AArch64 or AArch64_BE.
|
||||
static inline bool isArchAArch64(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isArchAArch64(Arch arch) noexcept {
|
||||
return arch == Arch::kAArch64 || arch == Arch::kAArch64_BE;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture is MIPS32_LE or MIPS32_BE.
|
||||
static inline bool isArchMIPS32(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isArchMIPS32(Arch arch) noexcept {
|
||||
return arch == Arch::kMIPS32_LE || arch == Arch::kMIPS32_BE;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture is MIPS64_LE or MIPS64_BE.
|
||||
static inline bool isArchMIPS64(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isArchMIPS64(Arch arch) noexcept {
|
||||
return arch == Arch::kMIPS64_LE || arch == Arch::kMIPS64_BE;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture family is X86 or X64.
|
||||
static inline bool isFamilyX86(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isFamilyX86(Arch arch) noexcept {
|
||||
return arch == Arch::kX86 || arch == Arch::kX64;
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture family is ARM, THUMB, or AArch64.
|
||||
static inline bool isFamilyARM(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isFamilyARM(Arch arch) noexcept {
|
||||
return isArchARM(arch) || isArchAArch64(arch) || isArchThumb(arch);
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture family is AArch32 (ARM or THUMB).
|
||||
static inline bool isFamilyAArch32(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isFamilyAArch32(Arch arch) noexcept {
|
||||
return isArchARM(arch) || isArchThumb(arch);
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture family is AArch64.
|
||||
static inline bool isFamilyAArch64(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isFamilyAArch64(Arch arch) noexcept {
|
||||
return isArchAArch64(arch);
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture family is MISP or MIPS64.
|
||||
static inline bool isFamilyMIPS(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isFamilyMIPS(Arch arch) noexcept {
|
||||
return isArchMIPS32(arch) || isArchMIPS64(arch);
|
||||
}
|
||||
|
||||
//! Tests whether the given architecture family is RISC-V (both 32-bit and 64-bit).
|
||||
static inline bool isFamilyRISCV(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isFamilyRISCV(Arch arch) noexcept {
|
||||
return arch == Arch::kRISCV32 || arch == Arch::kRISCV64;
|
||||
}
|
||||
|
||||
//! Returns a native general purpose register size from the given architecture.
|
||||
static inline uint32_t registerSizeFromArch(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG uint32_t registerSizeFromArch(Arch arch) noexcept {
|
||||
return is32Bit(arch) ? 4u : 8u;
|
||||
}
|
||||
|
||||
|
||||
@@ -91,7 +91,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Resets FormatOptions to its default initialized state.
|
||||
inline void reset() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept {
|
||||
_flags = FormatFlags::kNone;
|
||||
_indentation.fill(uint8_t(0));
|
||||
_padding.fill(uint16_t(0));
|
||||
@@ -103,31 +103,31 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns format flags.
|
||||
inline FormatFlags flags() const noexcept { return _flags; }
|
||||
ASMJIT_INLINE_NODEBUG FormatFlags flags() const noexcept { return _flags; }
|
||||
//! Tests whether the given `flag` is set in format flags.
|
||||
inline bool hasFlag(FormatFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(FormatFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
|
||||
//! Resets all format flags to `flags`.
|
||||
inline void setFlags(FormatFlags flags) noexcept { _flags = flags; }
|
||||
ASMJIT_INLINE_NODEBUG void setFlags(FormatFlags flags) noexcept { _flags = flags; }
|
||||
//! Adds `flags` to format flags.
|
||||
inline void addFlags(FormatFlags flags) noexcept { _flags |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG void addFlags(FormatFlags flags) noexcept { _flags |= flags; }
|
||||
//! Removes `flags` from format flags.
|
||||
inline void clearFlags(FormatFlags flags) noexcept { _flags &= ~flags; }
|
||||
ASMJIT_INLINE_NODEBUG void clearFlags(FormatFlags flags) noexcept { _flags &= ~flags; }
|
||||
|
||||
//! Returns indentation for the given indentation `group`.
|
||||
inline uint8_t indentation(FormatIndentationGroup group) const noexcept { return _indentation[group]; }
|
||||
ASMJIT_INLINE_NODEBUG uint8_t indentation(FormatIndentationGroup group) const noexcept { return _indentation[group]; }
|
||||
//! Sets indentation for the given indentation `group`.
|
||||
inline void setIndentation(FormatIndentationGroup group, uint32_t n) noexcept { _indentation[group] = uint8_t(n); }
|
||||
ASMJIT_INLINE_NODEBUG void setIndentation(FormatIndentationGroup group, uint32_t n) noexcept { _indentation[group] = uint8_t(n); }
|
||||
//! Resets indentation for the given indentation `group` to zero.
|
||||
inline void resetIndentation(FormatIndentationGroup group) noexcept { _indentation[group] = uint8_t(0); }
|
||||
ASMJIT_INLINE_NODEBUG void resetIndentation(FormatIndentationGroup group) noexcept { _indentation[group] = uint8_t(0); }
|
||||
|
||||
//! Returns pading for the given padding `group`.
|
||||
inline size_t padding(FormatPaddingGroup group) const noexcept { return _padding[group]; }
|
||||
//! Sets pading for the given padding `group`.
|
||||
inline void setPadding(FormatPaddingGroup group, size_t n) noexcept { _padding[group] = uint16_t(n); }
|
||||
//! Resets pading for the given padding `group` to zero, which means that a default padding will be used
|
||||
//! Returns padding for the given padding `group`.
|
||||
ASMJIT_INLINE_NODEBUG size_t padding(FormatPaddingGroup group) const noexcept { return _padding[group]; }
|
||||
//! Sets padding for the given padding `group`.
|
||||
ASMJIT_INLINE_NODEBUG void setPadding(FormatPaddingGroup group, size_t n) noexcept { _padding[group] = uint16_t(n); }
|
||||
//! Resets padding for the given padding `group` to zero, which means that a default padding will be used
|
||||
//! based on the target architecture properties.
|
||||
inline void resetPadding(FormatPaddingGroup group) noexcept { _padding[group] = uint16_t(0); }
|
||||
ASMJIT_INLINE_NODEBUG void resetPadding(FormatPaddingGroup group) noexcept { _padding[group] = uint16_t(0); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
@@ -228,7 +228,7 @@ struct CallConv {
|
||||
//! It's recommended to reset the \ref CallConv struct in case you would like create a custom calling convention
|
||||
//! as it prevents from using an uninitialized data (CallConv doesn't have a constructor that would initialize it,
|
||||
//! it's just a struct).
|
||||
inline void reset() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept {
|
||||
memset(this, 0, sizeof(*this));
|
||||
memset(_passedOrder.data(), 0xFF, sizeof(_passedOrder));
|
||||
}
|
||||
@@ -239,61 +239,61 @@ struct CallConv {
|
||||
//! \{
|
||||
|
||||
//! Returns the target architecture of this calling convention.
|
||||
inline Arch arch() const noexcept { return _arch; }
|
||||
ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return _arch; }
|
||||
//! Sets the target architecture of this calling convention.
|
||||
inline void setArch(Arch arch) noexcept { _arch = arch; }
|
||||
ASMJIT_INLINE_NODEBUG void setArch(Arch arch) noexcept { _arch = arch; }
|
||||
|
||||
//! Returns the calling convention id.
|
||||
inline CallConvId id() const noexcept { return _id; }
|
||||
ASMJIT_INLINE_NODEBUG CallConvId id() const noexcept { return _id; }
|
||||
//! Sets the calling convention id.
|
||||
inline void setId(CallConvId ccId) noexcept { _id = ccId; }
|
||||
ASMJIT_INLINE_NODEBUG void setId(CallConvId ccId) noexcept { _id = ccId; }
|
||||
|
||||
//! Returns the strategy used to assign registers to arguments.
|
||||
inline CallConvStrategy strategy() const noexcept { return _strategy; }
|
||||
ASMJIT_INLINE_NODEBUG CallConvStrategy strategy() const noexcept { return _strategy; }
|
||||
//! Sets the strategy used to assign registers to arguments.
|
||||
inline void setStrategy(CallConvStrategy ccStrategy) noexcept { _strategy = ccStrategy; }
|
||||
ASMJIT_INLINE_NODEBUG void setStrategy(CallConvStrategy ccStrategy) noexcept { _strategy = ccStrategy; }
|
||||
|
||||
//! Tests whether the calling convention has the given `flag` set.
|
||||
inline bool hasFlag(CallConvFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(CallConvFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
//! Returns the calling convention flags, see `Flags`.
|
||||
inline CallConvFlags flags() const noexcept { return _flags; }
|
||||
ASMJIT_INLINE_NODEBUG CallConvFlags flags() const noexcept { return _flags; }
|
||||
//! Adds the calling convention flags, see `Flags`.
|
||||
inline void setFlags(CallConvFlags flag) noexcept { _flags = flag; };
|
||||
ASMJIT_INLINE_NODEBUG void setFlags(CallConvFlags flag) noexcept { _flags = flag; };
|
||||
//! Adds the calling convention flags, see `Flags`.
|
||||
inline void addFlags(CallConvFlags flags) noexcept { _flags |= flags; };
|
||||
ASMJIT_INLINE_NODEBUG void addFlags(CallConvFlags flags) noexcept { _flags |= flags; };
|
||||
|
||||
//! Tests whether this calling convention specifies 'RedZone'.
|
||||
inline bool hasRedZone() const noexcept { return _redZoneSize != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasRedZone() const noexcept { return _redZoneSize != 0; }
|
||||
//! Tests whether this calling convention specifies 'SpillZone'.
|
||||
inline bool hasSpillZone() const noexcept { return _spillZoneSize != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasSpillZone() const noexcept { return _spillZoneSize != 0; }
|
||||
|
||||
//! Returns size of 'RedZone'.
|
||||
inline uint32_t redZoneSize() const noexcept { return _redZoneSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t redZoneSize() const noexcept { return _redZoneSize; }
|
||||
//! Returns size of 'SpillZone'.
|
||||
inline uint32_t spillZoneSize() const noexcept { return _spillZoneSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t spillZoneSize() const noexcept { return _spillZoneSize; }
|
||||
|
||||
//! Sets size of 'RedZone'.
|
||||
inline void setRedZoneSize(uint32_t size) noexcept { _redZoneSize = uint8_t(size); }
|
||||
ASMJIT_INLINE_NODEBUG void setRedZoneSize(uint32_t size) noexcept { _redZoneSize = uint8_t(size); }
|
||||
//! Sets size of 'SpillZone'.
|
||||
inline void setSpillZoneSize(uint32_t size) noexcept { _spillZoneSize = uint8_t(size); }
|
||||
ASMJIT_INLINE_NODEBUG void setSpillZoneSize(uint32_t size) noexcept { _spillZoneSize = uint8_t(size); }
|
||||
|
||||
//! Returns a natural stack alignment.
|
||||
inline uint32_t naturalStackAlignment() const noexcept { return _naturalStackAlignment; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t naturalStackAlignment() const noexcept { return _naturalStackAlignment; }
|
||||
//! Sets a natural stack alignment.
|
||||
//!
|
||||
//! This function can be used to override the default stack alignment in case that you know that it's alignment is
|
||||
//! different. For example it allows to implement custom calling conventions that guarantee higher stack alignment.
|
||||
inline void setNaturalStackAlignment(uint32_t value) noexcept { _naturalStackAlignment = uint8_t(value); }
|
||||
ASMJIT_INLINE_NODEBUG void setNaturalStackAlignment(uint32_t value) noexcept { _naturalStackAlignment = uint8_t(value); }
|
||||
|
||||
//! Returns the size of a register (or its part) to be saved and restored of the given `group`.
|
||||
inline uint32_t saveRestoreRegSize(RegGroup group) const noexcept { return _saveRestoreRegSize[group]; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t saveRestoreRegSize(RegGroup group) const noexcept { return _saveRestoreRegSize[group]; }
|
||||
//! Sets the size of a vector register (or its part) to be saved and restored.
|
||||
inline void setSaveRestoreRegSize(RegGroup group, uint32_t size) noexcept { _saveRestoreRegSize[group] = uint8_t(size); }
|
||||
ASMJIT_INLINE_NODEBUG void setSaveRestoreRegSize(RegGroup group, uint32_t size) noexcept { _saveRestoreRegSize[group] = uint8_t(size); }
|
||||
|
||||
//! Returns the alignment of a save-restore area of the given `group`.
|
||||
inline uint32_t saveRestoreAlignment(RegGroup group) const noexcept { return _saveRestoreAlignment[group]; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t saveRestoreAlignment(RegGroup group) const noexcept { return _saveRestoreAlignment[group]; }
|
||||
//! Sets the alignment of a save-restore area of the given `group`.
|
||||
inline void setSaveRestoreAlignment(RegGroup group, uint32_t alignment) noexcept { _saveRestoreAlignment[group] = uint8_t(alignment); }
|
||||
ASMJIT_INLINE_NODEBUG void setSaveRestoreAlignment(RegGroup group, uint32_t alignment) noexcept { _saveRestoreAlignment[group] = uint8_t(alignment); }
|
||||
|
||||
//! Returns the order of passed registers of the given `group`.
|
||||
inline const uint8_t* passedOrder(RegGroup group) const noexcept {
|
||||
@@ -403,7 +403,7 @@ struct FuncSignature {
|
||||
_args = args;
|
||||
}
|
||||
|
||||
inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = FuncSignature{}; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -411,25 +411,25 @@ struct FuncSignature {
|
||||
//! \{
|
||||
|
||||
//! Returns the calling convention.
|
||||
inline CallConvId callConvId() const noexcept { return _ccId; }
|
||||
ASMJIT_INLINE_NODEBUG CallConvId callConvId() const noexcept { return _ccId; }
|
||||
//! Sets the calling convention to `ccId`;
|
||||
inline void setCallConvId(CallConvId ccId) noexcept { _ccId = ccId; }
|
||||
ASMJIT_INLINE_NODEBUG void setCallConvId(CallConvId ccId) noexcept { _ccId = ccId; }
|
||||
|
||||
//! Tests whether the function has variable number of arguments (...).
|
||||
inline bool hasVarArgs() const noexcept { return _vaIndex != kNoVarArgs; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasVarArgs() const noexcept { return _vaIndex != kNoVarArgs; }
|
||||
//! Returns the variable arguments (...) index, `kNoVarArgs` if none.
|
||||
inline uint32_t vaIndex() const noexcept { return _vaIndex; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t vaIndex() const noexcept { return _vaIndex; }
|
||||
//! Sets the variable arguments (...) index to `index`.
|
||||
inline void setVaIndex(uint32_t index) noexcept { _vaIndex = uint8_t(index); }
|
||||
ASMJIT_INLINE_NODEBUG void setVaIndex(uint32_t index) noexcept { _vaIndex = uint8_t(index); }
|
||||
//! Resets the variable arguments index (making it a non-va function).
|
||||
inline void resetVaIndex() noexcept { _vaIndex = kNoVarArgs; }
|
||||
ASMJIT_INLINE_NODEBUG void resetVaIndex() noexcept { _vaIndex = kNoVarArgs; }
|
||||
|
||||
//! Returns the number of function arguments.
|
||||
inline uint32_t argCount() const noexcept { return _argCount; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t argCount() const noexcept { return _argCount; }
|
||||
|
||||
inline bool hasRet() const noexcept { return _ret != TypeId::kVoid; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasRet() const noexcept { return _ret != TypeId::kVoid; }
|
||||
//! Returns the return value type.
|
||||
inline TypeId ret() const noexcept { return _ret; }
|
||||
ASMJIT_INLINE_NODEBUG TypeId ret() const noexcept { return _ret; }
|
||||
|
||||
//! Returns the type of the argument at index `i`.
|
||||
inline TypeId arg(uint32_t i) const noexcept {
|
||||
@@ -437,7 +437,7 @@ struct FuncSignature {
|
||||
return _args[i];
|
||||
}
|
||||
//! Returns the array of function arguments' types.
|
||||
inline const TypeId* args() const noexcept { return _args; }
|
||||
ASMJIT_INLINE_NODEBUG const TypeId* args() const noexcept { return _args; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -445,7 +445,7 @@ struct FuncSignature {
|
||||
template<typename... RET_ARGS>
|
||||
class FuncSignatureT : public FuncSignature {
|
||||
public:
|
||||
inline FuncSignatureT(CallConvId ccId = CallConvId::kHost, uint32_t vaIndex = kNoVarArgs) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG FuncSignatureT(CallConvId ccId = CallConvId::kHost, uint32_t vaIndex = kNoVarArgs) noexcept {
|
||||
static constexpr TypeId ret_args[] = { (TypeId(TypeUtils::TypeIdOfT<RET_ARGS>::kTypeId))... };
|
||||
init(ccId, vaIndex, ret_args[0], ret_args + 1, uint32_t(ASMJIT_ARRAY_SIZE(ret_args) - 1));
|
||||
}
|
||||
@@ -459,7 +459,7 @@ public:
|
||||
//! \name Initialization & Reset
|
||||
//! \{
|
||||
|
||||
inline FuncSignatureBuilder(CallConvId ccId = CallConvId::kHost, uint32_t vaIndex = kNoVarArgs) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG FuncSignatureBuilder(CallConvId ccId = CallConvId::kHost, uint32_t vaIndex = kNoVarArgs) noexcept {
|
||||
init(ccId, vaIndex, TypeId::kVoid, _builderArgList, 0);
|
||||
}
|
||||
|
||||
@@ -469,10 +469,10 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Sets the return type to `retType`.
|
||||
inline void setRet(TypeId retType) noexcept { _ret = retType; }
|
||||
ASMJIT_INLINE_NODEBUG void setRet(TypeId retType) noexcept { _ret = retType; }
|
||||
//! Sets the return type based on `T`.
|
||||
template<typename T>
|
||||
inline void setRetT() noexcept { setRet(TypeId(TypeUtils::TypeIdOfT<T>::kTypeId)); }
|
||||
ASMJIT_INLINE_NODEBUG void setRetT() noexcept { setRet(TypeId(TypeUtils::TypeIdOfT<T>::kTypeId)); }
|
||||
|
||||
//! Sets the argument at index `index` to `argType`.
|
||||
inline void setArg(uint32_t index, TypeId argType) noexcept {
|
||||
@@ -537,20 +537,20 @@ struct FuncValue {
|
||||
//! \{
|
||||
|
||||
//! Initializes the `typeId` of this `FuncValue`.
|
||||
inline void initTypeId(TypeId typeId) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void initTypeId(TypeId typeId) noexcept {
|
||||
_data = uint32_t(typeId) << kTypeIdShift;
|
||||
}
|
||||
|
||||
inline void initReg(RegType regType, uint32_t regId, TypeId typeId, uint32_t flags = 0) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void initReg(RegType regType, uint32_t regId, TypeId typeId, uint32_t flags = 0) noexcept {
|
||||
_data = (uint32_t(regType) << kRegTypeShift) | (regId << kRegIdShift) | (uint32_t(typeId) << kTypeIdShift) | kFlagIsReg | flags;
|
||||
}
|
||||
|
||||
inline void initStack(int32_t offset, TypeId typeId) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void initStack(int32_t offset, TypeId typeId) noexcept {
|
||||
_data = (uint32_t(offset) << kStackOffsetShift) | (uint32_t(typeId) << kTypeIdShift) | kFlagIsStack;
|
||||
}
|
||||
|
||||
//! Resets the value to its unassigned state.
|
||||
inline void reset() noexcept { _data = 0; }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { _data = 0; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -577,52 +577,52 @@ struct FuncValue {
|
||||
//! \{
|
||||
|
||||
//! Returns true if the value is initialized (explicit bool cast).
|
||||
inline explicit operator bool() const noexcept { return _data != 0; }
|
||||
ASMJIT_INLINE_NODEBUG explicit operator bool() const noexcept { return _data != 0; }
|
||||
|
||||
inline void _replaceValue(uint32_t mask, uint32_t value) noexcept { _data = (_data & ~mask) | value; }
|
||||
ASMJIT_INLINE_NODEBUG void _replaceValue(uint32_t mask, uint32_t value) noexcept { _data = (_data & ~mask) | value; }
|
||||
|
||||
//! Tests whether the `FuncValue` has a flag `flag` set.
|
||||
inline bool hasFlag(uint32_t flag) const noexcept { return Support::test(_data, flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(uint32_t flag) const noexcept { return Support::test(_data, flag); }
|
||||
//! Adds `flags` to `FuncValue`.
|
||||
inline void addFlags(uint32_t flags) noexcept { _data |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG void addFlags(uint32_t flags) noexcept { _data |= flags; }
|
||||
//! Clears `flags` of `FuncValue`.
|
||||
inline void clearFlags(uint32_t flags) noexcept { _data &= ~flags; }
|
||||
ASMJIT_INLINE_NODEBUG void clearFlags(uint32_t flags) noexcept { _data &= ~flags; }
|
||||
|
||||
//! Tests whether the value is initialized (i.e. contains a valid data).
|
||||
inline bool isInitialized() const noexcept { return _data != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool isInitialized() const noexcept { return _data != 0; }
|
||||
//! Tests whether the argument is passed by register.
|
||||
inline bool isReg() const noexcept { return hasFlag(kFlagIsReg); }
|
||||
ASMJIT_INLINE_NODEBUG bool isReg() const noexcept { return hasFlag(kFlagIsReg); }
|
||||
//! Tests whether the argument is passed by stack.
|
||||
inline bool isStack() const noexcept { return hasFlag(kFlagIsStack); }
|
||||
ASMJIT_INLINE_NODEBUG bool isStack() const noexcept { return hasFlag(kFlagIsStack); }
|
||||
//! Tests whether the argument is passed by register.
|
||||
inline bool isAssigned() const noexcept { return hasFlag(kFlagIsReg | kFlagIsStack); }
|
||||
ASMJIT_INLINE_NODEBUG bool isAssigned() const noexcept { return hasFlag(kFlagIsReg | kFlagIsStack); }
|
||||
//! Tests whether the argument is passed through a pointer (used by WIN64 to pass XMM|YMM|ZMM).
|
||||
inline bool isIndirect() const noexcept { return hasFlag(kFlagIsIndirect); }
|
||||
ASMJIT_INLINE_NODEBUG bool isIndirect() const noexcept { return hasFlag(kFlagIsIndirect); }
|
||||
|
||||
//! Tests whether the argument was already processed (used internally).
|
||||
inline bool isDone() const noexcept { return hasFlag(kFlagIsDone); }
|
||||
ASMJIT_INLINE_NODEBUG bool isDone() const noexcept { return hasFlag(kFlagIsDone); }
|
||||
|
||||
//! Returns a register type of the register used to pass function argument or return value.
|
||||
inline RegType regType() const noexcept { return RegType((_data & kRegTypeMask) >> kRegTypeShift); }
|
||||
ASMJIT_INLINE_NODEBUG RegType regType() const noexcept { return RegType((_data & kRegTypeMask) >> kRegTypeShift); }
|
||||
//! Sets a register type of the register used to pass function argument or return value.
|
||||
inline void setRegType(RegType regType) noexcept { _replaceValue(kRegTypeMask, uint32_t(regType) << kRegTypeShift); }
|
||||
ASMJIT_INLINE_NODEBUG void setRegType(RegType regType) noexcept { _replaceValue(kRegTypeMask, uint32_t(regType) << kRegTypeShift); }
|
||||
|
||||
//! Returns a physical id of the register used to pass function argument or return value.
|
||||
inline uint32_t regId() const noexcept { return (_data & kRegIdMask) >> kRegIdShift; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t regId() const noexcept { return (_data & kRegIdMask) >> kRegIdShift; }
|
||||
//! Sets a physical id of the register used to pass function argument or return value.
|
||||
inline void setRegId(uint32_t regId) noexcept { _replaceValue(kRegIdMask, regId << kRegIdShift); }
|
||||
ASMJIT_INLINE_NODEBUG void setRegId(uint32_t regId) noexcept { _replaceValue(kRegIdMask, regId << kRegIdShift); }
|
||||
|
||||
//! Returns a stack offset of this argument.
|
||||
inline int32_t stackOffset() const noexcept { return int32_t(_data & kStackOffsetMask) >> kStackOffsetShift; }
|
||||
ASMJIT_INLINE_NODEBUG int32_t stackOffset() const noexcept { return int32_t(_data & kStackOffsetMask) >> kStackOffsetShift; }
|
||||
//! Sets a stack offset of this argument.
|
||||
inline void setStackOffset(int32_t offset) noexcept { _replaceValue(kStackOffsetMask, uint32_t(offset) << kStackOffsetShift); }
|
||||
ASMJIT_INLINE_NODEBUG void setStackOffset(int32_t offset) noexcept { _replaceValue(kStackOffsetMask, uint32_t(offset) << kStackOffsetShift); }
|
||||
|
||||
//! Tests whether the argument or return value has associated `TypeId`.
|
||||
inline bool hasTypeId() const noexcept { return Support::test(_data, kTypeIdMask); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasTypeId() const noexcept { return Support::test(_data, kTypeIdMask); }
|
||||
//! Returns a TypeId of this argument or return value.
|
||||
inline TypeId typeId() const noexcept { return TypeId((_data & kTypeIdMask) >> kTypeIdShift); }
|
||||
ASMJIT_INLINE_NODEBUG TypeId typeId() const noexcept { return TypeId((_data & kTypeIdMask) >> kTypeIdShift); }
|
||||
//! Sets a TypeId of this argument or return value.
|
||||
inline void setTypeId(TypeId typeId) noexcept { _replaceValue(kTypeIdMask, uint32_t(typeId) << kTypeIdShift); }
|
||||
ASMJIT_INLINE_NODEBUG void setTypeId(TypeId typeId) noexcept { _replaceValue(kTypeIdMask, uint32_t(typeId) << kTypeIdShift); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -661,8 +661,8 @@ public:
|
||||
return n;
|
||||
}
|
||||
|
||||
inline FuncValue* values() noexcept { return _values; }
|
||||
inline const FuncValue* values() const noexcept { return _values; }
|
||||
ASMJIT_INLINE_NODEBUG FuncValue* values() noexcept { return _values; }
|
||||
ASMJIT_INLINE_NODEBUG const FuncValue* values() const noexcept { return _values; }
|
||||
|
||||
inline void resetValue(size_t index) noexcept {
|
||||
ASMJIT_ASSERT(index < Globals::kMaxValuePack);
|
||||
@@ -764,33 +764,40 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Calling convention.
|
||||
CallConv _callConv;
|
||||
CallConv _callConv {};
|
||||
//! Number of function arguments.
|
||||
uint8_t _argCount;
|
||||
uint8_t _argCount = 0;
|
||||
//! Variable arguments index of `kNoVarArgs`.
|
||||
uint8_t _vaIndex;
|
||||
uint8_t _vaIndex = 0;
|
||||
//! Reserved for future use.
|
||||
uint16_t _reserved;
|
||||
uint16_t _reserved = 0;
|
||||
//! Registers that contain arguments.
|
||||
Support::Array<RegMask, Globals::kNumVirtGroups> _usedRegs;
|
||||
Support::Array<RegMask, Globals::kNumVirtGroups> _usedRegs {};
|
||||
//! Size of arguments passed by stack.
|
||||
uint32_t _argStackSize;
|
||||
uint32_t _argStackSize = 0;
|
||||
//! Function return value(s).
|
||||
FuncValuePack _rets;
|
||||
FuncValuePack _rets {};
|
||||
//! Function arguments.
|
||||
FuncValuePack _args[Globals::kMaxFuncArgs];
|
||||
FuncValuePack _args[Globals::kMaxFuncArgs] {};
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline FuncDetail() noexcept { reset(); }
|
||||
inline FuncDetail(const FuncDetail& other) noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG FuncDetail() noexcept {}
|
||||
ASMJIT_INLINE_NODEBUG FuncDetail(const FuncDetail& other) noexcept = default;
|
||||
|
||||
//! Initializes this `FuncDetail` to the given signature.
|
||||
ASMJIT_API Error init(const FuncSignature& signature, const Environment& environment) noexcept;
|
||||
inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = FuncDetail{}; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
ASMJIT_INLINE_NODEBUG FuncDetail& operator=(const FuncDetail& other) noexcept = default;
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -798,32 +805,32 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the function's calling convention, see `CallConv`.
|
||||
inline const CallConv& callConv() const noexcept { return _callConv; }
|
||||
ASMJIT_INLINE_NODEBUG const CallConv& callConv() const noexcept { return _callConv; }
|
||||
|
||||
//! Returns the associated calling convention flags, see `CallConv::Flags`.
|
||||
inline CallConvFlags flags() const noexcept { return _callConv.flags(); }
|
||||
ASMJIT_INLINE_NODEBUG CallConvFlags flags() const noexcept { return _callConv.flags(); }
|
||||
//! Checks whether a CallConv `flag` is set, see `CallConv::Flags`.
|
||||
inline bool hasFlag(CallConvFlags ccFlag) const noexcept { return _callConv.hasFlag(ccFlag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(CallConvFlags ccFlag) const noexcept { return _callConv.hasFlag(ccFlag); }
|
||||
|
||||
//! Tests whether the function has a return value.
|
||||
inline bool hasRet() const noexcept { return bool(_rets[0]); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasRet() const noexcept { return bool(_rets[0]); }
|
||||
//! Returns the number of function arguments.
|
||||
inline uint32_t argCount() const noexcept { return _argCount; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t argCount() const noexcept { return _argCount; }
|
||||
|
||||
//! Returns function return values.
|
||||
inline FuncValuePack& retPack() noexcept { return _rets; }
|
||||
ASMJIT_INLINE_NODEBUG FuncValuePack& retPack() noexcept { return _rets; }
|
||||
//! Returns function return values.
|
||||
inline const FuncValuePack& retPack() const noexcept { return _rets; }
|
||||
ASMJIT_INLINE_NODEBUG const FuncValuePack& retPack() const noexcept { return _rets; }
|
||||
|
||||
//! Returns a function return value associated with the given `valueIndex`.
|
||||
inline FuncValue& ret(size_t valueIndex = 0) noexcept { return _rets[valueIndex]; }
|
||||
ASMJIT_INLINE_NODEBUG FuncValue& ret(size_t valueIndex = 0) noexcept { return _rets[valueIndex]; }
|
||||
//! Returns a function return value associated with the given `valueIndex` (const).
|
||||
inline const FuncValue& ret(size_t valueIndex = 0) const noexcept { return _rets[valueIndex]; }
|
||||
ASMJIT_INLINE_NODEBUG const FuncValue& ret(size_t valueIndex = 0) const noexcept { return _rets[valueIndex]; }
|
||||
|
||||
//! Returns function argument packs array.
|
||||
inline FuncValuePack* argPacks() noexcept { return _args; }
|
||||
ASMJIT_INLINE_NODEBUG FuncValuePack* argPacks() noexcept { return _args; }
|
||||
//! Returns function argument packs array (const).
|
||||
inline const FuncValuePack* argPacks() const noexcept { return _args; }
|
||||
ASMJIT_INLINE_NODEBUG const FuncValuePack* argPacks() const noexcept { return _args; }
|
||||
|
||||
//! Returns function argument pack at the given `argIndex`.
|
||||
inline FuncValuePack& argPack(size_t argIndex) noexcept {
|
||||
@@ -858,26 +865,26 @@ public:
|
||||
}
|
||||
|
||||
//! Tests whether the function has variable arguments.
|
||||
inline bool hasVarArgs() const noexcept { return _vaIndex != kNoVarArgs; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasVarArgs() const noexcept { return _vaIndex != kNoVarArgs; }
|
||||
//! Returns an index of a first variable argument.
|
||||
inline uint32_t vaIndex() const noexcept { return _vaIndex; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t vaIndex() const noexcept { return _vaIndex; }
|
||||
|
||||
//! Tests whether the function passes one or more argument by stack.
|
||||
inline bool hasStackArgs() const noexcept { return _argStackSize != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasStackArgs() const noexcept { return _argStackSize != 0; }
|
||||
//! Returns stack size needed for function arguments passed on the stack.
|
||||
inline uint32_t argStackSize() const noexcept { return _argStackSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t argStackSize() const noexcept { return _argStackSize; }
|
||||
|
||||
//! Returns red zone size.
|
||||
inline uint32_t redZoneSize() const noexcept { return _callConv.redZoneSize(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t redZoneSize() const noexcept { return _callConv.redZoneSize(); }
|
||||
//! Returns spill zone size.
|
||||
inline uint32_t spillZoneSize() const noexcept { return _callConv.spillZoneSize(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t spillZoneSize() const noexcept { return _callConv.spillZoneSize(); }
|
||||
//! Returns natural stack alignment.
|
||||
inline uint32_t naturalStackAlignment() const noexcept { return _callConv.naturalStackAlignment(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t naturalStackAlignment() const noexcept { return _callConv.naturalStackAlignment(); }
|
||||
|
||||
//! Returns a mask of all passed registers of the given register `group`.
|
||||
inline RegMask passedRegs(RegGroup group) const noexcept { return _callConv.passedRegs(group); }
|
||||
ASMJIT_INLINE_NODEBUG RegMask passedRegs(RegGroup group) const noexcept { return _callConv.passedRegs(group); }
|
||||
//! Returns a mask of all preserved registers of the given register `group`.
|
||||
inline RegMask preservedRegs(RegGroup group) const noexcept { return _callConv.preservedRegs(group); }
|
||||
ASMJIT_INLINE_NODEBUG RegMask preservedRegs(RegGroup group) const noexcept { return _callConv.preservedRegs(group); }
|
||||
|
||||
//! Returns a mask of all used registers of the given register `group`.
|
||||
inline RegMask usedRegs(RegGroup group) const noexcept {
|
||||
@@ -1020,12 +1027,12 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline FuncFrame() noexcept { reset(); }
|
||||
inline FuncFrame(const FuncFrame& other) noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG FuncFrame() noexcept { reset(); }
|
||||
ASMJIT_INLINE_NODEBUG FuncFrame(const FuncFrame& other) noexcept = default;
|
||||
|
||||
ASMJIT_API Error init(const FuncDetail& func) noexcept;
|
||||
|
||||
inline void reset() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept {
|
||||
memset(this, 0, sizeof(FuncFrame));
|
||||
_spRegId = BaseReg::kIdBad;
|
||||
_saRegId = BaseReg::kIdBad;
|
||||
@@ -1038,84 +1045,84 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the target architecture of the function frame.
|
||||
inline Arch arch() const noexcept { return _arch; }
|
||||
ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return _arch; }
|
||||
|
||||
//! Returns function frame attributes, see `Attributes`.
|
||||
inline FuncAttributes attributes() const noexcept { return _attributes; }
|
||||
ASMJIT_INLINE_NODEBUG FuncAttributes attributes() const noexcept { return _attributes; }
|
||||
//! Checks whether the FuncFame contains an attribute `attr`.
|
||||
inline bool hasAttribute(FuncAttributes attr) const noexcept { return Support::test(_attributes, attr); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAttribute(FuncAttributes attr) const noexcept { return Support::test(_attributes, attr); }
|
||||
//! Adds attributes `attrs` to the FuncFrame.
|
||||
inline void addAttributes(FuncAttributes attrs) noexcept { _attributes |= attrs; }
|
||||
ASMJIT_INLINE_NODEBUG void addAttributes(FuncAttributes attrs) noexcept { _attributes |= attrs; }
|
||||
//! Clears attributes `attrs` from the FrameFrame.
|
||||
inline void clearAttributes(FuncAttributes attrs) noexcept { _attributes &= ~attrs; }
|
||||
ASMJIT_INLINE_NODEBUG void clearAttributes(FuncAttributes attrs) noexcept { _attributes &= ~attrs; }
|
||||
|
||||
//! Tests whether the function has variable number of arguments.
|
||||
inline bool hasVarArgs() const noexcept { return hasAttribute(FuncAttributes::kHasVarArgs); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasVarArgs() const noexcept { return hasAttribute(FuncAttributes::kHasVarArgs); }
|
||||
//! Sets the variable arguments flag.
|
||||
inline void setVarArgs() noexcept { addAttributes(FuncAttributes::kHasVarArgs); }
|
||||
ASMJIT_INLINE_NODEBUG void setVarArgs() noexcept { addAttributes(FuncAttributes::kHasVarArgs); }
|
||||
//! Resets variable arguments flag.
|
||||
inline void resetVarArgs() noexcept { clearAttributes(FuncAttributes::kHasVarArgs); }
|
||||
ASMJIT_INLINE_NODEBUG void resetVarArgs() noexcept { clearAttributes(FuncAttributes::kHasVarArgs); }
|
||||
|
||||
//! Tests whether the function preserves frame pointer (EBP|ESP on X86).
|
||||
inline bool hasPreservedFP() const noexcept { return hasAttribute(FuncAttributes::kHasPreservedFP); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasPreservedFP() const noexcept { return hasAttribute(FuncAttributes::kHasPreservedFP); }
|
||||
//! Enables preserved frame pointer.
|
||||
inline void setPreservedFP() noexcept { addAttributes(FuncAttributes::kHasPreservedFP); }
|
||||
ASMJIT_INLINE_NODEBUG void setPreservedFP() noexcept { addAttributes(FuncAttributes::kHasPreservedFP); }
|
||||
//! Disables preserved frame pointer.
|
||||
inline void resetPreservedFP() noexcept { clearAttributes(FuncAttributes::kHasPreservedFP); }
|
||||
ASMJIT_INLINE_NODEBUG void resetPreservedFP() noexcept { clearAttributes(FuncAttributes::kHasPreservedFP); }
|
||||
|
||||
//! Tests whether the function calls other functions.
|
||||
inline bool hasFuncCalls() const noexcept { return hasAttribute(FuncAttributes::kHasFuncCalls); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFuncCalls() const noexcept { return hasAttribute(FuncAttributes::kHasFuncCalls); }
|
||||
//! Sets `kFlagHasCalls` to true.
|
||||
inline void setFuncCalls() noexcept { addAttributes(FuncAttributes::kHasFuncCalls); }
|
||||
ASMJIT_INLINE_NODEBUG void setFuncCalls() noexcept { addAttributes(FuncAttributes::kHasFuncCalls); }
|
||||
//! Sets `kFlagHasCalls` to false.
|
||||
inline void resetFuncCalls() noexcept { clearAttributes(FuncAttributes::kHasFuncCalls); }
|
||||
ASMJIT_INLINE_NODEBUG void resetFuncCalls() noexcept { clearAttributes(FuncAttributes::kHasFuncCalls); }
|
||||
|
||||
//! Tests whether the function has AVX enabled.
|
||||
inline bool isAvxEnabled() const noexcept { return hasAttribute(FuncAttributes::kX86_AVXEnabled); }
|
||||
ASMJIT_INLINE_NODEBUG bool isAvxEnabled() const noexcept { return hasAttribute(FuncAttributes::kX86_AVXEnabled); }
|
||||
//! Enables AVX use.
|
||||
inline void setAvxEnabled() noexcept { addAttributes(FuncAttributes::kX86_AVXEnabled); }
|
||||
ASMJIT_INLINE_NODEBUG void setAvxEnabled() noexcept { addAttributes(FuncAttributes::kX86_AVXEnabled); }
|
||||
//! Disables AVX use.
|
||||
inline void resetAvxEnabled() noexcept { clearAttributes(FuncAttributes::kX86_AVXEnabled); }
|
||||
ASMJIT_INLINE_NODEBUG void resetAvxEnabled() noexcept { clearAttributes(FuncAttributes::kX86_AVXEnabled); }
|
||||
|
||||
//! Tests whether the function has AVX-512 enabled.
|
||||
inline bool isAvx512Enabled() const noexcept { return hasAttribute(FuncAttributes::kX86_AVX512Enabled); }
|
||||
ASMJIT_INLINE_NODEBUG bool isAvx512Enabled() const noexcept { return hasAttribute(FuncAttributes::kX86_AVX512Enabled); }
|
||||
//! Enables AVX-512 use.
|
||||
inline void setAvx512Enabled() noexcept { addAttributes(FuncAttributes::kX86_AVX512Enabled); }
|
||||
ASMJIT_INLINE_NODEBUG void setAvx512Enabled() noexcept { addAttributes(FuncAttributes::kX86_AVX512Enabled); }
|
||||
//! Disables AVX-512 use.
|
||||
inline void resetAvx512Enabled() noexcept { clearAttributes(FuncAttributes::kX86_AVX512Enabled); }
|
||||
ASMJIT_INLINE_NODEBUG void resetAvx512Enabled() noexcept { clearAttributes(FuncAttributes::kX86_AVX512Enabled); }
|
||||
|
||||
//! Tests whether the function has MMX cleanup - 'emms' instruction in epilog.
|
||||
inline bool hasMmxCleanup() const noexcept { return hasAttribute(FuncAttributes::kX86_MMXCleanup); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasMmxCleanup() const noexcept { return hasAttribute(FuncAttributes::kX86_MMXCleanup); }
|
||||
//! Enables MMX cleanup.
|
||||
inline void setMmxCleanup() noexcept { addAttributes(FuncAttributes::kX86_MMXCleanup); }
|
||||
ASMJIT_INLINE_NODEBUG void setMmxCleanup() noexcept { addAttributes(FuncAttributes::kX86_MMXCleanup); }
|
||||
//! Disables MMX cleanup.
|
||||
inline void resetMmxCleanup() noexcept { clearAttributes(FuncAttributes::kX86_MMXCleanup); }
|
||||
ASMJIT_INLINE_NODEBUG void resetMmxCleanup() noexcept { clearAttributes(FuncAttributes::kX86_MMXCleanup); }
|
||||
|
||||
//! Tests whether the function has AVX cleanup - 'vzeroupper' instruction in epilog.
|
||||
inline bool hasAvxCleanup() const noexcept { return hasAttribute(FuncAttributes::kX86_AVXCleanup); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvxCleanup() const noexcept { return hasAttribute(FuncAttributes::kX86_AVXCleanup); }
|
||||
//! Enables AVX cleanup.
|
||||
inline void setAvxCleanup() noexcept { addAttributes(FuncAttributes::kX86_AVXCleanup); }
|
||||
ASMJIT_INLINE_NODEBUG void setAvxCleanup() noexcept { addAttributes(FuncAttributes::kX86_AVXCleanup); }
|
||||
//! Disables AVX cleanup.
|
||||
inline void resetAvxCleanup() noexcept { clearAttributes(FuncAttributes::kX86_AVXCleanup); }
|
||||
ASMJIT_INLINE_NODEBUG void resetAvxCleanup() noexcept { clearAttributes(FuncAttributes::kX86_AVXCleanup); }
|
||||
|
||||
//! Tests whether the function uses call stack.
|
||||
inline bool hasCallStack() const noexcept { return _callStackSize != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasCallStack() const noexcept { return _callStackSize != 0; }
|
||||
//! Tests whether the function uses local stack.
|
||||
inline bool hasLocalStack() const noexcept { return _localStackSize != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasLocalStack() const noexcept { return _localStackSize != 0; }
|
||||
//! Tests whether vector registers can be saved and restored by using aligned reads and writes.
|
||||
inline bool hasAlignedVecSR() const noexcept { return hasAttribute(FuncAttributes::kAlignedVecSR); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAlignedVecSR() const noexcept { return hasAttribute(FuncAttributes::kAlignedVecSR); }
|
||||
//! Tests whether the function has to align stack dynamically.
|
||||
inline bool hasDynamicAlignment() const noexcept { return _finalStackAlignment >= _minDynamicAlignment; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasDynamicAlignment() const noexcept { return _finalStackAlignment >= _minDynamicAlignment; }
|
||||
|
||||
//! Tests whether the calling convention specifies 'RedZone'.
|
||||
inline bool hasRedZone() const noexcept { return _redZoneSize != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasRedZone() const noexcept { return _redZoneSize != 0; }
|
||||
//! Tests whether the calling convention specifies 'SpillZone'.
|
||||
inline bool hasSpillZone() const noexcept { return _spillZoneSize != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasSpillZone() const noexcept { return _spillZoneSize != 0; }
|
||||
|
||||
//! Returns the size of 'RedZone'.
|
||||
inline uint32_t redZoneSize() const noexcept { return _redZoneSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t redZoneSize() const noexcept { return _redZoneSize; }
|
||||
//! Returns the size of 'SpillZone'.
|
||||
inline uint32_t spillZoneSize() const noexcept { return _spillZoneSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t spillZoneSize() const noexcept { return _spillZoneSize; }
|
||||
|
||||
//! Resets the size of red zone, which would disable it entirely.
|
||||
//!
|
||||
@@ -1123,24 +1130,24 @@ public:
|
||||
//! bytes of stack to be accessible below stack pointer. These bytes are then accessible within the
|
||||
//! function and Compiler can use this space as a spill area. However, sometimes it's better to
|
||||
//! disallow the use of red zone in case that a user wants to use this stack for a custom purpose.
|
||||
inline void resetRedZone() noexcept { _redZoneSize = 0; }
|
||||
ASMJIT_INLINE_NODEBUG void resetRedZone() noexcept { _redZoneSize = 0; }
|
||||
|
||||
//! Returns natural stack alignment (guaranteed stack alignment upon entry).
|
||||
inline uint32_t naturalStackAlignment() const noexcept { return _naturalStackAlignment; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t naturalStackAlignment() const noexcept { return _naturalStackAlignment; }
|
||||
//! Returns natural stack alignment (guaranteed stack alignment upon entry).
|
||||
inline uint32_t minDynamicAlignment() const noexcept { return _minDynamicAlignment; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t minDynamicAlignment() const noexcept { return _minDynamicAlignment; }
|
||||
|
||||
//! Tests whether the callee must adjust SP before returning (X86-STDCALL only)
|
||||
inline bool hasCalleeStackCleanup() const noexcept { return _calleeStackCleanup != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasCalleeStackCleanup() const noexcept { return _calleeStackCleanup != 0; }
|
||||
//! Returns home many bytes of the stack the callee must adjust before returning (X86-STDCALL only)
|
||||
inline uint32_t calleeStackCleanup() const noexcept { return _calleeStackCleanup; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t calleeStackCleanup() const noexcept { return _calleeStackCleanup; }
|
||||
|
||||
//! Returns call stack alignment.
|
||||
inline uint32_t callStackAlignment() const noexcept { return _callStackAlignment; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t callStackAlignment() const noexcept { return _callStackAlignment; }
|
||||
//! Returns local stack alignment.
|
||||
inline uint32_t localStackAlignment() const noexcept { return _localStackAlignment; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t localStackAlignment() const noexcept { return _localStackAlignment; }
|
||||
//! Returns final stack alignment (the maximum value of call, local, and natural stack alignments).
|
||||
inline uint32_t finalStackAlignment() const noexcept { return _finalStackAlignment; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t finalStackAlignment() const noexcept { return _finalStackAlignment; }
|
||||
|
||||
//! Sets call stack alignment.
|
||||
//!
|
||||
@@ -1175,38 +1182,38 @@ public:
|
||||
}
|
||||
|
||||
//! Returns call stack size.
|
||||
inline uint32_t callStackSize() const noexcept { return _callStackSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t callStackSize() const noexcept { return _callStackSize; }
|
||||
//! Returns local stack size.
|
||||
inline uint32_t localStackSize() const noexcept { return _localStackSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t localStackSize() const noexcept { return _localStackSize; }
|
||||
|
||||
//! Sets call stack size.
|
||||
inline void setCallStackSize(uint32_t size) noexcept { _callStackSize = size; }
|
||||
ASMJIT_INLINE_NODEBUG void setCallStackSize(uint32_t size) noexcept { _callStackSize = size; }
|
||||
//! Sets local stack size.
|
||||
inline void setLocalStackSize(uint32_t size) noexcept { _localStackSize = size; }
|
||||
ASMJIT_INLINE_NODEBUG void setLocalStackSize(uint32_t size) noexcept { _localStackSize = size; }
|
||||
|
||||
//! Combines call stack size with `size`, updating it to the greater value.
|
||||
inline void updateCallStackSize(uint32_t size) noexcept { _callStackSize = Support::max(_callStackSize, size); }
|
||||
ASMJIT_INLINE_NODEBUG void updateCallStackSize(uint32_t size) noexcept { _callStackSize = Support::max(_callStackSize, size); }
|
||||
//! Combines local stack size with `size`, updating it to the greater value.
|
||||
inline void updateLocalStackSize(uint32_t size) noexcept { _localStackSize = Support::max(_localStackSize, size); }
|
||||
ASMJIT_INLINE_NODEBUG void updateLocalStackSize(uint32_t size) noexcept { _localStackSize = Support::max(_localStackSize, size); }
|
||||
|
||||
//! Returns final stack size (only valid after the FuncFrame is finalized).
|
||||
inline uint32_t finalStackSize() const noexcept { return _finalStackSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t finalStackSize() const noexcept { return _finalStackSize; }
|
||||
|
||||
//! Returns an offset to access the local stack (non-zero only if call stack is used).
|
||||
inline uint32_t localStackOffset() const noexcept { return _localStackOffset; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t localStackOffset() const noexcept { return _localStackOffset; }
|
||||
|
||||
//! Tests whether the function prolog/epilog requires a memory slot for storing unaligned SP.
|
||||
inline bool hasDAOffset() const noexcept { return _daOffset != kTagInvalidOffset; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasDAOffset() const noexcept { return _daOffset != kTagInvalidOffset; }
|
||||
//! Returns a memory offset used to store DA (dynamic alignment) slot (relative to SP).
|
||||
inline uint32_t daOffset() const noexcept { return _daOffset; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t daOffset() const noexcept { return _daOffset; }
|
||||
|
||||
inline uint32_t saOffset(uint32_t regId) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG uint32_t saOffset(uint32_t regId) const noexcept {
|
||||
return regId == _spRegId ? saOffsetFromSP()
|
||||
: saOffsetFromSA();
|
||||
}
|
||||
|
||||
inline uint32_t saOffsetFromSP() const noexcept { return _saOffsetFromSP; }
|
||||
inline uint32_t saOffsetFromSA() const noexcept { return _saOffsetFromSA; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t saOffsetFromSP() const noexcept { return _saOffsetFromSP; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t saOffsetFromSA() const noexcept { return _saOffsetFromSA; }
|
||||
|
||||
//! Returns mask of registers of the given register `group` that are modified by the function. The engine would
|
||||
//! then calculate which registers must be saved & restored by the function by using the data provided by the
|
||||
@@ -1244,7 +1251,7 @@ public:
|
||||
addDirtyRegs(std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
inline void setAllDirty() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void setAllDirty() noexcept {
|
||||
for (size_t i = 0; i < ASMJIT_ARRAY_SIZE(_dirtyRegs); i++)
|
||||
_dirtyRegs[i] = 0xFFFFFFFFu;
|
||||
}
|
||||
@@ -1281,35 +1288,35 @@ public:
|
||||
return _saveRestoreAlignment[group];
|
||||
}
|
||||
|
||||
inline bool hasSARegId() const noexcept { return _saRegId != BaseReg::kIdBad; }
|
||||
inline uint32_t saRegId() const noexcept { return _saRegId; }
|
||||
inline void setSARegId(uint32_t regId) { _saRegId = uint8_t(regId); }
|
||||
inline void resetSARegId() { setSARegId(BaseReg::kIdBad); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasSARegId() const noexcept { return _saRegId != BaseReg::kIdBad; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t saRegId() const noexcept { return _saRegId; }
|
||||
ASMJIT_INLINE_NODEBUG void setSARegId(uint32_t regId) { _saRegId = uint8_t(regId); }
|
||||
ASMJIT_INLINE_NODEBUG void resetSARegId() { setSARegId(BaseReg::kIdBad); }
|
||||
|
||||
//! Returns stack size required to save/restore registers via push/pop.
|
||||
inline uint32_t pushPopSaveSize() const noexcept { return _pushPopSaveSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t pushPopSaveSize() const noexcept { return _pushPopSaveSize; }
|
||||
//! Returns an offset to the stack where registers are saved via push/pop.
|
||||
inline uint32_t pushPopSaveOffset() const noexcept { return _pushPopSaveOffset; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t pushPopSaveOffset() const noexcept { return _pushPopSaveOffset; }
|
||||
|
||||
//! Returns stack size required to save/restore extra registers that don't use push/pop/
|
||||
//!
|
||||
//! \note On X86 this covers all registers except GP registers, on other architectures it can be always
|
||||
//! zero (for example AArch64 saves all registers via push/pop like instructions, so this would be zero).
|
||||
inline uint32_t extraRegSaveSize() const noexcept { return _extraRegSaveSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t extraRegSaveSize() const noexcept { return _extraRegSaveSize; }
|
||||
//! Returns an offset to the stack where extra registers are saved.
|
||||
inline uint32_t extraRegSaveOffset() const noexcept { return _extraRegSaveOffset; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t extraRegSaveOffset() const noexcept { return _extraRegSaveOffset; }
|
||||
|
||||
//! Tests whether the functions contains stack adjustment.
|
||||
inline bool hasStackAdjustment() const noexcept { return _stackAdjustment != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasStackAdjustment() const noexcept { return _stackAdjustment != 0; }
|
||||
//! Returns function's stack adjustment used in function's prolog and epilog.
|
||||
//!
|
||||
//! If the returned value is zero it means that the stack is not adjusted. This can mean both that the stack
|
||||
//! is not used and/or the stack is only adjusted by instructions that pust/pop registers into/from stack.
|
||||
inline uint32_t stackAdjustment() const noexcept { return _stackAdjustment; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t stackAdjustment() const noexcept { return _stackAdjustment; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Finaliztion
|
||||
//! \name Finalization
|
||||
//! \{
|
||||
|
||||
ASMJIT_API Error finalize() noexcept;
|
||||
@@ -1338,9 +1345,9 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline explicit FuncArgsAssignment(const FuncDetail* fd = nullptr) noexcept { reset(fd); }
|
||||
ASMJIT_INLINE_NODEBUG explicit FuncArgsAssignment(const FuncDetail* fd = nullptr) noexcept { reset(fd); }
|
||||
|
||||
inline FuncArgsAssignment(const FuncArgsAssignment& other) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG FuncArgsAssignment(const FuncArgsAssignment& other) noexcept {
|
||||
memcpy(this, &other, sizeof(*this));
|
||||
}
|
||||
|
||||
@@ -1356,13 +1363,13 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline const FuncDetail* funcDetail() const noexcept { return _funcDetail; }
|
||||
inline void setFuncDetail(const FuncDetail* fd) noexcept { _funcDetail = fd; }
|
||||
ASMJIT_INLINE_NODEBUG const FuncDetail* funcDetail() const noexcept { return _funcDetail; }
|
||||
ASMJIT_INLINE_NODEBUG void setFuncDetail(const FuncDetail* fd) noexcept { _funcDetail = fd; }
|
||||
|
||||
inline bool hasSARegId() const noexcept { return _saRegId != BaseReg::kIdBad; }
|
||||
inline uint32_t saRegId() const noexcept { return _saRegId; }
|
||||
inline void setSARegId(uint32_t regId) { _saRegId = uint8_t(regId); }
|
||||
inline void resetSARegId() { _saRegId = uint8_t(BaseReg::kIdBad); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasSARegId() const noexcept { return _saRegId != BaseReg::kIdBad; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t saRegId() const noexcept { return _saRegId; }
|
||||
ASMJIT_INLINE_NODEBUG void setSARegId(uint32_t regId) { _saRegId = uint8_t(regId); }
|
||||
ASMJIT_INLINE_NODEBUG void resetSARegId() { _saRegId = uint8_t(BaseReg::kIdBad); }
|
||||
|
||||
inline FuncValue& arg(size_t argIndex, size_t valueIndex) noexcept {
|
||||
ASMJIT_ASSERT(argIndex < ASMJIT_ARRAY_SIZE(_argPacks));
|
||||
|
||||
@@ -176,14 +176,14 @@ public:
|
||||
|
||||
FuncArgsContext() noexcept;
|
||||
|
||||
inline const ArchTraits& archTraits() const noexcept { return *_archTraits; }
|
||||
inline Arch arch() const noexcept { return _arch; }
|
||||
ASMJIT_INLINE_NODEBUG const ArchTraits& archTraits() const noexcept { return *_archTraits; }
|
||||
ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return _arch; }
|
||||
|
||||
inline uint32_t varCount() const noexcept { return _varCount; }
|
||||
inline size_t indexOf(const Var* var) const noexcept { return (size_t)(var - _vars); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t varCount() const noexcept { return _varCount; }
|
||||
ASMJIT_INLINE_NODEBUG size_t indexOf(const Var* var) const noexcept { return (size_t)(var - _vars); }
|
||||
|
||||
inline Var& var(size_t varId) noexcept { return _vars[varId]; }
|
||||
inline const Var& var(size_t varId) const noexcept { return _vars[varId]; }
|
||||
ASMJIT_INLINE_NODEBUG Var& var(size_t varId) noexcept { return _vars[varId]; }
|
||||
ASMJIT_INLINE_NODEBUG const Var& var(size_t varId) const noexcept { return _vars[varId]; }
|
||||
|
||||
Error initWorkData(const FuncFrame& frame, const FuncArgsAssignment& args, const RAConstraints* constraints) noexcept;
|
||||
Error markScratchRegs(FuncFrame& frame) noexcept;
|
||||
|
||||
@@ -135,10 +135,10 @@ static const constexpr NoInit_ NoInit {};
|
||||
} // {Globals}
|
||||
|
||||
template<typename Func>
|
||||
static inline Func ptr_as_func(void* func) noexcept { return Support::ptr_cast_impl<Func, void*>(func); }
|
||||
static ASMJIT_INLINE_NODEBUG Func ptr_as_func(void* func) noexcept { return Support::ptr_cast_impl<Func, void*>(func); }
|
||||
|
||||
template<typename Func>
|
||||
static inline void* func_as_ptr(Func func) noexcept { return Support::ptr_cast_impl<void*, Func>(func); }
|
||||
static ASMJIT_INLINE_NODEBUG void* func_as_ptr(Func func) noexcept { return Support::ptr_cast_impl<void*, Func>(func); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -340,7 +340,7 @@ namespace DebugUtils {
|
||||
//! \cond INTERNAL
|
||||
//! Used to silence warnings about unused arguments or variables.
|
||||
template<typename... Args>
|
||||
static inline void unused(Args&&...) noexcept {}
|
||||
static ASMJIT_INLINE_NODEBUG void unused(Args&&...) noexcept {}
|
||||
//! \endcond
|
||||
|
||||
//! Returns the error `err` passed.
|
||||
|
||||
@@ -20,7 +20,7 @@ ASMJIT_BEGIN_NAMESPACE
|
||||
//!
|
||||
//! Each architecture has a set of valid instructions indexed from 0. Instruction with 0 id is, however, a special
|
||||
//! instruction that describes a "no instruction" or "invalid instruction". Different architectures can assign a.
|
||||
//! different instruction to the same id, each architecture typicall has its own instructions indexed from 1.
|
||||
//! different instruction to the same id, each architecture typically has its own instructions indexed from 1.
|
||||
//!
|
||||
//! Instruction identifiers listed by architecture:
|
||||
//!
|
||||
@@ -231,17 +231,17 @@ public:
|
||||
//!
|
||||
//! Default values of `id` and `options` are zero, which means 'none' instruction. Such instruction is guaranteed
|
||||
//! to never exist for any architecture supported by AsmJit.
|
||||
inline explicit BaseInst(InstId instId = 0, InstOptions options = InstOptions::kNone) noexcept
|
||||
ASMJIT_INLINE_NODEBUG explicit BaseInst(InstId instId = 0, InstOptions options = InstOptions::kNone) noexcept
|
||||
: _id(instId),
|
||||
_options(options),
|
||||
_extraReg() {}
|
||||
|
||||
inline BaseInst(InstId instId, InstOptions options, const RegOnly& extraReg) noexcept
|
||||
ASMJIT_INLINE_NODEBUG BaseInst(InstId instId, InstOptions options, const RegOnly& extraReg) noexcept
|
||||
: _id(instId),
|
||||
_options(options),
|
||||
_extraReg(extraReg) {}
|
||||
|
||||
inline BaseInst(InstId instId, InstOptions options, const BaseReg& extraReg) noexcept
|
||||
ASMJIT_INLINE_NODEBUG BaseInst(InstId instId, InstOptions options, const BaseReg& extraReg) noexcept
|
||||
: _id(instId),
|
||||
_options(options),
|
||||
_extraReg { extraReg.signature(), extraReg.id() } {}
|
||||
@@ -252,22 +252,22 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the instruction id with modifiers.
|
||||
inline InstId id() const noexcept { return _id; }
|
||||
ASMJIT_INLINE_NODEBUG InstId id() const noexcept { return _id; }
|
||||
//! Sets the instruction id and modiiers from `id`.
|
||||
inline void setId(InstId id) noexcept { _id = id; }
|
||||
ASMJIT_INLINE_NODEBUG void setId(InstId id) noexcept { _id = id; }
|
||||
//! Resets the instruction id and modifiers to zero, see \ref kIdNone.
|
||||
inline void resetId() noexcept { _id = 0; }
|
||||
ASMJIT_INLINE_NODEBUG void resetId() noexcept { _id = 0; }
|
||||
|
||||
//! Returns a real instruction id that doesn't contain any modifiers.
|
||||
inline InstId realId() const noexcept { return _id & uint32_t(InstIdParts::kRealId); }
|
||||
ASMJIT_INLINE_NODEBUG InstId realId() const noexcept { return _id & uint32_t(InstIdParts::kRealId); }
|
||||
|
||||
template<InstIdParts kPart>
|
||||
inline uint32_t getInstIdPart() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG uint32_t getInstIdPart() const noexcept {
|
||||
return (uint32_t(_id) & uint32_t(kPart)) >> Support::ConstCTZ<uint32_t(kPart)>::value;
|
||||
}
|
||||
|
||||
template<InstIdParts kPart>
|
||||
inline void setInstIdPart(uint32_t value) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void setInstIdPart(uint32_t value) noexcept {
|
||||
_id = (_id & ~uint32_t(kPart)) | (value << Support::ConstCTZ<uint32_t(kPart)>::value);
|
||||
}
|
||||
|
||||
@@ -276,58 +276,58 @@ public:
|
||||
//! \name Instruction Options
|
||||
//! \{
|
||||
|
||||
inline InstOptions options() const noexcept { return _options; }
|
||||
inline bool hasOption(InstOptions option) const noexcept { return Support::test(_options, option); }
|
||||
inline void setOptions(InstOptions options) noexcept { _options = options; }
|
||||
inline void addOptions(InstOptions options) noexcept { _options |= options; }
|
||||
inline void clearOptions(InstOptions options) noexcept { _options &= ~options; }
|
||||
inline void resetOptions() noexcept { _options = InstOptions::kNone; }
|
||||
ASMJIT_INLINE_NODEBUG InstOptions options() const noexcept { return _options; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasOption(InstOptions option) const noexcept { return Support::test(_options, option); }
|
||||
ASMJIT_INLINE_NODEBUG void setOptions(InstOptions options) noexcept { _options = options; }
|
||||
ASMJIT_INLINE_NODEBUG void addOptions(InstOptions options) noexcept { _options |= options; }
|
||||
ASMJIT_INLINE_NODEBUG void clearOptions(InstOptions options) noexcept { _options &= ~options; }
|
||||
ASMJIT_INLINE_NODEBUG void resetOptions() noexcept { _options = InstOptions::kNone; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Extra Register
|
||||
//! \{
|
||||
|
||||
inline bool hasExtraReg() const noexcept { return _extraReg.isReg(); }
|
||||
inline RegOnly& extraReg() noexcept { return _extraReg; }
|
||||
inline const RegOnly& extraReg() const noexcept { return _extraReg; }
|
||||
inline void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); }
|
||||
inline void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); }
|
||||
inline void resetExtraReg() noexcept { _extraReg.reset(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasExtraReg() const noexcept { return _extraReg.isReg(); }
|
||||
ASMJIT_INLINE_NODEBUG RegOnly& extraReg() noexcept { return _extraReg; }
|
||||
ASMJIT_INLINE_NODEBUG const RegOnly& extraReg() const noexcept { return _extraReg; }
|
||||
ASMJIT_INLINE_NODEBUG void setExtraReg(const BaseReg& reg) noexcept { _extraReg.init(reg); }
|
||||
ASMJIT_INLINE_NODEBUG void setExtraReg(const RegOnly& reg) noexcept { _extraReg.init(reg); }
|
||||
ASMJIT_INLINE_NODEBUG void resetExtraReg() noexcept { _extraReg.reset(); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name ARM Specific
|
||||
//! \{
|
||||
|
||||
inline arm::CondCode armCondCode() const noexcept { return (arm::CondCode)getInstIdPart<InstIdParts::kARM_Cond>(); }
|
||||
inline void setArmCondCode(arm::CondCode cc) noexcept { setInstIdPart<InstIdParts::kARM_Cond>(uint32_t(cc)); }
|
||||
ASMJIT_INLINE_NODEBUG arm::CondCode armCondCode() const noexcept { return (arm::CondCode)getInstIdPart<InstIdParts::kARM_Cond>(); }
|
||||
ASMJIT_INLINE_NODEBUG void setArmCondCode(arm::CondCode cc) noexcept { setInstIdPart<InstIdParts::kARM_Cond>(uint32_t(cc)); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Statics
|
||||
//! \{
|
||||
|
||||
static inline constexpr InstId composeARMInstId(uint32_t id, arm::CondCode cc) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr InstId composeARMInstId(uint32_t id, arm::CondCode cc) noexcept {
|
||||
return id | (uint32_t(cc) << Support::ConstCTZ<uint32_t(InstIdParts::kARM_Cond)>::value);
|
||||
}
|
||||
|
||||
static inline constexpr InstId composeARMInstId(uint32_t id, arm::DataType dt, arm::CondCode cc = arm::CondCode::kAL) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr InstId composeARMInstId(uint32_t id, arm::DataType dt, arm::CondCode cc = arm::CondCode::kAL) noexcept {
|
||||
return id | (uint32_t(dt) << Support::ConstCTZ<uint32_t(InstIdParts::kA32_DT)>::value)
|
||||
| (uint32_t(cc) << Support::ConstCTZ<uint32_t(InstIdParts::kARM_Cond)>::value);
|
||||
}
|
||||
|
||||
static inline constexpr InstId composeARMInstId(uint32_t id, arm::DataType dt, arm::DataType dt2, arm::CondCode cc = arm::CondCode::kAL) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr InstId composeARMInstId(uint32_t id, arm::DataType dt, arm::DataType dt2, arm::CondCode cc = arm::CondCode::kAL) noexcept {
|
||||
return id | (uint32_t(dt) << Support::ConstCTZ<uint32_t(InstIdParts::kA32_DT)>::value)
|
||||
| (uint32_t(dt2) << Support::ConstCTZ<uint32_t(InstIdParts::kA32_DT2)>::value)
|
||||
| (uint32_t(cc) << Support::ConstCTZ<uint32_t(InstIdParts::kARM_Cond)>::value);
|
||||
}
|
||||
|
||||
static inline constexpr InstId extractRealId(uint32_t id) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr InstId extractRealId(uint32_t id) noexcept {
|
||||
return id & uint32_t(InstIdParts::kRealId);
|
||||
}
|
||||
|
||||
static inline constexpr arm::CondCode extractARMCondCode(uint32_t id) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr arm::CondCode extractARMCondCode(uint32_t id) noexcept {
|
||||
return (arm::CondCode)((uint32_t(id) & uint32_t(InstIdParts::kARM_Cond)) >> Support::ConstCTZ<uint32_t(InstIdParts::kARM_Cond)>::value);
|
||||
}
|
||||
|
||||
@@ -488,7 +488,7 @@ struct OpRWInfo {
|
||||
//! \{
|
||||
|
||||
//! Resets this operand information to all zeros.
|
||||
inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = OpRWInfo{}; }
|
||||
|
||||
//! Resets this operand info (resets all members) and set common information
|
||||
//! to the given `opFlags`, `regSize`, and possibly `physId`.
|
||||
@@ -505,7 +505,7 @@ struct OpRWInfo {
|
||||
_extendByteMask = 0;
|
||||
}
|
||||
|
||||
inline void _resetReserved() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void _resetReserved() noexcept {
|
||||
_reserved[0] = 0;
|
||||
}
|
||||
|
||||
@@ -515,40 +515,40 @@ struct OpRWInfo {
|
||||
//! \{
|
||||
|
||||
//! Returns operand flags.
|
||||
inline OpRWFlags opFlags() const noexcept { return _opFlags; }
|
||||
ASMJIT_INLINE_NODEBUG OpRWFlags opFlags() const noexcept { return _opFlags; }
|
||||
//! Tests whether operand flags contain the given `flag`.
|
||||
inline bool hasOpFlag(OpRWFlags flag) const noexcept { return Support::test(_opFlags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasOpFlag(OpRWFlags flag) const noexcept { return Support::test(_opFlags, flag); }
|
||||
|
||||
//! Adds the given `flags` to operand flags.
|
||||
inline void addOpFlags(OpRWFlags flags) noexcept { _opFlags |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG void addOpFlags(OpRWFlags flags) noexcept { _opFlags |= flags; }
|
||||
//! Removes the given `flags` from operand flags.
|
||||
inline void clearOpFlags(OpRWFlags flags) noexcept { _opFlags &= ~flags; }
|
||||
ASMJIT_INLINE_NODEBUG void clearOpFlags(OpRWFlags flags) noexcept { _opFlags &= ~flags; }
|
||||
|
||||
//! Tests whether this operand is read from.
|
||||
inline bool isRead() const noexcept { return hasOpFlag(OpRWFlags::kRead); }
|
||||
ASMJIT_INLINE_NODEBUG bool isRead() const noexcept { return hasOpFlag(OpRWFlags::kRead); }
|
||||
//! Tests whether this operand is written to.
|
||||
inline bool isWrite() const noexcept { return hasOpFlag(OpRWFlags::kWrite); }
|
||||
ASMJIT_INLINE_NODEBUG bool isWrite() const noexcept { return hasOpFlag(OpRWFlags::kWrite); }
|
||||
//! Tests whether this operand is both read and write.
|
||||
inline bool isReadWrite() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kRW; }
|
||||
ASMJIT_INLINE_NODEBUG bool isReadWrite() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kRW; }
|
||||
//! Tests whether this operand is read only.
|
||||
inline bool isReadOnly() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kRead; }
|
||||
ASMJIT_INLINE_NODEBUG bool isReadOnly() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kRead; }
|
||||
//! Tests whether this operand is write only.
|
||||
inline bool isWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kWrite; }
|
||||
ASMJIT_INLINE_NODEBUG bool isWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kRW) == OpRWFlags::kWrite; }
|
||||
|
||||
//! Returns the type of a lead register, which is followed by consecutive registers.
|
||||
inline uint32_t consecutiveLeadCount() const noexcept { return _consecutiveLeadCount; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t consecutiveLeadCount() const noexcept { return _consecutiveLeadCount; }
|
||||
|
||||
//! Tests whether this operand is Reg/Mem
|
||||
//!
|
||||
//! Reg/Mem operands can use either register or memory.
|
||||
inline bool isRm() const noexcept { return hasOpFlag(OpRWFlags::kRegMem); }
|
||||
ASMJIT_INLINE_NODEBUG bool isRm() const noexcept { return hasOpFlag(OpRWFlags::kRegMem); }
|
||||
|
||||
//! Tests whether the operand will be zero extended.
|
||||
inline bool isZExt() const noexcept { return hasOpFlag(OpRWFlags::kZExt); }
|
||||
ASMJIT_INLINE_NODEBUG bool isZExt() const noexcept { return hasOpFlag(OpRWFlags::kZExt); }
|
||||
|
||||
//! Tests whether the operand must have allocated a unique physical id that cannot be shared with other register
|
||||
//! operands.
|
||||
inline bool isUnique() const noexcept { return hasOpFlag(OpRWFlags::kUnique); }
|
||||
ASMJIT_INLINE_NODEBUG bool isUnique() const noexcept { return hasOpFlag(OpRWFlags::kUnique); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -557,38 +557,38 @@ struct OpRWInfo {
|
||||
|
||||
//! Tests whether this is a fake memory operand, which is only used, because of encoding. Fake memory operands do
|
||||
//! not access any memory, they are only used to encode registers.
|
||||
inline bool isMemFake() const noexcept { return hasOpFlag(OpRWFlags::kMemFake); }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemFake() const noexcept { return hasOpFlag(OpRWFlags::kMemFake); }
|
||||
|
||||
//! Tests whether the instruction's memory BASE register is used.
|
||||
inline bool isMemBaseUsed() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseRW); }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemBaseUsed() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseRW); }
|
||||
//! Tests whether the instruction reads from its BASE registers.
|
||||
inline bool isMemBaseRead() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseRead); }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemBaseRead() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseRead); }
|
||||
//! Tests whether the instruction writes to its BASE registers.
|
||||
inline bool isMemBaseWrite() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseWrite); }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemBaseWrite() const noexcept { return hasOpFlag(OpRWFlags::kMemBaseWrite); }
|
||||
//! Tests whether the instruction reads and writes from/to its BASE registers.
|
||||
inline bool isMemBaseReadWrite() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseRW; }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemBaseReadWrite() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseRW; }
|
||||
//! Tests whether the instruction only reads from its BASE registers.
|
||||
inline bool isMemBaseReadOnly() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseRead; }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemBaseReadOnly() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseRead; }
|
||||
//! Tests whether the instruction only writes to its BASE registers.
|
||||
inline bool isMemBaseWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseWrite; }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemBaseWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kMemBaseRW) == OpRWFlags::kMemBaseWrite; }
|
||||
|
||||
//! Tests whether the instruction modifies the BASE register before it uses it to calculate the target address.
|
||||
inline bool isMemBasePreModify() const noexcept { return hasOpFlag(OpRWFlags::kMemBasePreModify); }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemBasePreModify() const noexcept { return hasOpFlag(OpRWFlags::kMemBasePreModify); }
|
||||
//! Tests whether the instruction modifies the BASE register after it uses it to calculate the target address.
|
||||
inline bool isMemBasePostModify() const noexcept { return hasOpFlag(OpRWFlags::kMemBasePostModify); }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemBasePostModify() const noexcept { return hasOpFlag(OpRWFlags::kMemBasePostModify); }
|
||||
|
||||
//! Tests whether the instruction's memory INDEX register is used.
|
||||
inline bool isMemIndexUsed() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexRW); }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemIndexUsed() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexRW); }
|
||||
//! Tests whether the instruction reads the INDEX registers.
|
||||
inline bool isMemIndexRead() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexRead); }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemIndexRead() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexRead); }
|
||||
//! Tests whether the instruction writes to its INDEX registers.
|
||||
inline bool isMemIndexWrite() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexWrite); }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemIndexWrite() const noexcept { return hasOpFlag(OpRWFlags::kMemIndexWrite); }
|
||||
//! Tests whether the instruction reads and writes from/to its INDEX registers.
|
||||
inline bool isMemIndexReadWrite() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexRW; }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemIndexReadWrite() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexRW; }
|
||||
//! Tests whether the instruction only reads from its INDEX registers.
|
||||
inline bool isMemIndexReadOnly() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexRead; }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemIndexReadOnly() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexRead; }
|
||||
//! Tests whether the instruction only writes to its INDEX registers.
|
||||
inline bool isMemIndexWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexWrite; }
|
||||
ASMJIT_INLINE_NODEBUG bool isMemIndexWriteOnly() const noexcept { return (_opFlags & OpRWFlags::kMemIndexRW) == OpRWFlags::kMemIndexWrite; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -598,11 +598,11 @@ struct OpRWInfo {
|
||||
//! Returns a physical id of the register that is fixed for this operand.
|
||||
//!
|
||||
//! Returns \ref BaseReg::kIdBad if any register can be used.
|
||||
inline uint32_t physId() const noexcept { return _physId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t physId() const noexcept { return _physId; }
|
||||
//! Tests whether \ref physId() would return a valid physical register id.
|
||||
inline bool hasPhysId() const noexcept { return _physId != BaseReg::kIdBad; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasPhysId() const noexcept { return _physId != BaseReg::kIdBad; }
|
||||
//! Sets physical register id, which would be fixed for this operand.
|
||||
inline void setPhysId(uint32_t physId) noexcept { _physId = uint8_t(physId); }
|
||||
ASMJIT_INLINE_NODEBUG void setPhysId(uint32_t physId) noexcept { _physId = uint8_t(physId); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -610,9 +610,9 @@ struct OpRWInfo {
|
||||
//! \{
|
||||
|
||||
//! Returns Reg/Mem size of the operand.
|
||||
inline uint32_t rmSize() const noexcept { return _rmSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t rmSize() const noexcept { return _rmSize; }
|
||||
//! Sets Reg/Mem size of the operand.
|
||||
inline void setRmSize(uint32_t rmSize) noexcept { _rmSize = uint8_t(rmSize); }
|
||||
ASMJIT_INLINE_NODEBUG void setRmSize(uint32_t rmSize) noexcept { _rmSize = uint8_t(rmSize); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -620,18 +620,18 @@ struct OpRWInfo {
|
||||
//! \{
|
||||
|
||||
//! Returns read mask.
|
||||
inline uint64_t readByteMask() const noexcept { return _readByteMask; }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t readByteMask() const noexcept { return _readByteMask; }
|
||||
//! Returns write mask.
|
||||
inline uint64_t writeByteMask() const noexcept { return _writeByteMask; }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t writeByteMask() const noexcept { return _writeByteMask; }
|
||||
//! Returns extend mask.
|
||||
inline uint64_t extendByteMask() const noexcept { return _extendByteMask; }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t extendByteMask() const noexcept { return _extendByteMask; }
|
||||
|
||||
//! Sets read mask.
|
||||
inline void setReadByteMask(uint64_t mask) noexcept { _readByteMask = mask; }
|
||||
ASMJIT_INLINE_NODEBUG void setReadByteMask(uint64_t mask) noexcept { _readByteMask = mask; }
|
||||
//! Sets write mask.
|
||||
inline void setWriteByteMask(uint64_t mask) noexcept { _writeByteMask = mask; }
|
||||
//! Sets externd mask.
|
||||
inline void setExtendByteMask(uint64_t mask) noexcept { _extendByteMask = mask; }
|
||||
ASMJIT_INLINE_NODEBUG void setWriteByteMask(uint64_t mask) noexcept { _writeByteMask = mask; }
|
||||
//! Sets extend mask.
|
||||
ASMJIT_INLINE_NODEBUG void setExtendByteMask(uint64_t mask) noexcept { _extendByteMask = mask; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -665,7 +665,7 @@ struct InstRWInfo {
|
||||
uint8_t _rmFeature;
|
||||
//! Reserved for future use.
|
||||
uint8_t _reserved[18];
|
||||
//! Read/Write onfo of extra register (rep{} or kz{}).
|
||||
//! Read/Write info of extra register (rep{} or kz{}).
|
||||
OpRWInfo _extraReg;
|
||||
//! Read/Write info of instruction operands.
|
||||
OpRWInfo _operands[Globals::kMaxOpCount];
|
||||
@@ -676,7 +676,7 @@ struct InstRWInfo {
|
||||
//! \{
|
||||
|
||||
//! Resets this RW information to all zeros.
|
||||
inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = InstRWInfo{}; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -684,13 +684,13 @@ struct InstRWInfo {
|
||||
//! \{
|
||||
|
||||
//! Returns flags associated with the instruction, see \ref InstRWFlags.
|
||||
inline InstRWFlags instFlags() const noexcept { return _instFlags; }
|
||||
ASMJIT_INLINE_NODEBUG InstRWFlags instFlags() const noexcept { return _instFlags; }
|
||||
|
||||
//! Tests whether the instruction flags contain `flag`.
|
||||
inline bool hasInstFlag(InstRWFlags flag) const noexcept { return Support::test(_instFlags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasInstFlag(InstRWFlags flag) const noexcept { return Support::test(_instFlags, flag); }
|
||||
|
||||
//! Tests whether the instruction flags contain \ref InstRWFlags::kMovOp.
|
||||
inline bool isMovOp() const noexcept { return hasInstFlag(InstRWFlags::kMovOp); }
|
||||
ASMJIT_INLINE_NODEBUG bool isMovOp() const noexcept { return hasInstFlag(InstRWFlags::kMovOp); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -698,9 +698,9 @@ struct InstRWInfo {
|
||||
//! \{
|
||||
|
||||
//! Returns a mask of CPU flags read.
|
||||
inline CpuRWFlags readFlags() const noexcept { return _readFlags; }
|
||||
ASMJIT_INLINE_NODEBUG CpuRWFlags readFlags() const noexcept { return _readFlags; }
|
||||
//! Returns a mask of CPU flags written.
|
||||
inline CpuRWFlags writeFlags() const noexcept { return _writeFlags; }
|
||||
ASMJIT_INLINE_NODEBUG CpuRWFlags writeFlags() const noexcept { return _writeFlags; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -717,7 +717,7 @@ struct InstRWInfo {
|
||||
//! Some AVX+ instructions may require extra features for replacing registers with memory operands, for example
|
||||
//! VPSLLDQ instruction only supports `vpslldq reg, reg, imm` combination on AVX/AVX2 capable CPUs and requires
|
||||
//! AVX-512 for `vpslldq reg, mem, imm` combination.
|
||||
inline uint32_t rmFeature() const noexcept { return _rmFeature; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t rmFeature() const noexcept { return _rmFeature; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -725,10 +725,10 @@ struct InstRWInfo {
|
||||
//! \{
|
||||
|
||||
//! Returns RW information of extra register operand (extraReg).
|
||||
inline const OpRWInfo& extraReg() const noexcept { return _extraReg; }
|
||||
ASMJIT_INLINE_NODEBUG const OpRWInfo& extraReg() const noexcept { return _extraReg; }
|
||||
|
||||
//! Returns RW information of all instruction's operands.
|
||||
inline const OpRWInfo* operands() const noexcept { return _operands; }
|
||||
ASMJIT_INLINE_NODEBUG const OpRWInfo* operands() const noexcept { return _operands; }
|
||||
|
||||
//! Returns RW information of the operand at the given `index`.
|
||||
inline const OpRWInfo& operand(size_t index) const noexcept {
|
||||
@@ -737,7 +737,7 @@ struct InstRWInfo {
|
||||
}
|
||||
|
||||
//! Returns the number of operands this instruction has.
|
||||
inline uint32_t opCount() const noexcept { return _opCount; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t opCount() const noexcept { return _opCount; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
@@ -182,7 +182,7 @@ public:
|
||||
//! Destroys the `JitAllocator` instance and release all blocks held.
|
||||
ASMJIT_API ~JitAllocator() noexcept;
|
||||
|
||||
inline bool isInitialized() const noexcept { return _impl->blockSize == 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool isInitialized() const noexcept { return _impl->blockSize == 0; }
|
||||
|
||||
//! Free all allocated memory - makes all pointers returned by `alloc()` invalid.
|
||||
//!
|
||||
@@ -196,16 +196,16 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns allocator options, see `Flags`.
|
||||
inline JitAllocatorOptions options() const noexcept { return _impl->options; }
|
||||
ASMJIT_INLINE_NODEBUG JitAllocatorOptions options() const noexcept { return _impl->options; }
|
||||
//! Tests whether the allocator has the given `option` set.
|
||||
inline bool hasOption(JitAllocatorOptions option) const noexcept { return uint32_t(_impl->options & option) != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasOption(JitAllocatorOptions option) const noexcept { return uint32_t(_impl->options & option) != 0; }
|
||||
|
||||
//! Returns a base block size (a minimum size of block that the allocator would allocate).
|
||||
inline uint32_t blockSize() const noexcept { return _impl->blockSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t blockSize() const noexcept { return _impl->blockSize; }
|
||||
//! Returns granularity of the allocator.
|
||||
inline uint32_t granularity() const noexcept { return _impl->granularity; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t granularity() const noexcept { return _impl->granularity; }
|
||||
//! Returns pattern that is used to fill unused memory if `kFlagUseFillPattern` is set.
|
||||
inline uint32_t fillPattern() const noexcept { return _impl->fillPattern; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t fillPattern() const noexcept { return _impl->fillPattern; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -265,7 +265,7 @@ public:
|
||||
//! Returns a pointer having Read & Execute permissions (references executable memory).
|
||||
//!
|
||||
//! This pointer is never NULL if the allocation succeeded, it points to an executable memory.
|
||||
inline void* rx() const noexcept { return _rx; }
|
||||
ASMJIT_INLINE_NODEBUG void* rx() const noexcept { return _rx; }
|
||||
|
||||
//! Returns a pointer having Read & Write permissions (references writable memory).
|
||||
//!
|
||||
@@ -283,23 +283,23 @@ public:
|
||||
//! the permissions of the pointer to RW (that's per thread permissions). if \ref ProtectJitReadWriteScope is
|
||||
//! not used it's important to clear the instruction cache via \ref VirtMem::flushInstructionCache() after the
|
||||
//! write is done.
|
||||
inline void* rw() const noexcept { return _rw; }
|
||||
ASMJIT_INLINE_NODEBUG void* rw() const noexcept { return _rw; }
|
||||
|
||||
//! Returns size of this span, aligned to the allocator granularity.
|
||||
inline size_t size() const noexcept { return _size; }
|
||||
ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return _size; }
|
||||
|
||||
//! Returns span flags.
|
||||
inline Flags flags() const noexcept { return _flags; }
|
||||
ASMJIT_INLINE_NODEBUG Flags flags() const noexcept { return _flags; }
|
||||
|
||||
//! Shrinks this span to `newSize`.
|
||||
//!
|
||||
//! \note This is the only function that is able to change the size of a span, and it's only use case is to
|
||||
//! shrink the span size during \ref JitAllocator::write(). When the writer detects that the span size shrunk,
|
||||
//! it will automatically shrink the memory used by the span, and propagate the new aligned size to the caller.
|
||||
inline void shrink(size_t newSize) noexcept { _size = Support::min(_size, newSize); }
|
||||
ASMJIT_INLINE_NODEBUG void shrink(size_t newSize) noexcept { _size = Support::min(_size, newSize); }
|
||||
|
||||
//! Returns whether \ref rw() returns a non-null pointer.
|
||||
inline bool isDirectlyWritable() const noexcept { return _rw != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool isDirectlyWritable() const noexcept { return _rw != nullptr; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -473,8 +473,8 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline JitAllocator* allocator() const noexcept { return _allocator; }
|
||||
inline VirtMem::CachePolicy policy() const noexcept { return _policy; }
|
||||
ASMJIT_INLINE_NODEBUG JitAllocator* allocator() const noexcept { return _allocator; }
|
||||
ASMJIT_INLINE_NODEBUG VirtMem::CachePolicy policy() const noexcept { return _policy; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -482,23 +482,23 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Similar to `JitAllocator::write(span, offset, src, size)`, but under a write scope.
|
||||
inline Error write(Span& span, size_t offset, const void* src, size_t size) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error write(Span& span, size_t offset, const void* src, size_t size) noexcept {
|
||||
return _allocator->scopedWrite(*this, span, offset, src, size);
|
||||
}
|
||||
|
||||
//! Similar to `JitAllocator::write(span, writeFunc, userData)`, but under a write scope.
|
||||
inline Error write(Span& span, WriteFunc writeFunc, void* userData) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error write(Span& span, WriteFunc writeFunc, void* userData) noexcept {
|
||||
return _allocator->scopedWrite(*this, span, writeFunc, userData);
|
||||
}
|
||||
|
||||
//! Similar to `JitAllocator::write(span, <lambda>)`, but under a write scope.
|
||||
template<class Lambda>
|
||||
inline Error write(Span& span, Lambda&& lambdaFunc) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error write(Span& span, Lambda&& lambdaFunc) noexcept {
|
||||
return _allocator->scopedWrite(*this, span, lambdaFunc);
|
||||
}
|
||||
|
||||
//! Flushes accumulated changes in this write scope.
|
||||
inline Error flush() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error flush() noexcept {
|
||||
return _allocator->flushWriteScope(*this);
|
||||
}
|
||||
|
||||
@@ -524,31 +524,31 @@ public:
|
||||
size_t _overheadSize;
|
||||
|
||||
//! Resets the statistics to all zeros.
|
||||
inline void reset() noexcept { *this = Statistics{}; }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { *this = Statistics{}; }
|
||||
|
||||
//! Returns count of blocks managed by `JitAllocator` at the moment.
|
||||
inline size_t blockCount() const noexcept { return _blockCount; }
|
||||
ASMJIT_INLINE_NODEBUG size_t blockCount() const noexcept { return _blockCount; }
|
||||
//! Returns the number of active allocations.
|
||||
inline size_t allocationCount() const noexcept { return _allocationCount; }
|
||||
ASMJIT_INLINE_NODEBUG size_t allocationCount() const noexcept { return _allocationCount; }
|
||||
|
||||
//! Returns how many bytes are currently used.
|
||||
inline size_t usedSize() const noexcept { return _usedSize; }
|
||||
ASMJIT_INLINE_NODEBUG size_t usedSize() const noexcept { return _usedSize; }
|
||||
//! Returns the number of bytes unused by the allocator at the moment.
|
||||
inline size_t unusedSize() const noexcept { return _reservedSize - _usedSize; }
|
||||
ASMJIT_INLINE_NODEBUG size_t unusedSize() const noexcept { return _reservedSize - _usedSize; }
|
||||
//! Returns the total number of bytes bytes reserved by the allocator (sum of sizes of all blocks).
|
||||
inline size_t reservedSize() const noexcept { return _reservedSize; }
|
||||
ASMJIT_INLINE_NODEBUG size_t reservedSize() const noexcept { return _reservedSize; }
|
||||
//! Returns the number of bytes the allocator needs to manage the allocated memory.
|
||||
inline size_t overheadSize() const noexcept { return _overheadSize; }
|
||||
ASMJIT_INLINE_NODEBUG size_t overheadSize() const noexcept { return _overheadSize; }
|
||||
|
||||
inline double usedSizeAsPercent() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG double usedSizeAsPercent() const noexcept {
|
||||
return (double(usedSize()) / (double(reservedSize()) + 1e-16)) * 100.0;
|
||||
}
|
||||
|
||||
inline double unusedSizeAsPercent() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG double unusedSizeAsPercent() const noexcept {
|
||||
return (double(unusedSize()) / (double(reservedSize()) + 1e-16)) * 100.0;
|
||||
}
|
||||
|
||||
inline double overheadSizeAsPercent() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG double overheadSizeAsPercent() const noexcept {
|
||||
return (double(overheadSize()) / (double(reservedSize()) + 1e-16)) * 100.0;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -37,7 +37,7 @@ public:
|
||||
//! Destroys the `JitRuntime` instance.
|
||||
ASMJIT_API virtual ~JitRuntime() noexcept;
|
||||
|
||||
inline void reset(ResetPolicy resetPolicy = ResetPolicy::kSoft) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void reset(ResetPolicy resetPolicy = ResetPolicy::kSoft) noexcept {
|
||||
_allocator.reset(resetPolicy);
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the associated `JitAllocator`.
|
||||
inline JitAllocator* allocator() const noexcept { return const_cast<JitAllocator*>(&_allocator); }
|
||||
ASMJIT_INLINE_NODEBUG JitAllocator* allocator() const noexcept { return const_cast<JitAllocator*>(&_allocator); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -62,13 +62,13 @@ public:
|
||||
//! The beginning of the memory allocated for the function is returned in `dst`. If failed `Error` code is returned
|
||||
//! and `dst` is explicitly set to `nullptr` (this means that you don't have to set it to null before calling `add()`).
|
||||
template<typename Func>
|
||||
inline Error add(Func* dst, CodeHolder* code) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error add(Func* dst, CodeHolder* code) noexcept {
|
||||
return _add(Support::ptr_cast_impl<void**, Func*>(dst), code);
|
||||
}
|
||||
|
||||
//! Releases `p` which was obtained by calling `add()`.
|
||||
template<typename Func>
|
||||
inline Error release(Func p) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error release(Func p) noexcept {
|
||||
return _release(Support::ptr_cast_impl<void*, Func>(p));
|
||||
}
|
||||
|
||||
|
||||
@@ -47,38 +47,38 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns \ref FormatOptions of this logger.
|
||||
inline FormatOptions& options() noexcept { return _options; }
|
||||
ASMJIT_INLINE_NODEBUG FormatOptions& options() noexcept { return _options; }
|
||||
//! \overload
|
||||
inline const FormatOptions& options() const noexcept { return _options; }
|
||||
ASMJIT_INLINE_NODEBUG const FormatOptions& options() const noexcept { return _options; }
|
||||
//! Sets formatting options of this Logger to `options`.
|
||||
inline void setOptions(const FormatOptions& options) noexcept { _options = options; }
|
||||
ASMJIT_INLINE_NODEBUG void setOptions(const FormatOptions& options) noexcept { _options = options; }
|
||||
//! Resets formatting options of this Logger to defaults.
|
||||
inline void resetOptions() noexcept { _options.reset(); }
|
||||
ASMJIT_INLINE_NODEBUG void resetOptions() noexcept { _options.reset(); }
|
||||
|
||||
//! Returns formatting flags.
|
||||
inline FormatFlags flags() const noexcept { return _options.flags(); }
|
||||
ASMJIT_INLINE_NODEBUG FormatFlags flags() const noexcept { return _options.flags(); }
|
||||
//! Tests whether the logger has the given `flag` enabled.
|
||||
inline bool hasFlag(FormatFlags flag) const noexcept { return _options.hasFlag(flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(FormatFlags flag) const noexcept { return _options.hasFlag(flag); }
|
||||
//! Sets formatting flags to `flags`.
|
||||
inline void setFlags(FormatFlags flags) noexcept { _options.setFlags(flags); }
|
||||
ASMJIT_INLINE_NODEBUG void setFlags(FormatFlags flags) noexcept { _options.setFlags(flags); }
|
||||
//! Enables the given formatting `flags`.
|
||||
inline void addFlags(FormatFlags flags) noexcept { _options.addFlags(flags); }
|
||||
ASMJIT_INLINE_NODEBUG void addFlags(FormatFlags flags) noexcept { _options.addFlags(flags); }
|
||||
//! Disables the given formatting `flags`.
|
||||
inline void clearFlags(FormatFlags flags) noexcept { _options.clearFlags(flags); }
|
||||
ASMJIT_INLINE_NODEBUG void clearFlags(FormatFlags flags) noexcept { _options.clearFlags(flags); }
|
||||
|
||||
//! Returns indentation of a given indentation `group`.
|
||||
inline uint32_t indentation(FormatIndentationGroup type) const noexcept { return _options.indentation(type); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t indentation(FormatIndentationGroup type) const noexcept { return _options.indentation(type); }
|
||||
//! Sets indentation of the given indentation `group` to `n` spaces.
|
||||
inline void setIndentation(FormatIndentationGroup type, uint32_t n) noexcept { _options.setIndentation(type, n); }
|
||||
ASMJIT_INLINE_NODEBUG void setIndentation(FormatIndentationGroup type, uint32_t n) noexcept { _options.setIndentation(type, n); }
|
||||
//! Resets indentation of the given indentation `group` to 0 spaces.
|
||||
inline void resetIndentation(FormatIndentationGroup type) noexcept { _options.resetIndentation(type); }
|
||||
ASMJIT_INLINE_NODEBUG void resetIndentation(FormatIndentationGroup type) noexcept { _options.resetIndentation(type); }
|
||||
|
||||
//! Returns padding of a given padding `group`.
|
||||
inline size_t padding(FormatPaddingGroup type) const noexcept { return _options.padding(type); }
|
||||
ASMJIT_INLINE_NODEBUG size_t padding(FormatPaddingGroup type) const noexcept { return _options.padding(type); }
|
||||
//! Sets padding of a given padding `group` to `n`.
|
||||
inline void setPadding(FormatPaddingGroup type, uint32_t n) noexcept { _options.setPadding(type, n); }
|
||||
ASMJIT_INLINE_NODEBUG void setPadding(FormatPaddingGroup type, uint32_t n) noexcept { _options.setPadding(type, n); }
|
||||
//! Resets padding of a given padding `group` to 0, which means that a default will be used.
|
||||
inline void resetPadding(FormatPaddingGroup type) noexcept { _options.resetPadding(type); }
|
||||
ASMJIT_INLINE_NODEBUG void resetPadding(FormatPaddingGroup type) noexcept { _options.resetPadding(type); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -93,9 +93,9 @@ public:
|
||||
virtual Error _log(const char* data, size_t size) noexcept = 0;
|
||||
|
||||
//! Logs string `str`, which is either null terminated or having size `size`.
|
||||
inline Error log(const char* data, size_t size = SIZE_MAX) noexcept { return _log(data, size); }
|
||||
ASMJIT_INLINE_NODEBUG Error log(const char* data, size_t size = SIZE_MAX) noexcept { return _log(data, size); }
|
||||
//! Logs content of a string `str`.
|
||||
inline Error log(const String& str) noexcept { return _log(str.data(), str.size()); }
|
||||
ASMJIT_INLINE_NODEBUG Error log(const String& str) noexcept { return _log(str.data(), str.size()); }
|
||||
|
||||
//! Formats the message by using `snprintf()` and then passes the formatted string to \ref _log().
|
||||
ASMJIT_API Error logf(const char* fmt, ...) noexcept;
|
||||
@@ -127,14 +127,14 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the logging output stream or null if the logger has no output stream.
|
||||
inline FILE* file() const noexcept { return _file; }
|
||||
ASMJIT_INLINE_NODEBUG FILE* file() const noexcept { return _file; }
|
||||
|
||||
//! Sets the logging output stream to `stream` or null.
|
||||
//!
|
||||
//! \note If the `file` is null the logging will be disabled. When a logger is attached to `CodeHolder` or any
|
||||
//! emitter the logging API will always be called regardless of the output file. This means that if you really
|
||||
//! want to disable logging at emitter level you must not attach a logger to it.
|
||||
inline void setFile(FILE* file) noexcept { _file = file; }
|
||||
ASMJIT_INLINE_NODEBUG void setFile(FILE* file) noexcept { _file = file; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -165,16 +165,16 @@ public:
|
||||
//! Returns the content of the logger as \ref String.
|
||||
//!
|
||||
//! It can be moved, if desired.
|
||||
inline String& content() noexcept { return _content; }
|
||||
ASMJIT_INLINE_NODEBUG String& content() noexcept { return _content; }
|
||||
//! \overload
|
||||
inline const String& content() const noexcept { return _content; }
|
||||
ASMJIT_INLINE_NODEBUG const String& content() const noexcept { return _content; }
|
||||
|
||||
//! Returns aggregated logger data as `char*` pointer.
|
||||
//!
|
||||
//! The pointer is owned by `StringLogger`, it can't be modified or freed.
|
||||
inline const char* data() const noexcept { return _content.data(); }
|
||||
ASMJIT_INLINE_NODEBUG const char* data() const noexcept { return _content.data(); }
|
||||
//! Returns size of the data returned by `data()`.
|
||||
inline size_t dataSize() const noexcept { return _content.size(); }
|
||||
ASMJIT_INLINE_NODEBUG size_t dataSize() const noexcept { return _content.size(); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -182,7 +182,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Clears the accumulated logger data.
|
||||
inline void clear() noexcept { _content.clear(); }
|
||||
ASMJIT_INLINE_NODEBUG void clear() noexcept { _content.clear(); }
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -47,11 +47,11 @@ public:
|
||||
Handle _handle;
|
||||
#endif
|
||||
|
||||
ASMJIT_FORCE_INLINE Lock() noexcept;
|
||||
ASMJIT_FORCE_INLINE ~Lock() noexcept;
|
||||
ASMJIT_INLINE_NODEBUG Lock() noexcept;
|
||||
ASMJIT_INLINE_NODEBUG ~Lock() noexcept;
|
||||
|
||||
ASMJIT_FORCE_INLINE void lock() noexcept;
|
||||
ASMJIT_FORCE_INLINE void unlock() noexcept;
|
||||
ASMJIT_INLINE_NODEBUG void lock() noexcept;
|
||||
ASMJIT_INLINE_NODEBUG void unlock() noexcept;
|
||||
};
|
||||
//! \endcond
|
||||
|
||||
|
||||
@@ -21,30 +21,30 @@ ASMJIT_BEGIN_NAMESPACE
|
||||
static_assert(sizeof(Lock::Handle) == sizeof(CRITICAL_SECTION), "asmjit::Lock::Handle layout must match CRITICAL_SECTION");
|
||||
static_assert(alignof(Lock::Handle) == alignof(CRITICAL_SECTION), "asmjit::Lock::Handle alignment must match CRITICAL_SECTION");
|
||||
|
||||
ASMJIT_FORCE_INLINE Lock::Lock() noexcept { InitializeCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); }
|
||||
ASMJIT_FORCE_INLINE Lock::~Lock() noexcept { DeleteCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); }
|
||||
ASMJIT_FORCE_INLINE void Lock::lock() noexcept { EnterCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); }
|
||||
ASMJIT_FORCE_INLINE void Lock::unlock() noexcept { LeaveCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); }
|
||||
ASMJIT_INLINE_NODEBUG Lock::Lock() noexcept { InitializeCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); }
|
||||
ASMJIT_INLINE_NODEBUG Lock::~Lock() noexcept { DeleteCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); }
|
||||
ASMJIT_INLINE_NODEBUG void Lock::lock() noexcept { EnterCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); }
|
||||
ASMJIT_INLINE_NODEBUG void Lock::unlock() noexcept { LeaveCriticalSection(reinterpret_cast<CRITICAL_SECTION*>(&_handle)); }
|
||||
|
||||
#elif !defined(__EMSCRIPTEN__)
|
||||
|
||||
// PThread implementation.
|
||||
#ifdef PTHREAD_MUTEX_INITIALIZER
|
||||
ASMJIT_FORCE_INLINE Lock::Lock() noexcept : _handle(PTHREAD_MUTEX_INITIALIZER) {}
|
||||
ASMJIT_INLINE_NODEBUG Lock::Lock() noexcept : _handle(PTHREAD_MUTEX_INITIALIZER) {}
|
||||
#else
|
||||
ASMJIT_FORCE_INLINE Lock::Lock() noexcept { pthread_mutex_init(&_handle, nullptr); }
|
||||
ASMJIT_INLINE_NODEBUG Lock::Lock() noexcept { pthread_mutex_init(&_handle, nullptr); }
|
||||
#endif
|
||||
ASMJIT_FORCE_INLINE Lock::~Lock() noexcept { pthread_mutex_destroy(&_handle); }
|
||||
ASMJIT_FORCE_INLINE void Lock::lock() noexcept { pthread_mutex_lock(&_handle); }
|
||||
ASMJIT_FORCE_INLINE void Lock::unlock() noexcept { pthread_mutex_unlock(&_handle); }
|
||||
ASMJIT_INLINE_NODEBUG Lock::~Lock() noexcept { pthread_mutex_destroy(&_handle); }
|
||||
ASMJIT_INLINE_NODEBUG void Lock::lock() noexcept { pthread_mutex_lock(&_handle); }
|
||||
ASMJIT_INLINE_NODEBUG void Lock::unlock() noexcept { pthread_mutex_unlock(&_handle); }
|
||||
|
||||
#else
|
||||
|
||||
// Dummy implementation - Emscripten or other unsupported platform.
|
||||
ASMJIT_FORCE_INLINE Lock::Lock() noexcept {}
|
||||
ASMJIT_FORCE_INLINE Lock::~Lock() noexcept {}
|
||||
ASMJIT_FORCE_INLINE void Lock::lock() noexcept {}
|
||||
ASMJIT_FORCE_INLINE void Lock::unlock() noexcept {}
|
||||
ASMJIT_INLINE_NODEBUG Lock::Lock() noexcept {}
|
||||
ASMJIT_INLINE_NODEBUG Lock::~Lock() noexcept {}
|
||||
ASMJIT_INLINE_NODEBUG void Lock::lock() noexcept {}
|
||||
ASMJIT_INLINE_NODEBUG void Lock::unlock() noexcept {}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -55,9 +55,9 @@ public:
|
||||
|
||||
Lock& _target;
|
||||
|
||||
inline LockGuard(Lock& target) noexcept
|
||||
ASMJIT_INLINE_NODEBUG LockGuard(Lock& target) noexcept
|
||||
: _target(target) { _target.lock(); }
|
||||
inline ~LockGuard() noexcept { _target.unlock(); }
|
||||
ASMJIT_INLINE_NODEBUG ~LockGuard() noexcept { _target.unlock(); }
|
||||
};
|
||||
|
||||
#if !defined(_WIN32)
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
//! PhysReg to WorkReg mapping.
|
||||
uint32_t workIds[1 /* ... */];
|
||||
|
||||
static inline size_t sizeOf(size_t count) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG size_t sizeOf(size_t count) noexcept {
|
||||
return sizeof(PhysToWorkMap) - sizeof(uint32_t) + count * sizeof(uint32_t);
|
||||
}
|
||||
|
||||
@@ -163,16 +163,16 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline PhysToWorkMap* physToWorkMap() const noexcept { return _physToWorkMap; }
|
||||
inline WorkToPhysMap* workToPhysMap() const noexcept { return _workToPhysMap; }
|
||||
ASMJIT_INLINE_NODEBUG PhysToWorkMap* physToWorkMap() const noexcept { return _physToWorkMap; }
|
||||
ASMJIT_INLINE_NODEBUG WorkToPhysMap* workToPhysMap() const noexcept { return _workToPhysMap; }
|
||||
|
||||
inline RARegMask& assigned() noexcept { return _physToWorkMap->assigned; }
|
||||
inline const RARegMask& assigned() const noexcept { return _physToWorkMap->assigned; }
|
||||
inline uint32_t assigned(RegGroup group) const noexcept { return _physToWorkMap->assigned[group]; }
|
||||
ASMJIT_INLINE_NODEBUG RARegMask& assigned() noexcept { return _physToWorkMap->assigned; }
|
||||
ASMJIT_INLINE_NODEBUG const RARegMask& assigned() const noexcept { return _physToWorkMap->assigned; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t assigned(RegGroup group) const noexcept { return _physToWorkMap->assigned[group]; }
|
||||
|
||||
inline RARegMask& dirty() noexcept { return _physToWorkMap->dirty; }
|
||||
inline const RARegMask& dirty() const noexcept { return _physToWorkMap->dirty; }
|
||||
inline RegMask dirty(RegGroup group) const noexcept { return _physToWorkMap->dirty[group]; }
|
||||
ASMJIT_INLINE_NODEBUG RARegMask& dirty() noexcept { return _physToWorkMap->dirty; }
|
||||
ASMJIT_INLINE_NODEBUG const RARegMask& dirty() const noexcept { return _physToWorkMap->dirty; }
|
||||
ASMJIT_INLINE_NODEBUG RegMask dirty(RegGroup group) const noexcept { return _physToWorkMap->dirty[group]; }
|
||||
|
||||
inline uint32_t workToPhysId(RegGroup group, uint32_t workId) const noexcept {
|
||||
DebugUtils::unused(group);
|
||||
|
||||
@@ -115,20 +115,20 @@ struct RAStrategy {
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline void reset() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept {
|
||||
_type = RAStrategyType::kSimple;
|
||||
_flags = RAStrategyFlags::kNone;
|
||||
}
|
||||
|
||||
inline RAStrategyType type() const noexcept { return _type; }
|
||||
inline void setType(RAStrategyType type) noexcept { _type = type; }
|
||||
ASMJIT_INLINE_NODEBUG RAStrategyType type() const noexcept { return _type; }
|
||||
ASMJIT_INLINE_NODEBUG void setType(RAStrategyType type) noexcept { _type = type; }
|
||||
|
||||
inline bool isSimple() const noexcept { return _type == RAStrategyType::kSimple; }
|
||||
inline bool isComplex() const noexcept { return _type >= RAStrategyType::kComplex; }
|
||||
ASMJIT_INLINE_NODEBUG bool isSimple() const noexcept { return _type == RAStrategyType::kSimple; }
|
||||
ASMJIT_INLINE_NODEBUG bool isComplex() const noexcept { return _type >= RAStrategyType::kComplex; }
|
||||
|
||||
inline RAStrategyFlags flags() const noexcept { return _flags; }
|
||||
inline bool hasFlag(RAStrategyFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
inline void addFlags(RAStrategyFlags flags) noexcept { _flags |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG RAStrategyFlags flags() const noexcept { return _flags; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(RAStrategyFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG void addFlags(RAStrategyFlags flags) noexcept { _flags |= flags; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -153,7 +153,7 @@ struct RARegCount {
|
||||
//! \{
|
||||
|
||||
//! Resets all counters to zero.
|
||||
inline void reset() noexcept { _packed = 0; }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { _packed = 0; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -170,8 +170,8 @@ struct RARegCount {
|
||||
return _regs[size_t(group)];
|
||||
}
|
||||
|
||||
inline bool operator==(const RARegCount& other) const noexcept { return _packed == other._packed; }
|
||||
inline bool operator!=(const RARegCount& other) const noexcept { return _packed != other._packed; }
|
||||
ASMJIT_INLINE_NODEBUG bool operator==(const RARegCount& other) const noexcept { return _packed == other._packed; }
|
||||
ASMJIT_INLINE_NODEBUG bool operator!=(const RARegCount& other) const noexcept { return _packed != other._packed; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -233,17 +233,17 @@ struct RARegMask {
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline void init(const RARegMask& other) noexcept { _masks = other._masks; }
|
||||
ASMJIT_INLINE_NODEBUG void init(const RARegMask& other) noexcept { _masks = other._masks; }
|
||||
//! Reset all register masks to zero.
|
||||
inline void reset() noexcept { _masks.fill(0); }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { _masks.fill(0); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
inline bool operator==(const RARegMask& other) const noexcept { return _masks == other._masks; }
|
||||
inline bool operator!=(const RARegMask& other) const noexcept { return _masks != other._masks; }
|
||||
ASMJIT_INLINE_NODEBUG bool operator==(const RARegMask& other) const noexcept { return _masks == other._masks; }
|
||||
ASMJIT_INLINE_NODEBUG bool operator!=(const RARegMask& other) const noexcept { return _masks != other._masks; }
|
||||
|
||||
template<typename Index>
|
||||
inline uint32_t& operator[](const Index& index) noexcept { return _masks[index]; }
|
||||
@@ -315,20 +315,20 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline void reset() noexcept { _packed = 0; }
|
||||
inline void combineWith(const RARegsStats& other) noexcept { _packed |= other._packed; }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { _packed = 0; }
|
||||
ASMJIT_INLINE_NODEBUG void combineWith(const RARegsStats& other) noexcept { _packed |= other._packed; }
|
||||
|
||||
inline bool hasUsed() const noexcept { return (_packed & kMaskUsed) != 0u; }
|
||||
inline bool hasUsed(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexUsed + uint32_t(group))) != 0u; }
|
||||
inline void makeUsed(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexUsed + uint32_t(group)); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasUsed() const noexcept { return (_packed & kMaskUsed) != 0u; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasUsed(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexUsed + uint32_t(group))) != 0u; }
|
||||
ASMJIT_INLINE_NODEBUG void makeUsed(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexUsed + uint32_t(group)); }
|
||||
|
||||
inline bool hasFixed() const noexcept { return (_packed & kMaskFixed) != 0u; }
|
||||
inline bool hasFixed(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexFixed + uint32_t(group))) != 0u; }
|
||||
inline void makeFixed(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexFixed + uint32_t(group)); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFixed() const noexcept { return (_packed & kMaskFixed) != 0u; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFixed(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexFixed + uint32_t(group))) != 0u; }
|
||||
ASMJIT_INLINE_NODEBUG void makeFixed(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexFixed + uint32_t(group)); }
|
||||
|
||||
inline bool hasClobbered() const noexcept { return (_packed & kMaskClobbered) != 0u; }
|
||||
inline bool hasClobbered(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexClobbered + uint32_t(group))) != 0u; }
|
||||
inline void makeClobbered(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexClobbered + uint32_t(group)); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasClobbered() const noexcept { return (_packed & kMaskClobbered) != 0u; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasClobbered(RegGroup group) const noexcept { return (_packed & Support::bitMask(kIndexClobbered + uint32_t(group))) != 0u; }
|
||||
ASMJIT_INLINE_NODEBUG void makeClobbered(RegGroup group) noexcept { _packed |= Support::bitMask(kIndexClobbered + uint32_t(group)); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -346,18 +346,18 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline RALiveCount() noexcept = default;
|
||||
inline RALiveCount(const RALiveCount& other) noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG RALiveCount() noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG RALiveCount(const RALiveCount& other) noexcept = default;
|
||||
|
||||
inline void init(const RALiveCount& other) noexcept { n = other.n; }
|
||||
inline void reset() noexcept { n.fill(0); }
|
||||
ASMJIT_INLINE_NODEBUG void init(const RALiveCount& other) noexcept { n = other.n; }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { n.fill(0); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
inline RALiveCount& operator=(const RALiveCount& other) noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG RALiveCount& operator=(const RALiveCount& other) noexcept = default;
|
||||
|
||||
inline uint32_t& operator[](RegGroup group) noexcept { return n[group]; }
|
||||
inline const uint32_t& operator[](RegGroup group) const noexcept { return n[group]; }
|
||||
@@ -394,31 +394,31 @@ struct RALiveInterval {
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline RALiveInterval() noexcept : a(0), b(0) {}
|
||||
inline RALiveInterval(uint32_t a, uint32_t b) noexcept : a(a), b(b) {}
|
||||
inline RALiveInterval(const RALiveInterval& other) noexcept : a(other.a), b(other.b) {}
|
||||
ASMJIT_INLINE_NODEBUG RALiveInterval() noexcept : a(0), b(0) {}
|
||||
ASMJIT_INLINE_NODEBUG RALiveInterval(uint32_t a, uint32_t b) noexcept : a(a), b(b) {}
|
||||
ASMJIT_INLINE_NODEBUG RALiveInterval(const RALiveInterval& other) noexcept : a(other.a), b(other.b) {}
|
||||
|
||||
inline void init(uint32_t aVal, uint32_t bVal) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void init(uint32_t aVal, uint32_t bVal) noexcept {
|
||||
a = aVal;
|
||||
b = bVal;
|
||||
}
|
||||
inline void init(const RALiveInterval& other) noexcept { init(other.a, other.b); }
|
||||
inline void reset() noexcept { init(0, 0); }
|
||||
ASMJIT_INLINE_NODEBUG void init(const RALiveInterval& other) noexcept { init(other.a, other.b); }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { init(0, 0); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
inline RALiveInterval& operator=(const RALiveInterval& other) = default;
|
||||
ASMJIT_INLINE_NODEBUG RALiveInterval& operator=(const RALiveInterval& other) = default;
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline bool isValid() const noexcept { return a < b; }
|
||||
inline uint32_t width() const noexcept { return b - a; }
|
||||
ASMJIT_INLINE_NODEBUG bool isValid() const noexcept { return a < b; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t width() const noexcept { return b - a; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -437,23 +437,23 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline RALiveSpan() noexcept : RALiveInterval(), T() {}
|
||||
inline RALiveSpan(const RALiveSpan<T>& other) noexcept : RALiveInterval(other), T() {}
|
||||
inline RALiveSpan(const RALiveInterval& interval, const T& data) noexcept : RALiveInterval(interval), T(data) {}
|
||||
inline RALiveSpan(uint32_t a, uint32_t b) noexcept : RALiveInterval(a, b), T() {}
|
||||
inline RALiveSpan(uint32_t a, uint32_t b, const T& data) noexcept : RALiveInterval(a, b), T(data) {}
|
||||
ASMJIT_INLINE_NODEBUG RALiveSpan() noexcept : RALiveInterval(), T() {}
|
||||
ASMJIT_INLINE_NODEBUG RALiveSpan(const RALiveSpan<T>& other) noexcept : RALiveInterval(other), T() {}
|
||||
ASMJIT_INLINE_NODEBUG RALiveSpan(const RALiveInterval& interval, const T& data) noexcept : RALiveInterval(interval), T(data) {}
|
||||
ASMJIT_INLINE_NODEBUG RALiveSpan(uint32_t a, uint32_t b) noexcept : RALiveInterval(a, b), T() {}
|
||||
ASMJIT_INLINE_NODEBUG RALiveSpan(uint32_t a, uint32_t b, const T& data) noexcept : RALiveInterval(a, b), T(data) {}
|
||||
|
||||
inline void init(const RALiveSpan<T>& other) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void init(const RALiveSpan<T>& other) noexcept {
|
||||
RALiveInterval::init(static_cast<const RALiveInterval&>(other));
|
||||
T::init(static_cast<const T&>(other));
|
||||
}
|
||||
|
||||
inline void init(const RALiveSpan<T>& span, const T& data) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void init(const RALiveSpan<T>& span, const T& data) noexcept {
|
||||
RALiveInterval::init(static_cast<const RALiveInterval&>(span));
|
||||
T::init(data);
|
||||
}
|
||||
|
||||
inline void init(const RALiveInterval& interval, const T& data) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void init(const RALiveInterval& interval, const T& data) noexcept {
|
||||
RALiveInterval::init(interval);
|
||||
T::init(data);
|
||||
}
|
||||
@@ -463,7 +463,7 @@ public:
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
inline RALiveSpan& operator=(const RALiveSpan& other) {
|
||||
ASMJIT_INLINE_NODEBUG RALiveSpan& operator=(const RALiveSpan& other) {
|
||||
init(other);
|
||||
return *this;
|
||||
}
|
||||
@@ -483,23 +483,23 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline RALiveSpans() noexcept : _data() {}
|
||||
ASMJIT_INLINE_NODEBUG RALiveSpans() noexcept : _data() {}
|
||||
|
||||
inline void reset() noexcept { _data.reset(); }
|
||||
inline void release(ZoneAllocator* allocator) noexcept { _data.release(allocator); }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { _data.reset(); }
|
||||
ASMJIT_INLINE_NODEBUG void release(ZoneAllocator* allocator) noexcept { _data.release(allocator); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline bool empty() const noexcept { return _data.empty(); }
|
||||
inline uint32_t size() const noexcept { return _data.size(); }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _data.empty(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t size() const noexcept { return _data.size(); }
|
||||
|
||||
inline T* data() noexcept { return _data.data(); }
|
||||
inline const T* data() const noexcept { return _data.data(); }
|
||||
ASMJIT_INLINE_NODEBUG T* data() noexcept { return _data.data(); }
|
||||
ASMJIT_INLINE_NODEBUG const T* data() const noexcept { return _data.data(); }
|
||||
|
||||
inline bool isOpen() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool isOpen() const noexcept {
|
||||
uint32_t size = _data.size();
|
||||
return size > 0 && _data[size - 1].b == RALiveInterval::kInf;
|
||||
}
|
||||
@@ -509,7 +509,7 @@ public:
|
||||
//! \name Utilities
|
||||
//! \{
|
||||
|
||||
inline void swap(RALiveSpans<T>& other) noexcept { _data.swap(other._data); }
|
||||
ASMJIT_INLINE_NODEBUG void swap(RALiveSpans<T>& other) noexcept { _data.swap(other._data); }
|
||||
|
||||
//! Open the current live span.
|
||||
ASMJIT_FORCE_INLINE Error openAt(ZoneAllocator* allocator, uint32_t start, uint32_t end) noexcept {
|
||||
@@ -550,10 +550,10 @@ public:
|
||||
return width;
|
||||
}
|
||||
|
||||
inline T& operator[](uint32_t index) noexcept { return _data[index]; }
|
||||
inline const T& operator[](uint32_t index) const noexcept { return _data[index]; }
|
||||
ASMJIT_INLINE_NODEBUG T& operator[](uint32_t index) noexcept { return _data[index]; }
|
||||
ASMJIT_INLINE_NODEBUG const T& operator[](uint32_t index) const noexcept { return _data[index]; }
|
||||
|
||||
inline bool intersects(const RALiveSpans<T>& other) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool intersects(const RALiveSpans<T>& other) const noexcept {
|
||||
return intersects(*this, other);
|
||||
}
|
||||
|
||||
@@ -655,9 +655,9 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline uint32_t width() const noexcept { return _width; }
|
||||
inline float freq() const noexcept { return _freq; }
|
||||
inline float priority() const noexcept { return _priority; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t width() const noexcept { return _width; }
|
||||
ASMJIT_INLINE_NODEBUG float freq() const noexcept { return _freq; }
|
||||
ASMJIT_INLINE_NODEBUG float priority() const noexcept { return _priority; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -665,13 +665,13 @@ public:
|
||||
struct LiveRegData {
|
||||
uint32_t id;
|
||||
|
||||
inline explicit LiveRegData(uint32_t id = BaseReg::kIdBad) noexcept : id(id) {}
|
||||
inline LiveRegData(const LiveRegData& other) noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG explicit LiveRegData(uint32_t id = BaseReg::kIdBad) noexcept : id(id) {}
|
||||
ASMJIT_INLINE_NODEBUG LiveRegData(const LiveRegData& other) noexcept = default;
|
||||
|
||||
inline void init(const LiveRegData& other) noexcept { id = other.id; }
|
||||
ASMJIT_INLINE_NODEBUG void init(const LiveRegData& other) noexcept { id = other.id; }
|
||||
|
||||
inline bool operator==(const LiveRegData& other) const noexcept { return id == other.id; }
|
||||
inline bool operator!=(const LiveRegData& other) const noexcept { return id != other.id; }
|
||||
ASMJIT_INLINE_NODEBUG bool operator==(const LiveRegData& other) const noexcept { return id == other.id; }
|
||||
ASMJIT_INLINE_NODEBUG bool operator!=(const LiveRegData& other) const noexcept { return id != other.id; }
|
||||
};
|
||||
|
||||
typedef RALiveSpan<LiveRegData> LiveRegSpan;
|
||||
@@ -858,54 +858,54 @@ struct RATiedReg {
|
||||
//! \{
|
||||
|
||||
//! Returns the associated WorkReg id.
|
||||
inline uint32_t workId() const noexcept { return _workId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t workId() const noexcept { return _workId; }
|
||||
|
||||
inline bool hasConsecutiveParent() const noexcept { return _consecutiveParent != Globals::kInvalidId; }
|
||||
inline uint32_t consecutiveParent() const noexcept { return _consecutiveParent; }
|
||||
inline uint32_t consecutiveData() const noexcept { return consecutiveDataFromFlags(_flags); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasConsecutiveParent() const noexcept { return _consecutiveParent != Globals::kInvalidId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t consecutiveParent() const noexcept { return _consecutiveParent; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t consecutiveData() const noexcept { return consecutiveDataFromFlags(_flags); }
|
||||
|
||||
//! Returns TiedReg flags.
|
||||
inline RATiedFlags flags() const noexcept { return _flags; }
|
||||
ASMJIT_INLINE_NODEBUG RATiedFlags flags() const noexcept { return _flags; }
|
||||
//! Checks if the given `flag` is set.
|
||||
inline bool hasFlag(RATiedFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(RATiedFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
//! Adds tied register flags.
|
||||
inline void addFlags(RATiedFlags flags) noexcept { _flags |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG void addFlags(RATiedFlags flags) noexcept { _flags |= flags; }
|
||||
|
||||
//! Tests whether the register is read (writes `true` also if it's Read/Write).
|
||||
inline bool isRead() const noexcept { return hasFlag(RATiedFlags::kRead); }
|
||||
ASMJIT_INLINE_NODEBUG bool isRead() const noexcept { return hasFlag(RATiedFlags::kRead); }
|
||||
//! Tests whether the register is written (writes `true` also if it's Read/Write).
|
||||
inline bool isWrite() const noexcept { return hasFlag(RATiedFlags::kWrite); }
|
||||
ASMJIT_INLINE_NODEBUG bool isWrite() const noexcept { return hasFlag(RATiedFlags::kWrite); }
|
||||
//! Tests whether the register is read only.
|
||||
inline bool isReadOnly() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kRead; }
|
||||
ASMJIT_INLINE_NODEBUG bool isReadOnly() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kRead; }
|
||||
//! Tests whether the register is write only.
|
||||
inline bool isWriteOnly() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kWrite; }
|
||||
ASMJIT_INLINE_NODEBUG bool isWriteOnly() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kWrite; }
|
||||
//! Tests whether the register is read and written.
|
||||
inline bool isReadWrite() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kRW; }
|
||||
ASMJIT_INLINE_NODEBUG bool isReadWrite() const noexcept { return (_flags & RATiedFlags::kRW) == RATiedFlags::kRW; }
|
||||
|
||||
//! Tests whether the tied register has use operand (Read/ReadWrite).
|
||||
inline bool isUse() const noexcept { return hasFlag(RATiedFlags::kUse); }
|
||||
ASMJIT_INLINE_NODEBUG bool isUse() const noexcept { return hasFlag(RATiedFlags::kUse); }
|
||||
//! Tests whether the tied register has out operand (Write).
|
||||
inline bool isOut() const noexcept { return hasFlag(RATiedFlags::kOut); }
|
||||
ASMJIT_INLINE_NODEBUG bool isOut() const noexcept { return hasFlag(RATiedFlags::kOut); }
|
||||
|
||||
//! Tests whether the tied register has \ref RATiedFlags::kLeadConsecutive flag set.
|
||||
inline bool isLeadConsecutive() const noexcept { return hasFlag(RATiedFlags::kLeadConsecutive); }
|
||||
ASMJIT_INLINE_NODEBUG bool isLeadConsecutive() const noexcept { return hasFlag(RATiedFlags::kLeadConsecutive); }
|
||||
//! Tests whether the tied register has \ref RATiedFlags::kUseConsecutive flag set.
|
||||
inline bool isUseConsecutive() const noexcept { return hasFlag(RATiedFlags::kUseConsecutive); }
|
||||
ASMJIT_INLINE_NODEBUG bool isUseConsecutive() const noexcept { return hasFlag(RATiedFlags::kUseConsecutive); }
|
||||
//! Tests whether the tied register has \ref RATiedFlags::kOutConsecutive flag set.
|
||||
inline bool isOutConsecutive() const noexcept { return hasFlag(RATiedFlags::kOutConsecutive); }
|
||||
ASMJIT_INLINE_NODEBUG bool isOutConsecutive() const noexcept { return hasFlag(RATiedFlags::kOutConsecutive); }
|
||||
|
||||
//! Tests whether the tied register must be unique (cannot be allocated to any other allocated register).
|
||||
inline bool isUnique() const noexcept { return hasFlag(RATiedFlags::kUnique); }
|
||||
ASMJIT_INLINE_NODEBUG bool isUnique() const noexcept { return hasFlag(RATiedFlags::kUnique); }
|
||||
|
||||
//! Tests whether the tied register has any consecutive flag.
|
||||
inline bool hasAnyConsecutiveFlag() const noexcept { return hasFlag(RATiedFlags::kLeadConsecutive | RATiedFlags::kUseConsecutive | RATiedFlags::kOutConsecutive); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAnyConsecutiveFlag() const noexcept { return hasFlag(RATiedFlags::kLeadConsecutive | RATiedFlags::kUseConsecutive | RATiedFlags::kOutConsecutive); }
|
||||
|
||||
//! Tests whether the USE slot can be patched to memory operand.
|
||||
inline bool hasUseRM() const noexcept { return hasFlag(RATiedFlags::kUseRM); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasUseRM() const noexcept { return hasFlag(RATiedFlags::kUseRM); }
|
||||
//! Tests whether the OUT slot can be patched to memory operand.
|
||||
inline bool hasOutRM() const noexcept { return hasFlag(RATiedFlags::kOutRM); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasOutRM() const noexcept { return hasFlag(RATiedFlags::kOutRM); }
|
||||
|
||||
inline uint32_t rmSize() const noexcept { return _rmSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t rmSize() const noexcept { return _rmSize; }
|
||||
|
||||
inline void makeReadOnly() noexcept {
|
||||
_flags = (_flags & ~(RATiedFlags::kOut | RATiedFlags::kWrite)) | RATiedFlags::kUse;
|
||||
@@ -920,47 +920,47 @@ struct RATiedReg {
|
||||
}
|
||||
|
||||
//! Tests whether the register would duplicate.
|
||||
inline bool isDuplicate() const noexcept { return hasFlag(RATiedFlags::kDuplicate); }
|
||||
ASMJIT_INLINE_NODEBUG bool isDuplicate() const noexcept { return hasFlag(RATiedFlags::kDuplicate); }
|
||||
|
||||
//! Tests whether the register (and the instruction it's part of) appears last in the basic block.
|
||||
inline bool isLast() const noexcept { return hasFlag(RATiedFlags::kLast); }
|
||||
ASMJIT_INLINE_NODEBUG bool isLast() const noexcept { return hasFlag(RATiedFlags::kLast); }
|
||||
//! Tests whether the register should be killed after USEd and/or OUTed.
|
||||
inline bool isKill() const noexcept { return hasFlag(RATiedFlags::kKill); }
|
||||
ASMJIT_INLINE_NODEBUG bool isKill() const noexcept { return hasFlag(RATiedFlags::kKill); }
|
||||
|
||||
//! Tests whether the register is OUT or KILL (used internally by local register allocator).
|
||||
inline bool isOutOrKill() const noexcept { return hasFlag(RATiedFlags::kOut | RATiedFlags::kKill); }
|
||||
ASMJIT_INLINE_NODEBUG bool isOutOrKill() const noexcept { return hasFlag(RATiedFlags::kOut | RATiedFlags::kKill); }
|
||||
|
||||
//! Returns a register mask that describes allocable USE registers (Read/ReadWrite access).
|
||||
inline RegMask useRegMask() const noexcept { return _useRegMask; }
|
||||
ASMJIT_INLINE_NODEBUG RegMask useRegMask() const noexcept { return _useRegMask; }
|
||||
//! Returns a register mask that describes allocable OUT registers (WriteOnly access).
|
||||
inline RegMask outRegMask() const noexcept { return _outRegMask; }
|
||||
ASMJIT_INLINE_NODEBUG RegMask outRegMask() const noexcept { return _outRegMask; }
|
||||
|
||||
inline uint32_t refCount() const noexcept { return _refCount; }
|
||||
inline void addRefCount(uint32_t n = 1) noexcept { _refCount = uint8_t(_refCount + n); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t refCount() const noexcept { return _refCount; }
|
||||
ASMJIT_INLINE_NODEBUG void addRefCount(uint32_t n = 1) noexcept { _refCount = uint8_t(_refCount + n); }
|
||||
|
||||
//! Tests whether the register must be allocated to a fixed physical register before it's used.
|
||||
inline bool hasUseId() const noexcept { return _useId != BaseReg::kIdBad; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasUseId() const noexcept { return _useId != BaseReg::kIdBad; }
|
||||
//! Tests whether the register must be allocated to a fixed physical register before it's written.
|
||||
inline bool hasOutId() const noexcept { return _outId != BaseReg::kIdBad; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasOutId() const noexcept { return _outId != BaseReg::kIdBad; }
|
||||
|
||||
//! Returns a physical register id used for 'use' operation.
|
||||
inline uint32_t useId() const noexcept { return _useId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t useId() const noexcept { return _useId; }
|
||||
//! Returns a physical register id used for 'out' operation.
|
||||
inline uint32_t outId() const noexcept { return _outId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t outId() const noexcept { return _outId; }
|
||||
|
||||
inline uint32_t useRewriteMask() const noexcept { return _useRewriteMask; }
|
||||
inline uint32_t outRewriteMask() const noexcept { return _outRewriteMask; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t useRewriteMask() const noexcept { return _useRewriteMask; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t outRewriteMask() const noexcept { return _outRewriteMask; }
|
||||
|
||||
//! Sets a physical register used for 'use' operation.
|
||||
inline void setUseId(uint32_t index) noexcept { _useId = uint8_t(index); }
|
||||
ASMJIT_INLINE_NODEBUG void setUseId(uint32_t index) noexcept { _useId = uint8_t(index); }
|
||||
//! Sets a physical register used for 'out' operation.
|
||||
inline void setOutId(uint32_t index) noexcept { _outId = uint8_t(index); }
|
||||
ASMJIT_INLINE_NODEBUG void setOutId(uint32_t index) noexcept { _outId = uint8_t(index); }
|
||||
|
||||
inline bool isUseDone() const noexcept { return hasFlag(RATiedFlags::kUseDone); }
|
||||
inline bool isOutDone() const noexcept { return hasFlag(RATiedFlags::kUseDone); }
|
||||
ASMJIT_INLINE_NODEBUG bool isUseDone() const noexcept { return hasFlag(RATiedFlags::kUseDone); }
|
||||
ASMJIT_INLINE_NODEBUG bool isOutDone() const noexcept { return hasFlag(RATiedFlags::kUseDone); }
|
||||
|
||||
inline void markUseDone() noexcept { addFlags(RATiedFlags::kUseDone); }
|
||||
inline void markOutDone() noexcept { addFlags(RATiedFlags::kUseDone); }
|
||||
ASMJIT_INLINE_NODEBUG void markUseDone() noexcept { addFlags(RATiedFlags::kUseDone); }
|
||||
ASMJIT_INLINE_NODEBUG void markOutDone() noexcept { addFlags(RATiedFlags::kUseDone); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -1090,7 +1090,7 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline RAWorkReg(VirtReg* vReg, uint32_t workId) noexcept
|
||||
ASMJIT_INLINE_NODEBUG RAWorkReg(VirtReg* vReg, uint32_t workId) noexcept
|
||||
: _workId(workId),
|
||||
_virtId(vReg->id()),
|
||||
_virtReg(vReg),
|
||||
@@ -1101,97 +1101,97 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline uint32_t workId() const noexcept { return _workId; }
|
||||
inline uint32_t virtId() const noexcept { return _virtId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t workId() const noexcept { return _workId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t virtId() const noexcept { return _virtId; }
|
||||
|
||||
inline const char* name() const noexcept { return _virtReg->name(); }
|
||||
inline uint32_t nameSize() const noexcept { return _virtReg->nameSize(); }
|
||||
ASMJIT_INLINE_NODEBUG const char* name() const noexcept { return _virtReg->name(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t nameSize() const noexcept { return _virtReg->nameSize(); }
|
||||
|
||||
inline TypeId typeId() const noexcept { return _virtReg->typeId(); }
|
||||
ASMJIT_INLINE_NODEBUG TypeId typeId() const noexcept { return _virtReg->typeId(); }
|
||||
|
||||
inline RAWorkRegFlags flags() const noexcept { return _flags; }
|
||||
inline bool hasFlag(RAWorkRegFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
inline void addFlags(RAWorkRegFlags flags) noexcept { _flags |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG RAWorkRegFlags flags() const noexcept { return _flags; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(RAWorkRegFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG void addFlags(RAWorkRegFlags flags) noexcept { _flags |= flags; }
|
||||
|
||||
inline bool isAllocated() const noexcept { return hasFlag(RAWorkRegFlags::kAllocated); }
|
||||
inline void markAllocated() noexcept { addFlags(RAWorkRegFlags::kAllocated); }
|
||||
ASMJIT_INLINE_NODEBUG bool isAllocated() const noexcept { return hasFlag(RAWorkRegFlags::kAllocated); }
|
||||
ASMJIT_INLINE_NODEBUG void markAllocated() noexcept { addFlags(RAWorkRegFlags::kAllocated); }
|
||||
|
||||
inline bool isLeadConsecutive() const noexcept { return hasFlag(RAWorkRegFlags::kLeadConsecutive); }
|
||||
inline void markLeadConsecutive() noexcept { addFlags(RAWorkRegFlags::kLeadConsecutive); }
|
||||
ASMJIT_INLINE_NODEBUG bool isLeadConsecutive() const noexcept { return hasFlag(RAWorkRegFlags::kLeadConsecutive); }
|
||||
ASMJIT_INLINE_NODEBUG void markLeadConsecutive() noexcept { addFlags(RAWorkRegFlags::kLeadConsecutive); }
|
||||
|
||||
inline bool isProcessedConsecutive() const noexcept { return hasFlag(RAWorkRegFlags::kProcessedConsecutive); }
|
||||
inline void markProcessedConsecutive() noexcept { addFlags(RAWorkRegFlags::kProcessedConsecutive); }
|
||||
ASMJIT_INLINE_NODEBUG bool isProcessedConsecutive() const noexcept { return hasFlag(RAWorkRegFlags::kProcessedConsecutive); }
|
||||
ASMJIT_INLINE_NODEBUG void markProcessedConsecutive() noexcept { addFlags(RAWorkRegFlags::kProcessedConsecutive); }
|
||||
|
||||
inline bool isStackUsed() const noexcept { return hasFlag(RAWorkRegFlags::kStackUsed); }
|
||||
inline void markStackUsed() noexcept { addFlags(RAWorkRegFlags::kStackUsed); }
|
||||
ASMJIT_INLINE_NODEBUG bool isStackUsed() const noexcept { return hasFlag(RAWorkRegFlags::kStackUsed); }
|
||||
ASMJIT_INLINE_NODEBUG void markStackUsed() noexcept { addFlags(RAWorkRegFlags::kStackUsed); }
|
||||
|
||||
inline bool isStackPreferred() const noexcept { return hasFlag(RAWorkRegFlags::kStackPreferred); }
|
||||
inline void markStackPreferred() noexcept { addFlags(RAWorkRegFlags::kStackPreferred); }
|
||||
ASMJIT_INLINE_NODEBUG bool isStackPreferred() const noexcept { return hasFlag(RAWorkRegFlags::kStackPreferred); }
|
||||
ASMJIT_INLINE_NODEBUG void markStackPreferred() noexcept { addFlags(RAWorkRegFlags::kStackPreferred); }
|
||||
|
||||
//! Tests whether this RAWorkReg has been coalesced with another one (cannot be used anymore).
|
||||
inline bool isCoalesced() const noexcept { return hasFlag(RAWorkRegFlags::kCoalesced); }
|
||||
ASMJIT_INLINE_NODEBUG bool isCoalesced() const noexcept { return hasFlag(RAWorkRegFlags::kCoalesced); }
|
||||
|
||||
inline OperandSignature signature() const noexcept { return _signature; }
|
||||
inline RegType type() const noexcept { return _signature.regType(); }
|
||||
inline RegGroup group() const noexcept { return _signature.regGroup(); }
|
||||
ASMJIT_INLINE_NODEBUG OperandSignature signature() const noexcept { return _signature; }
|
||||
ASMJIT_INLINE_NODEBUG RegType type() const noexcept { return _signature.regType(); }
|
||||
ASMJIT_INLINE_NODEBUG RegGroup group() const noexcept { return _signature.regGroup(); }
|
||||
|
||||
inline VirtReg* virtReg() const noexcept { return _virtReg; }
|
||||
ASMJIT_INLINE_NODEBUG VirtReg* virtReg() const noexcept { return _virtReg; }
|
||||
|
||||
inline bool hasTiedReg() const noexcept { return _tiedReg != nullptr; }
|
||||
inline RATiedReg* tiedReg() const noexcept { return _tiedReg; }
|
||||
inline void setTiedReg(RATiedReg* tiedReg) noexcept { _tiedReg = tiedReg; }
|
||||
inline void resetTiedReg() noexcept { _tiedReg = nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasTiedReg() const noexcept { return _tiedReg != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG RATiedReg* tiedReg() const noexcept { return _tiedReg; }
|
||||
ASMJIT_INLINE_NODEBUG void setTiedReg(RATiedReg* tiedReg) noexcept { _tiedReg = tiedReg; }
|
||||
ASMJIT_INLINE_NODEBUG void resetTiedReg() noexcept { _tiedReg = nullptr; }
|
||||
|
||||
inline bool hasStackSlot() const noexcept { return _stackSlot != nullptr; }
|
||||
inline RAStackSlot* stackSlot() const noexcept { return _stackSlot; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasStackSlot() const noexcept { return _stackSlot != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG RAStackSlot* stackSlot() const noexcept { return _stackSlot; }
|
||||
|
||||
inline LiveRegSpans& liveSpans() noexcept { return _liveSpans; }
|
||||
inline const LiveRegSpans& liveSpans() const noexcept { return _liveSpans; }
|
||||
ASMJIT_INLINE_NODEBUG LiveRegSpans& liveSpans() noexcept { return _liveSpans; }
|
||||
ASMJIT_INLINE_NODEBUG const LiveRegSpans& liveSpans() const noexcept { return _liveSpans; }
|
||||
|
||||
inline RALiveStats& liveStats() noexcept { return _liveStats; }
|
||||
inline const RALiveStats& liveStats() const noexcept { return _liveStats; }
|
||||
ASMJIT_INLINE_NODEBUG RALiveStats& liveStats() noexcept { return _liveStats; }
|
||||
ASMJIT_INLINE_NODEBUG const RALiveStats& liveStats() const noexcept { return _liveStats; }
|
||||
|
||||
inline bool hasArgIndex() const noexcept { return _argIndex != kNoArgIndex; }
|
||||
inline uint32_t argIndex() const noexcept { return _argIndex; }
|
||||
inline uint32_t argValueIndex() const noexcept { return _argValueIndex; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasArgIndex() const noexcept { return _argIndex != kNoArgIndex; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t argIndex() const noexcept { return _argIndex; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t argValueIndex() const noexcept { return _argValueIndex; }
|
||||
|
||||
inline void setArgIndex(uint32_t argIndex, uint32_t valueIndex) noexcept {
|
||||
_argIndex = uint8_t(argIndex);
|
||||
_argValueIndex = uint8_t(valueIndex);
|
||||
}
|
||||
|
||||
inline bool hasHomeRegId() const noexcept { return _homeRegId != BaseReg::kIdBad; }
|
||||
inline uint32_t homeRegId() const noexcept { return _homeRegId; }
|
||||
inline void setHomeRegId(uint32_t physId) noexcept { _homeRegId = uint8_t(physId); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasHomeRegId() const noexcept { return _homeRegId != BaseReg::kIdBad; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t homeRegId() const noexcept { return _homeRegId; }
|
||||
ASMJIT_INLINE_NODEBUG void setHomeRegId(uint32_t physId) noexcept { _homeRegId = uint8_t(physId); }
|
||||
|
||||
inline bool hasHintRegId() const noexcept { return _hintRegId != BaseReg::kIdBad; }
|
||||
inline uint32_t hintRegId() const noexcept { return _hintRegId; }
|
||||
inline void setHintRegId(uint32_t physId) noexcept { _hintRegId = uint8_t(physId); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasHintRegId() const noexcept { return _hintRegId != BaseReg::kIdBad; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t hintRegId() const noexcept { return _hintRegId; }
|
||||
ASMJIT_INLINE_NODEBUG void setHintRegId(uint32_t physId) noexcept { _hintRegId = uint8_t(physId); }
|
||||
|
||||
inline RegMask useIdMask() const noexcept { return _useIdMask; }
|
||||
inline bool hasUseIdMask() const noexcept { return _useIdMask != 0u; }
|
||||
inline bool hasMultipleUseIds() const noexcept { return _useIdMask != 0u && !Support::isPowerOf2(_useIdMask); }
|
||||
inline void addUseIdMask(RegMask mask) noexcept { _useIdMask |= mask; }
|
||||
ASMJIT_INLINE_NODEBUG RegMask useIdMask() const noexcept { return _useIdMask; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasUseIdMask() const noexcept { return _useIdMask != 0u; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasMultipleUseIds() const noexcept { return _useIdMask != 0u && !Support::isPowerOf2(_useIdMask); }
|
||||
ASMJIT_INLINE_NODEBUG void addUseIdMask(RegMask mask) noexcept { _useIdMask |= mask; }
|
||||
|
||||
inline RegMask preferredMask() const noexcept { return _preferredMask; }
|
||||
inline bool hasPrereffedMask() const noexcept { return _preferredMask != 0xFFFFFFFFu; }
|
||||
inline void restrictPreferredMask(RegMask mask) noexcept { _preferredMask &= mask; }
|
||||
ASMJIT_INLINE_NODEBUG RegMask preferredMask() const noexcept { return _preferredMask; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasPreferredMask() const noexcept { return _preferredMask != 0xFFFFFFFFu; }
|
||||
ASMJIT_INLINE_NODEBUG void restrictPreferredMask(RegMask mask) noexcept { _preferredMask &= mask; }
|
||||
|
||||
inline RegMask consecutiveMask() const noexcept { return _consecutiveMask; }
|
||||
inline bool hasConsecutiveMask() const noexcept { return _consecutiveMask != 0xFFFFFFFFu; }
|
||||
inline void restrictConsecutiveMask(RegMask mask) noexcept { _consecutiveMask &= mask; }
|
||||
ASMJIT_INLINE_NODEBUG RegMask consecutiveMask() const noexcept { return _consecutiveMask; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasConsecutiveMask() const noexcept { return _consecutiveMask != 0xFFFFFFFFu; }
|
||||
ASMJIT_INLINE_NODEBUG void restrictConsecutiveMask(RegMask mask) noexcept { _consecutiveMask &= mask; }
|
||||
|
||||
inline RegMask clobberSurvivalMask() const noexcept { return _clobberSurvivalMask; }
|
||||
inline void addClobberSurvivalMask(RegMask mask) noexcept { _clobberSurvivalMask |= mask; }
|
||||
ASMJIT_INLINE_NODEBUG RegMask clobberSurvivalMask() const noexcept { return _clobberSurvivalMask; }
|
||||
ASMJIT_INLINE_NODEBUG void addClobberSurvivalMask(RegMask mask) noexcept { _clobberSurvivalMask |= mask; }
|
||||
|
||||
inline RegMask allocatedMask() const noexcept { return _allocatedMask; }
|
||||
inline void addAllocatedMask(RegMask mask) noexcept { _allocatedMask |= mask; }
|
||||
ASMJIT_INLINE_NODEBUG RegMask allocatedMask() const noexcept { return _allocatedMask; }
|
||||
ASMJIT_INLINE_NODEBUG void addAllocatedMask(RegMask mask) noexcept { _allocatedMask |= mask; }
|
||||
|
||||
inline uint64_t regByteMask() const noexcept { return _regByteMask; }
|
||||
inline void setRegByteMask(uint64_t mask) noexcept { _regByteMask = mask; }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t regByteMask() const noexcept { return _regByteMask; }
|
||||
ASMJIT_INLINE_NODEBUG void setRegByteMask(uint64_t mask) noexcept { _regByteMask = mask; }
|
||||
|
||||
inline bool hasImmediateConsecutives() const noexcept { return !_immediateConsecutives.empty(); }
|
||||
inline const ZoneBitVector& immediateConsecutives() const noexcept { return _immediateConsecutives; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasImmediateConsecutives() const noexcept { return !_immediateConsecutives.empty(); }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneBitVector& immediateConsecutives() const noexcept { return _immediateConsecutives; }
|
||||
|
||||
inline Error addImmediateConsecutive(ZoneAllocator* allocator, uint32_t workId) noexcept {
|
||||
if (_immediateConsecutives.size() <= workId)
|
||||
|
||||
@@ -83,31 +83,31 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline RAWorkReg* workRegById(uint32_t workId) const noexcept { return _pass->workRegById(workId); }
|
||||
inline PhysToWorkMap* physToWorkMap() const noexcept { return _curAssignment.physToWorkMap(); }
|
||||
inline WorkToPhysMap* workToPhysMap() const noexcept { return _curAssignment.workToPhysMap(); }
|
||||
ASMJIT_INLINE_NODEBUG RAWorkReg* workRegById(uint32_t workId) const noexcept { return _pass->workRegById(workId); }
|
||||
ASMJIT_INLINE_NODEBUG PhysToWorkMap* physToWorkMap() const noexcept { return _curAssignment.physToWorkMap(); }
|
||||
ASMJIT_INLINE_NODEBUG WorkToPhysMap* workToPhysMap() const noexcept { return _curAssignment.workToPhysMap(); }
|
||||
|
||||
//! Returns the currently processed block.
|
||||
inline RABlock* block() const noexcept { return _block; }
|
||||
ASMJIT_INLINE_NODEBUG RABlock* block() const noexcept { return _block; }
|
||||
//! Sets the currently processed block.
|
||||
inline void setBlock(RABlock* block) noexcept { _block = block; }
|
||||
ASMJIT_INLINE_NODEBUG void setBlock(RABlock* block) noexcept { _block = block; }
|
||||
|
||||
//! Returns the currently processed `InstNode`.
|
||||
inline InstNode* node() const noexcept { return _node; }
|
||||
ASMJIT_INLINE_NODEBUG InstNode* node() const noexcept { return _node; }
|
||||
//! Returns the currently processed `RAInst`.
|
||||
inline RAInst* raInst() const noexcept { return _raInst; }
|
||||
ASMJIT_INLINE_NODEBUG RAInst* raInst() const noexcept { return _raInst; }
|
||||
|
||||
//! Returns all tied regs as `RATiedReg` array.
|
||||
inline RATiedReg* tiedRegs() const noexcept { return _raInst->tiedRegs(); }
|
||||
ASMJIT_INLINE_NODEBUG RATiedReg* tiedRegs() const noexcept { return _raInst->tiedRegs(); }
|
||||
//! Returns tied registers grouped by the given `group`.
|
||||
inline RATiedReg* tiedRegs(RegGroup group) const noexcept { return _raInst->tiedRegs(group); }
|
||||
ASMJIT_INLINE_NODEBUG RATiedReg* tiedRegs(RegGroup group) const noexcept { return _raInst->tiedRegs(group); }
|
||||
|
||||
//! Returns count of all TiedRegs used by the instruction.
|
||||
inline uint32_t tiedCount() const noexcept { return _tiedTotal; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t tiedCount() const noexcept { return _tiedTotal; }
|
||||
//! Returns count of TiedRegs used by the given register `group`.
|
||||
inline uint32_t tiedCount(RegGroup group) const noexcept { return _tiedCount.get(group); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t tiedCount(RegGroup group) const noexcept { return _tiedCount.get(group); }
|
||||
|
||||
inline bool isGroupUsed(RegGroup group) const noexcept { return _tiedCount[group] != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool isGroupUsed(RegGroup group) const noexcept { return _tiedCount[group] != 0; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -126,7 +126,7 @@ public:
|
||||
//! a code sequence that is always executed regardless of the flow.
|
||||
Error switchToAssignment(PhysToWorkMap* dstPhysToWorkMap, const ZoneBitVector& liveIn, bool dstReadOnly, bool tryMode) noexcept;
|
||||
|
||||
inline Error spillRegsBeforeEntry(RABlock* block) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error spillRegsBeforeEntry(RABlock* block) noexcept {
|
||||
return spillScratchGpRegsBeforeEntry(block->entryScratchGpRegs());
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ public:
|
||||
kCostOfDirtyFlag = kCostOfFrequency / 4
|
||||
};
|
||||
|
||||
inline uint32_t costByFrequency(float freq) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG uint32_t costByFrequency(float freq) const noexcept {
|
||||
return uint32_t(int32_t(freq * float(kCostOfFrequency)));
|
||||
}
|
||||
|
||||
|
||||
@@ -137,7 +137,7 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline RABlock(BaseRAPass* ra) noexcept
|
||||
ASMJIT_INLINE_NODEBUG RABlock(BaseRAPass* ra) noexcept
|
||||
: _ra(ra) {}
|
||||
|
||||
//! \}
|
||||
@@ -145,96 +145,96 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline BaseRAPass* pass() const noexcept { return _ra; }
|
||||
inline ZoneAllocator* allocator() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG BaseRAPass* pass() const noexcept { return _ra; }
|
||||
ASMJIT_INLINE_NODEBUG ZoneAllocator* allocator() const noexcept;
|
||||
|
||||
inline uint32_t blockId() const noexcept { return _blockId; }
|
||||
inline RABlockFlags flags() const noexcept { return _flags; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t blockId() const noexcept { return _blockId; }
|
||||
ASMJIT_INLINE_NODEBUG RABlockFlags flags() const noexcept { return _flags; }
|
||||
|
||||
inline bool hasFlag(RABlockFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
inline void addFlags(RABlockFlags flags) noexcept { _flags |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(RABlockFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG void addFlags(RABlockFlags flags) noexcept { _flags |= flags; }
|
||||
|
||||
inline bool isAssigned() const noexcept { return _blockId != kUnassignedId; }
|
||||
ASMJIT_INLINE_NODEBUG bool isAssigned() const noexcept { return _blockId != kUnassignedId; }
|
||||
|
||||
inline bool isConstructed() const noexcept { return hasFlag(RABlockFlags::kIsConstructed); }
|
||||
inline bool isReachable() const noexcept { return hasFlag(RABlockFlags::kIsReachable); }
|
||||
inline bool isTargetable() const noexcept { return hasFlag(RABlockFlags::kIsTargetable); }
|
||||
inline bool isAllocated() const noexcept { return hasFlag(RABlockFlags::kIsAllocated); }
|
||||
inline bool isFuncExit() const noexcept { return hasFlag(RABlockFlags::kIsFuncExit); }
|
||||
inline bool hasTerminator() const noexcept { return hasFlag(RABlockFlags::kHasTerminator); }
|
||||
inline bool hasConsecutive() const noexcept { return hasFlag(RABlockFlags::kHasConsecutive); }
|
||||
inline bool hasJumpTable() const noexcept { return hasFlag(RABlockFlags::kHasJumpTable); }
|
||||
ASMJIT_INLINE_NODEBUG bool isConstructed() const noexcept { return hasFlag(RABlockFlags::kIsConstructed); }
|
||||
ASMJIT_INLINE_NODEBUG bool isReachable() const noexcept { return hasFlag(RABlockFlags::kIsReachable); }
|
||||
ASMJIT_INLINE_NODEBUG bool isTargetable() const noexcept { return hasFlag(RABlockFlags::kIsTargetable); }
|
||||
ASMJIT_INLINE_NODEBUG bool isAllocated() const noexcept { return hasFlag(RABlockFlags::kIsAllocated); }
|
||||
ASMJIT_INLINE_NODEBUG bool isFuncExit() const noexcept { return hasFlag(RABlockFlags::kIsFuncExit); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasTerminator() const noexcept { return hasFlag(RABlockFlags::kHasTerminator); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasConsecutive() const noexcept { return hasFlag(RABlockFlags::kHasConsecutive); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasJumpTable() const noexcept { return hasFlag(RABlockFlags::kHasJumpTable); }
|
||||
|
||||
inline void makeConstructed(const RARegsStats& regStats) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void makeConstructed(const RARegsStats& regStats) noexcept {
|
||||
_flags |= RABlockFlags::kIsConstructed;
|
||||
_regsStats.combineWith(regStats);
|
||||
}
|
||||
|
||||
inline void makeReachable() noexcept { _flags |= RABlockFlags::kIsReachable; }
|
||||
inline void makeTargetable() noexcept { _flags |= RABlockFlags::kIsTargetable; }
|
||||
inline void makeAllocated() noexcept { _flags |= RABlockFlags::kIsAllocated; }
|
||||
ASMJIT_INLINE_NODEBUG void makeReachable() noexcept { _flags |= RABlockFlags::kIsReachable; }
|
||||
ASMJIT_INLINE_NODEBUG void makeTargetable() noexcept { _flags |= RABlockFlags::kIsTargetable; }
|
||||
ASMJIT_INLINE_NODEBUG void makeAllocated() noexcept { _flags |= RABlockFlags::kIsAllocated; }
|
||||
|
||||
inline const RARegsStats& regsStats() const noexcept { return _regsStats; }
|
||||
ASMJIT_INLINE_NODEBUG const RARegsStats& regsStats() const noexcept { return _regsStats; }
|
||||
|
||||
inline bool hasPredecessors() const noexcept { return !_predecessors.empty(); }
|
||||
inline bool hasSuccessors() const noexcept { return !_successors.empty(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasPredecessors() const noexcept { return !_predecessors.empty(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasSuccessors() const noexcept { return !_successors.empty(); }
|
||||
|
||||
inline bool hasSuccessor(RABlock* block) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool hasSuccessor(RABlock* block) noexcept {
|
||||
if (block->_predecessors.size() < _successors.size())
|
||||
return block->_predecessors.contains(this);
|
||||
else
|
||||
return _successors.contains(block);
|
||||
}
|
||||
|
||||
inline const RABlocks& predecessors() const noexcept { return _predecessors; }
|
||||
inline const RABlocks& successors() const noexcept { return _successors; }
|
||||
ASMJIT_INLINE_NODEBUG const RABlocks& predecessors() const noexcept { return _predecessors; }
|
||||
ASMJIT_INLINE_NODEBUG const RABlocks& successors() const noexcept { return _successors; }
|
||||
|
||||
inline BaseNode* first() const noexcept { return _first; }
|
||||
inline BaseNode* last() const noexcept { return _last; }
|
||||
ASMJIT_INLINE_NODEBUG BaseNode* first() const noexcept { return _first; }
|
||||
ASMJIT_INLINE_NODEBUG BaseNode* last() const noexcept { return _last; }
|
||||
|
||||
inline void setFirst(BaseNode* node) noexcept { _first = node; }
|
||||
inline void setLast(BaseNode* node) noexcept { _last = node; }
|
||||
ASMJIT_INLINE_NODEBUG void setFirst(BaseNode* node) noexcept { _first = node; }
|
||||
ASMJIT_INLINE_NODEBUG void setLast(BaseNode* node) noexcept { _last = node; }
|
||||
|
||||
inline uint32_t firstPosition() const noexcept { return _firstPosition; }
|
||||
inline void setFirstPosition(uint32_t position) noexcept { _firstPosition = position; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t firstPosition() const noexcept { return _firstPosition; }
|
||||
ASMJIT_INLINE_NODEBUG void setFirstPosition(uint32_t position) noexcept { _firstPosition = position; }
|
||||
|
||||
inline uint32_t endPosition() const noexcept { return _endPosition; }
|
||||
inline void setEndPosition(uint32_t position) noexcept { _endPosition = position; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t endPosition() const noexcept { return _endPosition; }
|
||||
ASMJIT_INLINE_NODEBUG void setEndPosition(uint32_t position) noexcept { _endPosition = position; }
|
||||
|
||||
inline uint32_t povOrder() const noexcept { return _povOrder; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t povOrder() const noexcept { return _povOrder; }
|
||||
|
||||
inline RegMask entryScratchGpRegs() const noexcept;
|
||||
inline RegMask exitScratchGpRegs() const noexcept { return _exitScratchGpRegs; }
|
||||
ASMJIT_INLINE_NODEBUG RegMask entryScratchGpRegs() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG RegMask exitScratchGpRegs() const noexcept { return _exitScratchGpRegs; }
|
||||
|
||||
inline void addEntryScratchGpRegs(RegMask regMask) noexcept { _entryScratchGpRegs |= regMask; }
|
||||
inline void addExitScratchGpRegs(RegMask regMask) noexcept { _exitScratchGpRegs |= regMask; }
|
||||
ASMJIT_INLINE_NODEBUG void addEntryScratchGpRegs(RegMask regMask) noexcept { _entryScratchGpRegs |= regMask; }
|
||||
ASMJIT_INLINE_NODEBUG void addExitScratchGpRegs(RegMask regMask) noexcept { _exitScratchGpRegs |= regMask; }
|
||||
|
||||
inline bool hasSharedAssignmentId() const noexcept { return _sharedAssignmentId != Globals::kInvalidId; }
|
||||
inline uint32_t sharedAssignmentId() const noexcept { return _sharedAssignmentId; }
|
||||
inline void setSharedAssignmentId(uint32_t id) noexcept { _sharedAssignmentId = id; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasSharedAssignmentId() const noexcept { return _sharedAssignmentId != Globals::kInvalidId; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t sharedAssignmentId() const noexcept { return _sharedAssignmentId; }
|
||||
ASMJIT_INLINE_NODEBUG void setSharedAssignmentId(uint32_t id) noexcept { _sharedAssignmentId = id; }
|
||||
|
||||
inline uint64_t timestamp() const noexcept { return _timestamp; }
|
||||
inline bool hasTimestamp(uint64_t ts) const noexcept { return _timestamp == ts; }
|
||||
inline void setTimestamp(uint64_t ts) const noexcept { _timestamp = ts; }
|
||||
inline void resetTimestamp() const noexcept { _timestamp = 0; }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t timestamp() const noexcept { return _timestamp; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasTimestamp(uint64_t ts) const noexcept { return _timestamp == ts; }
|
||||
ASMJIT_INLINE_NODEBUG void setTimestamp(uint64_t ts) const noexcept { _timestamp = ts; }
|
||||
ASMJIT_INLINE_NODEBUG void resetTimestamp() const noexcept { _timestamp = 0; }
|
||||
|
||||
inline RABlock* consecutive() const noexcept { return hasConsecutive() ? _successors[0] : nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG RABlock* consecutive() const noexcept { return hasConsecutive() ? _successors[0] : nullptr; }
|
||||
|
||||
inline RABlock* iDom() noexcept { return _idom; }
|
||||
inline const RABlock* iDom() const noexcept { return _idom; }
|
||||
inline void setIDom(RABlock* block) noexcept { _idom = block; }
|
||||
ASMJIT_INLINE_NODEBUG RABlock* iDom() noexcept { return _idom; }
|
||||
ASMJIT_INLINE_NODEBUG const RABlock* iDom() const noexcept { return _idom; }
|
||||
ASMJIT_INLINE_NODEBUG void setIDom(RABlock* block) noexcept { _idom = block; }
|
||||
|
||||
inline ZoneBitVector& liveIn() noexcept { return _liveBits[kLiveIn]; }
|
||||
inline const ZoneBitVector& liveIn() const noexcept { return _liveBits[kLiveIn]; }
|
||||
ASMJIT_INLINE_NODEBUG ZoneBitVector& liveIn() noexcept { return _liveBits[kLiveIn]; }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneBitVector& liveIn() const noexcept { return _liveBits[kLiveIn]; }
|
||||
|
||||
inline ZoneBitVector& liveOut() noexcept { return _liveBits[kLiveOut]; }
|
||||
inline const ZoneBitVector& liveOut() const noexcept { return _liveBits[kLiveOut]; }
|
||||
ASMJIT_INLINE_NODEBUG ZoneBitVector& liveOut() noexcept { return _liveBits[kLiveOut]; }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneBitVector& liveOut() const noexcept { return _liveBits[kLiveOut]; }
|
||||
|
||||
inline ZoneBitVector& gen() noexcept { return _liveBits[kLiveGen]; }
|
||||
inline const ZoneBitVector& gen() const noexcept { return _liveBits[kLiveGen]; }
|
||||
ASMJIT_INLINE_NODEBUG ZoneBitVector& gen() noexcept { return _liveBits[kLiveGen]; }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneBitVector& gen() const noexcept { return _liveBits[kLiveGen]; }
|
||||
|
||||
inline ZoneBitVector& kill() noexcept { return _liveBits[kLiveKill]; }
|
||||
inline const ZoneBitVector& kill() const noexcept { return _liveBits[kLiveKill]; }
|
||||
ASMJIT_INLINE_NODEBUG ZoneBitVector& kill() noexcept { return _liveBits[kLiveKill]; }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneBitVector& kill() const noexcept { return _liveBits[kLiveKill]; }
|
||||
|
||||
inline Error resizeLiveBits(uint32_t size) noexcept {
|
||||
ASMJIT_PROPAGATE(_liveBits[kLiveIn ].resize(allocator(), size));
|
||||
@@ -244,9 +244,9 @@ public:
|
||||
return kErrorOk;
|
||||
}
|
||||
|
||||
inline bool hasEntryAssignment() const noexcept { return _entryPhysToWorkMap != nullptr; }
|
||||
inline PhysToWorkMap* entryPhysToWorkMap() const noexcept { return _entryPhysToWorkMap; }
|
||||
inline void setEntryAssignment(PhysToWorkMap* physToWorkMap) noexcept { _entryPhysToWorkMap = physToWorkMap; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasEntryAssignment() const noexcept { return _entryPhysToWorkMap != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG PhysToWorkMap* entryPhysToWorkMap() const noexcept { return _entryPhysToWorkMap; }
|
||||
ASMJIT_INLINE_NODEBUG void setEntryAssignment(PhysToWorkMap* physToWorkMap) noexcept { _entryPhysToWorkMap = physToWorkMap; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -318,38 +318,38 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns instruction RW flags.
|
||||
inline InstRWFlags instRWFlags() const noexcept { return _instRWFlags; };
|
||||
ASMJIT_INLINE_NODEBUG InstRWFlags instRWFlags() const noexcept { return _instRWFlags; };
|
||||
//! Tests whether the given `flag` is present in instruction RW flags.
|
||||
inline bool hasInstRWFlag(InstRWFlags flag) const noexcept { return Support::test(_instRWFlags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasInstRWFlag(InstRWFlags flag) const noexcept { return Support::test(_instRWFlags, flag); }
|
||||
//! Adds `flags` to instruction RW flags.
|
||||
inline void addInstRWFlags(InstRWFlags flags) noexcept { _instRWFlags |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG void addInstRWFlags(InstRWFlags flags) noexcept { _instRWFlags |= flags; }
|
||||
|
||||
//! Returns the instruction flags.
|
||||
inline RATiedFlags flags() const noexcept { return _flags; }
|
||||
ASMJIT_INLINE_NODEBUG RATiedFlags flags() const noexcept { return _flags; }
|
||||
//! Tests whether the instruction has flag `flag`.
|
||||
inline bool hasFlag(RATiedFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(RATiedFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
//! Replaces the existing instruction flags with `flags`.
|
||||
inline void setFlags(RATiedFlags flags) noexcept { _flags = flags; }
|
||||
ASMJIT_INLINE_NODEBUG void setFlags(RATiedFlags flags) noexcept { _flags = flags; }
|
||||
//! Adds instruction `flags` to this RAInst.
|
||||
inline void addFlags(RATiedFlags flags) noexcept { _flags |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG void addFlags(RATiedFlags flags) noexcept { _flags |= flags; }
|
||||
//! Clears instruction `flags` from this RAInst.
|
||||
inline void clearFlags(RATiedFlags flags) noexcept { _flags &= ~flags; }
|
||||
ASMJIT_INLINE_NODEBUG void clearFlags(RATiedFlags flags) noexcept { _flags &= ~flags; }
|
||||
|
||||
//! Tests whether this instruction can be transformed to another instruction if necessary.
|
||||
inline bool isTransformable() const noexcept { return hasFlag(RATiedFlags::kInst_IsTransformable); }
|
||||
ASMJIT_INLINE_NODEBUG bool isTransformable() const noexcept { return hasFlag(RATiedFlags::kInst_IsTransformable); }
|
||||
|
||||
//! Returns the associated block with this RAInst.
|
||||
inline RABlock* block() const noexcept { return _block; }
|
||||
ASMJIT_INLINE_NODEBUG RABlock* block() const noexcept { return _block; }
|
||||
|
||||
//! Returns tied registers (all).
|
||||
inline RATiedReg* tiedRegs() const noexcept { return const_cast<RATiedReg*>(_tiedRegs); }
|
||||
ASMJIT_INLINE_NODEBUG RATiedReg* tiedRegs() const noexcept { return const_cast<RATiedReg*>(_tiedRegs); }
|
||||
//! Returns tied registers for a given `group`.
|
||||
inline RATiedReg* tiedRegs(RegGroup group) const noexcept { return const_cast<RATiedReg*>(_tiedRegs) + _tiedIndex.get(group); }
|
||||
ASMJIT_INLINE_NODEBUG RATiedReg* tiedRegs(RegGroup group) const noexcept { return const_cast<RATiedReg*>(_tiedRegs) + _tiedIndex.get(group); }
|
||||
|
||||
//! Returns count of all tied registers.
|
||||
inline uint32_t tiedCount() const noexcept { return _tiedTotal; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t tiedCount() const noexcept { return _tiedTotal; }
|
||||
//! Returns count of tied registers of a given `group`.
|
||||
inline uint32_t tiedCount(RegGroup group) const noexcept { return _tiedCount[group]; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t tiedCount(RegGroup group) const noexcept { return _tiedCount[group]; }
|
||||
|
||||
//! Returns `RATiedReg` at the given `index`.
|
||||
inline RATiedReg* tiedAt(uint32_t index) const noexcept {
|
||||
@@ -371,7 +371,7 @@ public:
|
||||
//! \name Static Functions
|
||||
//! \{
|
||||
|
||||
static inline size_t sizeOf(uint32_t tiedRegCount) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG size_t sizeOf(uint32_t tiedRegCount) noexcept {
|
||||
return sizeof(RAInst) - sizeof(RATiedReg) + tiedRegCount * sizeof(RATiedReg);
|
||||
}
|
||||
|
||||
@@ -409,10 +409,10 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline RAInstBuilder() noexcept { reset(); }
|
||||
ASMJIT_INLINE_NODEBUG RAInstBuilder() noexcept { reset(); }
|
||||
|
||||
inline void init() noexcept { reset(); }
|
||||
inline void reset() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void init() noexcept { reset(); }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept {
|
||||
_instRWFlags = InstRWFlags::kNone;
|
||||
_aggregatedFlags = RATiedFlags::kNone;
|
||||
_forbiddenFlags = RATiedFlags::kNone;
|
||||
@@ -428,25 +428,25 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline InstRWFlags instRWFlags() const noexcept { return _instRWFlags; }
|
||||
inline bool hasInstRWFlag(InstRWFlags flag) const noexcept { return Support::test(_instRWFlags, flag); }
|
||||
inline void addInstRWFlags(InstRWFlags flags) noexcept { _instRWFlags |= flags; }
|
||||
inline void clearInstRWFlags(InstRWFlags flags) noexcept { _instRWFlags &= ~flags; }
|
||||
ASMJIT_INLINE_NODEBUG InstRWFlags instRWFlags() const noexcept { return _instRWFlags; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasInstRWFlag(InstRWFlags flag) const noexcept { return Support::test(_instRWFlags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG void addInstRWFlags(InstRWFlags flags) noexcept { _instRWFlags |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG void clearInstRWFlags(InstRWFlags flags) noexcept { _instRWFlags &= ~flags; }
|
||||
|
||||
inline RATiedFlags aggregatedFlags() const noexcept { return _aggregatedFlags; }
|
||||
inline void addAggregatedFlags(RATiedFlags flags) noexcept { _aggregatedFlags |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG RATiedFlags aggregatedFlags() const noexcept { return _aggregatedFlags; }
|
||||
ASMJIT_INLINE_NODEBUG void addAggregatedFlags(RATiedFlags flags) noexcept { _aggregatedFlags |= flags; }
|
||||
|
||||
inline RATiedFlags forbiddenFlags() const noexcept { return _forbiddenFlags; }
|
||||
inline void addForbiddenFlags(RATiedFlags flags) noexcept { _forbiddenFlags |= flags; }
|
||||
ASMJIT_INLINE_NODEBUG RATiedFlags forbiddenFlags() const noexcept { return _forbiddenFlags; }
|
||||
ASMJIT_INLINE_NODEBUG void addForbiddenFlags(RATiedFlags flags) noexcept { _forbiddenFlags |= flags; }
|
||||
|
||||
//! Returns the number of tied registers added to the builder.
|
||||
inline uint32_t tiedRegCount() const noexcept { return uint32_t((size_t)(_cur - _tiedRegs)); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t tiedRegCount() const noexcept { return uint32_t((size_t)(_cur - _tiedRegs)); }
|
||||
|
||||
inline RATiedReg* begin() noexcept { return _tiedRegs; }
|
||||
inline RATiedReg* end() noexcept { return _cur; }
|
||||
ASMJIT_INLINE_NODEBUG RATiedReg* begin() noexcept { return _tiedRegs; }
|
||||
ASMJIT_INLINE_NODEBUG RATiedReg* end() noexcept { return _cur; }
|
||||
|
||||
inline const RATiedReg* begin() const noexcept { return _tiedRegs; }
|
||||
inline const RATiedReg* end() const noexcept { return _cur; }
|
||||
ASMJIT_INLINE_NODEBUG const RATiedReg* begin() const noexcept { return _tiedRegs; }
|
||||
ASMJIT_INLINE_NODEBUG const RATiedReg* end() const noexcept { return _cur; }
|
||||
|
||||
//! Returns `RATiedReg` at the given `index`.
|
||||
inline RATiedReg* operator[](uint32_t index) noexcept {
|
||||
@@ -634,15 +634,15 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline bool empty() const noexcept { return _physToWorkMap == nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _physToWorkMap == nullptr; }
|
||||
|
||||
inline RegMask entryScratchGpRegs() const noexcept { return _entryScratchGpRegs; }
|
||||
inline void addEntryScratchGpRegs(RegMask mask) noexcept { _entryScratchGpRegs |= mask; }
|
||||
ASMJIT_INLINE_NODEBUG RegMask entryScratchGpRegs() const noexcept { return _entryScratchGpRegs; }
|
||||
ASMJIT_INLINE_NODEBUG void addEntryScratchGpRegs(RegMask mask) noexcept { _entryScratchGpRegs |= mask; }
|
||||
|
||||
inline const ZoneBitVector& liveIn() const noexcept { return _liveIn; }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneBitVector& liveIn() const noexcept { return _liveIn; }
|
||||
|
||||
inline PhysToWorkMap* physToWorkMap() const noexcept { return _physToWorkMap; }
|
||||
inline void assignPhysToWorkMap(PhysToWorkMap* physToWorkMap) noexcept { _physToWorkMap = physToWorkMap; }
|
||||
ASMJIT_INLINE_NODEBUG PhysToWorkMap* physToWorkMap() const noexcept { return _physToWorkMap; }
|
||||
ASMJIT_INLINE_NODEBUG void assignPhysToWorkMap(PhysToWorkMap* physToWorkMap) noexcept { _physToWorkMap = physToWorkMap; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -762,38 +762,38 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns \ref Logger passed to \ref runOnFunction().
|
||||
inline Logger* logger() const noexcept { return _logger; }
|
||||
ASMJIT_INLINE_NODEBUG Logger* logger() const noexcept { return _logger; }
|
||||
|
||||
//! Returns either a valid logger if the given `option` is set and logging is enabled, or nullptr.
|
||||
inline Logger* getLoggerIf(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option) ? _logger : nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG Logger* getLoggerIf(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option) ? _logger : nullptr; }
|
||||
|
||||
//! Returns whether the diagnostic `option` is enabled.
|
||||
//!
|
||||
//! \note Returns false if there is no logger (as diagnostics without logging make no sense).
|
||||
inline bool hasDiagnosticOption(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasDiagnosticOption(DiagnosticOptions option) const noexcept { return Support::test(_diagnosticOptions, option); }
|
||||
|
||||
//! Returns \ref Zone passed to \ref runOnFunction().
|
||||
inline Zone* zone() const noexcept { return _allocator.zone(); }
|
||||
ASMJIT_INLINE_NODEBUG Zone* zone() const noexcept { return _allocator.zone(); }
|
||||
//! Returns \ref ZoneAllocator used by the register allocator.
|
||||
inline ZoneAllocator* allocator() const noexcept { return const_cast<ZoneAllocator*>(&_allocator); }
|
||||
ASMJIT_INLINE_NODEBUG ZoneAllocator* allocator() const noexcept { return const_cast<ZoneAllocator*>(&_allocator); }
|
||||
|
||||
inline const ZoneVector<RASharedAssignment>& sharedAssignments() const { return _sharedAssignments; }
|
||||
inline uint32_t sharedAssignmentCount() const noexcept { return _sharedAssignments.size(); }
|
||||
ASMJIT_INLINE_NODEBUG const ZoneVector<RASharedAssignment>& sharedAssignments() const { return _sharedAssignments; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t sharedAssignmentCount() const noexcept { return _sharedAssignments.size(); }
|
||||
|
||||
//! Returns the current function node.
|
||||
inline FuncNode* func() const noexcept { return _func; }
|
||||
ASMJIT_INLINE_NODEBUG FuncNode* func() const noexcept { return _func; }
|
||||
//! Returns the stop of the current function.
|
||||
inline BaseNode* stop() const noexcept { return _stop; }
|
||||
ASMJIT_INLINE_NODEBUG BaseNode* stop() const noexcept { return _stop; }
|
||||
|
||||
//! Returns an extra block used by the current function being processed.
|
||||
inline BaseNode* extraBlock() const noexcept { return _extraBlock; }
|
||||
ASMJIT_INLINE_NODEBUG BaseNode* extraBlock() const noexcept { return _extraBlock; }
|
||||
//! Sets an extra block, see `extraBlock()`.
|
||||
inline void setExtraBlock(BaseNode* node) noexcept { _extraBlock = node; }
|
||||
ASMJIT_INLINE_NODEBUG void setExtraBlock(BaseNode* node) noexcept { _extraBlock = node; }
|
||||
|
||||
inline uint32_t endPosition() const noexcept { return _instructionCount * 2; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t endPosition() const noexcept { return _instructionCount * 2; }
|
||||
|
||||
inline const RARegMask& availableRegs() const noexcept { return _availableRegs; }
|
||||
inline const RARegMask& cloberredRegs() const noexcept { return _clobberedRegs; }
|
||||
ASMJIT_INLINE_NODEBUG const RARegMask& availableRegs() const noexcept { return _availableRegs; }
|
||||
ASMJIT_INLINE_NODEBUG const RARegMask& cloberredRegs() const noexcept { return _clobberedRegs; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -842,26 +842,26 @@ public:
|
||||
}
|
||||
|
||||
//! Returns all basic blocks of this function.
|
||||
inline RABlocks& blocks() noexcept { return _blocks; }
|
||||
ASMJIT_INLINE_NODEBUG RABlocks& blocks() noexcept { return _blocks; }
|
||||
//! \overload
|
||||
inline const RABlocks& blocks() const noexcept { return _blocks; }
|
||||
ASMJIT_INLINE_NODEBUG const RABlocks& blocks() const noexcept { return _blocks; }
|
||||
|
||||
//! Returns the count of basic blocks (returns size of `_blocks` array).
|
||||
inline uint32_t blockCount() const noexcept { return _blocks.size(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t blockCount() const noexcept { return _blocks.size(); }
|
||||
//! Returns the count of reachable basic blocks (returns size of `_pov` array).
|
||||
inline uint32_t reachableBlockCount() const noexcept { return _pov.size(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t reachableBlockCount() const noexcept { return _pov.size(); }
|
||||
|
||||
//! Tests whether the CFG has dangling blocks - these were created by `newBlock()`, but not added to CFG through
|
||||
//! `addBlocks()`. If `true` is returned and the CFG is constructed it means that something is missing and it's
|
||||
//! incomplete.
|
||||
//!
|
||||
//! \note This is only used to check if the number of created blocks matches the number of added blocks.
|
||||
inline bool hasDanglingBlocks() const noexcept { return _createdBlockCount != blockCount(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasDanglingBlocks() const noexcept { return _createdBlockCount != blockCount(); }
|
||||
|
||||
//! Gest a next timestamp to be used to mark CFG blocks.
|
||||
inline uint64_t nextTimestamp() const noexcept { return ++_lastTimestamp; }
|
||||
ASMJIT_INLINE_NODEBUG uint64_t nextTimestamp() const noexcept { return ++_lastTimestamp; }
|
||||
|
||||
//! Createss a new `RABlock` instance.
|
||||
//! Creates a new `RABlock` instance.
|
||||
//!
|
||||
//! \note New blocks don't have ID assigned until they are added to the block array by calling `addBlock()`.
|
||||
RABlock* newBlock(BaseNode* initialNode = nullptr) noexcept;
|
||||
@@ -974,14 +974,14 @@ public:
|
||||
const RABlock* _nearestCommonDominator(const RABlock* a, const RABlock* b) const noexcept;
|
||||
|
||||
//! Tests whether the basic block `a` dominates `b` - non-strict, returns true when `a == b`.
|
||||
inline bool dominates(const RABlock* a, const RABlock* b) const noexcept { return a == b ? true : _strictlyDominates(a, b); }
|
||||
ASMJIT_INLINE_NODEBUG bool dominates(const RABlock* a, const RABlock* b) const noexcept { return a == b ? true : _strictlyDominates(a, b); }
|
||||
//! Tests whether the basic block `a` dominates `b` - strict dominance check, returns false when `a == b`.
|
||||
inline bool strictlyDominates(const RABlock* a, const RABlock* b) const noexcept { return a == b ? false : _strictlyDominates(a, b); }
|
||||
ASMJIT_INLINE_NODEBUG bool strictlyDominates(const RABlock* a, const RABlock* b) const noexcept { return a == b ? false : _strictlyDominates(a, b); }
|
||||
|
||||
//! Returns a nearest common dominator of `a` and `b`.
|
||||
inline RABlock* nearestCommonDominator(RABlock* a, RABlock* b) const noexcept { return const_cast<RABlock*>(_nearestCommonDominator(a, b)); }
|
||||
ASMJIT_INLINE_NODEBUG RABlock* nearestCommonDominator(RABlock* a, RABlock* b) const noexcept { return const_cast<RABlock*>(_nearestCommonDominator(a, b)); }
|
||||
//! Returns a nearest common dominator of `a` and `b` (const).
|
||||
inline const RABlock* nearestCommonDominator(const RABlock* a, const RABlock* b) const noexcept { return _nearestCommonDominator(a, b); }
|
||||
ASMJIT_INLINE_NODEBUG const RABlock* nearestCommonDominator(const RABlock* a, const RABlock* b) const noexcept { return _nearestCommonDominator(a, b); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -1005,27 +1005,27 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns a native size of the general-purpose register of the target architecture.
|
||||
inline uint32_t registerSize() const noexcept { return _sp.size(); }
|
||||
inline uint32_t availableRegCount(RegGroup group) const noexcept { return _availableRegCount[group]; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t registerSize() const noexcept { return _sp.size(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t availableRegCount(RegGroup group) const noexcept { return _availableRegCount[group]; }
|
||||
|
||||
inline RAWorkReg* workRegById(uint32_t workId) const noexcept { return _workRegs[workId]; }
|
||||
ASMJIT_INLINE_NODEBUG RAWorkReg* workRegById(uint32_t workId) const noexcept { return _workRegs[workId]; }
|
||||
|
||||
inline RAWorkRegs& workRegs() noexcept { return _workRegs; }
|
||||
inline RAWorkRegs& workRegs(RegGroup group) noexcept { return _workRegsOfGroup[group]; }
|
||||
ASMJIT_INLINE_NODEBUG RAWorkRegs& workRegs() noexcept { return _workRegs; }
|
||||
ASMJIT_INLINE_NODEBUG RAWorkRegs& workRegs(RegGroup group) noexcept { return _workRegsOfGroup[group]; }
|
||||
|
||||
inline const RAWorkRegs& workRegs() const noexcept { return _workRegs; }
|
||||
inline const RAWorkRegs& workRegs(RegGroup group) const noexcept { return _workRegsOfGroup[group]; }
|
||||
ASMJIT_INLINE_NODEBUG const RAWorkRegs& workRegs() const noexcept { return _workRegs; }
|
||||
ASMJIT_INLINE_NODEBUG const RAWorkRegs& workRegs(RegGroup group) const noexcept { return _workRegsOfGroup[group]; }
|
||||
|
||||
inline uint32_t workRegCount() const noexcept { return _workRegs.size(); }
|
||||
inline uint32_t workRegCount(RegGroup group) const noexcept { return _workRegsOfGroup[group].size(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t workRegCount() const noexcept { return _workRegs.size(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t workRegCount(RegGroup group) const noexcept { return _workRegsOfGroup[group].size(); }
|
||||
|
||||
inline void _buildPhysIndex() noexcept {
|
||||
_physRegIndex.buildIndexes(_physRegCount);
|
||||
_physRegTotal = uint32_t(_physRegIndex[RegGroup::kMaxVirt]) +
|
||||
uint32_t(_physRegCount[RegGroup::kMaxVirt]) ;
|
||||
}
|
||||
inline uint32_t physRegIndex(RegGroup group) const noexcept { return _physRegIndex[group]; }
|
||||
inline uint32_t physRegTotal() const noexcept { return _physRegTotal; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t physRegIndex(RegGroup group) const noexcept { return _physRegIndex[group]; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t physRegTotal() const noexcept { return _physRegTotal; }
|
||||
|
||||
Error _asWorkReg(VirtReg* vReg, RAWorkReg** out) noexcept;
|
||||
|
||||
|
||||
@@ -104,13 +104,13 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Allocator used to allocate internal data.
|
||||
ZoneAllocator* _allocator;
|
||||
ZoneAllocator* _allocator {};
|
||||
//! Count of bytes used by all slots.
|
||||
uint32_t _bytesUsed;
|
||||
uint32_t _bytesUsed {};
|
||||
//! Calculated stack size (can be a bit greater than `_bytesUsed`).
|
||||
uint32_t _stackSize;
|
||||
uint32_t _stackSize {};
|
||||
//! Minimum stack alignment.
|
||||
uint32_t _alignment;
|
||||
uint32_t _alignment = 1;
|
||||
//! Stack slots vector.
|
||||
RAStackSlots _slots;
|
||||
|
||||
@@ -119,14 +119,9 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline RAStackAllocator() noexcept
|
||||
: _allocator(nullptr),
|
||||
_bytesUsed(0),
|
||||
_stackSize(0),
|
||||
_alignment(1),
|
||||
_slots() {}
|
||||
ASMJIT_INLINE_NODEBUG RAStackAllocator() noexcept {}
|
||||
|
||||
inline void reset(ZoneAllocator* allocator) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void reset(ZoneAllocator* allocator) noexcept {
|
||||
_allocator = allocator;
|
||||
_bytesUsed = 0;
|
||||
_stackSize = 0;
|
||||
@@ -139,15 +134,15 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline ZoneAllocator* allocator() const noexcept { return _allocator; }
|
||||
ASMJIT_INLINE_NODEBUG ZoneAllocator* allocator() const noexcept { return _allocator; }
|
||||
|
||||
inline uint32_t bytesUsed() const noexcept { return _bytesUsed; }
|
||||
inline uint32_t stackSize() const noexcept { return _stackSize; }
|
||||
inline uint32_t alignment() const noexcept { return _alignment; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t bytesUsed() const noexcept { return _bytesUsed; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t stackSize() const noexcept { return _stackSize; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t alignment() const noexcept { return _alignment; }
|
||||
|
||||
inline RAStackSlots& slots() noexcept { return _slots; }
|
||||
inline const RAStackSlots& slots() const noexcept { return _slots; }
|
||||
inline uint32_t slotCount() const noexcept { return _slots.size(); }
|
||||
ASMJIT_INLINE_NODEBUG RAStackSlots& slots() noexcept { return _slots; }
|
||||
ASMJIT_INLINE_NODEBUG const RAStackSlots& slots() const noexcept { return _slots; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t slotCount() const noexcept { return _slots.size(); }
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
@@ -131,16 +131,16 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a default-initialized string if zero length.
|
||||
inline String() noexcept
|
||||
ASMJIT_INLINE_NODEBUG String() noexcept
|
||||
: _small {} {}
|
||||
|
||||
//! Creates a string that takes ownership of the content of the `other` string.
|
||||
inline String(String&& other) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG String(String&& other) noexcept {
|
||||
_raw = other._raw;
|
||||
other._resetInternal();
|
||||
}
|
||||
|
||||
inline ~String() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG ~String() noexcept {
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -158,37 +158,37 @@ public:
|
||||
return *this;
|
||||
}
|
||||
|
||||
inline bool operator==(const char* other) const noexcept { return eq(other); }
|
||||
inline bool operator!=(const char* other) const noexcept { return !eq(other); }
|
||||
ASMJIT_INLINE_NODEBUG bool operator==(const char* other) const noexcept { return eq(other); }
|
||||
ASMJIT_INLINE_NODEBUG bool operator!=(const char* other) const noexcept { return !eq(other); }
|
||||
|
||||
inline bool operator==(const String& other) const noexcept { return eq(other); }
|
||||
inline bool operator!=(const String& other) const noexcept { return !eq(other); }
|
||||
ASMJIT_INLINE_NODEBUG bool operator==(const String& other) const noexcept { return eq(other); }
|
||||
ASMJIT_INLINE_NODEBUG bool operator!=(const String& other) const noexcept { return !eq(other); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline bool isExternal() const noexcept { return _type == kTypeExternal; }
|
||||
inline bool isLargeOrExternal() const noexcept { return _type >= kTypeLarge; }
|
||||
ASMJIT_INLINE_NODEBUG bool isExternal() const noexcept { return _type == kTypeExternal; }
|
||||
ASMJIT_INLINE_NODEBUG bool isLargeOrExternal() const noexcept { return _type >= kTypeLarge; }
|
||||
|
||||
//! Tests whether the string is empty.
|
||||
inline bool empty() const noexcept { return size() == 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return size() == 0; }
|
||||
//! Returns the size of the string.
|
||||
inline size_t size() const noexcept { return isLargeOrExternal() ? size_t(_large.size) : size_t(_type); }
|
||||
ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return isLargeOrExternal() ? size_t(_large.size) : size_t(_type); }
|
||||
//! Returns the capacity of the string.
|
||||
inline size_t capacity() const noexcept { return isLargeOrExternal() ? _large.capacity : size_t(kSSOCapacity); }
|
||||
ASMJIT_INLINE_NODEBUG size_t capacity() const noexcept { return isLargeOrExternal() ? _large.capacity : size_t(kSSOCapacity); }
|
||||
|
||||
//! Returns the data of the string.
|
||||
inline char* data() noexcept { return isLargeOrExternal() ? _large.data : _small.data; }
|
||||
ASMJIT_INLINE_NODEBUG char* data() noexcept { return isLargeOrExternal() ? _large.data : _small.data; }
|
||||
//! \overload
|
||||
inline const char* data() const noexcept { return isLargeOrExternal() ? _large.data : _small.data; }
|
||||
ASMJIT_INLINE_NODEBUG const char* data() const noexcept { return isLargeOrExternal() ? _large.data : _small.data; }
|
||||
|
||||
inline char* start() noexcept { return data(); }
|
||||
inline const char* start() const noexcept { return data(); }
|
||||
ASMJIT_INLINE_NODEBUG char* start() noexcept { return data(); }
|
||||
ASMJIT_INLINE_NODEBUG const char* start() const noexcept { return data(); }
|
||||
|
||||
inline char* end() noexcept { return data() + size(); }
|
||||
inline const char* end() const noexcept { return data() + size(); }
|
||||
ASMJIT_INLINE_NODEBUG char* end() noexcept { return data() + size(); }
|
||||
ASMJIT_INLINE_NODEBUG const char* end() const noexcept { return data() + size(); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -196,7 +196,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Swaps the content of this string with `other`.
|
||||
inline void swap(String& other) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void swap(String& other) noexcept {
|
||||
std::swap(_raw, other._raw);
|
||||
}
|
||||
|
||||
@@ -219,91 +219,91 @@ public:
|
||||
ASMJIT_API Error assign(const char* data, size_t size = SIZE_MAX) noexcept;
|
||||
|
||||
//! Replaces the current of the string with `other` string.
|
||||
inline Error assign(const String& other) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error assign(const String& other) noexcept {
|
||||
return assign(other.data(), other.size());
|
||||
}
|
||||
|
||||
//! Replaces the current of the string by a single `c` character.
|
||||
inline Error assign(char c) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error assign(char c) noexcept {
|
||||
return _opChar(ModifyOp::kAssign, c);
|
||||
}
|
||||
|
||||
//! Replaces the current of the string by a `c` character, repeated `n` times.
|
||||
inline Error assignChars(char c, size_t n) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error assignChars(char c, size_t n) noexcept {
|
||||
return _opChars(ModifyOp::kAssign, c, n);
|
||||
}
|
||||
|
||||
//! Replaces the current of the string by a formatted integer `i` (signed).
|
||||
inline Error assignInt(int64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error assignInt(int64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept {
|
||||
return _opNumber(ModifyOp::kAssign, uint64_t(i), base, width, flags | StringFormatFlags::kSigned);
|
||||
}
|
||||
|
||||
//! Replaces the current of the string by a formatted integer `i` (unsigned).
|
||||
inline Error assignUInt(uint64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error assignUInt(uint64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept {
|
||||
return _opNumber(ModifyOp::kAssign, i, base, width, flags);
|
||||
}
|
||||
|
||||
//! Replaces the current of the string by the given `data` converted to a HEX string.
|
||||
inline Error assignHex(const void* data, size_t size, char separator = '\0') noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error assignHex(const void* data, size_t size, char separator = '\0') noexcept {
|
||||
return _opHex(ModifyOp::kAssign, data, size, separator);
|
||||
}
|
||||
|
||||
//! Replaces the current of the string by a formatted string `fmt`.
|
||||
template<typename... Args>
|
||||
inline Error assignFormat(const char* fmt, Args&&... args) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error assignFormat(const char* fmt, Args&&... args) noexcept {
|
||||
return _opFormat(ModifyOp::kAssign, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
//! Replaces the current of the string by a formatted string `fmt` (va_list version).
|
||||
inline Error assignVFormat(const char* fmt, va_list ap) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error assignVFormat(const char* fmt, va_list ap) noexcept {
|
||||
return _opVFormat(ModifyOp::kAssign, fmt, ap);
|
||||
}
|
||||
|
||||
//! Appends `str` having the given size `size` to the string.
|
||||
//!
|
||||
//! Null terminated strings can set `size` to `SIZE_MAX`.
|
||||
inline Error append(const char* str, size_t size = SIZE_MAX) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error append(const char* str, size_t size = SIZE_MAX) noexcept {
|
||||
return _opString(ModifyOp::kAppend, str, size);
|
||||
}
|
||||
|
||||
//! Appends `other` string to this string.
|
||||
inline Error append(const String& other) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error append(const String& other) noexcept {
|
||||
return append(other.data(), other.size());
|
||||
}
|
||||
|
||||
//! Appends a single `c` character.
|
||||
inline Error append(char c) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error append(char c) noexcept {
|
||||
return _opChar(ModifyOp::kAppend, c);
|
||||
}
|
||||
|
||||
//! Appends `c` character repeated `n` times.
|
||||
inline Error appendChars(char c, size_t n) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error appendChars(char c, size_t n) noexcept {
|
||||
return _opChars(ModifyOp::kAppend, c, n);
|
||||
}
|
||||
|
||||
//! Appends a formatted integer `i` (signed).
|
||||
inline Error appendInt(int64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error appendInt(int64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept {
|
||||
return _opNumber(ModifyOp::kAppend, uint64_t(i), base, width, flags | StringFormatFlags::kSigned);
|
||||
}
|
||||
|
||||
//! Appends a formatted integer `i` (unsigned).
|
||||
inline Error appendUInt(uint64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error appendUInt(uint64_t i, uint32_t base = 0, size_t width = 0, StringFormatFlags flags = StringFormatFlags::kNone) noexcept {
|
||||
return _opNumber(ModifyOp::kAppend, i, base, width, flags);
|
||||
}
|
||||
|
||||
//! Appends the given `data` converted to a HEX string.
|
||||
inline Error appendHex(const void* data, size_t size, char separator = '\0') noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error appendHex(const void* data, size_t size, char separator = '\0') noexcept {
|
||||
return _opHex(ModifyOp::kAppend, data, size, separator);
|
||||
}
|
||||
|
||||
//! Appends a formatted string `fmt` with `args`.
|
||||
template<typename... Args>
|
||||
inline Error appendFormat(const char* fmt, Args&&... args) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error appendFormat(const char* fmt, Args&&... args) noexcept {
|
||||
return _opFormat(ModifyOp::kAppend, fmt, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
//! Appends a formatted string `fmt` (va_list version).
|
||||
inline Error appendVFormat(const char* fmt, va_list ap) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error appendVFormat(const char* fmt, va_list ap) noexcept {
|
||||
return _opVFormat(ModifyOp::kAppend, fmt, ap);
|
||||
}
|
||||
|
||||
@@ -313,7 +313,7 @@ public:
|
||||
ASMJIT_API Error truncate(size_t newSize) noexcept;
|
||||
|
||||
ASMJIT_API bool eq(const char* other, size_t size = SIZE_MAX) const noexcept;
|
||||
inline bool eq(const String& other) const noexcept { return eq(other.data(), other.size()); }
|
||||
ASMJIT_INLINE_NODEBUG bool eq(const String& other) const noexcept { return eq(other.data(), other.size()); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -351,7 +351,7 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline StringTmp() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG StringTmp() noexcept {
|
||||
_resetToTemporary();
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -40,14 +40,14 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns target's environment.
|
||||
inline const Environment& environment() const noexcept { return _environment; }
|
||||
ASMJIT_INLINE_NODEBUG const Environment& environment() const noexcept { return _environment; }
|
||||
//! Returns the target architecture.
|
||||
inline Arch arch() const noexcept { return _environment.arch(); }
|
||||
ASMJIT_INLINE_NODEBUG Arch arch() const noexcept { return _environment.arch(); }
|
||||
//! Returns the target sub-architecture.
|
||||
inline SubArch subArch() const noexcept { return _environment.subArch(); }
|
||||
ASMJIT_INLINE_NODEBUG SubArch subArch() const noexcept { return _environment.subArch(); }
|
||||
|
||||
//! Returns target CPU features.
|
||||
inline const CpuFeatures& cpuFeatures() const noexcept { return _cpuFeatures; }
|
||||
ASMJIT_INLINE_NODEBUG const CpuFeatures& cpuFeatures() const noexcept { return _cpuFeatures; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
@@ -164,74 +164,74 @@ struct TypeData {
|
||||
ASMJIT_VARAPI const TypeData _typeData;
|
||||
|
||||
//! Returns the scalar type of `typeId`.
|
||||
static inline TypeId scalarOf(TypeId typeId) noexcept { return _typeData.scalarOf[uint32_t(typeId)]; }
|
||||
static ASMJIT_INLINE_NODEBUG TypeId scalarOf(TypeId typeId) noexcept { return _typeData.scalarOf[uint32_t(typeId)]; }
|
||||
|
||||
//! Returns the size [in bytes] of `typeId`.
|
||||
static inline uint32_t sizeOf(TypeId typeId) noexcept { return _typeData.sizeOf[uint32_t(typeId)]; }
|
||||
static ASMJIT_INLINE_NODEBUG uint32_t sizeOf(TypeId typeId) noexcept { return _typeData.sizeOf[uint32_t(typeId)]; }
|
||||
|
||||
//! Tests whether a given type `typeId` is between `a` and `b`.
|
||||
static inline constexpr bool isBetween(TypeId typeId, TypeId a, TypeId b) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isBetween(TypeId typeId, TypeId a, TypeId b) noexcept {
|
||||
return Support::isBetween(uint32_t(typeId), uint32_t(a), uint32_t(b));
|
||||
}
|
||||
|
||||
//! Tests whether a given type `typeId` is \ref TypeId::kVoid.
|
||||
static inline constexpr bool isVoid(TypeId typeId) noexcept { return typeId == TypeId::kVoid; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isVoid(TypeId typeId) noexcept { return typeId == TypeId::kVoid; }
|
||||
//! Tests whether a given type `typeId` is a valid non-void type.
|
||||
static inline constexpr bool isValid(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kIntStart, TypeId::_kVec512End); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isValid(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kIntStart, TypeId::_kVec512End); }
|
||||
//! Tests whether a given type `typeId` is scalar (has no vector part).
|
||||
static inline constexpr bool isScalar(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kBaseStart, TypeId::_kBaseEnd); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isScalar(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kBaseStart, TypeId::_kBaseEnd); }
|
||||
//! Tests whether a given type `typeId` is abstract, which means that its size depends on register size.
|
||||
static inline constexpr bool isAbstract(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kIntPtr, TypeId::kUIntPtr); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isAbstract(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kIntPtr, TypeId::kUIntPtr); }
|
||||
|
||||
//! Tests whether a given type is a scalar integer (signed or unsigned) of any size.
|
||||
static inline constexpr bool isInt(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kIntStart, TypeId::_kIntEnd); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isInt(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kIntStart, TypeId::_kIntEnd); }
|
||||
//! Tests whether a given type is a scalar 8-bit integer (signed).
|
||||
static inline constexpr bool isInt8(TypeId typeId) noexcept { return typeId == TypeId::kInt8; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isInt8(TypeId typeId) noexcept { return typeId == TypeId::kInt8; }
|
||||
//! Tests whether a given type is a scalar 8-bit integer (unsigned).
|
||||
static inline constexpr bool isUInt8(TypeId typeId) noexcept { return typeId == TypeId::kUInt8; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isUInt8(TypeId typeId) noexcept { return typeId == TypeId::kUInt8; }
|
||||
//! Tests whether a given type is a scalar 16-bit integer (signed).
|
||||
static inline constexpr bool isInt16(TypeId typeId) noexcept { return typeId == TypeId::kInt16; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isInt16(TypeId typeId) noexcept { return typeId == TypeId::kInt16; }
|
||||
//! Tests whether a given type is a scalar 16-bit integer (unsigned).
|
||||
static inline constexpr bool isUInt16(TypeId typeId) noexcept { return typeId == TypeId::kUInt16; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isUInt16(TypeId typeId) noexcept { return typeId == TypeId::kUInt16; }
|
||||
//! Tests whether a given type is a scalar 32-bit integer (signed).
|
||||
static inline constexpr bool isInt32(TypeId typeId) noexcept { return typeId == TypeId::kInt32; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isInt32(TypeId typeId) noexcept { return typeId == TypeId::kInt32; }
|
||||
//! Tests whether a given type is a scalar 32-bit integer (unsigned).
|
||||
static inline constexpr bool isUInt32(TypeId typeId) noexcept { return typeId == TypeId::kUInt32; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isUInt32(TypeId typeId) noexcept { return typeId == TypeId::kUInt32; }
|
||||
//! Tests whether a given type is a scalar 64-bit integer (signed).
|
||||
static inline constexpr bool isInt64(TypeId typeId) noexcept { return typeId == TypeId::kInt64; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isInt64(TypeId typeId) noexcept { return typeId == TypeId::kInt64; }
|
||||
//! Tests whether a given type is a scalar 64-bit integer (unsigned).
|
||||
static inline constexpr bool isUInt64(TypeId typeId) noexcept { return typeId == TypeId::kUInt64; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isUInt64(TypeId typeId) noexcept { return typeId == TypeId::kUInt64; }
|
||||
|
||||
static inline constexpr bool isGp8(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt8, TypeId::kUInt8); }
|
||||
static inline constexpr bool isGp16(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt16, TypeId::kUInt16); }
|
||||
static inline constexpr bool isGp32(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt32, TypeId::kUInt32); }
|
||||
static inline constexpr bool isGp64(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt64, TypeId::kUInt64); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isGp8(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt8, TypeId::kUInt8); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isGp16(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt16, TypeId::kUInt16); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isGp32(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt32, TypeId::kUInt32); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isGp64(TypeId typeId) noexcept { return isBetween(typeId, TypeId::kInt64, TypeId::kUInt64); }
|
||||
|
||||
//! Tests whether a given type is a scalar floating point of any size.
|
||||
static inline constexpr bool isFloat(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kFloatStart, TypeId::_kFloatEnd); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isFloat(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kFloatStart, TypeId::_kFloatEnd); }
|
||||
//! Tests whether a given type is a scalar 32-bit float.
|
||||
static inline constexpr bool isFloat32(TypeId typeId) noexcept { return typeId == TypeId::kFloat32; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isFloat32(TypeId typeId) noexcept { return typeId == TypeId::kFloat32; }
|
||||
//! Tests whether a given type is a scalar 64-bit float.
|
||||
static inline constexpr bool isFloat64(TypeId typeId) noexcept { return typeId == TypeId::kFloat64; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isFloat64(TypeId typeId) noexcept { return typeId == TypeId::kFloat64; }
|
||||
//! Tests whether a given type is a scalar 80-bit float.
|
||||
static inline constexpr bool isFloat80(TypeId typeId) noexcept { return typeId == TypeId::kFloat80; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isFloat80(TypeId typeId) noexcept { return typeId == TypeId::kFloat80; }
|
||||
|
||||
static inline constexpr bool isMask(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kMaskStart, TypeId::_kMaskEnd); }
|
||||
static inline constexpr bool isMask8(TypeId typeId) noexcept { return typeId == TypeId::kMask8; }
|
||||
static inline constexpr bool isMask16(TypeId typeId) noexcept { return typeId == TypeId::kMask16; }
|
||||
static inline constexpr bool isMask32(TypeId typeId) noexcept { return typeId == TypeId::kMask32; }
|
||||
static inline constexpr bool isMask64(TypeId typeId) noexcept { return typeId == TypeId::kMask64; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isMask(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kMaskStart, TypeId::_kMaskEnd); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isMask8(TypeId typeId) noexcept { return typeId == TypeId::kMask8; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isMask16(TypeId typeId) noexcept { return typeId == TypeId::kMask16; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isMask32(TypeId typeId) noexcept { return typeId == TypeId::kMask32; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isMask64(TypeId typeId) noexcept { return typeId == TypeId::kMask64; }
|
||||
|
||||
static inline constexpr bool isMmx(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kMmxStart, TypeId::_kMmxEnd); }
|
||||
static inline constexpr bool isMmx32(TypeId typeId) noexcept { return typeId == TypeId::kMmx32; }
|
||||
static inline constexpr bool isMmx64(TypeId typeId) noexcept { return typeId == TypeId::kMmx64; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isMmx(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kMmxStart, TypeId::_kMmxEnd); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isMmx32(TypeId typeId) noexcept { return typeId == TypeId::kMmx32; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isMmx64(TypeId typeId) noexcept { return typeId == TypeId::kMmx64; }
|
||||
|
||||
static inline constexpr bool isVec(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec32Start, TypeId::_kVec512End); }
|
||||
static inline constexpr bool isVec32(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec32Start, TypeId::_kVec32End); }
|
||||
static inline constexpr bool isVec64(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec64Start, TypeId::_kVec64End); }
|
||||
static inline constexpr bool isVec128(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec128Start, TypeId::_kVec128End); }
|
||||
static inline constexpr bool isVec256(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec256Start, TypeId::_kVec256End); }
|
||||
static inline constexpr bool isVec512(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec512Start, TypeId::_kVec512End); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isVec(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec32Start, TypeId::_kVec512End); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isVec32(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec32Start, TypeId::_kVec32End); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isVec64(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec64Start, TypeId::_kVec64End); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isVec128(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec128Start, TypeId::_kVec128End); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isVec256(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec256Start, TypeId::_kVec256End); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isVec512(TypeId typeId) noexcept { return isBetween(typeId, TypeId::_kVec512Start, TypeId::_kVec512End); }
|
||||
|
||||
//! \cond
|
||||
enum TypeCategory : uint32_t {
|
||||
@@ -317,7 +317,7 @@ struct TypeIdOfT<T&> {
|
||||
|
||||
//! Returns a corresponding \ref TypeId of `T` type.
|
||||
template<typename T>
|
||||
static inline constexpr TypeId typeIdOfT() noexcept { return TypeId(TypeIdOfT<T>::kTypeId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr TypeId typeIdOfT() noexcept { return TypeId(TypeIdOfT<T>::kTypeId); }
|
||||
|
||||
//! Returns offset needed to convert a `kIntPtr` and `kUIntPtr` TypeId into a type that matches `registerSize`
|
||||
//! (general-purpose register size). If you find such TypeId it's then only about adding the offset to it.
|
||||
@@ -336,18 +336,18 @@ static inline constexpr TypeId typeIdOfT() noexcept { return TypeId(TypeIdOfT<T>
|
||||
//! // The same, but by using TypeUtils::deabstract() function.
|
||||
//! typeId = TypeUtils::deabstract(typeId, deabstractDelta);
|
||||
//! ```
|
||||
static inline constexpr uint32_t deabstractDeltaOfSize(uint32_t registerSize) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr uint32_t deabstractDeltaOfSize(uint32_t registerSize) noexcept {
|
||||
return registerSize >= 8 ? uint32_t(TypeId::kInt64) - uint32_t(TypeId::kIntPtr)
|
||||
: uint32_t(TypeId::kInt32) - uint32_t(TypeId::kIntPtr);
|
||||
}
|
||||
|
||||
//! Deabstracts a given `typeId` into a native type by using `deabstractDelta`, which was previously
|
||||
//! calculated by calling \ref deabstractDeltaOfSize() with a target native register size.
|
||||
static inline constexpr TypeId deabstract(TypeId typeId, uint32_t deabstractDelta) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr TypeId deabstract(TypeId typeId, uint32_t deabstractDelta) noexcept {
|
||||
return isAbstract(typeId) ? TypeId(uint32_t(typeId) + deabstractDelta) : typeId;
|
||||
}
|
||||
|
||||
static inline constexpr TypeId scalarToVector(TypeId scalarTypeId, TypeId vecStartId) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr TypeId scalarToVector(TypeId scalarTypeId, TypeId vecStartId) noexcept {
|
||||
return TypeId(uint32_t(vecStartId) + uint32_t(scalarTypeId) - uint32_t(TypeId::kInt8));
|
||||
}
|
||||
|
||||
|
||||
@@ -85,17 +85,17 @@ public:
|
||||
//!
|
||||
//! It's not required, but it's good practice to set `blockSize` to a reasonable value that depends on the usage
|
||||
//! of `Zone`. Greater block sizes are generally safer and perform better than unreasonably low block sizes.
|
||||
inline explicit Zone(size_t blockSize, size_t blockAlignment = 1) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG explicit Zone(size_t blockSize, size_t blockAlignment = 1) noexcept {
|
||||
_init(blockSize, blockAlignment, nullptr);
|
||||
}
|
||||
|
||||
//! Creates a new Zone with a first block pointing to a `temporary` memory.
|
||||
inline Zone(size_t blockSize, size_t blockAlignment, const Support::Temporary& temporary) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Zone(size_t blockSize, size_t blockAlignment, const Support::Temporary& temporary) noexcept {
|
||||
_init(blockSize, blockAlignment, &temporary);
|
||||
}
|
||||
|
||||
//! \overload
|
||||
inline Zone(size_t blockSize, size_t blockAlignment, const Support::Temporary* temporary) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Zone(size_t blockSize, size_t blockAlignment, const Support::Temporary* temporary) noexcept {
|
||||
_init(blockSize, blockAlignment, temporary);
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ public:
|
||||
//!
|
||||
//! This will destroy the `Zone` instance and release all blocks of memory allocated by it. It performs implicit
|
||||
//! `reset(ResetPolicy::kHard)`.
|
||||
inline ~Zone() noexcept { reset(ResetPolicy::kHard); }
|
||||
ASMJIT_INLINE_NODEBUG ~Zone() noexcept { reset(ResetPolicy::kHard); }
|
||||
|
||||
ASMJIT_API void _init(size_t blockSize, size_t blockAlignment, const Support::Temporary* temporary) noexcept;
|
||||
|
||||
@@ -133,24 +133,24 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether this `Zone` is actually a `ZoneTmp` that uses temporary memory.
|
||||
inline bool isTemporary() const noexcept { return _isTemporary != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool isTemporary() const noexcept { return _isTemporary != 0; }
|
||||
|
||||
//! Returns the default block size.
|
||||
inline size_t blockSize() const noexcept { return _blockSize; }
|
||||
ASMJIT_INLINE_NODEBUG size_t blockSize() const noexcept { return _blockSize; }
|
||||
//! Returns the default block alignment.
|
||||
inline size_t blockAlignment() const noexcept { return size_t(1) << _blockAlignmentShift; }
|
||||
ASMJIT_INLINE_NODEBUG size_t blockAlignment() const noexcept { return size_t(1) << _blockAlignmentShift; }
|
||||
//! Returns remaining size of the current block.
|
||||
inline size_t remainingSize() const noexcept { return (size_t)(_end - _ptr); }
|
||||
ASMJIT_INLINE_NODEBUG size_t remainingSize() const noexcept { return (size_t)(_end - _ptr); }
|
||||
|
||||
//! Returns the current zone cursor (dangerous).
|
||||
//!
|
||||
//! This is a function that can be used to get exclusive access to the current block's memory buffer.
|
||||
template<typename T = uint8_t>
|
||||
inline T* ptr() noexcept { return reinterpret_cast<T*>(_ptr); }
|
||||
ASMJIT_INLINE_NODEBUG T* ptr() noexcept { return reinterpret_cast<T*>(_ptr); }
|
||||
|
||||
//! Returns the end of the current zone block, only useful if you use `ptr()`.
|
||||
template<typename T = uint8_t>
|
||||
inline T* end() noexcept { return reinterpret_cast<T*>(_end); }
|
||||
ASMJIT_INLINE_NODEBUG T* end() noexcept { return reinterpret_cast<T*>(_end); }
|
||||
|
||||
//! Sets the current zone pointer to `ptr` (must be within the current block).
|
||||
template<typename T>
|
||||
@@ -185,7 +185,7 @@ public:
|
||||
}
|
||||
|
||||
//! Aligns the current pointer to `alignment`.
|
||||
inline void align(size_t alignment) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void align(size_t alignment) noexcept {
|
||||
_ptr = Support::min(Support::alignUp(_ptr, alignment), _end);
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ public:
|
||||
//!
|
||||
//! \note This function doesn't respect any alignment. If you need to ensure there is enough room for an aligned
|
||||
//! allocation you need to call `align()` before calling `ensure()`.
|
||||
inline Error ensure(size_t size) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error ensure(size_t size) noexcept {
|
||||
if (size <= remainingSize())
|
||||
return kErrorOk;
|
||||
else
|
||||
@@ -430,11 +430,11 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Zone used to allocate memory that fits into slots.
|
||||
Zone* _zone;
|
||||
Zone* _zone {};
|
||||
//! Indexed slots containing released memory.
|
||||
Slot* _slots[kLoCount + kHiCount];
|
||||
Slot* _slots[kLoCount + kHiCount] {};
|
||||
//! Dynamic blocks for larger allocations (no slots).
|
||||
DynamicBlock* _dynamicBlocks;
|
||||
DynamicBlock* _dynamicBlocks {};
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -444,26 +444,22 @@ public:
|
||||
//! Creates a new `ZoneAllocator`.
|
||||
//!
|
||||
//! \note To use it, you must first `init()` it.
|
||||
inline ZoneAllocator() noexcept {
|
||||
memset(this, 0, sizeof(*this));
|
||||
}
|
||||
ASMJIT_INLINE_NODEBUG ZoneAllocator() noexcept {}
|
||||
|
||||
//! Creates a new `ZoneAllocator` initialized to use `zone`.
|
||||
inline explicit ZoneAllocator(Zone* zone) noexcept {
|
||||
memset(this, 0, sizeof(*this));
|
||||
_zone = zone;
|
||||
}
|
||||
ASMJIT_INLINE_NODEBUG explicit ZoneAllocator(Zone* zone) noexcept
|
||||
: _zone(zone) {}
|
||||
|
||||
//! Destroys the `ZoneAllocator`.
|
||||
inline ~ZoneAllocator() noexcept { reset(); }
|
||||
ASMJIT_INLINE_NODEBUG ~ZoneAllocator() noexcept { reset(); }
|
||||
|
||||
//! Tests whether the `ZoneAllocator` is initialized (i.e. has `Zone`).
|
||||
inline bool isInitialized() const noexcept { return _zone != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool isInitialized() const noexcept { return _zone != nullptr; }
|
||||
|
||||
//! Convenience function to initialize the `ZoneAllocator` with `zone`.
|
||||
//!
|
||||
//! It's the same as calling `reset(zone)`.
|
||||
inline void init(Zone* zone) noexcept { reset(zone); }
|
||||
ASMJIT_INLINE_NODEBUG void init(Zone* zone) noexcept { reset(zone); }
|
||||
|
||||
//! Resets this `ZoneAllocator` and also forget about the current `Zone` which is attached (if any). Reset
|
||||
//! optionally attaches a new `zone` passed, or keeps the `ZoneAllocator` in an uninitialized state, if
|
||||
@@ -476,7 +472,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the assigned `Zone` of this allocator or null if this `ZoneAllocator` is not initialized.
|
||||
inline Zone* zone() const noexcept { return _zone; }
|
||||
ASMJIT_INLINE_NODEBUG Zone* zone() const noexcept { return _zone; }
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
@@ -59,7 +59,7 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline ZoneHashBase() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG ZoneHashBase() noexcept {
|
||||
reset();
|
||||
}
|
||||
|
||||
@@ -99,8 +99,8 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline bool empty() const noexcept { return _size == 0; }
|
||||
inline size_t size() const noexcept { return _size; }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _size == 0; }
|
||||
ASMJIT_INLINE_NODEBUG size_t size() const noexcept { return _size; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -150,10 +150,10 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline ZoneHash() noexcept
|
||||
ASMJIT_INLINE_NODEBUG ZoneHash() noexcept
|
||||
: ZoneHashBase() {}
|
||||
|
||||
inline ZoneHash(ZoneHash&& other) noexcept
|
||||
ASMJIT_INLINE_NODEBUG ZoneHash(ZoneHash&& other) noexcept
|
||||
: ZoneHash(other) {}
|
||||
|
||||
//! \}
|
||||
@@ -161,7 +161,7 @@ public:
|
||||
//! \name Utilities
|
||||
//! \{
|
||||
|
||||
inline void swap(ZoneHash& other) noexcept { ZoneHashBase::_swap(other); }
|
||||
ASMJIT_INLINE_NODEBUG void swap(ZoneHash& other) noexcept { ZoneHashBase::_swap(other); }
|
||||
|
||||
template<typename KeyT>
|
||||
inline NodeT* get(const KeyT& key) const noexcept {
|
||||
@@ -173,8 +173,8 @@ public:
|
||||
return node;
|
||||
}
|
||||
|
||||
inline NodeT* insert(ZoneAllocator* allocator, NodeT* node) noexcept { return static_cast<NodeT*>(_insert(allocator, node)); }
|
||||
inline NodeT* remove(ZoneAllocator* allocator, NodeT* node) noexcept { return static_cast<NodeT*>(_remove(allocator, node)); }
|
||||
ASMJIT_INLINE_NODEBUG NodeT* insert(ZoneAllocator* allocator, NodeT* node) noexcept { return static_cast<NodeT*>(_insert(allocator, node)); }
|
||||
ASMJIT_INLINE_NODEBUG NodeT* remove(ZoneAllocator* allocator, NodeT* node) noexcept { return static_cast<NodeT*>(_remove(allocator, node)); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
@@ -39,10 +39,10 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline ZoneListNode() noexcept
|
||||
ASMJIT_INLINE_NODEBUG ZoneListNode() noexcept
|
||||
: _listNodes { nullptr, nullptr } {}
|
||||
|
||||
inline ZoneListNode(ZoneListNode&& other) noexcept
|
||||
ASMJIT_INLINE_NODEBUG ZoneListNode(ZoneListNode&& other) noexcept
|
||||
: _listNodes { other._listNodes[0], other._listNodes[1] } {}
|
||||
|
||||
//! \}
|
||||
@@ -50,11 +50,11 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline bool hasPrev() const noexcept { return _listNodes[kNodeIndexPrev] != nullptr; }
|
||||
inline bool hasNext() const noexcept { return _listNodes[kNodeIndexNext] != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasPrev() const noexcept { return _listNodes[kNodeIndexPrev] != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasNext() const noexcept { return _listNodes[kNodeIndexNext] != nullptr; }
|
||||
|
||||
inline NodeT* prev() const noexcept { return _listNodes[kNodeIndexPrev]; }
|
||||
inline NodeT* next() const noexcept { return _listNodes[kNodeIndexNext]; }
|
||||
ASMJIT_INLINE_NODEBUG NodeT* prev() const noexcept { return _listNodes[kNodeIndexPrev]; }
|
||||
ASMJIT_INLINE_NODEBUG NodeT* next() const noexcept { return _listNodes[kNodeIndexNext]; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -78,20 +78,19 @@ public:
|
||||
//! \name Members
|
||||
//! \{
|
||||
|
||||
NodeT* _nodes[2];
|
||||
NodeT* _nodes[2] {};
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline ZoneList() noexcept
|
||||
: _nodes { nullptr, nullptr } {}
|
||||
ASMJIT_INLINE_NODEBUG ZoneList() noexcept {}
|
||||
|
||||
inline ZoneList(ZoneList&& other) noexcept
|
||||
ASMJIT_INLINE_NODEBUG ZoneList(ZoneList&& other) noexcept
|
||||
: _nodes { other._nodes[0], other._nodes[1] } {}
|
||||
|
||||
inline void reset() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept {
|
||||
_nodes[0] = nullptr;
|
||||
_nodes[1] = nullptr;
|
||||
}
|
||||
@@ -101,16 +100,16 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline bool empty() const noexcept { return _nodes[0] == nullptr; }
|
||||
inline NodeT* first() const noexcept { return _nodes[kNodeIndexFirst]; }
|
||||
inline NodeT* last() const noexcept { return _nodes[kNodeIndexLast]; }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _nodes[0] == nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG NodeT* first() const noexcept { return _nodes[kNodeIndexFirst]; }
|
||||
ASMJIT_INLINE_NODEBUG NodeT* last() const noexcept { return _nodes[kNodeIndexLast]; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Utilities
|
||||
//! \{
|
||||
|
||||
inline void swap(ZoneList& other) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void swap(ZoneList& other) noexcept {
|
||||
std::swap(_nodes[0], other._nodes[0]);
|
||||
std::swap(_nodes[1], other._nodes[1]);
|
||||
}
|
||||
@@ -144,11 +143,11 @@ public:
|
||||
node->_listNodes[ dir] = next;
|
||||
}
|
||||
|
||||
inline void append(NodeT* node) noexcept { _addNode(node, kNodeIndexLast); }
|
||||
inline void prepend(NodeT* node) noexcept { _addNode(node, kNodeIndexFirst); }
|
||||
ASMJIT_INLINE_NODEBUG void append(NodeT* node) noexcept { _addNode(node, kNodeIndexLast); }
|
||||
ASMJIT_INLINE_NODEBUG void prepend(NodeT* node) noexcept { _addNode(node, kNodeIndexFirst); }
|
||||
|
||||
inline void insertAfter(NodeT* ref, NodeT* node) noexcept { _insertNode(ref, node, NodeT::kNodeIndexNext); }
|
||||
inline void insertBefore(NodeT* ref, NodeT* node) noexcept { _insertNode(ref, node, NodeT::kNodeIndexPrev); }
|
||||
ASMJIT_INLINE_NODEBUG void insertAfter(NodeT* ref, NodeT* node) noexcept { _insertNode(ref, node, NodeT::kNodeIndexNext); }
|
||||
ASMJIT_INLINE_NODEBUG void insertBefore(NodeT* ref, NodeT* node) noexcept { _insertNode(ref, node, NodeT::kNodeIndexPrev); }
|
||||
|
||||
inline NodeT* unlink(NodeT* node) noexcept {
|
||||
NodeT* prev = node->prev();
|
||||
|
||||
@@ -44,31 +44,31 @@ public:
|
||||
//! Pointer to the end of the array.
|
||||
void* _end;
|
||||
|
||||
inline bool empty() const noexcept { return _start == _end; }
|
||||
inline Block* prev() const noexcept { return _link[kBlockIndexPrev]; }
|
||||
inline Block* next() const noexcept { return _link[kBlockIndexNext]; }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _start == _end; }
|
||||
ASMJIT_INLINE_NODEBUG Block* prev() const noexcept { return _link[kBlockIndexPrev]; }
|
||||
ASMJIT_INLINE_NODEBUG Block* next() const noexcept { return _link[kBlockIndexNext]; }
|
||||
|
||||
inline void setPrev(Block* block) noexcept { _link[kBlockIndexPrev] = block; }
|
||||
inline void setNext(Block* block) noexcept { _link[kBlockIndexNext] = block; }
|
||||
ASMJIT_INLINE_NODEBUG void setPrev(Block* block) noexcept { _link[kBlockIndexPrev] = block; }
|
||||
ASMJIT_INLINE_NODEBUG void setNext(Block* block) noexcept { _link[kBlockIndexNext] = block; }
|
||||
|
||||
template<typename T>
|
||||
inline T* start() const noexcept { return static_cast<T*>(_start); }
|
||||
ASMJIT_INLINE_NODEBUG T* start() const noexcept { return static_cast<T*>(_start); }
|
||||
template<typename T>
|
||||
inline void setStart(T* start) noexcept { _start = static_cast<void*>(start); }
|
||||
ASMJIT_INLINE_NODEBUG void setStart(T* start) noexcept { _start = static_cast<void*>(start); }
|
||||
|
||||
template<typename T>
|
||||
inline T* end() const noexcept { return (T*)_end; }
|
||||
ASMJIT_INLINE_NODEBUG T* end() const noexcept { return (T*)_end; }
|
||||
template<typename T>
|
||||
inline void setEnd(T* end) noexcept { _end = (void*)end; }
|
||||
ASMJIT_INLINE_NODEBUG void setEnd(T* end) noexcept { _end = (void*)end; }
|
||||
|
||||
template<typename T>
|
||||
inline T* data() const noexcept { return (T*)((uint8_t*)(this) + sizeof(Block)); }
|
||||
ASMJIT_INLINE_NODEBUG T* data() const noexcept { return (T*)((uint8_t*)(this) + sizeof(Block)); }
|
||||
|
||||
template<typename T>
|
||||
inline bool canPrepend() const noexcept { return _start > data<void>(); }
|
||||
ASMJIT_INLINE_NODEBUG bool canPrepend() const noexcept { return _start > data<void>(); }
|
||||
|
||||
template<typename T>
|
||||
inline bool canAppend() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG bool canAppend() const noexcept {
|
||||
size_t kNumBlockItems = (kBlockSize - sizeof(Block)) / sizeof(T);
|
||||
size_t kStartBlockIndex = sizeof(Block);
|
||||
size_t kEndBlockIndex = kStartBlockIndex + kNumBlockItems * sizeof(T);
|
||||
@@ -83,25 +83,21 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Allocator used to allocate data.
|
||||
ZoneAllocator* _allocator;
|
||||
ZoneAllocator* _allocator {};
|
||||
//! First and last blocks.
|
||||
Block* _block[2];
|
||||
Block* _block[2] {};
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline ZoneStackBase() noexcept {
|
||||
_allocator = nullptr;
|
||||
_block[0] = nullptr;
|
||||
_block[1] = nullptr;
|
||||
}
|
||||
inline ~ZoneStackBase() noexcept { reset(); }
|
||||
ASMJIT_INLINE_NODEBUG ZoneStackBase() noexcept {}
|
||||
ASMJIT_INLINE_NODEBUG ~ZoneStackBase() noexcept { reset(); }
|
||||
|
||||
inline bool isInitialized() const noexcept { return _allocator != nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG bool isInitialized() const noexcept { return _allocator != nullptr; }
|
||||
ASMJIT_API Error _init(ZoneAllocator* allocator, size_t middleIndex) noexcept;
|
||||
inline Error reset() noexcept { return _init(nullptr, 0); }
|
||||
ASMJIT_INLINE_NODEBUG Error reset() noexcept { return _init(nullptr, 0); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -109,7 +105,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns `ZoneAllocator` attached to this container.
|
||||
inline ZoneAllocator* allocator() const noexcept { return _allocator; }
|
||||
ASMJIT_INLINE_NODEBUG ZoneAllocator* allocator() const noexcept { return _allocator; }
|
||||
|
||||
inline bool empty() const noexcept {
|
||||
ASMJIT_ASSERT(isInitialized());
|
||||
|
||||
@@ -27,7 +27,7 @@ struct ZoneStringBase {
|
||||
};
|
||||
};
|
||||
|
||||
inline void reset() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept {
|
||||
_dummy = nullptr;
|
||||
_external = nullptr;
|
||||
}
|
||||
@@ -83,8 +83,8 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline ZoneString() noexcept { reset(); }
|
||||
inline void reset() noexcept { _base.reset(); }
|
||||
ASMJIT_INLINE_NODEBUG ZoneString() noexcept { reset(); }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { _base.reset(); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -92,21 +92,21 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether the string is empty.
|
||||
inline bool empty() const noexcept { return _base._size == 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _base._size == 0; }
|
||||
|
||||
//! Returns the string data.
|
||||
inline const char* data() const noexcept { return _base._size <= kMaxEmbeddedSize ? _base._embedded : _base._external; }
|
||||
ASMJIT_INLINE_NODEBUG const char* data() const noexcept { return _base._size <= kMaxEmbeddedSize ? _base._embedded : _base._external; }
|
||||
//! Returns the string size.
|
||||
inline uint32_t size() const noexcept { return _base._size; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t size() const noexcept { return _base._size; }
|
||||
|
||||
//! Tests whether the string is embedded (e.g. no dynamically allocated).
|
||||
inline bool isEmbedded() const noexcept { return _base._size <= kMaxEmbeddedSize; }
|
||||
ASMJIT_INLINE_NODEBUG bool isEmbedded() const noexcept { return _base._size <= kMaxEmbeddedSize; }
|
||||
|
||||
//! Copies a new `data` of the given `size` to the string.
|
||||
//!
|
||||
//! If the `size` exceeds the internal buffer the given `zone` will be used to duplicate the data, otherwise
|
||||
//! the internal buffer will be used as a storage.
|
||||
inline Error setData(Zone* zone, const char* data, size_t size) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error setData(Zone* zone, const char* data, size_t size) noexcept {
|
||||
return _base.setData(zone, kMaxEmbeddedSize, data, size);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,33 +35,32 @@ public:
|
||||
//! \name Members
|
||||
//! \{
|
||||
|
||||
uintptr_t _rbNodeData[2];
|
||||
uintptr_t _rbNodeData[2] {};
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline ZoneTreeNode() noexcept
|
||||
: _rbNodeData { 0, 0 } {}
|
||||
ASMJIT_INLINE_NODEBUG ZoneTreeNode() noexcept {}
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline bool isRed() const noexcept { return static_cast<bool>(_rbNodeData[0] & kRedMask); }
|
||||
ASMJIT_INLINE_NODEBUG bool isRed() const noexcept { return static_cast<bool>(_rbNodeData[0] & kRedMask); }
|
||||
|
||||
inline bool hasChild(size_t i) const noexcept { return _rbNodeData[i] > kRedMask; }
|
||||
inline bool hasLeft() const noexcept { return _rbNodeData[0] > kRedMask; }
|
||||
inline bool hasRight() const noexcept { return _rbNodeData[1] != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasChild(size_t i) const noexcept { return _rbNodeData[i] > kRedMask; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasLeft() const noexcept { return _rbNodeData[0] > kRedMask; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasRight() const noexcept { return _rbNodeData[1] != 0; }
|
||||
|
||||
template<typename T = ZoneTreeNode>
|
||||
inline T* child(size_t i) const noexcept { return static_cast<T*>(_getChild(i)); }
|
||||
ASMJIT_INLINE_NODEBUG T* child(size_t i) const noexcept { return static_cast<T*>(_getChild(i)); }
|
||||
template<typename T = ZoneTreeNode>
|
||||
inline T* left() const noexcept { return static_cast<T*>(_getLeft()); }
|
||||
ASMJIT_INLINE_NODEBUG T* left() const noexcept { return static_cast<T*>(_getLeft()); }
|
||||
template<typename T = ZoneTreeNode>
|
||||
inline T* right() const noexcept { return static_cast<T*>(_getRight()); }
|
||||
ASMJIT_INLINE_NODEBUG T* right() const noexcept { return static_cast<T*>(_getRight()); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -69,19 +68,19 @@ public:
|
||||
//! \name Internal
|
||||
//! \{
|
||||
|
||||
inline ZoneTreeNode* _getChild(size_t i) const noexcept { return (ZoneTreeNode*)(_rbNodeData[i] & kPtrMask); }
|
||||
inline ZoneTreeNode* _getLeft() const noexcept { return (ZoneTreeNode*)(_rbNodeData[0] & kPtrMask); }
|
||||
inline ZoneTreeNode* _getRight() const noexcept { return (ZoneTreeNode*)(_rbNodeData[1]); }
|
||||
ASMJIT_INLINE_NODEBUG ZoneTreeNode* _getChild(size_t i) const noexcept { return (ZoneTreeNode*)(_rbNodeData[i] & kPtrMask); }
|
||||
ASMJIT_INLINE_NODEBUG ZoneTreeNode* _getLeft() const noexcept { return (ZoneTreeNode*)(_rbNodeData[0] & kPtrMask); }
|
||||
ASMJIT_INLINE_NODEBUG ZoneTreeNode* _getRight() const noexcept { return (ZoneTreeNode*)(_rbNodeData[1]); }
|
||||
|
||||
inline void _setChild(size_t i, ZoneTreeNode* node) noexcept { _rbNodeData[i] = (_rbNodeData[i] & kRedMask) | (uintptr_t)node; }
|
||||
inline void _setLeft(ZoneTreeNode* node) noexcept { _rbNodeData[0] = (_rbNodeData[0] & kRedMask) | (uintptr_t)node; }
|
||||
inline void _setRight(ZoneTreeNode* node) noexcept { _rbNodeData[1] = (uintptr_t)node; }
|
||||
ASMJIT_INLINE_NODEBUG void _setChild(size_t i, ZoneTreeNode* node) noexcept { _rbNodeData[i] = (_rbNodeData[i] & kRedMask) | (uintptr_t)node; }
|
||||
ASMJIT_INLINE_NODEBUG void _setLeft(ZoneTreeNode* node) noexcept { _rbNodeData[0] = (_rbNodeData[0] & kRedMask) | (uintptr_t)node; }
|
||||
ASMJIT_INLINE_NODEBUG void _setRight(ZoneTreeNode* node) noexcept { _rbNodeData[1] = (uintptr_t)node; }
|
||||
|
||||
inline void _makeRed() noexcept { _rbNodeData[0] |= kRedMask; }
|
||||
inline void _makeBlack() noexcept { _rbNodeData[0] &= kPtrMask; }
|
||||
ASMJIT_INLINE_NODEBUG void _makeRed() noexcept { _rbNodeData[0] |= kRedMask; }
|
||||
ASMJIT_INLINE_NODEBUG void _makeBlack() noexcept { _rbNodeData[0] &= kPtrMask; }
|
||||
|
||||
//! Tests whether the node is RED (RED node must be non-null and must have RED flag set).
|
||||
static inline bool _isValidRed(ZoneTreeNode* node) noexcept { return node && node->isRed(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool _isValidRed(ZoneTreeNode* node) noexcept { return node && node->isRed(); }
|
||||
|
||||
//! \}
|
||||
//! \endcond
|
||||
@@ -96,7 +95,7 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline ZoneTreeNodeT() noexcept
|
||||
ASMJIT_INLINE_NODEBUG ZoneTreeNodeT() noexcept
|
||||
: ZoneTreeNode() {}
|
||||
|
||||
//! \}
|
||||
@@ -104,9 +103,9 @@ public:
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline NodeT* child(size_t i) const noexcept { return static_cast<NodeT*>(_getChild(i)); }
|
||||
inline NodeT* left() const noexcept { return static_cast<NodeT*>(_getLeft()); }
|
||||
inline NodeT* right() const noexcept { return static_cast<NodeT*>(_getRight()); }
|
||||
ASMJIT_INLINE_NODEBUG NodeT* child(size_t i) const noexcept { return static_cast<NodeT*>(_getChild(i)); }
|
||||
ASMJIT_INLINE_NODEBUG NodeT* left() const noexcept { return static_cast<NodeT*>(_getLeft()); }
|
||||
ASMJIT_INLINE_NODEBUG NodeT* right() const noexcept { return static_cast<NodeT*>(_getRight()); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -118,33 +117,30 @@ public:
|
||||
ASMJIT_NONCOPYABLE(ZoneTree)
|
||||
|
||||
typedef NodeT Node;
|
||||
NodeT* _root;
|
||||
NodeT* _root {};
|
||||
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline ZoneTree() noexcept
|
||||
: _root(nullptr) {}
|
||||
|
||||
inline ZoneTree(ZoneTree&& other) noexcept
|
||||
ASMJIT_INLINE_NODEBUG ZoneTree() noexcept {}
|
||||
ASMJIT_INLINE_NODEBUG ZoneTree(ZoneTree&& other) noexcept
|
||||
: _root(other._root) {}
|
||||
|
||||
inline void reset() noexcept { _root = nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept { _root = nullptr; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Accessors
|
||||
//! \{
|
||||
|
||||
inline bool empty() const noexcept { return _root == nullptr; }
|
||||
inline NodeT* root() const noexcept { return static_cast<NodeT*>(_root); }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _root == nullptr; }
|
||||
ASMJIT_INLINE_NODEBUG NodeT* root() const noexcept { return static_cast<NodeT*>(_root); }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Utilities
|
||||
//! \{
|
||||
|
||||
inline void swap(ZoneTree& other) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void swap(ZoneTree& other) noexcept {
|
||||
std::swap(_root, other._root);
|
||||
}
|
||||
|
||||
|
||||
@@ -73,11 +73,11 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether the vector is empty.
|
||||
inline bool empty() const noexcept { return _size == 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _size == 0; }
|
||||
//! Returns the vector size.
|
||||
inline size_type size() const noexcept { return _size; }
|
||||
ASMJIT_INLINE_NODEBUG size_type size() const noexcept { return _size; }
|
||||
//! Returns the vector capacity.
|
||||
inline size_type capacity() const noexcept { return _capacity; }
|
||||
ASMJIT_INLINE_NODEBUG size_type capacity() const noexcept { return _capacity; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -85,16 +85,16 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Makes the vector empty (won't change the capacity or data pointer).
|
||||
inline void clear() noexcept { _size = 0; }
|
||||
ASMJIT_INLINE_NODEBUG void clear() noexcept { _size = 0; }
|
||||
//! Resets the vector data and set its `size` to zero.
|
||||
inline void reset() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept {
|
||||
_data = nullptr;
|
||||
_size = 0;
|
||||
_capacity = 0;
|
||||
}
|
||||
|
||||
//! Truncates the vector to at most `n` items.
|
||||
inline void truncate(size_type n) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void truncate(size_type n) noexcept {
|
||||
_size = Support::min(_size, n);
|
||||
}
|
||||
|
||||
@@ -134,8 +134,8 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline ZoneVector() noexcept : ZoneVectorBase() {}
|
||||
inline ZoneVector(ZoneVector&& other) noexcept : ZoneVector(other) {}
|
||||
ASMJIT_INLINE_NODEBUG ZoneVector() noexcept : ZoneVectorBase() {}
|
||||
ASMJIT_INLINE_NODEBUG ZoneVector(ZoneVector&& other) noexcept : ZoneVector(other) {}
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -143,9 +143,9 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns vector data.
|
||||
inline T* data() noexcept { return static_cast<T*>(_data); }
|
||||
ASMJIT_INLINE_NODEBUG T* data() noexcept { return static_cast<T*>(_data); }
|
||||
//! Returns vector data (const)
|
||||
inline const T* data() const noexcept { return static_cast<const T*>(_data); }
|
||||
ASMJIT_INLINE_NODEBUG const T* data() const noexcept { return static_cast<const T*>(_data); }
|
||||
|
||||
//! Returns item at the given index `i` (const).
|
||||
inline const T& at(size_t i) const noexcept {
|
||||
@@ -163,23 +163,23 @@ public:
|
||||
//! \name STL Compatibility (Iterators)
|
||||
//! \{
|
||||
|
||||
inline iterator begin() noexcept { return iterator(data()); };
|
||||
inline const_iterator begin() const noexcept { return const_iterator(data()); };
|
||||
ASMJIT_INLINE_NODEBUG iterator begin() noexcept { return iterator(data()); };
|
||||
ASMJIT_INLINE_NODEBUG const_iterator begin() const noexcept { return const_iterator(data()); };
|
||||
|
||||
inline iterator end() noexcept { return iterator(data() + _size); };
|
||||
inline const_iterator end() const noexcept { return const_iterator(data() + _size); };
|
||||
ASMJIT_INLINE_NODEBUG iterator end() noexcept { return iterator(data() + _size); };
|
||||
ASMJIT_INLINE_NODEBUG const_iterator end() const noexcept { return const_iterator(data() + _size); };
|
||||
|
||||
inline reverse_iterator rbegin() noexcept { return reverse_iterator(end()); };
|
||||
inline const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); };
|
||||
ASMJIT_INLINE_NODEBUG reverse_iterator rbegin() noexcept { return reverse_iterator(end()); };
|
||||
ASMJIT_INLINE_NODEBUG const_reverse_iterator rbegin() const noexcept { return const_reverse_iterator(end()); };
|
||||
|
||||
inline reverse_iterator rend() noexcept { return reverse_iterator(begin()); };
|
||||
inline const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); };
|
||||
ASMJIT_INLINE_NODEBUG reverse_iterator rend() noexcept { return reverse_iterator(begin()); };
|
||||
ASMJIT_INLINE_NODEBUG const_reverse_iterator rend() const noexcept { return const_reverse_iterator(begin()); };
|
||||
|
||||
inline const_iterator cbegin() const noexcept { return const_iterator(data()); };
|
||||
inline const_iterator cend() const noexcept { return const_iterator(data() + _size); };
|
||||
ASMJIT_INLINE_NODEBUG const_iterator cbegin() const noexcept { return const_iterator(data()); };
|
||||
ASMJIT_INLINE_NODEBUG const_iterator cend() const noexcept { return const_iterator(data() + _size); };
|
||||
|
||||
inline const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); };
|
||||
inline const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); };
|
||||
ASMJIT_INLINE_NODEBUG const_reverse_iterator crbegin() const noexcept { return const_reverse_iterator(cend()); };
|
||||
ASMJIT_INLINE_NODEBUG const_reverse_iterator crend() const noexcept { return const_reverse_iterator(cbegin()); };
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -344,9 +344,9 @@ public:
|
||||
//!
|
||||
//! \note The vector must have at least one element. Attempting to use `first()` on empty vector will trigger
|
||||
//! an assertion failure in debug builds.
|
||||
inline T& first() noexcept { return operator[](0); }
|
||||
ASMJIT_INLINE_NODEBUG T& first() noexcept { return operator[](0); }
|
||||
//! \overload
|
||||
inline const T& first() const noexcept { return operator[](0); }
|
||||
ASMJIT_INLINE_NODEBUG const T& first() const noexcept { return operator[](0); }
|
||||
|
||||
//! Returns a reference to the last element of the vector.
|
||||
//!
|
||||
@@ -423,21 +423,21 @@ public:
|
||||
//! \name Internal
|
||||
//! \{
|
||||
|
||||
static inline uint32_t _wordsPerBits(uint32_t nBits) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG uint32_t _wordsPerBits(uint32_t nBits) noexcept {
|
||||
return ((nBits + kBitWordSizeInBits - 1) / kBitWordSizeInBits);
|
||||
}
|
||||
|
||||
static inline void _zeroBits(BitWord* dst, uint32_t nBitWords) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG void _zeroBits(BitWord* dst, uint32_t nBitWords) noexcept {
|
||||
for (uint32_t i = 0; i < nBitWords; i++)
|
||||
dst[i] = 0;
|
||||
}
|
||||
|
||||
static inline void _fillBits(BitWord* dst, uint32_t nBitWords) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG void _fillBits(BitWord* dst, uint32_t nBitWords) noexcept {
|
||||
for (uint32_t i = 0; i < nBitWords; i++)
|
||||
dst[i] = ~BitWord(0);
|
||||
}
|
||||
|
||||
static inline void _copyBits(BitWord* dst, const BitWord* src, uint32_t nBitWords) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG void _copyBits(BitWord* dst, const BitWord* src, uint32_t nBitWords) noexcept {
|
||||
for (uint32_t i = 0; i < nBitWords; i++)
|
||||
dst[i] = src[i];
|
||||
}
|
||||
@@ -448,9 +448,9 @@ public:
|
||||
//! \name Construction & Destruction
|
||||
//! \{
|
||||
|
||||
inline ZoneBitVector() noexcept {}
|
||||
ASMJIT_INLINE_NODEBUG ZoneBitVector() noexcept {}
|
||||
|
||||
inline ZoneBitVector(ZoneBitVector&& other) noexcept
|
||||
ASMJIT_INLINE_NODEBUG ZoneBitVector(ZoneBitVector&& other) noexcept
|
||||
: _data(other._data),
|
||||
_size(other._size),
|
||||
_capacity(other._capacity) {}
|
||||
@@ -460,8 +460,8 @@ public:
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
inline bool operator==(const ZoneBitVector& other) const noexcept { return eq(other); }
|
||||
inline bool operator!=(const ZoneBitVector& other) const noexcept { return !eq(other); }
|
||||
ASMJIT_INLINE_NODEBUG bool operator==(const ZoneBitVector& other) const noexcept { return eq(other); }
|
||||
ASMJIT_INLINE_NODEBUG bool operator!=(const ZoneBitVector& other) const noexcept { return !eq(other); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -469,44 +469,44 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether the bit-vector is empty (has no bits).
|
||||
inline bool empty() const noexcept { return _size == 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool empty() const noexcept { return _size == 0; }
|
||||
//! Returns the size of this bit-vector (in bits).
|
||||
inline uint32_t size() const noexcept { return _size; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t size() const noexcept { return _size; }
|
||||
//! Returns the capacity of this bit-vector (in bits).
|
||||
inline uint32_t capacity() const noexcept { return _capacity; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t capacity() const noexcept { return _capacity; }
|
||||
|
||||
//! Returns the size of the `BitWord[]` array in `BitWord` units.
|
||||
inline uint32_t sizeInBitWords() const noexcept { return _wordsPerBits(_size); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t sizeInBitWords() const noexcept { return _wordsPerBits(_size); }
|
||||
//! Returns the capacity of the `BitWord[]` array in `BitWord` units.
|
||||
inline uint32_t capacityInBitWords() const noexcept { return _wordsPerBits(_capacity); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t capacityInBitWords() const noexcept { return _wordsPerBits(_capacity); }
|
||||
|
||||
//! Returns bit-vector data as `BitWord[]`.
|
||||
inline BitWord* data() noexcept { return _data; }
|
||||
ASMJIT_INLINE_NODEBUG BitWord* data() noexcept { return _data; }
|
||||
//! \overload
|
||||
inline const BitWord* data() const noexcept { return _data; }
|
||||
ASMJIT_INLINE_NODEBUG const BitWord* data() const noexcept { return _data; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Utilities
|
||||
//! \{
|
||||
|
||||
inline void swap(ZoneBitVector& other) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void swap(ZoneBitVector& other) noexcept {
|
||||
std::swap(_data, other._data);
|
||||
std::swap(_size, other._size);
|
||||
std::swap(_capacity, other._capacity);
|
||||
}
|
||||
|
||||
inline void clear() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void clear() noexcept {
|
||||
_size = 0;
|
||||
}
|
||||
|
||||
inline void reset() noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void reset() noexcept {
|
||||
_data = nullptr;
|
||||
_size = 0;
|
||||
_capacity = 0;
|
||||
}
|
||||
|
||||
inline void truncate(uint32_t newSize) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void truncate(uint32_t newSize) noexcept {
|
||||
_size = Support::min(_size, newSize);
|
||||
_clearUnusedBits();
|
||||
}
|
||||
@@ -648,12 +648,13 @@ public:
|
||||
//! \{
|
||||
|
||||
inline void release(ZoneAllocator* allocator) noexcept {
|
||||
if (!_data) return;
|
||||
if (!_data)
|
||||
return;
|
||||
allocator->release(_data, _capacity / 8);
|
||||
reset();
|
||||
}
|
||||
|
||||
inline Error resize(ZoneAllocator* allocator, uint32_t newSize, bool newBitsValue = false) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Error resize(ZoneAllocator* allocator, uint32_t newSize, bool newBitsValue = false) noexcept {
|
||||
return _resize(allocator, newSize, newSize, newBitsValue);
|
||||
}
|
||||
|
||||
|
||||
@@ -101,7 +101,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
||||
//!
|
||||
//! The example should be self-explanatory. It shows how to work with labels, how to use operands, and how to emit
|
||||
//! instructions that can use different registers based on runtime selection. It implements 32-bit CDECL, WIN64,
|
||||
//! and SysV64 caling conventions and will work on most X86/X64 environments.
|
||||
//! and SysV64 calling conventions and will work on most X86/X64 environments.
|
||||
//!
|
||||
//! Although functions prologs / epilogs can be implemented manually, AsmJit provides utilities that can be used
|
||||
//! to create function prologs and epilogs automatically, see \ref asmjit_function for more details.
|
||||
@@ -615,7 +615,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
||||
//! // vaddpd zmm0 {k1} {z}, zmm1, [rcx] {1to8}
|
||||
//! a.k(k1).z().vaddpd(zmm0, zmm1, x86::mem(rcx)._1to8());
|
||||
//!
|
||||
//! // Embedded Rounding & Suppress-All-Exceptoins
|
||||
//! // Embedded Rounding & Suppress-All-Exceptions
|
||||
//! // -------------------------------------------
|
||||
//! //
|
||||
//! // - Rounding mode and {sae} are part of instruction options.
|
||||
@@ -653,8 +653,8 @@ public:
|
||||
// NOTE: x86::Assembler uses _privateData to store 'address-override' bit that is used to decide whether to emit
|
||||
// address-override (67H) prefix based on the memory BASE+INDEX registers. It's either `kX86MemInfo_67H_X86` or
|
||||
// `kX86MemInfo_67H_X64`.
|
||||
inline uint32_t _addressOverrideMask() const noexcept { return _privateData; }
|
||||
inline void _setAddressOverrideMask(uint32_t m) noexcept { _privateData = m; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t _addressOverrideMask() const noexcept { return _privateData; }
|
||||
ASMJIT_INLINE_NODEBUG void _setAddressOverrideMask(uint32_t m) noexcept { _privateData = m; }
|
||||
|
||||
//! \}
|
||||
//! \endcond
|
||||
|
||||
@@ -512,42 +512,42 @@ public:
|
||||
#endif
|
||||
|
||||
#define ASMJIT_NEW_REG_CUSTOM(FUNC, REG) \
|
||||
inline REG FUNC(TypeId typeId) { \
|
||||
ASMJIT_INLINE_NODEBUG REG FUNC(TypeId typeId) { \
|
||||
REG reg(Globals::NoInit); \
|
||||
_newReg(®, typeId); \
|
||||
return reg; \
|
||||
} \
|
||||
\
|
||||
template<typename... Args> \
|
||||
inline REG FUNC(TypeId typeId, const char* fmt, Args&&... args) { \
|
||||
ASMJIT_INLINE_NODEBUG REG FUNC(TypeId typeId, const char* fmt, Args&&... args) { \
|
||||
REG reg(Globals::NoInit); \
|
||||
ASMJIT_NEW_REG_FMT(reg, typeId, fmt, std::forward<Args>(args)...); \
|
||||
return reg; \
|
||||
}
|
||||
|
||||
#define ASMJIT_NEW_REG_TYPED(FUNC, REG, TYPE_ID) \
|
||||
inline REG FUNC() { \
|
||||
ASMJIT_INLINE_NODEBUG REG FUNC() { \
|
||||
REG reg(Globals::NoInit); \
|
||||
_newReg(®, TYPE_ID); \
|
||||
return reg; \
|
||||
} \
|
||||
\
|
||||
template<typename... Args> \
|
||||
inline REG FUNC(const char* fmt, Args&&... args) { \
|
||||
ASMJIT_INLINE_NODEBUG REG FUNC(const char* fmt, Args&&... args) { \
|
||||
REG reg(Globals::NoInit); \
|
||||
ASMJIT_NEW_REG_FMT(reg, TYPE_ID, fmt, std::forward<Args>(args)...); \
|
||||
return reg; \
|
||||
}
|
||||
|
||||
template<typename RegT>
|
||||
inline RegT newSimilarReg(const RegT& ref) {
|
||||
ASMJIT_INLINE_NODEBUG RegT newSimilarReg(const RegT& ref) {
|
||||
RegT reg(Globals::NoInit);
|
||||
_newReg(reg, ref);
|
||||
return reg;
|
||||
}
|
||||
|
||||
template<typename RegT, typename... Args>
|
||||
inline RegT newSimilarReg(const RegT& ref, const char* fmt, Args&&... args) {
|
||||
ASMJIT_INLINE_NODEBUG RegT newSimilarReg(const RegT& ref, const char* fmt, Args&&... args) {
|
||||
RegT reg(Globals::NoInit);
|
||||
ASMJIT_NEW_REG_FMT(reg, ref, fmt, std::forward<Args>(args)...);
|
||||
return reg;
|
||||
@@ -601,7 +601,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a new memory chunk allocated on the current function's stack.
|
||||
inline Mem newStack(uint32_t size, uint32_t alignment, const char* name = nullptr) {
|
||||
ASMJIT_INLINE_NODEBUG Mem newStack(uint32_t size, uint32_t alignment, const char* name = nullptr) {
|
||||
Mem m(Globals::NoInit);
|
||||
_newStack(&m, size, alignment, name);
|
||||
return m;
|
||||
@@ -613,38 +613,38 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Put data to a constant-pool and get a memory reference to it.
|
||||
inline Mem newConst(ConstPoolScope scope, const void* data, size_t size) {
|
||||
ASMJIT_INLINE_NODEBUG Mem newConst(ConstPoolScope scope, const void* data, size_t size) {
|
||||
Mem m(Globals::NoInit);
|
||||
_newConst(&m, scope, data, size);
|
||||
return m;
|
||||
}
|
||||
|
||||
//! Put a BYTE `val` to a constant-pool.
|
||||
inline Mem newByteConst(ConstPoolScope scope, uint8_t val) noexcept { return newConst(scope, &val, 1); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newByteConst(ConstPoolScope scope, uint8_t val) noexcept { return newConst(scope, &val, 1); }
|
||||
//! Put a WORD `val` to a constant-pool.
|
||||
inline Mem newWordConst(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newWordConst(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
|
||||
//! Put a DWORD `val` to a constant-pool.
|
||||
inline Mem newDWordConst(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newDWordConst(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
|
||||
//! Put a QWORD `val` to a constant-pool.
|
||||
inline Mem newQWordConst(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newQWordConst(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
|
||||
|
||||
//! Put a WORD `val` to a constant-pool.
|
||||
inline Mem newInt16Const(ConstPoolScope scope, int16_t val) noexcept { return newConst(scope, &val, 2); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newInt16Const(ConstPoolScope scope, int16_t val) noexcept { return newConst(scope, &val, 2); }
|
||||
//! Put a WORD `val` to a constant-pool.
|
||||
inline Mem newUInt16Const(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newUInt16Const(ConstPoolScope scope, uint16_t val) noexcept { return newConst(scope, &val, 2); }
|
||||
//! Put a DWORD `val` to a constant-pool.
|
||||
inline Mem newInt32Const(ConstPoolScope scope, int32_t val) noexcept { return newConst(scope, &val, 4); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newInt32Const(ConstPoolScope scope, int32_t val) noexcept { return newConst(scope, &val, 4); }
|
||||
//! Put a DWORD `val` to a constant-pool.
|
||||
inline Mem newUInt32Const(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newUInt32Const(ConstPoolScope scope, uint32_t val) noexcept { return newConst(scope, &val, 4); }
|
||||
//! Put a QWORD `val` to a constant-pool.
|
||||
inline Mem newInt64Const(ConstPoolScope scope, int64_t val) noexcept { return newConst(scope, &val, 8); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newInt64Const(ConstPoolScope scope, int64_t val) noexcept { return newConst(scope, &val, 8); }
|
||||
//! Put a QWORD `val` to a constant-pool.
|
||||
inline Mem newUInt64Const(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newUInt64Const(ConstPoolScope scope, uint64_t val) noexcept { return newConst(scope, &val, 8); }
|
||||
|
||||
//! Put a SP-FP `val` to a constant-pool.
|
||||
inline Mem newFloatConst(ConstPoolScope scope, float val) noexcept { return newConst(scope, &val, 4); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newFloatConst(ConstPoolScope scope, float val) noexcept { return newConst(scope, &val, 4); }
|
||||
//! Put a DP-FP `val` to a constant-pool.
|
||||
inline Mem newDoubleConst(ConstPoolScope scope, double val) noexcept { return newConst(scope, &val, 8); }
|
||||
ASMJIT_INLINE_NODEBUG Mem newDoubleConst(ConstPoolScope scope, double val) noexcept { return newConst(scope, &val, 8); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -652,9 +652,9 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Force the compiler to not follow the conditional or unconditional jump.
|
||||
inline Compiler& unfollow() noexcept { addInstOptions(InstOptions::kUnfollow); return *this; }
|
||||
ASMJIT_INLINE_NODEBUG Compiler& unfollow() noexcept { addInstOptions(InstOptions::kUnfollow); return *this; }
|
||||
//! Tell the compiler that the destination variable will be overwritten.
|
||||
inline Compiler& overwrite() noexcept { addInstOptions(InstOptions::kOverwrite); return *this; }
|
||||
ASMJIT_INLINE_NODEBUG Compiler& overwrite() noexcept { addInstOptions(InstOptions::kOverwrite); return *this; }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -662,7 +662,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Invoke a function call without `target` type enforcement.
|
||||
inline Error invoke_(InvokeNode** out, const Operand_& target, const FuncSignature& signature) {
|
||||
ASMJIT_INLINE_NODEBUG Error invoke_(InvokeNode** out, const Operand_& target, const FuncSignature& signature) {
|
||||
return addInvokeNode(out, Inst::kIdCall, target, signature);
|
||||
}
|
||||
|
||||
@@ -671,22 +671,22 @@ public:
|
||||
//! Creates a new \ref InvokeNode, initializes all the necessary members to match the given function `signature`,
|
||||
//! adds the node to the compiler, and stores its pointer to `out`. The operation is atomic, if anything fails
|
||||
//! nullptr is stored in `out` and error code is returned.
|
||||
inline Error invoke(InvokeNode** out, const Gp& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Gp& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
//! \overload
|
||||
inline Error invoke(InvokeNode** out, const Mem& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Mem& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
//! \overload
|
||||
inline Error invoke(InvokeNode** out, const Label& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Label& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
//! \overload
|
||||
inline Error invoke(InvokeNode** out, const Imm& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, const Imm& target, const FuncSignature& signature) { return invoke_(out, target, signature); }
|
||||
//! \overload
|
||||
inline Error invoke(InvokeNode** out, uint64_t target, const FuncSignature& signature) { return invoke_(out, Imm(int64_t(target)), signature); }
|
||||
ASMJIT_INLINE_NODEBUG Error invoke(InvokeNode** out, uint64_t target, const FuncSignature& signature) { return invoke_(out, Imm(int64_t(target)), signature); }
|
||||
|
||||
//! Return from function.
|
||||
inline Error ret() { return addRet(Operand(), Operand()); }
|
||||
ASMJIT_INLINE_NODEBUG Error ret() { return addRet(Operand(), Operand()); }
|
||||
//! \overload
|
||||
inline Error ret(const BaseReg& o0) { return addRet(o0, Operand()); }
|
||||
ASMJIT_INLINE_NODEBUG Error ret(const BaseReg& o0) { return addRet(o0, Operand()); }
|
||||
//! \overload
|
||||
inline Error ret(const BaseReg& o0, const BaseReg& o1) { return addRet(o0, o1); }
|
||||
ASMJIT_INLINE_NODEBUG Error ret(const BaseReg& o0, const BaseReg& o1) { return addRet(o0, o1); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -696,9 +696,9 @@ public:
|
||||
using EmitterExplicitT<Compiler>::jmp;
|
||||
|
||||
//! Adds a jump to the given `target` with the provided jump `annotation`.
|
||||
inline Error jmp(const BaseReg& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdJmp, target, annotation); }
|
||||
ASMJIT_INLINE_NODEBUG Error jmp(const BaseReg& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdJmp, target, annotation); }
|
||||
//! \overload
|
||||
inline Error jmp(const BaseMem& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdJmp, target, annotation); }
|
||||
ASMJIT_INLINE_NODEBUG Error jmp(const BaseMem& target, JumpAnnotation* annotation) { return emitAnnotatedJump(Inst::kIdJmp, target, annotation); }
|
||||
|
||||
//! \}
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
|
||||
//! \addtogroup asmjit_x86
|
||||
//! \{
|
||||
|
||||
static inline RegType vecTypeIdToRegType(TypeId typeId) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG RegType vecTypeIdToRegType(TypeId typeId) noexcept {
|
||||
return uint32_t(typeId) <= uint32_t(TypeId::_kVec128End) ? RegType::kX86_Xmm :
|
||||
uint32_t(typeId) <= uint32_t(TypeId::_kVec256End) ? RegType::kX86_Ymm : RegType::kX86_Zmm;
|
||||
}
|
||||
@@ -29,7 +29,7 @@ public:
|
||||
bool _avxEnabled;
|
||||
bool _avx512Enabled;
|
||||
|
||||
inline explicit EmitHelper(BaseEmitter* emitter = nullptr, bool avxEnabled = false, bool avx512Enabled = false) noexcept
|
||||
ASMJIT_INLINE_NODEBUG explicit EmitHelper(BaseEmitter* emitter = nullptr, bool avxEnabled = false, bool avx512Enabled = false) noexcept
|
||||
: BaseEmitHelper(emitter),
|
||||
_avxEnabled(avxEnabled || avx512Enabled),
|
||||
_avx512Enabled(avx512Enabled) {}
|
||||
|
||||
@@ -105,9 +105,9 @@ static constexpr CondCode _reverseCondTable[] = {
|
||||
//! \endcond
|
||||
|
||||
//! Reverses a condition code (reverses the corresponding operands of a comparison).
|
||||
static inline constexpr CondCode reverseCond(CondCode cond) noexcept { return _reverseCondTable[uint8_t(cond)]; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr CondCode reverseCond(CondCode cond) noexcept { return _reverseCondTable[uint8_t(cond)]; }
|
||||
//! Negates a condition code.
|
||||
static inline constexpr CondCode negateCond(CondCode cond) noexcept { return CondCode(uint8_t(cond) ^ 1u); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr CondCode negateCond(CondCode cond) noexcept { return CondCode(uint8_t(cond) ^ 1u); }
|
||||
|
||||
//! Instruction.
|
||||
//!
|
||||
@@ -1843,7 +1843,7 @@ namespace Inst {
|
||||
};
|
||||
|
||||
//! Tests whether the `instId` is defined.
|
||||
static inline constexpr bool isDefinedId(InstId instId) noexcept { return instId < _kIdCount; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr bool isDefinedId(InstId instId) noexcept { return instId < _kIdCount; }
|
||||
|
||||
//! \cond
|
||||
#define ASMJIT_INST_FROM_COND(ID) \
|
||||
@@ -1860,11 +1860,11 @@ namespace Inst {
|
||||
//! \endcond
|
||||
|
||||
//! Translates a condition code `cond` to a `jcc` instruction id.
|
||||
static constexpr InstId jccFromCond(CondCode cond) noexcept { return _jccTable[uint8_t(cond)]; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr InstId jccFromCond(CondCode cond) noexcept { return _jccTable[uint8_t(cond)]; }
|
||||
//! Translates a condition code `cond` to a `setcc` instruction id.
|
||||
static constexpr InstId setccFromCond(CondCode cond) noexcept { return _setccTable[uint8_t(cond)]; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr InstId setccFromCond(CondCode cond) noexcept { return _setccTable[uint8_t(cond)]; }
|
||||
//! Translates a condition code `cond` to a `cmovcc` instruction id.
|
||||
static constexpr InstId cmovccFromCond(CondCode cond) noexcept { return _cmovccTable[uint8_t(cond)]; }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr InstId cmovccFromCond(CondCode cond) noexcept { return _cmovccTable[uint8_t(cond)]; }
|
||||
} // {Inst}
|
||||
|
||||
//! FPU status word bits.
|
||||
@@ -2144,7 +2144,7 @@ enum class VReduceImm : uint8_t {
|
||||
ASMJIT_DEFINE_ENUM_FLAGS(VReduceImm)
|
||||
|
||||
//! Creates a \ref VReduceImm from a combination of `flags` and `fixedPointLength`.
|
||||
static inline constexpr VReduceImm vReduceImm(VReduceImm flags, uint32_t fixedPointLength) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr VReduceImm vReduceImm(VReduceImm flags, uint32_t fixedPointLength) noexcept {
|
||||
return flags | VReduceImm(fixedPointLength << 4);
|
||||
}
|
||||
|
||||
@@ -2179,7 +2179,7 @@ enum class TLogImm : uint8_t {
|
||||
ASMJIT_DEFINE_ENUM_FLAGS(TLogImm)
|
||||
|
||||
//! Creates an immediate that can be used by VPTERNLOG[D|Q] instructions.
|
||||
static inline constexpr TLogImm tLogFromBits(uint8_t b000, uint8_t b001, uint8_t b010, uint8_t b011, uint8_t b100, uint8_t b101, uint8_t b110, uint8_t b111) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr TLogImm tLogFromBits(uint8_t b000, uint8_t b001, uint8_t b010, uint8_t b011, uint8_t b100, uint8_t b101, uint8_t b110, uint8_t b111) noexcept {
|
||||
return TLogImm(uint8_t(b000 << 0) |
|
||||
uint8_t(b001 << 1) |
|
||||
uint8_t(b010 << 2) |
|
||||
@@ -2191,7 +2191,7 @@ static inline constexpr TLogImm tLogFromBits(uint8_t b000, uint8_t b001, uint8_t
|
||||
}
|
||||
|
||||
//! Creates an if/else logic that can be used by VPTERNLOG[D|Q] instructions.
|
||||
static inline constexpr TLogImm fLogIfElse(TLogImm condition, TLogImm a, TLogImm b) noexcept { return (condition & a) | (~condition & b); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr TLogImm fLogIfElse(TLogImm condition, TLogImm a, TLogImm b) noexcept { return (condition & a) | (~condition & b); }
|
||||
|
||||
//! Creates a shuffle immediate value that be used with SSE/AVX/AVX-512 instructions to shuffle 2 elements in a vector.
|
||||
//!
|
||||
@@ -2200,7 +2200,7 @@ static inline constexpr TLogImm fLogIfElse(TLogImm condition, TLogImm a, TLogImm
|
||||
//!
|
||||
//! Shuffle constants can be used to encode an immediate for these instructions:
|
||||
//! - `shufpd|vshufpd`
|
||||
static inline constexpr uint32_t shuffleImm(uint32_t a, uint32_t b) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr uint32_t shuffleImm(uint32_t a, uint32_t b) noexcept {
|
||||
return (a << 1) | b;
|
||||
}
|
||||
|
||||
@@ -2217,7 +2217,7 @@ static inline constexpr uint32_t shuffleImm(uint32_t a, uint32_t b) noexcept {
|
||||
//! - `pshufhw|vpshufhw`
|
||||
//! - `pshufd|vpshufd`
|
||||
//! - `shufps|vshufps`
|
||||
static inline constexpr uint32_t shuffleImm(uint32_t a, uint32_t b, uint32_t c, uint32_t d) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr uint32_t shuffleImm(uint32_t a, uint32_t b, uint32_t c, uint32_t d) noexcept {
|
||||
return (a << 6) | (b << 4) | (c << 2) | d;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ enum class Mode : uint8_t {
|
||||
ASMJIT_DEFINE_ENUM_FLAGS(Mode)
|
||||
|
||||
//! Converts architecture to operation mode, see \ref Mode.
|
||||
static constexpr Mode modeFromArch(Arch arch) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mode modeFromArch(Arch arch) noexcept {
|
||||
return arch == Arch::kX86 ? Mode::kX86 :
|
||||
arch == Arch::kX64 ? Mode::kX64 : Mode::kNone;
|
||||
}
|
||||
@@ -348,92 +348,92 @@ struct CommonInfo {
|
||||
//! \{
|
||||
|
||||
//! Returns instruction flags.
|
||||
inline InstFlags flags() const noexcept { return (InstFlags)_flags; }
|
||||
ASMJIT_INLINE_NODEBUG InstFlags flags() const noexcept { return (InstFlags)_flags; }
|
||||
//! Tests whether the instruction has a `flag`.
|
||||
inline bool hasFlag(InstFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(InstFlags flag) const noexcept { return Support::test(_flags, flag); }
|
||||
|
||||
//! Returns instruction AVX-512 flags.
|
||||
inline Avx512Flags avx512Flags() const noexcept { return (Avx512Flags)_avx512Flags; }
|
||||
ASMJIT_INLINE_NODEBUG Avx512Flags avx512Flags() const noexcept { return (Avx512Flags)_avx512Flags; }
|
||||
//! Tests whether the instruction has an AVX-512 `flag`.
|
||||
inline bool hasAvx512Flag(Avx512Flags flag) const noexcept { return Support::test(_avx512Flags, flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512Flag(Avx512Flags flag) const noexcept { return Support::test(_avx512Flags, flag); }
|
||||
|
||||
//! Tests whether the instruction is FPU instruction.
|
||||
inline bool isFpu() const noexcept { return hasFlag(InstFlags::kFpu); }
|
||||
ASMJIT_INLINE_NODEBUG bool isFpu() const noexcept { return hasFlag(InstFlags::kFpu); }
|
||||
//! Tests whether the instruction is MMX/3DNOW instruction that accesses MMX registers (includes EMMS and FEMMS).
|
||||
inline bool isMmx() const noexcept { return hasFlag(InstFlags::kMmx); }
|
||||
ASMJIT_INLINE_NODEBUG bool isMmx() const noexcept { return hasFlag(InstFlags::kMmx); }
|
||||
//! Tests whether the instruction is SSE|AVX|AVX512 instruction that accesses XMM|YMM|ZMM registers.
|
||||
inline bool isVec() const noexcept { return hasFlag(InstFlags::kVec); }
|
||||
ASMJIT_INLINE_NODEBUG bool isVec() const noexcept { return hasFlag(InstFlags::kVec); }
|
||||
//! Tests whether the instruction is SSE+ (SSE4.2, AES, SHA included) instruction that accesses XMM registers.
|
||||
inline bool isSse() const noexcept { return (flags() & (InstFlags::kVec | InstFlags::kVex | InstFlags::kEvex)) == InstFlags::kVec; }
|
||||
ASMJIT_INLINE_NODEBUG bool isSse() const noexcept { return (flags() & (InstFlags::kVec | InstFlags::kVex | InstFlags::kEvex)) == InstFlags::kVec; }
|
||||
//! Tests whether the instruction is AVX+ (FMA included) instruction that accesses XMM|YMM|ZMM registers.
|
||||
inline bool isAvx() const noexcept { return isVec() && isVexOrEvex(); }
|
||||
ASMJIT_INLINE_NODEBUG bool isAvx() const noexcept { return isVec() && isVexOrEvex(); }
|
||||
|
||||
//! Tests whether the instruction can be prefixed with LOCK prefix.
|
||||
inline bool hasLockPrefix() const noexcept { return hasFlag(InstFlags::kLock); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasLockPrefix() const noexcept { return hasFlag(InstFlags::kLock); }
|
||||
//! Tests whether the instruction can be prefixed with REP (REPE|REPZ) prefix.
|
||||
inline bool hasRepPrefix() const noexcept { return hasFlag(InstFlags::kRep); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasRepPrefix() const noexcept { return hasFlag(InstFlags::kRep); }
|
||||
//! Tests whether the instruction can be prefixed with XACQUIRE prefix.
|
||||
inline bool hasXAcquirePrefix() const noexcept { return hasFlag(InstFlags::kXAcquire); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasXAcquirePrefix() const noexcept { return hasFlag(InstFlags::kXAcquire); }
|
||||
//! Tests whether the instruction can be prefixed with XRELEASE prefix.
|
||||
inline bool hasXReleasePrefix() const noexcept { return hasFlag(InstFlags::kXRelease); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasXReleasePrefix() const noexcept { return hasFlag(InstFlags::kXRelease); }
|
||||
|
||||
//! Tests whether the rep prefix is supported by the instruction, but ignored (has no effect).
|
||||
inline bool isRepIgnored() const noexcept { return hasFlag(InstFlags::kRepIgnored); }
|
||||
ASMJIT_INLINE_NODEBUG bool isRepIgnored() const noexcept { return hasFlag(InstFlags::kRepIgnored); }
|
||||
//! Tests whether the instruction uses MIB.
|
||||
inline bool isMibOp() const noexcept { return hasFlag(InstFlags::kMib); }
|
||||
ASMJIT_INLINE_NODEBUG bool isMibOp() const noexcept { return hasFlag(InstFlags::kMib); }
|
||||
//! Tests whether the instruction uses VSIB.
|
||||
inline bool isVsibOp() const noexcept { return hasFlag(InstFlags::kVsib); }
|
||||
ASMJIT_INLINE_NODEBUG bool isVsibOp() const noexcept { return hasFlag(InstFlags::kVsib); }
|
||||
//! Tests whether the instruction uses TSIB (AMX, instruction requires MOD+SIB).
|
||||
inline bool isTsibOp() const noexcept { return hasFlag(InstFlags::kTsib); }
|
||||
ASMJIT_INLINE_NODEBUG bool isTsibOp() const noexcept { return hasFlag(InstFlags::kTsib); }
|
||||
//! Tests whether the instruction uses VEX (can be set together with EVEX if both are encodable).
|
||||
inline bool isVex() const noexcept { return hasFlag(InstFlags::kVex); }
|
||||
ASMJIT_INLINE_NODEBUG bool isVex() const noexcept { return hasFlag(InstFlags::kVex); }
|
||||
//! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable).
|
||||
inline bool isEvex() const noexcept { return hasFlag(InstFlags::kEvex); }
|
||||
ASMJIT_INLINE_NODEBUG bool isEvex() const noexcept { return hasFlag(InstFlags::kEvex); }
|
||||
//! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable).
|
||||
inline bool isVexOrEvex() const noexcept { return hasFlag(InstFlags::kVex | InstFlags::kEvex); }
|
||||
ASMJIT_INLINE_NODEBUG bool isVexOrEvex() const noexcept { return hasFlag(InstFlags::kVex | InstFlags::kEvex); }
|
||||
|
||||
//! Tests whether the instruction should prefer EVEX prefix instead of VEX prefix.
|
||||
inline bool preferEvex() const noexcept { return hasFlag(InstFlags::kPreferEvex); }
|
||||
ASMJIT_INLINE_NODEBUG bool preferEvex() const noexcept { return hasFlag(InstFlags::kPreferEvex); }
|
||||
|
||||
inline bool isEvexCompatible() const noexcept { return hasFlag(InstFlags::kEvexCompat); }
|
||||
inline bool isEvexKRegOnly() const noexcept { return hasFlag(InstFlags::kEvexKReg); }
|
||||
inline bool isEvexTwoOpOnly() const noexcept { return hasFlag(InstFlags::kEvexTwoOp); }
|
||||
inline bool isEvexTransformable() const noexcept { return hasFlag(InstFlags::kEvexTransformable); }
|
||||
ASMJIT_INLINE_NODEBUG bool isEvexCompatible() const noexcept { return hasFlag(InstFlags::kEvexCompat); }
|
||||
ASMJIT_INLINE_NODEBUG bool isEvexKRegOnly() const noexcept { return hasFlag(InstFlags::kEvexKReg); }
|
||||
ASMJIT_INLINE_NODEBUG bool isEvexTwoOpOnly() const noexcept { return hasFlag(InstFlags::kEvexTwoOp); }
|
||||
ASMJIT_INLINE_NODEBUG bool isEvexTransformable() const noexcept { return hasFlag(InstFlags::kEvexTransformable); }
|
||||
|
||||
//! Tests whether the instruction supports AVX512 masking {k}.
|
||||
inline bool hasAvx512K() const noexcept { return hasAvx512Flag(Avx512Flags::kK); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512K() const noexcept { return hasAvx512Flag(Avx512Flags::kK); }
|
||||
//! Tests whether the instruction supports AVX512 zeroing {k}{z}.
|
||||
inline bool hasAvx512Z() const noexcept { return hasAvx512Flag(Avx512Flags::kZ); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512Z() const noexcept { return hasAvx512Flag(Avx512Flags::kZ); }
|
||||
//! Tests whether the instruction supports AVX512 embedded-rounding {er}.
|
||||
inline bool hasAvx512ER() const noexcept { return hasAvx512Flag(Avx512Flags::kER); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512ER() const noexcept { return hasAvx512Flag(Avx512Flags::kER); }
|
||||
//! Tests whether the instruction supports AVX512 suppress-all-exceptions {sae}.
|
||||
inline bool hasAvx512SAE() const noexcept { return hasAvx512Flag(Avx512Flags::kSAE); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512SAE() const noexcept { return hasAvx512Flag(Avx512Flags::kSAE); }
|
||||
//! Tests whether the instruction supports AVX512 broadcast (either 32-bit or 64-bit).
|
||||
inline bool hasAvx512B() const noexcept { return hasAvx512Flag(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512B() const noexcept { return hasAvx512Flag(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64); }
|
||||
//! Tests whether the instruction supports AVX512 broadcast (16-bit).
|
||||
inline bool hasAvx512B16() const noexcept { return hasAvx512Flag(Avx512Flags::kB16); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512B16() const noexcept { return hasAvx512Flag(Avx512Flags::kB16); }
|
||||
//! Tests whether the instruction supports AVX512 broadcast (32-bit).
|
||||
inline bool hasAvx512B32() const noexcept { return hasAvx512Flag(Avx512Flags::kB32); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512B32() const noexcept { return hasAvx512Flag(Avx512Flags::kB32); }
|
||||
//! Tests whether the instruction supports AVX512 broadcast (64-bit).
|
||||
inline bool hasAvx512B64() const noexcept { return hasAvx512Flag(Avx512Flags::kB64); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512B64() const noexcept { return hasAvx512Flag(Avx512Flags::kB64); }
|
||||
|
||||
// Returns the size of the broadcast - either 2, 4, or 8, or 0 if broadcast is not supported.
|
||||
inline uint32_t broadcastSize() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG uint32_t broadcastSize() const noexcept {
|
||||
constexpr uint32_t kShift = Support::ConstCTZ<uint32_t(Avx512Flags::kB16)>::value;
|
||||
return (uint32_t(_avx512Flags) & uint32_t(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64)) >> (kShift - 1);
|
||||
}
|
||||
|
||||
inline uint32_t signatureIndex() const noexcept { return _iSignatureIndex; }
|
||||
inline uint32_t signatureCount() const noexcept { return _iSignatureCount; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t signatureIndex() const noexcept { return _iSignatureIndex; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t signatureCount() const noexcept { return _iSignatureCount; }
|
||||
|
||||
inline const InstSignature* signatureData() const noexcept { return _instSignatureTable + _iSignatureIndex; }
|
||||
inline const InstSignature* signatureEnd() const noexcept { return _instSignatureTable + _iSignatureIndex + _iSignatureCount; }
|
||||
ASMJIT_INLINE_NODEBUG const InstSignature* signatureData() const noexcept { return _instSignatureTable + _iSignatureIndex; }
|
||||
ASMJIT_INLINE_NODEBUG const InstSignature* signatureEnd() const noexcept { return _instSignatureTable + _iSignatureIndex + _iSignatureCount; }
|
||||
|
||||
//! Returns a control flow category of the instruction.
|
||||
inline InstControlFlow controlFlow() const noexcept { return (InstControlFlow)_controlFlow; }
|
||||
ASMJIT_INLINE_NODEBUG InstControlFlow controlFlow() const noexcept { return (InstControlFlow)_controlFlow; }
|
||||
|
||||
//! Returns a hint that can be used when both inputs are the same register.
|
||||
inline InstSameRegHint sameRegHint() const noexcept { return (InstSameRegHint)_sameRegHint; }
|
||||
ASMJIT_INLINE_NODEBUG InstSameRegHint sameRegHint() const noexcept { return (InstSameRegHint)_sameRegHint; }
|
||||
|
||||
//! \}
|
||||
};
|
||||
@@ -462,83 +462,83 @@ struct InstInfo {
|
||||
//! \{
|
||||
|
||||
//! Returns common information, see \ref CommonInfo.
|
||||
inline const CommonInfo& commonInfo() const noexcept { return _commonInfoTable[_commonInfoIndex]; }
|
||||
ASMJIT_INLINE_NODEBUG const CommonInfo& commonInfo() const noexcept { return _commonInfoTable[_commonInfoIndex]; }
|
||||
|
||||
//! Returns instruction flags, see \ref Flags.
|
||||
inline InstFlags flags() const noexcept { return commonInfo().flags(); }
|
||||
ASMJIT_INLINE_NODEBUG InstFlags flags() const noexcept { return commonInfo().flags(); }
|
||||
//! Tests whether the instruction has flag `flag`, see \ref Flags.
|
||||
inline bool hasFlag(InstFlags flag) const noexcept { return commonInfo().hasFlag(flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasFlag(InstFlags flag) const noexcept { return commonInfo().hasFlag(flag); }
|
||||
|
||||
//! Returns instruction AVX-512 flags, see \ref Avx512Flags.
|
||||
inline Avx512Flags avx512Flags() const noexcept { return commonInfo().avx512Flags(); }
|
||||
ASMJIT_INLINE_NODEBUG Avx512Flags avx512Flags() const noexcept { return commonInfo().avx512Flags(); }
|
||||
//! Tests whether the instruction has an AVX-512 `flag`, see \ref Avx512Flags.
|
||||
inline bool hasAvx512Flag(Avx512Flags flag) const noexcept { return commonInfo().hasAvx512Flag(flag); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512Flag(Avx512Flags flag) const noexcept { return commonInfo().hasAvx512Flag(flag); }
|
||||
|
||||
//! Tests whether the instruction is FPU instruction.
|
||||
inline bool isFpu() const noexcept { return commonInfo().isFpu(); }
|
||||
ASMJIT_INLINE_NODEBUG bool isFpu() const noexcept { return commonInfo().isFpu(); }
|
||||
//! Tests whether the instruction is MMX/3DNOW instruction that accesses MMX registers (includes EMMS and FEMMS).
|
||||
inline bool isMmx() const noexcept { return commonInfo().isMmx(); }
|
||||
ASMJIT_INLINE_NODEBUG bool isMmx() const noexcept { return commonInfo().isMmx(); }
|
||||
//! Tests whether the instruction is SSE|AVX|AVX512 instruction that accesses XMM|YMM|ZMM registers.
|
||||
inline bool isVec() const noexcept { return commonInfo().isVec(); }
|
||||
ASMJIT_INLINE_NODEBUG bool isVec() const noexcept { return commonInfo().isVec(); }
|
||||
//! Tests whether the instruction is SSE+ (SSE4.2, AES, SHA included) instruction that accesses XMM registers.
|
||||
inline bool isSse() const noexcept { return commonInfo().isSse(); }
|
||||
ASMJIT_INLINE_NODEBUG bool isSse() const noexcept { return commonInfo().isSse(); }
|
||||
//! Tests whether the instruction is AVX+ (FMA included) instruction that accesses XMM|YMM|ZMM registers.
|
||||
inline bool isAvx() const noexcept { return commonInfo().isAvx(); }
|
||||
ASMJIT_INLINE_NODEBUG bool isAvx() const noexcept { return commonInfo().isAvx(); }
|
||||
|
||||
//! Tests whether the instruction can be prefixed with LOCK prefix.
|
||||
inline bool hasLockPrefix() const noexcept { return commonInfo().hasLockPrefix(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasLockPrefix() const noexcept { return commonInfo().hasLockPrefix(); }
|
||||
//! Tests whether the instruction can be prefixed with REP (REPE|REPZ) prefix.
|
||||
inline bool hasRepPrefix() const noexcept { return commonInfo().hasRepPrefix(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasRepPrefix() const noexcept { return commonInfo().hasRepPrefix(); }
|
||||
//! Tests whether the instruction can be prefixed with XACQUIRE prefix.
|
||||
inline bool hasXAcquirePrefix() const noexcept { return commonInfo().hasXAcquirePrefix(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasXAcquirePrefix() const noexcept { return commonInfo().hasXAcquirePrefix(); }
|
||||
//! Tests whether the instruction can be prefixed with XRELEASE prefix.
|
||||
inline bool hasXReleasePrefix() const noexcept { return commonInfo().hasXReleasePrefix(); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasXReleasePrefix() const noexcept { return commonInfo().hasXReleasePrefix(); }
|
||||
|
||||
//! Tests whether the rep prefix is supported by the instruction, but ignored (has no effect).
|
||||
inline bool isRepIgnored() const noexcept { return commonInfo().isRepIgnored(); }
|
||||
ASMJIT_INLINE_NODEBUG bool isRepIgnored() const noexcept { return commonInfo().isRepIgnored(); }
|
||||
//! Tests whether the instruction uses MIB.
|
||||
inline bool isMibOp() const noexcept { return hasFlag(InstFlags::kMib); }
|
||||
ASMJIT_INLINE_NODEBUG bool isMibOp() const noexcept { return hasFlag(InstFlags::kMib); }
|
||||
//! Tests whether the instruction uses VSIB.
|
||||
inline bool isVsibOp() const noexcept { return hasFlag(InstFlags::kVsib); }
|
||||
ASMJIT_INLINE_NODEBUG bool isVsibOp() const noexcept { return hasFlag(InstFlags::kVsib); }
|
||||
//! Tests whether the instruction uses VEX (can be set together with EVEX if both are encodable).
|
||||
inline bool isVex() const noexcept { return hasFlag(InstFlags::kVex); }
|
||||
ASMJIT_INLINE_NODEBUG bool isVex() const noexcept { return hasFlag(InstFlags::kVex); }
|
||||
//! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable).
|
||||
inline bool isEvex() const noexcept { return hasFlag(InstFlags::kEvex); }
|
||||
ASMJIT_INLINE_NODEBUG bool isEvex() const noexcept { return hasFlag(InstFlags::kEvex); }
|
||||
//! Tests whether the instruction uses EVEX (can be set together with VEX if both are encodable).
|
||||
inline bool isVexOrEvex() const noexcept { return hasFlag(InstFlags::kVex | InstFlags::kEvex); }
|
||||
ASMJIT_INLINE_NODEBUG bool isVexOrEvex() const noexcept { return hasFlag(InstFlags::kVex | InstFlags::kEvex); }
|
||||
|
||||
inline bool isEvexCompatible() const noexcept { return hasFlag(InstFlags::kEvexCompat); }
|
||||
inline bool isEvexKRegOnly() const noexcept { return hasFlag(InstFlags::kEvexKReg); }
|
||||
inline bool isEvexTwoOpOnly() const noexcept { return hasFlag(InstFlags::kEvexTwoOp); }
|
||||
inline bool isEvexTransformable() const noexcept { return hasFlag(InstFlags::kEvexTransformable); }
|
||||
ASMJIT_INLINE_NODEBUG bool isEvexCompatible() const noexcept { return hasFlag(InstFlags::kEvexCompat); }
|
||||
ASMJIT_INLINE_NODEBUG bool isEvexKRegOnly() const noexcept { return hasFlag(InstFlags::kEvexKReg); }
|
||||
ASMJIT_INLINE_NODEBUG bool isEvexTwoOpOnly() const noexcept { return hasFlag(InstFlags::kEvexTwoOp); }
|
||||
ASMJIT_INLINE_NODEBUG bool isEvexTransformable() const noexcept { return hasFlag(InstFlags::kEvexTransformable); }
|
||||
|
||||
//! Tests whether the instruction supports AVX512 masking {k}.
|
||||
inline bool hasAvx512K() const noexcept { return hasAvx512Flag(Avx512Flags::kK); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512K() const noexcept { return hasAvx512Flag(Avx512Flags::kK); }
|
||||
//! Tests whether the instruction supports AVX512 zeroing {k}{z}.
|
||||
inline bool hasAvx512Z() const noexcept { return hasAvx512Flag(Avx512Flags::kZ); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512Z() const noexcept { return hasAvx512Flag(Avx512Flags::kZ); }
|
||||
//! Tests whether the instruction supports AVX512 embedded-rounding {er}.
|
||||
inline bool hasAvx512ER() const noexcept { return hasAvx512Flag(Avx512Flags::kER); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512ER() const noexcept { return hasAvx512Flag(Avx512Flags::kER); }
|
||||
//! Tests whether the instruction supports AVX512 suppress-all-exceptions {sae}.
|
||||
inline bool hasAvx512SAE() const noexcept { return hasAvx512Flag(Avx512Flags::kSAE); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512SAE() const noexcept { return hasAvx512Flag(Avx512Flags::kSAE); }
|
||||
//! Tests whether the instruction supports AVX512 broadcast (either 32-bit or 64-bit).
|
||||
inline bool hasAvx512B() const noexcept { return hasAvx512Flag(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512B() const noexcept { return hasAvx512Flag(Avx512Flags::kB16 | Avx512Flags::kB32 | Avx512Flags::kB64); }
|
||||
//! Tests whether the instruction supports AVX512 broadcast (16-bit).
|
||||
inline bool hasAvx512B16() const noexcept { return hasAvx512Flag(Avx512Flags::kB16); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512B16() const noexcept { return hasAvx512Flag(Avx512Flags::kB16); }
|
||||
//! Tests whether the instruction supports AVX512 broadcast (32-bit).
|
||||
inline bool hasAvx512B32() const noexcept { return hasAvx512Flag(Avx512Flags::kB32); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512B32() const noexcept { return hasAvx512Flag(Avx512Flags::kB32); }
|
||||
//! Tests whether the instruction supports AVX512 broadcast (64-bit).
|
||||
inline bool hasAvx512B64() const noexcept { return hasAvx512Flag(Avx512Flags::kB64); }
|
||||
ASMJIT_INLINE_NODEBUG bool hasAvx512B64() const noexcept { return hasAvx512Flag(Avx512Flags::kB64); }
|
||||
|
||||
//! Returns a control flow category of the instruction.
|
||||
inline InstControlFlow controlFlow() const noexcept { return commonInfo().controlFlow(); }
|
||||
ASMJIT_INLINE_NODEBUG InstControlFlow controlFlow() const noexcept { return commonInfo().controlFlow(); }
|
||||
//! Returns a hint that can be used when both inputs are the same register.
|
||||
inline InstSameRegHint sameRegHint() const noexcept { return commonInfo().sameRegHint(); }
|
||||
ASMJIT_INLINE_NODEBUG InstSameRegHint sameRegHint() const noexcept { return commonInfo().sameRegHint(); }
|
||||
|
||||
inline uint32_t signatureIndex() const noexcept { return commonInfo().signatureIndex(); }
|
||||
inline uint32_t signatureCount() const noexcept { return commonInfo().signatureCount(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t signatureIndex() const noexcept { return commonInfo().signatureIndex(); }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t signatureCount() const noexcept { return commonInfo().signatureCount(); }
|
||||
|
||||
inline const InstSignature* signatureData() const noexcept { return commonInfo().signatureData(); }
|
||||
inline const InstSignature* signatureEnd() const noexcept { return commonInfo().signatureEnd(); }
|
||||
ASMJIT_INLINE_NODEBUG const InstSignature* signatureData() const noexcept { return commonInfo().signatureData(); }
|
||||
ASMJIT_INLINE_NODEBUG const InstSignature* signatureEnd() const noexcept { return commonInfo().signatureEnd(); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
@@ -336,27 +336,27 @@ struct Opcode {
|
||||
// Opcode Builder
|
||||
// --------------
|
||||
|
||||
inline uint32_t get() const noexcept { return v; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t get() const noexcept { return v; }
|
||||
|
||||
inline bool hasW() const noexcept { return (v & kW) != 0; }
|
||||
inline bool has66h() const noexcept { return (v & kPP_66) != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool hasW() const noexcept { return (v & kW) != 0; }
|
||||
ASMJIT_INLINE_NODEBUG bool has66h() const noexcept { return (v & kPP_66) != 0; }
|
||||
|
||||
inline Opcode& add(uint32_t x) noexcept { return operator+=(x); }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& add(uint32_t x) noexcept { return operator+=(x); }
|
||||
|
||||
inline Opcode& add66h() noexcept { return operator|=(kPP_66); }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& add66h() noexcept { return operator|=(kPP_66); }
|
||||
template<typename T>
|
||||
inline Opcode& add66hIf(T exp) noexcept { return operator|=(uint32_t(exp) << kPP_Shift); }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& add66hIf(T exp) noexcept { return operator|=(uint32_t(exp) << kPP_Shift); }
|
||||
template<typename T>
|
||||
inline Opcode& add66hBySize(T size) noexcept { return add66hIf(size == 2); }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& add66hBySize(T size) noexcept { return add66hIf(size == 2); }
|
||||
|
||||
inline Opcode& addW() noexcept { return operator|=(kW); }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& addW() noexcept { return operator|=(kW); }
|
||||
template<typename T>
|
||||
inline Opcode& addWIf(T exp) noexcept { return operator|=(uint32_t(exp) << kW_Shift); }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& addWIf(T exp) noexcept { return operator|=(uint32_t(exp) << kW_Shift); }
|
||||
template<typename T>
|
||||
inline Opcode& addWBySize(T size) noexcept { return addWIf(size == 8); }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& addWBySize(T size) noexcept { return addWIf(size == 8); }
|
||||
|
||||
template<typename T>
|
||||
inline Opcode& addPrefixBySize(T size) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Opcode& addPrefixBySize(T size) noexcept {
|
||||
static const uint32_t mask[16] = {
|
||||
0, // #0
|
||||
0, // #1 -> nothing (already handled or not possible)
|
||||
@@ -372,7 +372,7 @@ struct Opcode {
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline Opcode& addArithBySize(T size) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Opcode& addArithBySize(T size) noexcept {
|
||||
static const uint32_t mask[16] = {
|
||||
0, // #0
|
||||
0, // #1 -> nothing
|
||||
@@ -387,45 +387,45 @@ struct Opcode {
|
||||
return operator|=(mask[size & 0xF]);
|
||||
}
|
||||
|
||||
inline Opcode& forceEvex() noexcept { return operator|=(kMM_ForceEvex); }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& forceEvex() noexcept { return operator|=(kMM_ForceEvex); }
|
||||
template<typename T>
|
||||
inline Opcode& forceEvexIf(T exp) noexcept { return operator|=(uint32_t(exp) << Support::ConstCTZ<uint32_t(kMM_ForceEvex)>::value); }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& forceEvexIf(T exp) noexcept { return operator|=(uint32_t(exp) << Support::ConstCTZ<uint32_t(kMM_ForceEvex)>::value); }
|
||||
|
||||
//! Extract `O` field (R) from the opcode (specified as /0..7 in instruction manuals).
|
||||
inline uint32_t extractModO() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG uint32_t extractModO() const noexcept {
|
||||
return (v >> kModO_Shift) & 0x07;
|
||||
}
|
||||
|
||||
//! Extract `RM` field (RM) from the opcode (usually specified as another opcode value).
|
||||
inline uint32_t extractModRM() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG uint32_t extractModRM() const noexcept {
|
||||
return (v >> kModRM_Shift) & 0x07;
|
||||
}
|
||||
|
||||
//! Extract `REX` prefix from opcode combined with `options`.
|
||||
inline uint32_t extractRex(InstOptions options) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG uint32_t extractRex(InstOptions options) const noexcept {
|
||||
// kREX was designed in a way that when shifted there will be no bytes set except REX.[B|X|R|W].
|
||||
// The returned value forms a real REX prefix byte. This case should be unit-tested as well.
|
||||
return (v | uint32_t(options)) >> kREX_Shift;
|
||||
}
|
||||
|
||||
inline uint32_t extractLLMMMMM(InstOptions options) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG uint32_t extractLLMMMMM(InstOptions options) const noexcept {
|
||||
uint32_t llMmmmm = uint32_t(v & (kLL_Mask | kMM_Mask));
|
||||
uint32_t vexEvex = uint32_t(options & InstOptions::kX86_Evex);
|
||||
return (llMmmmm | vexEvex) >> kMM_Shift;
|
||||
}
|
||||
|
||||
inline Opcode& operator=(uint32_t x) noexcept { v = x; return *this; }
|
||||
inline Opcode& operator+=(uint32_t x) noexcept { v += x; return *this; }
|
||||
inline Opcode& operator-=(uint32_t x) noexcept { v -= x; return *this; }
|
||||
inline Opcode& operator&=(uint32_t x) noexcept { v &= x; return *this; }
|
||||
inline Opcode& operator|=(uint32_t x) noexcept { v |= x; return *this; }
|
||||
inline Opcode& operator^=(uint32_t x) noexcept { v ^= x; return *this; }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& operator=(uint32_t x) noexcept { v = x; return *this; }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& operator+=(uint32_t x) noexcept { v += x; return *this; }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& operator-=(uint32_t x) noexcept { v -= x; return *this; }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& operator&=(uint32_t x) noexcept { v &= x; return *this; }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& operator|=(uint32_t x) noexcept { v |= x; return *this; }
|
||||
ASMJIT_INLINE_NODEBUG Opcode& operator^=(uint32_t x) noexcept { v ^= x; return *this; }
|
||||
|
||||
inline uint32_t operator&(uint32_t x) const noexcept { return v & x; }
|
||||
inline uint32_t operator|(uint32_t x) const noexcept { return v | x; }
|
||||
inline uint32_t operator^(uint32_t x) const noexcept { return v ^ x; }
|
||||
inline uint32_t operator<<(uint32_t x) const noexcept { return v << x; }
|
||||
inline uint32_t operator>>(uint32_t x) const noexcept { return v >> x; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t operator&(uint32_t x) const noexcept { return v & x; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t operator|(uint32_t x) const noexcept { return v | x; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t operator^(uint32_t x) const noexcept { return v ^ x; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t operator<<(uint32_t x) const noexcept { return v << x; }
|
||||
ASMJIT_INLINE_NODEBUG uint32_t operator>>(uint32_t x) const noexcept { return v >> x; }
|
||||
};
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -77,121 +77,121 @@ public:
|
||||
ASMJIT_DEFINE_ABSTRACT_REG(Reg, BaseReg)
|
||||
|
||||
//! Tests whether the register is a GPB register (8-bit).
|
||||
inline constexpr bool isGpb() const noexcept { return size() == 1; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isGpb() const noexcept { return size() == 1; }
|
||||
//! Tests whether the register is a low GPB register (8-bit).
|
||||
inline constexpr bool isGpbLo() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_GpbLo>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isGpbLo() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_GpbLo>::kSignature); }
|
||||
//! Tests whether the register is a high GPB register (8-bit).
|
||||
inline constexpr bool isGpbHi() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_GpbHi>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isGpbHi() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_GpbHi>::kSignature); }
|
||||
//! Tests whether the register is a GPW register (16-bit).
|
||||
inline constexpr bool isGpw() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpw>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isGpw() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpw>::kSignature); }
|
||||
//! Tests whether the register is a GPD register (32-bit).
|
||||
inline constexpr bool isGpd() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpd>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isGpd() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpd>::kSignature); }
|
||||
//! Tests whether the register is a GPQ register (64-bit).
|
||||
inline constexpr bool isGpq() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpq>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isGpq() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Gpq>::kSignature); }
|
||||
//! Tests whether the register is an XMM register (128-bit).
|
||||
inline constexpr bool isXmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Xmm>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isXmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Xmm>::kSignature); }
|
||||
//! Tests whether the register is a YMM register (256-bit).
|
||||
inline constexpr bool isYmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Ymm>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isYmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Ymm>::kSignature); }
|
||||
//! Tests whether the register is a ZMM register (512-bit).
|
||||
inline constexpr bool isZmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Zmm>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isZmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Zmm>::kSignature); }
|
||||
//! Tests whether the register is an MMX register (64-bit).
|
||||
inline constexpr bool isMm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Mm>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isMm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Mm>::kSignature); }
|
||||
//! Tests whether the register is a K register (64-bit).
|
||||
inline constexpr bool isKReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_KReg>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isKReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_KReg>::kSignature); }
|
||||
//! Tests whether the register is a segment register.
|
||||
inline constexpr bool isSReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_SReg>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isSReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_SReg>::kSignature); }
|
||||
//! Tests whether the register is a control register.
|
||||
inline constexpr bool isCReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_CReg>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isCReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_CReg>::kSignature); }
|
||||
//! Tests whether the register is a debug register.
|
||||
inline constexpr bool isDReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_DReg>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isDReg() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_DReg>::kSignature); }
|
||||
//! Tests whether the register is an FPU register (80-bit).
|
||||
inline constexpr bool isSt() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_St>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isSt() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_St>::kSignature); }
|
||||
//! Tests whether the register is a bound register.
|
||||
inline constexpr bool isBnd() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Bnd>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isBnd() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Bnd>::kSignature); }
|
||||
//! Tests whether the register is a TMM register.
|
||||
inline constexpr bool isTmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Tmm>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isTmm() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Tmm>::kSignature); }
|
||||
//! Tests whether the register is RIP.
|
||||
inline constexpr bool isRip() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Rip>::kSignature); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isRip() const noexcept { return hasBaseSignature(RegTraits<RegType::kX86_Rip>::kSignature); }
|
||||
|
||||
template<RegType REG_TYPE>
|
||||
inline void setRegT(uint32_t rId) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void setRegT(uint32_t rId) noexcept {
|
||||
setSignature(OperandSignature{RegTraits<REG_TYPE>::kSignature});
|
||||
setId(rId);
|
||||
}
|
||||
|
||||
inline void setTypeAndId(RegType type, uint32_t id) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void setTypeAndId(RegType type, uint32_t id) noexcept {
|
||||
setSignature(signatureOf(type));
|
||||
setId(id);
|
||||
}
|
||||
|
||||
static inline RegGroup groupOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToGroup(type); }
|
||||
static inline TypeId typeIdOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToTypeId(type); }
|
||||
static inline OperandSignature signatureOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToSignature(type); }
|
||||
static ASMJIT_INLINE_NODEBUG RegGroup groupOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToGroup(type); }
|
||||
static ASMJIT_INLINE_NODEBUG TypeId typeIdOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToTypeId(type); }
|
||||
static ASMJIT_INLINE_NODEBUG OperandSignature signatureOf(RegType type) noexcept { return ArchTraits::byArch(Arch::kX86).regTypeToSignature(type); }
|
||||
|
||||
template<RegType REG_TYPE>
|
||||
static inline RegGroup groupOfT() noexcept { return RegGroup(RegTraits<REG_TYPE>::kGroup); }
|
||||
static ASMJIT_INLINE_NODEBUG RegGroup groupOfT() noexcept { return RegGroup(RegTraits<REG_TYPE>::kGroup); }
|
||||
|
||||
template<RegType REG_TYPE>
|
||||
static inline TypeId typeIdOfT() noexcept { return TypeId(RegTraits<REG_TYPE>::kTypeId); }
|
||||
static ASMJIT_INLINE_NODEBUG TypeId typeIdOfT() noexcept { return TypeId(RegTraits<REG_TYPE>::kTypeId); }
|
||||
|
||||
template<RegType REG_TYPE>
|
||||
static inline OperandSignature signatureOfT() noexcept { return OperandSignature{RegTraits<REG_TYPE>::kSignature}; }
|
||||
static ASMJIT_INLINE_NODEBUG OperandSignature signatureOfT() noexcept { return OperandSignature{RegTraits<REG_TYPE>::kSignature}; }
|
||||
|
||||
static inline OperandSignature signatureOfVecByType(TypeId typeId) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG OperandSignature signatureOfVecByType(TypeId typeId) noexcept {
|
||||
return OperandSignature{typeId <= TypeId::_kVec128End ? uint32_t(RegTraits<RegType::kX86_Xmm>::kSignature) :
|
||||
typeId <= TypeId::_kVec256End ? uint32_t(RegTraits<RegType::kX86_Ymm>::kSignature) :
|
||||
uint32_t(RegTraits<RegType::kX86_Zmm>::kSignature)};
|
||||
}
|
||||
|
||||
static inline OperandSignature signatureOfVecBySize(uint32_t size) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG OperandSignature signatureOfVecBySize(uint32_t size) noexcept {
|
||||
return OperandSignature{size <= 16 ? uint32_t(RegTraits<RegType::kX86_Xmm>::kSignature) :
|
||||
size <= 32 ? uint32_t(RegTraits<RegType::kX86_Ymm>::kSignature) :
|
||||
uint32_t(RegTraits<RegType::kX86_Zmm>::kSignature)};
|
||||
}
|
||||
|
||||
//! Tests whether the `op` operand is either a low or high 8-bit GPB register.
|
||||
static inline bool isGpb(const Operand_& op) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpb(const Operand_& op) noexcept {
|
||||
// Check operand type, register group, and size. Not interested in register type.
|
||||
return op.signature().subset(Signature::kOpTypeMask | Signature::kRegGroupMask | Signature::kSizeMask) ==
|
||||
(Signature::fromOpType(OperandType::kReg) | Signature::fromRegGroup(RegGroup::kGp) | Signature::fromSize(1));
|
||||
}
|
||||
|
||||
static inline bool isGpbLo(const Operand_& op) noexcept { return op.as<Reg>().isGpbLo(); }
|
||||
static inline bool isGpbHi(const Operand_& op) noexcept { return op.as<Reg>().isGpbHi(); }
|
||||
static inline bool isGpw(const Operand_& op) noexcept { return op.as<Reg>().isGpw(); }
|
||||
static inline bool isGpd(const Operand_& op) noexcept { return op.as<Reg>().isGpd(); }
|
||||
static inline bool isGpq(const Operand_& op) noexcept { return op.as<Reg>().isGpq(); }
|
||||
static inline bool isXmm(const Operand_& op) noexcept { return op.as<Reg>().isXmm(); }
|
||||
static inline bool isYmm(const Operand_& op) noexcept { return op.as<Reg>().isYmm(); }
|
||||
static inline bool isZmm(const Operand_& op) noexcept { return op.as<Reg>().isZmm(); }
|
||||
static inline bool isMm(const Operand_& op) noexcept { return op.as<Reg>().isMm(); }
|
||||
static inline bool isKReg(const Operand_& op) noexcept { return op.as<Reg>().isKReg(); }
|
||||
static inline bool isSReg(const Operand_& op) noexcept { return op.as<Reg>().isSReg(); }
|
||||
static inline bool isCReg(const Operand_& op) noexcept { return op.as<Reg>().isCReg(); }
|
||||
static inline bool isDReg(const Operand_& op) noexcept { return op.as<Reg>().isDReg(); }
|
||||
static inline bool isSt(const Operand_& op) noexcept { return op.as<Reg>().isSt(); }
|
||||
static inline bool isBnd(const Operand_& op) noexcept { return op.as<Reg>().isBnd(); }
|
||||
static inline bool isTmm(const Operand_& op) noexcept { return op.as<Reg>().isTmm(); }
|
||||
static inline bool isRip(const Operand_& op) noexcept { return op.as<Reg>().isRip(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpbLo(const Operand_& op) noexcept { return op.as<Reg>().isGpbLo(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpbHi(const Operand_& op) noexcept { return op.as<Reg>().isGpbHi(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpw(const Operand_& op) noexcept { return op.as<Reg>().isGpw(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpd(const Operand_& op) noexcept { return op.as<Reg>().isGpd(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpq(const Operand_& op) noexcept { return op.as<Reg>().isGpq(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isXmm(const Operand_& op) noexcept { return op.as<Reg>().isXmm(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isYmm(const Operand_& op) noexcept { return op.as<Reg>().isYmm(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isZmm(const Operand_& op) noexcept { return op.as<Reg>().isZmm(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isMm(const Operand_& op) noexcept { return op.as<Reg>().isMm(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isKReg(const Operand_& op) noexcept { return op.as<Reg>().isKReg(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isSReg(const Operand_& op) noexcept { return op.as<Reg>().isSReg(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isCReg(const Operand_& op) noexcept { return op.as<Reg>().isCReg(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isDReg(const Operand_& op) noexcept { return op.as<Reg>().isDReg(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isSt(const Operand_& op) noexcept { return op.as<Reg>().isSt(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isBnd(const Operand_& op) noexcept { return op.as<Reg>().isBnd(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isTmm(const Operand_& op) noexcept { return op.as<Reg>().isTmm(); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isRip(const Operand_& op) noexcept { return op.as<Reg>().isRip(); }
|
||||
|
||||
static inline bool isGpb(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpb(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isGpbLo(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpbLo(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isGpbHi(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpbHi(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isGpw(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpw(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isGpd(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpd(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isGpq(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpq(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isXmm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isXmm(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isYmm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isYmm(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isZmm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isZmm(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isMm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isMm(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isKReg(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isKReg(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isSReg(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isSReg(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isCReg(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isCReg(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isDReg(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isDReg(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isSt(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isSt(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isBnd(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isBnd(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isTmm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isTmm(op)) & unsigned(op.id() == rId)); }
|
||||
static inline bool isRip(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isRip(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpb(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpb(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpbLo(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpbLo(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpbHi(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpbHi(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpw(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpw(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpd(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpd(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isGpq(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isGpq(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isXmm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isXmm(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isYmm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isYmm(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isZmm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isZmm(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isMm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isMm(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isKReg(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isKReg(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isSReg(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isSReg(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isCReg(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isCReg(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isDReg(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isDReg(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isSt(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isSt(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isBnd(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isBnd(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isTmm(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isTmm(op)) & unsigned(op.id() == rId)); }
|
||||
static ASMJIT_INLINE_NODEBUG bool isRip(const Operand_& op, uint32_t rId) noexcept { return bool(unsigned(isRip(op)) & unsigned(op.id() == rId)); }
|
||||
};
|
||||
|
||||
//! General purpose register (X86).
|
||||
@@ -223,17 +223,17 @@ public:
|
||||
};
|
||||
|
||||
//! Casts this register to 8-bit (LO) part.
|
||||
inline GpbLo r8() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG GpbLo r8() const noexcept;
|
||||
//! Casts this register to 8-bit (LO) part.
|
||||
inline GpbLo r8Lo() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG GpbLo r8Lo() const noexcept;
|
||||
//! Casts this register to 8-bit (HI) part.
|
||||
inline GpbHi r8Hi() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG GpbHi r8Hi() const noexcept;
|
||||
//! Casts this register to 16-bit.
|
||||
inline Gpw r16() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG Gpw r16() const noexcept;
|
||||
//! Casts this register to 32-bit.
|
||||
inline Gpd r32() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG Gpd r32() const noexcept;
|
||||
//! Casts this register to 64-bit.
|
||||
inline Gpq r64() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG Gpq r64() const noexcept;
|
||||
};
|
||||
|
||||
//! Vector register (XMM|YMM|ZMM) (X86).
|
||||
@@ -241,14 +241,14 @@ class Vec : public Reg {
|
||||
ASMJIT_DEFINE_ABSTRACT_REG(Vec, Reg)
|
||||
|
||||
//! Casts this register to XMM (clone).
|
||||
inline Xmm xmm() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG Xmm xmm() const noexcept;
|
||||
//! Casts this register to YMM.
|
||||
inline Ymm ymm() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG Ymm ymm() const noexcept;
|
||||
//! Casts this register to ZMM.
|
||||
inline Zmm zmm() const noexcept;
|
||||
ASMJIT_INLINE_NODEBUG Zmm zmm() const noexcept;
|
||||
|
||||
//! Casts this register to a register that has half the size (or XMM if it's already XMM).
|
||||
inline Vec half() const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG Vec half() const noexcept {
|
||||
return Vec(type() == RegType::kX86_Zmm ? signatureOfT<RegType::kX86_Ymm>() : signatureOfT<RegType::kX86_Xmm>(), id());
|
||||
}
|
||||
};
|
||||
@@ -300,21 +300,21 @@ class Gpq : public Gp { ASMJIT_DEFINE_FINAL_REG(Gpq, Gp, RegTraits<RegType::kX86
|
||||
class Xmm : public Vec {
|
||||
ASMJIT_DEFINE_FINAL_REG(Xmm, Vec, RegTraits<RegType::kX86_Xmm>)
|
||||
//! Casts this register to a register that has half the size (XMM).
|
||||
inline Xmm half() const noexcept { return Xmm(id()); }
|
||||
ASMJIT_INLINE_NODEBUG Xmm half() const noexcept { return Xmm(id()); }
|
||||
};
|
||||
|
||||
//! 256-bit YMM register (AVX+).
|
||||
class Ymm : public Vec {
|
||||
ASMJIT_DEFINE_FINAL_REG(Ymm, Vec, RegTraits<RegType::kX86_Ymm>)
|
||||
//! Casts this register to a register that has half the size (XMM).
|
||||
inline Xmm half() const noexcept { return Xmm(id()); }
|
||||
ASMJIT_INLINE_NODEBUG Xmm half() const noexcept { return Xmm(id()); }
|
||||
};
|
||||
|
||||
//! 512-bit ZMM register (AVX512+).
|
||||
class Zmm : public Vec {
|
||||
ASMJIT_DEFINE_FINAL_REG(Zmm, Vec, RegTraits<RegType::kX86_Zmm>)
|
||||
//! Casts this register to a register that has half the size (YMM).
|
||||
inline Ymm half() const noexcept { return Ymm(id()); }
|
||||
ASMJIT_INLINE_NODEBUG Ymm half() const noexcept { return Ymm(id()); }
|
||||
};
|
||||
|
||||
//! 64-bit MMX register (MMX+).
|
||||
@@ -335,60 +335,58 @@ class Tmm : public Reg { ASMJIT_DEFINE_FINAL_REG(Tmm, Reg, RegTraits<RegType::kX
|
||||
class Rip : public Reg { ASMJIT_DEFINE_FINAL_REG(Rip, Reg, RegTraits<RegType::kX86_Rip>) };
|
||||
|
||||
//! \cond
|
||||
inline GpbLo Gp::r8() const noexcept { return GpbLo(id()); }
|
||||
inline GpbLo Gp::r8Lo() const noexcept { return GpbLo(id()); }
|
||||
inline GpbHi Gp::r8Hi() const noexcept { return GpbHi(id()); }
|
||||
inline Gpw Gp::r16() const noexcept { return Gpw(id()); }
|
||||
inline Gpd Gp::r32() const noexcept { return Gpd(id()); }
|
||||
inline Gpq Gp::r64() const noexcept { return Gpq(id()); }
|
||||
inline Xmm Vec::xmm() const noexcept { return Xmm(id()); }
|
||||
inline Ymm Vec::ymm() const noexcept { return Ymm(id()); }
|
||||
inline Zmm Vec::zmm() const noexcept { return Zmm(id()); }
|
||||
ASMJIT_INLINE_NODEBUG GpbLo Gp::r8() const noexcept { return GpbLo(id()); }
|
||||
ASMJIT_INLINE_NODEBUG GpbLo Gp::r8Lo() const noexcept { return GpbLo(id()); }
|
||||
ASMJIT_INLINE_NODEBUG GpbHi Gp::r8Hi() const noexcept { return GpbHi(id()); }
|
||||
ASMJIT_INLINE_NODEBUG Gpw Gp::r16() const noexcept { return Gpw(id()); }
|
||||
ASMJIT_INLINE_NODEBUG Gpd Gp::r32() const noexcept { return Gpd(id()); }
|
||||
ASMJIT_INLINE_NODEBUG Gpq Gp::r64() const noexcept { return Gpq(id()); }
|
||||
ASMJIT_INLINE_NODEBUG Xmm Vec::xmm() const noexcept { return Xmm(id()); }
|
||||
ASMJIT_INLINE_NODEBUG Ymm Vec::ymm() const noexcept { return Ymm(id()); }
|
||||
ASMJIT_INLINE_NODEBUG Zmm Vec::zmm() const noexcept { return Zmm(id()); }
|
||||
//! \endcond
|
||||
|
||||
//! \namespace asmjit::x86::regs
|
||||
//!
|
||||
//! Registers provided by X86 and X64 ISAs are in both `asmjit::x86` and
|
||||
//! `asmjit::x86::regs` namespaces so they can be included with using directive.
|
||||
//! For example `using namespace asmjit::x86::regs` would include all registers,
|
||||
//! but not other X86-specific API, whereas `using namespace asmjit::x86` would
|
||||
//! include everything X86-specific.
|
||||
//! Registers provided by X86 and X64 ISAs are in both `asmjit::x86` and `asmjit::x86::regs` namespaces so they can
|
||||
//! be included with using directive. For example `using namespace asmjit::x86::regs` would include all registers,
|
||||
//! but not other X86-specific API, whereas `using namespace asmjit::x86` would include everything X86-specific.
|
||||
#ifndef _DOXYGEN
|
||||
namespace regs {
|
||||
#endif
|
||||
|
||||
//! Creates an 8-bit low GPB register operand.
|
||||
static constexpr GpbLo gpb(uint32_t rId) noexcept { return GpbLo(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr GpbLo gpb(uint32_t rId) noexcept { return GpbLo(rId); }
|
||||
//! Creates an 8-bit low GPB register operand.
|
||||
static constexpr GpbLo gpb_lo(uint32_t rId) noexcept { return GpbLo(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr GpbLo gpb_lo(uint32_t rId) noexcept { return GpbLo(rId); }
|
||||
//! Creates an 8-bit high GPB register operand.
|
||||
static constexpr GpbHi gpb_hi(uint32_t rId) noexcept { return GpbHi(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr GpbHi gpb_hi(uint32_t rId) noexcept { return GpbHi(rId); }
|
||||
//! Creates a 16-bit GPW register operand.
|
||||
static constexpr Gpw gpw(uint32_t rId) noexcept { return Gpw(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Gpw gpw(uint32_t rId) noexcept { return Gpw(rId); }
|
||||
//! Creates a 32-bit GPD register operand.
|
||||
static constexpr Gpd gpd(uint32_t rId) noexcept { return Gpd(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Gpd gpd(uint32_t rId) noexcept { return Gpd(rId); }
|
||||
//! Creates a 64-bit GPQ register operand (64-bit).
|
||||
static constexpr Gpq gpq(uint32_t rId) noexcept { return Gpq(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Gpq gpq(uint32_t rId) noexcept { return Gpq(rId); }
|
||||
//! Creates a 128-bit XMM register operand.
|
||||
static constexpr Xmm xmm(uint32_t rId) noexcept { return Xmm(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Xmm xmm(uint32_t rId) noexcept { return Xmm(rId); }
|
||||
//! Creates a 256-bit YMM register operand.
|
||||
static constexpr Ymm ymm(uint32_t rId) noexcept { return Ymm(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Ymm ymm(uint32_t rId) noexcept { return Ymm(rId); }
|
||||
//! Creates a 512-bit ZMM register operand.
|
||||
static constexpr Zmm zmm(uint32_t rId) noexcept { return Zmm(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Zmm zmm(uint32_t rId) noexcept { return Zmm(rId); }
|
||||
//! Creates a 64-bit Mm register operand.
|
||||
static constexpr Mm mm(uint32_t rId) noexcept { return Mm(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mm mm(uint32_t rId) noexcept { return Mm(rId); }
|
||||
//! Creates a 64-bit K register operand.
|
||||
static constexpr KReg k(uint32_t rId) noexcept { return KReg(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr KReg k(uint32_t rId) noexcept { return KReg(rId); }
|
||||
//! Creates a 32-bit or 64-bit control register operand.
|
||||
static constexpr CReg cr(uint32_t rId) noexcept { return CReg(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr CReg cr(uint32_t rId) noexcept { return CReg(rId); }
|
||||
//! Creates a 32-bit or 64-bit debug register operand.
|
||||
static constexpr DReg dr(uint32_t rId) noexcept { return DReg(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr DReg dr(uint32_t rId) noexcept { return DReg(rId); }
|
||||
//! Creates an 80-bit st register operand.
|
||||
static constexpr St st(uint32_t rId) noexcept { return St(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr St st(uint32_t rId) noexcept { return St(rId); }
|
||||
//! Creates a 128-bit bound register operand.
|
||||
static constexpr Bnd bnd(uint32_t rId) noexcept { return Bnd(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Bnd bnd(uint32_t rId) noexcept { return Bnd(rId); }
|
||||
//! Creates a TMM register operand.
|
||||
static constexpr Tmm tmm(uint32_t rId) noexcept { return Tmm(rId); }
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Tmm tmm(uint32_t rId) noexcept { return Tmm(rId); }
|
||||
|
||||
static constexpr GpbLo al = GpbLo(Gp::kIdAx);
|
||||
static constexpr GpbLo bl = GpbLo(Gp::kIdBx);
|
||||
@@ -723,25 +721,25 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Creates a default `Mem` operand that points to [0].
|
||||
inline constexpr Mem() noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem() noexcept
|
||||
: BaseMem() {}
|
||||
|
||||
inline constexpr Mem(const Mem& other) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem(const Mem& other) noexcept
|
||||
: BaseMem(other) {}
|
||||
|
||||
inline explicit Mem(Globals::NoInit_) noexcept
|
||||
ASMJIT_INLINE_NODEBUG explicit Mem(Globals::NoInit_) noexcept
|
||||
: BaseMem(Globals::NoInit) {}
|
||||
|
||||
inline constexpr Mem(const Signature& signature, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem(const Signature& signature, uint32_t baseId, uint32_t indexId, int32_t offset) noexcept
|
||||
: BaseMem(signature, baseId, indexId, offset) {}
|
||||
|
||||
inline constexpr Mem(const Label& base, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem(const Label& base, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
|
||||
: BaseMem(Signature::fromOpType(OperandType::kMem) |
|
||||
Signature::fromMemBaseType(RegType::kLabelTag) |
|
||||
Signature::fromSize(size) |
|
||||
signature, base.id(), 0, off) {}
|
||||
|
||||
inline constexpr Mem(const Label& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem(const Label& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
|
||||
: BaseMem(Signature::fromOpType(OperandType::kMem) |
|
||||
Signature::fromMemBaseType(RegType::kLabelTag) |
|
||||
Signature::fromMemIndexType(index.type()) |
|
||||
@@ -749,13 +747,13 @@ public:
|
||||
Signature::fromSize(size) |
|
||||
signature, base.id(), index.id(), off) {}
|
||||
|
||||
inline constexpr Mem(const BaseReg& base, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem(const BaseReg& base, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
|
||||
: BaseMem(Signature::fromOpType(OperandType::kMem) |
|
||||
Signature::fromMemBaseType(base.type()) |
|
||||
Signature::fromSize(size) |
|
||||
signature, base.id(), 0, off) {}
|
||||
|
||||
inline constexpr Mem(const BaseReg& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem(const BaseReg& base, const BaseReg& index, uint32_t shift, int32_t off, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
|
||||
: BaseMem(Signature::fromOpType(OperandType::kMem) |
|
||||
Signature::fromMemBaseType(base.type()) |
|
||||
Signature::fromMemIndexType(index.type()) |
|
||||
@@ -763,12 +761,12 @@ public:
|
||||
Signature::fromSize(size) |
|
||||
signature, base.id(), index.id(), off) {}
|
||||
|
||||
inline constexpr explicit Mem(uint64_t base, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr explicit Mem(uint64_t base, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
|
||||
: BaseMem(Signature::fromOpType(OperandType::kMem) |
|
||||
Signature::fromSize(size) |
|
||||
signature, uint32_t(base >> 32), 0, int32_t(uint32_t(base & 0xFFFFFFFFu))) {}
|
||||
|
||||
inline constexpr Mem(uint64_t base, const BaseReg& index, uint32_t shift = 0, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem(uint64_t base, const BaseReg& index, uint32_t shift = 0, uint32_t size = 0, Signature signature = OperandSignature{0}) noexcept
|
||||
: BaseMem(Signature::fromOpType(OperandType::kMem) |
|
||||
Signature::fromMemIndexType(index.type()) |
|
||||
Signature::fromValue<kSignatureMemShiftValueMask>(shift) |
|
||||
@@ -780,7 +778,7 @@ public:
|
||||
//! \name Overloaded Operators
|
||||
//! \{
|
||||
|
||||
inline Mem& operator=(const Mem& other) noexcept = default;
|
||||
ASMJIT_INLINE_NODEBUG Mem& operator=(const Mem& other) noexcept = default;
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -788,7 +786,7 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Clones the memory operand.
|
||||
inline constexpr Mem clone() const noexcept { return Mem(*this); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem clone() const noexcept { return Mem(*this); }
|
||||
|
||||
//! Creates a copy of this memory operand adjusted by `off`.
|
||||
inline Mem cloneAdjusted(int64_t off) const noexcept {
|
||||
@@ -805,7 +803,7 @@ public:
|
||||
}
|
||||
|
||||
//! Creates a copy of this memory operand with a broadcast `bcst`.
|
||||
inline constexpr Mem cloneBroadcasted(Broadcast bcst) const noexcept {
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem cloneBroadcasted(Broadcast bcst) const noexcept {
|
||||
return Mem((_signature & ~Signature{kSignatureMemBroadcastMask}) | Signature::fromValue<kSignatureMemBroadcastMask>(bcst), _baseId, _data[0], int32_t(_data[1]));
|
||||
}
|
||||
|
||||
@@ -817,16 +815,16 @@ public:
|
||||
//! Converts memory `baseType` and `baseId` to `x86::Reg` instance.
|
||||
//!
|
||||
//! The memory must have a valid base register otherwise the result will be wrong.
|
||||
inline Reg baseReg() const noexcept { return Reg::fromTypeAndId(baseType(), baseId()); }
|
||||
ASMJIT_INLINE_NODEBUG Reg baseReg() const noexcept { return Reg::fromTypeAndId(baseType(), baseId()); }
|
||||
|
||||
//! Converts memory `indexType` and `indexId` to `x86::Reg` instance.
|
||||
//!
|
||||
//! The memory must have a valid index register otherwise the result will be wrong.
|
||||
inline Reg indexReg() const noexcept { return Reg::fromTypeAndId(indexType(), indexId()); }
|
||||
ASMJIT_INLINE_NODEBUG Reg indexReg() const noexcept { return Reg::fromTypeAndId(indexType(), indexId()); }
|
||||
|
||||
using BaseMem::setIndex;
|
||||
|
||||
inline void setIndex(const BaseReg& index, uint32_t shift) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG void setIndex(const BaseReg& index, uint32_t shift) noexcept {
|
||||
setIndex(index);
|
||||
setShift(shift);
|
||||
}
|
||||
@@ -839,21 +837,21 @@ public:
|
||||
//! Returns the address type of the memory operand.
|
||||
//!
|
||||
//! By default, address type of newly created memory operands is always \ref AddrType::kDefault.
|
||||
inline constexpr AddrType addrType() const noexcept { return (AddrType)_signature.getField<kSignatureMemAddrTypeMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr AddrType addrType() const noexcept { return (AddrType)_signature.getField<kSignatureMemAddrTypeMask>(); }
|
||||
//! Sets the address type to `addrType`.
|
||||
inline void setAddrType(AddrType addrType) noexcept { _signature.setField<kSignatureMemAddrTypeMask>(uint32_t(addrType)); }
|
||||
ASMJIT_INLINE_NODEBUG void setAddrType(AddrType addrType) noexcept { _signature.setField<kSignatureMemAddrTypeMask>(uint32_t(addrType)); }
|
||||
//! Resets the address type to \ref AddrType::kDefault.
|
||||
inline void resetAddrType() noexcept { _signature.setField<kSignatureMemAddrTypeMask>(uint32_t(AddrType::kDefault)); }
|
||||
ASMJIT_INLINE_NODEBUG void resetAddrType() noexcept { _signature.setField<kSignatureMemAddrTypeMask>(uint32_t(AddrType::kDefault)); }
|
||||
|
||||
//! Tests whether the address type is \ref AddrType::kAbs.
|
||||
inline constexpr bool isAbs() const noexcept { return addrType() == AddrType::kAbs; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isAbs() const noexcept { return addrType() == AddrType::kAbs; }
|
||||
//! Sets the address type to \ref AddrType::kAbs.
|
||||
inline void setAbs() noexcept { setAddrType(AddrType::kAbs); }
|
||||
ASMJIT_INLINE_NODEBUG void setAbs() noexcept { setAddrType(AddrType::kAbs); }
|
||||
|
||||
//! Tests whether the address type is \ref AddrType::kRel.
|
||||
inline constexpr bool isRel() const noexcept { return addrType() == AddrType::kRel; }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool isRel() const noexcept { return addrType() == AddrType::kRel; }
|
||||
//! Sets the address type to \ref AddrType::kRel.
|
||||
inline void setRel() noexcept { setAddrType(AddrType::kRel); }
|
||||
ASMJIT_INLINE_NODEBUG void setRel() noexcept { setAddrType(AddrType::kRel); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -861,18 +859,18 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether the memory operand has a segment override.
|
||||
inline constexpr bool hasSegment() const noexcept { return _signature.hasField<kSignatureMemSegmentMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool hasSegment() const noexcept { return _signature.hasField<kSignatureMemSegmentMask>(); }
|
||||
//! Returns the associated segment override as `SReg` operand.
|
||||
inline constexpr SReg segment() const noexcept { return SReg(segmentId()); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr SReg segment() const noexcept { return SReg(segmentId()); }
|
||||
//! Returns segment override register id, see `SReg::Id`.
|
||||
inline constexpr uint32_t segmentId() const noexcept { return _signature.getField<kSignatureMemSegmentMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr uint32_t segmentId() const noexcept { return _signature.getField<kSignatureMemSegmentMask>(); }
|
||||
|
||||
//! Sets the segment override to `seg`.
|
||||
inline void setSegment(const SReg& seg) noexcept { setSegment(seg.id()); }
|
||||
ASMJIT_INLINE_NODEBUG void setSegment(const SReg& seg) noexcept { setSegment(seg.id()); }
|
||||
//! Sets the segment override to `id`.
|
||||
inline void setSegment(uint32_t rId) noexcept { _signature.setField<kSignatureMemSegmentMask>(rId); }
|
||||
ASMJIT_INLINE_NODEBUG void setSegment(uint32_t rId) noexcept { _signature.setField<kSignatureMemSegmentMask>(rId); }
|
||||
//! Resets the segment override.
|
||||
inline void resetSegment() noexcept { _signature.setField<kSignatureMemSegmentMask>(0); }
|
||||
ASMJIT_INLINE_NODEBUG void resetSegment() noexcept { _signature.setField<kSignatureMemSegmentMask>(0); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -880,13 +878,13 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether the memory operand has shift (aka scale) value.
|
||||
inline constexpr bool hasShift() const noexcept { return _signature.hasField<kSignatureMemShiftValueMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool hasShift() const noexcept { return _signature.hasField<kSignatureMemShiftValueMask>(); }
|
||||
//! Returns the memory operand's shift (aka scale) value.
|
||||
inline constexpr uint32_t shift() const noexcept { return _signature.getField<kSignatureMemShiftValueMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr uint32_t shift() const noexcept { return _signature.getField<kSignatureMemShiftValueMask>(); }
|
||||
//! Sets the memory operand's shift (aka scale) value.
|
||||
inline void setShift(uint32_t shift) noexcept { _signature.setField<kSignatureMemShiftValueMask>(shift); }
|
||||
ASMJIT_INLINE_NODEBUG void setShift(uint32_t shift) noexcept { _signature.setField<kSignatureMemShiftValueMask>(shift); }
|
||||
//! Resets the memory operand's shift (aka scale) value to zero.
|
||||
inline void resetShift() noexcept { _signature.setField<kSignatureMemShiftValueMask>(0); }
|
||||
ASMJIT_INLINE_NODEBUG void resetShift() noexcept { _signature.setField<kSignatureMemShiftValueMask>(0); }
|
||||
|
||||
//! \}
|
||||
|
||||
@@ -894,156 +892,168 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Tests whether the memory operand has broadcast {1tox}.
|
||||
inline constexpr bool hasBroadcast() const noexcept { return _signature.hasField<kSignatureMemBroadcastMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr bool hasBroadcast() const noexcept { return _signature.hasField<kSignatureMemBroadcastMask>(); }
|
||||
//! Returns the memory operand's broadcast.
|
||||
inline constexpr Broadcast getBroadcast() const noexcept { return (Broadcast)_signature.getField<kSignatureMemBroadcastMask>(); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr Broadcast getBroadcast() const noexcept { return (Broadcast)_signature.getField<kSignatureMemBroadcastMask>(); }
|
||||
//! Sets the memory operand's broadcast.
|
||||
inline void setBroadcast(Broadcast b) noexcept { _signature.setField<kSignatureMemBroadcastMask>(uint32_t(b)); }
|
||||
ASMJIT_INLINE_NODEBUG void setBroadcast(Broadcast b) noexcept { _signature.setField<kSignatureMemBroadcastMask>(uint32_t(b)); }
|
||||
//! Resets the memory operand's broadcast to none.
|
||||
inline void resetBroadcast() noexcept { _signature.setField<kSignatureMemBroadcastMask>(0); }
|
||||
ASMJIT_INLINE_NODEBUG void resetBroadcast() noexcept { _signature.setField<kSignatureMemBroadcastMask>(0); }
|
||||
|
||||
//! Returns a new `Mem` without a broadcast (the possible broadcast is cleared).
|
||||
inline constexpr Mem _1to1() const noexcept { return cloneBroadcasted(Broadcast::kNone); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem _1to1() const noexcept { return cloneBroadcasted(Broadcast::kNone); }
|
||||
//! Returns a new `Mem` with {1to2} broadcast (AVX-512).
|
||||
inline constexpr Mem _1to2() const noexcept { return cloneBroadcasted(Broadcast::k1To2); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem _1to2() const noexcept { return cloneBroadcasted(Broadcast::k1To2); }
|
||||
//! Returns a new `Mem` with {1to4} broadcast (AVX-512).
|
||||
inline constexpr Mem _1to4() const noexcept { return cloneBroadcasted(Broadcast::k1To4); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem _1to4() const noexcept { return cloneBroadcasted(Broadcast::k1To4); }
|
||||
//! Returns a new `Mem` with {1to8} broadcast (AVX-512).
|
||||
inline constexpr Mem _1to8() const noexcept { return cloneBroadcasted(Broadcast::k1To8); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem _1to8() const noexcept { return cloneBroadcasted(Broadcast::k1To8); }
|
||||
//! Returns a new `Mem` with {1to16} broadcast (AVX-512).
|
||||
inline constexpr Mem _1to16() const noexcept { return cloneBroadcasted(Broadcast::k1To16); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem _1to16() const noexcept { return cloneBroadcasted(Broadcast::k1To16); }
|
||||
//! Returns a new `Mem` with {1to32} broadcast (AVX-512).
|
||||
inline constexpr Mem _1to32() const noexcept { return cloneBroadcasted(Broadcast::k1To32); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem _1to32() const noexcept { return cloneBroadcasted(Broadcast::k1To32); }
|
||||
//! Returns a new `Mem` with {1to64} broadcast (AVX-512).
|
||||
inline constexpr Mem _1to64() const noexcept { return cloneBroadcasted(Broadcast::k1To64); }
|
||||
ASMJIT_INLINE_NODEBUG constexpr Mem _1to64() const noexcept { return cloneBroadcasted(Broadcast::k1To64); }
|
||||
|
||||
//! \}
|
||||
};
|
||||
|
||||
//! Creates `[base.reg + offset]` memory operand.
|
||||
static inline constexpr Mem ptr(const Gp& base, int32_t offset = 0, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, int32_t offset = 0, uint32_t size = 0) noexcept {
|
||||
return Mem(base, offset, size);
|
||||
}
|
||||
//! Creates `[base.reg + (index << shift) + offset]` memory operand (scalar index).
|
||||
static inline constexpr Mem ptr(const Gp& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept {
|
||||
return Mem(base, index, shift, offset, size);
|
||||
}
|
||||
//! Creates `[base.reg + (index << shift) + offset]` memory operand (vector index).
|
||||
static inline constexpr Mem ptr(const Gp& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Gp& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept {
|
||||
return Mem(base, index, shift, offset, size);
|
||||
}
|
||||
|
||||
//! Creates `[base + offset]` memory operand.
|
||||
static inline constexpr Mem ptr(const Label& base, int32_t offset = 0, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Label& base, int32_t offset = 0, uint32_t size = 0) noexcept {
|
||||
return Mem(base, offset, size);
|
||||
}
|
||||
//! Creates `[base + (index << shift) + offset]` memory operand.
|
||||
static inline constexpr Mem ptr(const Label& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Label& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept {
|
||||
return Mem(base, index, shift, offset, size);
|
||||
}
|
||||
//! Creates `[base + (index << shift) + offset]` memory operand.
|
||||
static inline constexpr Mem ptr(const Label& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Label& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0, uint32_t size = 0) noexcept {
|
||||
return Mem(base, index, shift, offset, size);
|
||||
}
|
||||
|
||||
//! Creates `[rip + offset]` memory operand.
|
||||
static inline constexpr Mem ptr(const Rip& rip_, int32_t offset = 0, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(const Rip& rip_, int32_t offset = 0, uint32_t size = 0) noexcept {
|
||||
return Mem(rip_, offset, size);
|
||||
}
|
||||
|
||||
//! Creates `[base]` absolute memory operand.
|
||||
static inline constexpr Mem ptr(uint64_t base, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(uint64_t base, uint32_t size = 0) noexcept {
|
||||
return Mem(base, size);
|
||||
}
|
||||
//! Creates `[base + (index.reg << shift)]` absolute memory operand.
|
||||
static inline constexpr Mem ptr(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
|
||||
return Mem(base, index, shift, size);
|
||||
}
|
||||
//! Creates `[base + (index.reg << shift)]` absolute memory operand.
|
||||
static inline constexpr Mem ptr(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
|
||||
return Mem(base, index, shift, size);
|
||||
}
|
||||
|
||||
//! Creates `[base]` absolute memory operand (absolute).
|
||||
static inline constexpr Mem ptr_abs(uint64_t base, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_abs(uint64_t base, uint32_t size = 0) noexcept {
|
||||
return Mem(base, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs));
|
||||
}
|
||||
//! Creates `[base + (index.reg << shift)]` absolute memory operand (absolute).
|
||||
static inline constexpr Mem ptr_abs(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_abs(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
|
||||
return Mem(base, index, shift, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs));
|
||||
}
|
||||
//! Creates `[base + (index.reg << shift)]` absolute memory operand (absolute).
|
||||
static inline constexpr Mem ptr_abs(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_abs(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
|
||||
return Mem(base, index, shift, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs));
|
||||
}
|
||||
|
||||
//! Creates `[base]` relative memory operand (relative).
|
||||
static inline constexpr Mem ptr_rel(uint64_t base, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_rel(uint64_t base, uint32_t size = 0) noexcept {
|
||||
return Mem(base, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel));
|
||||
}
|
||||
//! Creates `[base + (index.reg << shift)]` relative memory operand (relative).
|
||||
static inline constexpr Mem ptr_rel(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_rel(uint64_t base, const Reg& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
|
||||
return Mem(base, index, shift, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel));
|
||||
}
|
||||
//! Creates `[base + (index.reg << shift)]` relative memory operand (relative).
|
||||
static inline constexpr Mem ptr_rel(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem ptr_rel(uint64_t base, const Vec& index, uint32_t shift = 0, uint32_t size = 0) noexcept {
|
||||
return Mem(base, index, shift, size, OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel));
|
||||
}
|
||||
|
||||
#define ASMJIT_MEM_PTR(FUNC, SIZE) \
|
||||
static constexpr Mem FUNC(const Gp& base, int32_t offset = 0) noexcept { \
|
||||
return Mem(base, offset, SIZE); \
|
||||
} \
|
||||
static constexpr Mem FUNC(const Gp& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \
|
||||
return Mem(base, index, shift, offset, SIZE); \
|
||||
} \
|
||||
static constexpr Mem FUNC(const Gp& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \
|
||||
return Mem(base, index, shift, offset, SIZE); \
|
||||
} \
|
||||
static constexpr Mem FUNC(const Label& base, int32_t offset = 0) noexcept { \
|
||||
return Mem(base, offset, SIZE); \
|
||||
} \
|
||||
static constexpr Mem FUNC(const Label& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0) noexcept { \
|
||||
return Mem(base, index, shift, offset, SIZE); \
|
||||
} \
|
||||
static constexpr Mem FUNC(const Rip& rip_, int32_t offset = 0) noexcept { \
|
||||
return Mem(rip_, offset, SIZE); \
|
||||
} \
|
||||
static constexpr Mem FUNC(uint64_t base) noexcept { \
|
||||
return Mem(base, SIZE); \
|
||||
} \
|
||||
static constexpr Mem FUNC(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \
|
||||
return Mem(base, index, shift, SIZE); \
|
||||
} \
|
||||
static constexpr Mem FUNC(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \
|
||||
return Mem(base, index, shift, SIZE); \
|
||||
} \
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \
|
||||
const Gp& base, int32_t offset = 0) noexcept \
|
||||
{ return Mem(base, offset, SIZE); } \
|
||||
\
|
||||
static constexpr Mem FUNC##_abs(uint64_t base) noexcept { \
|
||||
return Mem(base, SIZE, \
|
||||
OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); \
|
||||
} \
|
||||
static constexpr Mem FUNC##_abs(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \
|
||||
return Mem(base, index, shift, SIZE, \
|
||||
OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); \
|
||||
} \
|
||||
static constexpr Mem FUNC##_abs(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \
|
||||
return Mem(base, index, shift, SIZE, \
|
||||
OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); \
|
||||
} \
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \
|
||||
const Gp& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0) noexcept \
|
||||
{ return Mem(base, index, shift, offset, SIZE); } \
|
||||
\
|
||||
static constexpr Mem FUNC##_rel(uint64_t base) noexcept { \
|
||||
return Mem(base, SIZE, \
|
||||
OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); \
|
||||
} \
|
||||
static constexpr Mem FUNC##_rel(uint64_t base, const Gp& index, uint32_t shift = 0) noexcept { \
|
||||
return Mem(base, index, shift, SIZE, \
|
||||
OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); \
|
||||
} \
|
||||
static constexpr Mem FUNC##_rel(uint64_t base, const Vec& index, uint32_t shift = 0) noexcept { \
|
||||
return Mem(base, index, shift, SIZE, \
|
||||
OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); \
|
||||
}
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \
|
||||
const Gp& base, const Vec& index, uint32_t shift = 0, int32_t offset = 0) noexcept \
|
||||
{ return Mem(base, index, shift, offset, SIZE); } \
|
||||
\
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \
|
||||
const Label& base, int32_t offset = 0) noexcept \
|
||||
{ return Mem(base, offset, SIZE); } \
|
||||
\
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \
|
||||
const Label& base, const Gp& index, uint32_t shift = 0, int32_t offset = 0) noexcept \
|
||||
{ return Mem(base, index, shift, offset, SIZE); } \
|
||||
\
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \
|
||||
const Rip& rip_, int32_t offset = 0) noexcept \
|
||||
{ return Mem(rip_, offset, SIZE); } \
|
||||
\
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \
|
||||
uint64_t base) noexcept \
|
||||
{ return Mem(base, SIZE); } \
|
||||
\
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \
|
||||
uint64_t base, const Gp& index, uint32_t shift = 0) noexcept \
|
||||
{ return Mem(base, index, shift, SIZE); } \
|
||||
\
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC( \
|
||||
uint64_t base, const Vec& index, uint32_t shift = 0) noexcept \
|
||||
{ return Mem(base, index, shift, SIZE); } \
|
||||
\
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC##_abs( \
|
||||
uint64_t base) noexcept \
|
||||
{ return Mem(base, SIZE, \
|
||||
OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); } \
|
||||
\
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC##_abs( \
|
||||
uint64_t base, const Gp& index, uint32_t shift = 0) noexcept \
|
||||
{ return Mem(base, index, shift, SIZE, \
|
||||
OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); } \
|
||||
\
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC##_abs( \
|
||||
uint64_t base, const Vec& index, uint32_t shift = 0) noexcept \
|
||||
{ return Mem(base, index, shift, SIZE, \
|
||||
OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kAbs)); } \
|
||||
\
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC##_rel( \
|
||||
uint64_t base) noexcept \
|
||||
{ return Mem(base, SIZE, \
|
||||
OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); } \
|
||||
\
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC##_rel( \
|
||||
uint64_t base, const Gp& index, uint32_t shift = 0) noexcept \
|
||||
{ return Mem(base, index, shift, SIZE, \
|
||||
OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); } \
|
||||
\
|
||||
static ASMJIT_INLINE_NODEBUG constexpr Mem FUNC##_rel( \
|
||||
uint64_t base, const Vec& index, uint32_t shift = 0) noexcept \
|
||||
{ return Mem(base, index, shift, SIZE, \
|
||||
OperandSignature::fromValue<Mem::kSignatureMemAddrTypeMask>(Mem::AddrType::kRel)); }
|
||||
|
||||
// Definition of memory operand constructors that use platform independent naming.
|
||||
ASMJIT_MEM_PTR(ptr_8, 1)
|
||||
|
||||
@@ -44,20 +44,20 @@ public:
|
||||
//! \{
|
||||
|
||||
//! Returns the compiler casted to `x86::Compiler`.
|
||||
inline Compiler* cc() const noexcept { return static_cast<Compiler*>(_cb); }
|
||||
ASMJIT_INLINE_NODEBUG Compiler* cc() const noexcept { return static_cast<Compiler*>(_cb); }
|
||||
|
||||
//! Returns emit helper.
|
||||
inline EmitHelper* emitHelper() noexcept { return &_emitHelper; }
|
||||
ASMJIT_INLINE_NODEBUG EmitHelper* emitHelper() noexcept { return &_emitHelper; }
|
||||
|
||||
inline bool avxEnabled() const noexcept { return _emitHelper._avxEnabled; }
|
||||
inline bool avx512Enabled() const noexcept { return _emitHelper._avx512Enabled; }
|
||||
ASMJIT_INLINE_NODEBUG bool avxEnabled() const noexcept { return _emitHelper._avxEnabled; }
|
||||
ASMJIT_INLINE_NODEBUG bool avx512Enabled() const noexcept { return _emitHelper._avx512Enabled; }
|
||||
|
||||
//! \}
|
||||
|
||||
//! \name Utilities
|
||||
//! \{
|
||||
|
||||
inline uint32_t choose(uint32_t sseInstId, uint32_t avxInstId) noexcept {
|
||||
ASMJIT_INLINE_NODEBUG InstId choose(InstId sseInstId, InstId avxInstId) noexcept {
|
||||
return avxEnabled() ? avxInstId : sseInstId;
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user