From d02235b83434943b52a6d7c57118205c5082de08 Mon Sep 17 00:00:00 2001 From: kobalicek Date: Sun, 27 Jun 2021 00:08:17 +0200 Subject: Refactored naming of data types in formatted text, which is now part of architecture traits --- src/asmjit/core/archtraits.cpp | 43 ++++++++++----- src/asmjit/core/archtraits.h | 51 ++++++++++++++++++ src/asmjit/core/assembler.cpp | 90 +++++++++++++++++++------------ src/asmjit/core/assembler.h | 2 +- src/asmjit/core/constpool.cpp | 19 +++++-- src/asmjit/core/constpool.h | 4 ++ src/asmjit/core/formatter.cpp | 112 +++++++++++++++++++++++++++++++++++++-- src/asmjit/core/formatter.h | 14 +++++ src/asmjit/core/logger.cpp | 22 -------- src/asmjit/core/logger.h | 3 -- src/asmjit/core/string.cpp | 45 +++++++++++++--- src/asmjit/x86/x86archtraits_p.h | 72 ++++++++++++++----------- 12 files changed, 357 insertions(+), 120 deletions(-) diff --git a/src/asmjit/core/archtraits.cpp b/src/asmjit/core/archtraits.cpp index ad983e7..6c50bb1 100644 --- a/src/asmjit/core/archtraits.cpp +++ b/src/asmjit/core/archtraits.cpp @@ -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] = { diff --git a/src/asmjit/core/archtraits.h b/src/asmjit/core/archtraits.h index 5af6c7e..43ef10f 100644 --- a/src/asmjit/core/archtraits.h +++ b/src/asmjit/core/archtraits.h @@ -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 diff --git a/src/asmjit/core/assembler.cpp b/src/asmjit/core/assembler.cpp index c0cbf0f..6f9fe00 100644 --- a/src/asmjit/core/assembler.cpp +++ b/src/asmjit/core/assembler.cpp @@ -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); - } + + writer.done(this); #ifndef ASMJIT_NO_LOGGING - if (_logger) - _logger->logBinary(start, totalSize); + if (_logger) { + StringTmp<512> sb; + Formatter::formatData(sb, _logger->flags(), arch(), typeId, data, itemCount, repeatCount); + sb.append('\n'); + _logger->log(sb); + } #endif - writer.done(this); 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(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()); diff --git a/src/asmjit/core/assembler.h b/src/asmjit/core/assembler.h index 6e38bc5..c0da819 100644 --- a/src/asmjit/core/assembler.h +++ b/src/asmjit/core/assembler.h @@ -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; diff --git a/src/asmjit/core/constpool.cpp b/src/asmjit/core/constpool.cpp index 65c995b..84d7cd3 100644 --- a/src/asmjit/core/constpool.cpp +++ b/src/asmjit/core/constpool.cpp @@ -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(_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(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; } diff --git a/src/asmjit/core/constpool.h b/src/asmjit/core/constpool.h index d9ac589..fc0e0bc 100644 --- a/src/asmjit/core/constpool.h +++ b/src/asmjit/core/constpool.h @@ -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; } //! \} diff --git a/src/asmjit/core/formatter.cpp b/src/asmjit/core/formatter.cpp index c757c5a..124eebf 100644 --- a/src/asmjit/core/formatter.cpp +++ b/src/asmjit/core/formatter.cpp @@ -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(data), itemCount); +} + Error formatInstruction( String& sb, uint32_t formatFlags, @@ -345,7 +442,7 @@ Error formatNode( case BaseNode::kNodeAlign: { const AlignNode* alignNode = node->as(); 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(); - 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(); + ASMJIT_PROPAGATE(sb.appendFormat("[ConstPool Size=%zu Alignment=%zu]", constPoolNode->size(), constPoolNode->alignment())); + break; + }; + case BaseNode::kNodeComment: { const CommentNode* commentNode = node->as(); ASMJIT_PROPAGATE(sb.appendFormat("; %s", commentNode->inlineComment())); diff --git a/src/asmjit/core/formatter.h b/src/asmjit/core/formatter.h index 14934ba..513d764 100644 --- a/src/asmjit/core/formatter.h +++ b/src/asmjit/core/formatter.h @@ -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 diff --git a/src/asmjit/core/logger.cpp b/src/asmjit/core/logger.cpp index 22e0b9a..90b17e3 100644 --- a/src/asmjit/core/logger.cpp +++ b/src/asmjit/core/logger.cpp @@ -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(data); - - while (i) { - uint32_t n = uint32_t(Support::min(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] // ============================================================================ diff --git a/src/asmjit/core/logger.h b/src/asmjit/core/logger.h index 2840869..ddc1cfc 100644 --- a/src/asmjit/core/logger.h +++ b/src/asmjit/core/logger.h @@ -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; - //! \} }; diff --git a/src/asmjit/core/string.cpp b/src/asmjit/core/string.cpp index e059884..8cebfcc 100644 --- a/src/asmjit/core/string.cpp +++ b/src/asmjit/core/string.cpp @@ -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()); diff --git a/src/asmjit/x86/x86archtraits_p.h b/src/asmjit/x86/x86archtraits_p.h index 095919c..66a6f50 100644 --- a/src/asmjit/x86/x86archtraits_p.h +++ b/src/asmjit/x86/x86archtraits_p.h @@ -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::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::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 + } }; //! \} -- cgit v1.2.3