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
31namespace llvm {
32
33class 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
71public:
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
80void MSP430MCCodeEmitter::encodeInstruction(const MCInst &MI,
81 SmallVectorImpl<char> &CB,
82 SmallVectorImpl<MCFixup> &Fixups,
83 const MCSubtargetInfo &STI) const {
84 const MCInstrDesc &Desc = MCII.get(Opcode: MI.getOpcode());
85 // Get byte count of instruction.
86 unsigned Size = Desc.getSize();
87
88 // Initialize fixup offset
89 Offset = 2;
90
91 uint64_t BinaryOpCode = getBinaryCodeForInstr(MI, Fixups, STI);
92 size_t WordCount = Size / 2;
93
94 while (WordCount--) {
95 support::endian::write(Out&: CB, V: (uint16_t)BinaryOpCode,
96 E: llvm::endianness::little);
97 BinaryOpCode >>= 16;
98 }
99}
100
101unsigned MSP430MCCodeEmitter::getMachineOpValue(const MCInst &MI,
102 const MCOperand &MO,
103 SmallVectorImpl<MCFixup> &Fixups,
104 const MCSubtargetInfo &STI) const {
105 if (MO.isReg())
106 return Ctx.getRegisterInfo()->getEncodingValue(Reg: MO.getReg());
107
108 if (MO.isImm()) {
109 Offset += 2;
110 return MO.getImm();
111 }
112
113 assert(MO.isExpr() && "Expected expr operand");
114 Fixups.push_back(Elt: MCFixup::create(Offset, Value: MO.getExpr(),
115 Kind: static_cast<MCFixupKind>(MSP430::fixup_16_byte), Loc: MI.getLoc()));
116 Offset += 2;
117 return 0;
118}
119
120unsigned MSP430MCCodeEmitter::getMemOpValue(const MCInst &MI, unsigned Op,
121 SmallVectorImpl<MCFixup> &Fixups,
122 const MCSubtargetInfo &STI) const {
123 const MCOperand &MO1 = MI.getOperand(i: Op);
124 assert(MO1.isReg() && "Register operand expected");
125 unsigned Reg = Ctx.getRegisterInfo()->getEncodingValue(Reg: MO1.getReg());
126
127 const MCOperand &MO2 = MI.getOperand(i: Op + 1);
128 if (MO2.isImm()) {
129 Offset += 2;
130 return ((unsigned)MO2.getImm() << 4) | Reg;
131 }
132
133 assert(MO2.isExpr() && "Expr operand expected");
134 MSP430::Fixups FixupKind;
135 switch (Reg) {
136 case 0:
137 FixupKind = MSP430::fixup_16_pcrel_byte;
138 break;
139 case 2:
140 FixupKind = MSP430::fixup_16_byte;
141 break;
142 default:
143 FixupKind = MSP430::fixup_16_byte;
144 break;
145 }
146 Fixups.push_back(Elt: MCFixup::create(Offset, Value: MO2.getExpr(),
147 Kind: static_cast<MCFixupKind>(FixupKind), Loc: MI.getLoc()));
148 Offset += 2;
149 return Reg;
150}
151
152unsigned MSP430MCCodeEmitter::getPCRelImmOpValue(const MCInst &MI, unsigned Op,
153 SmallVectorImpl<MCFixup> &Fixups,
154 const MCSubtargetInfo &STI) const {
155 const MCOperand &MO = MI.getOperand(i: Op);
156 if (MO.isImm())
157 return MO.getImm();
158
159 assert(MO.isExpr() && "Expr operand expected");
160 Fixups.push_back(Elt: MCFixup::create(Offset: 0, Value: MO.getExpr(),
161 Kind: static_cast<MCFixupKind>(MSP430::fixup_10_pcrel), Loc: MI.getLoc()));
162 return 0;
163}
164
165unsigned MSP430MCCodeEmitter::getCGImmOpValue(const MCInst &MI, unsigned Op,
166 SmallVectorImpl<MCFixup> &Fixups,
167 const MCSubtargetInfo &STI) const {
168 const MCOperand &MO = MI.getOperand(i: Op);
169 assert(MO.isImm() && "Expr operand expected");
170
171 int64_t Imm = MO.getImm();
172 switch (Imm) {
173 default:
174 llvm_unreachable("Invalid immediate value");
175 case 4: return 0x22;
176 case 8: return 0x32;
177 case 0: return 0x03;
178 case 1: return 0x13;
179 case 2: return 0x23;
180 case -1: return 0x33;
181 }
182}
183
184unsigned MSP430MCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned Op,
185 SmallVectorImpl<MCFixup> &Fixups,
186 const MCSubtargetInfo &STI) const {
187 const MCOperand &MO = MI.getOperand(i: Op);
188 assert(MO.isImm() && "Immediate operand expected");
189 switch (MO.getImm()) {
190 case MSP430CC::COND_NE: return 0;
191 case MSP430CC::COND_E: return 1;
192 case MSP430CC::COND_LO: return 2;
193 case MSP430CC::COND_HS: return 3;
194 case MSP430CC::COND_N: return 4;
195 case MSP430CC::COND_GE: return 5;
196 case MSP430CC::COND_L: return 6;
197 default:
198 llvm_unreachable("Unknown condition code");
199 }
200}
201
202MCCodeEmitter *createMSP430MCCodeEmitter(const MCInstrInfo &MCII,
203 MCContext &Ctx) {
204 return new MSP430MCCodeEmitter(Ctx, MCII);
205}
206
207#include "MSP430GenMCCodeEmitter.inc"
208
209} // end of namespace llvm
210