LLVM API Documentation

MipsAsmBackend.cpp
Go to the documentation of this file.
00001 //===-- MipsAsmBackend.cpp - Mips Asm Backend  ----------------------------===//
00002 //
00003 //                     The LLVM Compiler Infrastructure
00004 //
00005 // This file is distributed under the University of Illinois Open Source
00006 // License. See LICENSE.TXT for details.
00007 //
00008 //===----------------------------------------------------------------------===//
00009 //
00010 // This file implements the MipsAsmBackend class.
00011 //
00012 //===----------------------------------------------------------------------===//
00013 //
00014 
00015 #include "MCTargetDesc/MipsFixupKinds.h"
00016 #include "MCTargetDesc/MipsAsmBackend.h"
00017 #include "MCTargetDesc/MipsMCTargetDesc.h"
00018 #include "llvm/MC/MCAsmBackend.h"
00019 #include "llvm/MC/MCAssembler.h"
00020 #include "llvm/MC/MCContext.h"
00021 #include "llvm/MC/MCDirectives.h"
00022 #include "llvm/MC/MCELFObjectWriter.h"
00023 #include "llvm/MC/MCFixupKindInfo.h"
00024 #include "llvm/MC/MCObjectWriter.h"
00025 #include "llvm/MC/MCSubtargetInfo.h"
00026 #include "llvm/Support/ErrorHandling.h"
00027 #include "llvm/Support/MathExtras.h"
00028 #include "llvm/Support/raw_ostream.h"
00029 
00030 using namespace llvm;
00031 
00032 // Prepare value for the target space for it
00033 static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
00034                                  MCContext *Ctx = nullptr) {
00035 
00036   unsigned Kind = Fixup.getKind();
00037 
00038   // Add/subtract and shift
00039   switch (Kind) {
00040   default:
00041     return 0;
00042   case FK_Data_2:
00043   case FK_GPRel_4:
00044   case FK_Data_4:
00045   case FK_Data_8:
00046   case Mips::fixup_Mips_LO16:
00047   case Mips::fixup_Mips_GPREL16:
00048   case Mips::fixup_Mips_GPOFF_HI:
00049   case Mips::fixup_Mips_GPOFF_LO:
00050   case Mips::fixup_Mips_GOT_PAGE:
00051   case Mips::fixup_Mips_GOT_OFST:
00052   case Mips::fixup_Mips_GOT_DISP:
00053   case Mips::fixup_Mips_GOT_LO16:
00054   case Mips::fixup_Mips_CALL_LO16:
00055   case Mips::fixup_MICROMIPS_LO16:
00056   case Mips::fixup_MICROMIPS_GOT_PAGE:
00057   case Mips::fixup_MICROMIPS_GOT_OFST:
00058   case Mips::fixup_MICROMIPS_GOT_DISP:
00059   case Mips::fixup_MIPS_PCLO16:
00060     break;
00061   case Mips::fixup_Mips_PC16:
00062     // So far we are only using this type for branches.
00063     // For branches we start 1 instruction after the branch
00064     // so the displacement will be one instruction size less.
00065     Value -= 4;
00066     // The displacement is then divided by 4 to give us an 18 bit
00067     // address range. Forcing a signed division because Value can be negative.
00068     Value = (int64_t)Value / 4;
00069     // We now check if Value can be encoded as a 16-bit signed immediate.
00070     if (!isIntN(16, Value) && Ctx)
00071       Ctx->FatalError(Fixup.getLoc(), "out of range PC16 fixup");
00072     break;
00073   case Mips::fixup_MIPS_PC19_S2:
00074     // Forcing a signed division because Value can be negative.
00075     Value = (int64_t)Value / 4;
00076     // We now check if Value can be encoded as a 19-bit signed immediate.
00077     if (!isIntN(19, Value) && Ctx)
00078       Ctx->FatalError(Fixup.getLoc(), "out of range PC19 fixup");
00079     break;
00080   case Mips::fixup_Mips_26:
00081     // So far we are only using this type for jumps.
00082     // The displacement is then divided by 4 to give us an 28 bit
00083     // address range.
00084     Value >>= 2;
00085     break;
00086   case Mips::fixup_Mips_HI16:
00087   case Mips::fixup_Mips_GOT_Local:
00088   case Mips::fixup_Mips_GOT_HI16:
00089   case Mips::fixup_Mips_CALL_HI16:
00090   case Mips::fixup_MICROMIPS_HI16:
00091   case Mips::fixup_MIPS_PCHI16:
00092     // Get the 2nd 16-bits. Also add 1 if bit 15 is 1.
00093     Value = ((Value + 0x8000) >> 16) & 0xffff;
00094     break;
00095   case Mips::fixup_Mips_HIGHER:
00096     // Get the 3rd 16-bits.
00097     Value = ((Value + 0x80008000LL) >> 32) & 0xffff;
00098     break;
00099   case Mips::fixup_Mips_HIGHEST:
00100     // Get the 4th 16-bits.
00101     Value = ((Value + 0x800080008000LL) >> 48) & 0xffff;
00102     break;
00103   case Mips::fixup_MICROMIPS_26_S1:
00104     Value >>= 1;
00105     break;
00106   case Mips::fixup_MICROMIPS_PC16_S1:
00107     Value -= 4;
00108     // Forcing a signed division because Value can be negative.
00109     Value = (int64_t)Value / 2;
00110     // We now check if Value can be encoded as a 16-bit signed immediate.
00111     if (!isIntN(16, Value) && Ctx)
00112       Ctx->FatalError(Fixup.getLoc(), "out of range PC16 fixup");
00113     break;
00114   case Mips::fixup_MIPS_PC18_S3:
00115     // Forcing a signed division because Value can be negative.
00116     Value = (int64_t)Value / 8;
00117     // We now check if Value can be encoded as a 18-bit signed immediate.
00118     if (!isIntN(18, Value) && Ctx)
00119       Ctx->FatalError(Fixup.getLoc(), "out of range PC18 fixup");
00120     break;
00121   case Mips::fixup_MIPS_PC21_S2:
00122     Value -= 4;
00123     // Forcing a signed division because Value can be negative.
00124     Value = (int64_t) Value / 4;
00125     // We now check if Value can be encoded as a 21-bit signed immediate.
00126     if (!isIntN(21, Value) && Ctx)
00127       Ctx->FatalError(Fixup.getLoc(), "out of range PC21 fixup");
00128     break;
00129   case Mips::fixup_MIPS_PC26_S2:
00130     Value -= 4;
00131     // Forcing a signed division because Value can be negative.
00132     Value = (int64_t) Value / 4;
00133     // We now check if Value can be encoded as a 26-bit signed immediate.
00134     if (!isIntN(26, Value) && Ctx)
00135       Ctx->FatalError(Fixup.getLoc(), "out of range PC26 fixup");
00136     break;
00137   }
00138 
00139   return Value;
00140 }
00141 
00142 MCObjectWriter *MipsAsmBackend::createObjectWriter(raw_ostream &OS) const {
00143   return createMipsELFObjectWriter(OS,
00144     MCELFObjectTargetWriter::getOSABI(OSType), IsLittle, Is64Bit);
00145 }
00146 
00147 // Little-endian fixup data byte ordering:
00148 //   mips32r2:   a | b | x | x
00149 //   microMIPS:  x | x | a | b
00150 
00151 static bool needsMMLEByteOrder(unsigned Kind) {
00152   return Kind >= Mips::fixup_MICROMIPS_26_S1 &&
00153          Kind < Mips::LastTargetFixupKind;
00154 }
00155 
00156 // Calculate index for microMIPS specific little endian byte order
00157 static unsigned calculateMMLEIndex(unsigned i) {
00158   assert(i <= 3 && "Index out of range!");
00159 
00160   return (1 - i / 2) * 2 + i % 2;
00161 }
00162 
00163 /// ApplyFixup - Apply the \p Value for given \p Fixup into the provided
00164 /// data fragment, at the offset specified by the fixup and following the
00165 /// fixup kind as appropriate.
00166 void MipsAsmBackend::applyFixup(const MCFixup &Fixup, char *Data,
00167                                 unsigned DataSize, uint64_t Value,
00168                                 bool IsPCRel) const {
00169   MCFixupKind Kind = Fixup.getKind();
00170   Value = adjustFixupValue(Fixup, Value);
00171 
00172   if (!Value)
00173     return; // Doesn't change encoding.
00174 
00175   // Where do we start in the object
00176   unsigned Offset = Fixup.getOffset();
00177   // Number of bytes we need to fixup
00178   unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8;
00179   // Used to point to big endian bytes
00180   unsigned FullSize;
00181 
00182   switch ((unsigned)Kind) {
00183   case FK_Data_2:
00184   case Mips::fixup_Mips_16:
00185     FullSize = 2;
00186     break;
00187   case FK_Data_8:
00188   case Mips::fixup_Mips_64:
00189     FullSize = 8;
00190     break;
00191   case FK_Data_4:
00192   default:
00193     FullSize = 4;
00194     break;
00195   }
00196 
00197   // Grab current value, if any, from bits.
00198   uint64_t CurVal = 0;
00199 
00200   bool microMipsLEByteOrder = needsMMLEByteOrder((unsigned) Kind);
00201 
00202   for (unsigned i = 0; i != NumBytes; ++i) {
00203     unsigned Idx = IsLittle ? (microMipsLEByteOrder ? calculateMMLEIndex(i)
00204                                                     : i)
00205                             : (FullSize - 1 - i);
00206     CurVal |= (uint64_t)((uint8_t)Data[Offset + Idx]) << (i*8);
00207   }
00208 
00209   uint64_t Mask = ((uint64_t)(-1) >>
00210                     (64 - getFixupKindInfo(Kind).TargetSize));
00211   CurVal |= Value & Mask;
00212 
00213   // Write out the fixed up bytes back to the code/data bits.
00214   for (unsigned i = 0; i != NumBytes; ++i) {
00215     unsigned Idx = IsLittle ? (microMipsLEByteOrder ? calculateMMLEIndex(i)
00216                                                     : i)
00217                             : (FullSize - 1 - i);
00218     Data[Offset + Idx] = (uint8_t)((CurVal >> (i*8)) & 0xff);
00219   }
00220 }
00221 
00222 const MCFixupKindInfo &MipsAsmBackend::
00223 getFixupKindInfo(MCFixupKind Kind) const {
00224   const static MCFixupKindInfo LittleEndianInfos[Mips::NumTargetFixupKinds] = {
00225     // This table *must* be in same the order of fixup_* kinds in
00226     // MipsFixupKinds.h.
00227     //
00228     // name                    offset  bits  flags
00229     { "fixup_Mips_16",           0,     16,   0 },
00230     { "fixup_Mips_32",           0,     32,   0 },
00231     { "fixup_Mips_REL32",        0,     32,   0 },
00232     { "fixup_Mips_26",           0,     26,   0 },
00233     { "fixup_Mips_HI16",         0,     16,   0 },
00234     { "fixup_Mips_LO16",         0,     16,   0 },
00235     { "fixup_Mips_GPREL16",      0,     16,   0 },
00236     { "fixup_Mips_LITERAL",      0,     16,   0 },
00237     { "fixup_Mips_GOT_Global",   0,     16,   0 },
00238     { "fixup_Mips_GOT_Local",    0,     16,   0 },
00239     { "fixup_Mips_PC16",         0,     16,  MCFixupKindInfo::FKF_IsPCRel },
00240     { "fixup_Mips_CALL16",       0,     16,   0 },
00241     { "fixup_Mips_GPREL32",      0,     32,   0 },
00242     { "fixup_Mips_SHIFT5",       6,      5,   0 },
00243     { "fixup_Mips_SHIFT6",       6,      5,   0 },
00244     { "fixup_Mips_64",           0,     64,   0 },
00245     { "fixup_Mips_TLSGD",        0,     16,   0 },
00246     { "fixup_Mips_GOTTPREL",     0,     16,   0 },
00247     { "fixup_Mips_TPREL_HI",     0,     16,   0 },
00248     { "fixup_Mips_TPREL_LO",     0,     16,   0 },
00249     { "fixup_Mips_TLSLDM",       0,     16,   0 },
00250     { "fixup_Mips_DTPREL_HI",    0,     16,   0 },
00251     { "fixup_Mips_DTPREL_LO",    0,     16,   0 },
00252     { "fixup_Mips_Branch_PCRel", 0,     16,  MCFixupKindInfo::FKF_IsPCRel },
00253     { "fixup_Mips_GPOFF_HI",     0,     16,   0 },
00254     { "fixup_Mips_GPOFF_LO",     0,     16,   0 },
00255     { "fixup_Mips_GOT_PAGE",     0,     16,   0 },
00256     { "fixup_Mips_GOT_OFST",     0,     16,   0 },
00257     { "fixup_Mips_GOT_DISP",     0,     16,   0 },
00258     { "fixup_Mips_HIGHER",       0,     16,   0 },
00259     { "fixup_Mips_HIGHEST",      0,     16,   0 },
00260     { "fixup_Mips_GOT_HI16",     0,     16,   0 },
00261     { "fixup_Mips_GOT_LO16",     0,     16,   0 },
00262     { "fixup_Mips_CALL_HI16",    0,     16,   0 },
00263     { "fixup_Mips_CALL_LO16",    0,     16,   0 },
00264     { "fixup_Mips_PC18_S3",      0,     18,  MCFixupKindInfo::FKF_IsPCRel },
00265     { "fixup_MIPS_PC19_S2",      0,     19,  MCFixupKindInfo::FKF_IsPCRel },
00266     { "fixup_MIPS_PC21_S2",      0,     21,  MCFixupKindInfo::FKF_IsPCRel },
00267     { "fixup_MIPS_PC26_S2",      0,     26,  MCFixupKindInfo::FKF_IsPCRel },
00268     { "fixup_MIPS_PCHI16",       0,     16,  MCFixupKindInfo::FKF_IsPCRel },
00269     { "fixup_MIPS_PCLO16",       0,     16,  MCFixupKindInfo::FKF_IsPCRel },
00270     { "fixup_MICROMIPS_26_S1",   0,     26,   0 },
00271     { "fixup_MICROMIPS_HI16",    0,     16,   0 },
00272     { "fixup_MICROMIPS_LO16",    0,     16,   0 },
00273     { "fixup_MICROMIPS_GOT16",   0,     16,   0 },
00274     { "fixup_MICROMIPS_PC16_S1", 0,     16,   MCFixupKindInfo::FKF_IsPCRel },
00275     { "fixup_MICROMIPS_CALL16",  0,     16,   0 },
00276     { "fixup_MICROMIPS_GOT_DISP",        0,     16,   0 },
00277     { "fixup_MICROMIPS_GOT_PAGE",        0,     16,   0 },
00278     { "fixup_MICROMIPS_GOT_OFST",        0,     16,   0 },
00279     { "fixup_MICROMIPS_TLS_GD",          0,     16,   0 },
00280     { "fixup_MICROMIPS_TLS_LDM",         0,     16,   0 },
00281     { "fixup_MICROMIPS_TLS_DTPREL_HI16", 0,     16,   0 },
00282     { "fixup_MICROMIPS_TLS_DTPREL_LO16", 0,     16,   0 },
00283     { "fixup_MICROMIPS_TLS_TPREL_HI16",  0,     16,   0 },
00284     { "fixup_MICROMIPS_TLS_TPREL_LO16",  0,     16,   0 }
00285   };
00286 
00287   const static MCFixupKindInfo BigEndianInfos[Mips::NumTargetFixupKinds] = {
00288     // This table *must* be in same the order of fixup_* kinds in
00289     // MipsFixupKinds.h.
00290     //
00291     // name                    offset  bits  flags
00292     { "fixup_Mips_16",          16,     16,   0 },
00293     { "fixup_Mips_32",           0,     32,   0 },
00294     { "fixup_Mips_REL32",        0,     32,   0 },
00295     { "fixup_Mips_26",           6,     26,   0 },
00296     { "fixup_Mips_HI16",        16,     16,   0 },
00297     { "fixup_Mips_LO16",        16,     16,   0 },
00298     { "fixup_Mips_GPREL16",     16,     16,   0 },
00299     { "fixup_Mips_LITERAL",     16,     16,   0 },
00300     { "fixup_Mips_GOT_Global",  16,     16,   0 },
00301     { "fixup_Mips_GOT_Local",   16,     16,   0 },
00302     { "fixup_Mips_PC16",        16,     16,  MCFixupKindInfo::FKF_IsPCRel },
00303     { "fixup_Mips_CALL16",      16,     16,   0 },
00304     { "fixup_Mips_GPREL32",      0,     32,   0 },
00305     { "fixup_Mips_SHIFT5",      21,      5,   0 },
00306     { "fixup_Mips_SHIFT6",      21,      5,   0 },
00307     { "fixup_Mips_64",           0,     64,   0 },
00308     { "fixup_Mips_TLSGD",       16,     16,   0 },
00309     { "fixup_Mips_GOTTPREL",    16,     16,   0 },
00310     { "fixup_Mips_TPREL_HI",    16,     16,   0 },
00311     { "fixup_Mips_TPREL_LO",    16,     16,   0 },
00312     { "fixup_Mips_TLSLDM",      16,     16,   0 },
00313     { "fixup_Mips_DTPREL_HI",   16,     16,   0 },
00314     { "fixup_Mips_DTPREL_LO",   16,     16,   0 },
00315     { "fixup_Mips_Branch_PCRel",16,     16,  MCFixupKindInfo::FKF_IsPCRel },
00316     { "fixup_Mips_GPOFF_HI",    16,     16,   0 },
00317     { "fixup_Mips_GPOFF_LO",    16,     16,   0 },
00318     { "fixup_Mips_GOT_PAGE",    16,     16,   0 },
00319     { "fixup_Mips_GOT_OFST",    16,     16,   0 },
00320     { "fixup_Mips_GOT_DISP",    16,     16,   0 },
00321     { "fixup_Mips_HIGHER",      16,     16,   0 },
00322     { "fixup_Mips_HIGHEST",     16,     16,   0 },
00323     { "fixup_Mips_GOT_HI16",    16,     16,   0 },
00324     { "fixup_Mips_GOT_LO16",    16,     16,   0 },
00325     { "fixup_Mips_CALL_HI16",   16,     16,   0 },
00326     { "fixup_Mips_CALL_LO16",   16,     16,   0 },
00327     { "fixup_Mips_PC18_S3",     14,     18,  MCFixupKindInfo::FKF_IsPCRel },
00328     { "fixup_MIPS_PC19_S2",     13,     19,  MCFixupKindInfo::FKF_IsPCRel },
00329     { "fixup_MIPS_PC21_S2",     11,     21,  MCFixupKindInfo::FKF_IsPCRel },
00330     { "fixup_MIPS_PC26_S2",      6,     26,  MCFixupKindInfo::FKF_IsPCRel },
00331     { "fixup_MIPS_PCHI16",      16,     16,  MCFixupKindInfo::FKF_IsPCRel },
00332     { "fixup_MIPS_PCLO16",      16,     16,  MCFixupKindInfo::FKF_IsPCRel },
00333     { "fixup_MICROMIPS_26_S1",   6,     26,   0 },
00334     { "fixup_MICROMIPS_HI16",   16,     16,   0 },
00335     { "fixup_MICROMIPS_LO16",   16,     16,   0 },
00336     { "fixup_MICROMIPS_GOT16",  16,     16,   0 },
00337     { "fixup_MICROMIPS_PC16_S1",16,     16,   MCFixupKindInfo::FKF_IsPCRel },
00338     { "fixup_MICROMIPS_CALL16", 16,     16,   0 },
00339     { "fixup_MICROMIPS_GOT_DISP",        16,     16,   0 },
00340     { "fixup_MICROMIPS_GOT_PAGE",        16,     16,   0 },
00341     { "fixup_MICROMIPS_GOT_OFST",        16,     16,   0 },
00342     { "fixup_MICROMIPS_TLS_GD",          16,     16,   0 },
00343     { "fixup_MICROMIPS_TLS_LDM",         16,     16,   0 },
00344     { "fixup_MICROMIPS_TLS_DTPREL_HI16", 16,     16,   0 },
00345     { "fixup_MICROMIPS_TLS_DTPREL_LO16", 16,     16,   0 },
00346     { "fixup_MICROMIPS_TLS_TPREL_HI16",  16,     16,   0 },
00347     { "fixup_MICROMIPS_TLS_TPREL_LO16",  16,     16,   0 }
00348   };
00349 
00350   if (Kind < FirstTargetFixupKind)
00351     return MCAsmBackend::getFixupKindInfo(Kind);
00352 
00353   assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
00354           "Invalid kind!");
00355 
00356   if (IsLittle)
00357     return LittleEndianInfos[Kind - FirstTargetFixupKind];
00358   return BigEndianInfos[Kind - FirstTargetFixupKind];
00359 }
00360 
00361 /// WriteNopData - Write an (optimal) nop sequence of Count bytes
00362 /// to the given output. If the target cannot generate such a sequence,
00363 /// it should return an error.
00364 ///
00365 /// \return - True on success.
00366 bool MipsAsmBackend::writeNopData(uint64_t Count, MCObjectWriter *OW) const {
00367   // Check for a less than instruction size number of bytes
00368   // FIXME: 16 bit instructions are not handled yet here.
00369   // We shouldn't be using a hard coded number for instruction size.
00370   if (Count % 4) return false;
00371 
00372   uint64_t NumNops = Count / 4;
00373   for (uint64_t i = 0; i != NumNops; ++i)
00374     OW->Write32(0);
00375   return true;
00376 }
00377 
00378 /// processFixupValue - Target hook to process the literal value of a fixup
00379 /// if necessary.
00380 void MipsAsmBackend::processFixupValue(const MCAssembler &Asm,
00381                                        const MCAsmLayout &Layout,
00382                                        const MCFixup &Fixup,
00383                                        const MCFragment *DF,
00384                                        const MCValue &Target,
00385                                        uint64_t &Value,
00386                                        bool &IsResolved) {
00387   // At this point we'll ignore the value returned by adjustFixupValue as
00388   // we are only checking if the fixup can be applied correctly. We have
00389   // access to MCContext from here which allows us to report a fatal error
00390   // with *possibly* a source code location.
00391   (void)adjustFixupValue(Fixup, Value, &Asm.getContext());
00392 }
00393 
00394 // MCAsmBackend
00395 MCAsmBackend *llvm::createMipsAsmBackendEL32(const Target &T,
00396                                              const MCRegisterInfo &MRI,
00397                                              StringRef TT,
00398                                              StringRef CPU) {
00399   return new MipsAsmBackend(T, Triple(TT).getOS(),
00400                             /*IsLittle*/true, /*Is64Bit*/false);
00401 }
00402 
00403 MCAsmBackend *llvm::createMipsAsmBackendEB32(const Target &T,
00404                                              const MCRegisterInfo &MRI,
00405                                              StringRef TT,
00406                                              StringRef CPU) {
00407   return new MipsAsmBackend(T, Triple(TT).getOS(),
00408                             /*IsLittle*/false, /*Is64Bit*/false);
00409 }
00410 
00411 MCAsmBackend *llvm::createMipsAsmBackendEL64(const Target &T,
00412                                              const MCRegisterInfo &MRI,
00413                                              StringRef TT,
00414                                              StringRef CPU) {
00415   return new MipsAsmBackend(T, Triple(TT).getOS(),
00416                             /*IsLittle*/true, /*Is64Bit*/true);
00417 }
00418 
00419 MCAsmBackend *llvm::createMipsAsmBackendEB64(const Target &T,
00420                                              const MCRegisterInfo &MRI,
00421                                              StringRef TT,
00422                                              StringRef CPU) {
00423   return new MipsAsmBackend(T, Triple(TT).getOS(),
00424                             /*IsLittle*/false, /*Is64Bit*/true);
00425 }