MipsMCCodeEmitter.cpp revision 0082717cb537e2d1424f755a49510fa9f9e67071
1//===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===//
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 MipsMCCodeEmitter class.
11//
12//===----------------------------------------------------------------------===//
13//
14#define DEBUG_TYPE "mccodeemitter"
15#include "MCTargetDesc/MipsBaseInfo.h"
16#include "MCTargetDesc/MipsFixupKinds.h"
17#include "MCTargetDesc/MipsMCTargetDesc.h"
18#include "llvm/ADT/APFloat.h"
19#include "llvm/ADT/Statistic.h"
20#include "llvm/MC/MCCodeEmitter.h"
21#include "llvm/MC/MCContext.h"
22#include "llvm/MC/MCExpr.h"
23#include "llvm/MC/MCInst.h"
24#include "llvm/MC/MCInstrInfo.h"
25#include "llvm/MC/MCRegisterInfo.h"
26#include "llvm/MC/MCSubtargetInfo.h"
27#include "llvm/Support/raw_ostream.h"
28
29#define GET_INSTRMAP_INFO
30#include "MipsGenInstrInfo.inc"
31
32using namespace llvm;
33
34namespace {
35class MipsMCCodeEmitter : public MCCodeEmitter {
36  MipsMCCodeEmitter(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION;
37  void operator=(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION;
38  const MCInstrInfo &MCII;
39  MCContext &Ctx;
40  const MCSubtargetInfo &STI;
41  bool IsLittleEndian;
42  bool IsMicroMips;
43
44public:
45  MipsMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_,
46                    const MCSubtargetInfo &sti, bool IsLittle) :
47    MCII(mcii), Ctx(Ctx_), STI (sti), IsLittleEndian(IsLittle) {
48      IsMicroMips = STI.getFeatureBits() & Mips::FeatureMicroMips;
49    }
50
51  ~MipsMCCodeEmitter() {}
52
53  void EmitByte(unsigned char C, raw_ostream &OS) const {
54    OS << (char)C;
55  }
56
57  void EmitInstruction(uint64_t Val, unsigned Size, raw_ostream &OS) const {
58    // Output the instruction encoding in little endian byte order.
59    // Little-endian byte ordering:
60    //   mips32r2:   4 | 3 | 2 | 1
61    //   microMIPS:  2 | 1 | 4 | 3
62    if (IsLittleEndian && Size == 4 && IsMicroMips) {
63      EmitInstruction(Val>>16, 2, OS);
64      EmitInstruction(Val, 2, OS);
65    } else {
66      for (unsigned i = 0; i < Size; ++i) {
67        unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8;
68        EmitByte((Val >> Shift) & 0xff, OS);
69      }
70    }
71  }
72
73  void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
74                         SmallVectorImpl<MCFixup> &Fixups) const;
75
76  // getBinaryCodeForInstr - TableGen'erated function for getting the
77  // binary encoding for an instruction.
78  uint64_t getBinaryCodeForInstr(const MCInst &MI,
79                                 SmallVectorImpl<MCFixup> &Fixups) const;
80
81  // getBranchJumpOpValue - Return binary encoding of the jump
82  // target operand. If the machine operand requires relocation,
83  // record the relocation and return zero.
84   unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
85                                 SmallVectorImpl<MCFixup> &Fixups) const;
86
87   // getBranchTargetOpValue - Return binary encoding of the branch
88   // target operand. If the machine operand requires relocation,
89   // record the relocation and return zero.
90  unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
91                                  SmallVectorImpl<MCFixup> &Fixups) const;
92
93   // getMachineOpValue - Return binary encoding of operand. If the machin
94   // operand requires relocation, record the relocation and return zero.
95  unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
96                             SmallVectorImpl<MCFixup> &Fixups) const;
97
98  unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
99                          SmallVectorImpl<MCFixup> &Fixups) const;
100  unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
101                                 SmallVectorImpl<MCFixup> &Fixups) const;
102  unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
103                              SmallVectorImpl<MCFixup> &Fixups) const;
104  unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
105                              SmallVectorImpl<MCFixup> &Fixups) const;
106
107  unsigned
108  getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const;
109
110}; // class MipsMCCodeEmitter
111}  // namespace
112
113MCCodeEmitter *llvm::createMipsMCCodeEmitterEB(const MCInstrInfo &MCII,
114                                               const MCRegisterInfo &MRI,
115                                               const MCSubtargetInfo &STI,
116                                               MCContext &Ctx)
117{
118  return new MipsMCCodeEmitter(MCII, Ctx, STI, false);
119}
120
121MCCodeEmitter *llvm::createMipsMCCodeEmitterEL(const MCInstrInfo &MCII,
122                                               const MCRegisterInfo &MRI,
123                                               const MCSubtargetInfo &STI,
124                                               MCContext &Ctx)
125{
126  return new MipsMCCodeEmitter(MCII, Ctx, STI, true);
127}
128
129
130// If the D<shift> instruction has a shift amount that is greater
131// than 31 (checked in calling routine), lower it to a D<shift>32 instruction
132static void LowerLargeShift(MCInst& Inst) {
133
134  assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!");
135  assert(Inst.getOperand(2).isImm());
136
137  int64_t Shift = Inst.getOperand(2).getImm();
138  if (Shift <= 31)
139    return; // Do nothing
140  Shift -= 32;
141
142  // saminus32
143  Inst.getOperand(2).setImm(Shift);
144
145  switch (Inst.getOpcode()) {
146  default:
147    // Calling function is not synchronized
148    llvm_unreachable("Unexpected shift instruction");
149  case Mips::DSLL:
150    Inst.setOpcode(Mips::DSLL32);
151    return;
152  case Mips::DSRL:
153    Inst.setOpcode(Mips::DSRL32);
154    return;
155  case Mips::DSRA:
156    Inst.setOpcode(Mips::DSRA32);
157    return;
158  case Mips::DROTR:
159    Inst.setOpcode(Mips::DROTR32);
160    return;
161  }
162}
163
164// Pick a DEXT or DINS instruction variant based on the pos and size operands
165static void LowerDextDins(MCInst& InstIn) {
166  int Opcode = InstIn.getOpcode();
167
168  if (Opcode == Mips::DEXT)
169    assert(InstIn.getNumOperands() == 4 &&
170           "Invalid no. of machine operands for DEXT!");
171  else // Only DEXT and DINS are possible
172    assert(InstIn.getNumOperands() == 5 &&
173           "Invalid no. of machine operands for DINS!");
174
175  assert(InstIn.getOperand(2).isImm());
176  int64_t pos = InstIn.getOperand(2).getImm();
177  assert(InstIn.getOperand(3).isImm());
178  int64_t size = InstIn.getOperand(3).getImm();
179
180  if (size <= 32) {
181    if (pos < 32)  // DEXT/DINS, do nothing
182      return;
183    // DEXTU/DINSU
184    InstIn.getOperand(2).setImm(pos - 32);
185    InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU);
186    return;
187  }
188  // DEXTM/DINSM
189  assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32");
190  InstIn.getOperand(3).setImm(size - 32);
191  InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM);
192  return;
193}
194
195/// EncodeInstruction - Emit the instruction.
196/// Size the instruction with Desc.getSize().
197void MipsMCCodeEmitter::
198EncodeInstruction(const MCInst &MI, raw_ostream &OS,
199                  SmallVectorImpl<MCFixup> &Fixups) const
200{
201
202  // Non-pseudo instructions that get changed for direct object
203  // only based on operand values.
204  // If this list of instructions get much longer we will move
205  // the check to a function call. Until then, this is more efficient.
206  MCInst TmpInst = MI;
207  switch (MI.getOpcode()) {
208  // If shift amount is >= 32 it the inst needs to be lowered further
209  case Mips::DSLL:
210  case Mips::DSRL:
211  case Mips::DSRA:
212  case Mips::DROTR:
213    LowerLargeShift(TmpInst);
214    break;
215    // Double extract instruction is chosen by pos and size operands
216  case Mips::DEXT:
217  case Mips::DINS:
218    LowerDextDins(TmpInst);
219  }
220
221  unsigned long N = Fixups.size();
222  uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups);
223
224  // Check for unimplemented opcodes.
225  // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0
226  // so we have to special check for them.
227  unsigned Opcode = TmpInst.getOpcode();
228  if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary)
229    llvm_unreachable("unimplemented opcode in EncodeInstruction()");
230
231  if (STI.getFeatureBits() & Mips::FeatureMicroMips) {
232    int NewOpcode = Mips::Std2MicroMips (Opcode, Mips::Arch_micromips);
233    if (NewOpcode != -1) {
234      if (Fixups.size() > N)
235        Fixups.pop_back();
236      Opcode = NewOpcode;
237      TmpInst.setOpcode (NewOpcode);
238      Binary = getBinaryCodeForInstr(TmpInst, Fixups);
239    }
240  }
241
242  const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode());
243
244  // Get byte count of instruction
245  unsigned Size = Desc.getSize();
246  if (!Size)
247    llvm_unreachable("Desc.getSize() returns 0");
248
249  EmitInstruction(Binary, Size, OS);
250}
251
252/// getBranchTargetOpValue - Return binary encoding of the branch
253/// target operand. If the machine operand requires relocation,
254/// record the relocation and return zero.
255unsigned MipsMCCodeEmitter::
256getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
257                       SmallVectorImpl<MCFixup> &Fixups) const {
258
259  const MCOperand &MO = MI.getOperand(OpNo);
260
261  // If the destination is an immediate, divide by 4.
262  if (MO.isImm()) return MO.getImm() >> 2;
263
264  assert(MO.isExpr() &&
265         "getBranchTargetOpValue expects only expressions or immediates");
266
267  const MCExpr *Expr = MO.getExpr();
268  Fixups.push_back(MCFixup::Create(0, Expr,
269                                   MCFixupKind(Mips::fixup_Mips_PC16)));
270  return 0;
271}
272
273/// getJumpTargetOpValue - Return binary encoding of the jump
274/// target operand. If the machine operand requires relocation,
275/// record the relocation and return zero.
276unsigned MipsMCCodeEmitter::
277getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
278                     SmallVectorImpl<MCFixup> &Fixups) const {
279
280  const MCOperand &MO = MI.getOperand(OpNo);
281  // If the destination is an immediate, divide by 4.
282  if (MO.isImm()) return MO.getImm()>>2;
283
284  assert(MO.isExpr() &&
285         "getJumpTargetOpValue expects only expressions or an immediate");
286
287  const MCExpr *Expr = MO.getExpr();
288  Fixups.push_back(MCFixup::Create(0, Expr,
289                                   MCFixupKind(Mips::fixup_Mips_26)));
290  return 0;
291}
292
293unsigned MipsMCCodeEmitter::
294getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups) const {
295  int64_t Res;
296
297  if (Expr->EvaluateAsAbsolute(Res))
298    return Res;
299
300  MCExpr::ExprKind Kind = Expr->getKind();
301  if (Kind == MCExpr::Constant) {
302    return cast<MCConstantExpr>(Expr)->getValue();
303  }
304
305  if (Kind == MCExpr::Binary) {
306    unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups);
307    Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups);
308    return Res;
309  }
310  if (Kind == MCExpr::SymbolRef) {
311  Mips::Fixups FixupKind = Mips::Fixups(0);
312
313  switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
314  default: llvm_unreachable("Unknown fixup kind!");
315    break;
316  case MCSymbolRefExpr::VK_Mips_GPOFF_HI :
317    FixupKind = Mips::fixup_Mips_GPOFF_HI;
318    break;
319  case MCSymbolRefExpr::VK_Mips_GPOFF_LO :
320    FixupKind = Mips::fixup_Mips_GPOFF_LO;
321    break;
322  case MCSymbolRefExpr::VK_Mips_GOT_PAGE :
323    FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_GOT_PAGE
324                            : Mips::fixup_Mips_GOT_PAGE;
325    break;
326  case MCSymbolRefExpr::VK_Mips_GOT_OFST :
327    FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_GOT_OFST
328                            : Mips::fixup_Mips_GOT_OFST;
329    break;
330  case MCSymbolRefExpr::VK_Mips_GOT_DISP :
331    FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_GOT_DISP
332                            : Mips::fixup_Mips_GOT_DISP;
333    break;
334  case MCSymbolRefExpr::VK_Mips_GPREL:
335    FixupKind = Mips::fixup_Mips_GPREL16;
336    break;
337  case MCSymbolRefExpr::VK_Mips_GOT_CALL:
338    FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_CALL16
339                            : Mips::fixup_Mips_CALL16;
340    break;
341  case MCSymbolRefExpr::VK_Mips_GOT16:
342    FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_GOT16
343                            : Mips::fixup_Mips_GOT_Global;
344    break;
345  case MCSymbolRefExpr::VK_Mips_GOT:
346    FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_GOT16
347                            : Mips::fixup_Mips_GOT_Local;
348    break;
349  case MCSymbolRefExpr::VK_Mips_ABS_HI:
350    FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_HI16
351                            : Mips::fixup_Mips_HI16;
352    break;
353  case MCSymbolRefExpr::VK_Mips_ABS_LO:
354    FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_LO16
355                            : Mips::fixup_Mips_LO16;
356    break;
357  case MCSymbolRefExpr::VK_Mips_TLSGD:
358    FixupKind = Mips::fixup_Mips_TLSGD;
359    break;
360  case MCSymbolRefExpr::VK_Mips_TLSLDM:
361    FixupKind = Mips::fixup_Mips_TLSLDM;
362    break;
363  case MCSymbolRefExpr::VK_Mips_DTPREL_HI:
364    FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16
365                            : Mips::fixup_Mips_DTPREL_HI;
366    break;
367  case MCSymbolRefExpr::VK_Mips_DTPREL_LO:
368    FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16
369                            : Mips::fixup_Mips_DTPREL_LO;
370    break;
371  case MCSymbolRefExpr::VK_Mips_GOTTPREL:
372    FixupKind = Mips::fixup_Mips_GOTTPREL;
373    break;
374  case MCSymbolRefExpr::VK_Mips_TPREL_HI:
375    FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16
376                            : Mips::fixup_Mips_TPREL_HI;
377    break;
378  case MCSymbolRefExpr::VK_Mips_TPREL_LO:
379    FixupKind = IsMicroMips ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16
380                            : Mips::fixup_Mips_TPREL_LO;
381    break;
382  case MCSymbolRefExpr::VK_Mips_HIGHER:
383    FixupKind = Mips::fixup_Mips_HIGHER;
384    break;
385  case MCSymbolRefExpr::VK_Mips_HIGHEST:
386    FixupKind = Mips::fixup_Mips_HIGHEST;
387    break;
388  case MCSymbolRefExpr::VK_Mips_GOT_HI16:
389    FixupKind = Mips::fixup_Mips_GOT_HI16;
390    break;
391  case MCSymbolRefExpr::VK_Mips_GOT_LO16:
392    FixupKind = Mips::fixup_Mips_GOT_LO16;
393    break;
394  case MCSymbolRefExpr::VK_Mips_CALL_HI16:
395    FixupKind = Mips::fixup_Mips_CALL_HI16;
396    break;
397  case MCSymbolRefExpr::VK_Mips_CALL_LO16:
398    FixupKind = Mips::fixup_Mips_CALL_LO16;
399    break;
400  } // switch
401
402    Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind)));
403    return 0;
404  }
405  return 0;
406}
407
408/// getMachineOpValue - Return binary encoding of operand. If the machine
409/// operand requires relocation, record the relocation and return zero.
410unsigned MipsMCCodeEmitter::
411getMachineOpValue(const MCInst &MI, const MCOperand &MO,
412                  SmallVectorImpl<MCFixup> &Fixups) const {
413  if (MO.isReg()) {
414    unsigned Reg = MO.getReg();
415    unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);
416    return RegNo;
417  } else if (MO.isImm()) {
418    return static_cast<unsigned>(MO.getImm());
419  } else if (MO.isFPImm()) {
420    return static_cast<unsigned>(APFloat(MO.getFPImm())
421        .bitcastToAPInt().getHiBits(32).getLimitedValue());
422  }
423  // MO must be an Expr.
424  assert(MO.isExpr());
425  return getExprOpValue(MO.getExpr(),Fixups);
426}
427
428/// getMemEncoding - Return binary encoding of memory related operand.
429/// If the offset operand requires relocation, record the relocation.
430unsigned
431MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
432                                  SmallVectorImpl<MCFixup> &Fixups) const {
433  // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
434  assert(MI.getOperand(OpNo).isReg());
435  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups) << 16;
436  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups);
437
438  return (OffBits & 0xFFFF) | RegBits;
439}
440
441unsigned MipsMCCodeEmitter::
442getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
443                      SmallVectorImpl<MCFixup> &Fixups) const {
444  // Base register is encoded in bits 20-16, offset is encoded in bits 11-0.
445  assert(MI.getOperand(OpNo).isReg());
446  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups) << 16;
447  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups);
448
449  return (OffBits & 0x0FFF) | RegBits;
450}
451
452unsigned
453MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
454                                      SmallVectorImpl<MCFixup> &Fixups) const {
455  assert(MI.getOperand(OpNo).isImm());
456  unsigned SizeEncoding = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups);
457  return SizeEncoding - 1;
458}
459
460// FIXME: should be called getMSBEncoding
461//
462unsigned
463MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
464                                      SmallVectorImpl<MCFixup> &Fixups) const {
465  assert(MI.getOperand(OpNo-1).isImm());
466  assert(MI.getOperand(OpNo).isImm());
467  unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups);
468  unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups);
469
470  return Position + Size - 1;
471}
472
473#include "MipsGenMCCodeEmitter.inc"
474
475