Refactored naming of data types in formatted text, which is now part of architecture traits

This commit is contained in:
kobalicek
2021-06-27 00:08:17 +02:00
parent 0a709c7a28
commit d02235b834
12 changed files with 359 additions and 122 deletions

View File

@@ -40,18 +40,37 @@ ASMJIT_BEGIN_NAMESPACE
// ============================================================================
static const constexpr ArchTraits noArchTraits = {
0xFF, // SP.
0xFF, // FP.
0xFF, // LR.
0xFF, // PC.
{ 0, 0, 0 }, // Reserved.
0, // HW stack alignment.
0, // Min stack offset.
0, // Max stack offset.
{ 0, 0, 0, 0}, // ISA features [Gp, Vec, Other0, Other1].
{ { 0 } }, // RegTypeToSignature.
{ 0 }, // RegTypeToTypeId.
{ 0 } // TypeIdToRegType.
// SP/FP/LR/PC.
0xFF, 0xFF, 0xFF, 0xFF,
// Reserved,
{ 0, 0, 0 },
// HW stack alignment.
0,
// Min/Max stack offset.
0, 0,
// ISA features [Gp, Vec, Other0, Other1].
{ 0, 0, 0, 0},
// RegTypeToSignature.
{ { 0 } },
// RegTypeToTypeId.
{ 0 },
// TypeIdToRegType.
{ 0 },
// Word names of 8-bit, 16-bit, 32-bit, and 64-bit quantities.
{
ISAWordNameId::kByte,
ISAWordNameId::kHalf,
ISAWordNameId::kWord,
ISAWordNameId::kQuad
}
};
ASMJIT_VARAPI const ArchTraits _archTraits[Environment::kArchCount] = {

View File

@@ -33,6 +33,41 @@ ASMJIT_BEGIN_NAMESPACE
//! \addtogroup asmjit_core
//! \{
//! Identifier used to represent names of different data types across architectures.
enum class ISAWordNameId : uint8_t {
//! Describes 'db' (X86/X86_64 convention, always 8-bit quantity).
kDB = 0,
//! Describes 'dw' (X86/X86_64 convention, always 16-bit word).
kDW,
//! Describes 'dd' (X86/X86_64 convention, always 32-bit word).
kDD,
//! Describes 'dq' (X86/X86_64 convention, always 64-bit word).
kDQ,
//! Describes 'byte' (always 8-bit quantity).
kByte,
//! Describes 'half' (most likely 16-bit word).
kHalf,
//! Describes 'word' (either 16-bit or 32-bit word).
kWord,
//! Describes 'hword' (most likely 16-bit word).
kHWord,
//! Describes 'dword' (either 32-bit or 64-bit word).
kDWord,
//! Describes 'qword' (64-bit word).
kQWord,
//! Describes 'xword' (64-bit word).
kXWord,
//! Describes 'short' (always 16-bit word).
kShort,
//! Describes 'long' (most likely 32-bit word).
kLong,
//! Describes 'quad' (64-bit word).
kQuad,
//! Maximum value.
kMaxValue = kQuad
};
// ============================================================================
// [asmjit::ArchTraits]
// ============================================================================
@@ -60,6 +95,7 @@ struct ArchTraits {
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.
@@ -76,6 +112,9 @@ struct ArchTraits {
//! Maps base TypeId values (from TypeId::_kIdBaseStart) to register types, see \ref Type::Id.
uint8_t _typeIdToRegType[32];
//! Word name identifiers of 8-bit, 16-bit, 32-biit, and 64-bit quantities that appear in formatted text.
ISAWordNameId _isaWordNameIdTable[4];
//! Resets all members to zeros.
inline void reset() noexcept { memset(this, 0, sizeof(*this)); }
@@ -141,6 +180,18 @@ struct ArchTraits {
return _regTypeToTypeId[rType];
}
//! Returns a table of ISA word names that appear in formatted text. Word names are ISA dependent.
//!
//! The index of this table is log2 of the size:
//! - [0] 8-bits
//! - [1] 16-bits
//! - [2] 32-bits
//! - [3] 64-bits
inline const ISAWordNameId* isaWordNameIdTable() const noexcept { return _isaWordNameIdTable; }
//! Returns an ISA word name identifier of the given `index`, see \ref isaWordNameIdTable() for more details.
inline ISAWordNameId isaWordNameId(uint32_t index) const noexcept { return _isaWordNameIdTable[index]; }
//! \}
//! \name Statics

View File

@@ -138,19 +138,6 @@ Error BaseAssembler::bind(const Label& label) {
// [asmjit::BaseAssembler - Embed]
// ============================================================================
#ifndef ASMJIT_NO_LOGGING
struct DataSizeByPower {
char str[4];
};
static const DataSizeByPower dataSizeByPowerTable[] = {
{ "db" },
{ "dw" },
{ "dd" },
{ "dq" }
};
#endif
Error BaseAssembler::embed(const void* data, size_t dataSize) {
if (ASMJIT_UNLIKELY(!_code))
return reportError(DebugUtils::errored(kErrorNotInitialized));
@@ -162,30 +149,34 @@ Error BaseAssembler::embed(const void* data, size_t dataSize) {
ASMJIT_PROPAGATE(writer.ensureSpace(this, dataSize));
writer.emitData(data, dataSize);
writer.done(this);
#ifndef ASMJIT_NO_LOGGING
if (_logger)
_logger->logBinary(data, dataSize);
if (_logger) {
StringTmp<512> sb;
Formatter::formatData(sb, _logger->flags(), arch(), Type::kIdU8, data, dataSize, 1);
sb.append('\n');
_logger->log(sb);
}
#endif
writer.done(this);
return kErrorOk;
}
Error BaseAssembler::embedDataArray(uint32_t typeId, const void* data, size_t itemCcount, size_t repeatCount) {
Error BaseAssembler::embedDataArray(uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount) {
uint32_t deabstractDelta = Type::deabstractDeltaOfSize(registerSize());
uint32_t finalTypeId = Type::deabstract(typeId, deabstractDelta);
if (ASMJIT_UNLIKELY(!Type::isValid(finalTypeId)))
return reportError(DebugUtils::errored(kErrorInvalidArgument));
if (itemCcount == 0 || repeatCount == 0)
if (itemCount == 0 || repeatCount == 0)
return kErrorOk;
uint32_t typeSize = Type::sizeOf(finalTypeId);
Support::FastUInt8 of = 0;
size_t dataSize = Support::mulOverflow(itemCcount, size_t(typeSize), &of);
size_t dataSize = Support::mulOverflow(itemCount, size_t(typeSize), &of);
size_t totalSize = Support::mulOverflow(dataSize, repeatCount, &of);
if (ASMJIT_UNLIKELY(of))
@@ -194,23 +185,37 @@ Error BaseAssembler::embedDataArray(uint32_t typeId, const void* data, size_t it
CodeWriter writer(this);
ASMJIT_PROPAGATE(writer.ensureSpace(this, totalSize));
#ifndef ASMJIT_NO_LOGGING
const uint8_t* start = writer.cursor();
#endif
for (size_t i = 0; i < repeatCount; i++) {
for (size_t i = 0; i < repeatCount; i++)
writer.emitData(data, dataSize);
}
#ifndef ASMJIT_NO_LOGGING
if (_logger)
_logger->logBinary(start, totalSize);
#endif
writer.done(this);
#ifndef ASMJIT_NO_LOGGING
if (_logger) {
StringTmp<512> sb;
Formatter::formatData(sb, _logger->flags(), arch(), typeId, data, itemCount, repeatCount);
sb.append('\n');
_logger->log(sb);
}
#endif
return kErrorOk;
}
#ifndef ASMJIT_NO_LOGGING
static const uint8_t dataTypeIdBySize[9] = {
Type::kIdVoid, // [0] (invalid)
Type::kIdU8, // [1] (uint8_t)
Type::kIdU16, // [2] (uint16_t)
Type::kIdVoid, // [3] (invalid)
Type::kIdU32, // [4] (uint32_t)
Type::kIdVoid, // [5] (invalid)
Type::kIdVoid, // [6] (invalid)
Type::kIdVoid, // [7] (invalid)
Type::kIdU64 // [8] (uint64_t)
};
#endif
Error BaseAssembler::embedConstPool(const Label& label, const ConstPool& pool) {
if (ASMJIT_UNLIKELY(!_code))
return reportError(DebugUtils::errored(kErrorNotInitialized));
@@ -222,19 +227,32 @@ Error BaseAssembler::embedConstPool(const Label& label, const ConstPool& pool) {
ASMJIT_PROPAGATE(bind(label));
size_t size = pool.size();
if (!size)
return kErrorOk;
CodeWriter writer(this);
ASMJIT_PROPAGATE(writer.ensureSpace(this, size));
pool.fill(writer.cursor());
#ifndef ASMJIT_NO_LOGGING
if (_logger)
_logger->logBinary(writer.cursor(), size);
uint8_t* data = writer.cursor();
#endif
pool.fill(writer.cursor());
writer.advance(size);
writer.done(this);
#ifndef ASMJIT_NO_LOGGING
if (_logger) {
uint32_t dataSizeLog2 = Support::min<uint32_t>(Support::ctz(pool.minItemSize()), 3);
uint32_t dataSize = 1 << dataSizeLog2;
StringTmp<512> sb;
Formatter::formatData(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize], data, size >> dataSizeLog2);
sb.append('\n');
_logger->log(sb);
}
#endif
return kErrorOk;
}
@@ -261,7 +279,9 @@ Error BaseAssembler::embedLabel(const Label& label, size_t dataSize) {
#ifndef ASMJIT_NO_LOGGING
if (_logger) {
StringTmp<256> sb;
sb.appendFormat("%s ", dataSizeByPowerTable[Support::ctz(dataSize)].str);
sb.append('.');
Formatter::formatDataType(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize]);
sb.append(' ');
Formatter::formatLabel(sb, 0, this, label.id());
sb.append('\n');
_logger->log(sb);
@@ -320,7 +340,9 @@ Error BaseAssembler::embedLabelDelta(const Label& label, const Label& base, size
#ifndef ASMJIT_NO_LOGGING
if (_logger) {
StringTmp<256> sb;
sb.appendFormat(".%s (", dataSizeByPowerTable[Support::ctz(dataSize)].str);
sb.append('.');
Formatter::formatDataType(sb, _logger->flags(), arch(), dataTypeIdBySize[dataSize]);
sb.append(" (");
Formatter::formatLabel(sb, 0, this, label.id());
sb.append(" - ");
Formatter::formatLabel(sb, 0, this, base.id());

View File

@@ -121,7 +121,7 @@ public:
//! \{
ASMJIT_API Error embed(const void* data, size_t dataSize) override;
ASMJIT_API Error embedDataArray(uint32_t typeId, const void* data, size_t itemCcount, size_t repeatCount = 1) override;
ASMJIT_API Error embedDataArray(uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount = 1) override;
ASMJIT_API Error embedConstPool(const Label& label, const ConstPool& pool) override;
ASMJIT_API Error embedLabel(const Label& label, size_t dataSize = 0) override;

View File

@@ -52,6 +52,7 @@ void ConstPool::reset(Zone* zone) noexcept {
_gapPool = nullptr;
_size = 0;
_alignment = 0;
_minItemSize = 0;
}
// ============================================================================
@@ -186,7 +187,8 @@ Error ConstPool::add(const void* data, size_t size, size_t& dstOffset) noexcept
// Add the initial node to the right index.
node = ConstPool::Tree::_newNode(_zone, data, size, offset, false);
if (!node) return DebugUtils::errored(kErrorOutOfMemory);
if (ASMJIT_UNLIKELY(!node))
return DebugUtils::errored(kErrorOutOfMemory);
_tree[treeIndex].insert(node);
_alignment = Support::max<size_t>(_alignment, size);
@@ -197,23 +199,30 @@ Error ConstPool::add(const void* data, size_t size, size_t& dstOffset) noexcept
// We stop at size 4, it probably doesn't make sense to split constants down
// to 1 byte.
size_t pCount = 1;
while (size > 4) {
size >>= 1;
size_t smallerSize = size;
while (smallerSize > 4) {
pCount <<= 1;
smallerSize >>= 1;
ASMJIT_ASSERT(treeIndex != 0);
treeIndex--;
const uint8_t* pData = static_cast<const uint8_t*>(data);
for (size_t i = 0; i < pCount; i++, pData += size) {
for (size_t i = 0; i < pCount; i++, pData += smallerSize) {
node = _tree[treeIndex].get(pData);
if (node) continue;
node = ConstPool::Tree::_newNode(_zone, pData, size, offset + (i * size), true);
node = ConstPool::Tree::_newNode(_zone, pData, smallerSize, offset + (i * smallerSize), true);
_tree[treeIndex].insert(node);
}
}
if (_minItemSize == 0)
_minItemSize = size;
else
_minItemSize = Support::min(_minItemSize, size);
return kErrorOk;
}

View File

@@ -206,6 +206,8 @@ public:
size_t _size;
//! Required pool alignment.
size_t _alignment;
//! Minimum item size in the pool.
size_t _minItemSize;
//! \name Construction & Destruction
//! \{
@@ -226,6 +228,8 @@ public:
inline size_t size() const noexcept { return _size; }
//! Returns minimum alignment.
inline 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; }
//! \}

View File

@@ -24,6 +24,7 @@
#include "../core/api-build_p.h"
#ifndef ASMJIT_NO_LOGGING
#include "../core/archtraits.h"
#include "../core/builder.h"
#include "../core/codeholder.h"
#include "../core/compiler.h"
@@ -53,6 +54,24 @@ class VirtReg;
namespace Formatter {
static const char wordNameTable[][8] = {
"db",
"dw",
"dd",
"dq",
"byte",
"half",
"word",
"hword",
"dword",
"qword",
"xword",
"short",
"long",
"quad"
};
Error formatTypeId(String& sb, uint32_t typeId) noexcept {
if (typeId == Type::kIdVoid)
return sb.append("void");
@@ -188,6 +207,84 @@ Error formatOperand(
return kErrorInvalidArch;
}
ASMJIT_API Error formatDataType(
String& sb,
uint32_t formatFlags,
uint32_t arch,
uint32_t typeId) noexcept
{
DebugUtils::unused(formatFlags);
if (ASMJIT_UNLIKELY(arch >= Environment::kArchCount))
return DebugUtils::errored(kErrorInvalidArch);
uint32_t typeSize = Type::sizeOf(typeId);
if (typeSize == 0 || typeSize > 8)
return DebugUtils::errored(kErrorInvalidState);
uint32_t typeSizeLog2 = Support::ctz(typeSize);
return sb.append(wordNameTable[size_t(_archTraits[arch].isaWordNameId(typeSizeLog2))]);
}
static Error formatDataHelper(String& sb, const char* typeName, uint32_t typeSize, const uint8_t* data, size_t itemCount) noexcept {
sb.append('.');
sb.append(typeName);
sb.append(' ');
for (size_t i = 0; i < itemCount; i++) {
uint64_t v;
if (i != 0)
ASMJIT_PROPAGATE(sb.append(", ", 2));
switch (typeSize) {
case 1: v = data[0]; break;
case 2: v = Support::readU16u(data); break;
case 4: v = Support::readU32u(data); break;
case 8: v = Support::readU64u(data); break;
}
ASMJIT_PROPAGATE(sb.appendUInt(v, 16, typeSize * 2, String::kFormatAlternate));
data += typeSize;
}
return kErrorOk;
}
Error formatData(
String& sb,
uint32_t formatFlags,
uint32_t arch,
uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount) noexcept
{
DebugUtils::unused(formatFlags);
if (ASMJIT_UNLIKELY(arch >= Environment::kArchCount))
return DebugUtils::errored(kErrorInvalidArch);
uint32_t typeSize = Type::sizeOf(typeId);
if (typeSize == 0)
return DebugUtils::errored(kErrorInvalidState);
if (!Support::isPowerOf2(typeSize)) {
itemCount *= typeSize;
typeSize = 1;
}
while (typeSize > 8u) {
typeSize >>= 1;
itemCount <<= 1;
}
uint32_t typeSizeLog2 = Support::ctz(typeSize);
const char* wordName = wordNameTable[size_t(_archTraits[arch].isaWordNameId(typeSizeLog2))];
if (repeatCount > 1)
ASMJIT_PROPAGATE(sb.appendFormat(".repeat %zu ", repeatCount));
return formatDataHelper(sb, wordName, typeSize, static_cast<const uint8_t*>(data), itemCount);
}
Error formatInstruction(
String& sb,
uint32_t formatFlags,
@@ -345,7 +442,7 @@ Error formatNode(
case BaseNode::kNodeAlign: {
const AlignNode* alignNode = node->as<AlignNode>();
ASMJIT_PROPAGATE(
sb.appendFormat("align %u (%s)",
sb.appendFormat(".align %u (%s)",
alignNode->alignment(),
alignNode->alignMode() == kAlignCode ? "code" : "data"));
break;
@@ -353,10 +450,9 @@ Error formatNode(
case BaseNode::kNodeEmbedData: {
const EmbedDataNode* embedNode = node->as<EmbedDataNode>();
ASMJIT_PROPAGATE(sb.append("embed "));
if (embedNode->repeatCount() != 1)
ASMJIT_PROPAGATE(sb.appendFormat("[repeat=%zu] ", size_t(embedNode->repeatCount())));
ASMJIT_PROPAGATE(sb.appendFormat("%u bytes", embedNode->dataSize()));
ASMJIT_PROPAGATE(sb.append('.'));
ASMJIT_PROPAGATE(formatDataType(sb, formatFlags, builder->arch(), embedNode->typeId()));
ASMJIT_PROPAGATE(sb.appendFormat(" {Count=%zu Repeat=%zu TotalSize=%zu}", embedNode->itemCount(), embedNode->repeatCount(), embedNode->dataSize()));
break;
}
@@ -377,6 +473,12 @@ Error formatNode(
break;
}
case BaseNode::kNodeConstPool: {
const ConstPoolNode* constPoolNode = node->as<ConstPoolNode>();
ASMJIT_PROPAGATE(sb.appendFormat("[ConstPool Size=%zu Alignment=%zu]", constPoolNode->size(), constPoolNode->alignment()));
break;
};
case BaseNode::kNodeComment: {
const CommentNode* commentNode = node->as<CommentNode>();
ASMJIT_PROPAGATE(sb.appendFormat("; %s", commentNode->inlineComment()));

View File

@@ -203,6 +203,20 @@ ASMJIT_API Error formatOperand(
uint32_t arch,
const Operand_& op) noexcept;
//! Appends a formatted data-type to the output string `sb`.
ASMJIT_API Error formatDataType(
String& sb,
uint32_t formatFlags,
uint32_t arch,
uint32_t typeId) noexcept;
//! Appends a formatted data to the output string `sb`.
ASMJIT_API Error formatData(
String& sb,
uint32_t formatFlags,
uint32_t arch,
uint32_t typeId, const void* data, size_t itemCount, size_t repeatCount = 1) noexcept;
//! Appends a formatted instruction to the output string `sb`.
//!
//! \note Emitter is optional, but it's required to format named labels and

View File

@@ -59,28 +59,6 @@ Error Logger::logv(const char* fmt, va_list ap) noexcept {
return log(sb);
}
Error Logger::logBinary(const void* data, size_t size) noexcept {
static const char prefix[] = "db ";
StringTmp<256> sb;
sb.append(prefix, ASMJIT_ARRAY_SIZE(prefix) - 1);
size_t i = size;
const uint8_t* s = static_cast<const uint8_t*>(data);
while (i) {
uint32_t n = uint32_t(Support::min<size_t>(i, 16));
sb.truncate(ASMJIT_ARRAY_SIZE(prefix) - 1);
sb.appendHex(s, n);
sb.append('\n');
ASMJIT_PROPAGATE(log(sb));
s += n;
i -= n;
}
return kErrorOk;
}
// ============================================================================
// [asmjit::FileLogger - Construction / Destruction]
// ============================================================================

View File

@@ -119,9 +119,6 @@ public:
//! string to \ref _log().
ASMJIT_API Error logv(const char* fmt, va_list ap) noexcept;
//! Logs binary `data` of the given `size`.
ASMJIT_API Error logBinary(const void* data, size_t size) noexcept;
//! \}
};

View File

@@ -31,7 +31,7 @@ ASMJIT_BEGIN_NAMESPACE
// [asmjit::String - Globals]
// ============================================================================
static const char String_baseN[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
static const char String_baseN[] = "0123456789ABCDEF";
constexpr size_t kMinAllocSize = 64;
constexpr size_t kMaxAllocSize = SIZE_MAX - Globals::kGrowThreshold;
@@ -256,7 +256,7 @@ Error String::padEnd(size_t n, char c) noexcept {
}
Error String::_opNumber(uint32_t op, uint64_t i, uint32_t base, size_t width, uint32_t flags) noexcept {
if (base < 2 || base > 36)
if (base == 0)
base = 10;
char buf[128];
@@ -284,13 +284,39 @@ Error String::_opNumber(uint32_t op, uint64_t i, uint32_t base, size_t width, ui
// [Number]
// --------------------------------------------------------------------------
do {
uint64_t d = i / base;
uint64_t r = i % base;
switch (base) {
case 2:
case 8:
case 16: {
uint32_t shift = Support::ctz(base);
uint32_t mask = base - 1;
*--p = String_baseN[r];
i = d;
} while (i);
do {
uint64_t d = i >> shift;
size_t r = size_t(i & mask);
*--p = String_baseN[r];
i = d;
} while (i);
break;
}
case 10: {
do {
uint64_t d = i / 10;
uint64_t r = i % 10;
*--p = char(uint32_t('0') + uint32_t(r));
i = d;
} while (i);
break;
}
default:
return DebugUtils::errored(kErrorInvalidArgument);
}
size_t numberSize = (size_t)(buf + ASMJIT_ARRAY_SIZE(buf) - p);
@@ -540,6 +566,9 @@ UNIT(core_string) {
EXPECT(s.appendUInt(1234) == kErrorOk);
EXPECT(s.eq("1234") == true);
EXPECT(s.assignUInt(0xFFFF, 16, 0, String::kFormatAlternate) == kErrorOk);
EXPECT(s.eq("0xFFFF"));
StringTmp<64> sTmp;
EXPECT(sTmp.isLarge());
EXPECT(sTmp.isExternal());

View File

@@ -39,22 +39,20 @@ ASMJIT_BEGIN_SUB_NAMESPACE(x86)
// ============================================================================
static const constexpr ArchTraits x86ArchTraits = {
Gp::kIdSp, // SP.
Gp::kIdBp, // FP.
0xFF, // LR.
0xFF, // PC.
{ 0, 0, 0 }, // Reserved.
1, // HW stack alignment.
0x7FFFFFFFu, // Min stack offset.
0x7FFFFFFFu, // Max stack offset.
// SP/FP/LR/PC.
Gp::kIdSp, Gp::kIdBp, 0xFF, 0xFF,
// Reserved.
{ 0, 0, 0 },
// HW stack alignment.
1,
// Min/Max stack offset
0x7FFFFFFFu, 0x7FFFFFFFu,
// ISA features [Gp, Vec, Other0, Other1].
{
ArchTraits::kIsaFeatureSwap | ArchTraits::kIsaFeaturePushPop,
0,
0,
0
},
{ ArchTraits::kIsaFeatureSwap | ArchTraits::kIsaFeaturePushPop, 0, 0, 0 },
// RegInfo.
#define V(index) { x86::RegTraits<index>::kSignature }
@@ -83,8 +81,16 @@ static const constexpr ArchTraits x86ArchTraits = {
index + Type::_kIdBaseStart == Type::kIdMask64 ? Reg::kTypeKReg : \
index + Type::_kIdBaseStart == Type::kIdMmx32 ? Reg::kTypeMm : \
index + Type::_kIdBaseStart == Type::kIdMmx64 ? Reg::kTypeMm : Reg::kTypeNone)
{ ASMJIT_LOOKUP_TABLE_32(V, 0) }
{ ASMJIT_LOOKUP_TABLE_32(V, 0) },
#undef V
// Word names of 8-bit, 16-bit, 32-bit, and 64-bit quantities.
{
ISAWordNameId::kDB,
ISAWordNameId::kDW,
ISAWordNameId::kDD,
ISAWordNameId::kDQ
}
};
// ============================================================================
@@ -92,22 +98,20 @@ static const constexpr ArchTraits x86ArchTraits = {
// ============================================================================
static const constexpr ArchTraits x64ArchTraits = {
Gp::kIdSp, // SP.
Gp::kIdBp, // FP.
0xFF, // LR.
0xFF, // PC.
{ 0, 0, 0 }, // Reserved.
1, // HW stack alignment.
0x7FFFFFFFu, // Min stack offset.
0x7FFFFFFFu, // Max stack offset.
// SP/FP/LR/PC.
Gp::kIdSp, Gp::kIdBp, 0xFF, 0xFF,
// Reserved.
{ 0, 0, 0 },
// HW stack alignment.
1,
// Min/Max stack offset
0x7FFFFFFFu, 0x7FFFFFFFu,
// ISA features [Gp, Vec, Other0, Other1].
{
ArchTraits::kIsaFeatureSwap | ArchTraits::kIsaFeaturePushPop,
0,
0,
0
},
{ ArchTraits::kIsaFeatureSwap | ArchTraits::kIsaFeaturePushPop, 0, 0, 0 },
// RegInfo.
#define V(index) { x86::RegTraits<index>::kSignature }
@@ -138,8 +142,16 @@ static const constexpr ArchTraits x64ArchTraits = {
index + Type::_kIdBaseStart == Type::kIdMask64 ? Reg::kTypeKReg : \
index + Type::_kIdBaseStart == Type::kIdMmx32 ? Reg::kTypeMm : \
index + Type::_kIdBaseStart == Type::kIdMmx64 ? Reg::kTypeMm : Reg::kTypeNone)
{ ASMJIT_LOOKUP_TABLE_32(V, 0) }
{ ASMJIT_LOOKUP_TABLE_32(V, 0) },
#undef V
// Word names of 8-bit, 16-bit, 32-bit, and 64-bit quantities.
{
ISAWordNameId::kDB,
ISAWordNameId::kDW,
ISAWordNameId::kDD,
ISAWordNameId::kDQ
}
};
//! \}