xref: /freebsd-src/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp (revision fe6060f10f634930ff71b7c50291ddc610da2475)
1e8d8bef9SDimitry Andric //===-- CSKYAsmBackend.cpp - CSKY Assembler Backend -----------------------===//
2e8d8bef9SDimitry Andric //
3e8d8bef9SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4e8d8bef9SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
5e8d8bef9SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6e8d8bef9SDimitry Andric //
7e8d8bef9SDimitry Andric //===----------------------------------------------------------------------===//
8e8d8bef9SDimitry Andric 
9e8d8bef9SDimitry Andric #include "CSKYAsmBackend.h"
10e8d8bef9SDimitry Andric #include "MCTargetDesc/CSKYMCTargetDesc.h"
11*fe6060f1SDimitry Andric #include "llvm/ADT/DenseMap.h"
12e8d8bef9SDimitry Andric #include "llvm/MC/MCAsmLayout.h"
13e8d8bef9SDimitry Andric #include "llvm/MC/MCAssembler.h"
14e8d8bef9SDimitry Andric #include "llvm/MC/MCContext.h"
15e8d8bef9SDimitry Andric #include "llvm/MC/MCFixupKindInfo.h"
16e8d8bef9SDimitry Andric #include "llvm/MC/MCObjectWriter.h"
17e8d8bef9SDimitry Andric #include "llvm/Support/Debug.h"
18e8d8bef9SDimitry Andric 
19e8d8bef9SDimitry Andric #define DEBUG_TYPE "csky-asmbackend"
20e8d8bef9SDimitry Andric 
21e8d8bef9SDimitry Andric using namespace llvm;
22e8d8bef9SDimitry Andric 
23e8d8bef9SDimitry Andric std::unique_ptr<MCObjectTargetWriter>
24e8d8bef9SDimitry Andric CSKYAsmBackend::createObjectTargetWriter() const {
25e8d8bef9SDimitry Andric   return createCSKYELFObjectWriter();
26e8d8bef9SDimitry Andric }
27e8d8bef9SDimitry Andric 
28*fe6060f1SDimitry Andric const MCFixupKindInfo &
29*fe6060f1SDimitry Andric CSKYAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
30*fe6060f1SDimitry Andric 
31*fe6060f1SDimitry Andric   static llvm::DenseMap<unsigned, MCFixupKindInfo> Infos = {
32*fe6060f1SDimitry Andric       {CSKY::Fixups::fixup_csky_addr32, {"fixup_csky_addr32", 0, 32, 0}},
33*fe6060f1SDimitry Andric       {CSKY::Fixups::fixup_csky_pcrel_imm16_scale2,
34*fe6060f1SDimitry Andric        {"fixup_csky_pcrel_imm16_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
35*fe6060f1SDimitry Andric       {CSKY::Fixups::fixup_csky_pcrel_uimm16_scale4,
36*fe6060f1SDimitry Andric        {"fixup_csky_pcrel_uimm16_scale4", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
37*fe6060f1SDimitry Andric       {CSKY::Fixups::fixup_csky_pcrel_imm26_scale2,
38*fe6060f1SDimitry Andric        {"fixup_csky_pcrel_imm26_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
39*fe6060f1SDimitry Andric       {CSKY::Fixups::fixup_csky_pcrel_imm18_scale2,
40*fe6060f1SDimitry Andric        {"fixup_csky_pcrel_imm18_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}}};
41*fe6060f1SDimitry Andric   assert(Infos.size() == CSKY::NumTargetFixupKinds &&
42*fe6060f1SDimitry Andric          "Not all fixup kinds added to Infos array");
43*fe6060f1SDimitry Andric 
44*fe6060f1SDimitry Andric   assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
45*fe6060f1SDimitry Andric          "Invalid kind!");
46*fe6060f1SDimitry Andric   if (FirstTargetFixupKind <= Kind && Kind < FirstLiteralRelocationKind)
47*fe6060f1SDimitry Andric     return Infos[Kind];
48*fe6060f1SDimitry Andric   else if (Kind < FirstTargetFixupKind)
49*fe6060f1SDimitry Andric     return MCAsmBackend::getFixupKindInfo(Kind);
50*fe6060f1SDimitry Andric   else
51*fe6060f1SDimitry Andric     return MCAsmBackend::getFixupKindInfo(FK_NONE);
52*fe6060f1SDimitry Andric }
53*fe6060f1SDimitry Andric 
54*fe6060f1SDimitry Andric static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
55*fe6060f1SDimitry Andric                                  MCContext &Ctx) {
56*fe6060f1SDimitry Andric   switch (Fixup.getTargetKind()) {
57*fe6060f1SDimitry Andric   default:
58*fe6060f1SDimitry Andric     llvm_unreachable("Unknown fixup kind!");
59*fe6060f1SDimitry Andric   case FK_Data_1:
60*fe6060f1SDimitry Andric   case FK_Data_2:
61*fe6060f1SDimitry Andric   case FK_Data_4:
62*fe6060f1SDimitry Andric   case FK_Data_8:
63*fe6060f1SDimitry Andric     return Value;
64*fe6060f1SDimitry Andric   case CSKY::fixup_csky_addr32:
65*fe6060f1SDimitry Andric     return Value & 0xffffffff;
66*fe6060f1SDimitry Andric   case CSKY::fixup_csky_pcrel_imm16_scale2:
67*fe6060f1SDimitry Andric     if (!isIntN(17, Value))
68*fe6060f1SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
69*fe6060f1SDimitry Andric     if (Value & 0x1)
70*fe6060f1SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
71*fe6060f1SDimitry Andric 
72*fe6060f1SDimitry Andric     return (Value >> 1) & 0xffff;
73*fe6060f1SDimitry Andric   case CSKY::fixup_csky_pcrel_uimm16_scale4:
74*fe6060f1SDimitry Andric     if (!isUIntN(18, Value))
75*fe6060f1SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
76*fe6060f1SDimitry Andric     if (Value & 0x3)
77*fe6060f1SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");
78*fe6060f1SDimitry Andric 
79*fe6060f1SDimitry Andric     return (Value >> 2) & 0xffff;
80*fe6060f1SDimitry Andric   case CSKY::fixup_csky_pcrel_imm26_scale2:
81*fe6060f1SDimitry Andric     if (!isIntN(27, Value))
82*fe6060f1SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
83*fe6060f1SDimitry Andric     if (Value & 0x1)
84*fe6060f1SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
85*fe6060f1SDimitry Andric 
86*fe6060f1SDimitry Andric     return (Value >> 1) & 0x3ffffff;
87*fe6060f1SDimitry Andric   case CSKY::fixup_csky_pcrel_imm18_scale2:
88*fe6060f1SDimitry Andric     if (!isIntN(19, Value))
89*fe6060f1SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
90*fe6060f1SDimitry Andric     if (Value & 0x1)
91*fe6060f1SDimitry Andric       Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
92*fe6060f1SDimitry Andric 
93*fe6060f1SDimitry Andric     return (Value >> 1) & 0x3ffff;
94*fe6060f1SDimitry Andric   }
95*fe6060f1SDimitry Andric }
96e8d8bef9SDimitry Andric 
97e8d8bef9SDimitry Andric void CSKYAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
98e8d8bef9SDimitry Andric                                 const MCValue &Target,
99e8d8bef9SDimitry Andric                                 MutableArrayRef<char> Data, uint64_t Value,
100e8d8bef9SDimitry Andric                                 bool IsResolved,
101e8d8bef9SDimitry Andric                                 const MCSubtargetInfo *STI) const {
102*fe6060f1SDimitry Andric   MCFixupKind Kind = Fixup.getKind();
103*fe6060f1SDimitry Andric   if (Kind >= FirstLiteralRelocationKind)
104e8d8bef9SDimitry Andric     return;
105*fe6060f1SDimitry Andric   MCContext &Ctx = Asm.getContext();
106*fe6060f1SDimitry Andric   MCFixupKindInfo Info = getFixupKindInfo(Kind);
107*fe6060f1SDimitry Andric   if (!Value)
108*fe6060f1SDimitry Andric     return; // Doesn't change encoding.
109*fe6060f1SDimitry Andric   // Apply any target-specific value adjustments.
110*fe6060f1SDimitry Andric   Value = adjustFixupValue(Fixup, Value, Ctx);
111*fe6060f1SDimitry Andric 
112*fe6060f1SDimitry Andric   // Shift the value into position.
113*fe6060f1SDimitry Andric   Value <<= Info.TargetOffset;
114*fe6060f1SDimitry Andric 
115*fe6060f1SDimitry Andric   unsigned Offset = Fixup.getOffset();
116*fe6060f1SDimitry Andric   unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;
117*fe6060f1SDimitry Andric 
118*fe6060f1SDimitry Andric   assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
119*fe6060f1SDimitry Andric 
120*fe6060f1SDimitry Andric   // For each byte of the fragment that the fixup touches, mask in the
121*fe6060f1SDimitry Andric   // bits from the fixup value.
122*fe6060f1SDimitry Andric   bool IsLittleEndian = (Endian == support::little);
123*fe6060f1SDimitry Andric 
124*fe6060f1SDimitry Andric   if (IsLittleEndian && (NumBytes == 4)) {
125*fe6060f1SDimitry Andric     Data[Offset + 0] |= uint8_t((Value >> 16) & 0xff);
126*fe6060f1SDimitry Andric     Data[Offset + 1] |= uint8_t((Value >> 24) & 0xff);
127*fe6060f1SDimitry Andric     Data[Offset + 2] |= uint8_t(Value & 0xff);
128*fe6060f1SDimitry Andric     Data[Offset + 3] |= uint8_t((Value >> 8) & 0xff);
129*fe6060f1SDimitry Andric   } else {
130*fe6060f1SDimitry Andric     for (unsigned I = 0; I != NumBytes; I++) {
131*fe6060f1SDimitry Andric       unsigned Idx = IsLittleEndian ? I : (NumBytes - 1 - I);
132*fe6060f1SDimitry Andric       Data[Offset + Idx] |= uint8_t((Value >> (I * 8)) & 0xff);
133*fe6060f1SDimitry Andric     }
134*fe6060f1SDimitry Andric   }
135e8d8bef9SDimitry Andric }
136e8d8bef9SDimitry Andric 
137e8d8bef9SDimitry Andric bool CSKYAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
138e8d8bef9SDimitry Andric                                           const MCRelaxableFragment *DF,
139e8d8bef9SDimitry Andric                                           const MCAsmLayout &Layout) const {
140e8d8bef9SDimitry Andric   return false;
141e8d8bef9SDimitry Andric }
142e8d8bef9SDimitry Andric 
143e8d8bef9SDimitry Andric void CSKYAsmBackend::relaxInstruction(MCInst &Inst,
144e8d8bef9SDimitry Andric                                       const MCSubtargetInfo &STI) const {
145e8d8bef9SDimitry Andric   llvm_unreachable("CSKYAsmBackend::relaxInstruction() unimplemented");
146e8d8bef9SDimitry Andric }
147e8d8bef9SDimitry Andric 
148e8d8bef9SDimitry Andric bool CSKYAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const {
149e8d8bef9SDimitry Andric   if (Count % 2)
150e8d8bef9SDimitry Andric     return false;
151e8d8bef9SDimitry Andric 
152e8d8bef9SDimitry Andric   // MOV32 r0, r0
153e8d8bef9SDimitry Andric   while (Count >= 4) {
154e8d8bef9SDimitry Andric     OS.write("\xc4\x00\x48\x20", 4);
155e8d8bef9SDimitry Andric     Count -= 4;
156e8d8bef9SDimitry Andric   }
157e8d8bef9SDimitry Andric   // MOV16 r0, r0
158e8d8bef9SDimitry Andric   if (Count)
159e8d8bef9SDimitry Andric     OS.write("\x6c\x03", 2);
160e8d8bef9SDimitry Andric 
161e8d8bef9SDimitry Andric   return true;
162e8d8bef9SDimitry Andric }
163e8d8bef9SDimitry Andric 
164e8d8bef9SDimitry Andric MCAsmBackend *llvm::createCSKYAsmBackend(const Target &T,
165e8d8bef9SDimitry Andric                                          const MCSubtargetInfo &STI,
166e8d8bef9SDimitry Andric                                          const MCRegisterInfo &MRI,
167e8d8bef9SDimitry Andric                                          const MCTargetOptions &Options) {
168e8d8bef9SDimitry Andric   return new CSKYAsmBackend(STI, Options);
169e8d8bef9SDimitry Andric }
170