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