mirror of
https://github.com/asmjit/asmjit.git
synced 2025-12-17 12:34:35 +03:00
[ABI] Optimized size of instruction name data (X86, AArch64)
This commit is contained in:
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
#include "../core/cpuinfo.h"
|
#include "../core/cpuinfo.h"
|
||||||
#include "../core/misc_p.h"
|
#include "../core/misc_p.h"
|
||||||
#include "../core/support.h"
|
#include "../core/support_p.h"
|
||||||
#include "../arm/a64instapi_p.h"
|
#include "../arm/a64instapi_p.h"
|
||||||
#include "../arm/a64instdb_p.h"
|
#include "../arm/a64instdb_p.h"
|
||||||
#include "../arm/a64operand.h"
|
#include "../arm/a64operand.h"
|
||||||
@@ -26,8 +26,11 @@ Error InstInternal::instIdToString(Arch arch, InstId instId, String& output) noe
|
|||||||
if (ASMJIT_UNLIKELY(!Inst::isDefinedId(realId)))
|
if (ASMJIT_UNLIKELY(!Inst::isDefinedId(realId)))
|
||||||
return DebugUtils::errored(kErrorInvalidInstruction);
|
return DebugUtils::errored(kErrorInvalidInstruction);
|
||||||
|
|
||||||
const InstDB::InstInfo& info = InstDB::infoById(realId);
|
|
||||||
return output.append(InstDB::_nameData + info._nameDataIndex);
|
char nameData[32];
|
||||||
|
size_t nameSize = Support::decodeInstName(nameData, InstDB::_instNameIndexTable[realId], InstDB::_instNameStringTable);
|
||||||
|
|
||||||
|
return output.append(nameData, nameSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexcept {
|
InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexcept {
|
||||||
@@ -46,30 +49,28 @@ InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexce
|
|||||||
if (ASMJIT_UNLIKELY(prefix > 'z' - 'a'))
|
if (ASMJIT_UNLIKELY(prefix > 'z' - 'a'))
|
||||||
return Inst::kIdNone;
|
return Inst::kIdNone;
|
||||||
|
|
||||||
uint32_t index = InstDB::instNameIndex[prefix].start;
|
size_t base = InstDB::instNameIndex[prefix].start;
|
||||||
if (ASMJIT_UNLIKELY(!index))
|
size_t end = InstDB::instNameIndex[prefix].end;
|
||||||
|
|
||||||
|
if (ASMJIT_UNLIKELY(!base))
|
||||||
return Inst::kIdNone;
|
return Inst::kIdNone;
|
||||||
|
|
||||||
const char* nameData = InstDB::_nameData;
|
char nameData[32];
|
||||||
const InstDB::InstInfo* table = InstDB::_instInfoTable;
|
for (size_t lim = end - base; lim != 0; lim >>= 1) {
|
||||||
|
size_t instId = base + (lim >> 1);
|
||||||
|
size_t nameSize = Support::decodeInstName(nameData, InstDB::_instNameIndexTable[instId], InstDB::_instNameStringTable);
|
||||||
|
|
||||||
const InstDB::InstInfo* base = table + index;
|
int result = Support::compareStringViews(s, len, nameData, nameSize);
|
||||||
const InstDB::InstInfo* end = table + InstDB::instNameIndex[prefix].end;
|
if (result < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
for (size_t lim = (size_t)(end - base); lim != 0; lim >>= 1) {
|
if (result > 0) {
|
||||||
const InstDB::InstInfo* cur = base + (lim >> 1);
|
base = instId + 1;
|
||||||
int result = Support::cmpInstName(nameData + cur[0]._nameDataIndex, s, len);
|
|
||||||
|
|
||||||
if (result < 0) {
|
|
||||||
base = cur + 1;
|
|
||||||
lim--;
|
lim--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result > 0)
|
return InstId(instId);
|
||||||
continue;
|
|
||||||
|
|
||||||
return uint32_t((size_t)(cur - table));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Inst::kIdNone;
|
return Inst::kIdNone;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -39,9 +39,7 @@ struct InstInfo {
|
|||||||
uint32_t _encoding : 8;
|
uint32_t _encoding : 8;
|
||||||
//! Index to data specific to each encoding type.
|
//! Index to data specific to each encoding type.
|
||||||
uint32_t _encodingDataIndex : 8;
|
uint32_t _encodingDataIndex : 8;
|
||||||
uint32_t _reserved : 2;
|
uint32_t _reserved : 16;
|
||||||
//! Index to \ref _nameData.
|
|
||||||
uint32_t _nameDataIndex : 14;
|
|
||||||
|
|
||||||
uint16_t _rwInfoIndex;
|
uint16_t _rwInfoIndex;
|
||||||
uint16_t _flags;
|
uint16_t _flags;
|
||||||
|
|||||||
@@ -861,7 +861,8 @@ struct InstNameIndex {
|
|||||||
// ====================
|
// ====================
|
||||||
|
|
||||||
#ifndef ASMJIT_NO_TEXT
|
#ifndef ASMJIT_NO_TEXT
|
||||||
extern const char _nameData[];
|
extern const uint32_t _instNameIndexTable[];
|
||||||
|
extern const char _instNameStringTable[];
|
||||||
extern const InstNameIndex instNameIndex[26];
|
extern const InstNameIndex instNameIndex[26];
|
||||||
#endif // !ASMJIT_NO_TEXT
|
#endif // !ASMJIT_NO_TEXT
|
||||||
|
|
||||||
|
|||||||
@@ -939,6 +939,18 @@ static ASMJIT_FORCE_INLINE int cmpInstName(const char* a, const char* b, size_t
|
|||||||
return int(uint8_t(a[size]));
|
return int(uint8_t(a[size]));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//! Compares two string views.
|
||||||
|
static ASMJIT_FORCE_INLINE int compareStringViews(const char* aData, size_t aSize, const char* bData, size_t bSize) noexcept {
|
||||||
|
size_t size = Support::min(aSize, bSize);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
int c = int(uint8_t(aData[i])) - int(uint8_t(bData[i]));
|
||||||
|
if (c != 0)
|
||||||
|
return c;
|
||||||
|
}
|
||||||
|
|
||||||
|
return int(aSize) - int(bSize);
|
||||||
|
}
|
||||||
// Support - Memory Read Access - 8 Bits
|
// Support - Memory Read Access - 8 Bits
|
||||||
// =====================================
|
// =====================================
|
||||||
|
|
||||||
|
|||||||
64
src/asmjit/core/support_p.h
Normal file
64
src/asmjit/core/support_p.h
Normal file
@@ -0,0 +1,64 @@
|
|||||||
|
// This file is part of AsmJit project <https://asmjit.com>
|
||||||
|
//
|
||||||
|
// See asmjit.h or LICENSE.md for license and copyright information
|
||||||
|
// SPDX-License-Identifier: Zlib
|
||||||
|
|
||||||
|
#ifndef ASMJIT_CORE_SUPPORT_P_H_INCLUDED
|
||||||
|
#define ASMJIT_CORE_SUPPORT_P_H_INCLUDED
|
||||||
|
|
||||||
|
#include "../core/support.h"
|
||||||
|
|
||||||
|
ASMJIT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
//! \addtogroup asmjit_utilities
|
||||||
|
//! \{
|
||||||
|
|
||||||
|
namespace Support {
|
||||||
|
|
||||||
|
//! \cond INTERNAL
|
||||||
|
|
||||||
|
static ASMJIT_FORCE_INLINE char decode5BitChar(uint32_t c) noexcept {
|
||||||
|
uint32_t base = c <= 26 ? uint32_t('a') - 1u : uint32_t('0') - 27u;
|
||||||
|
return char(base + c);
|
||||||
|
}
|
||||||
|
|
||||||
|
static ASMJIT_FORCE_INLINE size_t decodeInstName(char nameOut[32], uint32_t index, const char* stringTable) noexcept {
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
if (index & 0x80000000u) {
|
||||||
|
// Small string of 5-bit characters.
|
||||||
|
for (i = 0; i < 6; i++, index >>= 5) {
|
||||||
|
uint32_t c = index & 0x1F;
|
||||||
|
if (c == 0)
|
||||||
|
break;
|
||||||
|
nameOut[i] = decode5BitChar(c);
|
||||||
|
}
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
size_t prefixBase = index & 0xFFFu;
|
||||||
|
size_t prefixSize = (index >> 12) & 0xFu;
|
||||||
|
|
||||||
|
size_t suffixBase = (index >> 16) & 0xFFFu;
|
||||||
|
size_t suffixSize = (index >> 28) & 0x7u;
|
||||||
|
|
||||||
|
for (i = 0; i < prefixSize; i++)
|
||||||
|
nameOut[i] = stringTable[prefixBase + i];
|
||||||
|
|
||||||
|
char* suffixOut = nameOut + prefixSize;
|
||||||
|
for (i = 0; i < suffixSize; i++)
|
||||||
|
suffixOut[i] = stringTable[suffixBase + i];
|
||||||
|
|
||||||
|
return prefixSize + suffixSize;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
//! \endcond
|
||||||
|
|
||||||
|
} // {Support}
|
||||||
|
|
||||||
|
//! \}
|
||||||
|
|
||||||
|
ASMJIT_END_NAMESPACE
|
||||||
|
|
||||||
|
#endif // ASMJIT_CORE_SUPPORT_P_H_INCLUDED
|
||||||
@@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#include "../core/cpuinfo.h"
|
#include "../core/cpuinfo.h"
|
||||||
#include "../core/misc_p.h"
|
#include "../core/misc_p.h"
|
||||||
#include "../core/support.h"
|
#include "../core/support_p.h"
|
||||||
#include "../x86/x86instapi_p.h"
|
#include "../x86/x86instapi_p.h"
|
||||||
#include "../x86/x86instdb_p.h"
|
#include "../x86/x86instdb_p.h"
|
||||||
#include "../x86/x86opcode_p.h"
|
#include "../x86/x86opcode_p.h"
|
||||||
@@ -44,8 +44,10 @@ Error InstInternal::instIdToString(Arch arch, InstId instId, String& output) noe
|
|||||||
if (ASMJIT_UNLIKELY(!Inst::isDefinedId(instId)))
|
if (ASMJIT_UNLIKELY(!Inst::isDefinedId(instId)))
|
||||||
return DebugUtils::errored(kErrorInvalidInstruction);
|
return DebugUtils::errored(kErrorInvalidInstruction);
|
||||||
|
|
||||||
const InstDB::InstInfo& info = InstDB::infoById(instId);
|
char nameData[32];
|
||||||
return output.append(InstDB::_nameData + info._nameDataIndex);
|
size_t nameSize = Support::decodeInstName(nameData, InstDB::_instNameIndexTable[instId], InstDB::_instNameStringTable);
|
||||||
|
|
||||||
|
return output.append(nameData, nameSize);
|
||||||
}
|
}
|
||||||
|
|
||||||
InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexcept {
|
InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexcept {
|
||||||
@@ -64,30 +66,28 @@ InstId InstInternal::stringToInstId(Arch arch, const char* s, size_t len) noexce
|
|||||||
if (ASMJIT_UNLIKELY(prefix > 'z' - 'a'))
|
if (ASMJIT_UNLIKELY(prefix > 'z' - 'a'))
|
||||||
return Inst::kIdNone;
|
return Inst::kIdNone;
|
||||||
|
|
||||||
uint32_t index = InstDB::instNameIndex[prefix].start;
|
size_t base = InstDB::instNameIndex[prefix].start;
|
||||||
if (ASMJIT_UNLIKELY(!index))
|
size_t end = InstDB::instNameIndex[prefix].end;
|
||||||
|
|
||||||
|
if (ASMJIT_UNLIKELY(!base))
|
||||||
return Inst::kIdNone;
|
return Inst::kIdNone;
|
||||||
|
|
||||||
const char* nameData = InstDB::_nameData;
|
char nameData[32];
|
||||||
const InstDB::InstInfo* table = InstDB::_instInfoTable;
|
for (size_t lim = end - base; lim != 0; lim >>= 1) {
|
||||||
|
size_t instId = base + (lim >> 1);
|
||||||
|
size_t nameSize = Support::decodeInstName(nameData, InstDB::_instNameIndexTable[instId], InstDB::_instNameStringTable);
|
||||||
|
|
||||||
const InstDB::InstInfo* base = table + index;
|
int result = Support::compareStringViews(s, len, nameData, nameSize);
|
||||||
const InstDB::InstInfo* end = table + InstDB::instNameIndex[prefix].end;
|
if (result < 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
for (size_t lim = (size_t)(end - base); lim != 0; lim >>= 1) {
|
if (result > 0) {
|
||||||
const InstDB::InstInfo* cur = base + (lim >> 1);
|
base = instId + 1;
|
||||||
int result = Support::cmpInstName(nameData + cur[0]._nameDataIndex, s, len);
|
|
||||||
|
|
||||||
if (result < 0) {
|
|
||||||
base = cur + 1;
|
|
||||||
lim--;
|
lim--;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (result > 0)
|
return InstId(instId);
|
||||||
continue;
|
|
||||||
|
|
||||||
return InstId((size_t)(cur - table));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return Inst::kIdNone;
|
return Inst::kIdNone;
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -442,8 +442,8 @@ ASMJIT_VARAPI const CommonInfo _commonInfoTable[];
|
|||||||
|
|
||||||
//! Instruction information.
|
//! Instruction information.
|
||||||
struct InstInfo {
|
struct InstInfo {
|
||||||
//! Index to \ref _nameData.
|
//! Reserved for future use.
|
||||||
uint32_t _nameDataIndex : 14;
|
uint32_t _reserved : 14;
|
||||||
//! Index to \ref _commonInfoTable.
|
//! Index to \ref _commonInfoTable.
|
||||||
uint32_t _commonInfoIndex : 10;
|
uint32_t _commonInfoIndex : 10;
|
||||||
//! Index to \ref _additionalInfoTable.
|
//! Index to \ref _additionalInfoTable.
|
||||||
|
|||||||
@@ -295,7 +295,8 @@ extern const uint32_t _mainOpcodeTable[];
|
|||||||
extern const uint32_t _altOpcodeTable[];
|
extern const uint32_t _altOpcodeTable[];
|
||||||
|
|
||||||
#ifndef ASMJIT_NO_TEXT
|
#ifndef ASMJIT_NO_TEXT
|
||||||
extern const char _nameData[];
|
extern const uint32_t _instNameIndexTable[];
|
||||||
|
extern const char _instNameStringTable[];
|
||||||
extern const InstNameIndex instNameIndex[26];
|
extern const InstNameIndex instNameIndex[26];
|
||||||
#endif // !ASMJIT_NO_TEXT
|
#endif // !ASMJIT_NO_TEXT
|
||||||
|
|
||||||
|
|||||||
@@ -133,11 +133,8 @@ class ArmTableGen extends core.TableGen {
|
|||||||
|
|
||||||
// [06] OpcodeDataIndex.
|
// [06] OpcodeDataIndex.
|
||||||
"([^\\)]+)" +
|
"([^\\)]+)" +
|
||||||
"\\s*,\\s*" +
|
|
||||||
|
|
||||||
// [07] NameDataIndex.
|
|
||||||
"([^\\)]+)" +
|
|
||||||
"\\s*\\)"
|
"\\s*\\)"
|
||||||
|
|
||||||
, "g");
|
, "g");
|
||||||
|
|
||||||
var m;
|
var m;
|
||||||
@@ -168,9 +165,7 @@ class ArmTableGen extends core.TableGen {
|
|||||||
opcodeData : opcodeData, // Opcode data.
|
opcodeData : opcodeData, // Opcode data.
|
||||||
opcodeDataIndex : -1, // Opcode data index.
|
opcodeDataIndex : -1, // Opcode data index.
|
||||||
rwInfo : rwInfo, // RW info.
|
rwInfo : rwInfo, // RW info.
|
||||||
flags : instFlags, // Instruction flags.
|
flags : instFlags // Instruction flags.
|
||||||
|
|
||||||
nameIndex : -1 // Index to InstDB::_nameData.
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -188,8 +183,7 @@ class ArmTableGen extends core.TableGen {
|
|||||||
String(inst.opcodeData ).padEnd(86) + ", " +
|
String(inst.opcodeData ).padEnd(86) + ", " +
|
||||||
String(inst.rwInfo ).padEnd(10) + ", " +
|
String(inst.rwInfo ).padEnd(10) + ", " +
|
||||||
String(inst.flags ).padEnd(26) + ", " +
|
String(inst.flags ).padEnd(26) + ", " +
|
||||||
String(inst.opcodeDataIndex ).padEnd( 3) + ", " +
|
String(inst.opcodeDataIndex ).padEnd( 3) + ")" ;
|
||||||
String(inst.nameIndex ).padEnd( 4) + ")";
|
|
||||||
}) + "\n";
|
}) + "\n";
|
||||||
return this.inject("InstInfo", s, this.insts.length * 4);
|
return this.inject("InstInfo", s, this.insts.length * 4);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -500,9 +500,8 @@ class X86TableGen extends core.TableGen {
|
|||||||
// --- autogenerated fields ---
|
// --- autogenerated fields ---
|
||||||
"([^\\)]+)" + "," + // [05] MainOpcodeIndex.
|
"([^\\)]+)" + "," + // [05] MainOpcodeIndex.
|
||||||
"([^\\)]+)" + "," + // [06] AltOpcodeIndex.
|
"([^\\)]+)" + "," + // [06] AltOpcodeIndex.
|
||||||
"([^\\)]+)" + "," + // [07] NameIndex.
|
"([^\\)]+)" + "," + // [07] CommonDataIndex.
|
||||||
"([^\\)]+)" + "," + // [08] CommonDataIndex.
|
"([^\\)]+)" + "\\)", // [08] OperationDataIndex.
|
||||||
"([^\\)]+)" + "\\)", // [09] OperationDataIndex.
|
|
||||||
"g");
|
"g");
|
||||||
|
|
||||||
var m;
|
var m;
|
||||||
@@ -562,7 +561,6 @@ class X86TableGen extends core.TableGen {
|
|||||||
String(inst.opcode1 ).padEnd(26) + ", " +
|
String(inst.opcode1 ).padEnd(26) + ", " +
|
||||||
String(inst.mainOpcodeIndex ).padEnd( 3) + ", " +
|
String(inst.mainOpcodeIndex ).padEnd( 3) + ", " +
|
||||||
String(inst.altOpcodeIndex ).padEnd( 3) + ", " +
|
String(inst.altOpcodeIndex ).padEnd( 3) + ", " +
|
||||||
String(inst.nameIndex ).padEnd( 5) + ", " +
|
|
||||||
String(inst.commonInfoIndex ).padEnd( 3) + ", " +
|
String(inst.commonInfoIndex ).padEnd( 3) + ", " +
|
||||||
String(inst.additionalInfoIndex).padEnd( 3) + ")";
|
String(inst.additionalInfoIndex).padEnd( 3) + ")";
|
||||||
}) + "\n";
|
}) + "\n";
|
||||||
|
|||||||
@@ -580,6 +580,218 @@ class IndexedString {
|
|||||||
}
|
}
|
||||||
exports.IndexedString = IndexedString;
|
exports.IndexedString = IndexedString;
|
||||||
|
|
||||||
|
|
||||||
|
// ============================================================================
|
||||||
|
// [InstructionNameData]
|
||||||
|
// ============================================================================
|
||||||
|
|
||||||
|
function decimalToHexString(number, pad) {
|
||||||
|
if (number < 0)
|
||||||
|
number = 0xFFFFFFFF + number + 1;
|
||||||
|
|
||||||
|
let s = number.toString(16).toUpperCase();
|
||||||
|
if (pad)
|
||||||
|
s = s.padStart(pad, "0")
|
||||||
|
return s;
|
||||||
|
}
|
||||||
|
|
||||||
|
function charTo5Bit(c) {
|
||||||
|
if (c >= 'a' && c <= 'z')
|
||||||
|
return 1 + (c.charCodeAt(0) - 'a'.charCodeAt(0));
|
||||||
|
else if (c >= '0' && c <= '4')
|
||||||
|
return 1 + 26 + (c.charCodeAt(0) - '0'.charCodeAt(0));
|
||||||
|
else
|
||||||
|
FAIL(`Character '${c}' cannot be encoded into a 5-bit string`);
|
||||||
|
}
|
||||||
|
|
||||||
|
class InstructionNameData {
|
||||||
|
constructor() {
|
||||||
|
this.names = [];
|
||||||
|
this.primaryTable = [];
|
||||||
|
this.stringTable = "";
|
||||||
|
this.size = 0;
|
||||||
|
this.indexComment = [];
|
||||||
|
this.maxNameLength = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
add(s) {
|
||||||
|
// First try to encode the string with 5-bit characters that fit into a 32-bit int.
|
||||||
|
if (/^[a-z0-4]{0,6}$/.test(s)) {
|
||||||
|
let index = 0;
|
||||||
|
for (let i = 0; i < s.length; i++)
|
||||||
|
index |= charTo5Bit(s[i]) << (i * 5);
|
||||||
|
|
||||||
|
this.names.push(s);
|
||||||
|
this.primaryTable.push(index | (1 << 31));
|
||||||
|
this.indexComment.push(`Small '${s}'.`);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
// Put the string into a string table.
|
||||||
|
this.names.push(s);
|
||||||
|
this.primaryTable.push(-1);
|
||||||
|
this.indexComment.push(``);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (this.maxNameLength < s.length)
|
||||||
|
this.maxNameLength = s.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
index() {
|
||||||
|
const kMaxPrefixSize = 15;
|
||||||
|
const kMaxSuffixSize = 7;
|
||||||
|
const names = [];
|
||||||
|
|
||||||
|
for (let idx = 0; idx < this.primaryTable.length; idx++) {
|
||||||
|
if (this.primaryTable[idx] === -1) {
|
||||||
|
names.push({ name: this.names[idx], index: idx });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
names.sort(function(a, b) {
|
||||||
|
if (a.name.length > b.name.length)
|
||||||
|
return -1;
|
||||||
|
if (a.name.length < b.name.length)
|
||||||
|
return 1;
|
||||||
|
return (a > b) ? 1 : (a < b) ? -1 : 0;
|
||||||
|
});
|
||||||
|
|
||||||
|
for (let z = 0; z < names.length; z++) {
|
||||||
|
const idx = names[z].index;
|
||||||
|
const name = names[z].name;
|
||||||
|
|
||||||
|
let done = false;
|
||||||
|
let longestPrefix = 0;
|
||||||
|
let longestSuffix = 0;
|
||||||
|
|
||||||
|
let prefix = "";
|
||||||
|
let suffix = "";
|
||||||
|
|
||||||
|
for (let i = Math.min(name.length, kMaxPrefixSize); i > 0; i--) {
|
||||||
|
prefix = name.substring(0, i);
|
||||||
|
suffix = name.substring(i);
|
||||||
|
|
||||||
|
const prefixIndex = this.stringTable.indexOf(prefix);
|
||||||
|
const suffixIndex = this.stringTable.indexOf(suffix);
|
||||||
|
|
||||||
|
// Matched both parts?
|
||||||
|
if (prefixIndex !== -1 && suffix === "") {
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefixIndex !== -1 && suffixIndex !== -1) {
|
||||||
|
done = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefixIndex !== -1 && longestPrefix === 0)
|
||||||
|
longestPrefix = prefix.length;
|
||||||
|
|
||||||
|
if (suffixIndex !== -1 && suffix.length > longestSuffix)
|
||||||
|
longestSuffix = suffix.length;
|
||||||
|
|
||||||
|
if (suffix.length === kMaxSuffixSize)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!done) {
|
||||||
|
let minPrefixSize = name.length >= 8 ? name.length / 2 + 1 : name.length - 2;
|
||||||
|
|
||||||
|
prefix = "";
|
||||||
|
suffix = "";
|
||||||
|
|
||||||
|
if (longestPrefix >= minPrefixSize) {
|
||||||
|
prefix = name.substring(0, longestPrefix);
|
||||||
|
suffix = name.substring(longestPrefix);
|
||||||
|
}
|
||||||
|
else if (longestSuffix) {
|
||||||
|
const splitAt = Math.min(name.length - longestSuffix, kMaxPrefixSize);;
|
||||||
|
prefix = name.substring(0, splitAt);
|
||||||
|
suffix = name.substring(splitAt);
|
||||||
|
}
|
||||||
|
else if (name.length > kMaxPrefixSize) {
|
||||||
|
prefix = name.substring(0, kMaxPrefixSize);
|
||||||
|
suffix = name.substring(kMaxPrefixSize);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
prefix = name;
|
||||||
|
suffix = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (suffix) {
|
||||||
|
const prefixIndex = this.addOrReferenceString(prefix);
|
||||||
|
const suffixIndex = this.addOrReferenceString(suffix);
|
||||||
|
|
||||||
|
this.primaryTable[idx] = prefixIndex | (prefix.length << 12) | (suffixIndex << 16) | (suffix.length << 28);
|
||||||
|
this.indexComment[idx] = `Large '${prefix}|${suffix}'.`;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
const prefixIndex = this.addOrReferenceString(prefix);
|
||||||
|
|
||||||
|
this.primaryTable[idx] = prefixIndex | (prefix.length << 12);
|
||||||
|
this.indexComment[idx] = `Large '${prefix}'.`;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
addOrReferenceString(s) {
|
||||||
|
let index = this.stringTable.indexOf(s);
|
||||||
|
if (index === -1) {
|
||||||
|
index = this.stringTable.length;
|
||||||
|
this.stringTable += s;
|
||||||
|
}
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
|
||||||
|
formatIndexTable(tableName) {
|
||||||
|
if (this.size === -1)
|
||||||
|
FAIL(`IndexedString.formatIndexTable(): Not indexed yet, call index()`);
|
||||||
|
|
||||||
|
let s = "";
|
||||||
|
for (let i = 0; i < this.primaryTable.length; i++) {
|
||||||
|
s += "0x" + decimalToHexString(this.primaryTable[i], 8);
|
||||||
|
s += i !== this.primaryTable.length - 1 ? "," : " ";
|
||||||
|
s += " // " + this.indexComment[i] + "\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return `const uint32_t ${tableName}[] = {\n${StringUtils.indent(s, " ")}};\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
formatStringTable(tableName) {
|
||||||
|
if (this.size === -1)
|
||||||
|
FAIL(`IndexedString.formatStringTable(): Not indexed yet, call index()`);
|
||||||
|
|
||||||
|
let s = "";
|
||||||
|
for (let i = 0; i < this.stringTable.length; i += 80) {
|
||||||
|
if (s)
|
||||||
|
s += "\n"
|
||||||
|
s += '"' + this.stringTable.substring(i, i + 80) + '"';
|
||||||
|
}
|
||||||
|
s += ";\n";
|
||||||
|
|
||||||
|
return `const char ${tableName}[] =\n${StringUtils.indent(s, " ")}\n`;
|
||||||
|
}
|
||||||
|
|
||||||
|
getSize() {
|
||||||
|
if (this.size === -1)
|
||||||
|
FAIL(`IndexedString.getSize(): Not indexed yet, call index()`);
|
||||||
|
|
||||||
|
return this.primaryTable.length * 4 + this.stringTable.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
getIndex(k) {
|
||||||
|
if (this.size === -1)
|
||||||
|
FAIL(`IndexedString.getIndex(): Not indexed yet, call index()`);
|
||||||
|
|
||||||
|
if (!hasOwn.call(this.map, k))
|
||||||
|
FAIL(`IndexedString.getIndex(): Key '${k}' not found.`);
|
||||||
|
|
||||||
|
return this.map[k];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
exports.InstructionNameData = InstructionNameData;
|
||||||
|
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
// [IndexedArray]
|
// [IndexedArray]
|
||||||
// ============================================================================
|
// ============================================================================
|
||||||
@@ -891,41 +1103,37 @@ class NameTable extends Task {
|
|||||||
}
|
}
|
||||||
|
|
||||||
run() {
|
run() {
|
||||||
const arch = this.ctx.arch;
|
|
||||||
const none = "Inst::kIdNone";
|
const none = "Inst::kIdNone";
|
||||||
|
|
||||||
const insts = this.ctx.insts;
|
const insts = this.ctx.insts;
|
||||||
const instNames = new IndexedString();
|
|
||||||
|
|
||||||
const instFirst = new Array(26);
|
const instFirst = new Array(26);
|
||||||
const instLast = new Array(26);
|
const instLast = new Array(26);
|
||||||
|
|
||||||
var maxLength = 0;
|
const instNameData = new InstructionNameData();
|
||||||
for (var i = 0; i < insts.length; i++) {
|
|
||||||
const inst = insts[i];
|
|
||||||
instNames.add(inst.displayName);
|
|
||||||
maxLength = Math.max(maxLength, inst.displayName.length);
|
|
||||||
}
|
|
||||||
instNames.index();
|
|
||||||
|
|
||||||
for (var i = 0; i < insts.length; i++) {
|
for (let i = 0; i < insts.length; i++)
|
||||||
|
instNameData.add(insts[i].displayName);
|
||||||
|
instNameData.index();
|
||||||
|
|
||||||
|
for (let i = 0; i < insts.length; i++) {
|
||||||
const inst = insts[i];
|
const inst = insts[i];
|
||||||
const name = inst.displayName;
|
const name = inst.displayName;
|
||||||
const nameIndex = instNames.getIndex(name);
|
|
||||||
|
|
||||||
const index = name.charCodeAt(0) - 'a'.charCodeAt(0);
|
const index = name.charCodeAt(0) - 'a'.charCodeAt(0);
|
||||||
|
|
||||||
if (index < 0 || index >= 26)
|
if (index < 0 || index >= 26)
|
||||||
FAIL(`TableGen.generateNameData(): Invalid lookup character '${name[0]}' of '${name}'`);
|
FAIL(`TableGen.generateNameData(): Invalid lookup character '${name[0]}' of '${name}'`);
|
||||||
|
|
||||||
inst.nameIndex = nameIndex;
|
|
||||||
if (instFirst[index] === undefined)
|
if (instFirst[index] === undefined)
|
||||||
instFirst[index] = `Inst::kId${inst.enum}`;
|
instFirst[index] = `Inst::kId${inst.enum}`;
|
||||||
instLast[index] = `Inst::kId${inst.enum}`;
|
instLast[index] = `Inst::kId${inst.enum}`;
|
||||||
}
|
}
|
||||||
|
|
||||||
var s = "";
|
var s = "";
|
||||||
s += `const char InstDB::_nameData[] =\n${instNames.format(kIndent, kJustify)}\n`;
|
s += instNameData.formatIndexTable("InstDB::_instNameIndexTable");
|
||||||
s += `\n`;
|
s += `\n`;
|
||||||
|
s += instNameData.formatStringTable("InstDB::_instNameStringTable");
|
||||||
|
s += `\n`;
|
||||||
|
|
||||||
s += `const InstDB::InstNameIndex InstDB::instNameIndex[26] = {\n`;
|
s += `const InstDB::InstNameIndex InstDB::instNameIndex[26] = {\n`;
|
||||||
for (var i = 0; i < instFirst.length; i++) {
|
for (var i = 0; i < instFirst.length; i++) {
|
||||||
const firstId = instFirst[i] || none;
|
const firstId = instFirst[i] || none;
|
||||||
@@ -939,9 +1147,9 @@ class NameTable extends Task {
|
|||||||
s += `};\n`;
|
s += `};\n`;
|
||||||
|
|
||||||
this.ctx.inject("NameLimits",
|
this.ctx.inject("NameLimits",
|
||||||
StringUtils.disclaimer(`enum : uint32_t { kMaxNameSize = ${maxLength} };\n`));
|
StringUtils.disclaimer(`enum : uint32_t { kMaxNameSize = ${instNameData.maxNameLength} };\n`));
|
||||||
|
|
||||||
return this.ctx.inject("NameData", StringUtils.disclaimer(s), instNames.getSize() + 26 * 4);
|
return this.ctx.inject("NameData", StringUtils.disclaimer(s), instNameData.getSize() + 26 * 4);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
exports.NameTable = NameTable;
|
exports.NameTable = NameTable;
|
||||||
|
|||||||
Reference in New Issue
Block a user