[mips] Implement %hi(sym1 - sym2) and %lo(sym1 - sym2) expressions
[oota-llvm.git] / lib / Target / Mips / MCTargetDesc / MipsMCCodeEmitter.cpp
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/MipsMCExpr.h"
18 #include "MCTargetDesc/MipsMCTargetDesc.h"
19 #include "llvm/ADT/APFloat.h"
20 #include "llvm/ADT/Statistic.h"
21 #include "llvm/MC/MCCodeEmitter.h"
22 #include "llvm/MC/MCContext.h"
23 #include "llvm/MC/MCExpr.h"
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/MC/MCInstrInfo.h"
26 #include "llvm/MC/MCRegisterInfo.h"
27 #include "llvm/MC/MCSubtargetInfo.h"
28 #include "llvm/Support/raw_ostream.h"
29
30 #define GET_INSTRMAP_INFO
31 #include "MipsGenInstrInfo.inc"
32
33 using namespace llvm;
34
35 namespace {
36 class MipsMCCodeEmitter : public MCCodeEmitter {
37   MipsMCCodeEmitter(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION;
38   void operator=(const MipsMCCodeEmitter &) LLVM_DELETED_FUNCTION;
39   const MCInstrInfo &MCII;
40   MCContext &Ctx;
41   bool IsLittleEndian;
42
43   bool isMicroMips(const MCSubtargetInfo &STI) const {
44     return STI.getFeatureBits() & Mips::FeatureMicroMips;
45   }
46
47 public:
48   MipsMCCodeEmitter(const MCInstrInfo &mcii, MCContext &Ctx_, bool IsLittle) :
49     MCII(mcii), Ctx(Ctx_), IsLittleEndian(IsLittle) { }
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, const MCSubtargetInfo &STI,
58                        raw_ostream &OS) const {
59     // Output the instruction encoding in little endian byte order.
60     // Little-endian byte ordering:
61     //   mips32r2:   4 | 3 | 2 | 1
62     //   microMIPS:  2 | 1 | 4 | 3
63     if (IsLittleEndian && Size == 4 && isMicroMips(STI)) {
64       EmitInstruction(Val>>16, 2, STI, OS);
65       EmitInstruction(Val, 2, STI, OS);
66     } else {
67       for (unsigned i = 0; i < Size; ++i) {
68         unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8;
69         EmitByte((Val >> Shift) & 0xff, OS);
70       }
71     }
72   }
73
74   void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
75                          SmallVectorImpl<MCFixup> &Fixups,
76                          const MCSubtargetInfo &STI) const;
77
78   // getBinaryCodeForInstr - TableGen'erated function for getting the
79   // binary encoding for an instruction.
80   uint64_t getBinaryCodeForInstr(const MCInst &MI,
81                                  SmallVectorImpl<MCFixup> &Fixups,
82                                  const MCSubtargetInfo &STI) const;
83
84   // getBranchJumpOpValue - Return binary encoding of the jump
85   // target operand. If the machine operand requires relocation,
86   // record the relocation and return zero.
87   unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
88                                 SmallVectorImpl<MCFixup> &Fixups,
89                                 const MCSubtargetInfo &STI) const;
90
91   // getBranchJumpOpValueMM - Return binary encoding of the microMIPS jump
92   // target operand. If the machine operand requires relocation,
93   // record the relocation and return zero.
94   unsigned getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,
95                                   SmallVectorImpl<MCFixup> &Fixups,
96                                   const MCSubtargetInfo &STI) const;
97
98    // getBranchTargetOpValue - Return binary encoding of the branch
99    // target operand. If the machine operand requires relocation,
100    // record the relocation and return zero.
101   unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
102                                   SmallVectorImpl<MCFixup> &Fixups,
103                                   const MCSubtargetInfo &STI) const;
104
105   // getBranchTargetOpValue - Return binary encoding of the microMIPS branch
106   // target operand. If the machine operand requires relocation,
107   // record the relocation and return zero.
108   unsigned getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo,
109                                     SmallVectorImpl<MCFixup> &Fixups,
110                                     const MCSubtargetInfo &STI) const;
111
112    // getMachineOpValue - Return binary encoding of operand. If the machin
113    // operand requires relocation, record the relocation and return zero.
114   unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
115                              SmallVectorImpl<MCFixup> &Fixups,
116                              const MCSubtargetInfo &STI) const;
117
118   unsigned getMSAMemEncoding(const MCInst &MI, unsigned OpNo,
119                              SmallVectorImpl<MCFixup> &Fixups,
120                              const MCSubtargetInfo &STI) const;
121
122   unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
123                           SmallVectorImpl<MCFixup> &Fixups,
124                           const MCSubtargetInfo &STI) const;
125   unsigned getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
126                                  SmallVectorImpl<MCFixup> &Fixups,
127                                  const MCSubtargetInfo &STI) const;
128   unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
129                               SmallVectorImpl<MCFixup> &Fixups,
130                               const MCSubtargetInfo &STI) const;
131   unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
132                               SmallVectorImpl<MCFixup> &Fixups,
133                               const MCSubtargetInfo &STI) const;
134
135   // getLSAImmEncoding - Return binary encoding of LSA immediate.
136   unsigned getLSAImmEncoding(const MCInst &MI, unsigned OpNo,
137                              SmallVectorImpl<MCFixup> &Fixups,
138                              const MCSubtargetInfo &STI) const;
139
140   unsigned
141   getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups,
142                  const MCSubtargetInfo &STI) const;
143
144 }; // class MipsMCCodeEmitter
145 }  // namespace
146
147 MCCodeEmitter *llvm::createMipsMCCodeEmitterEB(const MCInstrInfo &MCII,
148                                                const MCRegisterInfo &MRI,
149                                                const MCSubtargetInfo &STI,
150                                                MCContext &Ctx)
151 {
152   return new MipsMCCodeEmitter(MCII, Ctx, false);
153 }
154
155 MCCodeEmitter *llvm::createMipsMCCodeEmitterEL(const MCInstrInfo &MCII,
156                                                const MCRegisterInfo &MRI,
157                                                const MCSubtargetInfo &STI,
158                                                MCContext &Ctx)
159 {
160   return new MipsMCCodeEmitter(MCII, Ctx, true);
161 }
162
163
164 // If the D<shift> instruction has a shift amount that is greater
165 // than 31 (checked in calling routine), lower it to a D<shift>32 instruction
166 static void LowerLargeShift(MCInst& Inst) {
167
168   assert(Inst.getNumOperands() == 3 && "Invalid no. of operands for shift!");
169   assert(Inst.getOperand(2).isImm());
170
171   int64_t Shift = Inst.getOperand(2).getImm();
172   if (Shift <= 31)
173     return; // Do nothing
174   Shift -= 32;
175
176   // saminus32
177   Inst.getOperand(2).setImm(Shift);
178
179   switch (Inst.getOpcode()) {
180   default:
181     // Calling function is not synchronized
182     llvm_unreachable("Unexpected shift instruction");
183   case Mips::DSLL:
184     Inst.setOpcode(Mips::DSLL32);
185     return;
186   case Mips::DSRL:
187     Inst.setOpcode(Mips::DSRL32);
188     return;
189   case Mips::DSRA:
190     Inst.setOpcode(Mips::DSRA32);
191     return;
192   case Mips::DROTR:
193     Inst.setOpcode(Mips::DROTR32);
194     return;
195   }
196 }
197
198 // Pick a DEXT or DINS instruction variant based on the pos and size operands
199 static void LowerDextDins(MCInst& InstIn) {
200   int Opcode = InstIn.getOpcode();
201
202   if (Opcode == Mips::DEXT)
203     assert(InstIn.getNumOperands() == 4 &&
204            "Invalid no. of machine operands for DEXT!");
205   else // Only DEXT and DINS are possible
206     assert(InstIn.getNumOperands() == 5 &&
207            "Invalid no. of machine operands for DINS!");
208
209   assert(InstIn.getOperand(2).isImm());
210   int64_t pos = InstIn.getOperand(2).getImm();
211   assert(InstIn.getOperand(3).isImm());
212   int64_t size = InstIn.getOperand(3).getImm();
213
214   if (size <= 32) {
215     if (pos < 32)  // DEXT/DINS, do nothing
216       return;
217     // DEXTU/DINSU
218     InstIn.getOperand(2).setImm(pos - 32);
219     InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTU : Mips::DINSU);
220     return;
221   }
222   // DEXTM/DINSM
223   assert(pos < 32 && "DEXT/DINS cannot have both size and pos > 32");
224   InstIn.getOperand(3).setImm(size - 32);
225   InstIn.setOpcode((Opcode == Mips::DEXT) ? Mips::DEXTM : Mips::DINSM);
226   return;
227 }
228
229 /// EncodeInstruction - Emit the instruction.
230 /// Size the instruction with Desc.getSize().
231 void MipsMCCodeEmitter::
232 EncodeInstruction(const MCInst &MI, raw_ostream &OS,
233                   SmallVectorImpl<MCFixup> &Fixups,
234                   const MCSubtargetInfo &STI) const
235 {
236
237   // Non-pseudo instructions that get changed for direct object
238   // only based on operand values.
239   // If this list of instructions get much longer we will move
240   // the check to a function call. Until then, this is more efficient.
241   MCInst TmpInst = MI;
242   switch (MI.getOpcode()) {
243   // If shift amount is >= 32 it the inst needs to be lowered further
244   case Mips::DSLL:
245   case Mips::DSRL:
246   case Mips::DSRA:
247   case Mips::DROTR:
248     LowerLargeShift(TmpInst);
249     break;
250     // Double extract instruction is chosen by pos and size operands
251   case Mips::DEXT:
252   case Mips::DINS:
253     LowerDextDins(TmpInst);
254   }
255
256   unsigned long N = Fixups.size();
257   uint32_t Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
258
259   // Check for unimplemented opcodes.
260   // Unfortunately in MIPS both NOP and SLL will come in with Binary == 0
261   // so we have to special check for them.
262   unsigned Opcode = TmpInst.getOpcode();
263   if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary)
264     llvm_unreachable("unimplemented opcode in EncodeInstruction()");
265
266   if (STI.getFeatureBits() & Mips::FeatureMicroMips) {
267     int NewOpcode = Mips::Std2MicroMips (Opcode, Mips::Arch_micromips);
268     if (NewOpcode != -1) {
269       if (Fixups.size() > N)
270         Fixups.pop_back();
271       Opcode = NewOpcode;
272       TmpInst.setOpcode (NewOpcode);
273       Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI);
274     }
275   }
276
277   const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode());
278
279   // Get byte count of instruction
280   unsigned Size = Desc.getSize();
281   if (!Size)
282     llvm_unreachable("Desc.getSize() returns 0");
283
284   EmitInstruction(Binary, Size, STI, OS);
285 }
286
287 /// getBranchTargetOpValue - Return binary encoding of the branch
288 /// target operand. If the machine operand requires relocation,
289 /// record the relocation and return zero.
290 unsigned MipsMCCodeEmitter::
291 getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
292                        SmallVectorImpl<MCFixup> &Fixups,
293                        const MCSubtargetInfo &STI) const {
294
295   const MCOperand &MO = MI.getOperand(OpNo);
296
297   // If the destination is an immediate, divide by 4.
298   if (MO.isImm()) return MO.getImm() >> 2;
299
300   assert(MO.isExpr() &&
301          "getBranchTargetOpValue expects only expressions or immediates");
302
303   const MCExpr *Expr = MO.getExpr();
304   Fixups.push_back(MCFixup::Create(0, Expr,
305                                    MCFixupKind(Mips::fixup_Mips_PC16)));
306   return 0;
307 }
308
309 /// getBranchTargetOpValue - Return binary encoding of the microMIPS branch
310 /// target operand. If the machine operand requires relocation,
311 /// record the relocation and return zero.
312 unsigned MipsMCCodeEmitter::
313 getBranchTargetOpValueMM(const MCInst &MI, unsigned OpNo,
314                          SmallVectorImpl<MCFixup> &Fixups,
315                          const MCSubtargetInfo &STI) const {
316
317   const MCOperand &MO = MI.getOperand(OpNo);
318
319   // If the destination is an immediate, divide by 2.
320   if (MO.isImm()) return MO.getImm() >> 1;
321
322   assert(MO.isExpr() &&
323          "getBranchTargetOpValueMM expects only expressions or immediates");
324
325   const MCExpr *Expr = MO.getExpr();
326   Fixups.push_back(MCFixup::Create(0, Expr,
327                    MCFixupKind(Mips::
328                                fixup_MICROMIPS_PC16_S1)));
329   return 0;
330 }
331
332 /// getJumpTargetOpValue - Return binary encoding of the jump
333 /// target operand. If the machine operand requires relocation,
334 /// record the relocation and return zero.
335 unsigned MipsMCCodeEmitter::
336 getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
337                      SmallVectorImpl<MCFixup> &Fixups,
338                      const MCSubtargetInfo &STI) const {
339
340   const MCOperand &MO = MI.getOperand(OpNo);
341   // If the destination is an immediate, divide by 4.
342   if (MO.isImm()) return MO.getImm()>>2;
343
344   assert(MO.isExpr() &&
345          "getJumpTargetOpValue expects only expressions or an immediate");
346
347   const MCExpr *Expr = MO.getExpr();
348   Fixups.push_back(MCFixup::Create(0, Expr,
349                                    MCFixupKind(Mips::fixup_Mips_26)));
350   return 0;
351 }
352
353 unsigned MipsMCCodeEmitter::
354 getJumpTargetOpValueMM(const MCInst &MI, unsigned OpNo,
355                        SmallVectorImpl<MCFixup> &Fixups,
356                        const MCSubtargetInfo &STI) const {
357
358   const MCOperand &MO = MI.getOperand(OpNo);
359   // If the destination is an immediate, divide by 2.
360   if (MO.isImm()) return MO.getImm() >> 1;
361
362   assert(MO.isExpr() &&
363          "getJumpTargetOpValueMM expects only expressions or an immediate");
364
365   const MCExpr *Expr = MO.getExpr();
366   Fixups.push_back(MCFixup::Create(0, Expr,
367                                    MCFixupKind(Mips::fixup_MICROMIPS_26_S1)));
368   return 0;
369 }
370
371 unsigned MipsMCCodeEmitter::
372 getExprOpValue(const MCExpr *Expr,SmallVectorImpl<MCFixup> &Fixups,
373                const MCSubtargetInfo &STI) const {
374   int64_t Res;
375
376   if (Expr->EvaluateAsAbsolute(Res))
377     return Res;
378
379   MCExpr::ExprKind Kind = Expr->getKind();
380   if (Kind == MCExpr::Constant) {
381     return cast<MCConstantExpr>(Expr)->getValue();
382   }
383
384   if (Kind == MCExpr::Binary) {
385     unsigned Res = getExprOpValue(cast<MCBinaryExpr>(Expr)->getLHS(), Fixups, STI);
386     Res += getExprOpValue(cast<MCBinaryExpr>(Expr)->getRHS(), Fixups, STI);
387     return Res;
388   }
389
390   if (Kind == MCExpr::Target) {
391     const MipsMCExpr *MipsExpr = cast<MipsMCExpr>(Expr);
392
393     Mips::Fixups FixupKind = Mips::Fixups(0);
394     switch (MipsExpr->getKind()) {
395     default: llvm_unreachable("Unsupported fixup kind for target expression!");
396     case MipsMCExpr::VK_Mips_ABS_HI:
397       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
398                                    : Mips::fixup_Mips_HI16;
399       break;
400     case MipsMCExpr::VK_Mips_ABS_LO:
401       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
402                                    : Mips::fixup_Mips_LO16;
403       break;
404     }
405     Fixups.push_back(MCFixup::Create(0, MipsExpr, MCFixupKind(FixupKind)));
406     return 0;
407   }
408
409   if (Kind == MCExpr::SymbolRef) {
410     Mips::Fixups FixupKind = Mips::Fixups(0);
411
412     switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
413     default: llvm_unreachable("Unknown fixup kind!");
414       break;
415     case MCSymbolRefExpr::VK_Mips_GPOFF_HI :
416       FixupKind = Mips::fixup_Mips_GPOFF_HI;
417       break;
418     case MCSymbolRefExpr::VK_Mips_GPOFF_LO :
419       FixupKind = Mips::fixup_Mips_GPOFF_LO;
420       break;
421     case MCSymbolRefExpr::VK_Mips_GOT_PAGE :
422       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_PAGE
423                               : Mips::fixup_Mips_GOT_PAGE;
424       break;
425     case MCSymbolRefExpr::VK_Mips_GOT_OFST :
426       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_OFST
427                               : Mips::fixup_Mips_GOT_OFST;
428       break;
429     case MCSymbolRefExpr::VK_Mips_GOT_DISP :
430       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT_DISP
431                               : Mips::fixup_Mips_GOT_DISP;
432       break;
433     case MCSymbolRefExpr::VK_Mips_GPREL:
434       FixupKind = Mips::fixup_Mips_GPREL16;
435       break;
436     case MCSymbolRefExpr::VK_Mips_GOT_CALL:
437       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_CALL16
438                               : Mips::fixup_Mips_CALL16;
439       break;
440     case MCSymbolRefExpr::VK_Mips_GOT16:
441       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
442                               : Mips::fixup_Mips_GOT_Global;
443       break;
444     case MCSymbolRefExpr::VK_Mips_GOT:
445       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_GOT16
446                               : Mips::fixup_Mips_GOT_Local;
447       break;
448     case MCSymbolRefExpr::VK_Mips_ABS_HI:
449       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_HI16
450                               : Mips::fixup_Mips_HI16;
451       break;
452     case MCSymbolRefExpr::VK_Mips_ABS_LO:
453       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_LO16
454                               : Mips::fixup_Mips_LO16;
455       break;
456     case MCSymbolRefExpr::VK_Mips_TLSGD:
457       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_GD
458                               : Mips::fixup_Mips_TLSGD;
459       break;
460     case MCSymbolRefExpr::VK_Mips_TLSLDM:
461       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_LDM
462                               : Mips::fixup_Mips_TLSLDM;
463       break;
464     case MCSymbolRefExpr::VK_Mips_DTPREL_HI:
465       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_HI16
466                               : Mips::fixup_Mips_DTPREL_HI;
467       break;
468     case MCSymbolRefExpr::VK_Mips_DTPREL_LO:
469       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_DTPREL_LO16
470                               : Mips::fixup_Mips_DTPREL_LO;
471       break;
472     case MCSymbolRefExpr::VK_Mips_GOTTPREL:
473       FixupKind = Mips::fixup_Mips_GOTTPREL;
474       break;
475     case MCSymbolRefExpr::VK_Mips_TPREL_HI:
476       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_HI16
477                               : Mips::fixup_Mips_TPREL_HI;
478       break;
479     case MCSymbolRefExpr::VK_Mips_TPREL_LO:
480       FixupKind = isMicroMips(STI) ? Mips::fixup_MICROMIPS_TLS_TPREL_LO16
481                               : Mips::fixup_Mips_TPREL_LO;
482       break;
483     case MCSymbolRefExpr::VK_Mips_HIGHER:
484       FixupKind = Mips::fixup_Mips_HIGHER;
485       break;
486     case MCSymbolRefExpr::VK_Mips_HIGHEST:
487       FixupKind = Mips::fixup_Mips_HIGHEST;
488       break;
489     case MCSymbolRefExpr::VK_Mips_GOT_HI16:
490       FixupKind = Mips::fixup_Mips_GOT_HI16;
491       break;
492     case MCSymbolRefExpr::VK_Mips_GOT_LO16:
493       FixupKind = Mips::fixup_Mips_GOT_LO16;
494       break;
495     case MCSymbolRefExpr::VK_Mips_CALL_HI16:
496       FixupKind = Mips::fixup_Mips_CALL_HI16;
497       break;
498     case MCSymbolRefExpr::VK_Mips_CALL_LO16:
499       FixupKind = Mips::fixup_Mips_CALL_LO16;
500       break;
501     } // switch
502
503     Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind)));
504     return 0;
505   }
506   return 0;
507 }
508
509 /// getMachineOpValue - Return binary encoding of operand. If the machine
510 /// operand requires relocation, record the relocation and return zero.
511 unsigned MipsMCCodeEmitter::
512 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
513                   SmallVectorImpl<MCFixup> &Fixups,
514                   const MCSubtargetInfo &STI) const {
515   if (MO.isReg()) {
516     unsigned Reg = MO.getReg();
517     unsigned RegNo = Ctx.getRegisterInfo()->getEncodingValue(Reg);
518     return RegNo;
519   } else if (MO.isImm()) {
520     return static_cast<unsigned>(MO.getImm());
521   } else if (MO.isFPImm()) {
522     return static_cast<unsigned>(APFloat(MO.getFPImm())
523         .bitcastToAPInt().getHiBits(32).getLimitedValue());
524   }
525   // MO must be an Expr.
526   assert(MO.isExpr());
527   return getExprOpValue(MO.getExpr(),Fixups, STI);
528 }
529
530 /// getMSAMemEncoding - Return binary encoding of memory operand for LD/ST
531 /// instructions.
532 unsigned
533 MipsMCCodeEmitter::getMSAMemEncoding(const MCInst &MI, unsigned OpNo,
534                                      SmallVectorImpl<MCFixup> &Fixups,
535                                      const MCSubtargetInfo &STI) const {
536   // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
537   assert(MI.getOperand(OpNo).isReg());
538   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16;
539   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
540
541   // The immediate field of an LD/ST instruction is scaled which means it must
542   // be divided (when encoding) by the size (in bytes) of the instructions'
543   // data format.
544   // .b - 1 byte
545   // .h - 2 bytes
546   // .w - 4 bytes
547   // .d - 8 bytes
548   switch(MI.getOpcode())
549   {
550   default:
551     assert (0 && "Unexpected instruction");
552     break;
553   case Mips::LD_B:
554   case Mips::ST_B:
555     // We don't need to scale the offset in this case
556     break;
557   case Mips::LD_H:
558   case Mips::ST_H:
559     OffBits >>= 1;
560     break;
561   case Mips::LD_W:
562   case Mips::ST_W:
563     OffBits >>= 2;
564     break;
565   case Mips::LD_D:
566   case Mips::ST_D:
567     OffBits >>= 3;
568     break;
569   }
570
571   return (OffBits & 0xFFFF) | RegBits;
572 }
573
574 /// getMemEncoding - Return binary encoding of memory related operand.
575 /// If the offset operand requires relocation, record the relocation.
576 unsigned
577 MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
578                                   SmallVectorImpl<MCFixup> &Fixups,
579                                   const MCSubtargetInfo &STI) const {
580   // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
581   assert(MI.getOperand(OpNo).isReg());
582   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups, STI) << 16;
583   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
584
585   return (OffBits & 0xFFFF) | RegBits;
586 }
587
588 unsigned MipsMCCodeEmitter::
589 getMemEncodingMMImm12(const MCInst &MI, unsigned OpNo,
590                       SmallVectorImpl<MCFixup> &Fixups,
591                       const MCSubtargetInfo &STI) const {
592   // Base register is encoded in bits 20-16, offset is encoded in bits 11-0.
593   assert(MI.getOperand(OpNo).isReg());
594   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) << 16;
595   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups, STI);
596
597   return (OffBits & 0x0FFF) | RegBits;
598 }
599
600 unsigned
601 MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
602                                       SmallVectorImpl<MCFixup> &Fixups,
603                                       const MCSubtargetInfo &STI) const {
604   assert(MI.getOperand(OpNo).isImm());
605   unsigned SizeEncoding = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
606   return SizeEncoding - 1;
607 }
608
609 // FIXME: should be called getMSBEncoding
610 //
611 unsigned
612 MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
613                                       SmallVectorImpl<MCFixup> &Fixups,
614                                       const MCSubtargetInfo &STI) const {
615   assert(MI.getOperand(OpNo-1).isImm());
616   assert(MI.getOperand(OpNo).isImm());
617   unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups, STI);
618   unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI);
619
620   return Position + Size - 1;
621 }
622
623 unsigned
624 MipsMCCodeEmitter::getLSAImmEncoding(const MCInst &MI, unsigned OpNo,
625                                      SmallVectorImpl<MCFixup> &Fixups,
626                                      const MCSubtargetInfo &STI) const {
627   assert(MI.getOperand(OpNo).isImm());
628   // The immediate is encoded as 'immediate - 1'.
629   return getMachineOpValue(MI, MI.getOperand(OpNo), Fixups, STI) - 1;
630 }
631
632 #include "MipsGenMCCodeEmitter.inc"
633