blob: 625c73f0f9bf22525dad2624dd45737154c3582f [file] [log] [blame]
Wesley Peck4e9141f2010-10-21 03:57:26 +00001//===-- MBlazeMCCodeEmitter.cpp - Convert MBlaze 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 MBlazeMCCodeEmitter class.
11//
12//===----------------------------------------------------------------------===//
13
Chris Lattner2ac19022010-11-15 05:19:05 +000014#define DEBUG_TYPE "mccodeemitter"
Wesley Peck4e9141f2010-10-21 03:57:26 +000015#include "MBlaze.h"
16#include "MBlazeInstrInfo.h"
17#include "MBlazeFixupKinds.h"
18#include "llvm/MC/MCCodeEmitter.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
21#include "llvm/MC/MCSymbol.h"
22#include "llvm/MC/MCFixup.h"
23#include "llvm/ADT/Statistic.h"
24#include "llvm/Support/raw_ostream.h"
25using namespace llvm;
26
27STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
28
29namespace {
30class MBlazeMCCodeEmitter : public MCCodeEmitter {
31 MBlazeMCCodeEmitter(const MBlazeMCCodeEmitter &); // DO NOT IMPLEMENT
32 void operator=(const MBlazeMCCodeEmitter &); // DO NOT IMPLEMENT
33 const TargetMachine &TM;
34 const TargetInstrInfo &TII;
35 MCContext &Ctx;
36
37public:
38 MBlazeMCCodeEmitter(TargetMachine &tm, MCContext &ctx)
39 : TM(tm), TII(*TM.getInstrInfo()), Ctx(ctx) {
40 }
41
42 ~MBlazeMCCodeEmitter() {}
43
44 // getBinaryCodeForInstr - TableGen'erated function for getting the
45 // binary encoding for an instruction.
46 unsigned getBinaryCodeForInstr(const MCInst &MI) const;
47
48 /// getMachineOpValue - Return binary encoding of operand. If the machine
49 /// operand requires relocation, record the relocation and return zero.
50 unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO) const;
51 unsigned getMachineOpValue(const MCInst &MI, unsigned OpIdx) const {
52 return getMachineOpValue(MI, MI.getOperand(OpIdx));
53 }
54
55 unsigned getNumFixupKinds() const {
56 return 2;
57 }
58
59 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
60 const static MCFixupKindInfo Infos[] = {
Wesley Peck4b047132010-11-21 22:06:28 +000061 // name offset bits flags
62 { "reloc_pcrel_4byte", 2, 4 * 8, MCFixupKindInfo::FKF_IsPCRel },
63 { "reloc_pcrel_2byte", 2, 2 * 8, MCFixupKindInfo::FKF_IsPCRel } };
Wesley Peck4e9141f2010-10-21 03:57:26 +000064
65 if (Kind < FirstTargetFixupKind)
66 return MCCodeEmitter::getFixupKindInfo(Kind);
67
68 if (unsigned(Kind-FirstTargetFixupKind) < getNumFixupKinds())
69 return Infos[Kind - FirstTargetFixupKind];
70
71 assert(0 && "Invalid fixup kind.");
72 return Infos[0];
73 }
74
75 static unsigned GetMBlazeRegNum(const MCOperand &MO) {
76 // FIXME: getMBlazeRegisterNumbering() is sufficient?
77 assert(0 && "MBlazeMCCodeEmitter::GetMBlazeRegNum() not yet implemented.");
78 return 0;
79 }
80
81 void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const {
82 // The MicroBlaze uses a bit reversed format so we need to reverse the
83 // order of the bits. Taken from:
84 // http://graphics.stanford.edu/~seander/bithacks.html
85 C = ((C * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32;
86
87 OS << (char)C;
88 ++CurByte;
89 }
90
91 void EmitRawByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const {
92 OS << (char)C;
93 ++CurByte;
94 }
95
96 void EmitConstant(uint64_t Val, unsigned Size, unsigned &CurByte,
97 raw_ostream &OS) const {
Wesley Peck0a67d922010-11-08 19:40:01 +000098 assert(Size <= 8 && "size too big in emit constant");
Wesley Peck4e9141f2010-10-21 03:57:26 +000099
100 for (unsigned i = 0; i != Size; ++i) {
101 EmitByte(Val & 255, CurByte, OS);
102 Val >>= 8;
103 }
104 }
105
106 void EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const;
Wesley Peck4b047132010-11-21 22:06:28 +0000107 void EmitIMM(const MCInst &MI, unsigned &CurByte, raw_ostream &OS) const;
Wesley Peck4e9141f2010-10-21 03:57:26 +0000108
Wesley Peck4b047132010-11-21 22:06:28 +0000109 void EmitImmediate(const MCInst &MI, unsigned opNo, bool pcrel,
Wesley Peck4e9141f2010-10-21 03:57:26 +0000110 unsigned &CurByte, raw_ostream &OS,
111 SmallVectorImpl<MCFixup> &Fixups) const;
112
113 void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
114 SmallVectorImpl<MCFixup> &Fixups) const;
115};
116
117} // end anonymous namespace
118
119
120MCCodeEmitter *llvm::createMBlazeMCCodeEmitter(const Target &,
121 TargetMachine &TM,
122 MCContext &Ctx) {
123 return new MBlazeMCCodeEmitter(TM, Ctx);
124}
125
126/// getMachineOpValue - Return binary encoding of operand. If the machine
127/// operand requires relocation, record the relocation and return zero.
128unsigned MBlazeMCCodeEmitter::getMachineOpValue(const MCInst &MI,
129 const MCOperand &MO) const {
130 if (MO.isReg())
131 return MBlazeRegisterInfo::getRegisterNumbering(MO.getReg());
132 else if (MO.isImm())
133 return static_cast<unsigned>(MO.getImm());
Wesley Peck0a67d922010-11-08 19:40:01 +0000134 else if (MO.isExpr())
Wesley Peck4e9141f2010-10-21 03:57:26 +0000135 return 0; // The relocation has already been recorded at this point.
136 else {
137#ifndef NDEBUG
138 errs() << MO;
139#endif
140 llvm_unreachable(0);
141 }
142 return 0;
143}
144
145void MBlazeMCCodeEmitter::
146EmitIMM(const MCOperand &imm, unsigned &CurByte, raw_ostream &OS) const {
147 int32_t val = (int32_t)imm.getImm();
Wesley Peckef5b3902010-11-11 21:40:53 +0000148 if (val > 32767 || val < -32768) {
Wesley Peck4e9141f2010-10-21 03:57:26 +0000149 EmitByte(0x0D, CurByte, OS);
150 EmitByte(0x00, CurByte, OS);
151 EmitRawByte((val >> 24) & 0xFF, CurByte, OS);
152 EmitRawByte((val >> 16) & 0xFF, CurByte, OS);
153 }
154}
155
156void MBlazeMCCodeEmitter::
Wesley Peck4b047132010-11-21 22:06:28 +0000157EmitIMM(const MCInst &MI, unsigned &CurByte,raw_ostream &OS) const {
158 switch (MI.getOpcode()) {
159 default: break;
160
161 case MBlaze::ADDI32:
162 case MBlaze::ORI32:
163 case MBlaze::BRLID32:
164 EmitByte(0x0D, CurByte, OS);
165 EmitByte(0x00, CurByte, OS);
166 EmitRawByte(0, CurByte, OS);
167 EmitRawByte(0, CurByte, OS);
168 }
Wesley Pecka0603832010-10-27 00:23:01 +0000169}
170
171void MBlazeMCCodeEmitter::
Wesley Peck4b047132010-11-21 22:06:28 +0000172EmitImmediate(const MCInst &MI, unsigned opNo, bool pcrel, unsigned &CurByte,
173 raw_ostream &OS, SmallVectorImpl<MCFixup> &Fixups) const {
Wesley Peck0a67d922010-11-08 19:40:01 +0000174 assert(MI.getNumOperands()>opNo && "Not enought operands for instruction");
Wesley Peck4e9141f2010-10-21 03:57:26 +0000175
176 MCOperand oper = MI.getOperand(opNo);
Wesley Peck4b047132010-11-21 22:06:28 +0000177
Wesley Peck4e9141f2010-10-21 03:57:26 +0000178 if (oper.isImm()) {
Wesley Peck4b047132010-11-21 22:06:28 +0000179 EmitIMM(oper, CurByte, OS);
Wesley Peck4e9141f2010-10-21 03:57:26 +0000180 } else if (oper.isExpr()) {
Wesley Peck4b047132010-11-21 22:06:28 +0000181 MCFixupKind FixupKind;
182 switch (MI.getOpcode()) {
183 default:
184 FixupKind = pcrel ? MCFixupKind(MBlaze::reloc_pcrel_2byte) : FK_Data_2;
Wesley Peck4e9141f2010-10-21 03:57:26 +0000185 Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind));
Wesley Peck4b047132010-11-21 22:06:28 +0000186 break;
187 case MBlaze::ORI32:
188 case MBlaze::ADDI32:
189 case MBlaze::BRLID32:
190 FixupKind = pcrel ? MCFixupKind(MBlaze::reloc_pcrel_4byte) : FK_Data_4;
191 Fixups.push_back(MCFixup::Create(0,oper.getExpr(),FixupKind));
192 break;
193 }
Wesley Peck4e9141f2010-10-21 03:57:26 +0000194 }
195}
196
Wesley Pecka0603832010-10-27 00:23:01 +0000197
198
Wesley Peck4e9141f2010-10-21 03:57:26 +0000199void MBlazeMCCodeEmitter::
200EncodeInstruction(const MCInst &MI, raw_ostream &OS,
201 SmallVectorImpl<MCFixup> &Fixups) const {
202 unsigned Opcode = MI.getOpcode();
203 const TargetInstrDesc &Desc = TII.get(Opcode);
204 uint64_t TSFlags = Desc.TSFlags;
205 // Keep track of the current byte being emitted.
206 unsigned CurByte = 0;
207
Wesley Peck4b047132010-11-21 22:06:28 +0000208 // Emit an IMM instruction if the instruction we are encoding requires it
209 EmitIMM(MI,CurByte,OS);
210
Wesley Peck4e9141f2010-10-21 03:57:26 +0000211 switch ((TSFlags & MBlazeII::FormMask)) {
212 default: break;
Wesley Pecka0603832010-10-27 00:23:01 +0000213 case MBlazeII::FPseudo:
Wesley Peck4e9141f2010-10-21 03:57:26 +0000214 // Pseudo instructions don't get encoded.
215 return;
Wesley Pecka0603832010-10-27 00:23:01 +0000216 case MBlazeII::FRRI:
Wesley Peck4b047132010-11-21 22:06:28 +0000217 EmitImmediate(MI, 2, false, CurByte, OS, Fixups);
Wesley Peck4e9141f2010-10-21 03:57:26 +0000218 break;
Wesley Pecka0603832010-10-27 00:23:01 +0000219 case MBlazeII::FRIR:
Wesley Peck4b047132010-11-21 22:06:28 +0000220 EmitImmediate(MI, 1, false, CurByte, OS, Fixups);
Wesley Peck4e9141f2010-10-21 03:57:26 +0000221 break;
Wesley Pecka0603832010-10-27 00:23:01 +0000222 case MBlazeII::FCRI:
Wesley Peck4b047132010-11-21 22:06:28 +0000223 EmitImmediate(MI, 1, true, CurByte, OS, Fixups);
Wesley Peck4e9141f2010-10-21 03:57:26 +0000224 break;
Wesley Pecka0603832010-10-27 00:23:01 +0000225 case MBlazeII::FRCI:
Wesley Peck4b047132010-11-21 22:06:28 +0000226 EmitImmediate(MI, 1, true, CurByte, OS, Fixups);
Wesley Pecka0603832010-10-27 00:23:01 +0000227 case MBlazeII::FCCI:
Wesley Peck4b047132010-11-21 22:06:28 +0000228 EmitImmediate(MI, 0, true, CurByte, OS, Fixups);
Wesley Peck4e9141f2010-10-21 03:57:26 +0000229 break;
230 }
231
232 ++MCNumEmitted; // Keep track of the # of mi's emitted
233 unsigned Value = getBinaryCodeForInstr(MI);
Wesley Peck4b047132010-11-21 22:06:28 +0000234 EmitConstant(Value, 4, CurByte, OS);
Wesley Peck4e9141f2010-10-21 03:57:26 +0000235}
236
237// FIXME: These #defines shouldn't be necessary. Instead, tblgen should
238// be able to generate code emitter helpers for either variant, like it
239// does for the AsmWriter.
240#define MBlazeCodeEmitter MBlazeMCCodeEmitter
241#define MachineInstr MCInst
242#include "MBlazeGenCodeEmitter.inc"
243#undef MBlazeCodeEmitter
244#undef MachineInstr