aboutsummaryrefslogtreecommitdiff
path: root/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp')
-rw-r--r--contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp358
1 files changed, 358 insertions, 0 deletions
diff --git a/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp b/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
new file mode 100644
index 000000000000..4171a97e9000
--- /dev/null
+++ b/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
@@ -0,0 +1,358 @@
+//===-- CSKYAsmBackend.cpp - CSKY Assembler Backend -----------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#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"
+#include "llvm/MC/MCFixupKindInfo.h"
+#include "llvm/MC/MCObjectWriter.h"
+#include "llvm/Support/Debug.h"
+
+#define DEBUG_TYPE "csky-asmbackend"
+
+using namespace llvm;
+
+std::unique_ptr<MCObjectTargetWriter>
+CSKYAsmBackend::createObjectTargetWriter() const {
+ return createCSKYELFObjectWriter();
+}
+
+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_addr_hi16, {"fixup_csky_addr_hi16", 0, 32, 0}},
+ {CSKY::Fixups::fixup_csky_addr_lo16, {"fixup_csky_addr_lo16", 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 |
+ MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}},
+ {CSKY::Fixups::fixup_csky_pcrel_uimm8_scale4,
+ {"fixup_csky_pcrel_uimm8_scale4", 0, 32,
+ MCFixupKindInfo::FKF_IsPCRel |
+ MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}},
+ {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}},
+ {CSKY::Fixups::fixup_csky_got32, {"fixup_csky_got32", 0, 32, 0}},
+ {CSKY::Fixups::fixup_csky_got_imm18_scale4,
+ {"fixup_csky_got_imm18_scale4", 0, 32, 0}},
+ {CSKY::Fixups::fixup_csky_gotoff, {"fixup_csky_gotoff", 0, 32, 0}},
+ {CSKY::Fixups::fixup_csky_gotpc,
+ {"fixup_csky_gotpc", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},
+ {CSKY::Fixups::fixup_csky_plt32, {"fixup_csky_plt32", 0, 32, 0}},
+ {CSKY::Fixups::fixup_csky_plt_imm18_scale4,
+ {"fixup_csky_plt_imm18_scale4", 0, 32, 0}},
+ {CSKY::Fixups::fixup_csky_pcrel_imm10_scale2,
+ {"fixup_csky_pcrel_imm10_scale2", 0, 16, MCFixupKindInfo::FKF_IsPCRel}},
+ {CSKY::Fixups::fixup_csky_pcrel_uimm7_scale4,
+ {"fixup_csky_pcrel_uimm7_scale4", 0, 16,
+ MCFixupKindInfo::FKF_IsPCRel |
+ MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}},
+ {CSKY::Fixups::fixup_csky_doffset_imm18,
+ {"fixup_csky_doffset_imm18", 0, 18, 0}},
+ {CSKY::Fixups::fixup_csky_doffset_imm18_scale2,
+ {"fixup_csky_doffset_imm18_scale2", 0, 18, 0}},
+ {CSKY::Fixups::fixup_csky_doffset_imm18_scale4,
+ {"fixup_csky_doffset_imm18_scale4", 0, 18, 0}}};
+
+ assert(Infos.size() == CSKY::NumTargetFixupKinds &&
+ "Not all fixup kinds added to Infos array");
+
+ if (FirstTargetFixupKind <= Kind && Kind < FirstLiteralRelocationKind) {
+ assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
+ "Invalid kind!");
+
+ 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 CSKY::fixup_csky_got32:
+ case CSKY::fixup_csky_got_imm18_scale4:
+ case CSKY::fixup_csky_gotoff:
+ case CSKY::fixup_csky_gotpc:
+ case CSKY::fixup_csky_plt32:
+ case CSKY::fixup_csky_plt_imm18_scale4:
+ llvm_unreachable("Relocation should be unconditionally forced\n");
+ 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;
+ case CSKY::fixup_csky_pcrel_uimm8_scale4: {
+ if (!isUIntN(10, 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.");
+
+ unsigned IMM4L = (Value >> 2) & 0xf;
+ unsigned IMM4H = (Value >> 6) & 0xf;
+
+ Value = (IMM4H << 21) | (IMM4L << 4);
+ return Value;
+ }
+ case CSKY::fixup_csky_pcrel_imm10_scale2:
+ if (!isIntN(11, 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) & 0x3ff;
+ case CSKY::fixup_csky_pcrel_uimm7_scale4:
+ if ((Value >> 2) > 0xfe)
+ 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.");
+
+ if ((Value >> 2) <= 0x7f) {
+ unsigned IMM5L = (Value >> 2) & 0x1f;
+ unsigned IMM2H = (Value >> 7) & 0x3;
+
+ Value = (1 << 12) | (IMM2H << 8) | IMM5L;
+ } else {
+ unsigned IMM5L = (~Value >> 2) & 0x1f;
+ unsigned IMM2H = (~Value >> 7) & 0x3;
+
+ Value = (IMM2H << 8) | IMM5L;
+ }
+
+ return Value;
+ }
+}
+
+bool CSKYAsmBackend::fixupNeedsRelaxationAdvanced(const MCFixup &Fixup,
+ bool Resolved, uint64_t Value,
+ const MCRelaxableFragment *DF,
+ const MCAsmLayout &Layout,
+ const bool WasForced) const {
+ // Return true if the symbol is actually unresolved.
+ // Resolved could be always false when shouldForceRelocation return true.
+ // We use !WasForced to indicate that the symbol is unresolved and not forced
+ // by shouldForceRelocation.
+ if (!Resolved && !WasForced)
+ return true;
+
+ int64_t Offset = int64_t(Value);
+ switch (Fixup.getTargetKind()) {
+ default:
+ return false;
+ case CSKY::fixup_csky_pcrel_imm10_scale2:
+ return !isShiftedInt<10, 1>(Offset);
+ case CSKY::fixup_csky_pcrel_imm16_scale2:
+ return !isShiftedInt<16, 1>(Offset);
+ case CSKY::fixup_csky_pcrel_imm26_scale2:
+ return !isShiftedInt<26, 1>(Offset);
+ case CSKY::fixup_csky_pcrel_uimm7_scale4:
+ return ((Value >> 2) > 0xfe) || (Value & 0x3);
+ }
+}
+
+void CSKYAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
+ const MCValue &Target,
+ MutableArrayRef<char> Data, uint64_t Value,
+ bool IsResolved,
+ const MCSubtargetInfo *STI) const {
+ 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);
+ bool IsInstFixup = (Kind >= FirstTargetFixupKind);
+
+ if (IsLittleEndian && IsInstFixup && (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::mayNeedRelaxation(const MCInst &Inst,
+ const MCSubtargetInfo &STI) const {
+ switch (Inst.getOpcode()) {
+ default:
+ return false;
+ case CSKY::JBR32:
+ case CSKY::JBT32:
+ case CSKY::JBF32:
+ case CSKY::JBSR32:
+ if (!STI.getFeatureBits()[CSKY::Has2E3])
+ return false;
+ return true;
+ case CSKY::JBR16:
+ case CSKY::JBT16:
+ case CSKY::JBF16:
+ case CSKY::LRW16:
+ case CSKY::BR16:
+ return true;
+ }
+}
+
+bool CSKYAsmBackend::shouldForceRelocation(const MCAssembler &Asm,
+ const MCFixup &Fixup,
+ const MCValue &Target) {
+ if (Fixup.getKind() >= FirstLiteralRelocationKind)
+ return true;
+ switch (Fixup.getTargetKind()) {
+ default:
+ break;
+ case CSKY::fixup_csky_got32:
+ case CSKY::fixup_csky_got_imm18_scale4:
+ case CSKY::fixup_csky_gotoff:
+ case CSKY::fixup_csky_gotpc:
+ case CSKY::fixup_csky_plt32:
+ case CSKY::fixup_csky_plt_imm18_scale4:
+ case CSKY::fixup_csky_doffset_imm18:
+ case CSKY::fixup_csky_doffset_imm18_scale2:
+ case CSKY::fixup_csky_doffset_imm18_scale4:
+ return true;
+ }
+
+ return false;
+}
+
+bool CSKYAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup, uint64_t Value,
+ const MCRelaxableFragment *DF,
+ const MCAsmLayout &Layout) const {
+ return false;
+}
+
+void CSKYAsmBackend::relaxInstruction(MCInst &Inst,
+ const MCSubtargetInfo &STI) const {
+ MCInst Res;
+
+ switch (Inst.getOpcode()) {
+ default:
+ LLVM_DEBUG(Inst.dump());
+ llvm_unreachable("Opcode not expected!");
+ case CSKY::LRW16:
+ Res.setOpcode(CSKY::LRW32);
+ Res.addOperand(Inst.getOperand(0));
+ Res.addOperand(Inst.getOperand(1));
+ break;
+ case CSKY::BR16:
+ Res.setOpcode(CSKY::BR32);
+ Res.addOperand(Inst.getOperand(0));
+ break;
+ case CSKY::JBSR32:
+ Res.setOpcode(CSKY::JSRI32);
+ Res.addOperand(Inst.getOperand(1));
+ break;
+ case CSKY::JBR32:
+ Res.setOpcode(CSKY::JMPI32);
+ Res.addOperand(Inst.getOperand(1));
+ break;
+ case CSKY::JBT32:
+ case CSKY::JBF32:
+ Res.setOpcode(Inst.getOpcode() == CSKY::JBT32 ? CSKY::JBT_E : CSKY::JBF_E);
+ Res.addOperand(Inst.getOperand(0));
+ Res.addOperand(Inst.getOperand(1));
+ Res.addOperand(Inst.getOperand(2));
+ break;
+ case CSKY::JBR16:
+ Res.setOpcode(CSKY::JBR32);
+ Res.addOperand(Inst.getOperand(0));
+ Res.addOperand(Inst.getOperand(1));
+ break;
+ case CSKY::JBT16:
+ case CSKY::JBF16:
+ // ck801
+ unsigned opcode;
+ if (STI.getFeatureBits()[CSKY::HasE2])
+ opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT32 : CSKY::JBF32;
+ else
+ opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT_E : CSKY::JBF_E;
+
+ Res.setOpcode(opcode);
+ Res.addOperand(Inst.getOperand(0));
+ Res.addOperand(Inst.getOperand(1));
+ Res.addOperand(Inst.getOperand(2));
+ break;
+ }
+ Inst = std::move(Res);
+}
+
+bool CSKYAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,
+ const MCSubtargetInfo *STI) const {
+ OS.write_zeros(Count);
+ return true;
+}
+
+MCAsmBackend *llvm::createCSKYAsmBackend(const Target &T,
+ const MCSubtargetInfo &STI,
+ const MCRegisterInfo &MRI,
+ const MCTargetOptions &Options) {
+ return new CSKYAsmBackend(STI, Options);
+}