Index: lib/Target/ARM/ARMInstrNEON.td =================================================================== --- lib/Target/ARM/ARMInstrNEON.td +++ lib/Target/ARM/ARMInstrNEON.td @@ -34,6 +34,16 @@ let PrintMethod = "printNEONModImmOperand"; let ParserMatchClass = nImmSplatI32AsmOperand; } +def nImmSplatNotI16AsmOperand : AsmOperandClass { let Name = "NEONi16splatNot"; } +def nImmSplatNotI16 : Operand { + let PrintMethod = "printNEONModImmOperand"; + let ParserMatchClass = nImmSplatNotI16AsmOperand; +} +def nImmSplatNotI32AsmOperand : AsmOperandClass { let Name = "NEONi32splatNot"; } +def nImmSplatNotI32 : Operand { + let PrintMethod = "printNEONModImmOperand"; + let ParserMatchClass = nImmSplatNotI32AsmOperand; +} def nImmVMOVI32AsmOperand : AsmOperandClass { let Name = "NEONi32vmov"; } def nImmVMOVI32 : Operand { let PrintMethod = "printNEONModImmOperand"; @@ -6638,6 +6648,16 @@ (VORRd DPR:$Vdn, DPR:$Vdn, DPR:$Vm, pred:$p)>; defm : NEONDTAnyInstAlias<"vorr${p}", "$Vdn, $Vm", (VORRq QPR:$Vdn, QPR:$Vdn, QPR:$Vm, pred:$p)>; +// ... immediates +def : NEONInstAlias<"vand${p}.i16 $Vd, $imm", + (VBICiv4i16 DPR:$Vd, nImmSplatNotI16:$imm, pred:$p)>; +def : NEONInstAlias<"vand${p}.i32 $Vd, $imm", + (VBICiv2i32 DPR:$Vd, nImmSplatNotI32:$imm, pred:$p)>; +def : NEONInstAlias<"vand${p}.i16 $Vd, $imm", + (VBICiv8i16 QPR:$Vd, nImmSplatNotI16:$imm, pred:$p)>; +def : NEONInstAlias<"vand${p}.i32 $Vd, $imm", + (VBICiv4i32 QPR:$Vd, nImmSplatNotI32:$imm, pred:$p)>; + // VLD1 single-lane pseudo-instructions. These need special handling for // the lane index that an InstAlias can't handle, so we use these instead. Index: lib/Target/ARM/AsmParser/ARMAsmParser.cpp =================================================================== --- lib/Target/ARM/AsmParser/ARMAsmParser.cpp +++ lib/Target/ARM/AsmParser/ARMAsmParser.cpp @@ -1625,6 +1625,10 @@ return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00); } + bool isNEONi16splatNot() const { + return isNEONi16splat(); + } + bool isNEONi32splat() const { if (isNEONByteReplicate(4)) return false; // Leave that for bytes replication and forbid by default. @@ -1641,6 +1645,10 @@ (Value >= 0x01000000 && Value <= 0xff000000); } + bool isNEONi32splatNot() const { + return isNEONi32splat(); + } + bool isNEONByteReplicate(unsigned NumBytes) const { if (!isImm()) return false; @@ -2397,15 +2405,40 @@ Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00)); } +private: + unsigned validateNEONi16splatOperands(unsigned Value) const { + if (Value >= 256) + Value = (Value >> 8) | 0xa00; + else + Value |= 0x800; + return Value; + } + unsigned validateNEONi32splatOperands(unsigned Value) const { + if (Value >= 256 && Value <= 0xff00) + Value = (Value >> 8) | 0x200; + else if (Value > 0xffff && Value <= 0xff0000) + Value = (Value >> 16) | 0x400; + else if (Value > 0xffffff) + Value = (Value >> 24) | 0x600; + return Value; + } + +public: void addNEONi16splatOperands(MCInst &Inst, unsigned N) const { assert(N == 1 && "Invalid number of operands!"); // The immediate encodes the type of constant as well as the value. const MCConstantExpr *CE = dyn_cast(getImm()); unsigned Value = CE->getValue(); - if (Value >= 256) - Value = (Value >> 8) | 0xa00; - else - Value |= 0x800; + Value = validateNEONi16splatOperands(Value); + Inst.addOperand(MCOperand::CreateImm(Value)); + } + void addNEONi16splatNotOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + // The immediate encodes the type of constant as well as the value. + const MCConstantExpr *CE = dyn_cast(getImm()); + unsigned Value = CE->getValue(); + Value = ~Value & 0xffff; + Value = validateNEONi16splatOperands(Value); Inst.addOperand(MCOperand::CreateImm(Value)); } @@ -2414,12 +2447,16 @@ // The immediate encodes the type of constant as well as the value. const MCConstantExpr *CE = dyn_cast(getImm()); unsigned Value = CE->getValue(); - if (Value >= 256 && Value <= 0xff00) - Value = (Value >> 8) | 0x200; - else if (Value > 0xffff && Value <= 0xff0000) - Value = (Value >> 16) | 0x400; - else if (Value > 0xffffff) - Value = (Value >> 24) | 0x600; + Value = validateNEONi32splatOperands(Value); + Inst.addOperand(MCOperand::CreateImm(Value)); + } + void addNEONi32splatNotOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + // The immediate encodes the type of constant as well as the value. + const MCConstantExpr *CE = dyn_cast(getImm()); + unsigned Value = CE->getValue(); + Value = ~Value & 0xffffffff; + Value = validateNEONi32splatOperands(Value); Inst.addOperand(MCOperand::CreateImm(Value)); } Index: test/MC/ARM/neon-bitwise-encoding.s =================================================================== --- test/MC/ARM/neon-bitwise-encoding.s +++ test/MC/ARM/neon-bitwise-encoding.s @@ -41,6 +41,15 @@ @ CHECK: vbic q10, q10, q11 @ encoding: [0xf6,0x41,0x54,0xf2] @ CHECK: vbic d9, d9, d1 @ encoding: [0x11,0x91,0x19,0xf2] + vand.i16 d10, #0x03ff + vand.i32 d10, #0x03ffffff + vand.i16 q10, #0x03ff + vand.i32 q10, #0x03ffffff + +@ CHECK: vbic.i16 d10, #0xfc00 @ encoding: [0x3c,0xab,0x87,0xf3] +@ CHECK: vbic.i32 d10, #0xfc000000 @ encoding: [0x3c,0xa7,0x87,0xf3] +@ CHECK: vbic.i16 q10, #0xfc00 @ encoding: [0x7c,0x4b,0xc7,0xf3] +@ CHECK: vbic.i32 q10, #0xfc000000 @ encoding: [0x7c,0x47,0xc7,0xf3] vorn d16, d17, d16 vorn q8, q8, q9