diff --git a/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp b/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp index b522939af8a..55267b06409 100644 --- a/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp +++ b/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp @@ -906,6 +906,8 @@ static DecodeStatus DecodeMoveImmInstruction(llvm::MCInst &Inst, uint32_t insn, case ARM64::MOVZWi: case ARM64::MOVNWi: case ARM64::MOVKWi: + if (shift & (1U << 5)) + return Fail; DecodeGPR32RegisterClass(Inst, Rd, Addr, Decoder); break; case ARM64::MOVZXi: @@ -1339,6 +1341,10 @@ static DecodeStatus DecodeAddSubERegInstruction(llvm::MCInst &Inst, unsigned Rm = fieldFromInstruction(insn, 16, 5); unsigned extend = fieldFromInstruction(insn, 10, 6); + unsigned shift = extend & 0x7; + if (shift > 4) + return Fail; + switch (Inst.getOpcode()) { default: return Fail; diff --git a/test/MC/Disassembler/ARM64/basic-a64-undefined.txt b/test/MC/Disassembler/ARM64/basic-a64-undefined.txt index a2b66c21faf..24be5c24dc5 100644 --- a/test/MC/Disassembler/ARM64/basic-a64-undefined.txt +++ b/test/MC/Disassembler/ARM64/basic-a64-undefined.txt @@ -2,6 +2,15 @@ # LDR/STR: undefined if option field is 10x or 00x. # RUN: echo "0x00 0x08 0x20 0xf8" | llvm-mc -triple arm64 -disassemble 2>&1 | FileCheck %s -# RUN: echo "0x00 0x88 0x00 0xf8" | llvm-mc -triple arm64 -disassemble 2>&1 | FileCheck %s +# RUN: echo "0x00 0x88 0x20 0xf8" | llvm-mc -triple arm64 -disassemble 2>&1 | FileCheck %s + +# Instructions notionally in the add/sub (extended register) sheet, but with +# invalid shift amount or "opt" field. +# RUN: echo "0x00 0x10 0xa0 0x0b" | llvm-mc -triple=arm64 -disassemble 2>&1 | FileCheck %s +# RUN: echo "0x00 0x10 0x60 0x0b" | llvm-mc -triple=arm64 -disassemble 2>&1 | FileCheck %s +# RUN: echo "0x00 0x14 0x20 0x0b" | llvm-mc -triple=arm64 -disassemble 2>&1 | FileCheck %s + +# MOVK with sf == 0 and hw<1> == 1 is unallocated. +# RUN: echo "0x00 0x00 0xc0 0x72" | llvm-mc -triple=arm64 -disassemble 2>&1 | FileCheck %s # CHECK: invalid instruction encoding