add a fixup for conditional branches, giving us output like this:
[oota-llvm.git] / lib / Target / PowerPC / PPCMCCodeEmitter.cpp
1 //===-- PPCMCCodeEmitter.cpp - Convert PPC 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 PPCMCCodeEmitter class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #define DEBUG_TYPE "mccodeemitter"
15 #include "PPC.h"
16 #include "PPCRegisterInfo.h"
17 #include "PPCFixupKinds.h"
18 #include "llvm/MC/MCCodeEmitter.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/ADT/Statistic.h"
21 #include "llvm/Support/raw_ostream.h"
22 #include "llvm/Support/ErrorHandling.h"
23 using namespace llvm;
24
25 STATISTIC(MCNumEmitted, "Number of MC instructions emitted");
26
27 namespace {
28 class PPCMCCodeEmitter : public MCCodeEmitter {
29   PPCMCCodeEmitter(const PPCMCCodeEmitter &); // DO NOT IMPLEMENT
30   void operator=(const PPCMCCodeEmitter &);   // DO NOT IMPLEMENT
31   const TargetMachine &TM;
32   MCContext &Ctx;
33   
34 public:
35   PPCMCCodeEmitter(TargetMachine &tm, MCContext &ctx)
36     : TM(tm), Ctx(ctx) {
37   }
38   
39   ~PPCMCCodeEmitter() {}
40   
41   unsigned getNumFixupKinds() const { return PPC::NumTargetFixupKinds; }
42   
43   const MCFixupKindInfo &getFixupKindInfo(MCFixupKind Kind) const {
44     const static MCFixupKindInfo Infos[] = {
45       // name                     offset  bits  flags
46       { "fixup_ppc_br24",         6,      24,   MCFixupKindInfo::FKF_IsPCRel },
47       { "fixup_ppc_brcond14",     16,     14,   MCFixupKindInfo::FKF_IsPCRel }
48     };
49     
50     if (Kind < FirstTargetFixupKind)
51       return MCCodeEmitter::getFixupKindInfo(Kind);
52     
53     assert(unsigned(Kind - FirstTargetFixupKind) < getNumFixupKinds() &&
54            "Invalid kind!");
55     return Infos[Kind - FirstTargetFixupKind];
56   }
57
58   unsigned getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
59                                SmallVectorImpl<MCFixup> &Fixups) const;
60
61   unsigned getCondBrEncoding(const MCInst &MI, unsigned OpNo,
62                              SmallVectorImpl<MCFixup> &Fixups) const;
63
64   unsigned get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
65                                SmallVectorImpl<MCFixup> &Fixups) const;
66
67   /// getMachineOpValue - Return binary encoding of operand. If the machine
68   /// operand requires relocation, record the relocation and return zero.
69   unsigned getMachineOpValue(const MCInst &MI,const MCOperand &MO,
70                              SmallVectorImpl<MCFixup> &Fixups) const;
71   
72   // getBinaryCodeForInstr - TableGen'erated function for getting the
73   // binary encoding for an instruction.
74   unsigned getBinaryCodeForInstr(const MCInst &MI,
75                                  SmallVectorImpl<MCFixup> &Fixups) const;
76   void EncodeInstruction(const MCInst &MI, raw_ostream &OS,
77                          SmallVectorImpl<MCFixup> &Fixups) const {
78     unsigned Bits = getBinaryCodeForInstr(MI, Fixups);
79     
80     // Output the constant in big endian byte order.
81     for (unsigned i = 0; i != 4; ++i) {
82       OS << (char)(Bits >> 24);
83       Bits <<= 8;
84     }
85     
86     ++MCNumEmitted;  // Keep track of the # of mi's emitted.
87   }
88   
89 };
90   
91 } // end anonymous namespace
92   
93 MCCodeEmitter *llvm::createPPCMCCodeEmitter(const Target &, TargetMachine &TM,
94                                             MCContext &Ctx) {
95   return new PPCMCCodeEmitter(TM, Ctx);
96 }
97
98 unsigned PPCMCCodeEmitter::
99 getDirectBrEncoding(const MCInst &MI, unsigned OpNo,
100                     SmallVectorImpl<MCFixup> &Fixups) const {
101   const MCOperand &MO = MI.getOperand(OpNo);
102   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
103   
104   // Add a fixup for the branch target.
105   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
106                                    (MCFixupKind)PPC::fixup_ppc_br24));
107   return 0;
108 }
109
110 unsigned PPCMCCodeEmitter::getCondBrEncoding(const MCInst &MI, unsigned OpNo,
111                                      SmallVectorImpl<MCFixup> &Fixups) const {
112   const MCOperand &MO = MI.getOperand(OpNo);
113   if (MO.isReg() || MO.isImm()) return getMachineOpValue(MI, MO, Fixups);
114
115   // Add a fixup for the branch target.
116   Fixups.push_back(MCFixup::Create(0, MO.getExpr(),
117                                    (MCFixupKind)PPC::fixup_ppc_brcond14));
118   return 0;
119 }
120
121
122 unsigned PPCMCCodeEmitter::
123 get_crbitm_encoding(const MCInst &MI, unsigned OpNo,
124                     SmallVectorImpl<MCFixup> &Fixups) const {
125   const MCOperand &MO = MI.getOperand(OpNo);
126   assert((MI.getOpcode() == PPC::MTCRF || MI.getOpcode() == PPC::MFOCRF) &&
127          (MO.getReg() >= PPC::CR0 && MO.getReg() <= PPC::CR7));
128   return 0x80 >> PPCRegisterInfo::getRegisterNumbering(MO.getReg());
129 }
130
131
132 unsigned PPCMCCodeEmitter::
133 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
134                   SmallVectorImpl<MCFixup> &Fixups) const {
135   if (MO.isReg()) {
136     assert(MI.getOpcode() != PPC::MTCRF && MI.getOpcode() != PPC::MFOCRF);
137     return PPCRegisterInfo::getRegisterNumbering(MO.getReg());
138   }
139   
140   if (MO.isImm())
141     return MO.getImm();
142   
143   // FIXME.
144   return 0;
145 }
146
147
148 #include "PPCGenMCCodeEmitter.inc"