AArch64CA53Erratum843419Stub.cpp revision cfcb22478ca64c308df58f9abe6fa2dedb213c16
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
27namespace mcld {
28
29//===----------------------------------------------------------------------===//
30// AArch64CA53Erratum843419Stub
31//===----------------------------------------------------------------------===//
32AArch64CA53Erratum843419Stub::AArch64CA53Erratum843419Stub() {
33}
34
35/// for doClone
36AArch64CA53Erratum843419Stub::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
45AArch64CA53Erratum843419Stub::~AArch64CA53Erratum843419Stub() {
46}
47
48bool 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
61bool 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
85Stub* 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