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/Endian.h"
28 #include "llvm/Support/EndianStream.h"
29 #include "llvm/Support/raw_ostream.h"
30 
31 #define DEBUG_TYPE "mccodeemitter"
32 
33 namespace llvm {
34 
35 class MSP430MCCodeEmitter : public MCCodeEmitter {
36   MCContext &Ctx;
37   MCInstrInfo const &MCII;
38 
39   // Offset keeps track of current word number being emitted
40   // inside a particular instruction.
41   mutable unsigned Offset;
42 
43   /// TableGen'erated function for getting the binary encoding for an
44   /// instruction.
45   uint64_t getBinaryCodeForInstr(const MCInst &MI,
46                                  SmallVectorImpl<MCFixup> &Fixups,
47                                  const MCSubtargetInfo &STI) const;
48 
49   /// Returns the binary encoding of operands.
50   ///
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;
56 
57   unsigned getMemOpValue(const MCInst &MI, unsigned Op,
58                          SmallVectorImpl<MCFixup> &Fixups,
59                          const MCSubtargetInfo &STI) const;
60 
61   unsigned getPCRelImmOpValue(const MCInst &MI, unsigned Op,
62                               SmallVectorImpl<MCFixup> &Fixups,
63                               const MCSubtargetInfo &STI) const;
64 
65   unsigned getCGImmOpValue(const MCInst &MI, unsigned Op,
66                            SmallVectorImpl<MCFixup> &Fixups,
67                            const MCSubtargetInfo &STI) const;
68 
69   unsigned getCCOpValue(const MCInst &MI, unsigned Op,
70                         SmallVectorImpl<MCFixup> &Fixups,
71                         const MCSubtargetInfo &STI) const;
72 
73 public:
74   MSP430MCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
75       : Ctx(ctx), MCII(MCII) {}
76 
77   void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
78                          SmallVectorImpl<MCFixup> &Fixups,
79                          const MCSubtargetInfo &STI) const override;
80 };
81 
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();
89 
90   // Initialize fixup offset
91   Offset = 2;
92 
93   uint64_t BinaryOpCode = getBinaryCodeForInstr(MI, Fixups, STI);
94   size_t WordCount = Size / 2;
95 
96   while (WordCount--) {
97     support::endian::write(CB, (uint16_t)BinaryOpCode,
98                            llvm::endianness::little);
99     BinaryOpCode >>= 16;
100   }
101 }
102 
103 unsigned MSP430MCCodeEmitter::getMachineOpValue(const MCInst &MI,
104                                                 const MCOperand &MO,
105                                                 SmallVectorImpl<MCFixup> &Fixups,
106                                                 const MCSubtargetInfo &STI) const {
107   if (MO.isReg())
108     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
109 
110   if (MO.isImm()) {
111     Offset += 2;
112     return MO.getImm();
113   }
114 
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()));
118   Offset += 2;
119   return 0;
120 }
121 
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());
128 
129   const MCOperand &MO2 = MI.getOperand(Op + 1);
130   if (MO2.isImm()) {
131     Offset += 2;
132     return ((unsigned)MO2.getImm() << 4) | Reg;
133   }
134 
135   assert(MO2.isExpr() && "Expr operand expected");
136   MSP430::Fixups FixupKind;
137   switch (Reg) {
138   case 0:
139     FixupKind = MSP430::fixup_16_pcrel_byte;
140     break;
141   case 2:
142     FixupKind = MSP430::fixup_16_byte;
143     break;
144   default:
145     FixupKind = MSP430::fixup_16_byte;
146     break;
147   }
148   Fixups.push_back(MCFixup::create(Offset, MO2.getExpr(),
149     static_cast<MCFixupKind>(FixupKind), MI.getLoc()));
150   Offset += 2;
151   return Reg;
152 }
153 
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);
158   if (MO.isImm())
159     return MO.getImm();
160 
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()));
164   return 0;
165 }
166 
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");
172 
173   int64_t Imm = MO.getImm();
174   switch (Imm) {
175   default:
176     llvm_unreachable("Invalid immediate value");
177   case 4:  return 0x22;
178   case 8:  return 0x32;
179   case 0:  return 0x03;
180   case 1:  return 0x13;
181   case 2:  return 0x23;
182   case -1: return 0x33;
183   }
184 }
185 
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;
199   default:
200     llvm_unreachable("Unknown condition code");
201   }
202 }
203 
204 MCCodeEmitter *createMSP430MCCodeEmitter(const MCInstrInfo &MCII,
205                                          MCContext &Ctx) {
206   return new MSP430MCCodeEmitter(Ctx, MCII);
207 }
208 
209 #include "MSP430GenMCCodeEmitter.inc"
210 
211 } // end of namespace llvm
212