diff options
| author | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
|---|---|---|
| committer | Dimitry Andric <dim@FreeBSD.org> | 2021-07-29 20:15:26 +0000 |
| commit | 344a3780b2e33f6ca763666c380202b18aab72a3 (patch) | |
| tree | f0b203ee6eb71d7fdd792373e3c81eb18d6934dd /llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp | |
| parent | b60736ec1405bb0a8dd40989f67ef4c93da068ab (diff) | |
vendor/llvm-project/llvmorg-13-init-16847-g88e66fa60ae5vendor/llvm-project/llvmorg-12.0.1-rc2-0-ge7dac564cd0evendor/llvm-project/llvmorg-12.0.1-0-gfed41342a82f
Diffstat (limited to 'llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp')
| -rw-r--r-- | llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp | 104 |
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, |
