blob: fce1f3914def7b7d187ef2f8df6c0e5b12aac148 [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.
Jim Grosbach3e094132010-10-08 17:45:54 +000047 unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO) const;
48 unsigned getMachineOpValue(const MCInst &MI, unsigned OpIdx) const {
Jim Grosbach9af82ba2010-10-07 21:57:55 +000049 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 Grosbach56ac9072010-10-08 21:45:55 +0000109/// getMachineOpValue - Return binary encoding of operand. If the machine
110/// operand requires relocation, record the relocation and return zero.
111unsigned ARMMCCodeEmitter::getMachineOpValue(const MCInst &MI,
112 const MCOperand &MO) const {
113 if (MO.isReg())
114 // FIXME: Should shifted register stuff be handled as part of this? Maybe.
115 return getARMRegisterNumbering(MO.getReg());
116 else if (MO.isImm())
117 // FIXME: This is insufficient. Shifted immediates and all that... (blech).
118 return static_cast<unsigned>(MO.getImm());
119 else {
120#ifndef NDEBUG
121 errs() << MO;
122#endif
123 llvm_unreachable(0);
124 }
125 return 0;
126}
127
Jim Grosbach568eeed2010-09-17 18:46:17 +0000128void ARMMCCodeEmitter::
129EncodeInstruction(const MCInst &MI, raw_ostream &OS,
130 SmallVectorImpl<MCFixup> &Fixups) const {
Jim Grosbachd6d4b422010-10-07 22:12:50 +0000131 unsigned Opcode = MI.getOpcode();
132 const TargetInstrDesc &Desc = TII.get(Opcode);
133 uint64_t TSFlags = Desc.TSFlags;
Jim Grosbach58f38bf2010-10-08 00:39:21 +0000134 // Keep track of the current byte being emitted.
135 unsigned CurByte = 0;
Jim Grosbachd6d4b422010-10-07 22:12:50 +0000136
137 // Pseudo instructions don't get encoded.
138 if ((TSFlags & ARMII::FormMask) == ARMII::Pseudo)
139 return;
140
141 ++MCNumEmitted; // Keep track of the # of mi's emitted
Jim Grosbach3e094132010-10-08 17:45:54 +0000142 switch (Opcode) {
143 //FIXME: Any non-pseudos that need special handling, if there are any...
144 default: {
Jim Grosbach58f38bf2010-10-08 00:39:21 +0000145 unsigned Value = getBinaryCodeForInstr(MI);
146 EmitConstant(Value, 4, CurByte, OS);
147 break;
148 }
Jim Grosbachd6d4b422010-10-07 22:12:50 +0000149 }
Jim Grosbach568eeed2010-09-17 18:46:17 +0000150}
Jim Grosbach9af82ba2010-10-07 21:57:55 +0000151
152// FIXME: These #defines shouldn't be necessary. Instead, tblgen should
153// be able to generate code emitter helpers for either variant, like it
154// does for the AsmWriter.
155#define ARMCodeEmitter ARMMCCodeEmitter
156#define MachineInstr MCInst
157#include "ARMGenCodeEmitter.inc"
158#undef ARMCodeEmitter
159#undef MachineInstr