[ARM] Allow SP in rGPR, starting from ARMv8

Summary:
This patch handles assembly and disassembly, but not codegen, as of yet.

Additionally, it fixes a bug whereby SP and PC as shifted-reg operands
were treated as predictable in ARMv7 Thumb; and it enables the tests
for invalid and unpredictable instructions to run on both ARMv7 and ARMv8.

Reviewers: jmolloy, rengolin

Subscribers: aemerson, rengolin, llvm-commits

Differential Revision: http://reviews.llvm.org/D14141

llvm-svn: 251516
This commit is contained in:
Artyom Skrobov 2015-10-28 13:58:36 +00:00
parent 039b10423a
commit b43981076a
8 changed files with 137 additions and 67 deletions

View File

@ -343,6 +343,7 @@ public:
Match_RequiresNotITBlock,
Match_RequiresV6,
Match_RequiresThumb2,
Match_RequiresV8,
#define GET_OPERAND_DIAGNOSTIC_TYPES
#include "ARMGenAsmMatcher.inc"
@ -8529,18 +8530,29 @@ unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
inITBlock())
return Match_RequiresNotITBlock;
} else if (isThumbOne()) {
// Some high-register supporting Thumb1 encodings only allow both registers
// to be from r0-r7 when in Thumb2.
if (Opc == ARM::tADDhirr && !hasV6MOps() &&
isARMLowRegister(Inst.getOperand(1).getReg()) &&
isARMLowRegister(Inst.getOperand(2).getReg()))
return Match_RequiresThumb2;
// Others only require ARMv6 or later.
else if (Opc == ARM::tMOVr && !hasV6Ops() &&
isARMLowRegister(Inst.getOperand(0).getReg()) &&
isARMLowRegister(Inst.getOperand(1).getReg()))
return Match_RequiresV6;
}
// Some high-register supporting Thumb1 encodings only allow both registers
// to be from r0-r7 when in Thumb2.
else if (Opc == ARM::tADDhirr && isThumbOne() && !hasV6MOps() &&
isARMLowRegister(Inst.getOperand(1).getReg()) &&
isARMLowRegister(Inst.getOperand(2).getReg()))
return Match_RequiresThumb2;
// Others only require ARMv6 or later.
else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
isARMLowRegister(Inst.getOperand(0).getReg()) &&
isARMLowRegister(Inst.getOperand(1).getReg()))
return Match_RequiresV6;
for (unsigned I = 0; I < MCID.NumOperands; ++I)
if (MCID.OpInfo[I].RegClass == ARM::rGPRRegClassID) {
// rGPRRegClass excludes PC, and also excluded SP before ARMv8
if ((Inst.getOperand(I).getReg() == ARM::SP) && !hasV8Ops())
return Match_RequiresV8;
else if (Inst.getOperand(I).getReg() == ARM::PC)
return Match_InvalidOperand;
}
return Match_Success;
}
@ -8639,6 +8651,8 @@ bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
return Error(IDLoc, "instruction variant requires ARMv6 or later");
case Match_RequiresThumb2:
return Error(IDLoc, "instruction variant requires Thumb2");
case Match_RequiresV8:
return Error(IDLoc, "instruction variant requires ARMv8 or later");
case Match_ImmRange0_15: {
SMLoc ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getStartLoc();
if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
@ -9996,6 +10010,10 @@ unsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
"expression value must be representable in 32 bits");
}
break;
case MCK_rGPR:
if (hasV8Ops() && Op.isReg() && Op.getReg() == ARM::SP)
return Match_Success;
break;
case MCK_GPRPair:
if (Op.isReg() &&
MRI->getRegClass(ARM::GPRRegClassID).contains(Op.getReg()))

View File

