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