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