summaryrefslogtreecommitdiff
path: root/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
diff options
context:
space:
mode:
authorDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
committerDimitry Andric <dim@FreeBSD.org>2021-07-29 20:15:26 +0000
commit344a3780b2e33f6ca763666c380202b18aab72a3 (patch)
treef0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
parentb60736ec1405bb0a8dd40989f67ef4c93da068ab (diff)
Diffstat (limited to 'llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp')
-rw-r--r--llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp104
1 files changed, 102 insertions, 2 deletions
diff --git a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
index e30123d64755..7fb5f35548b4 100644
--- a/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
+++ b/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
@@ -8,6 +8,7 @@
#include "CSKYAsmBackend.h"
#include "MCTargetDesc/CSKYMCTargetDesc.h"
+#include "llvm/ADT/DenseMap.h"
#include "llvm/MC/MCAsmLayout.h"
#include "llvm/MC/MCAssembler.h"
#include "llvm/MC/MCContext.h"
@@ -24,14 +25,113 @@ CSKYAsmBackend::createObjectTargetWriter() const {
return createCSKYELFObjectWriter();
}
-unsigned int CSKYAsmBackend::getNumFixupKinds() const { return 1; }
+const MCFixupKindInfo &
+CSKYAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
+
+ static llvm::DenseMap<unsigned, MCFixupKindInfo> Infos = {
+ {CSKY::Fixups::fixup_csky_addr32, {"fixup_csky_addr32", 0, 32, 0}},
+ {CSKY::Fixups::fixup_csky_pcrel_imm16_scale2,
+ {"fixup_csky_pcrel_imm16_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
+ {CSKY::Fixups::fixup_csky_pcrel_uimm16_scale4,
+ {"fixup_csky_pcrel_uimm16_scale4", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
+ {CSKY::Fixups::fixup_csky_pcrel_imm26_scale2,
+ {"fixup_csky_pcrel_imm26_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
+ {CSKY::Fixups::fixup_csky_pcrel_imm18_scale2,
+ {"fixup_csky_pcrel_imm18_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}}};
+ assert(Infos.size() == CSKY::NumTargetFixupKinds &&
+ "Not all fixup kinds added to Infos array");
+
+ assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
+ "Invalid kind!");
+ if (FirstTargetFixupKind <= Kind && Kind < FirstLiteralRelocationKind)
+ return Infos[Kind];
+ else if (Kind < FirstTargetFixupKind)
+ return MCAsmBackend::getFixupKindInfo(Kind);
+ else
+ return MCAsmBackend::getFixupKindInfo(FK_NONE);
+}
+
+static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
+ MCContext &Ctx) {
+ switch (Fixup.getTargetKind()) {
+ default:
+ llvm_unreachable("Unknown fixup kind!");
+ case FK_Data_1:
+ case FK_Data_2:
+ case FK_Data_4:
+ case FK_Data_8:
+ return Value;
+ case CSKY::fixup_csky_addr32:
+ return Value & 0xffffffff;
+ case CSKY::fixup_csky_pcrel_imm16_scale2:
+ if (!isIntN(17, Value))
+ Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
+ if (Value & 0x1)
+ Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
+
+ return (Value >> 1) & 0xffff;
+ case CSKY::fixup_csky_pcrel_uimm16_scale4:
+ if (!isUIntN(18, Value))
+ Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
+ if (Value & 0x3)
+ Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");
+
+ return (Value >> 2) & 0xffff;
+ case CSKY::fixup_csky_pcrel_imm26_scale2:
+ if (!isIntN(27, Value))
+ Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
+ if (Value & 0x1)
+ Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
+
+ return (Value >> 1) & 0x3ffffff;
+ case CSKY::fixup_csky_pcrel_imm18_scale2:
+ if (!isIntN(19, Value))
+ Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");
+ if (Value & 0x1)
+ Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");
+
+ return (Value >> 1) & 0x3ffff;
+ }
+}
void CSKYAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
const MCValue &Target,
MutableArrayRef<char> Data, uint64_t Value,
bool IsResolved,
const MCSubtargetInfo *STI) const {
- return;
+ MCFixupKind Kind = Fixup.getKind();
+ if (Kind >= FirstLiteralRelocationKind)
+ return;
+ MCContext &Ctx = Asm.getContext();
+ MCFixupKindInfo Info = getFixupKindInfo(Kind);
+ if (!Value)
+ return; // Doesn't change encoding.
+ // Apply any target-specific value adjustments.
+ Value = adjustFixupValue(Fixup, Value, Ctx);
+
+ // Shift the value into position.
+ Value <<= Info.TargetOffset;
+
+ unsigned Offset = Fixup.getOffset();
+ unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;
+
+ assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");
+
+ // For each byte of the fragment that the fixup touches, mask in the
+ // bits from the fixup value.
+ bool IsLittleEndian = (Endian == support::little);
+
+ if (IsLittleEndian && (NumBytes == 4)) {
+ Data[Offset + 0] |= uint8_t((Value >> 16) & 0xff);
+ Data[Offset + 1] |= uint8_t((Value >> 24) & 0xff);
+ Data[Offset + 2] |= uint8_t(Value & 0xff);
+ Data[Offset + 3] |= uint8_t((Value >> 8) & 0xff);
+ } else {
+ for (unsigned I = 0; I != NumBytes; I++) {
+ unsigned Idx = IsLittleEndian ? I : (NumBytes - 1 - I);
+ Data[Offset + Idx] |= uint8_t((Value >> (I * 8)) & 0xff);
+ }
+ }
}
bool CSKYAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,