From 6af366be8ad3199f715c54e84c779e02bb8c18b8 Mon Sep 17 00:00:00 2001 From: Tim Northover Date: Tue, 23 Apr 2019 13:50:13 +0000 Subject: [PATCH] ARM: disallow add/sub to sp unless Rn is also sp. The manual says that Thumb2 add/sub instructions are only allowed to modify sp if the first source is also sp. This is slightly different from the usual rGPR restriction since it's context-sensitive, so implement it in C++. llvm-svn: 358987 --- llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp | 14 ++++++++++ .../Target/ARM/Disassembler/ARMDisassembler.cpp | 14 +++++++++- llvm/test/MC/ARM/invalid-addsub.s | 20 ++++++++++++++ llvm/test/MC/Disassembler/ARM/invalid-thumbv7.txt | 31 ++++++++++++++++++++++ 4 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 llvm/test/MC/ARM/invalid-addsub.s diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp index 65c6a56..9bc232a 100644 --- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -6792,6 +6792,20 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst, } break; + case ARM::t2ADDri: + case ARM::t2ADDri12: + case ARM::t2ADDrr: + case ARM::t2ADDrs: + case ARM::t2SUBri: + case ARM::t2SUBri12: + case ARM::t2SUBrr: + case ARM::t2SUBrs: + if (Inst.getOperand(0).getReg() == ARM::SP && + Inst.getOperand(1).getReg() != ARM::SP) + return Error(Operands[4]->getStartLoc(), + "source register must be sp if destination is sp"); + break; + // Final range checking for Thumb unconditional branch instructions. case ARM::tB: if (!(static_cast(*Operands[2])).isSignedOffset<11, 1>()) diff --git a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp index e92bcc5..7a8d9b0 100644 --- a/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp +++ b/llvm/lib/Target/ARM/Disassembler/ARMDisassembler.cpp @@ -441,6 +441,18 @@ static DecodeStatus checkDecodedInstruction(MCInst &MI, uint64_t &Size, return MCDisassembler::SoftFail; return Result; } + case ARM::t2ADDri: + case ARM::t2ADDri12: + case ARM::t2ADDrr: + case ARM::t2ADDrs: + case ARM::t2SUBri: + case ARM::t2SUBri12: + case ARM::t2SUBrr: + case ARM::t2SUBrs: + if (MI.getOperand(0).getReg() == ARM::SP && + MI.getOperand(1).getReg() != ARM::SP) + return MCDisassembler::SoftFail; + return Result; default: return Result; } } @@ -772,7 +784,7 @@ DecodeStatus ThumbDisassembler::getInstruction(MCInst &MI, uint64_t &Size, if (Result != MCDisassembler::Fail) { Size = 4; Check(Result, AddThumbPredicate(MI)); - return Result; + return checkDecodedInstruction(MI, Size, Address, OS, CS, Insn32, Result); } if (fieldFromInstruction(Insn32, 28, 4) == 0xE) { diff --git a/llvm/test/MC/ARM/invalid-addsub.s b/llvm/test/MC/ARM/invalid-addsub.s new file mode 100644 index 0000000..07c1a80 --- /dev/null +++ b/llvm/test/MC/ARM/invalid-addsub.s @@ -0,0 +1,20 @@ +@ RUN: not llvm-mc -triple thumbv7-apple-ios %s -o - 2>&1 | FileCheck %s + +@ CHECK: error: source register must be sp if destination is sp +@ CHECK: error: source register must be sp if destination is sp +@ CHECK: error: source register must be sp if destination is sp +@ CHECK: error: source register must be sp if destination is sp +add sp, r5, #1 +addw sp, r7, #4 +add sp, r3, r2 +add sp, r3, r5, lsl #3 + + +@ CHECK: error: source register must be sp if destination is sp +@ CHECK: error: source register must be sp if destination is sp +@ CHECK: error: source register must be sp if destination is sp +@ CHECK: error: source register must be sp if destination is sp +sub sp, r5, #1 +subw sp, r7, #4 +sub sp, r3, r2 +sub sp, r3, r5, lsl #3 diff --git a/llvm/test/MC/Disassembler/ARM/invalid-thumbv7.txt b/llvm/test/MC/Disassembler/ARM/invalid-thumbv7.txt index e295ed3..48b5b8b 100644 --- a/llvm/test/MC/Disassembler/ARM/invalid-thumbv7.txt +++ b/llvm/test/MC/Disassembler/ARM/invalid-thumbv7.txt @@ -394,3 +394,34 @@ [0xff,0xf3,0x30,0x80] # CHECK: invalid instruction encoding # CHECK-NEXT: [0xff,0xf3,0x30,0x80] + +#------------------------------------------------------------------------------ +# If dest is sp then source must be in T2 add/sub +#------------------------------------------------------------------------------ + +[0x05,0xf1,0x01,0x0d] +[0x07,0xf2,0x04,0x0d] +[0x03,0xeb,0x02,0x0d] +[0x03,0xeb,0xc5,0x0d] +# CHECK-V7: warning: potentially undefined instruction encoding +# CHECK-V7-NEXT: [0x05,0xf1,0x01,0x0d] +# CHECK-V7: warning: potentially undefined instruction encoding +# CHECK-V7-NEXT: [0x07,0xf2,0x04,0x0d] +# CHECK-V7: warning: potentially undefined instruction encoding +# CHECK-V7-NEXT: [0x03,0xeb,0x02,0x0d] +# CHECK-V7: warning: potentially undefined instruction encoding +# CHECK-V7-NEXT: [0x03,0xeb,0xc5,0x0d] + + +[0xa5,0xf1,0x01,0x0d] +[0xa7,0xf2,0x04,0x0d] +[0xa3,0xeb,0x02,0x0d] +[0xa3,0xeb,0xc5,0x0d] +# CHECK-V7: warning: potentially undefined instruction encoding +# CHECK-V7-NEXT: [0xa5,0xf1,0x01,0x0d] +# CHECK-V7: warning: potentially undefined instruction encoding +# CHECK-V7-NEXT: [0xa7,0xf2,0x04,0x0d] +# CHECK-V7: warning: potentially undefined instruction encoding +# CHECK-V7-NEXT: [0xa3,0xeb,0x02,0x0d] +# CHECK-V7: warning: potentially undefined instruction encoding +# CHECK-V7-NEXT: [0xa3,0xeb,0xc5,0x0d] -- 2.7.4