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;
40 MipsMCCodeEmitter(const MCInstrInfo &mcii, const MCSubtargetInfo &sti,
41 MCContext &ctx, bool IsLittle) :
42 MCII(mcii), STI(sti) , Ctx(ctx), IsLittleEndian(IsLittle) {}
44 ~MipsMCCodeEmitter() {}
46 void EmitByte(unsigned char C, raw_ostream &OS) const {
50 void EmitInstruction(uint64_t Val, unsigned Size, raw_ostream &OS) const {
51 // Output the instruction encoding in little endian byte order.
52 for (unsigned i = 0; i < Size; ++i) {
53 unsigned Shift = IsLittleEndian ? i * 8 : (Size - 1 - i) * 8;
54 EmitByte((Val >> Shift) & 0xff, OS);
58 void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
59 SmallVectorImpl<MCFixup> &Fixups) const;
61 // getBinaryCodeForInstr - TableGen'erated function for getting the
62 // binary encoding for an instruction.
63 uint64_t getBinaryCodeForInstr(const MCInst &MI,
64 SmallVectorImpl<MCFixup> &Fixups) const;
66 // getBranchJumpOpValue - Return binary encoding of the jump
67 // target operand. If the machine operand requires relocation,
68 // record the relocation and return zero.
69 unsigned getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
70 SmallVectorImpl<MCFixup> &Fixups) const;
72 // getBranchTargetOpValue - Return binary encoding of the branch
73 // target operand. If the machine operand requires relocation,
74 // record the relocation and return zero.
75 unsigned getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
76 SmallVectorImpl<MCFixup> &Fixups) const;
78 // getMachineOpValue - Return binary encoding of operand. If the machin
79 // operand requires relocation, record the relocation and return zero.
80 unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
81 SmallVectorImpl<MCFixup> &Fixups) const;
83 unsigned getMemEncoding(const MCInst &MI, unsigned OpNo,
84 SmallVectorImpl<MCFixup> &Fixups) const;
85 unsigned getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
86 SmallVectorImpl<MCFixup> &Fixups) const;
87 unsigned getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
88 SmallVectorImpl<MCFixup> &Fixups) const;
90 }; // class MipsMCCodeEmitter
93 MCCodeEmitter *llvm::createMipsMCCodeEmitterEB(const MCInstrInfo &MCII,
94 const MCSubtargetInfo &STI,
97 return new MipsMCCodeEmitter(MCII, STI, Ctx, false);
100 MCCodeEmitter *llvm::createMipsMCCodeEmitterEL(const MCInstrInfo &MCII,
101 const MCSubtargetInfo &STI,
104 return new MipsMCCodeEmitter(MCII, STI, Ctx, true);
107 /// EncodeInstruction - Emit the instruction.
108 /// Size the instruction (currently only 4 bytes
109 void MipsMCCodeEmitter::
110 EncodeInstruction(const MCInst &MI, raw_ostream &OS,
111 SmallVectorImpl<MCFixup> &Fixups) const
113 uint32_t Binary = getBinaryCodeForInstr(MI, Fixups);
115 // Check for unimplemented opcodes.
116 // Unfortunately in MIPS both NOT and SLL will come in with Binary == 0
117 // so we have to special check for them.
118 unsigned Opcode = MI.getOpcode();
119 if ((Opcode != Mips::NOP) && (Opcode != Mips::SLL) && !Binary)
120 llvm_unreachable("unimplemented opcode in EncodeInstruction()");
122 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
123 uint64_t TSFlags = Desc.TSFlags;
125 // Pseudo instructions don't get encoded and shouldn't be here
126 // in the first place!
127 if ((TSFlags & MipsII::FormMask) == MipsII::Pseudo)
128 llvm_unreachable("Pseudo opcode found in EncodeInstruction()");
130 // For now all instructions are 4 bytes
131 int Size = 4; // FIXME: Have Desc.getSize() return the correct value!
133 EmitInstruction(Binary, Size, OS);
136 /// getBranchTargetOpValue - Return binary encoding of the branch
137 /// target operand. If the machine operand requires relocation,
138 /// record the relocation and return zero.
139 unsigned MipsMCCodeEmitter::
140 getBranchTargetOpValue(const MCInst &MI, unsigned OpNo,
141 SmallVectorImpl<MCFixup> &Fixups) const {
143 const MCOperand &MO = MI.getOperand(OpNo);
144 assert(MO.isExpr() && "getBranchTargetOpValue expects only expressions");
146 const MCExpr *Expr = MO.getExpr();
147 Fixups.push_back(MCFixup::Create(0, Expr,
148 MCFixupKind(Mips::fixup_Mips_PC16)));
152 /// getJumpTargetOpValue - Return binary encoding of the jump
153 /// target operand. If the machine operand requires relocation,
154 /// record the relocation and return zero.
155 unsigned MipsMCCodeEmitter::
156 getJumpTargetOpValue(const MCInst &MI, unsigned OpNo,
157 SmallVectorImpl<MCFixup> &Fixups) const {
159 const MCOperand &MO = MI.getOperand(OpNo);
160 assert(MO.isExpr() && "getJumpTargetOpValue expects only expressions");
162 const MCExpr *Expr = MO.getExpr();
163 Fixups.push_back(MCFixup::Create(0, Expr,
164 MCFixupKind(Mips::fixup_Mips_26)));
168 /// getMachineOpValue - Return binary encoding of operand. If the machine
169 /// operand requires relocation, record the relocation and return zero.
170 unsigned MipsMCCodeEmitter::
171 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
172 SmallVectorImpl<MCFixup> &Fixups) const {
174 unsigned Reg = MO.getReg();
175 unsigned RegNo = getMipsRegisterNumbering(Reg);
177 } else if (MO.isImm()) {
178 return static_cast<unsigned>(MO.getImm());
179 } else if (MO.isFPImm()) {
180 return static_cast<unsigned>(APFloat(MO.getFPImm())
181 .bitcastToAPInt().getHiBits(32).getLimitedValue());
184 // MO must be an Expr.
187 const MCExpr *Expr = MO.getExpr();
188 MCExpr::ExprKind Kind = Expr->getKind();
190 if (Kind == MCExpr::Binary) {
191 Expr = static_cast<const MCBinaryExpr*>(Expr)->getLHS();
192 Kind = Expr->getKind();
195 assert (Kind == MCExpr::SymbolRef);
197 Mips::Fixups FixupKind = Mips::Fixups(0);
199 switch(cast<MCSymbolRefExpr>(Expr)->getKind()) {
200 case MCSymbolRefExpr::VK_Mips_GPREL:
201 FixupKind = Mips::fixup_Mips_GPREL16;
203 case MCSymbolRefExpr::VK_Mips_GOT_CALL:
204 FixupKind = Mips::fixup_Mips_CALL16;
206 case MCSymbolRefExpr::VK_Mips_GOT16:
207 FixupKind = Mips::fixup_Mips_GOT_Global;
209 case MCSymbolRefExpr::VK_Mips_GOT:
210 FixupKind = Mips::fixup_Mips_GOT_Local;
212 case MCSymbolRefExpr::VK_Mips_ABS_HI:
213 FixupKind = Mips::fixup_Mips_HI16;
215 case MCSymbolRefExpr::VK_Mips_ABS_LO:
216 FixupKind = Mips::fixup_Mips_LO16;
218 case MCSymbolRefExpr::VK_Mips_TLSGD:
219 FixupKind = Mips::fixup_Mips_TLSGD;
221 case MCSymbolRefExpr::VK_Mips_TLSLDM:
222 FixupKind = Mips::fixup_Mips_TLSLDM;
224 case MCSymbolRefExpr::VK_Mips_DTPREL_HI:
225 FixupKind = Mips::fixup_Mips_DTPREL_HI;
227 case MCSymbolRefExpr::VK_Mips_DTPREL_LO:
228 FixupKind = Mips::fixup_Mips_DTPREL_LO;
230 case MCSymbolRefExpr::VK_Mips_GOTTPREL:
231 FixupKind = Mips::fixup_Mips_GOTTPREL;
233 case MCSymbolRefExpr::VK_Mips_TPREL_HI:
234 FixupKind = Mips::fixup_Mips_TPREL_HI;
236 case MCSymbolRefExpr::VK_Mips_TPREL_LO:
237 FixupKind = Mips::fixup_Mips_TPREL_LO;
243 Fixups.push_back(MCFixup::Create(0, MO.getExpr(), MCFixupKind(FixupKind)));
245 // All of the information is in the fixup.
249 /// getMemEncoding - Return binary encoding of memory related operand.
250 /// If the offset operand requires relocation, record the relocation.
252 MipsMCCodeEmitter::getMemEncoding(const MCInst &MI, unsigned OpNo,
253 SmallVectorImpl<MCFixup> &Fixups) const {
254 // Base register is encoded in bits 20-16, offset is encoded in bits 15-0.
255 assert(MI.getOperand(OpNo).isReg());
256 unsigned RegBits = getMachineOpValue(MI, MI.getOperand(OpNo),Fixups) << 16;
257 unsigned OffBits = getMachineOpValue(MI, MI.getOperand(OpNo+1), Fixups);
259 return (OffBits & 0xFFFF) | RegBits;
263 MipsMCCodeEmitter::getSizeExtEncoding(const MCInst &MI, unsigned OpNo,
264 SmallVectorImpl<MCFixup> &Fixups) const {
265 assert(MI.getOperand(OpNo).isImm());
266 unsigned SizeEncoding = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups);
267 return SizeEncoding - 1;
270 // FIXME: should be called getMSBEncoding
273 MipsMCCodeEmitter::getSizeInsEncoding(const MCInst &MI, unsigned OpNo,
274 SmallVectorImpl<MCFixup> &Fixups) const {
275 assert(MI.getOperand(OpNo-1).isImm());
276 assert(MI.getOperand(OpNo).isImm());
277 unsigned Position = getMachineOpValue(MI, MI.getOperand(OpNo-1), Fixups);
278 unsigned Size = getMachineOpValue(MI, MI.getOperand(OpNo), Fixups);
280 return Position + Size - 1;
283 #include "MipsGenMCCodeEmitter.inc"