• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
adjustFixupValue(const MCFixup & Fixup,uint64_t Value)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
calculateLEIndex(unsigned i)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.
applyFixup(const MCAssembler & Asm,const MCFixup & Fixup,const MCValue & Target,MutableArrayRef<char> Data,uint64_t Value,bool IsResolved) const56 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 
getFixupKind(StringRef Name) const88 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 &
getFixupKindInfo(MCFixupKind Kind) const97 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>
createObjectTargetWriter() const116 Nios2AsmBackend::createObjectTargetWriter() const {
117   return createNios2ELFObjectWriter(MCELFObjectTargetWriter::getOSABI(OSType));
118 }
119 
writeNopData(raw_ostream & OS,uint64_t Count) const120 bool Nios2AsmBackend::writeNopData(raw_ostream &OS, uint64_t Count) const {
121   return true;
122 }
123 
124 // MCAsmBackend
createNios2AsmBackend(const Target & T,const MCSubtargetInfo & STI,const MCRegisterInfo & MRI,const MCTargetOptions & Options)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