1284c1978SDimitry Andric //===-- SystemZMCCodeEmitter.cpp - Convert SystemZ code to machine code ---===//
2284c1978SDimitry Andric //
3284c1978SDimitry Andric //                     The LLVM Compiler Infrastructure
4284c1978SDimitry Andric //
5284c1978SDimitry Andric // This file is distributed under the University of Illinois Open Source
6284c1978SDimitry Andric // License. See LICENSE.TXT for details.
7284c1978SDimitry Andric //
8284c1978SDimitry Andric //===----------------------------------------------------------------------===//
9284c1978SDimitry Andric //
10284c1978SDimitry Andric // This file implements the SystemZMCCodeEmitter class.
11284c1978SDimitry Andric //
12284c1978SDimitry Andric //===----------------------------------------------------------------------===//
13284c1978SDimitry Andric 
14284c1978SDimitry Andric #include "MCTargetDesc/SystemZMCFixups.h"
157a7e6055SDimitry Andric #include "MCTargetDesc/SystemZMCTargetDesc.h"
167a7e6055SDimitry Andric #include "llvm/ADT/SmallVector.h"
17284c1978SDimitry Andric #include "llvm/MC/MCCodeEmitter.h"
18284c1978SDimitry Andric #include "llvm/MC/MCContext.h"
19284c1978SDimitry Andric #include "llvm/MC/MCExpr.h"
207a7e6055SDimitry Andric #include "llvm/MC/MCFixup.h"
21ff0cc061SDimitry Andric #include "llvm/MC/MCInst.h"
22284c1978SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
23ff0cc061SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
247a7e6055SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
257a7e6055SDimitry Andric #include "llvm/Support/ErrorHandling.h"
267a7e6055SDimitry Andric #include "llvm/Support/raw_ostream.h"
277a7e6055SDimitry Andric #include <cassert>
287a7e6055SDimitry Andric #include <cstdint>
29284c1978SDimitry Andric 
30284c1978SDimitry Andric using namespace llvm;
31284c1978SDimitry Andric 
3291bc56edSDimitry Andric #define DEBUG_TYPE "mccodeemitter"
3391bc56edSDimitry Andric 
34284c1978SDimitry Andric namespace {
357a7e6055SDimitry Andric 
36284c1978SDimitry Andric class SystemZMCCodeEmitter : public MCCodeEmitter {
37284c1978SDimitry Andric   const MCInstrInfo &MCII;
38284c1978SDimitry Andric   MCContext &Ctx;
39284c1978SDimitry Andric 
40284c1978SDimitry Andric public:
SystemZMCCodeEmitter(const MCInstrInfo & mcii,MCContext & ctx)41284c1978SDimitry Andric   SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
42284c1978SDimitry Andric     : MCII(mcii), Ctx(ctx) {
43284c1978SDimitry Andric   }
44284c1978SDimitry Andric 
457a7e6055SDimitry Andric   ~SystemZMCCodeEmitter() override = default;
46284c1978SDimitry Andric 
47284c1978SDimitry Andric   // OVerride MCCodeEmitter.
48ff0cc061SDimitry Andric   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
4991bc56edSDimitry Andric                          SmallVectorImpl<MCFixup> &Fixups,
5091bc56edSDimitry Andric                          const MCSubtargetInfo &STI) const override;
51284c1978SDimitry Andric 
52284c1978SDimitry Andric private:
53284c1978SDimitry Andric   // Automatically generated by TableGen.
54284c1978SDimitry Andric   uint64_t getBinaryCodeForInstr(const MCInst &MI,
5591bc56edSDimitry Andric                                  SmallVectorImpl<MCFixup> &Fixups,
5691bc56edSDimitry Andric                                  const MCSubtargetInfo &STI) const;
57284c1978SDimitry Andric 
58284c1978SDimitry Andric   // Called by the TableGen code to get the binary encoding of operand
59284c1978SDimitry Andric   // MO in MI.  Fixups is the list of fixups against MI.
60f785676fSDimitry Andric   uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
6191bc56edSDimitry Andric                              SmallVectorImpl<MCFixup> &Fixups,
6291bc56edSDimitry Andric                              const MCSubtargetInfo &STI) const;
63f785676fSDimitry Andric 
64f785676fSDimitry Andric   // Called by the TableGen code to get the binary encoding of an address.
65f785676fSDimitry Andric   // The index or length, if any, is encoded first, followed by the base,
66f785676fSDimitry Andric   // followed by the displacement.  In a 20-bit displacement,
67f785676fSDimitry Andric   // the low 12 bits are encoded before the high 8 bits.
68f785676fSDimitry Andric   uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
6991bc56edSDimitry Andric                                SmallVectorImpl<MCFixup> &Fixups,
7091bc56edSDimitry Andric                                const MCSubtargetInfo &STI) const;
71f785676fSDimitry Andric   uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
7291bc56edSDimitry Andric                                SmallVectorImpl<MCFixup> &Fixups,
7391bc56edSDimitry Andric                                const MCSubtargetInfo &STI) const;
74f785676fSDimitry Andric   uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
7591bc56edSDimitry Andric                                 SmallVectorImpl<MCFixup> &Fixups,
7691bc56edSDimitry Andric                                 const MCSubtargetInfo &STI) const;
77f785676fSDimitry Andric   uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
7891bc56edSDimitry Andric                                 SmallVectorImpl<MCFixup> &Fixups,
7991bc56edSDimitry Andric                                 const MCSubtargetInfo &STI) const;
80*5517e702SDimitry Andric   uint64_t getBDLAddr12Len4Encoding(const MCInst &MI, unsigned OpNum,
81*5517e702SDimitry Andric                                     SmallVectorImpl<MCFixup> &Fixups,
82*5517e702SDimitry Andric                                     const MCSubtargetInfo &STI) const;
83f785676fSDimitry Andric   uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
8491bc56edSDimitry Andric                                     SmallVectorImpl<MCFixup> &Fixups,
8591bc56edSDimitry Andric                                     const MCSubtargetInfo &STI) const;
86d88c1a5aSDimitry Andric   uint64_t getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum,
87d88c1a5aSDimitry Andric                                 SmallVectorImpl<MCFixup> &Fixups,
88d88c1a5aSDimitry Andric                                 const MCSubtargetInfo &STI) const;
89ff0cc061SDimitry Andric   uint64_t getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
90ff0cc061SDimitry Andric                                 SmallVectorImpl<MCFixup> &Fixups,
91ff0cc061SDimitry Andric                                 const MCSubtargetInfo &STI) const;
92284c1978SDimitry Andric 
93284c1978SDimitry Andric   // Operand OpNum of MI needs a PC-relative fixup of kind Kind at
94284c1978SDimitry Andric   // Offset bytes from the start of MI.  Add the fixup to Fixups
95284c1978SDimitry Andric   // and return the in-place addend, which since we're a RELA target
96ff0cc061SDimitry Andric   // is always 0.  If AllowTLS is true and optional operand OpNum + 1
97ff0cc061SDimitry Andric   // is present, also emit a TLS call fixup for it.
98f785676fSDimitry Andric   uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
99284c1978SDimitry Andric                             SmallVectorImpl<MCFixup> &Fixups,
100ff0cc061SDimitry Andric                             unsigned Kind, int64_t Offset,
101ff0cc061SDimitry Andric                             bool AllowTLS) const;
102284c1978SDimitry Andric 
getPC16DBLEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const103f785676fSDimitry Andric   uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
10491bc56edSDimitry Andric                               SmallVectorImpl<MCFixup> &Fixups,
10591bc56edSDimitry Andric                               const MCSubtargetInfo &STI) const {
106ff0cc061SDimitry Andric     return getPCRelEncoding(MI, OpNum, Fixups,
107ff0cc061SDimitry Andric                             SystemZ::FK_390_PC16DBL, 2, false);
108284c1978SDimitry Andric   }
getPC32DBLEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const109f785676fSDimitry Andric   uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
11091bc56edSDimitry Andric                               SmallVectorImpl<MCFixup> &Fixups,
11191bc56edSDimitry Andric                               const MCSubtargetInfo &STI) const {
112ff0cc061SDimitry Andric     return getPCRelEncoding(MI, OpNum, Fixups,
113ff0cc061SDimitry Andric                             SystemZ::FK_390_PC32DBL, 2, false);
114ff0cc061SDimitry Andric   }
getPC16DBLTLSEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const115ff0cc061SDimitry Andric   uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
116ff0cc061SDimitry Andric                                  SmallVectorImpl<MCFixup> &Fixups,
117ff0cc061SDimitry Andric                                  const MCSubtargetInfo &STI) const {
118ff0cc061SDimitry Andric     return getPCRelEncoding(MI, OpNum, Fixups,
119ff0cc061SDimitry Andric                             SystemZ::FK_390_PC16DBL, 2, true);
120ff0cc061SDimitry Andric   }
getPC32DBLTLSEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const121ff0cc061SDimitry Andric   uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
122ff0cc061SDimitry Andric                                  SmallVectorImpl<MCFixup> &Fixups,
123ff0cc061SDimitry Andric                                  const MCSubtargetInfo &STI) const {
124ff0cc061SDimitry Andric     return getPCRelEncoding(MI, OpNum, Fixups,
125ff0cc061SDimitry Andric                             SystemZ::FK_390_PC32DBL, 2, true);
126284c1978SDimitry Andric   }
getPC12DBLBPPEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const127d88c1a5aSDimitry Andric   uint64_t getPC12DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
128d88c1a5aSDimitry Andric                                  SmallVectorImpl<MCFixup> &Fixups,
129d88c1a5aSDimitry Andric                                  const MCSubtargetInfo &STI) const {
130d88c1a5aSDimitry Andric     return getPCRelEncoding(MI, OpNum, Fixups,
131d88c1a5aSDimitry Andric                             SystemZ::FK_390_PC12DBL, 1, false);
132d88c1a5aSDimitry Andric   }
getPC16DBLBPPEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const133d88c1a5aSDimitry Andric   uint64_t getPC16DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
134d88c1a5aSDimitry Andric                                  SmallVectorImpl<MCFixup> &Fixups,
135d88c1a5aSDimitry Andric                                  const MCSubtargetInfo &STI) const {
136d88c1a5aSDimitry Andric     return getPCRelEncoding(MI, OpNum, Fixups,
137d88c1a5aSDimitry Andric                             SystemZ::FK_390_PC16DBL, 4, false);
138d88c1a5aSDimitry Andric   }
getPC24DBLBPPEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const139d88c1a5aSDimitry Andric   uint64_t getPC24DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
140d88c1a5aSDimitry Andric                                  SmallVectorImpl<MCFixup> &Fixups,
141d88c1a5aSDimitry Andric                                  const MCSubtargetInfo &STI) const {
142d88c1a5aSDimitry Andric     return getPCRelEncoding(MI, OpNum, Fixups,
143d88c1a5aSDimitry Andric                             SystemZ::FK_390_PC24DBL, 3, false);
144d88c1a5aSDimitry Andric   }
145d88c1a5aSDimitry Andric 
146d88c1a5aSDimitry Andric private:
147d88c1a5aSDimitry Andric   uint64_t computeAvailableFeatures(const FeatureBitset &FB) const;
148d88c1a5aSDimitry Andric   void verifyInstructionPredicates(const MCInst &MI,
149d88c1a5aSDimitry Andric                                    uint64_t AvailableFeatures) const;
150284c1978SDimitry Andric };
151284c1978SDimitry Andric 
1527a7e6055SDimitry Andric } // end anonymous namespace
153284c1978SDimitry Andric 
154284c1978SDimitry Andric void SystemZMCCodeEmitter::
encodeInstruction(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const155ff0cc061SDimitry Andric encodeInstruction(const MCInst &MI, raw_ostream &OS,
15691bc56edSDimitry Andric                   SmallVectorImpl<MCFixup> &Fixups,
15791bc56edSDimitry Andric                   const MCSubtargetInfo &STI) const {
158d88c1a5aSDimitry Andric   verifyInstructionPredicates(MI,
159d88c1a5aSDimitry Andric                               computeAvailableFeatures(STI.getFeatureBits()));
160d88c1a5aSDimitry Andric 
16191bc56edSDimitry Andric   uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
162284c1978SDimitry Andric   unsigned Size = MCII.get(MI.getOpcode()).getSize();
163284c1978SDimitry Andric   // Big-endian insertion of Size bytes.
164284c1978SDimitry Andric   unsigned ShiftValue = (Size * 8) - 8;
165284c1978SDimitry Andric   for (unsigned I = 0; I != Size; ++I) {
166284c1978SDimitry Andric     OS << uint8_t(Bits >> ShiftValue);
167284c1978SDimitry Andric     ShiftValue -= 8;
168284c1978SDimitry Andric   }
169284c1978SDimitry Andric }
170284c1978SDimitry Andric 
171f785676fSDimitry Andric uint64_t SystemZMCCodeEmitter::
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const172284c1978SDimitry Andric getMachineOpValue(const MCInst &MI, const MCOperand &MO,
17391bc56edSDimitry Andric                   SmallVectorImpl<MCFixup> &Fixups,
17491bc56edSDimitry Andric                   const MCSubtargetInfo &STI) const {
175284c1978SDimitry Andric   if (MO.isReg())
176f785676fSDimitry Andric     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
177284c1978SDimitry Andric   if (MO.isImm())
178f785676fSDimitry Andric     return static_cast<uint64_t>(MO.getImm());
179284c1978SDimitry Andric   llvm_unreachable("Unexpected operand type!");
180284c1978SDimitry Andric }
181284c1978SDimitry Andric 
182f785676fSDimitry Andric uint64_t SystemZMCCodeEmitter::
getBDAddr12Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const183f785676fSDimitry Andric getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
18491bc56edSDimitry Andric                     SmallVectorImpl<MCFixup> &Fixups,
18591bc56edSDimitry Andric                     const MCSubtargetInfo &STI) const {
18691bc56edSDimitry Andric   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
18791bc56edSDimitry Andric   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
188f785676fSDimitry Andric   assert(isUInt<4>(Base) && isUInt<12>(Disp));
189f785676fSDimitry Andric   return (Base << 12) | Disp;
190f785676fSDimitry Andric }
191f785676fSDimitry Andric 
192f785676fSDimitry Andric uint64_t SystemZMCCodeEmitter::
getBDAddr20Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const193f785676fSDimitry Andric getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
19491bc56edSDimitry Andric                     SmallVectorImpl<MCFixup> &Fixups,
19591bc56edSDimitry Andric                     const MCSubtargetInfo &STI) const {
19691bc56edSDimitry Andric   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
19791bc56edSDimitry Andric   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
198f785676fSDimitry Andric   assert(isUInt<4>(Base) && isInt<20>(Disp));
199f785676fSDimitry Andric   return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12);
200f785676fSDimitry Andric }
201f785676fSDimitry Andric 
202f785676fSDimitry Andric uint64_t SystemZMCCodeEmitter::
getBDXAddr12Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const203f785676fSDimitry Andric getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
20491bc56edSDimitry Andric                      SmallVectorImpl<MCFixup> &Fixups,
20591bc56edSDimitry Andric                      const MCSubtargetInfo &STI) const {
20691bc56edSDimitry Andric   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
20791bc56edSDimitry Andric   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
20891bc56edSDimitry Andric   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
209f785676fSDimitry Andric   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index));
210f785676fSDimitry Andric   return (Index << 16) | (Base << 12) | Disp;
211f785676fSDimitry Andric }
212f785676fSDimitry Andric 
213f785676fSDimitry Andric uint64_t SystemZMCCodeEmitter::
getBDXAddr20Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const214f785676fSDimitry Andric getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
21591bc56edSDimitry Andric                      SmallVectorImpl<MCFixup> &Fixups,
21691bc56edSDimitry Andric                      const MCSubtargetInfo &STI) const {
21791bc56edSDimitry Andric   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
21891bc56edSDimitry Andric   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
21991bc56edSDimitry Andric   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
220f785676fSDimitry Andric   assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index));
221f785676fSDimitry Andric   return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8)
222f785676fSDimitry Andric     | ((Disp & 0xff000) >> 12);
223f785676fSDimitry Andric }
224f785676fSDimitry Andric 
225f785676fSDimitry Andric uint64_t SystemZMCCodeEmitter::
getBDLAddr12Len4Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const226*5517e702SDimitry Andric getBDLAddr12Len4Encoding(const MCInst &MI, unsigned OpNum,
227*5517e702SDimitry Andric                          SmallVectorImpl<MCFixup> &Fixups,
228*5517e702SDimitry Andric                          const MCSubtargetInfo &STI) const {
229*5517e702SDimitry Andric   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
230*5517e702SDimitry Andric   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
231*5517e702SDimitry Andric   uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
232*5517e702SDimitry Andric   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len));
233*5517e702SDimitry Andric   return (Len << 16) | (Base << 12) | Disp;
234*5517e702SDimitry Andric }
235*5517e702SDimitry Andric 
236*5517e702SDimitry Andric uint64_t SystemZMCCodeEmitter::
getBDLAddr12Len8Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const237f785676fSDimitry Andric getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
23891bc56edSDimitry Andric                          SmallVectorImpl<MCFixup> &Fixups,
23991bc56edSDimitry Andric                          const MCSubtargetInfo &STI) const {
24091bc56edSDimitry Andric   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
24191bc56edSDimitry Andric   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
24291bc56edSDimitry Andric   uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
243f785676fSDimitry Andric   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len));
244f785676fSDimitry Andric   return (Len << 16) | (Base << 12) | Disp;
245f785676fSDimitry Andric }
246f785676fSDimitry Andric 
247ff0cc061SDimitry Andric uint64_t SystemZMCCodeEmitter::
getBDRAddr12Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const248d88c1a5aSDimitry Andric getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum,
249d88c1a5aSDimitry Andric                      SmallVectorImpl<MCFixup> &Fixups,
250d88c1a5aSDimitry Andric                      const MCSubtargetInfo &STI) const {
251d88c1a5aSDimitry Andric   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
252d88c1a5aSDimitry Andric   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
253d88c1a5aSDimitry Andric   uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
254d88c1a5aSDimitry Andric   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len));
255d88c1a5aSDimitry Andric   return (Len << 16) | (Base << 12) | Disp;
256d88c1a5aSDimitry Andric }
257d88c1a5aSDimitry Andric 
258d88c1a5aSDimitry Andric uint64_t SystemZMCCodeEmitter::
getBDVAddr12Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const259ff0cc061SDimitry Andric getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
260ff0cc061SDimitry Andric                      SmallVectorImpl<MCFixup> &Fixups,
261ff0cc061SDimitry Andric                      const MCSubtargetInfo &STI) const {
262ff0cc061SDimitry Andric   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
263ff0cc061SDimitry Andric   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
264ff0cc061SDimitry Andric   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
265ff0cc061SDimitry Andric   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<5>(Index));
266ff0cc061SDimitry Andric   return (Index << 16) | (Base << 12) | Disp;
267ff0cc061SDimitry Andric }
268ff0cc061SDimitry Andric 
269f785676fSDimitry Andric uint64_t
getPCRelEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,unsigned Kind,int64_t Offset,bool AllowTLS) const270f785676fSDimitry Andric SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
271284c1978SDimitry Andric                                        SmallVectorImpl<MCFixup> &Fixups,
272ff0cc061SDimitry Andric                                        unsigned Kind, int64_t Offset,
273ff0cc061SDimitry Andric                                        bool AllowTLS) const {
274284c1978SDimitry Andric   const MCOperand &MO = MI.getOperand(OpNum);
275f785676fSDimitry Andric   const MCExpr *Expr;
276284c1978SDimitry Andric   if (MO.isImm())
27797bc6c73SDimitry Andric     Expr = MCConstantExpr::create(MO.getImm() + Offset, Ctx);
278f785676fSDimitry Andric   else {
279f785676fSDimitry Andric     Expr = MO.getExpr();
280284c1978SDimitry Andric     if (Offset) {
281284c1978SDimitry Andric       // The operand value is relative to the start of MI, but the fixup
282284c1978SDimitry Andric       // is relative to the operand field itself, which is Offset bytes
283284c1978SDimitry Andric       // into MI.  Add Offset to the relocation value to cancel out
284284c1978SDimitry Andric       // this difference.
28597bc6c73SDimitry Andric       const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);
28697bc6c73SDimitry Andric       Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx);
287284c1978SDimitry Andric     }
288f785676fSDimitry Andric   }
289ff0cc061SDimitry Andric   Fixups.push_back(MCFixup::create(Offset, Expr, (MCFixupKind)Kind));
290ff0cc061SDimitry Andric 
291ff0cc061SDimitry Andric   // Output the fixup for the TLS marker if present.
292ff0cc061SDimitry Andric   if (AllowTLS && OpNum + 1 < MI.getNumOperands()) {
293ff0cc061SDimitry Andric     const MCOperand &MOTLS = MI.getOperand(OpNum + 1);
294ff0cc061SDimitry Andric     Fixups.push_back(MCFixup::create(0, MOTLS.getExpr(),
295ff0cc061SDimitry Andric                                      (MCFixupKind)SystemZ::FK_390_TLS_CALL));
296ff0cc061SDimitry Andric   }
297284c1978SDimitry Andric   return 0;
298284c1978SDimitry Andric }
299284c1978SDimitry Andric 
300d88c1a5aSDimitry Andric #define ENABLE_INSTR_PREDICATE_VERIFIER
301284c1978SDimitry Andric #include "SystemZGenMCCodeEmitter.inc"
3027a7e6055SDimitry Andric 
createSystemZMCCodeEmitter(const MCInstrInfo & MCII,const MCRegisterInfo & MRI,MCContext & Ctx)3037a7e6055SDimitry Andric MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
3047a7e6055SDimitry Andric                                                 const MCRegisterInfo &MRI,
3057a7e6055SDimitry Andric                                                 MCContext &Ctx) {
3067a7e6055SDimitry Andric   return new SystemZMCCodeEmitter(MCII, Ctx);
3077a7e6055SDimitry Andric }
308