1 //===-- Nios2AsmBackend.cpp - Nios2 Asm Backend --------------------------===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 // 10 // This file implements the Nios2AsmBackend class. 11 // 12 //===----------------------------------------------------------------------===// 13 // 14 15 #include "MCTargetDesc/Nios2AsmBackend.h" 16 #include "MCTargetDesc/Nios2FixupKinds.h" 17 #include "MCTargetDesc/Nios2MCTargetDesc.h" 18 #include "llvm/MC/MCAssembler.h" 19 #include "llvm/MC/MCELFObjectWriter.h" 20 #include "llvm/MC/MCFixupKindInfo.h" 21 #include "llvm/MC/MCObjectWriter.h" 22 #include "llvm/MC/MCSubtargetInfo.h" 23 24 using namespace llvm; 25 26 // Prepare value for the target space for it 27 static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value) { 28 29 unsigned Kind = Fixup.getKind(); 30 31 // Add/subtract and shift 32 switch (Kind) { 33 default: 34 return 0; 35 case Nios2::fixup_Nios2_LO16: 36 break; 37 case Nios2::fixup_Nios2_HI16: 38 // Get the higher 16-bits. Also add 1 if bit 15 is 1. 39 Value = ((Value + 0x8000) >> 16) & 0xffff; 40 break; 41 } 42 43 return Value; 44 } 45 46 // Calculate index for Nios2 specific little endian byte order 47 static unsigned calculateLEIndex(unsigned i) { 48 assert(i <= 3 && "Index out of range!"); 49 50 return (1 - i / 2) * 2 + i % 2; 51 } 52 53 /// ApplyFixup - Apply the \p Value for given \p Fixup into the provided 54 /// data fragment, at the offset specified by the fixup and following the 55 /// fixup kind as appropriate. 56 void Nios2AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup, 57 const MCValue &Target, 58 MutableArrayRef<char> Data, uint64_t Value, 59 bool IsResolved) const { 60 MCFixupKind Kind = Fixup.getKind(); 61 Value = adjustFixupValue(Fixup, Value); 62 63 if (!Value) 64 return; // Doesn't change encoding. 65 66 // Where do we start in the object 67 unsigned Offset = Fixup.getOffset(); 68 // Number of bytes we need to fixup 69 unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8; 70 // Grab current value, if any, from bits. 71 uint64_t CurVal = 0; 72 73 for (unsigned i = 0; i != NumBytes; ++i) { 74 unsigned Idx = calculateLEIndex(i); 75 CurVal |= (uint64_t)((uint8_t)Data[Offset + Idx]) << (i * 8); 76 } 77 78 uint64_t Mask = ((uint64_t)(-1) >> (64 - getFixupKindInfo(Kind).TargetSize)); 79 CurVal |= Value & Mask; 80 81 // Write out the fixed up bytes back to the code/data bits. 82 for (unsigned i = 0; i != NumBytes; ++i) { 83 unsigned Idx = calculateLEIndex(i); 84 Data[Offset + Idx] = (uint8_t)((CurVal >> (i * 8)) & 0xff); 85 } 86 } 87 88 Optional<MCFixupKind> Nios2AsmBackend::getFixupKind(StringRef Name) const { 89 return StringSwitch<Optional<MCFixupKind>>(Name) 90 .Case("R_NIOS2_NONE", (MCFixupKind)Nios2::fixup_Nios2_32) 91 .Case("R_NIOS2_32", FK_Data_4) 92 .Default(MCAsmBackend::getFixupKind(Name)); 93 } 94 95 //@getFixupKindInfo { 96 const MCFixupKindInfo & 97 Nios2AsmBackend::getFixupKindInfo(MCFixupKind Kind) const { 98 const static MCFixupKindInfo Infos[Nios2::NumTargetFixupKinds] = { 99 // This table *must* be in same the order of fixup_* kinds in 100 // Nios2FixupKinds.h. 101 // 102 // name offset bits flags 103 {"fixup_Nios2_32", 0, 32, 0}, 104 {"fixup_Nios2_HI16", 0, 16, 0}, 105 {"fixup_Nios2_LO16", 0, 16, 0}}; 106 107 if (Kind < FirstTargetFixupKind) 108 return MCAsmBackend::getFixupKindInfo(Kind); 109 110 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 111 "Invalid kind!"); 112 return Infos[Kind - FirstTargetFixupKind]; 113 } 114 115 std::unique_ptr<MCObjectTargetWriter> 116 Nios2AsmBackend::createObjectTargetWriter() const { 117 return createNios2ELFObjectWriter(MCELFObjectTargetWriter::getOSABI(OSType)); 118 } 119 120 bool Nios2AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const { 121 return true; 122 } 123 124 // MCAsmBackend 125 MCAsmBackend *llvm::createNios2AsmBackend(const Target &T, 126 const MCSubtargetInfo &STI, 127 const MCRegisterInfo &MRI, 128 const MCTargetOptions &Options) { 129 return new Nios2AsmBackend(T, STI.getTargetTriple().getOS()); 130 } 131