1 //===-- SystemZMCCodeEmitter.cpp - Convert SystemZ 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 SystemZMCCodeEmitter class.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "MCTargetDesc/SystemZMCTargetDesc.h"
15 #include "MCTargetDesc/SystemZMCFixups.h"
16 #include "llvm/MC/MCCodeEmitter.h"
17 #include "llvm/MC/MCContext.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCInstrInfo.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 
23 using namespace llvm;
24 
25 #define DEBUG_TYPE "mccodeemitter"
26 
27 namespace {
28 class SystemZMCCodeEmitter : public MCCodeEmitter {
29   const MCInstrInfo &MCII;
30   MCContext &Ctx;
31 
32 public:
33   SystemZMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx)
34     : MCII(mcii), Ctx(ctx) {
35   }
36 
37   ~SystemZMCCodeEmitter() override {}
38 
39   // OVerride MCCodeEmitter.
40   void encodeInstruction(const MCInst &MI, raw_ostream &OS,
41                          SmallVectorImpl<MCFixup> &Fixups,
42                          const MCSubtargetInfo &STI) const override;
43 
44 private:
45   // Automatically generated by TableGen.
46   uint64_t getBinaryCodeForInstr(const MCInst &MI,
47                                  SmallVectorImpl<MCFixup> &Fixups,
48                                  const MCSubtargetInfo &STI) const;
49 
50   // Called by the TableGen code to get the binary encoding of operand
51   // MO in MI.  Fixups is the list of fixups against MI.
52   uint64_t getMachineOpValue(const MCInst &MI, const MCOperand &MO,
53                              SmallVectorImpl<MCFixup> &Fixups,
54                              const MCSubtargetInfo &STI) const;
55 
56   // Called by the TableGen code to get the binary encoding of an address.
57   // The index or length, if any, is encoded first, followed by the base,
58   // followed by the displacement.  In a 20-bit displacement,
59   // the low 12 bits are encoded before the high 8 bits.
60   uint64_t getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
61                                SmallVectorImpl<MCFixup> &Fixups,
62                                const MCSubtargetInfo &STI) const;
63   uint64_t getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
64                                SmallVectorImpl<MCFixup> &Fixups,
65                                const MCSubtargetInfo &STI) const;
66   uint64_t getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
67                                 SmallVectorImpl<MCFixup> &Fixups,
68                                 const MCSubtargetInfo &STI) const;
69   uint64_t getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
70                                 SmallVectorImpl<MCFixup> &Fixups,
71                                 const MCSubtargetInfo &STI) const;
72   uint64_t getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
73                                     SmallVectorImpl<MCFixup> &Fixups,
74                                     const MCSubtargetInfo &STI) const;
75   uint64_t getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum,
76                                 SmallVectorImpl<MCFixup> &Fixups,
77                                 const MCSubtargetInfo &STI) const;
78   uint64_t getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
79                                 SmallVectorImpl<MCFixup> &Fixups,
80                                 const MCSubtargetInfo &STI) const;
81 
82   // Operand OpNum of MI needs a PC-relative fixup of kind Kind at
83   // Offset bytes from the start of MI.  Add the fixup to Fixups
84   // and return the in-place addend, which since we're a RELA target
85   // is always 0.  If AllowTLS is true and optional operand OpNum + 1
86   // is present, also emit a TLS call fixup for it.
87   uint64_t getPCRelEncoding(const MCInst &MI, unsigned OpNum,
88                             SmallVectorImpl<MCFixup> &Fixups,
89                             unsigned Kind, int64_t Offset,
90                             bool AllowTLS) const;
91 
92   uint64_t getPC16DBLEncoding(const MCInst &MI, unsigned OpNum,
93                               SmallVectorImpl<MCFixup> &Fixups,
94                               const MCSubtargetInfo &STI) const {
95     return getPCRelEncoding(MI, OpNum, Fixups,
96                             SystemZ::FK_390_PC16DBL, 2, false);
97   }
98   uint64_t getPC32DBLEncoding(const MCInst &MI, unsigned OpNum,
99                               SmallVectorImpl<MCFixup> &Fixups,
100                               const MCSubtargetInfo &STI) const {
101     return getPCRelEncoding(MI, OpNum, Fixups,
102                             SystemZ::FK_390_PC32DBL, 2, false);
103   }
104   uint64_t getPC16DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
105                                  SmallVectorImpl<MCFixup> &Fixups,
106                                  const MCSubtargetInfo &STI) const {
107     return getPCRelEncoding(MI, OpNum, Fixups,
108                             SystemZ::FK_390_PC16DBL, 2, true);
109   }
110   uint64_t getPC32DBLTLSEncoding(const MCInst &MI, unsigned OpNum,
111                                  SmallVectorImpl<MCFixup> &Fixups,
112                                  const MCSubtargetInfo &STI) const {
113     return getPCRelEncoding(MI, OpNum, Fixups,
114                             SystemZ::FK_390_PC32DBL, 2, true);
115   }
116   uint64_t getPC12DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
117                                  SmallVectorImpl<MCFixup> &Fixups,
118                                  const MCSubtargetInfo &STI) const {
119     return getPCRelEncoding(MI, OpNum, Fixups,
120                             SystemZ::FK_390_PC12DBL, 1, false);
121   }
122   uint64_t getPC16DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
123                                  SmallVectorImpl<MCFixup> &Fixups,
124                                  const MCSubtargetInfo &STI) const {
125     return getPCRelEncoding(MI, OpNum, Fixups,
126                             SystemZ::FK_390_PC16DBL, 4, false);
127   }
128   uint64_t getPC24DBLBPPEncoding(const MCInst &MI, unsigned OpNum,
129                                  SmallVectorImpl<MCFixup> &Fixups,
130                                  const MCSubtargetInfo &STI) const {
131     return getPCRelEncoding(MI, OpNum, Fixups,
132                             SystemZ::FK_390_PC24DBL, 3, false);
133   }
134 
135 private:
136   uint64_t computeAvailableFeatures(const FeatureBitset &FB) const;
137   void verifyInstructionPredicates(const MCInst &MI,
138                                    uint64_t AvailableFeatures) const;
139 };
140 } // end anonymous namespace
141 
142 MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
143                                                 const MCRegisterInfo &MRI,
144                                                 MCContext &Ctx) {
145   return new SystemZMCCodeEmitter(MCII, Ctx);
146 }
147 
148 void SystemZMCCodeEmitter::
149 encodeInstruction(const MCInst &MI, raw_ostream &OS,
150                   SmallVectorImpl<MCFixup> &Fixups,
151                   const MCSubtargetInfo &STI) const {
152   verifyInstructionPredicates(MI,
153                               computeAvailableFeatures(STI.getFeatureBits()));
154 
155   uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
156   unsigned Size = MCII.get(MI.getOpcode()).getSize();
157   // Big-endian insertion of Size bytes.
158   unsigned ShiftValue = (Size * 8) - 8;
159   for (unsigned I = 0; I != Size; ++I) {
160     OS << uint8_t(Bits >> ShiftValue);
161     ShiftValue -= 8;
162   }
163 }
164 
165 uint64_t SystemZMCCodeEmitter::
166 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
167                   SmallVectorImpl<MCFixup> &Fixups,
168                   const MCSubtargetInfo &STI) const {
169   if (MO.isReg())
170     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
171   if (MO.isImm())
172     return static_cast<uint64_t>(MO.getImm());
173   llvm_unreachable("Unexpected operand type!");
174 }
175 
176 uint64_t SystemZMCCodeEmitter::
177 getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
178                     SmallVectorImpl<MCFixup> &Fixups,
179                     const MCSubtargetInfo &STI) const {
180   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
181   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
182   assert(isUInt<4>(Base) && isUInt<12>(Disp));
183   return (Base << 12) | Disp;
184 }
185 
186 uint64_t SystemZMCCodeEmitter::
187 getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
188                     SmallVectorImpl<MCFixup> &Fixups,
189                     const MCSubtargetInfo &STI) const {
190   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
191   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
192   assert(isUInt<4>(Base) && isInt<20>(Disp));
193   return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12);
194 }
195 
196 uint64_t SystemZMCCodeEmitter::
197 getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
198                      SmallVectorImpl<MCFixup> &Fixups,
199                      const MCSubtargetInfo &STI) const {
200   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
201   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
202   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
203   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index));
204   return (Index << 16) | (Base << 12) | Disp;
205 }
206 
207 uint64_t SystemZMCCodeEmitter::
208 getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
209                      SmallVectorImpl<MCFixup> &Fixups,
210                      const MCSubtargetInfo &STI) const {
211   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
212   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
213   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
214   assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index));
215   return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8)
216     | ((Disp & 0xff000) >> 12);
217 }
218 
219 uint64_t SystemZMCCodeEmitter::
220 getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
221                          SmallVectorImpl<MCFixup> &Fixups,
222                          const MCSubtargetInfo &STI) const {
223   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
224   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
225   uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
226   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len));
227   return (Len << 16) | (Base << 12) | Disp;
228 }
229 
230 uint64_t SystemZMCCodeEmitter::
231 getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum,
232                      SmallVectorImpl<MCFixup> &Fixups,
233                      const MCSubtargetInfo &STI) const {
234   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
235   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
236   uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
237   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len));
238   return (Len << 16) | (Base << 12) | Disp;
239 }
240 
241 uint64_t SystemZMCCodeEmitter::
242 getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
243                      SmallVectorImpl<MCFixup> &Fixups,
244                      const MCSubtargetInfo &STI) const {
245   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
246   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
247   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
248   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<5>(Index));
249   return (Index << 16) | (Base << 12) | Disp;
250 }
251 
252 uint64_t
253 SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
254                                        SmallVectorImpl<MCFixup> &Fixups,
255                                        unsigned Kind, int64_t Offset,
256                                        bool AllowTLS) const {
257   const MCOperand &MO = MI.getOperand(OpNum);
258   const MCExpr *Expr;
259   if (MO.isImm())
260     Expr = MCConstantExpr::create(MO.getImm() + Offset, Ctx);
261   else {
262     Expr = MO.getExpr();
263     if (Offset) {
264       // The operand value is relative to the start of MI, but the fixup
265       // is relative to the operand field itself, which is Offset bytes
266       // into MI.  Add Offset to the relocation value to cancel out
267       // this difference.
268       const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);
269       Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx);
270     }
271   }
272   Fixups.push_back(MCFixup::create(Offset, Expr, (MCFixupKind)Kind));
273 
274   // Output the fixup for the TLS marker if present.
275   if (AllowTLS && OpNum + 1 < MI.getNumOperands()) {
276     const MCOperand &MOTLS = MI.getOperand(OpNum + 1);
277     Fixups.push_back(MCFixup::create(0, MOTLS.getExpr(),
278                                      (MCFixupKind)SystemZ::FK_390_TLS_CALL));
279   }
280   return 0;
281 }
282 
283 #define ENABLE_INSTR_PREDICATE_VERIFIER
284 #include "SystemZGenMCCodeEmitter.inc"
285