diff options
Diffstat (limited to 'llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp')
| -rw-r--r-- | llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp index 96d410e42be2..9ce00f76d9c7 100644 --- a/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ b/llvm/lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -238,6 +238,12 @@ static DecodeStatus DecodeSVEIncDecImm(MCInst &Inst, unsigned Imm, uint64_t Addr, const void *Decoder); static DecodeStatus DecodeSVCROp(MCInst &Inst, unsigned Imm, uint64_t Address, const void *Decoder); +static DecodeStatus DecodeCPYMemOpInstruction(MCInst &Inst, uint32_t insn, + uint64_t Addr, + const void *Decoder); +static DecodeStatus DecodeSETMemOpInstruction(MCInst &Inst, uint32_t insn, + uint64_t Addr, + const void *Decoder); static bool Check(DecodeStatus &Out, DecodeStatus In) { switch (In) { @@ -1842,3 +1848,52 @@ static DecodeStatus DecodeSVCROp(MCInst &Inst, unsigned Imm, uint64_t Address, } return Fail; } + +static DecodeStatus DecodeCPYMemOpInstruction(MCInst &Inst, uint32_t insn, + uint64_t Addr, + const void *Decoder) { + unsigned Rd = fieldFromInstruction(insn, 0, 5); + unsigned Rs = fieldFromInstruction(insn, 16, 5); + unsigned Rn = fieldFromInstruction(insn, 5, 5); + + // None of the registers may alias: if they do, then the instruction is not + // merely unpredictable but actually entirely unallocated. + if (Rd == Rs || Rs == Rn || Rd == Rn) + return MCDisassembler::Fail; + + // All three register operands are written back, so they all appear + // twice in the operand list, once as outputs and once as inputs. + if (!DecodeGPR64commonRegisterClass(Inst, Rd, Addr, Decoder) || + !DecodeGPR64commonRegisterClass(Inst, Rs, Addr, Decoder) || + !DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder) || + !DecodeGPR64commonRegisterClass(Inst, Rd, Addr, Decoder) || + !DecodeGPR64commonRegisterClass(Inst, Rs, Addr, Decoder) || + !DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder)) + return MCDisassembler::Fail; + + return MCDisassembler::Success; +} + +static DecodeStatus DecodeSETMemOpInstruction(MCInst &Inst, uint32_t insn, + uint64_t Addr, + const void *Decoder) { + unsigned Rd = fieldFromInstruction(insn, 0, 5); + unsigned Rm = fieldFromInstruction(insn, 16, 5); + unsigned Rn = fieldFromInstruction(insn, 5, 5); + + // None of the registers may alias: if they do, then the instruction is not + // merely unpredictable but actually entirely unallocated. + if (Rd == Rm || Rm == Rn || Rd == Rn) + return MCDisassembler::Fail; + + // Rd and Rn (not Rm) register operands are written back, so they appear + // twice in the operand list, once as outputs and once as inputs. + if (!DecodeGPR64commonRegisterClass(Inst, Rd, Addr, Decoder) || + !DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder) || + !DecodeGPR64commonRegisterClass(Inst, Rd, Addr, Decoder) || + !DecodeGPR64RegisterClass(Inst, Rn, Addr, Decoder) || + !DecodeGPR64RegisterClass(Inst, Rm, Addr, Decoder)) + return MCDisassembler::Fail; + + return MCDisassembler::Success; +} |
