1 //===-- MSP430MCCodeEmitter.cpp - Convert MSP430 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 MSP430MCCodeEmitter class.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #include "MSP430.h"
15 #include "MCTargetDesc/MSP430MCTargetDesc.h"
16 #include "MCTargetDesc/MSP430FixupKinds.h"
17
18 #include "llvm/ADT/APFloat.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/MC/MCCodeEmitter.h"
21 #include "llvm/MC/MCContext.h"
22 #include "llvm/MC/MCExpr.h"
23 #include "llvm/MC/MCFixup.h"
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/MC/MCInstrInfo.h"
26 #include "llvm/MC/MCRegisterInfo.h"
27 #include "llvm/MC/MCSubtargetInfo.h"
28 #include "llvm/Support/Endian.h"
29 #include "llvm/Support/EndianStream.h"
30 #include "llvm/Support/raw_ostream.h"
31
32 #define DEBUG_TYPE "mccodeemitter"
33
34 namespace llvm {
35
36 class MSP430MCCodeEmitter : public MCCodeEmitter {
37 MCContext &Ctx;
38 MCInstrInfo const &MCII;
39
40 // Offset keeps track of current word number being emitted
41 // inside a particular instruction.
42 mutable unsigned Offset;
43
44 /// TableGen'erated function for getting the binary encoding for an
45 /// instruction.
46 uint64_t getBinaryCodeForInstr(const MCInst &MI,
47 SmallVectorImpl<MCFixup> &Fixups,
48 const MCSubtargetInfo &STI) const;
49
50 /// Returns the binary encoding of operands.
51 ///
52 /// If an operand requires relocation, the relocation is recorded
53 /// and zero is returned.
54 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
55 SmallVectorImpl<MCFixup> &Fixups,
56 const MCSubtargetInfo &STI) const;
57
58 unsigned getMemOpValue(const MCInst &MI, unsigned Op,
59 SmallVectorImpl<MCFixup> &Fixups,
60 const MCSubtargetInfo &STI) const;
61
62 unsigned getPCRelImmOpValue(const MCInst &MI, unsigned Op,
63 SmallVectorImpl<MCFixup> &Fixups,
64 const MCSubtargetInfo &STI) const;
65
66 unsigned getCGImmOpValue(const MCInst &MI, unsigned Op,
67 SmallVectorImpl<MCFixup> &Fixups,
68 const MCSubtargetInfo &STI) const;
69
70 unsigned getCCOpValue(const MCInst &MI, unsigned Op,
71 SmallVectorImpl<MCFixup> &Fixups,
72 const MCSubtargetInfo &STI) const;
73
74 public:
MSP430MCCodeEmitter(MCContext & ctx,MCInstrInfo const & MCII)75 MSP430MCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
76 : Ctx(ctx), MCII(MCII) {}
77
78 void encodeInstruction(const MCInst &MI, raw_ostream &OS,
79 SmallVectorImpl<MCFixup> &Fixups,
80 const MCSubtargetInfo &STI) const override;
81 };
82
encodeInstruction(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const83 void MSP430MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
84 SmallVectorImpl<MCFixup> &Fixups,
85 const MCSubtargetInfo &STI) const {
86 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
87 // Get byte count of instruction.
88 unsigned Size = Desc.getSize();
89
90 // Initialize fixup offset
91 Offset = 2;
92
93 uint64_t BinaryOpCode = getBinaryCodeForInstr(MI, Fixups, STI);
94 size_t WordCount = Size / 2;
95
96 while (WordCount--) {
97 support::endian::write(OS, (uint16_t)BinaryOpCode, support::little);
98 BinaryOpCode >>= 16;
99 }
100 }
101
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const102 unsigned MSP430MCCodeEmitter::getMachineOpValue(const MCInst &MI,
103 const MCOperand &MO,
104 SmallVectorImpl<MCFixup> &Fixups,
105 const MCSubtargetInfo &STI) const {
106 if (MO.isReg())
107 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
108
109 if (MO.isImm()) {
110 Offset += 2;
111 return MO.getImm();
112 }
113
114 assert(MO.isExpr() && "Expected expr operand");
115 Fixups.push_back(MCFixup::create(Offset, MO.getExpr(),
116 static_cast<MCFixupKind>(MSP430::fixup_16_byte), MI.getLoc()));
117 Offset += 2;
118 return 0;
119 }
120
getMemOpValue(const MCInst & MI,unsigned Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const121 unsigned MSP430MCCodeEmitter::getMemOpValue(const MCInst &MI, unsigned Op,
122 SmallVectorImpl<MCFixup> &Fixups,
123 const MCSubtargetInfo &STI) const {
124 const MCOperand &MO1 = MI.getOperand(Op);
125 assert(MO1.isReg() && "Register operand expected");
126 unsigned Reg = Ctx.getRegisterInfo()->getEncodingValue(MO1.getReg());
127
128 const MCOperand &MO2 = MI.getOperand(Op + 1);
129 if (MO2.isImm()) {
130 Offset += 2;
131 return ((unsigned)MO2.getImm() << 4) | Reg;
132 }
133
134 assert(MO2.isExpr() && "Expr operand expected");
135 MSP430::Fixups FixupKind;
136 switch (Reg) {
137 case 0:
138 FixupKind = MSP430::fixup_16_pcrel_byte;
139 break;
140 case 2:
141 FixupKind = MSP430::fixup_16_byte;
142 break;
143 default:
144 FixupKind = MSP430::fixup_16_byte;
145 break;
146 }
147 Fixups.push_back(MCFixup::create(Offset, MO2.getExpr(),
148 static_cast<MCFixupKind>(FixupKind), MI.getLoc()));
149 Offset += 2;
150 return Reg;
151 }
152
getPCRelImmOpValue(const MCInst & MI,unsigned Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const153 unsigned MSP430MCCodeEmitter::getPCRelImmOpValue(const MCInst &MI, unsigned Op,
154 SmallVectorImpl<MCFixup> &Fixups,
155 const MCSubtargetInfo &STI) const {
156 const MCOperand &MO = MI.getOperand(Op);
157 if (MO.isImm())
158 return MO.getImm();
159
160 assert(MO.isExpr() && "Expr operand expected");
161 Fixups.push_back(MCFixup::create(0, MO.getExpr(),
162 static_cast<MCFixupKind>(MSP430::fixup_10_pcrel), MI.getLoc()));
163 return 0;
164 }
165
getCGImmOpValue(const MCInst & MI,unsigned Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const166 unsigned MSP430MCCodeEmitter::getCGImmOpValue(const MCInst &MI, unsigned Op,
167 SmallVectorImpl<MCFixup> &Fixups,
168 const MCSubtargetInfo &STI) const {
169 const MCOperand &MO = MI.getOperand(Op);
170 assert(MO.isImm() && "Expr operand expected");
171
172 int64_t Imm = MO.getImm();
173 switch (Imm) {
174 default:
175 llvm_unreachable("Invalid immediate value");
176 case 4: return 0x22;
177 case 8: return 0x32;
178 case 0: return 0x03;
179 case 1: return 0x13;
180 case 2: return 0x23;
181 case -1: return 0x33;
182 }
183 }
184
getCCOpValue(const MCInst & MI,unsigned Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const185 unsigned MSP430MCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned Op,
186 SmallVectorImpl<MCFixup> &Fixups,
187 const MCSubtargetInfo &STI) const {
188 const MCOperand &MO = MI.getOperand(Op);
189 assert(MO.isImm() && "Immediate operand expected");
190 switch (MO.getImm()) {
191 case MSP430CC::COND_NE: return 0;
192 case MSP430CC::COND_E: return 1;
193 case MSP430CC::COND_LO: return 2;
194 case MSP430CC::COND_HS: return 3;
195 case MSP430CC::COND_N: return 4;
196 case MSP430CC::COND_GE: return 5;
197 case MSP430CC::COND_L: return 6;
198 default:
199 llvm_unreachable("Unknown condition code");
200 }
201 }
202
createMSP430MCCodeEmitter(const MCInstrInfo & MCII,const MCRegisterInfo & MRI,MCContext & Ctx)203 MCCodeEmitter *createMSP430MCCodeEmitter(const MCInstrInfo &MCII,
204 const MCRegisterInfo &MRI,
205 MCContext &Ctx) {
206 return new MSP430MCCodeEmitter(Ctx, MCII);
207 }
208
209 #include "MSP430GenMCCodeEmitter.inc"
210
211 } // end of namespace llvm
212