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