1 //===-- MSP430MCCodeEmitter.cpp - Convert MSP430 code to machine code -----===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 // This file implements the MSP430MCCodeEmitter class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "MSP430.h"
15 #include "MCTargetDesc/MSP430MCTargetDesc.h"
16 #include "MCTargetDesc/MSP430FixupKinds.h"
17 
18 #include "llvm/ADT/APFloat.h"
19 #include "llvm/ADT/SmallVector.h"
20 #include "llvm/MC/MCCodeEmitter.h"
21 #include "llvm/MC/MCContext.h"
22 #include "llvm/MC/MCExpr.h"
23 #include "llvm/MC/MCFixup.h"
24 #include "llvm/MC/MCInst.h"
25 #include "llvm/MC/MCInstrInfo.h"
26 #include "llvm/MC/MCRegisterInfo.h"
27 #include "llvm/MC/MCSubtargetInfo.h"
28 #include "llvm/Support/Endian.h"
29 #include "llvm/Support/EndianStream.h"
30 #include "llvm/Support/raw_ostream.h"
31 
32 #define DEBUG_TYPE "mccodeemitter"
33 
34 namespace llvm {
35 
36 class MSP430MCCodeEmitter : public MCCodeEmitter {
37   MCContext &Ctx;
38   MCInstrInfo const &MCII;
39 
40   // Offset keeps track of current word number being emitted
41   // inside a particular instruction.
42   mutable unsigned Offset;
43 
44   /// TableGen'erated function for getting the binary encoding for an
45   /// instruction.
46   uint64_t getBinaryCodeForInstr(const MCInst &MI,
47                                  SmallVectorImpl<MCFixup> &Fixups,
48                                  const MCSubtargetInfo &STI) const;
49 
50   /// Returns the binary encoding of operands.
51   ///
52   /// If an operand requires relocation, the relocation is recorded
53   /// and zero is returned.
54   unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
55                              SmallVectorImpl<MCFixup> &Fixups,
56                              const MCSubtargetInfo &STI) const;
57 
58   unsigned getMemOpValue(const MCInst &MI, unsigned Op,
59                          SmallVectorImpl<MCFixup> &Fixups,
60                          const MCSubtargetInfo &STI) const;
61 
62   unsigned getPCRelImmOpValue(const MCInst &MI, unsigned Op,
63                               SmallVectorImpl<MCFixup> &Fixups,
64                               const MCSubtargetInfo &STI) const;
65 
66   unsigned getCGImmOpValue(const MCInst &MI, unsigned Op,
67                            SmallVectorImpl<MCFixup> &Fixups,
68                            const MCSubtargetInfo &STI) const;
69 
70   unsigned getCCOpValue(const MCInst &MI, unsigned Op,
71                         SmallVectorImpl<MCFixup> &Fixups,
72                         const MCSubtargetInfo &STI) const;
73 
74 public:
MSP430MCCodeEmitter(MCContext & ctx,MCInstrInfo const & MCII)75   MSP430MCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
76       : Ctx(ctx), MCII(MCII) {}
77 
78   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
79                          SmallVectorImpl<MCFixup> &Fixups,
80                          const MCSubtargetInfo &STI) const override;
81 };
82 
encodeInstruction(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const83 void MSP430MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
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(OS, (uint16_t)BinaryOpCode, support::little);
98     BinaryOpCode >>= 16;
99   }
100 }
101 
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const102 unsigned MSP430MCCodeEmitter::getMachineOpValue(const MCInst &MI,
103                                                 const MCOperand &MO,
104                                                 SmallVectorImpl<MCFixup> &Fixups,
105                                                 const MCSubtargetInfo &STI) const {
106   if (MO.isReg())
107     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
108 
109   if (MO.isImm()) {
110     Offset += 2;
111     return MO.getImm();
112   }
113 
114   assert(MO.isExpr() && "Expected expr operand");
115   Fixups.push_back(MCFixup::create(Offset, MO.getExpr(),
116       static_cast<MCFixupKind>(MSP430::fixup_16_byte), MI.getLoc()));
117   Offset += 2;
118   return 0;
119 }
120 
getMemOpValue(const MCInst & MI,unsigned Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const121 unsigned MSP430MCCodeEmitter::getMemOpValue(const MCInst &MI, unsigned Op,
122                                             SmallVectorImpl<MCFixup> &Fixups,
123                                             const MCSubtargetInfo &STI) const {
124   const MCOperand &MO1 = MI.getOperand(Op);
125   assert(MO1.isReg() && "Register operand expected");
126   unsigned Reg = Ctx.getRegisterInfo()->getEncodingValue(MO1.getReg());
127 
128   const MCOperand &MO2 = MI.getOperand(Op + 1);
129   if (MO2.isImm()) {
130     Offset += 2;
131     return ((unsigned)MO2.getImm() << 4) | Reg;
132   }
133 
134   assert(MO2.isExpr() && "Expr operand expected");
135   MSP430::Fixups FixupKind;
136   switch (Reg) {
137   case 0:
138     FixupKind = MSP430::fixup_16_pcrel_byte;
139     break;
140   case 2:
141     FixupKind = MSP430::fixup_16_byte;
142     break;
143   default:
144     FixupKind = MSP430::fixup_16_byte;
145     break;
146   }
147   Fixups.push_back(MCFixup::create(Offset, MO2.getExpr(),
148     static_cast<MCFixupKind>(FixupKind), MI.getLoc()));
149   Offset += 2;
150   return Reg;
151 }
152 
getPCRelImmOpValue(const MCInst & MI,unsigned Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const153 unsigned MSP430MCCodeEmitter::getPCRelImmOpValue(const MCInst &MI, unsigned Op,
154                                                  SmallVectorImpl<MCFixup> &Fixups,
155                                                  const MCSubtargetInfo &STI) const {
156   const MCOperand &MO = MI.getOperand(Op);
157   if (MO.isImm())
158     return MO.getImm();
159 
160   assert(MO.isExpr() && "Expr operand expected");
161   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
162     static_cast<MCFixupKind>(MSP430::fixup_10_pcrel), MI.getLoc()));
163   return 0;
164 }
165 
getCGImmOpValue(const MCInst & MI,unsigned Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const166 unsigned MSP430MCCodeEmitter::getCGImmOpValue(const MCInst &MI, unsigned Op,
167                                               SmallVectorImpl<MCFixup> &Fixups,
168                                               const MCSubtargetInfo &STI) const {
169   const MCOperand &MO = MI.getOperand(Op);
170   assert(MO.isImm() && "Expr operand expected");
171 
172   int64_t Imm = MO.getImm();
173   switch (Imm) {
174   default:
175     llvm_unreachable("Invalid immediate value");
176   case 4:  return 0x22;
177   case 8:  return 0x32;
178   case 0:  return 0x03;
179   case 1:  return 0x13;
180   case 2:  return 0x23;
181   case -1: return 0x33;
182   }
183 }
184 
getCCOpValue(const MCInst & MI,unsigned Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const185 unsigned MSP430MCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned Op,
186                                            SmallVectorImpl<MCFixup> &Fixups,
187                                            const MCSubtargetInfo &STI) const {
188   const MCOperand &MO = MI.getOperand(Op);
189   assert(MO.isImm() && "Immediate operand expected");
190   switch (MO.getImm()) {
191   case MSP430CC::COND_NE: return 0;
192   case MSP430CC::COND_E:  return 1;
193   case MSP430CC::COND_LO: return 2;
194   case MSP430CC::COND_HS: return 3;
195   case MSP430CC::COND_N:  return 4;
196   case MSP430CC::COND_GE: return 5;
197   case MSP430CC::COND_L:  return 6;
198   default:
199     llvm_unreachable("Unknown condition code");
200   }
201 }
202 
createMSP430MCCodeEmitter(const MCInstrInfo & MCII,const MCRegisterInfo & MRI,MCContext & Ctx)203 MCCodeEmitter *createMSP430MCCodeEmitter(const MCInstrInfo &MCII,
204                                          const MCRegisterInfo &MRI,
205                                          MCContext &Ctx) {
206   return new MSP430MCCodeEmitter(Ctx, MCII);
207 }
208 
209 #include "MSP430GenMCCodeEmitter.inc"
210 
211 } // end of namespace llvm
212