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