1 //===- AArch64CA53Erratum835769Stub.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 "AArch64CA53Erratum835769Stub.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/LDSymbol.h"
18 #include "mcld/LD/ResolveInfo.h"
19 
20 #include <llvm/ADT/StringExtras.h>
21 #include <llvm/Support/ELF.h>
22 
23 #include <cassert>
24 
25 namespace mcld {
26 
27 //===----------------------------------------------------------------------===//
28 // AArch64CA53Erratum835769Stub
29 //===----------------------------------------------------------------------===//
AArch64CA53Erratum835769Stub()30 AArch64CA53Erratum835769Stub::AArch64CA53Erratum835769Stub() {
31 }
32 
33 /// for doClone
AArch64CA53Erratum835769Stub(const uint32_t * pData,size_t pSize,const char * pName,const_fixup_iterator pBegin,const_fixup_iterator pEnd)34 AArch64CA53Erratum835769Stub::AArch64CA53Erratum835769Stub(
35     const uint32_t* pData,
36     size_t pSize,
37     const char* pName,
38     const_fixup_iterator pBegin,
39     const_fixup_iterator pEnd)
40     : AArch64CA53ErratumStub(pData, pSize, pName, pBegin, pEnd) {
41 }
42 
~AArch64CA53Erratum835769Stub()43 AArch64CA53Erratum835769Stub::~AArch64CA53Erratum835769Stub() {
44 }
45 
isMyDuty(const FragmentRef & pFragRef) const46 bool AArch64CA53Erratum835769Stub::isMyDuty(const FragmentRef& pFragRef) const {
47   unsigned rt;
48   unsigned rt2;
49   bool is_pair;
50   bool is_load;
51   ErratumSequence code;
52   pFragRef.memcpy(&code, sizeof(ErratumSequence), 0);
53 
54   if (AArch64InsnHelpers::isMLXL(code.insns[1]) &&
55       AArch64InsnHelpers::isMemOp(code.insns[0], rt, rt2, is_pair, is_load)) {
56     // Any SIMD memory op is independent of the subsequent MLA by definition of
57     // the erratum.
58     if (AArch64InsnHelpers::getBit(code.insns[0], 26) != 0) {
59       return true;
60     }
61 
62     // If not SIMD, check for integer memory ops and MLA relationship.
63     unsigned ra = AArch64InsnHelpers::getRa(code.insns[1]);
64     unsigned rm = AArch64InsnHelpers::getRm(code.insns[1]);
65     unsigned rn = AArch64InsnHelpers::getRn(code.insns[1]);
66 
67     // If this is a load and there's a true(RAW) dependency, we are safe and
68     // this is not an erratum sequence.
69     if (is_load &&
70         ((rt == ra) ||
71          (rt == rm) ||
72          (rt == rn) ||
73          (is_pair && ((rt2 == ra) || (rt2 == rm) || (rt2 == rn))))) {
74       return false;
75     }
76 
77     // We conservatively put out stubs for all other cases (including
78     // writebacks).
79     return true;
80   }
81 
82   return false;
83 }
84 
doClone()85 Stub* AArch64CA53Erratum835769Stub::doClone() {
86   return new AArch64CA53Erratum835769Stub(getData(),
87                                           size(),
88                                           "erratum_835769_veneer",
89                                           fixup_begin(),
90                                           fixup_end());
91 }
92 
93 }  // namespace mcld
94