xref: /aosp_15_r20/external/llvm/lib/Target/Lanai/MCTargetDesc/LanaiAsmBackend.cpp (revision 9880d6810fe72a1726cb53787c6711e909410d58)
1*9880d681SAndroid Build Coastguard Worker //===-- LanaiAsmBackend.cpp - Lanai Assembler Backend ---------------------===//
2*9880d681SAndroid Build Coastguard Worker //
3*9880d681SAndroid Build Coastguard Worker //                     The LLVM Compiler Infrastructure
4*9880d681SAndroid Build Coastguard Worker //
5*9880d681SAndroid Build Coastguard Worker // This file is distributed under the University of Illinois Open Source
6*9880d681SAndroid Build Coastguard Worker // License. See LICENSE.TXT for details.
7*9880d681SAndroid Build Coastguard Worker //
8*9880d681SAndroid Build Coastguard Worker //===----------------------------------------------------------------------===//
9*9880d681SAndroid Build Coastguard Worker 
10*9880d681SAndroid Build Coastguard Worker #include "LanaiFixupKinds.h"
11*9880d681SAndroid Build Coastguard Worker #include "MCTargetDesc/LanaiMCTargetDesc.h"
12*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAsmBackend.h"
13*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCAssembler.h"
14*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCDirectives.h"
15*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCELFObjectWriter.h"
16*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCFixupKindInfo.h"
17*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCObjectWriter.h"
18*9880d681SAndroid Build Coastguard Worker #include "llvm/MC/MCSubtargetInfo.h"
19*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/ErrorHandling.h"
20*9880d681SAndroid Build Coastguard Worker #include "llvm/Support/raw_ostream.h"
21*9880d681SAndroid Build Coastguard Worker 
22*9880d681SAndroid Build Coastguard Worker using namespace llvm;
23*9880d681SAndroid Build Coastguard Worker 
24*9880d681SAndroid Build Coastguard Worker // Prepare value for the target space
adjustFixupValue(unsigned Kind,uint64_t Value)25*9880d681SAndroid Build Coastguard Worker static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) {
26*9880d681SAndroid Build Coastguard Worker   switch (Kind) {
27*9880d681SAndroid Build Coastguard Worker   case FK_Data_1:
28*9880d681SAndroid Build Coastguard Worker   case FK_Data_2:
29*9880d681SAndroid Build Coastguard Worker   case FK_Data_4:
30*9880d681SAndroid Build Coastguard Worker   case FK_Data_8:
31*9880d681SAndroid Build Coastguard Worker     return Value;
32*9880d681SAndroid Build Coastguard Worker   case Lanai::FIXUP_LANAI_21:
33*9880d681SAndroid Build Coastguard Worker   case Lanai::FIXUP_LANAI_21_F:
34*9880d681SAndroid Build Coastguard Worker   case Lanai::FIXUP_LANAI_25:
35*9880d681SAndroid Build Coastguard Worker   case Lanai::FIXUP_LANAI_32:
36*9880d681SAndroid Build Coastguard Worker   case Lanai::FIXUP_LANAI_HI16:
37*9880d681SAndroid Build Coastguard Worker   case Lanai::FIXUP_LANAI_LO16:
38*9880d681SAndroid Build Coastguard Worker     return Value;
39*9880d681SAndroid Build Coastguard Worker   default:
40*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("Unknown fixup kind!");
41*9880d681SAndroid Build Coastguard Worker   }
42*9880d681SAndroid Build Coastguard Worker }
43*9880d681SAndroid Build Coastguard Worker 
44*9880d681SAndroid Build Coastguard Worker namespace {
45*9880d681SAndroid Build Coastguard Worker class LanaiAsmBackend : public MCAsmBackend {
46*9880d681SAndroid Build Coastguard Worker   Triple::OSType OSType;
47*9880d681SAndroid Build Coastguard Worker 
48*9880d681SAndroid Build Coastguard Worker public:
LanaiAsmBackend(const Target & T,Triple::OSType OST)49*9880d681SAndroid Build Coastguard Worker   LanaiAsmBackend(const Target &T, Triple::OSType OST)
50*9880d681SAndroid Build Coastguard Worker       : MCAsmBackend(), OSType(OST) {}
51*9880d681SAndroid Build Coastguard Worker 
52*9880d681SAndroid Build Coastguard Worker   void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
53*9880d681SAndroid Build Coastguard Worker                   uint64_t Value, bool IsPCRel) const override;
54*9880d681SAndroid Build Coastguard Worker 
55*9880d681SAndroid Build Coastguard Worker   MCObjectWriter *createObjectWriter(raw_pwrite_stream &OS) const override;
56*9880d681SAndroid Build Coastguard Worker 
57*9880d681SAndroid Build Coastguard Worker   // No instruction requires relaxation
fixupNeedsRelaxation(const MCFixup & Fixup,uint64_t Value,const MCRelaxableFragment * DF,const MCAsmLayout & Layout) const58*9880d681SAndroid Build Coastguard Worker   bool fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
59*9880d681SAndroid Build Coastguard Worker                             const MCRelaxableFragment *DF,
60*9880d681SAndroid Build Coastguard Worker                             const MCAsmLayout &Layout) const override {
61*9880d681SAndroid Build Coastguard Worker     return false;
62*9880d681SAndroid Build Coastguard Worker   }
63*9880d681SAndroid Build Coastguard Worker 
64*9880d681SAndroid Build Coastguard Worker   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const override;
65*9880d681SAndroid Build Coastguard Worker 
getNumFixupKinds() const66*9880d681SAndroid Build Coastguard Worker   unsigned getNumFixupKinds() const override {
67*9880d681SAndroid Build Coastguard Worker     return Lanai::NumTargetFixupKinds;
68*9880d681SAndroid Build Coastguard Worker   }
69*9880d681SAndroid Build Coastguard Worker 
mayNeedRelaxation(const MCInst & Inst) const70*9880d681SAndroid Build Coastguard Worker   bool mayNeedRelaxation(const MCInst &Inst) const override { return false; }
71*9880d681SAndroid Build Coastguard Worker 
relaxInstruction(const MCInst & Inst,const MCSubtargetInfo & STI,MCInst & Res) const72*9880d681SAndroid Build Coastguard Worker   void relaxInstruction(const MCInst &Inst, const MCSubtargetInfo &STI,
73*9880d681SAndroid Build Coastguard Worker                         MCInst &Res) const override {}
74*9880d681SAndroid Build Coastguard Worker 
75*9880d681SAndroid Build Coastguard Worker   bool writeNopData(uint64_t Count, MCObjectWriter *OW) const override;
76*9880d681SAndroid Build Coastguard Worker };
77*9880d681SAndroid Build Coastguard Worker 
writeNopData(uint64_t Count,MCObjectWriter * OW) const78*9880d681SAndroid Build Coastguard Worker bool LanaiAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
79*9880d681SAndroid Build Coastguard Worker   if ((Count % 4) != 0)
80*9880d681SAndroid Build Coastguard Worker     return false;
81*9880d681SAndroid Build Coastguard Worker 
82*9880d681SAndroid Build Coastguard Worker   for (uint64_t i = 0; i < Count; i += 4)
83*9880d681SAndroid Build Coastguard Worker     OW->write32(0x15000000);
84*9880d681SAndroid Build Coastguard Worker 
85*9880d681SAndroid Build Coastguard Worker   return true;
86*9880d681SAndroid Build Coastguard Worker }
87*9880d681SAndroid Build Coastguard Worker 
applyFixup(const MCFixup & Fixup,char * Data,unsigned DataSize,uint64_t Value,bool IsPCRel) const88*9880d681SAndroid Build Coastguard Worker void LanaiAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
89*9880d681SAndroid Build Coastguard Worker                                  unsigned DataSize, uint64_t Value,
90*9880d681SAndroid Build Coastguard Worker                                  bool IsPCRel) const {
91*9880d681SAndroid Build Coastguard Worker   MCFixupKind Kind = Fixup.getKind();
92*9880d681SAndroid Build Coastguard Worker   Value = adjustFixupValue(static_cast<unsigned>(Kind), Value);
93*9880d681SAndroid Build Coastguard Worker 
94*9880d681SAndroid Build Coastguard Worker   if (!Value)
95*9880d681SAndroid Build Coastguard Worker     return; // This value doesn't change the encoding
96*9880d681SAndroid Build Coastguard Worker 
97*9880d681SAndroid Build Coastguard Worker   // Where in the object and where the number of bytes that need
98*9880d681SAndroid Build Coastguard Worker   // fixing up
99*9880d681SAndroid Build Coastguard Worker   unsigned Offset = Fixup.getOffset();
100*9880d681SAndroid Build Coastguard Worker   unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8;
101*9880d681SAndroid Build Coastguard Worker   unsigned FullSize = 4;
102*9880d681SAndroid Build Coastguard Worker 
103*9880d681SAndroid Build Coastguard Worker   // Grab current value, if any, from bits.
104*9880d681SAndroid Build Coastguard Worker   uint64_t CurVal = 0;
105*9880d681SAndroid Build Coastguard Worker 
106*9880d681SAndroid Build Coastguard Worker   // Load instruction and apply value
107*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i != NumBytes; ++i) {
108*9880d681SAndroid Build Coastguard Worker     unsigned Idx = (FullSize - 1 - i);
109*9880d681SAndroid Build Coastguard Worker     CurVal |= static_cast<uint64_t>(static_cast<uint8_t>(Data[Offset + Idx]))
110*9880d681SAndroid Build Coastguard Worker               << (i * 8);
111*9880d681SAndroid Build Coastguard Worker   }
112*9880d681SAndroid Build Coastguard Worker 
113*9880d681SAndroid Build Coastguard Worker   uint64_t Mask =
114*9880d681SAndroid Build Coastguard Worker       (static_cast<uint64_t>(-1) >> (64 - getFixupKindInfo(Kind).TargetSize));
115*9880d681SAndroid Build Coastguard Worker   CurVal |= Value & Mask;
116*9880d681SAndroid Build Coastguard Worker 
117*9880d681SAndroid Build Coastguard Worker   // Write out the fixed up bytes back to the code/data bits.
118*9880d681SAndroid Build Coastguard Worker   for (unsigned i = 0; i != NumBytes; ++i) {
119*9880d681SAndroid Build Coastguard Worker     unsigned Idx = (FullSize - 1 - i);
120*9880d681SAndroid Build Coastguard Worker     Data[Offset + Idx] = static_cast<uint8_t>((CurVal >> (i * 8)) & 0xff);
121*9880d681SAndroid Build Coastguard Worker   }
122*9880d681SAndroid Build Coastguard Worker }
123*9880d681SAndroid Build Coastguard Worker 
124*9880d681SAndroid Build Coastguard Worker MCObjectWriter *
createObjectWriter(raw_pwrite_stream & OS) const125*9880d681SAndroid Build Coastguard Worker LanaiAsmBackend::createObjectWriter(raw_pwrite_stream &OS) const {
126*9880d681SAndroid Build Coastguard Worker   return createLanaiELFObjectWriter(OS,
127*9880d681SAndroid Build Coastguard Worker                                     MCELFObjectTargetWriter::getOSABI(OSType));
128*9880d681SAndroid Build Coastguard Worker }
129*9880d681SAndroid Build Coastguard Worker 
130*9880d681SAndroid Build Coastguard Worker const MCFixupKindInfo &
getFixupKindInfo(MCFixupKind Kind) const131*9880d681SAndroid Build Coastguard Worker LanaiAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
132*9880d681SAndroid Build Coastguard Worker   static const MCFixupKindInfo Infos[Lanai::NumTargetFixupKinds] = {
133*9880d681SAndroid Build Coastguard Worker       // This table *must* be in same the order of fixup_* kinds in
134*9880d681SAndroid Build Coastguard Worker       // LanaiFixupKinds.h.
135*9880d681SAndroid Build Coastguard Worker       // Note: The number of bits indicated here are assumed to be contiguous.
136*9880d681SAndroid Build Coastguard Worker       //   This does not hold true for LANAI_21 and LANAI_21_F which are applied
137*9880d681SAndroid Build Coastguard Worker       //   to bits 0x7cffff and 0x7cfffc, respectively. Since the 'bits' counts
138*9880d681SAndroid Build Coastguard Worker       //   here are used only for cosmetic purposes, we set the size to 16 bits
139*9880d681SAndroid Build Coastguard Worker       //   for these 21-bit relocation as llvm/lib/MC/MCAsmStreamer.cpp checks
140*9880d681SAndroid Build Coastguard Worker       //   no bits are set in the fixup range.
141*9880d681SAndroid Build Coastguard Worker       //
142*9880d681SAndroid Build Coastguard Worker       // name          offset bits flags
143*9880d681SAndroid Build Coastguard Worker       {"FIXUP_LANAI_NONE", 0, 32, 0},
144*9880d681SAndroid Build Coastguard Worker       {"FIXUP_LANAI_21", 16, 16 /*21*/, 0},
145*9880d681SAndroid Build Coastguard Worker       {"FIXUP_LANAI_21_F", 16, 16 /*21*/, 0},
146*9880d681SAndroid Build Coastguard Worker       {"FIXUP_LANAI_25", 7, 25, 0},
147*9880d681SAndroid Build Coastguard Worker       {"FIXUP_LANAI_32", 0, 32, 0},
148*9880d681SAndroid Build Coastguard Worker       {"FIXUP_LANAI_HI16", 16, 16, 0},
149*9880d681SAndroid Build Coastguard Worker       {"FIXUP_LANAI_LO16", 16, 16, 0}};
150*9880d681SAndroid Build Coastguard Worker 
151*9880d681SAndroid Build Coastguard Worker   if (Kind < FirstTargetFixupKind)
152*9880d681SAndroid Build Coastguard Worker     return MCAsmBackend::getFixupKindInfo(Kind);
153*9880d681SAndroid Build Coastguard Worker 
154*9880d681SAndroid Build Coastguard Worker   assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
155*9880d681SAndroid Build Coastguard Worker          "Invalid kind!");
156*9880d681SAndroid Build Coastguard Worker   return Infos[Kind - FirstTargetFixupKind];
157*9880d681SAndroid Build Coastguard Worker }
158*9880d681SAndroid Build Coastguard Worker 
159*9880d681SAndroid Build Coastguard Worker } // namespace
160*9880d681SAndroid Build Coastguard Worker 
createLanaiAsmBackend(const Target & T,const MCRegisterInfo & MRI,const Triple & TheTriple,StringRef CPU)161*9880d681SAndroid Build Coastguard Worker MCAsmBackend *llvm::createLanaiAsmBackend(const Target &T,
162*9880d681SAndroid Build Coastguard Worker                                           const MCRegisterInfo &MRI,
163*9880d681SAndroid Build Coastguard Worker                                           const Triple &TheTriple,
164*9880d681SAndroid Build Coastguard Worker                                           StringRef CPU) {
165*9880d681SAndroid Build Coastguard Worker   if (!TheTriple.isOSBinFormatELF())
166*9880d681SAndroid Build Coastguard Worker     llvm_unreachable("OS not supported");
167*9880d681SAndroid Build Coastguard Worker 
168*9880d681SAndroid Build Coastguard Worker   return new LanaiAsmBackend(T, TheTriple.getOS());
169*9880d681SAndroid Build Coastguard Worker }
170