1750ecec7SAkira Hatanaka //===-- MipsMCCodeEmitter.cpp - Convert Mips code to machine code ---------===//
2750ecec7SAkira Hatanaka //
3750ecec7SAkira Hatanaka //                     The LLVM Compiler Infrastructure
4750ecec7SAkira Hatanaka //
5750ecec7SAkira Hatanaka // This file is distributed under the University of Illinois Open Source
6750ecec7SAkira Hatanaka // License. See LICENSE.TXT for details.
7750ecec7SAkira Hatanaka //
8750ecec7SAkira Hatanaka //===----------------------------------------------------------------------===//
9750ecec7SAkira Hatanaka //
10750ecec7SAkira Hatanaka // This file implements the MipsMCCodeEmitter class.
11750ecec7SAkira Hatanaka //
12750ecec7SAkira Hatanaka //===----------------------------------------------------------------------===//
13750ecec7SAkira Hatanaka //
14750ecec7SAkira Hatanaka #define DEBUG_TYPE "mccodeemitter"
15*c85e3ff3SBruno Cardoso Lopes #include "MCTargetDesc/MipsBaseInfo.h"
16*c85e3ff3SBruno Cardoso Lopes #include "MCTargetDesc/MipsFixupKinds.h"
17*c85e3ff3SBruno Cardoso Lopes #include "MCTargetDesc/MipsMCTargetDesc.h"
18*c85e3ff3SBruno Cardoso Lopes #include "llvm/ADT/APFloat.h"
19*c85e3ff3SBruno Cardoso Lopes #include "llvm/ADT/Statistic.h"
20750ecec7SAkira Hatanaka #include "llvm/MC/MCCodeEmitter.h"
21750ecec7SAkira Hatanaka #include "llvm/MC/MCExpr.h"
22750ecec7SAkira Hatanaka #include "llvm/MC/MCInst.h"
23750ecec7SAkira Hatanaka #include "llvm/MC/MCInstrInfo.h"
24750ecec7SAkira Hatanaka #include "llvm/MC/MCRegisterInfo.h"
25750ecec7SAkira Hatanaka #include "llvm/MC/MCSubtargetInfo.h"
26750ecec7SAkira Hatanaka #include "llvm/Support/raw_ostream.h"
27750ecec7SAkira Hatanaka 
28750ecec7SAkira Hatanaka using namespace llvm;
29750ecec7SAkira Hatanaka 
30750ecec7SAkira Hatanaka namespace {
31750ecec7SAkira Hatanaka class MipsMCCodeEmitter : public MCCodeEmitter {
32750ecec7SAkira Hatanaka   MipsMCCodeEmitter(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT
33750ecec7SAkira Hatanaka   void operator=(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT
34750ecec7SAkira Hatanaka   const MCInstrInfo &MCII;
35750ecec7SAkira Hatanaka   const MCSubtargetInfo &STI;
36*c85e3ff3SBruno Cardoso Lopes   MCContext &Ctx;
37750ecec7SAkira Hatanaka 
38750ecec7SAkira Hatanaka public:
39750ecec7SAkira Hatanaka   MipsMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
40*c85e3ff3SBruno Cardoso Lopes                     MCContext &ctx) : MCII(mcii), STI(sti) , Ctx(ctx) {}
41750ecec7SAkira Hatanaka 
42750ecec7SAkira Hatanaka   ~MipsMCCodeEmitter() {}
43750ecec7SAkira Hatanaka 
44*c85e3ff3SBruno Cardoso Lopes   void EmitByte(unsigned char C, raw_ostream &OS) const {
45*c85e3ff3SBruno Cardoso Lopes     OS << (char)C;
46750ecec7SAkira Hatanaka   }
47*c85e3ff3SBruno Cardoso Lopes 
48*c85e3ff3SBruno Cardoso Lopes   void EmitInstruction(uint64_t Val, unsigned Size, raw_ostream &OS) const {
49*c85e3ff3SBruno Cardoso Lopes     // Output the instruction encoding in little endian byte order.
50*c85e3ff3SBruno Cardoso Lopes     for (unsigned i = 0; i != Size; ++i) {
51*c85e3ff3SBruno Cardoso Lopes       EmitByte(Val & 255, OS);
52*c85e3ff3SBruno Cardoso Lopes       Val >>= 8;
53*c85e3ff3SBruno Cardoso Lopes     }
54*c85e3ff3SBruno Cardoso Lopes   }
55*c85e3ff3SBruno Cardoso Lopes 
56*c85e3ff3SBruno Cardoso Lopes   void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
57*c85e3ff3SBruno Cardoso Lopes                          SmallVectorImpl<MCFixup> &Fixups) const;
58*c85e3ff3SBruno Cardoso Lopes 
59*c85e3ff3SBruno Cardoso Lopes   // getBinaryCodeForInstr - TableGen'erated function for getting the
60*c85e3ff3SBruno Cardoso Lopes   // binary encoding for an instruction.
61*c85e3ff3SBruno Cardoso Lopes   unsigned getBinaryCodeForInstr(const MCInst &MI,
62*c85e3ff3SBruno Cardoso Lopes                                  SmallVectorImpl<MCFixup> &Fixups) const;
63*c85e3ff3SBruno Cardoso Lopes 
64*c85e3ff3SBruno Cardoso Lopes   // getBranchJumpOpValue - Return binary encoding of the jump
65*c85e3ff3SBruno Cardoso Lopes   // target operand. If the machine operand requires relocation,
66*c85e3ff3SBruno Cardoso Lopes   // record the relocation and return zero.
67*c85e3ff3SBruno Cardoso Lopes    unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
68*c85e3ff3SBruno Cardoso Lopes                                  SmallVectorImpl<MCFixup> &Fixups) const;
69*c85e3ff3SBruno Cardoso Lopes 
70*c85e3ff3SBruno Cardoso Lopes    // getBranchTargetOpValue - Return binary encoding of the branch
71*c85e3ff3SBruno Cardoso Lopes    // target operand. If the machine operand requires relocation,
72*c85e3ff3SBruno Cardoso Lopes    // record the relocation and return zero.
73*c85e3ff3SBruno Cardoso Lopes   unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
74*c85e3ff3SBruno Cardoso Lopes                                   SmallVectorImpl<MCFixup> &Fixups) const;
75*c85e3ff3SBruno Cardoso Lopes 
76*c85e3ff3SBruno Cardoso Lopes    // getMachineOpValue - Return binary encoding of operand. If the machin
77*c85e3ff3SBruno Cardoso Lopes    // operand requires relocation, record the relocation and return zero.
78*c85e3ff3SBruno Cardoso Lopes   unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
79*c85e3ff3SBruno Cardoso Lopes                              SmallVectorImpl<MCFixup> &Fixups) const;
80*c85e3ff3SBruno Cardoso Lopes 
81*c85e3ff3SBruno Cardoso Lopes   unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
82*c85e3ff3SBruno Cardoso Lopes                           SmallVectorImpl<MCFixup> &Fixups) const;
83*c85e3ff3SBruno Cardoso Lopes   unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
84*c85e3ff3SBruno Cardoso Lopes                               SmallVectorImpl<MCFixup> &Fixups) const;
85*c85e3ff3SBruno Cardoso Lopes   unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
86*c85e3ff3SBruno Cardoso Lopes                               SmallVectorImpl<MCFixup> &Fixups) const;
87*c85e3ff3SBruno Cardoso Lopes 
88750ecec7SAkira Hatanaka }; // class MipsMCCodeEmitter
89750ecec7SAkira Hatanaka }  // namespace
90750ecec7SAkira Hatanaka 
91750ecec7SAkira Hatanaka MCCodeEmitter *llvm::createMipsMCCodeEmitter(const MCInstrInfo &MCII,
92750ecec7SAkira Hatanaka                                              const MCSubtargetInfo &STI,
93*c85e3ff3SBruno Cardoso Lopes                                              MCContext &Ctx)
94*c85e3ff3SBruno Cardoso Lopes {
95750ecec7SAkira Hatanaka   return new MipsMCCodeEmitter(MCII, STI, Ctx);
96750ecec7SAkira Hatanaka }
97*c85e3ff3SBruno Cardoso Lopes 
98*c85e3ff3SBruno Cardoso Lopes /// EncodeInstruction - Emit the instruction.
99*c85e3ff3SBruno Cardoso Lopes /// Size the instruction (currently only 4 bytes
100*c85e3ff3SBruno Cardoso Lopes void MipsMCCodeEmitter::
101*c85e3ff3SBruno Cardoso Lopes EncodeInstruction(const MCInst &MI, raw_ostream &OS,
102*c85e3ff3SBruno Cardoso Lopes                   SmallVectorImpl<MCFixup> &Fixups) const
103*c85e3ff3SBruno Cardoso Lopes {
104*c85e3ff3SBruno Cardoso Lopes   uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);
105*c85e3ff3SBruno Cardoso Lopes 
106*c85e3ff3SBruno Cardoso Lopes   // Check for unimplemented opcodes.
107*c85e3ff3SBruno Cardoso Lopes   // Unfortunately in MIPS both NOT and SLL will come in with Binary == 0
108*c85e3ff3SBruno Cardoso Lopes   // so we have to special check for them.
109*c85e3ff3SBruno Cardoso Lopes   unsigned Opcode = MI.getOpcode();
110*c85e3ff3SBruno Cardoso Lopes   if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary)
111*c85e3ff3SBruno Cardoso Lopes     llvm_unreachable("unimplemented opcode in EncodeInstruction()");
112*c85e3ff3SBruno Cardoso Lopes 
113*c85e3ff3SBruno Cardoso Lopes   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
114*c85e3ff3SBruno Cardoso Lopes   uint64_t TSFlags = Desc.TSFlags;
115*c85e3ff3SBruno Cardoso Lopes 
116*c85e3ff3SBruno Cardoso Lopes   // Pseudo instructions don't get encoded and shouldn't be here
117*c85e3ff3SBruno Cardoso Lopes   // in the first place!
118*c85e3ff3SBruno Cardoso Lopes   if ((TSFlags & MipsII::FormMask) == MipsII::Pseudo)
119*c85e3ff3SBruno Cardoso Lopes     llvm_unreachable("Pseudo opcode found in EncodeInstruction()");
120*c85e3ff3SBruno Cardoso Lopes 
121*c85e3ff3SBruno Cardoso Lopes   // For now all instructions are 4 bytes
122*c85e3ff3SBruno Cardoso Lopes   int Size = 4; // FIXME: Have Desc.getSize() return the correct value!
123*c85e3ff3SBruno Cardoso Lopes 
124*c85e3ff3SBruno Cardoso Lopes   EmitInstruction(Binary, Size, OS);
125*c85e3ff3SBruno Cardoso Lopes }
126*c85e3ff3SBruno Cardoso Lopes 
127*c85e3ff3SBruno Cardoso Lopes /// getBranchTargetOpValue - Return binary encoding of the branch
128*c85e3ff3SBruno Cardoso Lopes /// target operand. If the machine operand requires relocation,
129*c85e3ff3SBruno Cardoso Lopes /// record the relocation and return zero.
130*c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter::
131*c85e3ff3SBruno Cardoso Lopes getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
132*c85e3ff3SBruno Cardoso Lopes                        SmallVectorImpl<MCFixup> &Fixups) const {
133*c85e3ff3SBruno Cardoso Lopes 
134*c85e3ff3SBruno Cardoso Lopes   const MCOperand &MO = MI.getOperand(OpNo);
135*c85e3ff3SBruno Cardoso Lopes   assert(MO.isExpr() && "getBranchTargetOpValue expects only expressions");
136*c85e3ff3SBruno Cardoso Lopes 
137*c85e3ff3SBruno Cardoso Lopes   const MCExpr *Expr = MO.getExpr();
138*c85e3ff3SBruno Cardoso Lopes   Fixups.push_back(MCFixup::Create(0, Expr,
139*c85e3ff3SBruno Cardoso Lopes                                    MCFixupKind(Mips::fixup_Mips_PC16)));
140*c85e3ff3SBruno Cardoso Lopes   return 0;
141*c85e3ff3SBruno Cardoso Lopes }
142*c85e3ff3SBruno Cardoso Lopes 
143*c85e3ff3SBruno Cardoso Lopes /// getJumpTargetOpValue - Return binary encoding of the jump
144*c85e3ff3SBruno Cardoso Lopes /// target operand. If the machine operand requires relocation,
145*c85e3ff3SBruno Cardoso Lopes /// record the relocation and return zero.
146*c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter::
147*c85e3ff3SBruno Cardoso Lopes getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
148*c85e3ff3SBruno Cardoso Lopes                      SmallVectorImpl<MCFixup> &Fixups) const {
149*c85e3ff3SBruno Cardoso Lopes 
150*c85e3ff3SBruno Cardoso Lopes   const MCOperand &MO = MI.getOperand(OpNo);
151*c85e3ff3SBruno Cardoso Lopes   assert(MO.isExpr() && "getJumpTargetOpValue expects only expressions");
152*c85e3ff3SBruno Cardoso Lopes 
153*c85e3ff3SBruno Cardoso Lopes   const MCExpr *Expr = MO.getExpr();
154*c85e3ff3SBruno Cardoso Lopes   Fixups.push_back(MCFixup::Create(0, Expr,
155*c85e3ff3SBruno Cardoso Lopes                                    MCFixupKind(Mips::fixup_Mips_26)));
156*c85e3ff3SBruno Cardoso Lopes   return 0;
157*c85e3ff3SBruno Cardoso Lopes }
158*c85e3ff3SBruno Cardoso Lopes 
159*c85e3ff3SBruno Cardoso Lopes /// getMachineOpValue - Return binary encoding of operand. If the machine
160*c85e3ff3SBruno Cardoso Lopes /// operand requires relocation, record the relocation and return zero.
161*c85e3ff3SBruno Cardoso Lopes unsigned MipsMCCodeEmitter::
162*c85e3ff3SBruno Cardoso Lopes getMachineOpValue(const MCInst &MI, const MCOperand &MO,
163*c85e3ff3SBruno Cardoso Lopes                   SmallVectorImpl<MCFixup> &Fixups) const {
164*c85e3ff3SBruno Cardoso Lopes   if (MO.isReg()) {
165*c85e3ff3SBruno Cardoso Lopes     unsigned Reg = MO.getReg();
166*c85e3ff3SBruno Cardoso Lopes     unsigned RegNo = getMipsRegisterNumbering(Reg);
167*c85e3ff3SBruno Cardoso Lopes     return RegNo;
168*c85e3ff3SBruno Cardoso Lopes   } else if (MO.isImm()) {
169*c85e3ff3SBruno Cardoso Lopes     return static_cast<unsigned>(MO.getImm());
170*c85e3ff3SBruno Cardoso Lopes   } else if (MO.isFPImm()) {
171*c85e3ff3SBruno Cardoso Lopes     return static_cast<unsigned>(APFloat(MO.getFPImm())
172*c85e3ff3SBruno Cardoso Lopes         .bitcastToAPInt().getHiBits(32).getLimitedValue());
173*c85e3ff3SBruno Cardoso Lopes   } else if (MO.isExpr()) {
174*c85e3ff3SBruno Cardoso Lopes     const MCExpr *Expr = MO.getExpr();
175*c85e3ff3SBruno Cardoso Lopes     MCExpr::ExprKind Kind = Expr->getKind();
176*c85e3ff3SBruno Cardoso Lopes     if (Kind == MCExpr::SymbolRef) {
177*c85e3ff3SBruno Cardoso Lopes       Mips::Fixups FixupKind = Mips::fixup_Mips_NONE;
178*c85e3ff3SBruno Cardoso Lopes       MCSymbolRefExpr::VariantKind SymRefKind =
179*c85e3ff3SBruno Cardoso Lopes           cast<MCSymbolRefExpr>(Expr)->getKind();
180*c85e3ff3SBruno Cardoso Lopes       switch(SymRefKind) {
181*c85e3ff3SBruno Cardoso Lopes       case MCSymbolRefExpr::VK_Mips_GPREL:
182*c85e3ff3SBruno Cardoso Lopes         FixupKind = Mips::fixup_Mips_GPREL16;
183*c85e3ff3SBruno Cardoso Lopes         break;
184*c85e3ff3SBruno Cardoso Lopes       case MCSymbolRefExpr::VK_Mips_GOT_CALL:
185*c85e3ff3SBruno Cardoso Lopes         FixupKind = Mips::fixup_Mips_CALL16;
186*c85e3ff3SBruno Cardoso Lopes         break;
187*c85e3ff3SBruno Cardoso Lopes       case MCSymbolRefExpr::VK_Mips_GOT:
188*c85e3ff3SBruno Cardoso Lopes         FixupKind = Mips::fixup_Mips_GOT16;
189*c85e3ff3SBruno Cardoso Lopes         break;
190*c85e3ff3SBruno Cardoso Lopes       case MCSymbolRefExpr::VK_Mips_ABS_HI:
191*c85e3ff3SBruno Cardoso Lopes         FixupKind = Mips::fixup_Mips_HI16;
192*c85e3ff3SBruno Cardoso Lopes         break;
193*c85e3ff3SBruno Cardoso Lopes       case MCSymbolRefExpr::VK_Mips_ABS_LO:
194*c85e3ff3SBruno Cardoso Lopes         FixupKind = Mips::fixup_Mips_LO16;
195*c85e3ff3SBruno Cardoso Lopes         break;
196*c85e3ff3SBruno Cardoso Lopes       case MCSymbolRefExpr::VK_Mips_TLSGD:
197*c85e3ff3SBruno Cardoso Lopes         FixupKind = Mips::fixup_Mips_TLSGD;
198*c85e3ff3SBruno Cardoso Lopes         break;
199*c85e3ff3SBruno Cardoso Lopes       case MCSymbolRefExpr::VK_Mips_GOTTPREL:
200*c85e3ff3SBruno Cardoso Lopes         FixupKind = Mips::fixup_Mips_GOTTPREL;
201*c85e3ff3SBruno Cardoso Lopes         break;
202*c85e3ff3SBruno Cardoso Lopes       case MCSymbolRefExpr::VK_Mips_TPREL_HI:
203*c85e3ff3SBruno Cardoso Lopes         FixupKind = Mips::fixup_Mips_TPREL_HI;
204*c85e3ff3SBruno Cardoso Lopes         break;
205*c85e3ff3SBruno Cardoso Lopes       case MCSymbolRefExpr::VK_Mips_TPREL_LO:
206*c85e3ff3SBruno Cardoso Lopes         FixupKind = Mips::fixup_Mips_TPREL_LO;
207*c85e3ff3SBruno Cardoso Lopes         break;
208*c85e3ff3SBruno Cardoso Lopes       default:
209*c85e3ff3SBruno Cardoso Lopes         return 0;
210*c85e3ff3SBruno Cardoso Lopes       } // switch
211*c85e3ff3SBruno Cardoso Lopes       Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind)));
212*c85e3ff3SBruno Cardoso Lopes     } // if SymbolRef
213*c85e3ff3SBruno Cardoso Lopes     // All of the information is in the fixup.
214*c85e3ff3SBruno Cardoso Lopes     return 0;
215*c85e3ff3SBruno Cardoso Lopes   }
216*c85e3ff3SBruno Cardoso Lopes   llvm_unreachable("Unable to encode MCOperand!");
217*c85e3ff3SBruno Cardoso Lopes   // Not reached
218*c85e3ff3SBruno Cardoso Lopes   return 0;
219*c85e3ff3SBruno Cardoso Lopes }
220*c85e3ff3SBruno Cardoso Lopes 
221*c85e3ff3SBruno Cardoso Lopes /// getMemEncoding - Return binary encoding of memory related operand.
222*c85e3ff3SBruno Cardoso Lopes /// If the offset operand requires relocation, record the relocation.
223*c85e3ff3SBruno Cardoso Lopes unsigned
224*c85e3ff3SBruno Cardoso Lopes MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
225*c85e3ff3SBruno Cardoso Lopes                                   SmallVectorImpl<MCFixup> &Fixups) const {
226*c85e3ff3SBruno Cardoso Lopes   // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
227*c85e3ff3SBruno Cardoso Lopes   assert(MI.getOperand(OpNo).isReg());
228*c85e3ff3SBruno Cardoso Lopes   unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups) << 16;
229*c85e3ff3SBruno Cardoso Lopes   unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups);
230*c85e3ff3SBruno Cardoso Lopes 
231*c85e3ff3SBruno Cardoso Lopes   return (OffBits & 0xFFFF) | RegBits;
232*c85e3ff3SBruno Cardoso Lopes }
233*c85e3ff3SBruno Cardoso Lopes 
234*c85e3ff3SBruno Cardoso Lopes unsigned
235*c85e3ff3SBruno Cardoso Lopes MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
236*c85e3ff3SBruno Cardoso Lopes                                       SmallVectorImpl<MCFixup> &Fixups) const {
237*c85e3ff3SBruno Cardoso Lopes   // FIXME: implement
238*c85e3ff3SBruno Cardoso Lopes   return 0;
239*c85e3ff3SBruno Cardoso Lopes }
240*c85e3ff3SBruno Cardoso Lopes 
241*c85e3ff3SBruno Cardoso Lopes unsigned
242*c85e3ff3SBruno Cardoso Lopes MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
243*c85e3ff3SBruno Cardoso Lopes                                       SmallVectorImpl<MCFixup> &Fixups) const {
244*c85e3ff3SBruno Cardoso Lopes   // FIXME: implement
245*c85e3ff3SBruno Cardoso Lopes   return 0;
246*c85e3ff3SBruno Cardoso Lopes }
247*c85e3ff3SBruno Cardoso Lopes 
248*c85e3ff3SBruno Cardoso Lopes #include "MipsGenMCCodeEmitter.inc"
249*c85e3ff3SBruno Cardoso Lopes 
250