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