blob: 978c5333cd5b00e33dff058254fc776797fb1a8f [file] [log] [blame]
//===- 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 <llvm/ADT/StringExtras.h>
#include <llvm/Support/ELF.h>
#include <cassert>
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