1 //===-- MipsASMBackend.cpp - ---------===// 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 "MipsFixupKinds.h" 16 #include "MCTargetDesc/MipsMCTargetDesc.h" 17 #include "llvm/ADT/Twine.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/MCExpr.h" 23 #include "llvm/MC/MCMachObjectWriter.h" 24 #include "llvm/MC/MCObjectWriter.h" 25 #include "llvm/MC/MCSectionELF.h" 26 #include "llvm/MC/MCSectionMachO.h" 27 #include "llvm/MC/MCSubtargetInfo.h" 28 #include "llvm/Object/MachOFormat.h" 29 #include "llvm/Support/ELF.h" 30 #include "llvm/Support/ErrorHandling.h" 31 #include "llvm/Support/raw_ostream.h" 32 using namespace llvm; 33 34 static unsigned adjustFixupValue(unsigned Kind, uint64_t Value) { 35 36 // Add/subtract and shift 37 switch (Kind) { 38 default: 39 break; 40 case Mips::fixup_Mips_PC16: 41 // So far we are only using this type for branches. 42 // For branches we start 1 instruction after the branch 43 // so the displacement will be one instruction size less. 44 Value -= 4; 45 // The displacement is then divided by 4 to give us an 18 bit 46 // address range. 47 Value >>= 2; 48 break; 49 case Mips::fixup_Mips_26: 50 // So far we are only using this type for jumps. 51 // The displacement is then divided by 4 to give us an 28 bit 52 // address range. 53 Value >>= 2; 54 break; 55 } 56 57 // Mask off value for placement as an operand 58 switch (Kind) { 59 default: 60 break; 61 case FK_GPRel_4: 62 case FK_Data_4: 63 Value &= 0xffffffff; 64 break; 65 case Mips::fixup_Mips_26: 66 Value &= 0x03ffffff; 67 break; 68 case Mips::fixup_Mips_LO16: 69 case Mips::fixup_Mips_PC16: 70 Value &= 0x0000ffff; 71 break; 72 case Mips::fixup_Mips_HI16: 73 Value >>= 16; 74 break; 75 } 76 77 return Value; 78 } 79 80 namespace { 81 82 class MipsELFObjectWriter : public MCELFObjectTargetWriter { 83 public: 84 MipsELFObjectWriter(bool is64Bit, Triple::OSType OSType, uint16_t EMachine, 85 bool HasRelocationAddend) 86 : MCELFObjectTargetWriter(is64Bit, OSType, EMachine, 87 HasRelocationAddend) {} 88 }; 89 90 class MipsAsmBackend : public MCAsmBackend { 91 public: 92 MipsAsmBackend(const Target &T) : MCAsmBackend() {} 93 94 /// ApplyFixup - Apply the \arg Value for given \arg Fixup into the provided 95 /// data fragment, at the offset specified by the fixup and following the 96 /// fixup kind as appropriate. 97 void ApplyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize, 98 uint64_t Value) const { 99 unsigned Kind = (unsigned)Fixup.getKind(); 100 Value = adjustFixupValue(Kind, Value); 101 102 if (!Value) 103 return; // Doesn't change encoding. 104 105 unsigned Offset = Fixup.getOffset(); 106 switch (Kind) { 107 default: 108 llvm_unreachable("Unknown fixup kind!"); 109 case Mips::fixup_Mips_GOT16: // This will be fixed up at link time 110 break; 111 case FK_GPRel_4: 112 case FK_Data_4: 113 case Mips::fixup_Mips_26: 114 case Mips::fixup_Mips_LO16: 115 case Mips::fixup_Mips_PC16: 116 case Mips::fixup_Mips_HI16: 117 // For each byte of the fragment that the fixup touches, mask i 118 // the fixup value. The Value has been "split up" into the appr 119 // bitfields above. 120 for (unsigned i = 0; i != 4; ++i) // FIXME - Need to support 2 and 8 bytes 121 Data[Offset + i] += uint8_t((Value >> (i * 8)) & 0xff); 122 break; 123 } 124 } 125 126 unsigned getNumFixupKinds() const { return Mips::NumTargetFixupKinds; } 127 128 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const { 129 const static MCFixupKindInfo Infos[Mips::NumTargetFixupKinds] = { 130 // This table *must* be in the order that the fixup_* kinds a 131 // MipsFixupKinds.h. 132 // 133 // name offset bits flags 134 { "fixup_Mips_NONE", 0, 0, 0 }, 135 { "fixup_Mips_16", 0, 16, 0 }, 136 { "fixup_Mips_32", 0, 32, 0 }, 137 { "fixup_Mips_REL32", 0, 32, 0 }, 138 { "fixup_Mips_26", 0, 26, 0 }, 139 { "fixup_Mips_HI16", 0, 16, 0 }, 140 { "fixup_Mips_LO16", 0, 16, 0 }, 141 { "fixup_Mips_GPREL16", 0, 16, 0 }, 142 { "fixup_Mips_LITERAL", 0, 16, 0 }, 143 { "fixup_Mips_GOT16", 0, 16, 0 }, 144 { "fixup_Mips_PC16", 0, 16, MCFixupKindInfo::FKF_IsPCRel }, 145 { "fixup_Mips_CALL16", 0, 16, 0 }, 146 { "fixup_Mips_GPREL32", 0, 32, 0 }, 147 { "fixup_Mips_SHIFT5", 6, 5, 0 }, 148 { "fixup_Mips_SHIFT6", 6, 5, 0 }, 149 { "fixup_Mips_64", 0, 64, 0 }, 150 { "fixup_Mips_TLSGD", 0, 16, 0 }, 151 { "fixup_Mips_GOTTPREL", 0, 16, 0 }, 152 { "fixup_Mips_TPREL_HI", 0, 16, 0 }, 153 { "fixup_Mips_TPREL_LO", 0, 16, 0 }, 154 { "fixup_Mips_Branch_PCRel", 0, 16, MCFixupKindInfo::FKF_IsPCRel } 155 }; 156 157 if (Kind < FirstTargetFixupKind) 158 return MCAsmBackend::getFixupKindInfo(Kind); 159 160 assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() && 161 "Invalid kind!"); 162 return Infos[Kind - FirstTargetFixupKind]; 163 } 164 165 /// @name Target Relaxation Interfaces 166 /// @{ 167 168 /// MayNeedRelaxation - Check whether the given instruction may need 169 /// relaxation. 170 /// 171 /// \param Inst - The instruction to test. 172 bool MayNeedRelaxation(const MCInst &Inst) const { 173 return false; 174 } 175 176 /// RelaxInstruction - Relax the instruction in the given fragment 177 /// to the next wider instruction. 178 /// 179 /// \param Inst - The instruction to relax, which may be the same 180 /// as the output. 181 /// \parm Res [output] - On return, the relaxed instruction. 182 void RelaxInstruction(const MCInst &Inst, MCInst &Res) const { 183 } 184 185 /// @} 186 187 /// WriteNopData - Write an (optimal) nop sequence of Count bytes 188 /// to the given output. If the target cannot generate such a sequence, 189 /// it should return an error. 190 /// 191 /// \return - True on success. 192 bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const { 193 return true; 194 } 195 }; 196 197 class MipsEB_AsmBackend : public MipsAsmBackend { 198 public: 199 Triple::OSType OSType; 200 201 MipsEB_AsmBackend(const Target &T, Triple::OSType _OSType) 202 : MipsAsmBackend(T), OSType(_OSType) {} 203 204 MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 205 return createELFObjectWriter(createELFObjectTargetWriter(), 206 OS, /*IsLittleEndian*/ false); 207 } 208 209 MCELFObjectTargetWriter *createELFObjectTargetWriter() const { 210 return new MipsELFObjectWriter(false, OSType, ELF::EM_MIPS, false); 211 } 212 }; 213 214 class MipsEL_AsmBackend : public MipsAsmBackend { 215 public: 216 Triple::OSType OSType; 217 218 MipsEL_AsmBackend(const Target &T, Triple::OSType _OSType) 219 : MipsAsmBackend(T), OSType(_OSType) {} 220 221 MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 222 return createELFObjectWriter(createELFObjectTargetWriter(), 223 OS, /*IsLittleEndian*/ true); 224 } 225 226 MCELFObjectTargetWriter *createELFObjectTargetWriter() const { 227 return new MipsELFObjectWriter(false, OSType, ELF::EM_MIPS, false); 228 } 229 }; 230 } // namespace 231 232 MCAsmBackend *llvm::createMipsAsmBackend(const Target &T, StringRef TT) { 233 Triple TheTriple(TT); 234 235 // just return little endian for now 236 // 237 return new MipsEL_AsmBackend(T, Triple(TT).getOS()); 238 } 239