xref: /netbsd-src/external/apache2/llvm/dist/llvm/lib/Target/MSP430/MCTargetDesc/MSP430MCCodeEmitter.cpp (revision 7330f729ccf0bd976a06f95fad452fe774fc7fd1)
1*7330f729Sjoerg //===-- MSP430MCCodeEmitter.cpp - Convert MSP430 code to machine code -----===//
2*7330f729Sjoerg //
3*7330f729Sjoerg // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4*7330f729Sjoerg // See https://llvm.org/LICENSE.txt for license information.
5*7330f729Sjoerg // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6*7330f729Sjoerg //
7*7330f729Sjoerg //===----------------------------------------------------------------------===//
8*7330f729Sjoerg //
9*7330f729Sjoerg // This file implements the MSP430MCCodeEmitter class.
10*7330f729Sjoerg //
11*7330f729Sjoerg //===----------------------------------------------------------------------===//
12*7330f729Sjoerg 
13*7330f729Sjoerg #include "MSP430.h"
14*7330f729Sjoerg #include "MCTargetDesc/MSP430MCTargetDesc.h"
15*7330f729Sjoerg #include "MCTargetDesc/MSP430FixupKinds.h"
16*7330f729Sjoerg 
17*7330f729Sjoerg #include "llvm/ADT/APFloat.h"
18*7330f729Sjoerg #include "llvm/ADT/SmallVector.h"
19*7330f729Sjoerg #include "llvm/MC/MCCodeEmitter.h"
20*7330f729Sjoerg #include "llvm/MC/MCContext.h"
21*7330f729Sjoerg #include "llvm/MC/MCExpr.h"
22*7330f729Sjoerg #include "llvm/MC/MCFixup.h"
23*7330f729Sjoerg #include "llvm/MC/MCInst.h"
24*7330f729Sjoerg #include "llvm/MC/MCInstrInfo.h"
25*7330f729Sjoerg #include "llvm/MC/MCRegisterInfo.h"
26*7330f729Sjoerg #include "llvm/MC/MCSubtargetInfo.h"
27*7330f729Sjoerg #include "llvm/Support/Endian.h"
28*7330f729Sjoerg #include "llvm/Support/EndianStream.h"
29*7330f729Sjoerg #include "llvm/Support/raw_ostream.h"
30*7330f729Sjoerg 
31*7330f729Sjoerg #define DEBUG_TYPE "mccodeemitter"
32*7330f729Sjoerg 
33*7330f729Sjoerg namespace llvm {
34*7330f729Sjoerg 
35*7330f729Sjoerg class MSP430MCCodeEmitter : public MCCodeEmitter {
36*7330f729Sjoerg   MCContext &Ctx;
37*7330f729Sjoerg   MCInstrInfo const &MCII;
38*7330f729Sjoerg 
39*7330f729Sjoerg   // Offset keeps track of current word number being emitted
40*7330f729Sjoerg   // inside a particular instruction.
41*7330f729Sjoerg   mutable unsigned Offset;
42*7330f729Sjoerg 
43*7330f729Sjoerg   /// TableGen'erated function for getting the binary encoding for an
44*7330f729Sjoerg   /// instruction.
45*7330f729Sjoerg   uint64_t getBinaryCodeForInstr(const MCInst &MI,
46*7330f729Sjoerg                                  SmallVectorImpl<MCFixup> &Fixups,
47*7330f729Sjoerg                                  const MCSubtargetInfo &STI) const;
48*7330f729Sjoerg 
49*7330f729Sjoerg   /// Returns the binary encoding of operands.
50*7330f729Sjoerg   ///
51*7330f729Sjoerg   /// If an operand requires relocation, the relocation is recorded
52*7330f729Sjoerg   /// and zero is returned.
53*7330f729Sjoerg   unsigned getMachineOpValue(const MCInst &MI, const MCOperand &MO,
54*7330f729Sjoerg                              SmallVectorImpl<MCFixup> &Fixups,
55*7330f729Sjoerg                              const MCSubtargetInfo &STI) const;
56*7330f729Sjoerg 
57*7330f729Sjoerg   unsigned getMemOpValue(const MCInst &MI, unsigned Op,
58*7330f729Sjoerg                          SmallVectorImpl<MCFixup> &Fixups,
59*7330f729Sjoerg                          const MCSubtargetInfo &STI) const;
60*7330f729Sjoerg 
61*7330f729Sjoerg   unsigned getPCRelImmOpValue(const MCInst &MI, unsigned Op,
62*7330f729Sjoerg                               SmallVectorImpl<MCFixup> &Fixups,
63*7330f729Sjoerg                               const MCSubtargetInfo &STI) const;
64*7330f729Sjoerg 
65*7330f729Sjoerg   unsigned getCGImmOpValue(const MCInst &MI, unsigned Op,
66*7330f729Sjoerg                            SmallVectorImpl<MCFixup> &Fixups,
67*7330f729Sjoerg                            const MCSubtargetInfo &STI) const;
68*7330f729Sjoerg 
69*7330f729Sjoerg   unsigned getCCOpValue(const MCInst &MI, unsigned Op,
70*7330f729Sjoerg                         SmallVectorImpl<MCFixup> &Fixups,
71*7330f729Sjoerg                         const MCSubtargetInfo &STI) const;
72*7330f729Sjoerg 
73*7330f729Sjoerg public:
MSP430MCCodeEmitter(MCContext & ctx,MCInstrInfo const & MCII)74*7330f729Sjoerg   MSP430MCCodeEmitter(MCContext &ctx, MCInstrInfo const &MCII)
75*7330f729Sjoerg       : Ctx(ctx), MCII(MCII) {}
76*7330f729Sjoerg 
77*7330f729Sjoerg   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
78*7330f729Sjoerg                          SmallVectorImpl<MCFixup> &Fixups,
79*7330f729Sjoerg                          const MCSubtargetInfo &STI) const override;
80*7330f729Sjoerg };
81*7330f729Sjoerg 
encodeInstruction(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const82*7330f729Sjoerg void MSP430MCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
83*7330f729Sjoerg                                             SmallVectorImpl<MCFixup> &Fixups,
84*7330f729Sjoerg                                             const MCSubtargetInfo &STI) const {
85*7330f729Sjoerg   const MCInstrDesc &Desc = MCII.get(MI.getOpcode());
86*7330f729Sjoerg   // Get byte count of instruction.
87*7330f729Sjoerg   unsigned Size = Desc.getSize();
88*7330f729Sjoerg 
89*7330f729Sjoerg   // Initialize fixup offset
90*7330f729Sjoerg   Offset = 2;
91*7330f729Sjoerg 
92*7330f729Sjoerg   uint64_t BinaryOpCode = getBinaryCodeForInstr(MI, Fixups, STI);
93*7330f729Sjoerg   size_t WordCount = Size / 2;
94*7330f729Sjoerg 
95*7330f729Sjoerg   while (WordCount--) {
96*7330f729Sjoerg     support::endian::write(OS, (uint16_t)BinaryOpCode, support::little);
97*7330f729Sjoerg     BinaryOpCode >>= 16;
98*7330f729Sjoerg   }
99*7330f729Sjoerg }
100*7330f729Sjoerg 
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const101*7330f729Sjoerg unsigned MSP430MCCodeEmitter::getMachineOpValue(const MCInst &MI,
102*7330f729Sjoerg                                                 const MCOperand &MO,
103*7330f729Sjoerg                                                 SmallVectorImpl<MCFixup> &Fixups,
104*7330f729Sjoerg                                                 const MCSubtargetInfo &STI) const {
105*7330f729Sjoerg   if (MO.isReg())
106*7330f729Sjoerg     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
107*7330f729Sjoerg 
108*7330f729Sjoerg   if (MO.isImm()) {
109*7330f729Sjoerg     Offset += 2;
110*7330f729Sjoerg     return MO.getImm();
111*7330f729Sjoerg   }
112*7330f729Sjoerg 
113*7330f729Sjoerg   assert(MO.isExpr() && "Expected expr operand");
114*7330f729Sjoerg   Fixups.push_back(MCFixup::create(Offset, MO.getExpr(),
115*7330f729Sjoerg       static_cast<MCFixupKind>(MSP430::fixup_16_byte), MI.getLoc()));
116*7330f729Sjoerg   Offset += 2;
117*7330f729Sjoerg   return 0;
118*7330f729Sjoerg }
119*7330f729Sjoerg 
getMemOpValue(const MCInst & MI,unsigned Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const120*7330f729Sjoerg unsigned MSP430MCCodeEmitter::getMemOpValue(const MCInst &MI, unsigned Op,
121*7330f729Sjoerg                                             SmallVectorImpl<MCFixup> &Fixups,
122*7330f729Sjoerg                                             const MCSubtargetInfo &STI) const {
123*7330f729Sjoerg   const MCOperand &MO1 = MI.getOperand(Op);
124*7330f729Sjoerg   assert(MO1.isReg() && "Register operand expected");
125*7330f729Sjoerg   unsigned Reg = Ctx.getRegisterInfo()->getEncodingValue(MO1.getReg());
126*7330f729Sjoerg 
127*7330f729Sjoerg   const MCOperand &MO2 = MI.getOperand(Op + 1);
128*7330f729Sjoerg   if (MO2.isImm()) {
129*7330f729Sjoerg     Offset += 2;
130*7330f729Sjoerg     return ((unsigned)MO2.getImm() << 4) | Reg;
131*7330f729Sjoerg   }
132*7330f729Sjoerg 
133*7330f729Sjoerg   assert(MO2.isExpr() && "Expr operand expected");
134*7330f729Sjoerg   MSP430::Fixups FixupKind;
135*7330f729Sjoerg   switch (Reg) {
136*7330f729Sjoerg   case 0:
137*7330f729Sjoerg     FixupKind = MSP430::fixup_16_pcrel_byte;
138*7330f729Sjoerg     break;
139*7330f729Sjoerg   case 2:
140*7330f729Sjoerg     FixupKind = MSP430::fixup_16_byte;
141*7330f729Sjoerg     break;
142*7330f729Sjoerg   default:
143*7330f729Sjoerg     FixupKind = MSP430::fixup_16_byte;
144*7330f729Sjoerg     break;
145*7330f729Sjoerg   }
146*7330f729Sjoerg   Fixups.push_back(MCFixup::create(Offset, MO2.getExpr(),
147*7330f729Sjoerg     static_cast<MCFixupKind>(FixupKind), MI.getLoc()));
148*7330f729Sjoerg   Offset += 2;
149*7330f729Sjoerg   return Reg;
150*7330f729Sjoerg }
151*7330f729Sjoerg 
getPCRelImmOpValue(const MCInst & MI,unsigned Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const152*7330f729Sjoerg unsigned MSP430MCCodeEmitter::getPCRelImmOpValue(const MCInst &MI, unsigned Op,
153*7330f729Sjoerg                                                  SmallVectorImpl<MCFixup> &Fixups,
154*7330f729Sjoerg                                                  const MCSubtargetInfo &STI) const {
155*7330f729Sjoerg   const MCOperand &MO = MI.getOperand(Op);
156*7330f729Sjoerg   if (MO.isImm())
157*7330f729Sjoerg     return MO.getImm();
158*7330f729Sjoerg 
159*7330f729Sjoerg   assert(MO.isExpr() && "Expr operand expected");
160*7330f729Sjoerg   Fixups.push_back(MCFixup::create(0, MO.getExpr(),
161*7330f729Sjoerg     static_cast<MCFixupKind>(MSP430::fixup_10_pcrel), MI.getLoc()));
162*7330f729Sjoerg   return 0;
163*7330f729Sjoerg }
164*7330f729Sjoerg 
getCGImmOpValue(const MCInst & MI,unsigned Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const165*7330f729Sjoerg unsigned MSP430MCCodeEmitter::getCGImmOpValue(const MCInst &MI, unsigned Op,
166*7330f729Sjoerg                                               SmallVectorImpl<MCFixup> &Fixups,
167*7330f729Sjoerg                                               const MCSubtargetInfo &STI) const {
168*7330f729Sjoerg   const MCOperand &MO = MI.getOperand(Op);
169*7330f729Sjoerg   assert(MO.isImm() && "Expr operand expected");
170*7330f729Sjoerg 
171*7330f729Sjoerg   int64_t Imm = MO.getImm();
172*7330f729Sjoerg   switch (Imm) {
173*7330f729Sjoerg   default:
174*7330f729Sjoerg     llvm_unreachable("Invalid immediate value");
175*7330f729Sjoerg   case 4:  return 0x22;
176*7330f729Sjoerg   case 8:  return 0x32;
177*7330f729Sjoerg   case 0:  return 0x03;
178*7330f729Sjoerg   case 1:  return 0x13;
179*7330f729Sjoerg   case 2:  return 0x23;
180*7330f729Sjoerg   case -1: return 0x33;
181*7330f729Sjoerg   }
182*7330f729Sjoerg }
183*7330f729Sjoerg 
getCCOpValue(const MCInst & MI,unsigned Op,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const184*7330f729Sjoerg unsigned MSP430MCCodeEmitter::getCCOpValue(const MCInst &MI, unsigned Op,
185*7330f729Sjoerg                                            SmallVectorImpl<MCFixup> &Fixups,
186*7330f729Sjoerg                                            const MCSubtargetInfo &STI) const {
187*7330f729Sjoerg   const MCOperand &MO = MI.getOperand(Op);
188*7330f729Sjoerg   assert(MO.isImm() && "Immediate operand expected");
189*7330f729Sjoerg   switch (MO.getImm()) {
190*7330f729Sjoerg   case MSP430CC::COND_NE: return 0;
191*7330f729Sjoerg   case MSP430CC::COND_E:  return 1;
192*7330f729Sjoerg   case MSP430CC::COND_LO: return 2;
193*7330f729Sjoerg   case MSP430CC::COND_HS: return 3;
194*7330f729Sjoerg   case MSP430CC::COND_N:  return 4;
195*7330f729Sjoerg   case MSP430CC::COND_GE: return 5;
196*7330f729Sjoerg   case MSP430CC::COND_L:  return 6;
197*7330f729Sjoerg   default:
198*7330f729Sjoerg     llvm_unreachable("Unknown condition code");
199*7330f729Sjoerg   }
200*7330f729Sjoerg }
201*7330f729Sjoerg 
createMSP430MCCodeEmitter(const MCInstrInfo & MCII,const MCRegisterInfo & MRI,MCContext & Ctx)202*7330f729Sjoerg MCCodeEmitter *createMSP430MCCodeEmitter(const MCInstrInfo &MCII,
203*7330f729Sjoerg                                          const MCRegisterInfo &MRI,
204*7330f729Sjoerg                                          MCContext &Ctx) {
205*7330f729Sjoerg   return new MSP430MCCodeEmitter(Ctx, MCII);
206*7330f729Sjoerg }
207*7330f729Sjoerg 
208*7330f729Sjoerg #include "MSP430GenMCCodeEmitter.inc"
209*7330f729Sjoerg 
210*7330f729Sjoerg } // end of namespace llvm
211