blob: 908f6f08b9ab63f41f9a58b7e55cddac56242cff [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;
115
116 // Pseudo instructions don't get encoded.
117 if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo)
118 return;
119
120 ++MCNumEmitted; // Keep track of the # of mi's emitted
121 switch (TSFlags & ARMII::FormMask) {
122 default: {
123 llvm_unreachable("Unhandled instruction encoding format!");
124 break;
125 }
126 }
Jim Grosbach568eeed2010-09-17 18:46:17 +0000127}
Jim Grosbach9af82ba2010-10-07 21:57:55 +0000128
129// FIXME: These #defines shouldn't be necessary. Instead, tblgen should
130// be able to generate code emitter helpers for either variant, like it
131// does for the AsmWriter.
132#define ARMCodeEmitter ARMMCCodeEmitter
133#define MachineInstr MCInst
134#include "ARMGenCodeEmitter.inc"
135#undef ARMCodeEmitter
136#undef MachineInstr