diff options
Diffstat (limited to 'lib/Target/ARM/Disassembler/ARMDisassembler.cpp')
-rw-r--r-- | lib/Target/ARM/Disassembler/ARMDisassembler.cpp | 19 |
1 files changed, 19 insertions, 0 deletions
diff --git a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index 0edb7a5d93..da5b6b86aa 100644 --- a/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -918,12 +918,31 @@ static DecodeStatus DecodeRegListOperand(llvm::MCInst &Inst, unsigned Val, uint64_t Address, const void *Decoder) { DecodeStatus S = MCDisassembler::Success; + bool writebackLoad = false; + unsigned writebackReg = 0; + switch (Inst.getOpcode()) { + default: + break; + case ARM::LDMIA_UPD: + case ARM::LDMDB_UPD: + case ARM::LDMIB_UPD: + case ARM::LDMDA_UPD: + case ARM::t2LDMIA_UPD: + case ARM::t2LDMDB_UPD: + writebackLoad = true; + writebackReg = Inst.getOperand(0).getReg(); + break; + } + // Empty register lists are not allowed. if (CountPopulation_32(Val) == 0) return MCDisassembler::Fail; for (unsigned i = 0; i < 16; ++i) { if (Val & (1 << i)) { if (!Check(S, DecodeGPRRegisterClass(Inst, i, Address, Decoder))) return MCDisassembler::Fail; + // Writeback not allowed if Rn is in the target list. + if (writebackLoad && writebackReg == Inst.end()[-1].getReg()) + Check(S, MCDisassembler::SoftFail); } } |