blob: 5ccc8f5f7d1d8bc6d07ce21737a490259f741803 [file] [log] [blame]
Jim Grosbach568eeed2010-09-17 18:46:17 +00001//===-- ARM/ARMMCCodeEmitter.cpp - Convert ARM 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 ARMMCCodeEmitter class.
11//
12//===----------------------------------------------------------------------===//
13
14#define DEBUG_TYPE "arm-emitter"
15#include "ARM.h"
Jim Grosbachd6d4b422010-10-07 22:12:50 +000016#include "ARMInstrInfo.h"
Jim Grosbach568eeed2010-09-17 18:46:17 +000017#include "llvm/MC/MCCodeEmitter.h"
18#include "llvm/MC/MCExpr.h"
19#include "llvm/MC/MCInst.h"
Jim Grosbachd6d4b422010-10-07 22:12:50 +000020#include "llvm/ADT/Statistic.h"
Jim Grosbach568eeed2010-09-17 18:46:17 +000021#include "llvm/Support/raw_ostream.h"
22using namespace llvm;
23
Jim Grosbachd6d4b422010-10-07 22:12:50 +000024STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
25
Jim Grosbach568eeed2010-09-17 18:46:17 +000026namespace {
27class ARMMCCodeEmitter : public MCCodeEmitter {
28 ARMMCCodeEmitter(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
29 void operator=(const ARMMCCodeEmitter &); // DO NOT IMPLEMENT
30 const TargetMachine &TM;
31 const TargetInstrInfo &TII;
32 MCContext &Ctx;
33
34public:
35 ARMMCCodeEmitter(TargetMachine &tm, MCContext &ctx)
36 : TM(tm), TII(*TM.getInstrInfo()), Ctx(ctx) {
Jim Grosbach568eeed2010-09-17 18:46:17 +000037 }
38
39 ~ARMMCCodeEmitter() {}
40
Jim Grosbach9af82ba2010-10-07 21:57:55 +000041 // getBinaryCodeForInstr - TableGen'erated function for getting the
42 // binary encoding for an instruction.
Jim Grosbachbade37b2010-10-08 00:21:28 +000043 unsigned getBinaryCodeForInstr(const MCInst &MI) const;
Jim Grosbach9af82ba2010-10-07 21:57:55 +000044
45 /// getMachineOpValue - Return binary encoding of operand. If the machine
46 /// operand requires relocation, record the relocation and return zero.
47 unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO);
48 unsigned getMachineOpValue(const MCInst &MI, unsigned OpIdx) {
49 return getMachineOpValue(MI, MI.getOperand(OpIdx));
50 }
51
Jim Grosbach568eeed2010-09-17 18:46:17 +000052 unsigned getNumFixupKinds() const {
53 assert(0 && "ARMMCCodeEmitter::getNumFixupKinds() not yet implemented.");
Michael J. Spencer895dda62010-09-18 17:54:37 +000054 return 0;
Jim Grosbach568eeed2010-09-17 18:46:17 +000055 }
56
57 const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
58 static MCFixupKindInfo rtn;
59 assert(0 && "ARMMCCodeEmitter::getFixupKindInfo() not yet implemented.");
60 return rtn;
61 }
62
63 static unsigned GetARMRegNum(const MCOperand &MO) {
64 // FIXME: getARMRegisterNumbering() is sufficient?
65 assert(0 && "ARMMCCodeEmitter::GetARMRegNum() not yet implemented.");
66 return 0;
67 }
68
69 void EmitByte(unsigned char C, unsigned &CurByte, raw_ostream &OS) const {
70 OS << (char)C;
71 ++CurByte;
72 }
73
74 void EmitConstant(uint64_t Val, unsigned Size, unsigned &CurByte,
75 raw_ostream &OS) const {
76 // Output the constant in little endian byte order.
77 for (unsigned i = 0; i != Size; ++i) {
78 EmitByte(Val & 255, CurByte, OS);
79 Val >>= 8;
80 }
81 }
82
83 void EmitImmediate(const MCOperand &Disp,
84 unsigned ImmSize, MCFixupKind FixupKind,
85 unsigned &CurByte, raw_ostream &OS,
86 SmallVectorImpl<MCFixup> &Fixups,
87 int ImmOffset = 0) const;
88
89 void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
90 SmallVectorImpl<MCFixup> &Fixups) const;
Jim Grosbach568eeed2010-09-17 18:46:17 +000091};
92
93} // end anonymous namespace
94
95
96MCCodeEmitter *llvm::createARMMCCodeEmitter(const Target &,
97 TargetMachine &TM,
98 MCContext &Ctx) {
99 return new ARMMCCodeEmitter(TM, Ctx);
100}
101
102void ARMMCCodeEmitter::
103EmitImmediate(const MCOperand &DispOp, unsigned Size, MCFixupKind FixupKind,
104 unsigned &CurByte, raw_ostream &OS,
105 SmallVectorImpl<MCFixup> &Fixups, int ImmOffset) const {
106 assert(0 && "ARMMCCodeEmitter::EmitImmediate() not yet implemented.");
107}
108
Jim Grosbach568eeed2010-09-17 18:46:17 +0000109void ARMMCCodeEmitter::
110EncodeInstruction(const MCInst &MI, raw_ostream &OS,
111 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbachd6d4b422010-10-07 22:12:50 +0000112 unsigned Opcode = MI.getOpcode();
113 const TargetInstrDesc &Desc = TII.get(Opcode);
114 uint64_t TSFlags = Desc.TSFlags;
Jim Grosbach58f38bf2010-10-08 00:39:21 +0000115 // Keep track of the current byte being emitted.
116 unsigned CurByte = 0;
Jim Grosbachd6d4b422010-10-07 22:12:50 +0000117
118 // Pseudo instructions don't get encoded.
119 if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo)
120 return;
121
122 ++MCNumEmitted; // Keep track of the # of mi's emitted
123 switch (TSFlags & ARMII::FormMask) {
Jim Grosbach58f38bf2010-10-08 00:39:21 +0000124 case ARMII::BrMiscFrm:
125 case ARMII::MiscFrm: {
126 unsigned Value = getBinaryCodeForInstr(MI);
127 EmitConstant(Value, 4, CurByte, OS);
128 break;
129 }
Jim Grosbachd6d4b422010-10-07 22:12:50 +0000130 default: {
131 llvm_unreachable("Unhandled instruction encoding format!");
132 break;
133 }
134 }
Jim Grosbach568eeed2010-09-17 18:46:17 +0000135}
Jim Grosbach9af82ba2010-10-07 21:57:55 +0000136
137// FIXME: These #defines shouldn't be necessary. Instead, tblgen should
138// be able to generate code emitter helpers for either variant, like it
139// does for the AsmWriter.
140#define ARMCodeEmitter ARMMCCodeEmitter
141#define MachineInstr MCInst
142#include "ARMGenCodeEmitter.inc"
143#undef ARMCodeEmitter
144#undef MachineInstr