xref: /freebsd/contrib/llvm-project/llvm/lib/Target/SystemZ/MCTargetDesc/SystemZMCCodeEmitter.cpp (revision 0fca6ea1d4eea4c934cfff25ac9ee8ad6fe95583)
1  //===-- SystemZMCCodeEmitter.cpp - Convert SystemZ 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 SystemZMCCodeEmitter class.
10  //
11  //===----------------------------------------------------------------------===//
12  
13  #include "MCTargetDesc/SystemZMCFixups.h"
14  #include "MCTargetDesc/SystemZMCTargetDesc.h"
15  #include "llvm/ADT/SmallVector.h"
16  #include "llvm/MC/MCCodeEmitter.h"
17  #include "llvm/MC/MCContext.h"
18  #include "llvm/MC/MCExpr.h"
19  #include "llvm/MC/MCFixup.h"
20  #include "llvm/MC/MCInst.h"
21  #include "llvm/MC/MCInstrInfo.h"
22  #include "llvm/MC/MCRegisterInfo.h"
23  #include "llvm/MC/MCSubtargetInfo.h"
24  #include "llvm/Support/ErrorHandling.h"
25  #include <cassert>
26  #include <cstdint>
27  
28  using namespace llvm;
29  
30  #define DEBUG_TYPE "mccodeemitter"
31  
32  namespace {
33  
34  class SystemZMCCodeEmitter : public MCCodeEmitter {
35    const MCInstrInfo &MCII;
36    MCContext &Ctx;
37  
38  public:
SystemZMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)39    SystemZMCCodeEmitter(const MCInstrInfo &MCII, MCContext &Ctx)
40        : MCII(MCII), Ctx(Ctx) {}
41  
42    ~SystemZMCCodeEmitter() override = default;
43  
44    // OVerride MCCodeEmitter.
45    void encodeInstruction(const MCInst &MI, SmallVectorImpl<char> &CB,
46                           SmallVectorImpl<MCFixup> &Fixups,
47                           const MCSubtargetInfo &STI) const override;
48  
49  private:
50    // Automatically generated by TableGen.
51    uint64_t getBinaryCodeForInstr(const MCInst &MI,
52                                   SmallVectorImpl<MCFixup> &Fixups,
53                                   const MCSubtargetInfo &STI) const;
54    uint32_t getOperandBitOffset(const MCInst &MI, unsigned OpNum,
55                                 const MCSubtargetInfo &STI) const;
56  
57    // Called by the TableGen code to get the binary encoding of operand
58    // MO in MI.  Fixups is the list of fixups against MI.
59    uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
60                               SmallVectorImpl<MCFixup> &Fixups,
61                               const MCSubtargetInfo &STI) const;
62  
63    // Return the encoded immediate value for the OpNum operand. If it is a
64    // symbol, add a fixup for it and return 0.
65    template <SystemZ::FixupKind Kind>
66    uint64_t getImmOpValue(const MCInst &MI, unsigned OpNum,
67                           SmallVectorImpl<MCFixup> &Fixups,
68                           const MCSubtargetInfo &STI) const;
69  
70    // Called by the TableGen code to get the binary encoding of a length value.
71    // Length values are encoded by subtracting 1 from the actual value.
72    template <SystemZ::FixupKind Kind>
73    uint64_t getLenEncoding(const MCInst &MI, unsigned OpNum,
74                            SmallVectorImpl<MCFixup> &Fixups,
75                            const MCSubtargetInfo &STI) const;
76  
77    // Operand OpNum of MI needs a PC-relative fixup of kind Kind at
78    // Offset bytes from the start of MI.  Add the fixup to Fixups
79    // and return the in-place addend, which since we're a RELA target
80    // is always 0.  If AllowTLS is true and optional operand OpNum + 1
81    // is present, also emit a TLS call fixup for it.
82    uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
83                              SmallVectorImpl<MCFixup> &Fixups,
84                              unsigned Kind, int64_t Offset,
85                              bool AllowTLS) const;
86  
getPC16DBLEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const87    uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
88                                SmallVectorImpl<MCFixup> &Fixups,
89                                const MCSubtargetInfo &STI) const {
90      return getPCRelEncoding(MI, OpNum, Fixups,
91                              SystemZ::FK_390_PC16DBL, 2, false);
92    }
getPC32DBLEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const93    uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
94                                SmallVectorImpl<MCFixup> &Fixups,
95                                const MCSubtargetInfo &STI) const {
96      return getPCRelEncoding(MI, OpNum, Fixups,
97                              SystemZ::FK_390_PC32DBL, 2, false);
98    }
getPC16DBLTLSEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const99    uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
100                                   SmallVectorImpl<MCFixup> &Fixups,
101                                   const MCSubtargetInfo &STI) const {
102      return getPCRelEncoding(MI, OpNum, Fixups,
103                              SystemZ::FK_390_PC16DBL, 2, true);
104    }
getPC32DBLTLSEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const105    uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
106                                   SmallVectorImpl<MCFixup> &Fixups,
107                                   const MCSubtargetInfo &STI) const {
108      return getPCRelEncoding(MI, OpNum, Fixups,
109                              SystemZ::FK_390_PC32DBL, 2, true);
110    }
getPC12DBLBPPEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const111    uint64_t getPC12DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
112                                   SmallVectorImpl<MCFixup> &Fixups,
113                                   const MCSubtargetInfo &STI) const {
114      return getPCRelEncoding(MI, OpNum, Fixups,
115                              SystemZ::FK_390_PC12DBL, 1, false);
116    }
getPC16DBLBPPEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const117    uint64_t getPC16DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
118                                   SmallVectorImpl<MCFixup> &Fixups,
119                                   const MCSubtargetInfo &STI) const {
120      return getPCRelEncoding(MI, OpNum, Fixups,
121                              SystemZ::FK_390_PC16DBL, 4, false);
122    }
getPC24DBLBPPEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const123    uint64_t getPC24DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
124                                   SmallVectorImpl<MCFixup> &Fixups,
125                                   const MCSubtargetInfo &STI) const {
126      return getPCRelEncoding(MI, OpNum, Fixups,
127                              SystemZ::FK_390_PC24DBL, 3, false);
128    }
129  };
130  
131  } // end anonymous namespace
132  
encodeInstruction(const MCInst & MI,SmallVectorImpl<char> & CB,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const133  void SystemZMCCodeEmitter::encodeInstruction(const MCInst &MI,
134                                               SmallVectorImpl<char> &CB,
135                                               SmallVectorImpl<MCFixup> &Fixups,
136                                               const MCSubtargetInfo &STI) const {
137    uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
138    unsigned Size = MCII.get(MI.getOpcode()).getSize();
139    // Big-endian insertion of Size bytes.
140    unsigned ShiftValue = (Size * 8) - 8;
141    for (unsigned I = 0; I != Size; ++I) {
142      CB.push_back(uint8_t(Bits >> ShiftValue));
143      ShiftValue -= 8;
144    }
145  }
146  
147  uint64_t SystemZMCCodeEmitter::
getMachineOpValue(const MCInst & MI,const MCOperand & MO,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const148  getMachineOpValue(const MCInst &MI, const MCOperand &MO,
149                    SmallVectorImpl<MCFixup> &Fixups,
150                    const MCSubtargetInfo &STI) const {
151    if (MO.isReg())
152      return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
153    // SystemZAsmParser::parseAnyRegister() produces KindImm when registers are
154    // specified as integers.
155    if (MO.isImm())
156      return static_cast<uint64_t>(MO.getImm());
157    llvm_unreachable("Unexpected operand type!");
158  }
159  
160  template <SystemZ::FixupKind Kind>
getImmOpValue(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const161  uint64_t SystemZMCCodeEmitter::getImmOpValue(const MCInst &MI, unsigned OpNum,
162                                               SmallVectorImpl<MCFixup> &Fixups,
163                                               const MCSubtargetInfo &STI) const {
164    const MCOperand &MO = MI.getOperand(OpNum);
165    if (MO.isImm())
166      return static_cast<uint64_t>(MO.getImm());
167    if (MO.isExpr()) {
168      unsigned MIBitSize = MCII.get(MI.getOpcode()).getSize() * 8;
169      uint32_t RawBitOffset = getOperandBitOffset(MI, OpNum, STI);
170      unsigned OpBitSize =
171          SystemZ::MCFixupKindInfos[Kind - FirstTargetFixupKind].TargetSize;
172      uint32_t BitOffset = MIBitSize - RawBitOffset - OpBitSize;
173      Fixups.push_back(MCFixup::create(BitOffset >> 3, MO.getExpr(),
174                                       (MCFixupKind)Kind, MI.getLoc()));
175      return 0;
176    }
177    llvm_unreachable("Unexpected operand type!");
178  }
179  
180  template <SystemZ::FixupKind Kind>
181  uint64_t
getLenEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,const MCSubtargetInfo & STI) const182  SystemZMCCodeEmitter::getLenEncoding(const MCInst &MI, unsigned OpNum,
183                                       SmallVectorImpl<MCFixup> &Fixups,
184                                       const MCSubtargetInfo &STI) const {
185    return getImmOpValue<Kind>(MI, OpNum, Fixups, STI) - 1;
186  }
187  
188  uint64_t
getPCRelEncoding(const MCInst & MI,unsigned OpNum,SmallVectorImpl<MCFixup> & Fixups,unsigned Kind,int64_t Offset,bool AllowTLS) const189  SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
190                                         SmallVectorImpl<MCFixup> &Fixups,
191                                         unsigned Kind, int64_t Offset,
192                                         bool AllowTLS) const {
193    SMLoc Loc = MI.getLoc();
194    const MCOperand &MO = MI.getOperand(OpNum);
195    const MCExpr *Expr;
196    if (MO.isImm())
197      Expr = MCConstantExpr::create(MO.getImm() + Offset, Ctx);
198    else {
199      Expr = MO.getExpr();
200      if (Offset) {
201        // The operand value is relative to the start of MI, but the fixup
202        // is relative to the operand field itself, which is Offset bytes
203        // into MI.  Add Offset to the relocation value to cancel out
204        // this difference.
205        const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);
206        Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx);
207      }
208    }
209    Fixups.push_back(MCFixup::create(Offset, Expr, (MCFixupKind)Kind, Loc));
210  
211    // Output the fixup for the TLS marker if present.
212    if (AllowTLS && OpNum + 1 < MI.getNumOperands()) {
213      const MCOperand &MOTLS = MI.getOperand(OpNum + 1);
214      Fixups.push_back(MCFixup::create(
215          0, MOTLS.getExpr(), (MCFixupKind)SystemZ::FK_390_TLS_CALL, Loc));
216    }
217    return 0;
218  }
219  
220  #define GET_OPERAND_BIT_OFFSET
221  #include "SystemZGenMCCodeEmitter.inc"
222  
createSystemZMCCodeEmitter(const MCInstrInfo & MCII,MCContext & Ctx)223  MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
224                                                  MCContext &Ctx) {
225    return new SystemZMCCodeEmitter(MCII, Ctx);
226  }
227