@ -966,8 +966,13 @@ static DecodeStatus DecodetcGPRRegisterClass(MCInst &Inst, unsigned RegNo,
static DecodeStatus DecoderGPRRegisterClass(MCInst &Inst, unsigned RegNo,
uint64_t Address, const void *Decoder) {
DecodeStatus S = MCDisassembler::Success;
if (RegNo == 13 || RegNo == 15)
const FeatureBitset &featureBits =
((const MCDisassembler*)Decoder)->getSubtargetInfo().getFeatureBits();
if ((RegNo == 13 && !featureBits[ARM::HasV8Ops]) || RegNo == 15)
S = MCDisassembler::SoftFail;
Check(S, DecodeGPRRegisterClass(Inst, RegNo, Address, Decoder));
return S;
}
@ -1127,7 +1132,7 @@ static DecodeStatus DecodeSORegImmOperand(MCInst &Inst, unsigned Val,
unsigned imm = fieldFromInstruction(Val, 7, 5);
// Register-immediate
if (!Check(S, DecodeGPRRegisterClass(Inst, Rm, Address, Decoder)))
if (!Check(S, DecoderGPRRegisterClass(Inst, Rm, Address, Decoder)))
return MCDisassembler::Fail;
ARM_AM::ShiftOpc Shift = ARM_AM::lsl;

View File

@ -3,7 +3,7 @@
@ RUN: llvm-mc -triple thumbv8 -show-encoding < %s | FileCheck %s --check-prefix=CHECK-V8
@ RUN: not llvm-mc -triple thumbv7 -show-encoding < %s 2>&1 | FileCheck %s --check-prefix=CHECK-V7
@ HLT
@ HLT (in ARMv8 only)
hlt #0
hlt #63
@ CHECK-V8: hlt #0 @ encoding: [0x80,0xba]
@ -19,12 +19,23 @@
@ CHECK-V8: hlt #24 @ encoding: [0x98,0xba]
@ CHECK-V7: error: instruction requires: armv8
@ Can accept AL condition code
@ Can accept AL condition code (in ARMv8 only)
hltal #24
@ CHECK-V8: hlt #24 @ encoding: [0x98,0xba]
@ CHECK-V7: error: instruction requires: armv8
@ DCPS{1,2,3}
@ Can accept SP as rGPR (in ARMv8 only)
sbc.w r6, r3, sp, asr #16
and.w r6, r3, sp, asr #16
and sp, r0, #0
@ CHECK-V8: sbc.w r6, r3, sp, asr #16 @ encoding: [0x63,0xeb,0x2d,0x46]
@ CHECK-V8: and.w r6, r3, sp, asr #16 @ encoding: [0x03,0xea,0x2d,0x46]
@ CHECK-V8: and sp, r0, #0 @ encoding: [0x00,0xf0,0x00,0x0d]
@ CHECK-V7: error: instruction variant requires ARMv8 or later
@ CHECK-V7: error: instruction variant requires ARMv8 or later
@ CHECK-V7: error: invalid operand for instruction
@ DCPS{1,2,3} (in ARMv8 only)
dcps1
dcps2
dcps3
@ -36,7 +47,7 @@
@ CHECK-V7: error: instruction requires: armv8
@------------------------------------------------------------------------------
@ DMB (v8 barriers)
@ DMB (ARMv8-only barriers)
@------------------------------------------------------------------------------
dmb ishld
dmb oshld
@ -53,7 +64,7 @@
@ CHECK-V7: error: invalid operand for instruction
@------------------------------------------------------------------------------
@ DSB (v8 barriers)
@ DSB (ARMv8-only barriers)
@------------------------------------------------------------------------------
dsb ishld
dsb oshld
@ -70,7 +81,7 @@
@ CHECK-V7: error: invalid operand for instruction
@------------------------------------------------------------------------------
@ SEVL
@ SEVL (in ARMv8 only)
@------------------------------------------------------------------------------
sevl
sevl.w

View File

@ -1,7 +1,7 @@
@ RUN: not llvm-mc -triple=armv7-apple-darwin < %s 2> %t
@ RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
@ RUN: FileCheck --check-prefix=CHECK-ERRORS --check-prefix=CHECK-ERRORS-V7 < %t %s
@ RUN: not llvm-mc -triple=armv8 < %s 2> %t
@ RUN: FileCheck --check-prefix=CHECK-ERRORS-V8 < %t %s
@ RUN: FileCheck --check-prefix=CHECK-ERRORS --check-prefix=CHECK-ERRORS-V8 < %t %s
@ Check for various assembly diagnostic messages on invalid input.
@ -98,22 +98,22 @@
@ Out of range immediates for v8 HLT instruction.
hlt #65536
hlt #-1
@CHECK-ERRORS-V8: error: invalid operand for instruction
@CHECK-ERRORS-V8: hlt #65536
@CHECK-ERRORS-V8: ^
@CHECK-ERRORS-V8: error: invalid operand for instruction
@CHECK-ERRORS-V8: hlt #-1
@CHECK-ERRORS-V8: ^
@CHECK-ERRORS: error: invalid operand for instruction
@CHECK-ERRORS: hlt #65536
@CHECK-ERRORS: ^
@CHECK-ERRORS: error: invalid operand for instruction
@CHECK-ERRORS: hlt #-1
@CHECK-ERRORS: ^
@ Illegal condition code for v8 HLT instruction.
hlteq #2
hltlt #23
@CHECK-ERRORS-V8: error: instruction 'hlt' is not predicable, but condition code specified
@CHECK-ERRORS-V8: hlteq #2
@CHECK-ERRORS-V8: ^
@CHECK-ERRORS-V8: error: instruction 'hlt' is not predicable, but condition code specified
@CHECK-ERRORS-V8: hltlt #23
@CHECK-ERRORS-V8: ^
@CHECK-ERRORS: error: instruction 'hlt' is not predicable, but condition code specified
@CHECK-ERRORS: hlteq #2
@CHECK-ERRORS: ^
@CHECK-ERRORS: error: instruction 'hlt' is not predicable, but condition code specified
@CHECK-ERRORS: hltlt #23
@CHECK-ERRORS: ^
@ Out of range 4 and 3 bit immediates on CDP[2]
@ -149,7 +149,8 @@
@ CHECK-ERRORS: error: invalid operand for instruction
@ CHECK-ERRORS: error: invalid operand for instruction
@ CHECK-ERRORS: error: immediate operand must be in the range [0,15]
@ CHECK-ERRORS: error: immediate operand must be in the range [0,15]
@ CHECK-ERRORS-V7: error: immediate operand must be in the range [0,15]
@ CHECK-ERRORS-V8: error: invalid operand for instruction
@ p10 and p11 are reserved for NEON
mcr p10, #2, r5, c1, c1, #4
@ -183,7 +184,8 @@
@ CHECK-ERRORS: error: invalid operand for instruction
@ CHECK-ERRORS: error: invalid operand for instruction
@ CHECK-ERRORS: error: immediate operand must be in the range [0,15]
@ CHECK-ERRORS: error: immediate operand must be in the range [0,15]
@ CHECK-ERRORS-V7: error: immediate operand must be in the range [0,15]
@ CHECK-ERRORS-V8: error: invalid operand for instruction
@ Shifter operand validation for PKH instructions.
pkhbt r2, r2, r3, lsl #-1
@ -394,12 +396,14 @@
ldc2 p2, c8, [r1], { 256 }
ldc2 p2, c8, [r1], { -1 }
@ CHECK-ERRORS: error: coprocessor option must be an immediate in range [0, 255]
@ CHECK-ERRORS: ldc2 p2, c8, [r1], { 256 }
@ CHECK-ERRORS: ^
@ CHECK-ERRORS: error: coprocessor option must be an immediate in range [0, 255]
@ CHECK-ERRORS: ldc2 p2, c8, [r1], { -1 }
@ CHECK-ERRORS: ^
@ CHECK-ERRORS-V7: error: coprocessor option must be an immediate in range [0, 255]
@ CHECK-ERRORS-V7: ldc2 p2, c8, [r1], { 256 }
@ CHECK-ERRORS-V7: ^
@ CHECK-ERRORS-V8: error: register expected
@ CHECK-ERRORS-V7: error: coprocessor option must be an immediate in range [0, 255]
@ CHECK-ERRORS-V7: ldc2 p2, c8, [r1], { -1 }
@ CHECK-ERRORS-V7: ^
@ CHECK-ERRORS-V8: error: register expected
@ Bad CPS instruction format.
cps f,#1
@ -470,14 +474,14 @@
vrintn.f32 s8, s9
vrintp.f64.f64 d10, d11
vrintm.f64 d12, d13
@ CHECK-ERRORS: error: instruction requires: FPARMv8
@ CHECK-ERRORS: error: instruction requires: FPARMv8
@ CHECK-ERRORS: error: instruction requires: FPARMv8
@ CHECK-ERRORS: error: instruction requires: FPARMv8
@ CHECK-ERRORS: error: instruction requires: FPARMv8
@ CHECK-ERRORS: error: instruction requires: FPARMv8
@ CHECK-ERRORS: error: instruction requires: FPARMv8
@ CHECK-ERRORS: error: instruction requires: FPARMv8
@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
@ CHECK-ERRORS-V7: error: instruction requires: FPARMv8
stm sp!, {r0, pc}^
ldm sp!, {r0}^

View File

@ -6,40 +6,40 @@
sbc.w r12, lr, r0
sbc.w r1, r8, r9, lsr #32
sbc.w r2, r7, pc, lsr #16
sbc.w r2, r7, r10, lsr #16
sbc.w r3, r6, r10, lsl #0
sbc.w r4, r5, lr, lsl #16
sbc.w r5, r4, r11, asr #32
sbc.w r6, r3, sp, asr #16
sbc.w r6, r3, r12, asr #16
sbc.w r7, r2, r12, rrx
sbc.w r8, r1, r0, ror #16
@ CHECK: sbc.w r12, lr, r0 @ encoding: [0x6e,0xeb,0x00,0x0c]
@ CHECK: sbc.w r1, r8, r9, lsr #32 @ encoding: [0x68,0xeb,0x19,0x01]
@ CHECK: sbc.w r2, r7, pc, lsr #16 @ encoding: [0x67,0xeb,0x1f,0x42]
@ CHECK: sbc.w r2, r7, r10, lsr #16 @ encoding: [0x67,0xeb,0x1a,0x42]
@ CHECK: sbc.w r3, r6, r10 @ encoding: [0x66,0xeb,0x0a,0x03]
@ CHECK: sbc.w r4, r5, lr, lsl #16 @ encoding: [0x65,0xeb,0x0e,0x44]
@ CHECK: sbc.w r5, r4, r11, asr #32 @ encoding: [0x64,0xeb,0x2b,0x05]
@ CHECK: sbc.w r6, r3, sp, asr #16 @ encoding: [0x63,0xeb,0x2d,0x46]
@ CHECK: sbc.w r6, r3, r12, asr #16 @ encoding: [0x63,0xeb,0x2c,0x46]
@ CHECK: sbc.w r7, r2, r12, rrx @ encoding: [0x62,0xeb,0x3c,0x07]
@ CHECK: sbc.w r8, r1, r0, ror #16 @ encoding: [0x61,0xeb,0x30,0x48]
and.w r12, lr, r0
and.w r1, r8, r9, lsr #32
and.w r2, r7, pc, lsr #16
and.w r2, r7, r10, lsr #16
and.w r3, r6, r10, lsl #0
and.w r4, r5, lr, lsl #16
and.w r5, r4, r11, asr #32
and.w r6, r3, sp, asr #16
and.w r6, r3, r12, asr #16
and.w r7, r2, r12, rrx
and.w r8, r1, r0, ror #16
@ CHECK: and.w r12, lr, r0 @ encoding: [0x0e,0xea,0x00,0x0c]
@ CHECK: and.w r1, r8, r9, lsr #32 @ encoding: [0x08,0xea,0x19,0x01]
@ CHECK: and.w r2, r7, pc, lsr #16 @ encoding: [0x07,0xea,0x1f,0x42]
@ CHECK: and.w r2, r7, r10, lsr #16 @ encoding: [0x07,0xea,0x1a,0x42]
@ CHECK: and.w r3, r6, r10 @ encoding: [0x06,0xea,0x0a,0x03]
@ CHECK: and.w r4, r5, lr, lsl #16 @ encoding: [0x05,0xea,0x0e,0x44]
@ CHECK: and.w r5, r4, r11, asr #32 @ encoding: [0x04,0xea,0x2b,0x05]
@ CHECK: and.w r6, r3, sp, asr #16 @ encoding: [0x03,0xea,0x2d,0x46]
@ CHECK: and.w r6, r3, r12, asr #16 @ encoding: [0x03,0xea,0x2c,0x46]
@ CHECK: and.w r7, r2, r12, rrx @ encoding: [0x02,0xea,0x3c,0x07]
@ CHECK: and.w r8, r1, r0, ror #16 @ encoding: [0x01,0xea,0x30,0x48]

View File

@ -1,5 +1,8 @@
@ RUN: not llvm-mc -triple=thumbv7-apple-darwin < %s 2> %t
@ RUN: FileCheck --check-prefix=CHECK-ERRORS < %t %s
@ RUN: FileCheck --check-prefix=CHECK-ERRORS --check-prefix=CHECK-ERRORS-V7 < %t %s
@ RUN: not llvm-mc -triple=thumbv8-apple-darwin < %s 2> %t
@ RUN: FileCheck --check-prefix=CHECK-ERRORS --check-prefix=CHECK-ERRORS-V8 < %t %s
@ Ill-formed IT block instructions.
itet eq
@ -41,7 +44,8 @@
@ CHECK-ERRORS: error: invalid operand for instruction
@ CHECK-ERRORS: error: invalid operand for instruction
@ CHECK-ERRORS: error: immediate operand must be in the range [0,15]
@ CHECK-ERRORS: error: immediate operand must be in the range [0,15]
@ CHECK-ERRORS-V7: error: immediate operand must be in the range [0,15]
@ CHECK-ERRORS-V8: error: invalid operand for instruction
isb #-1
isb #16
@ -87,7 +91,14 @@ foo2:
@ CHECK-ERRORS: error: invalid operand for instruction
@ CHECK-ERRORS: error: invalid operand for instruction
ssat r0, #1, r0, asr #32
usat r0, #1, r0, asr #32
ssat r0, #1, r0, asr #32
usat r0, #1, r0, asr #32
@ CHECK-ERRORS: error: 'asr #32' shift amount not allowed in Thumb mode
@ CHECK-ERRORS: error: 'asr #32' shift amount not allowed in Thumb mode
@ PC is not valid as shifted-rGPR
sbc.w r2, r7, pc, lsr #16
and.w r2, r7, pc, lsr #16
@ CHECK-ERRORS: error: invalid operand for instruction
@ CHECK-ERRORS: error: invalid operand for instruction

View File

@ -1,4 +1,5 @@
# RUN: not llvm-mc -disassemble %s -mcpu cortex-a8 -triple thumbv7 2>&1 | FileCheck %s
# RUN: not llvm-mc -disassemble %s -mcpu cortex-a8 -triple thumbv7 2>&1 | FileCheck %s --check-prefix=CHECK --check-prefix=CHECK-V7
# RUN: not llvm-mc -disassemble %s -mcpu cortex-a53 -triple thumbv8 2>&1 | FileCheck %s
# This file is checking Thumbv7 encodings which are globally invalid, usually due
# to the constraints of the instructions not being met. For example invalid
@ -359,10 +360,22 @@
# 32-bit Thumb STM instructions cannot have a writeback register which appears
# in the list.
[0xa1,0xe8,0x07,0x04]
[0xa1 0xe8 0x07 0x04]
# CHECK: warning: potentially undefined instruction encoding
# CHECK-NEXT: [0xa1,0xe8,0x07,0x04]
# CHECK-NEXT: [0xa1 0xe8 0x07 0x04]
[0x21,0xe9,0x07,0x04]
[0x21 0xe9 0x07 0x04]
# CHECK: warning: potentially undefined instruction encoding
# CHECK-NEXT: [0x21,0xe9,0x07,0x04]
# CHECK-NEXT: [0x21 0xe9 0x07 0x04]
#------------------------------------------------------------------------------
# SP is invalid as rGPR before ARMv8
#------------------------------------------------------------------------------
[0x00 0xf0 0x00 0x0d]
# CHECK-V7: warning: potentially undefined instruction encoding
# CHECK-V7-NEXT: [0x00 0xf0 0x00 0x0d]
[0x63 0xeb 0x2d 0x46]
# CHECK-V7: warning: potentially undefined instruction encoding
# CHECK-V7-NEXT: [0x63 0xeb 0x2d 0x46]

View File

@ -1,4 +1,5 @@
# RUN: llvm-mc -disassemble -triple thumbv8 -mattr=+db -show-encoding < %s | FileCheck %s
# RUN: llvm-mc -disassemble -triple thumbv8 -mattr=+db -show-encoding 2>%t < %s | FileCheck %s
# RUN: FileCheck -allow-empty -check-prefix=STDERR < %t %s
0x80 0xba
# CHECK: hlt #0
@ -26,3 +27,10 @@
# CHECK: dmb oshld
# CHECK: dmb nshld
# CHECK: dmb ld
[0x00 0xf0 0x00 0x0d]
[0x63 0xeb 0x2d 0x46]
# CHECK: and sp, r0, #0
# CHECK: sbc.w r6, r3, sp, asr #16
# STDERR-NOT: warning