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 };
117 } // end anonymous namespace
118 
119 MCCodeEmitter *llvm::createSystemZMCCodeEmitter(const MCInstrInfo &MCII,
120                                                 const MCRegisterInfo &MRI,
121                                                 MCContext &Ctx) {
122   return new SystemZMCCodeEmitter(MCII, Ctx);
123 }
124 
125 void SystemZMCCodeEmitter::
126 encodeInstruction(const MCInst &MI, raw_ostream &OS,
127                   SmallVectorImpl<MCFixup> &Fixups,
128                   const MCSubtargetInfo &STI) const {
129   uint64_t Bits = getBinaryCodeForInstr(MI, Fixups, STI);
130   unsigned Size = MCII.get(MI.getOpcode()).getSize();
131   // Big-endian insertion of Size bytes.
132   unsigned ShiftValue = (Size * 8) - 8;
133   for (unsigned I = 0; I != Size; ++I) {
134     OS << uint8_t(Bits >> ShiftValue);
135     ShiftValue -= 8;
136   }
137 }
138 
139 uint64_t SystemZMCCodeEmitter::
140 getMachineOpValue(const MCInst &MI, const MCOperand &MO,
141                   SmallVectorImpl<MCFixup> &Fixups,
142                   const MCSubtargetInfo &STI) const {
143   if (MO.isReg())
144     return Ctx.getRegisterInfo()->getEncodingValue(MO.getReg());
145   if (MO.isImm())
146     return static_cast<uint64_t>(MO.getImm());
147   llvm_unreachable("Unexpected operand type!");
148 }
149 
150 uint64_t SystemZMCCodeEmitter::
151 getBDAddr12Encoding(const MCInst &MI, unsigned OpNum,
152                     SmallVectorImpl<MCFixup> &Fixups,
153                     const MCSubtargetInfo &STI) const {
154   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
155   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
156   assert(isUInt<4>(Base) && isUInt<12>(Disp));
157   return (Base << 12) | Disp;
158 }
159 
160 uint64_t SystemZMCCodeEmitter::
161 getBDAddr20Encoding(const MCInst &MI, unsigned OpNum,
162                     SmallVectorImpl<MCFixup> &Fixups,
163                     const MCSubtargetInfo &STI) const {
164   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
165   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
166   assert(isUInt<4>(Base) && isInt<20>(Disp));
167   return (Base << 20) | ((Disp & 0xfff) << 8) | ((Disp & 0xff000) >> 12);
168 }
169 
170 uint64_t SystemZMCCodeEmitter::
171 getBDXAddr12Encoding(const MCInst &MI, unsigned OpNum,
172                      SmallVectorImpl<MCFixup> &Fixups,
173                      const MCSubtargetInfo &STI) const {
174   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
175   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
176   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
177   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Index));
178   return (Index << 16) | (Base << 12) | Disp;
179 }
180 
181 uint64_t SystemZMCCodeEmitter::
182 getBDXAddr20Encoding(const MCInst &MI, unsigned OpNum,
183                      SmallVectorImpl<MCFixup> &Fixups,
184                      const MCSubtargetInfo &STI) const {
185   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
186   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
187   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
188   assert(isUInt<4>(Base) && isInt<20>(Disp) && isUInt<4>(Index));
189   return (Index << 24) | (Base << 20) | ((Disp & 0xfff) << 8)
190     | ((Disp & 0xff000) >> 12);
191 }
192 
193 uint64_t SystemZMCCodeEmitter::
194 getBDLAddr12Len8Encoding(const MCInst &MI, unsigned OpNum,
195                          SmallVectorImpl<MCFixup> &Fixups,
196                          const MCSubtargetInfo &STI) const {
197   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
198   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
199   uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI) - 1;
200   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<8>(Len));
201   return (Len << 16) | (Base << 12) | Disp;
202 }
203 
204 uint64_t SystemZMCCodeEmitter::
205 getBDRAddr12Encoding(const MCInst &MI, unsigned OpNum,
206                      SmallVectorImpl<MCFixup> &Fixups,
207                      const MCSubtargetInfo &STI) const {
208   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
209   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
210   uint64_t Len  = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
211   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<4>(Len));
212   return (Len << 16) | (Base << 12) | Disp;
213 }
214 
215 uint64_t SystemZMCCodeEmitter::
216 getBDVAddr12Encoding(const MCInst &MI, unsigned OpNum,
217                      SmallVectorImpl<MCFixup> &Fixups,
218                      const MCSubtargetInfo &STI) const {
219   uint64_t Base = getMachineOpValue(MI, MI.getOperand(OpNum), Fixups, STI);
220   uint64_t Disp = getMachineOpValue(MI, MI.getOperand(OpNum + 1), Fixups, STI);
221   uint64_t Index = getMachineOpValue(MI, MI.getOperand(OpNum + 2), Fixups, STI);
222   assert(isUInt<4>(Base) && isUInt<12>(Disp) && isUInt<5>(Index));
223   return (Index << 16) | (Base << 12) | Disp;
224 }
225 
226 uint64_t
227 SystemZMCCodeEmitter::getPCRelEncoding(const MCInst &MI, unsigned OpNum,
228                                        SmallVectorImpl<MCFixup> &Fixups,
229                                        unsigned Kind, int64_t Offset,
230                                        bool AllowTLS) const {
231   const MCOperand &MO = MI.getOperand(OpNum);
232   const MCExpr *Expr;
233   if (MO.isImm())
234     Expr = MCConstantExpr::create(MO.getImm() + Offset, Ctx);
235   else {
236     Expr = MO.getExpr();
237     if (Offset) {
238       // The operand value is relative to the start of MI, but the fixup
239       // is relative to the operand field itself, which is Offset bytes
240       // into MI.  Add Offset to the relocation value to cancel out
241       // this difference.
242       const MCExpr *OffsetExpr = MCConstantExpr::create(Offset, Ctx);
243       Expr = MCBinaryExpr::createAdd(Expr, OffsetExpr, Ctx);
244     }
245   }
246   Fixups.push_back(MCFixup::create(Offset, Expr, (MCFixupKind)Kind));
247 
248   // Output the fixup for the TLS marker if present.
249   if (AllowTLS && OpNum + 1 < MI.getNumOperands()) {
250     const MCOperand &MOTLS = MI.getOperand(OpNum + 1);
251     Fixups.push_back(MCFixup::create(0, MOTLS.getExpr(),
252                                      (MCFixupKind)SystemZ::FK_390_TLS_CALL));
253   }
254   return 0;
255 }
256 
257 #include "SystemZGenMCCodeEmitter.inc"
258