1 //===-- MipsASMBackend.cpp - Mips 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 MipsAsmBackend and MipsELFObjectWriter classes. 11 // 12 //===----------------------------------------------------------------------===// 13 // 14 15 #include "MipsBaseInfo.h" 16 #include "MipsFixupKinds.h" 17 #include "MCTargetDesc/MipsMCTargetDesc.h" 18 #include "llvm/MC/MCAsmBackend.h" 19 #include "llvm/MC/MCAssembler.h" 20 #include "llvm/MC/MCDirectives.h" 21 #include "llvm/MC/MCELFObjectWriter.h" 22 #include "llvm/MC/MCFixupKindInfo.h" 23 #include "llvm/MC/MCObjectWriter.h" 24 #include "llvm/MC/MCSubtargetInfo.h" 25 #include "llvm/Support/ErrorHandling.h" 26 #include "llvm/Support/raw_ostream.h" 27 28 using namespace llvm; 29 30 // Prepare value for the target space for it 31 static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { 32 33 // Add/subtract and shift 34 switch (Kind) { 35 default: 36 return 0; 37 case FK_GPRel_4: 38 case FK_Data_4: 39 case Mips::fixup_Mips_LO16: 40 break; 41 case Mips::fixup_Mips_PC16: 42 // So far we are only using this type for branches. 43 // For branches we start 1 instruction after the branch 44 // so the displacement will be one instruction size less. 45 Value -= 4; 46 // The displacement is then divided by 4 to give us an 18 bit 47 // address range. 48 Value >>= 2; 49 break; 50 case Mips::fixup_Mips_26: 51 // So far we are only using this type for jumps. 52 // The displacement is then divided by 4 to give us an 28 bit 53 // address range. 54 Value >>= 2; 55 break; 56 case Mips::fixup_Mips_HI16: 57 case Mips::fixup_Mips_GOT_Local: 58 // Get the higher 16-bits. Also add 1 if bit 15 is 1. 59 Value = ((Value + 0x8000) >> 16) & 0xffff; 60 break; 61 } 62 63 return Value; 64 } 65 66 namespace { 67 class MipsAsmBackend : public MCAsmBackend { 68 Triple::OSType OSType; 69 bool IsLittle; // Big or little endian 70 bool Is64Bit; // 32 or 64 bit words 71 72 public: 73 MipsAsmBackend(const Target &T, Triple::OSType _OSType, 74 bool _isLittle, bool _is64Bit) 75 :MCAsmBackend(), OSType(_OSType), IsLittle(_isLittle), Is64Bit(_is64Bit) {} 76 77 MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 78 return createMipsELFObjectWriter(OS, OSType, IsLittle, Is64Bit); 79 } 80 81 /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided 82 /// data fragment, at the offset specified by the fixup and following the 83 /// fixup kind as appropriate. 84 void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 85 uint64_t Value) const { 86 MCFixupKind Kind = Fixup.getKind(); 87 Value = adjustFixupValue((unsigned)Kind, Value); 88 int64_t SymOffset = MipsGetSymAndOffset(Fixup).second; 89 90 if (!Value && !SymOffset) 91 return; // Doesn't change encoding. 92 93 // Where do we start in the object 94 unsigned Offset = Fixup.getOffset(); 95 // Number of bytes we need to fixup 96 unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8; 97 // Used to point to big endian bytes 98 unsigned FullSize; 99 100 switch ((unsigned)Kind) { 101 case Mips::fixup_Mips_16: 102 FullSize = 2; 103 break; 104 case Mips::fixup_Mips_64: 105 FullSize = 8; 106 break; 107 default: 108 FullSize = 4; 109 break; 110 } 111 112 // Grab current value, if any, from bits. 113 uint64_t CurVal = 0; 114 115 for (unsigned i = 0; i != NumBytes; ++i) { 116 unsigned Idx = IsLittle ? i : (FullSize - 1 - i); 117 CurVal |= (uint64_t)((uint8_t)Data[Offset + Idx]) << (i*8); 118 } 119 120 uint64_t Mask = ((uint64_t)(-1) >> (64 - getFixupKindInfo(Kind).TargetSize)); 121 CurVal |= (Value + SymOffset) & Mask; 122 123 // Write out the fixed up bytes back to the code/data bits. 124 for (unsigned i = 0; i != NumBytes; ++i) { 125 unsigned Idx = IsLittle ? i : (FullSize - 1 - i); 126 Data[Offset + Idx] = (uint8_t)((CurVal >> (i*8)) & 0xff); 127 } 128 } 129 130 unsigned getNumFixupKinds() const { return Mips::NumTargetFixupKinds; } 131 132 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { 133 const static MCFixupKindInfo Infos[Mips::NumTargetFixupKinds] = { 134 // This table *must* be in same the order of fixup_* kinds in 135 // MipsFixupKinds.h. 136 // 137 // name offset bits flags 138 { "fixup_Mips_16", 0, 16, 0 }, 139 { "fixup_Mips_32", 0, 32, 0 }, 140 { "fixup_Mips_REL32", 0, 32, 0 }, 141 { "fixup_Mips_26", 0, 26, 0 }, 142 { "fixup_Mips_HI16", 0, 16, 0 }, 143 { "fixup_Mips_LO16", 0, 16, 0 }, 144 { "fixup_Mips_GPREL16", 0, 16, 0 }, 145 { "fixup_Mips_LITERAL", 0, 16, 0 }, 146 { "fixup_Mips_GOT_Global", 0, 16, 0 }, 147 { "fixup_Mips_GOT_Local", 0, 16, 0 }, 148 { "fixup_Mips_PC16", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 149 { "fixup_Mips_CALL16", 0, 16, 0 }, 150 { "fixup_Mips_GPREL32", 0, 32, 0 }, 151 { "fixup_Mips_SHIFT5", 6, 5, 0 }, 152 { "fixup_Mips_SHIFT6", 6, 5, 0 }, 153 { "fixup_Mips_64", 0, 64, 0 }, 154 { "fixup_Mips_TLSGD", 0, 16, 0 }, 155 { "fixup_Mips_GOTTPREL", 0, 16, 0 }, 156 { "fixup_Mips_TPREL_HI", 0, 16, 0 }, 157 { "fixup_Mips_TPREL_LO", 0, 16, 0 }, 158 { "fixup_Mips_TLSLDM", 0, 16, 0 }, 159 { "fixup_Mips_DTPREL_HI", 0, 16, 0 }, 160 { "fixup_Mips_DTPREL_LO", 0, 16, 0 }, 161 { "fixup_Mips_Branch_PCRel", 0, 16, MCFixupKindInfo::FKF_IsPCRel } 162 }; 163 164 if (Kind < FirstTargetFixupKind) 165 return MCAsmBackend::getFixupKindInfo(Kind); 166 167 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 168 "Invalid kind!"); 169 return Infos[Kind - FirstTargetFixupKind]; 170 } 171 172 /// @name Target Relaxation Interfaces 173 /// @{ 174 175 /// MayNeedRelaxation - Check whether the given instruction may need 176 /// relaxation. 177 /// 178 /// \param Inst - The instruction to test. 179 bool mayNeedRelaxation(const MCInst &Inst) const { 180 return false; 181 } 182 183 /// fixupNeedsRelaxation - Target specific predicate for whether a given 184 /// fixup requires the associated instruction to be relaxed. 185 bool fixupNeedsRelaxation(const MCFixup &Fixup, 186 uint64_t Value, 187 const MCInstFragment *DF, 188 const MCAsmLayout &Layout) const { 189 // FIXME. 190 assert(0 && "RelaxInstruction() unimplemented"); 191 return false; 192 } 193 194 /// RelaxInstruction - Relax the instruction in the given fragment 195 /// to the next wider instruction. 196 /// 197 /// \param Inst - The instruction to relax, which may be the same 198 /// as the output. 199 /// \parm Res [output] - On return, the relaxed instruction. 200 void relaxInstruction(const MCInst &Inst, MCInst &Res) const { 201 } 202 203 /// @} 204 205 /// WriteNopData - Write an (optimal) nop sequence of Count bytes 206 /// to the given output. If the target cannot generate such a sequence, 207 /// it should return an error. 208 /// 209 /// \return - True on success. 210 bool writeNopData(uint64_t Count, MCObjectWriter *OW) const { 211 return true; 212 } 213 }; // class MipsAsmBackend 214 215 } // namespace 216 217 // MCAsmBackend 218 MCAsmBackend *llvm::createMipsAsmBackendEL32(const Target &T, StringRef TT) { 219 return new MipsAsmBackend(T, Triple(TT).getOS(), 220 /*IsLittle*/true, /*Is64Bit*/false); 221 } 222 223 MCAsmBackend *llvm::createMipsAsmBackendEB32(const Target &T, StringRef TT) { 224 return new MipsAsmBackend(T, Triple(TT).getOS(), 225 /*IsLittle*/false, /*Is64Bit*/false); 226 } 227 228 MCAsmBackend *llvm::createMipsAsmBackendEL64(const Target &T, StringRef TT) { 229 return new MipsAsmBackend(T, Triple(TT).getOS(), 230 /*IsLittle*/true, /*Is64Bit*/true); 231 } 232 233 MCAsmBackend *llvm::createMipsAsmBackendEB64(const Target &T, StringRef TT) { 234 return new MipsAsmBackend(T, Triple(TT).getOS(), 235 /*IsLittle*/false, /*Is64Bit*/true); 236 } 237 238