Defcon/hook_lib/asmjit/arm/a64formatter.cpp
MatrixMMOfficial 9631e4ca40 Initial commit
2023-11-26 08:54:06 -05:00

299 lines
7.4 KiB
C++

// 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/a64formatter_p.h"
#include "../arm/a64instapi_p.h"
#include "../arm/a64instdb_p.h"
#include "../arm/a64operand.h"
#ifndef ASMJIT_NO_COMPILER
#include "../core/compiler.h"
#endif
ASMJIT_BEGIN_SUB_NAMESPACE(a64)
// a64::FormatterInternal - Format Register
// ========================================
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_GpW:
if (rId == Gp::kIdZr)
return sb.append("wzr");
if (rId == Gp::kIdSp)
return sb.append("wsp");
letter = 'w';
break;
case RegType::kARM_GpX:
if (rId == Gp::kIdZr)
return sb.append("xzr");
if (rId == Gp::kIdSp)
return sb.append("sp");
letter = 'x';
break;
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;
default:
ASMJIT_PROPAGATE(sb.appendFormat("<Reg-%u>?$u", uint32_t(regType), rId));
break;
}
if (letter)
ASMJIT_PROPAGATE(sb.appendFormat("%c%u", letter, rId));
}
if (elementType) {
char elementLetter = '\0';
uint32_t elementCount = 0;
switch (elementType) {
case Vec::kElementTypeB:
elementLetter = 'b';
elementCount = 16;
break;
case Vec::kElementTypeH:
elementLetter = 'h';
elementCount = 8;
break;
case Vec::kElementTypeS:
elementLetter = 's';
elementCount = 4;
break;
case Vec::kElementTypeD:
elementLetter = 'd';
elementCount = 2;
break;
default:
return sb.append(".<Unknown>");
}
if (elementLetter) {
if (elementIndex == 0xFFFFFFFFu) {
if (regType == RegType::kARM_VecD)
elementCount /= 2u;
ASMJIT_PROPAGATE(sb.appendFormat(".%u%c", elementCount, elementLetter));
}
else {
ASMJIT_PROPAGATE(sb.appendFormat(".%c[%u]", elementLetter, elementIndex));
}
}
}
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.as<Vec>().elementType();
uint32_t elementIndex = op.as<Vec>().elementIndex();
if (!op.as<Vec>().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, (ShiftOp)m.predicate()));
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();
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());
}
return sb.append("<None>");
}
// a64::FormatterInternal - Format Instruction
// ===========================================
ASMJIT_FAVOR_SIZE Error FormatterInternal::formatInstruction(
String& sb,
FormatFlags flags,
const BaseEmitter* emitter,
Arch arch,
const BaseInst& inst, const Operand_* operands, size_t opCount) noexcept {
DebugUtils::unused(arch);
// Format instruction options and instruction mnemonic.
InstId instId = inst.realId();
if (instId < Inst::_kIdCount)
ASMJIT_PROPAGATE(InstInternal::instIdToString(arch, instId, sb));
else
ASMJIT_PROPAGATE(sb.appendFormat("[InstId=#%u]", unsigned(instId)));
CondCode cc = inst.armCondCode();
if (cc != CondCode::kAL) {
ASMJIT_PROPAGATE(sb.append('.'));
ASMJIT_PROPAGATE(formatCondCode(sb, cc));
}
for (uint32_t i = 0; i < opCount; i++) {
const Operand_& op = operands[i];
if (op.isNone())
break;
ASMJIT_PROPAGATE(sb.append(i == 0 ? " " : ", "));
ASMJIT_PROPAGATE(formatOperand(sb, flags, emitter, arch, op));
}
return kErrorOk;
}
ASMJIT_END_SUB_NAMESPACE
#endif // !ASMJIT_NO_LOGGING