mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-10 02:54:58 -06:00
disas/libvixl: Update to libvixl 1.6
Update our copy of libvixl to upstream 1.6. There are no changes of any particular interest to QEMU, so this is simply keeping up with current upstream. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1412091418-25744-1-git-send-email-peter.maydell@linaro.org
This commit is contained in:
parent
c6faa758e3
commit
6aea44fc2b
12 changed files with 718 additions and 335 deletions
|
@ -57,7 +57,7 @@ char* Disassembler::GetOutput() {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitAddSubImmediate(Instruction* instr) {
|
||||
void Disassembler::VisitAddSubImmediate(const Instruction* instr) {
|
||||
bool rd_is_zr = RdIsZROrSP(instr);
|
||||
bool stack_op = (rd_is_zr || RnIsZROrSP(instr)) &&
|
||||
(instr->ImmAddSub() == 0) ? true : false;
|
||||
|
@ -102,7 +102,7 @@ void Disassembler::VisitAddSubImmediate(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitAddSubShifted(Instruction* instr) {
|
||||
void Disassembler::VisitAddSubShifted(const Instruction* instr) {
|
||||
bool rd_is_zr = RdIsZROrSP(instr);
|
||||
bool rn_is_zr = RnIsZROrSP(instr);
|
||||
const char *mnemonic = "";
|
||||
|
@ -149,7 +149,7 @@ void Disassembler::VisitAddSubShifted(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitAddSubExtended(Instruction* instr) {
|
||||
void Disassembler::VisitAddSubExtended(const Instruction* instr) {
|
||||
bool rd_is_zr = RdIsZROrSP(instr);
|
||||
const char *mnemonic = "";
|
||||
Extend mode = static_cast<Extend>(instr->ExtendMode());
|
||||
|
@ -187,7 +187,7 @@ void Disassembler::VisitAddSubExtended(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitAddSubWithCarry(Instruction* instr) {
|
||||
void Disassembler::VisitAddSubWithCarry(const Instruction* instr) {
|
||||
bool rn_is_zr = RnIsZROrSP(instr);
|
||||
const char *mnemonic = "";
|
||||
const char *form = "'Rd, 'Rn, 'Rm";
|
||||
|
@ -222,7 +222,7 @@ void Disassembler::VisitAddSubWithCarry(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitLogicalImmediate(Instruction* instr) {
|
||||
void Disassembler::VisitLogicalImmediate(const Instruction* instr) {
|
||||
bool rd_is_zr = RdIsZROrSP(instr);
|
||||
bool rn_is_zr = RnIsZROrSP(instr);
|
||||
const char *mnemonic = "";
|
||||
|
@ -294,7 +294,7 @@ bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitLogicalShifted(Instruction* instr) {
|
||||
void Disassembler::VisitLogicalShifted(const Instruction* instr) {
|
||||
bool rd_is_zr = RdIsZROrSP(instr);
|
||||
bool rn_is_zr = RnIsZROrSP(instr);
|
||||
const char *mnemonic = "";
|
||||
|
@ -345,7 +345,7 @@ void Disassembler::VisitLogicalShifted(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitConditionalCompareRegister(Instruction* instr) {
|
||||
void Disassembler::VisitConditionalCompareRegister(const Instruction* instr) {
|
||||
const char *mnemonic = "";
|
||||
const char *form = "'Rn, 'Rm, 'INzcv, 'Cond";
|
||||
|
||||
|
@ -360,7 +360,7 @@ void Disassembler::VisitConditionalCompareRegister(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitConditionalCompareImmediate(Instruction* instr) {
|
||||
void Disassembler::VisitConditionalCompareImmediate(const Instruction* instr) {
|
||||
const char *mnemonic = "";
|
||||
const char *form = "'Rn, 'IP, 'INzcv, 'Cond";
|
||||
|
||||
|
@ -375,7 +375,7 @@ void Disassembler::VisitConditionalCompareImmediate(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitConditionalSelect(Instruction* instr) {
|
||||
void Disassembler::VisitConditionalSelect(const Instruction* instr) {
|
||||
bool rnm_is_zr = (RnIsZROrSP(instr) && RmIsZROrSP(instr));
|
||||
bool rn_is_rm = (instr->Rn() == instr->Rm());
|
||||
const char *mnemonic = "";
|
||||
|
@ -428,7 +428,7 @@ void Disassembler::VisitConditionalSelect(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitBitfield(Instruction* instr) {
|
||||
void Disassembler::VisitBitfield(const Instruction* instr) {
|
||||
unsigned s = instr->ImmS();
|
||||
unsigned r = instr->ImmR();
|
||||
unsigned rd_size_minus_1 =
|
||||
|
@ -506,7 +506,7 @@ void Disassembler::VisitBitfield(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitExtract(Instruction* instr) {
|
||||
void Disassembler::VisitExtract(const Instruction* instr) {
|
||||
const char *mnemonic = "";
|
||||
const char *form = "'Rd, 'Rn, 'Rm, 'IExtract";
|
||||
|
||||
|
@ -527,7 +527,7 @@ void Disassembler::VisitExtract(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitPCRelAddressing(Instruction* instr) {
|
||||
void Disassembler::VisitPCRelAddressing(const Instruction* instr) {
|
||||
switch (instr->Mask(PCRelAddressingMask)) {
|
||||
case ADR: Format(instr, "adr", "'Xd, 'AddrPCRelByte"); break;
|
||||
case ADRP: Format(instr, "adrp", "'Xd, 'AddrPCRelPage"); break;
|
||||
|
@ -536,7 +536,7 @@ void Disassembler::VisitPCRelAddressing(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitConditionalBranch(Instruction* instr) {
|
||||
void Disassembler::VisitConditionalBranch(const Instruction* instr) {
|
||||
switch (instr->Mask(ConditionalBranchMask)) {
|
||||
case B_cond: Format(instr, "b.'CBrn", "'BImmCond"); break;
|
||||
default: VIXL_UNREACHABLE();
|
||||
|
@ -544,7 +544,8 @@ void Disassembler::VisitConditionalBranch(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitUnconditionalBranchToRegister(Instruction* instr) {
|
||||
void Disassembler::VisitUnconditionalBranchToRegister(
|
||||
const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form = "'Xn";
|
||||
|
||||
|
@ -564,7 +565,7 @@ void Disassembler::VisitUnconditionalBranchToRegister(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitUnconditionalBranch(Instruction* instr) {
|
||||
void Disassembler::VisitUnconditionalBranch(const Instruction* instr) {
|
||||
const char *mnemonic = "";
|
||||
const char *form = "'BImmUncn";
|
||||
|
||||
|
@ -577,7 +578,7 @@ void Disassembler::VisitUnconditionalBranch(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitDataProcessing1Source(Instruction* instr) {
|
||||
void Disassembler::VisitDataProcessing1Source(const Instruction* instr) {
|
||||
const char *mnemonic = "";
|
||||
const char *form = "'Rd, 'Rn";
|
||||
|
||||
|
@ -598,7 +599,7 @@ void Disassembler::VisitDataProcessing1Source(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitDataProcessing2Source(Instruction* instr) {
|
||||
void Disassembler::VisitDataProcessing2Source(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form = "'Rd, 'Rn, 'Rm";
|
||||
|
||||
|
@ -619,7 +620,7 @@ void Disassembler::VisitDataProcessing2Source(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitDataProcessing3Source(Instruction* instr) {
|
||||
void Disassembler::VisitDataProcessing3Source(const Instruction* instr) {
|
||||
bool ra_is_zr = RaIsZROrSP(instr);
|
||||
const char *mnemonic = "";
|
||||
const char *form = "'Xd, 'Wn, 'Wm, 'Xa";
|
||||
|
@ -697,7 +698,7 @@ void Disassembler::VisitDataProcessing3Source(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitCompareBranch(Instruction* instr) {
|
||||
void Disassembler::VisitCompareBranch(const Instruction* instr) {
|
||||
const char *mnemonic = "";
|
||||
const char *form = "'Rt, 'BImmCmpa";
|
||||
|
||||
|
@ -712,7 +713,7 @@ void Disassembler::VisitCompareBranch(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitTestBranch(Instruction* instr) {
|
||||
void Disassembler::VisitTestBranch(const Instruction* instr) {
|
||||
const char *mnemonic = "";
|
||||
// If the top bit of the immediate is clear, the tested register is
|
||||
// disassembled as Wt, otherwise Xt. As the top bit of the immediate is
|
||||
|
@ -729,7 +730,7 @@ void Disassembler::VisitTestBranch(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitMoveWideImmediate(Instruction* instr) {
|
||||
void Disassembler::VisitMoveWideImmediate(const Instruction* instr) {
|
||||
const char *mnemonic = "";
|
||||
const char *form = "'Rd, 'IMoveImm";
|
||||
|
||||
|
@ -768,7 +769,7 @@ void Disassembler::VisitMoveWideImmediate(Instruction* instr) {
|
|||
V(LDR_s, "ldr", "'St") \
|
||||
V(LDR_d, "ldr", "'Dt")
|
||||
|
||||
void Disassembler::VisitLoadStorePreIndex(Instruction* instr) {
|
||||
void Disassembler::VisitLoadStorePreIndex(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form = "(LoadStorePreIndex)";
|
||||
|
||||
|
@ -782,7 +783,7 @@ void Disassembler::VisitLoadStorePreIndex(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitLoadStorePostIndex(Instruction* instr) {
|
||||
void Disassembler::VisitLoadStorePostIndex(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form = "(LoadStorePostIndex)";
|
||||
|
||||
|
@ -796,7 +797,7 @@ void Disassembler::VisitLoadStorePostIndex(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitLoadStoreUnsignedOffset(Instruction* instr) {
|
||||
void Disassembler::VisitLoadStoreUnsignedOffset(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form = "(LoadStoreUnsignedOffset)";
|
||||
|
||||
|
@ -811,7 +812,7 @@ void Disassembler::VisitLoadStoreUnsignedOffset(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitLoadStoreRegisterOffset(Instruction* instr) {
|
||||
void Disassembler::VisitLoadStoreRegisterOffset(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form = "(LoadStoreRegisterOffset)";
|
||||
|
||||
|
@ -826,7 +827,7 @@ void Disassembler::VisitLoadStoreRegisterOffset(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitLoadStoreUnscaledOffset(Instruction* instr) {
|
||||
void Disassembler::VisitLoadStoreUnscaledOffset(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form = "'Wt, ['Xns'ILS]";
|
||||
const char *form_x = "'Xt, ['Xns'ILS]";
|
||||
|
@ -857,7 +858,7 @@ void Disassembler::VisitLoadStoreUnscaledOffset(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitLoadLiteral(Instruction* instr) {
|
||||
void Disassembler::VisitLoadLiteral(const Instruction* instr) {
|
||||
const char *mnemonic = "ldr";
|
||||
const char *form = "(LoadLiteral)";
|
||||
|
||||
|
@ -866,6 +867,11 @@ void Disassembler::VisitLoadLiteral(Instruction* instr) {
|
|||
case LDR_x_lit: form = "'Xt, 'ILLiteral 'LValue"; break;
|
||||
case LDR_s_lit: form = "'St, 'ILLiteral 'LValue"; break;
|
||||
case LDR_d_lit: form = "'Dt, 'ILLiteral 'LValue"; break;
|
||||
case LDRSW_x_lit: {
|
||||
mnemonic = "ldrsw";
|
||||
form = "'Xt, 'ILLiteral 'LValue";
|
||||
break;
|
||||
}
|
||||
default: mnemonic = "unimplemented";
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
|
@ -883,7 +889,7 @@ void Disassembler::VisitLoadLiteral(Instruction* instr) {
|
|||
V(STP_d, "stp", "'Dt, 'Dt2", "8") \
|
||||
V(LDP_d, "ldp", "'Dt, 'Dt2", "8")
|
||||
|
||||
void Disassembler::VisitLoadStorePairPostIndex(Instruction* instr) {
|
||||
void Disassembler::VisitLoadStorePairPostIndex(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form = "(LoadStorePairPostIndex)";
|
||||
|
||||
|
@ -897,7 +903,7 @@ void Disassembler::VisitLoadStorePairPostIndex(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitLoadStorePairPreIndex(Instruction* instr) {
|
||||
void Disassembler::VisitLoadStorePairPreIndex(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form = "(LoadStorePairPreIndex)";
|
||||
|
||||
|
@ -911,7 +917,7 @@ void Disassembler::VisitLoadStorePairPreIndex(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitLoadStorePairOffset(Instruction* instr) {
|
||||
void Disassembler::VisitLoadStorePairOffset(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form = "(LoadStorePairOffset)";
|
||||
|
||||
|
@ -925,7 +931,7 @@ void Disassembler::VisitLoadStorePairOffset(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitLoadStorePairNonTemporal(Instruction* instr) {
|
||||
void Disassembler::VisitLoadStorePairNonTemporal(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form;
|
||||
|
||||
|
@ -944,7 +950,7 @@ void Disassembler::VisitLoadStorePairNonTemporal(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitLoadStoreExclusive(Instruction* instr) {
|
||||
void Disassembler::VisitLoadStoreExclusive(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form;
|
||||
|
||||
|
@ -987,7 +993,7 @@ void Disassembler::VisitLoadStoreExclusive(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitFPCompare(Instruction* instr) {
|
||||
void Disassembler::VisitFPCompare(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form = "'Fn, 'Fm";
|
||||
const char *form_zero = "'Fn, #0.0";
|
||||
|
@ -1003,7 +1009,7 @@ void Disassembler::VisitFPCompare(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitFPConditionalCompare(Instruction* instr) {
|
||||
void Disassembler::VisitFPConditionalCompare(const Instruction* instr) {
|
||||
const char *mnemonic = "unmplemented";
|
||||
const char *form = "'Fn, 'Fm, 'INzcv, 'Cond";
|
||||
|
||||
|
@ -1018,7 +1024,7 @@ void Disassembler::VisitFPConditionalCompare(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitFPConditionalSelect(Instruction* instr) {
|
||||
void Disassembler::VisitFPConditionalSelect(const Instruction* instr) {
|
||||
const char *mnemonic = "";
|
||||
const char *form = "'Fd, 'Fn, 'Fm, 'Cond";
|
||||
|
||||
|
@ -1031,7 +1037,7 @@ void Disassembler::VisitFPConditionalSelect(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitFPDataProcessing1Source(Instruction* instr) {
|
||||
void Disassembler::VisitFPDataProcessing1Source(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form = "'Fd, 'Fn";
|
||||
|
||||
|
@ -1059,7 +1065,7 @@ void Disassembler::VisitFPDataProcessing1Source(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitFPDataProcessing2Source(Instruction* instr) {
|
||||
void Disassembler::VisitFPDataProcessing2Source(const Instruction* instr) {
|
||||
const char *mnemonic = "";
|
||||
const char *form = "'Fd, 'Fn, 'Fm";
|
||||
|
||||
|
@ -1083,7 +1089,7 @@ void Disassembler::VisitFPDataProcessing2Source(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitFPDataProcessing3Source(Instruction* instr) {
|
||||
void Disassembler::VisitFPDataProcessing3Source(const Instruction* instr) {
|
||||
const char *mnemonic = "";
|
||||
const char *form = "'Fd, 'Fn, 'Fm, 'Fa";
|
||||
|
||||
|
@ -1102,7 +1108,7 @@ void Disassembler::VisitFPDataProcessing3Source(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitFPImmediate(Instruction* instr) {
|
||||
void Disassembler::VisitFPImmediate(const Instruction* instr) {
|
||||
const char *mnemonic = "";
|
||||
const char *form = "(FPImmediate)";
|
||||
|
||||
|
@ -1115,7 +1121,7 @@ void Disassembler::VisitFPImmediate(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitFPIntegerConvert(Instruction* instr) {
|
||||
void Disassembler::VisitFPIntegerConvert(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form = "(FPIntegerConvert)";
|
||||
const char *form_rf = "'Rd, 'Fn";
|
||||
|
@ -1171,7 +1177,7 @@ void Disassembler::VisitFPIntegerConvert(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitFPFixedPointConvert(Instruction* instr) {
|
||||
void Disassembler::VisitFPFixedPointConvert(const Instruction* instr) {
|
||||
const char *mnemonic = "";
|
||||
const char *form = "'Rd, 'Fn, 'IFPFBits";
|
||||
const char *form_fr = "'Fd, 'Rn, 'IFPFBits";
|
||||
|
@ -1199,7 +1205,7 @@ void Disassembler::VisitFPFixedPointConvert(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitSystem(Instruction* instr) {
|
||||
void Disassembler::VisitSystem(const Instruction* instr) {
|
||||
// Some system instructions hijack their Op and Cp fields to represent a
|
||||
// range of immediates instead of indicating a different instruction. This
|
||||
// makes the decoding tricky.
|
||||
|
@ -1267,7 +1273,7 @@ void Disassembler::VisitSystem(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitException(Instruction* instr) {
|
||||
void Disassembler::VisitException(const Instruction* instr) {
|
||||
const char *mnemonic = "unimplemented";
|
||||
const char *form = "'IDebug";
|
||||
|
||||
|
@ -1286,22 +1292,75 @@ void Disassembler::VisitException(Instruction* instr) {
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::VisitUnimplemented(Instruction* instr) {
|
||||
void Disassembler::VisitUnimplemented(const Instruction* instr) {
|
||||
Format(instr, "unimplemented", "(Unimplemented)");
|
||||
}
|
||||
|
||||
|
||||
void Disassembler::VisitUnallocated(Instruction* instr) {
|
||||
void Disassembler::VisitUnallocated(const Instruction* instr) {
|
||||
Format(instr, "unallocated", "(Unallocated)");
|
||||
}
|
||||
|
||||
|
||||
void Disassembler::ProcessOutput(Instruction* /*instr*/) {
|
||||
void Disassembler::ProcessOutput(const Instruction* /*instr*/) {
|
||||
// The base disasm does nothing more than disassembling into a buffer.
|
||||
}
|
||||
|
||||
|
||||
void Disassembler::Format(Instruction* instr, const char* mnemonic,
|
||||
void Disassembler::AppendRegisterNameToOutput(const Instruction* instr,
|
||||
const CPURegister& reg) {
|
||||
USE(instr);
|
||||
VIXL_ASSERT(reg.IsValid());
|
||||
char reg_char;
|
||||
|
||||
if (reg.IsRegister()) {
|
||||
reg_char = reg.Is64Bits() ? 'x' : 'w';
|
||||
} else {
|
||||
VIXL_ASSERT(reg.IsFPRegister());
|
||||
reg_char = reg.Is64Bits() ? 'd' : 's';
|
||||
}
|
||||
|
||||
if (reg.IsFPRegister() || !(reg.Aliases(sp) || reg.Aliases(xzr))) {
|
||||
// A normal register: w0 - w30, x0 - x30, s0 - s31, d0 - d31.
|
||||
AppendToOutput("%c%d", reg_char, reg.code());
|
||||
} else if (reg.Aliases(sp)) {
|
||||
// Disassemble w31/x31 as stack pointer wsp/sp.
|
||||
AppendToOutput("%s", reg.Is64Bits() ? "sp" : "wsp");
|
||||
} else {
|
||||
// Disassemble w31/x31 as zero register wzr/xzr.
|
||||
AppendToOutput("%czr", reg_char);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Disassembler::AppendPCRelativeOffsetToOutput(const Instruction* instr,
|
||||
int64_t offset) {
|
||||
USE(instr);
|
||||
char sign = (offset < 0) ? '-' : '+';
|
||||
AppendToOutput("#%c0x%" PRIx64, sign, std::abs(offset));
|
||||
}
|
||||
|
||||
|
||||
void Disassembler::AppendAddressToOutput(const Instruction* instr,
|
||||
const void* addr) {
|
||||
USE(instr);
|
||||
AppendToOutput("(addr %p)", addr);
|
||||
}
|
||||
|
||||
|
||||
void Disassembler::AppendCodeAddressToOutput(const Instruction* instr,
|
||||
const void* addr) {
|
||||
AppendAddressToOutput(instr, addr);
|
||||
}
|
||||
|
||||
|
||||
void Disassembler::AppendDataAddressToOutput(const Instruction* instr,
|
||||
const void* addr) {
|
||||
AppendAddressToOutput(instr, addr);
|
||||
}
|
||||
|
||||
|
||||
void Disassembler::Format(const Instruction* instr, const char* mnemonic,
|
||||
const char* format) {
|
||||
VIXL_ASSERT(mnemonic != NULL);
|
||||
ResetOutput();
|
||||
|
@ -1315,7 +1374,7 @@ void Disassembler::Format(Instruction* instr, const char* mnemonic,
|
|||
}
|
||||
|
||||
|
||||
void Disassembler::Substitute(Instruction* instr, const char* string) {
|
||||
void Disassembler::Substitute(const Instruction* instr, const char* string) {
|
||||
char chr = *string++;
|
||||
while (chr != '\0') {
|
||||
if (chr == '\'') {
|
||||
|
@ -1328,7 +1387,8 @@ void Disassembler::Substitute(Instruction* instr, const char* string) {
|
|||
}
|
||||
|
||||
|
||||
int Disassembler::SubstituteField(Instruction* instr, const char* format) {
|
||||
int Disassembler::SubstituteField(const Instruction* instr,
|
||||
const char* format) {
|
||||
switch (format[0]) {
|
||||
case 'R': // Register. X or W, selected by sf bit.
|
||||
case 'F': // FP Register. S or D, selected by type field.
|
||||
|
@ -1354,7 +1414,7 @@ int Disassembler::SubstituteField(Instruction* instr, const char* format) {
|
|||
}
|
||||
|
||||
|
||||
int Disassembler::SubstituteRegisterField(Instruction* instr,
|
||||
int Disassembler::SubstituteRegisterField(const Instruction* instr,
|
||||
const char* format) {
|
||||
unsigned reg_num = 0;
|
||||
unsigned field_len = 2;
|
||||
|
@ -1381,34 +1441,47 @@ int Disassembler::SubstituteRegisterField(Instruction* instr,
|
|||
field_len = 3;
|
||||
}
|
||||
|
||||
char reg_type;
|
||||
CPURegister::RegisterType reg_type;
|
||||
unsigned reg_size;
|
||||
|
||||
if (format[0] == 'R') {
|
||||
// Register type is R: use sf bit to choose X and W.
|
||||
reg_type = instr->SixtyFourBits() ? 'x' : 'w';
|
||||
reg_type = CPURegister::kRegister;
|
||||
reg_size = instr->SixtyFourBits() ? kXRegSize : kWRegSize;
|
||||
} else if (format[0] == 'F') {
|
||||
// Floating-point register: use type field to choose S or D.
|
||||
reg_type = ((instr->FPType() & 1) == 0) ? 's' : 'd';
|
||||
reg_type = CPURegister::kFPRegister;
|
||||
reg_size = ((instr->FPType() & 1) == 0) ? kSRegSize : kDRegSize;
|
||||
} else {
|
||||
// Register type is specified. Make it lower case.
|
||||
reg_type = format[0] + 0x20;
|
||||
// The register type is specified.
|
||||
switch (format[0]) {
|
||||
case 'W':
|
||||
reg_type = CPURegister::kRegister; reg_size = kWRegSize; break;
|
||||
case 'X':
|
||||
reg_type = CPURegister::kRegister; reg_size = kXRegSize; break;
|
||||
case 'S':
|
||||
reg_type = CPURegister::kFPRegister; reg_size = kSRegSize; break;
|
||||
case 'D':
|
||||
reg_type = CPURegister::kFPRegister; reg_size = kDRegSize; break;
|
||||
default:
|
||||
VIXL_UNREACHABLE();
|
||||
reg_type = CPURegister::kRegister;
|
||||
reg_size = kXRegSize;
|
||||
}
|
||||
}
|
||||
|
||||
if ((reg_num != kZeroRegCode) || (reg_type == 's') || (reg_type == 'd')) {
|
||||
// A normal register: w0 - w30, x0 - x30, s0 - s31, d0 - d31.
|
||||
AppendToOutput("%c%d", reg_type, reg_num);
|
||||
} else if (format[2] == 's') {
|
||||
// Disassemble w31/x31 as stack pointer wsp/sp.
|
||||
AppendToOutput("%s", (reg_type == 'w') ? "wsp" : "sp");
|
||||
} else {
|
||||
// Disassemble w31/x31 as zero register wzr/xzr.
|
||||
AppendToOutput("%czr", reg_type);
|
||||
if ((reg_type == CPURegister::kRegister) &&
|
||||
(reg_num == kZeroRegCode) && (format[2] == 's')) {
|
||||
reg_num = kSPRegInternalCode;
|
||||
}
|
||||
|
||||
AppendRegisterNameToOutput(instr, CPURegister(reg_num, reg_size, reg_type));
|
||||
|
||||
return field_len;
|
||||
}
|
||||
|
||||
|
||||
int Disassembler::SubstituteImmediateField(Instruction* instr,
|
||||
int Disassembler::SubstituteImmediateField(const Instruction* instr,
|
||||
const char* format) {
|
||||
VIXL_ASSERT(format[0] == 'I');
|
||||
|
||||
|
@ -1458,8 +1531,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
|||
}
|
||||
case 'C': { // ICondB - Immediate Conditional Branch.
|
||||
int64_t offset = instr->ImmCondBranch() << 2;
|
||||
char sign = (offset >= 0) ? '+' : '-';
|
||||
AppendToOutput("#%c0x%" PRIx64, sign, offset);
|
||||
AppendPCRelativeOffsetToOutput(instr, offset);
|
||||
return 6;
|
||||
}
|
||||
case 'A': { // IAddSub.
|
||||
|
@ -1522,7 +1594,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
|||
}
|
||||
|
||||
|
||||
int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr,
|
||||
int Disassembler::SubstituteBitfieldImmediateField(const Instruction* instr,
|
||||
const char* format) {
|
||||
VIXL_ASSERT((format[0] == 'I') && (format[1] == 'B'));
|
||||
unsigned r = instr->ImmR();
|
||||
|
@ -1557,7 +1629,7 @@ int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr,
|
|||
}
|
||||
|
||||
|
||||
int Disassembler::SubstituteLiteralField(Instruction* instr,
|
||||
int Disassembler::SubstituteLiteralField(const Instruction* instr,
|
||||
const char* format) {
|
||||
VIXL_ASSERT(strncmp(format, "LValue", 6) == 0);
|
||||
USE(format);
|
||||
|
@ -1565,16 +1637,21 @@ int Disassembler::SubstituteLiteralField(Instruction* instr,
|
|||
switch (instr->Mask(LoadLiteralMask)) {
|
||||
case LDR_w_lit:
|
||||
case LDR_x_lit:
|
||||
case LDRSW_x_lit:
|
||||
case LDR_s_lit:
|
||||
case LDR_d_lit: AppendToOutput("(addr %p)", instr->LiteralAddress()); break;
|
||||
default: VIXL_UNREACHABLE();
|
||||
case LDR_d_lit:
|
||||
AppendDataAddressToOutput(instr, instr->LiteralAddress());
|
||||
break;
|
||||
default:
|
||||
VIXL_UNREACHABLE();
|
||||
}
|
||||
|
||||
return 6;
|
||||
}
|
||||
|
||||
|
||||
int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) {
|
||||
int Disassembler::SubstituteShiftField(const Instruction* instr,
|
||||
const char* format) {
|
||||
VIXL_ASSERT(format[0] == 'H');
|
||||
VIXL_ASSERT(instr->ShiftDP() <= 0x3);
|
||||
|
||||
|
@ -1597,7 +1674,7 @@ int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) {
|
|||
}
|
||||
|
||||
|
||||
int Disassembler::SubstituteConditionField(Instruction* instr,
|
||||
int Disassembler::SubstituteConditionField(const Instruction* instr,
|
||||
const char* format) {
|
||||
VIXL_ASSERT(format[0] == 'C');
|
||||
const char* condition_code[] = { "eq", "ne", "hs", "lo",
|
||||
|
@ -1618,27 +1695,28 @@ int Disassembler::SubstituteConditionField(Instruction* instr,
|
|||
}
|
||||
|
||||
|
||||
int Disassembler::SubstitutePCRelAddressField(Instruction* instr,
|
||||
int Disassembler::SubstitutePCRelAddressField(const Instruction* instr,
|
||||
const char* format) {
|
||||
VIXL_ASSERT((strcmp(format, "AddrPCRelByte") == 0) || // Used by `adr`.
|
||||
(strcmp(format, "AddrPCRelPage") == 0)); // Used by `adrp`.
|
||||
|
||||
int64_t offset = instr->ImmPCRel();
|
||||
Instruction * base = instr;
|
||||
const Instruction * base = instr;
|
||||
|
||||
if (format[9] == 'P') {
|
||||
offset *= kPageSize;
|
||||
base = AlignDown(base, kPageSize);
|
||||
}
|
||||
|
||||
char sign = (offset < 0) ? '-' : '+';
|
||||
void * target = reinterpret_cast<void *>(base + offset);
|
||||
AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, std::abs(offset), target);
|
||||
const void* target = reinterpret_cast<const void*>(base + offset);
|
||||
AppendPCRelativeOffsetToOutput(instr, offset);
|
||||
AppendToOutput(" ");
|
||||
AppendAddressToOutput(instr, target);
|
||||
return 13;
|
||||
}
|
||||
|
||||
|
||||
int Disassembler::SubstituteBranchTargetField(Instruction* instr,
|
||||
int Disassembler::SubstituteBranchTargetField(const Instruction* instr,
|
||||
const char* format) {
|
||||
VIXL_ASSERT(strncmp(format, "BImm", 4) == 0);
|
||||
|
||||
|
@ -1655,19 +1733,18 @@ int Disassembler::SubstituteBranchTargetField(Instruction* instr,
|
|||
default: VIXL_UNIMPLEMENTED();
|
||||
}
|
||||
offset <<= kInstructionSizeLog2;
|
||||
char sign = '+';
|
||||
if (offset < 0) {
|
||||
offset = -offset;
|
||||
sign = '-';
|
||||
}
|
||||
const void* target_address = reinterpret_cast<const void*>(instr + offset);
|
||||
VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
|
||||
void * address = reinterpret_cast<void *>(instr + offset);
|
||||
AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, offset, address);
|
||||
|
||||
AppendPCRelativeOffsetToOutput(instr, offset);
|
||||
AppendToOutput(" ");
|
||||
AppendCodeAddressToOutput(instr, target_address);
|
||||
|
||||
return 8;
|
||||
}
|
||||
|
||||
|
||||
int Disassembler::SubstituteExtendField(Instruction* instr,
|
||||
int Disassembler::SubstituteExtendField(const Instruction* instr,
|
||||
const char* format) {
|
||||
VIXL_ASSERT(strncmp(format, "Ext", 3) == 0);
|
||||
VIXL_ASSERT(instr->ExtendMode() <= 7);
|
||||
|
@ -1694,7 +1771,7 @@ int Disassembler::SubstituteExtendField(Instruction* instr,
|
|||
}
|
||||
|
||||
|
||||
int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
|
||||
int Disassembler::SubstituteLSRegOffsetField(const Instruction* instr,
|
||||
const char* format) {
|
||||
VIXL_ASSERT(strncmp(format, "Offsetreg", 9) == 0);
|
||||
const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl",
|
||||
|
@ -1723,7 +1800,7 @@ int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
|
|||
}
|
||||
|
||||
|
||||
int Disassembler::SubstitutePrefetchField(Instruction* instr,
|
||||
int Disassembler::SubstitutePrefetchField(const Instruction* instr,
|
||||
const char* format) {
|
||||
VIXL_ASSERT(format[0] == 'P');
|
||||
USE(format);
|
||||
|
@ -1738,7 +1815,7 @@ int Disassembler::SubstitutePrefetchField(Instruction* instr,
|
|||
return 6;
|
||||
}
|
||||
|
||||
int Disassembler::SubstituteBarrierField(Instruction* instr,
|
||||
int Disassembler::SubstituteBarrierField(const Instruction* instr,
|
||||
const char* format) {
|
||||
VIXL_ASSERT(format[0] == 'M');
|
||||
USE(format);
|
||||
|
@ -1770,7 +1847,7 @@ void Disassembler::AppendToOutput(const char* format, ...) {
|
|||
}
|
||||
|
||||
|
||||
void PrintDisassembler::ProcessOutput(Instruction* instr) {
|
||||
void PrintDisassembler::ProcessOutput(const Instruction* instr) {
|
||||
fprintf(stream_, "0x%016" PRIx64 " %08" PRIx32 "\t\t%s\n",
|
||||
reinterpret_cast<uint64_t>(instr),
|
||||
instr->InstructionBits(),
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue