Bug Summary

File:llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp
Warning:line 501, column 14
Value stored to 'Ext' during its initialization is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -disable-llvm-verifier -discard-value-names -main-file-name M68kDisassembler.cpp -analyzer-store=region -analyzer-opt-analyze-nested-blocks -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=cplusplus -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -mframe-pointer=none -fmath-errno -fno-rounding-math -mconstructor-aliases -munwind-tables -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -ffunction-sections -fdata-sections -fcoverage-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/M68k/Disassembler -resource-dir /usr/lib/llvm-14/lib/clang/14.0.0 -D _GNU_SOURCE -D __STDC_CONSTANT_MACROS -D __STDC_FORMAT_MACROS -D __STDC_LIMIT_MACROS -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/M68k/Disassembler -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/Target/M68k/Disassembler -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/Target/M68k -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/M68k -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/include -I /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/include -D NDEBUG -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/x86_64-linux-gnu/c++/10 -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../include/c++/10/backward -internal-isystem /usr/lib/llvm-14/lib/clang/14.0.0/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/10/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-unused-parameter -Wwrite-strings -Wno-missing-field-initializers -Wno-long-long -Wno-maybe-uninitialized -Wno-class-memaccess -Wno-redundant-move -Wno-pessimizing-move -Wno-noexcept-type -Wno-comment -std=c++14 -fdeprecated-macro -fdebug-compilation-dir=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/build-llvm/lib/Target/M68k/Disassembler -fdebug-prefix-map=/build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e=. -ferror-limit 19 -fvisibility hidden -fvisibility-inlines-hidden -stack-protector 2 -fgnuc-version=4.2.1 -vectorize-loops -vectorize-slp -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2021-09-04-040900-46481-1 -x c++ /build/llvm-toolchain-snapshot-14~++20210903100615+fd66b44ec19e/llvm/lib/Target/M68k/Disassembler/M68kDisassembler.cpp
1//===- M68kDisassembler.cpp - Disassembler for M68k -------------*- 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// This file is part of the M68k Disassembler.
10//
11//===----------------------------------------------------------------------===//
12
13#include "M68k.h"
14#include "M68kRegisterInfo.h"
15#include "M68kSubtarget.h"
16#include "MCTargetDesc/M68kMCCodeEmitter.h"
17#include "MCTargetDesc/M68kMCTargetDesc.h"
18#include "TargetInfo/M68kTargetInfo.h"
19
20#include "llvm/MC/MCAsmInfo.h"
21#include "llvm/MC/MCContext.h"
22#include "llvm/MC/MCDisassembler/MCDisassembler.h"
23#include "llvm/MC/MCInst.h"
24#include "llvm/Support/TargetRegistry.h"
25
26using namespace llvm;
27
28#define DEBUG_TYPE"m68k-disassembler" "m68k-disassembler"
29
30typedef MCDisassembler::DecodeStatus DecodeStatus;
31
32namespace {
33constexpr unsigned MaxInstructionWords = 11;
34
35class M68kInstructionBuffer {
36 typedef SmallVector<uint16_t, MaxInstructionWords> BufferType;
37 BufferType Buffer;
38
39public:
40 M68kInstructionBuffer() {}
41
42 template <typename TIt>
43 M68kInstructionBuffer(TIt Start, TIt End) : Buffer(Start, End) {}
44
45 unsigned size() const { return Buffer.size(); }
46
47 BufferType::const_iterator begin() const { return Buffer.begin(); }
48 BufferType::const_iterator end() const { return Buffer.end(); }
49
50 uint16_t operator[](unsigned Index) const {
51 assert((Index < Buffer.size()) && "tried to read out of bounds word")(static_cast<void> (0));
52 return Buffer[Index];
53 }
54
55 void truncate(unsigned NewLength) {
56 assert((NewLength <= Buffer.size()) &&(static_cast<void> (0))
57 "instruction buffer too short to truncate")(static_cast<void> (0));
58 Buffer.resize(NewLength);
59 }
60
61 void dump() const;
62
63 static M68kInstructionBuffer fill(ArrayRef<uint8_t> Bytes);
64};
65
66class M68kInstructionReader {
67 M68kInstructionBuffer Buffer;
68 unsigned NumRead;
69
70public:
71 M68kInstructionReader(M68kInstructionBuffer Buf) : Buffer(Buf), NumRead(0) {}
72
73 unsigned size() const { return (Buffer.size() * 16) - NumRead; }
74
75 uint64_t readBits(unsigned NumBits);
76};
77
78struct M68kInstructionLookup {
79 unsigned OpCode;
80 M68kInstructionBuffer Mask;
81 M68kInstructionBuffer Value;
82
83 unsigned size() const { return Mask.size(); }
84
85 // Check whether this instruction could possibly match the given bytes.
86 bool matches(const M68kInstructionBuffer &Test) const;
87 void dump() const;
88};
89
90class M68kInstructionLookupBuilder {
91 std::array<uint16_t, MaxInstructionWords> Mask;
92 std::array<uint16_t, MaxInstructionWords> Value;
93 unsigned NumWritten;
94
95public:
96 M68kInstructionLookupBuilder() : NumWritten(0) {
97 Mask.fill(0);
98 Value.fill(0);
99 }
100
101 unsigned numWords() const {
102 assert(!(NumWritten & 0xf) && "instructions must be whole words")(static_cast<void> (0));
103 return NumWritten >> 4;
104 }
105
106 bool isValid() const;
107 M68kInstructionLookup build(unsigned OpCode);
108 void addBits(unsigned N, uint64_t Bits);
109 void skipBits(unsigned N);
110};
111
112/// A disassembler class for M68k.
113class M68kDisassembler : public MCDisassembler {
114 MCInstrInfo *MCII;
115 std::vector<M68kInstructionLookup> Lookups;
116
117public:
118 M68kDisassembler(const MCSubtargetInfo &STI, MCContext &Ctx,
119 MCInstrInfo *MCII)
120 : MCDisassembler(STI, Ctx), MCII(MCII) {
121 buildBeadTable();
122 }
123 virtual ~M68kDisassembler() {}
124
125 void buildBeadTable();
126 DecodeStatus getInstruction(MCInst &Instr, uint64_t &Size,
127 ArrayRef<uint8_t> Bytes, uint64_t Address,
128 raw_ostream &CStream) const override;
129 void decodeReg(MCInst &Instr, unsigned int Bead,
130 M68kInstructionReader &Reader, unsigned &Scratch) const;
131 void decodeImm(MCInst &Instr, unsigned int Bead,
132 M68kInstructionReader &Reader, unsigned &Scratch) const;
133 unsigned int getRegOperandIndex(MCInst &Instr, unsigned int Bead) const;
134 unsigned int getImmOperandIndex(MCInst &Instr, unsigned int Bead) const;
135};
136} // namespace
137
138static unsigned RegisterDecode[] = {
139 M68k::A0, M68k::A1, M68k::A2, M68k::A3, M68k::A4, M68k::A5,
140 M68k::A6, M68k::SP, M68k::D0, M68k::D1, M68k::D2, M68k::D3,
141 M68k::D4, M68k::D5, M68k::D6, M68k::D7,
142};
143
144#if !defined(NDEBUG1) || defined(LLVM_ENABLE_DUMP)
145LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__))
146void M68kInstructionBuffer::dump() const {
147 for (auto Word : Buffer) {
148 for (unsigned B = 0; B < 16; ++B) {
149 uint16_t Bit = (1 << (16 - B - 1));
150 unsigned IsClear = !(Word & Bit);
151
152 if (B == 8)
153 dbgs() << " ";
154
155 char Ch = IsClear ? '0' : '1';
156 dbgs() << Ch;
157 }
158
159 dbgs() << " ";
160 }
161
162 dbgs() << "\n";
163}
164#endif
165
166M68kInstructionBuffer M68kInstructionBuffer::fill(ArrayRef<uint8_t> Bytes) {
167 SmallVector<uint16_t, MaxInstructionWords> Buffer;
168 Buffer.resize(std::min(Bytes.size() / 2, Buffer.max_size()));
169
170 for (unsigned I = 0, E = Buffer.size(); I < E; ++I) {
171 unsigned Offset = I * 2;
172 uint64_t Hi = Bytes[Offset];
173 uint64_t Lo = Bytes[Offset + 1];
174 uint64_t Word = (Hi << 8) | Lo;
175 Buffer[I] = Word;
176
177 LLVM_DEBUG(do { } while (false)
178 errs() << format("Read word %x (%d)\n", (unsigned)Word, Buffer.size()))do { } while (false);
179 }
180
181 return M68kInstructionBuffer(Buffer.begin(), Buffer.end());
182}
183
184uint64_t M68kInstructionReader::readBits(unsigned NumBits) {
185 assert((size() >= NumBits) && "not enough bits to read")(static_cast<void> (0));
186
187 // We have to read the bits in 16-bit chunks because we read them as
188 // 16-bit words but they're actually written in big-endian. If a read
189 // crosses a word boundary we have to be careful.
190
191 uint64_t Value = 0;
192 unsigned BitsRead = 0;
193
194 while (BitsRead < NumBits) {
195 unsigned AvailableThisWord = 16 - (NumRead & 0xf);
196 unsigned ToRead = std::min(NumBits, AvailableThisWord);
197
198 unsigned WordIndex = NumRead >> 4;
199 uint64_t ThisWord = Buffer[WordIndex] >> (NumRead & 0xf);
200 uint64_t Mask = (1 << ToRead) - 1;
201 Value |= (ThisWord & Mask) << BitsRead;
202 NumRead += ToRead;
203 BitsRead += ToRead;
204 }
205 return Value;
206}
207
208bool M68kInstructionLookup::matches(const M68kInstructionBuffer &Test) const {
209 if (Test.size() < Value.size())
210 return false;
211
212 for (unsigned I = 0, E = Value.size(); I < E; ++I) {
213 uint16_t Have = Test[I];
214 uint16_t Need = Value[I];
215 uint16_t WordMask = Mask[I];
216
217 if ((Have & WordMask) != Need)
218 return false;
219 }
220
221 return true;
222}
223
224#if !defined(NDEBUG1) || defined(LLVM_ENABLE_DUMP)
225LLVM_DUMP_METHOD__attribute__((noinline)) __attribute__((__used__))
226void M68kInstructionLookup::dump() const {
227 dbgs() << "M68kInstructionLookup " << OpCode << " ";
228
229 for (unsigned I = 0, E = Mask.size(); I < E; ++I) {
230 uint16_t WordMask = Mask[I];
231 uint16_t WordValue = Value[I];
232
233 for (unsigned B = 0; B < 16; ++B) {
234 uint16_t Bit = (1 << (15 - B));
235 unsigned IsMasked = !(WordMask & Bit);
236 unsigned IsClear = !(WordValue & Bit);
237
238 if (B == 8)
239 dbgs() << " ";
240
241 char Ch = IsMasked ? '?' : (IsClear ? '0' : '1');
242 dbgs() << Ch;
243 }
244
245 dbgs() << " ";
246 }
247
248 dbgs() << "\n";
249}
250#endif
251
252bool M68kInstructionLookupBuilder::isValid() const {
253 for (unsigned I = 0, E = numWords(); I < E; ++I)
254 if (Mask[I])
255 return true;
256
257 return false;
258}
259
260M68kInstructionLookup M68kInstructionLookupBuilder::build(unsigned OpCode) {
261 unsigned NumWords = numWords();
262 M68kInstructionBuffer MaskBuffer(Mask.begin(), Mask.begin() + NumWords);
263 M68kInstructionBuffer ValueBuffer(Value.begin(), Value.begin() + NumWords);
264 M68kInstructionLookup Ret;
265 Ret.OpCode = OpCode;
266 Ret.Mask = MaskBuffer;
267 Ret.Value = ValueBuffer;
268 return Ret;
269}
270
271void M68kInstructionLookupBuilder::addBits(unsigned N, uint64_t Bits) {
272 while (N > 0) {
273 unsigned WordIndex = NumWritten >> 4;
274 unsigned WordOffset = NumWritten & 0xf;
275 unsigned AvailableThisWord = 16 - WordOffset;
276 unsigned ToWrite = std::min(AvailableThisWord, N);
277
278 uint16_t WordMask = (1 << ToWrite) - 1;
279 uint16_t BitsToWrite = Bits & WordMask;
280
281 Value[WordIndex] |= (BitsToWrite << WordOffset);
282 Mask[WordIndex] |= (WordMask << WordOffset);
283
284 Bits >>= ToWrite;
285 N -= ToWrite;
286 NumWritten += ToWrite;
287 }
288}
289
290void M68kInstructionLookupBuilder::skipBits(unsigned N) { NumWritten += N; }
291
292// This is a bit of a hack: we can't generate this table at table-gen time
293// because some of the definitions are in our platform.
294void M68kDisassembler::buildBeadTable() {
295 const unsigned NumInstr = M68k::INSTRUCTION_LIST_END;
296 Lookups.reserve(NumInstr);
297
298 for (unsigned I = 0; I < NumInstr; ++I) {
299 M68kInstructionLookupBuilder Builder;
300
301 for (const uint8_t *PartPtr = M68k::getMCInstrBeads(I); *PartPtr;
302 ++PartPtr) {
303 uint8_t Bead = *PartPtr;
304 unsigned Ext = Bead >> 4;
305 unsigned Op = Bead & 0xf;
306
307 switch (Op) {
308 case M68kBeads::Ctrl:
309 // Term will have already been skipped by the loop.
310 assert((Ext == M68kBeads::Ignore) && "unexpected command bead")(static_cast<void> (0));
311 break;
312
313 case M68kBeads::Bits1:
314 Builder.addBits(1, Ext);
315 break;
316
317 case M68kBeads::Bits2:
318 Builder.addBits(2, Ext);
319 break;
320
321 case M68kBeads::Bits3:
322 Builder.addBits(3, Ext);
323 break;
324
325 case M68kBeads::Bits4:
326 Builder.addBits(4, Ext);
327 break;
328
329 case M68kBeads::DAReg:
330 case M68kBeads::DA:
331 case M68kBeads::DReg:
332 case M68kBeads::Reg:
333 if (Op != M68kBeads::DA)
334 Builder.skipBits(3);
335
336 if (Op != M68kBeads::Reg && Op != M68kBeads::DReg)
337 Builder.skipBits(1);
338
339 break;
340
341 case M68kBeads::Disp8:
342 Builder.skipBits(8);
343 break;
344
345 case M68kBeads::Imm8:
346 case M68kBeads::Imm16:
347 Builder.skipBits(16);
348 break;
349
350 case M68kBeads::Imm32:
351 Builder.skipBits(32);
352 break;
353
354 case M68kBeads::Imm3:
355 Builder.skipBits(3);
356 break;
357
358 default:
359 llvm_unreachable("unhandled bead type")__builtin_unreachable();
360 }
361 }
362
363 // Ignore instructions which are unmatchable (usually pseudo instructions).
364 if (!Builder.isValid())
365 continue;
366
367 Lookups.push_back(Builder.build(I));
368 }
369}
370
371unsigned M68kDisassembler::getRegOperandIndex(MCInst &Instr,
372 unsigned Bead) const {
373 unsigned Ext = Bead >> 4;
374
375 const MCInstrDesc &Desc = MCII->get(Instr.getOpcode());
376 auto MIOpIdx = M68k::getLogicalOperandIdx(Instr.getOpcode(), Ext & 7);
377
378 if (M68kII::hasMultiMIOperands(Instr.getOpcode(), Ext & 7)) {
379 bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL;
380 if (IsPCRel)
381 MIOpIdx += M68k::PCRelIndex;
382 else if (Ext & 8)
383 MIOpIdx += M68k::MemIndex;
384 else
385 MIOpIdx += M68k::MemBase;
386 }
387
388 return MIOpIdx;
389}
390
391unsigned M68kDisassembler::getImmOperandIndex(MCInst &Instr,
392 unsigned Bead) const {
393 unsigned Ext = Bead >> 4;
394
395 const MCInstrDesc &Desc = MCII->get(Instr.getOpcode());
396 auto MIOpIdx = M68k::getLogicalOperandIdx(Instr.getOpcode(), Ext & 7);
397
398 if (M68kII::hasMultiMIOperands(Instr.getOpcode(), Ext & 7)) {
399 bool IsPCRel = Desc.OpInfo[MIOpIdx].OperandType == MCOI::OPERAND_PCREL;
400 if (IsPCRel)
401 MIOpIdx += M68k::PCRelDisp;
402 else if (Ext & 8)
403 MIOpIdx += M68k::MemOuter;
404 else
405 MIOpIdx += M68k::MemDisp;
406 }
407
408 return MIOpIdx;
409}
410
411void M68kDisassembler::decodeReg(MCInst &Instr, unsigned Bead,
412 M68kInstructionReader &Reader,
413 unsigned &Scratch) const {
414 unsigned Op = Bead & 0xf;
415 LLVM_DEBUG(errs() << format("decodeReg %x\n", Bead))do { } while (false);
416
417 if (Op != M68kBeads::DA)
418 Scratch = (Scratch & ~7) | Reader.readBits(3);
419
420 if (Op != M68kBeads::Reg) {
421 bool DA = (Op != M68kBeads::DReg) && Reader.readBits(1);
422 if (!DA)
423 Scratch |= 8;
424 else
425 Scratch &= ~8;
426 }
427}
428
429void M68kDisassembler::decodeImm(MCInst &Instr, unsigned Bead,
430 M68kInstructionReader &Reader,
431 unsigned &Scratch) const {
432 unsigned Op = Bead & 0xf;
433 LLVM_DEBUG(errs() << format("decodeImm %x\n", Bead))do { } while (false);
434
435 unsigned NumToRead;
436 switch (Op) {
437 case M68kBeads::Disp8:
438 NumToRead = 8;
439 break;
440 case M68kBeads::Imm8:
441 case M68kBeads::Imm16:
442 NumToRead = 16;
443 break;
444 case M68kBeads::Imm32:
445 NumToRead = 32;
446 break;
447 case M68kBeads::Imm3:
448 NumToRead = 3;
449 break;
450 default:
451 llvm_unreachable("invalid imm")__builtin_unreachable();
452 }
453
454 Scratch = (Scratch << NumToRead) | Reader.readBits(NumToRead);
455}
456
457DecodeStatus M68kDisassembler::getInstruction(MCInst &Instr, uint64_t &Size,
458 ArrayRef<uint8_t> Bytes,
459 uint64_t Address,
460 raw_ostream &CStream) const {
461 // Read and shift the input (fetch as much as we can for now).
462 auto Buffer = M68kInstructionBuffer::fill(Bytes);
463 if (Buffer.size() == 0)
464 return Fail;
465
466 // Check through our lookup table.
467 bool Found = false;
468 for (unsigned I = 0, E = Lookups.size(); I < E; ++I) {
469 const M68kInstructionLookup &Lookup = Lookups[I];
470 if (!Lookup.matches(Buffer))
471 continue;
472
473 Found = true;
474 Size = Lookup.size() * 2;
475 Buffer.truncate(Lookup.size());
476 Instr.setOpcode(Lookup.OpCode);
477 LLVM_DEBUG(errs() << "decoding instruction " << MCII->getName(Lookup.OpCode)do { } while (false)
478 << "\n")do { } while (false);
479 break;
480 }
481
482 if (!Found)
483 return Fail;
484
485 M68kInstructionReader Reader(Buffer);
486 const MCInstrDesc &Desc = MCII->get(Instr.getOpcode());
487 unsigned NumOperands = Desc.NumOperands;
488
489 // Now use the beads to decode the operands.
490 enum class OperandType {
491 Invalid,
492 Reg,
493 Imm,
494 };
495
496 SmallVector<OperandType, 6> OpType(NumOperands, OperandType::Invalid);
497 SmallVector<unsigned, 6> Scratch(NumOperands, 0);
498 for (const uint8_t *PartPtr = M68k::getMCInstrBeads(Instr.getOpcode());
499 *PartPtr; ++PartPtr) {
500 uint8_t Bead = *PartPtr;
501 unsigned Ext = Bead >> 4;
Value stored to 'Ext' during its initialization is never read
502 unsigned Op = Bead & 0xf;
503 unsigned MIOpIdx;
504
505 switch (Op) {
506 case M68kBeads::Ctrl:
507 // Term will have already been skipped by the loop.
508 assert((Ext == M68kBeads::Ignore) && "unexpected command bead")(static_cast<void> (0));
509 break;
510
511 // These bits are constant - if we're here we've already matched them.
512 case M68kBeads::Bits1:
513 Reader.readBits(1);
514 break;
515 case M68kBeads::Bits2:
516 Reader.readBits(2);
517 break;
518 case M68kBeads::Bits3:
519 Reader.readBits(3);
520 break;
521 case M68kBeads::Bits4:
522 Reader.readBits(4);
523 break;
524
525 case M68kBeads::DAReg:
526 case M68kBeads::DA:
527 case M68kBeads::DReg:
528 case M68kBeads::Reg:
529 MIOpIdx = getRegOperandIndex(Instr, Bead);
530 assert(((OpType[MIOpIdx] == OperandType::Invalid) ||(static_cast<void> (0))
531 (OpType[MIOpIdx] == OperandType::Reg)) &&(static_cast<void> (0))
532 "operands cannot change type")(static_cast<void> (0));
533 OpType[MIOpIdx] = OperandType::Reg;
534 decodeReg(Instr, Bead, Reader, Scratch[MIOpIdx]);
535 break;
536
537 case M68kBeads::Disp8:
538 case M68kBeads::Imm8:
539 case M68kBeads::Imm16:
540 case M68kBeads::Imm32:
541 case M68kBeads::Imm3:
542 MIOpIdx = getImmOperandIndex(Instr, Bead);
543 assert(((OpType[MIOpIdx] == OperandType::Invalid) ||(static_cast<void> (0))
544 (OpType[MIOpIdx] == OperandType::Imm)) &&(static_cast<void> (0))
545 "operands cannot change type")(static_cast<void> (0));
546 OpType[MIOpIdx] = OperandType::Imm;
547 decodeImm(Instr, Bead, Reader, Scratch[MIOpIdx]);
548 break;
549
550 default:
551 llvm_unreachable("unhandled bead type")__builtin_unreachable();
552 }
553 }
554
555 // Copy constrained operands.
556 for (unsigned DstMIOpIdx = 0; DstMIOpIdx < NumOperands; ++DstMIOpIdx) {
557 int TiedTo = Desc.getOperandConstraint(DstMIOpIdx, MCOI::TIED_TO);
558 if (TiedTo < 0)
559 continue;
560
561 unsigned SrcMIOpIdx = TiedTo;
562
563 unsigned OpCount = 0;
564 for (unsigned I = 0;; ++I) {
565 unsigned Offset = M68k::getLogicalOperandIdx(Instr.getOpcode(), I);
566 assert(Offset <= SrcMIOpIdx && "missing logical operand")(static_cast<void> (0));
567 if (Offset == SrcMIOpIdx) {
568 OpCount = M68k::getLogicalOperandSize(Instr.getOpcode(), I);
569 break;
570 }
571 }
572 assert(OpCount != 0 && "operand count not found")(static_cast<void> (0));
573
574 for (unsigned I = 0; I < OpCount; ++I) {
575 assert(OpType[DstMIOpIdx + I] == OperandType::Invalid &&(static_cast<void> (0))
576 "tried to stomp over operand whilst applying constraints")(static_cast<void> (0));
577 OpType[DstMIOpIdx + I] = OpType[SrcMIOpIdx + I];
578 Scratch[DstMIOpIdx + I] = Scratch[SrcMIOpIdx + I];
579 }
580 }
581
582 // Create the operands from our scratch space.
583 for (unsigned O = 0; O < NumOperands; ++O) {
584 switch (OpType[O]) {
585 case OperandType::Invalid:
586 assert(false && "operand not parsed")(static_cast<void> (0));
587
588 case OperandType::Imm:
589 Instr.addOperand(MCOperand::createImm(Scratch[O]));
590 break;
591
592 case OperandType::Reg:
593 Instr.addOperand(MCOperand::createReg(RegisterDecode[Scratch[O]]));
594 break;
595 }
596 }
597
598 assert((Reader.size() == 0) && "wrong number of bits consumed")(static_cast<void> (0));
599 return Success;
600}
601
602static MCDisassembler *createM68kDisassembler(const Target &T,
603 const MCSubtargetInfo &STI,
604 MCContext &Ctx) {
605 return new M68kDisassembler(STI, Ctx, T.createMCInstrInfo());
606}
607
608extern "C" LLVM_EXTERNAL_VISIBILITY__attribute__ ((visibility("default"))) void LLVMInitializeM68kDisassembler() {
609 // Register the disassembler.
610 TargetRegistry::RegisterMCDisassembler(getTheM68kTarget(),
611 createM68kDisassembler);
612}