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
, SmallVectorImpl
<char> &CB
,
78 SmallVectorImpl
<MCFixup
> &Fixups
,
79 const MCSubtargetInfo
&STI
) const override
;
82 void MSP430MCCodeEmitter::encodeInstruction(const MCInst
&MI
,
83 SmallVectorImpl
<char> &CB
,
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();
90 // Initialize fixup offset
93 uint64_t BinaryOpCode
= getBinaryCodeForInstr(MI
, Fixups
, STI
);
94 size_t WordCount
= Size
/ 2;
97 support::endian::write(CB
, (uint16_t)BinaryOpCode
,
98 llvm::endianness::little
);
103 unsigned MSP430MCCodeEmitter::getMachineOpValue(const MCInst
&MI
,
105 SmallVectorImpl
<MCFixup
> &Fixups
,
106 const MCSubtargetInfo
&STI
) const {
108 return Ctx
.getRegisterInfo()->getEncodingValue(MO
.getReg());
115 assert(MO
.isExpr() && "Expected expr operand");
116 Fixups
.push_back(MCFixup::create(Offset
, MO
.getExpr(),
117 static_cast<MCFixupKind
>(MSP430::fixup_16_byte
), MI
.getLoc()));
122 unsigned MSP430MCCodeEmitter::getMemOpValue(const MCInst
&MI
, unsigned Op
,
123 SmallVectorImpl
<MCFixup
> &Fixups
,
124 const MCSubtargetInfo
&STI
) const {
125 const MCOperand
&MO1
= MI
.getOperand(Op
);
126 assert(MO1
.isReg() && "Register operand expected");
127 unsigned Reg
= Ctx
.getRegisterInfo()->getEncodingValue(MO1
.getReg());
129 const MCOperand
&MO2
= MI
.getOperand(Op
+ 1);
132 return ((unsigned)MO2
.getImm() << 4) | Reg
;
135 assert(MO2
.isExpr() && "Expr operand expected");
136 MSP430::Fixups FixupKind
;
139 FixupKind
= MSP430::fixup_16_pcrel_byte
;
142 FixupKind
= MSP430::fixup_16_byte
;
145 FixupKind
= MSP430::fixup_16_byte
;
148 Fixups
.push_back(MCFixup::create(Offset
, MO2
.getExpr(),
149 static_cast<MCFixupKind
>(FixupKind
), MI
.getLoc()));
154 unsigned MSP430MCCodeEmitter::getPCRelImmOpValue(const MCInst
&MI
, unsigned Op
,
155 SmallVectorImpl
<MCFixup
> &Fixups
,
156 const MCSubtargetInfo
&STI
) const {
157 const MCOperand
&MO
= MI
.getOperand(Op
);
161 assert(MO
.isExpr() && "Expr operand expected");
162 Fixups
.push_back(MCFixup::create(0, MO
.getExpr(),
163 static_cast<MCFixupKind
>(MSP430::fixup_10_pcrel
), MI
.getLoc()));
167 unsigned MSP430MCCodeEmitter::getCGImmOpValue(const MCInst
&MI
, unsigned Op
,
168 SmallVectorImpl
<MCFixup
> &Fixups
,
169 const MCSubtargetInfo
&STI
) const {
170 const MCOperand
&MO
= MI
.getOperand(Op
);
171 assert(MO
.isImm() && "Expr operand expected");
173 int64_t Imm
= MO
.getImm();
176 llvm_unreachable("Invalid immediate value");
182 case -1: return 0x33;
186 unsigned MSP430MCCodeEmitter::getCCOpValue(const MCInst
&MI
, unsigned Op
,
187 SmallVectorImpl
<MCFixup
> &Fixups
,
188 const MCSubtargetInfo
&STI
) const {
189 const MCOperand
&MO
= MI
.getOperand(Op
);
190 assert(MO
.isImm() && "Immediate operand expected");
191 switch (MO
.getImm()) {
192 case MSP430CC::COND_NE
: return 0;
193 case MSP430CC::COND_E
: return 1;
194 case MSP430CC::COND_LO
: return 2;
195 case MSP430CC::COND_HS
: return 3;
196 case MSP430CC::COND_N
: return 4;
197 case MSP430CC::COND_GE
: return 5;
198 case MSP430CC::COND_L
: return 6;
200 llvm_unreachable("Unknown condition code");
204 MCCodeEmitter
*createMSP430MCCodeEmitter(const MCInstrInfo
&MCII
,
206 return new MSP430MCCodeEmitter(Ctx
, MCII
);
209 #include "MSP430GenMCCodeEmitter.inc"
211 } // end of namespace llvm