MipsAsmBackend.cpp revision 370b78d795154899a22ca2b4674e890661ff1d59
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" 32using namespace llvm; 33 34static 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 80namespace { 81 82class MipsELFObjectWriter : public MCELFObjectTargetWriter { 83public: 84 MipsELFObjectWriter(bool is64Bit, Triple::OSType OSType, uint16_t EMachine, 85 bool HasRelocationAddend) 86 : MCELFObjectTargetWriter(is64Bit, OSType, EMachine, 87 HasRelocationAddend) {} 88}; 89 90class MipsAsmBackend : public MCAsmBackend { 91public: 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 /// fixupNeedsRelaxation - Target specific predicate for whether a given 177 /// fixup requires the associated instruction to be relaxed. 178 bool fixupNeedsRelaxation(const MCFixup &Fixup, 179 uint64_t Value, 180 const MCInstFragment *DF, 181 const MCAsmLayout &Layout) const { 182 // FIXME. 183 assert(0 && "RelaxInstruction() unimplemented"); 184 } 185 186 /// RelaxInstruction - Relax the instruction in the given fragment 187 /// to the next wider instruction. 188 /// 189 /// \param Inst - The instruction to relax, which may be the same 190 /// as the output. 191 /// \parm Res [output] - On return, the relaxed instruction. 192 void RelaxInstruction(const MCInst &Inst, MCInst &Res) const { 193 } 194 195 /// @} 196 197 /// WriteNopData - Write an (optimal) nop sequence of Count bytes 198 /// to the given output. If the target cannot generate such a sequence, 199 /// it should return an error. 200 /// 201 /// \return - True on success. 202 bool WriteNopData(uint64_t Count, MCObjectWriter *OW) const { 203 return true; 204 } 205}; 206 207class MipsEB_AsmBackend : public MipsAsmBackend { 208public: 209 Triple::OSType OSType; 210 211 MipsEB_AsmBackend(const Target &T, Triple::OSType _OSType) 212 : MipsAsmBackend(T), OSType(_OSType) {} 213 214 MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 215 return createELFObjectWriter(createELFObjectTargetWriter(), 216 OS, /*IsLittleEndian*/ false); 217 } 218 219 MCELFObjectTargetWriter *createELFObjectTargetWriter() const { 220 return new MipsELFObjectWriter(false, OSType, ELF::EM_MIPS, false); 221 } 222}; 223 224class MipsEL_AsmBackend : public MipsAsmBackend { 225public: 226 Triple::OSType OSType; 227 228 MipsEL_AsmBackend(const Target &T, Triple::OSType _OSType) 229 : MipsAsmBackend(T), OSType(_OSType) {} 230 231 MCObjectWriter *createObjectWriter(raw_ostream &OS) const { 232 return createELFObjectWriter(createELFObjectTargetWriter(), 233 OS, /*IsLittleEndian*/ true); 234 } 235 236 MCELFObjectTargetWriter *createELFObjectTargetWriter() const { 237 return new MipsELFObjectWriter(false, OSType, ELF::EM_MIPS, false); 238 } 239}; 240} // namespace 241 242MCAsmBackend *llvm::createMipsAsmBackend(const Target &T, StringRef TT) { 243 Triple TheTriple(TT); 244 245 // just return little endian for now 246 // 247 return new MipsEL_AsmBackend(T, Triple(TT).getOS()); 248} 249