Index: lib/Target/AArch64/AArch64InstrFormats.td =================================================================== --- lib/Target/AArch64/AArch64InstrFormats.td +++ lib/Target/AArch64/AArch64InstrFormats.td @@ -9224,6 +9224,231 @@ } // let Predicates = [HasNeon, HasRDM] //---------------------------------------------------------------------------- +// ARMv8.3 Complex ADD/MLA instructions +//---------------------------------------------------------------------------- + +def ComplexRotationOperand : AsmOperandClass { + let Name = "ComplexRotation"; + let DiagnosticType = "InvalidComplexRotation"; +} +def complexrotateop : Operand { + let ParserMatchClass = ComplexRotationOperand; + let PrintMethod = "printComplexRotationOp"; +} +def ComplexRotationOddOperand : AsmOperandClass { + let Name = "ComplexRotationOdd"; + let DiagnosticType = "InvalidComplexRotationOdd"; + let SuperClasses = [ComplexRotationOperand]; +} +def complexrotateopodd : Operand { + let ParserMatchClass = ComplexRotationOddOperand; + let PrintMethod = "printComplexRotationOpOdd"; +} + +let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in +class BaseSIMDThreeSameVectorComplex size, bits<3> opcode, + RegisterOperand regtype, Operand rottype, + string asm, string kind, + list pattern> + : I<(outs regtype:$Rd), (ins regtype:$Rn, regtype:$Rm, rottype:$rot), asm, + "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot" + "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "", pattern>, + Sched<[WriteV]> { + bits<5> Rd; + bits<5> Rn; + bits<5> Rm; + bits<1> rot; + let Inst{31} = 0; + let Inst{30} = Q; + let Inst{29} = U; + let Inst{28-24} = 0b01110; + let Inst{23-22} = size; + let Inst{21} = 0; + let Inst{20-16} = Rm; + let Inst{15-13} = opcode; + // Non-tied version (FCADD) only has one rotation bit + let Inst{12} = rot; + let Inst{11} = 0; + let Inst{10} = 1; + let Inst{9-5} = Rn; + let Inst{4-0} = Rd; +} + +multiclass SIMDThreeSameVectorComplexHSD opcode, Operand rottype, + string asm, SDPatternOperator OpNode> { + let Predicates = [HasV8_3a,HasNEON,HasFullFP16] in { + def v4f16 : BaseSIMDThreeSameVectorComplex<0, U, 0b01, opcode, V64, rottype, + asm, ".4h", + [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), + (v4f16 V64:$Rm), (rottype i32:$rot)))]>; + + def v8f16 : BaseSIMDThreeSameVectorComplex<1, U, 0b01, opcode, V128, rottype, + asm, ".8h", + [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd), + (v8f16 V128:$Rn), (v8f16 V128:$Rm), + (rottype i32:$rot)))]>; + } + + let Predicates = [HasV8_3a,HasNEON] in { + def v2f32 : BaseSIMDThreeSameVectorComplex<0, U, 0b10, opcode, V64, rottype, + asm, ".2s", + [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), + (v2f32 V64:$Rm), (rottype i32:$rot)))]>; + + def v4f32 : BaseSIMDThreeSameVectorComplex<1, U, 0b10, opcode, V128, rottype, + asm, ".4s", + [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd), + (v4f32 V128:$Rn), (v4f32 V128:$Rm), + (rottype i32:$rot)))]>; + + def v2f64 : BaseSIMDThreeSameVectorComplex<1, U, 0b11, opcode, V128, rottype, + asm, ".2d", + [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd), + (v2f64 V128:$Rn), (v2f64 V128:$Rm), + (rottype i32:$rot)))]>; + } +} + +let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in +class BaseSIMDThreeSameVectorTiedComplex size, + bits<3> opcode, + RegisterOperand regtype, + Operand rottype, string asm, + string kind, list pattern> + : I<(outs regtype:$dst), + (ins regtype:$Rd, regtype:$Rn, regtype:$Rm, rottype:$rot), asm, + "{\t$Rd" # kind # ", $Rn" # kind # ", $Rm" # kind # ", $rot" + "|" # kind # "\t$Rd, $Rn, $Rm, $rot}", "$Rd = $dst", pattern>, + Sched<[WriteV]> { + bits<5> Rd; + bits<5> Rn; + bits<5> Rm; + bits<2> rot; + let Inst{31} = 0; + let Inst{30} = Q; + let Inst{29} = U; + let Inst{28-24} = 0b01110; + let Inst{23-22} = size; + let Inst{21} = 0; + let Inst{20-16} = Rm; + let Inst{15-13} = opcode; + let Inst{12-11} = rot; + let Inst{10} = 1; + let Inst{9-5} = Rn; + let Inst{4-0} = Rd; +} + +multiclass SIMDThreeSameVectorTiedComplexHSD opcode, + Operand rottype, string asm, + SDPatternOperator OpNode> { + let Predicates = [HasV8_3a,HasNEON,HasFullFP16] in { + def v4f16 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b01, opcode, V64, + rottype, asm, ".4h", + [(set (v4f16 V64:$dst), (OpNode (v4f16 V64:$Rd), (v4f16 V64:$Rn), + (v4f16 V64:$Rm), (rottype i32:$rot)))]>; + + def v8f16 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b01, opcode, V128, + rottype, asm, ".8h", + [(set (v8f16 V128:$dst), (OpNode (v8f16 V128:$Rd), + (v8f16 V128:$Rn), (v8f16 V128:$Rm), + (rottype i32:$rot)))]>; + } + + let Predicates = [HasV8_3a,HasNEON] in { + def v2f32 : BaseSIMDThreeSameVectorTiedComplex<0, U, 0b10, opcode, V64, + rottype, asm, ".2s", + [(set (v2f32 V64:$dst), (OpNode (v2f32 V64:$Rd), (v2f32 V64:$Rn), + (v2f32 V64:$Rm), (rottype i32:$rot)))]>; + + def v4f32 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b10, opcode, V128, + rottype, asm, ".4s", + [(set (v4f32 V128:$dst), (OpNode (v4f32 V128:$Rd), + (v4f32 V128:$Rn), (v4f32 V128:$Rm), + (rottype i32:$rot)))]>; + + def v2f64 : BaseSIMDThreeSameVectorTiedComplex<1, U, 0b11, opcode, V128, + rottype, asm, ".2d", + [(set (v2f64 V128:$dst), (OpNode (v2f64 V128:$Rd), + (v2f64 V128:$Rn), (v2f64 V128:$Rm), + (rottype i32:$rot)))]>; + } +} + +let mayLoad = 0, mayStore = 0, hasSideEffects = 0 in +class BaseSIMDIndexedTiedComplex size, + bit opc1, bit opc2, RegisterOperand dst_reg, + RegisterOperand lhs_reg, + RegisterOperand rhs_reg, Operand vec_idx, + Operand rottype, string asm, + string apple_kind, string dst_kind, + string lhs_kind, string rhs_kind, + list pattern> + : I<(outs dst_reg:$dst), + (ins dst_reg:$Rd, lhs_reg:$Rn, rhs_reg:$Rm, vec_idx:$idx, rottype:$rot), + asm, + "{\t$Rd" # dst_kind # ", $Rn" # lhs_kind # ", $Rm" # rhs_kind # "$idx, $rot" # + "|" # apple_kind # "\t$Rd, $Rn, $Rm$idx, $rot}", "$Rd = $dst", pattern>, + Sched<[WriteV]> { + bits<5> Rd; + bits<5> Rn; + bits<5> Rm; + bits<2> rot; + + let Inst{31} = 0; + let Inst{30} = Q; + let Inst{29} = U; + let Inst{28} = Scalar; + let Inst{27-24} = 0b1111; + let Inst{23-22} = size; + // Bit 21 must be set by the derived class. + let Inst{20-16} = Rm; + let Inst{15} = opc1; + let Inst{14-13} = rot; + let Inst{12} = opc2; + // Bit 11 must be set by the derived class. + let Inst{10} = 0; + let Inst{9-5} = Rn; + let Inst{4-0} = Rd; +} + +// The complex instructions index by pairs of elements, so the VectorIndexes +// don't match the lane types, and the index bits are different to the other +// classes. +multiclass SIMDIndexedTiedComplexHSD { + let Predicates = [HasV8_3a,HasNEON,HasFullFP16] in { + def v4f16_indexed : BaseSIMDIndexedTiedComplex<0, 1, 0, 0b01, opc1, opc2, V64, + V64, V128, VectorIndexD, + rottype, asm, ".4h", ".4h", + ".4h", ".h", []> { + bits<1> idx; + let Inst{11} = 0; + let Inst{21} = idx{0}; + } + + def v8f16_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b01, opc1, opc2, + V128, V128, V128, VectorIndexS, + rottype, asm, ".8h", ".8h", + ".8h", ".h", []> { + bits<2> idx; + let Inst{11} = idx{1}; + let Inst{21} = idx{0}; + } + } // Predicates = [HasV8_3a,HasNEON,HasFullFP16] + + let Predicates = [HasV8_3a,HasNEON] in { + def v4f32_indexed : BaseSIMDIndexedTiedComplex<1, 1, 0, 0b10, opc1, opc2, + V128, V128, V128, VectorIndexD, + rottype, asm, ".4s", ".4s", + ".4s", ".s", []> { + bits<1> idx; + let Inst{11} = idx{0}; + let Inst{21} = 0; + } + } // Predicates = [HasV8_3a,HasNEON] +} + +//---------------------------------------------------------------------------- // Crypto extensions //---------------------------------------------------------------------------- Index: lib/Target/AArch64/AArch64InstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64InstrInfo.td +++ lib/Target/AArch64/AArch64InstrInfo.td @@ -3250,6 +3250,17 @@ (FACGTv2f64 V128:$dst, V128:$src2, V128:$src1), 0>; //===----------------------------------------------------------------------===// +// v8.3a complex add and multiply-accumulate. No predicate here, that is done +// inside the multiclass as the F16 versions need different predicates. +//===----------------------------------------------------------------------===// +defm FCMLA : SIMDThreeSameVectorTiedComplexHSD<1, 0b110, complexrotateop, + "fcmla", null_frag>; +defm FCADD : SIMDThreeSameVectorComplexHSD<1, 0b111, complexrotateopodd, + "fcadd", null_frag>; +defm FCMLA : SIMDIndexedTiedComplexHSD<1, 0, 1, complexrotateop, "fcmla", + null_frag>; + +//===----------------------------------------------------------------------===// // Advanced SIMD three scalar instructions. //===----------------------------------------------------------------------===// Index: lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -986,6 +986,26 @@ AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum); } + bool isComplexRotation() const { + if (!isImm()) return false; + + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + uint64_t Value = CE->getValue(); + + return (Value % 90 == 0 && Value <= 270); + } + + bool isComplexRotationOdd() const { + if (!isImm()) return false; + + const MCConstantExpr *CE = dyn_cast(getImm()); + if (!CE) return false; + uint64_t Value = CE->getValue(); + + return (Value % 180 == 90 && Value <= 270); + } + /// Is this a vector list with the type implicit (presumably attached to the /// instruction itself)? template bool isImplicitlyTypedVectorList() const { @@ -1672,6 +1692,18 @@ Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff)); } + void addComplexRotationOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90)); + } + + void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + const MCConstantExpr *MCE = cast(getImm()); + Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180)); + } + void print(raw_ostream &OS) const override; static std::unique_ptr @@ -3722,6 +3754,10 @@ return Error(Loc, "expected readable system register"); case Match_MSR: return Error(Loc, "expected writable system register or pstate"); + case Match_InvalidComplexRotation: + return Error(Loc, "complex rotation must be 0, 90, 180 or 270."); + case Match_InvalidComplexRotationOdd: + return Error(Loc, "complex rotation must be 90 or 270."); case Match_MnemonicFail: return Error(Loc, "unrecognized instruction mnemonic"); default: @@ -4131,6 +4167,8 @@ case Match_InvalidIndexS: case Match_InvalidIndexD: case Match_InvalidLabel: + case Match_InvalidComplexRotation: + case Match_InvalidComplexRotationOdd: case Match_MSR: case Match_MRS: { if (ErrorInfo >= Operands.size()) Index: lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h =================================================================== --- lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h +++ lib/Target/AArch64/InstPrinter/AArch64InstPrinter.h @@ -155,6 +155,10 @@ const MCSubtargetInfo &STI, raw_ostream &O); void printSIMDType10Operand(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, raw_ostream &O); + void printComplexRotationOp(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O); + void printComplexRotationOpOdd(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, raw_ostream &O); template void printGPRSeqPairsClassOperand(const MCInst *MI, unsigned OpNum, const MCSubtargetInfo &STI, Index: lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp =================================================================== --- lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp +++ lib/Target/AArch64/InstPrinter/AArch64InstPrinter.cpp @@ -1473,3 +1473,18 @@ uint64_t Val = AArch64_AM::decodeAdvSIMDModImmType10(RawVal); O << format("#%#016llx", Val); } + +void AArch64InstPrinter::printComplexRotationOp(const MCInst *MI, unsigned OpNo, + const MCSubtargetInfo &STI, + raw_ostream &O) { + unsigned Val = MI->getOperand(OpNo).getImm(); + O << "#" << Val * 90; +} + +void AArch64InstPrinter::printComplexRotationOpOdd(const MCInst *MI, + unsigned OpNo, + const MCSubtargetInfo &STI, + raw_ostream &O) { + unsigned Val = MI->getOperand(OpNo).getImm(); + O << "#" << (Val * 180) + 90; +} Index: lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp =================================================================== --- lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp +++ lib/Target/AArch64/MCTargetDesc/AArch64MCCodeEmitter.cpp @@ -163,6 +163,13 @@ SmallVectorImpl &Fixups, const MCSubtargetInfo &STI) const; + uint32_t getComplexRotationOpValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + uint32_t getComplexRotationOpOddValue(const MCInst &MI, unsigned OpIdx, + SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const; + unsigned fixMOVZ(const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const; @@ -521,6 +528,32 @@ return ShiftVal == 8 ? 0 : 1; } +/// getComplexRotationOpValue - Return encoding for a complex rotation operand. +uint32_t AArch64MCCodeEmitter::getComplexRotationOpValue( + const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpIdx); + assert(MO.isImm() && + "Expected an immediate value for the complex rotation!"); + unsigned Angle = MO.getImm(); + assert((Angle == 0 || Angle == 90 || Angle == 180 || Angle == 270) && + "Invalid complex rotation!"); + return Angle; +} + +/// getComplexRotationOpValue - Return encoding for a complex rotation operand. +uint32_t AArch64MCCodeEmitter::getComplexRotationOpOddValue( + const MCInst &MI, unsigned OpIdx, SmallVectorImpl &Fixups, + const MCSubtargetInfo &STI) const { + const MCOperand &MO = MI.getOperand(OpIdx); + assert(MO.isImm() && + "Expected an immediate value for the complex rotation!"); + unsigned Angle = MO.getImm(); + assert((Angle == 90 || Angle == 270) && + "Invalid odd complex rotation!"); + return Angle; +} + unsigned AArch64MCCodeEmitter::fixMOVZ(const MCInst &MI, unsigned EncodedValue, const MCSubtargetInfo &STI) const { // If one of the signed fixup kinds is applied to a MOVZ instruction, the Index: test/MC/AArch64/armv8.3a-complex.s =================================================================== --- /dev/null +++ test/MC/AArch64/armv8.3a-complex.s @@ -0,0 +1,148 @@ +// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.3a,-fullfp16 < %s 2>%t | FileCheck %s --check-prefix=CHECK --check-prefix=NO-FP16 +// RUN: FileCheck --check-prefix=STDERR --check-prefix=STDERR-NO-FP16 %s < %t +// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.3a,+fullfp16 < %s 2>%t | FileCheck %s --check-prefix=CHECK --check-prefix=FP16 +// RUN: FileCheck --check-prefix=STDERR --check-prefix=STDERR-FP16 %s < %t +// RUN: not llvm-mc -triple aarch64-none-linux-gnu -show-encoding -mattr=+v8.2a,-v8.3a,+fullfp16 < %s 2>&1 | FileCheck %s --check-prefix=NO-V83A + + +// ==== FCMLA vector ==== +// Types + fcmla v0.4h, v1.4h, v2.4h, #0 +// FP16: fcmla v0.4h, v1.4h, v2.4h, #0 // encoding: [0x20,0xc4,0x42,0x2e] +// STDERR-NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: fullfp16 +// NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcmla v0.8h, v1.8h, v2.8h, #0 +// FP16: fcmla v0.8h, v1.8h, v2.8h, #0 // encoding: [0x20,0xc4,0x42,0x6e] +// STDERR-NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: fullfp16 +// NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcmla v0.2s, v1.2s, v2.2s, #0 +// CHECK: fcmla v0.2s, v1.2s, v2.2s, #0 // encoding: [0x20,0xc4,0x82,0x2e] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcmla v0.4s, v1.4s, v2.4s, #0 +// CHECK: fcmla v0.4s, v1.4s, v2.4s, #0 // encoding: [0x20,0xc4,0x82,0x6e] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcmla v0.2d, v1.2d, v2.2d, #0 +// CHECK: fcmla v0.2d, v1.2d, v2.2d, #0 // encoding: [0x20,0xc4,0xc2,0x6e] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + +// Rotations + fcmla v0.2s, v1.2s, v2.2s, #0 +// CHECK: fcmla v0.2s, v1.2s, v2.2s, #0 // encoding: [0x20,0xc4,0x82,0x2e] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcmla v0.2s, v1.2s, v2.2s, #90 +// CHECK: fcmla v0.2s, v1.2s, v2.2s, #90 // encoding: [0x20,0xcc,0x82,0x2e] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcmla v0.2s, v1.2s, v2.2s, #180 +// CHECK: fcmla v0.2s, v1.2s, v2.2s, #180 // encoding: [0x20,0xd4,0x82,0x2e] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcmla v0.2s, v1.2s, v2.2s, #270 +// CHECK: fcmla v0.2s, v1.2s, v2.2s, #270 // encoding: [0x20,0xdc,0x82,0x2e] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + +// Invalid rotations + fcmla v0.2s, v1.2s, v2.2s, #1 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: complex rotation must be 0, 90, 180 or 270. + fcmla v0.2s, v1.2s, v2.2s, #360 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: complex rotation must be 0, 90, 180 or 270. + fcmla v0.2s, v1.2s, v2.2s, #-90 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: complex rotation must be 0, 90, 180 or 270. + +// ==== FCADD vector ==== +// Types + fcadd v0.4h, v1.4h, v2.4h, #90 +// FP16: fcadd v0.4h, v1.4h, v2.4h, #90 // encoding: [0x20,0xe4,0x42,0x2e] +// STDERR-NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: fullfp16 +// NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcadd v0.8h, v1.8h, v2.8h, #90 +// FP16: fcadd v0.8h, v1.8h, v2.8h, #90 // encoding: [0x20,0xe4,0x42,0x6e] +// STDERR-NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: fullfp16 +// NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcadd v0.2s, v1.2s, v2.2s, #90 +// CHECK: fcadd v0.2s, v1.2s, v2.2s, #90 // encoding: [0x20,0xe4,0x82,0x2e] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcadd v0.4s, v1.4s, v2.4s, #90 +// CHECK: fcadd v0.4s, v1.4s, v2.4s, #90 // encoding: [0x20,0xe4,0x82,0x6e] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcadd v0.2d, v1.2d, v2.2d, #90 +// CHECK: fcadd v0.2d, v1.2d, v2.2d, #90 // encoding: [0x20,0xe4,0xc2,0x6e] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + +// Rotations + fcadd v0.2s, v1.2s, v2.2s, #90 +// CHECK: fcadd v0.2s, v1.2s, v2.2s, #90 // encoding: [0x20,0xe4,0x82,0x2e] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcadd v0.2s, v1.2s, v2.2s, #270 +// CHECK: fcadd v0.2s, v1.2s, v2.2s, #270 // encoding: [0x20,0xf4,0x82,0x2e] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + +// Invalid rotations + fcadd v0.2s, v1.2s, v2.2s, #1 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: complex rotation must be 90 or 270. + fcadd v0.2s, v1.2s, v2.2s, #360 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: complex rotation must be 90 or 270. + fcadd v0.2s, v1.2s, v2.2s, #-90 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: complex rotation must be 90 or 270. + fcadd v0.2s, v1.2s, v2.2s, #0 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: complex rotation must be 90 or 270. + fcadd v0.2s, v1.2s, v2.2s, #180 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: complex rotation must be 90 or 270. + +// ==== FCMLA indexed ==== +// Types + fcmla v0.4h, v1.4h, v2.h[0], #0 +// FP16: fcmla v0.4h, v1.4h, v2.h[0], #0 // encoding: [0x20,0x10,0x42,0x2f] +// STDERR-NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: fullfp16 +// NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcmla v0.8h, v1.8h, v2.h[0], #0 +// FP16: fcmla v0.8h, v1.8h, v2.h[0], #0 // encoding: [0x20,0x10,0x42,0x6f] +// STDERR-NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: fullfp16 +// NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcmla v0.2s, v1.2s, v2.s[0], #0 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: invalid operand for instruction +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: invalid operand for instruction + fcmla v0.4s, v1.4s, v2.s[0], #0 +// CHECK: fcmla v0.4s, v1.4s, v2.s[0], #0 // encoding: [0x20,0x10,0x82,0x6f] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcmla v0.2d, v1.2d, v2.d[0], #0 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: invalid operand for instruction +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: invalid operand for instruction + +// Rotations + fcmla v0.4s, v1.4s, v2.s[0], #90 +// CHECK: fcmla v0.4s, v1.4s, v2.s[0], #90 // encoding: [0x20,0x30,0x82,0x6f] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcmla v0.4s, v1.4s, v2.s[0], #180 +// CHECK: fcmla v0.4s, v1.4s, v2.s[0], #180 // encoding: [0x20,0x50,0x82,0x6f] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcmla v0.4s, v1.4s, v2.s[0], #270 +// CHECK: fcmla v0.4s, v1.4s, v2.s[0], #270 // encoding: [0x20,0x70,0x82,0x6f] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + +// Valid indices + fcmla v0.4h, v1.4h, v2.h[1], #0 +// FP16: fcmla v0.4h, v1.4h, v2.h[1], #0 // encoding: [0x20,0x10,0x62,0x2f] +// STDERR-NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: fullfp16 +// NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcmla v0.8h, v1.8h, v2.h[3], #0 +// FP16: fcmla v0.8h, v1.8h, v2.h[3], #0 // encoding: [0x20,0x18,0x62,0x6f] +// STDERR-NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: fullfp16 +// NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: error: instruction requires: armv8.3a + fcmla v0.4s, v1.4s, v2.s[1], #0 +// CHECK: fcmla v0.4s, v1.4s, v2.s[1], #0 // encoding: [0x20,0x18,0x82,0x6f] +// NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: error: instruction requires: armv8.3a + +// Invalid indices + fcmla v0.4h, v1.4h, v2.h[2], #0 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: vector lane must be an integer in range [0, 1]. + fcmla v0.8h, v1.8h, v2.h[4], #0 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: vector lane must be an integer in range [0, 3]. + fcmla v0.4s, v1.4s, v2.s[2], #0 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: vector lane must be an integer in range [0, 1]. + +// Invalid rotations + fcmla v0.4s, v1.4s, v2.s[0], #1 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: complex rotation must be 0, 90, 180 or 270. + fcmla v0.4s, v1.4s, v2.s[0], #360 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: complex rotation must be 0, 90, 180 or 270. + fcmla v0.4s, v1.4s, v2.s[0], #-90 +// STDERR: :[[@LINE-1]]:{{[0-9]*}}: error: complex rotation must be 0, 90, 180 or 270. Index: test/MC/Disassembler/AArch64/armv8.3a-complex.txt =================================================================== --- /dev/null +++ test/MC/Disassembler/AArch64/armv8.3a-complex.txt @@ -0,0 +1,101 @@ +# RUN: not llvm-mc -triple aarch64-none-linux-gnu -mattr=+v8.3a,-fullfp16 --disassemble < %s 2>%t | FileCheck %s --check-prefix=CHECK +# RUN: FileCheck %s < %t --check-prefix=NO-FP16 +# RUN: llvm-mc -triple aarch64-none-linux-gnu -mattr=+v8.3a,+fullfp16 --disassemble < %s 2>%t | FileCheck %s --check-prefix=CHECK --check-prefix=FP16 +# RUN: not llvm-mc -triple aarch64-none-linux-gnu -mattr=-v8.3a,+fullfp16 --disassemble < %s 2>&1 | FileCheck %s --check-prefix=NO-V83A + +###### FCMLA vector +[0x20,0xc4,0x42,0x2e] +# FP16: fcmla v0.4h, v1.4h, v2.4h, #0 +# NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +# NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0xc4,0x42,0x6e] +# FP16: fcmla v0.8h, v1.8h, v2.8h, #0 +# NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +# NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0xc4,0x82,0x2e] +# CHECK: fcmla v0.2s, v1.2s, v2.2s, #0 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0xc4,0x82,0x6e] +# CHECK: fcmla v0.4s, v1.4s, v2.4s, #0 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0xc4,0xc2,0x6e] +# CHECK: fcmla v0.2d, v1.2d, v2.2d, #0 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding + + +[0x20,0xc4,0x82,0x2e] +# CHECK: fcmla v0.2s, v1.2s, v2.2s, #0 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0xcc,0x82,0x2e] +# CHECK: fcmla v0.2s, v1.2s, v2.2s, #90 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0xd4,0x82,0x2e] +# CHECK: fcmla v0.2s, v1.2s, v2.2s, #180 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0xdc,0x82,0x2e] +# CHECK: fcmla v0.2s, v1.2s, v2.2s, #270 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding + + +###### FCADD vector +[0x20,0xe4,0x42,0x2e] +# FP16: fcadd v0.4h, v1.4h, v2.4h, #90 +# NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +# NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0xe4,0x42,0x6e] +# FP16: fcadd v0.8h, v1.8h, v2.8h, #90 +# NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +# NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0xe4,0x82,0x2e] +# CHECK: fcadd v0.2s, v1.2s, v2.2s, #90 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0xe4,0x82,0x6e] +# CHECK: fcadd v0.4s, v1.4s, v2.4s, #90 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0xe4,0xc2,0x6e] +# CHECK: fcadd v0.2d, v1.2d, v2.2d, #90 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding + + +[0x20,0xe4,0x82,0x2e] +# CHECK: fcadd v0.2s, v1.2s, v2.2s, #90 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0xf4,0x82,0x2e] +# CHECK: fcadd v0.2s, v1.2s, v2.2s, #270 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding + +[0x20,0x10,0x42,0x2f] +# FP16: fcmla v0.4h, v1.4h, v2.h[0], #0 +# NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +# NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0x10,0x42,0x6f] +# FP16: fcmla v0.8h, v1.8h, v2.h[0], #0 +# NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +# NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0x10,0x82,0x6f] +# CHECK: fcmla v0.4s, v1.4s, v2.s[0], #0 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding + + +[0x20,0x30,0x82,0x6f] +# CHECK: fcmla v0.4s, v1.4s, v2.s[0], #90 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0x50,0x82,0x6f] +# CHECK: fcmla v0.4s, v1.4s, v2.s[0], #180 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0x70,0x82,0x6f] +# CHECK: fcmla v0.4s, v1.4s, v2.s[0], #270 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding + + +[0x20,0x10,0x62,0x2f] +# FP16: fcmla v0.4h, v1.4h, v2.h[1], #0 +# NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +# NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0x18,0x62,0x6f] +# FP16: fcmla v0.8h, v1.8h, v2.h[3], #0 +# NO-FP16: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding +# NO-V83A: :[[@LINE-3]]:{{[0-9]*}}: warning: invalid instruction encoding +[0x20,0x18,0x82,0x6f] +# CHECK: fcmla v0.4s, v1.4s, v2.s[1], #0 +# NO-V83A: :[[@LINE-2]]:{{[0-9]*}}: warning: invalid instruction encoding