mirror of
https://github.com/RPCS3/llvm-mirror.git
synced 2024-11-24 03:33:20 +01:00
[ARM] Fix a check in vmov/vmvn immediate parsing
Summary: Currently the check is incorrect and the following invalid instruction is accepted and incorrectly assembled: vmov.i32 d2, #0x00a500a6 This patch fixes the issue. Reviewers: olista01, rengolin Reviewed By: rengolin Subscribers: SjoerdMeijer, javed.absar, rogfer01, llvm-commits, kristof.beyls Differential Revision: https://reviews.llvm.org/D44460 llvm-svn: 327704
This commit is contained in:
parent
bbb9946268
commit
f11562aa0d
@ -1880,6 +1880,17 @@ public:
|
||||
bool isNEONi16ByteReplicate() const { return isNEONByteReplicate(2); }
|
||||
bool isNEONi32ByteReplicate() const { return isNEONByteReplicate(4); }
|
||||
|
||||
static bool isValidNEONi32vmovImm(int64_t Value) {
|
||||
// i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
|
||||
// for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
|
||||
return ((Value & 0xffffffffffffff00) == 0) ||
|
||||
((Value & 0xffffffffffff00ff) == 0) ||
|
||||
((Value & 0xffffffffff00ffff) == 0) ||
|
||||
((Value & 0xffffffff00ffffff) == 0) ||
|
||||
((Value & 0xffffffffffff00ff) == 0xff) ||
|
||||
((Value & 0xffffffffff00ffff) == 0xffff);
|
||||
}
|
||||
|
||||
bool isNEONi32vmov() const {
|
||||
if (isNEONByteReplicate(4))
|
||||
return false; // Let it to be classified as byte-replicate case.
|
||||
@ -1889,16 +1900,7 @@ public:
|
||||
// Must be a constant.
|
||||
if (!CE)
|
||||
return false;
|
||||
int64_t Value = CE->getValue();
|
||||
// i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
|
||||
// for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
|
||||
// FIXME: This is probably wrong and a copy and paste from previous example
|
||||
return (Value >= 0 && Value < 256) ||
|
||||
(Value >= 0x0100 && Value <= 0xff00) ||
|
||||
(Value >= 0x010000 && Value <= 0xff0000) ||
|
||||
(Value >= 0x01000000 && Value <= 0xff000000) ||
|
||||
(Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
|
||||
(Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
|
||||
return isValidNEONi32vmovImm(CE->getValue());
|
||||
}
|
||||
|
||||
bool isNEONi32vmovNeg() const {
|
||||
@ -1906,16 +1908,7 @@ public:
|
||||
const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
|
||||
// Must be a constant.
|
||||
if (!CE) return false;
|
||||
int64_t Value = ~CE->getValue();
|
||||
// i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
|
||||
// for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
|
||||
// FIXME: This is probably wrong and a copy and paste from previous example
|
||||
return (Value >= 0 && Value < 256) ||
|
||||
(Value >= 0x0100 && Value <= 0xff00) ||
|
||||
(Value >= 0x010000 && Value <= 0xff0000) ||
|
||||
(Value >= 0x01000000 && Value <= 0xff000000) ||
|
||||
(Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
|
||||
(Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
|
||||
return isValidNEONi32vmovImm(~CE->getValue());
|
||||
}
|
||||
|
||||
bool isNEONi64splat() const {
|
||||
|
@ -10,6 +10,10 @@
|
||||
@ CHECK: note: operand must be a register in range [q0, q15]
|
||||
@ CHECK: note: invalid operand for instruction
|
||||
@ CHECK: error: invalid instruction, any one of the following would fix this:
|
||||
@ CHECK-NEXT: vmov.i32 d2, #0x00a500a6
|
||||
@ CHECK: note: operand must be a register in range [d0, d31]
|
||||
@ CHECK: note: invalid operand for instruction
|
||||
@ CHECK: error: invalid instruction, any one of the following would fix this:
|
||||
@ CHECK-NEXT: vmov.i16 q2, #0xffab
|
||||
@ CHECK: note: operand must be a register in range [q0, q15]
|
||||
@ CHECK: note: invalid operand for instruction
|
||||
@ -27,6 +31,10 @@
|
||||
@ CHECK: note: operand must be a register in range [q0, q15]
|
||||
@ CHECK: note: invalid operand for instruction
|
||||
@ CHECK: error: invalid instruction, any one of the following would fix this:
|
||||
@ CHECK-NEXT: vmvn.i32 d2, #0x00a500a6
|
||||
@ CHECK: note: operand must be a register in range [d0, d31]
|
||||
@ CHECK: note: invalid operand for instruction
|
||||
@ CHECK: error: invalid instruction, any one of the following would fix this:
|
||||
@ CHECK-NEXT: vmvn.i16 q2, #0xffab
|
||||
@ CHECK: note: operand must be a register in range [q0, q15]
|
||||
@ CHECK: note: invalid operand for instruction
|
||||
@ -37,10 +45,12 @@
|
||||
|
||||
vmov.i32 d2, #0xffffffab
|
||||
vmov.i32 q2, #0xffffffab
|
||||
vmov.i32 d2, #0x00a500a6
|
||||
vmov.i16 q2, #0xffab
|
||||
vmov.i16 q2, #0xffab
|
||||
|
||||
vmvn.i32 d2, #0xffffffab
|
||||
vmvn.i32 q2, #0xffffffab
|
||||
vmvn.i32 d2, #0x00a500a6
|
||||
vmvn.i16 q2, #0xffab
|
||||
vmvn.i16 q2, #0xffab
|
||||
|
Loading…
Reference in New Issue
Block a user