1 //===-- MSP430MCCodeEmitter.cpp - Convert MSP430 code to machine code -----===//
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
7 //===----------------------------------------------------------------------===//
9 // This file implements the MSP430MCCodeEmitter class.
11 //===----------------------------------------------------------------------===//
14 #include "MCTargetDesc/MSP430MCTargetDesc.h"
15 #include "MCTargetDesc/MSP430FixupKinds.h"
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/Endian.h"
28 #include "llvm/Support/EndianStream.h"
29 #include "llvm/Support/raw_ostream.h"
31 #define DEBUG_TYPE "mccodeemitter"
35 class MSP430MCCodeEmitter : public MCCodeEmitter {
37 MCInstrInfo const &MCII;
39 // Offset keeps track of current word number being emitted
40 // inside a particular instruction.
41 mutable unsigned Offset;
43 /// TableGen'erated function for getting the binary encoding for an
45 uint64_t getBinaryCodeForInstr(const MCInst &MI,
46 SmallVectorImpl<MCFixup> &Fixups,
47 const MCSubtargetInfo &STI) const;
49 /// Returns the binary encoding of operands.
51 /// If an operand requires relocation, the relocation is recorded
52 /// and zero is returned.
53 unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
54 SmallVectorImpl<MCFixup> &Fixups,
55 const MCSubtargetInfo &STI) const;
57 unsigned getMemOpValue(const MCInst &MI, unsigned Op,
58 SmallVectorImpl<MCFixup> &Fixups,
59 const MCSubtargetInfo &STI) const;
61 unsigned getPCRelImmOpValue(const MCInst &MI, unsigned Op,
62 SmallVectorImpl<MCFixup> &Fixups,
63 const MCSubtargetInfo &STI) const;
65 unsigned getCGImmOpValue(const MCInst &MI, unsigned Op,
66 SmallVectorImpl<MCFixup> &Fixups,
67 const MCSubtargetInfo &STI) const;
69 unsigned getCCOpValue(const MCInst &MI, unsigned Op,
70 SmallVectorImpl<MCFixup> &Fixups,
71 const MCSubtargetInfo &STI) const;
74 MSP430MCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
75 : Ctx(ctx), MCII(MCII) {}
77 void encodeInstruction(const MCInst &MI, raw_ostream &OS,
78 SmallVectorImpl<MCFixup> &Fixups,
79 const MCSubtargetInfo &STI) const override;
82 void MSP430MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
83 SmallVectorImpl<MCFixup> &Fixups,
84 const MCSubtargetInfo &STI) const {
85 const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
86 // Get byte count of instruction.
87 unsigned Size = Desc.getSize();
89 // Initialize fixup offset
92 uint64_t BinaryOpCode = getBinaryCodeForInstr(MI, Fixups, STI);
93 size_t WordCount = Size / 2;
96 support::endian::write(OS, (uint16_t)BinaryOpCode, support::little);
101 unsigned MSP430MCCodeEmitter::getMachineOpValue(const MCInst &MI,
103 SmallVectorImpl<MCFixup> &Fixups,
104 const MCSubtargetInfo &STI) const {
106 return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
113 assert(MO.isExpr() && "Expected expr operand");
114 Fixups.push_back(MCFixup::create(Offset, MO.getExpr(),
115 static_cast<MCFixupKind>(MSP430::fixup_16_byte), MI.getLoc()));
120 unsigned MSP430MCCodeEmitter::getMemOpValue(const MCInst &MI, unsigned Op,
121 SmallVectorImpl<MCFixup> &Fixups,
122 const MCSubtargetInfo &STI) const {
123 const MCOperand &MO1 = MI.getOperand(Op);
124 assert(MO1.isReg() && "Register operand expected");
125 unsigned Reg = Ctx.getRegisterInfo()->getEncodingValue(MO1.getReg());
127 const MCOperand &MO2 = MI.getOperand(Op + 1);
130 return ((unsigned)MO2.getImm() << 4) | Reg;
133 assert(MO2.isExpr() && "Expr operand expected");
134 MSP430::Fixups FixupKind;
137 FixupKind = MSP430::fixup_16_pcrel_byte;
140 FixupKind = MSP430::fixup_16_byte;
143 FixupKind = MSP430::fixup_16_byte;
146 Fixups.push_back(MCFixup::create(Offset, MO2.getExpr(),
147 static_cast<MCFixupKind>(FixupKind), MI.getLoc()));
152 unsigned MSP430MCCodeEmitter::getPCRelImmOpValue(const MCInst &MI, unsigned Op,
153 SmallVectorImpl<MCFixup> &Fixups,
154 const MCSubtargetInfo &STI) const {
155 const MCOperand &MO = MI.getOperand(Op);
159 assert(MO.isExpr() && "Expr operand expected");
160 Fixups.push_back(MCFixup::create(0, MO.getExpr(),
161 static_cast<MCFixupKind>(MSP430::fixup_10_pcrel), MI.getLoc()));
165 unsigned MSP430MCCodeEmitter::getCGImmOpValue(const MCInst &MI, unsigned Op,
166 SmallVectorImpl<MCFixup> &Fixups,
167 const MCSubtargetInfo &STI) const {
168 const MCOperand &MO = MI.getOperand(Op);
169 assert(MO.isImm() && "Expr operand expected");
171 int64_t Imm = MO.getImm();
174 llvm_unreachable("Invalid immediate value");
180 case -1: return 0x33;
184 unsigned MSP430MCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned Op,
185 SmallVectorImpl<MCFixup> &Fixups,
186 const MCSubtargetInfo &STI) const {
187 const MCOperand &MO = MI.getOperand(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;
198 llvm_unreachable("Unknown condition code");
202 MCCodeEmitter *createMSP430MCCodeEmitter(const MCInstrInfo &MCII,
203 const MCRegisterInfo &MRI,
205 return new MSP430MCCodeEmitter(Ctx, MCII);
208 #include "MSP430GenMCCodeEmitter.inc"
210 } // end of namespace llvm