1
0
mirror of https://github.com/RPCS3/llvm-mirror.git synced 2024-10-20 19:42:54 +02:00

[ARM] Add missing Thumb2 assembler diagnostics.

Mostly just adding checks for Thumb2 instructions which correspond to
ARM instructions which already had diagnostics. While I'm here, also fix
ARM-mode strd to check the input registers correctly.

Differential Revision: https://reviews.llvm.org/D48610

llvm-svn: 335909
This commit is contained in:
Eli Friedman 2018-06-28 19:53:12 +00:00
parent b38cbbaefd
commit 951f2d2f6e
5 changed files with 230 additions and 90 deletions

View File

@ -561,6 +561,8 @@ class ARMAsmParser : public MCTargetAsmParser {
bool shouldOmitPredicateOperand(StringRef Mnemonic, OperandVector &Operands);
bool isITBlockTerminator(MCInst &Inst) const;
void fixupGNULDRDAlias(StringRef Mnemonic, OperandVector &Operands);
bool validateLDRDSTRD(MCInst &Inst, const OperandVector &Operands,
bool Load, bool ARMMode, bool Writeback);
public:
enum ARMMatchResultTy {
@ -6302,6 +6304,65 @@ bool ARMAsmParser::validatetSTMRegList(const MCInst &Inst,
return false;
}
bool ARMAsmParser::validateLDRDSTRD(MCInst &Inst,
const OperandVector &Operands,
bool Load, bool ARMMode, bool Writeback) {
unsigned RtIndex = Load || !Writeback ? 0 : 1;
unsigned Rt = MRI->getEncodingValue(Inst.getOperand(RtIndex).getReg());
unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(RtIndex + 1).getReg());
if (ARMMode) {
// Rt can't be R14.
if (Rt == 14)
return Error(Operands[3]->getStartLoc(),
"Rt can't be R14");
// Rt must be even-numbered.
if ((Rt & 1) == 1)
return Error(Operands[3]->getStartLoc(),
"Rt must be even-numbered");
// Rt2 must be Rt + 1.
if (Rt2 != Rt + 1) {
if (Load)
return Error(Operands[3]->getStartLoc(),
"destination operands must be sequential");
else
return Error(Operands[3]->getStartLoc(),
"source operands must be sequential");
}
// FIXME: Diagnose m == 15
// FIXME: Diagnose ldrd with m == t || m == t2.
}
if (!ARMMode && Load) {
if (Rt2 == Rt)
return Error(Operands[3]->getStartLoc(),
"destination operands can't be identical");
}
if (Writeback) {
unsigned Rn = MRI->getEncodingValue(Inst.getOperand(3).getReg());
if (Rn == Rt || Rn == Rt2) {
if (Load)
return Error(Operands[3]->getStartLoc(),
"base register needs to be different from destination "
"registers");
else
return Error(Operands[3]->getStartLoc(),
"source register and base register can't be identical");
}
// FIXME: Diagnose ldrd/strd with writeback and n == 15.
// (Except the immediate form of ldrd?)
}
return false;
}
// FIXME: We would really like to be able to tablegen'erate this.
bool ARMAsmParser::validateInstruction(MCInst &Inst,
const OperandVector &Operands) {
@ -6364,50 +6425,27 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
break;
}
case ARM::LDRD:
if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/true,
/*Writeback*/false))
return true;
break;
case ARM::LDRD_PRE:
case ARM::LDRD_POST: {
const unsigned RtReg = Inst.getOperand(0).getReg();
// Rt can't be R14.
if (RtReg == ARM::LR)
return Error(Operands[3]->getStartLoc(),
"Rt can't be R14");
const unsigned Rt = MRI->getEncodingValue(RtReg);
// Rt must be even-numbered.
if ((Rt & 1) == 1)
return Error(Operands[3]->getStartLoc(),
"Rt must be even-numbered");
// Rt2 must be Rt + 1.
const unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg());
if (Rt2 != Rt + 1)
return Error(Operands[3]->getStartLoc(),
"destination operands must be sequential");
if (Opcode == ARM::LDRD_PRE || Opcode == ARM::LDRD_POST) {
const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(3).getReg());
// For addressing modes with writeback, the base register needs to be
// different from the destination registers.
if (Rn == Rt || Rn == Rt2)
return Error(Operands[3]->getStartLoc(),
"base register needs to be different from destination "
"registers");
}
return false;
}
case ARM::LDRD_POST:
if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/true,
/*Writeback*/true))
return true;
break;
case ARM::t2LDRDi8:
if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/false,
/*Writeback*/false))
return true;
break;
case ARM::t2LDRD_PRE:
case ARM::t2LDRD_POST: {
// Rt2 must be different from Rt.
unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg());
unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg());
if (Rt2 == Rt)
return Error(Operands[3]->getStartLoc(),
"destination operands can't be identical");
return false;
}
case ARM::t2LDRD_POST:
if (validateLDRDSTRD(Inst, Operands, /*Load*/true, /*ARMMode*/false,
/*Writeback*/true))
return true;
break;
case ARM::t2BXJ: {
const unsigned RmReg = Inst.getOperand(0).getReg();
// Rm = SP is no longer unpredictable in v8-A
@ -6416,35 +6454,39 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
"r13 (SP) is an unpredictable operand to BXJ");
return false;
}
case ARM::STRD: {
// Rt2 must be Rt + 1.
unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg());
unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg());
if (Rt2 != Rt + 1)
return Error(Operands[3]->getStartLoc(),
"source operands must be sequential");
return false;
}
case ARM::STRD:
if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/true,
/*Writeback*/false))
return true;
break;
case ARM::STRD_PRE:
case ARM::STRD_POST: {
// Rt2 must be Rt + 1.
unsigned Rt = MRI->getEncodingValue(Inst.getOperand(1).getReg());
unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(2).getReg());
if (Rt2 != Rt + 1)
return Error(Operands[3]->getStartLoc(),
"source operands must be sequential");
return false;
}
case ARM::STRD_POST:
if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/true,
/*Writeback*/true))
return true;
break;
case ARM::t2STRD_PRE:
case ARM::t2STRD_POST:
if (validateLDRDSTRD(Inst, Operands, /*Load*/false, /*ARMMode*/false,
/*Writeback*/true))
return true;
break;
case ARM::STR_PRE_IMM:
case ARM::STR_PRE_REG:
case ARM::t2STR_PRE:
case ARM::STR_POST_IMM:
case ARM::STR_POST_REG:
case ARM::t2STR_POST:
case ARM::STRH_PRE:
case ARM::t2STRH_PRE:
case ARM::STRH_POST:
case ARM::t2STRH_POST:
case ARM::STRB_PRE_IMM:
case ARM::STRB_PRE_REG:
case ARM::t2STRB_PRE:
case ARM::STRB_POST_IMM:
case ARM::STRB_POST_REG: {
case ARM::STRB_POST_REG:
case ARM::t2STRB_POST: {
// Rt must be different from Rn.
const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(1).getReg());
const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg());
@ -6456,18 +6498,28 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
}
case ARM::LDR_PRE_IMM:
case ARM::LDR_PRE_REG:
case ARM::t2LDR_PRE:
case ARM::LDR_POST_IMM:
case ARM::LDR_POST_REG:
case ARM::t2LDR_POST:
case ARM::LDRH_PRE:
case ARM::t2LDRH_PRE:
case ARM::LDRH_POST:
case ARM::t2LDRH_POST:
case ARM::LDRSH_PRE:
case ARM::t2LDRSH_PRE:
case ARM::LDRSH_POST:
case ARM::t2LDRSH_POST:
case ARM::LDRB_PRE_IMM:
case ARM::LDRB_PRE_REG:
case ARM::t2LDRB_PRE:
case ARM::LDRB_POST_IMM:
case ARM::LDRB_POST_REG:
case ARM::t2LDRB_POST:
case ARM::LDRSB_PRE:
case ARM::LDRSB_POST: {
case ARM::t2LDRSB_PRE:
case ARM::LDRSB_POST:
case ARM::t2LDRSB_POST: {
// Rt must be different from Rn.
const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg());
const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg());
@ -6478,7 +6530,9 @@ bool ARMAsmParser::validateInstruction(MCInst &Inst,
return false;
}
case ARM::SBFX:
case ARM::UBFX: {
case ARM::t2SBFX:
case ARM::UBFX:
case ARM::t2UBFX: {
// Width must be in range [1, 32-lsb].
unsigned LSB = Inst.getOperand(2).getImm();
unsigned Widthm1 = Inst.getOperand(3).getImm();

View File

@ -404,21 +404,21 @@ Lbaz: .quad 0
@------------------------------------------------------------------------------
@ STRD (immediate)
@------------------------------------------------------------------------------
strd r1, r2, [r4]
strd r2, r3, [r4]
strd r2, r3, [r6, #1]
strd r3, r4, [r7, #22]!
strd r0, r1, [r7, #22]!
strd r4, r5, [r8], #7
strd r5, r6, [sp], #0
strd r4, r5, [sp], #0
strd r6, r7, [lr], #+0
strd r7, r8, [r9], #-0
strd r10, r11, [r9], #-0
@ CHECK: strd r1, r2, [r4] @ encoding: [0xf0,0x10,0xc4,0xe1]
@ CHECK: strd r2, r3, [r4] @ encoding: [0xf0,0x20,0xc4,0xe1]
@ CHECK: strd r2, r3, [r6, #1] @ encoding: [0xf1,0x20,0xc6,0xe1]
@ CHECK: strd r3, r4, [r7, #22]! @ encoding: [0xf6,0x31,0xe7,0xe1]
@ CHECK: strd r0, r1, [r7, #22]! @ encoding: [0xf6,0x01,0xe7,0xe1]
@ CHECK: strd r4, r5, [r8], #7 @ encoding: [0xf7,0x40,0xc8,0xe0]
@ CHECK: strd r5, r6, [sp], #0 @ encoding: [0xf0,0x50,0xcd,0xe0]
@ CHECK: strd r4, r5, [sp], #0 @ encoding: [0xf0,0x40,0xcd,0xe0]
@ CHECK: strd r6, r7, [lr], #0 @ encoding: [0xf0,0x60,0xce,0xe0]
@ CHECK: strd r7, r8, [r9], #-0 @ encoding: [0xf0,0x70,0x49,0xe0]
@ CHECK: strd r10, r11, [r9], #-0 @ encoding: [0xf0,0xa0,0x49,0xe0]
@------------------------------------------------------------------------------
@ -429,14 +429,14 @@ Lbaz: .quad 0
@ STRD (register)
@------------------------------------------------------------------------------
strd r8, r9, [r4, r1]
strd r7, r8, [r3, r9]!
strd r6, r7, [r3, r9]!
strd r6, r7, [r5], r8
strd r5, r6, [r12], -r10
strd r4, r5, [r12], -r10
@ CHECK: strd r8, r9, [r4, r1] @ encoding: [0xf1,0x80,0x84,0xe1]
@ CHECK: strd r7, r8, [r3, r9]! @ encoding: [0xf9,0x70,0xa3,0xe1]
@ CHECK: strd r6, r7, [r3, r9]! @ encoding: [0xf9,0x60,0xa3,0xe1]
@ CHECK: strd r6, r7, [r5], r8 @ encoding: [0xf8,0x60,0x85,0xe0]
@ CHECK: strd r5, r6, [r12], -r10 @ encoding: [0xfa,0x50,0x0c,0xe0]
@ CHECK: strd r4, r5, [r12], -r10 @ encoding: [0xfa,0x40,0x0c,0xe0]
@------------------------------------------------------------------------------

View File

@ -399,10 +399,13 @@
@ CHECK-ERRORS: ubfx r14, pc, #1, #2
@ CHECK-ERRORS: ^
@ Out of order Rt/Rt2 operands for ldrd
@ Out of order Rt/Rt2 operands for ldrd/strd
ldrd r4, r3, [r8]
ldrd r4, r3, [r8, #8]!
ldrd r4, r3, [r8], #8
strd r4, r3, [r8]
strd r4, r3, [r8, #8]!
strd r4, r3, [r8], #8
@ CHECK-ERRORS: error: destination operands must be sequential
@ CHECK-ERRORS: ldrd r4, r3, [r8]
@ CHECK-ERRORS: ^
@ -411,6 +414,53 @@
@ CHECK-ERRORS: ^
@ CHECK-ERRORS: error: destination operands must be sequential
@ CHECK-ERRORS: ldrd r4, r3, [r8], #8
@ CHECK-ERRORS: ^
@ CHECK-ERRORS: error: source operands must be sequential
@ CHECK-ERRORS: strd r4, r3, [r8]
@ CHECK-ERRORS: ^
@ CHECK-ERRORS: error: source operands must be sequential
@ CHECK-ERRORS: strd r4, r3, [r8, #8]!
@ CHECK-ERRORS: ^
@ CHECK-ERRORS: error: source operands must be sequential
@ CHECK-ERRORS: strd r4, r3, [r8], #8
@ CHECK-ERRORS: ^
@ Odd first register for ldrd/strd
ldrd r5, r6, [r8]
strd r5, r6, [r8]
@ CHECK-ERRORS: error: Rt must be even-numbered
@ CHECK-ERRORS: ldrd r5, r6, [r8]
@ CHECK-ERRORS: ^
@ CHECK-ERRORS: error: Rt must be even-numbered
@ CHECK-ERRORS: strd r5, r6, [r8]
@ CHECK-ERRORS: ^
@ Post-increment with base equal to source
ldrd r6, r7, [r6]!
ldrd r6, r7, [r7]!
strd r6, r7, [r6]!
strd r6, r7, [r7]!
@ CHECK-ERRORS: error: base register needs to be different from destination registers
@ CHECK-ERRORS: ldrd r6, r7, [r6]!
@ CHECK-ERRORS: ^
@ CHECK-ERRORS: error: base register needs to be different from destination registers
@ CHECK-ERRORS: ldrd r6, r7, [r7]!
@ CHECK-ERRORS: ^
@ CHECK-ERRORS: error: source register and base register can't be identical
@ CHECK-ERRORS: strd r6, r7, [r6]!
@ CHECK-ERRORS: ^
@ CHECK-ERRORS: error: source register and base register can't be identical
@ CHECK-ERRORS: strd r6, r7, [r7]!
@ CHECK-ERRORS: ^
@ Paired load/store of pc
ldrd lr, pc, [r6]!
strd lr, pc, [r6]!
@ CHECK-ERRORS: error: Rt can't be R14
@ CHECK-ERRORS: ldrd lr, pc, [r6]!
@ CHECK-ERRORS: ^
@ CHECK-ERRORS: error: Rt can't be R14
@ CHECK-ERRORS: strd lr, pc, [r6]!
@ CHECK-ERRORS: ^

View File

@ -360,3 +360,54 @@
adds r0
@ CHECK-ERRORS: error: too few operands for instruction
@ CHECK-ERRORS: error: too few operands for instruction
@------------------------------------------------------------------------------
@ Out of range width for SBFX/UBFX
@------------------------------------------------------------------------------
sbfx r4, r5, #31, #2
ubfx r4, r5, #16, #17
@ CHECK-ERRORS-V8: error: bitfield width must be in range [1,32-lsb]
@ CHECK-ERRORS-V8: sbfx r4, r5, #31, #2
@ CHECK-ERRORS-V8: ^
@ CHECK-ERRORS-V8: error: bitfield width must be in range [1,32-lsb]
@ CHECK-ERRORS-V8: ubfx r4, r5, #16, #17
@ CHECK-ERRORS-V8: ^
@------------------------------------------------------------------------------
@ Writeback store writing to same register as value
@------------------------------------------------------------------------------
str r0, [r0, #4]!
str r0, [r0], #4
strh r0, [r0, #2]!
strh r0, [r0], #2
strb r0, [r0, #1]!
strb r0, [r0], #1
strd r0, r1, [r0], #1
strd r1, r0, [r0], #1
@ CHECK-ERRORS-V8: error: source register and base register can't be identical
@ CHECK-ERRORS-V8: str r0, [r0, #4]!
@ CHECK-ERRORS-V8: ^
@ CHECK-ERRORS-V8: error: source register and base register can't be identical
@ CHECK-ERRORS-V8: str r0, [r0], #4
@ CHECK-ERRORS-V8: ^
@ CHECK-ERRORS-V8: error: source register and base register can't be identical
@ CHECK-ERRORS-V8: strh r0, [r0, #2]!
@ CHECK-ERRORS-V8: ^
@ CHECK-ERRORS-V8: error: source register and base register can't be identical
@ CHECK-ERRORS-V8: strh r0, [r0], #2
@ CHECK-ERRORS-V8: ^
@ CHECK-ERRORS-V8: error: source register and base register can't be identical
@ CHECK-ERRORS-V8: strb r0, [r0, #1]!
@ CHECK-ERRORS-V8: ^
@ CHECK-ERRORS-V8: error: source register and base register can't be identical
@ CHECK-ERRORS-V8: strb r0, [r0], #1
@ CHECK-ERRORS-V8: ^
@ CHECK-ERRORS-V8: error: source register and base register can't be identical
@ CHECK-ERRORS-V8: strd r0, r1, [r0], #1
@ CHECK-ERRORS-V8: ^
@ CHECK-ERRORS-V8: error: source register and base register can't be identical
@ CHECK-ERRORS-V8: strd r1, r0, [r0], #1
@ CHECK-ERRORS-V8: ^

View File

@ -695,9 +695,6 @@ it ge
strexge r0, r0, [pc]
@ CHECK: [[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge
strdge r0, r0, [r0], #-0
@ CHECK: :[[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge
strdge r0, r0, [r1], #-0
@ CHECK: :[[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge
@ -743,9 +740,6 @@ it ge
strdge r0, r0, [pc], #-0
@ CHECK: :[[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge
strdge r0, r0, [r0], #0
@ CHECK: :[[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge
strdge r0, r0, [r1], #0
@ CHECK: :[[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge
@ -839,9 +833,6 @@ it ge
strdge r0, r0, [pc, #-0]
@ CHECK: :[[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge
strdge r0, r0, [r0, #-0]!
@ CHECK: :[[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge
strdge r0, r0, [r1, #-0]!
@ CHECK: :[[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge
@ -887,9 +878,6 @@ it ge
strdge r0, r0, [pc, #-0]!
@ CHECK: :[[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge
strdge r0, r0, [r0]
@ CHECK: :[[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge
strdge r0, r0, [r1]
@ CHECK: :[[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge
@ -935,9 +923,6 @@ it ge
strdge r0, r0, [pc]
@ CHECK: :[[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge
strdge r0, r0, [r0, #0]!
@ CHECK: :[[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge
strdge r0, r0, [r1, #0]!
@ CHECK: :[[@LINE+2]]:1: warning: deprecated instruction in IT block
it ge