//===- AArch64CA53Erratum843419Stub.cpp -----------------------------------===// // // The MCLinker Project // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// #include "AArch64CA53Erratum843419Stub.h" #include "AArch64InsnHelpers.h" #include "mcld/Fragment/FragmentRef.h" #include "mcld/Fragment/Relocation.h" #include "mcld/IRBuilder.h" #include "mcld/LD/BranchIsland.h" #include "mcld/LD/LDSection.h" #include "mcld/LD/LDSymbol.h" #include "mcld/LD/ResolveInfo.h" #include "mcld/LD/SectionData.h" #include #include #include namespace mcld { //===----------------------------------------------------------------------===// // AArch64CA53Erratum843419Stub //===----------------------------------------------------------------------===// AArch64CA53Erratum843419Stub::AArch64CA53Erratum843419Stub() { } /// for doClone AArch64CA53Erratum843419Stub::AArch64CA53Erratum843419Stub( const uint32_t* pData, size_t pSize, const char* pName, const_fixup_iterator pBegin, const_fixup_iterator pEnd) : AArch64CA53ErratumStub(pData, pSize, pName, pBegin, pEnd) { } AArch64CA53Erratum843419Stub::~AArch64CA53Erratum843419Stub() { } bool AArch64CA53Erratum843419Stub::isErratum843419Sequence(unsigned insn1, unsigned insn2, unsigned insn3) { unsigned rt; unsigned rt2; bool is_pair; bool is_load; return AArch64InsnHelpers::isMemOp(insn2, rt, rt2, is_pair, is_load) && (!is_pair || (is_pair && !is_load)) && AArch64InsnHelpers::isLDSTUIMM(insn3) && (AArch64InsnHelpers::getRn(insn3) == AArch64InsnHelpers::getRd(insn1)); } bool AArch64CA53Erratum843419Stub::isMyDuty(const FragmentRef& pFragRef) const { if ((pFragRef.offset() + AArch64InsnHelpers::InsnSize * 3) > pFragRef.frag()->size()) { return false; } // The first instruction must be ending at 0xFF8 or 0xFFC. const uint64_t vma = pFragRef.frag()->getParent()->getSection().addr() + pFragRef.getOutputOffset(); const unsigned page_offset = (vma & 0xFFF); if ((page_offset != 0xFF8) && (page_offset != 0xFFC)) { return false; } ErratumSequence code; pFragRef.memcpy(&code, AArch64InsnHelpers::InsnSize * 3, 0); if (isErratum843419Sequence(code.insns[0], code.insns[1], code.insns[2])) { return true; } return false; } Stub* AArch64CA53Erratum843419Stub::doClone() { return new AArch64CA53Erratum843419Stub(getData(), size(), "erratum_843419_veneer", fixup_begin(), fixup_end()); } } // namespace mcld