From 7ac29214cef4bc1952102541171488bd51f88890 Mon Sep 17 00:00:00 2001 From: Bradley Smith Date: Wed, 9 Apr 2014 14:41:38 +0000 Subject: [PATCH] [ARM64] Register-offset loads and stores with the 'option' field equal to 00x or 10x are undefined. git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@205858 91177308-0d34-0410-b5e6-96231b3b80d8 --- .../ARM64/Disassembler/ARM64Disassembler.cpp | 19 +++++-------------- .../ARM64/basic-a64-undefined.txt | 7 +++++++ 2 files changed, 12 insertions(+), 14 deletions(-) create mode 100644 test/MC/Disassembler/ARM64/basic-a64-undefined.txt diff --git a/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp b/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp index 44c501f76b3..b522939af8a 100644 --- a/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp +++ b/lib/Target/ARM64/Disassembler/ARM64Disassembler.cpp @@ -1262,70 +1262,61 @@ static DecodeStatus DecodeRegOffsetLdStInstruction(llvm::MCInst &Inst, unsigned Rm = fieldFromInstruction(insn, 16, 5); unsigned extendHi = fieldFromInstruction(insn, 13, 3); unsigned extendLo = fieldFromInstruction(insn, 12, 1); - unsigned extend = 0; + unsigned extend = (extendHi << 1) | extendLo; + + // All RO load-store instructions are undefined if option == 00x or 10x. + if (extend >> 2 == 0x0 || extend >> 2 == 0x2) + return Fail; switch (Inst.getOpcode()) { default: return Fail; case ARM64::LDRSWro: - extend = (extendHi << 1) | extendLo; DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRXro: case ARM64::STRXro: - extend = (extendHi << 1) | extendLo; DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRWro: case ARM64::STRWro: - extend = (extendHi << 1) | extendLo; DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRQro: case ARM64::STRQro: - extend = (extendHi << 1) | extendLo; DecodeFPR128RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRDro: case ARM64::STRDro: - extend = (extendHi << 1) | extendLo; DecodeFPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRSro: case ARM64::STRSro: - extend = (extendHi << 1) | extendLo; DecodeFPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRHro: - extend = (extendHi << 1) | extendLo; DecodeFPR16RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRBro: - extend = (extendHi << 1) | extendLo; DecodeFPR8RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRBBro: case ARM64::STRBBro: case ARM64::LDRSBWro: - extend = (extendHi << 1) | extendLo; DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRHHro: case ARM64::STRHHro: case ARM64::LDRSHWro: - extend = (extendHi << 1) | extendLo; DecodeGPR32RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRSHXro: - extend = (extendHi << 1) | extendLo; DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::LDRSBXro: - extend = (extendHi << 1) | extendLo; DecodeGPR64RegisterClass(Inst, Rt, Addr, Decoder); break; case ARM64::PRFMro: - extend = (extendHi << 1) | extendLo; Inst.addOperand(MCOperand::CreateImm(Rt)); } diff --git a/test/MC/Disassembler/ARM64/basic-a64-undefined.txt b/test/MC/Disassembler/ARM64/basic-a64-undefined.txt new file mode 100644 index 00000000000..a2b66c21faf --- /dev/null +++ b/test/MC/Disassembler/ARM64/basic-a64-undefined.txt @@ -0,0 +1,7 @@ +# These spawn another process so they're rather expensive. Not many. + +# 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 + +# CHECK: invalid instruction encoding