Re-sort all of the includes with ./utils/sort_includes.py so that
[oota-llvm.git] / lib / Target / Mips / MCTargetDesc / MipsAsmBackend.cpp
1 //===-- MipsASMBackend.cpp - Mips 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 MipsAsmBackend and MipsELFObjectWriter classes.
11 //
12 //===----------------------------------------------------------------------===//
13 //
14
15 #include "MipsFixupKinds.h"
16 #include "MCTargetDesc/MipsMCTargetDesc.h"
17 #include "llvm/MC/MCAsmBackend.h"
18 #include "llvm/MC/MCAssembler.h"
19 #include "llvm/MC/MCContext.h"
20 #include "llvm/MC/MCDirectives.h"
21 #include "llvm/MC/MCELFObjectWriter.h"
22 #include "llvm/MC/MCFixupKindInfo.h"
23 #include "llvm/MC/MCObjectWriter.h"
24 #include "llvm/MC/MCSubtargetInfo.h"
25 #include "llvm/Support/ErrorHandling.h"
26 #include "llvm/Support/MathExtras.h"
27 #include "llvm/Support/raw_ostream.h"
28
29 using namespace llvm;
30
31 // Prepare value for the target space for it
32 static unsigned adjustFixupValue(const MCFixup &Fixup, uint64_t Value,
33                                  MCContext *Ctx = NULL) {
34
35   unsigned Kind = Fixup.getKind();
36
37   // Add/subtract and shift
38   switch (Kind) {
39   default:
40     return 0;
41   case FK_GPRel_4:
42   case FK_Data_4:
43   case FK_Data_8:
44   case Mips::fixup_Mips_LO16:
45   case Mips::fixup_Mips_GPREL16:
46   case Mips::fixup_Mips_GPOFF_HI:
47   case Mips::fixup_Mips_GPOFF_LO:
48   case Mips::fixup_Mips_GOT_PAGE:
49   case Mips::fixup_Mips_GOT_OFST:
50   case Mips::fixup_Mips_GOT_DISP:
51   case Mips::fixup_Mips_GOT_LO16:
52   case Mips::fixup_Mips_CALL_LO16:
53   case Mips::fixup_MICROMIPS_LO16:
54   case Mips::fixup_MICROMIPS_GOT_PAGE:
55   case Mips::fixup_MICROMIPS_GOT_OFST:
56   case Mips::fixup_MICROMIPS_GOT_DISP:
57     break;
58   case Mips::fixup_Mips_PC16:
59     // So far we are only using this type for branches.
60     // For branches we start 1 instruction after the branch
61     // so the displacement will be one instruction size less.
62     Value -= 4;
63     // The displacement is then divided by 4 to give us an 18 bit
64     // address range. Forcing a signed division because Value can be negative.
65     Value = (int64_t)Value / 4;
66     // We now check if Value can be encoded as a 16-bit signed immediate.
67     if (!isIntN(16, Value) && Ctx)
68       Ctx->FatalError(Fixup.getLoc(), "out of range PC16 fixup");
69     break;
70   case Mips::fixup_Mips_26:
71     // So far we are only using this type for jumps.
72     // The displacement is then divided by 4 to give us an 28 bit
73     // address range.
74     Value >>= 2;
75     break;
76   case Mips::fixup_Mips_HI16:
77   case Mips::fixup_Mips_GOT_Local:
78   case Mips::fixup_Mips_GOT_HI16:
79   case Mips::fixup_Mips_CALL_HI16:
80   case Mips::fixup_MICROMIPS_HI16:
81     // Get the 2nd 16-bits. Also add 1 if bit 15 is 1.
82     Value = ((Value + 0x8000) >> 16) & 0xffff;
83     break;
84   case Mips::fixup_Mips_HIGHER:
85     // Get the 3rd 16-bits.
86     Value = ((Value + 0x80008000LL) >> 32) & 0xffff;
87     break;
88   case Mips::fixup_Mips_HIGHEST:
89     // Get the 4th 16-bits.
90     Value = ((Value + 0x800080008000LL) >> 48) & 0xffff;
91     break;
92   case Mips::fixup_MICROMIPS_26_S1:
93     Value >>= 1;
94     break;
95   case Mips::fixup_MICROMIPS_PC16_S1:
96     Value -= 4;
97     // Forcing a signed division because Value can be negative.
98     Value = (int64_t)Value / 2;
99     // We now check if Value can be encoded as a 16-bit signed immediate.
100     if (!isIntN(16, Value) && Ctx)
101       Ctx->FatalError(Fixup.getLoc(), "out of range PC16 fixup");
102     break;
103   }
104
105   return Value;
106 }
107
108 namespace {
109 class MipsAsmBackend : public MCAsmBackend {
110   Triple::OSType OSType;
111   bool IsLittle; // Big or little endian
112   bool Is64Bit;  // 32 or 64 bit words
113
114 public:
115   MipsAsmBackend(const Target &T,  Triple::OSType _OSType,
116                  bool _isLittle, bool _is64Bit)
117     :MCAsmBackend(), OSType(_OSType), IsLittle(_isLittle), Is64Bit(_is64Bit) {}
118
119   MCObjectWriter *createObjectWriter(raw_ostream &OS) const {
120     return createMipsELFObjectWriter(OS,
121       MCELFObjectTargetWriter::getOSABI(OSType), IsLittle, Is64Bit);
122   }
123
124   /// ApplyFixup - Apply the \p Value for given \p Fixup into the provided
125   /// data fragment, at the offset specified by the fixup and following the
126   /// fixup kind as appropriate.
127   void applyFixup(const MCFixup &Fixup, char *Data, unsigned DataSize,
128                   uint64_t Value) const {
129     MCFixupKind Kind = Fixup.getKind();
130     Value = adjustFixupValue(Fixup, Value);
131
132     if (!Value)
133       return; // Doesn't change encoding.
134
135     // Where do we start in the object
136     unsigned Offset = Fixup.getOffset();
137     // Number of bytes we need to fixup
138     unsigned NumBytes = (getFixupKindInfo(Kind).TargetSize + 7) / 8;
139     // Used to point to big endian bytes
140     unsigned FullSize;
141
142     switch ((unsigned)Kind) {
143     case Mips::fixup_Mips_16:
144       FullSize = 2;
145       break;
146     case Mips::fixup_Mips_64:
147       FullSize = 8;
148       break;
149     default:
150       FullSize = 4;
151       break;
152     }
153
154     // Grab current value, if any, from bits.
155     uint64_t CurVal = 0;
156
157     for (unsigned i = 0; i != NumBytes; ++i) {
158       unsigned Idx = IsLittle ? i : (FullSize - 1 - i);
159       CurVal |= (uint64_t)((uint8_t)Data[Offset + Idx]) << (i*8);
160     }
161
162     uint64_t Mask = ((uint64_t)(-1) >>
163                      (64 - getFixupKindInfo(Kind).TargetSize));
164     CurVal |= Value & Mask;
165
166     // Write out the fixed up bytes back to the code/data bits.
167     for (unsigned i = 0; i != NumBytes; ++i) {
168       unsigned Idx = IsLittle ? i : (FullSize - 1 - i);
169       Data[Offset + Idx] = (uint8_t)((CurVal >> (i*8)) & 0xff);
170     }
171   }
172
173   unsigned getNumFixupKinds() const { return Mips::NumTargetFixupKinds; }
174
175   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
176     const static MCFixupKindInfo Infos[Mips::NumTargetFixupKinds] = {
177       // This table *must* be in same the order of fixup_* kinds in
178       // MipsFixupKinds.h.
179       //
180       // name                    offset  bits  flags
181       { "fixup_Mips_16",           0,     16,   0 },
182       { "fixup_Mips_32",           0,     32,   0 },
183       { "fixup_Mips_REL32",        0,     32,   0 },
184       { "fixup_Mips_26",           0,     26,   0 },
185       { "fixup_Mips_HI16",         0,     16,   0 },
186       { "fixup_Mips_LO16",         0,     16,   0 },
187       { "fixup_Mips_GPREL16",      0,     16,   0 },
188       { "fixup_Mips_LITERAL",      0,     16,   0 },
189       { "fixup_Mips_GOT_Global",   0,     16,   0 },
190       { "fixup_Mips_GOT_Local",    0,     16,   0 },
191       { "fixup_Mips_PC16",         0,     16,  MCFixupKindInfo::FKF_IsPCRel },
192       { "fixup_Mips_CALL16",       0,     16,   0 },
193       { "fixup_Mips_GPREL32",      0,     32,   0 },
194       { "fixup_Mips_SHIFT5",       6,      5,   0 },
195       { "fixup_Mips_SHIFT6",       6,      5,   0 },
196       { "fixup_Mips_64",           0,     64,   0 },
197       { "fixup_Mips_TLSGD",        0,     16,   0 },
198       { "fixup_Mips_GOTTPREL",     0,     16,   0 },
199       { "fixup_Mips_TPREL_HI",     0,     16,   0 },
200       { "fixup_Mips_TPREL_LO",     0,     16,   0 },
201       { "fixup_Mips_TLSLDM",       0,     16,   0 },
202       { "fixup_Mips_DTPREL_HI",    0,     16,   0 },
203       { "fixup_Mips_DTPREL_LO",    0,     16,   0 },
204       { "fixup_Mips_Branch_PCRel", 0,     16,  MCFixupKindInfo::FKF_IsPCRel },
205       { "fixup_Mips_GPOFF_HI",     0,     16,   0 },
206       { "fixup_Mips_GPOFF_LO",     0,     16,   0 },
207       { "fixup_Mips_GOT_PAGE",     0,     16,   0 },
208       { "fixup_Mips_GOT_OFST",     0,     16,   0 },
209       { "fixup_Mips_GOT_DISP",     0,     16,   0 },
210       { "fixup_Mips_HIGHER",       0,     16,   0 },
211       { "fixup_Mips_HIGHEST",      0,     16,   0 },
212       { "fixup_Mips_GOT_HI16",     0,     16,   0 },
213       { "fixup_Mips_GOT_LO16",     0,     16,   0 },
214       { "fixup_Mips_CALL_HI16",    0,     16,   0 },
215       { "fixup_Mips_CALL_LO16",    0,     16,   0 },
216       { "fixup_MICROMIPS_26_S1",   0,     26,   0 },
217       { "fixup_MICROMIPS_HI16",    0,     16,   0 },
218       { "fixup_MICROMIPS_LO16",    0,     16,   0 },
219       { "fixup_MICROMIPS_GOT16",   0,     16,   0 },
220       { "fixup_MICROMIPS_PC16_S1", 0,     16,   MCFixupKindInfo::FKF_IsPCRel },
221       { "fixup_MICROMIPS_CALL16",  0,     16,   0 },
222       { "fixup_MICROMIPS_GOT_DISP",        0,     16,   0 },
223       { "fixup_MICROMIPS_GOT_PAGE",        0,     16,   0 },
224       { "fixup_MICROMIPS_GOT_OFST",        0,     16,   0 },
225       { "fixup_MICROMIPS_TLS_GD",          0,     16,   0 },
226       { "fixup_MICROMIPS_TLS_LDM",         0,     16,   0 },
227       { "fixup_MICROMIPS_TLS_DTPREL_HI16", 0,     16,   0 },
228       { "fixup_MICROMIPS_TLS_DTPREL_LO16", 0,     16,   0 },
229       { "fixup_MICROMIPS_TLS_TPREL_HI16",  0,     16,   0 },
230       { "fixup_MICROMIPS_TLS_TPREL_LO16",  0,     16,   0 }
231     };
232
233     if (Kind < FirstTargetFixupKind)
234       return MCAsmBackend::getFixupKindInfo(Kind);
235
236     assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
237            "Invalid kind!");
238     return Infos[Kind - FirstTargetFixupKind];
239   }
240
241   /// @name Target Relaxation Interfaces
242   /// @{
243
244   /// MayNeedRelaxation - Check whether the given instruction may need
245   /// relaxation.
246   ///
247   /// \param Inst - The instruction to test.
248   bool mayNeedRelaxation(const MCInst &Inst) const {
249     return false;
250   }
251
252   /// fixupNeedsRelaxation - Target specific predicate for whether a given
253   /// fixup requires the associated instruction to be relaxed.
254   bool fixupNeedsRelaxation(const MCFixup &Fixup,
255                             uint64_t Value,
256                             const MCRelaxableFragment *DF,
257                             const MCAsmLayout &Layout) const {
258     // FIXME.
259     assert(0 && "RelaxInstruction() unimplemented");
260     return false;
261   }
262
263   /// RelaxInstruction - Relax the instruction in the given fragment
264   /// to the next wider instruction.
265   ///
266   /// \param Inst - The instruction to relax, which may be the same
267   /// as the output.
268   /// \param [out] Res On return, the relaxed instruction.
269   void relaxInstruction(const MCInst &Inst, MCInst &Res) const {
270   }
271
272   /// @}
273
274   /// WriteNopData - Write an (optimal) nop sequence of Count bytes
275   /// to the given output. If the target cannot generate such a sequence,
276   /// it should return an error.
277   ///
278   /// \return - True on success.
279   bool writeNopData(uint64_t Count, MCObjectWriter *OW) const {
280     // Check for a less than instruction size number of bytes
281     // FIXME: 16 bit instructions are not handled yet here.
282     // We shouldn't be using a hard coded number for instruction size.
283     if (Count % 4) return false;
284
285     uint64_t NumNops = Count / 4;
286     for (uint64_t i = 0; i != NumNops; ++i)
287       OW->Write32(0);
288     return true;
289   }
290
291   /// processFixupValue - Target hook to process the literal value of a fixup
292   /// if necessary.
293   void processFixupValue(const MCAssembler &Asm, const MCAsmLayout &Layout,
294                          const MCFixup &Fixup, const MCFragment *DF,
295                          MCValue &Target, uint64_t &Value,
296                          bool &IsResolved) {
297     // At this point we'll ignore the value returned by adjustFixupValue as
298     // we are only checking if the fixup can be applied correctly. We have
299     // access to MCContext from here which allows us to report a fatal error
300     // with *possibly* a source code location.
301     (void)adjustFixupValue(Fixup, Value, &Asm.getContext());
302   }
303
304 }; // class MipsAsmBackend
305
306 } // namespace
307
308 // MCAsmBackend
309 MCAsmBackend *llvm::createMipsAsmBackendEL32(const Target &T,
310                                              const MCRegisterInfo &MRI,
311                                              StringRef TT,
312                                              StringRef CPU) {
313   return new MipsAsmBackend(T, Triple(TT).getOS(),
314                             /*IsLittle*/true, /*Is64Bit*/false);
315 }
316
317 MCAsmBackend *llvm::createMipsAsmBackendEB32(const Target &T,
318                                              const MCRegisterInfo &MRI,
319                                              StringRef TT,
320                                              StringRef CPU) {
321   return new MipsAsmBackend(T, Triple(TT).getOS(),
322                             /*IsLittle*/false, /*Is64Bit*/false);
323 }
324
325 MCAsmBackend *llvm::createMipsAsmBackendEL64(const Target &T,
326                                              const MCRegisterInfo &MRI,
327                                              StringRef TT,
328                                              StringRef CPU) {
329   return new MipsAsmBackend(T, Triple(TT).getOS(),
330                             /*IsLittle*/true, /*Is64Bit*/true);
331 }
332
333 MCAsmBackend *llvm::createMipsAsmBackendEB64(const Target &T,
334                                              const MCRegisterInfo &MRI,
335                                              StringRef TT,
336                                              StringRef CPU) {
337   return new MipsAsmBackend(T, Triple(TT).getOS(),
338                             /*IsLittle*/false, /*Is64Bit*/true);
339 }
340