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