1 //===-- MBlazeMCCodeEmitter.cpp - Convert MBlaze 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 MBlazeMCCodeEmitter class.
12 //===----------------------------------------------------------------------===//
14 #define DEBUG_TYPE "mccodeemitter"
16 #include "MBlazeInstrInfo.h"
17 #include "llvm/MC/MCCodeEmitter.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCSymbol.h"
21 #include "llvm/MC/MCFixup.h"
22 #include "llvm/ADT/Statistic.h"
23 #include "llvm/Support/raw_ostream.h"
26 STATISTIC(MCNumEmitted
, "Number of MC instructions emitted");
29 class MBlazeMCCodeEmitter
: public MCCodeEmitter
{
30 MBlazeMCCodeEmitter(const MBlazeMCCodeEmitter
&); // DO NOT IMPLEMENT
31 void operator=(const MBlazeMCCodeEmitter
&); // DO NOT IMPLEMENT
32 const TargetMachine
&TM
;
33 const TargetInstrInfo
&TII
;
37 MBlazeMCCodeEmitter(TargetMachine
&tm
, MCContext
&ctx
)
38 : TM(tm
), TII(*TM
.getInstrInfo()), Ctx(ctx
) {
41 ~MBlazeMCCodeEmitter() {}
43 // getBinaryCodeForInstr - TableGen'erated function for getting the
44 // binary encoding for an instruction.
45 unsigned getBinaryCodeForInstr(const MCInst
&MI
) const;
47 /// getMachineOpValue - Return binary encoding of operand. If the machine
48 /// operand requires relocation, record the relocation and return zero.
49 unsigned getMachineOpValue(const MCInst
&MI
,const MCOperand
&MO
) const;
50 unsigned getMachineOpValue(const MCInst
&MI
, unsigned OpIdx
) const {
51 return getMachineOpValue(MI
, MI
.getOperand(OpIdx
));
54 static unsigned GetMBlazeRegNum(const MCOperand
&MO
) {
55 // FIXME: getMBlazeRegisterNumbering() is sufficient?
56 assert(0 && "MBlazeMCCodeEmitter::GetMBlazeRegNum() not yet implemented.");
60 void EmitByte(unsigned char C
, unsigned &CurByte
, raw_ostream
&OS
) const {
61 // The MicroBlaze uses a bit reversed format so we need to reverse the
62 // order of the bits. Taken from:
63 // http://graphics.stanford.edu/~seander/bithacks.html
64 C
= ((C
* 0x80200802ULL
) & 0x0884422110ULL
) * 0x0101010101ULL
>> 32;
70 void EmitRawByte(unsigned char C
, unsigned &CurByte
, raw_ostream
&OS
) const {
75 void EmitConstant(uint64_t Val
, unsigned Size
, unsigned &CurByte
,
76 raw_ostream
&OS
) const {
77 assert(Size
<= 8 && "size too big in emit constant");
79 for (unsigned i
= 0; i
!= Size
; ++i
) {
80 EmitByte(Val
& 255, CurByte
, OS
);
85 void EmitIMM(const MCOperand
&imm
, unsigned &CurByte
, raw_ostream
&OS
) const;
86 void EmitIMM(const MCInst
&MI
, unsigned &CurByte
, raw_ostream
&OS
) const;
88 void EmitImmediate(const MCInst
&MI
, unsigned opNo
, bool pcrel
,
89 unsigned &CurByte
, raw_ostream
&OS
,
90 SmallVectorImpl
<MCFixup
> &Fixups
) const;
92 void EncodeInstruction(const MCInst
&MI
, raw_ostream
&OS
,
93 SmallVectorImpl
<MCFixup
> &Fixups
) const;
96 } // end anonymous namespace
99 MCCodeEmitter
*llvm::createMBlazeMCCodeEmitter(const Target
&,
102 return new MBlazeMCCodeEmitter(TM
, Ctx
);
105 /// getMachineOpValue - Return binary encoding of operand. If the machine
106 /// operand requires relocation, record the relocation and return zero.
107 unsigned MBlazeMCCodeEmitter::getMachineOpValue(const MCInst
&MI
,
108 const MCOperand
&MO
) const {
110 return MBlazeRegisterInfo::getRegisterNumbering(MO
.getReg());
112 return static_cast<unsigned>(MO
.getImm());
113 else if (MO
.isExpr())
114 return 0; // The relocation has already been recorded at this point.
124 void MBlazeMCCodeEmitter::
125 EmitIMM(const MCOperand
&imm
, unsigned &CurByte
, raw_ostream
&OS
) const {
126 int32_t val
= (int32_t)imm
.getImm();
127 if (val
> 32767 || val
< -32768) {
128 EmitByte(0x0D, CurByte
, OS
);
129 EmitByte(0x00, CurByte
, OS
);
130 EmitRawByte((val
>> 24) & 0xFF, CurByte
, OS
);
131 EmitRawByte((val
>> 16) & 0xFF, CurByte
, OS
);
135 void MBlazeMCCodeEmitter::
136 EmitIMM(const MCInst
&MI
, unsigned &CurByte
,raw_ostream
&OS
) const {
137 switch (MI
.getOpcode()) {
140 case MBlaze::ADDIK32
:
142 case MBlaze::BRLID32
:
143 EmitByte(0x0D, CurByte
, OS
);
144 EmitByte(0x00, CurByte
, OS
);
145 EmitRawByte(0, CurByte
, OS
);
146 EmitRawByte(0, CurByte
, OS
);
150 void MBlazeMCCodeEmitter::
151 EmitImmediate(const MCInst
&MI
, unsigned opNo
, bool pcrel
, unsigned &CurByte
,
152 raw_ostream
&OS
, SmallVectorImpl
<MCFixup
> &Fixups
) const {
153 assert(MI
.getNumOperands()>opNo
&& "Not enought operands for instruction");
155 MCOperand oper
= MI
.getOperand(opNo
);
158 EmitIMM(oper
, CurByte
, OS
);
159 } else if (oper
.isExpr()) {
160 MCFixupKind FixupKind
;
161 switch (MI
.getOpcode()) {
163 FixupKind
= pcrel
? FK_PCRel_2
: FK_Data_2
;
164 Fixups
.push_back(MCFixup::Create(0,oper
.getExpr(),FixupKind
));
167 case MBlaze::ADDIK32
:
168 case MBlaze::BRLID32
:
169 FixupKind
= pcrel
? FK_PCRel_4
: FK_Data_4
;
170 Fixups
.push_back(MCFixup::Create(0,oper
.getExpr(),FixupKind
));
178 void MBlazeMCCodeEmitter::
179 EncodeInstruction(const MCInst
&MI
, raw_ostream
&OS
,
180 SmallVectorImpl
<MCFixup
> &Fixups
) const {
181 unsigned Opcode
= MI
.getOpcode();
182 const TargetInstrDesc
&Desc
= TII
.get(Opcode
);
183 uint64_t TSFlags
= Desc
.TSFlags
;
184 // Keep track of the current byte being emitted.
185 unsigned CurByte
= 0;
187 // Emit an IMM instruction if the instruction we are encoding requires it
188 EmitIMM(MI
,CurByte
,OS
);
190 switch ((TSFlags
& MBlazeII::FormMask
)) {
192 case MBlazeII::FPseudo
:
193 // Pseudo instructions don't get encoded.
196 EmitImmediate(MI
, 2, false, CurByte
, OS
, Fixups
);
199 EmitImmediate(MI
, 1, false, CurByte
, OS
, Fixups
);
202 EmitImmediate(MI
, 1, true, CurByte
, OS
, Fixups
);
205 EmitImmediate(MI
, 1, true, CurByte
, OS
, Fixups
);
207 EmitImmediate(MI
, 0, true, CurByte
, OS
, Fixups
);
211 ++MCNumEmitted
; // Keep track of the # of mi's emitted
212 unsigned Value
= getBinaryCodeForInstr(MI
);
213 EmitConstant(Value
, 4, CurByte
, OS
);
216 // FIXME: These #defines shouldn't be necessary. Instead, tblgen should
217 // be able to generate code emitter helpers for either variant, like it
218 // does for the AsmWriter.
219 #define MBlazeCodeEmitter MBlazeMCCodeEmitter
220 #define MachineInstr MCInst
221 #include "MBlazeGenCodeEmitter.inc"
222 #undef MBlazeCodeEmitter