Index: lib/Target/AArch64/AArch64RegisterInfo.td =================================================================== --- lib/Target/AArch64/AArch64RegisterInfo.td +++ lib/Target/AArch64/AArch64RegisterInfo.td @@ -835,12 +835,34 @@ let Size = 128; } -class ZPRAsmOperand : AsmOperandClass { +// SVE restricted 4 bit scalable vector register class +def ZPR_4b : RegisterClass<"AArch64", + [nxv16i8, nxv8i16, nxv4i32, nxv2i64, + nxv2f16, nxv4f16, nxv8f16, + nxv1f32, nxv2f32, nxv4f32, + nxv1f64, nxv2f64], + 128, (sequence "Z%u", 0, 15)> { + let Size = 128; +} + +// SVE restricted 3 bit scalable vector register class +def ZPR_3b : RegisterClass<"AArch64", + [nxv16i8, nxv8i16, nxv4i32, nxv2i64, + nxv2f16, nxv4f16, nxv8f16, + nxv1f32, nxv2f32, nxv4f32, + nxv1f64, nxv2f64], + 128, (sequence "Z%u", 0, 7)> { + let Size = 128; +} + +class ZPRAsmOperand + : AsmOperandClass { let Name = "SVE" # name # "Reg"; let PredicateMethod = "isSVEDataVectorRegOfWidth<" - # Width # ", AArch64::ZPRRegClassID>"; + # Width # ", AArch64::ZPR" + # RegClassSuffix # "RegClassID>"; let RenderMethod = "addRegOperands"; - let DiagnosticType = "InvalidZPR" # Width; + let DiagnosticType = "InvalidZPR" # RegClassSuffix # Width; let ParserMethod = "tryParseSVEDataVector"; } @@ -859,6 +881,22 @@ def ZPR64 : ZPRRegOp<"d", ZPRAsmOp64, ZPR>; def ZPR128 : ZPRRegOp<"q", ZPRAsmOp128, ZPR>; +def ZPRAsmOp3b8 : ZPRAsmOperand<"Vector3bB", 8, "_3b">; +def ZPRAsmOp3b16 : ZPRAsmOperand<"Vector3bH", 16, "_3b">; +def ZPRAsmOp3b32 : ZPRAsmOperand<"Vector3bS", 32, "_3b">; + +def ZPR3b8 : ZPRRegOp<"b", ZPRAsmOp3b8, ZPR_3b>; +def ZPR3b16 : ZPRRegOp<"h", ZPRAsmOp3b16, ZPR_3b>; +def ZPR3b32 : ZPRRegOp<"s", ZPRAsmOp3b32, ZPR_3b>; + +def ZPRAsmOp4b16 : ZPRAsmOperand<"Vector4bH", 16, "_4b">; +def ZPRAsmOp4b32 : ZPRAsmOperand<"Vector4bS", 32, "_4b">; +def ZPRAsmOp4b64 : ZPRAsmOperand<"Vector4bD", 64, "_4b">; + +def ZPR4b16 : ZPRRegOp<"h", ZPRAsmOp4b16, ZPR_4b>; +def ZPR4b32 : ZPRRegOp<"s", ZPRAsmOp4b32, ZPR_4b>; +def ZPR4b64 : ZPRRegOp<"d", ZPRAsmOp4b64, ZPR_4b>; + class FPRasZPR : AsmOperandClass{ let Name = "FPR" # Width # "asZPR"; let PredicateMethod = "isFPRasZPR"; Index: lib/Target/AArch64/AArch64SVEInstrInfo.td =================================================================== --- lib/Target/AArch64/AArch64SVEInstrInfo.td +++ lib/Target/AArch64/AArch64SVEInstrInfo.td @@ -39,6 +39,9 @@ defm FMUL_ZPmI : sve_fp_2op_i_p_zds<0b010, "fmul", sve_fpimm_half_two>; defm FMAX_ZPmI : sve_fp_2op_i_p_zds<0b110, "fmax", sve_fpimm_zero_one>; + + defm FMUL_ZZZI : sve_fp_fmul_by_indexed_elem<"fmul">; + // Splat immediate (unpredicated) defm DUP_ZI : sve_int_dup_imm<"dup">; defm FDUP_ZI : sve_int_dup_fpimm<"fdup">; Index: lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp =================================================================== --- lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp +++ lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp @@ -952,6 +952,8 @@ RegKind RK; switch (Class) { case AArch64::ZPRRegClassID: + case AArch64::ZPR_3bRegClassID: + case AArch64::ZPR_4bRegClassID: RK = RegKind::SVEDataVector; break; case AArch64::PPRRegClassID: @@ -4092,6 +4094,18 @@ case Match_InvalidZPR64: case Match_InvalidZPR128: return Error(Loc, "invalid element width"); + case Match_InvalidZPR_3b8: + return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b"); + case Match_InvalidZPR_3b16: + return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h"); + case Match_InvalidZPR_3b32: + return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s"); + case Match_InvalidZPR_4b16: + return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h"); + case Match_InvalidZPR_4b32: + return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s"); + case Match_InvalidZPR_4b64: + return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d"); case Match_InvalidSVEPattern: return Error(Loc, "invalid predicate pattern"); case Match_InvalidSVEPredicateAnyReg: @@ -4599,6 +4613,12 @@ case Match_InvalidZPR32: case Match_InvalidZPR64: case Match_InvalidZPR128: + case Match_InvalidZPR_3b8: + case Match_InvalidZPR_3b16: + case Match_InvalidZPR_3b32: + case Match_InvalidZPR_4b16: + case Match_InvalidZPR_4b32: + case Match_InvalidZPR_4b64: case Match_InvalidSVEPredicateAnyReg: case Match_InvalidSVEPattern: case Match_InvalidSVEPredicateBReg: Index: lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp =================================================================== --- lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp +++ lib/Target/AArch64/Disassembler/AArch64Disassembler.cpp @@ -91,6 +91,12 @@ static DecodeStatus DecodeZPRRegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decode); +static DecodeStatus DecodeZPR_4bRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decode); +static DecodeStatus DecodeZPR_3bRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void *Decode); static DecodeStatus DecodeZPR2RegisterClass(MCInst &Inst, unsigned RegNo, uint64_t Address, const void *Decode); @@ -499,6 +505,22 @@ return Success; } +static DecodeStatus DecodeZPR_4bRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void* Decoder) { + if (RegNo > 15) + return Fail; + return DecodeZPRRegisterClass(Inst, RegNo, Address, Decoder); +} + +static DecodeStatus DecodeZPR_3bRegisterClass(MCInst &Inst, unsigned RegNo, + uint64_t Address, + const void* Decoder) { + if (RegNo > 7) + return Fail; + return DecodeZPRRegisterClass(Inst, RegNo, Address, Decoder); +} + static const unsigned ZZDecoderTable[] = { AArch64::Z0_Z1, AArch64::Z1_Z2, AArch64::Z2_Z3, AArch64::Z3_Z4, AArch64::Z4_Z5, AArch64::Z5_Z6, AArch64::Z6_Z7, AArch64::Z7_Z8, Index: lib/Target/AArch64/SVEInstrFormats.td =================================================================== --- lib/Target/AArch64/SVEInstrFormats.td +++ lib/Target/AArch64/SVEInstrFormats.td @@ -781,6 +781,45 @@ def _D : sve_fp_2op_i_p_zds<0b11, opc, asm, ZPR64, imm_ty>; } +//===----------------------------------------------------------------------===// +// SVE Floating Point Multiply - Indexed Group +//===----------------------------------------------------------------------===// + +class sve_fp_fmul_by_indexed_elem sz, string asm, ZPRRegOp zprty, + ZPRRegOp zprty2, Operand itype> +: I<(outs zprty:$Zd), (ins zprty:$Zn, zprty2:$Zm, itype:$iop), + asm, "\t$Zd, $Zn, $Zm$iop", "", []>, Sched<[]> { + bits<5> Zd; + bits<5> Zn; + let Inst{31-24} = 0b01100100; + let Inst{23-22} = sz; + let Inst{21} = 0b1; + let Inst{15-10} = 0b001000; + let Inst{9-5} = Zn; + let Inst{4-0} = Zd; +} + +multiclass sve_fp_fmul_by_indexed_elem { + def _H : sve_fp_fmul_by_indexed_elem<{0, ?}, asm, ZPR16, ZPR3b16, VectorIndexH> { + bits<3> Zm; + bits<3> iop; + let Inst{22} = iop{2}; + let Inst{20-19} = iop{1-0}; + let Inst{18-16} = Zm; + } + def _S : sve_fp_fmul_by_indexed_elem<0b10, asm, ZPR32, ZPR3b32, VectorIndexS> { + bits<3> Zm; + bits<2> iop; + let Inst{20-19} = iop; + let Inst{18-16} = Zm; + } + def _D : sve_fp_fmul_by_indexed_elem<0b11, asm, ZPR64, ZPR4b64, VectorIndexD> { + bits<4> Zm; + bit iop; + let Inst{20} = iop; + let Inst{19-16} = Zm; + } +} //===----------------------------------------------------------------------===// // SVE Stack Allocation Group Index: test/MC/AArch64/SVE/fmul-diagnostics.s =================================================================== --- test/MC/AArch64/SVE/fmul-diagnostics.s +++ test/MC/AArch64/SVE/fmul-diagnostics.s @@ -32,3 +32,61 @@ // CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid floating point constant, expected 0.5 or 2.0. // CHECK-NEXT: fmul z0.h, p0/m, z0.h, #1.9999999999999999999999999 // CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Restricted ZPR range + +fmul z0.h, z0.h, z8.b[0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z7.h +// CHECK-NEXT: fmul z0.h, z0.h, z8.b[0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.h, z0.h, z8.h[0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.h..z7.h +// CHECK-NEXT: fmul z0.h, z0.h, z8.h[0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.s, z0.s, z8.s[0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.s..z7.s +// CHECK-NEXT: fmul z0.s, z0.s, z8.s[0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.d, z0.d, z16.d[0] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: Invalid restricted vector register, expected z0.d..z15.d +// CHECK-NEXT: fmul z0.d, z0.d, z16.d[0] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + + +// --------------------------------------------------------------------------// +// Index out of bounds + +fmul z0.h, z0.h, z0.h[-1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 7]. +// CHECK-NEXT: fmul z0.h, z0.h, z0.h[-1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.h, z0.h, z0.h[8] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 7]. +// CHECK-NEXT: fmul z0.h, z0.h, z0.h[8] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.s, z0.s, z0.s[-1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3]. +// CHECK-NEXT: fmul z0.s, z0.s, z0.s[-1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.s, z0.s, z0.s[4] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 3]. +// CHECK-NEXT: fmul z0.s, z0.s, z0.s[4] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.d, z0.d, z0.d[-1] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 1]. +// CHECK-NEXT: fmul z0.d, z0.d, z0.d[-1] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: + +fmul z0.d, z0.d, z0.d[2] +// CHECK: [[@LINE-1]]:{{[0-9]+}}: error: vector lane must be an integer in range [0, 1]. +// CHECK-NEXT: fmul z0.d, z0.d, z0.d[2] +// CHECK-NOT: [[@LINE-1]]:{{[0-9]+}}: Index: test/MC/AArch64/SVE/fmul.s =================================================================== --- test/MC/AArch64/SVE/fmul.s +++ test/MC/AArch64/SVE/fmul.s @@ -48,3 +48,39 @@ // CHECK-ENCODING: [0x3f,0x9c,0xda,0x65] // CHECK-ERROR: instruction requires: sve // CHECK-UNKNOWN: 3f 9c da 65 + +fmul z0.h, z0.h, z0.h[0] +// CHECK-INST: fmul z0.h, z0.h, z0.h[0] +// CHECK-ENCODING: [0x00,0x20,0x20,0x64] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 20 20 64 + +fmul z0.s, z0.s, z0.s[0] +// CHECK-INST: fmul z0.s, z0.s, z0.s[0] +// CHECK-ENCODING: [0x00,0x20,0xa0,0x64] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 20 a0 64 + +fmul z0.d, z0.d, z0.d[0] +// CHECK-INST: fmul z0.d, z0.d, z0.d[0] +// CHECK-ENCODING: [0x00,0x20,0xe0,0x64] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: 00 20 e0 64 + +fmul z31.h, z31.h, z7.h[7] +// CHECK-INST: fmul z31.h, z31.h, z7.h[7] +// CHECK-ENCODING: [0xff,0x23,0x7f,0x64] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff 23 7f 64 + +fmul z31.s, z31.s, z7.s[3] +// CHECK-INST: fmul z31.s, z31.s, z7.s[3] +// CHECK-ENCODING: [0xff,0x23,0xbf,0x64] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff 23 bf 64 + +fmul z31.d, z31.d, z15.d[1] +// CHECK-INST: fmul z31.d, z31.d, z15.d[1] +// CHECK-ENCODING: [0xff,0x23,0xff,0x64] +// CHECK-ERROR: instruction requires: sve +// CHECK-UNKNOWN: ff 23 ff 64