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