You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

175 lines
6.9 KiB

// AsmJit - Machine code generation for C++
//
// * Official AsmJit Home Page: https://asmjit.com
// * Official Github Repository: https://github.com/asmjit/asmjit
//
// Copyright (c) 2008-2020 The AsmJit Authors
//
// This software is provided 'as-is', without any express or implied
// warranty. In no event will the authors be held liable for any damages
// arising from the use of this software.
//
// Permission is granted to anyone to use this software for any purpose,
// including commercial applications, and to alter it and redistribute it
// freely, subject to the following restrictions:
//
// 1. The origin of this software must not be misrepresented; you must not
// claim that you wrote the original software. If you use this software
// in a product, an acknowledgment in the product documentation would be
// appreciated but is not required.
// 2. Altered source versions must be plainly marked as such, and must not be
// misrepresented as being the original software.
// 3. This notice may not be removed or altered from any source distribution.
#ifndef ASMJIT_CORE_ARCHTRAITS_H_INCLUDED
#define ASMJIT_CORE_ARCHTRAITS_H_INCLUDED
#include "../core/environment.h"
#include "../core/operand.h"
#include "../core/type.h"
ASMJIT_BEGIN_NAMESPACE
//! \addtogroup asmjit_core
//! \{
// ============================================================================
// [asmjit::ArchTraits]
// ============================================================================
//! Architecture traits used by Function API and Compiler's register allocator.
struct ArchTraits {
//! ISA features for each register group.
enum IsaFeatures : uint32_t {
//! ISA features a register swap by using a single instruction.
kIsaFeatureSwap = 0x01u,
//! ISA features a push/pop like instruction for this register group.
kIsaFeaturePushPop = 0x02u,
};
//! Stack pointer register id.
uint8_t _spRegId;
//! Frame pointer register id.
uint8_t _fpRegId;
//! Link register id.
uint8_t _linkRegId;
//! Instruction pointer (or program counter) register id, if accessible.
uint8_t _ipRegId;
// Reserved.
uint8_t _reserved[3];
//! Hardware stack alignment requirement.
uint8_t _hwStackAlignment;
//! Minimum addressable offset on stack guaranteed for all instructions.
uint32_t _minStackOffset;
//! Maximum addressable offset on stack depending on specific instruction.
uint32_t _maxStackOffset;
//! Flags for each virtual register group (always covers GP and Vec groups).
uint8_t _isaFlags[BaseReg::kGroupVirt];
//! Maps register type into a signature, that provides group, size and can
//! be used to construct register operands.
RegInfo _regInfo[BaseReg::kTypeMax + 1];
//! Maps a register to type-id, see \ref Type::Id.
uint8_t _regTypeToTypeId[BaseReg::kTypeMax + 1];
//! Maps base TypeId values (from TypeId::_kIdBaseStart) to register types, see \ref Type::Id.
uint8_t _typeIdToRegType[32];
//! Resets all members to zeros.
inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
//! \name Accessors
//! \{
//! Returns stack pointer register id.
inline constexpr uint32_t spRegId() const noexcept { return _spRegId; }
//! Returns stack frame register id.
inline constexpr uint32_t fpRegId() const noexcept { return _fpRegId; }
//! Returns link register id, if the architecture provides it.
inline constexpr uint32_t linkRegId() const noexcept { return _linkRegId; }
//! Returns instruction pointer register id, if the architecture provides it.
inline constexpr 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 constexpr 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 constexpr bool hasLinkReg() const noexcept { return _linkRegId != BaseReg::kIdBad; }
//! Returns minimum addressable offset on stack guaranteed for all instructions.
inline constexpr uint32_t minStackOffset() const noexcept { return _minStackOffset; }
//! Returns maximum addressable offset on stack depending on specific instruction.
inline constexpr uint32_t maxStackOffset() const noexcept { return _maxStackOffset; }
//! Returns ISA flags of the given register `group`.
inline constexpr uint32_t isaFlags(uint32_t group) const noexcept { return _isaFlags[group]; }
//! Tests whether the given register `group` has the given `flag` set.
inline constexpr bool hasIsaFlag(uint32_t group, uint32_t flag) const noexcept { return (_isaFlags[group] & flag) != 0; }
//! Tests whether the ISA provides register swap instruction for the given register `group`.
inline constexpr bool hasSwap(uint32_t group) const noexcept { return hasIsaFlag(group, kIsaFeatureSwap); }
//! Tests whether the ISA provides push/pop instructions for the given register `group`.
inline constexpr bool hasPushPop(uint32_t group) const noexcept { return hasIsaFlag(group, kIsaFeaturePushPop); }
inline uint32_t hasRegType(uint32_t rType) const noexcept {
return rType <= BaseReg::kTypeMax && _regInfo[rType].signature() != 0;
}
inline uint32_t regTypeToSignature(uint32_t rType) const noexcept {
ASMJIT_ASSERT(rType <= BaseReg::kTypeMax);
return _regInfo[rType].signature();
}
inline uint32_t regTypeToGroup(uint32_t rType) const noexcept {
ASMJIT_ASSERT(rType <= BaseReg::kTypeMax);
return _regInfo[rType].group();
}
inline uint32_t regTypeToSize(uint32_t rType) const noexcept {
ASMJIT_ASSERT(rType <= BaseReg::kTypeMax);
return _regInfo[rType].size();
}
inline uint32_t regTypeToTypeId(uint32_t rType) const noexcept {
ASMJIT_ASSERT(rType <= BaseReg::kTypeMax);
return _regTypeToTypeId[rType];
}
//! \}
//! \name Statics
//! \{
//! Returns a const reference to `ArchTraits` for the given architecture `arch`.
static inline const ArchTraits& byArch(uint32_t arch) noexcept;
//! \}
};
ASMJIT_VARAPI const ArchTraits _archTraits[Environment::kArchCount];
inline const ArchTraits& ArchTraits::byArch(uint32_t arch) noexcept { return _archTraits[arch & ~Environment::kArchBigEndianMask]; }
// ============================================================================
// [asmjit::ArchUtils]
// ============================================================================
//! Architecture utilities.
namespace ArchUtils {
ASMJIT_API Error typeIdToRegInfo(uint32_t arch, uint32_t typeId, uint32_t* typeIdOut, RegInfo* regInfo) noexcept;
} // {ArchUtils}
//! \}
ASMJIT_END_NAMESPACE
#endif // ASMJIT_CORE_ARCHTRAITS_H_INCLUDED