Index: llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ llvm/trunk/lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -1880,6 +1880,17 @@ 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 @@ // 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 @@ const MCConstantExpr *CE = dyn_cast(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 { Index: llvm/trunk/test/MC/ARM/vmov-vmvn-illegal-cases.s =================================================================== --- llvm/trunk/test/MC/ARM/vmov-vmvn-illegal-cases.s +++ llvm/trunk/test/MC/ARM/vmov-vmvn-illegal-cases.s @@ -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