disas/libvixl: Update to libvixl 1.4
Update our copy of libvixl to upstream's 1.4 release. Note that we no longer need any local fixes for compilation on 32 bit hosts -- they have all been integrated upstream. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1399040419-9227-1-git-send-email-peter.maydell@linaro.org Acked-by: Richard Henderson <rth@twiddle.net>
This commit is contained in:
parent
cd2b9b8680
commit
09319b3041
File diff suppressed because it is too large
Load Diff
@ -116,6 +116,8 @@ V_(ImmCmpBranch, 23, 5, SignedBits) \
|
||||
V_(ImmLLiteral, 23, 5, SignedBits) \
|
||||
V_(ImmException, 20, 5, Bits) \
|
||||
V_(ImmHint, 11, 5, Bits) \
|
||||
V_(ImmBarrierDomain, 11, 10, Bits) \
|
||||
V_(ImmBarrierType, 9, 8, Bits) \
|
||||
\
|
||||
/* System (MRS, MSR) */ \
|
||||
V_(ImmSystemRegister, 19, 5, Bits) \
|
||||
@ -181,7 +183,7 @@ enum Condition {
|
||||
inline Condition InvertCondition(Condition cond) {
|
||||
// Conditions al and nv behave identically, as "always true". They can't be
|
||||
// inverted, because there is no "always false" condition.
|
||||
ASSERT((cond != al) && (cond != nv));
|
||||
VIXL_ASSERT((cond != al) && (cond != nv));
|
||||
return static_cast<Condition>(cond ^ 1);
|
||||
}
|
||||
|
||||
@ -246,6 +248,20 @@ enum SystemHint {
|
||||
SEVL = 5
|
||||
};
|
||||
|
||||
enum BarrierDomain {
|
||||
OuterShareable = 0,
|
||||
NonShareable = 1,
|
||||
InnerShareable = 2,
|
||||
FullSystem = 3
|
||||
};
|
||||
|
||||
enum BarrierType {
|
||||
BarrierOther = 0,
|
||||
BarrierReads = 1,
|
||||
BarrierWrites = 2,
|
||||
BarrierAll = 3
|
||||
};
|
||||
|
||||
// System/special register names.
|
||||
// This information is not encoded as one field but as the concatenation of
|
||||
// multiple fields (Op0<0>, Op1, Crn, Crm, Op2).
|
||||
@ -274,7 +290,7 @@ enum SystemRegister {
|
||||
//
|
||||
// The enumerations can be used like this:
|
||||
//
|
||||
// ASSERT(instr->Mask(PCRelAddressingFMask) == PCRelAddressingFixed);
|
||||
// VIXL_ASSERT(instr->Mask(PCRelAddressingFMask) == PCRelAddressingFixed);
|
||||
// switch(instr->Mask(PCRelAddressingMask)) {
|
||||
// case ADR: Format("adr 'Xd, 'AddrPCRelByte"); break;
|
||||
// case ADRP: Format("adrp 'Xd, 'AddrPCRelPage"); break;
|
||||
@ -560,6 +576,15 @@ enum ExceptionOp {
|
||||
DCPS3 = ExceptionFixed | 0x00A00003
|
||||
};
|
||||
|
||||
enum MemBarrierOp {
|
||||
MemBarrierFixed = 0xD503309F,
|
||||
MemBarrierFMask = 0xFFFFF09F,
|
||||
MemBarrierMask = 0xFFFFF0FF,
|
||||
DSB = MemBarrierFixed | 0x00000000,
|
||||
DMB = MemBarrierFixed | 0x00000020,
|
||||
ISB = MemBarrierFixed | 0x00000040
|
||||
};
|
||||
|
||||
// Any load or store.
|
||||
enum LoadStoreAnyOp {
|
||||
LoadStoreAnyFMask = 0x0a000000,
|
||||
@ -927,17 +952,22 @@ enum FPDataProcessing1SourceOp {
|
||||
FRINTN = FRINTN_s,
|
||||
FRINTP_s = FPDataProcessing1SourceFixed | 0x00048000,
|
||||
FRINTP_d = FPDataProcessing1SourceFixed | FP64 | 0x00048000,
|
||||
FRINTP = FRINTP_s,
|
||||
FRINTM_s = FPDataProcessing1SourceFixed | 0x00050000,
|
||||
FRINTM_d = FPDataProcessing1SourceFixed | FP64 | 0x00050000,
|
||||
FRINTM = FRINTM_s,
|
||||
FRINTZ_s = FPDataProcessing1SourceFixed | 0x00058000,
|
||||
FRINTZ_d = FPDataProcessing1SourceFixed | FP64 | 0x00058000,
|
||||
FRINTZ = FRINTZ_s,
|
||||
FRINTA_s = FPDataProcessing1SourceFixed | 0x00060000,
|
||||
FRINTA_d = FPDataProcessing1SourceFixed | FP64 | 0x00060000,
|
||||
FRINTA = FRINTA_s,
|
||||
FRINTX_s = FPDataProcessing1SourceFixed | 0x00070000,
|
||||
FRINTX_d = FPDataProcessing1SourceFixed | FP64 | 0x00070000,
|
||||
FRINTX = FRINTX_s,
|
||||
FRINTI_s = FPDataProcessing1SourceFixed | 0x00078000,
|
||||
FRINTI_d = FPDataProcessing1SourceFixed | FP64 | 0x00078000
|
||||
FRINTI_d = FPDataProcessing1SourceFixed | FP64 | 0x00078000,
|
||||
FRINTI = FRINTI_s
|
||||
};
|
||||
|
||||
// Floating point data processing 2 source.
|
||||
|
@ -132,7 +132,7 @@ void Decoder::InsertVisitorBefore(DecoderVisitor* new_visitor,
|
||||
}
|
||||
// We reached the end of the list. The last element must be
|
||||
// registered_visitor.
|
||||
ASSERT(*it == registered_visitor);
|
||||
VIXL_ASSERT(*it == registered_visitor);
|
||||
visitors_.insert(it, new_visitor);
|
||||
}
|
||||
|
||||
@ -150,7 +150,7 @@ void Decoder::InsertVisitorAfter(DecoderVisitor* new_visitor,
|
||||
}
|
||||
// We reached the end of the list. The last element must be
|
||||
// registered_visitor.
|
||||
ASSERT(*it == registered_visitor);
|
||||
VIXL_ASSERT(*it == registered_visitor);
|
||||
visitors_.push_back(new_visitor);
|
||||
}
|
||||
|
||||
@ -161,16 +161,16 @@ void Decoder::RemoveVisitor(DecoderVisitor* visitor) {
|
||||
|
||||
|
||||
void Decoder::DecodePCRelAddressing(Instruction* instr) {
|
||||
ASSERT(instr->Bits(27, 24) == 0x0);
|
||||
VIXL_ASSERT(instr->Bits(27, 24) == 0x0);
|
||||
// We know bit 28 is set, as <b28:b27> = 0 is filtered out at the top level
|
||||
// decode.
|
||||
ASSERT(instr->Bit(28) == 0x1);
|
||||
VIXL_ASSERT(instr->Bit(28) == 0x1);
|
||||
VisitPCRelAddressing(instr);
|
||||
}
|
||||
|
||||
|
||||
void Decoder::DecodeBranchSystemException(Instruction* instr) {
|
||||
ASSERT((instr->Bits(27, 24) == 0x4) ||
|
||||
VIXL_ASSERT((instr->Bits(27, 24) == 0x4) ||
|
||||
(instr->Bits(27, 24) == 0x5) ||
|
||||
(instr->Bits(27, 24) == 0x6) ||
|
||||
(instr->Bits(27, 24) == 0x7) );
|
||||
@ -271,7 +271,7 @@ void Decoder::DecodeBranchSystemException(Instruction* instr) {
|
||||
|
||||
|
||||
void Decoder::DecodeLoadStore(Instruction* instr) {
|
||||
ASSERT((instr->Bits(27, 24) == 0x8) ||
|
||||
VIXL_ASSERT((instr->Bits(27, 24) == 0x8) ||
|
||||
(instr->Bits(27, 24) == 0x9) ||
|
||||
(instr->Bits(27, 24) == 0xC) ||
|
||||
(instr->Bits(27, 24) == 0xD) );
|
||||
@ -390,7 +390,7 @@ void Decoder::DecodeLoadStore(Instruction* instr) {
|
||||
|
||||
|
||||
void Decoder::DecodeLogical(Instruction* instr) {
|
||||
ASSERT(instr->Bits(27, 24) == 0x2);
|
||||
VIXL_ASSERT(instr->Bits(27, 24) == 0x2);
|
||||
|
||||
if (instr->Mask(0x80400000) == 0x00400000) {
|
||||
VisitUnallocated(instr);
|
||||
@ -409,7 +409,7 @@ void Decoder::DecodeLogical(Instruction* instr) {
|
||||
|
||||
|
||||
void Decoder::DecodeBitfieldExtract(Instruction* instr) {
|
||||
ASSERT(instr->Bits(27, 24) == 0x3);
|
||||
VIXL_ASSERT(instr->Bits(27, 24) == 0x3);
|
||||
|
||||
if ((instr->Mask(0x80400000) == 0x80000000) ||
|
||||
(instr->Mask(0x80400000) == 0x00400000) ||
|
||||
@ -434,7 +434,7 @@ void Decoder::DecodeBitfieldExtract(Instruction* instr) {
|
||||
|
||||
|
||||
void Decoder::DecodeAddSubImmediate(Instruction* instr) {
|
||||
ASSERT(instr->Bits(27, 24) == 0x1);
|
||||
VIXL_ASSERT(instr->Bits(27, 24) == 0x1);
|
||||
if (instr->Bit(23) == 1) {
|
||||
VisitUnallocated(instr);
|
||||
} else {
|
||||
@ -444,8 +444,8 @@ void Decoder::DecodeAddSubImmediate(Instruction* instr) {
|
||||
|
||||
|
||||
void Decoder::DecodeDataProcessing(Instruction* instr) {
|
||||
ASSERT((instr->Bits(27, 24) == 0xA) ||
|
||||
(instr->Bits(27, 24) == 0xB) );
|
||||
VIXL_ASSERT((instr->Bits(27, 24) == 0xA) ||
|
||||
(instr->Bits(27, 24) == 0xB));
|
||||
|
||||
if (instr->Bit(24) == 0) {
|
||||
if (instr->Bit(28) == 0) {
|
||||
@ -559,8 +559,8 @@ void Decoder::DecodeDataProcessing(Instruction* instr) {
|
||||
|
||||
|
||||
void Decoder::DecodeFP(Instruction* instr) {
|
||||
ASSERT((instr->Bits(27, 24) == 0xE) ||
|
||||
(instr->Bits(27, 24) == 0xF) );
|
||||
VIXL_ASSERT((instr->Bits(27, 24) == 0xE) ||
|
||||
(instr->Bits(27, 24) == 0xF));
|
||||
|
||||
if (instr->Bit(28) == 0) {
|
||||
DecodeAdvSIMDDataProcessing(instr);
|
||||
@ -665,14 +665,14 @@ void Decoder::DecodeFP(Instruction* instr) {
|
||||
VisitFPConditionalSelect(instr);
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Bit 30 == 1 has been handled earlier.
|
||||
ASSERT(instr->Bit(30) == 0);
|
||||
VIXL_ASSERT(instr->Bit(30) == 0);
|
||||
if (instr->Mask(0xA0800000) != 0) {
|
||||
VisitUnallocated(instr);
|
||||
} else {
|
||||
@ -687,21 +687,21 @@ void Decoder::DecodeFP(Instruction* instr) {
|
||||
|
||||
void Decoder::DecodeAdvSIMDLoadStore(Instruction* instr) {
|
||||
// TODO: Implement Advanced SIMD load/store instruction decode.
|
||||
ASSERT(instr->Bits(29, 25) == 0x6);
|
||||
VIXL_ASSERT(instr->Bits(29, 25) == 0x6);
|
||||
VisitUnimplemented(instr);
|
||||
}
|
||||
|
||||
|
||||
void Decoder::DecodeAdvSIMDDataProcessing(Instruction* instr) {
|
||||
// TODO: Implement Advanced SIMD data processing instruction decode.
|
||||
ASSERT(instr->Bits(27, 25) == 0x7);
|
||||
VIXL_ASSERT(instr->Bits(27, 25) == 0x7);
|
||||
VisitUnimplemented(instr);
|
||||
}
|
||||
|
||||
|
||||
#define DEFINE_VISITOR_CALLERS(A) \
|
||||
void Decoder::Visit##A(Instruction *instr) { \
|
||||
ASSERT(instr->Mask(A##FMask) == A##Fixed); \
|
||||
VIXL_ASSERT(instr->Mask(A##FMask) == A##Fixed); \
|
||||
std::list<DecoderVisitor*>::iterator it; \
|
||||
for (it = visitors_.begin(); it != visitors_.end(); it++) { \
|
||||
(*it)->Visit##A(instr); \
|
||||
|
@ -95,7 +95,7 @@ void Disassembler::VisitAddSubImmediate(Instruction* instr) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -142,7 +142,7 @@ void Disassembler::VisitAddSubShifted(Instruction* instr) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -180,7 +180,7 @@ void Disassembler::VisitAddSubExtended(Instruction* instr) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -215,7 +215,7 @@ void Disassembler::VisitAddSubWithCarry(Instruction* instr) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -258,30 +258,30 @@ void Disassembler::VisitLogicalImmediate(Instruction* instr) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
|
||||
|
||||
bool Disassembler::IsMovzMovnImm(unsigned reg_size, uint64_t value) {
|
||||
ASSERT((reg_size == kXRegSize) ||
|
||||
((reg_size == kWRegSize) && (value <= 0xffffffff)));
|
||||
VIXL_ASSERT((reg_size == kXRegSize) ||
|
||||
((reg_size == kWRegSize) && (value <= 0xffffffff)));
|
||||
|
||||
// Test for movz: 16 bits set at positions 0, 16, 32 or 48.
|
||||
if (((value & 0xffffffffffff0000ULL) == 0ULL) ||
|
||||
((value & 0xffffffff0000ffffULL) == 0ULL) ||
|
||||
((value & 0xffff0000ffffffffULL) == 0ULL) ||
|
||||
((value & 0x0000ffffffffffffULL) == 0ULL)) {
|
||||
if (((value & UINT64_C(0xffffffffffff0000)) == 0) ||
|
||||
((value & UINT64_C(0xffffffff0000ffff)) == 0) ||
|
||||
((value & UINT64_C(0xffff0000ffffffff)) == 0) ||
|
||||
((value & UINT64_C(0x0000ffffffffffff)) == 0)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// Test for movn: NOT(16 bits set at positions 0, 16, 32 or 48).
|
||||
if ((reg_size == kXRegSize) &&
|
||||
(((value & 0xffffffffffff0000ULL) == 0xffffffffffff0000ULL) ||
|
||||
((value & 0xffffffff0000ffffULL) == 0xffffffff0000ffffULL) ||
|
||||
((value & 0xffff0000ffffffffULL) == 0xffff0000ffffffffULL) ||
|
||||
((value & 0x0000ffffffffffffULL) == 0x0000ffffffffffffULL))) {
|
||||
(((~value & UINT64_C(0xffffffffffff0000)) == 0) ||
|
||||
((~value & UINT64_C(0xffffffff0000ffff)) == 0) ||
|
||||
((~value & UINT64_C(0xffff0000ffffffff)) == 0) ||
|
||||
((~value & UINT64_C(0x0000ffffffffffff)) == 0))) {
|
||||
return true;
|
||||
}
|
||||
if ((reg_size == kWRegSize) &&
|
||||
@ -337,7 +337,7 @@ void Disassembler::VisitLogicalShifted(Instruction* instr) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
|
||||
Format(instr, mnemonic, form);
|
||||
@ -353,7 +353,7 @@ void Disassembler::VisitConditionalCompareRegister(Instruction* instr) {
|
||||
case CCMN_x: mnemonic = "ccmn"; break;
|
||||
case CCMP_w:
|
||||
case CCMP_x: mnemonic = "ccmp"; break;
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -368,7 +368,7 @@ void Disassembler::VisitConditionalCompareImmediate(Instruction* instr) {
|
||||
case CCMN_x_imm: mnemonic = "ccmn"; break;
|
||||
case CCMP_w_imm:
|
||||
case CCMP_x_imm: mnemonic = "ccmp"; break;
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -421,7 +421,7 @@ void Disassembler::VisitConditionalSelect(Instruction* instr) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -520,7 +520,7 @@ void Disassembler::VisitExtract(Instruction* instr) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -538,7 +538,7 @@ void Disassembler::VisitPCRelAddressing(Instruction* instr) {
|
||||
void Disassembler::VisitConditionalBranch(Instruction* instr) {
|
||||
switch (instr->Mask(ConditionalBranchMask)) {
|
||||
case B_cond: Format(instr, "b.'CBrn", "'BImmCond"); break;
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
||||
@ -570,7 +570,7 @@ void Disassembler::VisitUnconditionalBranch(Instruction* instr) {
|
||||
switch (instr->Mask(UnconditionalBranchMask)) {
|
||||
case B: mnemonic = "b"; break;
|
||||
case BL: mnemonic = "bl"; break;
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -591,7 +591,7 @@ void Disassembler::VisitDataProcessing1Source(Instruction* instr) {
|
||||
FORMAT(CLS, "cls");
|
||||
#undef FORMAT
|
||||
case REV32_x: mnemonic = "rev32"; break;
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -690,7 +690,7 @@ void Disassembler::VisitDataProcessing3Source(Instruction* instr) {
|
||||
form = form_xxx;
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -705,7 +705,7 @@ void Disassembler::VisitCompareBranch(Instruction* instr) {
|
||||
case CBZ_x: mnemonic = "cbz"; break;
|
||||
case CBNZ_w:
|
||||
case CBNZ_x: mnemonic = "cbnz"; break;
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -722,7 +722,7 @@ void Disassembler::VisitTestBranch(Instruction* instr) {
|
||||
switch (instr->Mask(TestBranchMask)) {
|
||||
case TBZ: mnemonic = "tbz"; break;
|
||||
case TBNZ: mnemonic = "tbnz"; break;
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -742,7 +742,7 @@ void Disassembler::VisitMoveWideImmediate(Instruction* instr) {
|
||||
case MOVZ_x: mnemonic = "movz"; break;
|
||||
case MOVK_w:
|
||||
case MOVK_x: mnemonic = "movk"; form = "'Rd, 'IMoveLSL"; break;
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -981,7 +981,7 @@ void Disassembler::VisitFPConditionalSelect(Instruction* instr) {
|
||||
switch (instr->Mask(FPConditionalSelectMask)) {
|
||||
case FCSEL_s:
|
||||
case FCSEL_d: mnemonic = "fcsel"; break;
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -1033,7 +1033,7 @@ void Disassembler::VisitFPDataProcessing2Source(Instruction* instr) {
|
||||
FORMAT(FMINNM, "fminnm");
|
||||
FORMAT(FNMUL, "fnmul");
|
||||
#undef FORMAT
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -1052,7 +1052,7 @@ void Disassembler::VisitFPDataProcessing3Source(Instruction* instr) {
|
||||
FORMAT(FNMADD, "fnmadd");
|
||||
FORMAT(FNMSUB, "fnmsub");
|
||||
#undef FORMAT
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -1065,7 +1065,7 @@ void Disassembler::VisitFPImmediate(Instruction* instr) {
|
||||
switch (instr->Mask(FPImmediateMask)) {
|
||||
case FMOV_s_imm: mnemonic = "fmov"; form = "'Sd, 'IFPSingle"; break;
|
||||
case FMOV_d_imm: mnemonic = "fmov"; form = "'Dd, 'IFPDouble"; break;
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -1082,6 +1082,14 @@ void Disassembler::VisitFPIntegerConvert(Instruction* instr) {
|
||||
case FMOV_xd: mnemonic = "fmov"; form = form_rf; break;
|
||||
case FMOV_sw:
|
||||
case FMOV_dx: mnemonic = "fmov"; form = form_fr; break;
|
||||
case FCVTAS_ws:
|
||||
case FCVTAS_xs:
|
||||
case FCVTAS_wd:
|
||||
case FCVTAS_xd: mnemonic = "fcvtas"; form = form_rf; break;
|
||||
case FCVTAU_ws:
|
||||
case FCVTAU_xs:
|
||||
case FCVTAU_wd:
|
||||
case FCVTAU_xd: mnemonic = "fcvtau"; form = form_rf; break;
|
||||
case FCVTMS_ws:
|
||||
case FCVTMS_xs:
|
||||
case FCVTMS_wd:
|
||||
@ -1141,7 +1149,7 @@ void Disassembler::VisitFPFixedPointConvert(Instruction* instr) {
|
||||
case UCVTF_sx_fixed:
|
||||
case UCVTF_dw_fixed:
|
||||
case UCVTF_dx_fixed: mnemonic = "ucvtf"; form = form_fr; break;
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
Format(instr, mnemonic, form);
|
||||
}
|
||||
@ -1176,7 +1184,7 @@ void Disassembler::VisitSystem(Instruction* instr) {
|
||||
}
|
||||
}
|
||||
} else if (instr->Mask(SystemHintFMask) == SystemHintFixed) {
|
||||
ASSERT(instr->Mask(SystemHintMask) == HINT);
|
||||
VIXL_ASSERT(instr->Mask(SystemHintMask) == HINT);
|
||||
switch (instr->ImmHint()) {
|
||||
case NOP: {
|
||||
mnemonic = "nop";
|
||||
@ -1184,6 +1192,24 @@ void Disassembler::VisitSystem(Instruction* instr) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (instr->Mask(MemBarrierFMask) == MemBarrierFixed) {
|
||||
switch (instr->Mask(MemBarrierMask)) {
|
||||
case DMB: {
|
||||
mnemonic = "dmb";
|
||||
form = "'M";
|
||||
break;
|
||||
}
|
||||
case DSB: {
|
||||
mnemonic = "dsb";
|
||||
form = "'M";
|
||||
break;
|
||||
}
|
||||
case ISB: {
|
||||
mnemonic = "isb";
|
||||
form = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Format(instr, mnemonic, form);
|
||||
@ -1226,7 +1252,7 @@ void Disassembler::ProcessOutput(Instruction* /*instr*/) {
|
||||
|
||||
void Disassembler::Format(Instruction* instr, const char* mnemonic,
|
||||
const char* format) {
|
||||
ASSERT(mnemonic != NULL);
|
||||
VIXL_ASSERT(mnemonic != NULL);
|
||||
ResetOutput();
|
||||
Substitute(instr, mnemonic);
|
||||
if (format != NULL) {
|
||||
@ -1268,8 +1294,9 @@ int Disassembler::SubstituteField(Instruction* instr, const char* format) {
|
||||
case 'A': return SubstitutePCRelAddressField(instr, format);
|
||||
case 'B': return SubstituteBranchTargetField(instr, format);
|
||||
case 'O': return SubstituteLSRegOffsetField(instr, format);
|
||||
case 'M': return SubstituteBarrierField(instr, format);
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
VIXL_UNREACHABLE();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@ -1294,7 +1321,7 @@ int Disassembler::SubstituteRegisterField(Instruction* instr,
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
|
||||
// Increase field length for registers tagged as stack.
|
||||
@ -1331,7 +1358,7 @@ int Disassembler::SubstituteRegisterField(Instruction* instr,
|
||||
|
||||
int Disassembler::SubstituteImmediateField(Instruction* instr,
|
||||
const char* format) {
|
||||
ASSERT(format[0] == 'I');
|
||||
VIXL_ASSERT(format[0] == 'I');
|
||||
|
||||
switch (format[1]) {
|
||||
case 'M': { // IMoveImm or IMoveLSL.
|
||||
@ -1339,10 +1366,10 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
||||
uint64_t imm = instr->ImmMoveWide() << (16 * instr->ShiftMoveWide());
|
||||
AppendToOutput("#0x%" PRIx64, imm);
|
||||
} else {
|
||||
ASSERT(format[5] == 'L');
|
||||
VIXL_ASSERT(format[5] == 'L');
|
||||
AppendToOutput("#0x%" PRIx64, instr->ImmMoveWide());
|
||||
if (instr->ShiftMoveWide() > 0) {
|
||||
AppendToOutput(", lsl #%" PRId64, 16 * instr->ShiftMoveWide());
|
||||
AppendToOutput(", lsl #%d", 16 * instr->ShiftMoveWide());
|
||||
}
|
||||
}
|
||||
return 8;
|
||||
@ -1384,14 +1411,14 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
||||
return 6;
|
||||
}
|
||||
case 'A': { // IAddSub.
|
||||
ASSERT(instr->ShiftAddSub() <= 1);
|
||||
VIXL_ASSERT(instr->ShiftAddSub() <= 1);
|
||||
int64_t imm = instr->ImmAddSub() << (12 * instr->ShiftAddSub());
|
||||
AppendToOutput("#0x%" PRIx64 " (%" PRId64 ")", imm, imm);
|
||||
return 7;
|
||||
}
|
||||
case 'F': { // IFPSingle, IFPDouble or IFPFBits.
|
||||
if (format[3] == 'F') { // IFPFbits.
|
||||
AppendToOutput("#%" PRId64, 64 - instr->FPScale());
|
||||
AppendToOutput("#%d", 64 - instr->FPScale());
|
||||
return 8;
|
||||
} else {
|
||||
AppendToOutput("#0x%" PRIx64 " (%.4f)", instr->ImmFP(),
|
||||
@ -1412,27 +1439,27 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
||||
return 5;
|
||||
}
|
||||
case 'P': { // IP - Conditional compare.
|
||||
AppendToOutput("#%" PRId64, instr->ImmCondCmp());
|
||||
AppendToOutput("#%d", instr->ImmCondCmp());
|
||||
return 2;
|
||||
}
|
||||
case 'B': { // Bitfields.
|
||||
return SubstituteBitfieldImmediateField(instr, format);
|
||||
}
|
||||
case 'E': { // IExtract.
|
||||
AppendToOutput("#%" PRId64, instr->ImmS());
|
||||
AppendToOutput("#%d", instr->ImmS());
|
||||
return 8;
|
||||
}
|
||||
case 'S': { // IS - Test and branch bit.
|
||||
AppendToOutput("#%" PRId64, (instr->ImmTestBranchBit5() << 5) |
|
||||
instr->ImmTestBranchBit40());
|
||||
AppendToOutput("#%d", (instr->ImmTestBranchBit5() << 5) |
|
||||
instr->ImmTestBranchBit40());
|
||||
return 2;
|
||||
}
|
||||
case 'D': { // IDebug - HLT and BRK instructions.
|
||||
AppendToOutput("#0x%" PRIx64, instr->ImmException());
|
||||
AppendToOutput("#0x%x", instr->ImmException());
|
||||
return 6;
|
||||
}
|
||||
default: {
|
||||
UNIMPLEMENTED();
|
||||
VIXL_UNIMPLEMENTED();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -1441,7 +1468,7 @@ int Disassembler::SubstituteImmediateField(Instruction* instr,
|
||||
|
||||
int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr,
|
||||
const char* format) {
|
||||
ASSERT((format[0] == 'I') && (format[1] == 'B'));
|
||||
VIXL_ASSERT((format[0] == 'I') && (format[1] == 'B'));
|
||||
unsigned r = instr->ImmR();
|
||||
unsigned s = instr->ImmS();
|
||||
|
||||
@ -1455,19 +1482,19 @@ int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr,
|
||||
AppendToOutput("#%d", s + 1);
|
||||
return 5;
|
||||
} else {
|
||||
ASSERT(format[3] == '-');
|
||||
VIXL_ASSERT(format[3] == '-');
|
||||
AppendToOutput("#%d", s - r + 1);
|
||||
return 7;
|
||||
}
|
||||
}
|
||||
case 'Z': { // IBZ-r.
|
||||
ASSERT((format[3] == '-') && (format[4] == 'r'));
|
||||
VIXL_ASSERT((format[3] == '-') && (format[4] == 'r'));
|
||||
unsigned reg_size = (instr->SixtyFourBits() == 1) ? kXRegSize : kWRegSize;
|
||||
AppendToOutput("#%d", reg_size - r);
|
||||
return 5;
|
||||
}
|
||||
default: {
|
||||
UNREACHABLE();
|
||||
VIXL_UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -1476,7 +1503,7 @@ int Disassembler::SubstituteBitfieldImmediateField(Instruction* instr,
|
||||
|
||||
int Disassembler::SubstituteLiteralField(Instruction* instr,
|
||||
const char* format) {
|
||||
ASSERT(strncmp(format, "LValue", 6) == 0);
|
||||
VIXL_ASSERT(strncmp(format, "LValue", 6) == 0);
|
||||
USE(format);
|
||||
|
||||
switch (instr->Mask(LoadLiteralMask)) {
|
||||
@ -1484,7 +1511,7 @@ int Disassembler::SubstituteLiteralField(Instruction* instr,
|
||||
case LDR_x_lit:
|
||||
case LDR_s_lit:
|
||||
case LDR_d_lit: AppendToOutput("(addr %p)", instr->LiteralAddress()); break;
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
|
||||
return 6;
|
||||
@ -1492,12 +1519,12 @@ int Disassembler::SubstituteLiteralField(Instruction* instr,
|
||||
|
||||
|
||||
int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) {
|
||||
ASSERT(format[0] == 'H');
|
||||
ASSERT(instr->ShiftDP() <= 0x3);
|
||||
VIXL_ASSERT(format[0] == 'H');
|
||||
VIXL_ASSERT(instr->ShiftDP() <= 0x3);
|
||||
|
||||
switch (format[1]) {
|
||||
case 'D': { // HDP.
|
||||
ASSERT(instr->ShiftDP() != ROR);
|
||||
VIXL_ASSERT(instr->ShiftDP() != ROR);
|
||||
} // Fall through.
|
||||
case 'L': { // HLo.
|
||||
if (instr->ImmDPShift() != 0) {
|
||||
@ -1508,7 +1535,7 @@ int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) {
|
||||
return 3;
|
||||
}
|
||||
default:
|
||||
UNIMPLEMENTED();
|
||||
VIXL_UNIMPLEMENTED();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@ -1516,7 +1543,7 @@ int Disassembler::SubstituteShiftField(Instruction* instr, const char* format) {
|
||||
|
||||
int Disassembler::SubstituteConditionField(Instruction* instr,
|
||||
const char* format) {
|
||||
ASSERT(format[0] == 'C');
|
||||
VIXL_ASSERT(format[0] == 'C');
|
||||
const char* condition_code[] = { "eq", "ne", "hs", "lo",
|
||||
"mi", "pl", "vs", "vc",
|
||||
"hi", "ls", "ge", "lt",
|
||||
@ -1538,27 +1565,27 @@ int Disassembler::SubstituteConditionField(Instruction* instr,
|
||||
int Disassembler::SubstitutePCRelAddressField(Instruction* instr,
|
||||
const char* format) {
|
||||
USE(format);
|
||||
ASSERT(strncmp(format, "AddrPCRel", 9) == 0);
|
||||
VIXL_ASSERT(strncmp(format, "AddrPCRel", 9) == 0);
|
||||
|
||||
int offset = instr->ImmPCRel();
|
||||
|
||||
// Only ADR (AddrPCRelByte) is supported.
|
||||
ASSERT(strcmp(format, "AddrPCRelByte") == 0);
|
||||
VIXL_ASSERT(strcmp(format, "AddrPCRelByte") == 0);
|
||||
|
||||
char sign = '+';
|
||||
if (offset < 0) {
|
||||
offset = -offset;
|
||||
sign = '-';
|
||||
}
|
||||
// TODO: Extend this to support printing the target address.
|
||||
AppendToOutput("#%c0x%x", sign, offset);
|
||||
VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
|
||||
AppendToOutput("#%c0x%x (addr %p)", sign, offset, instr + offset);
|
||||
return 13;
|
||||
}
|
||||
|
||||
|
||||
int Disassembler::SubstituteBranchTargetField(Instruction* instr,
|
||||
const char* format) {
|
||||
ASSERT(strncmp(format, "BImm", 4) == 0);
|
||||
VIXL_ASSERT(strncmp(format, "BImm", 4) == 0);
|
||||
|
||||
int64_t offset = 0;
|
||||
switch (format[5]) {
|
||||
@ -1570,7 +1597,7 @@ int Disassembler::SubstituteBranchTargetField(Instruction* instr,
|
||||
case 'm': offset = instr->ImmCmpBranch(); break;
|
||||
// BImmTest - test and branch immediate.
|
||||
case 'e': offset = instr->ImmTestBranch(); break;
|
||||
default: UNIMPLEMENTED();
|
||||
default: VIXL_UNIMPLEMENTED();
|
||||
}
|
||||
offset <<= kInstructionSizeLog2;
|
||||
char sign = '+';
|
||||
@ -1578,15 +1605,16 @@ int Disassembler::SubstituteBranchTargetField(Instruction* instr,
|
||||
offset = -offset;
|
||||
sign = '-';
|
||||
}
|
||||
AppendToOutput("#%c0x%" PRIx64, sign, offset);
|
||||
VIXL_STATIC_ASSERT(sizeof(*instr) == 1);
|
||||
AppendToOutput("#%c0x%" PRIx64 " (addr %p)", sign, offset, instr + offset);
|
||||
return 8;
|
||||
}
|
||||
|
||||
|
||||
int Disassembler::SubstituteExtendField(Instruction* instr,
|
||||
const char* format) {
|
||||
ASSERT(strncmp(format, "Ext", 3) == 0);
|
||||
ASSERT(instr->ExtendMode() <= 7);
|
||||
VIXL_ASSERT(strncmp(format, "Ext", 3) == 0);
|
||||
VIXL_ASSERT(instr->ExtendMode() <= 7);
|
||||
USE(format);
|
||||
|
||||
const char* extend_mode[] = { "uxtb", "uxth", "uxtw", "uxtx",
|
||||
@ -1598,12 +1626,12 @@ int Disassembler::SubstituteExtendField(Instruction* instr,
|
||||
(((instr->ExtendMode() == UXTW) && (instr->SixtyFourBits() == 0)) ||
|
||||
(instr->ExtendMode() == UXTX))) {
|
||||
if (instr->ImmExtendShift() > 0) {
|
||||
AppendToOutput(", lsl #%" PRId64, instr->ImmExtendShift());
|
||||
AppendToOutput(", lsl #%d", instr->ImmExtendShift());
|
||||
}
|
||||
} else {
|
||||
AppendToOutput(", %s", extend_mode[instr->ExtendMode()]);
|
||||
if (instr->ImmExtendShift() > 0) {
|
||||
AppendToOutput(" #%" PRId64, instr->ImmExtendShift());
|
||||
AppendToOutput(" #%d", instr->ImmExtendShift());
|
||||
}
|
||||
}
|
||||
return 3;
|
||||
@ -1612,7 +1640,7 @@ int Disassembler::SubstituteExtendField(Instruction* instr,
|
||||
|
||||
int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
|
||||
const char* format) {
|
||||
ASSERT(strncmp(format, "Offsetreg", 9) == 0);
|
||||
VIXL_ASSERT(strncmp(format, "Offsetreg", 9) == 0);
|
||||
const char* extend_mode[] = { "undefined", "undefined", "uxtw", "lsl",
|
||||
"undefined", "undefined", "sxtw", "sxtx" };
|
||||
USE(format);
|
||||
@ -1632,7 +1660,7 @@ int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
|
||||
if (!((ext == UXTX) && (shift == 0))) {
|
||||
AppendToOutput(", %s", extend_mode[ext]);
|
||||
if (shift != 0) {
|
||||
AppendToOutput(" #%" PRId64, instr->SizeLS());
|
||||
AppendToOutput(" #%d", instr->SizeLS());
|
||||
}
|
||||
}
|
||||
return 9;
|
||||
@ -1641,7 +1669,7 @@ int Disassembler::SubstituteLSRegOffsetField(Instruction* instr,
|
||||
|
||||
int Disassembler::SubstitutePrefetchField(Instruction* instr,
|
||||
const char* format) {
|
||||
ASSERT(format[0] == 'P');
|
||||
VIXL_ASSERT(format[0] == 'P');
|
||||
USE(format);
|
||||
|
||||
int prefetch_mode = instr->PrefetchMode();
|
||||
@ -1654,6 +1682,23 @@ int Disassembler::SubstitutePrefetchField(Instruction* instr,
|
||||
return 6;
|
||||
}
|
||||
|
||||
int Disassembler::SubstituteBarrierField(Instruction* instr,
|
||||
const char* format) {
|
||||
VIXL_ASSERT(format[0] == 'M');
|
||||
USE(format);
|
||||
|
||||
static const char* options[4][4] = {
|
||||
{ "sy (0b0000)", "oshld", "oshst", "osh" },
|
||||
{ "sy (0b0100)", "nshld", "nshst", "nsh" },
|
||||
{ "sy (0b1000)", "ishld", "ishst", "ish" },
|
||||
{ "sy (0b1100)", "ld", "st", "sy" }
|
||||
};
|
||||
int domain = instr->ImmBarrierDomain();
|
||||
int type = instr->ImmBarrierType();
|
||||
|
||||
AppendToOutput("%s", options[domain][type]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
void Disassembler::ResetOutput() {
|
||||
buffer_pos_ = 0;
|
||||
|
@ -64,6 +64,7 @@ class Disassembler: public DecoderVisitor {
|
||||
int SubstituteBranchTargetField(Instruction* instr, const char* format);
|
||||
int SubstituteLSRegOffsetField(Instruction* instr, const char* format);
|
||||
int SubstitutePrefetchField(Instruction* instr, const char* format);
|
||||
int SubstituteBarrierField(Instruction* instr, const char* format);
|
||||
|
||||
inline bool RdIsZROrSP(Instruction* instr) const {
|
||||
return (instr->Rd() == kZeroRegCode);
|
||||
|
@ -33,20 +33,20 @@ namespace vixl {
|
||||
static uint64_t RotateRight(uint64_t value,
|
||||
unsigned int rotate,
|
||||
unsigned int width) {
|
||||
ASSERT(width <= 64);
|
||||
VIXL_ASSERT(width <= 64);
|
||||
rotate &= 63;
|
||||
return ((value & ((1UL << rotate) - 1UL)) << (width - rotate)) |
|
||||
(value >> rotate);
|
||||
return ((value & ((UINT64_C(1) << rotate) - 1)) <<
|
||||
(width - rotate)) | (value >> rotate);
|
||||
}
|
||||
|
||||
|
||||
static uint64_t RepeatBitsAcrossReg(unsigned reg_size,
|
||||
uint64_t value,
|
||||
unsigned width) {
|
||||
ASSERT((width == 2) || (width == 4) || (width == 8) || (width == 16) ||
|
||||
(width == 32));
|
||||
ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
|
||||
uint64_t result = value & ((1UL << width) - 1UL);
|
||||
VIXL_ASSERT((width == 2) || (width == 4) || (width == 8) || (width == 16) ||
|
||||
(width == 32));
|
||||
VIXL_ASSERT((reg_size == kWRegSize) || (reg_size == kXRegSize));
|
||||
uint64_t result = value & ((UINT64_C(1) << width) - 1);
|
||||
for (unsigned i = width; i < reg_size; i *= 2) {
|
||||
result |= (result << i);
|
||||
}
|
||||
@ -84,7 +84,7 @@ uint64_t Instruction::ImmLogical() {
|
||||
if (imm_s == 0x3F) {
|
||||
return 0;
|
||||
}
|
||||
uint64_t bits = (1UL << (imm_s + 1)) - 1;
|
||||
uint64_t bits = (UINT64_C(1) << (imm_s + 1)) - 1;
|
||||
return RotateRight(bits, imm_r, 64);
|
||||
} else {
|
||||
if ((imm_s >> 1) == 0x1F) {
|
||||
@ -96,14 +96,14 @@ uint64_t Instruction::ImmLogical() {
|
||||
if ((imm_s & mask) == mask) {
|
||||
return 0;
|
||||
}
|
||||
uint64_t bits = (1UL << ((imm_s & mask) + 1)) - 1;
|
||||
uint64_t bits = (UINT64_C(1) << ((imm_s & mask) + 1)) - 1;
|
||||
return RepeatBitsAcrossReg(reg_size,
|
||||
RotateRight(bits, imm_r & mask, width),
|
||||
width);
|
||||
}
|
||||
}
|
||||
}
|
||||
UNREACHABLE();
|
||||
VIXL_UNREACHABLE();
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -155,7 +155,7 @@ Instruction* Instruction::ImmPCOffsetTarget() {
|
||||
offset = ImmPCRel();
|
||||
} else {
|
||||
// All PC-relative branches.
|
||||
ASSERT(BranchType() != UnknownBranchType);
|
||||
VIXL_ASSERT(BranchType() != UnknownBranchType);
|
||||
// Relative branch offsets are instruction-size-aligned.
|
||||
offset = ImmBranch() << kInstructionSizeLog2;
|
||||
}
|
||||
@ -169,7 +169,7 @@ inline int Instruction::ImmBranch() const {
|
||||
case UncondBranchType: return ImmUncondBranch();
|
||||
case CompareBranchType: return ImmCmpBranch();
|
||||
case TestBranchType: return ImmTestBranch();
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
@ -186,7 +186,7 @@ void Instruction::SetImmPCOffsetTarget(Instruction* target) {
|
||||
|
||||
void Instruction::SetPCRelImmTarget(Instruction* target) {
|
||||
// ADRP is not supported, so 'this' must point to an ADR instruction.
|
||||
ASSERT(Mask(PCRelAddressingMask) == ADR);
|
||||
VIXL_ASSERT(Mask(PCRelAddressingMask) == ADR);
|
||||
|
||||
Instr imm = Assembler::ImmPCRelAddress(target - this);
|
||||
|
||||
@ -195,7 +195,7 @@ void Instruction::SetPCRelImmTarget(Instruction* target) {
|
||||
|
||||
|
||||
void Instruction::SetBranchImmTarget(Instruction* target) {
|
||||
ASSERT(((target - this) & 3) == 0);
|
||||
VIXL_ASSERT(((target - this) & 3) == 0);
|
||||
Instr branch_imm = 0;
|
||||
uint32_t imm_mask = 0;
|
||||
int offset = (target - this) >> kInstructionSizeLog2;
|
||||
@ -220,14 +220,14 @@ void Instruction::SetBranchImmTarget(Instruction* target) {
|
||||
imm_mask = ImmTestBranch_mask;
|
||||
break;
|
||||
}
|
||||
default: UNREACHABLE();
|
||||
default: VIXL_UNREACHABLE();
|
||||
}
|
||||
SetInstructionBits(Mask(~imm_mask) | branch_imm);
|
||||
}
|
||||
|
||||
|
||||
void Instruction::SetImmLLiteral(Instruction* source) {
|
||||
ASSERT(((source - this) & 3) == 0);
|
||||
VIXL_ASSERT(((source - this) & 3) == 0);
|
||||
int offset = (source - this) >> kLiteralEntrySizeLog2;
|
||||
Instr imm = Assembler::ImmLLiteral(offset);
|
||||
Instr mask = ImmLLiteral_mask;
|
||||
|
@ -44,30 +44,36 @@ const unsigned kMaxLoadLiteralRange = 1 * MBytes;
|
||||
const unsigned kWRegSize = 32;
|
||||
const unsigned kWRegSizeLog2 = 5;
|
||||
const unsigned kWRegSizeInBytes = kWRegSize / 8;
|
||||
const unsigned kWRegSizeInBytesLog2 = kWRegSizeLog2 - 3;
|
||||
const unsigned kXRegSize = 64;
|
||||
const unsigned kXRegSizeLog2 = 6;
|
||||
const unsigned kXRegSizeInBytes = kXRegSize / 8;
|
||||
const unsigned kXRegSizeInBytesLog2 = kXRegSizeLog2 - 3;
|
||||
const unsigned kSRegSize = 32;
|
||||
const unsigned kSRegSizeLog2 = 5;
|
||||
const unsigned kSRegSizeInBytes = kSRegSize / 8;
|
||||
const unsigned kSRegSizeInBytesLog2 = kSRegSizeLog2 - 3;
|
||||
const unsigned kDRegSize = 64;
|
||||
const unsigned kDRegSizeLog2 = 6;
|
||||
const unsigned kDRegSizeInBytes = kDRegSize / 8;
|
||||
const int64_t kWRegMask = 0x00000000ffffffffLL;
|
||||
const int64_t kXRegMask = 0xffffffffffffffffLL;
|
||||
const int64_t kSRegMask = 0x00000000ffffffffLL;
|
||||
const int64_t kDRegMask = 0xffffffffffffffffLL;
|
||||
const int64_t kXSignMask = 0x1LL << 63;
|
||||
const int64_t kWSignMask = 0x1LL << 31;
|
||||
const int64_t kByteMask = 0xffL;
|
||||
const int64_t kHalfWordMask = 0xffffL;
|
||||
const int64_t kWordMask = 0xffffffffLL;
|
||||
const uint64_t kXMaxUInt = 0xffffffffffffffffULL;
|
||||
const uint64_t kWMaxUInt = 0xffffffffULL;
|
||||
const int64_t kXMaxInt = 0x7fffffffffffffffLL;
|
||||
const int64_t kXMinInt = 0x8000000000000000LL;
|
||||
const int32_t kWMaxInt = 0x7fffffff;
|
||||
const int32_t kWMinInt = 0x80000000;
|
||||
const unsigned kDRegSizeInBytesLog2 = kDRegSizeLog2 - 3;
|
||||
const uint64_t kWRegMask = UINT64_C(0xffffffff);
|
||||
const uint64_t kXRegMask = UINT64_C(0xffffffffffffffff);
|
||||
const uint64_t kSRegMask = UINT64_C(0xffffffff);
|
||||
const uint64_t kDRegMask = UINT64_C(0xffffffffffffffff);
|
||||
const uint64_t kSSignMask = UINT64_C(0x80000000);
|
||||
const uint64_t kDSignMask = UINT64_C(0x8000000000000000);
|
||||
const uint64_t kWSignMask = UINT64_C(0x80000000);
|
||||
const uint64_t kXSignMask = UINT64_C(0x8000000000000000);
|
||||
const uint64_t kByteMask = UINT64_C(0xff);
|
||||
const uint64_t kHalfWordMask = UINT64_C(0xffff);
|
||||
const uint64_t kWordMask = UINT64_C(0xffffffff);
|
||||
const uint64_t kXMaxUInt = UINT64_C(0xffffffffffffffff);
|
||||
const uint64_t kWMaxUInt = UINT64_C(0xffffffff);
|
||||
const int64_t kXMaxInt = INT64_C(0x7fffffffffffffff);
|
||||
const int64_t kXMinInt = INT64_C(0x8000000000000000);
|
||||
const int32_t kWMaxInt = INT32_C(0x7fffffff);
|
||||
const int32_t kWMinInt = INT32_C(0x80000000);
|
||||
const unsigned kLinkRegCode = 30;
|
||||
const unsigned kZeroRegCode = 31;
|
||||
const unsigned kSPRegInternalCode = 63;
|
||||
@ -81,18 +87,28 @@ const unsigned kFloatExponentBits = 8;
|
||||
|
||||
const float kFP32PositiveInfinity = rawbits_to_float(0x7f800000);
|
||||
const float kFP32NegativeInfinity = rawbits_to_float(0xff800000);
|
||||
const double kFP64PositiveInfinity = rawbits_to_double(0x7ff0000000000000ULL);
|
||||
const double kFP64NegativeInfinity = rawbits_to_double(0xfff0000000000000ULL);
|
||||
const double kFP64PositiveInfinity =
|
||||
rawbits_to_double(UINT64_C(0x7ff0000000000000));
|
||||
const double kFP64NegativeInfinity =
|
||||
rawbits_to_double(UINT64_C(0xfff0000000000000));
|
||||
|
||||
// This value is a signalling NaN as both a double and as a float (taking the
|
||||
// least-significant word).
|
||||
static const double kFP64SignallingNaN = rawbits_to_double(0x7ff000007f800001ULL);
|
||||
static const double kFP64SignallingNaN =
|
||||
rawbits_to_double(UINT64_C(0x7ff000007f800001));
|
||||
static const float kFP32SignallingNaN = rawbits_to_float(0x7f800001);
|
||||
|
||||
// A similar value, but as a quiet NaN.
|
||||
static const double kFP64QuietNaN = rawbits_to_double(0x7ff800007fc00001ULL);
|
||||
static const double kFP64QuietNaN =
|
||||
rawbits_to_double(UINT64_C(0x7ff800007fc00001));
|
||||
static const float kFP32QuietNaN = rawbits_to_float(0x7fc00001);
|
||||
|
||||
// The default NaN values (for FPCR.DN=1).
|
||||
static const double kFP64DefaultNaN =
|
||||
rawbits_to_double(UINT64_C(0x7ff8000000000000));
|
||||
static const float kFP32DefaultNaN = rawbits_to_float(0x7fc00000);
|
||||
|
||||
|
||||
enum LSDataSize {
|
||||
LSByte = 0,
|
||||
LSHalfword = 1,
|
||||
@ -325,7 +341,7 @@ class Instruction {
|
||||
}
|
||||
|
||||
inline Instruction* InstructionAtOffset(int64_t offset) {
|
||||
ASSERT(IsWordAligned(this + offset));
|
||||
VIXL_ASSERT(IsWordAligned(this + offset));
|
||||
return this + offset;
|
||||
}
|
||||
|
||||
|
@ -27,8 +27,20 @@
|
||||
#ifndef VIXL_GLOBALS_H
|
||||
#define VIXL_GLOBALS_H
|
||||
|
||||
// Get the standard printf format macros for C99 stdint types.
|
||||
// Get standard C99 macros for integer types.
|
||||
#ifndef __STDC_CONSTANT_MACROS
|
||||
#define __STDC_CONSTANT_MACROS
|
||||
#endif
|
||||
|
||||
#ifndef __STDC_LIMIT_MACROS
|
||||
#define __STDC_LIMIT_MACROS
|
||||
#endif
|
||||
|
||||
#ifndef __STDC_FORMAT_MACROS
|
||||
#define __STDC_FORMAT_MACROS
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
#include <assert.h>
|
||||
@ -45,21 +57,29 @@ typedef uint8_t byte;
|
||||
const int KBytes = 1024;
|
||||
const int MBytes = 1024 * KBytes;
|
||||
|
||||
#define ABORT() printf("in %s, line %i", __FILE__, __LINE__); abort()
|
||||
#define VIXL_ABORT() printf("in %s, line %i", __FILE__, __LINE__); abort()
|
||||
#ifdef DEBUG
|
||||
#define ASSERT(condition) assert(condition)
|
||||
#define CHECK(condition) ASSERT(condition)
|
||||
#define UNIMPLEMENTED() printf("UNIMPLEMENTED\t"); ABORT()
|
||||
#define UNREACHABLE() printf("UNREACHABLE\t"); ABORT()
|
||||
#define VIXL_ASSERT(condition) assert(condition)
|
||||
#define VIXL_CHECK(condition) VIXL_ASSERT(condition)
|
||||
#define VIXL_UNIMPLEMENTED() printf("UNIMPLEMENTED\t"); VIXL_ABORT()
|
||||
#define VIXL_UNREACHABLE() printf("UNREACHABLE\t"); VIXL_ABORT()
|
||||
#else
|
||||
#define ASSERT(condition) ((void) 0)
|
||||
#define CHECK(condition) assert(condition)
|
||||
#define UNIMPLEMENTED() ((void) 0)
|
||||
#define UNREACHABLE() ((void) 0)
|
||||
#define VIXL_ASSERT(condition) ((void) 0)
|
||||
#define VIXL_CHECK(condition) assert(condition)
|
||||
#define VIXL_UNIMPLEMENTED() ((void) 0)
|
||||
#define VIXL_UNREACHABLE() ((void) 0)
|
||||
#endif
|
||||
// This is not as powerful as template based assertions, but it is simple.
|
||||
// It assumes that the descriptions are unique. If this starts being a problem,
|
||||
// we can switch to a different implemention.
|
||||
#define VIXL_CONCAT(a, b) a##b
|
||||
#define VIXL_STATIC_ASSERT_LINE(line, condition) \
|
||||
typedef char VIXL_CONCAT(STATIC_ASSERT_LINE_, line)[(condition) ? 1 : -1] \
|
||||
__attribute__((unused))
|
||||
#define VIXL_STATIC_ASSERT(condition) VIXL_STATIC_ASSERT_LINE(__LINE__, condition) //NOLINT
|
||||
|
||||
template <typename T> inline void USE(T) {}
|
||||
|
||||
#define ALIGNMENT_EXCEPTION() printf("ALIGNMENT EXCEPTION\t"); ABORT()
|
||||
#define VIXL_ALIGNMENT_EXCEPTION() printf("ALIGNMENT EXCEPTION\t"); VIXL_ABORT()
|
||||
|
||||
#endif // VIXL_GLOBALS_H
|
||||
|
@ -34,9 +34,7 @@ namespace vixl {
|
||||
// Currently we assume running the simulator implies running on x86 hardware.
|
||||
inline void HostBreakpoint() { asm("int3"); }
|
||||
#else
|
||||
inline void HostBreakpoint() {
|
||||
// TODO: Implement HostBreakpoint on a64.
|
||||
}
|
||||
inline void HostBreakpoint() { asm("brk"); }
|
||||
#endif
|
||||
} // namespace vixl
|
||||
|
||||
|
@ -58,9 +58,9 @@ double rawbits_to_double(uint64_t bits) {
|
||||
|
||||
|
||||
int CountLeadingZeros(uint64_t value, int width) {
|
||||
ASSERT((width == 32) || (width == 64));
|
||||
VIXL_ASSERT((width == 32) || (width == 64));
|
||||
int count = 0;
|
||||
uint64_t bit_test = 1UL << (width - 1);
|
||||
uint64_t bit_test = UINT64_C(1) << (width - 1);
|
||||
while ((count < width) && ((bit_test & value) == 0)) {
|
||||
count++;
|
||||
bit_test >>= 1;
|
||||
@ -70,7 +70,7 @@ int CountLeadingZeros(uint64_t value, int width) {
|
||||
|
||||
|
||||
int CountLeadingSignBits(int64_t value, int width) {
|
||||
ASSERT((width == 32) || (width == 64));
|
||||
VIXL_ASSERT((width == 32) || (width == 64));
|
||||
if (value >= 0) {
|
||||
return CountLeadingZeros(value, width) - 1;
|
||||
} else {
|
||||
@ -80,7 +80,7 @@ int CountLeadingSignBits(int64_t value, int width) {
|
||||
|
||||
|
||||
int CountTrailingZeros(uint64_t value, int width) {
|
||||
ASSERT((width == 32) || (width == 64));
|
||||
VIXL_ASSERT((width == 32) || (width == 64));
|
||||
int count = 0;
|
||||
while ((count < width) && (((value >> count) & 1) == 0)) {
|
||||
count++;
|
||||
@ -92,10 +92,10 @@ int CountTrailingZeros(uint64_t value, int width) {
|
||||
int CountSetBits(uint64_t value, int width) {
|
||||
// TODO: Other widths could be added here, as the implementation already
|
||||
// supports them.
|
||||
ASSERT((width == 32) || (width == 64));
|
||||
VIXL_ASSERT((width == 32) || (width == 64));
|
||||
|
||||
// Mask out unused bits to ensure that they are not counted.
|
||||
value &= (0xffffffffffffffffULL >> (64-width));
|
||||
value &= (UINT64_C(0xffffffffffffffff) >> (64-width));
|
||||
|
||||
// Add up the set bits.
|
||||
// The algorithm works by adding pairs of bit fields together iteratively,
|
||||
@ -108,18 +108,19 @@ int CountSetBits(uint64_t value, int width) {
|
||||
// value = h+g+f+e d+c+b+a
|
||||
// \ |
|
||||
// value = h+g+f+e+d+c+b+a
|
||||
value = ((value >> 1) & 0x5555555555555555ULL) +
|
||||
(value & 0x5555555555555555ULL);
|
||||
value = ((value >> 2) & 0x3333333333333333ULL) +
|
||||
(value & 0x3333333333333333ULL);
|
||||
value = ((value >> 4) & 0x0f0f0f0f0f0f0f0fULL) +
|
||||
(value & 0x0f0f0f0f0f0f0f0fULL);
|
||||
value = ((value >> 8) & 0x00ff00ff00ff00ffULL) +
|
||||
(value & 0x00ff00ff00ff00ffULL);
|
||||
value = ((value >> 16) & 0x0000ffff0000ffffULL) +
|
||||
(value & 0x0000ffff0000ffffULL);
|
||||
value = ((value >> 32) & 0x00000000ffffffffULL) +
|
||||
(value & 0x00000000ffffffffULL);
|
||||
const uint64_t kMasks[] = {
|
||||
UINT64_C(0x5555555555555555),
|
||||
UINT64_C(0x3333333333333333),
|
||||
UINT64_C(0x0f0f0f0f0f0f0f0f),
|
||||
UINT64_C(0x00ff00ff00ff00ff),
|
||||
UINT64_C(0x0000ffff0000ffff),
|
||||
UINT64_C(0x00000000ffffffff),
|
||||
};
|
||||
|
||||
for (unsigned i = 0; i < (sizeof(kMasks) / sizeof(kMasks[0])); i++) {
|
||||
int shift = 1 << i;
|
||||
value = ((value >> shift) & kMasks[i]) + (value & kMasks[i]);
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
@ -27,7 +27,7 @@
|
||||
#ifndef VIXL_UTILS_H
|
||||
#define VIXL_UTILS_H
|
||||
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
#include "globals.h"
|
||||
|
||||
@ -35,19 +35,19 @@ namespace vixl {
|
||||
|
||||
// Check number width.
|
||||
inline bool is_intn(unsigned n, int64_t x) {
|
||||
ASSERT((0 < n) && (n < 64));
|
||||
int64_t limit = 1ULL << (n - 1);
|
||||
VIXL_ASSERT((0 < n) && (n < 64));
|
||||
int64_t limit = INT64_C(1) << (n - 1);
|
||||
return (-limit <= x) && (x < limit);
|
||||
}
|
||||
|
||||
inline bool is_uintn(unsigned n, int64_t x) {
|
||||
ASSERT((0 < n) && (n < 64));
|
||||
VIXL_ASSERT((0 < n) && (n < 64));
|
||||
return !(x >> n);
|
||||
}
|
||||
|
||||
inline unsigned truncate_to_intn(unsigned n, int64_t x) {
|
||||
ASSERT((0 < n) && (n < 64));
|
||||
return (x & ((1ULL << n) - 1));
|
||||
VIXL_ASSERT((0 < n) && (n < 64));
|
||||
return (x & ((INT64_C(1) << n) - 1));
|
||||
}
|
||||
|
||||
#define INT_1_TO_63_LIST(V) \
|
||||
@ -90,13 +90,67 @@ inline int64_t signed_bitextract_64(int msb, int lsb, int64_t x) {
|
||||
return (x << (63 - msb)) >> (lsb + 63 - msb);
|
||||
}
|
||||
|
||||
// floating point representation
|
||||
// Floating point representation.
|
||||
uint32_t float_to_rawbits(float value);
|
||||
uint64_t double_to_rawbits(double value);
|
||||
float rawbits_to_float(uint32_t bits);
|
||||
double rawbits_to_double(uint64_t bits);
|
||||
|
||||
// Bits counting.
|
||||
|
||||
// NaN tests.
|
||||
inline bool IsSignallingNaN(double num) {
|
||||
const uint64_t kFP64QuietNaNMask = UINT64_C(0x0008000000000000);
|
||||
uint64_t raw = double_to_rawbits(num);
|
||||
if (isnan(num) && ((raw & kFP64QuietNaNMask) == 0)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
inline bool IsSignallingNaN(float num) {
|
||||
const uint32_t kFP32QuietNaNMask = 0x00400000;
|
||||
uint32_t raw = float_to_rawbits(num);
|
||||
if (isnan(num) && ((raw & kFP32QuietNaNMask) == 0)) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
template <typename T>
|
||||
inline bool IsQuietNaN(T num) {
|
||||
return isnan(num) && !IsSignallingNaN(num);
|
||||
}
|
||||
|
||||
|
||||
// Convert the NaN in 'num' to a quiet NaN.
|
||||
inline double ToQuietNaN(double num) {
|
||||
const uint64_t kFP64QuietNaNMask = UINT64_C(0x0008000000000000);
|
||||
VIXL_ASSERT(isnan(num));
|
||||
return rawbits_to_double(double_to_rawbits(num) | kFP64QuietNaNMask);
|
||||
}
|
||||
|
||||
|
||||
inline float ToQuietNaN(float num) {
|
||||
const uint32_t kFP32QuietNaNMask = 0x00400000;
|
||||
VIXL_ASSERT(isnan(num));
|
||||
return rawbits_to_float(float_to_rawbits(num) | kFP32QuietNaNMask);
|
||||
}
|
||||
|
||||
|
||||
// Fused multiply-add.
|
||||
inline double FusedMultiplyAdd(double op1, double op2, double a) {
|
||||
return fma(op1, op2, a);
|
||||
}
|
||||
|
||||
|
||||
inline float FusedMultiplyAdd(float op1, float op2, float a) {
|
||||
return fmaf(op1, op2, a);
|
||||
}
|
||||
|
||||
|
||||
// Bit counting.
|
||||
int CountLeadingZeros(uint64_t value, int width);
|
||||
int CountLeadingSignBits(int64_t value, int width);
|
||||
int CountTrailingZeros(uint64_t value, int width);
|
||||
@ -106,20 +160,30 @@ int CountSetBits(uint64_t value, int width);
|
||||
// TODO: rename/refactor to make it specific to instructions.
|
||||
template<typename T>
|
||||
bool IsWordAligned(T pointer) {
|
||||
ASSERT(sizeof(pointer) == sizeof(intptr_t)); // NOLINT(runtime/sizeof)
|
||||
VIXL_ASSERT(sizeof(pointer) == sizeof(intptr_t)); // NOLINT(runtime/sizeof)
|
||||
return (reinterpret_cast<intptr_t>(pointer) & 3) == 0;
|
||||
}
|
||||
|
||||
// Increment a pointer until it has the specified alignment.
|
||||
template<class T>
|
||||
T AlignUp(T pointer, size_t alignment) {
|
||||
ASSERT(sizeof(pointer) == sizeof(uintptr_t));
|
||||
VIXL_STATIC_ASSERT(sizeof(pointer) == sizeof(uintptr_t));
|
||||
uintptr_t pointer_raw = reinterpret_cast<uintptr_t>(pointer);
|
||||
size_t align_step = (alignment - pointer_raw) % alignment;
|
||||
ASSERT((pointer_raw + align_step) % alignment == 0);
|
||||
VIXL_ASSERT((pointer_raw + align_step) % alignment == 0);
|
||||
return reinterpret_cast<T>(pointer_raw + align_step);
|
||||
}
|
||||
|
||||
// Decrement a pointer until it has the specified alignment.
|
||||
template<class T>
|
||||
T AlignDown(T pointer, size_t alignment) {
|
||||
VIXL_STATIC_ASSERT(sizeof(pointer) == sizeof(uintptr_t));
|
||||
uintptr_t pointer_raw = reinterpret_cast<uintptr_t>(pointer);
|
||||
size_t align_step = pointer_raw % alignment;
|
||||
VIXL_ASSERT((pointer_raw - align_step) % alignment == 0);
|
||||
return reinterpret_cast<T>(pointer_raw - align_step);
|
||||
}
|
||||
|
||||
|
||||
} // namespace vixl
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user