File: | llvm/lib/Target/M68k/MCTargetDesc/M68kMCCodeEmitter.cpp |
Warning: | line 234, column 5 Value stored to 'NoExpr' is never read |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
1 | //===-- M68kMCCodeEmitter.cpp - Convert M68k code emitter ---*- C++ -*-===// |
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 | /// \file |
10 | /// This file contains defintions for M68k code emitter. |
11 | /// |
12 | //===----------------------------------------------------------------------===// |
13 | |
14 | #include "MCTargetDesc/M68kMCCodeEmitter.h" |
15 | #include "MCTargetDesc/M68kBaseInfo.h" |
16 | #include "MCTargetDesc/M68kFixupKinds.h" |
17 | #include "MCTargetDesc/M68kMCTargetDesc.h" |
18 | |
19 | #include "llvm/MC/MCCodeEmitter.h" |
20 | #include "llvm/MC/MCContext.h" |
21 | #include "llvm/MC/MCExpr.h" |
22 | #include "llvm/MC/MCInst.h" |
23 | #include "llvm/MC/MCInstrInfo.h" |
24 | #include "llvm/MC/MCRegisterInfo.h" |
25 | #include "llvm/MC/MCSubtargetInfo.h" |
26 | #include "llvm/MC/MCSymbol.h" |
27 | #include "llvm/Support/Debug.h" |
28 | #include "llvm/Support/EndianStream.h" |
29 | #include "llvm/Support/raw_ostream.h" |
30 | |
31 | using namespace llvm; |
32 | |
33 | #define DEBUG_TYPE"m68k-mccodeemitter" "m68k-mccodeemitter" |
34 | |
35 | namespace { |
36 | class M68kMCCodeEmitter : public MCCodeEmitter { |
37 | M68kMCCodeEmitter(const M68kMCCodeEmitter &) = delete; |
38 | void operator=(const M68kMCCodeEmitter &) = delete; |
39 | const MCInstrInfo &MCII; |
40 | MCContext &Ctx; |
41 | |
42 | public: |
43 | M68kMCCodeEmitter(const MCInstrInfo &mcii, MCContext &ctx) |
44 | : MCII(mcii), Ctx(ctx) {} |
45 | |
46 | ~M68kMCCodeEmitter() override {} |
47 | |
48 | // TableGen'erated function |
49 | const uint8_t *getGenInstrBeads(const MCInst &MI) const { |
50 | return M68k::getMCInstrBeads(MI.getOpcode()); |
51 | } |
52 | |
53 | unsigned encodeBits(unsigned ThisByte, uint8_t Bead, const MCInst &MI, |
54 | const MCInstrDesc &Desc, uint64_t &Buffer, |
55 | unsigned Offset, SmallVectorImpl<MCFixup> &Fixups, |
56 | const MCSubtargetInfo &STI) const; |
57 | |
58 | unsigned encodeReg(unsigned ThisByte, uint8_t Bead, const MCInst &MI, |
59 | const MCInstrDesc &Desc, uint64_t &Buffer, unsigned Offset, |
60 | SmallVectorImpl<MCFixup> &Fixups, |
61 | const MCSubtargetInfo &STI) const; |
62 | |
63 | unsigned encodeImm(unsigned ThisByte, uint8_t Bead, const MCInst &MI, |
64 | const MCInstrDesc &Desc, uint64_t &Buffer, unsigned Offset, |
65 | SmallVectorImpl<MCFixup> &Fixups, |
66 | const MCSubtargetInfo &STI) const; |
67 | |
68 | void encodeInstruction(const MCInst &MI, raw_ostream &OS, |
69 | SmallVectorImpl<MCFixup> &Fixups, |
70 | const MCSubtargetInfo &STI) const override; |
71 | }; |
72 | |
73 | } // end anonymous namespace |
74 | |
75 | unsigned M68kMCCodeEmitter::encodeBits(unsigned ThisByte, uint8_t Bead, |
76 | const MCInst &MI, |
77 | const MCInstrDesc &Desc, |
78 | uint64_t &Buffer, unsigned Offset, |
79 | SmallVectorImpl<MCFixup> &Fixups, |
80 | const MCSubtargetInfo &STI) const { |
81 | unsigned Num = 0; |
82 | switch (Bead & 0xF) { |
83 | case M68kBeads::Bits1: |
84 | Num = 1; |
85 | break; |
86 | case M68kBeads::Bits2: |
87 | Num = 2; |
88 | break; |
89 | case M68kBeads::Bits3: |
90 | Num = 3; |
91 | break; |
92 | case M68kBeads::Bits4: |
93 | Num = 4; |
94 | break; |
95 | } |
96 | unsigned char Val = (Bead & 0xF0) >> 4; |
97 | |
98 | LLVM_DEBUG(dbgs() << "\tEncodeBits"do { } while (false) |
99 | << " Num: " << Num << " Val: 0x")do { } while (false); |
100 | LLVM_DEBUG(dbgs().write_hex(Val) << "\n")do { } while (false); |
101 | |
102 | Buffer |= (Val << Offset); |
103 | |
104 | return Num; |
105 | } |
106 | |
107 | unsigned M68kMCCodeEmitter::encodeReg(unsigned ThisByte, uint8_t Bead, |
108 | const MCInst &MI, const MCInstrDesc &Desc, |
109 | uint64_t &Buffer, unsigned Offset, |
110 | SmallVectorImpl<MCFixup> &Fixups, |
111 | const MCSubtargetInfo &STI) const { |
112 | bool DA, Reg; |
113 | switch (Bead & 0xF) { |
114 | default: |
115 | llvm_unreachable("Unrecognized Bead code for register type")__builtin_unreachable(); |
116 | case M68kBeads::DAReg: |
117 | Reg = true; |
118 | DA = true; |
119 | break; |
120 | case M68kBeads::DA: |
121 | Reg = false; |
122 | DA = true; |
123 | break; |
124 | case M68kBeads::DReg: |
125 | case M68kBeads::Reg: |
126 | Reg = true; |
127 | DA = false; |
128 | break; |
129 | } |
130 | |
131 | unsigned Op = (Bead & 0x70) >> 4; |
132 | bool Alt = (Bead & 0x80); |
133 | LLVM_DEBUG(dbgs() << "\tEncodeReg"do { } while (false) |
134 | << " Op: " << Op << ", DA: " << DA << ", Reg: " << Regdo { } while (false) |
135 | << ", Alt: " << Alt << "\n")do { } while (false); |
136 | |
137 | auto MIOpIdx = M68k::getLogicalOperandIdx(MI.getOpcode(), Op); |
138 | bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL; |
139 | |
140 | MCOperand MCO; |
141 | if (M68kII::hasMultiMIOperands(MI.getOpcode(), Op)) { |
142 | if (IsPCRel) { |
143 | assert(Alt &&(static_cast<void> (0)) |
144 | "PCRel addresses use Alt bead register encoding by default")(static_cast<void> (0)); |
145 | MCO = MI.getOperand(MIOpIdx + M68k::PCRelIndex); |
146 | } else { |
147 | MCO = MI.getOperand(MIOpIdx + (Alt ? M68k::MemIndex : M68k::MemBase)); |
148 | } |
149 | } else { |
150 | assert(!Alt && "You cannot use Alt register with a simple operand")(static_cast<void> (0)); |
151 | MCO = MI.getOperand(MIOpIdx); |
152 | } |
153 | |
154 | unsigned RegNum = MCO.getReg(); |
155 | auto RI = Ctx.getRegisterInfo(); |
156 | |
157 | unsigned Written = 0; |
158 | if (Reg) { |
159 | uint32_t Val = RI->getEncodingValue(RegNum); |
160 | Buffer |= (Val & 7) << Offset; |
161 | Offset += 3; |
162 | Written += 3; |
163 | } |
164 | |
165 | if (DA) { |
166 | Buffer |= (uint64_t)M68kII::isAddressRegister(RegNum) << Offset; |
167 | Written++; |
168 | } |
169 | |
170 | return Written; |
171 | } |
172 | |
173 | static unsigned EmitConstant(uint64_t Val, unsigned Size, unsigned Pad, |
174 | uint64_t &Buffer, unsigned Offset) { |
175 | assert(Size + Offset <= 64 && isUIntN(Size, Val) && "Value does not fit")(static_cast<void> (0)); |
176 | |
177 | // Writing Value in host's endianness |
178 | Buffer |= (Val & ((1ULL << Size) - 1)) << Offset; |
179 | return Size + Pad; |
180 | } |
181 | |
182 | unsigned M68kMCCodeEmitter::encodeImm(unsigned ThisByte, uint8_t Bead, |
183 | const MCInst &MI, const MCInstrDesc &Desc, |
184 | uint64_t &Buffer, unsigned Offset, |
185 | SmallVectorImpl<MCFixup> &Fixups, |
186 | const MCSubtargetInfo &STI) const { |
187 | unsigned ThisWord = ThisByte / 2; |
188 | unsigned Size = 0; |
189 | unsigned Pad = 0; |
190 | unsigned FixOffset = 0; |
191 | int64_t Addendum = 0; |
192 | bool NoExpr = false; |
193 | |
194 | unsigned Type = Bead & 0xF; |
195 | unsigned Op = (Bead & 0x70) >> 4; |
196 | bool Alt = (Bead & 0x80); |
197 | |
198 | auto MIOpIdx = M68k::getLogicalOperandIdx(MI.getOpcode(), Op); |
199 | bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL; |
200 | |
201 | // The PC value upon instruction reading of a short jump will point to the |
202 | // next instruction, thus we need to compensate 2 bytes, which is the diff |
203 | // between the patch point and the PC. |
204 | if (IsPCRel && ThisWord == 0) |
205 | Addendum -= 2; |
206 | |
207 | switch (Type) { |
208 | // ??? what happens if it is not byte aligned |
209 | // ??? is it even possible |
210 | case M68kBeads::Disp8: |
211 | Size = 8; |
212 | Pad = 0; |
213 | FixOffset = ThisByte + 1; |
214 | Addendum += 1; |
215 | break; |
216 | case M68kBeads::Imm8: |
217 | Size = 8; |
218 | Pad = 8; |
219 | FixOffset = ThisByte; |
220 | break; |
221 | case M68kBeads::Imm16: |
222 | Size = 16; |
223 | Pad = 0; |
224 | FixOffset = ThisByte; |
225 | break; |
226 | case M68kBeads::Imm32: |
227 | Size = 32; |
228 | Pad = 0; |
229 | FixOffset = ThisByte; |
230 | break; |
231 | case M68kBeads::Imm3: |
232 | Size = 3; |
233 | Pad = 0; |
234 | NoExpr = true; |
Value stored to 'NoExpr' is never read | |
235 | break; |
236 | } |
237 | |
238 | LLVM_DEBUG(dbgs() << "\tEncodeImm"do { } while (false) |
239 | << " Op: " << Op << ", Size: " << Size << ", Alt: " << Altdo { } while (false) |
240 | << "\n")do { } while (false); |
241 | |
242 | MCOperand MCO; |
243 | if (M68kII::hasMultiMIOperands(MI.getOpcode(), Op)) { |
244 | |
245 | if (IsPCRel) { |
246 | assert(!Alt && "You cannot use ALT operand with PCRel")(static_cast<void> (0)); |
247 | MCO = MI.getOperand(MIOpIdx + M68k::PCRelDisp); |
248 | } else { |
249 | MCO = MI.getOperand(MIOpIdx + (Alt ? M68k::MemOuter : M68k::MemDisp)); |
250 | } |
251 | |
252 | if (MCO.isExpr()) { |
253 | assert(!NoExpr && "Cannot use expression here")(static_cast<void> (0)); |
254 | const MCExpr *Expr = MCO.getExpr(); |
255 | |
256 | // This only makes sense for PCRel instructions since PC points to the |
257 | // extension word and Disp8 for example is right justified and requires |
258 | // correction. E.g. R_68K_PC32 is calculated as S + A - P, P for Disp8 |
259 | // will be EXTENSION_WORD + 1 thus we need to have A equal to 1 to |
260 | // compensate. |
261 | // TODO count extension words |
262 | if (IsPCRel && Addendum != 0) { |
263 | Expr = MCBinaryExpr::createAdd( |
264 | Expr, MCConstantExpr::create(Addendum, Ctx), Ctx); |
265 | } |
266 | |
267 | Fixups.push_back(MCFixup::create( |
268 | FixOffset, Expr, getFixupForSize(Size, IsPCRel), MI.getLoc())); |
269 | // Write zeros |
270 | return EmitConstant(0, Size, Pad, Buffer, Offset); |
271 | } |
272 | |
273 | } else { |
274 | MCO = MI.getOperand(MIOpIdx); |
275 | if (MCO.isExpr()) { |
276 | assert(!NoExpr && "Cannot use expression here")(static_cast<void> (0)); |
277 | const MCExpr *Expr = MCO.getExpr(); |
278 | |
279 | if (Addendum != 0) { |
280 | Expr = MCBinaryExpr::createAdd( |
281 | Expr, MCConstantExpr::create(Addendum, Ctx), Ctx); |
282 | } |
283 | |
284 | Fixups.push_back(MCFixup::create( |
285 | FixOffset, Expr, getFixupForSize(Size, IsPCRel), MI.getLoc())); |
286 | // Write zeros |
287 | return EmitConstant(0, Size, Pad, Buffer, Offset); |
288 | } |
289 | } |
290 | |
291 | int64_t I = MCO.getImm(); |
292 | |
293 | // Store 8 as 0, thus making range 1-8 |
294 | if (Type == M68kBeads::Imm3 && Alt) { |
295 | assert(I && "Cannot encode Alt Imm3 zero value")(static_cast<void> (0)); |
296 | I %= 8; |
297 | } else { |
298 | assert(isIntN(Size, I))(static_cast<void> (0)); |
299 | } |
300 | |
301 | uint64_t Imm = I; |
302 | |
303 | // 32 bit Imm requires HI16 first then LO16 |
304 | if (Size == 32) { |
305 | Offset += EmitConstant((Imm >> 16) & 0xFFFF, 16, Pad, Buffer, Offset); |
306 | EmitConstant(Imm & 0xFFFF, 16, Pad, Buffer, Offset); |
307 | return Size; |
308 | } |
309 | |
310 | return EmitConstant(Imm & ((1ULL << Size) - 1), Size, Pad, Buffer, Offset); |
311 | } |
312 | |
313 | #include "M68kGenMCCodeBeads.inc" |
314 | |
315 | void M68kMCCodeEmitter::encodeInstruction(const MCInst &MI, raw_ostream &OS, |
316 | SmallVectorImpl<MCFixup> &Fixups, |
317 | const MCSubtargetInfo &STI) const { |
318 | unsigned Opcode = MI.getOpcode(); |
319 | const MCInstrDesc &Desc = MCII.get(Opcode); |
320 | |
321 | LLVM_DEBUG(dbgs() << "EncodeInstruction: " << MCII.getName(Opcode) << "("do { } while (false) |
322 | << Opcode << ")\n")do { } while (false); |
323 | |
324 | const uint8_t *Beads = getGenInstrBeads(MI); |
325 | if (!Beads || !*Beads) { |
326 | llvm_unreachable("*** Instruction does not have Beads defined")__builtin_unreachable(); |
327 | } |
328 | |
329 | uint64_t Buffer = 0; |
330 | unsigned Offset = 0; |
331 | unsigned ThisByte = 0; |
332 | |
333 | for (uint8_t Bead = *Beads; Bead; Bead = *++Beads) { |
334 | // Check for control beads |
335 | if (!(Bead & 0xF)) { |
336 | switch (Bead >> 4) { |
337 | case M68kBeads::Ignore: |
338 | continue; |
339 | } |
340 | } |
341 | |
342 | switch (Bead & 0xF) { |
343 | default: |
344 | llvm_unreachable("Unknown Bead code")__builtin_unreachable(); |
345 | break; |
346 | case M68kBeads::Bits1: |
347 | case M68kBeads::Bits2: |
348 | case M68kBeads::Bits3: |
349 | case M68kBeads::Bits4: |
350 | Offset += |
351 | encodeBits(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI); |
352 | break; |
353 | case M68kBeads::DAReg: |
354 | case M68kBeads::DA: |
355 | case M68kBeads::DReg: |
356 | case M68kBeads::Reg: |
357 | Offset += |
358 | encodeReg(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI); |
359 | break; |
360 | case M68kBeads::Disp8: |
361 | case M68kBeads::Imm8: |
362 | case M68kBeads::Imm16: |
363 | case M68kBeads::Imm32: |
364 | case M68kBeads::Imm3: |
365 | Offset += |
366 | encodeImm(ThisByte, Bead, MI, Desc, Buffer, Offset, Fixups, STI); |
367 | break; |
368 | } |
369 | |
370 | // Since M68k is Big Endian we need to rotate each instruction word |
371 | while (Offset / 16) { |
372 | support::endian::write<uint16_t>(OS, Buffer, support::big); |
373 | Buffer >>= 16; |
374 | Offset -= 16; |
375 | ThisByte += 2; |
376 | } |
377 | } |
378 | |
379 | assert(Offset == 0 && "M68k Instructions are % 2 bytes")(static_cast<void> (0)); |
380 | assert((ThisByte && !(ThisByte % 2)) && "M68k Instructions are % 2 bytes")(static_cast<void> (0)); |
381 | } |
382 | |
383 | MCCodeEmitter *llvm::createM68kMCCodeEmitter(const MCInstrInfo &MCII, |
384 | const MCRegisterInfo &MRI, |
385 | MCContext &Ctx) { |
386 | return new M68kMCCodeEmitter(MCII, Ctx); |
387 | } |