Home | History | Annotate | Download | only in MCTargetDesc
      1 //===-- Nios2AsmBackend.cpp - Nios2 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 Nios2AsmBackend class.
     11 //
     12 //===----------------------------------------------------------------------===//
     13 //
     14 
     15 #include "MCTargetDesc/Nios2AsmBackend.h"
     16 #include "MCTargetDesc/Nios2FixupKinds.h"
     17 #include "MCTargetDesc/Nios2MCTargetDesc.h"
     18 #include "llvm/MC/MCAssembler.h"
     19 #include "llvm/MC/MCELFObjectWriter.h"
     20 #include "llvm/MC/MCFixupKindInfo.h"
     21 #include "llvm/MC/MCObjectWriter.h"
     22 #include "llvm/MC/MCSubtargetInfo.h"
     23 
     24 using namespace llvm;
     25 
     26 // Prepare value for the target space for it
     27 static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value) {
     28 
     29   unsigned Kind = Fixup.getKind();
     30 
     31   // Add/subtract and shift
     32   switch (Kind) {
     33   default:
     34     return 0;
     35   case Nios2::fixup_Nios2_LO16:
     36     break;
     37   case Nios2::fixup_Nios2_HI16:
     38     // Get the higher 16-bits. Also add 1 if bit 15 is 1.
     39     Value = ((Value + 0x8000) >> 16) & 0xffff;
     40     break;
     41   }
     42 
     43   return Value;
     44 }
     45 
     46 // Calculate index for Nios2 specific little endian byte order
     47 static unsigned calculateLEIndex(unsigned i) {
     48   assert(i <= 3 && "Index out of range!");
     49 
     50   return (1 - i / 2) * 2 + i % 2;
     51 }
     52 
     53 /// ApplyFixup - Apply the \p Value for given \p Fixup into the provided
     54 /// data fragment, at the offset specified by the fixup and following the
     55 /// fixup kind as appropriate.
     56 void Nios2AsmBackend::applyFixup(const MCAssembler &Asm, const MCFixup &Fixup,
     57                                  const MCValue &Target,
     58                                  MutableArrayRef<char> Data, uint64_t Value,
     59                                  bool IsResolved) const {
     60   MCFixupKind Kind = Fixup.getKind();
     61   Value = adjustFixupValue(Fixup, Value);
     62 
     63   if (!Value)
     64     return; // Doesn't change encoding.
     65 
     66   // Where do we start in the object
     67   unsigned Offset = Fixup.getOffset();
     68   // Number of bytes we need to fixup
     69   unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8;
     70   // Grab current value, if any, from bits.
     71   uint64_t CurVal = 0;
     72 
     73   for (unsigned i = 0; i != NumBytes; ++i) {
     74     unsigned Idx = calculateLEIndex(i);
     75     CurVal |= (uint64_t)((uint8_t)Data[Offset + Idx]) << (i * 8);
     76   }
     77 
     78   uint64_t Mask = ((uint64_t)(-1) >> (64 - getFixupKindInfo(Kind).TargetSize));
     79   CurVal |= Value & Mask;
     80 
     81   // Write out the fixed up bytes back to the code/data bits.
     82   for (unsigned i = 0; i != NumBytes; ++i) {
     83     unsigned Idx = calculateLEIndex(i);
     84     Data[Offset + Idx] = (uint8_t)((CurVal >> (i * 8)) & 0xff);
     85   }
     86 }
     87 
     88 Optional<MCFixupKind> Nios2AsmBackend::getFixupKind(StringRef Name) const {
     89   return StringSwitch<Optional<MCFixupKind>>(Name)
     90       .Case("R_NIOS2_NONE", (MCFixupKind)Nios2::fixup_Nios2_32)
     91       .Case("R_NIOS2_32", FK_Data_4)
     92       .Default(MCAsmBackend::getFixupKind(Name));
     93 }
     94 
     95 //@getFixupKindInfo {
     96 const MCFixupKindInfo &
     97 Nios2AsmBackend::getFixupKindInfo(MCFixupKind Kind) const {
     98   const static MCFixupKindInfo Infos[Nios2::NumTargetFixupKinds] = {
     99       // This table *must* be in same the order of fixup_* kinds in
    100       // Nios2FixupKinds.h.
    101       //
    102       // name                        offset  bits  flags
    103       {"fixup_Nios2_32", 0, 32, 0},
    104       {"fixup_Nios2_HI16", 0, 16, 0},
    105       {"fixup_Nios2_LO16", 0, 16, 0}};
    106 
    107   if (Kind < FirstTargetFixupKind)
    108     return MCAsmBackend::getFixupKindInfo(Kind);
    109 
    110   assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
    111          "Invalid kind!");
    112   return Infos[Kind - FirstTargetFixupKind];
    113 }
    114 
    115 std::unique_ptr<MCObjectTargetWriter>
    116 Nios2AsmBackend::createObjectTargetWriter() const {
    117   return createNios2ELFObjectWriter(MCELFObjectTargetWriter::getOSABI(OSType));
    118 }
    119 
    120 bool Nios2AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const {
    121   return true;
    122 }
    123 
    124 // MCAsmBackend
    125 MCAsmBackend *llvm::createNios2AsmBackend(const Target &T,
    126                                           const MCSubtargetInfo &STI,
    127                                           const MCRegisterInfo &MRI,
    128                                           const MCTargetOptions &Options) {
    129   return new Nios2AsmBackend(T, STI.getTargetTriple().getOS());
    130 }
    131