summaryrefslogtreecommitdiffstatshomepage
path: root/3rdparty/asmjit/src/asmjit/arm/armformatter.cpp
diff options
context:
space:
mode:
Diffstat (limited to '3rdparty/asmjit/src/asmjit/arm/armformatter.cpp')
-rw-r--r--3rdparty/asmjit/src/asmjit/arm/armformatter.cpp588
1 files changed, 588 insertions, 0 deletions
diff --git a/3rdparty/asmjit/src/asmjit/arm/armformatter.cpp b/3rdparty/asmjit/src/asmjit/arm/armformatter.cpp
new file mode 100644
index 00000000000..3fe2c6b911c
--- /dev/null
+++ b/3rdparty/asmjit/src/asmjit/arm/armformatter.cpp
@@ -0,0 +1,588 @@
+// 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
+
+#include "../core/api-build_p.h"
+#ifndef ASMJIT_NO_LOGGING
+
+#include "../core/misc_p.h"
+#include "../core/support.h"
+#include "../arm/armformatter_p.h"
+#include "../arm/a64operand.h"
+#include "../arm/a64instapi_p.h"
+#include "../arm/a64instdb_p.h"
+
+#ifndef ASMJIT_NO_COMPILER
+ #include "../core/compiler.h"
+#endif
+
+ASMJIT_BEGIN_SUB_NAMESPACE(arm)
+
+// arm::FormatterInternal - Format Feature
+// =======================================
+
+Error FormatterInternal::formatFeature(String& sb, uint32_t featureId) noexcept {
+ // @EnumStringBegin{"enum": "CpuFeatures::ARM", "output": "sFeature", "strip": "k"}@
+ static const char sFeatureString[] =
+ "None\0"
+ "ARMv6\0"
+ "ARMv7\0"
+ "ARMv8a\0"
+ "THUMB\0"
+ "THUMBv2\0"
+ "ABLE\0"
+ "ADERR\0"
+ "AES\0"
+ "AFP\0"
+ "AIE\0"
+ "AMU1\0"
+ "AMU1_1\0"
+ "ANERR\0"
+ "ASIMD\0"
+ "BF16\0"
+ "BRBE\0"
+ "BTI\0"
+ "BWE\0"
+ "CCIDX\0"
+ "CHK\0"
+ "CLRBHB\0"
+ "CMOW\0"
+ "CONSTPACFIELD\0"
+ "CPA\0"
+ "CPA2\0"
+ "CPUID\0"
+ "CRC32\0"
+ "CSSC\0"
+ "CSV2\0"
+ "CSV2_3\0"
+ "CSV3\0"
+ "D128\0"
+ "DGH\0"
+ "DIT\0"
+ "DOTPROD\0"
+ "DPB\0"
+ "DPB2\0"
+ "EBEP\0"
+ "EBF16\0"
+ "ECBHB\0"
+ "ECV\0"
+ "EDHSR\0"
+ "EDSP\0"
+ "FAMINMAX\0"
+ "FCMA\0"
+ "FGT\0"
+ "FGT2\0"
+ "FHM\0"
+ "FLAGM\0"
+ "FLAGM2\0"
+ "FMAC\0"
+ "FP\0"
+ "FP16\0"
+ "FP16CONV\0"
+ "FP8\0"
+ "FP8DOT2\0"
+ "FP8DOT4\0"
+ "FP8FMA\0"
+ "FPMR\0"
+ "FRINTTS\0"
+ "GCS\0"
+ "HACDBS\0"
+ "HAFDBS\0"
+ "HAFT\0"
+ "HDBSS\0"
+ "HBC\0"
+ "HCX\0"
+ "HPDS\0"
+ "HPDS2\0"
+ "I8MM\0"
+ "IDIVA\0"
+ "IDIVT\0"
+ "ITE\0"
+ "JSCVT\0"
+ "LOR\0"
+ "LRCPC\0"
+ "LRCPC2\0"
+ "LRCPC3\0"
+ "LS64\0"
+ "LS64_ACCDATA\0"
+ "LS64_V\0"
+ "LSE\0"
+ "LSE128\0"
+ "LSE2\0"
+ "LUT\0"
+ "LVA\0"
+ "LVA3\0"
+ "MEC\0"
+ "MOPS\0"
+ "MPAM\0"
+ "MTE\0"
+ "MTE2\0"
+ "MTE3\0"
+ "MTE4\0"
+ "MTE_ASYM_FAULT\0"
+ "MTE_ASYNC\0"
+ "MTE_CANONICAL_TAGS\0"
+ "MTE_NO_ADDRESS_TAGS\0"
+ "MTE_PERM_S1\0"
+ "MTE_STORE_ONLY\0"
+ "MTE_TAGGED_FAR\0"
+ "MTPMU\0"
+ "NMI\0"
+ "NV\0"
+ "NV2\0"
+ "PAN\0"
+ "PAN2\0"
+ "PAN3\0"
+ "PAUTH\0"
+ "PFAR\0"
+ "PMU\0"
+ "PMULL\0"
+ "PRFMSLC\0"
+ "RAS\0"
+ "RAS1_1\0"
+ "RAS2\0"
+ "RASSA2\0"
+ "RDM\0"
+ "RME\0"
+ "RNG\0"
+ "RNG_TRAP\0"
+ "RPRES\0"
+ "RPRFM\0"
+ "S1PIE\0"
+ "S1POE\0"
+ "S2PIE\0"
+ "S2POE\0"
+ "SB\0"
+ "SCTLR2\0"
+ "SEBEP\0"
+ "SEL2\0"
+ "SHA1\0"
+ "SHA256\0"
+ "SHA3\0"
+ "SHA512\0"
+ "SM3\0"
+ "SM4\0"
+ "SME\0"
+ "SME2\0"
+ "SME2_1\0"
+ "SME_B16B16\0"
+ "SME_B16F32\0"
+ "SME_BI32I32\0"
+ "SME_F16F16\0"
+ "SME_F16F32\0"
+ "SME_F32F32\0"
+ "SME_F64F64\0"
+ "SME_F8F16\0"
+ "SME_F8F32\0"
+ "SME_FA64\0"
+ "SME_I16I32\0"
+ "SME_I16I64\0"
+ "SME_I8I32\0"
+ "SME_LUTv2\0"
+ "SPE\0"
+ "SPE1_1\0"
+ "SPE1_2\0"
+ "SPE1_3\0"
+ "SPE1_4\0"
+ "SPE_ALTCLK\0"
+ "SPE_CRR\0"
+ "SPE_EFT\0"
+ "SPE_FDS\0"
+ "SPE_FPF\0"
+ "SPE_SME\0"
+ "SPECRES\0"
+ "SPECRES2\0"
+ "SPMU\0"
+ "SSBS\0"
+ "SSBS2\0"
+ "SSVE_FP8DOT2\0"
+ "SSVE_FP8DOT4\0"
+ "SSVE_FP8FMA\0"
+ "SVE\0"
+ "SVE2\0"
+ "SVE2_1\0"
+ "SVE_AES\0"
+ "SVE_B16B16\0"
+ "SVE_BF16\0"
+ "SVE_BITPERM\0"
+ "SVE_EBF16\0"
+ "SVE_F32MM\0"
+ "SVE_F64MM\0"
+ "SVE_I8MM\0"
+ "SVE_PMULL128\0"
+ "SVE_SHA3\0"
+ "SVE_SM4\0"
+ "SYSINSTR128\0"
+ "SYSREG128\0"
+ "THE\0"
+ "TLBIOS\0"
+ "TLBIRANGE\0"
+ "TLBIW\0"
+ "TME\0"
+ "TRF\0"
+ "UAO\0"
+ "VFP_D32\0"
+ "VHE\0"
+ "VMID16\0"
+ "WFXT\0"
+ "XNX\0"
+ "XS\0"
+ "<Unknown>\0";
+
+ static const uint16_t sFeatureIndex[] = {
+ 0, 5, 11, 17, 24, 30, 38, 43, 49, 53, 57, 61, 66, 73, 79, 85, 90, 95, 99,
+ 103, 109, 113, 120, 125, 139, 143, 148, 154, 160, 165, 170, 177, 182, 187,
+ 191, 195, 203, 207, 212, 217, 223, 229, 233, 239, 244, 253, 258, 262, 267,
+ 271, 277, 284, 289, 292, 297, 306, 310, 318, 326, 333, 338, 346, 350, 357,
+ 364, 369, 375, 379, 383, 388, 394, 399, 405, 411, 415, 421, 425, 431, 438,
+ 445, 450, 463, 470, 474, 481, 486, 490, 494, 499, 503, 508, 513, 517, 522,
+ 527, 532, 547, 557, 576, 596, 608, 623, 638, 644, 648, 651, 655, 659, 664,
+ 669, 675, 680, 684, 690, 698, 702, 709, 714, 721, 725, 729, 733, 742, 748,
+ 754, 760, 766, 772, 778, 781, 788, 794, 799, 804, 811, 816, 823, 827, 831,
+ 835, 840, 847, 858, 869, 881, 892, 903, 914, 925, 935, 945, 954, 965, 976,
+ 986, 996, 1000, 1007, 1014, 1021, 1028, 1039, 1047, 1055, 1063, 1071, 1079,
+ 1087, 1096, 1101, 1106, 1112, 1125, 1138, 1150, 1154, 1159, 1166, 1174, 1185,
+ 1194, 1206, 1216, 1226, 1236, 1245, 1258, 1267, 1275, 1287, 1297, 1301, 1308,
+ 1318, 1324, 1328, 1332, 1336, 1344, 1348, 1355, 1360, 1364, 1367
+ };
+ // @EnumStringEnd@
+
+ return sb.append(sFeatureString + sFeatureIndex[Support::min<uint32_t>(featureId, uint32_t(CpuFeatures::ARM::kMaxValue) + 1)]);
+}
+
+// arm::FormatterInternal - Format Constants
+// =========================================
+
+ASMJIT_FAVOR_SIZE Error FormatterInternal::formatCondCode(String& sb, CondCode cc) noexcept {
+ static const char condCodeData[] =
+ "al\0" "na\0"
+ "eq\0" "ne\0"
+ "hs\0" "lo\0" "mi\0" "pl\0" "vs\0" "vc\0"
+ "hi\0" "ls\0" "ge\0" "lt\0" "gt\0" "le\0"
+ "<Unknown>";
+ return sb.append(condCodeData + Support::min<uint32_t>(uint32_t(cc), 16u) * 3);
+}
+
+ASMJIT_FAVOR_SIZE Error FormatterInternal::formatShiftOp(String& sb, ShiftOp shiftOp) noexcept {
+ const char* str = nullptr;
+ switch (shiftOp) {
+ case ShiftOp::kLSL: str = "lsl"; break;
+ case ShiftOp::kLSR: str = "lsr"; break;
+ case ShiftOp::kASR: str = "asr"; break;
+ case ShiftOp::kROR: str = "ror"; break;
+ case ShiftOp::kRRX: str = "rrx"; break;
+ case ShiftOp::kMSL: str = "msl"; break;
+ case ShiftOp::kUXTB: str = "uxtb"; break;
+ case ShiftOp::kUXTH: str = "uxth"; break;
+ case ShiftOp::kUXTW: str = "uxtw"; break;
+ case ShiftOp::kUXTX: str = "uxtx"; break;
+ case ShiftOp::kSXTB: str = "sxtb"; break;
+ case ShiftOp::kSXTH: str = "sxth"; break;
+ case ShiftOp::kSXTW: str = "sxtw"; break;
+ case ShiftOp::kSXTX: str = "sxtx"; break;
+ default: str = "<Unknown>"; break;
+ }
+ return sb.append(str);
+}
+
+// arm::FormatterInternal - Format Register
+// ========================================
+
+struct FormatElementData {
+ char letter;
+ uint8_t elementCount;
+ uint8_t onlyIndex;
+ uint8_t reserved;
+};
+
+static constexpr FormatElementData formatElementDataTable[9] = {
+ { '?' , 0 , 0, 0 }, // None
+ { 'b' , 16, 0, 0 }, // bX or b[index]
+ { 'h' , 8 , 0, 0 }, // hX or h[index]
+ { 's' , 4 , 0, 0 }, // sX or s[index]
+ { 'd' , 2 , 0, 0 }, // dX or d[index]
+ { 'b' , 4 , 1, 0 }, // ?? or b4[index]
+ { 'h' , 2 , 1, 0 }, // ?? or h2[index]
+ { '?' , 0 , 0, 0 }, // invalid (possibly stored in Operand)
+ { '?' , 0 , 0, 0 } // invalid (never stored in Operand, bug...)
+};
+
+ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegister(
+ String& sb,
+ FormatFlags flags,
+ const BaseEmitter* emitter,
+ Arch arch,
+ RegType regType,
+ uint32_t rId,
+ uint32_t elementType,
+ uint32_t elementIndex) noexcept {
+
+ DebugUtils::unused(flags);
+ DebugUtils::unused(arch);
+
+ static const char bhsdq[] = "bhsdq";
+
+ bool virtRegFormatted = false;
+
+#ifndef ASMJIT_NO_COMPILER
+ if (Operand::isVirtId(rId)) {
+ if (emitter && emitter->isCompiler()) {
+ const BaseCompiler* cc = static_cast<const BaseCompiler*>(emitter);
+ if (cc->isVirtIdValid(rId)) {
+ VirtReg* vReg = cc->virtRegById(rId);
+ ASMJIT_ASSERT(vReg != nullptr);
+
+ const char* name = vReg->name();
+ if (name && name[0] != '\0')
+ ASMJIT_PROPAGATE(sb.append(name));
+ else
+ ASMJIT_PROPAGATE(sb.appendFormat("%%%u", unsigned(Operand::virtIdToIndex(rId))));
+
+ virtRegFormatted = true;
+ }
+ }
+ }
+#else
+ DebugUtils::unused(emitter, flags);
+#endif
+
+ if (!virtRegFormatted) {
+ char letter = '\0';
+ switch (regType) {
+ case RegType::kARM_VecB:
+ case RegType::kARM_VecH:
+ case RegType::kARM_VecS:
+ case RegType::kARM_VecD:
+ case RegType::kARM_VecV:
+ letter = bhsdq[uint32_t(regType) - uint32_t(RegType::kARM_VecB)];
+ if (elementType)
+ letter = 'v';
+ break;
+
+ case RegType::kARM_GpW:
+ if (Environment::is64Bit(arch)) {
+ letter = 'w';
+
+ if (rId == a64::Gp::kIdZr)
+ return sb.append("wzr", 3);
+
+ if (rId == a64::Gp::kIdSp)
+ return sb.append("wsp", 3);
+ }
+ else {
+ letter = 'r';
+ }
+ break;
+
+ case RegType::kARM_GpX:
+ if (Environment::is64Bit(arch)) {
+ if (rId == a64::Gp::kIdZr)
+ return sb.append("xzr", 3);
+ if (rId == a64::Gp::kIdSp)
+ return sb.append("sp", 2);
+
+ letter = 'x';
+ break;
+ }
+
+ // X registers are undefined in 32-bit mode.
+ ASMJIT_FALLTHROUGH;
+
+ default:
+ ASMJIT_PROPAGATE(sb.appendFormat("<Reg-%u>?%u", uint32_t(regType), rId));
+ break;
+ }
+
+ if (letter)
+ ASMJIT_PROPAGATE(sb.appendFormat("%c%u", letter, rId));
+ }
+
+ constexpr uint32_t kElementTypeCount = uint32_t(a64::VecElementType::kMaxValue) + 1;
+ if (elementType) {
+ elementType = Support::min(elementType, kElementTypeCount);
+
+ FormatElementData elementData = formatElementDataTable[elementType];
+ uint32_t elementCount = elementData.elementCount;
+
+ if (regType == RegType::kARM_VecD) {
+ elementCount /= 2u;
+ }
+
+ ASMJIT_PROPAGATE(sb.append('.'));
+ if (elementCount) {
+ ASMJIT_PROPAGATE(sb.appendUInt(elementCount));
+ }
+ ASMJIT_PROPAGATE(sb.append(elementData.letter));
+ }
+
+ if (elementIndex != 0xFFFFFFFFu) {
+ ASMJIT_PROPAGATE(sb.appendFormat("[%u]", elementIndex));
+ }
+
+ return kErrorOk;
+}
+
+ASMJIT_FAVOR_SIZE Error FormatterInternal::formatRegisterList(
+ String& sb,
+ FormatFlags flags,
+ const BaseEmitter* emitter,
+ Arch arch,
+ RegType regType,
+ uint32_t rMask) noexcept {
+
+ bool first = true;
+
+ ASMJIT_PROPAGATE(sb.append('{'));
+ while (rMask != 0u) {
+ uint32_t start = Support::ctz(rMask);
+ uint32_t count = 0u;
+
+ uint32_t mask = 1u << start;
+ do {
+ rMask &= ~mask;
+ mask <<= 1u;
+ count++;
+ } while (rMask & mask);
+
+ if (!first)
+ ASMJIT_PROPAGATE(sb.append(", "));
+
+ ASMJIT_PROPAGATE(formatRegister(sb, flags, emitter, arch, regType, start, 0, 0xFFFFFFFFu));
+ if (count >= 2u) {
+ ASMJIT_PROPAGATE(sb.append('-'));
+ ASMJIT_PROPAGATE(formatRegister(sb, flags, emitter, arch, regType, start + count - 1, 0, 0xFFFFFFFFu));
+ }
+
+ first = false;
+ }
+ ASMJIT_PROPAGATE(sb.append('}'));
+
+ return kErrorOk;
+}
+
+// a64::FormatterInternal - Format Operand
+// =======================================
+
+ASMJIT_FAVOR_SIZE Error FormatterInternal::formatOperand(
+ String& sb,
+ FormatFlags flags,
+ const BaseEmitter* emitter,
+ Arch arch,
+ const Operand_& op) noexcept {
+
+ if (op.isReg()) {
+ const BaseReg& reg = op.as<BaseReg>();
+
+ uint32_t elementType = op._signature.getField<BaseVec::kSignatureRegElementTypeMask>();
+ uint32_t elementIndex = op.as<BaseVec>().elementIndex();
+
+ if (!op.as<BaseVec>().hasElementIndex())
+ elementIndex = 0xFFFFFFFFu;
+
+ return formatRegister(sb, flags, emitter, arch, reg.type(), reg.id(), elementType, elementIndex);
+ }
+
+ if (op.isMem()) {
+ const Mem& m = op.as<Mem>();
+ ASMJIT_PROPAGATE(sb.append('['));
+
+ if (m.hasBase()) {
+ if (m.hasBaseLabel()) {
+ ASMJIT_PROPAGATE(Formatter::formatLabel(sb, flags, emitter, m.baseId()));
+ }
+ else {
+ FormatFlags modifiedFlags = flags;
+ if (m.isRegHome()) {
+ ASMJIT_PROPAGATE(sb.append('&'));
+ modifiedFlags &= ~FormatFlags::kRegCasts;
+ }
+ ASMJIT_PROPAGATE(formatRegister(sb, modifiedFlags, emitter, arch, m.baseType(), m.baseId()));
+ }
+ }
+ else {
+ // ARM really requires base.
+ if (m.hasIndex() || m.hasOffset()) {
+ ASMJIT_PROPAGATE(sb.append("<None>"));
+ }
+ }
+
+ // The post index makes it look like there was another operand, but it's
+ // still the part of AsmJit's `arm::Mem` operand so it's consistent with
+ // other architectures.
+ if (m.isPostIndex())
+ ASMJIT_PROPAGATE(sb.append(']'));
+
+ if (m.hasIndex()) {
+ ASMJIT_PROPAGATE(sb.append(", "));
+ ASMJIT_PROPAGATE(formatRegister(sb, flags, emitter, arch, m.indexType(), m.indexId()));
+ }
+
+ if (m.hasOffset()) {
+ ASMJIT_PROPAGATE(sb.append(", "));
+
+ int64_t off = int64_t(m.offset());
+ uint32_t base = 10;
+
+ if (Support::test(flags, FormatFlags::kHexOffsets) && uint64_t(off) > 9)
+ base = 16;
+
+ if (base == 10) {
+ ASMJIT_PROPAGATE(sb.appendInt(off, base));
+ }
+ else {
+ ASMJIT_PROPAGATE(sb.append("0x"));
+ ASMJIT_PROPAGATE(sb.appendUInt(uint64_t(off), base));
+ }
+ }
+
+ if (m.hasShift()) {
+ ASMJIT_PROPAGATE(sb.append(' '));
+ if (!m.isPreOrPost())
+ ASMJIT_PROPAGATE(formatShiftOp(sb, m.shiftOp()));
+ ASMJIT_PROPAGATE(sb.appendFormat(" %u", m.shift()));
+ }
+
+ if (!m.isPostIndex())
+ ASMJIT_PROPAGATE(sb.append(']'));
+
+ if (m.isPreIndex())
+ ASMJIT_PROPAGATE(sb.append('!'));
+
+ return kErrorOk;
+ }
+
+ if (op.isImm()) {
+ const Imm& i = op.as<Imm>();
+ int64_t val = i.value();
+ uint32_t predicate = i.predicate();
+
+ if (predicate) {
+ ASMJIT_PROPAGATE(formatShiftOp(sb, ShiftOp(predicate)));
+ ASMJIT_PROPAGATE(sb.append(' '));
+ }
+
+ if (Support::test(flags, FormatFlags::kHexImms) && uint64_t(val) > 9) {
+ ASMJIT_PROPAGATE(sb.append("0x"));
+ return sb.appendUInt(uint64_t(val), 16);
+ }
+ else {
+ return sb.appendInt(val, 10);
+ }
+ }
+
+ if (op.isLabel()) {
+ return Formatter::formatLabel(sb, flags, emitter, op.id());
+ }
+
+ if (op.isRegList()) {
+ const BaseRegList& regList = op.as<BaseRegList>();
+ return formatRegisterList(sb, flags, emitter, arch, regList.type(), regList.list());
+ }
+
+ return sb.append("<None>");
+}
+
+ASMJIT_END_SUB_NAMESPACE
+
+#endif // !ASMJIT_NO_LOGGING