15f613dfdSUlrich Weigand //===-- SystemZMCCodeEmitter.cpp - Convert SystemZ code to machine code ---===//
25f613dfdSUlrich Weigand //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
65f613dfdSUlrich Weigand //
75f613dfdSUlrich Weigand //===----------------------------------------------------------------------===//
85f613dfdSUlrich Weigand //
95f613dfdSUlrich Weigand // This file implements the SystemZMCCodeEmitter class.
105f613dfdSUlrich Weigand //
115f613dfdSUlrich Weigand //===----------------------------------------------------------------------===//
125f613dfdSUlrich Weigand 
135f613dfdSUlrich Weigand #include "MCTargetDesc/SystemZMCFixups.h"
143943d2b0SEugene Zelenko #include "MCTargetDesc/SystemZMCTargetDesc.h"
151c3ef9efSJonas Paulsson #include "SystemZInstrInfo.h"
163943d2b0SEugene Zelenko #include "llvm/ADT/SmallVector.h"
175f613dfdSUlrich Weigand #include "llvm/MC/MCCodeEmitter.h"
185f613dfdSUlrich Weigand #include "llvm/MC/MCContext.h"
195f613dfdSUlrich Weigand #include "llvm/MC/MCExpr.h"
203943d2b0SEugene Zelenko #include "llvm/MC/MCFixup.h"
213de83e40SPete Cooper #include "llvm/MC/MCInst.h"
225f613dfdSUlrich Weigand #include "llvm/MC/MCInstrInfo.h"
233de83e40SPete Cooper #include "llvm/MC/MCRegisterInfo.h"
243943d2b0SEugene Zelenko #include "llvm/MC/MCSubtargetInfo.h"
253943d2b0SEugene Zelenko #include "llvm/Support/ErrorHandling.h"
263943d2b0SEugene Zelenko #include "llvm/Support/raw_ostream.h"
273943d2b0SEugene Zelenko #include <cassert>
283943d2b0SEugene Zelenko #include <cstdint>
295f613dfdSUlrich Weigand 
305f613dfdSUlrich Weigand using namespace llvm;
315f613dfdSUlrich Weigand 
3284e68b29SChandler Carruth #define DEBUG_TYPE "mccodeemitter"
3384e68b29SChandler Carruth 
345f613dfdSUlrich Weigand namespace {
353943d2b0SEugene Zelenko 
365f613dfdSUlrich Weigand class SystemZMCCodeEmitter : public MCCodeEmitter {
375f613dfdSUlrich Weigand   const MCInstrInfo &MCII;
385f613dfdSUlrich Weigand   MCContext &Ctx;
395f613dfdSUlrich Weigand 
40e547b04dSJonas Paulsson   mutable unsigned MemOpsEmitted;
41e547b04dSJonas Paulsson 
425f613dfdSUlrich Weigand public:
SystemZMCCodeEmitter(const MCInstrInfo & mcii,MCContext & ctx)435f613dfdSUlrich Weigand   SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
445f613dfdSUlrich Weigand     : MCII(mcii), Ctx(ctx) {
455f613dfdSUlrich Weigand   }
465f613dfdSUlrich Weigand 
473943d2b0SEugene Zelenko   ~SystemZMCCodeEmitter() override = default;
485f613dfdSUlrich Weigand 
495f613dfdSUlrich Weigand   // OVerride MCCodeEmitter.
5091df21f7SJim Grosbach   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
519784cef3SDavid Woodhouse                          SmallVectorImpl<MCFixup> &Fixups,
5273156025SCraig Topper                          const MCSubtargetInfo &STI) const override;
535f613dfdSUlrich Weigand 
545f613dfdSUlrich Weigand private:
555f613dfdSUlrich Weigand   // Automatically generated by TableGen.
565f613dfdSUlrich Weigand   uint64_t getBinaryCodeForInstr(const MCInst &MI,
573fa98a65SDavid Woodhouse                                  SmallVectorImpl<MCFixup> &Fixups,
583fa98a65SDavid Woodhouse                                  const MCSubtargetInfo &STI) const;
595f613dfdSUlrich Weigand 
605f613dfdSUlrich Weigand   // Called by the TableGen code to get the binary encoding of operand
615f613dfdSUlrich Weigand   // MO in MI.  Fixups is the list of fixups against MI.
62d454ec0cSRichard Sandiford   uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
633fa98a65SDavid Woodhouse                              SmallVectorImpl<MCFixup> &Fixups,
643fa98a65SDavid Woodhouse                              const MCSubtargetInfo &STI) const;
65d454ec0cSRichard Sandiford 
661c3ef9efSJonas Paulsson   // Return the displacement value for the OpNum operand. If it is a symbol,
671c3ef9efSJonas Paulsson   // add a fixup for it and return 0.
681c3ef9efSJonas Paulsson   uint64_t getDispOpValue(const MCInst &MI, unsigned OpNum,
691c3ef9efSJonas Paulsson                           SmallVectorImpl<MCFixup> &Fixups,
701c3ef9efSJonas Paulsson                           SystemZ::FixupKind Kind) const;
711c3ef9efSJonas Paulsson 
72d454ec0cSRichard Sandiford   // Called by the TableGen code to get the binary encoding of an address.
731d959008SRichard Sandiford   // The index or length, if any, is encoded first, followed by the base,
74d454ec0cSRichard Sandiford   // followed by the displacement.  In a 20-bit displacement,
75d454ec0cSRichard Sandiford   // the low 12 bits are encoded before the high 8 bits.
76d454ec0cSRichard Sandiford   uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
773fa98a65SDavid Woodhouse                                SmallVectorImpl<MCFixup> &Fixups,
783fa98a65SDavid Woodhouse                                const MCSubtargetInfo &STI) const;
79d454ec0cSRichard Sandiford   uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
803fa98a65SDavid Woodhouse                                SmallVectorImpl<MCFixup> &Fixups,
813fa98a65SDavid Woodhouse                                const MCSubtargetInfo &STI) const;
82d454ec0cSRichard Sandiford   uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
833fa98a65SDavid Woodhouse                                 SmallVectorImpl<MCFixup> &Fixups,
843fa98a65SDavid Woodhouse                                 const MCSubtargetInfo &STI) const;
85d454ec0cSRichard Sandiford   uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
863fa98a65SDavid Woodhouse                                 SmallVectorImpl<MCFixup> &Fixups,
873fa98a65SDavid Woodhouse                                 const MCSubtargetInfo &STI) const;
88c7eb5a95SUlrich Weigand   uint64_t getBDLAddr12Len4Encoding(const MCInst &MI, unsigned OpNum,
89c7eb5a95SUlrich Weigand                                     SmallVectorImpl<MCFixup> &Fixups,
90c7eb5a95SUlrich Weigand                                     const MCSubtargetInfo &STI) const;
911d959008SRichard Sandiford   uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
923fa98a65SDavid Woodhouse                                     SmallVectorImpl<MCFixup> &Fixups,
933fa98a65SDavid Woodhouse                                     const MCSubtargetInfo &STI) const;
94ec5d779eSUlrich Weigand   uint64_t getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum,
95ec5d779eSUlrich Weigand                                 SmallVectorImpl<MCFixup> &Fixups,
96ec5d779eSUlrich Weigand                                 const MCSubtargetInfo &STI) const;
97a8b04e1cSUlrich Weigand   uint64_t getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
98a8b04e1cSUlrich Weigand                                 SmallVectorImpl<MCFixup> &Fixups,
99a8b04e1cSUlrich Weigand                                 const MCSubtargetInfo &STI) const;
1005f613dfdSUlrich Weigand 
1015f613dfdSUlrich Weigand   // Operand OpNum of MI needs a PC-relative fixup of kind Kind at
1025f613dfdSUlrich Weigand   // Offset bytes from the start of MI.  Add the fixup to Fixups
1035f613dfdSUlrich Weigand   // and return the in-place addend, which since we're a RELA target
1047bdd7c23SUlrich Weigand   // is always 0.  If AllowTLS is true and optional operand OpNum + 1
1057bdd7c23SUlrich Weigand   // is present, also emit a TLS call fixup for it.
106d454ec0cSRichard Sandiford   uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
1075f613dfdSUlrich Weigand                             SmallVectorImpl<MCFixup> &Fixups,
1087bdd7c23SUlrich Weigand                             unsigned Kind, int64_t Offset,
1097bdd7c23SUlrich Weigand                             bool AllowTLS) const;
1105f613dfdSUlrich Weigand 
getPC16DBLEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const111d454ec0cSRichard Sandiford   uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
1123fa98a65SDavid Woodhouse                               SmallVectorImpl<MCFixup> &Fixups,
1133fa98a65SDavid Woodhouse                               const MCSubtargetInfo &STI) const {
1147bdd7c23SUlrich Weigand     return getPCRelEncoding(MI, OpNum, Fixups,
1157bdd7c23SUlrich Weigand                             SystemZ::FK_390_PC16DBL, 2, false);
1165f613dfdSUlrich Weigand   }
getPC32DBLEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const117d454ec0cSRichard Sandiford   uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
1183fa98a65SDavid Woodhouse                               SmallVectorImpl<MCFixup> &Fixups,
1193fa98a65SDavid Woodhouse                               const MCSubtargetInfo &STI) const {
1207bdd7c23SUlrich Weigand     return getPCRelEncoding(MI, OpNum, Fixups,
1217bdd7c23SUlrich Weigand                             SystemZ::FK_390_PC32DBL, 2, false);
1227bdd7c23SUlrich Weigand   }
getPC16DBLTLSEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const1237bdd7c23SUlrich Weigand   uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
1247bdd7c23SUlrich Weigand                                  SmallVectorImpl<MCFixup> &Fixups,
1257bdd7c23SUlrich Weigand                                  const MCSubtargetInfo &STI) const {
1267bdd7c23SUlrich Weigand     return getPCRelEncoding(MI, OpNum, Fixups,
1277bdd7c23SUlrich Weigand                             SystemZ::FK_390_PC16DBL, 2, true);
1287bdd7c23SUlrich Weigand   }
getPC32DBLTLSEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const1297bdd7c23SUlrich Weigand   uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
1307bdd7c23SUlrich Weigand                                  SmallVectorImpl<MCFixup> &Fixups,
1317bdd7c23SUlrich Weigand                                  const MCSubtargetInfo &STI) const {
1327bdd7c23SUlrich Weigand     return getPCRelEncoding(MI, OpNum, Fixups,
1337bdd7c23SUlrich Weigand                             SystemZ::FK_390_PC32DBL, 2, true);
1345f613dfdSUlrich Weigand   }
getPC12DBLBPPEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const13584404f30SUlrich Weigand   uint64_t getPC12DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
13684404f30SUlrich Weigand                                  SmallVectorImpl<MCFixup> &Fixups,
13784404f30SUlrich Weigand                                  const MCSubtargetInfo &STI) const {
13884404f30SUlrich Weigand     return getPCRelEncoding(MI, OpNum, Fixups,
13984404f30SUlrich Weigand                             SystemZ::FK_390_PC12DBL, 1, false);
14084404f30SUlrich Weigand   }
getPC16DBLBPPEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const14184404f30SUlrich Weigand   uint64_t getPC16DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
14284404f30SUlrich Weigand                                  SmallVectorImpl<MCFixup> &Fixups,
14384404f30SUlrich Weigand                                  const MCSubtargetInfo &STI) const {
14484404f30SUlrich Weigand     return getPCRelEncoding(MI, OpNum, Fixups,
14584404f30SUlrich Weigand                             SystemZ::FK_390_PC16DBL, 4, false);
14684404f30SUlrich Weigand   }
getPC24DBLBPPEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const14784404f30SUlrich Weigand   uint64_t getPC24DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
14884404f30SUlrich Weigand                                  SmallVectorImpl<MCFixup> &Fixups,
14984404f30SUlrich Weigand                                  const MCSubtargetInfo &STI) const {
15084404f30SUlrich Weigand     return getPCRelEncoding(MI, OpNum, Fixups,
15184404f30SUlrich Weigand                             SystemZ::FK_390_PC24DBL, 3, false);
15284404f30SUlrich Weigand   }
1535f613dfdSUlrich Weigand };
1545f613dfdSUlrich Weigand 
1553943d2b0SEugene Zelenko } // end anonymous namespace
1565f613dfdSUlrich Weigand 
encodeInstruction(const MCInst & MI,raw_ostream & OS,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const157*3e0bf1c7SDavid Green void SystemZMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS,
1589784cef3SDavid Woodhouse                                              SmallVectorImpl<MCFixup> &Fixups,
1599784cef3SDavid Woodhouse                                              const MCSubtargetInfo &STI) const {
160e547b04dSJonas Paulsson   MemOpsEmitted = 0;
1613fa98a65SDavid Woodhouse   uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
1625f613dfdSUlrich Weigand   unsigned Size = MCII.get(MI.getOpcode()).getSize();
1635f613dfdSUlrich Weigand   // Big-endian insertion of Size bytes.
1645f613dfdSUlrich Weigand   unsigned ShiftValue = (Size * 8) - 8;
1655f613dfdSUlrich Weigand   for (unsigned I = 0; I != Size; ++I) {
1665f613dfdSUlrich Weigand     OS << uint8_t(Bits >> ShiftValue);
1675f613dfdSUlrich Weigand     ShiftValue -= 8;
1685f613dfdSUlrich Weigand   }
1695f613dfdSUlrich Weigand }
1705f613dfdSUlrich Weigand 
171d454ec0cSRichard Sandiford uint64_t SystemZMCCodeEmitter::
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const1725f613dfdSUlrich Weigand getMachineOpValue(const MCInst &MI, const MCOperand &MO,
1733fa98a65SDavid Woodhouse                   SmallVectorImpl<MCFixup> &Fixups,
1743fa98a65SDavid Woodhouse                   const MCSubtargetInfo &STI) const {
1755f613dfdSUlrich Weigand   if (MO.isReg())
176bc07a890SBill Wendling     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
1775f613dfdSUlrich Weigand   if (MO.isImm())
178d454ec0cSRichard Sandiford     return static_cast<uint64_t>(MO.getImm());
1795f613dfdSUlrich Weigand   llvm_unreachable("Unexpected operand type!");
1805f613dfdSUlrich Weigand }
1815f613dfdSUlrich Weigand 
182d454ec0cSRichard Sandiford uint64_t SystemZMCCodeEmitter::
getDispOpValue(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,SystemZ::FixupKind Kind) const1831c3ef9efSJonas Paulsson getDispOpValue(const MCInst &MI, unsigned OpNum,
1841c3ef9efSJonas Paulsson                SmallVectorImpl<MCFixup> &Fixups,
1851c3ef9efSJonas Paulsson                SystemZ::FixupKind Kind) const {
1861c3ef9efSJonas Paulsson   const MCOperand &MO = MI.getOperand(OpNum);
187e547b04dSJonas Paulsson   if (MO.isImm()) {
188e547b04dSJonas Paulsson     ++MemOpsEmitted;
1891c3ef9efSJonas Paulsson     return static_cast<uint64_t>(MO.getImm());
190e547b04dSJonas Paulsson   }
1911c3ef9efSJonas Paulsson   if (MO.isExpr()) {
1921c3ef9efSJonas Paulsson     // All instructions follow the pattern where the first displacement has a
1931c3ef9efSJonas Paulsson     // 2 bytes offset, and the second one 4 bytes.
194e547b04dSJonas Paulsson     unsigned ByteOffs = MemOpsEmitted++ == 0 ? 2 : 4;
1955bf4f2acSJonas Paulsson     Fixups.push_back(MCFixup::create(ByteOffs, MO.getExpr(), (MCFixupKind)Kind,
1965bf4f2acSJonas Paulsson                                      MI.getLoc()));
1971c3ef9efSJonas Paulsson     assert(Fixups.size() <= 2 && "More than two memory operands in MI?");
1981c3ef9efSJonas Paulsson     return 0;
1991c3ef9efSJonas Paulsson   }
2001c3ef9efSJonas Paulsson   llvm_unreachable("Unexpected operand type!");
2011c3ef9efSJonas Paulsson }
2021c3ef9efSJonas Paulsson 
2031c3ef9efSJonas Paulsson uint64_t SystemZMCCodeEmitter::
getBDAddr12Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const204d454ec0cSRichard Sandiford getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
2053fa98a65SDavid Woodhouse                     SmallVectorImpl<MCFixup> &Fixups,
2063fa98a65SDavid Woodhouse                     const MCSubtargetInfo &STI) const {
2073fa98a65SDavid Woodhouse   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
2081c3ef9efSJonas Paulsson   uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
209d454ec0cSRichard Sandiford   assert(isUInt<4>(Base) && isUInt<12>(Disp));
210d454ec0cSRichard Sandiford   return (Base << 12) | Disp;
211d454ec0cSRichard Sandiford }
212d454ec0cSRichard Sandiford 
213d454ec0cSRichard Sandiford uint64_t SystemZMCCodeEmitter::
getBDAddr20Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const214d454ec0cSRichard Sandiford getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
2153fa98a65SDavid Woodhouse                     SmallVectorImpl<MCFixup> &Fixups,
2163fa98a65SDavid Woodhouse                     const MCSubtargetInfo &STI) const {
2173fa98a65SDavid Woodhouse   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
2181c3ef9efSJonas Paulsson   uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_20);
219d454ec0cSRichard Sandiford   assert(isUInt<4>(Base) && isInt<20>(Disp));
220d454ec0cSRichard Sandiford   return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12);
221d454ec0cSRichard Sandiford }
222d454ec0cSRichard Sandiford 
223d454ec0cSRichard Sandiford uint64_t SystemZMCCodeEmitter::
getBDXAddr12Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const224d454ec0cSRichard Sandiford getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
2253fa98a65SDavid Woodhouse                      SmallVectorImpl<MCFixup> &Fixups,
2263fa98a65SDavid Woodhouse                      const MCSubtargetInfo &STI) const {
2273fa98a65SDavid Woodhouse   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
2281c3ef9efSJonas Paulsson   uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
2293fa98a65SDavid Woodhouse   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
230d454ec0cSRichard Sandiford   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index));
231d454ec0cSRichard Sandiford   return (Index << 16) | (Base << 12) | Disp;
232d454ec0cSRichard Sandiford }
233d454ec0cSRichard Sandiford 
234d454ec0cSRichard Sandiford uint64_t SystemZMCCodeEmitter::
getBDXAddr20Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const235d454ec0cSRichard Sandiford getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
2363fa98a65SDavid Woodhouse                      SmallVectorImpl<MCFixup> &Fixups,
2373fa98a65SDavid Woodhouse                      const MCSubtargetInfo &STI) const {
2383fa98a65SDavid Woodhouse   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
2391c3ef9efSJonas Paulsson   uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_20);
2403fa98a65SDavid Woodhouse   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
241d454ec0cSRichard Sandiford   assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index));
242d454ec0cSRichard Sandiford   return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8)
243d454ec0cSRichard Sandiford     | ((Disp & 0xff000) >> 12);
244d454ec0cSRichard Sandiford }
245d454ec0cSRichard Sandiford 
2461d959008SRichard Sandiford uint64_t SystemZMCCodeEmitter::
getBDLAddr12Len4Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const247c7eb5a95SUlrich Weigand getBDLAddr12Len4Encoding(const MCInst &MI, unsigned OpNum,
248c7eb5a95SUlrich Weigand                          SmallVectorImpl<MCFixup> &Fixups,
249c7eb5a95SUlrich Weigand                          const MCSubtargetInfo &STI) const {
250c7eb5a95SUlrich Weigand   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
2511c3ef9efSJonas Paulsson   uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
252c7eb5a95SUlrich Weigand   uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
253c7eb5a95SUlrich Weigand   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len));
254c7eb5a95SUlrich Weigand   return (Len << 16) | (Base << 12) | Disp;
255c7eb5a95SUlrich Weigand }
256c7eb5a95SUlrich Weigand 
257c7eb5a95SUlrich Weigand uint64_t SystemZMCCodeEmitter::
getBDLAddr12Len8Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const2581d959008SRichard Sandiford getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
2593fa98a65SDavid Woodhouse                          SmallVectorImpl<MCFixup> &Fixups,
2603fa98a65SDavid Woodhouse                          const MCSubtargetInfo &STI) const {
2613fa98a65SDavid Woodhouse   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
2621c3ef9efSJonas Paulsson   uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
2633fa98a65SDavid Woodhouse   uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
2641d959008SRichard Sandiford   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len));
2651d959008SRichard Sandiford   return (Len << 16) | (Base << 12) | Disp;
2661d959008SRichard Sandiford }
2671d959008SRichard Sandiford 
268a8b04e1cSUlrich Weigand uint64_t SystemZMCCodeEmitter::
getBDRAddr12Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const269ec5d779eSUlrich Weigand getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum,
270ec5d779eSUlrich Weigand                      SmallVectorImpl<MCFixup> &Fixups,
271ec5d779eSUlrich Weigand                      const MCSubtargetInfo &STI) const {
272ec5d779eSUlrich Weigand   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
2731c3ef9efSJonas Paulsson   uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
274ec5d779eSUlrich Weigand   uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
275ec5d779eSUlrich Weigand   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len));
276ec5d779eSUlrich Weigand   return (Len << 16) | (Base << 12) | Disp;
277ec5d779eSUlrich Weigand }
278ec5d779eSUlrich Weigand 
279ec5d779eSUlrich Weigand uint64_t SystemZMCCodeEmitter::
getBDVAddr12Encoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const280a8b04e1cSUlrich Weigand getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
281a8b04e1cSUlrich Weigand                      SmallVectorImpl<MCFixup> &Fixups,
282a8b04e1cSUlrich Weigand                      const MCSubtargetInfo &STI) const {
283a8b04e1cSUlrich Weigand   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
2841c3ef9efSJonas Paulsson   uint64_t Disp = getDispOpValue(MI, OpNum + 1, Fixups, SystemZ::FK_390_12);
285a8b04e1cSUlrich Weigand   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
286a8b04e1cSUlrich Weigand   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<5>(Index));
287a8b04e1cSUlrich Weigand   return (Index << 16) | (Base << 12) | Disp;
288a8b04e1cSUlrich Weigand }
289a8b04e1cSUlrich Weigand 
290d454ec0cSRichard Sandiford uint64_t
getPCRelEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,unsigned Kind,int64_t Offset,bool AllowTLS) const291d454ec0cSRichard Sandiford SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
2925f613dfdSUlrich Weigand                                        SmallVectorImpl<MCFixup> &Fixups,
2937bdd7c23SUlrich Weigand                                        unsigned Kind, int64_t Offset,
2947bdd7c23SUlrich Weigand                                        bool AllowTLS) const {
2955bf4f2acSJonas Paulsson   SMLoc Loc = MI.getLoc();
2965f613dfdSUlrich Weigand   const MCOperand &MO = MI.getOperand(OpNum);
2971fb5883dSRichard Sandiford   const MCExpr *Expr;
2985f613dfdSUlrich Weigand   if (MO.isImm())
29913760bd1SJim Grosbach     Expr = MCConstantExpr::create(MO.getImm() + Offset, Ctx);
3001fb5883dSRichard Sandiford   else {
3011fb5883dSRichard Sandiford     Expr = MO.getExpr();
3025f613dfdSUlrich Weigand     if (Offset) {
3035f613dfdSUlrich Weigand       // The operand value is relative to the start of MI, but the fixup
3045f613dfdSUlrich Weigand       // is relative to the operand field itself, which is Offset bytes
3055f613dfdSUlrich Weigand       // into MI.  Add Offset to the relocation value to cancel out
3065f613dfdSUlrich Weigand       // this difference.
30713760bd1SJim Grosbach       const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);
30813760bd1SJim Grosbach       Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx);
3095f613dfdSUlrich Weigand     }
3101fb5883dSRichard Sandiford   }
3115bf4f2acSJonas Paulsson   Fixups.push_back(MCFixup::create(Offset, Expr, (MCFixupKind)Kind, Loc));
3127bdd7c23SUlrich Weigand 
3137bdd7c23SUlrich Weigand   // Output the fixup for the TLS marker if present.
3147bdd7c23SUlrich Weigand   if (AllowTLS && OpNum + 1 < MI.getNumOperands()) {
3157bdd7c23SUlrich Weigand     const MCOperand &MOTLS = MI.getOperand(OpNum + 1);
3165bf4f2acSJonas Paulsson     Fixups.push_back(MCFixup::create(
3175bf4f2acSJonas Paulsson         0, MOTLS.getExpr(), (MCFixupKind)SystemZ::FK_390_TLS_CALL, Loc));
3187bdd7c23SUlrich Weigand   }
3195f613dfdSUlrich Weigand   return 0;
3205f613dfdSUlrich Weigand }
3215f613dfdSUlrich Weigand 
3225f613dfdSUlrich Weigand #include "SystemZGenMCCodeEmitter.inc"
3233943d2b0SEugene Zelenko 
createSystemZMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)3243943d2b0SEugene Zelenko MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
3253943d2b0SEugene Zelenko                                                 MCContext &Ctx) {
3263943d2b0SEugene Zelenko   return new SystemZMCCodeEmitter(MCII, Ctx);
3273943d2b0SEugene Zelenko }
328