1cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines//===- AArch64CA53Erratum843419Stub.cpp -----------------------------------===// 2cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// 3cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// The MCLinker Project 4cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// 5cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// This file is distributed under the University of Illinois Open Source 6cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// License. See LICENSE.TXT for details. 7cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// 8cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines//===----------------------------------------------------------------------===// 9cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 10cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "AArch64CA53Erratum843419Stub.h" 11cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "AArch64InsnHelpers.h" 12cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 13cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/Fragment/FragmentRef.h" 14cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/Fragment/Relocation.h" 15cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/IRBuilder.h" 16cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/LD/BranchIsland.h" 17cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/LD/LDSection.h" 18cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/LD/LDSymbol.h" 19cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/LD/ResolveInfo.h" 20cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include "mcld/LD/SectionData.h" 21cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 22cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include <llvm/ADT/StringExtras.h> 23cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include <llvm/Support/ELF.h> 24cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 25cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines#include <cassert> 26cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 27cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesnamespace mcld { 28cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 29cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines//===----------------------------------------------------------------------===// 30cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines// AArch64CA53Erratum843419Stub 31cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines//===----------------------------------------------------------------------===// 32cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen HinesAArch64CA53Erratum843419Stub::AArch64CA53Erratum843419Stub() { 33cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 34cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 35cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines/// for doClone 36cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen HinesAArch64CA53Erratum843419Stub::AArch64CA53Erratum843419Stub( 37cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines const uint32_t* pData, 38cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines size_t pSize, 39cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines const char* pName, 40cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines const_fixup_iterator pBegin, 41cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines const_fixup_iterator pEnd) 42cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines : AArch64CA53ErratumStub(pData, pSize, pName, pBegin, pEnd) { 43cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 44cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 45cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen HinesAArch64CA53Erratum843419Stub::~AArch64CA53Erratum843419Stub() { 46cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 47cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 48cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesbool AArch64CA53Erratum843419Stub::isErratum843419Sequence(unsigned insn1, 49cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines unsigned insn2, 50cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines unsigned insn3) { 51cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines unsigned rt; 52cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines unsigned rt2; 53cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines bool is_pair; 54cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines bool is_load; 55cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return AArch64InsnHelpers::isMemOp(insn2, rt, rt2, is_pair, is_load) && 56cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines (!is_pair || (is_pair && !is_load)) && 57cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines AArch64InsnHelpers::isLDSTUIMM(insn3) && 58cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines (AArch64InsnHelpers::getRn(insn3) == AArch64InsnHelpers::getRd(insn1)); 59cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 60cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 61cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hinesbool AArch64CA53Erratum843419Stub::isMyDuty(const FragmentRef& pFragRef) const { 62cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if ((pFragRef.offset() + AArch64InsnHelpers::InsnSize * 3) > 63cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines pFragRef.frag()->size()) { 64cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return false; 65cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 66cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 67cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines // The first instruction must be ending at 0xFF8 or 0xFFC. 68cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines const uint64_t vma = pFragRef.frag()->getParent()->getSection().addr() + 69cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines pFragRef.getOutputOffset(); 70cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines const unsigned page_offset = (vma & 0xFFF); 71cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if ((page_offset != 0xFF8) && (page_offset != 0xFFC)) { 72cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return false; 73cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 74cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 75cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines ErratumSequence code; 76cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines pFragRef.memcpy(&code, AArch64InsnHelpers::InsnSize * 3, 0); 77cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 78cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines if (isErratum843419Sequence(code.insns[0], code.insns[1], code.insns[2])) { 79cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return true; 80cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines } 81cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 82cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return false; 83cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 84cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 85cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen HinesStub* AArch64CA53Erratum843419Stub::doClone() { 86cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines return new AArch64CA53Erratum843419Stub(getData(), 87cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines size(), 88cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines "erratum_843419_veneer", 89cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines fixup_begin(), 90cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines fixup_end()); 91cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} 92cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines 93cfcb22478ca64c308df58f9abe6fa2dedb213c16Stephen Hines} // namespace mcld 94