Path: blob/main/contrib/llvm-project/llvm/lib/Target/CSKY/MCTargetDesc/CSKYAsmBackend.cpp
35294 views
//===-- CSKYAsmBackend.cpp - CSKY Assembler Backend -----------------------===//1//2// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.3// See https://llvm.org/LICENSE.txt for license information.4// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception5//6//===----------------------------------------------------------------------===//78#include "CSKYAsmBackend.h"9#include "MCTargetDesc/CSKYMCTargetDesc.h"10#include "llvm/ADT/DenseMap.h"11#include "llvm/MC/MCAssembler.h"12#include "llvm/MC/MCContext.h"13#include "llvm/MC/MCFixupKindInfo.h"14#include "llvm/MC/MCObjectWriter.h"15#include "llvm/Support/Debug.h"1617#define DEBUG_TYPE "csky-asmbackend"1819using namespace llvm;2021std::unique_ptr<MCObjectTargetWriter>22CSKYAsmBackend::createObjectTargetWriter() const {23return createCSKYELFObjectWriter();24}2526const MCFixupKindInfo &27CSKYAsmBackend::getFixupKindInfo(MCFixupKind Kind) const {2829static llvm::DenseMap<unsigned, MCFixupKindInfo> Infos = {30{CSKY::Fixups::fixup_csky_addr32, {"fixup_csky_addr32", 0, 32, 0}},31{CSKY::Fixups::fixup_csky_addr_hi16, {"fixup_csky_addr_hi16", 0, 32, 0}},32{CSKY::Fixups::fixup_csky_addr_lo16, {"fixup_csky_addr_lo16", 0, 32, 0}},33{CSKY::Fixups::fixup_csky_pcrel_imm16_scale2,34{"fixup_csky_pcrel_imm16_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},35{CSKY::Fixups::fixup_csky_pcrel_uimm16_scale4,36{"fixup_csky_pcrel_uimm16_scale4", 0, 32,37MCFixupKindInfo::FKF_IsPCRel |38MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}},39{CSKY::Fixups::fixup_csky_pcrel_uimm8_scale4,40{"fixup_csky_pcrel_uimm8_scale4", 0, 32,41MCFixupKindInfo::FKF_IsPCRel |42MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}},43{CSKY::Fixups::fixup_csky_pcrel_imm26_scale2,44{"fixup_csky_pcrel_imm26_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},45{CSKY::Fixups::fixup_csky_pcrel_imm18_scale2,46{"fixup_csky_pcrel_imm18_scale2", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},47{CSKY::Fixups::fixup_csky_got32, {"fixup_csky_got32", 0, 32, 0}},48{CSKY::Fixups::fixup_csky_got_imm18_scale4,49{"fixup_csky_got_imm18_scale4", 0, 32, 0}},50{CSKY::Fixups::fixup_csky_gotoff, {"fixup_csky_gotoff", 0, 32, 0}},51{CSKY::Fixups::fixup_csky_gotpc,52{"fixup_csky_gotpc", 0, 32, MCFixupKindInfo::FKF_IsPCRel}},53{CSKY::Fixups::fixup_csky_plt32, {"fixup_csky_plt32", 0, 32, 0}},54{CSKY::Fixups::fixup_csky_plt_imm18_scale4,55{"fixup_csky_plt_imm18_scale4", 0, 32, 0}},56{CSKY::Fixups::fixup_csky_pcrel_imm10_scale2,57{"fixup_csky_pcrel_imm10_scale2", 0, 16, MCFixupKindInfo::FKF_IsPCRel}},58{CSKY::Fixups::fixup_csky_pcrel_uimm7_scale4,59{"fixup_csky_pcrel_uimm7_scale4", 0, 16,60MCFixupKindInfo::FKF_IsPCRel |61MCFixupKindInfo::FKF_IsAlignedDownTo32Bits}},62{CSKY::Fixups::fixup_csky_doffset_imm18,63{"fixup_csky_doffset_imm18", 0, 18, 0}},64{CSKY::Fixups::fixup_csky_doffset_imm18_scale2,65{"fixup_csky_doffset_imm18_scale2", 0, 18, 0}},66{CSKY::Fixups::fixup_csky_doffset_imm18_scale4,67{"fixup_csky_doffset_imm18_scale4", 0, 18, 0}}};6869assert(Infos.size() == CSKY::NumTargetFixupKinds &&70"Not all fixup kinds added to Infos array");7172if (FirstTargetFixupKind <= Kind && Kind < FirstLiteralRelocationKind) {73assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&74"Invalid kind!");7576return Infos[Kind];77} else if (Kind < FirstTargetFixupKind) {78return MCAsmBackend::getFixupKindInfo(Kind);79} else {80return MCAsmBackend::getFixupKindInfo(FK_NONE);81}82}8384static uint64_t adjustFixupValue(const MCFixup &Fixup, uint64_t Value,85MCContext &Ctx) {86switch (Fixup.getTargetKind()) {87default:88llvm_unreachable("Unknown fixup kind!");89case CSKY::fixup_csky_got32:90case CSKY::fixup_csky_got_imm18_scale4:91case CSKY::fixup_csky_gotoff:92case CSKY::fixup_csky_gotpc:93case CSKY::fixup_csky_plt32:94case CSKY::fixup_csky_plt_imm18_scale4:95llvm_unreachable("Relocation should be unconditionally forced\n");96case FK_Data_1:97case FK_Data_2:98case FK_Data_4:99case FK_Data_8:100return Value;101case CSKY::fixup_csky_addr32:102return Value & 0xffffffff;103case CSKY::fixup_csky_pcrel_imm16_scale2:104if (!isIntN(17, Value))105Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");106if (Value & 0x1)107Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");108109return (Value >> 1) & 0xffff;110case CSKY::fixup_csky_pcrel_uimm16_scale4:111if (!isUIntN(18, Value))112Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");113if (Value & 0x3)114Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");115116return (Value >> 2) & 0xffff;117case CSKY::fixup_csky_pcrel_imm26_scale2:118if (!isIntN(27, Value))119Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");120if (Value & 0x1)121Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");122123return (Value >> 1) & 0x3ffffff;124case CSKY::fixup_csky_pcrel_imm18_scale2:125if (!isIntN(19, Value))126Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");127if (Value & 0x1)128Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");129130return (Value >> 1) & 0x3ffff;131case CSKY::fixup_csky_pcrel_uimm8_scale4: {132if (!isUIntN(10, Value))133Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");134if (Value & 0x3)135Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");136137unsigned IMM4L = (Value >> 2) & 0xf;138unsigned IMM4H = (Value >> 6) & 0xf;139140Value = (IMM4H << 21) | (IMM4L << 4);141return Value;142}143case CSKY::fixup_csky_pcrel_imm10_scale2:144if (!isIntN(11, Value))145Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");146if (Value & 0x1)147Ctx.reportError(Fixup.getLoc(), "fixup value must be 2-byte aligned.");148149return (Value >> 1) & 0x3ff;150case CSKY::fixup_csky_pcrel_uimm7_scale4:151if ((Value >> 2) > 0xfe)152Ctx.reportError(Fixup.getLoc(), "out of range pc-relative fixup value.");153if (Value & 0x3)154Ctx.reportError(Fixup.getLoc(), "fixup value must be 4-byte aligned.");155156if ((Value >> 2) <= 0x7f) {157unsigned IMM5L = (Value >> 2) & 0x1f;158unsigned IMM2H = (Value >> 7) & 0x3;159160Value = (1 << 12) | (IMM2H << 8) | IMM5L;161} else {162unsigned IMM5L = (~Value >> 2) & 0x1f;163unsigned IMM2H = (~Value >> 7) & 0x3;164165Value = (IMM2H << 8) | IMM5L;166}167168return Value;169}170}171172bool CSKYAsmBackend::fixupNeedsRelaxationAdvanced(const MCAssembler &Asm,173const MCFixup &Fixup,174bool Resolved, uint64_t Value,175const MCRelaxableFragment *DF,176const bool WasForced) const {177// Return true if the symbol is actually unresolved.178// Resolved could be always false when shouldForceRelocation return true.179// We use !WasForced to indicate that the symbol is unresolved and not forced180// by shouldForceRelocation.181if (!Resolved && !WasForced)182return true;183184int64_t Offset = int64_t(Value);185switch (Fixup.getTargetKind()) {186default:187return false;188case CSKY::fixup_csky_pcrel_imm10_scale2:189return !isShiftedInt<10, 1>(Offset);190case CSKY::fixup_csky_pcrel_imm16_scale2:191return !isShiftedInt<16, 1>(Offset);192case CSKY::fixup_csky_pcrel_imm26_scale2:193return !isShiftedInt<26, 1>(Offset);194case CSKY::fixup_csky_pcrel_uimm7_scale4:195return ((Value >> 2) > 0xfe) || (Value & 0x3);196}197}198199void CSKYAsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,200const MCValue &Target,201MutableArrayRef<char> Data, uint64_t Value,202bool IsResolved,203const MCSubtargetInfo *STI) const {204MCFixupKind Kind = Fixup.getKind();205if (Kind >= FirstLiteralRelocationKind)206return;207MCContext &Ctx = Asm.getContext();208MCFixupKindInfo Info = getFixupKindInfo(Kind);209if (!Value)210return; // Doesn't change encoding.211// Apply any target-specific value adjustments.212Value = adjustFixupValue(Fixup, Value, Ctx);213214// Shift the value into position.215Value <<= Info.TargetOffset;216217unsigned Offset = Fixup.getOffset();218unsigned NumBytes = alignTo(Info.TargetSize + Info.TargetOffset, 8) / 8;219220assert(Offset + NumBytes <= Data.size() && "Invalid fixup offset!");221222// For each byte of the fragment that the fixup touches, mask in the223// bits from the fixup value.224bool IsLittleEndian = (Endian == llvm::endianness::little);225bool IsInstFixup = (Kind >= FirstTargetFixupKind);226227if (IsLittleEndian && IsInstFixup && (NumBytes == 4)) {228Data[Offset + 0] |= uint8_t((Value >> 16) & 0xff);229Data[Offset + 1] |= uint8_t((Value >> 24) & 0xff);230Data[Offset + 2] |= uint8_t(Value & 0xff);231Data[Offset + 3] |= uint8_t((Value >> 8) & 0xff);232} else {233for (unsigned I = 0; I != NumBytes; I++) {234unsigned Idx = IsLittleEndian ? I : (NumBytes - 1 - I);235Data[Offset + Idx] |= uint8_t((Value >> (I * 8)) & 0xff);236}237}238}239240bool CSKYAsmBackend::mayNeedRelaxation(const MCInst &Inst,241const MCSubtargetInfo &STI) const {242switch (Inst.getOpcode()) {243default:244return false;245case CSKY::JBR32:246case CSKY::JBT32:247case CSKY::JBF32:248case CSKY::JBSR32:249if (!STI.hasFeature(CSKY::Has2E3))250return false;251return true;252case CSKY::JBR16:253case CSKY::JBT16:254case CSKY::JBF16:255case CSKY::LRW16:256case CSKY::BR16:257return true;258}259}260261bool CSKYAsmBackend::shouldForceRelocation(const MCAssembler &Asm,262const MCFixup &Fixup,263const MCValue &Target,264const MCSubtargetInfo * /*STI*/) {265if (Fixup.getKind() >= FirstLiteralRelocationKind)266return true;267switch (Fixup.getTargetKind()) {268default:269break;270case CSKY::fixup_csky_got32:271case CSKY::fixup_csky_got_imm18_scale4:272case CSKY::fixup_csky_gotoff:273case CSKY::fixup_csky_gotpc:274case CSKY::fixup_csky_plt32:275case CSKY::fixup_csky_plt_imm18_scale4:276case CSKY::fixup_csky_doffset_imm18:277case CSKY::fixup_csky_doffset_imm18_scale2:278case CSKY::fixup_csky_doffset_imm18_scale4:279return true;280}281282return false;283}284285bool CSKYAsmBackend::fixupNeedsRelaxation(const MCFixup &Fixup,286uint64_t Value) const {287return false;288}289290void CSKYAsmBackend::relaxInstruction(MCInst &Inst,291const MCSubtargetInfo &STI) const {292MCInst Res;293294switch (Inst.getOpcode()) {295default:296LLVM_DEBUG(Inst.dump());297llvm_unreachable("Opcode not expected!");298case CSKY::LRW16:299Res.setOpcode(CSKY::LRW32);300Res.addOperand(Inst.getOperand(0));301Res.addOperand(Inst.getOperand(1));302break;303case CSKY::BR16:304Res.setOpcode(CSKY::BR32);305Res.addOperand(Inst.getOperand(0));306break;307case CSKY::JBSR32:308Res.setOpcode(CSKY::JSRI32);309Res.addOperand(Inst.getOperand(1));310break;311case CSKY::JBR32:312Res.setOpcode(CSKY::JMPI32);313Res.addOperand(Inst.getOperand(1));314break;315case CSKY::JBT32:316case CSKY::JBF32:317Res.setOpcode(Inst.getOpcode() == CSKY::JBT32 ? CSKY::JBT_E : CSKY::JBF_E);318Res.addOperand(Inst.getOperand(0));319Res.addOperand(Inst.getOperand(1));320Res.addOperand(Inst.getOperand(2));321break;322case CSKY::JBR16:323Res.setOpcode(CSKY::JBR32);324Res.addOperand(Inst.getOperand(0));325Res.addOperand(Inst.getOperand(1));326break;327case CSKY::JBT16:328case CSKY::JBF16:329// ck801330unsigned opcode;331if (STI.hasFeature(CSKY::HasE2))332opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT32 : CSKY::JBF32;333else334opcode = Inst.getOpcode() == CSKY::JBT16 ? CSKY::JBT_E : CSKY::JBF_E;335336Res.setOpcode(opcode);337Res.addOperand(Inst.getOperand(0));338Res.addOperand(Inst.getOperand(1));339Res.addOperand(Inst.getOperand(2));340break;341}342Inst = std::move(Res);343}344345bool CSKYAsmBackend::writeNopData(raw_ostream &OS, uint64_t Count,346const MCSubtargetInfo *STI) const {347OS.write_zeros(Count);348return true;349}350351MCAsmBackend *llvm::createCSKYAsmBackend(const Target &T,352const MCSubtargetInfo &STI,353const MCRegisterInfo &MRI,354const MCTargetOptions &Options) {355return new CSKYAsmBackend(STI, Options);356}357358359