1 //===-- MipsMCCodeEmitter.cpp - Convert Mips code to machine code ---------===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 // This file implements the MipsMCCodeEmitter class.
12 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "mccodeemitter"
15 #include "MCTargetDesc/MipsBaseInfo.h"
16 #include "MCTargetDesc/MipsFixupKinds.h"
17 #include "MCTargetDesc/MipsMCTargetDesc.h"
18 #include "llvm/ADT/APFloat.h"
19 #include "llvm/ADT/Statistic.h"
20 #include "llvm/MC/MCCodeEmitter.h"
21 #include "llvm/MC/MCExpr.h"
22 #include "llvm/MC/MCInst.h"
23 #include "llvm/MC/MCInstrInfo.h"
24 #include "llvm/MC/MCRegisterInfo.h"
25 #include "llvm/MC/MCSubtargetInfo.h"
26 #include "llvm/Support/raw_ostream.h"
31 class MipsMCCodeEmitter : public MCCodeEmitter {
32 MipsMCCodeEmitter(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT
33 void operator=(const MipsMCCodeEmitter &); // DO NOT IMPLEMENT
34 const MCInstrInfo &MCII;
35 const MCSubtargetInfo &STI;
39 MipsMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
40 MCContext &ctx) : MCII(mcii), STI(sti) , Ctx(ctx) {}
42 ~MipsMCCodeEmitter() {}
44 void EmitByte(unsigned char C, raw_ostream &OS) const {
48 void EmitInstruction(uint64_t Val, unsigned Size, raw_ostream &OS) const {
49 // Output the instruction encoding in little endian byte order.
50 for (unsigned i = 0; i != Size; ++i) {
51 EmitByte(Val & 255, OS);
56 void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
57 SmallVectorImpl<MCFixup> &Fixups) const;
59 // getBinaryCodeForInstr - TableGen'erated function for getting the
60 // binary encoding for an instruction.
61 unsigned getBinaryCodeForInstr(const MCInst &MI,
62 SmallVectorImpl<MCFixup> &Fixups) const;
64 // getBranchJumpOpValue - Return binary encoding of the jump
65 // target operand. If the machine operand requires relocation,
66 // record the relocation and return zero.
67 unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
68 SmallVectorImpl<MCFixup> &Fixups) const;
70 // getBranchTargetOpValue - Return binary encoding of the branch
71 // target operand. If the machine operand requires relocation,
72 // record the relocation and return zero.
73 unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
74 SmallVectorImpl<MCFixup> &Fixups) const;
76 // getMachineOpValue - Return binary encoding of operand. If the machin
77 // operand requires relocation, record the relocation and return zero.
78 unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
79 SmallVectorImpl<MCFixup> &Fixups) const;
81 unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
82 SmallVectorImpl<MCFixup> &Fixups) const;
83 unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
84 SmallVectorImpl<MCFixup> &Fixups) const;
85 unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
86 SmallVectorImpl<MCFixup> &Fixups) const;
88 }; // class MipsMCCodeEmitter
91 MCCodeEmitter *llvm::createMipsMCCodeEmitter(const MCInstrInfo &MCII,
92 const MCSubtargetInfo &STI,
95 return new MipsMCCodeEmitter(MCII, STI, Ctx);
98 /// EncodeInstruction - Emit the instruction.
99 /// Size the instruction (currently only 4 bytes
100 void MipsMCCodeEmitter::
101 EncodeInstruction(const MCInst &MI, raw_ostream &OS,
102 SmallVectorImpl<MCFixup> &Fixups) const
104 uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);
106 // Check for unimplemented opcodes.
107 // Unfortunately in MIPS both NOT and SLL will come in with Binary == 0
108 // so we have to special check for them.
109 unsigned Opcode = MI.getOpcode();
110 if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary)
111 llvm_unreachable("unimplemented opcode in EncodeInstruction()");
113 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
114 uint64_t TSFlags = Desc.TSFlags;
116 // Pseudo instructions don't get encoded and shouldn't be here
117 // in the first place!
118 if ((TSFlags & MipsII::FormMask) == MipsII::Pseudo)
119 llvm_unreachable("Pseudo opcode found in EncodeInstruction()");
121 // For now all instructions are 4 bytes
122 int Size = 4; // FIXME: Have Desc.getSize() return the correct value!
124 EmitInstruction(Binary, Size, OS);
127 /// getBranchTargetOpValue - Return binary encoding of the branch
128 /// target operand. If the machine operand requires relocation,
129 /// record the relocation and return zero.
130 unsigned MipsMCCodeEmitter::
131 getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
132 SmallVectorImpl<MCFixup> &Fixups) const {
134 const MCOperand &MO = MI.getOperand(OpNo);
135 assert(MO.isExpr() && "getBranchTargetOpValue expects only expressions");
137 const MCExpr *Expr = MO.getExpr();
138 Fixups.push_back(MCFixup::Create(0, Expr,
139 MCFixupKind(Mips::fixup_Mips_PC16)));
143 /// getJumpTargetOpValue - Return binary encoding of the jump
144 /// target operand. If the machine operand requires relocation,
145 /// record the relocation and return zero.
146 unsigned MipsMCCodeEmitter::
147 getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
148 SmallVectorImpl<MCFixup> &Fixups) const {
150 const MCOperand &MO = MI.getOperand(OpNo);
151 assert(MO.isExpr() && "getJumpTargetOpValue expects only expressions");
153 const MCExpr *Expr = MO.getExpr();
154 Fixups.push_back(MCFixup::Create(0, Expr,
155 MCFixupKind(Mips::fixup_Mips_26)));
159 /// getMachineOpValue - Return binary encoding of operand. If the machine
160 /// operand requires relocation, record the relocation and return zero.
161 unsigned MipsMCCodeEmitter::
162 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
163 SmallVectorImpl<MCFixup> &Fixups) const {
165 unsigned Reg = MO.getReg();
166 unsigned RegNo = getMipsRegisterNumbering(Reg);
168 } else if (MO.isImm()) {
169 return static_cast<unsigned>(MO.getImm());
170 } else if (MO.isFPImm()) {
171 return static_cast<unsigned>(APFloat(MO.getFPImm())
172 .bitcastToAPInt().getHiBits(32).getLimitedValue());
173 } else if (MO.isExpr()) {
174 const MCExpr *Expr = MO.getExpr();
175 MCExpr::ExprKind Kind = Expr->getKind();
178 if (Kind == MCExpr::Binary) {
179 const MCBinaryExpr *BE = static_cast<const MCBinaryExpr*>(Expr);
181 Kind = Expr->getKind();
182 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(BE->getRHS());
183 assert((Kind == MCExpr::SymbolRef) && CE &&
184 "Binary expression must be sym+const.");
185 Ret = CE->getValue();
188 if (Kind == MCExpr::SymbolRef) {
189 Mips::Fixups FixupKind;
190 switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
191 case MCSymbolRefExpr::VK_Mips_GPREL:
192 FixupKind = Mips::fixup_Mips_GPREL16;
194 case MCSymbolRefExpr::VK_Mips_GOT_CALL:
195 FixupKind = Mips::fixup_Mips_CALL16;
197 case MCSymbolRefExpr::VK_Mips_GOT:
198 FixupKind = Mips::fixup_Mips_GOT16;
200 case MCSymbolRefExpr::VK_Mips_ABS_HI:
201 FixupKind = Mips::fixup_Mips_HI16;
203 case MCSymbolRefExpr::VK_Mips_ABS_LO:
204 FixupKind = Mips::fixup_Mips_LO16;
206 case MCSymbolRefExpr::VK_Mips_TLSGD:
207 FixupKind = Mips::fixup_Mips_TLSGD;
209 case MCSymbolRefExpr::VK_Mips_GOTTPREL:
210 FixupKind = Mips::fixup_Mips_GOTTPREL;
212 case MCSymbolRefExpr::VK_Mips_TPREL_HI:
213 FixupKind = Mips::fixup_Mips_TPREL_HI;
215 case MCSymbolRefExpr::VK_Mips_TPREL_LO:
216 FixupKind = Mips::fixup_Mips_TPREL_LO;
221 Fixups.push_back(MCFixup::Create(0, Expr, MCFixupKind(FixupKind)));
223 // All of the information is in the fixup.
226 llvm_unreachable("Unable to encode MCOperand!");
231 /// getMemEncoding - Return binary encoding of memory related operand.
232 /// If the offset operand requires relocation, record the relocation.
234 MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
235 SmallVectorImpl<MCFixup> &Fixups) const {
236 // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
237 assert(MI.getOperand(OpNo).isReg());
238 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups) << 16;
239 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups);
241 return (OffBits & 0xFFFF) | RegBits;
245 MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
246 SmallVectorImpl<MCFixup> &Fixups) const {
247 assert(MI.getOperand(OpNo).isImm());
248 unsigned szEncoding = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups);
249 return szEncoding - 1;
252 // FIXME: should be called getMSBEncoding
255 MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
256 SmallVectorImpl<MCFixup> &Fixups) const {
257 assert(MI.getOperand(OpNo-1).isImm());
258 assert(MI.getOperand(OpNo).isImm());
259 unsigned pos = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups);
260 unsigned sz = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups);
265 #include "MipsGenMCCodeEmitter.inc"