1234353Sdim//===-- MipsMCCodeEmitter.cpp - Convert Mips Code to Machine Code ---------===//
2226584Sdim//
3226584Sdim//                     The LLVM Compiler Infrastructure
4226584Sdim//
5226584Sdim// This file is distributed under the University of Illinois Open Source
6226584Sdim// License. See LICENSE.TXT for details.
7226584Sdim//
8226584Sdim//===----------------------------------------------------------------------===//
9226584Sdim//
10226584Sdim// This file implements the MipsMCCodeEmitter class.
11226584Sdim//
12226584Sdim//===----------------------------------------------------------------------===//
13226584Sdim//
14276479Sdim
15276479Sdim#include "MipsMCCodeEmitter.h"
16234353Sdim#include "MCTargetDesc/MipsFixupKinds.h"
17276479Sdim#include "MCTargetDesc/MipsMCExpr.h"
18234353Sdim#include "MCTargetDesc/MipsMCTargetDesc.h"
19234353Sdim#include "llvm/ADT/APFloat.h"
20276479Sdim#include "llvm/ADT/SmallVector.h"
21249423Sdim#include "llvm/MC/MCContext.h"
22226584Sdim#include "llvm/MC/MCExpr.h"
23280031Sdim#include "llvm/MC/MCFixup.h"
24226584Sdim#include "llvm/MC/MCInst.h"
25226584Sdim#include "llvm/MC/MCInstrInfo.h"
26288943Sdim#include "llvm/MC/MCRegisterInfo.h"
27226584Sdim#include "llvm/MC/MCSubtargetInfo.h"
28226584Sdim#include "llvm/Support/raw_ostream.h"
29226584Sdim
30276479Sdim#define DEBUG_TYPE "mccodeemitter"
31276479Sdim
32251662Sdim#define GET_INSTRMAP_INFO
33251662Sdim#include "MipsGenInstrInfo.inc"
34276479Sdim#undef GET_INSTRMAP_INFO
35251662Sdim
36276479Sdimnamespace llvm {
37276479SdimMCCodeEmitter *createMipsMCCodeEmitterEB(const MCInstrInfo &MCII,
38276479Sdim                                         const MCRegisterInfo &MRI,
39276479Sdim                                         MCContext &Ctx) {
40276479Sdim  return new MipsMCCodeEmitter(MCII, Ctx, false);
41226584Sdim}
42234353Sdim
43276479SdimMCCodeEmitter *createMipsMCCodeEmitterEL(const MCInstrInfo &MCII,
44276479Sdim                                         const MCRegisterInfo &MRI,
45276479Sdim                                         MCContext &Ctx) {
46276479Sdim  return new MipsMCCodeEmitter(MCII, Ctx, true);
47234353Sdim}
48276479Sdim} // End of namespace llvm.
49234353Sdim
50261991Sdim// If the D<shift> instruction has a shift amount that is greater
51261991Sdim// than 31 (checked in calling routine), lower it to a D<shift>32 instruction
52261991Sdimstatic void LowerLargeShift(MCInst& Inst) {
53261991Sdim
54261991Sdim  assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!");
55261991Sdim  assert(Inst.getOperand(2).isImm());
56261991Sdim
57261991Sdim  int64_t Shift = Inst.getOperand(2).getImm();
58261991Sdim  if (Shift <= 31)
59261991Sdim    return; // Do nothing
60261991Sdim  Shift -= 32;
61261991Sdim
62261991Sdim  // saminus32
63261991Sdim  Inst.getOperand(2).setImm(Shift);
64261991Sdim
65261991Sdim  switch (Inst.getOpcode()) {
66261991Sdim  default:
67261991Sdim    // Calling function is not synchronized
68261991Sdim    llvm_unreachable("Unexpected shift instruction");
69261991Sdim  case Mips::DSLL:
70261991Sdim    Inst.setOpcode(Mips::DSLL32);
71261991Sdim    return;
72261991Sdim  case Mips::DSRL:
73261991Sdim    Inst.setOpcode(Mips::DSRL32);
74261991Sdim    return;
75261991Sdim  case Mips::DSRA:
76261991Sdim    Inst.setOpcode(Mips::DSRA32);
77261991Sdim    return;
78261991Sdim  case Mips::DROTR:
79261991Sdim    Inst.setOpcode(Mips::DROTR32);
80261991Sdim    return;
81261991Sdim  }
82261991Sdim}
83261991Sdim
84261991Sdim// Pick a DEXT or DINS instruction variant based on the pos and size operands
85261991Sdimstatic void LowerDextDins(MCInst& InstIn) {
86261991Sdim  int Opcode = InstIn.getOpcode();
87261991Sdim
88261991Sdim  if (Opcode == Mips::DEXT)
89261991Sdim    assert(InstIn.getNumOperands() == 4 &&
90261991Sdim           "Invalid no. of machine operands for DEXT!");
91261991Sdim  else // Only DEXT and DINS are possible
92261991Sdim    assert(InstIn.getNumOperands() == 5 &&
93261991Sdim           "Invalid no. of machine operands for DINS!");
94261991Sdim
95261991Sdim  assert(InstIn.getOperand(2).isImm());
96261991Sdim  int64_t pos = InstIn.getOperand(2).getImm();
97261991Sdim  assert(InstIn.getOperand(3).isImm());
98261991Sdim  int64_t size = InstIn.getOperand(3).getImm();
99261991Sdim
100261991Sdim  if (size <= 32) {
101261991Sdim    if (pos < 32)  // DEXT/DINS, do nothing
102261991Sdim      return;
103261991Sdim    // DEXTU/DINSU
104261991Sdim    InstIn.getOperand(2).setImm(pos - 32);
105261991Sdim    InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU);
106261991Sdim    return;
107261991Sdim  }
108261991Sdim  // DEXTM/DINSM
109261991Sdim  assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32");
110261991Sdim  InstIn.getOperand(3).setImm(size - 32);
111261991Sdim  InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM);
112261991Sdim  return;
113261991Sdim}
114261991Sdim
115276479Sdimbool MipsMCCodeEmitter::isMicroMips(const MCSubtargetInfo &STI) const {
116288943Sdim  return STI.getFeatureBits()[Mips::FeatureMicroMips];
117276479Sdim}
118276479Sdim
119288943Sdimbool MipsMCCodeEmitter::isMips32r6(const MCSubtargetInfo &STI) const {
120288943Sdim  return STI.getFeatureBits()[Mips::FeatureMips32r6];
121288943Sdim}
122288943Sdim
123276479Sdimvoid MipsMCCodeEmitter::EmitByte(unsigned char C, raw_ostream &OS) const {
124276479Sdim  OS << (char)C;
125276479Sdim}
126276479Sdim
127276479Sdimvoid MipsMCCodeEmitter::EmitInstruction(uint64_t Val, unsigned Size,
128276479Sdim                                        const MCSubtargetInfo &STI,
129276479Sdim                                        raw_ostream &OS) const {
130276479Sdim  // Output the instruction encoding in little endian byte order.
131276479Sdim  // Little-endian byte ordering:
132276479Sdim  //   mips32r2:   4 | 3 | 2 | 1
133276479Sdim  //   microMIPS:  2 | 1 | 4 | 3
134276479Sdim  if (IsLittleEndian && Size == 4 && isMicroMips(STI)) {
135276479Sdim    EmitInstruction(Val >> 16, 2, STI, OS);
136276479Sdim    EmitInstruction(Val, 2, STI, OS);
137276479Sdim  } else {
138276479Sdim    for (unsigned i = 0; i < Size; ++i) {
139276479Sdim      unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8;
140276479Sdim      EmitByte((Val >> Shift) & 0xff, OS);
141276479Sdim    }
142276479Sdim  }
143276479Sdim}
144276479Sdim
145288943Sdim/// encodeInstruction - Emit the instruction.
146261991Sdim/// Size the instruction with Desc.getSize().
147234353Sdimvoid MipsMCCodeEmitter::
148288943SdimencodeInstruction(const MCInst &MI, raw_ostream &OS,
149276479Sdim                  SmallVectorImpl<MCFixup> &Fixups,
150276479Sdim                  const MCSubtargetInfo &STI) const
151234353Sdim{
152234353Sdim
153243830Sdim  // Non-pseudo instructions that get changed for direct object
154243830Sdim  // only based on operand values.
155243830Sdim  // If this list of instructions get much longer we will move
156243830Sdim  // the check to a function call. Until then, this is more efficient.
157243830Sdim  MCInst TmpInst = MI;
158243830Sdim  switch (MI.getOpcode()) {
159243830Sdim  // If shift amount is >= 32 it the inst needs to be lowered further
160243830Sdim  case Mips::DSLL:
161243830Sdim  case Mips::DSRL:
162243830Sdim  case Mips::DSRA:
163261991Sdim  case Mips::DROTR:
164261991Sdim    LowerLargeShift(TmpInst);
165243830Sdim    break;
166243830Sdim    // Double extract instruction is chosen by pos and size operands
167243830Sdim  case Mips::DEXT:
168243830Sdim  case Mips::DINS:
169261991Sdim    LowerDextDins(TmpInst);
170243830Sdim  }
171243830Sdim
172261991Sdim  unsigned long N = Fixups.size();
173276479Sdim  uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
174243830Sdim
175234353Sdim  // Check for unimplemented opcodes.
176243830Sdim  // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0
177234353Sdim  // so we have to special check for them.
178243830Sdim  unsigned Opcode = TmpInst.getOpcode();
179280031Sdim  if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) &&
180280031Sdim      (Opcode != Mips::SLL_MM) && !Binary)
181288943Sdim    llvm_unreachable("unimplemented opcode in encodeInstruction()");
182234353Sdim
183288943Sdim  int NewOpcode = -1;
184288943Sdim  if (isMicroMips(STI)) {
185288943Sdim    if (isMips32r6(STI)) {
186288943Sdim      NewOpcode = Mips::MipsR62MicroMipsR6(Opcode, Mips::Arch_micromipsr6);
187288943Sdim      if (NewOpcode == -1)
188288943Sdim        NewOpcode = Mips::Std2MicroMipsR6(Opcode, Mips::Arch_micromipsr6);
189288943Sdim    }
190288943Sdim    else
191288943Sdim      NewOpcode = Mips::Std2MicroMips(Opcode, Mips::Arch_micromips);
192288943Sdim
193296417Sdim    // Check whether it is Dsp instruction.
194296417Sdim    if (NewOpcode == -1)
195296417Sdim      NewOpcode = Mips::Dsp2MicroMips(Opcode, Mips::Arch_mmdsp);
196296417Sdim
197251662Sdim    if (NewOpcode != -1) {
198261991Sdim      if (Fixups.size() > N)
199261991Sdim        Fixups.pop_back();
200288943Sdim
201251662Sdim      Opcode = NewOpcode;
202251662Sdim      TmpInst.setOpcode (NewOpcode);
203276479Sdim      Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
204251662Sdim    }
205251662Sdim  }
206251662Sdim
207243830Sdim  const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode());
208234353Sdim
209243830Sdim  // Get byte count of instruction
210243830Sdim  unsigned Size = Desc.getSize();
211243830Sdim  if (!Size)
212243830Sdim    llvm_unreachable("Desc.getSize() returns 0");
213234353Sdim
214276479Sdim  EmitInstruction(Binary, Size, STI, OS);
215234353Sdim}
216234353Sdim
217234353Sdim/// getBranchTargetOpValue - Return binary encoding of the branch
218234353Sdim/// target operand. If the machine operand requires relocation,
219234353Sdim/// record the relocation and return zero.
220234353Sdimunsigned MipsMCCodeEmitter::
221234353SdimgetBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
222276479Sdim                       SmallVectorImpl<MCFixup> &Fixups,
223276479Sdim                       const MCSubtargetInfo &STI) const {
224234353Sdim
225234353Sdim  const MCOperand &MO = MI.getOperand(OpNo);
226234353Sdim
227249423Sdim  // If the destination is an immediate, divide by 4.
228249423Sdim  if (MO.isImm()) return MO.getImm() >> 2;
229249423Sdim
230243830Sdim  assert(MO.isExpr() &&
231243830Sdim         "getBranchTargetOpValue expects only expressions or immediates");
232243830Sdim
233288943Sdim  const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
234288943Sdim      MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
235288943Sdim  Fixups.push_back(MCFixup::create(0, FixupExpression,
236234353Sdim                                   MCFixupKind(Mips::fixup_Mips_PC16)));
237234353Sdim  return 0;
238234353Sdim}
239234353Sdim
240280031Sdim/// getBranchTarget7OpValueMM - Return binary encoding of the microMIPS branch
241280031Sdim/// target operand. If the machine operand requires relocation,
242280031Sdim/// record the relocation and return zero.
243280031Sdimunsigned MipsMCCodeEmitter::
244280031SdimgetBranchTarget7OpValueMM(const MCInst &MI, unsigned OpNo,
245280031Sdim                          SmallVectorImpl<MCFixup> &Fixups,
246280031Sdim                          const MCSubtargetInfo &STI) const {
247280031Sdim
248280031Sdim  const MCOperand &MO = MI.getOperand(OpNo);
249280031Sdim
250280031Sdim  // If the destination is an immediate, divide by 2.
251280031Sdim  if (MO.isImm()) return MO.getImm() >> 1;
252280031Sdim
253280031Sdim  assert(MO.isExpr() &&
254280031Sdim         "getBranchTargetOpValueMM expects only expressions or immediates");
255280031Sdim
256280031Sdim  const MCExpr *Expr = MO.getExpr();
257288943Sdim  Fixups.push_back(MCFixup::create(0, Expr,
258280031Sdim                                   MCFixupKind(Mips::fixup_MICROMIPS_PC7_S1)));
259280031Sdim  return 0;
260280031Sdim}
261280031Sdim
262288943Sdim/// getBranchTargetOpValueMMPC10 - Return binary encoding of the microMIPS
263288943Sdim/// 10-bit branch target operand. If the machine operand requires relocation,
264288943Sdim/// record the relocation and return zero.
265288943Sdimunsigned MipsMCCodeEmitter::
266288943SdimgetBranchTargetOpValueMMPC10(const MCInst &MI, unsigned OpNo,
267288943Sdim                             SmallVectorImpl<MCFixup> &Fixups,
268288943Sdim                             const MCSubtargetInfo &STI) const {
269288943Sdim
270288943Sdim  const MCOperand &MO = MI.getOperand(OpNo);
271288943Sdim
272288943Sdim  // If the destination is an immediate, divide by 2.
273288943Sdim  if (MO.isImm()) return MO.getImm() >> 1;
274288943Sdim
275288943Sdim  assert(MO.isExpr() &&
276288943Sdim         "getBranchTargetOpValuePC10 expects only expressions or immediates");
277288943Sdim
278288943Sdim  const MCExpr *Expr = MO.getExpr();
279288943Sdim  Fixups.push_back(MCFixup::create(0, Expr,
280288943Sdim                   MCFixupKind(Mips::fixup_MICROMIPS_PC10_S1)));
281288943Sdim  return 0;
282288943Sdim}
283288943Sdim
284261991Sdim/// getBranchTargetOpValue - Return binary encoding of the microMIPS branch
285261991Sdim/// target operand. If the machine operand requires relocation,
286261991Sdim/// record the relocation and return zero.
287261991Sdimunsigned MipsMCCodeEmitter::
288261991SdimgetBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo,
289276479Sdim                         SmallVectorImpl<MCFixup> &Fixups,
290276479Sdim                         const MCSubtargetInfo &STI) const {
291261991Sdim
292261991Sdim  const MCOperand &MO = MI.getOperand(OpNo);
293261991Sdim
294261991Sdim  // If the destination is an immediate, divide by 2.
295261991Sdim  if (MO.isImm()) return MO.getImm() >> 1;
296261991Sdim
297261991Sdim  assert(MO.isExpr() &&
298261991Sdim         "getBranchTargetOpValueMM expects only expressions or immediates");
299261991Sdim
300261991Sdim  const MCExpr *Expr = MO.getExpr();
301288943Sdim  Fixups.push_back(MCFixup::create(0, Expr,
302261991Sdim                   MCFixupKind(Mips::
303261991Sdim                               fixup_MICROMIPS_PC16_S1)));
304261991Sdim  return 0;
305261991Sdim}
306261991Sdim
307276479Sdim/// getBranchTarget21OpValue - Return binary encoding of the branch
308276479Sdim/// target operand. If the machine operand requires relocation,
309276479Sdim/// record the relocation and return zero.
310276479Sdimunsigned MipsMCCodeEmitter::
311276479SdimgetBranchTarget21OpValue(const MCInst &MI, unsigned OpNo,
312276479Sdim                         SmallVectorImpl<MCFixup> &Fixups,
313276479Sdim                         const MCSubtargetInfo &STI) const {
314276479Sdim
315276479Sdim  const MCOperand &MO = MI.getOperand(OpNo);
316276479Sdim
317276479Sdim  // If the destination is an immediate, divide by 4.
318276479Sdim  if (MO.isImm()) return MO.getImm() >> 2;
319276479Sdim
320276479Sdim  assert(MO.isExpr() &&
321276479Sdim         "getBranchTarget21OpValue expects only expressions or immediates");
322276479Sdim
323288943Sdim  const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
324288943Sdim      MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
325288943Sdim  Fixups.push_back(MCFixup::create(0, FixupExpression,
326276479Sdim                                   MCFixupKind(Mips::fixup_MIPS_PC21_S2)));
327276479Sdim  return 0;
328276479Sdim}
329276479Sdim
330276479Sdim/// getBranchTarget26OpValue - Return binary encoding of the branch
331276479Sdim/// target operand. If the machine operand requires relocation,
332276479Sdim/// record the relocation and return zero.
333276479Sdimunsigned MipsMCCodeEmitter::
334276479SdimgetBranchTarget26OpValue(const MCInst &MI, unsigned OpNo,
335276479Sdim                         SmallVectorImpl<MCFixup> &Fixups,
336276479Sdim                         const MCSubtargetInfo &STI) const {
337276479Sdim
338276479Sdim  const MCOperand &MO = MI.getOperand(OpNo);
339276479Sdim
340276479Sdim  // If the destination is an immediate, divide by 4.
341276479Sdim  if (MO.isImm()) return MO.getImm() >> 2;
342276479Sdim
343276479Sdim  assert(MO.isExpr() &&
344276479Sdim         "getBranchTarget26OpValue expects only expressions or immediates");
345276479Sdim
346288943Sdim  const MCExpr *FixupExpression = MCBinaryExpr::createAdd(
347288943Sdim      MO.getExpr(), MCConstantExpr::create(-4, Ctx), Ctx);
348288943Sdim  Fixups.push_back(MCFixup::create(0, FixupExpression,
349276479Sdim                                   MCFixupKind(Mips::fixup_MIPS_PC26_S2)));
350276479Sdim  return 0;
351276479Sdim}
352276479Sdim
353296417Sdim/// getBranchTarget26OpValueMM - Return binary encoding of the branch
354296417Sdim/// target operand. If the machine operand requires relocation,
355296417Sdim/// record the relocation and return zero.
356296417Sdimunsigned MipsMCCodeEmitter::getBranchTarget26OpValueMM(
357296417Sdim    const MCInst &MI, unsigned OpNo, SmallVectorImpl<MCFixup> &Fixups,
358296417Sdim    const MCSubtargetInfo &STI) const {
359296417Sdim
360296417Sdim  const MCOperand &MO = MI.getOperand(OpNo);
361296417Sdim
362296417Sdim  // If the destination is an immediate, divide by 2.
363296417Sdim  if (MO.isImm())
364296417Sdim    return MO.getImm() >> 1;
365296417Sdim
366296417Sdim  // TODO: Push 26 PC fixup.
367296417Sdim  return 0;
368296417Sdim}
369296417Sdim
370276479Sdim/// getJumpOffset16OpValue - Return binary encoding of the jump
371276479Sdim/// target operand. If the machine operand requires relocation,
372276479Sdim/// record the relocation and return zero.
373276479Sdimunsigned MipsMCCodeEmitter::
374276479SdimgetJumpOffset16OpValue(const MCInst &MI, unsigned OpNo,
375276479Sdim                       SmallVectorImpl<MCFixup> &Fixups,
376276479Sdim                       const MCSubtargetInfo &STI) const {
377276479Sdim
378276479Sdim  const MCOperand &MO = MI.getOperand(OpNo);
379276479Sdim
380276479Sdim  if (MO.isImm()) return MO.getImm();
381276479Sdim
382276479Sdim  assert(MO.isExpr() &&
383276479Sdim         "getJumpOffset16OpValue expects only expressions or an immediate");
384276479Sdim
385276479Sdim   // TODO: Push fixup.
386276479Sdim   return 0;
387276479Sdim}
388276479Sdim
389234353Sdim/// getJumpTargetOpValue - Return binary encoding of the jump
390234353Sdim/// target operand. If the machine operand requires relocation,
391234353Sdim/// record the relocation and return zero.
392234353Sdimunsigned MipsMCCodeEmitter::
393234353SdimgetJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
394276479Sdim                     SmallVectorImpl<MCFixup> &Fixups,
395276479Sdim                     const MCSubtargetInfo &STI) const {
396234353Sdim
397234353Sdim  const MCOperand &MO = MI.getOperand(OpNo);
398249423Sdim  // If the destination is an immediate, divide by 4.
399249423Sdim  if (MO.isImm()) return MO.getImm()>>2;
400249423Sdim
401243830Sdim  assert(MO.isExpr() &&
402243830Sdim         "getJumpTargetOpValue expects only expressions or an immediate");
403234353Sdim
404234353Sdim  const MCExpr *Expr = MO.getExpr();
405288943Sdim  Fixups.push_back(MCFixup::create(0, Expr,
406234353Sdim                                   MCFixupKind(Mips::fixup_Mips_26)));
407234353Sdim  return 0;
408234353Sdim}
409234353Sdim
410234353Sdimunsigned MipsMCCodeEmitter::
411261991SdimgetJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,
412276479Sdim                       SmallVectorImpl<MCFixup> &Fixups,
413276479Sdim                       const MCSubtargetInfo &STI) const {
414261991Sdim
415261991Sdim  const MCOperand &MO = MI.getOperand(OpNo);
416261991Sdim  // If the destination is an immediate, divide by 2.
417261991Sdim  if (MO.isImm()) return MO.getImm() >> 1;
418261991Sdim
419261991Sdim  assert(MO.isExpr() &&
420261991Sdim         "getJumpTargetOpValueMM expects only expressions or an immediate");
421261991Sdim
422261991Sdim  const MCExpr *Expr = MO.getExpr();
423288943Sdim  Fixups.push_back(MCFixup::create(0, Expr,
424261991Sdim                                   MCFixupKind(Mips::fixup_MICROMIPS_26_S1)));
425261991Sdim  return 0;
426261991Sdim}
427261991Sdim
428261991Sdimunsigned MipsMCCodeEmitter::
429280031SdimgetUImm5Lsl2Encoding(const MCInst &MI, unsigned OpNo,
430280031Sdim                     SmallVectorImpl<MCFixup> &Fixups,
431280031Sdim                     const MCSubtargetInfo &STI) const {
432280031Sdim
433280031Sdim  const MCOperand &MO = MI.getOperand(OpNo);
434280031Sdim  if (MO.isImm()) {
435280031Sdim    // The immediate is encoded as 'immediate << 2'.
436280031Sdim    unsigned Res = getMachineOpValue(MI, MO, Fixups, STI);
437280031Sdim    assert((Res & 3) == 0);
438280031Sdim    return Res >> 2;
439280031Sdim  }
440280031Sdim
441280031Sdim  assert(MO.isExpr() &&
442280031Sdim         "getUImm5Lsl2Encoding expects only expressions or an immediate");
443280031Sdim
444280031Sdim  return 0;
445280031Sdim}
446280031Sdim
447280031Sdimunsigned MipsMCCodeEmitter::
448280031SdimgetSImm3Lsa2Value(const MCInst &MI, unsigned OpNo,
449280031Sdim                  SmallVectorImpl<MCFixup> &Fixups,
450280031Sdim                  const MCSubtargetInfo &STI) const {
451280031Sdim
452280031Sdim  const MCOperand &MO = MI.getOperand(OpNo);
453280031Sdim  if (MO.isImm()) {
454280031Sdim    int Value = MO.getImm();
455280031Sdim    return Value >> 2;
456280031Sdim  }
457280031Sdim
458280031Sdim  return 0;
459280031Sdim}
460280031Sdim
461280031Sdimunsigned MipsMCCodeEmitter::
462280031SdimgetUImm6Lsl2Encoding(const MCInst &MI, unsigned OpNo,
463280031Sdim                     SmallVectorImpl<MCFixup> &Fixups,
464280031Sdim                     const MCSubtargetInfo &STI) const {
465280031Sdim
466280031Sdim  const MCOperand &MO = MI.getOperand(OpNo);
467280031Sdim  if (MO.isImm()) {
468280031Sdim    unsigned Value = MO.getImm();
469280031Sdim    return Value >> 2;
470280031Sdim  }
471280031Sdim
472280031Sdim  return 0;
473280031Sdim}
474280031Sdim
475280031Sdimunsigned MipsMCCodeEmitter::
476280031SdimgetSImm9AddiuspValue(const MCInst &MI, unsigned OpNo,
477280031Sdim                     SmallVectorImpl<MCFixup> &Fixups,
478280031Sdim                     const MCSubtargetInfo &STI) const {
479280031Sdim
480280031Sdim  const MCOperand &MO = MI.getOperand(OpNo);
481280031Sdim  if (MO.isImm()) {
482280031Sdim    unsigned Binary = (MO.getImm() >> 2) & 0x0000ffff;
483280031Sdim    return (((Binary & 0x8000) >> 7) | (Binary & 0x00ff));
484280031Sdim  }
485280031Sdim
486280031Sdim  return 0;
487280031Sdim}
488280031Sdim
489280031Sdimunsigned MipsMCCodeEmitter::
490288943SdimgetExprOpValue(const MCExpr *Expr, SmallVectorImpl<MCFixup> &Fixups,
491276479Sdim               const MCSubtargetInfo &STI) const {
492251662Sdim  int64_t Res;
493234353Sdim
494288943Sdim  if (Expr->evaluateAsAbsolute(Res))
495251662Sdim    return Res;
496234353Sdim
497234353Sdim  MCExpr::ExprKind Kind = Expr->getKind();
498251662Sdim  if (Kind == MCExpr::Constant) {
499251662Sdim    return cast<MCConstantExpr>(Expr)->getValue();
500251662Sdim  }
501234353Sdim
502234353Sdim  if (Kind == MCExpr::Binary) {
503276479Sdim    unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI);
504276479Sdim    Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups, STI);
505251662Sdim    return Res;
506234353Sdim  }
507276479Sdim
508276479Sdim  if (Kind == MCExpr::Target) {
509276479Sdim    const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr);
510276479Sdim
511276479Sdim    Mips::Fixups FixupKind = Mips::Fixups(0);
512276479Sdim    switch (MipsExpr->getKind()) {
513276479Sdim    default: llvm_unreachable("Unsupported fixup kind for target expression!");
514276479Sdim    case MipsMCExpr::VK_Mips_HIGHEST:
515276479Sdim      FixupKind = Mips::fixup_Mips_HIGHEST;
516276479Sdim      break;
517276479Sdim    case MipsMCExpr::VK_Mips_HIGHER:
518276479Sdim      FixupKind = Mips::fixup_Mips_HIGHER;
519276479Sdim      break;
520276479Sdim    case MipsMCExpr::VK_Mips_HI:
521276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
522276479Sdim                                   : Mips::fixup_Mips_HI16;
523276479Sdim      break;
524276479Sdim    case MipsMCExpr::VK_Mips_LO:
525276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
526276479Sdim                                   : Mips::fixup_Mips_LO16;
527276479Sdim      break;
528276479Sdim    }
529288943Sdim    Fixups.push_back(MCFixup::create(0, MipsExpr, MCFixupKind(FixupKind)));
530276479Sdim    return 0;
531276479Sdim  }
532276479Sdim
533251662Sdim  if (Kind == MCExpr::SymbolRef) {
534276479Sdim    Mips::Fixups FixupKind = Mips::Fixups(0);
535234353Sdim
536276479Sdim    switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
537276479Sdim    default: llvm_unreachable("Unknown fixup kind!");
538276479Sdim      break;
539288943Sdim    case MCSymbolRefExpr::VK_None:
540288943Sdim      FixupKind = Mips::fixup_Mips_32; // FIXME: This is ok for O32/N32 but not N64.
541288943Sdim      break;
542276479Sdim    case MCSymbolRefExpr::VK_Mips_GPOFF_HI :
543276479Sdim      FixupKind = Mips::fixup_Mips_GPOFF_HI;
544276479Sdim      break;
545276479Sdim    case MCSymbolRefExpr::VK_Mips_GPOFF_LO :
546276479Sdim      FixupKind = Mips::fixup_Mips_GPOFF_LO;
547276479Sdim      break;
548276479Sdim    case MCSymbolRefExpr::VK_Mips_GOT_PAGE :
549276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE
550276479Sdim                              : Mips::fixup_Mips_GOT_PAGE;
551276479Sdim      break;
552276479Sdim    case MCSymbolRefExpr::VK_Mips_GOT_OFST :
553276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST
554276479Sdim                              : Mips::fixup_Mips_GOT_OFST;
555276479Sdim      break;
556276479Sdim    case MCSymbolRefExpr::VK_Mips_GOT_DISP :
557276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP
558276479Sdim                              : Mips::fixup_Mips_GOT_DISP;
559276479Sdim      break;
560276479Sdim    case MCSymbolRefExpr::VK_Mips_GPREL:
561276479Sdim      FixupKind = Mips::fixup_Mips_GPREL16;
562276479Sdim      break;
563276479Sdim    case MCSymbolRefExpr::VK_Mips_GOT_CALL:
564276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16
565276479Sdim                              : Mips::fixup_Mips_CALL16;
566276479Sdim      break;
567276479Sdim    case MCSymbolRefExpr::VK_Mips_GOT16:
568276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
569276479Sdim                              : Mips::fixup_Mips_GOT_Global;
570276479Sdim      break;
571276479Sdim    case MCSymbolRefExpr::VK_Mips_GOT:
572276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
573276479Sdim                              : Mips::fixup_Mips_GOT_Local;
574276479Sdim      break;
575276479Sdim    case MCSymbolRefExpr::VK_Mips_ABS_HI:
576276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
577276479Sdim                              : Mips::fixup_Mips_HI16;
578276479Sdim      break;
579276479Sdim    case MCSymbolRefExpr::VK_Mips_ABS_LO:
580276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
581276479Sdim                              : Mips::fixup_Mips_LO16;
582276479Sdim      break;
583276479Sdim    case MCSymbolRefExpr::VK_Mips_TLSGD:
584276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD
585276479Sdim                              : Mips::fixup_Mips_TLSGD;
586276479Sdim      break;
587276479Sdim    case MCSymbolRefExpr::VK_Mips_TLSLDM:
588276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM
589276479Sdim                              : Mips::fixup_Mips_TLSLDM;
590276479Sdim      break;
591276479Sdim    case MCSymbolRefExpr::VK_Mips_DTPREL_HI:
592276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16
593276479Sdim                              : Mips::fixup_Mips_DTPREL_HI;
594276479Sdim      break;
595276479Sdim    case MCSymbolRefExpr::VK_Mips_DTPREL_LO:
596276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16
597276479Sdim                              : Mips::fixup_Mips_DTPREL_LO;
598276479Sdim      break;
599276479Sdim    case MCSymbolRefExpr::VK_Mips_GOTTPREL:
600276479Sdim      FixupKind = Mips::fixup_Mips_GOTTPREL;
601276479Sdim      break;
602276479Sdim    case MCSymbolRefExpr::VK_Mips_TPREL_HI:
603276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16
604276479Sdim                              : Mips::fixup_Mips_TPREL_HI;
605276479Sdim      break;
606276479Sdim    case MCSymbolRefExpr::VK_Mips_TPREL_LO:
607276479Sdim      FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16
608276479Sdim                              : Mips::fixup_Mips_TPREL_LO;
609276479Sdim      break;
610276479Sdim    case MCSymbolRefExpr::VK_Mips_HIGHER:
611276479Sdim      FixupKind = Mips::fixup_Mips_HIGHER;
612276479Sdim      break;
613276479Sdim    case MCSymbolRefExpr::VK_Mips_HIGHEST:
614276479Sdim      FixupKind = Mips::fixup_Mips_HIGHEST;
615276479Sdim      break;
616276479Sdim    case MCSymbolRefExpr::VK_Mips_GOT_HI16:
617276479Sdim      FixupKind = Mips::fixup_Mips_GOT_HI16;
618276479Sdim      break;
619276479Sdim    case MCSymbolRefExpr::VK_Mips_GOT_LO16:
620276479Sdim      FixupKind = Mips::fixup_Mips_GOT_LO16;
621276479Sdim      break;
622276479Sdim    case MCSymbolRefExpr::VK_Mips_CALL_HI16:
623276479Sdim      FixupKind = Mips::fixup_Mips_CALL_HI16;
624276479Sdim      break;
625276479Sdim    case MCSymbolRefExpr::VK_Mips_CALL_LO16:
626276479Sdim      FixupKind = Mips::fixup_Mips_CALL_LO16;
627276479Sdim      break;
628276479Sdim    case MCSymbolRefExpr::VK_Mips_PCREL_HI16:
629276479Sdim      FixupKind = Mips::fixup_MIPS_PCHI16;
630276479Sdim      break;
631276479Sdim    case MCSymbolRefExpr::VK_Mips_PCREL_LO16:
632276479Sdim      FixupKind = Mips::fixup_MIPS_PCLO16;
633276479Sdim      break;
634276479Sdim    } // switch
635234353Sdim
636288943Sdim    Fixups.push_back(MCFixup::create(0, Expr, MCFixupKind(FixupKind)));
637251662Sdim    return 0;
638251662Sdim  }
639234353Sdim  return 0;
640234353Sdim}
641234353Sdim
642251662Sdim/// getMachineOpValue - Return binary encoding of operand. If the machine
643251662Sdim/// operand requires relocation, record the relocation and return zero.
644251662Sdimunsigned MipsMCCodeEmitter::
645251662SdimgetMachineOpValue(const MCInst &MI, const MCOperand &MO,
646276479Sdim                  SmallVectorImpl<MCFixup> &Fixups,
647276479Sdim                  const MCSubtargetInfo &STI) const {
648251662Sdim  if (MO.isReg()) {
649251662Sdim    unsigned Reg = MO.getReg();
650261991Sdim    unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);
651251662Sdim    return RegNo;
652251662Sdim  } else if (MO.isImm()) {
653251662Sdim    return static_cast<unsigned>(MO.getImm());
654251662Sdim  } else if (MO.isFPImm()) {
655251662Sdim    return static_cast<unsigned>(APFloat(MO.getFPImm())
656251662Sdim        .bitcastToAPInt().getHiBits(32).getLimitedValue());
657251662Sdim  }
658251662Sdim  // MO must be an Expr.
659251662Sdim  assert(MO.isExpr());
660276479Sdim  return getExprOpValue(MO.getExpr(),Fixups, STI);
661251662Sdim}
662251662Sdim
663276479Sdim/// getMSAMemEncoding - Return binary encoding of memory operand for LD/ST
664276479Sdim/// instructions.
665276479Sdimunsigned
666276479SdimMipsMCCodeEmitter::getMSAMemEncoding(const MCInst &MI, unsigned OpNo,
667276479Sdim                                     SmallVectorImpl<MCFixup> &Fixups,
668276479Sdim                                     const MCSubtargetInfo &STI) const {
669276479Sdim  // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
670276479Sdim  assert(MI.getOperand(OpNo).isReg());
671276479Sdim  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16;
672276479Sdim  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
673276479Sdim
674276479Sdim  // The immediate field of an LD/ST instruction is scaled which means it must
675276479Sdim  // be divided (when encoding) by the size (in bytes) of the instructions'
676276479Sdim  // data format.
677276479Sdim  // .b - 1 byte
678276479Sdim  // .h - 2 bytes
679276479Sdim  // .w - 4 bytes
680276479Sdim  // .d - 8 bytes
681276479Sdim  switch(MI.getOpcode())
682276479Sdim  {
683276479Sdim  default:
684276479Sdim    assert (0 && "Unexpected instruction");
685276479Sdim    break;
686276479Sdim  case Mips::LD_B:
687276479Sdim  case Mips::ST_B:
688276479Sdim    // We don't need to scale the offset in this case
689276479Sdim    break;
690276479Sdim  case Mips::LD_H:
691276479Sdim  case Mips::ST_H:
692276479Sdim    OffBits >>= 1;
693276479Sdim    break;
694276479Sdim  case Mips::LD_W:
695276479Sdim  case Mips::ST_W:
696276479Sdim    OffBits >>= 2;
697276479Sdim    break;
698276479Sdim  case Mips::LD_D:
699276479Sdim  case Mips::ST_D:
700276479Sdim    OffBits >>= 3;
701276479Sdim    break;
702276479Sdim  }
703276479Sdim
704276479Sdim  return (OffBits & 0xFFFF) | RegBits;
705276479Sdim}
706276479Sdim
707234353Sdim/// getMemEncoding - Return binary encoding of memory related operand.
708234353Sdim/// If the offset operand requires relocation, record the relocation.
709234353Sdimunsigned
710234353SdimMipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
711276479Sdim                                  SmallVectorImpl<MCFixup> &Fixups,
712276479Sdim                                  const MCSubtargetInfo &STI) const {
713234353Sdim  // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
714234353Sdim  assert(MI.getOperand(OpNo).isReg());
715276479Sdim  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16;
716276479Sdim  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
717234353Sdim
718234353Sdim  return (OffBits & 0xFFFF) | RegBits;
719234353Sdim}
720234353Sdim
721261991Sdimunsigned MipsMCCodeEmitter::
722280031SdimgetMemEncodingMMImm4(const MCInst &MI, unsigned OpNo,
723280031Sdim                     SmallVectorImpl<MCFixup> &Fixups,
724280031Sdim                     const MCSubtargetInfo &STI) const {
725280031Sdim  // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
726280031Sdim  assert(MI.getOperand(OpNo).isReg());
727280031Sdim  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
728280031Sdim                                       Fixups, STI) << 4;
729280031Sdim  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
730280031Sdim                                       Fixups, STI);
731280031Sdim
732280031Sdim  return (OffBits & 0xF) | RegBits;
733280031Sdim}
734280031Sdim
735280031Sdimunsigned MipsMCCodeEmitter::
736280031SdimgetMemEncodingMMImm4Lsl1(const MCInst &MI, unsigned OpNo,
737280031Sdim                         SmallVectorImpl<MCFixup> &Fixups,
738280031Sdim                         const MCSubtargetInfo &STI) const {
739280031Sdim  // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
740280031Sdim  assert(MI.getOperand(OpNo).isReg());
741280031Sdim  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
742280031Sdim                                       Fixups, STI) << 4;
743280031Sdim  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
744280031Sdim                                       Fixups, STI) >> 1;
745280031Sdim
746280031Sdim  return (OffBits & 0xF) | RegBits;
747280031Sdim}
748280031Sdim
749280031Sdimunsigned MipsMCCodeEmitter::
750280031SdimgetMemEncodingMMImm4Lsl2(const MCInst &MI, unsigned OpNo,
751280031Sdim                         SmallVectorImpl<MCFixup> &Fixups,
752280031Sdim                         const MCSubtargetInfo &STI) const {
753280031Sdim  // Base register is encoded in bits 6-4, offset is encoded in bits 3-0.
754280031Sdim  assert(MI.getOperand(OpNo).isReg());
755280031Sdim  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),
756280031Sdim                                       Fixups, STI) << 4;
757280031Sdim  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
758280031Sdim                                       Fixups, STI) >> 2;
759280031Sdim
760280031Sdim  return (OffBits & 0xF) | RegBits;
761280031Sdim}
762280031Sdim
763280031Sdimunsigned MipsMCCodeEmitter::
764280031SdimgetMemEncodingMMSPImm5Lsl2(const MCInst &MI, unsigned OpNo,
765280031Sdim                           SmallVectorImpl<MCFixup> &Fixups,
766280031Sdim                           const MCSubtargetInfo &STI) const {
767280031Sdim  // Register is encoded in bits 9-5, offset is encoded in bits 4-0.
768280031Sdim  assert(MI.getOperand(OpNo).isReg() &&
769296417Sdim         (MI.getOperand(OpNo).getReg() == Mips::SP ||
770296417Sdim         MI.getOperand(OpNo).getReg() == Mips::SP_64) &&
771280031Sdim         "Unexpected base register!");
772280031Sdim  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
773280031Sdim                                       Fixups, STI) >> 2;
774280031Sdim
775280031Sdim  return OffBits & 0x1F;
776280031Sdim}
777280031Sdim
778280031Sdimunsigned MipsMCCodeEmitter::
779288943SdimgetMemEncodingMMGPImm7Lsl2(const MCInst &MI, unsigned OpNo,
780288943Sdim                           SmallVectorImpl<MCFixup> &Fixups,
781288943Sdim                           const MCSubtargetInfo &STI) const {
782288943Sdim  // Register is encoded in bits 9-7, offset is encoded in bits 6-0.
783288943Sdim  assert(MI.getOperand(OpNo).isReg() &&
784288943Sdim         MI.getOperand(OpNo).getReg() == Mips::GP &&
785288943Sdim         "Unexpected base register!");
786288943Sdim
787288943Sdim  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1),
788288943Sdim                                       Fixups, STI) >> 2;
789288943Sdim
790288943Sdim  return OffBits & 0x7F;
791288943Sdim}
792288943Sdim
793288943Sdimunsigned MipsMCCodeEmitter::
794296417SdimgetMemEncodingMMImm9(const MCInst &MI, unsigned OpNo,
795296417Sdim                     SmallVectorImpl<MCFixup> &Fixups,
796296417Sdim                     const MCSubtargetInfo &STI) const {
797296417Sdim  // Base register is encoded in bits 20-16, offset is encoded in bits 8-0.
798296417Sdim  assert(MI.getOperand(OpNo).isReg());
799296417Sdim  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,
800296417Sdim                                       STI) << 16;
801296417Sdim  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo + 1), Fixups, STI);
802296417Sdim
803296417Sdim  return (OffBits & 0x1FF) | RegBits;
804296417Sdim}
805296417Sdim
806296417Sdimunsigned MipsMCCodeEmitter::
807261991SdimgetMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
808276479Sdim                      SmallVectorImpl<MCFixup> &Fixups,
809276479Sdim                      const MCSubtargetInfo &STI) const {
810280031Sdim  // opNum can be invalid if instruction had reglist as operand.
811280031Sdim  // MemOperand is always last operand of instruction (base + offset).
812280031Sdim  switch (MI.getOpcode()) {
813280031Sdim  default:
814280031Sdim    break;
815280031Sdim  case Mips::SWM32_MM:
816280031Sdim  case Mips::LWM32_MM:
817280031Sdim    OpNo = MI.getNumOperands() - 2;
818280031Sdim    break;
819280031Sdim  }
820280031Sdim
821261991Sdim  // Base register is encoded in bits 20-16, offset is encoded in bits 11-0.
822261991Sdim  assert(MI.getOperand(OpNo).isReg());
823276479Sdim  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) << 16;
824276479Sdim  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
825261991Sdim
826261991Sdim  return (OffBits & 0x0FFF) | RegBits;
827261991Sdim}
828261991Sdim
829280031Sdimunsigned MipsMCCodeEmitter::
830296417SdimgetMemEncodingMMImm16(const MCInst &MI, unsigned OpNo,
831296417Sdim                      SmallVectorImpl<MCFixup> &Fixups,
832296417Sdim                      const MCSubtargetInfo &STI) const {
833296417Sdim  // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
834296417Sdim  assert(MI.getOperand(OpNo).isReg());
835296417Sdim  unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups,
836296417Sdim                                       STI) << 16;
837296417Sdim  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
838296417Sdim
839296417Sdim  return (OffBits & 0xFFFF) | RegBits;
840296417Sdim}
841296417Sdim
842296417Sdimunsigned MipsMCCodeEmitter::
843280031SdimgetMemEncodingMMImm4sp(const MCInst &MI, unsigned OpNo,
844280031Sdim                       SmallVectorImpl<MCFixup> &Fixups,
845280031Sdim                       const MCSubtargetInfo &STI) const {
846280031Sdim  // opNum can be invalid if instruction had reglist as operand
847280031Sdim  // MemOperand is always last operand of instruction (base + offset)
848280031Sdim  switch (MI.getOpcode()) {
849280031Sdim  default:
850280031Sdim    break;
851280031Sdim  case Mips::SWM16_MM:
852296417Sdim  case Mips::SWM16_MMR6:
853280031Sdim  case Mips::LWM16_MM:
854296417Sdim  case Mips::LWM16_MMR6:
855280031Sdim    OpNo = MI.getNumOperands() - 2;
856280031Sdim    break;
857280031Sdim  }
858280031Sdim
859280031Sdim  // Offset is encoded in bits 4-0.
860280031Sdim  assert(MI.getOperand(OpNo).isReg());
861280031Sdim  // Base register is always SP - thus it is not encoded.
862280031Sdim  assert(MI.getOperand(OpNo+1).isImm());
863280031Sdim  unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
864280031Sdim
865280031Sdim  return ((OffBits >> 2) & 0x0F);
866280031Sdim}
867280031Sdim
868234353Sdim// FIXME: should be called getMSBEncoding
869234353Sdim//
870234353Sdimunsigned
871234353SdimMipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
872276479Sdim                                      SmallVectorImpl<MCFixup> &Fixups,
873276479Sdim                                      const MCSubtargetInfo &STI) const {
874234353Sdim  assert(MI.getOperand(OpNo-1).isImm());
875234353Sdim  assert(MI.getOperand(OpNo).isImm());
876276479Sdim  unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups, STI);
877276479Sdim  unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
878234353Sdim
879234353Sdim  return Position + Size - 1;
880234353Sdim}
881234353Sdim
882296417Sdimtemplate <unsigned Bits, int Offset>
883261991Sdimunsigned
884296417SdimMipsMCCodeEmitter::getUImmWithOffsetEncoding(const MCInst &MI, unsigned OpNo,
885296417Sdim                                             SmallVectorImpl<MCFixup> &Fixups,
886296417Sdim                                             const MCSubtargetInfo &STI) const {
887261991Sdim  assert(MI.getOperand(OpNo).isImm());
888296417Sdim  unsigned Value = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
889296417Sdim  Value -= Offset;
890296417Sdim  return Value;
891261991Sdim}
892261991Sdim
893276479Sdimunsigned
894276479SdimMipsMCCodeEmitter::getSimm19Lsl2Encoding(const MCInst &MI, unsigned OpNo,
895276479Sdim                                         SmallVectorImpl<MCFixup> &Fixups,
896276479Sdim                                         const MCSubtargetInfo &STI) const {
897276479Sdim  const MCOperand &MO = MI.getOperand(OpNo);
898276479Sdim  if (MO.isImm()) {
899276479Sdim    // The immediate is encoded as 'immediate << 2'.
900276479Sdim    unsigned Res = getMachineOpValue(MI, MO, Fixups, STI);
901276479Sdim    assert((Res & 3) == 0);
902276479Sdim    return Res >> 2;
903276479Sdim  }
904276479Sdim
905276479Sdim  assert(MO.isExpr() &&
906276479Sdim         "getSimm19Lsl2Encoding expects only expressions or an immediate");
907276479Sdim
908276479Sdim  const MCExpr *Expr = MO.getExpr();
909288943Sdim  Fixups.push_back(MCFixup::create(0, Expr,
910276479Sdim                                   MCFixupKind(Mips::fixup_MIPS_PC19_S2)));
911276479Sdim  return 0;
912276479Sdim}
913276479Sdim
914276479Sdimunsigned
915276479SdimMipsMCCodeEmitter::getSimm18Lsl3Encoding(const MCInst &MI, unsigned OpNo,
916276479Sdim                                         SmallVectorImpl<MCFixup> &Fixups,
917276479Sdim                                         const MCSubtargetInfo &STI) const {
918276479Sdim  const MCOperand &MO = MI.getOperand(OpNo);
919276479Sdim  if (MO.isImm()) {
920276479Sdim    // The immediate is encoded as 'immediate << 3'.
921276479Sdim    unsigned Res = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
922276479Sdim    assert((Res & 7) == 0);
923276479Sdim    return Res >> 3;
924276479Sdim  }
925276479Sdim
926276479Sdim  assert(MO.isExpr() &&
927276479Sdim         "getSimm18Lsl2Encoding expects only expressions or an immediate");
928276479Sdim
929276479Sdim  const MCExpr *Expr = MO.getExpr();
930288943Sdim  Fixups.push_back(MCFixup::create(0, Expr,
931276479Sdim                                   MCFixupKind(Mips::fixup_MIPS_PC18_S3)));
932276479Sdim  return 0;
933276479Sdim}
934276479Sdim
935280031Sdimunsigned
936280031SdimMipsMCCodeEmitter::getUImm3Mod8Encoding(const MCInst &MI, unsigned OpNo,
937280031Sdim                                        SmallVectorImpl<MCFixup> &Fixups,
938280031Sdim                                        const MCSubtargetInfo &STI) const {
939280031Sdim  assert(MI.getOperand(OpNo).isImm());
940280031Sdim  const MCOperand &MO = MI.getOperand(OpNo);
941280031Sdim  return MO.getImm() % 8;
942280031Sdim}
943280031Sdim
944280031Sdimunsigned
945280031SdimMipsMCCodeEmitter::getUImm4AndValue(const MCInst &MI, unsigned OpNo,
946280031Sdim                                    SmallVectorImpl<MCFixup> &Fixups,
947280031Sdim                                    const MCSubtargetInfo &STI) const {
948280031Sdim  assert(MI.getOperand(OpNo).isImm());
949280031Sdim  const MCOperand &MO = MI.getOperand(OpNo);
950280031Sdim  unsigned Value = MO.getImm();
951280031Sdim  switch (Value) {
952280031Sdim    case 128:   return 0x0;
953280031Sdim    case 1:     return 0x1;
954280031Sdim    case 2:     return 0x2;
955280031Sdim    case 3:     return 0x3;
956280031Sdim    case 4:     return 0x4;
957280031Sdim    case 7:     return 0x5;
958280031Sdim    case 8:     return 0x6;
959280031Sdim    case 15:    return 0x7;
960280031Sdim    case 16:    return 0x8;
961280031Sdim    case 31:    return 0x9;
962280031Sdim    case 32:    return 0xa;
963280031Sdim    case 63:    return 0xb;
964280031Sdim    case 64:    return 0xc;
965280031Sdim    case 255:   return 0xd;
966280031Sdim    case 32768: return 0xe;
967280031Sdim    case 65535: return 0xf;
968280031Sdim  }
969280031Sdim  llvm_unreachable("Unexpected value");
970280031Sdim}
971280031Sdim
972280031Sdimunsigned
973280031SdimMipsMCCodeEmitter::getRegisterListOpValue(const MCInst &MI, unsigned OpNo,
974280031Sdim                                          SmallVectorImpl<MCFixup> &Fixups,
975280031Sdim                                          const MCSubtargetInfo &STI) const {
976280031Sdim  unsigned res = 0;
977280031Sdim
978280031Sdim  // Register list operand is always first operand of instruction and it is
979280031Sdim  // placed before memory operand (register + imm).
980280031Sdim
981280031Sdim  for (unsigned I = OpNo, E = MI.getNumOperands() - 2; I < E; ++I) {
982280031Sdim    unsigned Reg = MI.getOperand(I).getReg();
983280031Sdim    unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);
984280031Sdim    if (RegNo != 31)
985280031Sdim      res++;
986280031Sdim    else
987280031Sdim      res |= 0x10;
988280031Sdim  }
989280031Sdim  return res;
990280031Sdim}
991280031Sdim
992280031Sdimunsigned
993280031SdimMipsMCCodeEmitter::getRegisterListOpValue16(const MCInst &MI, unsigned OpNo,
994280031Sdim                                            SmallVectorImpl<MCFixup> &Fixups,
995280031Sdim                                            const MCSubtargetInfo &STI) const {
996280031Sdim  return (MI.getNumOperands() - 4);
997280031Sdim}
998280031Sdim
999280031Sdimunsigned
1000280031SdimMipsMCCodeEmitter::getRegisterPairOpValue(const MCInst &MI, unsigned OpNo,
1001280031Sdim                                          SmallVectorImpl<MCFixup> &Fixups,
1002280031Sdim                                          const MCSubtargetInfo &STI) const {
1003280031Sdim  return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
1004280031Sdim}
1005280031Sdim
1006288943Sdimunsigned
1007288943SdimMipsMCCodeEmitter::getMovePRegPairOpValue(const MCInst &MI, unsigned OpNo,
1008288943Sdim                                          SmallVectorImpl<MCFixup> &Fixups,
1009288943Sdim                                          const MCSubtargetInfo &STI) const {
1010288943Sdim  unsigned res = 0;
1011288943Sdim
1012288943Sdim  if (MI.getOperand(0).getReg() == Mips::A1 &&
1013288943Sdim      MI.getOperand(1).getReg() == Mips::A2)
1014288943Sdim    res = 0;
1015288943Sdim  else if (MI.getOperand(0).getReg() == Mips::A1 &&
1016288943Sdim           MI.getOperand(1).getReg() == Mips::A3)
1017288943Sdim    res = 1;
1018288943Sdim  else if (MI.getOperand(0).getReg() == Mips::A2 &&
1019288943Sdim           MI.getOperand(1).getReg() == Mips::A3)
1020288943Sdim    res = 2;
1021288943Sdim  else if (MI.getOperand(0).getReg() == Mips::A0 &&
1022288943Sdim           MI.getOperand(1).getReg() == Mips::S5)
1023288943Sdim    res = 3;
1024288943Sdim  else if (MI.getOperand(0).getReg() == Mips::A0 &&
1025288943Sdim           MI.getOperand(1).getReg() == Mips::S6)
1026288943Sdim    res = 4;
1027288943Sdim  else if (MI.getOperand(0).getReg() == Mips::A0 &&
1028288943Sdim           MI.getOperand(1).getReg() == Mips::A1)
1029288943Sdim    res = 5;
1030288943Sdim  else if (MI.getOperand(0).getReg() == Mips::A0 &&
1031288943Sdim           MI.getOperand(1).getReg() == Mips::A2)
1032288943Sdim    res = 6;
1033288943Sdim  else if (MI.getOperand(0).getReg() == Mips::A0 &&
1034288943Sdim           MI.getOperand(1).getReg() == Mips::A3)
1035288943Sdim    res = 7;
1036288943Sdim
1037288943Sdim  return res;
1038288943Sdim}
1039288943Sdim
1040288943Sdimunsigned
1041288943SdimMipsMCCodeEmitter::getSimm23Lsl2Encoding(const MCInst &MI, unsigned OpNo,
1042288943Sdim                                         SmallVectorImpl<MCFixup> &Fixups,
1043288943Sdim                                         const MCSubtargetInfo &STI) const {
1044288943Sdim  const MCOperand &MO = MI.getOperand(OpNo);
1045288943Sdim  assert(MO.isImm() && "getSimm23Lsl2Encoding expects only an immediate");
1046288943Sdim  // The immediate is encoded as 'immediate >> 2'.
1047288943Sdim  unsigned Res = static_cast<unsigned>(MO.getImm());
1048288943Sdim  assert((Res & 3) == 0);
1049288943Sdim  return Res >> 2;
1050288943Sdim}
1051288943Sdim
1052234353Sdim#include "MipsGenMCCodeEmitter.inc"
1053